Ported .Net Core commits:
hondacrx: - Initial commit: Switch to .Net Core 2.0 - Fix build and removed not needed files Fabi: - Updated solution platforms. - Changed folder structure. - Change library target framework to netstandard2.0. - Updated solution platforms again... - Removed windows specific kernel32 function usage (Ctrl-C handler).
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.Scripting;
|
||||
using System;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.Ahnkahet.Amanitar
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint Bash = 57094; // Victim
|
||||
public const uint EntanglingRoots = 57095; // Random Victim 100y
|
||||
public const uint Mini = 57055; // Self
|
||||
public const uint VenomBoltVolley = 57088; // Random Victim 100y
|
||||
public const uint HealthyMushroomPotentFungus = 56648; // Killer 3y
|
||||
public const uint PoisonousMushroomPoisonCloud = 57061; // Self - Duration 8 Sec
|
||||
public const uint PoisonousMushroomVisualArea = 61566; // Self
|
||||
public const uint PoisonousMushroomVisualAura = 56741; // Self
|
||||
public const uint PutridMushroom = 31690; // To Make The Mushrooms Visible
|
||||
public const uint PowerMushroomVisualAura = 56740;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
public const uint Trigger = 19656;
|
||||
public const uint HealthyMushroom = 30391;
|
||||
public const uint PoisonousMushroom = 30435;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_amanitar : BossAI
|
||||
{
|
||||
public boss_amanitar(Creature creature) : base(creature, DataTypes.Amanitar) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
me.SetMeleeDamageSchool(SpellSchools.Nature);
|
||||
me.ApplySpellImmune(0, SpellImmunity.School, SpellSchoolMask.Nature, true);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
SpawnAdds();
|
||||
task.Repeat(TimeSpan.FromSeconds(20));
|
||||
});
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(9), task =>
|
||||
{
|
||||
DoCast(SelectTarget(SelectAggroTarget.Random, 0, 100, true), SpellIds.EntanglingRoots, true);
|
||||
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15));
|
||||
});
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(14), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Bash);
|
||||
task.Repeat(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(12));
|
||||
});
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(18), task =>
|
||||
{
|
||||
DoCast(SpellIds.Mini);
|
||||
task.Repeat(TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(30));
|
||||
});
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
DoCast(SelectTarget(SelectAggroTarget.Random, 0, 100, true), SpellIds.VenomBoltVolley, true);
|
||||
task.Repeat(TimeSpan.FromSeconds(18), TimeSpan.FromSeconds(22));
|
||||
});
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
instance.DoRemoveAurasDueToSpellOnPlayers(SpellIds.Mini);
|
||||
}
|
||||
|
||||
void SpawnAdds()
|
||||
{
|
||||
int u = 0;
|
||||
|
||||
for (byte i = 0; i < 30; ++i)
|
||||
{
|
||||
Position pos = me.GetRandomNearPosition(30.0f);
|
||||
pos.posZ = me.GetMap().GetHeight(pos.GetPositionX(), pos.GetPositionY(), MapConst.MaxHeight) + 2.0f;
|
||||
|
||||
Creature trigger = me.SummonCreature(CreatureIds.Trigger, pos);
|
||||
if (trigger)
|
||||
{
|
||||
Creature temp1 = trigger.FindNearestCreature(CreatureIds.HealthyMushroom, 4.0f, true);
|
||||
Creature temp2 = trigger.FindNearestCreature(CreatureIds.PoisonousMushroom, 4.0f, true);
|
||||
if (temp1 || temp2)
|
||||
{
|
||||
trigger.DisappearAndDie();
|
||||
}
|
||||
else
|
||||
{
|
||||
u = 1 - u;
|
||||
trigger.DisappearAndDie();
|
||||
me.SummonCreature(u > 0 ? CreatureIds.PoisonousMushroom : CreatureIds.HealthyMushroom, pos, TempSummonType.TimedOrCorpseDespawn, 60 * Time.InMilliseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_amanitar_mushrooms : ScriptedAI
|
||||
{
|
||||
public npc_amanitar_mushrooms(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), task =>
|
||||
{
|
||||
if (me.GetEntry() == CreatureIds.PoisonousMushroom)
|
||||
{
|
||||
DoCast(me, SpellIds.PoisonousMushroomVisualArea, true);
|
||||
DoCast(me, SpellIds.PoisonousMushroomPoisonCloud);
|
||||
}
|
||||
task.Repeat(TimeSpan.FromSeconds(7));
|
||||
});
|
||||
|
||||
me.SetDisplayId(me.GetCreatureTemplate().ModelId2);
|
||||
DoCast(SpellIds.PutridMushroom);
|
||||
|
||||
if (me.GetEntry() == CreatureIds.PoisonousMushroom)
|
||||
DoCast(SpellIds.PoisonousMushroomVisualAura);
|
||||
else
|
||||
DoCast(SpellIds.PowerMushroomVisualAura);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (damage >= me.GetHealth() && me.GetEntry() == CreatureIds.HealthyMushroom)
|
||||
DoCast(me, SpellIds.HealthyMushroomPotentFungus, true);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who) { }
|
||||
public override void AttackStart(Unit victim) { }
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* 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.Scripting;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.Ahnkahet.ElderNadox
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint BroodPlague = 56130;
|
||||
public const uint HBroodRage = 59465;
|
||||
public const uint Enrage = 26662; // Enraged If Too Far Away From Home
|
||||
public const uint SummonSwarmers = 56119; // 2x 30178 -- 2x Every 10secs
|
||||
public const uint SummonSwarmGuard = 56120; // 1x 30176
|
||||
|
||||
// Adds
|
||||
public const uint SwarmBuff = 56281;
|
||||
public const uint Sprint = 56354;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SaySlay = 1;
|
||||
public const uint SayDeath = 2;
|
||||
public const uint SayEggSac = 3;
|
||||
public const uint EmoteHatches = 4;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint DataRespectYourElders = 6;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_elder_nadox : BossAI
|
||||
{
|
||||
public boss_elder_nadox(Creature creature) : base(creature, DataTypes.ElderNadox)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
GuardianSummoned = false;
|
||||
GuardianDied = false;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(TextIds.SayAggro);
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(13), task =>
|
||||
{
|
||||
DoCast(SelectTarget(SelectAggroTarget.Random, 0, 100, true), SpellIds.BroodPlague, true);
|
||||
task.Repeat(TimeSpan.FromSeconds(15));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
|
||||
{
|
||||
/// @todo: summoned by egg
|
||||
DoCast(me, SpellIds.SummonSwarmers);
|
||||
if (RandomHelper.URand(1, 3) == 3) // 33% chance of dialog
|
||||
Talk(TextIds.SayEggSac);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
|
||||
{
|
||||
DoCast(SpellIds.HBroodRage);
|
||||
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(50));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
if (me.HasAura(SpellIds.Enrage))
|
||||
return;
|
||||
if (me.GetPositionZ() < 24.0f)
|
||||
DoCast(me, SpellIds.Enrage, true);
|
||||
task.Repeat();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void SummonedCreatureDies(Creature summon, Unit killer)
|
||||
{
|
||||
if (summon.GetEntry() == AKCreatureIds.AhnkaharGuardian)
|
||||
GuardianDied = true;
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == Misc.DataRespectYourElders)
|
||||
return !GuardianDied ? 1 : 0u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.IsTypeId(TypeId.Player))
|
||||
Talk(TextIds.SaySlay);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(TextIds.SayDeath);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (!GuardianSummoned && me.HealthBelowPct(50))
|
||||
{
|
||||
/// @todo: summoned by egg
|
||||
Talk(TextIds.EmoteHatches, me);
|
||||
DoCast(me, SpellIds.SummonSwarmGuard);
|
||||
GuardianSummoned = true;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool GuardianSummoned;
|
||||
bool GuardianDied;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_ahnkahar_nerubian : ScriptedAI
|
||||
{
|
||||
public npc_ahnkahar_nerubian(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(13), task =>
|
||||
{
|
||||
DoCast(me, SpellIds.Sprint);
|
||||
task.Repeat(TimeSpan.FromSeconds(20));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
// 56159 - Swarm
|
||||
[Script]
|
||||
class spell_ahn_kahet_swarm : SpellScript
|
||||
{
|
||||
public spell_ahn_kahet_swarm()
|
||||
{
|
||||
_targetCount = 0;
|
||||
}
|
||||
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.SwarmBuff);
|
||||
}
|
||||
|
||||
void CountTargets(List<WorldObject> targets)
|
||||
{
|
||||
_targetCount = targets.Count;
|
||||
}
|
||||
|
||||
void HandleDummy(uint effIndex)
|
||||
{
|
||||
if (_targetCount != 0)
|
||||
{
|
||||
Aura aura = GetCaster().GetAura(SpellIds.SwarmBuff);
|
||||
if (aura != null)
|
||||
{
|
||||
aura.SetStackAmount((byte)_targetCount);
|
||||
aura.RefreshDuration();
|
||||
}
|
||||
else
|
||||
GetCaster().CastCustomSpell(SpellIds.SwarmBuff, SpellValueMod.AuraStack, _targetCount, GetCaster(), TriggerCastFlags.FullMask);
|
||||
}
|
||||
else
|
||||
GetCaster().RemoveAurasDueToSpell(SpellIds.SwarmBuff);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(CountTargets, 0, Targets.UnitSrcAreaAlly));
|
||||
OnEffectHit.Add(new EffectHandler(HandleDummy, 0, SpellEffectName.Dummy));
|
||||
}
|
||||
|
||||
int _targetCount;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_respect_your_elders : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_respect_your_elders() : base("achievement_respect_your_elders") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
return target && target.GetAI().GetData(Misc.DataRespectYourElders) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.Ahnkahet.JedogaShadowseeker
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint SphereVisual = 56075;
|
||||
public const uint GiftOfTheHerald = 56219;
|
||||
public const uint CycloneStrike = 56855; // Self
|
||||
public const uint LightningBolt = 56891; // 40y
|
||||
public const uint Thundershock = 56926; // 30y
|
||||
|
||||
public const uint BeamVisualJedogasAufseher1 = 60342;
|
||||
public const uint BeamVisualJedogasAufseher2 = 56312;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SaySacrifice1 = 1;
|
||||
public const uint SaySacrifice2 = 2;
|
||||
public const uint SaySlay = 3;
|
||||
public const uint SayDeath = 4;
|
||||
public const uint SayPreaching = 5;
|
||||
}
|
||||
struct Misc
|
||||
{
|
||||
public const int ActionInitiateKilled = 1;
|
||||
public const uint DataVolunteerWork = 2;
|
||||
|
||||
public static Position[] JedogaPosition =
|
||||
{
|
||||
new Position(372.330994f, -705.278015f, -0.624178f, 5.427970f),
|
||||
new Position(372.330994f, -705.278015f, -16.179716f, 5.427970f)
|
||||
};
|
||||
}
|
||||
|
||||
[Script]
|
||||
public class boss_jedoga_shadowseeker : ScriptedAI
|
||||
{
|
||||
public boss_jedoga_shadowseeker(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature.GetInstanceScript();
|
||||
bFirstTime = true;
|
||||
bPreDone = false;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiOpFerTimer = RandomHelper.URand(15 * Time.InMilliseconds, 20 * Time.InMilliseconds);
|
||||
|
||||
uiCycloneTimer = 3 * Time.InMilliseconds;
|
||||
uiBoltTimer = 7 * Time.InMilliseconds;
|
||||
uiThunderTimer = 12 * Time.InMilliseconds;
|
||||
|
||||
bOpFerok = false;
|
||||
bOpFerokFail = false;
|
||||
bOnGround = false;
|
||||
bCanDown = false;
|
||||
volunteerWork = true;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
|
||||
if (!bFirstTime)
|
||||
instance.SetBossState(DataTypes.JedogaShadowseeker, EncounterState.Fail);
|
||||
|
||||
instance.SetGuidData(DataTypes.PlJedogaTarget, ObjectGuid.Empty);
|
||||
instance.SetGuidData(DataTypes.AddJedogaVictim, ObjectGuid.Empty);
|
||||
instance.SetData(DataTypes.JedogaResetInitiands, 0);
|
||||
MoveUp();
|
||||
|
||||
bFirstTime = false;
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
if (instance == null || (who.GetTypeId() == TypeId.Unit && who.GetEntry() == AKCreatureIds.JedogaController))
|
||||
return;
|
||||
|
||||
Talk(TextIds.SayAggro);
|
||||
me.SetInCombatWithZone();
|
||||
instance.SetBossState(DataTypes.JedogaShadowseeker, EncounterState.InProgress);
|
||||
}
|
||||
|
||||
public override void AttackStart(Unit who)
|
||||
{
|
||||
if (!who || (who.GetTypeId() == TypeId.Unit && who.GetEntry() == AKCreatureIds.JedogaController))
|
||||
return;
|
||||
|
||||
base.AttackStart(who);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit Victim)
|
||||
{
|
||||
if (!Victim || !Victim.IsTypeId(TypeId.Player))
|
||||
return;
|
||||
|
||||
Talk(TextIds.SaySlay);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Talk(TextIds.SayDeath);
|
||||
instance.SetBossState(DataTypes.JedogaShadowseeker, EncounterState.Done);
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
if (action == Misc.ActionInitiateKilled)
|
||||
volunteerWork = false;
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == Misc.DataVolunteerWork)
|
||||
return volunteerWork ? 1 : 0u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void MoveInLineOfSight(Unit who)
|
||||
{
|
||||
if (instance == null || !who || (who.IsTypeId(TypeId.Unit) && who.GetEntry() == AKCreatureIds.JedogaController))
|
||||
return;
|
||||
|
||||
if (!bPreDone && who.IsTypeId(TypeId.Player) && me.GetDistance(who) < 100.0f)
|
||||
{
|
||||
Talk(TextIds.SayPreaching);
|
||||
bPreDone = true;
|
||||
}
|
||||
|
||||
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress || !bOnGround)
|
||||
return;
|
||||
|
||||
if (!me.GetVictim() && me.CanCreatureAttack(who))
|
||||
{
|
||||
float attackRadius = me.GetAttackDistance(who);
|
||||
if (me.IsWithinDistInMap(who, attackRadius) && me.IsWithinLOSInMap(who))
|
||||
{
|
||||
if (!me.GetVictim())
|
||||
{
|
||||
who.RemoveAurasByType(AuraType.ModStealth);
|
||||
AttackStart(who);
|
||||
}
|
||||
else
|
||||
{
|
||||
who.SetInCombatWith(me);
|
||||
me.AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoveDown()
|
||||
{
|
||||
bOpFerokFail = false;
|
||||
|
||||
instance.SetData(DataTypes.JedogaTriggerSwitch, 0);
|
||||
me.GetMotionMaster().MovePoint(1, Misc.JedogaPosition[1]);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, false);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, false);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
||||
|
||||
me.RemoveAurasDueToSpell(SpellIds.SphereVisual);
|
||||
|
||||
bOnGround = true;
|
||||
|
||||
if (UpdateVictim())
|
||||
{
|
||||
AttackStart(me.GetVictim());
|
||||
me.GetMotionMaster().MoveChase(me.GetVictim());
|
||||
}
|
||||
else
|
||||
{
|
||||
Unit target = Global.ObjAccessor.GetUnit(me, instance.GetGuidData(DataTypes.PlJedogaTarget));
|
||||
if (target)
|
||||
{
|
||||
AttackStart(target);
|
||||
instance.SetData(DataTypes.JedogaResetInitiands, 0);
|
||||
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress)
|
||||
EnterCombat(target);
|
||||
}
|
||||
else if (!me.IsInCombat())
|
||||
EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
|
||||
void MoveUp()
|
||||
{
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, true);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, true);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
||||
|
||||
me.AttackStop();
|
||||
me.RemoveAllAuras();
|
||||
me.LoadCreaturesAddon();
|
||||
me.GetMotionMaster().MovePoint(0, Misc.JedogaPosition[0]);
|
||||
|
||||
instance.SetData(DataTypes.JedogaTriggerSwitch, 1);
|
||||
if (instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.InProgress)
|
||||
GetVictimForSacrifice();
|
||||
|
||||
bOnGround = false;
|
||||
uiOpFerTimer = RandomHelper.URand(15 * Time.InMilliseconds, 30 * Time.InMilliseconds);
|
||||
}
|
||||
|
||||
void GetVictimForSacrifice()
|
||||
{
|
||||
ObjectGuid victim = instance.GetGuidData(DataTypes.AddJedogaInitiand);
|
||||
if (!victim.IsEmpty())
|
||||
{
|
||||
Talk(TextIds.SaySacrifice1);
|
||||
instance.SetGuidData(DataTypes.AddJedogaVictim, victim);
|
||||
}
|
||||
else
|
||||
bCanDown = true;
|
||||
}
|
||||
|
||||
void Sacrifice()
|
||||
{
|
||||
Talk(TextIds.SaySacrifice2);
|
||||
|
||||
me.InterruptNonMeleeSpells(false);
|
||||
DoCast(me, SpellIds.GiftOfTheHerald, false);
|
||||
|
||||
bOpFerok = false;
|
||||
bCanDown = true;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress && instance.GetData(DataTypes.AllInitiandDead) != 0)
|
||||
MoveDown();
|
||||
|
||||
if (bOpFerok && !bOnGround && !bCanDown)
|
||||
Sacrifice();
|
||||
|
||||
if (bOpFerokFail && !bOnGround && !bCanDown)
|
||||
bCanDown = true;
|
||||
|
||||
if (bCanDown)
|
||||
{
|
||||
MoveDown();
|
||||
bCanDown = false;
|
||||
}
|
||||
|
||||
if (bOnGround)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiCycloneTimer <= diff)
|
||||
{
|
||||
DoCast(me, SpellIds.CycloneStrike, false);
|
||||
uiCycloneTimer = RandomHelper.URand(15 * Time.InMilliseconds, 30 * Time.InMilliseconds);
|
||||
}
|
||||
else uiCycloneTimer -= diff;
|
||||
|
||||
if (uiBoltTimer <= diff)
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100, true);
|
||||
if (target)
|
||||
me.CastSpell(target, SpellIds.LightningBolt, false);
|
||||
|
||||
uiBoltTimer = RandomHelper.URand(15 * Time.InMilliseconds, 30 * Time.InMilliseconds);
|
||||
}
|
||||
else uiBoltTimer -= diff;
|
||||
|
||||
if (uiThunderTimer <= diff)
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100, true);
|
||||
if (target)
|
||||
me.CastSpell(target, SpellIds.Thundershock, false);
|
||||
|
||||
uiThunderTimer = RandomHelper.URand(15 * Time.InMilliseconds, 30 * Time.InMilliseconds);
|
||||
}
|
||||
else uiThunderTimer -= diff;
|
||||
|
||||
if (uiOpFerTimer <= diff)
|
||||
MoveUp();
|
||||
else
|
||||
uiOpFerTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
|
||||
uint uiOpFerTimer;
|
||||
uint uiCycloneTimer;
|
||||
uint uiBoltTimer;
|
||||
uint uiThunderTimer;
|
||||
|
||||
bool bPreDone;
|
||||
public bool bOpFerok;
|
||||
bool bOnGround;
|
||||
public bool bOpFerokFail;
|
||||
bool bCanDown;
|
||||
bool volunteerWork;
|
||||
bool bFirstTime;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_jedoga_initiand : ScriptedAI
|
||||
{
|
||||
public npc_jedoga_initiand(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature.GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
bWalking = false;
|
||||
bCheckTimer = 2 * Time.InMilliseconds;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
|
||||
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress)
|
||||
{
|
||||
me.RemoveAurasDueToSpell(SpellIds.SphereVisual);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, false);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, false);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoCast(me, SpellIds.SphereVisual, false);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, true);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, true);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
if (!killer || instance == null)
|
||||
return;
|
||||
|
||||
if (bWalking)
|
||||
{
|
||||
Creature boss = ObjectAccessor.GetCreature(me, instance.GetGuidData(DataTypes.JedogaShadowseeker));
|
||||
if (boss)
|
||||
{
|
||||
if (!boss.GetAI<boss_jedoga_shadowseeker>().bOpFerok)
|
||||
boss.GetAI<boss_jedoga_shadowseeker>().bOpFerokFail = true;
|
||||
|
||||
if (killer.IsTypeId(TypeId.Player))
|
||||
boss.GetAI().DoAction(Misc.ActionInitiateKilled);
|
||||
}
|
||||
|
||||
instance.SetGuidData(DataTypes.AddJedogaVictim, ObjectGuid.Empty);
|
||||
|
||||
bWalking = false;
|
||||
}
|
||||
if (killer.IsTypeId(TypeId.Player))
|
||||
instance.SetGuidData(DataTypes.PlJedogaTarget, killer.GetGUID());
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who) { }
|
||||
|
||||
public override void AttackStart(Unit victim)
|
||||
{
|
||||
if ((instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.InProgress) || !victim)
|
||||
return;
|
||||
|
||||
base.AttackStart(victim);
|
||||
}
|
||||
|
||||
public override void MoveInLineOfSight(Unit who)
|
||||
{
|
||||
if ((instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.InProgress) || !who)
|
||||
return;
|
||||
|
||||
base.MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType uiType, uint uiPointId)
|
||||
{
|
||||
if (uiType != MovementGeneratorType.Point || instance == null)
|
||||
return;
|
||||
|
||||
switch (uiPointId)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
Creature boss = me.GetMap().GetCreature(instance.GetGuidData(DataTypes.JedogaShadowseeker));
|
||||
if (boss)
|
||||
{
|
||||
boss.GetAI<boss_jedoga_shadowseeker>().bOpFerok = true;
|
||||
boss.GetAI<boss_jedoga_shadowseeker>().bOpFerokFail = false;
|
||||
me.KillSelf();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (bCheckTimer <= diff)
|
||||
{
|
||||
if (me.GetGUID() == instance.GetGuidData(DataTypes.AddJedogaVictim) && !bWalking)
|
||||
{
|
||||
me.RemoveAurasDueToSpell(SpellIds.SphereVisual);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, false);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, false);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
||||
|
||||
float distance = me.GetDistance(Misc.JedogaPosition[1]);
|
||||
|
||||
if (distance < 9.0f)
|
||||
me.SetSpeedRate(UnitMoveType.Walk, 0.5f);
|
||||
else if (distance < 15.0f)
|
||||
me.SetSpeedRate(UnitMoveType.Walk, 0.75f);
|
||||
else if (distance < 20.0f)
|
||||
me.SetSpeedRate(UnitMoveType.Walk, 1.0f);
|
||||
|
||||
me.GetMotionMaster().Clear(false);
|
||||
me.GetMotionMaster().MovePoint(1, Misc.JedogaPosition[1]);
|
||||
bWalking = true;
|
||||
}
|
||||
if (!bWalking)
|
||||
{
|
||||
if (instance.GetBossState(DataTypes.JedogaShadowseeker) != EncounterState.InProgress && me.HasAura(SpellIds.SphereVisual))
|
||||
{
|
||||
me.RemoveAurasDueToSpell(SpellIds.SphereVisual);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, false);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, false);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
||||
}
|
||||
if (instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.InProgress && !me.HasAura(SpellIds.SphereVisual))
|
||||
{
|
||||
DoCast(me, SpellIds.SphereVisual, false);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Normal, true);
|
||||
me.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, true);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable | UnitFlags.NonAttackable);
|
||||
}
|
||||
}
|
||||
bCheckTimer = 2 * Time.InMilliseconds;
|
||||
}
|
||||
else bCheckTimer -= diff;
|
||||
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
|
||||
uint bCheckTimer;
|
||||
bool bWalking;
|
||||
}
|
||||
|
||||
|
||||
[Script]
|
||||
class npc_jedogas_aufseher_trigger : ScriptedAI
|
||||
{
|
||||
public npc_jedogas_aufseher_trigger(Creature creature) : base(creature)
|
||||
{
|
||||
instance = creature.GetInstanceScript();
|
||||
bRemoved = false;
|
||||
bRemoved2 = false;
|
||||
bCast = false;
|
||||
bCast2 = false;
|
||||
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
public override void Reset() { }
|
||||
public override void EnterCombat(Unit who) { }
|
||||
public override void AttackStart(Unit victim) { }
|
||||
public override void MoveInLineOfSight(Unit who) { }
|
||||
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!bRemoved && me.GetPositionX() > 440.0f)
|
||||
{
|
||||
if (instance.GetBossState(DataTypes.PrinceTaldaram) == EncounterState.Done)
|
||||
{
|
||||
me.InterruptNonMeleeSpells(true);
|
||||
bRemoved = true;
|
||||
return;
|
||||
}
|
||||
if (!bCast)
|
||||
{
|
||||
DoCast(me, SpellIds.BeamVisualJedogasAufseher1, false);
|
||||
bCast = true;
|
||||
}
|
||||
}
|
||||
if (!bRemoved2 && me.GetPositionX() < 440.0f)
|
||||
{
|
||||
if (!bCast2 && instance.GetData(DataTypes.JedogaTriggerSwitch) != 0)
|
||||
{
|
||||
DoCast(me, SpellIds.BeamVisualJedogasAufseher2, false);
|
||||
bCast2 = true;
|
||||
}
|
||||
if (bCast2 && instance.GetData(DataTypes.JedogaTriggerSwitch) == 0)
|
||||
{
|
||||
me.InterruptNonMeleeSpells(true);
|
||||
bCast2 = false;
|
||||
}
|
||||
if (!bRemoved2 && instance.GetBossState(DataTypes.JedogaShadowseeker) == EncounterState.Done)
|
||||
{
|
||||
me.InterruptNonMeleeSpells(true);
|
||||
bRemoved2 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
|
||||
bool bRemoved;
|
||||
bool bRemoved2;
|
||||
bool bCast;
|
||||
bool bCast2;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_volunteer_work : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_volunteer_work() : base("achievement_volunteer_work") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
Creature Jedoga = target.ToCreature();
|
||||
if (Jedoga)
|
||||
if (Jedoga.GetAI().GetData(Misc.DataVolunteerWork) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.Ahnkahet.PrinceTaldaram
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint Bloodthirst = 55968; // Trigger Spell + Add Aura
|
||||
public const uint ConjureFlameSphere = 55931;
|
||||
public const uint FlameSphereSummon1 = 55895; // 1x 30106
|
||||
public const uint FlameSphereSummon2 = 59511; // 1x 31686
|
||||
public const uint FlameSphereSummon3 = 59512; // 1x 31687
|
||||
public const uint FlameSphereSpawnEffect = 55891;
|
||||
public const uint FlameSphereVisual = 55928;
|
||||
public const uint FlameSpherePeriodic = 55926;
|
||||
public const uint FlameSphereDeathEffect = 55947;
|
||||
public const uint EmbraceOfTheVampyr = 55959;
|
||||
public const uint Vanish = 55964;
|
||||
|
||||
public const uint BeamVisual = 60342;
|
||||
public const uint HoverFall = 60425;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
public const uint FlameSphere1 = 30106;
|
||||
public const uint FlameSphere2 = 31686;
|
||||
public const uint FlameSphere3 = 31687;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint Say1 = 0;
|
||||
public const uint SayWarning = 1;
|
||||
public const uint SayAggro = 2;
|
||||
public const uint SaySlay = 3;
|
||||
public const uint SayDeath = 4;
|
||||
public const uint SayFeed = 5;
|
||||
public const uint SayVanish = 6;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint EventConjureFlameSpheres = 1;
|
||||
public const uint EventBloodthirst = 2;
|
||||
public const uint EventVanish = 3;
|
||||
public const uint EventJustVanished = 4;
|
||||
public const uint EventVanished = 5;
|
||||
public const uint EventFeeding = 6;
|
||||
|
||||
// Flame Sphere
|
||||
public const uint EventStartMove = 7;
|
||||
public const uint EventDespawn = 8;
|
||||
|
||||
public const uint DataEmbraceDmg = 20000;
|
||||
public const uint DataEmbraceDmgH = 40000;
|
||||
public const float DataSphereDistance = 25.0f;
|
||||
public const float DataSphereAngleOffset = MathFunctions.PI / 2;
|
||||
public const float DataGroundPositionZ = 11.30809f;
|
||||
}
|
||||
|
||||
[Script]
|
||||
public class boss_prince_taldaram : BossAI
|
||||
{
|
||||
public boss_prince_taldaram(Creature creature) : base(creature, DataTypes.PrinceTaldaram)
|
||||
{
|
||||
me.SetDisableGravity(true);
|
||||
_embraceTakenDamage = 0;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
_flameSphereTargetGUID.Clear();
|
||||
_embraceTargetGUID.Clear();
|
||||
_embraceTakenDamage = 0;
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(TextIds.SayAggro);
|
||||
_events.ScheduleEvent(Misc.EventBloodthirst, 10000);
|
||||
_events.ScheduleEvent(Misc.EventVanish, RandomHelper.URand(25000, 35000));
|
||||
_events.ScheduleEvent(Misc.EventConjureFlameSpheres, 5000);
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
base.JustSummoned(summon);
|
||||
|
||||
switch (summon.GetEntry())
|
||||
{
|
||||
case CreatureIds.FlameSphere1:
|
||||
case CreatureIds.FlameSphere2:
|
||||
case CreatureIds.FlameSphere3:
|
||||
summon.GetAI().SetGUID(_flameSphereTargetGUID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Misc.EventBloodthirst:
|
||||
DoCast(me, SpellIds.Bloodthirst);
|
||||
_events.ScheduleEvent(Misc.EventBloodthirst, 10000);
|
||||
break;
|
||||
case Misc.EventConjureFlameSpheres:
|
||||
// random target?
|
||||
Unit victim = me.GetVictim();
|
||||
if (victim)
|
||||
{
|
||||
_flameSphereTargetGUID = victim.GetGUID();
|
||||
DoCast(victim, SpellIds.ConjureFlameSphere);
|
||||
}
|
||||
_events.ScheduleEvent(Misc.EventConjureFlameSpheres, 15000);
|
||||
break;
|
||||
case Misc.EventVanish:
|
||||
{
|
||||
var players = me.GetMap().GetPlayers();
|
||||
uint targets = 0;
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player && player.IsAlive())
|
||||
++targets;
|
||||
}
|
||||
|
||||
if (targets > 2)
|
||||
{
|
||||
Talk(TextIds.SayVanish);
|
||||
DoCast(me, SpellIds.Vanish);
|
||||
me.SetInCombatState(true); // Prevents the boss from resetting
|
||||
_events.DelayEvents(500);
|
||||
_events.ScheduleEvent(Misc.EventJustVanished, 500);
|
||||
Unit embraceTarget = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (embraceTarget)
|
||||
_embraceTargetGUID = embraceTarget.GetGUID();
|
||||
}
|
||||
_events.ScheduleEvent(Misc.EventVanish, RandomHelper.URand(25000, 35000));
|
||||
break;
|
||||
}
|
||||
case Misc.EventJustVanished:
|
||||
{
|
||||
Unit embraceTarget = GetEmbraceTarget();
|
||||
if (embraceTarget)
|
||||
{
|
||||
me.GetMotionMaster().Clear();
|
||||
me.SetSpeedRate(UnitMoveType.Walk, 2.0f);
|
||||
me.GetMotionMaster().MoveChase(embraceTarget);
|
||||
}
|
||||
_events.ScheduleEvent(Misc.EventVanished, 1300);
|
||||
}
|
||||
break;
|
||||
case Misc.EventVanished:
|
||||
{
|
||||
Unit embraceTarget = GetEmbraceTarget();
|
||||
if (embraceTarget)
|
||||
DoCast(embraceTarget, SpellIds.EmbraceOfTheVampyr);
|
||||
Talk(TextIds.SayFeed);
|
||||
me.GetMotionMaster().Clear();
|
||||
me.SetSpeedRate(UnitMoveType.Walk, 1.0f);
|
||||
me.GetMotionMaster().MoveChase(me.GetVictim());
|
||||
_events.ScheduleEvent(Misc.EventFeeding, 20000);
|
||||
}
|
||||
break;
|
||||
case Misc.EventFeeding:
|
||||
_embraceTargetGUID.Clear();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit doneBy, ref uint damage)
|
||||
{
|
||||
Unit embraceTarget = GetEmbraceTarget();
|
||||
|
||||
if (embraceTarget && embraceTarget.IsAlive())
|
||||
{
|
||||
_embraceTakenDamage += damage;
|
||||
if (_embraceTakenDamage > DungeonMode<uint>(Misc.DataEmbraceDmg, Misc.DataEmbraceDmgH))
|
||||
{
|
||||
_embraceTargetGUID.Clear();
|
||||
me.CastStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Talk(TextIds.SayDeath);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
if (!victim.IsTypeId(TypeId.Player))
|
||||
return;
|
||||
|
||||
if (victim.GetGUID() == _embraceTargetGUID)
|
||||
_embraceTargetGUID.Clear();
|
||||
|
||||
Talk(TextIds.SaySlay);
|
||||
}
|
||||
|
||||
public bool CheckSpheres()
|
||||
{
|
||||
for (byte i = 0; i < 2; ++i)
|
||||
{
|
||||
if (instance.GetData(DataTypes.Sphere1 + i) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
RemovePrison();
|
||||
return true;
|
||||
}
|
||||
|
||||
Unit GetEmbraceTarget()
|
||||
{
|
||||
if (!_embraceTargetGUID.IsEmpty())
|
||||
return Global.ObjAccessor.GetUnit(me, _embraceTargetGUID);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void RemovePrison()
|
||||
{
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
me.RemoveAurasDueToSpell(SpellIds.BeamVisual);
|
||||
me.SetHomePosition(me.GetPositionX(), me.GetPositionY(), Misc.DataGroundPositionZ, me.GetOrientation());
|
||||
DoCast(SpellIds.HoverFall);
|
||||
me.SetDisableGravity(false);
|
||||
me.GetMotionMaster().MoveLand(0, me.GetHomePosition());
|
||||
Talk(TextIds.SayWarning);
|
||||
instance.HandleGameObject(instance.GetGuidData(DataTypes.PrinceTaldaramPlatform), true);
|
||||
}
|
||||
|
||||
ObjectGuid _flameSphereTargetGUID;
|
||||
ObjectGuid _embraceTargetGUID;
|
||||
uint _embraceTakenDamage;
|
||||
}
|
||||
|
||||
[Script] // 30106, 31686, 31687 - Flame Sphere
|
||||
class npc_prince_taldaram_flame_sphere : ScriptedAI
|
||||
{
|
||||
public npc_prince_taldaram_flame_sphere(Creature creature) : base(creature)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
DoCast(me, SpellIds.FlameSphereSpawnEffect, true);
|
||||
DoCast(me, SpellIds.FlameSphereVisual, true);
|
||||
|
||||
_flameSphereTargetGUID.Clear();
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(Misc.EventStartMove, 3 * Time.InMilliseconds);
|
||||
_events.ScheduleEvent(Misc.EventDespawn, 13 * Time.InMilliseconds);
|
||||
}
|
||||
|
||||
public override void SetGUID(ObjectGuid guid, int id = 0)
|
||||
{
|
||||
_flameSphereTargetGUID = guid;
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who) { }
|
||||
|
||||
public override void MoveInLineOfSight(Unit who) { }
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Misc.EventStartMove:
|
||||
{
|
||||
DoCast(me, SpellIds.FlameSpherePeriodic, true);
|
||||
|
||||
/// @todo: find correct values
|
||||
float angleOffset = 0.0f;
|
||||
float distOffset = Misc.DataSphereDistance;
|
||||
|
||||
switch (me.GetEntry())
|
||||
{
|
||||
case CreatureIds.FlameSphere1:
|
||||
break;
|
||||
case CreatureIds.FlameSphere2:
|
||||
angleOffset = Misc.DataSphereAngleOffset;
|
||||
break;
|
||||
case CreatureIds.FlameSphere3:
|
||||
angleOffset = -Misc.DataSphereAngleOffset;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
Unit sphereTarget = Global.ObjAccessor.GetUnit(me, _flameSphereTargetGUID);
|
||||
if (!sphereTarget)
|
||||
return;
|
||||
|
||||
float angle = me.GetAngle(sphereTarget) + angleOffset;
|
||||
float x = me.GetPositionX() + distOffset * (float)Math.Cos(angle);
|
||||
float y = me.GetPositionY() + distOffset * (float)Math.Sin(angle);
|
||||
|
||||
/// @todo: correct speed
|
||||
me.GetMotionMaster().MovePoint(0, x, y, me.GetPositionZ());
|
||||
break;
|
||||
}
|
||||
case Misc.EventDespawn:
|
||||
DoCast(me, SpellIds.FlameSphereDeathEffect, true);
|
||||
me.DespawnOrUnsummon(1000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ObjectGuid _flameSphereTargetGUID;
|
||||
}
|
||||
|
||||
[Script] // 193093, 193094 - Ancient Nerubian Device
|
||||
class go_prince_taldaram_sphere : GameObjectScript
|
||||
{
|
||||
public go_prince_taldaram_sphere() : base("go_prince_taldaram_sphere") { }
|
||||
|
||||
public override bool OnGossipHello(Player player, GameObject go)
|
||||
{
|
||||
InstanceScript instance = go.GetInstanceScript();
|
||||
if (instance == null)
|
||||
return false;
|
||||
|
||||
Creature PrinceTaldaram = ObjectAccessor.GetCreature(go, instance.GetGuidData(DataTypes.PrinceTaldaram));
|
||||
if (PrinceTaldaram && PrinceTaldaram.IsAlive())
|
||||
{
|
||||
go.SetFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
go.SetGoState(GameObjectState.Active);
|
||||
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GameObjectIds.Sphere1:
|
||||
instance.SetData(DataTypes.Sphere1, (uint)EncounterState.InProgress);
|
||||
PrinceTaldaram.GetAI().Talk(TextIds.Say1);
|
||||
break;
|
||||
case GameObjectIds.Sphere2:
|
||||
instance.SetData(DataTypes.Sphere2, (uint)EncounterState.InProgress);
|
||||
PrinceTaldaram.GetAI().Talk(TextIds.Say1);
|
||||
break;
|
||||
}
|
||||
|
||||
PrinceTaldaram.GetAI<boss_prince_taldaram>().CheckSpheres();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 55931 - Conjure Flame Sphere
|
||||
class spell_prince_taldaram_conjure_flame_sphere : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.FlameSphereSummon1, SpellIds.FlameSphereSummon2, SpellIds.FlameSphereSummon3);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
caster.CastSpell(caster, SpellIds.FlameSphereSummon1, true);
|
||||
|
||||
if (caster.GetMap().IsHeroic())
|
||||
{
|
||||
caster.CastSpell(caster, SpellIds.FlameSphereSummon2, true);
|
||||
caster.CastSpell(caster, SpellIds.FlameSphereSummon3, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.Dummy));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 55895, 59511, 59512 - Flame Sphere Summon
|
||||
class spell_prince_taldaram_flame_sphere_summon : SpellScript
|
||||
{
|
||||
void SetDest(ref SpellDestination dest)
|
||||
{
|
||||
dest.RelocateOffset(new Position(0.0f, 0.0f, 5.5f, 0.0f));
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnDestinationTargetSelect.Add(new DestinationTargetSelectHandler(SetDest, 0, Targets.DestCaster));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* 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.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.Ahnkahet
|
||||
{
|
||||
struct DataTypes
|
||||
{
|
||||
// Encounter States/Boss GUIDs
|
||||
public const uint ElderNadox = 0;
|
||||
public const uint PrinceTaldaram = 1;
|
||||
public const uint JedogaShadowseeker = 2;
|
||||
public const uint Amanitar = 3;
|
||||
public const uint HeraldVolazj = 4;
|
||||
|
||||
// Additional Data
|
||||
public const uint Sphere1 = 5;
|
||||
public const uint Sphere2 = 6;
|
||||
public const uint PrinceTaldaramPlatform = 7;
|
||||
public const uint PlJedogaTarget = 8;
|
||||
public const uint AddJedogaVictim = 9;
|
||||
public const uint AddJedogaInitiand = 10;
|
||||
public const uint JedogaTriggerSwitch = 11;
|
||||
public const uint JedogaResetInitiands = 12;
|
||||
public const uint AllInitiandDead = 13;
|
||||
}
|
||||
|
||||
struct AKCreatureIds
|
||||
{
|
||||
public const uint ElderNadox = 29309;
|
||||
public const uint PrinceTaldaram = 29308;
|
||||
public const uint JedogaShadowseeker = 29310;
|
||||
public const uint Amanitar = 30258;
|
||||
public const uint HeraldVolazj = 29311;
|
||||
|
||||
// Elder Nadox
|
||||
public const uint AhnkaharGuardian = 30176;
|
||||
public const uint AhnkaharSwarmer = 30178;
|
||||
|
||||
// Jedoga Shadowseeker
|
||||
public const uint Initiand = 30114;
|
||||
public const uint JedogaController = 30181;
|
||||
|
||||
// Herald Volazj
|
||||
//public const uint TwistedVisage1 = 30621,
|
||||
//public const uint TwistedVisage2 = 30622,
|
||||
//public const uint TwistedVisage3 = 30623,
|
||||
//public const uint TwistedVisage4 = 30624,
|
||||
public const uint TwistedVisage = 30625;
|
||||
}
|
||||
|
||||
struct GameObjectIds
|
||||
{
|
||||
public const uint PrinceTaldaramGate = 192236;
|
||||
public const uint PrinceTaldaramPlatform = 193564;
|
||||
public const uint Sphere1 = 193093;
|
||||
public const uint Sphere2 = 193094;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class instance_ahnkahet : InstanceMapScript
|
||||
{
|
||||
public instance_ahnkahet() : base("instance_ahnkahet", 619) { }
|
||||
|
||||
class instance_ahnkahet_InstanceScript : InstanceScript
|
||||
{
|
||||
public instance_ahnkahet_InstanceScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("AK");
|
||||
SetBossNumber(DataTypes.HeraldVolazj + 1);
|
||||
LoadDoorData(new DoorData(GameObjectIds.PrinceTaldaramGate, DataTypes.PrinceTaldaram, DoorType.Passage));
|
||||
|
||||
SwitchTrigger = 0;
|
||||
|
||||
SpheresState[0] = 0;
|
||||
SpheresState[1] = 0;
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
case AKCreatureIds.ElderNadox:
|
||||
ElderNadoxGUID = creature.GetGUID();
|
||||
break;
|
||||
case AKCreatureIds.PrinceTaldaram:
|
||||
PrinceTaldaramGUID = creature.GetGUID();
|
||||
break;
|
||||
case AKCreatureIds.JedogaShadowseeker:
|
||||
JedogaShadowseekerGUID = creature.GetGUID();
|
||||
break;
|
||||
case AKCreatureIds.Amanitar:
|
||||
AmanitarGUID = creature.GetGUID();
|
||||
break;
|
||||
case AKCreatureIds.HeraldVolazj:
|
||||
HeraldVolazjGUID = creature.GetGUID();
|
||||
break;
|
||||
case AKCreatureIds.Initiand:
|
||||
InitiandGUIDs.Add(creature.GetGUID());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectCreate(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GameObjectIds.PrinceTaldaramPlatform:
|
||||
PrinceTaldaramPlatformGUID = go.GetGUID();
|
||||
if (GetBossState(DataTypes.PrinceTaldaram) == EncounterState.Done)
|
||||
HandleGameObject(ObjectGuid.Empty, true, go);
|
||||
break;
|
||||
case GameObjectIds.Sphere1:
|
||||
if (SpheresState[0] != 0)
|
||||
{
|
||||
go.SetGoState(GameObjectState.Active);
|
||||
go.SetFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
}
|
||||
else
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
break;
|
||||
case GameObjectIds.Sphere2:
|
||||
if (SpheresState[1] != 0)
|
||||
{
|
||||
go.SetGoState(GameObjectState.Active);
|
||||
go.SetFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
}
|
||||
else
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
break;
|
||||
case GameObjectIds.PrinceTaldaramGate:
|
||||
AddDoor(go, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectRemove(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GameObjectIds.PrinceTaldaramGate:
|
||||
AddDoor(go, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetData(uint type, uint data)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.Sphere1:
|
||||
case DataTypes.Sphere2:
|
||||
SpheresState[type - DataTypes.Sphere1] = data;
|
||||
break;
|
||||
case DataTypes.JedogaTriggerSwitch:
|
||||
SwitchTrigger = (byte)data;
|
||||
break;
|
||||
case DataTypes.JedogaResetInitiands:
|
||||
foreach (ObjectGuid guid in InitiandGUIDs)
|
||||
{
|
||||
Creature creature = instance.GetCreature(guid);
|
||||
if (creature)
|
||||
{
|
||||
creature.Respawn();
|
||||
if (!creature.IsInEvadeMode())
|
||||
creature.GetAI().EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.Sphere1:
|
||||
case DataTypes.Sphere2:
|
||||
return SpheresState[type - DataTypes.Sphere1];
|
||||
case DataTypes.AllInitiandDead:
|
||||
foreach (ObjectGuid guid in InitiandGUIDs)
|
||||
{
|
||||
Creature cr = instance.GetCreature(guid);
|
||||
if (!cr || cr.IsAlive())
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
case DataTypes.JedogaTriggerSwitch:
|
||||
return SwitchTrigger;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void SetGuidData(uint type, ObjectGuid data)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.AddJedogaVictim:
|
||||
JedogaSacrifices = data;
|
||||
break;
|
||||
case DataTypes.PlJedogaTarget:
|
||||
JedogaTarget = data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGuidData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.ElderNadox:
|
||||
return ElderNadoxGUID;
|
||||
case DataTypes.PrinceTaldaram:
|
||||
return PrinceTaldaramGUID;
|
||||
case DataTypes.JedogaShadowseeker:
|
||||
return JedogaShadowseekerGUID;
|
||||
case DataTypes.Amanitar:
|
||||
return AmanitarGUID;
|
||||
case DataTypes.HeraldVolazj:
|
||||
return HeraldVolazjGUID;
|
||||
case DataTypes.PrinceTaldaramPlatform:
|
||||
return PrinceTaldaramPlatformGUID;
|
||||
case DataTypes.AddJedogaInitiand:
|
||||
{
|
||||
List<ObjectGuid> vInitiands = new List<ObjectGuid>();
|
||||
foreach (ObjectGuid guid in InitiandGUIDs)
|
||||
{
|
||||
Creature cr = instance.GetCreature(guid);
|
||||
if (cr && cr.IsAlive())
|
||||
vInitiands.Add(guid);
|
||||
}
|
||||
if (vInitiands.Empty())
|
||||
return ObjectGuid.Empty;
|
||||
|
||||
return vInitiands.SelectRandom();
|
||||
}
|
||||
case DataTypes.AddJedogaVictim:
|
||||
return JedogaSacrifices;
|
||||
case DataTypes.PlJedogaTarget:
|
||||
return JedogaTarget;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
public override bool SetBossState(uint type, EncounterState state)
|
||||
{
|
||||
if (!base.SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.JedogaShadowseeker:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
foreach (ObjectGuid guid in InitiandGUIDs)
|
||||
{
|
||||
Creature cr = instance.GetCreature(guid);
|
||||
if (cr)
|
||||
cr.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteSaveDataMore(string data)
|
||||
{
|
||||
data += SpheresState[0] + ' ' + SpheresState[1];
|
||||
}
|
||||
|
||||
void ReadSaveDataMore(string data)
|
||||
{
|
||||
data += SpheresState[0];
|
||||
data += SpheresState[1];
|
||||
}
|
||||
|
||||
ObjectGuid ElderNadoxGUID;
|
||||
ObjectGuid PrinceTaldaramGUID;
|
||||
ObjectGuid JedogaShadowseekerGUID;
|
||||
ObjectGuid AmanitarGUID;
|
||||
ObjectGuid HeraldVolazjGUID;
|
||||
|
||||
ObjectGuid PrinceTaldaramPlatformGUID;
|
||||
ObjectGuid JedogaSacrifices;
|
||||
ObjectGuid JedogaTarget;
|
||||
|
||||
List<ObjectGuid> InitiandGUIDs = new List<ObjectGuid>();
|
||||
|
||||
uint[] SpheresState = new uint[2];
|
||||
byte SwitchTrigger;
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_ahnkahet_InstanceScript(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,649 @@
|
||||
/*
|
||||
* 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.AzjolNerub.Anubarak
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint Emerge = 53500;
|
||||
public const uint Submerge = 53421;
|
||||
public const uint ImpaleAura = 53456;
|
||||
public const uint ImpaleVisual = 53455;
|
||||
public const uint ImpaleDamage = 53454;
|
||||
public const uint LeechingSwarm = 53467;
|
||||
public const uint Pound = 59433;
|
||||
public const uint PoundDamage = 59432;
|
||||
public const uint CarrionBeetles = 53520;
|
||||
public const uint CarrionBeetle = 53521;
|
||||
|
||||
public const uint SummonDarter = 53599;
|
||||
public const uint SummonAssassin = 53609;
|
||||
public const uint SummonGuardian = 53614;
|
||||
public const uint SummonVenomancer = 53615;
|
||||
|
||||
public const uint Dart = 59349;
|
||||
public const uint Backstab = 52540;
|
||||
public const uint AssassinVisual = 53611;
|
||||
public const uint SunderArmor = 53618;
|
||||
public const uint PoisonBolt = 53617;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
public const uint WorldTrigger = 22515;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SaySlay = 1;
|
||||
public const uint SayDeath = 2;
|
||||
public const uint SayLocust = 3;
|
||||
public const uint SaySubmerge = 4;
|
||||
public const uint SayIntro = 5;
|
||||
}
|
||||
|
||||
struct EventIds
|
||||
{
|
||||
public const uint Pound = 1;
|
||||
public const uint Impale = 2;
|
||||
public const uint LeechingSwarm = 3;
|
||||
public const uint CarrionBeetles = 4;
|
||||
public const uint Submerge = 5; // Use Event For This So We Don'T Submerge Mid-Cast
|
||||
public const uint Darter = 6;
|
||||
public const uint Assassin = 7;
|
||||
public const uint Guardian = 8;
|
||||
public const uint Venomancer = 9;
|
||||
public const uint CloseDoor = 10;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint AchievGottaGoStartEvent = 20381;
|
||||
|
||||
public const byte PhaseEmerge = 1;
|
||||
public const byte PhaseSubmerge = 2;
|
||||
|
||||
public const int GuidTypePet = 0;
|
||||
public const int GuidTypeImpale = 1;
|
||||
|
||||
public const byte SummonGroupWorldTriggerGuardian = 1;
|
||||
|
||||
public const int ActionPetDied = 1;
|
||||
public const int ActionPetEvade = 2;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_anub_arak : BossAI
|
||||
{
|
||||
public boss_anub_arak(Creature creature) : base(creature, ANDataTypes.Anubarak) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable);
|
||||
instance.DoStopCriteriaTimer(CriteriaTimedTypes.Event, Misc.AchievGottaGoStartEvent);
|
||||
_nextSubmerge = 75;
|
||||
_petCount = 0;
|
||||
}
|
||||
|
||||
public override bool CanAIAttack(Unit victim) { return true; } // do not check boundary here
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
base.EnterCombat(who);
|
||||
|
||||
GameObject door = instance.GetGameObject(ANDataTypes.AnubarakWall);
|
||||
if (door)
|
||||
door.SetGoState(GameObjectState.Active); // open door for now
|
||||
GameObject door2 = instance.GetGameObject(ANDataTypes.AnubarakWall2);
|
||||
if (door2)
|
||||
door2.SetGoState(GameObjectState.Active);
|
||||
|
||||
Talk(TextIds.SayAggro);
|
||||
instance.DoStartCriteriaTimer(CriteriaTimedTypes.Event, Misc.AchievGottaGoStartEvent);
|
||||
|
||||
_events.SetPhase(Misc.PhaseEmerge);
|
||||
_events.ScheduleEvent(EventIds.CloseDoor, TimeSpan.FromSeconds(5));
|
||||
_events.ScheduleEvent(EventIds.Pound, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(4), 0, Misc.PhaseEmerge);
|
||||
_events.ScheduleEvent(EventIds.LeechingSwarm, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(7), 0, Misc.PhaseEmerge);
|
||||
_events.ScheduleEvent(EventIds.CarrionBeetles, TimeSpan.FromSeconds(14), TimeSpan.FromSeconds(17), 0, Misc.PhaseEmerge);
|
||||
|
||||
// set up world triggers
|
||||
List<TempSummon> summoned;
|
||||
me.SummonCreatureGroup(Misc.SummonGroupWorldTriggerGuardian, out summoned);
|
||||
if (summoned.Empty()) // something went wrong
|
||||
{
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
return;
|
||||
}
|
||||
_guardianTrigger = summoned.First().GetGUID();
|
||||
|
||||
Creature trigger = DoSummon(CreatureIds.WorldTrigger, me.GetPosition(), 0u, TempSummonType.ManualDespawn);
|
||||
if (trigger)
|
||||
_assassinTrigger = trigger.GetGUID();
|
||||
else
|
||||
{
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
summons.DespawnAll();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EventIds.CloseDoor:
|
||||
GameObject door = instance.GetGameObject(ANDataTypes.AnubarakWall);
|
||||
if (door)
|
||||
door.SetGoState(GameObjectState.Ready);
|
||||
GameObject door2 = instance.GetGameObject(ANDataTypes.AnubarakWall2);
|
||||
if (door2)
|
||||
door2.SetGoState(GameObjectState.Ready);
|
||||
break;
|
||||
case EventIds.Pound:
|
||||
DoCastVictim(SpellIds.Pound);
|
||||
_events.Repeat(TimeSpan.FromSeconds(26), TimeSpan.FromSeconds(32));
|
||||
break;
|
||||
case EventIds.LeechingSwarm:
|
||||
Talk(TextIds.SayLocust);
|
||||
DoCastAOE(SpellIds.LeechingSwarm);
|
||||
_events.Repeat(TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(28));
|
||||
break;
|
||||
case EventIds.CarrionBeetles:
|
||||
DoCastAOE(SpellIds.CarrionBeetles);
|
||||
_events.Repeat(TimeSpan.FromSeconds(24), TimeSpan.FromSeconds(27));
|
||||
break;
|
||||
case EventIds.Impale:
|
||||
Creature impaleTarget = ObjectAccessor.GetCreature(me, _impaleTarget);
|
||||
if (impaleTarget)
|
||||
DoCast(impaleTarget, SpellIds.ImpaleDamage, true);
|
||||
break;
|
||||
case EventIds.Submerge:
|
||||
Talk(TextIds.SaySubmerge);
|
||||
DoCastSelf(SpellIds.Submerge);
|
||||
break;
|
||||
case EventIds.Darter:
|
||||
{
|
||||
List<Creature> triggers = new List<Creature>();
|
||||
me.GetCreatureListWithEntryInGrid(triggers, CreatureIds.WorldTrigger);
|
||||
if (!triggers.Empty())
|
||||
{
|
||||
var it = triggers.SelectRandom();
|
||||
it.CastSpell(it, SpellIds.SummonDarter, true);
|
||||
_events.Repeat(TimeSpan.FromSeconds(11));
|
||||
}
|
||||
else
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
break;
|
||||
}
|
||||
case EventIds.Assassin:
|
||||
{
|
||||
Creature trigger = ObjectAccessor.GetCreature(me, _assassinTrigger);
|
||||
if (trigger)
|
||||
{
|
||||
trigger.CastSpell(trigger, SpellIds.SummonAssassin, true);
|
||||
trigger.CastSpell(trigger, SpellIds.SummonAssassin, true);
|
||||
if (_assassinCount > 2)
|
||||
{
|
||||
_assassinCount -= 2;
|
||||
_events.Repeat(TimeSpan.FromSeconds(20));
|
||||
}
|
||||
else
|
||||
_assassinCount = 0;
|
||||
}
|
||||
else // something went wrong
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
break;
|
||||
}
|
||||
case EventIds.Guardian:
|
||||
{
|
||||
Creature trigger = ObjectAccessor.GetCreature(me, _guardianTrigger);
|
||||
if (trigger)
|
||||
{
|
||||
trigger.CastSpell(trigger, SpellIds.SummonGuardian, true);
|
||||
trigger.CastSpell(trigger, SpellIds.SummonGuardian, true);
|
||||
if (_guardianCount > 2)
|
||||
{
|
||||
_guardianCount -= 2;
|
||||
_events.Repeat(TimeSpan.FromSeconds(20));
|
||||
}
|
||||
else
|
||||
_guardianCount = 0;
|
||||
}
|
||||
else
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
}
|
||||
break;
|
||||
case EventIds.Venomancer:
|
||||
{
|
||||
Creature trigger = ObjectAccessor.GetCreature(me, _guardianTrigger);
|
||||
if (trigger)
|
||||
{
|
||||
trigger.CastSpell(trigger, SpellIds.SummonVenomancer, true);
|
||||
trigger.CastSpell(trigger, SpellIds.SummonVenomancer, true);
|
||||
if (_venomancerCount > 2)
|
||||
{
|
||||
_venomancerCount -= 2;
|
||||
_events.Repeat(TimeSpan.FromSeconds(20));
|
||||
}
|
||||
else
|
||||
_venomancerCount = 0;
|
||||
}
|
||||
else
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
});
|
||||
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(TextIds.SayDeath);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
if (victim.IsTypeId(TypeId.Player))
|
||||
Talk(TextIds.SaySlay);
|
||||
}
|
||||
|
||||
public override void SetGUID(ObjectGuid guid, int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Misc.GuidTypePet:
|
||||
{
|
||||
Creature creature = ObjectAccessor.GetCreature(me, guid);
|
||||
if (creature)
|
||||
JustSummoned(creature);
|
||||
else // something has gone horribly wrong
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
break;
|
||||
}
|
||||
case Misc.GuidTypeImpale:
|
||||
_impaleTarget = guid;
|
||||
_events.ScheduleEvent(EventIds.Impale, TimeSpan.FromSeconds(4));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case Misc.ActionPetDied:
|
||||
if (_petCount == 0) // underflow check - something has gone horribly wrong
|
||||
{
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
return;
|
||||
}
|
||||
if (--_petCount == 0) // last pet died, emerge
|
||||
{
|
||||
me.RemoveAurasDueToSpell(SpellIds.Submerge);
|
||||
me.RemoveAurasDueToSpell(SpellIds.ImpaleAura);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable);
|
||||
DoCastSelf(SpellIds.Emerge);
|
||||
_events.SetPhase(Misc.PhaseEmerge);
|
||||
_events.ScheduleEvent(EventIds.Pound, TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(18), 0, Misc.PhaseEmerge);
|
||||
_events.ScheduleEvent(EventIds.LeechingSwarm, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), 0, Misc.PhaseEmerge);
|
||||
_events.ScheduleEvent(EventIds.CarrionBeetles, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15), 0, Misc.PhaseEmerge);
|
||||
}
|
||||
break;
|
||||
case Misc.ActionPetEvade:
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit source, ref uint damage)
|
||||
{
|
||||
if (me.HasAura(SpellIds.Submerge))
|
||||
damage = 0;
|
||||
else
|
||||
if (_nextSubmerge != 0 && me.HealthBelowPctDamaged((int)_nextSubmerge, damage))
|
||||
{
|
||||
_events.CancelEvent(EventIds.Submerge);
|
||||
_events.ScheduleEvent(EventIds.Submerge, 0, 0, Misc.PhaseEmerge);
|
||||
_nextSubmerge = _nextSubmerge - 25;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SpellHit(Unit whose, SpellInfo spell)
|
||||
{
|
||||
if (spell.Id == SpellIds.Submerge)
|
||||
{
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable);
|
||||
me.RemoveAurasDueToSpell(SpellIds.LeechingSwarm);
|
||||
DoCastSelf(SpellIds.ImpaleAura, true);
|
||||
|
||||
_events.SetPhase(Misc.PhaseSubmerge);
|
||||
switch (_nextSubmerge)
|
||||
{
|
||||
case 50: // first submerge phase
|
||||
_assassinCount = 4;
|
||||
_guardianCount = 2;
|
||||
_venomancerCount = 0;
|
||||
break;
|
||||
case 25: // second submerge phase
|
||||
_assassinCount = 6;
|
||||
_guardianCount = 2;
|
||||
_venomancerCount = 2;
|
||||
break;
|
||||
case 0: // third submerge phase
|
||||
_assassinCount = 6;
|
||||
_guardianCount = 2;
|
||||
_venomancerCount = 2;
|
||||
_events.ScheduleEvent(EventIds.Darter, TimeSpan.FromSeconds(0), 0, Misc.PhaseSubmerge);
|
||||
break;
|
||||
}
|
||||
_petCount = (uint)(_guardianCount + _venomancerCount);
|
||||
if (_assassinCount != 0)
|
||||
_events.ScheduleEvent(EventIds.Assassin, TimeSpan.FromSeconds(0), 0, Misc.PhaseSubmerge);
|
||||
if (_guardianCount != 0)
|
||||
_events.ScheduleEvent(EventIds.Guardian, TimeSpan.FromSeconds(4), 0, Misc.PhaseSubmerge);
|
||||
if (_venomancerCount != 0)
|
||||
_events.ScheduleEvent(EventIds.Venomancer, TimeSpan.FromSeconds(20), 0, Misc.PhaseSubmerge);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid _impaleTarget;
|
||||
uint _nextSubmerge;
|
||||
uint _petCount;
|
||||
ObjectGuid _guardianTrigger;
|
||||
ObjectGuid _assassinTrigger;
|
||||
byte _assassinCount;
|
||||
byte _guardianCount;
|
||||
byte _venomancerCount;
|
||||
}
|
||||
|
||||
class npc_anubarak_pet_template : ScriptedAI
|
||||
{
|
||||
public npc_anubarak_pet_template(Creature creature, bool isLarge) : base(creature)
|
||||
{
|
||||
_instance = creature.GetInstanceScript();
|
||||
_isLarge = isLarge;
|
||||
}
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
|
||||
Creature anubarak = _instance.GetCreature(ANDataTypes.Anubarak);
|
||||
if (anubarak)
|
||||
anubarak.GetAI().SetGUID(me.GetGUID(), Misc.GuidTypePet);
|
||||
else
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
base.JustDied(killer);
|
||||
if (_isLarge)
|
||||
{
|
||||
Creature anubarak = _instance.GetCreature(ANDataTypes.Anubarak);
|
||||
if (anubarak)
|
||||
anubarak.GetAI().DoAction(Misc.ActionPetDied);
|
||||
}
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
Creature anubarak = _instance.GetCreature(ANDataTypes.Anubarak);
|
||||
if (anubarak)
|
||||
anubarak.GetAI().DoAction(Misc.ActionPetEvade);
|
||||
else
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
protected InstanceScript _instance;
|
||||
bool _isLarge;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anubarak_anub_ar_darter : npc_anubarak_pet_template
|
||||
{
|
||||
public npc_anubarak_anub_ar_darter(Creature creature) : base(creature, false) { }
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
DoCastAOE(SpellIds.Dart);
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anubarak_anub_ar_assassin : npc_anubarak_pet_template
|
||||
{
|
||||
public npc_anubarak_anub_ar_assassin(Creature creature) : base(creature, false)
|
||||
{
|
||||
_backstabTimer = 6 * Time.InMilliseconds;
|
||||
}
|
||||
|
||||
bool IsInBounds(Position jumpTo, List<AreaBoundary> boundary)
|
||||
{
|
||||
if (boundary == null)
|
||||
return true;
|
||||
foreach (var it in boundary)
|
||||
if (!it.IsWithinBoundary(jumpTo))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Position GetRandomPositionAround(Creature anubarak)
|
||||
{
|
||||
float DISTANCE_MIN = 10.0f;
|
||||
float DISTANCE_MAX = 30.0f;
|
||||
double angle = RandomHelper.NextDouble() * 2.0 * Math.PI;
|
||||
return new Position(anubarak.GetPositionX() + (float)(RandomHelper.FRand(DISTANCE_MIN, DISTANCE_MAX) * Math.Sin(angle)), anubarak.GetPositionY() + (float)(RandomHelper.FRand(DISTANCE_MIN, DISTANCE_MAX) * Math.Cos(angle)), anubarak.GetPositionZ());
|
||||
}
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
var boundary = _instance.GetBossBoundary(ANDataTypes.Anubarak);
|
||||
Creature anubarak = _instance.GetCreature(ANDataTypes.Anubarak);
|
||||
if (anubarak)
|
||||
{
|
||||
Position jumpTo;
|
||||
do
|
||||
jumpTo = GetRandomPositionAround(anubarak);
|
||||
while (!IsInBounds(jumpTo, boundary));
|
||||
me.GetMotionMaster().MoveJump(jumpTo, 40.0f, 40.0f);
|
||||
DoCastSelf(SpellIds.AssassinVisual, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (diff >= _backstabTimer)
|
||||
{
|
||||
if (me.GetVictim() && me.GetVictim().isInBack(me))
|
||||
DoCastVictim(SpellIds.Backstab);
|
||||
_backstabTimer = 6 * Time.InMilliseconds;
|
||||
}
|
||||
else
|
||||
_backstabTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (id == EventId.Jump)
|
||||
{
|
||||
me.RemoveAurasDueToSpell(SpellIds.AssassinVisual);
|
||||
DoZoneInCombat();
|
||||
}
|
||||
}
|
||||
|
||||
uint _backstabTimer;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anubarak_anub_ar_guardian : npc_anubarak_pet_template
|
||||
{
|
||||
public npc_anubarak_anub_ar_guardian(Creature creature) : base(creature, true)
|
||||
{
|
||||
_sunderTimer = 6 * Time.InMilliseconds;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (diff >= _sunderTimer)
|
||||
{
|
||||
DoCastVictim(SpellIds.SunderArmor);
|
||||
_sunderTimer = 12 * Time.InMilliseconds;
|
||||
}
|
||||
else
|
||||
_sunderTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
uint _sunderTimer;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anubarak_anub_ar_venomancer : npc_anubarak_pet_template
|
||||
{
|
||||
public npc_anubarak_anub_ar_venomancer(Creature creature) : base(creature, true)
|
||||
{
|
||||
_boltTimer = 5 * Time.InMilliseconds;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (diff >= _boltTimer)
|
||||
{
|
||||
DoCastVictim(SpellIds.PoisonBolt);
|
||||
_boltTimer = RandomHelper.URand(2, 3) * Time.InMilliseconds;
|
||||
}
|
||||
else
|
||||
_boltTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
uint _boltTimer;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anubarak_impale_target : NullCreatureAI
|
||||
{
|
||||
public npc_anubarak_impale_target(Creature creature) : base(creature) { }
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
Creature anubarak = me.GetInstanceScript().GetCreature(ANDataTypes.Anubarak);
|
||||
if (anubarak)
|
||||
{
|
||||
DoCastSelf(SpellIds.ImpaleVisual);
|
||||
me.DespawnOrUnsummon(TimeSpan.FromSeconds(6));
|
||||
anubarak.GetAI().SetGUID(me.GetGUID(), Misc.GuidTypeImpale);
|
||||
}
|
||||
else
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_anubarak_pound : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.PoundDamage);
|
||||
}
|
||||
|
||||
void HandleDummy(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
GetCaster().CastSpell(target, SpellIds.PoundDamage, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleDummy, 0, SpellEffectName.ApplyAura));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_anubarak_carrion_beetles : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.CarrionBeetle);
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect eff)
|
||||
{
|
||||
GetCaster().CastSpell(GetCaster(), SpellIds.CarrionBeetle, true);
|
||||
GetCaster().CastSpell(GetCaster(), SpellIds.CarrionBeetle, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(HandlePeriodic, 0, AuraType.PeriodicDummy));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,866 @@
|
||||
/*
|
||||
* 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.AzjolNerub.KrikthirTheGatewatcher
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
// Krik'Thir The Gatewatcher
|
||||
public const uint SubbossAggroTrigger = 52343;
|
||||
public const uint Swarm = 52440;
|
||||
public const uint MindFlay = 52586;
|
||||
public const uint CurseOfFatigue = 52592;
|
||||
public const uint Frenzy = 28747;
|
||||
|
||||
// Watchers - Shared
|
||||
public const uint WebWrap = 52086;
|
||||
public const uint WebWrapWrapped = 52087;
|
||||
public const uint InfectedBite = 52469;
|
||||
|
||||
// Watcher Gashra
|
||||
public const uint Enrage = 52470;
|
||||
// Watcher Narjil
|
||||
public const uint BlindingWebs = 52524;
|
||||
// Watcher Silthik
|
||||
public const uint PoisonSpray = 52493;
|
||||
|
||||
// Anub'Ar Warrior
|
||||
public const uint Cleave = 49806;
|
||||
public const uint Strike = 52532;
|
||||
|
||||
// Anub'Ar Skirmisher
|
||||
public const uint Charge = 52538;
|
||||
public const uint Backstab = 52540;
|
||||
public const uint FixtateTrigger = 52536;
|
||||
public const uint FixtateTriggered = 52537;
|
||||
|
||||
// Anub'Ar Shadowcaster
|
||||
public const uint ShadowBolt = 52534;
|
||||
public const uint ShadowNova = 52535;
|
||||
|
||||
// Skittering Infector
|
||||
public const uint AcidSplash = 52446;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint DataPetGroup = 0;
|
||||
|
||||
// Krik'thir the Gatewatcher
|
||||
public const uint EventSendGroup = 1;
|
||||
public const uint EventSwarm = 2;
|
||||
public const uint EventMindFlay = 3;
|
||||
public const uint EventFrenzy = 4;
|
||||
}
|
||||
|
||||
struct ActionIds
|
||||
{
|
||||
public const int GashraDied = 0;
|
||||
public const int NarjilDied = 1;
|
||||
public const int SilthikDied = 2;
|
||||
public const int WatcherEngaged = 3;
|
||||
public const int PetEngaged = 4;
|
||||
public const int PetEvade = 5;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SaySlay = 1;
|
||||
public const uint SayDeath = 2;
|
||||
public const uint SaySwarm = 3;
|
||||
public const uint SayPrefight = 4;
|
||||
public const uint SaySendGroup = 5;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_krik_thir : BossAI
|
||||
{
|
||||
public boss_krik_thir(Creature creature) : base(creature, ANDataTypes.KrikthirTheGatewatcher) { }
|
||||
|
||||
void SummonAdds()
|
||||
{
|
||||
if (instance.GetBossState(ANDataTypes.KrikthirTheGatewatcher) == EncounterState.Done)
|
||||
return;
|
||||
|
||||
for (byte i = 1; i <= 3; ++i)
|
||||
{
|
||||
List<TempSummon> summons;
|
||||
me.SummonCreatureGroup(i, out summons);
|
||||
|
||||
foreach (TempSummon summon in summons)
|
||||
summon.GetAI().SetData(Misc.DataPetGroup, i);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
_hadFrenzy = false;
|
||||
_petsInCombat = false;
|
||||
_watchersActive = 0;
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
}
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
SummonAdds();
|
||||
}
|
||||
|
||||
public override void JustRespawned()
|
||||
{
|
||||
base.JustRespawned();
|
||||
SummonAdds();
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
if (victim.IsTypeId(TypeId.Player))
|
||||
Talk(TextIds.SaySlay);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
summons.Clear();
|
||||
base.JustDied(killer);
|
||||
Talk(TextIds.SayDeath);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_petsInCombat = false;
|
||||
me.SetReactState(ReactStates.Aggressive);
|
||||
summons.DoZoneInCombat();
|
||||
|
||||
_events.CancelEvent(Misc.EventSendGroup);
|
||||
_events.ScheduleEvent(Misc.EventSwarm, TimeSpan.FromSeconds(5));
|
||||
_events.ScheduleEvent(Misc.EventMindFlay, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(3));
|
||||
|
||||
base.EnterCombat(who);
|
||||
}
|
||||
|
||||
public override void MoveInLineOfSight(Unit who)
|
||||
{
|
||||
if (!me.HasReactState(ReactStates.Passive))
|
||||
{
|
||||
base.MoveInLineOfSight(who);
|
||||
return;
|
||||
}
|
||||
|
||||
if (me.CanStartAttack(who, false) && me.IsWithinDistInMap(who, me.GetAttackDistance(who) + me.m_CombatDistance))
|
||||
EnterCombat(who);
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
summons.DespawnAll();
|
||||
_DespawnAtEvade();
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case -ANInstanceMisc.ActionGatewatcherGreet:
|
||||
if (!_hadGreet && me.IsAlive() && !me.IsInCombat() && !_petsInCombat)
|
||||
{
|
||||
_hadGreet = true;
|
||||
Talk(TextIds.SayPrefight);
|
||||
}
|
||||
break;
|
||||
case ActionIds.GashraDied:
|
||||
case ActionIds.NarjilDied:
|
||||
case ActionIds.SilthikDied:
|
||||
if (_watchersActive == 0) // something is wrong
|
||||
{
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
return;
|
||||
}
|
||||
if ((--_watchersActive) == 0) // if there are no watchers currently in combat...
|
||||
_events.RescheduleEvent(Misc.EventSendGroup, TimeSpan.FromSeconds(5)); // ...send the next watcher after the targets sooner
|
||||
break;
|
||||
case ActionIds.WatcherEngaged:
|
||||
++_watchersActive;
|
||||
break;
|
||||
case ActionIds.PetEngaged:
|
||||
if (_petsInCombat || me.IsInCombat())
|
||||
break;
|
||||
_petsInCombat = true;
|
||||
Talk(TextIds.SayAggro);
|
||||
_events.ScheduleEvent(Misc.EventSendGroup, TimeSpan.FromSeconds(70));
|
||||
break;
|
||||
case ActionIds.PetEvade:
|
||||
EnterEvadeMode(EvadeReason.Other);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim() && !_petsInCombat)
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
if (me.HealthBelowPct(10) && !_hadFrenzy)
|
||||
{
|
||||
_hadFrenzy = true;
|
||||
_events.ScheduleEvent(Misc.EventFrenzy, TimeSpan.FromSeconds(1));
|
||||
}
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Misc.EventSendGroup:
|
||||
DoCastAOE(SpellIds.SubbossAggroTrigger, true);
|
||||
_events.Repeat(TimeSpan.FromSeconds(70));
|
||||
break;
|
||||
case Misc.EventSwarm:
|
||||
DoCastAOE(SpellIds.Swarm);
|
||||
Talk(TextIds.SaySwarm);
|
||||
break;
|
||||
case Misc.EventMindFlay:
|
||||
DoCastVictim(SpellIds.MindFlay);
|
||||
_events.Repeat(TimeSpan.FromSeconds(9), TimeSpan.FromSeconds(11));
|
||||
break;
|
||||
case Misc.EventFrenzy:
|
||||
DoCastSelf(SpellIds.Frenzy);
|
||||
DoCastAOE(SpellIds.CurseOfFatigue);
|
||||
_events.Repeat(TimeSpan.FromSeconds(15));
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
});
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void SpellHit(Unit whose, SpellInfo spell)
|
||||
{
|
||||
if (spell.Id == SpellIds.SubbossAggroTrigger)
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
public override void SpellHitTarget(Unit who, SpellInfo spell)
|
||||
{
|
||||
if (spell.Id == SpellIds.SubbossAggroTrigger)
|
||||
Talk(TextIds.SaySendGroup);
|
||||
}
|
||||
|
||||
bool _hadGreet;
|
||||
bool _hadFrenzy;
|
||||
bool _petsInCombat;
|
||||
byte _watchersActive;
|
||||
}
|
||||
|
||||
class npc_gatewatcher_petAI : ScriptedAI
|
||||
{
|
||||
public npc_gatewatcher_petAI(Creature creature, bool isWatcher) : base(creature)
|
||||
{
|
||||
_instance = creature.GetInstanceScript();
|
||||
_isWatcher = isWatcher;
|
||||
}
|
||||
|
||||
public virtual void _EnterCombat() { }
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
if (_isWatcher)
|
||||
{
|
||||
_isWatcher = false;
|
||||
|
||||
TempSummon meSummon = me.ToTempSummon();
|
||||
if (meSummon)
|
||||
{
|
||||
Creature summoner = meSummon.GetSummonerCreatureBase();
|
||||
if (summoner)
|
||||
summoner.GetAI().DoAction(ActionIds.WatcherEngaged);
|
||||
}
|
||||
}
|
||||
|
||||
if (me.HasReactState(ReactStates.Passive))
|
||||
{
|
||||
List<Creature> others = new List<Creature>();
|
||||
me.GetCreatureListWithEntryInGrid(others, 0, 40.0f);
|
||||
foreach (Creature other in others)
|
||||
{
|
||||
if (other.GetAI().GetData(Misc.DataPetGroup) == _petGroup)
|
||||
{
|
||||
other.SetReactState(ReactStates.Aggressive);
|
||||
other.GetAI().AttackStart(who);
|
||||
}
|
||||
}
|
||||
|
||||
TempSummon meSummon = me.ToTempSummon();
|
||||
if (meSummon)
|
||||
{
|
||||
Creature summoner = meSummon.GetSummonerCreatureBase();
|
||||
if (summoner)
|
||||
summoner.GetAI().DoAction(ActionIds.PetEngaged);
|
||||
}
|
||||
}
|
||||
_EnterCombat();
|
||||
base.EnterCombat(who);
|
||||
}
|
||||
|
||||
public override void SetData(uint data, uint value)
|
||||
{
|
||||
if (data == Misc.DataPetGroup)
|
||||
{
|
||||
_petGroup = value;
|
||||
me.SetReactState(_petGroup != 0 ? ReactStates.Passive : ReactStates.Aggressive);
|
||||
}
|
||||
}
|
||||
|
||||
public override uint GetData(uint data)
|
||||
{
|
||||
if (data == Misc.DataPetGroup)
|
||||
return _petGroup;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void MoveInLineOfSight(Unit who)
|
||||
{
|
||||
if (!me.HasReactState(ReactStates.Passive))
|
||||
{
|
||||
base.MoveInLineOfSight(who);
|
||||
return;
|
||||
}
|
||||
|
||||
if (me.CanStartAttack(who, false) && me.IsWithinDistInMap(who, me.GetAttackDistance(who) + me.m_CombatDistance))
|
||||
EnterCombat(who);
|
||||
}
|
||||
|
||||
public override void SpellHit(Unit whose, SpellInfo spell)
|
||||
{
|
||||
if (spell.Id == SpellIds.SubbossAggroTrigger)
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
TempSummon meSummon = me.ToTempSummon();
|
||||
if (meSummon)
|
||||
{
|
||||
Creature summoner = meSummon.GetSummonerCreatureBase();
|
||||
if (summoner)
|
||||
summoner.GetAI().DoAction(ActionIds.PetEvade);
|
||||
else
|
||||
me.DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
base.EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
protected InstanceScript _instance;
|
||||
uint _petGroup;
|
||||
bool _isWatcher;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_watcher_gashra : npc_gatewatcher_petAI
|
||||
{
|
||||
public npc_watcher_gashra(Creature creature) : base(creature, true)
|
||||
{
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
DoCastSelf(SpellIds.Enrage);
|
||||
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(20));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(16), TimeSpan.FromSeconds(19), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.WebWrap);
|
||||
task.Repeat(TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(19));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(11), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.InfectedBite);
|
||||
task.Repeat(TimeSpan.FromSeconds(23), TimeSpan.FromSeconds(27));
|
||||
});
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Creature krikthir = _instance.GetCreature(ANDataTypes.KrikthirTheGatewatcher);
|
||||
if (krikthir && krikthir.IsAlive())
|
||||
krikthir.GetAI().DoAction(ActionIds.GashraDied);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_watcher_narjil : npc_gatewatcher_petAI
|
||||
{
|
||||
public npc_watcher_narjil(Creature creature) : base(creature, true) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(18), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.BlindingWebs);
|
||||
task.Repeat(TimeSpan.FromSeconds(23), TimeSpan.FromSeconds(27));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.WebWrap);
|
||||
task.Repeat(TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(19));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(11), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.InfectedBite);
|
||||
task.Repeat(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(25));
|
||||
});
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Creature krikthir = _instance.GetCreature(ANDataTypes.KrikthirTheGatewatcher);
|
||||
if (krikthir && krikthir.IsAlive())
|
||||
krikthir.GetAI().DoAction(ActionIds.NarjilDied);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_watcher_silthik : npc_gatewatcher_petAI
|
||||
{
|
||||
public npc_watcher_silthik(Creature creature) : base(creature, true) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(16), TimeSpan.FromSeconds(19), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.PoisonSpray);
|
||||
task.Repeat(TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(19));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(11), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.WebWrap);
|
||||
task.Repeat(TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(17));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.InfectedBite);
|
||||
task.Repeat(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(24));
|
||||
});
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Creature krikthir = _instance.GetCreature(ANDataTypes.KrikthirTheGatewatcher);
|
||||
if (krikthir && krikthir.IsAlive())
|
||||
krikthir.GetAI().DoAction(ActionIds.SilthikDied);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_warrior : npc_gatewatcher_petAI
|
||||
{
|
||||
public npc_anub_ar_warrior(Creature creature) : base(creature, false) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(9), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Cleave);
|
||||
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(16));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Strike);
|
||||
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(19));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_skirmisher : npc_gatewatcher_petAI
|
||||
{
|
||||
public npc_anub_ar_skirmisher(Creature creature) : base(creature, false) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.Charge);
|
||||
task.Repeat(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(25));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(9), task =>
|
||||
{
|
||||
if (me.GetVictim() && me.GetVictim().isInBack(me))
|
||||
DoCastVictim(SpellIds.Backstab);
|
||||
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(13));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void SpellHitTarget(Unit target, SpellInfo spell)
|
||||
{
|
||||
if (spell.Id == SpellIds.Charge && target)
|
||||
DoCast(target, SpellIds.FixtateTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_shadowcaster : npc_gatewatcher_petAI
|
||||
{
|
||||
public npc_anub_ar_shadowcaster(Creature creature) : base(creature, false) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(4), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.ShadowBolt);
|
||||
task.Repeat(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(4));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(14), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.ShadowNova);
|
||||
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(16));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_skittering_swarmer : ScriptedAI
|
||||
{
|
||||
public npc_skittering_swarmer(Creature creature) : base(creature) { }
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
Creature gatewatcher = me.GetInstanceScript().GetCreature(ANDataTypes.KrikthirTheGatewatcher);
|
||||
if (gatewatcher)
|
||||
{
|
||||
Unit target = gatewatcher.getAttackerForHelper();
|
||||
if (target)
|
||||
AttackStart(target);
|
||||
gatewatcher.GetAI().JustSummoned(me);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_skittering_infector : ScriptedAI
|
||||
{
|
||||
public npc_skittering_infector(Creature creature) : base(creature) { }
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
Creature gatewatcher = me.GetInstanceScript().GetCreature(ANDataTypes.KrikthirTheGatewatcher);
|
||||
if (gatewatcher)
|
||||
{
|
||||
Unit target = gatewatcher.getAttackerForHelper();
|
||||
if (target)
|
||||
AttackStart(target);
|
||||
gatewatcher.GetAI().JustSummoned(me);
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
DoCastAOE(SpellIds.AcidSplash);
|
||||
base.JustDied(killer);
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_gatewatcher_web_wrap : NullCreatureAI
|
||||
{
|
||||
public npc_gatewatcher_web_wrap(Creature creature) : base(creature) { }
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
TempSummon meSummon = me.ToTempSummon();
|
||||
if (meSummon)
|
||||
{
|
||||
Unit summoner = meSummon.GetSummoner();
|
||||
if (summoner)
|
||||
summoner.RemoveAurasDueToSpell(SpellIds.WebWrapWrapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_gatewatcher_subboss_trigger : SpellScript
|
||||
{
|
||||
void HandleTargets(List<WorldObject> targetList)
|
||||
{
|
||||
// Remove any Watchers that are already in combat
|
||||
foreach (var obj in targetList.ToList())
|
||||
{
|
||||
Creature creature = obj.ToCreature();
|
||||
if (creature)
|
||||
if (creature.IsAlive() && !creature.IsInCombat())
|
||||
continue;
|
||||
|
||||
targetList.Remove(obj);
|
||||
}
|
||||
|
||||
// Default to Krik'thir himself if he isn't engaged
|
||||
WorldObject target = null;
|
||||
if (GetCaster() && !GetCaster().IsInCombat())
|
||||
target = GetCaster();
|
||||
// Unless there are Watchers that aren't engaged yet
|
||||
if (!targetList.Empty())
|
||||
{
|
||||
// If there are, pick one of them at random
|
||||
target = targetList.SelectRandom();
|
||||
}
|
||||
// And hit only that one
|
||||
targetList.Clear();
|
||||
if (target)
|
||||
targetList.Add(target);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(HandleTargets, 0, Targets.UnitSrcAreaEntry));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_anub_ar_skirmisher_fixtate : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.FixtateTriggered);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
target.CastSpell(GetCaster(), SpellIds.FixtateTriggered, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_gatewatcher_web_wrap : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.WebWrapWrapped);
|
||||
}
|
||||
|
||||
void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.Expire)
|
||||
return;
|
||||
|
||||
Unit target = GetTarget();
|
||||
if (target)
|
||||
target.CastSpell(target, SpellIds.WebWrapWrapped, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectRemove.Add(new EffectApplyHandler(HandleEffectRemove, 0, AuraType.ModRoot, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_watch_him_die : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_watch_him_die() : base("achievement_watch_him_die") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
InstanceScript instance = target.GetInstanceScript();
|
||||
if (instance == null)
|
||||
return false;
|
||||
|
||||
foreach (uint watcherData in new[] { ANDataTypes.WatcherGashra, ANDataTypes.WatcherNarjil, ANDataTypes.WatcherSilthik })
|
||||
{
|
||||
Creature watcher = instance.GetCreature(watcherData);
|
||||
if (watcher)
|
||||
if (watcher.IsAlive())
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,943 @@
|
||||
/*
|
||||
* 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.Combat;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.AzjolNerub.Nadronox
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
// Hadronox
|
||||
public const uint WebFrontDoors = 53177;
|
||||
public const uint WebSideDoors = 53185;
|
||||
public const uint LeechPoison = 53030;
|
||||
public const uint LeechPoisonHeal = 53800;
|
||||
public const uint AcidCloud = 53400;
|
||||
public const uint WebGrab = 57731;
|
||||
public const uint PierceArmor = 53418;
|
||||
|
||||
// Anub'Ar Opponent Summoning Spells
|
||||
public const uint SummonChampionPeriodic = 53035;
|
||||
public const uint SummonCryptFiendPeriodic = 53037;
|
||||
public const uint SummonNecromancerPeriodic = 53036;
|
||||
public const uint SummonChampionTop = 53064;
|
||||
public const uint SummonCryptFiendTop = 53065;
|
||||
public const uint SummonNecromancerTop = 53066;
|
||||
public const uint SummonChampionBottom = 53090;
|
||||
public const uint SummonCryptFiendBottom = 53091;
|
||||
public const uint SummonNecromancerBottom = 53092;
|
||||
|
||||
// Anub'Ar Crusher
|
||||
public const uint Smash = 53318;
|
||||
public const uint Frenzy = 53801;
|
||||
|
||||
// Anub'Ar Foes - Shared
|
||||
public const uint Taunt = 53798;
|
||||
|
||||
// Anub'Ar Champion
|
||||
public const uint Rend = 59343;
|
||||
public const uint Pummel = 59344;
|
||||
|
||||
// Anub'Ar Crypt Guard
|
||||
public const uint CrushingWebs = 59347;
|
||||
public const uint InfectedWound = 59348;
|
||||
|
||||
// Anub'Ar Necromancer
|
||||
public const uint ShadowBolt = 53333;
|
||||
public const uint AnimateBones1 = 53334;
|
||||
public const uint AnimateBones2 = 53336;
|
||||
}
|
||||
|
||||
enum SummonGroups
|
||||
{
|
||||
Crusher1 = 1,
|
||||
Crusher2 = 2,
|
||||
Crusher3 = 3
|
||||
}
|
||||
|
||||
struct ActionIds
|
||||
{
|
||||
public const int HadronoxMove = 1;
|
||||
public const int CrusherEngaged = 2;
|
||||
public const int PackWalk = 3;
|
||||
}
|
||||
|
||||
struct Data
|
||||
{
|
||||
public const uint CrusherPackId = 1;
|
||||
public const uint HadronoxEnteredCombat = 2;
|
||||
public const uint HadronoxWebbedDoors = 3;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
public const uint Crusher = 28922;
|
||||
public const uint WorldtriggerLarge = 23472;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayCrusherAggro = 1;
|
||||
public const uint EmoteCrusherFrenzy = 2;
|
||||
public const uint EmoteHadronoxMove = 1;
|
||||
}
|
||||
|
||||
// Movement IDs used by the permanently spawning Anub'ar opponents - they are done in sequence, as one finishes, the next one starts
|
||||
enum MovementIds
|
||||
{
|
||||
None = 0,
|
||||
Outside,
|
||||
Downstairs,
|
||||
Downstairs2,
|
||||
Hadronox, // this one might have us take a detour to avoid pathfinding "through" the floor...
|
||||
HadronoxReal // while this one will always make us movechase
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public static Position[] hadronoxStep =
|
||||
{
|
||||
new Position(515.5848f, 544.2007f, 673.6272f),
|
||||
new Position(562.191f , 514.068f , 696.4448f),
|
||||
new Position(610.3828f, 518.6407f, 695.9385f),
|
||||
new Position(530.42f , 560.003f, 733.0308f)
|
||||
};
|
||||
|
||||
public static Position[] crusherWaypoints =
|
||||
{
|
||||
new Position(529.6913f, 547.1257f, 731.9155f, 4.799650f),
|
||||
new Position(517.51f , 561.439f , 734.0306f, 4.520403f),
|
||||
new Position(543.414f , 551.728f , 732.0522f, 3.996804f)
|
||||
};
|
||||
|
||||
public static Position[] championWaypoints =
|
||||
{
|
||||
new Position(539.2076f, 549.7539f, 732.8668f, 4.55531f),
|
||||
new Position(527.3098f, 559.5197f, 732.9407f, 4.742493f),
|
||||
new Position()
|
||||
};
|
||||
|
||||
public static Position[] cryptFiendWaypoints =
|
||||
{
|
||||
new Position(520.3911f, 548.7895f, 732.0118f, 5.0091f),
|
||||
new Position(),
|
||||
new Position(550.9611f, 545.1674f, 731.9031f, 3.996804f)
|
||||
};
|
||||
|
||||
public static Position[] necromancerWaypoints =
|
||||
{
|
||||
new Position(),
|
||||
new Position(507.6937f, 563.3471f, 734.8986f, 4.520403f),
|
||||
new Position(535.1049f, 552.8961f, 732.8441f, 3.996804f),
|
||||
};
|
||||
|
||||
public static Position[] initialMoves =
|
||||
{
|
||||
new Position(485.314606f, 611.418640f, 771.428406f),
|
||||
new Position(575.760437f, 611.516418f, 771.427368f),
|
||||
new Position(588.930725f, 598.233276f, 739.142151f)
|
||||
};
|
||||
|
||||
public static Position[] downstairsMoves =
|
||||
{
|
||||
new Position(513.574341f, 587.022156f, 736.229065f),
|
||||
new Position(537.920410f, 580.436157f, 732.796692f),
|
||||
new Position(601.289246f, 583.259644f, 725.443054f),
|
||||
};
|
||||
|
||||
public static Position[] downstairsMoves2 =
|
||||
{
|
||||
new Position(571.498718f, 576.978333f, 727.582947f),
|
||||
new Position(571.498718f, 576.978333f, 727.582947f),
|
||||
new Position()
|
||||
};
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_hadronox : BossAI
|
||||
{
|
||||
public boss_hadronox(Creature creature) : base(creature, ANDataTypes.Hadronox) { }
|
||||
|
||||
bool IsInCombatWithPlayer()
|
||||
{
|
||||
List<HostileReference> refs = me.GetThreatManager().getThreatList();
|
||||
foreach (HostileReference hostileRef in refs)
|
||||
{
|
||||
Unit target = hostileRef.getTarget();
|
||||
if (target)
|
||||
if (target.IsControlledByPlayer())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetStep(byte step)
|
||||
{
|
||||
if (_lastPlayerCombatState)
|
||||
return;
|
||||
|
||||
_step = step;
|
||||
me.SetHomePosition(Misc.hadronoxStep[step]);
|
||||
me.GetMotionMaster().Clear();
|
||||
me.AttackStop();
|
||||
SetCombatMovement(false);
|
||||
me.GetMotionMaster().MovePoint(0, Misc.hadronoxStep[step]);
|
||||
}
|
||||
|
||||
void SummonCrusherPack(SummonGroups group)
|
||||
{
|
||||
List<TempSummon> summoned;
|
||||
me.SummonCreatureGroup((byte)group, out summoned);
|
||||
foreach (TempSummon summon in summoned)
|
||||
{
|
||||
summon.GetAI().SetData(Data.CrusherPackId, (uint)group);
|
||||
summon.GetAI().DoAction(ActionIds.PackWalk);
|
||||
}
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (type != MovementGeneratorType.Point)
|
||||
return;
|
||||
SetCombatMovement(true);
|
||||
AttackStart(me.GetVictim());
|
||||
if (_step < Misc.hadronoxStep.Length - 1)
|
||||
return;
|
||||
DoCastAOE(SpellIds.WebFrontDoors);
|
||||
DoCastAOE(SpellIds.WebSideDoors);
|
||||
_doorsWebbed = true;
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
public override uint GetData(uint data)
|
||||
{
|
||||
if (data == Data.HadronoxEnteredCombat)
|
||||
return _enteredCombat ? 1 : 0u;
|
||||
if (data == Data.HadronoxWebbedDoors)
|
||||
return _doorsWebbed ? 1 : 0u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override bool CanAIAttack(Unit target)
|
||||
{
|
||||
// Prevent Hadronox from going too far from her current home position
|
||||
if (!target.IsControlledByPlayer() && target.GetDistance(me.GetHomePosition()) > 20.0f)
|
||||
return false;
|
||||
return base.CanAIAttack(target);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(7), task =>
|
||||
{
|
||||
DoCastAOE(SpellIds.LeechPoison);
|
||||
task.Repeat(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(9));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(13), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.AcidCloud);
|
||||
task.Repeat(TimeSpan.FromSeconds(16), TimeSpan.FromSeconds(23));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(19), task =>
|
||||
{
|
||||
DoCastAOE(SpellIds.WebGrab);
|
||||
task.Repeat(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(25));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(7), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.PierceArmor);
|
||||
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), task =>
|
||||
{
|
||||
if (IsInCombatWithPlayer() != _lastPlayerCombatState)
|
||||
{
|
||||
_lastPlayerCombatState = !_lastPlayerCombatState;
|
||||
if (_lastPlayerCombatState) // we are now in combat with players
|
||||
{
|
||||
if (!instance.CheckRequiredBosses(ANDataTypes.Hadronox))
|
||||
{
|
||||
EnterEvadeMode(EvadeReason.SequenceBreak);
|
||||
return;
|
||||
}
|
||||
// cancel current point movement if engaged by players
|
||||
if (me.GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Point)
|
||||
{
|
||||
me.GetMotionMaster().Clear();
|
||||
SetCombatMovement(true);
|
||||
AttackStart(me.GetVictim());
|
||||
}
|
||||
}
|
||||
else // we are no longer in combat with players - reset the encounter
|
||||
EnterEvadeMode(EvadeReason.NoHostiles);
|
||||
}
|
||||
task.Repeat(TimeSpan.FromSeconds(1));
|
||||
});
|
||||
|
||||
me.setActive(true);
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ActionIds.CrusherEngaged:
|
||||
if (_enteredCombat)
|
||||
break;
|
||||
instance.SetBossState(ANDataTypes.Hadronox, EncounterState.InProgress);
|
||||
_enteredCombat = true;
|
||||
SummonCrusherPack(SummonGroups.Crusher2);
|
||||
SummonCrusherPack(SummonGroups.Crusher3);
|
||||
break;
|
||||
case ActionIds.HadronoxMove:
|
||||
if (_step < Misc.hadronoxStep.Length - 1)
|
||||
{
|
||||
SetStep((byte)(_step + 1));
|
||||
Talk(TextIds.EmoteHadronoxMove);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
List<Creature> triggers = new List<Creature>();
|
||||
me.GetCreatureListWithEntryInGrid(triggers, CreatureIds.WorldtriggerLarge);
|
||||
foreach (Creature trigger in triggers)
|
||||
{
|
||||
if (trigger.HasAura(SpellIds.SummonChampionPeriodic) || trigger.HasAura(SpellIds.WebFrontDoors) || trigger.HasAura(SpellIds.WebSideDoors))
|
||||
_DespawnAtEvade(25, trigger);
|
||||
}
|
||||
_DespawnAtEvade(25);
|
||||
summons.DespawnAll();
|
||||
foreach (ObjectGuid gNerubian in _anubar)
|
||||
{
|
||||
Creature nerubian = ObjectAccessor.GetCreature(me, gNerubian);
|
||||
if (nerubian)
|
||||
nerubian.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetGUID(ObjectGuid guid, int what)
|
||||
{
|
||||
_anubar.Add(guid);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
me.SetFloatValue(UnitFields.BoundingRadius, 9.0f);
|
||||
me.SetFloatValue(UnitFields.CombatReach, 9.0f);
|
||||
_enteredCombat = false;
|
||||
_doorsWebbed = false;
|
||||
_lastPlayerCombatState = false;
|
||||
SetStep(0);
|
||||
SetCombatMovement(true);
|
||||
SummonCrusherPack(SummonGroups.Crusher1);
|
||||
}
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
if (me.IsAlive())
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void JustRespawned()
|
||||
{
|
||||
base.JustRespawned();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
// Safeguard to prevent Hadronox dying to NPCs
|
||||
public override void DamageTaken(Unit who, ref uint damage)
|
||||
{
|
||||
if (!who.IsControlledByPlayer() && me.HealthBelowPct(70))
|
||||
{
|
||||
if (me.HealthBelowPctDamaged(5, damage))
|
||||
damage = 0;
|
||||
else
|
||||
damage *= (uint)((me.GetHealthPct() - 5.0f) / 65.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
// Do not enter combat with zone
|
||||
}
|
||||
|
||||
bool _enteredCombat; // has a player entered combat with the first crusher pack? (talk and spawn two more packs)
|
||||
bool _doorsWebbed; // obvious - have we reached the top and webbed the doors shut? (trigger for hadronox denied achievement)
|
||||
bool _lastPlayerCombatState; // was there a player in our threat list the last time we checked (we check every second)
|
||||
byte _step;
|
||||
List<ObjectGuid> _anubar = new List<ObjectGuid>();
|
||||
}
|
||||
|
||||
class npc_hadronox_crusherPackAI : ScriptedAI
|
||||
{
|
||||
public npc_hadronox_crusherPackAI(Creature creature, Position[] positions) : base(creature)
|
||||
{
|
||||
_instance = creature.GetInstanceScript();
|
||||
_positions = positions;
|
||||
_myPack = 0;
|
||||
_doFacing = false;
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
if (action == ActionIds.PackWalk)
|
||||
{
|
||||
switch (_myPack)
|
||||
{
|
||||
case SummonGroups.Crusher1:
|
||||
case SummonGroups.Crusher2:
|
||||
case SummonGroups.Crusher3:
|
||||
me.GetMotionMaster().MovePoint(ActionIds.PackWalk, _positions[_myPack - SummonGroups.Crusher1]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (type == MovementGeneratorType.Point && id == ActionIds.PackWalk)
|
||||
_doFacing = true;
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
Creature hadronox = _instance.GetCreature(ANDataTypes.Hadronox);
|
||||
if (hadronox)
|
||||
hadronox.GetAI().EnterEvadeMode(EvadeReason.Other);
|
||||
}
|
||||
|
||||
public override uint GetData(uint data)
|
||||
{
|
||||
if (data == Data.CrusherPackId)
|
||||
return (uint)_myPack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void SetData(uint data, uint value)
|
||||
{
|
||||
if (data == Data.CrusherPackId)
|
||||
{
|
||||
_myPack = (SummonGroups)value;
|
||||
me.SetReactState(_myPack != 0 ? ReactStates.Passive : ReactStates.Aggressive);
|
||||
}
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
if (me.HasReactState(ReactStates.Passive))
|
||||
{
|
||||
List<Creature> others = new List<Creature>();
|
||||
me.GetCreatureListWithEntryInGrid(others, 0, 40.0f);
|
||||
foreach (Creature other in others)
|
||||
{
|
||||
if (other.GetAI().GetData(Data.CrusherPackId) == (uint)_myPack)
|
||||
{
|
||||
other.SetReactState(ReactStates.Aggressive);
|
||||
other.GetAI().AttackStart(who);
|
||||
}
|
||||
}
|
||||
}
|
||||
_EnterCombat();
|
||||
base.EnterCombat(who);
|
||||
}
|
||||
|
||||
public virtual void _EnterCombat() { }
|
||||
|
||||
public override void MoveInLineOfSight(Unit who)
|
||||
{
|
||||
if (!me.HasReactState(ReactStates.Passive))
|
||||
{
|
||||
base.MoveInLineOfSight(who);
|
||||
return;
|
||||
}
|
||||
|
||||
if (me.CanStartAttack(who, false) && me.IsWithinDistInMap(who, me.GetAttackDistance(who) + me.m_CombatDistance))
|
||||
EnterCombat(who);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (_doFacing)
|
||||
{
|
||||
_doFacing = false;
|
||||
me.SetFacingTo(_positions[_myPack - SummonGroups.Crusher1].GetOrientation());
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
protected InstanceScript _instance;
|
||||
Position[] _positions;
|
||||
protected SummonGroups _myPack;
|
||||
bool _doFacing;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_crusher : npc_hadronox_crusherPackAI
|
||||
{
|
||||
public npc_anub_ar_crusher(Creature creature) : base(creature, Misc.crusherWaypoints) { }
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Smash);
|
||||
task.Repeat(TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(21));
|
||||
});
|
||||
|
||||
if (_myPack != SummonGroups.Crusher1)
|
||||
return;
|
||||
|
||||
Creature hadronox = _instance.GetCreature(ANDataTypes.Hadronox);
|
||||
if (hadronox)
|
||||
{
|
||||
if (hadronox.GetAI().GetData(Data.HadronoxEnteredCombat) != 0)
|
||||
return;
|
||||
hadronox.GetAI().DoAction(ActionIds.CrusherEngaged);
|
||||
}
|
||||
|
||||
Talk(TextIds.SayCrusherAggro);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit source, ref uint damage)
|
||||
{
|
||||
if (_hadFrenzy || !me.HealthBelowPctDamaged(25, damage))
|
||||
return;
|
||||
_hadFrenzy = true;
|
||||
Talk(TextIds.EmoteCrusherFrenzy);
|
||||
DoCastSelf(SpellIds.Frenzy);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Creature hadronox = _instance.GetCreature(ANDataTypes.Hadronox);
|
||||
if (hadronox)
|
||||
hadronox.GetAI().DoAction(ActionIds.HadronoxMove);
|
||||
base.JustDied(killer);
|
||||
}
|
||||
|
||||
bool _hadFrenzy;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_crusher_champion : npc_hadronox_crusherPackAI
|
||||
{
|
||||
public npc_anub_ar_crusher_champion(Creature creature) : base(creature, Misc.championWaypoints) { }
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Rend);
|
||||
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(16));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(19), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Pummel);
|
||||
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(17));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_crusher_crypt_fiend : npc_hadronox_crusherPackAI
|
||||
{
|
||||
public npc_anub_ar_crusher_crypt_fiend(Creature creature) : base(creature, Misc.cryptFiendWaypoints) { }
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.CrushingWebs);
|
||||
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(16));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(19), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.InfectedWound);
|
||||
task.Repeat(TimeSpan.FromSeconds(16), TimeSpan.FromSeconds(25));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_crusher_necromancer : npc_hadronox_crusherPackAI
|
||||
{
|
||||
public npc_anub_ar_crusher_necromancer(Creature creature) : base(creature, Misc.necromancerWaypoints) { }
|
||||
|
||||
public override void _EnterCombat()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(4), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.ShadowBolt);
|
||||
task.Repeat(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(37), TimeSpan.FromSeconds(45), task =>
|
||||
{
|
||||
DoCastVictim(RandomHelper.URand(0, 1) != 0 ? SpellIds.AnimateBones2 : SpellIds.AnimateBones1);
|
||||
task.Repeat(TimeSpan.FromSeconds(35), TimeSpan.FromSeconds(50));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class npc_hadronox_foeAI : ScriptedAI
|
||||
{
|
||||
public npc_hadronox_foeAI(Creature creature) : base(creature)
|
||||
{
|
||||
_instance = creature.GetInstanceScript();
|
||||
_nextMovement = MovementIds.Outside;
|
||||
_mySpawn = 0;
|
||||
}
|
||||
|
||||
public override void InitializeAI()
|
||||
{
|
||||
base.InitializeAI();
|
||||
Creature hadronox = _instance.GetCreature(ANDataTypes.Hadronox);
|
||||
if (hadronox)
|
||||
hadronox.GetAI().SetGUID(me.GetGUID());
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (type == MovementGeneratorType.Point)
|
||||
_nextMovement = (MovementIds)(id + 1);
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (_nextMovement != 0)
|
||||
{
|
||||
switch (_nextMovement)
|
||||
{
|
||||
case MovementIds.Outside:
|
||||
{
|
||||
float dist = float.PositiveInfinity;
|
||||
for (byte spawn = 0; spawn < Misc.initialMoves.Length; ++spawn)
|
||||
{
|
||||
float thisDist = Misc.initialMoves[spawn].GetExactDistSq(me);
|
||||
if (thisDist < dist)
|
||||
{
|
||||
_mySpawn = spawn;
|
||||
dist = thisDist;
|
||||
}
|
||||
}
|
||||
me.GetMotionMaster().MovePoint((uint)MovementIds.Outside, Misc.initialMoves[_mySpawn], false); // do not pathfind here, we have to pass through a "wall" of webbing
|
||||
break;
|
||||
}
|
||||
case MovementIds.Downstairs:
|
||||
me.GetMotionMaster().MovePoint((uint)MovementIds.Downstairs, Misc.downstairsMoves[_mySpawn]);
|
||||
break;
|
||||
case MovementIds.Downstairs2:
|
||||
if (Misc.downstairsMoves2[_mySpawn].GetPositionX() > 0.0f) // might be unset for this spawn - if yes, skip
|
||||
{
|
||||
me.GetMotionMaster().MovePoint((uint)MovementIds.Downstairs2, Misc.downstairsMoves2[_mySpawn]);
|
||||
break;
|
||||
}
|
||||
goto case MovementIds.Hadronox;
|
||||
// intentional missing break
|
||||
case MovementIds.Hadronox:
|
||||
case MovementIds.HadronoxReal:
|
||||
{
|
||||
float zCutoff = 702.0f;
|
||||
Creature hadronox = _instance.GetCreature(ANDataTypes.Hadronox);
|
||||
if (hadronox && hadronox.IsAlive())
|
||||
{
|
||||
if (_nextMovement != MovementIds.HadronoxReal)
|
||||
{
|
||||
if (hadronox.GetPositionZ() < zCutoff)
|
||||
{
|
||||
me.GetMotionMaster().MovePoint((uint)MovementIds.Hadronox, Misc.hadronoxStep[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
AttackStart(hadronox);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_nextMovement = MovementIds.None;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
InstanceScript _instance;
|
||||
|
||||
MovementIds _nextMovement;
|
||||
byte _mySpawn;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_champion : npc_hadronox_foeAI
|
||||
{
|
||||
public npc_anub_ar_champion(Creature creature) : base(creature) { }
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Rend);
|
||||
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(16));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(19), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Pummel);
|
||||
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(17));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(50), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Taunt);
|
||||
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(50));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_crypt_fiend : npc_hadronox_foeAI
|
||||
{
|
||||
public npc_anub_ar_crypt_fiend(Creature creature) : base(creature) { }
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.CrushingWebs);
|
||||
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(16));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(19), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.InfectedWound);
|
||||
task.Repeat(TimeSpan.FromSeconds(16), TimeSpan.FromSeconds(25));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(50), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Taunt);
|
||||
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(50));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_anub_ar_necromancer : npc_hadronox_foeAI
|
||||
{
|
||||
public npc_anub_ar_necromancer(Creature creature) : base(creature) { }
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(4), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.ShadowBolt);
|
||||
task.Repeat(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(37), TimeSpan.FromSeconds(45), task =>
|
||||
{
|
||||
DoCastVictim(RandomHelper.URand(0, 1) != 0 ? SpellIds.AnimateBones2 : SpellIds.AnimateBones1);
|
||||
task.Repeat(TimeSpan.FromSeconds(35), TimeSpan.FromSeconds(50));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(50), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Taunt);
|
||||
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(50));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Script("spell_hadronox_periodic_summon_champion", SpellIds.SummonChampionTop, SpellIds.SummonChampionBottom)]
|
||||
[Script("spell_hadronox_periodic_summon_crypt_fiend", SpellIds.SummonCryptFiendTop, SpellIds.SummonCryptFiendBottom)]
|
||||
[Script("spell_hadronox_periodic_summon_necromancer", SpellIds.SummonNecromancerTop, SpellIds.SummonNecromancerBottom)]
|
||||
class spell_hadronox_periodic_summon_template : AuraScript
|
||||
{
|
||||
public spell_hadronox_periodic_summon_template(uint topSpellId, uint bottomSpellId) : base()
|
||||
{
|
||||
_topSpellId = topSpellId;
|
||||
_bottomSpellId = bottomSpellId;
|
||||
}
|
||||
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(_topSpellId, _bottomSpellId);
|
||||
}
|
||||
|
||||
void HandleApply(AuraEffect eff, AuraEffectHandleModes mode)
|
||||
{
|
||||
AuraEffect effect = GetAura().GetEffect(0);
|
||||
if (effect != null)
|
||||
effect.SetPeriodicTimer(RandomHelper.IRand(2, 17) * Time.InMilliseconds);
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect eff)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
InstanceScript instance = caster.GetInstanceScript();
|
||||
if (instance == null)
|
||||
return;
|
||||
if (instance.GetBossState(ANDataTypes.Hadronox) == EncounterState.Done)
|
||||
GetAura().Remove();
|
||||
else
|
||||
{
|
||||
if (caster.GetPositionZ() >= 750.0f)
|
||||
caster.CastSpell(caster, _topSpellId, true);
|
||||
else
|
||||
caster.CastSpell(caster, _bottomSpellId, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
AfterEffectApply.Add(new EffectApplyHandler(HandleApply, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.Real));
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(HandlePeriodic, 0, AuraType.PeriodicDummy));
|
||||
}
|
||||
|
||||
uint _topSpellId;
|
||||
uint _bottomSpellId;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_hadronox_leeching_poison : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.LeechPoisonHeal);
|
||||
}
|
||||
|
||||
void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
if (GetTargetApplication().GetRemoveMode() != AuraRemoveMode.ByDeath)
|
||||
return;
|
||||
|
||||
if (GetTarget().IsGuardian())
|
||||
return;
|
||||
|
||||
Unit caster = GetCaster();
|
||||
if (caster)
|
||||
caster.CastSpell(caster, SpellIds.LeechPoisonHeal, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectRemove.Add(new EffectApplyHandler(HandleEffectRemove, 0, AuraType.PeriodicLeech, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_hadronox_web_doors : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.SummonChampionPeriodic, SpellIds.SummonCryptFiendPeriodic, SpellIds.SummonNecromancerPeriodic);
|
||||
}
|
||||
|
||||
void HandleDummy(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
{
|
||||
target.RemoveAurasDueToSpell(SpellIds.SummonChampionPeriodic);
|
||||
target.RemoveAurasDueToSpell(SpellIds.SummonCryptFiendPeriodic);
|
||||
target.RemoveAurasDueToSpell(SpellIds.SummonNecromancerPeriodic);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleDummy, 0, SpellEffectName.ApplyAura));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_hadronox_denied : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_hadronox_denied() : base("achievement_hadronox_denied") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
Creature cTarget = target.ToCreature();
|
||||
if (cTarget)
|
||||
if (cTarget.GetAI().GetData(Data.HadronoxWebbedDoors) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
|
||||
namespace Scripts.Northrend.AzjolNerub.AzjolNerub
|
||||
{
|
||||
struct ANDataTypes
|
||||
{
|
||||
// Encounter States/Boss Guids
|
||||
public const uint KrikthirTheGatewatcher = 0;
|
||||
public const uint Hadronox = 1;
|
||||
public const uint Anubarak = 2;
|
||||
|
||||
// Additional Data
|
||||
public const uint WatcherNarjil = 3;
|
||||
public const uint WatcherGashra = 4;
|
||||
public const uint WatcherSilthik = 5;
|
||||
public const uint AnubarakWall = 6;
|
||||
public const uint AnubarakWall2 = 7;
|
||||
}
|
||||
|
||||
struct ANCreatureIds
|
||||
{
|
||||
public const uint Krikthir = 28684;
|
||||
public const uint Hadronox = 28921;
|
||||
public const uint Anubarak = 29120;
|
||||
|
||||
public const uint WatcherNarjil = 28729;
|
||||
public const uint WatcherGashra = 28730;
|
||||
public const uint WatcherSilthik = 28731;
|
||||
}
|
||||
|
||||
struct ANGameObjectIds
|
||||
{
|
||||
public const uint KrikthirDoor = 192395;
|
||||
public const uint AnubarakDoor1 = 192396;
|
||||
public const uint AnubarakDoor2 = 192397;
|
||||
public const uint AnubarakDoor3 = 192398;
|
||||
}
|
||||
|
||||
// These are passed as -action to AI's DoAction to differentiate between them and boss scripts' own actions
|
||||
struct ANInstanceMisc
|
||||
{
|
||||
public const string DataHeader = "AN";
|
||||
public const uint EncounterCount = 3;
|
||||
|
||||
public const int ActionGatewatcherGreet = 1;
|
||||
|
||||
public static DoorData[] doorData =
|
||||
{
|
||||
new DoorData(ANGameObjectIds.KrikthirDoor, ANDataTypes.KrikthirTheGatewatcher, DoorType.Passage),
|
||||
new DoorData(ANGameObjectIds.AnubarakDoor1, ANDataTypes.Anubarak, DoorType.Room ),
|
||||
new DoorData(ANGameObjectIds.AnubarakDoor2, ANDataTypes.Anubarak, DoorType.Room ),
|
||||
new DoorData(ANGameObjectIds.AnubarakDoor3, ANDataTypes.Anubarak, DoorType.Room )
|
||||
};
|
||||
|
||||
public static ObjectData[] creatureData =
|
||||
{
|
||||
new ObjectData(ANCreatureIds.Krikthir, ANDataTypes.KrikthirTheGatewatcher ),
|
||||
new ObjectData(ANCreatureIds.Hadronox, ANDataTypes.Hadronox ),
|
||||
new ObjectData(ANCreatureIds.Anubarak, ANDataTypes.Anubarak ),
|
||||
new ObjectData(ANCreatureIds.WatcherNarjil, ANDataTypes.WatcherGashra ),
|
||||
new ObjectData(ANCreatureIds.WatcherGashra, ANDataTypes.WatcherSilthik ),
|
||||
new ObjectData(ANCreatureIds.WatcherSilthik, ANDataTypes.WatcherNarjil )
|
||||
};
|
||||
|
||||
public static ObjectData[] gameobjectData =
|
||||
{
|
||||
new ObjectData(ANGameObjectIds.AnubarakDoor1, ANDataTypes.AnubarakWall),
|
||||
new ObjectData(ANGameObjectIds.AnubarakDoor3, ANDataTypes.AnubarakWall2)
|
||||
};
|
||||
|
||||
public static BossBoundaryEntry[] boundaries =
|
||||
{
|
||||
new BossBoundaryEntry(ANDataTypes.KrikthirTheGatewatcher, new RectangleBoundary(400.0f, 580.0f, 623.5f, 810.0f)),
|
||||
new BossBoundaryEntry(ANDataTypes.Hadronox, new ZRangeBoundary(666.0f, 776.0f)),
|
||||
new BossBoundaryEntry(ANDataTypes.Anubarak, new CircleBoundary(new Position(550.6178f, 253.5917f), 26.0f))
|
||||
};
|
||||
}
|
||||
|
||||
[Script]
|
||||
class instance_azjol_nerub : InstanceMapScript
|
||||
{
|
||||
public instance_azjol_nerub() : base(nameof(instance_azjol_nerub), 601) { }
|
||||
|
||||
class instance_azjol_nerub_InstanceScript : InstanceScript
|
||||
{
|
||||
public instance_azjol_nerub_InstanceScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders(ANInstanceMisc.DataHeader);
|
||||
SetBossNumber(ANInstanceMisc.EncounterCount);
|
||||
LoadBossBoundaries(ANInstanceMisc.boundaries);
|
||||
LoadDoorData(ANInstanceMisc.doorData);
|
||||
LoadObjectData(ANInstanceMisc.creatureData, ANInstanceMisc.gameobjectData);
|
||||
}
|
||||
|
||||
public override void OnUnitDeath(Unit who)
|
||||
{
|
||||
base.OnUnitDeath(who);
|
||||
Creature creature = who.ToCreature();
|
||||
if (!creature || creature.IsCritter() || creature.IsControlledByPlayer())
|
||||
return;
|
||||
|
||||
Creature gatewatcher = GetCreature(ANDataTypes.KrikthirTheGatewatcher);
|
||||
if (gatewatcher)
|
||||
gatewatcher.GetAI().DoAction(-ANInstanceMisc.ActionGatewatcherGreet);
|
||||
}
|
||||
|
||||
public override bool CheckRequiredBosses(uint bossId, Player player)
|
||||
{
|
||||
if (_SkipCheckRequiredBosses(player))
|
||||
return true;
|
||||
|
||||
if (bossId > ANDataTypes.KrikthirTheGatewatcher && GetBossState(ANDataTypes.KrikthirTheGatewatcher) != EncounterState.Done)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_azjol_nerub_InstanceScript(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,650 @@
|
||||
/*
|
||||
* 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 Framework.Dynamic;
|
||||
using Game.AI;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend.CrusadersColiseum.TrialOfTheChampion
|
||||
{
|
||||
struct TrialOfChampionSpells
|
||||
{
|
||||
//Vehicle
|
||||
public const uint CHARGE = 63010;
|
||||
public const uint SHIELD_BREAKER = 68504;
|
||||
public const uint SHIELD = 66482;
|
||||
|
||||
// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior
|
||||
public const uint MORTAL_STRIKE = 68783;
|
||||
public const uint MORTAL_STRIKE_H = 68784;
|
||||
public const uint BLADESTORM = 63784;
|
||||
public const uint INTERCEPT = 67540;
|
||||
public const uint ROLLING_THROW = 47115; //not implemented in the AI yet...
|
||||
|
||||
// Ambrose Boltspark && Eressea Dawnsinger || Mage
|
||||
public const uint FIREBALL = 66042;
|
||||
public const uint FIREBALL_H = 68310;
|
||||
public const uint BLAST_WAVE = 66044;
|
||||
public const uint BLAST_WAVE_H = 68312;
|
||||
public const uint HASTE = 66045;
|
||||
public const uint POLYMORPH = 66043;
|
||||
public const uint POLYMORPH_H = 68311;
|
||||
|
||||
// Colosos && Runok Wildmane || Shaman
|
||||
public const uint CHAIN_LIGHTNING = 67529;
|
||||
public const uint CHAIN_LIGHTNING_H = 68319;
|
||||
public const uint EARTH_SHIELD = 67530;
|
||||
public const uint HEALING_WAVE = 67528;
|
||||
public const uint HEALING_WAVE_H = 68318;
|
||||
public const uint HEX_OF_MENDING = 67534;
|
||||
|
||||
// Jaelyne Evensong && Zul'tore || Hunter
|
||||
public const uint DISENGAGE = 68340; //not implemented in the AI yet...
|
||||
public const uint LIGHTNING_ARROWS = 66083;
|
||||
public const uint MULTI_SHOT = 66081;
|
||||
public const uint SHOOT = 65868;
|
||||
public const uint SHOOT_H = 67988;
|
||||
|
||||
// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge
|
||||
public const uint EVISCERATE = 67709;
|
||||
public const uint EVISCERATE_H = 68317;
|
||||
public const uint FAN_OF_KNIVES = 67706;
|
||||
public const uint POISON_BOTTLE = 67701;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class generic_vehicleAI_toc5 : npc_escortAI
|
||||
{
|
||||
public generic_vehicleAI_toc5(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
SetDespawnAtEnd(false);
|
||||
uiWaypointPath = 0;
|
||||
|
||||
instance = creature.GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiChargeTimer = 5000;
|
||||
uiShieldBreakerTimer = 8000;
|
||||
uiBuffTimer = RandomHelper.URand(30000, 60000);
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void SetData(uint uiType, uint uiData)
|
||||
{
|
||||
switch (uiType)
|
||||
{
|
||||
case 1:
|
||||
AddWaypoint(0, 747.36f, 634.07f, 411.572f);
|
||||
AddWaypoint(1, 780.43f, 607.15f, 411.82f);
|
||||
AddWaypoint(2, 785.99f, 599.41f, 411.92f);
|
||||
AddWaypoint(3, 778.44f, 601.64f, 411.79f);
|
||||
uiWaypointPath = 1;
|
||||
break;
|
||||
case 2:
|
||||
AddWaypoint(0, 747.35f, 634.07f, 411.57f);
|
||||
AddWaypoint(1, 768.72f, 581.01f, 411.92f);
|
||||
AddWaypoint(2, 763.55f, 590.52f, 411.71f);
|
||||
uiWaypointPath = 2;
|
||||
break;
|
||||
case 3:
|
||||
AddWaypoint(0, 747.35f, 634.07f, 411.57f);
|
||||
AddWaypoint(1, 784.02f, 645.33f, 412.39f);
|
||||
AddWaypoint(2, 775.67f, 641.91f, 411.91f);
|
||||
uiWaypointPath = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (uiType <= 3)
|
||||
Start(false, true);
|
||||
}
|
||||
|
||||
public override void WaypointReached(uint waypointId)
|
||||
{
|
||||
switch (waypointId)
|
||||
{
|
||||
case 2:
|
||||
if (uiWaypointPath == 3 || uiWaypointPath == 2)
|
||||
instance.SetData((uint)Data.DATA_MOVEMENT_DONE, instance.GetData((uint)Data.DATA_MOVEMENT_DONE) + 1);
|
||||
break;
|
||||
case 3:
|
||||
instance.SetData((uint)Data.DATA_MOVEMENT_DONE, instance.GetData((uint)Data.DATA_MOVEMENT_DONE) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
DoCastSpellShield();
|
||||
}
|
||||
|
||||
void DoCastSpellShield()
|
||||
{
|
||||
for (byte i = 0; i < 3; ++i)
|
||||
DoCast(me, TrialOfChampionSpells.SHIELD, true);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint uiDiff)
|
||||
{
|
||||
base.UpdateAI(uiDiff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiBuffTimer <= uiDiff)
|
||||
{
|
||||
if (!me.HasAura(TrialOfChampionSpells.SHIELD))
|
||||
DoCastSpellShield();
|
||||
|
||||
uiBuffTimer = RandomHelper.URand(30000, 45000);
|
||||
}
|
||||
else
|
||||
uiBuffTimer -= uiDiff;
|
||||
|
||||
if (uiChargeTimer <= uiDiff)
|
||||
{
|
||||
var players = me.GetMap().GetPlayers();
|
||||
if (!players.Empty())
|
||||
{
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player && !player.IsGameMaster() && me.IsInRange(player, 8.0f, 25.0f, false))
|
||||
{
|
||||
DoResetThreat();
|
||||
me.AddThreat(player, 1.0f);
|
||||
DoCast(player, TrialOfChampionSpells.CHARGE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
uiChargeTimer = 5000;
|
||||
}
|
||||
else
|
||||
uiChargeTimer -= uiDiff;
|
||||
|
||||
//dosen't work at all
|
||||
if (uiShieldBreakerTimer <= uiDiff)
|
||||
{
|
||||
Vehicle pVehicle = me.GetVehicleKit();
|
||||
if (!pVehicle)
|
||||
return;
|
||||
|
||||
Unit pPassenger = pVehicle.GetPassenger(0);
|
||||
if (pPassenger)
|
||||
{
|
||||
var players = me.GetMap().GetPlayers();
|
||||
if (!players.Empty())
|
||||
{
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player && !player.IsGameMaster() && me.IsInRange(player, 10.0f, 30.0f, false))
|
||||
{
|
||||
pPassenger.CastSpell(player, TrialOfChampionSpells.SHIELD_BREAKER, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uiShieldBreakerTimer = 7000;
|
||||
}
|
||||
else
|
||||
uiShieldBreakerTimer -= uiDiff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
|
||||
uint uiChargeTimer;
|
||||
uint uiShieldBreakerTimer;
|
||||
uint uiBuffTimer;
|
||||
|
||||
uint uiWaypointPath;
|
||||
}
|
||||
|
||||
abstract class boss_basic_toc5AI : ScriptedAI
|
||||
{
|
||||
public boss_basic_toc5AI(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature.GetInstanceScript();
|
||||
|
||||
bDone = false;
|
||||
bHome = false;
|
||||
|
||||
uiPhase = 0;
|
||||
uiPhaseTimer = 0;
|
||||
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
// THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.ImmuneToPc);
|
||||
}
|
||||
|
||||
public abstract void Initialize();
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void JustReachedHome()
|
||||
{
|
||||
base.JustReachedHome();
|
||||
|
||||
if (!bHome)
|
||||
return;
|
||||
|
||||
uiPhaseTimer = 15000;
|
||||
uiPhase = 1;
|
||||
|
||||
bHome = false;
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
instance.SetData((uint)Data.BOSS_GRAND_CHAMPIONS, (uint)EncounterState.Done);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!bDone && GrandChampionsOutVehicle(me))
|
||||
{
|
||||
bDone = true;
|
||||
|
||||
if (me.GetGUID() == instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_1))
|
||||
me.SetHomePosition(739.678f, 662.541f, 412.393f, 4.49f);
|
||||
else if (me.GetGUID() == instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_2))
|
||||
me.SetHomePosition(746.71f, 661.02f, 411.69f, 4.6f);
|
||||
else if (me.GetGUID() == instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_3))
|
||||
me.SetHomePosition(754.34f, 660.70f, 412.39f, 4.79f);
|
||||
|
||||
EnterEvadeMode();
|
||||
bHome = true;
|
||||
}
|
||||
|
||||
if (uiPhaseTimer <= diff)
|
||||
{
|
||||
if (uiPhase == 1)
|
||||
{
|
||||
AggroAllPlayers(me);
|
||||
uiPhase = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
uiPhaseTimer -= diff;
|
||||
}
|
||||
|
||||
public bool InVehicle()
|
||||
{
|
||||
return !me.m_movementInfo.transport.guid.IsEmpty();
|
||||
}
|
||||
|
||||
void AggroAllPlayers(Creature temp)
|
||||
{
|
||||
var PlList = temp.GetMap().GetPlayers();
|
||||
|
||||
if (PlList.Empty())
|
||||
return;
|
||||
|
||||
foreach (var player in PlList)
|
||||
{
|
||||
if (player)
|
||||
{
|
||||
if (player.IsGameMaster())
|
||||
continue;
|
||||
|
||||
if (player.IsAlive())
|
||||
{
|
||||
temp.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.ImmuneToPc);
|
||||
temp.SetReactState(ReactStates.Aggressive);
|
||||
temp.SetInCombatWith(player);
|
||||
player.SetInCombatWith(temp);
|
||||
temp.AddThreat(player, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GrandChampionsOutVehicle(Creature me)
|
||||
{
|
||||
InstanceScript instance = me.GetInstanceScript();
|
||||
|
||||
if (instance == null)
|
||||
return false;
|
||||
|
||||
Creature pGrandChampion1 = ObjectAccessor.GetCreature(me, instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_1));
|
||||
Creature pGrandChampion2 = ObjectAccessor.GetCreature(me, instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_2));
|
||||
Creature pGrandChampion3 = ObjectAccessor.GetCreature(me, instance.GetGuidData((uint)Data64.DATA_GRAND_CHAMPION_3));
|
||||
|
||||
if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3)
|
||||
{
|
||||
if (pGrandChampion1.m_movementInfo.transport.guid.IsEmpty() &&
|
||||
pGrandChampion2.m_movementInfo.transport.guid.IsEmpty() &&
|
||||
pGrandChampion3.m_movementInfo.transport.guid.IsEmpty())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public TaskScheduler NonCombatEvents = new TaskScheduler();
|
||||
|
||||
public InstanceScript instance;
|
||||
|
||||
public byte uiPhase;
|
||||
public uint uiPhaseTimer;
|
||||
|
||||
bool bDone;
|
||||
public bool bHome;
|
||||
}
|
||||
|
||||
[Script]
|
||||
// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior
|
||||
class boss_warrior_toc5 : boss_basic_toc5AI
|
||||
{
|
||||
public boss_warrior_toc5(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
DoCastVictim(TrialOfChampionSpells.BLADESTORM);
|
||||
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), task =>
|
||||
{
|
||||
var players = me.GetMap().GetPlayers();
|
||||
if (!players.Empty())
|
||||
{
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player && !player.IsGameMaster() && me.IsInRange(player, 8.0f, 25.0f, false))
|
||||
{
|
||||
DoResetThreat();
|
||||
me.AddThreat(player, 5.0f);
|
||||
DoCast(player, TrialOfChampionSpells.INTERCEPT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
task.Repeat(TimeSpan.FromSeconds(7));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12), task =>
|
||||
{
|
||||
DoCastVictim(TrialOfChampionSpells.MORTAL_STRIKE);
|
||||
task.Repeat(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
base.UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim() || InVehicle())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Script]
|
||||
// Ambrose Boltspark && Eressea Dawnsinger || Mage
|
||||
class boss_mage_toc5 : boss_basic_toc5AI
|
||||
{
|
||||
public boss_mage_toc5(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
DoCastVictim(TrialOfChampionSpells.FIREBALL);
|
||||
task.Repeat(TimeSpan.FromSeconds(5));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, TrialOfChampionSpells.POLYMORPH);
|
||||
task.Repeat(TimeSpan.FromSeconds(8));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
|
||||
{
|
||||
DoCastAOE(TrialOfChampionSpells.BLAST_WAVE, false);
|
||||
task.Repeat(TimeSpan.FromSeconds(13));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(22), task =>
|
||||
{
|
||||
me.InterruptNonMeleeSpells(true);
|
||||
|
||||
DoCast(me, TrialOfChampionSpells.HASTE);
|
||||
task.Repeat(TimeSpan.FromSeconds(22));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
base.UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim() || InVehicle())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
// Colosos && Runok Wildmane || Shaman
|
||||
class boss_shaman_toc5 : boss_basic_toc5AI
|
||||
{
|
||||
public boss_shaman_toc5(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(16), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, TrialOfChampionSpells.CHAIN_LIGHTNING);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(16));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
|
||||
{
|
||||
bool bChance = RandomHelper.randChance(50);
|
||||
|
||||
if (!bChance)
|
||||
{
|
||||
Unit pFriend = DoSelectLowestHpFriendly(40);
|
||||
if (pFriend)
|
||||
DoCast(pFriend, TrialOfChampionSpells.HEALING_WAVE);
|
||||
}
|
||||
else
|
||||
DoCast(me, TrialOfChampionSpells.HEALING_WAVE);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(12));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35), task =>
|
||||
{
|
||||
DoCast(me, TrialOfChampionSpells.EARTH_SHIELD);
|
||||
task.Repeat(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(25), task =>
|
||||
{
|
||||
DoCastVictim(TrialOfChampionSpells.HEX_OF_MENDING, true);
|
||||
task.Repeat(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(25));
|
||||
});
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
DoCast(me, TrialOfChampionSpells.EARTH_SHIELD);
|
||||
DoCast(who, TrialOfChampionSpells.HEX_OF_MENDING);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
base.UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim() || InVehicle())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
// Jaelyne Evensong && Zul'tore || Hunter
|
||||
class boss_hunter_toc5 : boss_basic_toc5AI
|
||||
{
|
||||
public boss_hunter_toc5(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), task =>
|
||||
{
|
||||
DoCastAOE(TrialOfChampionSpells.LIGHTNING_ARROWS, false);
|
||||
task.Repeat(TimeSpan.FromSeconds(7));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
|
||||
{
|
||||
ObjectGuid uiTargetGUID = ObjectGuid.Empty;
|
||||
Unit target = SelectTarget(SelectAggroTarget.Farthest, 0, 30.0f);
|
||||
if (target)
|
||||
{
|
||||
uiTargetGUID = target.GetGUID();
|
||||
DoCast(target, TrialOfChampionSpells.SHOOT);
|
||||
}
|
||||
|
||||
bool bShoot = true;
|
||||
task.Repeat(TimeSpan.FromSeconds(12));
|
||||
task.Schedule(TimeSpan.FromSeconds(3), task1 =>
|
||||
{
|
||||
if (bShoot)
|
||||
{
|
||||
me.InterruptNonMeleeSpells(true);
|
||||
|
||||
Unit target1 = Global.ObjAccessor.GetUnit(me, uiTargetGUID);
|
||||
if (target1 && me.IsInRange(target1, 5.0f, 30.0f, false))
|
||||
{
|
||||
DoCast(target1, TrialOfChampionSpells.MULTI_SHOT);
|
||||
}
|
||||
else
|
||||
{
|
||||
var players = me.GetMap().GetPlayers();
|
||||
if (!players.Empty())
|
||||
{
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player && !player.IsGameMaster() && me.IsInRange(player, 5.0f, 30.0f, false))
|
||||
{
|
||||
DoCast(player, TrialOfChampionSpells.MULTI_SHOT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bShoot = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
base.UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim() || InVehicle())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge
|
||||
class boss_rouge_toc5 : boss_basic_toc5AI
|
||||
{
|
||||
public boss_rouge_toc5(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
DoCastVictim(TrialOfChampionSpells.EVISCERATE);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(8));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(14), task =>
|
||||
{
|
||||
DoCastAOE(TrialOfChampionSpells.FAN_OF_KNIVES, false);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(14));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(19), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, TrialOfChampionSpells.POISON_BOTTLE);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(19));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
base.UpdateAI(diff);
|
||||
|
||||
if (!UpdateVictim() || !me.m_movementInfo.transport.guid.IsEmpty())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* 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 Framework.GameMath;
|
||||
using Framework.IO;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Game.AI;
|
||||
|
||||
namespace Scripts.Northrend.CrusadersColiseum.TrialOfTheChampion
|
||||
{
|
||||
[Script]
|
||||
class instance_trial_of_the_champion : InstanceMapScript
|
||||
{
|
||||
public instance_trial_of_the_champion() : base("instance_trial_of_the_champion", 650) { }
|
||||
|
||||
class instance_trial_of_the_champion_InstanceMapScript : InstanceScript
|
||||
{
|
||||
public instance_trial_of_the_champion_InstanceMapScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("TC");
|
||||
uiMovementDone = 0;
|
||||
uiGrandChampionsDeaths = 0;
|
||||
uiArgentSoldierDeaths = 0;
|
||||
|
||||
//bDone = false;
|
||||
}
|
||||
|
||||
public override bool IsEncounterInProgress()
|
||||
{
|
||||
for (byte i = 0; i < 4; ++i)
|
||||
{
|
||||
if (m_auiEncounter[i] == EncounterState.InProgress)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
var players = instance.GetPlayers();
|
||||
Team TeamInInstance = 0;
|
||||
|
||||
if (!players.Empty())
|
||||
{
|
||||
Player player = players.First();
|
||||
if (player)
|
||||
TeamInInstance = player.GetTeam();
|
||||
}
|
||||
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
// Champions
|
||||
case VehicleIds.MOKRA_SKILLCRUSHER_MOUNT:
|
||||
if (TeamInInstance == Team.Horde)
|
||||
creature.UpdateEntry(VehicleIds.MARSHAL_JACOB_ALERIUS_MOUNT);
|
||||
break;
|
||||
case VehicleIds.ERESSEA_DAWNSINGER_MOUNT:
|
||||
if (TeamInInstance == Team.Horde)
|
||||
creature.UpdateEntry(VehicleIds.AMBROSE_BOLTSPARK_MOUNT);
|
||||
break;
|
||||
case VehicleIds.RUNOK_WILDMANE_MOUNT:
|
||||
if (TeamInInstance == Team.Horde)
|
||||
creature.UpdateEntry(VehicleIds.COLOSOS_MOUNT);
|
||||
break;
|
||||
case VehicleIds.ZUL_TORE_MOUNT:
|
||||
if (TeamInInstance == Team.Horde)
|
||||
creature.UpdateEntry(VehicleIds.EVENSONG_MOUNT);
|
||||
break;
|
||||
case VehicleIds.DEATHSTALKER_VESCERI_MOUNT:
|
||||
if (TeamInInstance == Team.Horde)
|
||||
creature.UpdateEntry(VehicleIds.LANA_STOUTHAMMER_MOUNT);
|
||||
break;
|
||||
// Coliseum Announcer || Just NPC_JAEREN must be spawned.
|
||||
case CreatureIds.JAEREN:
|
||||
uiAnnouncerGUID = creature.GetGUID();
|
||||
if (TeamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.ARELAS);
|
||||
break;
|
||||
case VehicleIds.ARGENT_WARHORSE:
|
||||
case VehicleIds.ARGENT_BATTLEWORG:
|
||||
VehicleList.Add(creature.GetGUID());
|
||||
break;
|
||||
case CreatureIds.EADRIC:
|
||||
case CreatureIds.PALETRESS:
|
||||
uiArgentChampionGUID = creature.GetGUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectCreate(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GameObjectIds.MAIN_GATE:
|
||||
uiMainGateGUID = go.GetGUID();
|
||||
break;
|
||||
case GameObjectIds.CHAMPIONS_LOOT:
|
||||
case GameObjectIds.CHAMPIONS_LOOT_H:
|
||||
uiChampionLootGUID = go.GetGUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetData(uint uiType, uint uiData)
|
||||
{
|
||||
switch (uiType)
|
||||
{
|
||||
case (uint)Data.DATA_MOVEMENT_DONE:
|
||||
uiMovementDone = (ushort)uiData;
|
||||
if (uiMovementDone == 3)
|
||||
{
|
||||
Creature pAnnouncer = instance.GetCreature(uiAnnouncerGUID);
|
||||
if (pAnnouncer)
|
||||
pAnnouncer.GetAI().SetData((uint)Data.DATA_IN_POSITION, 0);
|
||||
}
|
||||
break;
|
||||
case (uint)Data.BOSS_GRAND_CHAMPIONS:
|
||||
m_auiEncounter[0] = (EncounterState)uiData;
|
||||
if (uiData == (uint)EncounterState.InProgress)
|
||||
{
|
||||
foreach (var guid in VehicleList)
|
||||
{
|
||||
Creature summon = instance.GetCreature(guid);
|
||||
if (summon)
|
||||
summon.RemoveFromWorld();
|
||||
}
|
||||
}
|
||||
else if (uiData == (uint)EncounterState.Done)
|
||||
{
|
||||
++uiGrandChampionsDeaths;
|
||||
if (uiGrandChampionsDeaths == 3)
|
||||
{
|
||||
Creature pAnnouncer = instance.GetCreature(uiAnnouncerGUID);
|
||||
if (pAnnouncer)
|
||||
{
|
||||
pAnnouncer.GetMotionMaster().MovePoint(0, 748.309f, 619.487f, 411.171f);
|
||||
pAnnouncer.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
pAnnouncer.SummonGameObject(instance.IsHeroic() ? GameObjectIds.CHAMPIONS_LOOT_H : GameObjectIds.CHAMPIONS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, Quaternion.WAxis, 90000);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case (uint)Data.DATA_ARGENT_SOLDIER_DEFEATED:
|
||||
uiArgentSoldierDeaths = (byte)uiData;
|
||||
if (uiArgentSoldierDeaths == 9)
|
||||
{
|
||||
Creature pBoss = instance.GetCreature(uiArgentChampionGUID);
|
||||
if (pBoss)
|
||||
{
|
||||
pBoss.GetMotionMaster().MovePoint(0, 746.88f, 618.74f, 411.06f);
|
||||
pBoss.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
pBoss.SetReactState(ReactStates.Aggressive);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case (uint)Data.BOSS_ARGENT_CHALLENGE_E:
|
||||
{
|
||||
m_auiEncounter[1] = (EncounterState)uiData;
|
||||
Creature pAnnouncer = instance.GetCreature(uiAnnouncerGUID);
|
||||
if (pAnnouncer)
|
||||
{
|
||||
pAnnouncer.GetMotionMaster().MovePoint(0, 748.309f, 619.487f, 411.171f);
|
||||
pAnnouncer.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
pAnnouncer.SummonGameObject(instance.IsHeroic() ? GameObjectIds.EADRIC_LOOT_H : GameObjectIds.EADRIC_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, Quaternion.WAxis, 90000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case (uint)Data.BOSS_ARGENT_CHALLENGE_P:
|
||||
{
|
||||
m_auiEncounter[2] = (EncounterState)uiData;
|
||||
Creature pAnnouncer = instance.GetCreature(uiAnnouncerGUID);
|
||||
if (pAnnouncer)
|
||||
{
|
||||
pAnnouncer.GetMotionMaster().MovePoint(0, 748.309f, 619.487f, 411.171f);
|
||||
pAnnouncer.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
pAnnouncer.SummonGameObject(instance.IsHeroic() ? GameObjectIds.PALETRESS_LOOT_H : GameObjectIds.PALETRESS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, Quaternion.WAxis, 90000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (uiData == (uint)EncounterState.Done)
|
||||
SaveToDB();
|
||||
}
|
||||
|
||||
public override uint GetData(uint uiData)
|
||||
{
|
||||
switch (uiData)
|
||||
{
|
||||
case (uint)Data.BOSS_GRAND_CHAMPIONS:
|
||||
return (uint)m_auiEncounter[0];
|
||||
case (uint)Data.BOSS_ARGENT_CHALLENGE_E:
|
||||
return (uint)m_auiEncounter[1];
|
||||
case (uint)Data.BOSS_ARGENT_CHALLENGE_P:
|
||||
return (uint)m_auiEncounter[2];
|
||||
case (uint)Data.BOSS_BLACK_KNIGHT:
|
||||
return (uint)m_auiEncounter[3];
|
||||
|
||||
case (uint)Data.DATA_MOVEMENT_DONE:
|
||||
return uiMovementDone;
|
||||
case (uint)Data.DATA_ARGENT_SOLDIER_DEFEATED:
|
||||
return uiArgentSoldierDeaths;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGuidData(uint uiData)
|
||||
{
|
||||
switch (uiData)
|
||||
{
|
||||
case (uint)Data64.DATA_ANNOUNCER:
|
||||
return uiAnnouncerGUID;
|
||||
case (uint)Data64.DATA_MAIN_GATE:
|
||||
return uiMainGateGUID;
|
||||
|
||||
case (uint)Data64.DATA_GRAND_CHAMPION_1:
|
||||
return uiGrandChampion1GUID;
|
||||
case (uint)Data64.DATA_GRAND_CHAMPION_2:
|
||||
return uiGrandChampion2GUID;
|
||||
case (uint)Data64.DATA_GRAND_CHAMPION_3:
|
||||
return uiGrandChampion3GUID;
|
||||
}
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
public override void SetGuidData(uint uiType, ObjectGuid uiData)
|
||||
{
|
||||
switch (uiType)
|
||||
{
|
||||
case (uint)Data64.DATA_GRAND_CHAMPION_1:
|
||||
uiGrandChampion1GUID = uiData;
|
||||
break;
|
||||
case (uint)Data64.DATA_GRAND_CHAMPION_2:
|
||||
uiGrandChampion2GUID = uiData;
|
||||
break;
|
||||
case (uint)Data64.DATA_GRAND_CHAMPION_3:
|
||||
uiGrandChampion3GUID = uiData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetSaveData()
|
||||
{
|
||||
OUT_SAVE_INST_DATA();
|
||||
|
||||
string str_data = string.Format("T C {0} {1} {2} {3} {4} {5}", m_auiEncounter[0], m_auiEncounter[1], m_auiEncounter[2], m_auiEncounter[3], uiGrandChampionsDeaths, uiMovementDone);
|
||||
|
||||
OUT_SAVE_INST_DATA_COMPLETE();
|
||||
return str_data;
|
||||
}
|
||||
|
||||
public override void Load(string str)
|
||||
{
|
||||
if (str.IsEmpty())
|
||||
{
|
||||
OUT_LOAD_INST_DATA_FAIL();
|
||||
return;
|
||||
}
|
||||
|
||||
OUT_LOAD_INST_DATA(str);
|
||||
|
||||
StringArguments loadStream = new StringArguments(str);
|
||||
string dataHead = loadStream.NextString();
|
||||
|
||||
if (dataHead[0] == 'T' && dataHead[1] == 'C')
|
||||
{
|
||||
for (byte i = 0; i < 4; ++i)
|
||||
{
|
||||
m_auiEncounter[i] = (EncounterState)loadStream.NextUInt32();
|
||||
if (m_auiEncounter[i] == EncounterState.InProgress)
|
||||
m_auiEncounter[i] = EncounterState.NotStarted;
|
||||
|
||||
}
|
||||
|
||||
uiGrandChampionsDeaths = loadStream.NextUInt16();
|
||||
uiMovementDone = loadStream.NextUInt16();
|
||||
}
|
||||
else
|
||||
OUT_LOAD_INST_DATA_FAIL();
|
||||
|
||||
OUT_LOAD_INST_DATA_COMPLETE();
|
||||
}
|
||||
|
||||
EncounterState[] m_auiEncounter = new EncounterState[4];
|
||||
|
||||
ushort uiMovementDone;
|
||||
ushort uiGrandChampionsDeaths;
|
||||
byte uiArgentSoldierDeaths;
|
||||
|
||||
ObjectGuid uiAnnouncerGUID;
|
||||
ObjectGuid uiMainGateGUID;
|
||||
//ObjectGuid uiGrandChampionVehicle1GUID;
|
||||
//ObjectGuid uiGrandChampionVehicle2GUID;
|
||||
//ObjectGuid uiGrandChampionVehicle3GUID;
|
||||
ObjectGuid uiGrandChampion1GUID;
|
||||
ObjectGuid uiGrandChampion2GUID;
|
||||
ObjectGuid uiGrandChampion3GUID;
|
||||
ObjectGuid uiChampionLootGUID;
|
||||
ObjectGuid uiArgentChampionGUID;
|
||||
|
||||
List<ObjectGuid> VehicleList = new List<ObjectGuid>();
|
||||
|
||||
//bool bDone;
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_trial_of_the_champion_InstanceMapScript(map);
|
||||
}
|
||||
|
||||
public static T GetTrialOfTheChampionAI<T>(Creature creature) where T : CreatureAI
|
||||
{
|
||||
return GetInstanceAI<T>(creature, "instance_trial_of_the_champion");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,588 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
|
||||
|
||||
namespace Scripts.Northrend.CrusadersColiseum.TrialOfTheChampion
|
||||
{
|
||||
struct TrialOfTheChampionConst
|
||||
{
|
||||
public const uint SAY_INTRO_1 = 0;
|
||||
public const uint SAY_INTRO_2 = 1;
|
||||
public const uint SAY_INTRO_3 = 2;
|
||||
public const uint SAY_AGGRO = 3;
|
||||
public const uint SAY_PHASE_2 = 4;
|
||||
public const uint SAY_PHASE_3 = 5;
|
||||
public const uint SAY_KILL_PLAYER = 6;
|
||||
public const uint SAY_DEATH = 7;
|
||||
|
||||
public const string GOSSIP_START_EVENT1 = "I'm ready to start challenge.";
|
||||
public const string GOSSIP_START_EVENT2 = "I'm ready for the next challenge.";
|
||||
}
|
||||
|
||||
enum Data
|
||||
{
|
||||
BOSS_GRAND_CHAMPIONS,
|
||||
BOSS_ARGENT_CHALLENGE_E,
|
||||
BOSS_ARGENT_CHALLENGE_P,
|
||||
BOSS_BLACK_KNIGHT,
|
||||
DATA_MOVEMENT_DONE,
|
||||
DATA_LESSER_CHAMPIONS_DEFEATED,
|
||||
DATA_START,
|
||||
DATA_IN_POSITION,
|
||||
DATA_ARGENT_SOLDIER_DEFEATED
|
||||
};
|
||||
|
||||
enum Data64
|
||||
{
|
||||
DATA_ANNOUNCER,
|
||||
DATA_MAIN_GATE,
|
||||
|
||||
DATA_GRAND_CHAMPION_VEHICLE_1,
|
||||
DATA_GRAND_CHAMPION_VEHICLE_2,
|
||||
DATA_GRAND_CHAMPION_VEHICLE_3,
|
||||
|
||||
DATA_GRAND_CHAMPION_1,
|
||||
DATA_GRAND_CHAMPION_2,
|
||||
DATA_GRAND_CHAMPION_3
|
||||
};
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
// Horde Champions
|
||||
public const uint MOKRA = 35572;
|
||||
public const uint ERESSEA = 35569;
|
||||
public const uint RUNOK = 35571;
|
||||
public const uint ZULTORE = 35570;
|
||||
public const uint VISCERI = 35617;
|
||||
|
||||
// Alliance Champions
|
||||
public const uint JACOB = 34705;
|
||||
public const uint AMBROSE = 34702;
|
||||
public const uint COLOSOS = 34701;
|
||||
public const uint JAELYNE = 34657;
|
||||
public const uint LANA = 34703;
|
||||
|
||||
public const uint EADRIC = 35119;
|
||||
public const uint PALETRESS = 34928;
|
||||
|
||||
public const uint ARGENT_LIGHWIELDER = 35309;
|
||||
public const uint ARGENT_MONK = 35305;
|
||||
public const uint PRIESTESS = 35307;
|
||||
|
||||
public const uint BLACK_KNIGHT = 35451;
|
||||
|
||||
public const uint RISEN_JAEREN = 35545;
|
||||
public const uint RISEN_ARELAS = 35564;
|
||||
|
||||
public const uint JAEREN = 35004;
|
||||
public const uint ARELAS = 35005;
|
||||
}
|
||||
|
||||
struct GameObjectIds
|
||||
{
|
||||
public const uint MAIN_GATE = 195647;
|
||||
|
||||
public const uint CHAMPIONS_LOOT = 195709;
|
||||
public const uint CHAMPIONS_LOOT_H = 195710;
|
||||
|
||||
public const uint EADRIC_LOOT = 195374;
|
||||
public const uint EADRIC_LOOT_H = 195375;
|
||||
|
||||
public const uint PALETRESS_LOOT = 195323;
|
||||
public const uint PALETRESS_LOOT_H = 195324;
|
||||
}
|
||||
|
||||
struct VehicleIds
|
||||
{
|
||||
//Grand Champions Alliance Vehicles
|
||||
public const uint MARSHAL_JACOB_ALERIUS_MOUNT = 35637;
|
||||
public const uint AMBROSE_BOLTSPARK_MOUNT = 35633;
|
||||
public const uint COLOSOS_MOUNT = 35768;
|
||||
public const uint EVENSONG_MOUNT = 34658;
|
||||
public const uint LANA_STOUTHAMMER_MOUNT = 35636;
|
||||
//Faction Champions (ALLIANCE)
|
||||
public const uint DARNASSIA_NIGHTSABER = 33319;
|
||||
public const uint EXODAR_ELEKK = 33318;
|
||||
public const uint STORMWIND_STEED = 33217;
|
||||
public const uint GNOMEREGAN_MECHANOSTRIDER = 33317;
|
||||
public const uint IRONFORGE_RAM = 33316;
|
||||
//Grand Champions Horde Vehicles
|
||||
public const uint MOKRA_SKILLCRUSHER_MOUNT = 35638;
|
||||
public const uint ERESSEA_DAWNSINGER_MOUNT = 35635;
|
||||
public const uint RUNOK_WILDMANE_MOUNT = 35640;
|
||||
public const uint ZUL_TORE_MOUNT = 35641;
|
||||
public const uint DEATHSTALKER_VESCERI_MOUNT = 35634;
|
||||
//Faction Champions (HORDE)
|
||||
public const uint FORSAKE_WARHORSE = 33324;
|
||||
public const uint THUNDER_BLUFF_KODO = 33322;
|
||||
public const uint ORGRIMMAR_WOLF = 33320;
|
||||
public const uint SILVERMOON_HAWKSTRIDER = 33323;
|
||||
public const uint DARKSPEAR_RAPTOR = 33321;
|
||||
|
||||
public const uint ARGENT_WARHORSE = 35644;
|
||||
public const uint ARGENT_BATTLEWORG = 36558;
|
||||
|
||||
public const uint BLACK_KNIGHT = 35491;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_announcer_toc5 : CreatureScript
|
||||
{
|
||||
public npc_announcer_toc5() : base("npc_announcer_toc5") { }
|
||||
|
||||
class npc_announcer_toc5AI : ScriptedAI
|
||||
{
|
||||
public npc_announcer_toc5AI(Creature creature) : base(creature)
|
||||
{
|
||||
instance = creature.GetInstanceScript();
|
||||
|
||||
uiSummonTimes = 0;
|
||||
uiLesserChampions = 0;
|
||||
|
||||
uiFirstBoss = 0;
|
||||
uiSecondBoss = 0;
|
||||
uiThirdBoss = 0;
|
||||
|
||||
uiArgentChampion = 0;
|
||||
|
||||
uiPhase = 0;
|
||||
uiTimer = 0;
|
||||
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
me.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
|
||||
SetGrandChampionsForEncounter();
|
||||
SetArgentChampion();
|
||||
}
|
||||
|
||||
void NextStep(uint uiTimerStep, bool bNextStep = true, byte uiPhaseStep = 0)
|
||||
{
|
||||
uiTimer = uiTimerStep;
|
||||
if (bNextStep)
|
||||
++uiPhase;
|
||||
else
|
||||
uiPhase = uiPhaseStep;
|
||||
}
|
||||
|
||||
public override void SetData(uint uiType, uint uiData)
|
||||
{
|
||||
switch (uiType)
|
||||
{
|
||||
case (uint)Data.DATA_START:
|
||||
DoSummonGrandChampion(uiFirstBoss);
|
||||
NextStep(10000, false, 1);
|
||||
break;
|
||||
case (uint)Data.DATA_IN_POSITION: //movement EncounterState.Done.
|
||||
me.GetMotionMaster().MovePoint(1, 735.81f, 661.92f, 412.39f);
|
||||
GameObject go = ObjectAccessor.GetGameObject(me, instance.GetGuidData((uint)Data64.DATA_MAIN_GATE));
|
||||
if (go)
|
||||
instance.HandleGameObject(go.GetGUID(), false);
|
||||
NextStep(10000, false, 3);
|
||||
break;
|
||||
case (uint)Data.DATA_LESSER_CHAMPIONS_DEFEATED:
|
||||
{
|
||||
++uiLesserChampions;
|
||||
List<ObjectGuid> TempList = new List<ObjectGuid>();
|
||||
if (uiLesserChampions == 3 || uiLesserChampions == 6)
|
||||
{
|
||||
switch (uiLesserChampions)
|
||||
{
|
||||
case 3:
|
||||
TempList = Champion2List;
|
||||
break;
|
||||
case 6:
|
||||
TempList = Champion3List;
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var guid in TempList)
|
||||
{
|
||||
Creature summon = ObjectAccessor.GetCreature(me, guid);
|
||||
if (summon)
|
||||
AggroAllPlayers(summon);
|
||||
}
|
||||
}
|
||||
else if (uiLesserChampions == 9)
|
||||
StartGrandChampionsAttack();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StartGrandChampionsAttack()
|
||||
{
|
||||
Creature pGrandChampion1 = ObjectAccessor.GetCreature(me, uiVehicle1GUID);
|
||||
Creature pGrandChampion2 = ObjectAccessor.GetCreature(me, uiVehicle2GUID);
|
||||
Creature pGrandChampion3 = ObjectAccessor.GetCreature(me, uiVehicle3GUID);
|
||||
|
||||
if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3)
|
||||
{
|
||||
AggroAllPlayers(pGrandChampion1);
|
||||
AggroAllPlayers(pGrandChampion2);
|
||||
AggroAllPlayers(pGrandChampion3);
|
||||
}
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType uiType, uint uiPointId)
|
||||
{
|
||||
if (uiType != MovementGeneratorType.Point)
|
||||
return;
|
||||
|
||||
if (uiPointId == 1)
|
||||
me.SetFacingTo(4.714f);
|
||||
}
|
||||
|
||||
void DoSummonGrandChampion(uint uiBoss)
|
||||
{
|
||||
++uiSummonTimes;
|
||||
uint VEHICLE_TO_SUMMON1 = 0;
|
||||
uint VEHICLE_TO_SUMMON2 = 0;
|
||||
switch (uiBoss)
|
||||
{
|
||||
case 0:
|
||||
VEHICLE_TO_SUMMON1 = VehicleIds.MOKRA_SKILLCRUSHER_MOUNT;
|
||||
VEHICLE_TO_SUMMON2 = VehicleIds.ORGRIMMAR_WOLF;
|
||||
break;
|
||||
case 1:
|
||||
VEHICLE_TO_SUMMON1 = VehicleIds.ERESSEA_DAWNSINGER_MOUNT;
|
||||
VEHICLE_TO_SUMMON2 = VehicleIds.SILVERMOON_HAWKSTRIDER;
|
||||
break;
|
||||
case 2:
|
||||
VEHICLE_TO_SUMMON1 = VehicleIds.RUNOK_WILDMANE_MOUNT;
|
||||
VEHICLE_TO_SUMMON2 = VehicleIds.THUNDER_BLUFF_KODO;
|
||||
break;
|
||||
case 3:
|
||||
VEHICLE_TO_SUMMON1 = VehicleIds.ZUL_TORE_MOUNT;
|
||||
VEHICLE_TO_SUMMON2 = VehicleIds.DARKSPEAR_RAPTOR;
|
||||
break;
|
||||
case 4:
|
||||
VEHICLE_TO_SUMMON1 = VehicleIds.DEATHSTALKER_VESCERI_MOUNT;
|
||||
VEHICLE_TO_SUMMON2 = VehicleIds.FORSAKE_WARHORSE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
Creature pBoss = me.SummonCreature(VEHICLE_TO_SUMMON1, SpawnPosition);
|
||||
if (pBoss)
|
||||
{
|
||||
ObjectGuid uiGrandChampionBoss = ObjectGuid.Empty;
|
||||
Vehicle pVehicle = pBoss.GetVehicleKit();
|
||||
if (pVehicle)
|
||||
{
|
||||
Unit unit = pVehicle.GetPassenger(0);
|
||||
if (unit)
|
||||
uiGrandChampionBoss = unit.GetGUID();
|
||||
}
|
||||
|
||||
switch (uiSummonTimes)
|
||||
{
|
||||
case 1:
|
||||
uiVehicle1GUID = pBoss.GetGUID();
|
||||
instance.SetGuidData((uint)Data64.DATA_GRAND_CHAMPION_VEHICLE_1, uiVehicle1GUID);
|
||||
instance.SetGuidData((uint)Data64.DATA_GRAND_CHAMPION_1, uiGrandChampionBoss);
|
||||
break;
|
||||
case 2:
|
||||
|
||||
uiVehicle2GUID = pBoss.GetGUID();
|
||||
instance.SetGuidData((uint)Data64.DATA_GRAND_CHAMPION_VEHICLE_2, uiVehicle2GUID);
|
||||
instance.SetGuidData((uint)Data64.DATA_GRAND_CHAMPION_2, uiGrandChampionBoss);
|
||||
break;
|
||||
case 3:
|
||||
uiVehicle3GUID = pBoss.GetGUID();
|
||||
instance.SetGuidData((uint)Data64.DATA_GRAND_CHAMPION_VEHICLE_3, uiVehicle3GUID);
|
||||
instance.SetGuidData((uint)Data64.DATA_GRAND_CHAMPION_3, uiGrandChampionBoss);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
pBoss.GetAI().SetData(uiSummonTimes, 0);
|
||||
|
||||
for (byte i = 0; i < 3; ++i)
|
||||
{
|
||||
Creature pAdd = me.SummonCreature(VEHICLE_TO_SUMMON2, SpawnPosition, TempSummonType.CorpseDespawn);
|
||||
if (pAdd)
|
||||
{
|
||||
switch (uiSummonTimes)
|
||||
{
|
||||
case 1:
|
||||
Champion1List.Add(pAdd.GetGUID());
|
||||
break;
|
||||
case 2:
|
||||
Champion2List.Add(pAdd.GetGUID());
|
||||
break;
|
||||
case 3:
|
||||
Champion3List.Add(pAdd.GetGUID());
|
||||
break;
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
pAdd.GetMotionMaster().MoveFollow(pBoss, 2.0f, MathFunctions.PI);
|
||||
break;
|
||||
case 1:
|
||||
pAdd.GetMotionMaster().MoveFollow(pBoss, 2.0f, MathFunctions.PI / 2);
|
||||
break;
|
||||
case 2:
|
||||
pAdd.GetMotionMaster().MoveFollow(pBoss, 2.0f, MathFunctions.PI / 2 + MathFunctions.PI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoStartArgentChampionEncounter()
|
||||
{
|
||||
me.GetMotionMaster().MovePoint(1, 735.81f, 661.92f, 412.39f);
|
||||
|
||||
if (me.SummonCreature(uiArgentChampion, SpawnPosition))
|
||||
{
|
||||
for (byte i = 0; i < 3; ++i)
|
||||
{
|
||||
Creature lightwielderTrash = me.SummonCreature(CreatureIds.ARGENT_LIGHWIELDER, SpawnPosition);
|
||||
if (lightwielderTrash)
|
||||
lightwielderTrash.GetAI().SetData(i, 0);
|
||||
|
||||
Creature monkTrash = me.SummonCreature(CreatureIds.ARGENT_MONK, SpawnPosition);
|
||||
if (monkTrash)
|
||||
monkTrash.GetAI().SetData(i, 0);
|
||||
|
||||
Creature priestessTrash = me.SummonCreature(CreatureIds.PRIESTESS, SpawnPosition);
|
||||
if (priestessTrash)
|
||||
priestessTrash.GetAI().SetData(i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetGrandChampionsForEncounter()
|
||||
{
|
||||
uiFirstBoss = RandomHelper.URand(0, 4);
|
||||
|
||||
while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss)
|
||||
{
|
||||
uiSecondBoss = RandomHelper.URand(0, 4);
|
||||
uiThirdBoss = RandomHelper.URand(0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void SetArgentChampion()
|
||||
{
|
||||
byte uiTempBoss = (byte)RandomHelper.URand(0, 1);
|
||||
|
||||
switch (uiTempBoss)
|
||||
{
|
||||
case 0:
|
||||
uiArgentChampion = CreatureIds.EADRIC;
|
||||
break;
|
||||
case 1:
|
||||
uiArgentChampion = CreatureIds.PALETRESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void StartEncounter()
|
||||
{
|
||||
me.RemoveFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
|
||||
if (instance.GetData((uint)Data.BOSS_BLACK_KNIGHT) == (uint)EncounterState.NotStarted)
|
||||
{
|
||||
if (instance.GetData((uint)Data.BOSS_ARGENT_CHALLENGE_E) == (uint)EncounterState.NotStarted && instance.GetData((uint)Data.BOSS_ARGENT_CHALLENGE_P) == (uint)EncounterState.NotStarted)
|
||||
{
|
||||
if (instance.GetData((uint)Data.BOSS_GRAND_CHAMPIONS) == (uint)EncounterState.NotStarted)
|
||||
SetData((uint)Data.DATA_START, 0);
|
||||
|
||||
if (instance.GetData((uint)Data.BOSS_GRAND_CHAMPIONS) == (uint)EncounterState.Done)
|
||||
DoStartArgentChampionEncounter();
|
||||
}
|
||||
|
||||
if ((instance.GetData((uint)Data.BOSS_GRAND_CHAMPIONS) == (uint)EncounterState.Done &&
|
||||
instance.GetData((uint)Data.BOSS_ARGENT_CHALLENGE_E) == (uint)EncounterState.Done) ||
|
||||
instance.GetData((uint)Data.BOSS_ARGENT_CHALLENGE_P) == (uint)EncounterState.Done)
|
||||
me.SummonCreature(VehicleIds.BLACK_KNIGHT, 769.834f, 651.915f, 447.035f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void AggroAllPlayers(Creature temp)
|
||||
{
|
||||
var PlList = me.GetMap().GetPlayers();
|
||||
|
||||
if (PlList.Empty())
|
||||
return;
|
||||
|
||||
foreach (var player in PlList)
|
||||
{
|
||||
if (player.IsGameMaster())
|
||||
continue;
|
||||
|
||||
if (player.IsAlive())
|
||||
{
|
||||
temp.SetHomePosition(me.GetPositionX(), me.GetPositionY(), me.GetPositionZ(), me.GetOrientation());
|
||||
temp.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
temp.SetReactState(ReactStates.Aggressive);
|
||||
temp.SetInCombatWith(player);
|
||||
player.SetInCombatWith(temp);
|
||||
temp.AddThreat(player, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
base.UpdateAI(diff);
|
||||
|
||||
if (uiTimer <= diff)
|
||||
{
|
||||
switch (uiPhase)
|
||||
{
|
||||
case 1:
|
||||
DoSummonGrandChampion(uiSecondBoss);
|
||||
NextStep(10000, true);
|
||||
break;
|
||||
case 2:
|
||||
DoSummonGrandChampion(uiThirdBoss);
|
||||
NextStep(0, false);
|
||||
break;
|
||||
case 3:
|
||||
if (!Champion1List.Empty())
|
||||
{
|
||||
foreach (var guid in Champion1List)
|
||||
{
|
||||
Creature summon = ObjectAccessor.GetCreature(me, guid);
|
||||
if (summon)
|
||||
AggroAllPlayers(summon);
|
||||
}
|
||||
NextStep(0, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
uiTimer -= diff;
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
if (instance.GetData((uint)Data.BOSS_GRAND_CHAMPIONS) == (uint)EncounterState.NotStarted)
|
||||
{
|
||||
summon.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
summon.SetReactState(ReactStates.Passive);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SummonedCreatureDespawn(Creature summon)
|
||||
{
|
||||
switch (summon.GetEntry())
|
||||
{
|
||||
case VehicleIds.DARNASSIA_NIGHTSABER:
|
||||
case VehicleIds.EXODAR_ELEKK:
|
||||
case VehicleIds.STORMWIND_STEED:
|
||||
case VehicleIds.GNOMEREGAN_MECHANOSTRIDER:
|
||||
case VehicleIds.IRONFORGE_RAM:
|
||||
case VehicleIds.FORSAKE_WARHORSE:
|
||||
case VehicleIds.THUNDER_BLUFF_KODO:
|
||||
case VehicleIds.ORGRIMMAR_WOLF:
|
||||
case VehicleIds.SILVERMOON_HAWKSTRIDER:
|
||||
case VehicleIds.DARKSPEAR_RAPTOR:
|
||||
SetData((uint)Data.DATA_LESSER_CHAMPIONS_DEFEATED, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
|
||||
byte uiSummonTimes;
|
||||
byte uiLesserChampions;
|
||||
|
||||
uint uiArgentChampion;
|
||||
|
||||
uint uiFirstBoss;
|
||||
uint uiSecondBoss;
|
||||
uint uiThirdBoss;
|
||||
|
||||
uint uiPhase;
|
||||
uint uiTimer;
|
||||
|
||||
ObjectGuid uiVehicle1GUID;
|
||||
ObjectGuid uiVehicle2GUID;
|
||||
ObjectGuid uiVehicle3GUID;
|
||||
|
||||
List<ObjectGuid> Champion1List = new List<ObjectGuid>();
|
||||
List<ObjectGuid> Champion2List = new List<ObjectGuid>();
|
||||
List<ObjectGuid> Champion3List = new List<ObjectGuid>();
|
||||
|
||||
Position SpawnPosition = new Position(746.261f, 657.401f, 411.681f, 4.65f);
|
||||
}
|
||||
|
||||
public override bool OnGossipHello(Player player, Creature creature)
|
||||
{
|
||||
InstanceScript instance = creature.GetInstanceScript();
|
||||
|
||||
if (instance != null &&
|
||||
((instance.GetData((uint)Data.BOSS_GRAND_CHAMPIONS) == (uint)EncounterState.Done &&
|
||||
instance.GetData((uint)Data.BOSS_BLACK_KNIGHT) == (uint)EncounterState.Done &&
|
||||
instance.GetData((uint)Data.BOSS_ARGENT_CHALLENGE_E) == (uint)EncounterState.Done) ||
|
||||
instance.GetData((uint)Data.BOSS_ARGENT_CHALLENGE_P) == (uint)EncounterState.Done))
|
||||
return false;
|
||||
|
||||
if (instance != null &&
|
||||
instance.GetData((uint)Data.BOSS_GRAND_CHAMPIONS) == (uint)EncounterState.NotStarted &&
|
||||
instance.GetData((uint)Data.BOSS_ARGENT_CHALLENGE_E) == (uint)EncounterState.NotStarted &&
|
||||
instance.GetData((uint)Data.BOSS_ARGENT_CHALLENGE_P) == (uint)EncounterState.NotStarted &&
|
||||
instance.GetData((uint)Data.BOSS_BLACK_KNIGHT) == (uint)EncounterState.NotStarted)
|
||||
player.ADD_GOSSIP_ITEM(GossipOptionIcon.Chat, TrialOfTheChampionConst.GOSSIP_START_EVENT1, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 1);
|
||||
else if (instance != null)
|
||||
player.ADD_GOSSIP_ITEM(GossipOptionIcon.Chat, TrialOfTheChampionConst.GOSSIP_START_EVENT2, eTradeskill.GossipSenderMain, eTradeskill.GossipActionInfoDef + 1);
|
||||
|
||||
player.SEND_GOSSIP_MENU(player.GetGossipTextId(creature), creature.GetGUID());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnGossipSelect(Player player, Creature creature, uint sender, uint action)
|
||||
{
|
||||
player.PlayerTalkClass.ClearMenus();
|
||||
if (action == eTradeskill.GossipActionInfoDef + 1)
|
||||
{
|
||||
player.CLOSE_GOSSIP_MENU();
|
||||
((npc_announcer_toc5AI)creature.GetAI()).StartEncounter();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override CreatureAI GetAI(Creature creature)
|
||||
{
|
||||
return instance_trial_of_the_champion.GetTrialOfTheChampionAI<npc_announcer_toc5AI>(creature);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace Scripts.Northrend.CrusadersColiseum.TrialOfTheCrusader
|
||||
{
|
||||
struct Jaraxxus
|
||||
{
|
||||
public const uint SayIntro = 0;
|
||||
public const uint SayAggro = 1;
|
||||
public const uint EmoteLegionFlame = 2;
|
||||
public const uint EmoteNetherPortal = 3;
|
||||
public const uint SayMistressOfPain = 4;
|
||||
public const uint EmoteIncinerate = 5;
|
||||
public const uint SayIncinerate = 6;
|
||||
public const uint EmoteInfernalEruption = 7;
|
||||
public const uint SayInfernalEruption = 8;
|
||||
public const uint SayKillPlayer = 9;
|
||||
public const uint SayDeath = 10;
|
||||
public const uint SayBerserk = 11;
|
||||
|
||||
public const uint NpcLegionFlame = 34784;
|
||||
public const uint NpcInfernalVolcano = 34813;
|
||||
public const uint NpcFelInfernal = 34815; // Immune To All Cc On Heroic (Stuns; Banish; Interrupt; Etc)
|
||||
public const uint NpcNetherPortal = 34825;
|
||||
public const uint NpcMistressOfPain = 34826;
|
||||
|
||||
public const uint SpellLegionFlame = 66197; // Player Should Run Away From Raid Because He Triggers Legion Flame
|
||||
public const uint SpellLegionFlameEffect = 66201; // Used By Trigger Npc
|
||||
public const uint SpellNetherPower = 66228; // +20% Of Spell Damage Per Stack; Stackable Up To 5/10 Times; Must Be Dispelled/Stealed
|
||||
public const uint SpellFelLighting = 66528; // Jumps To Nearby Targets
|
||||
public const uint SpellFelFireball = 66532; // Does Heavy Damage To The Tank; Interruptable
|
||||
public const uint SpellIncinerateFlesh = 66237; // Target Must Be Healed Or Will Trigger Burning Inferno
|
||||
public const uint SpellBurningInferno = 66242; // Triggered By Incinerate Flesh
|
||||
public const uint SpellInfernalEruption = 66258; // Summons Infernal Volcano
|
||||
public const uint SpellInfernalEruptionEffect = 66252; // Summons Felflame Infernal (3 At Normal And Inifinity At Heroic)
|
||||
public const uint SpellNetherPortal = 66269; // Summons Nether Portal
|
||||
public const uint SpellNetherPortalEffect = 66263; // Summons Mistress Of Pain (1 At Normal And Infinity At Heroic)
|
||||
|
||||
public const uint SpellBerserk = 64238; // Unused
|
||||
|
||||
// Mistress Of Pain Spells
|
||||
public const uint SpellShivanSlash = 67098;
|
||||
public const uint SpellSpinningStrike = 66283;
|
||||
public const uint SpellMistressKiss = 66336;
|
||||
public const uint SpellFelInferno = 67047;
|
||||
public const uint SpellFelStreak = 66494;
|
||||
public const int SpellLordHittin = 66326; // Special Effect Preventing More Specific Spells Be Cast On The Same Player Within 10 Seconds
|
||||
public const uint SpellMistressKissDamageSilence = 66359;
|
||||
|
||||
// Lord Jaraxxus
|
||||
public const uint EventFelFireball = 1;
|
||||
public const uint EventFelLightning = 2;
|
||||
public const uint EventIncinerateFlesh = 3;
|
||||
public const uint EventNetherPower = 4;
|
||||
public const uint EventLegionFlame = 5;
|
||||
public const uint EventSummonoNetherPortal = 6;
|
||||
public const uint EventSummonInfernalEruption = 7;
|
||||
|
||||
// Mistress Of Pain
|
||||
public const uint EventShivanSlash = 8;
|
||||
public const uint EventSpinningStrike = 9;
|
||||
public const uint EventMistressKiss = 10;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_jaraxxus : BossAI
|
||||
{
|
||||
public boss_jaraxxus(Creature creature) : base(creature, DataTypes.BossJaraxxus) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
_events.ScheduleEvent(Jaraxxus.EventFelFireball, 5 * Time.InMilliseconds);
|
||||
_events.ScheduleEvent(Jaraxxus.EventFelLightning, RandomHelper.URand(10 * Time.InMilliseconds, 15 * Time.InMilliseconds));
|
||||
_events.ScheduleEvent(Jaraxxus.EventIncinerateFlesh, RandomHelper.URand(20 * Time.InMilliseconds, 25 * Time.InMilliseconds));
|
||||
_events.ScheduleEvent(Jaraxxus.EventNetherPower, 40 * Time.InMilliseconds);
|
||||
_events.ScheduleEvent(Jaraxxus.EventLegionFlame, 30 * Time.InMilliseconds);
|
||||
_events.ScheduleEvent(Jaraxxus.EventSummonoNetherPortal, 20 * Time.InMilliseconds);
|
||||
_events.ScheduleEvent(Jaraxxus.EventSummonInfernalEruption, 80 * Time.InMilliseconds);
|
||||
}
|
||||
|
||||
public override void JustReachedHome()
|
||||
{
|
||||
_JustReachedHome();
|
||||
instance.SetBossState(DataTypes.BossJaraxxus, EncounterState.Fail);
|
||||
DoCast(me, Spells.JaraxxusChains);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.IsTypeId(TypeId.Player))
|
||||
{
|
||||
Talk(Jaraxxus.SayKillPlayer);
|
||||
instance.SetData(DataTypes.TributeToImmortalityEligible, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(Jaraxxus.SayDeath);
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summoned)
|
||||
{
|
||||
summons.Summon(summoned);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(Jaraxxus.SayAggro);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Jaraxxus.EventFelFireball:
|
||||
DoCastVictim(Jaraxxus.SpellFelFireball);
|
||||
_events.ScheduleEvent(Jaraxxus.EventFelFireball, RandomHelper.URand(10 * Time.InMilliseconds, 15 * Time.InMilliseconds));
|
||||
return;
|
||||
case Jaraxxus.EventFelLightning:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 0.0f, true, -Jaraxxus.SpellLordHittin);
|
||||
if (target)
|
||||
DoCast(target, Jaraxxus.SpellFelLighting);
|
||||
_events.ScheduleEvent(Jaraxxus.EventFelLightning, RandomHelper.URand(10 * Time.InMilliseconds, 15 * Time.InMilliseconds));
|
||||
return;
|
||||
}
|
||||
case Jaraxxus.EventIncinerateFlesh:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 1, 0.0f, true, -Jaraxxus.SpellLordHittin);
|
||||
if (target)
|
||||
{
|
||||
Talk(Jaraxxus.EmoteIncinerate, target);
|
||||
Talk(Jaraxxus.SayIncinerate);
|
||||
DoCast(target, Jaraxxus.SpellInfernalEruption);
|
||||
}
|
||||
_events.ScheduleEvent(Jaraxxus.EventIncinerateFlesh, RandomHelper.URand(20 * Time.InMilliseconds, 25 * Time.InMilliseconds));
|
||||
return;
|
||||
}
|
||||
case Jaraxxus.EventNetherPower:
|
||||
me.CastCustomSpell(Jaraxxus.SpellNetherPower, SpellValueMod.AuraStack, RaidMode(5, 10, 5, 10), me, true);
|
||||
_events.ScheduleEvent(Jaraxxus.EventNetherPower, 40 * Time.InMilliseconds);
|
||||
return;
|
||||
case Jaraxxus.EventLegionFlame:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 1, 0.0f, true, -Jaraxxus.SpellLordHittin);
|
||||
if (target)
|
||||
{
|
||||
Talk(Jaraxxus.EmoteLegionFlame, target);
|
||||
DoCast(target, Jaraxxus.SpellLegionFlame);
|
||||
}
|
||||
_events.ScheduleEvent(Jaraxxus.EventLegionFlame, 30 * Time.InMilliseconds);
|
||||
return;
|
||||
}
|
||||
case Jaraxxus.EventSummonoNetherPortal:
|
||||
Talk(Jaraxxus.EmoteNetherPortal);
|
||||
Talk(Jaraxxus.SayMistressOfPain);
|
||||
DoCast(Jaraxxus.SpellNetherPortal);
|
||||
_events.ScheduleEvent(Jaraxxus.EventSummonoNetherPortal, 2 * Time.Minute * Time.InMilliseconds);
|
||||
return;
|
||||
case Jaraxxus.EventSummonInfernalEruption:
|
||||
Talk(Jaraxxus.EmoteInfernalEruption);
|
||||
Talk(Jaraxxus.SayInfernalEruption);
|
||||
DoCast(Jaraxxus.SpellInfernalEruption);
|
||||
_events.ScheduleEvent(Jaraxxus.EventSummonInfernalEruption, 2 * Time.Minute * Time.InMilliseconds);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_legion_flame : ScriptedAI
|
||||
{
|
||||
public npc_legion_flame(Creature creature) : base(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
_instance = creature.GetInstanceScript();
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable);
|
||||
me.SetInCombatWithZone();
|
||||
DoCast(Jaraxxus.SpellLegionFlameEffect);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
UpdateVictim();
|
||||
if (_instance.GetBossState(DataTypes.BossJaraxxus) != EncounterState.InProgress)
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
InstanceScript _instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_infernal_volcano : ScriptedAI
|
||||
{
|
||||
public npc_infernal_volcano(Creature creature) : base(creature)
|
||||
{
|
||||
_summons = new SummonList(me);
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
|
||||
if (!IsHeroic())
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable | UnitFlags.Pacified);
|
||||
else
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable | UnitFlags.Pacified);
|
||||
|
||||
_summons.DespawnAll();
|
||||
}
|
||||
|
||||
public override void IsSummonedBy(Unit summoner)
|
||||
{
|
||||
DoCast(Jaraxxus.SpellInfernalEruptionEffect);
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summoned)
|
||||
{
|
||||
_summons.Summon(summoned);
|
||||
// makes immediate corpse despawn of summoned Felflame Infernals
|
||||
summoned.SetCorpseDelay(0);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
// used to despawn corpse immediately
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff) { }
|
||||
|
||||
SummonList _summons;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_fel_infernal : ScriptedAI
|
||||
{
|
||||
public npc_fel_infernal(Creature creature) : base(creature)
|
||||
{
|
||||
_instance = creature.GetInstanceScript();
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_felStreakTimer = 30 * Time.InMilliseconds;
|
||||
me.SetInCombatWithZone();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (_instance.GetBossState(DataTypes.BossJaraxxus) != EncounterState.InProgress)
|
||||
{
|
||||
me.DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (_felStreakTimer <= diff)
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 0.0f, true);
|
||||
if (target)
|
||||
DoCast(target, Jaraxxus.SpellFelStreak);
|
||||
_felStreakTimer = 30 * Time.InMilliseconds;
|
||||
}
|
||||
else
|
||||
_felStreakTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
uint _felStreakTimer;
|
||||
InstanceScript _instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_nether_portal : ScriptedAI
|
||||
{
|
||||
public npc_nether_portal(Creature creature) : base(creature)
|
||||
{
|
||||
_summons = new SummonList(me);
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
|
||||
if (!IsHeroic())
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable | UnitFlags.Pacified);
|
||||
else
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable | UnitFlags.NotSelectable | UnitFlags.Pacified);
|
||||
|
||||
_summons.DespawnAll();
|
||||
}
|
||||
|
||||
public override void IsSummonedBy(Unit summoner)
|
||||
{
|
||||
DoCast(Jaraxxus.SpellNetherPortalEffect);
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summoned)
|
||||
{
|
||||
_summons.Summon(summoned);
|
||||
// makes immediate corpse despawn of summoned Mistress of Pain
|
||||
summoned.SetCorpseDelay(0);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
// used to despawn corpse immediately
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff) { }
|
||||
|
||||
SummonList _summons;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_mistress_of_pain : ScriptedAI
|
||||
{
|
||||
public npc_mistress_of_pain(Creature creature) : base(creature)
|
||||
{
|
||||
_instance = creature.GetInstanceScript();
|
||||
_instance.SetData(DataTypes.MistressOfPainCount, DataTypes.Increase);
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_events.ScheduleEvent(Jaraxxus.EventShivanSlash, 30 * Time.InMilliseconds);
|
||||
_events.ScheduleEvent(Jaraxxus.EventSpinningStrike, 30 * Time.InMilliseconds);
|
||||
if (IsHeroic())
|
||||
_events.ScheduleEvent(Jaraxxus.EventMistressKiss, 15 * Time.InMilliseconds);
|
||||
me.SetInCombatWithZone();
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_instance.SetData(DataTypes.MistressOfPainCount, DataTypes.Decrease);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (_instance.GetBossState(DataTypes.BossJaraxxus) != EncounterState.InProgress)
|
||||
{
|
||||
me.DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Jaraxxus.EventShivanSlash:
|
||||
DoCastVictim(Jaraxxus.SpellShivanSlash);
|
||||
_events.ScheduleEvent(Jaraxxus.EventShivanSlash, 30 * Time.InMilliseconds);
|
||||
return;
|
||||
case Jaraxxus.EventSpinningStrike:
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 0.0f, true);
|
||||
if (target)
|
||||
DoCast(target, Jaraxxus.SpellSpinningStrike);
|
||||
_events.ScheduleEvent(Jaraxxus.EventSpinningStrike, 30 * Time.InMilliseconds);
|
||||
return;
|
||||
case Jaraxxus.EventMistressKiss:
|
||||
DoCast(me, Jaraxxus.SpellMistressKiss);
|
||||
_events.ScheduleEvent(Jaraxxus.EventMistressKiss, 30 * Time.InMilliseconds);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
InstanceScript _instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_mistress_kiss : AuraScript
|
||||
{
|
||||
public override bool Load()
|
||||
{
|
||||
return ValidateSpellInfo(Jaraxxus.SpellMistressKissDamageSilence);
|
||||
}
|
||||
|
||||
void HandleDummyTick(AuraEffect aurEff)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
Unit target = GetTarget();
|
||||
if (caster && target)
|
||||
{
|
||||
if (target.HasUnitState(UnitState.Casting))
|
||||
{
|
||||
caster.CastSpell(target, Jaraxxus.SpellMistressKissDamageSilence, true);
|
||||
target.RemoveAurasDueToSpell(GetSpellInfo().Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(HandleDummyTick, 0, AuraType.PeriodicDummy));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_mistress_kiss_area : SpellScript
|
||||
{
|
||||
void FilterTargets(List<WorldObject> targets)
|
||||
{
|
||||
// get a list of players with mana
|
||||
targets.RemoveAll(unit => unit.IsTypeId(TypeId.Player) && unit.ToPlayer().getPowerType() == PowerType.Mana);
|
||||
if (targets.Empty())
|
||||
return;
|
||||
|
||||
WorldObject target = targets.SelectRandom();
|
||||
targets.Clear();
|
||||
targets.Add(target);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, 0, Targets.UnitSrcAreaEnemy));
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+409
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* 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.Entities;
|
||||
using Game.Maps;
|
||||
|
||||
namespace Scripts.Northrend.CrusadersColiseum.TrialOfTheCrusader
|
||||
{
|
||||
struct DataTypes
|
||||
{
|
||||
public const uint BossBeasts = 0;
|
||||
public const uint BossJaraxxus = 1;
|
||||
public const uint BossCrusaders = 2;
|
||||
public const uint BossValkiries = 3;
|
||||
public const uint BossLichKing = 4; // Not Really A Boss But Oh Well
|
||||
public const uint BossAnubarak = 5;
|
||||
public const uint MaxEncounters = 6;
|
||||
|
||||
public const uint Counter = 8;
|
||||
public const uint Event = 9;
|
||||
|
||||
public const uint EventTimer = 101;
|
||||
public const uint EventNpc = 102;
|
||||
public const uint NorthrendBeasts = 103;
|
||||
|
||||
public const uint SnoboldCount = 301;
|
||||
public const uint MistressOfPainCount = 302;
|
||||
public const uint TributeToImmortalityEligible = 303;
|
||||
|
||||
public const uint Increase = 501;
|
||||
public const uint Decrease = 502;
|
||||
}
|
||||
|
||||
struct Spells
|
||||
{
|
||||
public const uint WilfredPortal = 68424;
|
||||
public const uint JaraxxusChains = 67924;
|
||||
public const uint CorpseTeleport = 69016;
|
||||
public const uint DestroyFloorKnockup = 68193;
|
||||
}
|
||||
|
||||
struct WorldStateIds
|
||||
{
|
||||
public const uint Show = 4390;
|
||||
public const uint Count = 4389;
|
||||
}
|
||||
|
||||
enum AnnouncerMessages
|
||||
{
|
||||
Beasts = 724001,
|
||||
Jaraxxus = 724002,
|
||||
Crusaders = 724003,
|
||||
Valkiries = 724004,
|
||||
LichKing = 724005,
|
||||
Anubarak = 724006
|
||||
}
|
||||
|
||||
public struct CreatureIds
|
||||
{
|
||||
public const uint Barrent = 34816;
|
||||
public const uint Tirion = 34996;
|
||||
public const uint TirionFordring = 36095;
|
||||
public const uint ArgentMage = 36097;
|
||||
public const uint Fizzlebang = 35458;
|
||||
public const uint Garrosh = 34995;
|
||||
public const uint Varian = 34990;
|
||||
public const uint LichKing = 35877;
|
||||
|
||||
public const uint Thrall = 34994;
|
||||
public const uint Proudmoore = 34992;
|
||||
public const uint WilfredPortal = 17965;
|
||||
public const uint Trigger = 35651;
|
||||
|
||||
public const uint Icehowl = 34797;
|
||||
public const uint Gormok = 34796;
|
||||
public const uint Dreadscale = 34799;
|
||||
public const uint Acidmaw = 35144;
|
||||
|
||||
public const uint Jaraxxus = 34780;
|
||||
|
||||
public const uint ChampionsController = 34781;
|
||||
|
||||
public const uint AllianceDeathKnight = 34461;
|
||||
public const uint AllianceDruidBalance = 34460;
|
||||
public const uint AllianceDruidRestoration = 34469;
|
||||
public const uint AllianceHunter = 34467;
|
||||
public const uint AllianceMage = 34468;
|
||||
public const uint AlliancePaladinHoly = 34465;
|
||||
public const uint AlliancePaladinRetribution = 34471;
|
||||
public const uint AlliancePriestDiscipline = 34466;
|
||||
public const uint AlliancePriestShadow = 34473;
|
||||
public const uint AllianceRogue = 34472;
|
||||
public const uint AllianceShamanEnhancement = 34463;
|
||||
public const uint AllianceShamanRestoration = 34470;
|
||||
public const uint AllianceWarlock = 34474;
|
||||
public const uint AllianceWarrior = 34475;
|
||||
|
||||
public const uint HordeDeathKnight = 34458;
|
||||
public const uint HordeDruidBalance = 34451;
|
||||
public const uint HordeDruidRestoration = 34459;
|
||||
public const uint HordeHunter = 34448;
|
||||
public const uint HordeMage = 34449;
|
||||
public const uint HordePaladinHoly = 34445;
|
||||
public const uint HordePaladinRetribution = 34456;
|
||||
public const uint HordePriestDiscipline = 34447;
|
||||
public const uint HordePriestShadow = 34441;
|
||||
public const uint HordeRogue = 34454;
|
||||
public const uint HordeShamanEnhancement = 34455;
|
||||
public const uint HordeShamanRestoration = 34444;
|
||||
public const uint HordeWarlock = 34450;
|
||||
public const uint HordeWarrior = 34453;
|
||||
|
||||
public const uint Lightbane = 34497;
|
||||
public const uint Darkbane = 34496;
|
||||
|
||||
public const uint DarkEssence = 34567;
|
||||
public const uint LightEssence = 34568;
|
||||
|
||||
public const uint Anubarak = 34564;
|
||||
}
|
||||
|
||||
struct GameObjectIds
|
||||
{
|
||||
public const uint CrusadersCache10 = 195631;
|
||||
public const uint CrusadersCache25 = 195632;
|
||||
public const uint CrusadersCache10H = 195633;
|
||||
public const uint CrusadersCache25H = 195635;
|
||||
|
||||
// Tribute Chest (Heroic)
|
||||
// 10-Man Modes
|
||||
public const uint TributeChest10h25 = 195668; // 10man 01-24 Attempts
|
||||
public const uint TributeChest10h45 = 195667; // 10man 25-44 Attempts
|
||||
public const uint TributeChest10h50 = 195666; // 10man 45-49 Attempts
|
||||
public const uint TributeChest10h99 = 195665; // 10man 50 Attempts
|
||||
// 25-Man Modes
|
||||
public const uint TributeChest25h25 = 195672; // 25man 01-24 Attempts
|
||||
public const uint TributeChest25h45 = 195671; // 25man 25-44 Attempts
|
||||
public const uint TributeChest25h50 = 195670; // 25man 45-49 Attempts
|
||||
public const uint TributeChest25h99 = 195669; // 25man 50 Attempts
|
||||
|
||||
public const uint ArgentColiseumFloor = 195527; //20943
|
||||
public const uint MainGateDoor = 195647;
|
||||
public const uint EastPortcullis = 195648;
|
||||
public const uint WebDoor = 195485;
|
||||
public const uint PortalToDalaran = 195682;
|
||||
}
|
||||
|
||||
struct AchievementData
|
||||
{
|
||||
// Northrend Beasts
|
||||
public const uint UpperBackPain10Player = 11779;
|
||||
public const uint UpperBackPain10PlayerHeroic = 11802;
|
||||
public const uint UpperBackPain25Player = 11780;
|
||||
public const uint UpperBackPain25PlayerHeroic = 11801;
|
||||
// Lord Jaraxxus
|
||||
public const uint ThreeSixtyPainSpike10Player = 11838;
|
||||
public const uint ThreeSixtyPainSpike10PlayerHeroic = 11861;
|
||||
public const uint ThreeSixtyPainSpike25Player = 11839;
|
||||
public const uint ThreeSixtyPainSpike25PlayerHeroic = 11862;
|
||||
// Tribute
|
||||
public const uint ATributeToSkill10Player = 12344;
|
||||
public const uint ATributeToSkill25Player = 12338;
|
||||
public const uint ATributeToMadSkill10Player = 12347;
|
||||
public const uint ATributeToMadSkill25Player = 12341;
|
||||
public const uint ATributeToInsanity10Player = 12349;
|
||||
public const uint ATributeToInsanity25Player = 12343;
|
||||
public const uint ATributeToImmortalityHorde = 12358;
|
||||
public const uint ATributeToImmortalityAlliance = 12359;
|
||||
public const uint ATributeToDedicatedInsanity = 12360;
|
||||
public const uint RealmFirstGrandCrusader = 12350;
|
||||
|
||||
// Dummy Spells - Not Existing In Dbc But We Don'T Need That
|
||||
public const uint SpellWormsKilledIn10Seconds = 68523;
|
||||
public const uint SpellChampionsKilledInMinute = 68620;
|
||||
public const uint SpellDefeatFactionChampions = 68184;
|
||||
public const uint SpellTraitorKing10 = 68186;
|
||||
public const uint SpellTraitorKing25 = 68515;
|
||||
|
||||
// Timed Events
|
||||
public const uint EventStartTwinsFight = 21853;
|
||||
}
|
||||
|
||||
struct NorthrendBeasts
|
||||
{
|
||||
public const uint GormokInProgress = 1000;
|
||||
public const uint GormokDone = 1001;
|
||||
public const uint SnakesInProgress = 2000;
|
||||
public const uint DreadscaleSubmerged = 2001;
|
||||
public const uint AcidmawSubmerged = 2002;
|
||||
public const uint SnakesSpecial = 2003;
|
||||
public const uint SnakesDone = 2004;
|
||||
public const uint IcehowlInProgress = 3000;
|
||||
public const uint IcehowlDone = 3001;
|
||||
}
|
||||
|
||||
struct Texts
|
||||
{
|
||||
// Highlord Tirion Fordring - 34996
|
||||
public const uint Stage_0_01 = 0;
|
||||
public const uint Stage_0_02 = 1;
|
||||
public const uint Stage_0_04 = 2;
|
||||
public const uint Stage_0_05 = 3;
|
||||
public const uint Stage_0_06 = 4;
|
||||
public const uint Stage_0_Wipe = 5;
|
||||
public const uint Stage_1_01 = 6;
|
||||
public const uint Stage_1_07 = 7;
|
||||
public const uint Stage_1_08 = 8;
|
||||
public const uint Stage_1_11 = 9;
|
||||
public const uint Stage_2_01 = 10;
|
||||
public const uint Stage_2_03 = 11;
|
||||
public const uint Stage_2_06 = 12;
|
||||
public const uint Stage_3_01 = 13;
|
||||
public const uint Stage_3_02 = 14;
|
||||
public const uint Stage_4_01 = 15;
|
||||
public const uint Stage_4_03 = 16;
|
||||
|
||||
// Varian Wrynn
|
||||
public const uint Stage_0_03a = 0;
|
||||
public const uint Stage_1_10 = 1;
|
||||
public const uint Stage_2_02a = 2;
|
||||
public const uint Stage_2_04a = 3;
|
||||
public const uint Stage_2_05a = 4;
|
||||
public const uint Stage_3_03a = 5;
|
||||
|
||||
// Garrosh
|
||||
public const uint Stage_0_03h = 0;
|
||||
public const uint Stage_1_09 = 1;
|
||||
public const uint Stage_2_02h = 2;
|
||||
public const uint Stage_2_04h = 3;
|
||||
public const uint Stage_2_05h = 4;
|
||||
public const uint Stage_3_03h = 5;
|
||||
|
||||
// Wilfred Fizzlebang
|
||||
public const uint Stage_1_02 = 0;
|
||||
public const uint Stage_1_03 = 1;
|
||||
public const uint Stage_1_04 = 2;
|
||||
public const uint Stage_1_06 = 3;
|
||||
|
||||
// Lord Jaraxxus
|
||||
public const uint Stage_1_05 = 0;
|
||||
|
||||
// The Lich King
|
||||
public const uint Stage_4_02 = 0;
|
||||
public const uint Stage_4_05 = 1;
|
||||
public const uint Stage_4_04 = 2;
|
||||
|
||||
// Highlord Tirion Fordring - 36095
|
||||
public const uint Stage_4_06 = 0;
|
||||
public const uint Stage_4_07 = 1;
|
||||
}
|
||||
|
||||
struct MiscData
|
||||
{
|
||||
public const uint DespawnTime = 300000;
|
||||
|
||||
public const uint DisplayIdDestroyedFloor = 9060;
|
||||
|
||||
public static BossBoundaryEntry[] boundaries =
|
||||
{
|
||||
new BossBoundaryEntry(DataTypes.BossBeasts, new CircleBoundary(new Position(563.26f, 139.6f), 75.0)),
|
||||
new BossBoundaryEntry(DataTypes.BossJaraxxus, new CircleBoundary(new Position(563.26f, 139.6f), 75.0)),
|
||||
new BossBoundaryEntry(DataTypes.BossCrusaders, new CircleBoundary(new Position(563.26f, 139.6f), 75.0)),
|
||||
new BossBoundaryEntry(DataTypes.BossValkiries, new CircleBoundary(new Position(563.26f, 139.6f), 75.0)),
|
||||
new BossBoundaryEntry(DataTypes.BossAnubarak, new EllipseBoundary(new Position(746.0f, 135.0f), 100.0, 75.0))
|
||||
};
|
||||
|
||||
public static _Messages[] _GossipMessage =
|
||||
{
|
||||
new _Messages(AnnouncerMessages.Beasts, eTradeskill.GossipActionInfoDef + 1, false, DataTypes.BossBeasts),
|
||||
new _Messages(AnnouncerMessages.Jaraxxus, eTradeskill.GossipActionInfoDef + 2, false, DataTypes.BossJaraxxus),
|
||||
new _Messages(AnnouncerMessages.Crusaders, eTradeskill.GossipActionInfoDef + 3, false, DataTypes.BossCrusaders),
|
||||
new _Messages(AnnouncerMessages.Valkiries, eTradeskill.GossipActionInfoDef + 4, false, DataTypes.BossValkiries),
|
||||
new _Messages(AnnouncerMessages.LichKing, eTradeskill.GossipActionInfoDef + 5, false, DataTypes.BossAnubarak),
|
||||
new _Messages(AnnouncerMessages.Anubarak, eTradeskill.GossipActionInfoDef + 6, true, DataTypes.BossAnubarak)
|
||||
};
|
||||
|
||||
public static Position[] ToCSpawnLoc =
|
||||
{
|
||||
new Position(563.912f, 261.625f, 394.73f, 4.70437f), // 0 Center
|
||||
new Position( 575.451f, 261.496f, 394.73f, 4.6541f), // 1 Left
|
||||
new Position( 549.951f, 261.55f, 394.73f, 4.74835f) // 2 Right
|
||||
};
|
||||
|
||||
public static Position[] ToCCommonLoc =
|
||||
{
|
||||
new Position(559.257996f, 90.266197f, 395.122986f, 0), // 0 Barrent
|
||||
|
||||
new Position(563.672974f, 139.571f, 393.837006f, 0), // 1 Center
|
||||
new Position(563.833008f, 187.244995f, 394.5f, 0), // 2 Backdoor
|
||||
new Position(577.347839f, 195.338888f, 395.14f, 0), // 3 - Right
|
||||
new Position(550.955933f, 195.338888f, 395.14f, 0), // 4 - Left
|
||||
new Position(563.833008f, 195.244995f, 394.585561f, 0), // 5 - Center
|
||||
new Position(573.5f, 180.5f, 395.14f, 0), // 6 Move 0 Right
|
||||
new Position(553.5f, 180.5f, 395.14f, 0), // 7 Move 0 Left
|
||||
new Position(573.0f, 170.0f, 395.14f, 0), // 8 Move 1 Right
|
||||
new Position(555.5f, 170.0f, 395.14f, 0), // 9 Move 1 Left
|
||||
new Position(563.8f, 216.1f, 395.1f, 0), // 10 Behind the door
|
||||
|
||||
new Position(575.042358f, 195.260727f, 395.137146f, 0), // 5
|
||||
new Position(552.248901f, 195.331955f, 395.132658f, 0), // 6
|
||||
new Position(573.342285f, 195.515823f, 395.135956f, 0), // 7
|
||||
new Position(554.239929f, 195.825577f, 395.137909f, 0), // 8
|
||||
new Position(571.042358f, 195.260727f, 395.137146f, 0), // 9
|
||||
new Position(556.720581f, 195.015472f, 395.132658f, 0), // 10
|
||||
new Position(569.534119f, 195.214478f, 395.139526f, 0), // 11
|
||||
new Position(569.231201f, 195.941071f, 395.139526f, 0), // 12
|
||||
new Position(558.811610f, 195.985779f, 394.671661f, 0), // 13
|
||||
new Position(567.641724f, 195.351501f, 394.659943f, 0), // 14
|
||||
new Position(560.633972f, 195.391708f, 395.137543f, 0), // 15
|
||||
new Position(565.816956f, 195.477921f, 395.136810f, 0) // 16
|
||||
};
|
||||
|
||||
public static Position[] JaraxxusLoc =
|
||||
{
|
||||
new Position(508.104767f, 138.247345f, 395.128052f, 0), // 0 - Fizzlebang start location
|
||||
new Position(548.610596f, 139.807800f, 394.321838f, 0), // 1 - fizzlebang end
|
||||
new Position(581.854187f, 138.0f, 394.319f, 0), // 2 - Portal Right
|
||||
new Position(550.558838f, 138.0f, 394.319f, 0) // 3 - Portal Left
|
||||
};
|
||||
|
||||
public static Position[] FactionChampionLoc =
|
||||
{
|
||||
new Position(514.231f, 105.569f, 418.234f, 0), // 0 - Horde Initial Pos 0
|
||||
new Position(508.334f, 115.377f, 418.234f, 0), // 1 - Horde Initial Pos 1
|
||||
new Position(506.454f, 126.291f, 418.234f, 0), // 2 - Horde Initial Pos 2
|
||||
new Position(506.243f, 106.596f, 421.592f, 0), // 3 - Horde Initial Pos 3
|
||||
new Position(499.885f, 117.717f, 421.557f, 0), // 4 - Horde Initial Pos 4
|
||||
|
||||
new Position(613.127f, 100.443f, 419.74f, 0), // 5 - Ally Initial Pos 0
|
||||
new Position(621.126f, 128.042f, 418.231f, 0), // 6 - Ally Initial Pos 1
|
||||
new Position(618.829f, 113.606f, 418.232f, 0), // 7 - Ally Initial Pos 2
|
||||
new Position(625.845f, 112.914f, 421.575f, 0), // 8 - Ally Initial Pos 3
|
||||
new Position(615.566f, 109.653f, 418.234f, 0), // 9 - Ally Initial Pos 4
|
||||
|
||||
new Position(535.469f, 113.012f, 394.66f, 0), // 10 - Horde Final Pos 0
|
||||
new Position(526.417f, 137.465f, 394.749f, 0), // 11 - Horde Final Pos 1
|
||||
new Position(528.108f, 111.057f, 395.289f, 0), // 12 - Horde Final Pos 2
|
||||
new Position(519.92f, 134.285f, 395.289f, 0), // 13 - Horde Final Pos 3
|
||||
new Position(533.648f, 119.148f, 394.646f, 0), // 14 - Horde Final Pos 4
|
||||
new Position(531.399f, 125.63f, 394.708f, 0), // 15 - Horde Final Pos 5
|
||||
new Position(528.958f, 131.47f, 394.73f, 0), // 16 - Horde Final Pos 6
|
||||
new Position(526.309f, 116.667f, 394.833f, 0), // 17 - Horde Final Pos 7
|
||||
new Position(524.238f, 122.411f, 394.819f, 0), // 18 - Horde Final Pos 8
|
||||
new Position(521.901f, 128.488f, 394.832f, 0) // 19 - Horde Final Pos 9
|
||||
};
|
||||
|
||||
public static Position[] TwinValkyrsLoc =
|
||||
{
|
||||
new Position(586.060242f, 117.514809f, 394.41f, 0), // 0 - Dark essence 1
|
||||
new Position(541.602112f, 161.879837f, 394.41f, 0), // 1 - Dark essence 2
|
||||
new Position(541.021118f, 117.262932f, 394.41f, 0), // 2 - Light essence 1
|
||||
new Position(586.200562f, 162.145523f, 394.41f, 0) // 3 - Light essence 2
|
||||
};
|
||||
|
||||
public static Position[] LichKingLoc =
|
||||
{
|
||||
new Position(563.549f, 152.474f, 394.393f, 0), // 0 - Lich king start
|
||||
new Position(563.547f, 141.613f, 393.908f, 0) // 1 - Lich king end
|
||||
};
|
||||
|
||||
public static Position[] AnubarakLoc =
|
||||
{
|
||||
new Position(787.932556f, 133.289780f, 142.612152f, 0), // 0 - Anub'arak start location
|
||||
new Position(695.240051f, 137.834824f, 142.200000f, 0), // 1 - Anub'arak move point location
|
||||
new Position(694.886353f, 102.484665f, 142.119614f, 0), // 3 - Nerub Spawn
|
||||
new Position(694.500671f, 185.363968f, 142.117905f, 0), // 5 - Nerub Spawn
|
||||
new Position(731.987244f, 83.3824690f, 142.119614f, 0), // 2 - Nerub Spawn
|
||||
new Position(740.184509f, 193.443390f, 142.117584f, 0) // 4 - Nerub Spawn
|
||||
};
|
||||
|
||||
public static Position[] EndSpawnLoc =
|
||||
{
|
||||
new Position(648.9167f, 131.0208f, 141.6161f, 0), // 0 - Highlord Tirion Fordring
|
||||
new Position(649.1614f, 142.0399f, 141.3057f, 0), // 1 - Argent Mage
|
||||
new Position(644.6250f, 149.2743f, 140.6015f, 0) // 2 - Portal to Dalaran
|
||||
};
|
||||
}
|
||||
|
||||
struct _Messages
|
||||
{
|
||||
public _Messages(AnnouncerMessages _msg, uint _id, bool _state, uint _encounter)
|
||||
{
|
||||
msgnum = _msg;
|
||||
id = _id;
|
||||
state = _state;
|
||||
encounter = _encounter;
|
||||
}
|
||||
|
||||
public AnnouncerMessages msgnum;
|
||||
public uint id;
|
||||
public bool state;
|
||||
public uint encounter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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 Framework.Database;
|
||||
using Game.AI;
|
||||
using Game.Entities;
|
||||
using Game.Mails;
|
||||
using Game.Scripting;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend
|
||||
{
|
||||
struct DalaranConst
|
||||
{
|
||||
//Mageguard
|
||||
public const uint SpellTrespasserA = 54028;
|
||||
public const uint SpellTrespasserH = 54029;
|
||||
|
||||
public const uint SpellSunreaverDisguiseFemale = 70973;
|
||||
public const uint SpellSunreaverDisguiseMale = 70974;
|
||||
public const uint SpellSilverConenantDisguiseFemale = 70971;
|
||||
public const uint SpellSilverConenantDisguiseMale = 70972;
|
||||
|
||||
public const int NpcAplleboughA = 29547;
|
||||
public const int NpcSweetberryH = 29715;
|
||||
|
||||
//Minigob
|
||||
public const int SpellManabonked = 61834;
|
||||
public const int SpellTeleportVisual = 51347;
|
||||
public const int SpellImprovedBlink = 61995;
|
||||
|
||||
public const int EventSelectTarget = 1;
|
||||
public const int EventBlink = 2;
|
||||
public const int EventDespawnVisual = 3;
|
||||
public const int EventDespawn = 4;
|
||||
|
||||
public const int MailMinigobEntry = 264;
|
||||
public const int MailDeliverDelayMin = 5 * Time.Minute;
|
||||
public const int MailDeliverDelayMax = 15 * Time.Minute;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_mageguard_dalaran : ScriptedAI
|
||||
{
|
||||
public npc_mageguard_dalaran(Creature creature) : base(creature)
|
||||
{
|
||||
creature.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
creature.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchools.Normal, true);
|
||||
creature.ApplySpellImmune(0, SpellImmunity.Damage, SpellSchoolMask.Magic, true);
|
||||
}
|
||||
|
||||
public override void Reset() { }
|
||||
|
||||
public override void EnterCombat(Unit who) { }
|
||||
|
||||
public override void AttackStart(Unit who) { }
|
||||
|
||||
public override void MoveInLineOfSight(Unit who)
|
||||
{
|
||||
if (!who || !who.IsInWorld || who.GetZoneId() != 4395)
|
||||
return;
|
||||
|
||||
if (!me.IsWithinDist(who, 65.0f, false))
|
||||
return;
|
||||
|
||||
Player player = who.GetCharmerOrOwnerPlayerOrPlayerItself();
|
||||
|
||||
if (!player || player.IsGameMaster() || player.IsBeingTeleported() ||
|
||||
// If player has Disguise aura for quest A Meeting With The Magister or An Audience With The Arcanist, do not teleport it away but let it pass
|
||||
player.HasAura(DalaranConst.SpellSunreaverDisguiseFemale) || player.HasAura(DalaranConst.SpellSunreaverDisguiseMale) ||
|
||||
player.HasAura(DalaranConst.SpellSilverConenantDisguiseFemale) || player.HasAura(DalaranConst.SpellSilverConenantDisguiseMale))
|
||||
return;
|
||||
|
||||
switch (me.GetEntry())
|
||||
{
|
||||
case 29254:
|
||||
if (player.GetTeam() == Team.Horde) // Horde unit found in Alliance area
|
||||
{
|
||||
if (GetClosestCreatureWithEntry(me, DalaranConst.NpcAplleboughA, 32.0f))
|
||||
{
|
||||
if (me.isInBackInMap(who, 12.0f)) // In my line of sight, "outdoors", and behind me
|
||||
DoCast(who, DalaranConst.SpellTrespasserA); // Teleport the Horde unit out
|
||||
}
|
||||
else // In my line of sight, and "indoors"
|
||||
DoCast(who, DalaranConst.SpellTrespasserA); // Teleport the Horde unit out
|
||||
}
|
||||
break;
|
||||
case 29255:
|
||||
if (player.GetTeam() == Team.Alliance) // Alliance unit found in Horde area
|
||||
{
|
||||
if (GetClosestCreatureWithEntry(me, DalaranConst.NpcSweetberryH, 32.0f))
|
||||
{
|
||||
if (me.isInBackInMap(who, 12.0f)) // In my line of sight, "outdoors", and behind me
|
||||
DoCast(who, DalaranConst.SpellTrespasserH); // Teleport the Alliance unit out
|
||||
}
|
||||
else // In my line of sight, and "indoors"
|
||||
DoCast(who, DalaranConst.SpellTrespasserH); // Teleport the Alliance unit out
|
||||
}
|
||||
break;
|
||||
}
|
||||
me.SetOrientation(me.GetHomePosition().GetOrientation());
|
||||
return;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff) { }
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_minigob_manabonk : ScriptedAI
|
||||
{
|
||||
public npc_minigob_manabonk(Creature creature) : base(creature)
|
||||
{
|
||||
me.setActive(true);
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
me.SetVisible(false);
|
||||
_events.ScheduleEvent(DalaranConst.EventSelectTarget, Time.InMilliseconds);
|
||||
}
|
||||
|
||||
Player SelectTargetInDalaran()
|
||||
{
|
||||
List<Player> PlayerInDalaranList = new List<Player>();
|
||||
|
||||
var players = me.GetMap().GetPlayers();
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player.GetZoneId() == me.GetZoneId() && !player.IsFlying() && !player.IsMounted() && !player.IsGameMaster())
|
||||
PlayerInDalaranList.Add(player);
|
||||
}
|
||||
|
||||
if (PlayerInDalaranList.Empty())
|
||||
return null;
|
||||
|
||||
return PlayerInDalaranList.SelectRandom();
|
||||
}
|
||||
|
||||
void SendMailToPlayer(Player player)
|
||||
{
|
||||
SQLTransaction trans = new SQLTransaction();
|
||||
uint deliverDelay = RandomHelper.URand(DalaranConst.MailDeliverDelayMin, DalaranConst.MailDeliverDelayMax);
|
||||
new MailDraft(DalaranConst.MailMinigobEntry, true).SendMailTo(trans, new MailReceiver(player), new MailSender(MailMessageType.Creature, me.GetEntry()), MailCheckMask.None, deliverDelay);
|
||||
DB.Characters.CommitTransaction(trans);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case DalaranConst.EventSelectTarget:
|
||||
me.SetVisible(true);
|
||||
DoCast(me, DalaranConst.SpellTeleportVisual);
|
||||
Player player = SelectTargetInDalaran();
|
||||
if (player)
|
||||
{
|
||||
me.NearTeleportTo(player.GetPositionX(), player.GetPositionY(), player.GetPositionZ(), 0.0f);
|
||||
DoCast(player, DalaranConst.SpellManabonked);
|
||||
SendMailToPlayer(player);
|
||||
}
|
||||
_events.ScheduleEvent(DalaranConst.EventBlink, 3 * Time.InMilliseconds);
|
||||
break;
|
||||
case DalaranConst.EventBlink:
|
||||
{
|
||||
DoCast(me, DalaranConst.SpellImprovedBlink);
|
||||
Position pos = me.GetRandomNearPosition(RandomHelper.FRand(15, 40));
|
||||
me.GetMotionMaster().MovePoint(0, pos.posX, pos.posY, pos.posZ);
|
||||
_events.ScheduleEvent(DalaranConst.EventDespawn, 3 * Time.InMilliseconds);
|
||||
_events.ScheduleEvent(DalaranConst.EventDespawnVisual, (uint)(2.5 * Time.InMilliseconds));
|
||||
break;
|
||||
}
|
||||
case DalaranConst.EventDespawnVisual:
|
||||
DoCast(me, DalaranConst.SpellTeleportVisual);
|
||||
break;
|
||||
case DalaranConst.EventDespawn:
|
||||
me.DespawnOrUnsummon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* 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 System;
|
||||
|
||||
namespace Scripts.Northrend.DraktharonKeep.KingDred
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint BellowingRoar = 22686; // Fears The Group; Can Be Resisted/Dispelled
|
||||
public const uint GrievousBite = 48920;
|
||||
public const uint ManglingSlash = 48873; // Cast On The Current Tank; Adds Debuf
|
||||
public const uint FearsomeRoar = 48849;
|
||||
public const uint PiercingSlash = 48878; // Debuff --> Armor Reduced By 75%
|
||||
public const uint RaptorCall = 59416; // Dummy
|
||||
public const uint GutRip = 49710;
|
||||
public const uint Rend = 13738;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const int ActionRaptorKilled = 1;
|
||||
public const uint DataRaptorsKilled = 2;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_king_dred : BossAI
|
||||
{
|
||||
public boss_king_dred(Creature creature) : base(creature, DTKDataTypes.KingDred)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
raptorsKilled = 0;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
_Reset();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(33), task =>
|
||||
{
|
||||
DoCastAOE(SpellIds.BellowingRoar);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.GrievousBite);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(18.5), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.ManglingSlash);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
DoCastAOE(SpellIds.FearsomeRoar);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(17), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.PiercingSlash);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(25), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.RaptorCall);
|
||||
|
||||
float x, y, z;
|
||||
me.GetClosePoint(out x, out y, out z, me.GetObjectSize() / 3, 10.0f);
|
||||
me.SummonCreature(RandomHelper.RAND(DTKCreatureIds.DrakkariGutripper, DTKCreatureIds.DrakkariScytheclaw), x, y, z, 0, TempSummonType.DeadDespawn, 1000);
|
||||
task.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
if (action == Misc.ActionRaptorKilled)
|
||||
++raptorsKilled;
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == Misc.DataRaptorsKilled)
|
||||
return raptorsKilled;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
byte raptorsKilled;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_drakkari_gutripper : ScriptedAI
|
||||
{
|
||||
public npc_drakkari_gutripper(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = me.GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.GutRip, false);
|
||||
task.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Creature dred = ObjectAccessor.GetCreature(me, instance.GetGuidData(DTKDataTypes.KingDred));
|
||||
if (dred)
|
||||
dred.GetAI().DoAction(Misc.ActionRaptorKilled);
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_drakkari_scytheclaw : ScriptedAI
|
||||
{
|
||||
public npc_drakkari_scytheclaw(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = me.GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Rend, false);
|
||||
task.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Creature dred = ObjectAccessor.GetCreature(me, instance.GetGuidData(DTKDataTypes.KingDred));
|
||||
if (dred)
|
||||
dred.GetAI().DoAction(Misc.ActionRaptorKilled);
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_king_dred : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_king_dred() : base("achievement_king_dred") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
Creature dred = target.ToCreature();
|
||||
if (dred)
|
||||
if (dred.GetAI().GetData(Misc.DataRaptorsKilled) >= 6)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace Scripts.Northrend.DraktharonKeep.Novos
|
||||
{
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SayKill = 1;
|
||||
public const uint SayDeath = 2;
|
||||
public const uint SaySummoningAdds = 3; // Unused
|
||||
public const uint SayArcaneField = 4;
|
||||
public const uint EmoteSummoningAdds = 5; // Unused
|
||||
}
|
||||
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint BeamChannel = 52106;
|
||||
public const uint ArcaneField = 47346;
|
||||
|
||||
public const uint SummonRisenShadowcaster = 49105;
|
||||
public const uint SummonFetidTrollCorpse = 49103;
|
||||
public const uint SummonHulkingCorpse = 49104;
|
||||
public const uint SummonCrystalHandler = 49179; //not used
|
||||
public const uint SummonCopyOfMinions = 59933; //not used
|
||||
|
||||
public const uint ArcaneBlast = 49198;
|
||||
public const uint Blizzard = 49034;
|
||||
public const uint Frostbolt = 49037;
|
||||
public const uint WrathOfMisery = 50089;
|
||||
public const uint SummonMinions = 59910;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const int ActionResetCrystals = 0;
|
||||
public const int ActionActivateCrystal = 1;
|
||||
public const int ActionDeactivate = 2;
|
||||
public const uint EventAttack = 3;
|
||||
public const uint EventSummonMinions = 4;
|
||||
public const uint EventSummonRisenShadowcaster = 5;
|
||||
public const uint EventSummonFetidTrollCorpse = 6;
|
||||
public const uint EventSummonHulkingCorpse = 7;
|
||||
public const uint EventSummonCrystalHandler = 8;
|
||||
public const uint DataNovosAchiev = 9;
|
||||
|
||||
public static SummonerInfo[] summoners =
|
||||
{
|
||||
new SummonerInfo(EventSummonRisenShadowcaster, 7),
|
||||
new SummonerInfo(EventSummonFetidTrollCorpse, 3),
|
||||
new SummonerInfo(EventSummonHulkingCorpse, 30),
|
||||
new SummonerInfo(EventSummonCrystalHandler, 15)
|
||||
};
|
||||
|
||||
public struct SummonerInfo
|
||||
{
|
||||
public SummonerInfo(uint _eventid, uint _timer)
|
||||
{
|
||||
eventId = _eventid;
|
||||
timer = _timer;
|
||||
}
|
||||
|
||||
public uint eventId;
|
||||
public uint timer;
|
||||
}
|
||||
|
||||
public static Position[] SummonPositions =
|
||||
{
|
||||
new Position(-306.8209f, -703.7687f, 27.2919f, 3.401838f),
|
||||
new Position(-421.395f, -705.7863f, 28.57594f, 4.830696f),
|
||||
new Position(-308.1955f, -704.8419f, 27.2919f, 3.010279f),
|
||||
new Position(-424.1306f, -705.7354f, 28.57594f, 5.325676f)
|
||||
};
|
||||
|
||||
public const float MaxYCoordOhNovosMAX = -771.95f;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_novos : BossAI
|
||||
{
|
||||
public boss_novos(Creature creature) : base(creature, DTKDataTypes.Novos)
|
||||
{
|
||||
Initialize();
|
||||
_bubbled = false;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_ohNovos = true;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
|
||||
Initialize();
|
||||
SetCrystalsStatus(false);
|
||||
SetSummonerStatus(false);
|
||||
SetBubbled(false);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit victim)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(TextIds.SayAggro);
|
||||
|
||||
SetCrystalsStatus(true);
|
||||
SetSummonerStatus(true);
|
||||
SetBubbled(true);
|
||||
}
|
||||
|
||||
public override void AttackStart(Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
if (me.Attack(target, true))
|
||||
DoStartNoMovement(target);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.IsTypeId(TypeId.Player))
|
||||
Talk(TextIds.SayKill);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(TextIds.SayDeath);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim() || _bubbled)
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Misc.EventSummonMinions:
|
||||
DoCast(SpellIds.SummonMinions);
|
||||
_events.ScheduleEvent(Misc.EventSummonMinions, 15000);
|
||||
break;
|
||||
case Misc.EventAttack:
|
||||
Unit victim = SelectTarget(SelectAggroTarget.Random);
|
||||
if (victim)
|
||||
DoCast(victim, RandomHelper.RAND(SpellIds.ArcaneBlast, SpellIds.Blizzard, SpellIds.Frostbolt, SpellIds.WrathOfMisery));
|
||||
_events.ScheduleEvent(Misc.EventAttack, 3000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
if (action == DTKDataTypes.ActionCrystalHandlerDied)
|
||||
{
|
||||
Talk(TextIds.SayArcaneField);
|
||||
SetSummonerStatus(false);
|
||||
SetBubbled(false);
|
||||
_events.ScheduleEvent(Misc.EventAttack, 3000);
|
||||
if (IsHeroic())
|
||||
_events.ScheduleEvent(Misc.EventSummonMinions, 15000);
|
||||
}
|
||||
}
|
||||
|
||||
public override void MoveInLineOfSight(Unit who)
|
||||
{
|
||||
base.MoveInLineOfSight(who);
|
||||
|
||||
if (!_ohNovos || !who || !who.IsTypeId(TypeId.Player) || who.GetPositionY() > Misc.MaxYCoordOhNovosMAX)
|
||||
return;
|
||||
|
||||
uint entry = who.GetEntry();
|
||||
if (entry == DTKCreatureIds.HulkingCorpse || entry == DTKCreatureIds.RisenShadowcaster || entry == DTKCreatureIds.FetidTrollCorpse)
|
||||
_ohNovos = false;
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
return type == Misc.DataNovosAchiev && _ohNovos ? 1 : 0u;
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
me.Yell(TextIds.SaySummoningAdds, summon);
|
||||
me.TextEmote(TextIds.EmoteSummoningAdds, summon);
|
||||
|
||||
summon.SelectNearestTargetInAttackDistance(50f);
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void SetBubbled(bool state)
|
||||
{
|
||||
_bubbled = state;
|
||||
if (!state)
|
||||
{
|
||||
if (me.HasFlag(UnitFields.Flags, UnitFlags.NonAttackable))
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
me.CastStop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!me.HasFlag(UnitFields.Flags, UnitFlags.NonAttackable))
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
DoCast(SpellIds.ArcaneField);
|
||||
}
|
||||
}
|
||||
|
||||
void SetSummonerStatus(bool active)
|
||||
{
|
||||
for (byte i = 0; i < 4; i++)
|
||||
{
|
||||
ObjectGuid guid = instance.GetGuidData(DTKDataTypes.NovosSummoner1 + i);
|
||||
if (!guid.IsEmpty())
|
||||
{
|
||||
Creature crystalChannelTarget = ObjectAccessor.GetCreature(me, guid);
|
||||
if (crystalChannelTarget)
|
||||
{
|
||||
if (active)
|
||||
crystalChannelTarget.GetAI().SetData(Misc.summoners[i].eventId, Misc.summoners[i].timer);
|
||||
else
|
||||
crystalChannelTarget.GetAI().Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetCrystalsStatus(bool active)
|
||||
{
|
||||
for (byte i = 0; i < 4; i++)
|
||||
{
|
||||
ObjectGuid guid = instance.GetGuidData(DTKDataTypes.NovosCrystal1 + i);
|
||||
if (!guid.IsEmpty())
|
||||
{
|
||||
GameObject crystal = ObjectAccessor.GetGameObject(me, guid);
|
||||
if (crystal)
|
||||
SetCrystalStatus(crystal, active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetCrystalStatus(GameObject crystal, bool active)
|
||||
{
|
||||
crystal.SetGoState(active ? GameObjectState.Active : GameObjectState.Ready);
|
||||
|
||||
Creature crystalChannelTarget = crystal.FindNearestCreature(DTKCreatureIds.CrystalChannelTarget, 5.0f);
|
||||
if (crystalChannelTarget)
|
||||
{
|
||||
if (active)
|
||||
crystalChannelTarget.CastSpell(null, SpellIds.BeamChannel);
|
||||
else if (crystalChannelTarget.HasUnitState(UnitState.Casting))
|
||||
crystalChannelTarget.CastStop();
|
||||
}
|
||||
}
|
||||
|
||||
bool _ohNovos;
|
||||
bool _bubbled;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_crystal_channel_target : ScriptedAI
|
||||
{
|
||||
public npc_crystal_channel_target(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_events.Reset();
|
||||
_crystalHandlerCount = 0;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Misc.EventSummonCrystalHandler:
|
||||
me.SummonCreature(DTKCreatureIds.CrystalHandler, Misc.SummonPositions[_crystalHandlerCount++]);
|
||||
if (_crystalHandlerCount < 4)
|
||||
_events.Repeat(TimeSpan.FromSeconds(15));
|
||||
break;
|
||||
case Misc.EventSummonRisenShadowcaster:
|
||||
DoCast(SpellIds.SummonRisenShadowcaster);
|
||||
_events.Repeat(TimeSpan.FromSeconds(7));
|
||||
break;
|
||||
case Misc.EventSummonFetidTrollCorpse:
|
||||
DoCast(SpellIds.SummonFetidTrollCorpse);
|
||||
_events.Repeat(TimeSpan.FromSeconds(3));
|
||||
break;
|
||||
case Misc.EventSummonHulkingCorpse:
|
||||
DoCast(SpellIds.SummonHulkingCorpse);
|
||||
_events.Repeat(TimeSpan.FromSeconds(30));
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override void SetData(uint id, uint value)
|
||||
{
|
||||
_events.ScheduleEvent(id, TimeSpan.FromSeconds(value));
|
||||
}
|
||||
|
||||
public override void SummonedCreatureDies(Creature summon, Unit killer)
|
||||
{
|
||||
if (_crystalHandlerCount < 4)
|
||||
return;
|
||||
|
||||
InstanceScript instance = me.GetInstanceScript();
|
||||
if (instance != null)
|
||||
{
|
||||
ObjectGuid guid = instance.GetGuidData(DTKDataTypes.Novos);
|
||||
if (!guid.IsEmpty())
|
||||
{
|
||||
Creature novos = ObjectAccessor.GetCreature(me, guid);
|
||||
if (novos)
|
||||
novos.GetAI().DoAction(DTKDataTypes.ActionCrystalHandlerDied);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
InstanceScript instance = me.GetInstanceScript();
|
||||
if (instance != null)
|
||||
{
|
||||
ObjectGuid guid = instance.GetGuidData(DTKDataTypes.Novos);
|
||||
if (!guid.IsEmpty())
|
||||
{
|
||||
Creature novos = ObjectAccessor.GetCreature(me, guid);
|
||||
if (novos)
|
||||
novos.GetAI().JustSummoned(summon);
|
||||
}
|
||||
}
|
||||
|
||||
if (summon)
|
||||
summon.GetMotionMaster().MovePath(summon.GetEntry() * 100, false);
|
||||
}
|
||||
|
||||
uint _crystalHandlerCount;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_oh_novos : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_oh_novos() : base("achievement_oh_novos") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
return target && target.IsTypeId(TypeId.Unit) && target.ToCreature().GetAI().GetData(Misc.DataNovosAchiev) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_novos_summon_minions : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.SummonCopyOfMinions);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
for (byte i = 0; i < 2; ++i)
|
||||
GetCaster().CastSpell((Unit)null, SpellIds.SummonCopyOfMinions, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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.Scripting;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
|
||||
namespace Scripts.Northrend.DraktharonKeep.TharonJa
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
// Skeletal Spells (Phase 1)
|
||||
public const uint CurseOfLife = 49527;
|
||||
public const uint RainOfFire = 49518;
|
||||
public const uint ShadowVolley = 49528;
|
||||
public const uint DecayFlesh = 49356; // Cast At End Of Phase 1; Starts Phase 2
|
||||
// Flesh Spells (Phase 2)
|
||||
public const uint GiftOfTharonJa = 52509;
|
||||
public const uint ClearGiftOfTharonJa = 53242;
|
||||
public const uint EyeBeam = 49544;
|
||||
public const uint LightningBreath = 49537;
|
||||
public const uint PoisonCloud = 49548;
|
||||
public const uint ReturnFlesh = 53463; // Channeled Spell Ending Phase Two And Returning To Phase 1. This Ability Will Stun The Party For 6 Seconds.
|
||||
public const uint AchievementCheck = 61863;
|
||||
public const uint FleshVisual = 52582;
|
||||
public const uint Dummy = 49551;
|
||||
}
|
||||
|
||||
struct EventIds
|
||||
{
|
||||
public const uint CurseOfLife = 1;
|
||||
public const uint RainOfFire = 2;
|
||||
public const uint ShadowVolley = 3;
|
||||
|
||||
public const uint EyeBeam = 4;
|
||||
public const uint LightningBreath = 5;
|
||||
public const uint PoisonCloud = 6;
|
||||
|
||||
public const uint DecayFlesh = 7;
|
||||
public const uint GoingFlesh = 8;
|
||||
public const uint ReturnFlesh = 9;
|
||||
public const uint GoingSkeletal = 10;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SayKill = 1;
|
||||
public const uint SayFlesh = 2;
|
||||
public const uint SaySkeleton = 3;
|
||||
public const uint SayDeath = 4;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint ModelFlesh = 27073;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_tharon_ja : BossAI
|
||||
{
|
||||
public boss_tharon_ja(Creature creature) : base(creature, DTKDataTypes.TharonJa) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
me.RestoreDisplayId();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
Talk(TextIds.SayAggro);
|
||||
_EnterCombat();
|
||||
|
||||
_events.ScheduleEvent(EventIds.DecayFlesh, TimeSpan.FromSeconds(20));
|
||||
_events.ScheduleEvent(EventIds.CurseOfLife, TimeSpan.FromSeconds(1));
|
||||
_events.ScheduleEvent(EventIds.RainOfFire, TimeSpan.FromSeconds(14), TimeSpan.FromSeconds(18));
|
||||
_events.ScheduleEvent(EventIds.ShadowVolley, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(10));
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.IsTypeId(TypeId.Player))
|
||||
Talk(TextIds.SayKill);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
|
||||
Talk(TextIds.SayDeath);
|
||||
DoCastAOE(SpellIds.ClearGiftOfTharonJa, true);
|
||||
DoCastAOE(SpellIds.AchievementCheck, true);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EventIds.CurseOfLife:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.CurseOfLife);
|
||||
_events.ScheduleEvent(EventIds.CurseOfLife, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15));
|
||||
}
|
||||
return;
|
||||
case EventIds.ShadowVolley:
|
||||
DoCastVictim(SpellIds.ShadowVolley);
|
||||
_events.ScheduleEvent(EventIds.ShadowVolley, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(10));
|
||||
return;
|
||||
case EventIds.RainOfFire:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.RainOfFire);
|
||||
_events.ScheduleEvent(EventIds.RainOfFire, TimeSpan.FromSeconds(14), TimeSpan.FromSeconds(18));
|
||||
}
|
||||
return;
|
||||
case EventIds.LightningBreath:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.LightningBreath);
|
||||
_events.ScheduleEvent(EventIds.LightningBreath, TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(7));
|
||||
}
|
||||
return;
|
||||
case EventIds.EyeBeam:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.EyeBeam);
|
||||
_events.ScheduleEvent(EventIds.EyeBeam, TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(6));
|
||||
}
|
||||
return;
|
||||
case EventIds.PoisonCloud:
|
||||
DoCastAOE(SpellIds.PoisonCloud);
|
||||
_events.ScheduleEvent(EventIds.PoisonCloud, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(12));
|
||||
return;
|
||||
case EventIds.DecayFlesh:
|
||||
DoCastAOE(SpellIds.DecayFlesh);
|
||||
_events.ScheduleEvent(EventIds.GoingFlesh, TimeSpan.FromSeconds(6));
|
||||
return;
|
||||
case EventIds.GoingFlesh:
|
||||
Talk(TextIds.SayFlesh);
|
||||
me.SetDisplayId(Misc.ModelFlesh);
|
||||
DoCastAOE(SpellIds.GiftOfTharonJa, true);
|
||||
DoCast(me, SpellIds.FleshVisual, true);
|
||||
DoCast(me, SpellIds.Dummy, true);
|
||||
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(EventIds.ReturnFlesh, TimeSpan.FromSeconds(20));
|
||||
_events.ScheduleEvent(EventIds.LightningBreath, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(4));
|
||||
_events.ScheduleEvent(EventIds.EyeBeam, TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(8));
|
||||
_events.ScheduleEvent(EventIds.PoisonCloud, TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(7));
|
||||
break;
|
||||
case EventIds.ReturnFlesh:
|
||||
DoCastAOE(SpellIds.ReturnFlesh);
|
||||
_events.ScheduleEvent(EventIds.GoingSkeletal, 6000);
|
||||
return;
|
||||
case EventIds.GoingSkeletal:
|
||||
Talk(TextIds.SaySkeleton);
|
||||
me.RestoreDisplayId();
|
||||
DoCastAOE(SpellIds.ClearGiftOfTharonJa, true);
|
||||
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(EventIds.DecayFlesh, TimeSpan.FromSeconds(20));
|
||||
_events.ScheduleEvent(EventIds.CurseOfLife, TimeSpan.FromSeconds(1));
|
||||
_events.ScheduleEvent(EventIds.RainOfFire, TimeSpan.FromSeconds(14), TimeSpan.FromSeconds(18));
|
||||
_events.ScheduleEvent(EventIds.ShadowVolley, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(10));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
});
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_tharon_ja_clear_gift_of_tharon_ja : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.GiftOfTharonJa);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
target.RemoveAura(SpellIds.GiftOfTharonJa);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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.Scripting;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
|
||||
namespace Scripts.Northrend.DraktharonKeep.Trollgore
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint InfectedWound = 49637;
|
||||
public const uint Crush = 49639;
|
||||
public const uint CorpseExplode = 49555;
|
||||
public const uint CorpseExplodeDamage = 49618;
|
||||
public const uint Consume = 49380;
|
||||
public const uint ConsumeBuff = 49381;
|
||||
public const uint ConsumeBuffH = 59805;
|
||||
|
||||
public const uint SummonInvaderA = 49456;
|
||||
public const uint SummonInvaderB = 49457;
|
||||
public const uint SummonInvaderC = 49458; // Can'T Find Any Sniffs
|
||||
|
||||
public const uint InvaderTaunt = 49405;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SayKill = 1;
|
||||
public const uint SayConsume = 2;
|
||||
public const uint SayExplode = 3;
|
||||
public const uint SayDeath = 4;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint DataConsumptionJunction = 1;
|
||||
public const uint PointLanding = 1;
|
||||
|
||||
public static Position Landing = new Position(-263.0534f, -660.8658f, 26.50903f, 0.0f);
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_trollgore : BossAI
|
||||
{
|
||||
public boss_trollgore(Creature creature) : base(creature, DTKDataTypes.Trollgore)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_consumptionJunction = true;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(TextIds.SayAggro);
|
||||
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
|
||||
{
|
||||
Talk(TextIds.SayConsume);
|
||||
DoCastAOE(SpellIds.Consume);
|
||||
task.Repeat();
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Crush);
|
||||
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(60), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.InfectedWound);
|
||||
task.Repeat(TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(3), task =>
|
||||
{
|
||||
Talk(TextIds.SayExplode);
|
||||
DoCastAOE(SpellIds.CorpseExplode);
|
||||
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(19));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(40), task =>
|
||||
{
|
||||
for (byte i = 0; i < 3; ++i)
|
||||
{
|
||||
Creature trigger = ObjectAccessor.GetCreature(me, instance.GetGuidData(DTKDataTypes.TrollgoreInvaderSummoner1 + i));
|
||||
if (trigger)
|
||||
trigger.CastSpell(trigger, RandomHelper.RAND(SpellIds.SummonInvaderA, SpellIds.SummonInvaderB, SpellIds.SummonInvaderC), true, null, null, me.GetGUID());
|
||||
}
|
||||
|
||||
task.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
if (_consumptionJunction)
|
||||
{
|
||||
Aura ConsumeAura = me.GetAura(DungeonMode(SpellIds.ConsumeBuff, SpellIds.ConsumeBuffH));
|
||||
if (ConsumeAura != null && ConsumeAura.GetStackAmount() > 9)
|
||||
_consumptionJunction = false;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(TextIds.SayDeath);
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == Misc.DataConsumptionJunction)
|
||||
return _consumptionJunction ? 1 : 0u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
if (victim.IsTypeId(TypeId.Player))
|
||||
Talk(TextIds.SayKill);
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
summon.GetMotionMaster().MovePoint(Misc.PointLanding, Misc.Landing);
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
bool _consumptionJunction;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_drakkari_invader : ScriptedAI
|
||||
{
|
||||
public npc_drakkari_invader(Creature creature) : base(creature) { }
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint pointId)
|
||||
{
|
||||
if (type == MovementGeneratorType.Point && pointId == Misc.PointLanding)
|
||||
{
|
||||
me.Dismount();
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.ImmuneToPc | UnitFlags.ImmuneToNpc);
|
||||
DoCastAOE(SpellIds.InvaderTaunt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 49380, 59803 - Consume
|
||||
class spell_trollgore_consume : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.ConsumeBuff);
|
||||
}
|
||||
|
||||
void HandleConsume(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
target.CastSpell(GetCaster(), SpellIds.ConsumeBuff, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleConsume, 1, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 49555, 59807 - Corpse Explode
|
||||
class spell_trollgore_corpse_explode : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.CorpseExplodeDamage);
|
||||
}
|
||||
|
||||
void PeriodicTick(AuraEffect aurEff)
|
||||
{
|
||||
if (aurEff.GetTickNumber() == 2)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
if (caster)
|
||||
caster.CastSpell(GetTarget(), SpellIds.CorpseExplodeDamage, true, null, aurEff);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
Creature target = GetTarget().ToCreature();
|
||||
if (target)
|
||||
target.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(PeriodicTick, 0, AuraType.Dummy));
|
||||
AfterEffectRemove.Add(new EffectApplyHandler(HandleRemove, 0, AuraType.PeriodicDummy, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 49405 - Invader Taunt Trigger
|
||||
class spell_trollgore_invader_taunt : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo((uint)spellInfo.GetEffect(0).CalcValue());
|
||||
}
|
||||
|
||||
void HandleTaunt(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
target.CastSpell(GetCaster(), (uint)GetEffectValue(), true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleTaunt, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_consumption_junction : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_consumption_junction() : base("achievement_consumption_junction") { }
|
||||
|
||||
public override bool OnCheck(Player source, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
Creature Trollgore = target.ToCreature();
|
||||
if (Trollgore)
|
||||
if (Trollgore.GetAI().GetData(Misc.DataConsumptionJunction) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 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 Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
|
||||
namespace Scripts.Northrend.DraktharonKeep
|
||||
{
|
||||
struct DTKDataTypes
|
||||
{
|
||||
// Encounter States/Boss Guids
|
||||
public const uint Trollgore = 0;
|
||||
public const uint Novos = 1;
|
||||
public const uint KingDred = 2;
|
||||
public const uint TharonJa = 3;
|
||||
|
||||
// Additional Data
|
||||
//public const uint KingDredAchiev;
|
||||
|
||||
public const uint TrollgoreInvaderSummoner1 = 4;
|
||||
public const uint TrollgoreInvaderSummoner2 = 5;
|
||||
public const uint TrollgoreInvaderSummoner3 = 6;
|
||||
|
||||
public const uint NovosCrystal1 = 7;
|
||||
public const uint NovosCrystal2 = 8;
|
||||
public const uint NovosCrystal3 = 9;
|
||||
public const uint NovosCrystal4 = 10;
|
||||
public const uint NovosSummoner1 = 11;
|
||||
public const uint NovosSummoner2 = 12;
|
||||
public const uint NovosSummoner3 = 13;
|
||||
public const uint NovosSummoner4 = 14;
|
||||
|
||||
public const int ActionCrystalHandlerDied = 15;
|
||||
}
|
||||
|
||||
struct DTKCreatureIds
|
||||
{
|
||||
public const uint Trollgore = 26630;
|
||||
public const uint Novos = 26631;
|
||||
public const uint KingDred = 27483;
|
||||
public const uint TharonJa = 26632;
|
||||
|
||||
// Trollgore
|
||||
public const uint DrakkariInvaderA = 27709;
|
||||
public const uint DrakkariInvaderB = 27753;
|
||||
public const uint DrakkariInvaderC = 27754;
|
||||
|
||||
// Novos
|
||||
public const uint CrystalChannelTarget = 26712;
|
||||
public const uint CrystalHandler = 26627;
|
||||
public const uint HulkingCorpse = 27597;
|
||||
public const uint FetidTrollCorpse = 27598;
|
||||
public const uint RisenShadowcaster = 27600;
|
||||
|
||||
// King Dred
|
||||
public const uint DrakkariGutripper = 26641;
|
||||
public const uint DrakkariScytheclaw = 26628;
|
||||
|
||||
public const uint WorldTrigger = 22515;
|
||||
}
|
||||
|
||||
struct DTKGameObjectIds
|
||||
{
|
||||
public const uint NovosCrystal1 = 189299;
|
||||
public const uint NovosCrystal2 = 189300;
|
||||
public const uint NovosCrystal3 = 189301;
|
||||
public const uint NovosCrystal4 = 189302;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class instance_drak_tharon_keep : InstanceMapScript
|
||||
{
|
||||
public instance_drak_tharon_keep() : base(nameof(instance_drak_tharon_keep), 600) { }
|
||||
|
||||
class instance_drak_tharon_keep_InstanceScript : InstanceScript
|
||||
{
|
||||
public instance_drak_tharon_keep_InstanceScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("DTK");
|
||||
SetBossNumber(4);
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
case DTKCreatureIds.Trollgore:
|
||||
TrollgoreGUID = creature.GetGUID();
|
||||
break;
|
||||
case DTKCreatureIds.Novos:
|
||||
NovosGUID = creature.GetGUID();
|
||||
break;
|
||||
case DTKCreatureIds.KingDred:
|
||||
KingDredGUID = creature.GetGUID();
|
||||
break;
|
||||
case DTKCreatureIds.TharonJa:
|
||||
TharonJaGUID = creature.GetGUID();
|
||||
break;
|
||||
case DTKCreatureIds.WorldTrigger:
|
||||
InitializeTrollgoreInvaderSummoner(creature);
|
||||
break;
|
||||
case DTKCreatureIds.CrystalChannelTarget:
|
||||
InitializeNovosSummoner(creature);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectCreate(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case DTKGameObjectIds.NovosCrystal1:
|
||||
NovosCrystalGUIDs[0] = go.GetGUID();
|
||||
break;
|
||||
case DTKGameObjectIds.NovosCrystal2:
|
||||
NovosCrystalGUIDs[1] = go.GetGUID();
|
||||
break;
|
||||
case DTKGameObjectIds.NovosCrystal3:
|
||||
NovosCrystalGUIDs[2] = go.GetGUID();
|
||||
break;
|
||||
case DTKGameObjectIds.NovosCrystal4:
|
||||
NovosCrystalGUIDs[3] = go.GetGUID();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeTrollgoreInvaderSummoner(Creature creature)
|
||||
{
|
||||
float y = creature.GetPositionY();
|
||||
float z = creature.GetPositionZ();
|
||||
|
||||
if (z < 50.0f)
|
||||
return;
|
||||
|
||||
if (y < -650.0f && y > -660.0f)
|
||||
TrollgoreInvaderSummonerGuids[0] = creature.GetGUID();
|
||||
else if (y < -660.0f && y > -670.0f)
|
||||
TrollgoreInvaderSummonerGuids[1] = creature.GetGUID();
|
||||
else if (y < -675.0f && y > -685.0f)
|
||||
TrollgoreInvaderSummonerGuids[2] = creature.GetGUID();
|
||||
}
|
||||
|
||||
void InitializeNovosSummoner(Creature creature)
|
||||
{
|
||||
float x = creature.GetPositionX();
|
||||
float y = creature.GetPositionY();
|
||||
float z = creature.GetPositionZ();
|
||||
|
||||
if (x < -374.0f && x > -379.0f && y > -820.0f && y < -815.0f && z < 60.0f && z > 58.0f)
|
||||
NovosSummonerGUIDs[0] = creature.GetGUID();
|
||||
else if (x < -379.0f && x > -385.0f && y > -820.0f && y < -815.0f && z < 60.0f && z > 58.0f)
|
||||
NovosSummonerGUIDs[1] = creature.GetGUID();
|
||||
else if (x < -374.0f && x > -385.0f && y > -827.0f && y < -820.0f && z < 60.0f && z > 58.0f)
|
||||
NovosSummonerGUIDs[2] = creature.GetGUID();
|
||||
else if (x < -338.0f && x > -380.0f && y > -727.0f && y < 721.0f && z < 30.0f && z > 26.0f)
|
||||
NovosSummonerGUIDs[3] = creature.GetGUID();
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGuidData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DTKDataTypes.Trollgore:
|
||||
return TrollgoreGUID;
|
||||
case DTKDataTypes.Novos:
|
||||
return NovosGUID;
|
||||
case DTKDataTypes.KingDred:
|
||||
return KingDredGUID;
|
||||
case DTKDataTypes.TharonJa:
|
||||
return TharonJaGUID;
|
||||
case DTKDataTypes.TrollgoreInvaderSummoner1:
|
||||
case DTKDataTypes.TrollgoreInvaderSummoner2:
|
||||
case DTKDataTypes.TrollgoreInvaderSummoner3:
|
||||
return TrollgoreInvaderSummonerGuids[type - DTKDataTypes.TrollgoreInvaderSummoner1];
|
||||
case DTKDataTypes.NovosCrystal1:
|
||||
case DTKDataTypes.NovosCrystal2:
|
||||
case DTKDataTypes.NovosCrystal3:
|
||||
case DTKDataTypes.NovosCrystal4:
|
||||
return NovosCrystalGUIDs[type - DTKDataTypes.NovosCrystal1];
|
||||
case DTKDataTypes.NovosSummoner1:
|
||||
case DTKDataTypes.NovosSummoner2:
|
||||
case DTKDataTypes.NovosSummoner3:
|
||||
case DTKDataTypes.NovosSummoner4:
|
||||
return NovosSummonerGUIDs[type - DTKDataTypes.NovosSummoner1];
|
||||
}
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
ObjectGuid TrollgoreGUID;
|
||||
ObjectGuid NovosGUID;
|
||||
ObjectGuid KingDredGUID;
|
||||
ObjectGuid TharonJaGUID;
|
||||
|
||||
ObjectGuid[] TrollgoreInvaderSummonerGuids = new ObjectGuid[3];
|
||||
ObjectGuid[] NovosCrystalGUIDs = new ObjectGuid[4];
|
||||
ObjectGuid[] NovosSummonerGUIDs = new ObjectGuid[4];
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_drak_tharon_keep_InstanceScript(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* 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;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend.FrozenHalls.ForgeOfSouls.Bronjahm
|
||||
{
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SaySlay = 1;
|
||||
public const uint SayDeath = 2;
|
||||
public const uint SaySoulStorm = 3;
|
||||
public const uint SayCorruptSoul = 4;
|
||||
}
|
||||
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint MagicSBane = 68793;
|
||||
public const uint ShadowBolt = 70043;
|
||||
public const uint CorruptSoul = 68839;
|
||||
public const uint ConsumeSoul = 68861;
|
||||
public const uint Teleport = 68988;
|
||||
public const uint Fear = 68950;
|
||||
public const uint Soulstorm = 68872;
|
||||
public const uint SoulstormChannel = 69008; // Pre-Fight
|
||||
public const uint SoulstormVisual = 68870; // Pre-Cast Soulstorm
|
||||
public const uint PurpleBanishVisual = 68862; // Used By Soul Fragment (Aura)
|
||||
}
|
||||
|
||||
struct EventIds
|
||||
{
|
||||
public const uint MagicBane = 1;
|
||||
public const uint ShadowBolt = 2;
|
||||
public const uint CorruptSoul = 3;
|
||||
public const uint Soulstorm = 4;
|
||||
public const uint Fear = 5;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint DataSoulPower = 1;
|
||||
|
||||
public const byte Phase1 = 1;
|
||||
public const byte Phase2 = 2;
|
||||
|
||||
public static uint[] SoulstormVisualSpells =
|
||||
{
|
||||
68904,
|
||||
68886,
|
||||
68905,
|
||||
68896,
|
||||
68906,
|
||||
68897,
|
||||
68907,
|
||||
68898
|
||||
};
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_bronjahm : BossAI
|
||||
{
|
||||
public boss_bronjahm(Creature creature) : base(creature, DataType.Bronjahm)
|
||||
{
|
||||
DoCast(me, SpellIds.SoulstormChannel, true);
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
_events.SetPhase(Misc.Phase1);
|
||||
_events.ScheduleEvent(EventIds.ShadowBolt, 2000);
|
||||
_events.ScheduleEvent(EventIds.MagicBane, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(20));
|
||||
_events.ScheduleEvent(EventIds.CorruptSoul, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35), 0, Misc.Phase1);
|
||||
}
|
||||
|
||||
public override void JustReachedHome()
|
||||
{
|
||||
_JustReachedHome();
|
||||
DoCast(me, SpellIds.SoulstormChannel, true);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(TextIds.SayAggro);
|
||||
me.RemoveAurasDueToSpell(SpellIds.SoulstormChannel);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(TextIds.SayDeath);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.GetTypeId() == TypeId.Player)
|
||||
Talk(TextIds.SaySlay);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (_events.IsInPhase(Misc.Phase1) && !HealthAbovePct(30))
|
||||
{
|
||||
_events.SetPhase(Misc.Phase2);
|
||||
DoCast(me, SpellIds.Teleport);
|
||||
_events.ScheduleEvent(EventIds.Fear, TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(16), 0, Misc.Phase2);
|
||||
_events.ScheduleEvent(EventIds.Soulstorm, 100, 0, Misc.Phase2);
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
if (summon.GetEntry() == CreatureIds.CorruptedSoulFragment)
|
||||
{
|
||||
summons.Summon(summon);
|
||||
summon.SetReactState(ReactStates.Passive);
|
||||
summon.GetMotionMaster().MoveFollow(me, me.GetObjectSize(), 0.0f);
|
||||
summon.CastSpell(summon, SpellIds.PurpleBanishVisual, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == Misc.DataSoulPower)
|
||||
{
|
||||
uint count = 0;
|
||||
foreach (ObjectGuid guid in summons)
|
||||
{
|
||||
Creature summon = ObjectAccessor.GetCreature(me, guid);
|
||||
if (summon)
|
||||
if (summon.GetEntry() == CreatureIds.CorruptedSoulFragment && summon.IsAlive())
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EventIds.MagicBane:
|
||||
DoCastAOE(SpellIds.MagicSBane);
|
||||
_events.ScheduleEvent(EventIds.MagicBane, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(20));
|
||||
break;
|
||||
case EventIds.ShadowBolt:
|
||||
if (_events.IsInPhase(Misc.Phase2))
|
||||
{
|
||||
DoCastVictim(SpellIds.ShadowBolt);
|
||||
_events.ScheduleEvent(EventIds.ShadowBolt, TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!me.IsWithinMeleeRange(me.GetVictim()))
|
||||
DoCastVictim(SpellIds.ShadowBolt);
|
||||
_events.ScheduleEvent(EventIds.ShadowBolt, TimeSpan.FromMilliseconds(2));
|
||||
}
|
||||
break;
|
||||
case EventIds.CorruptSoul:
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 1, 0.0f, true);
|
||||
if (target)
|
||||
{
|
||||
Talk(TextIds.SayCorruptSoul);
|
||||
DoCast(target, SpellIds.CorruptSoul);
|
||||
}
|
||||
_events.ScheduleEvent(EventIds.CorruptSoul, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35), 0, Misc.Phase1);
|
||||
break;
|
||||
case EventIds.Soulstorm:
|
||||
Talk(TextIds.SaySoulStorm);
|
||||
me.CastSpell(me, SpellIds.SoulstormVisual, true);
|
||||
me.CastSpell(me, SpellIds.Soulstorm, false);
|
||||
break;
|
||||
case EventIds.Fear:
|
||||
me.CastCustomSpell(SpellIds.Fear, SpellValueMod.MaxTargets, 1, null, false);
|
||||
_events.ScheduleEvent(EventIds.Fear, TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12), 0, Misc.Phase2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
});
|
||||
|
||||
if (!_events.IsInPhase(Misc.Phase2))
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_corrupted_soul_fragment : ScriptedAI
|
||||
{
|
||||
public npc_corrupted_soul_fragment(Creature creature) : base(creature)
|
||||
{
|
||||
instance = me.GetInstanceScript();
|
||||
}
|
||||
|
||||
public override void IsSummonedBy(Unit summoner)
|
||||
{
|
||||
Creature bronjahm = ObjectAccessor.GetCreature(me, instance.GetGuidData(DataType.Bronjahm));
|
||||
if (bronjahm)
|
||||
bronjahm.GetAI().JustSummoned(me);
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (type != MovementGeneratorType.Follow)
|
||||
return;
|
||||
|
||||
if (instance.GetGuidData(DataType.Bronjahm).GetCounter() != id)
|
||||
return;
|
||||
|
||||
me.CastSpell((Unit)null, SpellIds.ConsumeSoul, true);
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_bronjahm_magic_bane : SpellScript
|
||||
{
|
||||
void RecalculateDamage()
|
||||
{
|
||||
if (GetHitUnit().getPowerType() != PowerType.Mana)
|
||||
return;
|
||||
|
||||
int maxDamage = GetCaster().GetMap().IsHeroic() ? 15000 : 10000;
|
||||
int newDamage = GetHitDamage() + (GetHitUnit().GetMaxPower(PowerType.Mana) / 2);
|
||||
|
||||
SetHitDamage(Math.Min(maxDamage, newDamage));
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnHit.Add(new HitHandler(RecalculateDamage));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_bronjahm_consume_soul : SpellScript
|
||||
{
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
GetHitUnit().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_bronjahm_soulstorm_visual : AuraScript
|
||||
{
|
||||
void HandlePeriodicTick(AuraEffect aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
GetTarget().CastSpell(GetTarget(), Misc.SoulstormVisualSpells[aurEff.GetTickNumber() % 8], true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(HandlePeriodicTick, 0, AuraType.PeriodicDummy));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_bronjahm_soulstorm_targeting : SpellScript
|
||||
{
|
||||
void FilterTargets(List<WorldObject> targets)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
targets.RemoveAll(target =>
|
||||
{
|
||||
return caster.GetExactDist2d(target) <= 10.0f;
|
||||
});
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, SpellConst.EffectAll, Targets.UnitDestAreaEnemy));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_bronjahm_soul_power : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_bronjahm_soul_power() : base("achievement_bronjahm_soul_power") { }
|
||||
|
||||
public override bool OnCheck(Player source, Unit target)
|
||||
{
|
||||
return target && target.GetAI().GetData(Misc.DataSoulPower) >= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,414 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Game.Entities;
|
||||
using Framework.Constants;
|
||||
using Game.Scripting;
|
||||
using Game.AI;
|
||||
using Game.Spells;
|
||||
|
||||
namespace Scripts.Northrend.FrozenHalls.ForgeOfSouls.DevourerOfSouls
|
||||
{
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayFaceAggro = 0;
|
||||
public const byte SayFaceAngerSlay = 1;
|
||||
public const byte SayFaceSorrowSlay = 2;
|
||||
public const byte SayFaceDesireSlay = 3;
|
||||
public const uint SayFaceDeath = 4;
|
||||
public const uint EmoteMirroredSoul = 5;
|
||||
public const uint EmoteUnleashSoul = 6;
|
||||
public const uint SayFaceUnleashSoul = 7;
|
||||
public const uint EmoteWailingSoul = 8;
|
||||
public const uint SayFaceWailingSoul = 9;
|
||||
|
||||
public const uint SayJainaOutro = 0;
|
||||
public const uint SaySylvanasOutro = 0;
|
||||
}
|
||||
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint PhantomBlast = 68982;
|
||||
public const uint MirroredSoulProcAura = 69023;
|
||||
public const uint MirroredSoulDamage = 69034;
|
||||
public const uint MirroredSoulTargetSelector = 69048;
|
||||
public const uint MirroredSoulBuff = 69051;
|
||||
public const uint WellOfSouls = 68820;
|
||||
public const uint UnleashedSouls = 68939;
|
||||
public const uint WailingSoulsStarting = 68912; // Initial Spell Cast At Begining Of Wailing Souls Phase
|
||||
public const uint WailingSoulsBeam = 68875; // The Beam Visual
|
||||
public const uint WailingSouls = 68873; // The Actual Spell
|
||||
// 68871; 68873; 68875; 68876; 68899; 68912; 70324;
|
||||
// 68899 Trigger 68871
|
||||
}
|
||||
|
||||
struct ModelIds
|
||||
{
|
||||
public const uint Anger = 30148;
|
||||
public const uint Sorrow = 30149;
|
||||
public const uint Desire = 30150;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint DataThreeFaced = 1;
|
||||
|
||||
public static outroPosition[] outroPositions =
|
||||
{
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5590.47f, 2427.79f, 705.935f, 0.802851f)),
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5593.59f, 2428.34f, 705.935f, 0.977384f)),
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5600.81f, 2429.31f, 705.935f, 0.890118f)),
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5600.81f, 2421.12f, 705.935f, 0.890118f)),
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5601.43f, 2426.53f, 705.935f, 0.890118f)),
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5601.55f, 2418.36f, 705.935f, 1.15192f)),
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5598, 2429.14f, 705.935f, 1.0472f)),
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5594.04f, 2424.87f, 705.935f, 1.15192f)),
|
||||
new outroPosition(CreatureIds.Champion1Alliance, CreatureIds.Champion1Horde, new Position(5597.89f, 2421.54f, 705.935f, 0.610865f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5598.57f, 2434.62f, 705.935f, 1.13446f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5585.46f, 2417.99f, 705.935f, 1.06465f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5605.81f, 2428.42f, 705.935f, 0.820305f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5591.61f, 2412.66f, 705.935f, 0.925025f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5593.9f, 2410.64f, 705.935f, 0.872665f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion2Horde, new Position(5586.76f, 2416.73f, 705.935f, 0.942478f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion3Horde, new Position(5592.23f, 2419.14f, 705.935f, 0.855211f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion3Horde, new Position(5594.61f, 2416.87f, 705.935f, 0.907571f)),
|
||||
new outroPosition(CreatureIds.Champion2Alliance, CreatureIds.Champion3Horde, new Position(5589.77f, 2421.03f, 705.935f, 0.855211f)),
|
||||
|
||||
new outroPosition(CreatureIds.Koreln, CreatureIds.Loralen, new Position(5602.58f, 2435.95f, 705.935f, 0.959931f)),
|
||||
new outroPosition(CreatureIds.Elandra, CreatureIds.Kalira, new Position(5606.13f, 2433.16f, 705.935f, 0.785398f)),
|
||||
new outroPosition(CreatureIds.JainaPart2, CreatureIds.SylvanasPart2, new Position(5606.12f, 2436.6f, 705.935f, 0.890118f)),
|
||||
};
|
||||
|
||||
public static Position CrucibleSummonPos = new Position(5672.294f, 2520.686f, 713.4386f, 0.9599311f);
|
||||
}
|
||||
|
||||
struct outroPosition
|
||||
{
|
||||
public outroPosition(uint allianceEntry, uint hordeEntry, Position movePosition)
|
||||
{
|
||||
Entry = new uint[2];
|
||||
Entry[0] = allianceEntry;
|
||||
Entry[1] = hordeEntry;
|
||||
|
||||
MovePosition = movePosition;
|
||||
}
|
||||
|
||||
public uint[] Entry;
|
||||
public Position MovePosition;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_devourer_of_souls : BossAI
|
||||
{
|
||||
public boss_devourer_of_souls(Creature creature) : base(creature, DataType.DevourerOfSouls)
|
||||
{
|
||||
Initialize();
|
||||
beamAngle = 0.0f;
|
||||
beamAngleDiff = 0.0f;
|
||||
wailingSoulTick = 0;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
threeFaced = true;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
me.SetControlled(false, UnitState.Root);
|
||||
me.SetDisplayId(ModelIds.Anger);
|
||||
me.SetReactState(ReactStates.Aggressive);
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(TextIds.SayFaceAggro);
|
||||
|
||||
if (!me.FindNearestCreature(CreatureIds.CrucibleOfSouls, 60)) // Prevent double spawn
|
||||
me.GetMap().SummonCreature(CreatureIds.CrucibleOfSouls, Misc.CrucibleSummonPos);
|
||||
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.PhantomBlast);
|
||||
task.Repeat(TimeSpan.FromSeconds(5));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
DoCastAOE(SpellIds.MirroredSoulTargetSelector);
|
||||
Talk(TextIds.EmoteMirroredSoul);
|
||||
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.WellOfSouls);
|
||||
task.Repeat(TimeSpan.FromSeconds(20));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(20), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.UnleashedSouls);
|
||||
me.SetDisplayId(ModelIds.Sorrow);
|
||||
Talk(TextIds.SayFaceUnleashSoul);
|
||||
Talk(TextIds.EmoteUnleashSoul);
|
||||
task.Repeat(TimeSpan.FromSeconds(30));
|
||||
task.Schedule(TimeSpan.FromSeconds(5), () => me.SetDisplayId(ModelIds.Anger));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(70), task =>
|
||||
{
|
||||
me.SetDisplayId(ModelIds.Desire);
|
||||
Talk(TextIds.SayFaceWailingSoul);
|
||||
Talk(TextIds.EmoteWailingSoul);
|
||||
DoCast(me, SpellIds.WailingSoulsStarting);
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
{
|
||||
me.SetFacingToObject(target);
|
||||
DoCast(me, SpellIds.WailingSoulsBeam);
|
||||
}
|
||||
|
||||
beamAngle = me.GetOrientation();
|
||||
|
||||
beamAngleDiff = (float)Math.PI / 30.0f; // PI/2 in 15 sec = PI/30 per tick
|
||||
if (RandomHelper.RAND(true, false))
|
||||
beamAngleDiff = -beamAngleDiff;
|
||||
|
||||
me.InterruptNonMeleeSpells(false);
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
|
||||
//Remove any target
|
||||
me.SetTarget(ObjectGuid.Empty);
|
||||
|
||||
me.GetMotionMaster().Clear();
|
||||
me.SetControlled(true, UnitState.Root);
|
||||
|
||||
wailingSoulTick = 15;
|
||||
|
||||
_scheduler.DelayAll(TimeSpan.FromSeconds(18)); // no other events during wailing souls
|
||||
|
||||
// first one after 3 secs.
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(3), tickTask =>
|
||||
{
|
||||
beamAngle += beamAngleDiff;
|
||||
me.SetFacingTo(beamAngle, true);
|
||||
me.StopMoving();
|
||||
|
||||
DoCast(me, SpellIds.WailingSouls);
|
||||
|
||||
if (--wailingSoulTick != 0)
|
||||
tickTask.Repeat(TimeSpan.FromSeconds(1));
|
||||
else
|
||||
{
|
||||
me.SetReactState(ReactStates.Aggressive);
|
||||
me.SetDisplayId(ModelIds.Anger);
|
||||
me.SetControlled(false, UnitState.Root);
|
||||
me.GetMotionMaster().MoveChase(me.GetVictim());
|
||||
task.Repeat(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(70));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
if (victim.GetTypeId() != TypeId.Player)
|
||||
return;
|
||||
|
||||
byte textId = 0;
|
||||
switch (me.GetDisplayId())
|
||||
{
|
||||
case ModelIds.Anger:
|
||||
textId = TextIds.SayFaceAngerSlay;
|
||||
break;
|
||||
case ModelIds.Sorrow:
|
||||
textId = TextIds.SayFaceSorrowSlay;
|
||||
break;
|
||||
case ModelIds.Desire:
|
||||
textId = TextIds.SayFaceDesireSlay;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (textId != 0)
|
||||
Talk(textId);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
|
||||
Position spawnPoint = new Position(5618.139f, 2451.873f, 705.854f, 0);
|
||||
|
||||
Talk(TextIds.SayFaceDeath);
|
||||
|
||||
int entryIndex;
|
||||
if (instance.GetData(DataType.TeamInInstance) == (uint)Team.Alliance)
|
||||
entryIndex = 0;
|
||||
else
|
||||
entryIndex = 1;
|
||||
|
||||
for (var i = 0; Misc.outroPositions[i].Entry[entryIndex] != 0; ++i)
|
||||
{
|
||||
Creature summon = me.SummonCreature(Misc.outroPositions[i].Entry[entryIndex], spawnPoint, TempSummonType.DeadDespawn);
|
||||
if (summon)
|
||||
{
|
||||
summon.GetMotionMaster().MovePoint(0, Misc.outroPositions[i].MovePosition);
|
||||
if (summon.GetEntry() == CreatureIds.JainaPart2)
|
||||
summon.GetAI().Talk(TextIds.SayJainaOutro);
|
||||
else if (summon.GetEntry() == CreatureIds.SylvanasPart2)
|
||||
summon.GetAI().Talk(TextIds.SaySylvanasOutro);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void SpellHitTarget(Unit target, SpellInfo spell)
|
||||
{
|
||||
if (spell.Id == SpellIds.PhantomBlast)
|
||||
threeFaced = false;
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == Misc.DataThreeFaced)
|
||||
return threeFaced ? 1 : 0u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
// Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool threeFaced;
|
||||
|
||||
// wailing soul event
|
||||
float beamAngle;
|
||||
float beamAngleDiff;
|
||||
sbyte wailingSoulTick;
|
||||
}
|
||||
|
||||
[Script] // 69051 - Mirrored Soul
|
||||
class spell_devourer_of_souls_mirrored_soul : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.MirroredSoulProcAura);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
target.CastSpell(GetCaster(), SpellIds.MirroredSoulProcAura, true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69023 - Mirrored Soul (Proc)
|
||||
class spell_devourer_of_souls_mirrored_soul_proc : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.MirroredSoulDamage);
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo eventInfo)
|
||||
{
|
||||
return GetCaster() && GetCaster().IsAlive();
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
DamageInfo damageInfo = eventInfo.GetDamageInfo();
|
||||
if (damageInfo == null || damageInfo.GetDamage() == 0)
|
||||
return;
|
||||
|
||||
int damage = (int)MathFunctions.CalculatePct(damageInfo.GetDamage(), 45);
|
||||
GetTarget().CastCustomSpell(SpellIds.MirroredSoulDamage, SpellValueMod.BasePoint0, damage, GetCaster(), true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
DoCheckProc.Add(new CheckProcHandler(CheckProc));
|
||||
OnEffectProc.Add(new EffectProcHandler(HandleProc, 0, AuraType.ProcTriggerSpell));
|
||||
}
|
||||
}
|
||||
|
||||
[Script] // 69048 - Mirrored Soul (Target Selector)
|
||||
class spell_devourer_of_souls_mirrored_soul_target_selector : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.MirroredSoulBuff);
|
||||
}
|
||||
|
||||
void FilterTargets(List<WorldObject> targets)
|
||||
{
|
||||
if (targets.Empty())
|
||||
return;
|
||||
|
||||
WorldObject target = targets.SelectRandom();
|
||||
targets.Clear();
|
||||
targets.Add(target);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
GetCaster().CastSpell(target, SpellIds.MirroredSoulBuff, false);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, 0, Targets.UnitSrcAreaEntry));
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_three_faced : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_three_faced() : base("achievement_three_faced") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
Creature devourer = target.ToCreature();
|
||||
if (devourer)
|
||||
if (devourer.GetAI().GetData(Misc.DataThreeFaced) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* 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 System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend.FrozenHalls.ForgeOfSouls
|
||||
{
|
||||
struct DataType
|
||||
{
|
||||
// Encounter states and GUIDs
|
||||
public const uint Bronjahm = 0;
|
||||
public const uint DevourerOfSouls = 1;
|
||||
|
||||
// Additional Data
|
||||
public const uint TeamInInstance = 2;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
public const uint Bronjahm = 36497;
|
||||
public const uint Devourer = 36502;
|
||||
public const uint CorruptedSoulFragment = 36535;
|
||||
|
||||
public const uint SylvanasPart1 = 37596;
|
||||
public const uint SylvanasPart2 = 38161;
|
||||
public const uint JainaPart1 = 37597;
|
||||
public const uint JainaPart2 = 38160;
|
||||
public const uint Kalira = 37583;
|
||||
public const uint Elandra = 37774;
|
||||
public const uint Loralen = 37779;
|
||||
public const uint Koreln = 37582;
|
||||
public const uint Champion1Horde = 37584;
|
||||
public const uint Champion2Horde = 37587;
|
||||
public const uint Champion3Horde = 37588;
|
||||
public const uint Champion1Alliance = 37496;
|
||||
public const uint Champion2Alliance = 37497;
|
||||
public const uint CrucibleOfSouls = 37094;
|
||||
}
|
||||
|
||||
struct EventIds
|
||||
{
|
||||
public const uint None = 0;
|
||||
|
||||
// Jaina/Sylvanas Intro
|
||||
public const uint Intro1 = 1;
|
||||
public const uint Intro2 = 2;
|
||||
public const uint Intro3 = 3;
|
||||
public const uint Intro4 = 4;
|
||||
public const uint Intro5 = 5;
|
||||
public const uint Intro6 = 6;
|
||||
public const uint Intro7 = 7;
|
||||
public const uint Intro8 = 8;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayJainaIntro1 = 0;
|
||||
public const uint SayJainaIntro2 = 1;
|
||||
public const uint SayJainaIntro3 = 2;
|
||||
public const uint SayJainaIntro4 = 3;
|
||||
public const uint SayJainaIntro5 = 4;
|
||||
public const uint SayJainaIntro6 = 5;
|
||||
public const uint SayJainaIntro7 = 6;
|
||||
public const uint SayJainaIntro8 = 7;
|
||||
|
||||
public const uint SaySylvanasIntro1 = 0;
|
||||
public const uint SaySylvanasIntro2 = 1;
|
||||
public const uint SaySylvanasIntro3 = 2;
|
||||
public const uint SaySylvanasIntro4 = 3;
|
||||
public const uint SaySylvanasIntro5 = 4;
|
||||
public const uint SaySylvanasIntro6 = 5;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint MenuIdJaina = 10943;
|
||||
public const uint MenuIdSylvanas = 10971;
|
||||
public const uint GossipOptionId = 0;
|
||||
}
|
||||
|
||||
enum Phase
|
||||
{
|
||||
Normal,
|
||||
Intro,
|
||||
}
|
||||
|
||||
[Script]
|
||||
class instance_forge_of_souls : InstanceMapScript
|
||||
{
|
||||
public instance_forge_of_souls() : base(nameof(instance_forge_of_souls), 632) { }
|
||||
|
||||
class instance_forge_of_souls_InstanceScript : InstanceScript
|
||||
{
|
||||
public instance_forge_of_souls_InstanceScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("FOS");
|
||||
SetBossNumber(2);
|
||||
|
||||
teamInInstance = 0;
|
||||
}
|
||||
|
||||
public override void OnPlayerEnter(Player player)
|
||||
{
|
||||
if (teamInInstance == 0)
|
||||
teamInInstance = player.GetTeam();
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
if (teamInInstance == 0)
|
||||
{
|
||||
var players = instance.GetPlayers();
|
||||
if (!players.Empty())
|
||||
{
|
||||
Player player = players[0];
|
||||
if (player)
|
||||
teamInInstance = player.GetTeam();
|
||||
}
|
||||
}
|
||||
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
case CreatureIds.Bronjahm:
|
||||
bronjahm = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.Devourer:
|
||||
devourerOfSouls = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.SylvanasPart1:
|
||||
if (teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.JainaPart1);
|
||||
break;
|
||||
case CreatureIds.Loralen:
|
||||
if (teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.Elandra);
|
||||
break;
|
||||
case CreatureIds.Kalira:
|
||||
if (teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.Koreln);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataType.TeamInInstance:
|
||||
return (uint)teamInInstance;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGuidData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataType.Bronjahm:
|
||||
return bronjahm;
|
||||
case DataType.DevourerOfSouls:
|
||||
return devourerOfSouls;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
ObjectGuid bronjahm;
|
||||
ObjectGuid devourerOfSouls;
|
||||
|
||||
Team teamInInstance;
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_forge_of_souls_InstanceScript(map);
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_sylvanas_fos : ScriptedAI
|
||||
{
|
||||
public npc_sylvanas_fos(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
me.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
phase = Phase.Normal;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_events.Reset();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void sGossipSelect(Player player, uint menuId, uint gossipListId)
|
||||
{
|
||||
if (menuId == Misc.MenuIdSylvanas && gossipListId == Misc.GossipOptionId)
|
||||
{
|
||||
player.CLOSE_GOSSIP_MENU();
|
||||
phase = Phase.Intro;
|
||||
me.RemoveFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(EventIds.Intro1, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (phase == Phase.Intro)
|
||||
{
|
||||
_events.Update(diff);
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EventIds.Intro1:
|
||||
Talk(TextIds.SaySylvanasIntro1);
|
||||
_events.ScheduleEvent(EventIds.Intro2, 11500);
|
||||
break;
|
||||
|
||||
case EventIds.Intro2:
|
||||
Talk(TextIds.SaySylvanasIntro2);
|
||||
_events.ScheduleEvent(EventIds.Intro3, 10500);
|
||||
break;
|
||||
|
||||
case EventIds.Intro3:
|
||||
Talk(TextIds.SaySylvanasIntro3);
|
||||
_events.ScheduleEvent(EventIds.Intro4, 9500);
|
||||
break;
|
||||
|
||||
case EventIds.Intro4:
|
||||
Talk(TextIds.SaySylvanasIntro4);
|
||||
_events.ScheduleEvent(EventIds.Intro5, 10500);
|
||||
break;
|
||||
|
||||
case EventIds.Intro5:
|
||||
Talk(TextIds.SaySylvanasIntro5);
|
||||
_events.ScheduleEvent(EventIds.Intro6, 9500);
|
||||
break;
|
||||
|
||||
case EventIds.Intro6:
|
||||
Talk(TextIds.SaySylvanasIntro6);
|
||||
// End of Intro
|
||||
phase = Phase.Normal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
Phase phase;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_jaina_fos : ScriptedAI
|
||||
{
|
||||
public npc_jaina_fos(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
me.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
phase = Phase.Normal;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_events.Reset();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void sGossipSelect(Player player, uint menuId, uint gossipListId)
|
||||
{
|
||||
if (menuId == Misc.MenuIdJaina && gossipListId == Misc.GossipOptionId)
|
||||
{
|
||||
player.CLOSE_GOSSIP_MENU();
|
||||
phase = Phase.Intro;
|
||||
me.RemoveFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(EventIds.Intro1, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (phase == Phase.Intro)
|
||||
{
|
||||
_events.Update(diff);
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EventIds.Intro1:
|
||||
Talk(TextIds.SayJainaIntro1);
|
||||
_events.ScheduleEvent(EventIds.Intro2, 8000);
|
||||
break;
|
||||
|
||||
case EventIds.Intro2:
|
||||
Talk(TextIds.SayJainaIntro2);
|
||||
_events.ScheduleEvent(EventIds.Intro3, 8500);
|
||||
break;
|
||||
|
||||
case EventIds.Intro3:
|
||||
Talk(TextIds.SayJainaIntro3);
|
||||
_events.ScheduleEvent(EventIds.Intro4, 8000);
|
||||
break;
|
||||
|
||||
case EventIds.Intro4:
|
||||
Talk(TextIds.SayJainaIntro4);
|
||||
_events.ScheduleEvent(EventIds.Intro5, 10000);
|
||||
break;
|
||||
|
||||
case EventIds.Intro5:
|
||||
Talk(TextIds.SayJainaIntro5);
|
||||
_events.ScheduleEvent(EventIds.Intro6, 8000);
|
||||
break;
|
||||
|
||||
case EventIds.Intro6:
|
||||
Talk(TextIds.SayJainaIntro6);
|
||||
_events.ScheduleEvent(EventIds.Intro7, 12000);
|
||||
break;
|
||||
|
||||
case EventIds.Intro7:
|
||||
Talk(TextIds.SayJainaIntro7);
|
||||
_events.ScheduleEvent(EventIds.Intro8, 8000);
|
||||
break;
|
||||
|
||||
case EventIds.Intro8:
|
||||
Talk(TextIds.SayJainaIntro8);
|
||||
// End of Intro
|
||||
phase = Phase.Normal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
Phase phase;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Game.AI;
|
||||
using Game.Entities;
|
||||
using Framework.Constants;
|
||||
using Game.Spells;
|
||||
using Game.Scripting;
|
||||
|
||||
namespace Scripts.Northrend.FrozenHalls.PitOfSaron.BossForgemasterGarfrost
|
||||
{
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SayPhase2 = 1;
|
||||
public const uint SayPhase3 = 2;
|
||||
public const uint SayDeath = 3;
|
||||
public const uint SaySlay = 4;
|
||||
public const uint SayThrowSaronite = 5;
|
||||
public const uint SayCastDeepFreeze = 6;
|
||||
|
||||
public const uint SayTyrannusDeath = 0;
|
||||
}
|
||||
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint Permafrost = 70326;
|
||||
public const uint ThrowSaronite = 68788;
|
||||
public const uint ThunderingStomp = 68771;
|
||||
public const uint ChillingWave = 68778;
|
||||
public const uint DeepFreeze = 70381;
|
||||
public const uint ForgeMace = 68785;
|
||||
public const uint ForgeBlade = 68774;
|
||||
|
||||
public const uint PermafrostAura = 68786;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const byte PhaseOne = 1;
|
||||
public const byte PhaseTwo = 2;
|
||||
public const byte PhaseThree = 3;
|
||||
|
||||
public const int EquipIdSword = 49345;
|
||||
public const int EquipIdMace = 49344;
|
||||
public const uint AchievDoesntGoToEleven = 0;
|
||||
public const uint PointForge = 0;
|
||||
|
||||
public static Position northForgePos = new Position(722.5643f, -234.1615f, 527.182f, 2.16421f);
|
||||
public static Position southForgePos = new Position(639.257f, -210.1198f, 529.015f, 0.523599f);
|
||||
}
|
||||
|
||||
struct Events
|
||||
{
|
||||
public const uint ThrowSaronite = 1;
|
||||
public const uint ChillingWave = 2;
|
||||
public const uint DeepFreeze = 3;
|
||||
public const uint ForgeJump = 4;
|
||||
public const uint ResumeAttack = 5;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_garfrost : BossAI
|
||||
{
|
||||
public boss_garfrost(Creature creature) : base(creature, DataTypes.Garfrost) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
_events.SetPhase(Misc.PhaseOne);
|
||||
SetEquipmentSlots(true);
|
||||
_permafrostStack = 0;
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(TextIds.SayAggro);
|
||||
DoCast(me, SpellIds.Permafrost);
|
||||
me.CallForHelp(70.0f);
|
||||
_events.ScheduleEvent(Events.ThrowSaronite, 7000);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
if (victim.IsPlayer())
|
||||
Talk(TextIds.SaySlay);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(TextIds.SayDeath);
|
||||
me.RemoveAllGameObjects();
|
||||
|
||||
Creature tyrannus = ObjectAccessor.GetCreature(me, instance.GetGuidData(DataTypes.Tyrannus));
|
||||
if (tyrannus)
|
||||
tyrannus.GetAI().Talk(TextIds.SayTyrannusDeath);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (_events.IsInPhase(Misc.PhaseOne) && !HealthAbovePct(66))
|
||||
{
|
||||
_events.SetPhase(Misc.PhaseTwo);
|
||||
Talk(TextIds.SayPhase2);
|
||||
_events.DelayEvents(8000);
|
||||
DoCast(me, SpellIds.ThunderingStomp);
|
||||
_events.ScheduleEvent(Events.ForgeJump, 1500);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_events.IsInPhase(Misc.PhaseTwo) && !HealthAbovePct(33))
|
||||
{
|
||||
_events.SetPhase(Misc.PhaseThree);
|
||||
Talk(TextIds.SayPhase3);
|
||||
_events.DelayEvents(8000);
|
||||
DoCast(me, SpellIds.ThunderingStomp);
|
||||
_events.ScheduleEvent(Events.ForgeJump, 1500);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (type != MovementGeneratorType.Effect || id != Misc.PointForge)
|
||||
return;
|
||||
|
||||
if (_events.IsInPhase(Misc.PhaseTwo))
|
||||
{
|
||||
DoCast(me, SpellIds.ForgeBlade);
|
||||
SetEquipmentSlots(false, Misc.EquipIdSword);
|
||||
}
|
||||
if (_events.IsInPhase(Misc.PhaseThree))
|
||||
{
|
||||
me.RemoveAurasDueToSpell(SpellIds.ForgeBlade);
|
||||
DoCast(me, SpellIds.ForgeMace);
|
||||
SetEquipmentSlots(false, Misc.EquipIdMace);
|
||||
}
|
||||
_events.ScheduleEvent(Events.ResumeAttack, 5000);
|
||||
}
|
||||
|
||||
public override void SpellHitTarget(Unit target, SpellInfo spell)
|
||||
{
|
||||
if (spell.Id == SpellIds.PermafrostAura)
|
||||
{
|
||||
Aura aura = target.GetAura(SpellIds.PermafrostAura);
|
||||
if (aura != null)
|
||||
_permafrostStack = Math.Max(_permafrostStack, aura.GetStackAmount());
|
||||
}
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
return _permafrostStack;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Events.ThrowSaronite:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 0.0f, true);
|
||||
if (target)
|
||||
{
|
||||
Talk(TextIds.SayThrowSaronite, target);
|
||||
DoCast(target, SpellIds.ThrowSaronite);
|
||||
}
|
||||
_events.ScheduleEvent(Events.ThrowSaronite, TimeSpan.FromSeconds(12.5), TimeSpan.FromSeconds(20));
|
||||
}
|
||||
break;
|
||||
case Events.ChillingWave:
|
||||
DoCast(me, SpellIds.ChillingWave);
|
||||
_events.ScheduleEvent(Events.ChillingWave, 40000, 0, Misc.PhaseTwo);
|
||||
break;
|
||||
case Events.DeepFreeze:
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 0.0f, true);
|
||||
if (target)
|
||||
{
|
||||
Talk(TextIds.SayCastDeepFreeze, target);
|
||||
DoCast(target, SpellIds.DeepFreeze);
|
||||
}
|
||||
_events.ScheduleEvent(Events.DeepFreeze, 35000, 0, Misc.PhaseThree);
|
||||
}
|
||||
break;
|
||||
case Events.ForgeJump:
|
||||
me.AttackStop();
|
||||
if (_events.IsInPhase(Misc.PhaseTwo))
|
||||
me.GetMotionMaster().MoveJump(Misc.northForgePos, 25.0f, 15.0f, Misc.PointForge);
|
||||
else if (_events.IsInPhase(Misc.PhaseThree))
|
||||
me.GetMotionMaster().MoveJump(Misc.southForgePos, 25.0f, 15.0f, Misc.PointForge);
|
||||
break;
|
||||
case Events.ResumeAttack:
|
||||
if (_events.IsInPhase(Misc.PhaseTwo))
|
||||
_events.ScheduleEvent(Events.ChillingWave, 5000, 0, Misc.PhaseTwo);
|
||||
else if (_events.IsInPhase(Misc.PhaseThree))
|
||||
_events.ScheduleEvent(Events.DeepFreeze, 10000, 0, Misc.PhaseThree);
|
||||
AttackStart(me.GetVictim());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
});
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
uint _permafrostStack;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_garfrost_permafrost : SpellScript
|
||||
{
|
||||
public spell_garfrost_permafrost()
|
||||
{
|
||||
prevented = false;
|
||||
}
|
||||
|
||||
void PreventHitByLoS(SpellMissInfo missInfo)
|
||||
{
|
||||
if (missInfo != SpellMissInfo.None)
|
||||
return;
|
||||
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
//Temporary Line of Sight Check
|
||||
List<GameObject> blockList = new List<GameObject>();
|
||||
caster.GetGameObjectListWithEntryInGrid(blockList, GameObjectIds.SaroniteRock, 100.0f);
|
||||
if (!blockList.Empty())
|
||||
{
|
||||
foreach (var obj in blockList)
|
||||
{
|
||||
if (!obj.IsInvisibleDueToDespawn())
|
||||
{
|
||||
if (obj.IsInBetween(caster, target, 4.0f))
|
||||
{
|
||||
prevented = true;
|
||||
target.ApplySpellImmune(GetSpellInfo().Id, SpellImmunity.Id, GetSpellInfo().Id, true);
|
||||
PreventHitDefaultEffect(0);
|
||||
PreventHitDefaultEffect(1);
|
||||
PreventHitDefaultEffect(2);
|
||||
PreventHitDamage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreImmunity()
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
{
|
||||
target.ApplySpellImmune(GetSpellInfo().Id, SpellImmunity.Id, GetSpellInfo().Id, false);
|
||||
if (prevented)
|
||||
PreventHitAura();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
BeforeHit.Add(new BeforeHitHandler(PreventHitByLoS));
|
||||
AfterHit.Add(new HitHandler(RestoreImmunity));
|
||||
}
|
||||
|
||||
bool prevented;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_doesnt_go_to_eleven : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_doesnt_go_to_eleven() : base("achievement_doesnt_go_to_eleven") { }
|
||||
|
||||
public override bool OnCheck(Player source, Unit target)
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
Creature garfrost = target.ToCreature();
|
||||
if (garfrost)
|
||||
if (garfrost.GetAI().GetData(Misc.AchievDoesntGoToEleven) <= 10)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,674 @@
|
||||
using System;
|
||||
using Game.Entities;
|
||||
using Game.Scripting;
|
||||
using Game.AI;
|
||||
using Framework.Constants;
|
||||
using Game.Maps;
|
||||
using Game.Spells;
|
||||
|
||||
namespace Scripts.Northrend.FrozenHalls.PitOfSaron.BossKrickAndIck
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint MightyKick = 69021; //Ick'S Spell
|
||||
public const uint ShadowBolt = 69028; //Krick'S Spell
|
||||
public const uint ToxicWaste = 69024; //Krick'S Spell
|
||||
public const uint ExplosiveBarrageKrick = 69012; //Special Spell 1
|
||||
public const uint ExplosiveBarrageIck = 69263; //Special Spell 1
|
||||
public const uint PoisonNova = 68989; //Special Spell 2
|
||||
public const uint Pursuit = 68987; //Special Spell 3
|
||||
|
||||
public const uint ExplosiveBarrageSummon = 69015;
|
||||
public const uint ExplodingOrb = 69017; //Visual On Exploding Orb
|
||||
public const uint AutoGrow = 69020; //Grow Effect On Exploding Orb
|
||||
public const uint HastyGrow = 44851; //Need To Check Growing Stacks
|
||||
public const uint ExplosiveBarrageDamage = 69019; //Damage Done By Orb While Exploding
|
||||
|
||||
public const uint Strangulating = 69413; //Krick'S Selfcast In Intro
|
||||
public const uint Suicide = 7;
|
||||
public const uint KrickKillCredit = 71308;
|
||||
public const uint NecromanticPower = 69753;
|
||||
}
|
||||
|
||||
struct TextIds
|
||||
{
|
||||
// Krick
|
||||
public const uint SayKrickAggro = 0;
|
||||
public const uint SayKrickSlay = 1;
|
||||
public const uint SayKrickBarrage1 = 2;
|
||||
public const uint SayKrickBarrage2 = 3;
|
||||
public const uint SayKrickPoisonNova = 4;
|
||||
public const uint SayKrickChase = 5;
|
||||
public const uint SayKrickOutro1 = 6;
|
||||
public const uint SayKrickOutro3 = 7;
|
||||
public const uint SayKrickOutro5 = 8;
|
||||
public const uint SayKrickOutro8 = 9;
|
||||
|
||||
// Ick
|
||||
public const uint SayIckPoisonNova = 0;
|
||||
public const uint SayIckChase1 = 1;
|
||||
|
||||
// Outro
|
||||
public const uint SayJaynaOutro2 = 0;
|
||||
public const uint SayJaynaOutro4 = 1;
|
||||
public const uint SayJaynaOutro10 = 2;
|
||||
public const uint SaySylvanasOutro2 = 0;
|
||||
public const uint SaySylvanasOutro4 = 1;
|
||||
public const uint SaySylvanasOutro10 = 2;
|
||||
public const uint SayTyrannusOutro7 = 1;
|
||||
public const uint SayTyrannusOutro9 = 2;
|
||||
}
|
||||
|
||||
struct Events
|
||||
{
|
||||
public const uint MightyKick = 1;
|
||||
public const uint ShadowBolt = 2;
|
||||
public const uint ToxicWaste = 3;
|
||||
public const uint Special = 4; //Special Spell Selection (One Of Event 5; 6 Or 7)
|
||||
public const uint Pursuit = 5;
|
||||
public const uint PoisonNova = 6;
|
||||
public const uint ExplosiveBarrage = 7;
|
||||
|
||||
// Krick Outro
|
||||
public const uint Outro1 = 8;
|
||||
public const uint Outro2 = 9;
|
||||
public const uint Outro3 = 10;
|
||||
public const uint Outro4 = 11;
|
||||
public const uint Outro5 = 12;
|
||||
public const uint Outro6 = 13;
|
||||
public const uint Outro7 = 14;
|
||||
public const uint Outro8 = 15;
|
||||
public const uint Outro9 = 16;
|
||||
public const uint Outro10 = 17;
|
||||
public const uint Outro11 = 18;
|
||||
public const uint Outro12 = 19;
|
||||
public const uint Outro13 = 20;
|
||||
public const uint OutroEnd = 21;
|
||||
}
|
||||
|
||||
enum KrickPhase
|
||||
{
|
||||
Combat = 1,
|
||||
Outro = 2
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const int ActionOutro = 1;
|
||||
|
||||
public const uint PointKrickIntro = 364770;
|
||||
public const uint PointKrickDeath = 364771;
|
||||
|
||||
public static Position[] outroPos =
|
||||
{
|
||||
new Position(828.9342f, 118.6247f, 509.5190f, 0.0000000f), // Krick's Outro Position
|
||||
new Position( 841.0100f, 196.2450f, 573.9640f, 0.2046099f), // Scourgelord Tyrannus Outro Position (Tele to...)
|
||||
new Position( 777.2274f, 119.5521f, 510.0363f, 6.0562930f), // Sylvanas / Jaine Outro Spawn Position (NPC_SYLVANAS_PART1)
|
||||
new Position(823.3984f, 114.4907f, 509.4899f, 0.0000000f), // Sylvanas / Jaine Outro Move Position (1)
|
||||
new Position( 835.5887f, 139.4345f, 530.9526f, 0.0000000f), // Tyrannus fly down Position (not sniffed)
|
||||
new Position( 828.9342f, 118.6247f, 514.5190f, 0.0000000f), // Krick's Choke Position
|
||||
new Position(828.9342f, 118.6247f, 509.4958f, 0.0000000f), // Kirck's Death Position
|
||||
new Position(914.4820f, 143.1602f, 633.3624f, 0.0000000f) // Tyrannus fly up (not sniffed)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
[Script]
|
||||
class boss_ick : BossAI
|
||||
{
|
||||
public boss_ick(Creature creature) : base(creature, DataTypes.Ick)
|
||||
{
|
||||
_tempThreat = 0;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_events.Reset();
|
||||
instance.SetBossState(DataTypes.Ick, EncounterState.NotStarted);
|
||||
}
|
||||
|
||||
Creature GetKrick()
|
||||
{
|
||||
return ObjectAccessor.GetCreature(me, instance.GetGuidData(DataTypes.Krick));
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
|
||||
Creature krick = GetKrick();
|
||||
if (krick)
|
||||
krick.GetAI().Talk(TextIds.SayKrickAggro);
|
||||
|
||||
_events.ScheduleEvent(Events.MightyKick, 20000);
|
||||
_events.ScheduleEvent(Events.ToxicWaste, 5000);
|
||||
_events.ScheduleEvent(Events.ShadowBolt, 10000);
|
||||
_events.ScheduleEvent(Events.Special, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35));
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
me.GetMotionMaster().Clear();
|
||||
base.EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Creature krick = GetKrick();
|
||||
if (krick)
|
||||
{
|
||||
Vehicle vehicle = me.GetVehicleKit();
|
||||
if (vehicle)
|
||||
vehicle.RemoveAllPassengers();
|
||||
if (krick.IsAIEnabled)
|
||||
krick.GetAI().DoAction(Misc.ActionOutro);
|
||||
}
|
||||
|
||||
instance.SetBossState(DataTypes.Ick, EncounterState.Done);
|
||||
}
|
||||
|
||||
public void SetTempThreat(float threat)
|
||||
{
|
||||
_tempThreat = threat;
|
||||
}
|
||||
|
||||
public void _ResetThreat(Unit target)
|
||||
{
|
||||
DoModifyThreatPercent(target, -100);
|
||||
me.AddThreat(target, _tempThreat);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!me.IsInCombat())
|
||||
return;
|
||||
|
||||
if (!me.GetVictim() && me.GetThreatManager().isThreatListEmpty())
|
||||
{
|
||||
EnterEvadeMode(EvadeReason.NoHostiles);
|
||||
return;
|
||||
}
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Events.ToxicWaste:
|
||||
{
|
||||
Creature krick = GetKrick();
|
||||
if (krick)
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
krick.CastSpell(target, SpellIds.ToxicWaste);
|
||||
_events.ScheduleEvent(Events.ToxicWaste, TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(10));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Events.ShadowBolt:
|
||||
{
|
||||
Creature krick = GetKrick();
|
||||
if (krick)
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 1);
|
||||
if (target)
|
||||
krick.CastSpell(target, SpellIds.ShadowBolt);
|
||||
_events.ScheduleEvent(Events.ShadowBolt, 15000);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case Events.MightyKick:
|
||||
DoCastVictim(SpellIds.MightyKick);
|
||||
_events.ScheduleEvent(Events.MightyKick, 25000);
|
||||
return;
|
||||
case Events.Special:
|
||||
//select one of these three special _events
|
||||
_events.ScheduleEvent(RandomHelper.RAND(Events.ExplosiveBarrage, Events.PoisonNova, Events.Pursuit), 1000);
|
||||
_events.ScheduleEvent(Events.Special, TimeSpan.FromSeconds(23), TimeSpan.FromSeconds(28));
|
||||
break;
|
||||
case Events.ExplosiveBarrage:
|
||||
{
|
||||
Creature krick = GetKrick();
|
||||
if (krick)
|
||||
{
|
||||
krick.GetAI().Talk(TextIds.SayKrickBarrage1);
|
||||
krick.GetAI().Talk(TextIds.SayKrickBarrage2);
|
||||
krick.CastSpell(krick, SpellIds.ExplosiveBarrageKrick, true);
|
||||
DoCast(me, SpellIds.ExplosiveBarrageIck);
|
||||
}
|
||||
_events.DelayEvents(20000);
|
||||
}
|
||||
break;
|
||||
case Events.PoisonNova:
|
||||
{
|
||||
Creature krick = GetKrick();
|
||||
if (krick)
|
||||
krick.GetAI().Talk(TextIds.SayKrickPoisonNova);
|
||||
|
||||
Talk(TextIds.SayIckPoisonNova);
|
||||
DoCast(me, SpellIds.PoisonNova);
|
||||
}
|
||||
break;
|
||||
case Events.Pursuit:
|
||||
{
|
||||
Creature krick = GetKrick();
|
||||
if (krick)
|
||||
krick.GetAI().Talk(TextIds.SayKrickChase);
|
||||
DoCast(me, SpellIds.Pursuit);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
});
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
float _tempThreat;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_krick : ScriptedAI
|
||||
{
|
||||
public boss_krick(Creature creature) : base(creature)
|
||||
{
|
||||
_instanceScript = creature.GetInstanceScript();
|
||||
_summons = new SummonList(creature);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_phase = KrickPhase.Combat;
|
||||
_outroNpcGUID.Clear();
|
||||
_tyrannusGUID.Clear();
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_events.Reset();
|
||||
Initialize();
|
||||
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
}
|
||||
|
||||
Creature GetIck()
|
||||
{
|
||||
return ObjectAccessor.GetCreature(me, _instanceScript.GetGuidData(DataTypes.Ick));
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
if (victim.IsPlayer())
|
||||
Talk(TextIds.SayKrickSlay);
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
_summons.Summon(summon);
|
||||
if (summon.GetEntry() == CreatureIds.ExplodingOrb)
|
||||
{
|
||||
summon.CastSpell(summon, SpellIds.ExplodingOrb, true);
|
||||
summon.CastSpell(summon, SpellIds.AutoGrow, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void DoAction(int actionId)
|
||||
{
|
||||
if (actionId == Misc.ActionOutro)
|
||||
{
|
||||
Creature tyrannusPtr = ObjectAccessor.GetCreature(me, _instanceScript.GetGuidData(DataTypes.TyrannusEvent));
|
||||
if (tyrannusPtr)
|
||||
tyrannusPtr.NearTeleportTo(Misc.outroPos[1].GetPositionX(), Misc.outroPos[1].GetPositionY(), Misc.outroPos[1].GetPositionZ(), Misc.outroPos[1].GetOrientation());
|
||||
else
|
||||
tyrannusPtr = me.SummonCreature(CreatureIds.TyrannusEvents, Misc.outroPos[1], TempSummonType.ManualDespawn);
|
||||
|
||||
tyrannusPtr.SetCanFly(true);
|
||||
me.GetMotionMaster().MovePoint(Misc.PointKrickIntro, Misc.outroPos[0].GetPositionX(), Misc.outroPos[0].GetPositionY(), Misc.outroPos[0].GetPositionZ());
|
||||
tyrannusPtr.SetFacingToObject(me);
|
||||
}
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (type != MovementGeneratorType.Point || id != Misc.PointKrickIntro)
|
||||
return;
|
||||
|
||||
Talk(TextIds.SayKrickOutro1);
|
||||
_phase = KrickPhase.Outro;
|
||||
_events.Reset();
|
||||
_events.ScheduleEvent(Events.Outro1, 1000);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (_phase != KrickPhase.Outro)
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Events.Outro1:
|
||||
{
|
||||
Creature temp = ObjectAccessor.GetCreature(me, _instanceScript.GetGuidData(DataTypes.JainaSylvanas1));
|
||||
if (temp)
|
||||
temp.DespawnOrUnsummon();
|
||||
|
||||
Creature jainaOrSylvanas = null;
|
||||
if (_instanceScript.GetData(DataTypes.TeamInInstance) == (uint)Team.Alliance)
|
||||
jainaOrSylvanas = me.SummonCreature(CreatureIds.JainaPart1, Misc.outroPos[2], TempSummonType.ManualDespawn);
|
||||
else
|
||||
jainaOrSylvanas = me.SummonCreature(CreatureIds.SylvanasPart1, Misc.outroPos[2], TempSummonType.ManualDespawn);
|
||||
|
||||
if (jainaOrSylvanas)
|
||||
{
|
||||
jainaOrSylvanas.GetMotionMaster().MovePoint(0, Misc.outroPos[3]);
|
||||
_outroNpcGUID = jainaOrSylvanas.GetGUID();
|
||||
}
|
||||
_events.ScheduleEvent(Events.Outro2, 6000);
|
||||
break;
|
||||
}
|
||||
case Events.Outro2:
|
||||
{
|
||||
Creature jainaOrSylvanas = ObjectAccessor.GetCreature(me, _outroNpcGUID);
|
||||
if (jainaOrSylvanas)
|
||||
{
|
||||
jainaOrSylvanas.SetFacingToObject(me);
|
||||
me.SetFacingToObject(jainaOrSylvanas);
|
||||
if (_instanceScript.GetData(DataTypes.TeamInInstance) == (uint)Team.Alliance)
|
||||
jainaOrSylvanas.GetAI().Talk(TextIds.SayJaynaOutro2);
|
||||
else
|
||||
jainaOrSylvanas.GetAI().Talk(TextIds.SaySylvanasOutro2);
|
||||
}
|
||||
_events.ScheduleEvent(Events.Outro3, 5000);
|
||||
}
|
||||
break;
|
||||
case Events.Outro3:
|
||||
Talk(TextIds.SayKrickOutro3);
|
||||
_events.ScheduleEvent(Events.Outro4, 18000);
|
||||
break;
|
||||
case Events.Outro4:
|
||||
{
|
||||
Creature jainaOrSylvanas = ObjectAccessor.GetCreature(me, _outroNpcGUID);
|
||||
if (jainaOrSylvanas)
|
||||
{
|
||||
if (_instanceScript.GetData(DataTypes.TeamInInstance) == (uint)Team.Alliance)
|
||||
jainaOrSylvanas.GetAI().Talk(TextIds.SayJaynaOutro4);
|
||||
else
|
||||
jainaOrSylvanas.GetAI().Talk(TextIds.SaySylvanasOutro4);
|
||||
}
|
||||
_events.ScheduleEvent(Events.Outro5, 5000);
|
||||
}
|
||||
break;
|
||||
case Events.Outro5:
|
||||
Talk(TextIds.SayKrickOutro5);
|
||||
_events.ScheduleEvent(Events.Outro6, 1000);
|
||||
break;
|
||||
case Events.Outro6:
|
||||
{
|
||||
Creature tyrannus = ObjectAccessor.GetCreature(me, _instanceScript.GetGuidData(DataTypes.TyrannusEvent));
|
||||
if (tyrannus)
|
||||
{
|
||||
tyrannus.SetSpeedRate(UnitMoveType.Flight, 3.5f);
|
||||
tyrannus.GetMotionMaster().MovePoint(1, Misc.outroPos[4]);
|
||||
_tyrannusGUID = tyrannus.GetGUID();
|
||||
}
|
||||
_events.ScheduleEvent(Events.Outro7, 5000);
|
||||
}
|
||||
break;
|
||||
case Events.Outro7:
|
||||
{
|
||||
Creature tyrannus = ObjectAccessor.GetCreature(me, _tyrannusGUID);
|
||||
if (tyrannus)
|
||||
tyrannus.GetAI().Talk(TextIds.SayTyrannusOutro7);
|
||||
_events.ScheduleEvent(Events.Outro8, 5000);
|
||||
}
|
||||
break;
|
||||
case Events.Outro8:
|
||||
//! HACK: Creature's can't have MOVEMENTFLAG_FLYING
|
||||
me.AddUnitMovementFlag(MovementFlag.Flying);
|
||||
me.GetMotionMaster().MovePoint(0, Misc.outroPos[5]);
|
||||
DoCast(me, SpellIds.Strangulating);
|
||||
_events.ScheduleEvent(Events.Outro9, 2000);
|
||||
break;
|
||||
case Events.Outro9:
|
||||
{
|
||||
Talk(TextIds.SayKrickOutro8);
|
||||
/// @todo Tyrannus starts killing Krick.
|
||||
// there shall be some visual spell effect
|
||||
Creature tyrannus = ObjectAccessor.GetCreature(me, _tyrannusGUID);
|
||||
if (tyrannus)
|
||||
tyrannus.CastSpell(me, SpellIds.NecromanticPower, true); //not sure if it's the right spell :/
|
||||
_events.ScheduleEvent(Events.Outro10, 1000);
|
||||
}
|
||||
break;
|
||||
case Events.Outro10:
|
||||
//! HACK: Creature's can't have MOVEMENTFLAG_FLYING
|
||||
me.RemoveUnitMovementFlag(MovementFlag.Flying);
|
||||
me.AddUnitMovementFlag(MovementFlag.FallingFar);
|
||||
me.GetMotionMaster().MovePoint(0, Misc.outroPos[6]);
|
||||
_events.ScheduleEvent(Events.Outro11, 2000);
|
||||
break;
|
||||
case Events.Outro11:
|
||||
DoCast(me, SpellIds.KrickKillCredit); // don't really know if we need it
|
||||
me.SetStandState(UnitStandStateType.Dead);
|
||||
me.SetHealth(0);
|
||||
_events.ScheduleEvent(Events.Outro12, 3000);
|
||||
break;
|
||||
case Events.Outro12:
|
||||
{
|
||||
Creature tyrannus = ObjectAccessor.GetCreature(me, _tyrannusGUID);
|
||||
if (tyrannus)
|
||||
tyrannus.GetAI().Talk(TextIds.SayTyrannusOutro9);
|
||||
_events.ScheduleEvent(Events.Outro13, 2000);
|
||||
}
|
||||
break;
|
||||
case Events.Outro13:
|
||||
{
|
||||
Creature jainaOrSylvanas = ObjectAccessor.GetCreature(me, _outroNpcGUID);
|
||||
if (jainaOrSylvanas)
|
||||
{
|
||||
if (_instanceScript.GetData(DataTypes.TeamInInstance) == (uint)Team.Alliance)
|
||||
jainaOrSylvanas.GetAI().Talk(TextIds.SayJaynaOutro10);
|
||||
else
|
||||
jainaOrSylvanas.GetAI().Talk(TextIds.SaySylvanasOutro10);
|
||||
}
|
||||
// End of OUTRO. for now...
|
||||
_events.ScheduleEvent(Events.OutroEnd, 3000);
|
||||
|
||||
Creature tyrannus = ObjectAccessor.GetCreature(me, _tyrannusGUID);
|
||||
if (tyrannus)
|
||||
tyrannus.GetMotionMaster().MovePoint(0, Misc.outroPos[7]);
|
||||
}
|
||||
break;
|
||||
case Events.OutroEnd:
|
||||
{
|
||||
Creature tyrannus = ObjectAccessor.GetCreature(me, _tyrannusGUID);
|
||||
if (tyrannus)
|
||||
tyrannus.DespawnOrUnsummon();
|
||||
|
||||
me.DisappearAndDie();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
InstanceScript _instanceScript;
|
||||
SummonList _summons;
|
||||
|
||||
KrickPhase _phase;
|
||||
ObjectGuid _outroNpcGUID;
|
||||
ObjectGuid _tyrannusGUID;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_krick_explosive_barrage : AuraScript
|
||||
{
|
||||
void HandlePeriodicTick(AuraEffect aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
Unit caster = GetCaster();
|
||||
if (caster)
|
||||
{
|
||||
if (caster.IsCreature())
|
||||
{
|
||||
var players = caster.GetMap().GetPlayers();
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player)
|
||||
if (player.IsWithinDist(caster, 60.0f)) // don't know correct range
|
||||
caster.CastSpell(player, SpellIds.ExplosiveBarrageSummon, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(HandlePeriodicTick, 0, AuraType.PeriodicTriggerSpell));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_ick_explosive_barrage : AuraScript
|
||||
{
|
||||
void HandleEffectApply(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
if (caster)
|
||||
if (caster.IsCreature())
|
||||
caster.GetMotionMaster().MoveIdle();
|
||||
}
|
||||
|
||||
void HandleEffectRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
if (caster)
|
||||
{
|
||||
if (caster.IsCreature())
|
||||
{
|
||||
caster.GetMotionMaster().Clear();
|
||||
caster.GetMotionMaster().MoveChase(caster.GetVictim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
AfterEffectApply.Add(new EffectApplyHandler(HandleEffectApply, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
|
||||
AfterEffectRemove.Add(new EffectApplyHandler(HandleEffectRemove, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_exploding_orb_hasty_grow : AuraScript
|
||||
{
|
||||
void OnStackChange(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
if (GetStackAmount() == 15)
|
||||
{
|
||||
Unit target = GetTarget(); // store target because aura gets removed
|
||||
target.CastSpell(target, SpellIds.ExplosiveBarrageDamage, false);
|
||||
target.RemoveAurasDueToSpell(SpellIds.HastyGrow);
|
||||
target.RemoveAurasDueToSpell(SpellIds.AutoGrow);
|
||||
target.RemoveAurasDueToSpell(SpellIds.ExplodingOrb);
|
||||
|
||||
Creature creature = target.ToCreature();
|
||||
if (creature)
|
||||
creature.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
AfterEffectApply.Add(new EffectApplyHandler(OnStackChange, 0, AuraType.ModScale, AuraEffectHandleModes.Reapply));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_krick_pursuit : SpellScript
|
||||
{
|
||||
void HandleScriptEffect(uint effIndex)
|
||||
{
|
||||
if (GetCaster())
|
||||
{
|
||||
Creature ick = GetCaster().ToCreature();
|
||||
if (ick)
|
||||
{
|
||||
Unit target = ick.GetAI().SelectTarget(SelectAggroTarget.Random, 0, 200.0f, true);
|
||||
if (target)
|
||||
{
|
||||
ick.GetAI().Talk(TextIds.SayIckChase1, target);
|
||||
ick.AddAura(GetSpellInfo().Id, target);
|
||||
ick.GetAI<boss_ick>().SetTempThreat(ick.GetThreatManager().getThreat(target));
|
||||
ick.AddThreat(target, GetEffectValue());
|
||||
target.AddThreat(ick, GetEffectValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 1, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_krick_pursuit_AuraScript : AuraScript
|
||||
{
|
||||
void HandleExtraEffect(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
if (caster)
|
||||
{
|
||||
Creature creCaster = caster.ToCreature();
|
||||
if (creCaster)
|
||||
creCaster.GetAI<boss_ick>()._ResetThreat(GetTarget());
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
AfterEffectRemove.Add(new EffectApplyHandler(HandleExtraEffect, 0, AuraType.Dummy, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_krick_pursuit_confusion : AuraScript
|
||||
{
|
||||
void OnApply(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
GetTarget().ApplySpellImmune(0, SpellImmunity.State, AuraType.ModTaunt, true);
|
||||
GetTarget().ApplySpellImmune(0, SpellImmunity.Effect, SpellEffectName.AttackMe, true);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
GetTarget().ApplySpellImmune(0, SpellImmunity.State, AuraType.ModTaunt, false);
|
||||
GetTarget().ApplySpellImmune(0, SpellImmunity.Effect, SpellEffectName.AttackMe, false);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectApply.Add(new EffectApplyHandler(OnApply, 2, AuraType.Linked, AuraEffectHandleModes.Real));
|
||||
OnEffectRemove.Add(new EffectApplyHandler(OnRemove, 2, AuraType.Linked, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,344 @@
|
||||
using System.Collections.Generic;
|
||||
using Game.Entities;
|
||||
using Game.Scripting;
|
||||
using Game.Maps;
|
||||
using Framework.Constants;
|
||||
using Framework.Dynamic;
|
||||
|
||||
namespace Scripts.Northrend.FrozenHalls.PitOfSaron
|
||||
{
|
||||
struct Misc
|
||||
{
|
||||
// positions for Martin Victus (37591) and Gorkun Ironskull (37592)
|
||||
public static Position SlaveLeaderPos = new Position(689.7158f, -104.8736f, 513.7360f, 0.0f);
|
||||
// position for Jaina and Sylvanas
|
||||
public static Position EventLeaderPos2 = new Position(1054.368f, 107.14620f, 628.4467f, 0.0f);
|
||||
|
||||
public static DoorData[] Doors =
|
||||
{
|
||||
new DoorData(GameObjectIds.IceWall, DataTypes.Garfrost, DoorType.Passage),
|
||||
new DoorData(GameObjectIds.IceWall, DataTypes.Ick, DoorType.Passage),
|
||||
new DoorData(GameObjectIds.HallsOfReflectionPortcullis, DataTypes.Tyrannus, DoorType.Passage),
|
||||
};
|
||||
}
|
||||
|
||||
class instance_pit_of_saron : InstanceMapScript
|
||||
{
|
||||
public instance_pit_of_saron() : base(nameof(instance_pit_of_saron), 658) { }
|
||||
|
||||
class instance_pit_of_saron_InstanceScript : InstanceScript
|
||||
{
|
||||
public instance_pit_of_saron_InstanceScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("POS");
|
||||
SetBossNumber(3);
|
||||
LoadDoorData(Misc.Doors);
|
||||
_teamInInstance = 0;
|
||||
_cavernActive = 0;
|
||||
_shardsHit = 0;
|
||||
}
|
||||
|
||||
public override void OnPlayerEnter(Player player)
|
||||
{
|
||||
if (_teamInInstance == 0)
|
||||
_teamInInstance = player.GetTeam();
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
if (_teamInInstance == 0)
|
||||
{
|
||||
var players = instance.GetPlayers();
|
||||
if (!players.Empty())
|
||||
{
|
||||
Player player = players[0];
|
||||
if (player)
|
||||
_teamInInstance = player.GetTeam();
|
||||
}
|
||||
}
|
||||
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
case CreatureIds.Garfrost:
|
||||
_garfrostGUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.Krick:
|
||||
_krickGUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.Ick:
|
||||
_ickGUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.Tyrannus:
|
||||
_tyrannusGUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.Rimefang:
|
||||
_rimefangGUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.TyrannusEvents:
|
||||
_tyrannusEventGUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.SylvanasPart1:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.JainaPart1);
|
||||
_jainaOrSylvanas1GUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.SylvanasPart2:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.JainaPart2);
|
||||
_jainaOrSylvanas2GUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.Kilara:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.Elandra);
|
||||
break;
|
||||
case CreatureIds.Koralen:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.Korlaen);
|
||||
break;
|
||||
case CreatureIds.Champion1Horde:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.Champion1Alliance);
|
||||
break;
|
||||
case CreatureIds.Champion2Horde:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.Champion2Alliance);
|
||||
break;
|
||||
case CreatureIds.Champion3Horde: // No 3rd set for Alliance?
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.Champion2Alliance);
|
||||
break;
|
||||
case CreatureIds.HordeSlave1:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.AllianceSlave1);
|
||||
break;
|
||||
case CreatureIds.HordeSlave2:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.AllianceSlave2);
|
||||
break;
|
||||
case CreatureIds.HordeSlave3:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.AllianceSlave3);
|
||||
break;
|
||||
case CreatureIds.HordeSlave4:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.AllianceSlave4);
|
||||
break;
|
||||
case CreatureIds.FreedSlave1Horde:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.FreedSlave1Alliance);
|
||||
break;
|
||||
case CreatureIds.FreedSlave2Horde:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.FreedSlave2Alliance);
|
||||
break;
|
||||
case CreatureIds.FreedSlave3Horde:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.FreedSlave3Alliance);
|
||||
break;
|
||||
case CreatureIds.RescuedSlaveHorde:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.RescuedSlaveAlliance);
|
||||
break;
|
||||
case CreatureIds.MartinVictus1:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.MartinVictus1);
|
||||
break;
|
||||
case CreatureIds.MartinVictus2:
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.MartinVictus2);
|
||||
break;
|
||||
case CreatureIds.CavernEventTrigger:
|
||||
_cavernstriggersVector.Add(creature.GetGUID());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectCreate(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GameObjectIds.IceWall:
|
||||
case GameObjectIds.HallsOfReflectionPortcullis:
|
||||
AddDoor(go, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectRemove(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GameObjectIds.IceWall:
|
||||
case GameObjectIds.HallsOfReflectionPortcullis:
|
||||
AddDoor(go, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SetBossState(uint type, EncounterState state)
|
||||
{
|
||||
if (!base.SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.Garfrost:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
Creature summoner = instance.GetCreature(_garfrostGUID);
|
||||
if (summoner)
|
||||
{
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
summoner.SummonCreature(CreatureIds.MartinVictus1, Misc.SlaveLeaderPos, TempSummonType.ManualDespawn);
|
||||
else
|
||||
summoner.SummonCreature(CreatureIds.GorkunIronskull2, Misc.SlaveLeaderPos, TempSummonType.ManualDespawn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DataTypes.Tyrannus:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
Creature summoner = instance.GetCreature(_tyrannusGUID);
|
||||
if (summoner)
|
||||
{
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
summoner.SummonCreature(CreatureIds.JainaPart2, Misc.EventLeaderPos2, TempSummonType.ManualDespawn);
|
||||
else
|
||||
summoner.SummonCreature(CreatureIds.SylvanasPart2, Misc.EventLeaderPos2, TempSummonType.ManualDespawn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.TeamInInstance:
|
||||
return (uint)_teamInInstance;
|
||||
case DataTypes.IceShardsHit:
|
||||
return _shardsHit;
|
||||
case DataTypes.CavernActive:
|
||||
return _cavernActive;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void SetData(uint type, uint data)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.IceShardsHit:
|
||||
_shardsHit = (byte)data;
|
||||
break;
|
||||
case DataTypes.CavernActive:
|
||||
if (data != 0)
|
||||
{
|
||||
_cavernActive = (byte)data;
|
||||
HandleCavernEventTrigger(true);
|
||||
}
|
||||
else
|
||||
HandleCavernEventTrigger(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGuidData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.Garfrost:
|
||||
return _garfrostGUID;
|
||||
case DataTypes.Krick:
|
||||
return _krickGUID;
|
||||
case DataTypes.Ick:
|
||||
return _ickGUID;
|
||||
case DataTypes.Tyrannus:
|
||||
return _tyrannusGUID;
|
||||
case DataTypes.Rimefang:
|
||||
return _rimefangGUID;
|
||||
case DataTypes.TyrannusEvent:
|
||||
return _tyrannusEventGUID;
|
||||
case DataTypes.JainaSylvanas1:
|
||||
return _jainaOrSylvanas1GUID;
|
||||
case DataTypes.JainaSylvanas2:
|
||||
return _jainaOrSylvanas2GUID;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
void HandleCavernEventTrigger(bool activate)
|
||||
{
|
||||
foreach (ObjectGuid guid in _cavernstriggersVector)
|
||||
{
|
||||
Creature trigger = instance.GetCreature(guid);
|
||||
if (trigger)
|
||||
{
|
||||
if (activate)
|
||||
trigger.m_Events.AddEvent(new ScheduledIcicleSummons(trigger), trigger.m_Events.CalculateTime(1000));
|
||||
else
|
||||
trigger.m_Events.KillAllEvents(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid _garfrostGUID;
|
||||
ObjectGuid _krickGUID;
|
||||
ObjectGuid _ickGUID;
|
||||
ObjectGuid _tyrannusGUID;
|
||||
ObjectGuid _rimefangGUID;
|
||||
|
||||
ObjectGuid _tyrannusEventGUID;
|
||||
ObjectGuid _jainaOrSylvanas1GUID;
|
||||
ObjectGuid _jainaOrSylvanas2GUID;
|
||||
List<ObjectGuid> _cavernstriggersVector = new List<ObjectGuid>();
|
||||
|
||||
Team _teamInInstance;
|
||||
byte _shardsHit;
|
||||
byte _cavernActive;
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_pit_of_saron_InstanceScript(map);
|
||||
}
|
||||
}
|
||||
|
||||
class ScheduledIcicleSummons : BasicEvent
|
||||
{
|
||||
public ScheduledIcicleSummons(Creature trigger)
|
||||
{
|
||||
_trigger = trigger;
|
||||
}
|
||||
|
||||
public override bool Execute(ulong time, uint diff)
|
||||
{
|
||||
if (RandomHelper.randChance(12))
|
||||
{
|
||||
_trigger.CastSpell(_trigger, SpellIds.IcicleSummon, true);
|
||||
_trigger.m_Events.AddEvent(new ScheduledIcicleSummons(_trigger), _trigger.m_Events.CalculateTime(RandomHelper.URand(20000, 35000)));
|
||||
}
|
||||
else
|
||||
_trigger.m_Events.AddEvent(new ScheduledIcicleSummons(_trigger), _trigger.m_Events.CalculateTime(RandomHelper.URand(1000, 20000)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Creature _trigger;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
using System;
|
||||
using Game.Entities;
|
||||
using Game.AI;
|
||||
using Game.Spells;
|
||||
using Game.DataStorage;
|
||||
using Game.Scripting;
|
||||
using Framework.Constants;
|
||||
using Game.Maps;
|
||||
|
||||
namespace Scripts.Northrend.FrozenHalls.PitOfSaron
|
||||
{
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayTyrannusCavernEntrance = 3;
|
||||
}
|
||||
|
||||
struct DataTypes
|
||||
{
|
||||
// Encounter States And Guids
|
||||
public const uint Garfrost = 0;
|
||||
public const uint Ick = 1;
|
||||
public const uint Tyrannus = 2;
|
||||
|
||||
// Guids
|
||||
public const uint Rimefang = 3;
|
||||
public const uint Krick = 4;
|
||||
public const uint JainaSylvanas1 = 5; // Guid Of Either Jaina Or Sylvanas Part 1; Depending On Team; As It'S The Same Spawn.
|
||||
public const uint JainaSylvanas2 = 6; // Guid Of Either Jaina Or Sylvanas Part 2; Depending On Team; As It'S The Same Spawn.
|
||||
public const uint TyrannusEvent = 7;
|
||||
public const uint TeamInInstance = 8;
|
||||
public const uint IceShardsHit = 9;
|
||||
public const uint CavernActive = 10;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
public const uint Garfrost = 36494;
|
||||
public const uint Krick = 36477;
|
||||
public const uint Ick = 36476;
|
||||
public const uint Tyrannus = 36658;
|
||||
public const uint Rimefang = 36661;
|
||||
|
||||
public const uint TyrannusEvents = 36794;
|
||||
public const uint SylvanasPart1 = 36990;
|
||||
public const uint SylvanasPart2 = 38189;
|
||||
public const uint JainaPart1 = 36993;
|
||||
public const uint JainaPart2 = 38188;
|
||||
public const uint Kilara = 37583;
|
||||
public const uint Elandra = 37774;
|
||||
public const uint Koralen = 37779;
|
||||
public const uint Korlaen = 37582;
|
||||
public const uint Champion1Horde = 37584;
|
||||
public const uint Champion2Horde = 37587;
|
||||
public const uint Champion3Horde = 37588;
|
||||
public const uint Champion1Alliance = 37496;
|
||||
public const uint Champion2Alliance = 37497;
|
||||
|
||||
public const uint HordeSlave1 = 36770;
|
||||
public const uint HordeSlave2 = 36771;
|
||||
public const uint HordeSlave3 = 36772;
|
||||
public const uint HordeSlave4 = 36773;
|
||||
public const uint AllianceSlave1 = 36764;
|
||||
public const uint AllianceSlave2 = 36765;
|
||||
public const uint AllianceSlave3 = 36766;
|
||||
public const uint AllianceSlave4 = 36767;
|
||||
public const uint FreedSlave1Alliance = 37575;
|
||||
public const uint FreedSlave2Alliance = 37572;
|
||||
public const uint FreedSlave3Alliance = 37576;
|
||||
public const uint FreedSlave1Horde = 37579;
|
||||
public const uint FreedSlave2Horde = 37578;
|
||||
public const uint FreedSlave3Horde = 37577;
|
||||
public const uint RescuedSlaveAlliance = 36888;
|
||||
public const uint RescuedSlaveHorde = 36889;
|
||||
public const uint MartinVictus1 = 37591;
|
||||
public const uint MartinVictus2 = 37580;
|
||||
public const uint GorkunIronskull1 = 37581;
|
||||
public const uint GorkunIronskull2 = 37592;
|
||||
|
||||
public const uint ForgemasterStalker = 36495;
|
||||
public const uint ExplodingOrb = 36610;
|
||||
public const uint YmirjarDeathbringer = 36892;
|
||||
public const uint IcyBlast = 36731;
|
||||
public const uint CavernEventTrigger = 32780;
|
||||
}
|
||||
|
||||
struct GameObjectIds
|
||||
{
|
||||
public const uint SaroniteRock = 196485;
|
||||
public const uint IceWall = 201885;
|
||||
public const uint HallsOfReflectionPortcullis = 201848;
|
||||
}
|
||||
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint IcicleSummon = 69424;
|
||||
public const uint IcicleFallTrigger = 69426;
|
||||
public const uint IcicleFallVisual = 69428;
|
||||
public const uint AchievDontLookUpCredit = 72845;
|
||||
|
||||
public const uint Fireball = 69583; //Ymirjar Flamebearer
|
||||
public const uint Hellfire = 69586;
|
||||
public const uint TacticalBlink = 69584;
|
||||
public const uint FrostBreath = 69527; //Iceborn Proto-Drake
|
||||
public const uint LeapingFaceMaul = 69504; // Geist Ambusher
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_ymirjar_flamebearer : ScriptedAI
|
||||
{
|
||||
public npc_ymirjar_flamebearer(Creature creature) : base(creature)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(4), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.Fireball);
|
||||
task.Repeat(TimeSpan.FromSeconds(5));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.TacticalBlink);
|
||||
DoCast(me, SpellIds.Hellfire);
|
||||
task.Repeat(TimeSpan.FromSeconds(12));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_iceborn_protodrake : ScriptedAI
|
||||
{
|
||||
public npc_iceborn_protodrake(Creature creature) : base(creature) { }
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
Vehicle vehicle = me.GetVehicleKit();
|
||||
if (vehicle)
|
||||
vehicle.RemoveAllPassengers();
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.FrostBreath);
|
||||
task.Repeat(TimeSpan.FromSeconds(10));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_geist_ambusher : ScriptedAI
|
||||
{
|
||||
public npc_geist_ambusher(Creature creature) : base(creature) { }
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
if (who.GetTypeId() != TypeId.Player)
|
||||
return;
|
||||
|
||||
// the max range is determined by aggro range
|
||||
if (me.GetDistance(who) > 5.0f)
|
||||
DoCast(who, SpellIds.LeapingFaceMaul);
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(9), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 5.0f, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.LeapingFaceMaul);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(9), TimeSpan.FromSeconds(14));
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_trash_npc_glacial_strike : AuraScript
|
||||
{
|
||||
void PeriodicTick(AuraEffect aurEff)
|
||||
{
|
||||
if (GetTarget().IsFullHealth())
|
||||
{
|
||||
GetTarget().RemoveAura(GetId(), ObjectGuid.Empty, 0, AuraRemoveMode.EnemySpell);
|
||||
PreventDefaultAction();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(PeriodicTick, 2, AuraType.PeriodicDamagePercent));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pit_of_saron_icicle : PassiveAI
|
||||
{
|
||||
public npc_pit_of_saron_icicle(Creature creature) : base(creature)
|
||||
{
|
||||
me.SetDisplayId(me.GetCreatureTemplate().ModelId1);
|
||||
}
|
||||
|
||||
public override void IsSummonedBy(Unit summoner)
|
||||
{
|
||||
_summonerGUID = summoner.GetGUID();
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromMilliseconds(3650), task =>
|
||||
{
|
||||
DoCastSelf(SpellIds.IcicleFallTrigger, true);
|
||||
DoCastSelf(SpellIds.IcicleFallVisual);
|
||||
|
||||
Unit caster = Global.ObjAccessor.GetUnit(me, _summonerGUID);
|
||||
if (caster)
|
||||
caster.RemoveDynObject(SpellIds.IcicleSummon);
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
ObjectGuid _summonerGUID;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_pos_ice_shards : SpellScript
|
||||
{
|
||||
void HandleScriptEffect(uint effIndex)
|
||||
{
|
||||
if (GetHitPlayer())
|
||||
GetCaster().GetInstanceScript().SetData(DataTypes.CavernActive, 1);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 0, SpellEffectName.SchoolDamage));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class at_pit_cavern_entrance : AreaTriggerScript
|
||||
{
|
||||
public at_pit_cavern_entrance() : base("at_pit_cavern_entrance") { }
|
||||
|
||||
public override bool OnTrigger(Player player, AreaTriggerRecord areaTrigger, bool entered)
|
||||
{
|
||||
if (!entered)
|
||||
return true;
|
||||
|
||||
InstanceScript instance = player.GetInstanceScript();
|
||||
if (instance != null)
|
||||
{
|
||||
if (instance.GetData(DataTypes.CavernActive) != 0)
|
||||
return true;
|
||||
|
||||
instance.SetData(DataTypes.CavernActive, 1);
|
||||
|
||||
Creature tyrannus = ObjectAccessor.GetCreature(player, instance.GetGuidData(DataTypes.TyrannusEvent));
|
||||
if (tyrannus)
|
||||
tyrannus.GetAI().Talk(TextIds.SayTyrannusCavernEntrance);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class at_pit_cavern_end : AreaTriggerScript
|
||||
{
|
||||
public at_pit_cavern_end() : base("at_pit_cavern_end") { }
|
||||
|
||||
public override bool OnTrigger(Player player, AreaTriggerRecord areaTrigger, bool entered)
|
||||
{
|
||||
if (!entered)
|
||||
return true;
|
||||
|
||||
InstanceScript instance = player.GetInstanceScript();
|
||||
if (instance != null)
|
||||
{
|
||||
instance.SetData(DataTypes.CavernActive, 0);
|
||||
|
||||
if (instance.GetData(DataTypes.IceShardsHit) == 0)
|
||||
instance.DoUpdateCriteria(CriteriaTypes.BeSpellTarget, SpellIds.AchievDontLookUpCredit, 0, player);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* 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;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend.Gundrak.DrakkariColossus
|
||||
{
|
||||
struct TextIds
|
||||
{
|
||||
// Drakkari Elemental
|
||||
public const uint EmoteMojo = 0;
|
||||
public const uint EmoteActivateAltar = 1;
|
||||
}
|
||||
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint Emerge = 54850;
|
||||
public const uint ElementalSpawnEffect = 54888;
|
||||
public const uint MojoVolley = 54849;
|
||||
public const uint SurgeVisual = 54827;
|
||||
public const uint Merge = 54878;
|
||||
public const uint MightyBlow = 54719;
|
||||
public const uint Surge = 54801;
|
||||
public const uint FreezeAnim = 16245;
|
||||
public const uint MojoPuddle = 55627;
|
||||
public const uint MojoWave = 55626;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint EventMightyBlow = 1;
|
||||
public const uint EventSurge = 1;
|
||||
|
||||
public const int ActionSummonElemental = 1;
|
||||
public const int ActionFreezeColossus = 2;
|
||||
public const int ActionUnfreezeColossus = 3;
|
||||
public const int ActionReturnToColossus = 1;
|
||||
|
||||
public const byte ColossusPhaseNormal = 1;
|
||||
public const byte ColossusPhaseFirstElementalSummon = 2;
|
||||
public const byte ColossusPhaseSecondElementalSummon = 3;
|
||||
|
||||
public const uint DataColossusPhase = 1;
|
||||
public const uint DataIntroDone = 2;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_drakkari_colossus : BossAI
|
||||
{
|
||||
public boss_drakkari_colossus(Creature creature) : base(creature, GDDataTypes.DrakkariColossus)
|
||||
{
|
||||
Initialize();
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
introDone = false;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
phase = Misc.ColossusPhaseNormal;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
|
||||
if (GetData(Misc.DataIntroDone) != 0)
|
||||
{
|
||||
me.SetReactState(ReactStates.Aggressive);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.ImmuneToPc);
|
||||
me.RemoveAura(SpellIds.FreezeAnim);
|
||||
}
|
||||
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.MightyBlow);
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15));
|
||||
});
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
me.RemoveAura(SpellIds.FreezeAnim);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case Misc.ActionSummonElemental:
|
||||
DoCast(SpellIds.Emerge);
|
||||
break;
|
||||
case Misc.ActionFreezeColossus:
|
||||
me.GetMotionMaster().Clear();
|
||||
me.GetMotionMaster().MoveIdle();
|
||||
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.ImmuneToPc);
|
||||
DoCast(me, SpellIds.FreezeAnim);
|
||||
break;
|
||||
case Misc.ActionUnfreezeColossus:
|
||||
if (me.GetReactState() == ReactStates.Aggressive)
|
||||
return;
|
||||
|
||||
me.SetReactState(ReactStates.Aggressive);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.ImmuneToPc);
|
||||
me.RemoveAura(SpellIds.FreezeAnim);
|
||||
|
||||
me.SetInCombatWithZone();
|
||||
|
||||
if (me.GetVictim())
|
||||
me.GetMotionMaster().MoveChase(me.GetVictim(), 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (me.HasFlag(UnitFields.Flags, UnitFlags.ImmuneToPc))
|
||||
damage = 0;
|
||||
|
||||
if (phase == Misc.ColossusPhaseNormal ||
|
||||
phase == Misc.ColossusPhaseFirstElementalSummon)
|
||||
{
|
||||
if (HealthBelowPct(phase == Misc.ColossusPhaseNormal ? 50 : 5))
|
||||
{
|
||||
damage = 0;
|
||||
phase = (phase == Misc.ColossusPhaseNormal ? Misc.ColossusPhaseFirstElementalSummon : Misc.ColossusPhaseSecondElementalSummon);
|
||||
DoAction(Misc.ActionFreezeColossus);
|
||||
DoAction(Misc.ActionSummonElemental);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override uint GetData(uint data)
|
||||
{
|
||||
if (data == Misc.DataColossusPhase)
|
||||
return phase;
|
||||
else if (data == Misc.DataIntroDone)
|
||||
return introDone ? 1 : 0u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void SetData(uint type, uint data)
|
||||
{
|
||||
if (type == Misc.DataIntroDone)
|
||||
introDone = data != 0;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
if (me.GetReactState() == ReactStates.Aggressive)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void JustSummoned(Creature summon)
|
||||
{
|
||||
summon.SetInCombatWithZone();
|
||||
|
||||
if (phase == Misc.ColossusPhaseSecondElementalSummon)
|
||||
summon.SetHealth(summon.GetMaxHealth() / 2);
|
||||
}
|
||||
|
||||
byte phase;
|
||||
bool introDone;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_drakkari_elemental : ScriptedAI
|
||||
{
|
||||
public boss_drakkari_elemental(Creature creature) : base(creature)
|
||||
{
|
||||
DoCast(me, SpellIds.ElementalSpawnEffect);
|
||||
instance = creature.GetInstanceScript();
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15), task =>
|
||||
{
|
||||
DoCast(SpellIds.SurgeVisual);
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 1, 0.0f, true);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.Surge);
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15));
|
||||
});
|
||||
|
||||
me.AddAura(SpellIds.MojoVolley, me);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Talk(TextIds.EmoteActivateAltar);
|
||||
|
||||
Creature colossus = instance.GetCreature(GDDataTypes.DrakkariColossus);
|
||||
if (colossus)
|
||||
killer.Kill(colossus);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case Misc.ActionReturnToColossus:
|
||||
Talk(TextIds.EmoteMojo);
|
||||
DoCast(SpellIds.SurgeVisual);
|
||||
Creature colossus = instance.GetCreature(GDDataTypes.DrakkariColossus);
|
||||
if (colossus)
|
||||
// what if the elemental is more than 80 yards from drakkari colossus ?
|
||||
DoCast(colossus, SpellIds.Merge, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (HealthBelowPct(50))
|
||||
{
|
||||
Creature colossus = instance.GetCreature(GDDataTypes.DrakkariColossus);
|
||||
if (colossus)
|
||||
{
|
||||
if (colossus.GetAI().GetData(Misc.DataColossusPhase) == Misc.ColossusPhaseFirstElementalSummon)
|
||||
{
|
||||
damage = 0;
|
||||
|
||||
// to prevent spell spaming
|
||||
if (me.HasUnitState(UnitState.Charging))
|
||||
return;
|
||||
|
||||
// not sure about this, the idea of this code is to prevent bug the elemental
|
||||
// if it is not in a acceptable distance to cast the charge spell.
|
||||
if (me.GetDistance(colossus) > 80.0f)
|
||||
{
|
||||
if (me.GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Point)
|
||||
return;
|
||||
|
||||
me.GetMotionMaster().MovePoint(0, colossus.GetPositionX(), colossus.GetPositionY(), colossus.GetPositionZ());
|
||||
return;
|
||||
}
|
||||
DoAction(Misc.ActionReturnToColossus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
public override void SpellHitTarget(Unit target, SpellInfo spell)
|
||||
{
|
||||
if (spell.Id == SpellIds.Merge)
|
||||
{
|
||||
Creature colossus = target.ToCreature();
|
||||
if (colossus)
|
||||
{
|
||||
colossus.GetAI().DoAction(Misc.ActionUnfreezeColossus);
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_living_mojo : ScriptedAI
|
||||
{
|
||||
public npc_living_mojo(Creature creature) : base(creature)
|
||||
{
|
||||
instance = creature.GetInstanceScript();
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(2), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.MojoWave);
|
||||
task.Repeat(TimeSpan.FromSeconds(15));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(7), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.MojoPuddle);
|
||||
task.Repeat(TimeSpan.FromSeconds(18));
|
||||
});
|
||||
}
|
||||
|
||||
void MoveMojos(Creature boss)
|
||||
{
|
||||
List<Creature> mojosList = new List<Creature>();
|
||||
boss.GetCreatureListWithEntryInGrid(mojosList, me.GetEntry(), 12.0f);
|
||||
if (!mojosList.Empty())
|
||||
{
|
||||
foreach (var mojo in mojosList)
|
||||
{
|
||||
if (mojo)
|
||||
mojo.GetMotionMaster().MovePoint(1, boss.GetHomePosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (type != MovementGeneratorType.Point)
|
||||
return;
|
||||
|
||||
if (id == 1)
|
||||
{
|
||||
Creature colossus = instance.GetCreature(GDDataTypes.DrakkariColossus);
|
||||
if (colossus)
|
||||
{
|
||||
colossus.GetAI().DoAction(Misc.ActionUnfreezeColossus);
|
||||
if (colossus.GetAI().GetData(Misc.DataIntroDone) == 0)
|
||||
colossus.GetAI().SetData(Misc.DataIntroDone, 1);
|
||||
colossus.SetInCombatWithZone();
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void AttackStart(Unit attacker)
|
||||
{
|
||||
if (me.GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Point)
|
||||
return;
|
||||
|
||||
// we do this checks to see if the creature is one of the creatures that sorround the boss
|
||||
Creature colossus = instance.GetCreature(GDDataTypes.DrakkariColossus);
|
||||
if (colossus)
|
||||
{
|
||||
Position homePosition = me.GetHomePosition();
|
||||
|
||||
float distance = homePosition.GetExactDist(colossus.GetHomePosition());
|
||||
|
||||
if (distance < 12.0f)
|
||||
{
|
||||
MoveMojos(colossus);
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
}
|
||||
else
|
||||
base.AttackStart(attacker);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.Scripting;
|
||||
using System;
|
||||
|
||||
namespace Scripts.Northrend.Gundrak.EckTheFerocious
|
||||
{
|
||||
struct TextIds
|
||||
{
|
||||
public const uint EmoteSpawn = 0;
|
||||
}
|
||||
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint Berserk = 55816; // Eck goes berserk, increasing his attack speed by 150% and all damage he deals by 500%.
|
||||
public const uint Bite = 55813; // Eck bites down hard, inflicting 150% of his normal damage to an enemy.
|
||||
public const uint Spit = 55814; // Eck spits toxic bile at enemies in a cone in front of him, inflicting 2970 Nature damage and draining 220 mana every 1 sec for 3 sec.
|
||||
public const uint Spring1 = 55815; // Eck leaps at a distant target. --> Drops aggro and charges a random player. Tank can simply taunt him back.
|
||||
public const uint Spring2 = 55837; // Eck leaps at a distant target.
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_eck : BossAI
|
||||
{
|
||||
public boss_eck(Creature creature) : base(creature, GDDataTypes.EckTheFerocious)
|
||||
{
|
||||
Initialize();
|
||||
Talk(TextIds.EmoteSpawn);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_berserk = false;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
|
||||
_scheduler.SetValidator(() => !me.HasUnitState(UnitState.Casting));
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Bite);
|
||||
task.Repeat(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Spit);
|
||||
task.Repeat(TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(14));
|
||||
});
|
||||
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 1, 35.0f, true);
|
||||
if (target)
|
||||
DoCast(target, RandomHelper.RAND(SpellIds.Spring1, SpellIds.Spring2));
|
||||
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10));
|
||||
});
|
||||
|
||||
// 60-90 secs according to wowwiki
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(90), 1, task =>
|
||||
{
|
||||
DoCast(me, SpellIds.Berserk);
|
||||
_berserk = true;
|
||||
});
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (!_berserk && me.HealthBelowPctDamaged(20, damage))
|
||||
{
|
||||
_scheduler.RescheduleGroup(1, TimeSpan.FromSeconds(1));
|
||||
_berserk = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool _berserk;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* 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 Framework.IO;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Scripts.Northrend.Gundrak
|
||||
{
|
||||
struct GDInstanceMisc
|
||||
{
|
||||
public const uint TimerStatueActivation = 3500;
|
||||
|
||||
public static DoorData[] doorData =
|
||||
{
|
||||
new DoorData(GDGameObjectIds.GalDarahDoor1, GDDataTypes.GalDarah, DoorType.Passage),
|
||||
new DoorData(GDGameObjectIds.GalDarahDoor2, GDDataTypes.GalDarah, DoorType.Passage),
|
||||
new DoorData(GDGameObjectIds.GalDarahDoor3, GDDataTypes.GalDarah, DoorType.Room),
|
||||
new DoorData(GDGameObjectIds.EckTheFerociousDoor, GDDataTypes.Moorabi, DoorType.Passage),
|
||||
new DoorData(GDGameObjectIds.EckTheFerociousDoorBehind, GDDataTypes.EckTheFerocious, DoorType.Passage),
|
||||
};
|
||||
|
||||
public static ObjectData[] creatureData =
|
||||
{
|
||||
new ObjectData(GDCreatureIds.DrakkariColossus, GDDataTypes.DrakkariColossus),
|
||||
};
|
||||
|
||||
public static ObjectData[] gameObjectData =
|
||||
{
|
||||
new ObjectData(GDGameObjectIds.SladRanAltar, GDDataTypes.SladRanAltar),
|
||||
new ObjectData(GDGameObjectIds.MoorabiAltar, GDDataTypes.MoorabiAltar),
|
||||
new ObjectData(GDGameObjectIds.DrakkariColossusAltar, GDDataTypes.DrakkariColossusAltar),
|
||||
new ObjectData(GDGameObjectIds.SladRanStatue, GDDataTypes.SladRanStatue),
|
||||
new ObjectData(GDGameObjectIds.MoorabiStatue, GDDataTypes.MoorabiStatue),
|
||||
new ObjectData(GDGameObjectIds.DrakkariColossusStatue, GDDataTypes.DrakkariColossusStatue),
|
||||
new ObjectData(GDGameObjectIds.GalDarahStatue, GDDataTypes.GalDarahStatue),
|
||||
new ObjectData(GDGameObjectIds.Trapdoor, GDDataTypes.Trapdoor),
|
||||
new ObjectData(GDGameObjectIds.Collision, GDDataTypes.Collision)
|
||||
};
|
||||
|
||||
public static Position EckSpawnPoint = new Position(1643.877930f, 936.278015f, 107.204948f, 0.668432f);
|
||||
}
|
||||
|
||||
struct GDDataTypes
|
||||
{
|
||||
// Encounter Ids // Encounter States // Boss Guids
|
||||
public const uint SladRan = 0;
|
||||
public const uint DrakkariColossus = 1;
|
||||
public const uint Moorabi = 2;
|
||||
public const uint GalDarah = 3;
|
||||
public const uint EckTheFerocious = 4;
|
||||
|
||||
// Additional Objects
|
||||
public const uint SladRanAltar = 5;
|
||||
public const uint DrakkariColossusAltar = 6;
|
||||
public const uint MoorabiAltar = 7;
|
||||
|
||||
public const uint SladRanStatue = 8;
|
||||
public const uint DrakkariColossusStatue = 9;
|
||||
public const uint MoorabiStatue = 10;
|
||||
public const uint GalDarahStatue = 11;
|
||||
|
||||
public const uint Trapdoor = 12;
|
||||
public const uint Collision = 13;
|
||||
public const uint Bridge = 14;
|
||||
|
||||
public const uint StatueActivate = 15;
|
||||
}
|
||||
|
||||
struct GDCreatureIds
|
||||
{
|
||||
public const uint SladRan = 29304;
|
||||
public const uint Moorabi = 29305;
|
||||
public const uint GalDarah = 29306;
|
||||
public const uint DrakkariColossus = 29307;
|
||||
public const uint RuinDweller = 29920;
|
||||
public const uint EckTheFerocious = 29932;
|
||||
public const uint AltarTrigger = 30298;
|
||||
}
|
||||
|
||||
struct GDGameObjectIds
|
||||
{
|
||||
public const uint SladRanAltar = 192518;
|
||||
public const uint MoorabiAltar = 192519;
|
||||
public const uint DrakkariColossusAltar = 192520;
|
||||
public const uint SladRanStatue = 192564;
|
||||
public const uint MoorabiStatue = 192565;
|
||||
public const uint GalDarahStatue = 192566;
|
||||
public const uint DrakkariColossusStatue = 192567;
|
||||
public const uint EckTheFerociousDoor = 192632;
|
||||
public const uint EckTheFerociousDoorBehind = 192569;
|
||||
public const uint GalDarahDoor1 = 193208;
|
||||
public const uint GalDarahDoor2 = 193209;
|
||||
public const uint GalDarahDoor3 = 192568;
|
||||
public const uint Trapdoor = 193188;
|
||||
public const uint Collision = 192633;
|
||||
}
|
||||
|
||||
struct GDSpellIds
|
||||
{
|
||||
public const uint FireBeamMammoth = 57068;
|
||||
public const uint FireBeamSnake = 57071;
|
||||
public const uint FireBeamElemental = 57072;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class instance_gundrak : InstanceMapScript
|
||||
{
|
||||
public instance_gundrak() : base(nameof(instance_gundrak), 604) { }
|
||||
|
||||
class instance_gundrak_InstanceMapScript : InstanceScript
|
||||
{
|
||||
public instance_gundrak_InstanceMapScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("GD");
|
||||
SetBossNumber(5);
|
||||
LoadDoorData(GDInstanceMisc.doorData);
|
||||
LoadObjectData(GDInstanceMisc.creatureData, GDInstanceMisc.gameObjectData);
|
||||
|
||||
SladRanStatueState = GameObjectState.Active;
|
||||
DrakkariColossusStatueState = GameObjectState.Active;
|
||||
MoorabiStatueState = GameObjectState.Active;
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
case GDCreatureIds.RuinDweller:
|
||||
if (creature.IsAlive())
|
||||
DwellerGUIDs.Add(creature.GetGUID());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
base.OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
public override void OnGameObjectCreate(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GDGameObjectIds.SladRanAltar:
|
||||
if (GetBossState(GDDataTypes.SladRan) == EncounterState.Done)
|
||||
{
|
||||
if (SladRanStatueState == GameObjectState.Active)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
else
|
||||
go.SetGoState(GameObjectState.Active);
|
||||
}
|
||||
break;
|
||||
case GDGameObjectIds.MoorabiAltar:
|
||||
if (GetBossState(GDDataTypes.Moorabi) == EncounterState.Done)
|
||||
{
|
||||
if (MoorabiStatueState == GameObjectState.Active)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
else
|
||||
go.SetGoState(GameObjectState.Active);
|
||||
}
|
||||
break;
|
||||
case GDGameObjectIds.DrakkariColossusAltar:
|
||||
if (GetBossState(GDDataTypes.DrakkariColossus) == EncounterState.Done)
|
||||
{
|
||||
if (DrakkariColossusStatueState == GameObjectState.Active)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
else
|
||||
go.SetGoState(GameObjectState.Active);
|
||||
}
|
||||
break;
|
||||
case GDGameObjectIds.SladRanStatue:
|
||||
go.SetGoState(SladRanStatueState);
|
||||
break;
|
||||
case GDGameObjectIds.MoorabiStatue:
|
||||
go.SetGoState(MoorabiStatueState);
|
||||
break;
|
||||
case GDGameObjectIds.GalDarahStatue:
|
||||
go.SetGoState(CheckRequiredBosses(GDDataTypes.GalDarah) ? GameObjectState.ActiveAlternative : GameObjectState.Ready);
|
||||
break;
|
||||
case GDGameObjectIds.DrakkariColossusStatue:
|
||||
go.SetGoState(DrakkariColossusStatueState);
|
||||
break;
|
||||
case GDGameObjectIds.EckTheFerociousDoor:
|
||||
// Don't store door on non-heroic
|
||||
if (!instance.IsHeroic())
|
||||
return;
|
||||
break;
|
||||
case GDGameObjectIds.Trapdoor:
|
||||
go.SetGoState(CheckRequiredBosses(GDDataTypes.GalDarah) ? GameObjectState.Ready : GameObjectState.Active);
|
||||
break;
|
||||
case GDGameObjectIds.Collision:
|
||||
go.SetGoState(CheckRequiredBosses(GDDataTypes.GalDarah) ? GameObjectState.Active : GameObjectState.Ready);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
base.OnGameObjectCreate(go);
|
||||
}
|
||||
|
||||
public override void OnUnitDeath(Unit unit)
|
||||
{
|
||||
if (unit.GetEntry() == GDCreatureIds.RuinDweller)
|
||||
{
|
||||
DwellerGUIDs.Remove(unit.GetGUID());
|
||||
|
||||
if (DwellerGUIDs.Empty())
|
||||
unit.SummonCreature(GDCreatureIds.EckTheFerocious, GDInstanceMisc.EckSpawnPoint, TempSummonType.CorpseTimedDespawn, 300 * Time.InMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SetBossState(uint type, EncounterState state)
|
||||
{
|
||||
if (!base.SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GDDataTypes.SladRan:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
GameObject go = GetGameObject(GDDataTypes.SladRanAltar);
|
||||
if (go)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
}
|
||||
break;
|
||||
case GDDataTypes.DrakkariColossus:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
GameObject go = GetGameObject(GDDataTypes.DrakkariColossusAltar);
|
||||
if (go)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
}
|
||||
break;
|
||||
case GDDataTypes.Moorabi:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
GameObject go = GetGameObject(GDDataTypes.MoorabiAltar);
|
||||
if (go)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CheckRequiredBosses(uint bossId, Player player = null)
|
||||
{
|
||||
if (_SkipCheckRequiredBosses(player))
|
||||
return true;
|
||||
|
||||
switch (bossId)
|
||||
{
|
||||
case GDDataTypes.EckTheFerocious:
|
||||
if (!instance.IsHeroic() || GetBossState(GDDataTypes.Moorabi) != EncounterState.Done)
|
||||
return false;
|
||||
break;
|
||||
case GDDataTypes.GalDarah:
|
||||
if (SladRanStatueState != GameObjectState.ActiveAlternative
|
||||
|| DrakkariColossusStatueState != GameObjectState.ActiveAlternative
|
||||
|| MoorabiStatueState != GameObjectState.ActiveAlternative)
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsBridgeReady()
|
||||
{
|
||||
return SladRanStatueState == GameObjectState.Ready && DrakkariColossusStatueState == GameObjectState.Ready && MoorabiStatueState == GameObjectState.Ready;
|
||||
}
|
||||
|
||||
public override void SetData(uint type, uint data)
|
||||
{
|
||||
if (type == GDDataTypes.StatueActivate)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case GDGameObjectIds.SladRanAltar:
|
||||
_events.ScheduleEvent(GDDataTypes.SladRanStatue, GDInstanceMisc.TimerStatueActivation);
|
||||
break;
|
||||
case GDGameObjectIds.DrakkariColossusAltar:
|
||||
_events.ScheduleEvent(GDDataTypes.DrakkariColossusStatue, GDInstanceMisc.TimerStatueActivation);
|
||||
break;
|
||||
case GDGameObjectIds.MoorabiAltar:
|
||||
_events.ScheduleEvent(GDDataTypes.MoorabiStatue, GDInstanceMisc.TimerStatueActivation);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteSaveDataMore(StringBuilder data)
|
||||
{
|
||||
data.AppendFormat("{0} {1} {2} ", (uint)SladRanStatueState, (uint)DrakkariColossusStatueState, (uint)MoorabiStatueState);
|
||||
}
|
||||
|
||||
public override void ReadSaveDataMore(StringArguments data)
|
||||
{
|
||||
SladRanStatueState = (GameObjectState)data.NextUInt32();
|
||||
DrakkariColossusStatueState = (GameObjectState)data.NextUInt32();
|
||||
MoorabiStatueState = (GameObjectState)data.NextUInt32();
|
||||
|
||||
if (IsBridgeReady())
|
||||
_events.ScheduleEvent(GDDataTypes.Bridge, GDInstanceMisc.TimerStatueActivation);
|
||||
}
|
||||
|
||||
void ToggleGameObject(uint type, GameObjectState state)
|
||||
{
|
||||
GameObject go = GetGameObject(type);
|
||||
if (go)
|
||||
go.SetGoState(state);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GDDataTypes.SladRanStatue:
|
||||
SladRanStatueState = state;
|
||||
break;
|
||||
case GDDataTypes.DrakkariColossusStatue:
|
||||
DrakkariColossusStatueState = state;
|
||||
break;
|
||||
case GDDataTypes.MoorabiStatue:
|
||||
MoorabiStatueState = state;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(uint diff)
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
uint spellId = 0;
|
||||
uint altarId = 0;
|
||||
switch (eventId)
|
||||
{
|
||||
case GDDataTypes.SladRanStatue:
|
||||
spellId = GDSpellIds.FireBeamSnake;
|
||||
altarId = GDDataTypes.SladRanAltar;
|
||||
break;
|
||||
case GDDataTypes.DrakkariColossusStatue:
|
||||
spellId = GDSpellIds.FireBeamElemental;
|
||||
altarId = GDDataTypes.DrakkariColossusAltar;
|
||||
break;
|
||||
case GDDataTypes.MoorabiStatue:
|
||||
spellId = GDSpellIds.FireBeamMammoth;
|
||||
altarId = GDDataTypes.MoorabiAltar;
|
||||
break;
|
||||
case GDDataTypes.Bridge:
|
||||
for (uint type = GDDataTypes.SladRanStatue; type <= GDDataTypes.GalDarahStatue; ++type)
|
||||
ToggleGameObject(type, GameObjectState.ActiveAlternative);
|
||||
ToggleGameObject(GDDataTypes.Trapdoor, GameObjectState.Ready);
|
||||
ToggleGameObject(GDDataTypes.Collision, GameObjectState.Active);
|
||||
SaveToDB();
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject altar = GetGameObject(altarId);
|
||||
if (altar)
|
||||
{
|
||||
Creature trigger = altar.FindNearestCreature(GDCreatureIds.AltarTrigger, 10.0f);
|
||||
if (trigger)
|
||||
trigger.CastSpell((Unit)null, spellId, true);
|
||||
}
|
||||
|
||||
// eventId equals statueId
|
||||
ToggleGameObject(eventId, GameObjectState.Ready);
|
||||
|
||||
if (IsBridgeReady())
|
||||
_events.ScheduleEvent(GDDataTypes.Bridge, GDInstanceMisc.TimerStatueActivation);
|
||||
|
||||
SaveToDB();
|
||||
});
|
||||
}
|
||||
|
||||
List<ObjectGuid> DwellerGUIDs = new List<ObjectGuid>();
|
||||
|
||||
GameObjectState SladRanStatueState;
|
||||
GameObjectState DrakkariColossusStatueState;
|
||||
GameObjectState MoorabiStatueState;
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_gundrak_InstanceMapScript(map);
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class go_gundrak_altar : GameObjectScript
|
||||
{
|
||||
public go_gundrak_altar() : base("go_gundrak_altar") { }
|
||||
|
||||
public override bool OnGossipHello(Player player, GameObject go)
|
||||
{
|
||||
go.SetFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
go.SetGoState(GameObjectState.Active);
|
||||
|
||||
InstanceScript instance = go.GetInstanceScript();
|
||||
if (instance != null)
|
||||
{
|
||||
instance.SetData(GDDataTypes.StatueActivate, go.GetEntry());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,733 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
namespace Scripts.Northrend.IcecrownCitadel
|
||||
{
|
||||
struct IccConst
|
||||
{
|
||||
public const uint WeeklyNPCs = 9;
|
||||
}
|
||||
|
||||
struct Bosses
|
||||
{
|
||||
public const uint LordMarrowgar = 0;
|
||||
public const uint LadyDeathwhisper = 1;
|
||||
public const uint GunshipBattle = 2;
|
||||
public const uint DeathbringerSaurfang = 3;
|
||||
public const uint Festergut = 4;
|
||||
public const uint Rotface = 5;
|
||||
public const uint ProfessorPutricide = 6;
|
||||
public const uint BloodPrinceCouncil = 7;
|
||||
public const uint BloodQueenLanaThel = 8;
|
||||
public const uint SisterSvalna = 9;
|
||||
public const uint ValithriaDreamwalker = 10;
|
||||
public const uint Sindragosa = 11;
|
||||
public const uint TheLichKing = 12;
|
||||
|
||||
public const uint MaxEncounters = 13;
|
||||
}
|
||||
|
||||
struct Texts
|
||||
{
|
||||
// Highlord Tirion Fordring (At Light'S Hammer)
|
||||
public const uint SayTirionIntro1 = 0;
|
||||
public const uint SayTirionIntro2 = 1;
|
||||
public const uint SayTirionIntro3 = 2;
|
||||
public const uint SayTirionIntro4 = 3;
|
||||
public const uint SayTirionIntroH5 = 4;
|
||||
public const uint SayTirionIntroA5 = 5;
|
||||
|
||||
// The Lich King (At Light'S Hammer)
|
||||
public const uint SayLkIntro1 = 0;
|
||||
public const uint SayLkIntro2 = 1;
|
||||
public const uint SayLkIntro3 = 2;
|
||||
public const uint SayLkIntro4 = 3;
|
||||
public const uint SayLkIntro5 = 4;
|
||||
|
||||
// Highlord Bolvar Fordragon (At Light'S Hammer)
|
||||
public const uint SayBolvarIntro1 = 0;
|
||||
|
||||
// High Overlord Saurfang (At Light'S Hammer)
|
||||
public const uint SaySaurfangIntro1 = 15;
|
||||
public const uint SaySaurfangIntro2 = 16;
|
||||
public const uint SaySaurfangIntro3 = 17;
|
||||
public const uint SaySaurfangIntro4 = 18;
|
||||
|
||||
// Muradin Bronzebeard (At Light'S Hammer)
|
||||
public const uint SayMuradinIntro1 = 13;
|
||||
public const uint SayMuradinIntro2 = 14;
|
||||
public const uint SayMuradinIntro3 = 15;
|
||||
|
||||
// Deathbound Ward
|
||||
public const uint SayTrapActivate = 0;
|
||||
|
||||
// Rotting Frost Giant
|
||||
public const uint EmoteDeathPlagueWarning = 0;
|
||||
|
||||
// Sister Svalna
|
||||
public const uint SaySvalnaKillCaptain = 1; // Happens When She Kills A Captain
|
||||
public const uint SaySvalnaKill = 4;
|
||||
public const uint SaySvalnaCaptainDeath = 5; // Happens When A Captain Resurrected By Her Dies
|
||||
public const uint SaySvalnaDeath = 6;
|
||||
public const uint EmoteSvalnaImpale = 7;
|
||||
public const uint EmoteSvalnaBrokenShield = 8;
|
||||
|
||||
public const uint SayCrokIntro1 = 0; // Ready Your Arms; My Argent Brothers. The Vrykul Will Protect The Frost Queen With Their Lives.
|
||||
public const uint SayArnathIntro2 = 5; // Even Dying Here Beats Spending Another Day Collecting Reagents For That Madman; Finklestein.
|
||||
public const uint SayCrokIntro3 = 1; // Enough Idle Banter! Our Champions Have Arrived - Support Them As We Push Our Way Through The Hall!
|
||||
public const uint SaySvalnaEventStart = 0; // You May Have Once Fought Beside Me; Crok; But Now You Are Nothing More Than A Traitor. Come; Your Second Death Approaches!
|
||||
public const uint SayCrokCombatWp0 = 2; // Draw Them Back To Us; And We'Ll Assist You.
|
||||
public const uint SayCrokCombatWp1 = 3; // Quickly; Push On!
|
||||
public const uint SayCrokFinalWp = 4; // Her Reinforcements Will Arrive Shortly; We Must Bring Her Down Quickly!
|
||||
public const uint SaySvalnaResurrectCaptains = 2; // Foolish Crok. You Brought My Reinforcements With You. Arise; Argent Champions; And Serve The Lich King In Death!
|
||||
public const uint SayCrokCombatSvalna = 5; // I'Ll Draw Her Attacks. Return Our Brothers To Their Graves; Then Help Me Bring Her Down!
|
||||
public const uint SaySvalnaAggro = 3; // Come; Scourgebane. I'Ll Show The Master Which Of Us Is Truly Worthy Of The Title Of "Champion"!
|
||||
public const uint SayCaptainDeath = 0;
|
||||
public const uint SayCaptainResurrected = 1;
|
||||
public const uint SayCaptainKill = 2;
|
||||
public const uint SayCaptainSecondDeath = 3;
|
||||
public const uint SayCaptainSurviveTalk = 4;
|
||||
public const uint SayCrokWeakeningGauntlet = 6;
|
||||
public const uint SayCrokWeakeningSvalna = 7;
|
||||
public const uint SayCrokDeath = 8;
|
||||
}
|
||||
|
||||
struct InstanceSpells
|
||||
{
|
||||
// Rotting Frost Giant
|
||||
public const uint DeathPlague = 72879;
|
||||
public const uint DeathPlagueAura = 72865;
|
||||
public const uint RecentlyInfected = 72884;
|
||||
public const uint DeathPlagueKill = 72867;
|
||||
public const uint Stomp = 64652;
|
||||
public const uint ArcticBreath = 72848;
|
||||
|
||||
// Frost Freeze Trap
|
||||
public const uint ColdflameJets = 70460;
|
||||
|
||||
// Alchemist Adrianna
|
||||
public const uint HarvestBlightSpecimen = 72155;
|
||||
public const uint HarvestBlightSpecimen25 = 72162;
|
||||
|
||||
// Crok Scourgebane
|
||||
public const uint IceboundArmor = 70714;
|
||||
public const uint ScourgeStrike = 71488;
|
||||
public const uint DeathStrike = 71489;
|
||||
|
||||
// Sister Svalna
|
||||
public const uint CaressOfDeath = 70078;
|
||||
public const uint ImpalingSpearKill = 70196;
|
||||
public const uint ReviveChampion = 70053;
|
||||
public const uint Undeath = 70089;
|
||||
public const uint ImpalingSpear = 71443;
|
||||
public const uint AetherShield = 71463;
|
||||
public const uint HurlSpear = 71466;
|
||||
|
||||
// Captain Arnath
|
||||
public const uint DominateMind = 14515;
|
||||
public const uint FlashHealNormal = 71595;
|
||||
public const uint PowerWordShieldNormal = 71548;
|
||||
public const uint SmiteNormal = 71546;
|
||||
public const uint FlashHealUndead = 71782;
|
||||
public const uint PowerWordShieldUndead = 71780;
|
||||
public const uint SmiteUndead = 71778;
|
||||
public static uint SpellFlashHeal(bool isUndead) { return isUndead ? InstanceSpells.FlashHealUndead : InstanceSpells.FlashHealNormal; }
|
||||
public static uint SpellPowerWordShield(bool isUndead) { return isUndead ? InstanceSpells.PowerWordShieldUndead : InstanceSpells.PowerWordShieldNormal; }
|
||||
public static uint SpellSmite(bool isUndead) { return isUndead ? InstanceSpells.SmiteUndead : InstanceSpells.SmiteNormal; }
|
||||
|
||||
// Captain Brandon
|
||||
public const uint CrusaderStrike = 71549;
|
||||
public const uint DivineShield = 71550;
|
||||
public const uint JudgementOfCommand = 71551;
|
||||
public const uint HammerOfBetrayal = 71784;
|
||||
|
||||
// Captain Grondel
|
||||
public const uint Charge = 71553;
|
||||
public const uint MortalStrike = 71552;
|
||||
public const uint SunderArmor = 71554;
|
||||
public const uint Conflagration = 71785;
|
||||
|
||||
// Captain Rupert
|
||||
public const uint FelIronBombNormal = 71592;
|
||||
public const uint MachineGunNormal = 71594;
|
||||
public const uint RocketLaunchNormal = 71590;
|
||||
public const uint FelIronBombUndead = 71787;
|
||||
public const uint MachineGunUndead = 71788;
|
||||
public const uint RocketLaunchUndead = 71786;
|
||||
public static uint SpellFelIronBomb(bool isUndead) { return isUndead ? InstanceSpells.FelIronBombUndead : InstanceSpells.FelIronBombNormal; }
|
||||
public static uint SpellMachineGun(bool isUndead) { return isUndead ? InstanceSpells.MachineGunUndead : InstanceSpells.MachineGunNormal; }
|
||||
public static uint SpellRocketLaunch(bool isUndead) { return isUndead ? InstanceSpells.RocketLaunchUndead : InstanceSpells.RocketLaunchNormal; }
|
||||
|
||||
// Invisible Stalker (Float; Uninteractible; Largeaoi)
|
||||
public const uint SoulMissile = 72585;
|
||||
|
||||
public const uint Berserk = 26662;
|
||||
public const uint Berserk2 = 47008;
|
||||
|
||||
// Deathbound Ward
|
||||
public const uint StoneForm = 70733;
|
||||
|
||||
// Residue Rendezvous
|
||||
public const uint OrangeBlightResidue = 72144;
|
||||
public const uint GreenBlightResidue = 72145;
|
||||
|
||||
// The Lich King
|
||||
public const uint ArthasTeleporterCeremony = 72915;
|
||||
public const uint FrostmourneTeleportVisual = 73078;
|
||||
|
||||
// Shadowmourne questline
|
||||
public const uint UnsatedCraving = 71168;
|
||||
public const uint ShadowsFate = 71169;
|
||||
}
|
||||
|
||||
struct EventTypes
|
||||
{
|
||||
// Highlord Tirion Fordring (At Light'S Hammer)
|
||||
// The Lich King (At Light'S Hammer)
|
||||
// Highlord Bolvar Fordragon (At Light'S Hammer)
|
||||
// High Overlord Saurfang (At Light'S Hammer)
|
||||
// Muradin Bronzebeard (At Light'S Hammer)
|
||||
public const uint TirionIntro2 = 1;
|
||||
public const uint TirionIntro3 = 2;
|
||||
public const uint TirionIntro4 = 3;
|
||||
public const uint TirionIntro5 = 4;
|
||||
public const uint LkIntro1 = 5;
|
||||
public const uint TirionIntro6 = 6;
|
||||
public const uint LkIntro2 = 7;
|
||||
public const uint LkIntro3 = 8;
|
||||
public const uint LkIntro4 = 9;
|
||||
public const uint BolvarIntro1 = 10;
|
||||
public const uint LkIntro5 = 11;
|
||||
public const uint SaurfangIntro1 = 12;
|
||||
public const uint TirionIntroH7 = 13;
|
||||
public const uint SaurfangIntro2 = 14;
|
||||
public const uint SaurfangIntro3 = 15;
|
||||
public const uint SaurfangIntro4 = 16;
|
||||
public const uint SaurfangRun = 17;
|
||||
public const uint MuradinIntro1 = 18;
|
||||
public const uint MuradinIntro2 = 19;
|
||||
public const uint MuradinIntro3 = 20;
|
||||
public const uint TirionIntroA7 = 21;
|
||||
public const uint MuradinIntro4 = 22;
|
||||
public const uint MuradinIntro5 = 23;
|
||||
public const uint MuradinRun = 24;
|
||||
|
||||
// Rotting Frost Giant
|
||||
public const uint DeathPlague = 25;
|
||||
public const uint Stomp = 26;
|
||||
public const uint ArcticBreath = 27;
|
||||
|
||||
// Frost Freeze Trap
|
||||
public const uint ActivateTrap = 28;
|
||||
|
||||
// Crok Scourgebane
|
||||
public const uint ScourgeStrike = 29;
|
||||
public const uint DeathStrike = 30;
|
||||
public const uint HealthCheck = 31;
|
||||
public const uint CrokIntro3 = 32;
|
||||
public const uint StartPathing = 33;
|
||||
|
||||
// Sister Svalna
|
||||
public const uint ArnathIntro2 = 34;
|
||||
public const uint SvalnaStart = 35;
|
||||
public const uint SvalnaResurrect = 36;
|
||||
public const uint SvalnaCombat = 37;
|
||||
public const uint ImpalingSpear = 38;
|
||||
public const uint AetherShield = 39;
|
||||
|
||||
// Captain Arnath
|
||||
public const uint ArnathFlashHeal = 40;
|
||||
public const uint ArnathPwShield = 41;
|
||||
public const uint ArnathSmite = 42;
|
||||
public const uint ArnathDominateMind = 43;
|
||||
|
||||
// Captain Brandon
|
||||
public const uint BrandonCrusaderStrike = 44;
|
||||
public const uint BrandonDivineShield = 45;
|
||||
public const uint BrandonJudgementOfCommand = 46;
|
||||
public const uint BrandonHammerOfBetrayal = 47;
|
||||
|
||||
// Captain Grondel
|
||||
public const uint GrondelChargeCheck = 48;
|
||||
public const uint GrondelMortalStrike = 49;
|
||||
public const uint GrondelSunderArmor = 50;
|
||||
public const uint GrondelConflagration = 51;
|
||||
|
||||
// Captain Rupert
|
||||
public const uint RupertFelIronBomb = 52;
|
||||
public const uint RupertMachineGun = 53;
|
||||
public const uint RupertRocketLaunch = 54;
|
||||
|
||||
// Invisible Stalker (Float; Uninteractible; Largeaoi)
|
||||
public const uint SoulMissile = 55;
|
||||
}
|
||||
|
||||
struct DataTypes
|
||||
{
|
||||
// Additional Data
|
||||
public const uint SaurfangEventNpc = 13;
|
||||
public const uint BonedAchievement = 14;
|
||||
public const uint OozeDanceAchievement = 15;
|
||||
public const uint PutricideTable = 16;
|
||||
public const uint NauseaAchievement = 17;
|
||||
public const uint OrbWhispererAchievement = 18;
|
||||
public const uint PrinceKelesethGuid = 19;
|
||||
public const uint PrinceTaldaramGuid = 20;
|
||||
public const uint PrinceValanarGuid = 21;
|
||||
public const uint BloodPrincesControl = 22;
|
||||
public const uint SindragosaFrostwyrms = 23;
|
||||
public const uint Spinestalker = 24;
|
||||
public const uint Rimefang = 25;
|
||||
public const uint ColdflameJets = 26;
|
||||
public const uint TeamInInstance = 27;
|
||||
public const uint BloodQuickeningState = 28;
|
||||
public const uint HeroicAttempts = 29;
|
||||
public const uint CrokScourgebane = 30;
|
||||
public const uint CaptainArnath = 31;
|
||||
public const uint CaptainBrandon = 32;
|
||||
public const uint CaptainGrondel = 33;
|
||||
public const uint CaptainRupert = 34;
|
||||
public const uint ValithriaTrigger = 35;
|
||||
public const uint ValithriaLichKing = 36;
|
||||
public const uint HighlordTirionFordring = 37;
|
||||
public const uint ArthasPlatform = 38;
|
||||
public const uint TerenasMenethil = 39;
|
||||
public const uint EnemyGunship = 40;
|
||||
public const uint UpperSpireTeleAct = 41;
|
||||
}
|
||||
|
||||
struct WorldStates
|
||||
{
|
||||
public const uint ShowTimer = 4903;
|
||||
public const uint ExecutionTime = 4904;
|
||||
public const uint ShowAttempts = 4940;
|
||||
public const uint AttemptsRemaining = 4941;
|
||||
public const uint AttemptsMax = 4942;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
// At Light'S Hammer
|
||||
public const uint HighlordTirionFordringLh = 37119;
|
||||
public const uint TheLichKingLh = 37181;
|
||||
public const uint HighlordBolvarFordragonLh = 37183;
|
||||
public const uint KorKronGeneral = 37189;
|
||||
public const uint AllianceCommander = 37190;
|
||||
public const uint Tortunok = 37992; // Druid Armor H
|
||||
public const uint AlanaMoonstrike = 37999; // Druid Armor A
|
||||
public const uint GerardoTheSuave = 37993; // Hunter Armor H
|
||||
public const uint TalanMoonstrike = 37998; // Hunter Armor A
|
||||
public const uint UvlusBanefire = 38284; // Mage Armor H
|
||||
public const uint MalfusGrimfrost = 38283; // Mage Armor A
|
||||
public const uint IkfirusTheVile = 37991; // Rogue Armor H
|
||||
public const uint Yili = 37997; // Rogue Armor A
|
||||
public const uint VolGuk = 38841; // Shaman Armor H
|
||||
public const uint Jedebia = 38840; // Shaman Armor A
|
||||
public const uint HaraggTheUnseen = 38181; // Warlock Armor H
|
||||
public const uint NibyTheAlmighty = 38182; // Warlock Armor N
|
||||
public const uint GarroshHellscream = 39372;
|
||||
public const uint KingVarianWrynn = 39371;
|
||||
public const uint DeathboundWard = 37007;
|
||||
public const uint LadyJainaProudmooreQuest = 38606;
|
||||
public const uint MuradinBronzaBeardQuest = 38607;
|
||||
public const uint UtherTheLightBringerQuest = 38608;
|
||||
public const uint LadySylvanasWindrunnerQuest = 38609;
|
||||
|
||||
// Weekly Quests
|
||||
public const uint InfiltratorMinchar = 38471;
|
||||
public const uint KorKronLieutenant = 38491;
|
||||
public const uint SkybreakerLieutenant = 38492;
|
||||
public const uint RottingFrostGiant10 = 38490;
|
||||
public const uint RottingFrostGiant25 = 38494;
|
||||
public const uint AlchemistAdrianna = 38501;
|
||||
public const uint AlrinTheAgile = 38551;
|
||||
public const uint InfiltratorMincharBq = 38558;
|
||||
public const uint MincharBeamStalker = 38557;
|
||||
public const uint ValithriaDreamwalkerQuest = 38589;
|
||||
|
||||
// Lord Marrowgar
|
||||
public const uint LordMarrowgar = 36612;
|
||||
public const uint Coldflame = 36672;
|
||||
public const uint BoneSpike = 36619;
|
||||
|
||||
// Lady Deathwhisper
|
||||
public const uint LadyDeathwhisper = 36855;
|
||||
public const uint CultFanatic = 37890;
|
||||
public const uint DeformedFanatic = 38135;
|
||||
public const uint ReanimatedFanatic = 38009;
|
||||
public const uint CultAdherent = 37949;
|
||||
public const uint EmpoweredAdherent = 38136;
|
||||
public const uint ReanimatedAdherent = 38010;
|
||||
public const uint VengefulShade = 38222;
|
||||
|
||||
// Icecrown Gunship Battle
|
||||
public const uint MartyrStalkerIGBSaurfang = 38569;
|
||||
public const uint AllianceGunshipCannon = 36838;
|
||||
public const uint HordeGunshipCannon = 36839;
|
||||
public const uint SkybreakerDeckhand = 36970;
|
||||
public const uint OrgrimsHammerCrew = 36971;
|
||||
public const uint IGBHighOverlordSaurfang = 36939;
|
||||
public const uint IGBMuradinBrozebeard = 36948;
|
||||
public const uint TheSkybreaker = 37540;
|
||||
public const uint OrgrimsHammer = 37215;
|
||||
public const uint GunshipHull = 37547;
|
||||
public const uint TeleportPortal = 37227;
|
||||
public const uint TeleportExit = 37488;
|
||||
public const uint SkybreakerSorcerer = 37116;
|
||||
public const uint SkybreakerRifleman = 36969;
|
||||
public const uint SkybreakerMortarSoldier = 36978;
|
||||
public const uint SkybreakerMarine = 36950;
|
||||
public const uint SkybreakerSergeant = 36961;
|
||||
public const uint KorKronBattleMage = 37117;
|
||||
public const uint KorKronAxeThrower = 36968;
|
||||
public const uint KorKronRocketeer = 36982;
|
||||
public const uint KorKronReaver = 36957;
|
||||
public const uint KorKronSergeant = 36960;
|
||||
public const uint ZafodBoombox = 37184;
|
||||
public const uint HighCaptainJustinBartlett = 37182;
|
||||
public const uint SkyReaverKormBlackscar = 37833;
|
||||
|
||||
// Deathbringer Saurfang
|
||||
public const uint DeathbringerSaurfang = 37813;
|
||||
public const uint BloodBeast = 38508;
|
||||
public const uint SeJainaProudmoore = 37188; // Se Means Saurfang Event
|
||||
public const uint SeMuradinBronzebeard = 37200;
|
||||
public const uint SeKingVarianWrynn = 37879;
|
||||
public const uint SeHighOverlordSaurfang = 37187;
|
||||
public const uint SeKorKronReaver = 37920;
|
||||
public const uint SeSkybreakerMarine = 37830;
|
||||
public const uint FrostFreezeTrap = 37744;
|
||||
|
||||
// Festergut
|
||||
public const uint Festergut = 36626;
|
||||
public const uint GasDummy = 36659;
|
||||
public const uint MalleableOozeStalker = 38556;
|
||||
|
||||
// Rotface
|
||||
public const uint Rotface = 36627;
|
||||
public const uint OozeSprayStalker = 37986;
|
||||
public const uint PuddleStalker = 37013;
|
||||
public const uint UnstableExplosionStalker = 38107;
|
||||
public const uint VileGasStalker = 38548;
|
||||
|
||||
// Professor Putricide
|
||||
public const uint ProfessorPutricide = 36678;
|
||||
public const uint AbominationWingMadScientistStalker = 37824;
|
||||
public const uint GrowingOozePuddle = 37690;
|
||||
public const uint GasCloud = 37562;
|
||||
public const uint VolatileOoze = 37697;
|
||||
public const uint ChokingGasBomb = 38159;
|
||||
public const uint TearGasTargetStalker = 38317;
|
||||
public const uint MutatedAbomination10 = 37672;
|
||||
public const uint MutatedAbomination25 = 38285;
|
||||
|
||||
// Blood Prince Council
|
||||
public const uint PrinceKeleseth = 37972;
|
||||
public const uint PrinceTaldaram = 37973;
|
||||
public const uint PrinceValanar = 37970;
|
||||
public const uint BloodOrbController = 38008;
|
||||
public const uint FloatingTrigger = 30298;
|
||||
public const uint DarkNucleus = 38369;
|
||||
public const uint BallOfFlame = 38332;
|
||||
public const uint BallOfInfernoFlame = 38451;
|
||||
public const uint KineticBombTarget = 38458;
|
||||
public const uint KineticBomb = 38454;
|
||||
public const uint ShockVortex = 38422;
|
||||
|
||||
// Blood-Queen Lana'Thel
|
||||
public const uint BloodQueenLanaThel = 37955;
|
||||
|
||||
// Frostwing Halls Gauntlet Event
|
||||
public const uint CrokScourgebane = 37129;
|
||||
public const uint CaptainArnath = 37122;
|
||||
public const uint CaptainBrandon = 37123;
|
||||
public const uint CaptainGrondel = 37124;
|
||||
public const uint CaptainRupert = 37125;
|
||||
public const uint CaptainArnathUndead = 37491;
|
||||
public const uint CaptainBrandonUndead = 37493;
|
||||
public const uint CaptainGrondelUndead = 37494;
|
||||
public const uint CaptainRupertUndead = 37495;
|
||||
public const uint YmirjarBattleMaiden = 37132;
|
||||
public const uint YmirjarDeathbringer = 38125;
|
||||
public const uint YmirjarFrostbinder = 37127;
|
||||
public const uint YmirjarHuntress = 37134;
|
||||
public const uint YmirjarWarlord = 37133;
|
||||
public const uint SisterSvalna = 37126;
|
||||
public const uint ImpalingSpear = 38248;
|
||||
|
||||
// Valithria Dreamwalker
|
||||
public const uint ValithriaDreamwalker = 36789;
|
||||
public const uint GreenDragonCombatTrigger = 38752;
|
||||
public const uint RisenArchmage = 37868;
|
||||
public const uint BlazingSkeleton = 36791;
|
||||
public const uint Suppresser = 37863;
|
||||
public const uint BlisteringZombie = 37934;
|
||||
public const uint GluttonousAbomination = 37886;
|
||||
public const uint ManaVoid = 38068;
|
||||
public const uint ColumnOfFrost = 37918;
|
||||
public const uint RotWorm = 37907;
|
||||
public const uint TheLichKingValithria = 16980;
|
||||
public const uint DreamPortalPreEffect = 38186;
|
||||
public const uint NightmarePortalPreEffect = 38429;
|
||||
public const uint DreamPortal = 37945;
|
||||
public const uint NightmarePortal = 38430;
|
||||
|
||||
// Sindragosa
|
||||
public const uint Sindragosa = 36853;
|
||||
public const uint Spinestalker = 37534;
|
||||
public const uint Rimefang = 37533;
|
||||
public const uint FrostwardenHandler = 37531;
|
||||
public const uint FrostwingWhelp = 37532;
|
||||
public const uint IcyBlast = 38223;
|
||||
public const uint FrostBomb = 37186;
|
||||
public const uint IceTomb = 36980;
|
||||
|
||||
// The Lich King
|
||||
public const uint TheLichKing = 36597;
|
||||
public const uint HighlordTirionFordringLk = 38995;
|
||||
public const uint TerenasMenethilFrostmourne = 36823;
|
||||
public const uint SpiritWarden = 36824;
|
||||
public const uint TerenasMenethilFrostmourneH = 39217;
|
||||
public const uint ShamblingHorror = 37698;
|
||||
public const uint DrudgeGhoul = 37695;
|
||||
public const uint IceSphere = 36633;
|
||||
public const uint RagingSpirit = 36701;
|
||||
public const uint Defile = 38757;
|
||||
public const uint ValkyrShadowguard = 36609;
|
||||
public const uint VileSpirit = 37799;
|
||||
public const uint WickedSpirit = 39190;
|
||||
public const uint StrangulateVehicle = 36598;
|
||||
public const uint WorldTrigger = 22515;
|
||||
public const uint WorldTriggerInfiniteAoi = 36171;
|
||||
public const uint SpiritBomb = 39189;
|
||||
public const uint FrostmourneTrigger = 38584;
|
||||
|
||||
// Generic
|
||||
public const uint InvisibleStalker = 30298;
|
||||
}
|
||||
|
||||
struct GameObjectIds
|
||||
{
|
||||
// ICC Teleporters
|
||||
public const uint TransporterLichKing = 202223;
|
||||
public const uint TransporterUpperSpire = 202235;
|
||||
public const uint TransporterLightsHammer = 202242;
|
||||
public const uint TransporterRampart = 202243;
|
||||
public const uint TransporterDeathBringer = 202244;
|
||||
public const uint TransporterOratory = 202245;
|
||||
public const uint TransporterSindragosa = 202246;
|
||||
|
||||
// Lower Spire Trash
|
||||
public const uint SpiritAlarm1 = 201814;
|
||||
public const uint SpiritAlarm2 = 201815;
|
||||
public const uint SpiritAlarm3 = 201816;
|
||||
public const uint SpiritAlarm4 = 201817;
|
||||
|
||||
// Lord Marrogar
|
||||
public const uint DoodadIcecrownIcewall02 = 201910;
|
||||
public const uint LordMarrowgarIcewall = 201911;
|
||||
public const uint LordMarrowgarSEntrance = 201857;
|
||||
|
||||
// Lady Deathwhisper
|
||||
public const uint OratoryOfTheDamnedEntrance = 201563;
|
||||
public const uint LadyDeathwhisperElevator = 202220;
|
||||
|
||||
// Icecrown Gunship Battle - Horde raid
|
||||
public const uint OrgrimsHammer_H = 201812;
|
||||
public const uint TheSkybreaker_H = 201811;
|
||||
public const uint GunshipArmory_H_10N = 202178;
|
||||
public const uint GunshipArmory_H_25N = 202180;
|
||||
public const uint GunshipArmory_H_10H = 202177;
|
||||
public const uint GunshipArmory_H_25H = 202179;
|
||||
|
||||
// Icecrown Gunship Battle - Alliance raid
|
||||
public const uint OrgrimsHammer_A = 201581;
|
||||
public const uint TheSkybreaker_A = 201580;
|
||||
public const uint GunshipArmory_A_10N = 201873;
|
||||
public const uint GunshipArmory_A_25N = 201874;
|
||||
public const uint GunshipArmory_A_10H = 201872;
|
||||
public const uint GunshipArmory_A_25H = 201875;
|
||||
|
||||
// Deathbringer Saurfang
|
||||
public const uint SaurfangSDoor = 201825;
|
||||
public const uint DeathbringerSCache10n = 202239;
|
||||
public const uint DeathbringerSCache25n = 202240;
|
||||
public const uint DeathbringerSCache10h = 202238;
|
||||
public const uint DeathbringerSCache25h = 202241;
|
||||
|
||||
// Professor Putricide
|
||||
public const uint OrangePlagueMonsterEntrance = 201371;
|
||||
public const uint GreenPlagueMonsterEntrance = 201370;
|
||||
public const uint ScientistAirlockDoorCollision = 201612;
|
||||
public const uint ScientistAirlockDoorOrange = 201613;
|
||||
public const uint ScientistAirlockDoorGreen = 201614;
|
||||
public const uint DoodadIcecrownOrangetubes02 = 201617;
|
||||
public const uint DoodadIcecrownGreentubes02 = 201618;
|
||||
public const uint ScientistEntrance = 201372;
|
||||
public const uint DrinkMe = 201584;
|
||||
public const uint PlagueSigil = 202182;
|
||||
|
||||
// Blood Prince Council
|
||||
public const uint CrimsonHallDoor = 201376;
|
||||
public const uint BloodElfCouncilDoor = 201378;
|
||||
public const uint BloodElfCouncilDoorRight = 201377;
|
||||
|
||||
// Blood-Queen Lana'Thel
|
||||
public const uint DoodadIcecrownBloodprinceDoor01 = 201746;
|
||||
public const uint DoodadIcecrownGrate01 = 201755;
|
||||
public const uint BloodwingSigil = 202183;
|
||||
|
||||
// Valithria Dreamwalker
|
||||
public const uint GreenDragonBossEntrance = 201375;
|
||||
public const uint GreenDragonBossExit = 201374;
|
||||
public const uint DoodadIcecrownRoostportcullis01 = 201380;
|
||||
public const uint DoodadIcecrownRoostportcullis02 = 201381;
|
||||
public const uint DoodadIcecrownRoostportcullis03 = 201382;
|
||||
public const uint DoodadIcecrownRoostportcullis04 = 201383;
|
||||
public const uint CacheOfTheDreamwalker10n = 201959;
|
||||
public const uint CacheOfTheDreamwalker25n = 202339;
|
||||
public const uint CacheOfTheDreamwalker10h = 202338;
|
||||
public const uint CacheOfTheDreamwalker25h = 202340;
|
||||
|
||||
// Sindragosa
|
||||
public const uint SindragosaEntranceDoor = 201373;
|
||||
public const uint SindragosaShortcutEntranceDoor = 201369;
|
||||
public const uint SindragosaShortcutExitDoor = 201379;
|
||||
public const uint IceWall = 202396;
|
||||
public const uint IceBlock = 201722;
|
||||
public const uint SigilOfTheFrostwing = 202181;
|
||||
|
||||
// The Lich King
|
||||
public const uint ArthasPlatform = 202161;
|
||||
public const uint ArthasPrecipice = 202078;
|
||||
public const uint DoodadIcecrownThronefrostywind01 = 202188;
|
||||
public const uint DoodadIcecrownThronefrostyedge01 = 202189;
|
||||
public const uint DoodadIceshardStanding02 = 202141;
|
||||
public const uint DoodadIceshardStanding01 = 202142;
|
||||
public const uint DoodadIceshardStanding03 = 202143;
|
||||
public const uint DoodadIceshardStanding04 = 202144;
|
||||
public const uint DoodadIcecrownSnowedgewarning01 = 202190;
|
||||
public const uint FrozenLavaman = 202436;
|
||||
public const uint LavamanPillarsChained = 202437;
|
||||
public const uint LavamanPillarsUnchained = 202438;
|
||||
}
|
||||
|
||||
struct AchievementCriteriaIds
|
||||
{
|
||||
// Lord Marrowgar
|
||||
public const uint Boned10n = 12775;
|
||||
public const uint Boned25n = 12962;
|
||||
public const uint Boned10h = 13393;
|
||||
public const uint Boned25h = 13394;
|
||||
|
||||
// Rotface
|
||||
public const uint DancesWithOozes10 = 12984;
|
||||
public const uint DancesWithOozes25 = 12966;
|
||||
public const uint DancesWithOozes10H = 12985;
|
||||
public const uint DancesWithOozes25H = 12983;
|
||||
|
||||
// Professor Putricide
|
||||
public const uint Nausea10 = 12987;
|
||||
public const uint Nausea25 = 12968;
|
||||
public const uint Nausea10H = 12988;
|
||||
public const uint Nausea25H = 12981;
|
||||
|
||||
// Blood Prince Council
|
||||
public const uint OrbWhisperer10 = 13033;
|
||||
public const uint OrbWhisperer25 = 12969;
|
||||
public const uint OrbWhisperer10H = 13034;
|
||||
public const uint OrbWhisperer25H = 13032;
|
||||
|
||||
// Blood-Queen Lana'Thel
|
||||
public const uint KillLanaThel10m = 13340;
|
||||
public const uint KillLanaThel25m = 13360;
|
||||
public const uint OnceBittenTwiceShy10 = 12780;
|
||||
public const uint OnceBittenTwiceShy25 = 13012;
|
||||
public const uint OnceBittenTwiceShy10V = 13011;
|
||||
public const uint OnceBittenTwiceShy25V = 13013;
|
||||
}
|
||||
|
||||
struct WeeklyQuestIds
|
||||
{
|
||||
public const uint Deprogramming10 = 24869;
|
||||
public const uint Deprogramming25 = 24875;
|
||||
public const uint SecuringTheRamparts10 = 24870;
|
||||
public const uint SecuringTheRamparts25 = 24877;
|
||||
public const uint ResidueRendezvous10 = 24873;
|
||||
public const uint ResidueRendezvous25 = 24878;
|
||||
public const uint BloodQuickening10 = 24874;
|
||||
public const uint BloodQuickening25 = 24879;
|
||||
public const uint RespiteForATornmentedSoul10 = 24872;
|
||||
public const uint RespiteForATornmentedSoul25 = 24880;
|
||||
}
|
||||
|
||||
struct Actions
|
||||
{
|
||||
// Icecrown Gunship Battle
|
||||
public const int EnemyGunshipTalk = -369390;
|
||||
public const int ExitShip = -369391;
|
||||
|
||||
// Festergut
|
||||
public const int FestergutCombat = -366260;
|
||||
public const int FestergutGas = -366261;
|
||||
public const int FestergutDeath = -366262;
|
||||
|
||||
// Rotface
|
||||
public const int RotfaceCombat = -366270;
|
||||
public const int RotfaceOoze = -366271;
|
||||
public const int RotfaceDeath = -366272;
|
||||
public const int ChangePhase = -366780;
|
||||
|
||||
// Blood-Queen Lana'Thel
|
||||
public const int KillMinchar = -379550;
|
||||
|
||||
// Frostwing Halls Gauntlet Event
|
||||
public const int VrykulDeath = 37129;
|
||||
|
||||
// Sindragosa
|
||||
public const int StartFrostwyrm = -368530;
|
||||
public const int TriggerAsphyxiation = -368531;
|
||||
|
||||
// The Lich King
|
||||
public const int RestoreLight = -72262;
|
||||
public const int FrostmourneIntro = -36823;
|
||||
|
||||
// Sister Svalna
|
||||
public const int KillCaptain = 1;
|
||||
public const int StartGauntlet = 2;
|
||||
public const int ResurrectCaptains = 3;
|
||||
public const int CaptainDies = 4;
|
||||
public const int ResetEvent = 5;
|
||||
}
|
||||
|
||||
struct TeleporterSpells
|
||||
{
|
||||
public const uint LIGHT_S_HAMMER_TELEPORT = 70781;
|
||||
public const uint ORATORY_OF_THE_DAMNED_TELEPORT = 70856;
|
||||
public const uint RAMPART_OF_SKULLS_TELEPORT = 70857;
|
||||
public const uint DEATHBRINGER_S_RISE_TELEPORT = 7085;
|
||||
public const uint UPPER_SPIRE_TELEPORT = 70859;
|
||||
public const uint FROZEN_THRONE_TELEPORT = 70860;
|
||||
public const uint SINDRAGOSA_S_LAIR_TELEPORT = 70861;
|
||||
}
|
||||
|
||||
struct AreaIds
|
||||
{
|
||||
public const uint IcecrownCitadel = 4812;
|
||||
public const uint TheFrozenThrone = 4859;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.DataStorage;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
using Game.Spells;
|
||||
|
||||
namespace Scripts.Northrend.IcecrownCitadel
|
||||
{
|
||||
[Script]
|
||||
class icecrown_citadel_teleport : GameObjectScript
|
||||
{
|
||||
public icecrown_citadel_teleport() : base("icecrown_citadel_teleport") { }
|
||||
|
||||
public class icecrown_citadel_teleportAI : GameObjectAI
|
||||
{
|
||||
public icecrown_citadel_teleportAI(GameObject go) : base(go) { }
|
||||
|
||||
public override bool GossipSelect(Player player, uint menuId, uint gossipListId)
|
||||
{
|
||||
if (gossipListId >= TeleportSpells.Length)
|
||||
return false;
|
||||
|
||||
player.PlayerTalkClass.ClearMenus();
|
||||
player.CLOSE_GOSSIP_MENU();
|
||||
SpellInfo spell = Global.SpellMgr.GetSpellInfo(TeleportSpells[gossipListId]);
|
||||
if (spell == null)
|
||||
return false;
|
||||
|
||||
if (player.IsInCombat())
|
||||
{
|
||||
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, player.GetMapId(), spell.Id, player.GetMap().GenerateLowGuid(HighGuid.Cast));
|
||||
Spell.SendCastResult(player, spell, 0, castId, SpellCastResult.AffectingCombat);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override GameObjectAI GetAI(GameObject go)
|
||||
{
|
||||
return GetInstanceAI<icecrown_citadel_teleportAI>(go, "instance_icecrown_citadel");
|
||||
}
|
||||
|
||||
public const uint GOSSIP_SENDER_ICC_PORT = 631;
|
||||
|
||||
static uint[] TeleportSpells =
|
||||
{
|
||||
TeleporterSpells.LIGHT_S_HAMMER_TELEPORT, // 0
|
||||
TeleporterSpells.ORATORY_OF_THE_DAMNED_TELEPORT, // 1
|
||||
0, // 2
|
||||
TeleporterSpells.RAMPART_OF_SKULLS_TELEPORT, // 3
|
||||
TeleporterSpells.DEATHBRINGER_S_RISE_TELEPORT, // 4
|
||||
TeleporterSpells.UPPER_SPIRE_TELEPORT, // 5
|
||||
TeleporterSpells.SINDRAGOSA_S_LAIR_TELEPORT // 6
|
||||
};
|
||||
}
|
||||
|
||||
[Script]
|
||||
class at_frozen_throne_teleport : AreaTriggerScript
|
||||
{
|
||||
public at_frozen_throne_teleport() : base("at_frozen_throne_teleport") { }
|
||||
|
||||
public override bool OnTrigger(Player player, AreaTriggerRecord areaTrigger, bool entered)
|
||||
{
|
||||
if (player.IsInCombat())
|
||||
{
|
||||
SpellInfo spell = Global.SpellMgr.GetSpellInfo(TeleporterSpells.FROZEN_THRONE_TELEPORT);
|
||||
if (spell != null)
|
||||
{
|
||||
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, player.GetMapId(), spell.Id, player.GetMap().GenerateLowGuid(HighGuid.Cast));
|
||||
Spell.SendCastResult(player, spell, 0, castId, SpellCastResult.AffectingCombat);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
InstanceScript instance = player.GetInstanceScript();
|
||||
if (instance != null)
|
||||
if (instance.GetBossState(Bosses.ProfessorPutricide) == EncounterState.Done &&
|
||||
instance.GetBossState(Bosses.BloodQueenLanaThel) == EncounterState.Done &&
|
||||
instance.GetBossState(Bosses.Sindragosa) == EncounterState.Done &&
|
||||
instance.GetBossState(Bosses.TheLichKing) != EncounterState.InProgress)
|
||||
player.CastSpell(player, TeleporterSpells.FROZEN_THRONE_TELEPORT, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* 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.Movement;
|
||||
using Game.Scripting;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace Scripts.Northrend.IcecrownCitadel
|
||||
{
|
||||
namespace Marrorgar
|
||||
{
|
||||
struct Texts
|
||||
{
|
||||
public const int SayEnterZone = 0;
|
||||
public const int SayAggro = 1;
|
||||
public const int SayBoneStorm = 2;
|
||||
public const int SayBonespike = 3;
|
||||
public const int SayKill = 4;
|
||||
public const int SayDeath = 5;
|
||||
public const int SayBerserk = 6;
|
||||
public const int EmoteBoneStorm = 7;
|
||||
}
|
||||
|
||||
struct Spells
|
||||
{
|
||||
// Lord Marrowgar
|
||||
public const uint BoneSlice = 69055;
|
||||
public const uint BoneStorm = 69076;
|
||||
public const uint BoneSpikeGraveyard = 69057;
|
||||
public const uint ColdflameNormal = 69140;
|
||||
public const uint ColdflameBoneStorm = 72705;
|
||||
|
||||
// Bone Spike
|
||||
public const uint Impaled = 69065;
|
||||
public const uint RideVehicle = 46598;
|
||||
|
||||
// Coldflame
|
||||
public const uint ColdflamePassive = 69145;
|
||||
public const uint ColdflameSummon = 69147;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public static uint[] BoneSpikeSummonId = { 69062, 72669, 72670 };
|
||||
|
||||
public const uint EventBoneSpikeGraveyard = 1;
|
||||
public const uint EventColdflame = 2;
|
||||
public const uint EventBoneStormBegin = 3;
|
||||
public const uint EventBoneStormMove = 4;
|
||||
public const uint EventBoneStormEnd = 5;
|
||||
public const uint EventEnableBoneSlice = 6;
|
||||
public const uint EventEnrage = 7;
|
||||
public const uint EventWarnBoneStorm = 8;
|
||||
|
||||
public const uint EventColdflameTrigger = 9;
|
||||
public const uint EventFailBoned = 10;
|
||||
|
||||
public const uint EventGroupSpecial = 1;
|
||||
|
||||
public const uint PointTargetBonestormPlayer = 36612631;
|
||||
public const uint PointTargetColdflame = 36672631;
|
||||
|
||||
public const int DataColdflameGuid = 0;
|
||||
|
||||
// Manual Marking For Targets Hit By Bone Slice As No Aura Exists For This Purpose
|
||||
// These Units Are The Tanks In This Encounter
|
||||
// And Should Be Immune To Bone Spike Graveyard
|
||||
public const int DataSpikeImmune = 1;
|
||||
//DataSpikeImmune1; = 2; // Reserved & Used
|
||||
//DataSpikeImmune2; = 3; // Reserved & Used
|
||||
|
||||
public const int ActionClearSpikeImmunities = 1;
|
||||
|
||||
public const uint MaxBoneSpikeImmune = 3;
|
||||
}
|
||||
|
||||
class BoneSpikeTargetSelector : ISelector
|
||||
{
|
||||
public BoneSpikeTargetSelector(UnitAI ai)
|
||||
{
|
||||
_ai = ai;
|
||||
}
|
||||
|
||||
public bool Check(Unit unit)
|
||||
{
|
||||
if (!unit.IsTypeId(TypeId.Player))
|
||||
return false;
|
||||
|
||||
if (unit.HasAura(Spells.Impaled))
|
||||
return false;
|
||||
|
||||
// Check if it is one of the tanks soaking Bone Slice
|
||||
for (int i = 0; i < Misc.MaxBoneSpikeImmune; ++i)
|
||||
if (unit.GetGUID() == _ai.GetGUID(Misc.DataSpikeImmune + i))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
UnitAI _ai;
|
||||
}
|
||||
|
||||
[Script]
|
||||
public class boss_lord_marrowgar : BossAI
|
||||
{
|
||||
public boss_lord_marrowgar(Creature creature) : base(creature, Bosses.LordMarrowgar)
|
||||
{
|
||||
_boneStormDuration = RaidMode<uint>(20000, 30000, 20000, 30000);
|
||||
_baseSpeed = creature.GetSpeedRate(UnitMoveType.Run);
|
||||
_coldflameLastPos.Relocate(creature);
|
||||
_introDone = false;
|
||||
_boneSlice = false;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
me.SetSpeedRate(UnitMoveType.Run, _baseSpeed);
|
||||
me.RemoveAurasDueToSpell(Spells.BoneStorm);
|
||||
me.RemoveAurasDueToSpell(InstanceSpells.Berserk);
|
||||
|
||||
_events.ScheduleEvent(Misc.EventEnableBoneSlice, 10000);
|
||||
_events.ScheduleEvent(Misc.EventBoneSpikeGraveyard, 15000, Misc.EventGroupSpecial);
|
||||
_events.ScheduleEvent(Misc.EventColdflame, 5000, Misc.EventGroupSpecial);
|
||||
_events.ScheduleEvent(Misc.EventWarnBoneStorm, RandomHelper.URand(45000, 50000));
|
||||
_events.ScheduleEvent(Misc.EventEnrage, 600000);
|
||||
_boneSlice = false;
|
||||
_boneSpikeImmune.Clear();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
Talk(Texts.SayAggro);
|
||||
|
||||
me.setActive(true);
|
||||
DoZoneInCombat();
|
||||
instance.SetBossState(Bosses.LordMarrowgar, EncounterState.InProgress);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Talk(Texts.SayDeath);
|
||||
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
public override void JustReachedHome()
|
||||
{
|
||||
_JustReachedHome();
|
||||
instance.SetBossState(Bosses.LordMarrowgar, EncounterState.Fail);
|
||||
instance.SetData(DataTypes.BonedAchievement, 1); // reset
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
if (victim.IsTypeId(TypeId.Player))
|
||||
Talk(Texts.SayKill);
|
||||
}
|
||||
|
||||
public override void MoveInLineOfSight(Unit who)
|
||||
{
|
||||
if (!_introDone && me.IsWithinDistInMap(who, 70.0f))
|
||||
{
|
||||
Talk(Texts.SayEnterZone);
|
||||
_introDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case Misc.EventBoneSpikeGraveyard:
|
||||
if (IsHeroic() || !me.HasAura(Spells.BoneStorm))
|
||||
DoCast(me, Spells.BoneSpikeGraveyard);
|
||||
_events.ScheduleEvent(Misc.EventBoneSpikeGraveyard, RandomHelper.URand(15000, 20000), Misc.EventGroupSpecial);
|
||||
break;
|
||||
case Misc.EventColdflame:
|
||||
_coldflameLastPos.Relocate(me);
|
||||
_coldflameTarget.Clear();
|
||||
if (!me.HasAura(Spells.BoneStorm))
|
||||
DoCastAOE(Spells.ColdflameNormal);
|
||||
else
|
||||
DoCast(me, Spells.ColdflameBoneStorm);
|
||||
_events.ScheduleEvent(Misc.EventColdflame, 5000, Misc.EventGroupSpecial);
|
||||
break;
|
||||
case Misc.EventWarnBoneStorm:
|
||||
_boneSlice = false;
|
||||
Talk(Texts.SayBoneStorm);
|
||||
me.FinishSpell(CurrentSpellTypes.Melee, false);
|
||||
DoCast(me, Spells.BoneStorm);
|
||||
_events.DelayEvents(3000, Misc.EventGroupSpecial);
|
||||
_events.ScheduleEvent(Misc.EventBoneStormBegin, 3050);
|
||||
_events.ScheduleEvent(Misc.EventWarnBoneStorm, RandomHelper.URand(90000, 95000));
|
||||
break;
|
||||
case Misc.EventBoneStormBegin:
|
||||
Aura pStorm = me.GetAura(Spells.BoneStorm);
|
||||
if (pStorm != null)
|
||||
pStorm.SetDuration((int)_boneStormDuration);
|
||||
me.SetSpeedRate(UnitMoveType.Run, _baseSpeed * 3.0f);
|
||||
Talk(Texts.SayBoneStorm);
|
||||
_events.ScheduleEvent(Misc.EventBoneStormEnd, _boneStormDuration + 1);
|
||||
goto case Misc.EventBoneStormMove;
|
||||
// no break here
|
||||
case Misc.EventBoneStormMove:
|
||||
{
|
||||
_events.ScheduleEvent(Misc.EventBoneStormMove, _boneStormDuration / 3);
|
||||
Unit unit = SelectTarget(SelectAggroTarget.Random, 0, new NonTankTargetSelector(me));
|
||||
if (!unit)
|
||||
unit = SelectTarget(SelectAggroTarget.Random, 0, 0.0f, true);
|
||||
if (unit)
|
||||
me.GetMotionMaster().MovePoint(Misc.PointTargetBonestormPlayer, unit);
|
||||
break;
|
||||
}
|
||||
case Misc.EventBoneStormEnd:
|
||||
if (me.GetMotionMaster().GetCurrentMovementGeneratorType() == MovementGeneratorType.Point)
|
||||
me.GetMotionMaster().MovementExpired();
|
||||
me.GetMotionMaster().MoveChase(me.GetVictim());
|
||||
me.SetSpeedRate(UnitMoveType.Run, _baseSpeed);
|
||||
_events.CancelEvent(Misc.EventBoneStormMove);
|
||||
_events.ScheduleEvent(Misc.EventEnableBoneSlice, 10000);
|
||||
if (!IsHeroic())
|
||||
_events.RescheduleEvent(Misc.EventBoneSpikeGraveyard, 15000, Misc.EventGroupSpecial);
|
||||
break;
|
||||
case Misc.EventEnableBoneSlice:
|
||||
_boneSlice = true;
|
||||
break;
|
||||
case Misc.EventEnrage:
|
||||
DoCast(me, Texts.SayBerserk, true);
|
||||
Talk(Texts.SayBerserk);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// We should not melee attack when storming
|
||||
if (me.HasAura(Spells.BoneStorm))
|
||||
return;
|
||||
|
||||
// 10 seconds since encounter start Bone Slice replaces melee attacks
|
||||
if (_boneSlice && !me.GetCurrentSpell(CurrentSpellTypes.Melee))
|
||||
DoCastVictim(Spells.BoneSlice);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
if (type != MovementGeneratorType.Point || id != Misc.PointTargetBonestormPlayer)
|
||||
return;
|
||||
|
||||
// lock movement
|
||||
me.GetMotionMaster().MoveIdle();
|
||||
}
|
||||
|
||||
public Position GetLastColdflamePosition()
|
||||
{
|
||||
return _coldflameLastPos;
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGUID(int type = 0)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Misc.DataColdflameGuid:
|
||||
return _coldflameTarget;
|
||||
case Misc.DataSpikeImmune + 0:
|
||||
case Misc.DataSpikeImmune + 1:
|
||||
case Misc.DataSpikeImmune + 2:
|
||||
{
|
||||
int index = type - Misc.DataSpikeImmune;
|
||||
if (index < _boneSpikeImmune.Count)
|
||||
return _boneSpikeImmune[index];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
public override void SetGUID(ObjectGuid guid, int type = 0)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Misc.DataColdflameGuid:
|
||||
_coldflameTarget = guid;
|
||||
break;
|
||||
case Misc.DataSpikeImmune:
|
||||
_boneSpikeImmune.Add(guid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
if (action != Misc.ActionClearSpikeImmunities)
|
||||
return;
|
||||
|
||||
_boneSpikeImmune.Clear();
|
||||
}
|
||||
|
||||
Position _coldflameLastPos = new Position();
|
||||
List<ObjectGuid> _boneSpikeImmune = new List<ObjectGuid>();
|
||||
ObjectGuid _coldflameTarget;
|
||||
uint _boneStormDuration;
|
||||
float _baseSpeed;
|
||||
bool _introDone;
|
||||
bool _boneSlice;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_coldflame : ScriptedAI
|
||||
{
|
||||
public npc_coldflame(Creature creature) : base(creature) { }
|
||||
|
||||
public override void IsSummonedBy(Unit owner)
|
||||
{
|
||||
if (!owner.IsTypeId(TypeId.Player))
|
||||
return;
|
||||
|
||||
Position pos = new Position();
|
||||
var marrowgarAI = (boss_lord_marrowgar)owner.GetAI();
|
||||
if (marrowgarAI != null)
|
||||
pos.Relocate(marrowgarAI.GetLastColdflamePosition());
|
||||
else
|
||||
pos.Relocate(owner);
|
||||
|
||||
if (owner.HasAura(Spells.BoneStorm))
|
||||
{
|
||||
float ang = Position.NormalizeOrientation(pos.GetAngle(me));
|
||||
me.SetOrientation(ang);
|
||||
owner.GetNearPoint2D(out pos.posX, out pos.posY, 5.0f - owner.GetObjectSize(), ang);
|
||||
}
|
||||
else
|
||||
{
|
||||
Player target = Global.ObjAccessor.GetPlayer(owner, owner.GetAI().GetGUID(Misc.DataColdflameGuid));
|
||||
if (!target)
|
||||
{
|
||||
me.DespawnOrUnsummon();
|
||||
return;
|
||||
}
|
||||
|
||||
float ang = Position.NormalizeOrientation(pos.GetAngle(target));
|
||||
me.SetOrientation(ang);
|
||||
owner.GetNearPoint2D(out pos.posX, out pos.posY, 15.0f - owner.GetObjectSize(), ang);
|
||||
}
|
||||
|
||||
me.NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), me.GetPositionZ(), me.GetOrientation());
|
||||
DoCast(Spells.ColdflameSummon);
|
||||
_events.ScheduleEvent(Misc.EventColdflameTrigger, 500);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
if (_events.ExecuteEvent() == Misc.EventColdflameTrigger)
|
||||
{
|
||||
Position newPos = me.GetNearPosition(5.0f, 0.0f);
|
||||
me.NearTeleportTo(newPos.GetPositionX(), newPos.GetPositionY(), me.GetPositionZ(), me.GetOrientation());
|
||||
DoCast(Spells.ColdflameSummon);
|
||||
_events.ScheduleEvent(Misc.EventColdflameTrigger, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_bone_spike : ScriptedAI
|
||||
{
|
||||
public npc_bone_spike(Creature creature)
|
||||
: base(creature)
|
||||
{
|
||||
_hasTrappedUnit = false;
|
||||
Contract.Assert(creature.GetVehicleKit());
|
||||
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
TempSummon summ = me.ToTempSummon();
|
||||
if (summ)
|
||||
{
|
||||
Unit trapped = summ.GetSummoner();
|
||||
if (trapped)
|
||||
trapped.RemoveAurasDueToSpell(Spells.Impaled);
|
||||
}
|
||||
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit victim)
|
||||
{
|
||||
me.DespawnOrUnsummon();
|
||||
victim.RemoveAurasDueToSpell(Spells.Impaled);
|
||||
}
|
||||
|
||||
public override void IsSummonedBy(Unit summoner)
|
||||
{
|
||||
DoCast(summoner, Spells.Impaled);
|
||||
summoner.CastSpell(me, Spells.RideVehicle, true);
|
||||
_events.ScheduleEvent(Misc.EventFailBoned, 8000);
|
||||
_hasTrappedUnit = true;
|
||||
}
|
||||
|
||||
public override void PassengerBoarded(Unit passenger, sbyte seat, bool apply)
|
||||
{
|
||||
if (!apply)
|
||||
return;
|
||||
|
||||
// @HACK - Change passenger offset to the one taken directly from sniffs
|
||||
// Remove this when proper calculations are implemented.
|
||||
// This fixes healing spiked people
|
||||
MoveSplineInit init = new MoveSplineInit(passenger);
|
||||
init.DisableTransportPathTransformations();
|
||||
init.MoveTo(-0.02206125f, -0.02132235f, 5.514783f, false);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!_hasTrappedUnit)
|
||||
return;
|
||||
|
||||
_events.Update(diff);
|
||||
|
||||
if (_events.ExecuteEvent() == Misc.EventFailBoned)
|
||||
{
|
||||
InstanceScript instance = me.GetInstanceScript();
|
||||
if (instance != null)
|
||||
instance.SetData(DataTypes.BonedAchievement, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool _hasTrappedUnit;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_marrowgar_coldflame : SpellScript
|
||||
{
|
||||
void SelectTarget(List<WorldObject> targets)
|
||||
{
|
||||
targets.Clear();
|
||||
// select any unit but not the tank (by owners threatlist)
|
||||
Unit target = GetCaster().GetAI().SelectTarget(SelectAggroTarget.Random, 1, -GetCaster().GetObjectSize(), true, -(int)Spells.Impaled);
|
||||
if (!target)
|
||||
target = GetCaster().GetAI().SelectTarget(SelectAggroTarget.Random, 0, 0.0f, true); // or the tank if its solo
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
GetCaster().GetAI().SetGUID(target.GetGUID(), Misc.DataColdflameGuid);
|
||||
|
||||
targets.Add(target);
|
||||
}
|
||||
|
||||
void HandleScriptEffect(uint effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
GetCaster().CastSpell(GetHitUnit(), (uint)GetEffectValue(), true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(SelectTarget, 0, Targets.UnitDestAreaEnemy));
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_marrowgar_coldflame_bonestorm : SpellScript
|
||||
{
|
||||
void HandleScriptEffect(uint effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
for (byte i = 0; i < 4; ++i)
|
||||
GetCaster().CastSpell(GetHitUnit(), (uint)(GetEffectValue() + i), true);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScriptEffect, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_marrowgar_coldflame_damage : AuraScript
|
||||
{
|
||||
bool CanBeAppliedOn(Unit target)
|
||||
{
|
||||
if (target.HasAura(Spells.Impaled))
|
||||
return false;
|
||||
|
||||
if (target.GetExactDist2d(GetOwner()) > GetSpellInfo().GetEffect(target.GetMap().GetDifficultyID(), 0).CalcRadius())
|
||||
return false;
|
||||
|
||||
Aura aur = target.GetAura(GetId());
|
||||
if (aur != null)
|
||||
if (aur.GetOwner() != GetOwner())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
DoCheckAreaTarget.Add(new CheckAreaTargetHandler(CanBeAppliedOn));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_marrowgar_bone_spike_graveyard : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(Misc.BoneSpikeSummonId);
|
||||
}
|
||||
|
||||
public override bool Load()
|
||||
{
|
||||
return GetCaster().IsTypeId(TypeId.Unit) && GetCaster().IsAIEnabled;
|
||||
}
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
return GetCaster().GetAI().SelectTarget(SelectAggroTarget.Random, 0, new BoneSpikeTargetSelector(GetCaster().GetAI())) ? SpellCastResult.SpellCastOk : SpellCastResult.NoValidTargets;
|
||||
}
|
||||
|
||||
void HandleSpikes(uint effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
Creature marrowgar = GetCaster().ToCreature();
|
||||
if (marrowgar)
|
||||
{
|
||||
CreatureAI marrowgarAI = marrowgar.GetAI();
|
||||
byte boneSpikeCount = (byte)(Convert.ToBoolean((int)GetCaster().GetMap().GetSpawnMode() & 1) ? 3 : 1);
|
||||
|
||||
List<Unit> targets = marrowgarAI.SelectTargetList(new BoneSpikeTargetSelector(marrowgarAI), boneSpikeCount, SelectAggroTarget.Random);
|
||||
if (targets.Empty())
|
||||
return;
|
||||
|
||||
uint i = 0;
|
||||
foreach (var target in targets)
|
||||
{
|
||||
target.CastSpell(target, Misc.BoneSpikeSummonId[i], true);
|
||||
i++;
|
||||
}
|
||||
|
||||
marrowgarAI.Talk(Texts.SayBonespike);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnCheckCast.Add(new CheckCastHandler(CheckCast));
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleSpikes, 1, SpellEffectName.ApplyAura));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_marrowgar_bone_storm : SpellScript
|
||||
{
|
||||
void RecalculateDamage()
|
||||
{
|
||||
SetHitDamage((int)(GetHitDamage() / Math.Max(Math.Sqrt(GetHitUnit().GetExactDist2d(GetCaster())), 1.0f)));
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnHit.Add(new HitHandler(RecalculateDamage));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_marrowgar_bone_slice : SpellScript
|
||||
{
|
||||
public override bool Load()
|
||||
{
|
||||
_targetCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClearSpikeImmunities()
|
||||
{
|
||||
GetCaster().GetAI().DoAction(Misc.ActionClearSpikeImmunities);
|
||||
}
|
||||
|
||||
void CountTargets(List<WorldObject> targets)
|
||||
{
|
||||
_targetCount = (uint)Math.Min(targets.Count, GetSpellInfo().MaxAffectedTargets);
|
||||
}
|
||||
|
||||
void SplitDamage()
|
||||
{
|
||||
// Mark the unit as hit, even if the spell missed or was dodged/parried
|
||||
GetCaster().GetAI().SetGUID(GetHitUnit().GetGUID(), Misc.DataSpikeImmune);
|
||||
|
||||
if (_targetCount == 0)
|
||||
return; // This spell can miss all targets
|
||||
|
||||
SetHitDamage((int)(GetHitDamage() / _targetCount));
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
BeforeCast.Add(new CastHandler(ClearSpikeImmunities));
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(CountTargets, 0, Targets.UnitDestAreaEnemy));
|
||||
OnHit.Add(new HitHandler(SplitDamage));
|
||||
}
|
||||
|
||||
uint _targetCount;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 Game.Entities;
|
||||
|
||||
namespace Scripts.Northrend.IcecrownCitadel
|
||||
{
|
||||
public class Sindragosa
|
||||
{
|
||||
Position RimefangFlyPos = new Position(4413.309f, 2456.421f, 233.3795f, 2.890186f);
|
||||
Position RimefangLandPos = new Position(4413.309f, 2456.421f, 203.3848f, 2.890186f);
|
||||
Position SpinestalkerFlyPos = new Position(4418.895f, 2514.233f, 230.4864f, 3.396045f);
|
||||
Position SpinestalkerLandPos = new Position(4418.895f, 2514.233f, 203.3848f, 3.396045f);
|
||||
public static Position SindragosaSpawnPos = new Position(4818.700f, 2483.710f, 287.0650f, 3.089233f);
|
||||
Position SindragosaFlyPos = new Position(4475.190f, 2484.570f, 234.8510f, 3.141593f);
|
||||
Position SindragosaLandPos = new Position(4419.190f, 2484.570f, 203.3848f, 3.141593f);
|
||||
Position SindragosaAirPos = new Position(4475.990f, 2484.430f, 247.9340f, 3.141593f);
|
||||
Position SindragosaAirPosFar = new Position(4525.600f, 2485.150f, 245.0820f, 3.141593f);
|
||||
Position SindragosaFlyInPos = new Position(4419.190f, 2484.360f, 232.5150f, 3.141593f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 Game.Entities;
|
||||
|
||||
namespace Scripts.Northrend.IcecrownCitadel
|
||||
{
|
||||
public class TheLichKing
|
||||
{
|
||||
Position CenterPosition = new Position(503.6282f, -2124.655f, 840.8569f, 0.0f);
|
||||
Position TirionIntro = new Position(489.2970f, -2124.840f, 840.8569f, 0.0f);
|
||||
Position TirionCharge = new Position(482.9019f, -2124.479f, 840.8570f, 0.0f);
|
||||
Position[] LichKingIntro =
|
||||
{
|
||||
new Position(432.0851f, -2123.673f, 864.6582f, 0.0f),
|
||||
new Position(457.8351f, -2123.423f, 841.1582f, 0.0f),
|
||||
new Position(465.0730f, -2123.470f, 840.8569f, 0.0f),
|
||||
};
|
||||
Position OutroPosition1 = new Position(493.6286f, -2124.569f, 840.8569f, 0.0f);
|
||||
Position OutroFlying = new Position(508.9897f, -2124.561f, 845.3565f, 0.0f);
|
||||
public static Position TerenasSpawn = new Position(495.5542f, -2517.012f, 1050.000f, 4.6993f);
|
||||
Position TerenasSpawnHeroic = new Position(495.7080f, -2523.760f, 1050.000f, 0.0f);
|
||||
public static Position SpiritWardenSpawn = new Position(495.3406f, -2529.983f, 1050.000f, 1.5592f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 Game.Entities;
|
||||
|
||||
namespace Scripts.Northrend.IcecrownCitadel
|
||||
{
|
||||
public class ValithriaDreamwalker
|
||||
{
|
||||
public static Position ValithriaSpawnPos = new Position(4210.813f, 2484.443f, 364.9558f, 0.01745329f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Scripts.Northrend.Naxxramas
|
||||
{
|
||||
struct TextIds
|
||||
{
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SayGreet = 1;
|
||||
public const uint SaySlay = 2;
|
||||
|
||||
public const uint EmoteLocust = 3;
|
||||
|
||||
public const uint EmoteFrenzy = 0;
|
||||
public const uint EmoteSpawn = 1;
|
||||
public const uint EmoteScarab = 2;
|
||||
}
|
||||
|
||||
struct EventIds
|
||||
{
|
||||
public const uint Impale = 1; // Cast Impale On A Random Target
|
||||
public const uint Locust = 2; // Begin Channeling Locust Swarm
|
||||
public const uint LocustEnds = 3; // Locust Swarm Dissipates
|
||||
public const uint SpawnGuard = 4; // 10-Man Only - Crypt Guard Has Delayed Spawn; Also Used For The Locust Swarm Crypt Guard In Both Modes
|
||||
public const uint Scarabs = 5; // Spawn Corpse Scarabs
|
||||
public const uint Berserk = 6; // Berserk
|
||||
}
|
||||
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint Impale = 28783; // 25-Man: 56090
|
||||
public const uint LocustSwarm = 28785; // 25-Man: 54021
|
||||
public const uint SummonCorpseScarabsPlr = 29105; // This Spawns 5 Corpse Scarabs On Top Of Player
|
||||
public const uint SummonCorpseScarabsMob = 28864; // This Spawns 10 Corpse Scarabs On Top Of Dead Guards
|
||||
public const uint Berserk = 27680;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint achievTimedStartEvent = 9891;
|
||||
|
||||
public const uint PhaseNormal = 1;
|
||||
public const uint PhaseSwarm = 2;
|
||||
|
||||
public const uint SpawnGroupsInitial25M = 1;
|
||||
public const uint SpawnGroupsSingleSpawn = 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Scripts.Northrend.Nexus.EyeOfEternity
|
||||
{
|
||||
class BossMalygos
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* 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 Framework.GameMath;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Scripts.Northrend.Nexus.EyeOfEternity
|
||||
{
|
||||
struct EyeOfEternityConst
|
||||
{
|
||||
public const uint MaxEncounter = 1;
|
||||
public const uint EventFocusingIris = 20711;
|
||||
}
|
||||
|
||||
struct InstanceData
|
||||
{
|
||||
public const uint MalygosEvent = 1;
|
||||
public const uint VortexHandling = 2;
|
||||
public const uint PowerSparksHandling = 3;
|
||||
public const uint RespawnIris = 4;
|
||||
}
|
||||
|
||||
struct InstanceData64
|
||||
{
|
||||
public const uint Trigger = 0;
|
||||
public const uint Malygos = 1;
|
||||
public const uint Platform = 2;
|
||||
public const uint AlexstraszaBunnyGUID = 3;
|
||||
public const uint HeartOfMagicGUID = 4;
|
||||
public const uint FocusingIrisGUID = 5;
|
||||
public const uint GiftBoxBunnyGUID = 6;
|
||||
}
|
||||
|
||||
struct InstanceNpcs
|
||||
{
|
||||
public const uint Malygos = 28859;
|
||||
public const uint VortexTrigger = 30090;
|
||||
public const uint PortalTrigger = 30118;
|
||||
public const uint PowerSpark = 30084;
|
||||
public const uint HoverDiskMelee = 30234;
|
||||
public const uint HoverDiskCaster = 30248;
|
||||
public const uint ArcaneOverload = 30282;
|
||||
public const uint WyrmrestSkytalon = 30161;
|
||||
public const uint Alexstrasza = 32295;
|
||||
public const uint AlexstraszaBunny = 31253;
|
||||
public const uint AlexstraszasGift = 32448;
|
||||
public const uint SurgeOfPower = 30334;
|
||||
}
|
||||
|
||||
struct InstanceGameObjects
|
||||
{
|
||||
public const uint NexusRaidPlatform = 193070;
|
||||
public const uint ExitPortal = 193908;
|
||||
public const uint FocusingIris10 = 193958;
|
||||
public const uint FocusingIris25 = 193960;
|
||||
public const uint AlexstraszaSGift10 = 193905;
|
||||
public const uint AlexstraszaSGift25 = 193967;
|
||||
public const uint HeartOfMagic10 = 194158;
|
||||
public const uint HeartOfMagic25 = 194159;
|
||||
}
|
||||
|
||||
struct InstanceSpells
|
||||
{
|
||||
public const uint Vortex4 = 55853; // Damage | Used To Enter To The Vehicle
|
||||
public const uint Vortex5 = 56263; // Damage | Used To Enter To The Vehicle
|
||||
public const uint PortalOpened = 61236;
|
||||
public const uint RideRedDragonTriggered = 56072;
|
||||
public const uint IrisOpened = 61012; // Visual When Starting Encounter
|
||||
public const uint SummomRedDragonBuddy = 56070;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class instance_eye_of_eternity : InstanceMapScript
|
||||
{
|
||||
public instance_eye_of_eternity() : base("instance_eye_of_eternity", 616) { }
|
||||
|
||||
class instance_eye_of_eternity_InstanceMapScript : InstanceScript
|
||||
{
|
||||
public instance_eye_of_eternity_InstanceMapScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("EOE");
|
||||
SetBossNumber(EyeOfEternityConst.MaxEncounter);
|
||||
}
|
||||
|
||||
public override void OnPlayerEnter(Player player)
|
||||
{
|
||||
if (GetBossState(0) == EncounterState.Done)
|
||||
player.CastSpell(player, InstanceSpells.SummomRedDragonBuddy, true);
|
||||
}
|
||||
|
||||
public override bool SetBossState(uint type, EncounterState state)
|
||||
{
|
||||
if (!base.SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
if (type == InstanceData.MalygosEvent)
|
||||
{
|
||||
if (state == EncounterState.Fail)
|
||||
{
|
||||
foreach (var triggerGuid in portalTriggers)
|
||||
{
|
||||
Creature trigger = instance.GetCreature(triggerGuid);
|
||||
if (trigger)
|
||||
{
|
||||
// just in case
|
||||
trigger.RemoveAllAuras();
|
||||
trigger.GetAI().Reset();
|
||||
}
|
||||
}
|
||||
|
||||
SpawnGameObject(InstanceGameObjects.ExitPortal, exitPortalPosition);
|
||||
|
||||
GameObject platform = instance.GetGameObject(platformGUID);
|
||||
if (platform)
|
||||
platform.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.Destroyed);
|
||||
}
|
||||
else if (state == EncounterState.Done)
|
||||
SpawnGameObject(InstanceGameObjects.ExitPortal, exitPortalPosition);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @todo this should be handled in map, maybe add a summon function in map
|
||||
// There is no other way afaik...
|
||||
void SpawnGameObject(uint entry, Position pos)
|
||||
{
|
||||
GameObject go = new GameObject();
|
||||
if (go.Create(entry, instance, PhaseMasks.Normal, pos, Quaternion.WAxis, 255, GameObjectState.Ready))
|
||||
instance.AddToMap(go);
|
||||
}
|
||||
|
||||
public override void OnGameObjectCreate(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case InstanceGameObjects.NexusRaidPlatform:
|
||||
platformGUID = go.GetGUID();
|
||||
break;
|
||||
case InstanceGameObjects.FocusingIris10:
|
||||
case InstanceGameObjects.FocusingIris25:
|
||||
irisGUID = go.GetGUID();
|
||||
focusingIrisPosition = go.GetPosition();
|
||||
break;
|
||||
case InstanceGameObjects.ExitPortal:
|
||||
exitPortalGUID = go.GetGUID();
|
||||
exitPortalPosition = go.GetPosition();
|
||||
break;
|
||||
case InstanceGameObjects.HeartOfMagic10:
|
||||
case InstanceGameObjects.HeartOfMagic25:
|
||||
heartOfMagicGUID = go.GetGUID();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
case InstanceNpcs.VortexTrigger:
|
||||
vortexTriggers.Add(creature.GetGUID());
|
||||
break;
|
||||
case InstanceNpcs.Malygos:
|
||||
malygosGUID = creature.GetGUID();
|
||||
break;
|
||||
case InstanceNpcs.PortalTrigger:
|
||||
portalTriggers.Add(creature.GetGUID());
|
||||
break;
|
||||
case InstanceNpcs.AlexstraszaBunny:
|
||||
alexstraszaBunnyGUID = creature.GetGUID();
|
||||
break;
|
||||
case InstanceNpcs.AlexstraszasGift:
|
||||
giftBoxBunnyGUID = creature.GetGUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnUnitDeath(Unit unit)
|
||||
{
|
||||
if (!unit.IsTypeId(TypeId.Player))
|
||||
return;
|
||||
|
||||
// Player continues to be moving after death no matter if spline will be cleared along with all movements,
|
||||
// so on next world tick was all about delay if box will pop or not (when new movement will be registered)
|
||||
// since in EoE you never stop falling. However root at this precise* moment works,
|
||||
// it will get cleared on release. If by any chance some lag happen "Reload()" and "RepopMe()" works,
|
||||
// last test I made now gave me 50/0 of this bug so I can't do more about it.
|
||||
unit.SetControlled(true, UnitState.Root);
|
||||
}
|
||||
|
||||
public override void ProcessEvent(WorldObject obj, uint eventId)
|
||||
{
|
||||
if (eventId == EyeOfEternityConst.EventFocusingIris)
|
||||
{
|
||||
Creature alexstraszaBunny = instance.GetCreature(alexstraszaBunnyGUID);
|
||||
if (alexstraszaBunny)
|
||||
alexstraszaBunny.CastSpell(alexstraszaBunny, InstanceSpells.IrisOpened);
|
||||
|
||||
GameObject iris = instance.GetGameObject(irisGUID);
|
||||
if (iris)
|
||||
iris.SetFlag(GameObjectFields.Flags, GameObjectFlags.InUse);
|
||||
|
||||
Creature malygos = instance.GetCreature(malygosGUID);
|
||||
if (malygos)
|
||||
malygos.GetAI().DoAction(0); // ACTION_LAND_ENCOUNTER_START
|
||||
|
||||
GameObject exitPortal = instance.GetGameObject(exitPortalGUID);
|
||||
if (exitPortal)
|
||||
exitPortal.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
void VortexHandling()
|
||||
{
|
||||
Creature malygos = instance.GetCreature(malygosGUID);
|
||||
if (malygos)
|
||||
{
|
||||
var threatList = malygos.GetThreatManager().getThreatList();
|
||||
foreach (var guid in vortexTriggers)
|
||||
{
|
||||
if (threatList.Empty())
|
||||
return;
|
||||
|
||||
byte counter = 0;
|
||||
Creature trigger = instance.GetCreature(guid);
|
||||
if (trigger)
|
||||
{
|
||||
// each trigger have to cast the spell to 5 players.
|
||||
foreach (var refe in threatList)
|
||||
{
|
||||
if (counter >= 5)
|
||||
break;
|
||||
|
||||
Unit target = refe.getTarget();
|
||||
if (target)
|
||||
{
|
||||
Player player = target.ToPlayer();
|
||||
|
||||
if (!player || player.IsGameMaster() || player.HasAura(InstanceSpells.Vortex4))
|
||||
continue;
|
||||
|
||||
player.CastSpell(trigger, InstanceSpells.Vortex4, true);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PowerSparksHandling()
|
||||
{
|
||||
bool next = (lastPortalGUID == portalTriggers.Last() || !lastPortalGUID.IsEmpty() ? true : false);
|
||||
|
||||
foreach (var guid in portalTriggers)
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
Creature trigger = instance.GetCreature(guid);
|
||||
if (trigger)
|
||||
{
|
||||
lastPortalGUID = trigger.GetGUID();
|
||||
trigger.CastSpell(trigger, InstanceSpells.PortalOpened, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (guid == lastPortalGUID)
|
||||
next = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetData(uint data, uint value)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case InstanceData.VortexHandling:
|
||||
VortexHandling();
|
||||
break;
|
||||
case InstanceData.PowerSparksHandling:
|
||||
PowerSparksHandling();
|
||||
break;
|
||||
case InstanceData.RespawnIris:
|
||||
SpawnGameObject(instance.GetDifficultyID() == Difficulty.Raid10N ? InstanceGameObjects.FocusingIris10 : InstanceGameObjects.FocusingIris25, focusingIrisPosition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGuidData(uint data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case InstanceData64.Trigger:
|
||||
return vortexTriggers.First();
|
||||
case InstanceData64.Malygos:
|
||||
return malygosGUID;
|
||||
case InstanceData64.Platform:
|
||||
return platformGUID;
|
||||
case InstanceData64.AlexstraszaBunnyGUID:
|
||||
return alexstraszaBunnyGUID;
|
||||
case InstanceData64.HeartOfMagicGUID:
|
||||
return heartOfMagicGUID;
|
||||
case InstanceData64.FocusingIrisGUID:
|
||||
return irisGUID;
|
||||
case InstanceData64.GiftBoxBunnyGUID:
|
||||
return giftBoxBunnyGUID;
|
||||
}
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
List<ObjectGuid> vortexTriggers = new List<ObjectGuid>();
|
||||
List<ObjectGuid> portalTriggers = new List<ObjectGuid>();
|
||||
ObjectGuid malygosGUID;
|
||||
ObjectGuid irisGUID;
|
||||
ObjectGuid lastPortalGUID;
|
||||
ObjectGuid platformGUID;
|
||||
ObjectGuid exitPortalGUID;
|
||||
ObjectGuid heartOfMagicGUID;
|
||||
ObjectGuid alexstraszaBunnyGUID;
|
||||
ObjectGuid giftBoxBunnyGUID;
|
||||
Position focusingIrisPosition;
|
||||
Position exitPortalPosition;
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_eye_of_eternity_InstanceMapScript(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* 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 System;
|
||||
|
||||
namespace Scripts.Northrend.Nexus.Nexus
|
||||
{
|
||||
struct AnomalusConst
|
||||
{
|
||||
//Spells
|
||||
public const uint SpellSpark = 47751;
|
||||
public const uint SpellSparkHeroic = 57062;
|
||||
public const uint SpellRiftShield = 47748;
|
||||
public const uint SpellChargeRift = 47747; // Works Wrong (Affect Players; Not Rifts)
|
||||
public const uint SpellCreateRift = 47743; // Don'T Work; Using Wa
|
||||
public const uint SpellArcaneAttraction = 57063; // No Idea; When It'S Used
|
||||
|
||||
public const uint SpellChaoticEnergyBurst = 47688;
|
||||
public const uint SpellChargedChaoticEnergyBurst = 47737;
|
||||
public const uint SpellArcaneform = 48019; // Chaotic Rift Visual
|
||||
|
||||
//Texts
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SayDeath = 1;
|
||||
public const uint SayRift = 2;
|
||||
public const uint SayShield = 3;
|
||||
public const uint SayRiftEmote = 4; // Needs To Be Added To Script
|
||||
public const uint SayShieldEmote = 5; // Needs To Be Added To Script
|
||||
|
||||
//Misc
|
||||
public const uint NpcCrazedManaWraith = 26746;
|
||||
public const uint NpcChaoticRift = 26918;
|
||||
|
||||
public const uint DataChaosTheory = 1;
|
||||
|
||||
public static Position[] RiftLocation =
|
||||
{
|
||||
new Position(652.64f, -273.70f, -8.75f, 0.0f),
|
||||
new Position(634.45f, -265.94f, -8.44f, 0.0f),
|
||||
new Position(620.73f, -281.17f, -9.02f, 0.0f),
|
||||
new Position(626.10f, -304.67f, -9.44f, 0.0f),
|
||||
new Position(639.87f, -314.11f, -9.49f, 0.0f),
|
||||
new Position(651.72f, -297.44f, -9.37f, 0.0f)
|
||||
};
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_anomalus : ScriptedAI
|
||||
{
|
||||
public boss_anomalus(Creature creature) : base(creature)
|
||||
{
|
||||
instance = me.GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, AnomalusConst.SpellSpark);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(5));
|
||||
});
|
||||
|
||||
Phase = 0;
|
||||
uiChaoticRiftGUID.Clear();
|
||||
chaosTheory = true;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
|
||||
instance.SetBossState(DataTypes.Anomalus, EncounterState.NotStarted);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
Talk(AnomalusConst.SayAggro);
|
||||
|
||||
instance.SetBossState(DataTypes.Anomalus, EncounterState.InProgress);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Talk(AnomalusConst.SayDeath);
|
||||
|
||||
instance.SetBossState(DataTypes.Anomalus, EncounterState.Done);
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == AnomalusConst.DataChaosTheory)
|
||||
return chaosTheory ? 1 : 0u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void SummonedCreatureDies(Creature summoned, Unit who)
|
||||
{
|
||||
if (summoned.GetEntry() == AnomalusConst.NpcChaoticRift)
|
||||
chaosTheory = false;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me.GetDistance(me.GetHomePosition()) > 60.0f)
|
||||
{
|
||||
// Not blizzlike, hack to avoid an exploit
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
|
||||
if (me.HasAura(AnomalusConst.SpellRiftShield))
|
||||
{
|
||||
if (!uiChaoticRiftGUID.IsEmpty())
|
||||
{
|
||||
Creature Rift = ObjectAccessor.GetCreature(me, uiChaoticRiftGUID);
|
||||
if (Rift && Rift.IsDead())
|
||||
{
|
||||
me.RemoveAurasDueToSpell(AnomalusConst.SpellRiftShield);
|
||||
uiChaoticRiftGUID.Clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
uiChaoticRiftGUID.Clear();
|
||||
|
||||
if ((Phase == 0) && HealthBelowPct(50))
|
||||
{
|
||||
Phase = 1;
|
||||
Talk(AnomalusConst.SayShield);
|
||||
DoCast(me, AnomalusConst.SpellRiftShield);
|
||||
Creature Rift = me.SummonCreature(AnomalusConst.NpcChaoticRift, AnomalusConst.RiftLocation[RandomHelper.IRand(0, 5)], TempSummonType.TimedDespawnOOC, 1000);
|
||||
if (Rift)
|
||||
{
|
||||
//DoCast(Rift, SPELL_CHARGE_RIFT);
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
Rift.GetAI().AttackStart(target);
|
||||
uiChaoticRiftGUID = Rift.GetGUID();
|
||||
Talk(AnomalusConst.SayRift);
|
||||
}
|
||||
}
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
|
||||
byte Phase;
|
||||
ObjectGuid uiChaoticRiftGUID;
|
||||
bool chaosTheory;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_chaotic_rift : ScriptedAI
|
||||
{
|
||||
public npc_chaotic_rift(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = me.GetInstanceScript();
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
uiChaoticEnergyBurstTimer = 1000;
|
||||
uiSummonCrazedManaWraithTimer = 5000;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
me.SetDisplayId(me.GetCreatureTemplate().ModelId2);
|
||||
DoCast(me, AnomalusConst.SpellArcaneform, false);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (uiChaoticEnergyBurstTimer <= diff)
|
||||
{
|
||||
Creature Anomalus = ObjectAccessor.GetCreature(me, instance.GetGuidData(DataTypes.Anomalus));
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
{
|
||||
if (Anomalus && Anomalus.HasAura(AnomalusConst.SpellRiftShield))
|
||||
DoCast(target, AnomalusConst.SpellChargedChaoticEnergyBurst);
|
||||
else
|
||||
DoCast(target, AnomalusConst.SpellChaoticEnergyBurst);
|
||||
}
|
||||
uiChaoticEnergyBurstTimer = 1000;
|
||||
}
|
||||
else
|
||||
uiChaoticEnergyBurstTimer -= diff;
|
||||
|
||||
if (uiSummonCrazedManaWraithTimer <= diff)
|
||||
{
|
||||
Creature Wraith = me.SummonCreature(AnomalusConst.NpcCrazedManaWraith, me.GetPositionX() + 1, me.GetPositionY() + 1, me.GetPositionZ(), 0, TempSummonType.TimedDespawnOOC, 1000);
|
||||
if (Wraith)
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
Wraith.GetAI().AttackStart(target);
|
||||
}
|
||||
Creature Anomalus = ObjectAccessor.GetCreature(me, instance.GetGuidData(DataTypes.Anomalus));
|
||||
if (Anomalus && Anomalus.HasAura(AnomalusConst.SpellRiftShield))
|
||||
uiSummonCrazedManaWraithTimer = 5000;
|
||||
else
|
||||
uiSummonCrazedManaWraithTimer = 10000;
|
||||
}
|
||||
else
|
||||
uiSummonCrazedManaWraithTimer -= diff;
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
|
||||
uint uiChaoticEnergyBurstTimer;
|
||||
uint uiSummonCrazedManaWraithTimer;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_chaos_theory : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_chaos_theory() : base("achievement_chaos_theory")
|
||||
{
|
||||
}
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
Creature Anomalus = target.ToCreature();
|
||||
if (Anomalus)
|
||||
if (Anomalus.GetAI().GetData(AnomalusConst.DataChaosTheory) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend.Nexus.Nexus
|
||||
{
|
||||
struct KeristraszaConst
|
||||
{
|
||||
//Spells
|
||||
public const uint SpellFrozenPrison = 47854;
|
||||
public const uint SpellTailSweep = 50155;
|
||||
public const uint SpellCrystalChains = 50997;
|
||||
public const uint SpellEnrage = 8599;
|
||||
public const uint SpellCrystalFireBreath = 48096;
|
||||
public const uint SpellCrystalize = 48179;
|
||||
public const uint SpellIntenseCold = 48094;
|
||||
public const uint SpellIntenseColdTriggered = 48095;
|
||||
|
||||
//Yells
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SaySlay = 1;
|
||||
public const uint SayEnrage = 2;
|
||||
public const uint SayDeath = 3;
|
||||
public const uint SayCrystalNova = 4;
|
||||
public const uint SayFrenzy = 5;
|
||||
|
||||
//Misc
|
||||
public const uint DataIntenseCold = 1;
|
||||
public const uint DataContainmentSpheres = 3;
|
||||
}
|
||||
|
||||
[Script]
|
||||
public class boss_keristrasza : BossAI
|
||||
{
|
||||
public boss_keristrasza(Creature creature) : base(creature, DataTypes.Keristrasza)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_enrage = false;
|
||||
|
||||
//Crystal FireBreath
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(14), task =>
|
||||
{
|
||||
DoCastVictim(KeristraszaConst.SpellCrystalFireBreath);
|
||||
task.Repeat(TimeSpan.FromSeconds(14));
|
||||
});
|
||||
|
||||
//CrystalChainsCrystalize
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(DungeonMode<uint>(30, 11)), task =>
|
||||
{
|
||||
Talk(KeristraszaConst.SayCrystalNova);
|
||||
if (IsHeroic())
|
||||
DoCast(me, KeristraszaConst.SpellCrystalize);
|
||||
else
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (target)
|
||||
DoCast(target, KeristraszaConst.SpellCrystalChains);
|
||||
}
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(DungeonMode<uint>(30, 11)));
|
||||
});
|
||||
|
||||
//TailSweep
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
|
||||
{
|
||||
DoCast(me, KeristraszaConst.SpellTailSweep);
|
||||
task.Repeat(TimeSpan.FromSeconds(5));
|
||||
});
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
_intenseColdList.Clear();
|
||||
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.Stunned);
|
||||
|
||||
RemovePrison(CheckContainmentSpheres());
|
||||
_Reset();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
Talk(KeristraszaConst.SayAggro);
|
||||
DoCastAOE(KeristraszaConst.SpellIntenseCold);
|
||||
_EnterCombat();
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Talk(KeristraszaConst.SayDeath);
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.IsTypeId(TypeId.Player))
|
||||
Talk(KeristraszaConst.SaySlay);
|
||||
}
|
||||
|
||||
public bool CheckContainmentSpheres(bool removePrison = false)
|
||||
{
|
||||
for (uint i = DataTypes.AnomalusContainmetSphere; i < (DataTypes.AnomalusContainmetSphere + KeristraszaConst.DataContainmentSpheres); ++i)
|
||||
{
|
||||
GameObject containmentSpheres = ObjectAccessor.GetGameObject(me, instance.GetGuidData(i));
|
||||
if (!containmentSpheres || containmentSpheres.GetGoState() != GameObjectState.Active)
|
||||
return false;
|
||||
}
|
||||
if (removePrison)
|
||||
RemovePrison(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemovePrison(bool remove)
|
||||
{
|
||||
if (remove)
|
||||
{
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.ImmuneToPc);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
if (me.HasAura(KeristraszaConst.SpellFrozenPrison))
|
||||
me.RemoveAurasDueToSpell(KeristraszaConst.SpellFrozenPrison);
|
||||
}
|
||||
else
|
||||
{
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.ImmuneToPc);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NonAttackable);
|
||||
DoCast(me, KeristraszaConst.SpellFrozenPrison, false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetGUID(ObjectGuid guid, int id = 0)
|
||||
{
|
||||
if (id == KeristraszaConst.DataIntenseCold)
|
||||
_intenseColdList.Add(guid);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (!_enrage && me.HealthBelowPctDamaged(25, damage))
|
||||
{
|
||||
Talk(KeristraszaConst.SayEnrage);
|
||||
Talk(KeristraszaConst.SayFrenzy);
|
||||
DoCast(me, KeristraszaConst.SpellEnrage);
|
||||
_enrage = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool _enrage;
|
||||
|
||||
public List<ObjectGuid> _intenseColdList = new List<ObjectGuid>();
|
||||
}
|
||||
|
||||
[Script]
|
||||
class containment_sphere : GameObjectScript
|
||||
{
|
||||
public containment_sphere() : base("containment_sphere") { }
|
||||
|
||||
public override bool OnGossipHello(Player player, GameObject go)
|
||||
{
|
||||
InstanceScript instance = go.GetInstanceScript();
|
||||
|
||||
Creature pKeristrasza = ObjectAccessor.GetCreature(go, instance.GetGuidData(DataTypes.Keristrasza));
|
||||
if (pKeristrasza && pKeristrasza.IsAlive())
|
||||
{
|
||||
// maybe these are hacks :(
|
||||
go.SetFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
go.SetGoState(GameObjectState.Active);
|
||||
|
||||
((boss_keristrasza)pKeristrasza.GetAI()).CheckContainmentSpheres(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_intense_cold : AuraScript
|
||||
{
|
||||
void HandlePeriodicTick(AuraEffect aurEff)
|
||||
{
|
||||
if (aurEff.GetBase().GetStackAmount() < 2)
|
||||
return;
|
||||
Unit caster = GetCaster();
|
||||
/// @todo the caster should be boss but not the player
|
||||
if (!caster || caster.GetAI() == null)
|
||||
return;
|
||||
|
||||
caster.GetAI().SetGUID(GetTarget().GetGUID(), (int)KeristraszaConst.DataIntenseCold);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(HandlePeriodicTick, 1, AuraType.PeriodicDamage));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_intense_cold : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_intense_cold() : base("achievement_intense_cold") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
var _intenseColdList = ((boss_keristrasza)target.ToCreature().GetAI())._intenseColdList;
|
||||
if (!_intenseColdList.Empty())
|
||||
{
|
||||
foreach (var guid in _intenseColdList)
|
||||
if (player.GetGUID() == guid)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
namespace Scripts.Northrend.Nexus.Nexus
|
||||
{
|
||||
struct MagusTelestraConst
|
||||
{
|
||||
//Spells
|
||||
public const uint SpellIceNova = 47772;
|
||||
public const uint SpellIceNovaH = 56935;
|
||||
public const uint SpellFirebomb = 47773;
|
||||
public const uint SpellFirebombH = 56934;
|
||||
public const uint SpellGravityWell = 47756;
|
||||
public const uint SpellTelestraBack = 47714;
|
||||
public const uint SpellFireMagusVisual = 47705;
|
||||
public const uint SpellFrostMagusVisual = 47706;
|
||||
public const uint SpellArcaneMagusVisual = 47704;
|
||||
public const uint SpellWearChristmasHat = 61400;
|
||||
|
||||
//Npcs
|
||||
public const uint NpcFireMagus = 26928;
|
||||
public const uint NpcFrostMagus = 26930;
|
||||
public const uint NpcArcaneMagus = 26929;
|
||||
|
||||
//Texts
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SayKill = 1;
|
||||
public const uint SayDeath = 2;
|
||||
public const uint SayMerge = 3;
|
||||
public const uint SaySplit = 4;
|
||||
|
||||
//Misc
|
||||
public const uint DataSplitPersonality = 1;
|
||||
public const ushort GameEventWinterVeil = 2;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_magus_telestra : ScriptedAI
|
||||
{
|
||||
public boss_magus_telestra(Creature creature) : base(creature)
|
||||
{
|
||||
instance = creature.GetInstanceScript();
|
||||
bFireMagusDead = false;
|
||||
bFrostMagusDead = false;
|
||||
bArcaneMagusDead = false;
|
||||
uiIsWaitingToAppearTimer = 0;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
Phase = 0;
|
||||
|
||||
uiIceNovaTimer = 7 * Time.InMilliseconds;
|
||||
uiFireBombTimer = 0;
|
||||
uiGravityWellTimer = 15 * Time.InMilliseconds;
|
||||
uiCooldown = 0;
|
||||
|
||||
for (byte n = 0; n < 3; ++n)
|
||||
time[n] = 0;
|
||||
|
||||
splitPersonality = 0;
|
||||
bIsWaitingToAppear = false;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
|
||||
instance.SetBossState(DataTypes.MagusTelestra, EncounterState.NotStarted);
|
||||
|
||||
if (IsHeroic() && Global.GameEventMgr.IsActiveEvent(MagusTelestraConst.GameEventWinterVeil) && !me.HasAura(MagusTelestraConst.SpellWearChristmasHat))
|
||||
me.AddAura(MagusTelestraConst.SpellWearChristmasHat, me);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
Talk(MagusTelestraConst.SayAggro);
|
||||
|
||||
instance.SetBossState(DataTypes.MagusTelestra, EncounterState.InProgress);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Talk(MagusTelestraConst.SayDeath);
|
||||
|
||||
instance.SetBossState(DataTypes.MagusTelestra, EncounterState.Done);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.IsTypeId(TypeId.Player))
|
||||
Talk(MagusTelestraConst.SayKill);
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == MagusTelestraConst.DataSplitPersonality)
|
||||
return splitPersonality;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
//Return since we have no target
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (bIsWaitingToAppear)
|
||||
{
|
||||
me.StopMoving();
|
||||
me.AttackStop();
|
||||
if (uiIsWaitingToAppearTimer <= diff)
|
||||
{
|
||||
me.CastSpell(me, 47714, true);
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
bIsWaitingToAppear = false;
|
||||
InVanish = false;
|
||||
me.SendAIReaction(AiReaction.Hostile);
|
||||
}
|
||||
else
|
||||
uiIsWaitingToAppearTimer -= diff;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Phase == 1) || (Phase == 3))
|
||||
{
|
||||
if (bFireMagusDead && bFrostMagusDead && bArcaneMagusDead)
|
||||
{
|
||||
for (byte n = 0; n < 3; ++n)
|
||||
time[n] = 0;
|
||||
|
||||
me.GetMotionMaster().Clear();
|
||||
DoCast(me, MagusTelestraConst.SpellTelestraBack);
|
||||
if (Phase == 1)
|
||||
Phase = 2;
|
||||
if (Phase == 3)
|
||||
Phase = 4;
|
||||
bIsWaitingToAppear = true;
|
||||
uiIsWaitingToAppearTimer = 4 * Time.InMilliseconds;
|
||||
Talk(MagusTelestraConst.SayMerge);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Phase == 0) && HealthBelowPct(50))
|
||||
{
|
||||
InVanish = true;
|
||||
Phase = 1;
|
||||
me.CastStop();
|
||||
me.RemoveAllAuras();
|
||||
me.CastSpell(me, 47710, false);
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
bFireMagusDead = false;
|
||||
bFrostMagusDead = false;
|
||||
bArcaneMagusDead = false;
|
||||
Talk(MagusTelestraConst.SaySplit);
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsHeroic() && (Phase == 2) && HealthBelowPct(10))
|
||||
{
|
||||
InVanish = true;
|
||||
Phase = 3;
|
||||
me.CastStop();
|
||||
me.RemoveAllAuras();
|
||||
me.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
bFireMagusDead = false;
|
||||
bFrostMagusDead = false;
|
||||
bArcaneMagusDead = false;
|
||||
Talk(MagusTelestraConst.SaySplit);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uiCooldown != 0)
|
||||
{
|
||||
if (uiCooldown <= diff)
|
||||
uiCooldown = 0;
|
||||
else
|
||||
{
|
||||
uiCooldown -= diff;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (uiIceNovaTimer <= diff)
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
{
|
||||
DoCast(target, MagusTelestraConst.SpellIceNova, false);
|
||||
uiCooldown = 1500;
|
||||
}
|
||||
uiIceNovaTimer = 15 * Time.InMilliseconds;
|
||||
}
|
||||
else uiIceNovaTimer -= diff;
|
||||
|
||||
if (uiGravityWellTimer <= diff)
|
||||
{
|
||||
Unit target = me.GetVictim();
|
||||
if (target)
|
||||
{
|
||||
DoCast(target, MagusTelestraConst.SpellGravityWell);
|
||||
uiCooldown = 6 * Time.InMilliseconds;
|
||||
}
|
||||
uiGravityWellTimer = 15 * Time.InMilliseconds;
|
||||
}
|
||||
else uiGravityWellTimer -= diff;
|
||||
|
||||
if (uiFireBombTimer <= diff)
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
{
|
||||
DoCast(target, MagusTelestraConst.SpellFirebomb, false);
|
||||
uiCooldown = 2 * Time.InMilliseconds;
|
||||
}
|
||||
uiFireBombTimer = 2 * Time.InMilliseconds;
|
||||
}
|
||||
else uiFireBombTimer -= diff;
|
||||
|
||||
if (!InVanish)
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void SummonedCreatureDies(Creature summon, Unit killer)
|
||||
{
|
||||
if (summon.IsAlive())
|
||||
return;
|
||||
|
||||
switch (summon.GetEntry())
|
||||
{
|
||||
case MagusTelestraConst.NpcFireMagus:
|
||||
bFireMagusDead = true;
|
||||
break;
|
||||
case MagusTelestraConst.NpcFrostMagus:
|
||||
bFrostMagusDead = true;
|
||||
break;
|
||||
case MagusTelestraConst.NpcArcaneMagus:
|
||||
bArcaneMagusDead = true;
|
||||
break;
|
||||
}
|
||||
|
||||
byte i = 0;
|
||||
while (time[i] != 0)
|
||||
++i;
|
||||
|
||||
time[i] = Global.WorldMgr.GetGameTime();
|
||||
if (i == 2 && (time[2] - time[1] < 5) && (time[1] - time[0] < 5))
|
||||
++splitPersonality;
|
||||
}
|
||||
|
||||
InstanceScript instance;
|
||||
|
||||
bool bFireMagusDead;
|
||||
bool bFrostMagusDead;
|
||||
bool bArcaneMagusDead;
|
||||
bool bIsWaitingToAppear;
|
||||
bool InVanish;
|
||||
|
||||
uint uiIsWaitingToAppearTimer;
|
||||
uint uiIceNovaTimer;
|
||||
uint uiFireBombTimer;
|
||||
uint uiGravityWellTimer;
|
||||
uint uiCooldown;
|
||||
|
||||
byte Phase;
|
||||
byte splitPersonality;
|
||||
long[] time = new long[3];
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_split_personality : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_split_personality() : base("achievement_split_personality") { }
|
||||
|
||||
public override bool OnCheck(Player player, Unit target)
|
||||
{
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
Creature Telestra = target.ToCreature();
|
||||
if (Telestra)
|
||||
if (Telestra.GetAI().GetData(MagusTelestraConst.DataSplitPersonality) == 2)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.Scripting;
|
||||
using System;
|
||||
|
||||
namespace Scripts.Northrend.Nexus.Nexus
|
||||
{
|
||||
struct NexusCommandersConst
|
||||
{
|
||||
//Spells
|
||||
public const uint SpellBattleShout = 31403;
|
||||
public const uint SpellCharge = 60067;
|
||||
public const uint SpellFrighteningShout = 19134;
|
||||
public const uint SpellWhirlwind = 38618;
|
||||
public const uint SpellFrozenPrison = 47543;
|
||||
|
||||
//Texts
|
||||
public const uint SayAggro = 0;
|
||||
public const uint SayKill = 1;
|
||||
public const uint SayDeath = 2;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_nexus_commanders : BossAI
|
||||
{
|
||||
boss_nexus_commanders(Creature creature) : base(creature, DataTypes.Commander) { }
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
Talk(NexusCommandersConst.SayAggro);
|
||||
me.RemoveAurasDueToSpell(NexusCommandersConst.SpellFrozenPrison);
|
||||
DoCast(me, NexusCommandersConst.SpellBattleShout);
|
||||
|
||||
//Charge
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(4), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, 100.0f, true);
|
||||
if (target)
|
||||
DoCast(target, NexusCommandersConst.SpellCharge);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(11), TimeSpan.FromSeconds(15));
|
||||
});
|
||||
|
||||
//Whirlwind
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(8), task =>
|
||||
{
|
||||
DoCast(me, NexusCommandersConst.SpellWhirlwind);
|
||||
task.Repeat(TimeSpan.FromSeconds(19.5), TimeSpan.FromSeconds(25));
|
||||
});
|
||||
|
||||
//Frightening Shout
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(13), TimeSpan.FromSeconds(15), task =>
|
||||
{
|
||||
DoCastAOE(NexusCommandersConst.SpellFrighteningShout);
|
||||
task.Repeat(TimeSpan.FromSeconds(45), TimeSpan.FromSeconds(55));
|
||||
});
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(NexusCommandersConst.SayDeath);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.IsTypeId(TypeId.Player))
|
||||
Talk(NexusCommandersConst.SayKill);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* 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.Scripting;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
|
||||
namespace Scripts.Northrend.Nexus.Nexus
|
||||
{
|
||||
struct OrmorokConst
|
||||
{
|
||||
//Spells
|
||||
public const uint SpellReflection = 47981;
|
||||
public const uint SpellTrample = 48016;
|
||||
public const uint SpellFrenzy = 48017;
|
||||
public const uint SpellSummonCrystallineTangler = 61564;
|
||||
public const uint SpellCrystalSpikes = 47958;
|
||||
|
||||
//Texts
|
||||
public const uint SayAggro = 1;
|
||||
public const uint SayDeath = 2;
|
||||
public const uint SayReflect = 3;
|
||||
public const uint SayCrystalSpikes = 4;
|
||||
public const uint SayKill = 5;
|
||||
public const uint SayFrenzy = 6;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_ormorok : BossAI
|
||||
{
|
||||
public boss_ormorok(Creature creature) : base(creature, DataTypes.Ormorok)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
frenzy = false;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
_EnterCombat();
|
||||
|
||||
//Crystal Spikes
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
|
||||
{
|
||||
Talk(OrmorokConst.SayCrystalSpikes);
|
||||
DoCast(OrmorokConst.SpellCrystalSpikes);
|
||||
task.Repeat(TimeSpan.FromSeconds(12));
|
||||
});
|
||||
|
||||
//Trample
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
|
||||
{
|
||||
DoCast(me, OrmorokConst.SpellTrample);
|
||||
task.Repeat(TimeSpan.FromSeconds(10));
|
||||
});
|
||||
|
||||
//Spell Reflection
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
|
||||
{
|
||||
Talk(OrmorokConst.SayReflect);
|
||||
DoCast(me, OrmorokConst.SpellReflection);
|
||||
task.Repeat(TimeSpan.FromSeconds(30));
|
||||
});
|
||||
|
||||
//Heroic Crystalline Tangler
|
||||
if (IsHeroic())
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(17), task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0, new OrmorokTanglerPredicate(me));
|
||||
if (target)
|
||||
DoCast(target, OrmorokConst.SpellSummonCrystallineTangler);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(17));
|
||||
});
|
||||
}
|
||||
|
||||
Talk(OrmorokConst.SayAggro);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (!frenzy && HealthBelowPct(25))
|
||||
{
|
||||
Talk(OrmorokConst.SayFrenzy);
|
||||
DoCast(me, OrmorokConst.SpellFrenzy);
|
||||
frenzy = true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
Talk(OrmorokConst.SayDeath);
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.IsTypeId(TypeId.Player))
|
||||
Talk(OrmorokConst.SayKill);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
bool frenzy;
|
||||
}
|
||||
|
||||
class OrmorokTanglerPredicate : ISelector
|
||||
{
|
||||
public OrmorokTanglerPredicate(Unit unit)
|
||||
{
|
||||
me = unit;
|
||||
}
|
||||
|
||||
public bool Check(Unit target)
|
||||
{
|
||||
return target.GetDistance2d(me) >= 5.0f;
|
||||
}
|
||||
|
||||
Unit me;
|
||||
}
|
||||
|
||||
struct CrystalSpikesConst
|
||||
{
|
||||
public const uint NpcCrystalSpikeInitial = 27101;
|
||||
public const uint NpcCrystalSpikeTrigger = 27079;
|
||||
|
||||
public const uint DataCount = 1;
|
||||
public const uint MaxCount = 5;
|
||||
|
||||
public const uint SpellCrystalSpikeDamage = 47944;
|
||||
|
||||
public const uint GoCrystalSpikeTrap = 188537;
|
||||
|
||||
|
||||
public static uint[] CrystalSpikeSummon =
|
||||
{
|
||||
47936,
|
||||
47942,
|
||||
7943
|
||||
};
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_crystal_spike_trigger : ScriptedAI
|
||||
{
|
||||
public npc_crystal_spike_trigger(Creature creature) : base(creature) { }
|
||||
|
||||
public override void IsSummonedBy(Unit owner)
|
||||
{
|
||||
switch (me.GetEntry())
|
||||
{
|
||||
case CrystalSpikesConst.NpcCrystalSpikeInitial:
|
||||
_count = 0;
|
||||
me.SetFacingToObject(owner);
|
||||
break;
|
||||
case CrystalSpikesConst.NpcCrystalSpikeTrigger:
|
||||
Creature trigger = owner.ToCreature();
|
||||
if (trigger)
|
||||
_count = trigger.GetAI().GetData(CrystalSpikesConst.DataCount) + 1;
|
||||
break;
|
||||
default:
|
||||
_count = CrystalSpikesConst.MaxCount;
|
||||
break;
|
||||
}
|
||||
|
||||
if (me.GetEntry() == CrystalSpikesConst.NpcCrystalSpikeTrigger)
|
||||
{
|
||||
GameObject trap = me.FindNearestGameObject(CrystalSpikesConst.GoCrystalSpikeTrap, 1.0f);
|
||||
if (trap)
|
||||
trap.Use(me);
|
||||
}
|
||||
|
||||
//Despawn
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(2), task =>
|
||||
{
|
||||
if (me.GetEntry() == CrystalSpikesConst.NpcCrystalSpikeTrigger)
|
||||
{
|
||||
GameObject trap = me.FindNearestGameObject(CrystalSpikesConst.GoCrystalSpikeTrap, 1.0f);
|
||||
if (trap)
|
||||
trap.Delete();
|
||||
}
|
||||
|
||||
me.DespawnOrUnsummon();
|
||||
});
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
return type == CrystalSpikesConst.DataCount ? _count : 0;
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
uint _count;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_crystal_spike : AuraScript
|
||||
{
|
||||
void HandlePeriodic(AuraEffect aurEff)
|
||||
{
|
||||
Unit target = GetTarget();
|
||||
if (target.GetEntry() == CrystalSpikesConst.NpcCrystalSpikeInitial || target.GetEntry() == CrystalSpikesConst.NpcCrystalSpikeTrigger)
|
||||
{
|
||||
Creature trigger = target.ToCreature();
|
||||
if (trigger)
|
||||
{
|
||||
uint spell = target.GetEntry() == CrystalSpikesConst.NpcCrystalSpikeInitial ? CrystalSpikesConst.CrystalSpikeSummon[0] : CrystalSpikesConst.CrystalSpikeSummon[RandomHelper.IRand(0, 2)];
|
||||
if (trigger.GetAI().GetData(CrystalSpikesConst.DataCount) < CrystalSpikesConst.MaxCount)
|
||||
trigger.CastSpell(trigger, spell, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(HandlePeriodic, 0, AuraType.PeriodicDummy));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* 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.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
|
||||
namespace Scripts.Northrend.Nexus.Nexus
|
||||
{
|
||||
struct DataTypes
|
||||
{
|
||||
public const uint Commander = 0;
|
||||
public const uint MagusTelestra = 1;
|
||||
public const uint Anomalus = 2;
|
||||
public const uint Ormorok = 3;
|
||||
public const uint Keristrasza = 4;
|
||||
|
||||
public const uint AnomalusContainmetSphere = 5;
|
||||
public const uint OrmorokContainmetSphere = 6;
|
||||
public const uint TelestraContainmetSphere = 7;
|
||||
}
|
||||
|
||||
struct CreatureIds
|
||||
{
|
||||
public const uint Anomalus = 26763;
|
||||
public const uint Keristrasza = 26723;
|
||||
|
||||
// Alliance
|
||||
public const uint AllianceBerserker = 26800;
|
||||
public const uint AllianceRanger = 26802;
|
||||
public const uint AllianceCleric = 26805;
|
||||
public const uint AllianceCommander = 27949;
|
||||
public const uint CommanderStoutbeard = 26796;
|
||||
|
||||
// Horde
|
||||
public const uint HordeBerserker = 26799;
|
||||
public const uint HordeRanger = 26801;
|
||||
public const uint HordeCleric = 26803;
|
||||
public const uint HordeCommander = 27947;
|
||||
public const uint CommanderKolurg = 26798;
|
||||
}
|
||||
|
||||
struct GameObjectIds
|
||||
{
|
||||
public const uint AnomalusContainmetSphere = 188527;
|
||||
public const uint OrmoroksContainmetSphere = 188528;
|
||||
public const uint TelestrasContainmetSphere = 188526;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class instance_nexus : InstanceMapScript
|
||||
{
|
||||
public instance_nexus() : base(nameof(instance_nexus), 576) { }
|
||||
|
||||
class instance_nexus_InstanceMapScript : InstanceScript
|
||||
{
|
||||
public instance_nexus_InstanceMapScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("NEX");
|
||||
SetBossNumber(DataTypes.Keristrasza + 1);
|
||||
_teamInInstance = 0;
|
||||
}
|
||||
|
||||
public override void OnPlayerEnter(Player player)
|
||||
{
|
||||
if (_teamInInstance == 0)
|
||||
_teamInInstance = player.GetTeam();
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
case CreatureIds.Anomalus:
|
||||
AnomalusGUID = creature.GetGUID();
|
||||
break;
|
||||
case CreatureIds.Keristrasza:
|
||||
KeristraszaGUID = creature.GetGUID();
|
||||
break;
|
||||
// Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs.
|
||||
case CreatureIds.AllianceBerserker:
|
||||
if (ServerAllowsTwoSideGroups())
|
||||
creature.SetFaction(16);
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.HordeBerserker);
|
||||
break;
|
||||
case CreatureIds.AllianceRanger:
|
||||
if (ServerAllowsTwoSideGroups())
|
||||
creature.SetFaction(16);
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.HordeRanger);
|
||||
break;
|
||||
case CreatureIds.AllianceCleric:
|
||||
if (ServerAllowsTwoSideGroups())
|
||||
creature.SetFaction(16);
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.HordeCleric);
|
||||
break;
|
||||
case CreatureIds.AllianceCommander:
|
||||
if (ServerAllowsTwoSideGroups())
|
||||
creature.SetFaction(16);
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.HordeCommander);
|
||||
break;
|
||||
case CreatureIds.CommanderStoutbeard:
|
||||
if (ServerAllowsTwoSideGroups())
|
||||
creature.SetFaction(16);
|
||||
if (_teamInInstance == Team.Alliance)
|
||||
creature.UpdateEntry(CreatureIds.CommanderKolurg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectCreate(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GameObjectIds.AnomalusContainmetSphere:
|
||||
AnomalusContainmentSphere = go.GetGUID();
|
||||
if (GetBossState(DataTypes.Anomalus) == EncounterState.Done)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
break;
|
||||
case GameObjectIds.OrmoroksContainmetSphere:
|
||||
OrmoroksContainmentSphere = go.GetGUID();
|
||||
if (GetBossState(DataTypes.Ormorok) == EncounterState.Done)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
break;
|
||||
case GameObjectIds.TelestrasContainmetSphere:
|
||||
TelestrasContainmentSphere = go.GetGUID();
|
||||
if (GetBossState(DataTypes.MagusTelestra) == EncounterState.Done)
|
||||
go.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SetBossState(uint type, EncounterState state)
|
||||
{
|
||||
if (!base.SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.MagusTelestra:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
GameObject sphere = instance.GetGameObject(TelestrasContainmentSphere);
|
||||
if (sphere)
|
||||
sphere.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
}
|
||||
break;
|
||||
case DataTypes.Anomalus:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
GameObject sphere = instance.GetGameObject(AnomalusContainmentSphere);
|
||||
if (sphere)
|
||||
sphere.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
}
|
||||
break;
|
||||
case DataTypes.Ormorok:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
GameObject sphere = instance.GetGameObject(OrmoroksContainmentSphere);
|
||||
if (sphere)
|
||||
sphere.RemoveFlag(GameObjectFields.Flags, GameObjectFlags.NotSelectable);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGuidData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataTypes.Anomalus:
|
||||
return AnomalusGUID;
|
||||
case DataTypes.Keristrasza:
|
||||
return KeristraszaGUID;
|
||||
case DataTypes.AnomalusContainmetSphere:
|
||||
return AnomalusContainmentSphere;
|
||||
case DataTypes.OrmorokContainmetSphere:
|
||||
return OrmoroksContainmentSphere;
|
||||
case DataTypes.TelestraContainmetSphere:
|
||||
return TelestrasContainmentSphere;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
ObjectGuid AnomalusGUID;
|
||||
ObjectGuid KeristraszaGUID;
|
||||
ObjectGuid AnomalusContainmentSphere;
|
||||
ObjectGuid OrmoroksContainmentSphere;
|
||||
ObjectGuid TelestrasContainmentSphere;
|
||||
Team _teamInInstance;
|
||||
}
|
||||
|
||||
public override InstanceScript GetInstanceScript(InstanceMap map)
|
||||
{
|
||||
return new instance_nexus_InstanceMapScript(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Scripts.Northrend.Nexus.Oculus
|
||||
{
|
||||
/*
|
||||
struct DataTypes
|
||||
{
|
||||
// Encounter States/Boss GUIDs
|
||||
public const uint Drakos = 0;
|
||||
public const uint Varos = 1;
|
||||
public const uint Urom = 2;
|
||||
public const uint Eregos = 3;
|
||||
// GPS System
|
||||
public const uint Constructs = 4;
|
||||
}
|
||||
|
||||
class instance_oculus : InstanceMapScript
|
||||
{
|
||||
public instance_oculus() : base(nameof(instance_oculus), 578) { }
|
||||
|
||||
class instance_oculus_InstanceMapScript : InstanceScript
|
||||
{
|
||||
public instance_oculus_InstanceMapScript(Map map) : base(map)
|
||||
{
|
||||
SetHeaders("OC");
|
||||
SetBossNumber(DataTypes.Eregos + 1);
|
||||
LoadDoorData(doorData);
|
||||
|
||||
CentrifugueConstructCounter = 0;
|
||||
}
|
||||
|
||||
public override void OnCreatureCreate(Creature creature)
|
||||
{
|
||||
switch (creature.GetEntry())
|
||||
{
|
||||
case NPC_DRAKOS:
|
||||
DrakosGUID = creature.GetGUID();
|
||||
break;
|
||||
case NPC_VAROS:
|
||||
VarosGUID = creature.GetGUID();
|
||||
if (GetBossState(DATA_DRAKOS) == EncounterState.Done)
|
||||
creature.SetPhaseMask(1, true);
|
||||
break;
|
||||
case NPC_UROM:
|
||||
UromGUID = creature.GetGUID();
|
||||
if (GetBossState(DATA_VAROS) == EncounterState.Done)
|
||||
creature.SetPhaseMask(1, true);
|
||||
break;
|
||||
case NPC_EREGOS:
|
||||
EregosGUID = creature.GetGUID();
|
||||
if (GetBossState(DATA_UROM) == EncounterState.Done)
|
||||
creature.SetPhaseMask(1, true);
|
||||
break;
|
||||
case NPC_CENTRIFUGE_CONSTRUCT:
|
||||
if (creature.IsAlive())
|
||||
DoUpdateWorldState(WORLD_STATE_CENTRIFUGE_CONSTRUCT_AMOUNT, ++CentrifugueConstructCounter);
|
||||
break;
|
||||
case NPC_BELGARISTRASZ:
|
||||
BelgaristraszGUID = creature.GetGUID();
|
||||
if (GetBossState(DATA_DRAKOS) == EncounterState.Done)
|
||||
{
|
||||
creature.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
creature.Relocate(BelgaristraszMove);
|
||||
}
|
||||
break;
|
||||
case NPC_ETERNOS:
|
||||
EternosGUID = creature.GetGUID();
|
||||
if (GetBossState(DATA_DRAKOS) == EncounterState.Done)
|
||||
{
|
||||
creature.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
creature.Relocate(EternosMove);
|
||||
}
|
||||
break;
|
||||
case NPC_VERDISA:
|
||||
VerdisaGUID = creature.GetGUID();
|
||||
if (GetBossState(DATA_DRAKOS) == EncounterState.Done)
|
||||
{
|
||||
creature.SetFlag(UnitFields.NpcFlags, NPCFlags.Gossip);
|
||||
creature.Relocate(VerdisaMove);
|
||||
}
|
||||
break;
|
||||
case NPC_GREATER_WHELP:
|
||||
if (GetBossState(DATA_UROM) == EncounterState.Done)
|
||||
{
|
||||
creature.SetPhaseMask(1, true);
|
||||
GreaterWhelpList.Add(creature.GetGUID());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectCreate(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GO_DRAGON_CAGE_DOOR:
|
||||
AddDoor(go, true);
|
||||
break;
|
||||
case GO_EREGOS_CACHE_N:
|
||||
case GO_EREGOS_CACHE_H:
|
||||
EregosCacheGUID = go.GetGUID();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGameObjectRemove(GameObject go)
|
||||
{
|
||||
switch (go.GetEntry())
|
||||
{
|
||||
case GO_DRAGON_CAGE_DOOR:
|
||||
AddDoor(go, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnUnitDeath(Unit unit)
|
||||
{
|
||||
Creature creature = unit.ToCreature();
|
||||
if (!creature)
|
||||
return;
|
||||
|
||||
if (creature.GetEntry() == NPC_CENTRIFUGE_CONSTRUCT)
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_CENTRIFUGE_CONSTRUCT_AMOUNT, --CentrifugueConstructCounter);
|
||||
|
||||
if (CentrifugueConstructCounter == 0)
|
||||
{
|
||||
Creature varos = instance.GetCreature(VarosGUID);
|
||||
if (varos)
|
||||
varos.RemoveAllAuras();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void FillInitialWorldStates(InitWorldStates packet)
|
||||
{
|
||||
if (GetBossState(DATA_DRAKOS) == EncounterState.Done && GetBossState(DATA_VAROS) != EncounterState.Done)
|
||||
{
|
||||
packet.Worldstates.Add(WORLD_STATE_CENTRIFUGE_CONSTRUCT_SHOW, 1);
|
||||
packet.Worldstates.Add(WORLD_STATE_CENTRIFUGE_CONSTRUCT_AMOUNT, CentrifugueConstructCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
packet.Worldstates.Add(WORLD_STATE_CENTRIFUGE_CONSTRUCT_SHOW, 0);
|
||||
packet.Worldstates.Add(WORLD_STATE_CENTRIFUGE_CONSTRUCT_AMOUNT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ProcessEvent(WorldObject Unit, uint eventId)
|
||||
{
|
||||
if (eventId != EVENT_CALL_DRAGON)
|
||||
return;
|
||||
|
||||
Creature varos = instance.GetCreature(VarosGUID);
|
||||
if (varos)
|
||||
{
|
||||
Creature drake = varos.SummonCreature(NPC_AZURE_RING_GUARDIAN, varos.GetPositionX(), varos.GetPositionY(), varos.GetPositionZ() + 40);
|
||||
if (drake)
|
||||
drake.GetAI().DoAction(ACTION_CALL_DRAGON_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool SetBossState(uint type, EncounterState state)
|
||||
{
|
||||
if (!base.SetBossState(type, state))
|
||||
return false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DATA_DRAKOS:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_CENTRIFUGE_CONSTRUCT_SHOW, 1);
|
||||
DoUpdateWorldState(WORLD_STATE_CENTRIFUGE_CONSTRUCT_AMOUNT, CentrifugueConstructCounter);
|
||||
FreeDragons();
|
||||
Creature varos = instance.GetCreature(VarosGUID);
|
||||
if (varos)
|
||||
varos.SetPhaseMask(1, true);
|
||||
events.ScheduleEvent(EVENT_VAROS_INTRO, 15000);
|
||||
}
|
||||
break;
|
||||
case DATA_VAROS:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_CENTRIFUGE_CONSTRUCT_SHOW, 0);
|
||||
Creature urom = instance.GetCreature(UromGUID);
|
||||
if (urom)
|
||||
urom.SetPhaseMask(1, true);
|
||||
}
|
||||
break;
|
||||
case DATA_UROM:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
Creature eregos = instance.GetCreature(EregosGUID);
|
||||
if (eregos)
|
||||
{
|
||||
eregos.SetPhaseMask(1, true);
|
||||
GreaterWhelps();
|
||||
events.ScheduleEvent(EVENT_EREGOS_INTRO, 5000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DATA_EREGOS:
|
||||
if (state == EncounterState.Done)
|
||||
{
|
||||
GameObject cache = instance.GetGameObject(EregosCacheGUID);
|
||||
if (cache)
|
||||
{
|
||||
cache.SetRespawnTime((int)cache.GetRespawnDelay());
|
||||
cache.RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
if (type == DATA_CONSTRUCTS)
|
||||
{
|
||||
if (CentrifugueConstructCounter == 0)
|
||||
return KILL_NO_CONSTRUCT;
|
||||
else if (CentrifugueConstructCounter == 1)
|
||||
return KILL_ONE_CONSTRUCT;
|
||||
else if (CentrifugueConstructCounter > 1)
|
||||
return KILL_MORE_CONSTRUCT;
|
||||
}
|
||||
|
||||
return KILL_NO_CONSTRUCT;
|
||||
}
|
||||
|
||||
public override ObjectGuid GetGuidData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_DRAKOS:
|
||||
return DrakosGUID;
|
||||
case DATA_VAROS:
|
||||
return VarosGUID;
|
||||
case DATA_UROM:
|
||||
return UromGUID;
|
||||
case DATA_EREGOS:
|
||||
return EregosGUID;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ObjectGuid.Empty;
|
||||
}
|
||||
|
||||
void FreeDragons()
|
||||
{
|
||||
Creature belgaristrasz = instance.GetCreature(BelgaristraszGUID);
|
||||
if (belgaristrasz)
|
||||
{
|
||||
belgaristrasz.SetWalk(true);
|
||||
belgaristrasz.GetMotionMaster().MovePoint(POINT_MOVE_OUT, BelgaristraszMove);
|
||||
}
|
||||
|
||||
Creature eternos = instance.GetCreature(EternosGUID);
|
||||
if (eternos)
|
||||
{
|
||||
eternos.SetWalk(true);
|
||||
eternos.GetMotionMaster().MovePoint(POINT_MOVE_OUT, EternosMove);
|
||||
}
|
||||
|
||||
Creature verdisa = instance.GetCreature(VerdisaGUID);
|
||||
if (verdisa)
|
||||
{
|
||||
verdisa.SetWalk(true);
|
||||
verdisa.GetMotionMaster().MovePoint(POINT_MOVE_OUT, VerdisaMove);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(uint diff)
|
||||
{
|
||||
_events.Update(diff);
|
||||
|
||||
_events.ExecuteEvents(eventId =>
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_VAROS_INTRO:
|
||||
Creature varos = instance.GetCreature(VarosGUID);
|
||||
if (varos)
|
||||
varos.GetAI().Talk(SAY_VAROS_INTRO_TEXT);
|
||||
break;
|
||||
case EVENT_EREGOS_INTRO:
|
||||
Creature eregos = instance.GetCreature(EregosGUID);
|
||||
if (eregos)
|
||||
eregos.GetAI().Talk(SAY_EREGOS_INTRO_TEXT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void GreaterWhelps()
|
||||
{
|
||||
foreach (ObjectGuid guid in GreaterWhelpList)
|
||||
{
|
||||
Creature gwhelp = instance.GetCreature(guid);
|
||||
if (gwhelp)
|
||||
gwhelp.SetPhaseMask(1, true);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGuid DrakosGUID;
|
||||
ObjectGuid VarosGUID;
|
||||
ObjectGuid UromGUID;
|
||||
ObjectGuid EregosGUID;
|
||||
|
||||
ObjectGuid BelgaristraszGUID;
|
||||
ObjectGuid EternosGUID;
|
||||
ObjectGuid VerdisaGUID;
|
||||
|
||||
byte CentrifugueConstructCounter;
|
||||
|
||||
ObjectGuid EregosCacheGUID;
|
||||
|
||||
List<ObjectGuid> GreaterWhelpList = new List<ObjectGuid>();
|
||||
|
||||
EventMap events = new EventMap();
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 Game.Entities;
|
||||
|
||||
namespace Scripts.Northrend.Ulduar
|
||||
{
|
||||
namespace Algalon
|
||||
{
|
||||
class AlgalonTheObserver
|
||||
{
|
||||
public static Position AlgalonSummonPos = new Position(1632.531f, -304.8516f, 450.1123f, 1.530165f);
|
||||
public static Position AlgalonLandPos = new Position(1632.668f, -302.7656f, 417.3211f, 1.530165f);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Scripts.Northrend.Ulduar
|
||||
{
|
||||
namespace Razorscale
|
||||
{
|
||||
/*class boss_razorscale_controller : BossAI
|
||||
{
|
||||
public boss_razorscale_controller(Creature creature) : base(creature, InstanceData.RazorscaleControl)
|
||||
{
|
||||
me.SetDisplayId(me.GetCreatureTemplate().ModelId2);
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
}
|
||||
|
||||
public override void SpellHit(Unit caster, SpellInfo spell)
|
||||
{
|
||||
switch (spell.Id)
|
||||
{
|
||||
case SPELL_FLAMED:
|
||||
GameObject Harpoon = ObjectAccessor.GetGameObject(me, instance.GetGuidData(GO_RAZOR_HARPOON_1));
|
||||
if (Harpoon)
|
||||
Harpoon.RemoveFromWorld();
|
||||
Harpoon = ObjectAccessor.GetGameObject(me, instance.GetGuidData(GO_RAZOR_HARPOON_2));
|
||||
if (Harpoon)
|
||||
Harpoon.RemoveFromWorld();
|
||||
Harpoon = ObjectAccessor.GetGameObject(me, instance.GetGuidData(GO_RAZOR_HARPOON_3));
|
||||
if (Harpoon)
|
||||
Harpoon.RemoveFromWorld();
|
||||
Harpoon = ObjectAccessor.GetGameObject(me, instance.GetGuidData(GO_RAZOR_HARPOON_4));
|
||||
if (Harpoon)
|
||||
Harpoon.RemoveFromWorld();
|
||||
|
||||
DoAction(ACTION_HARPOON_BUILD);
|
||||
DoAction(ACTION_PLACE_BROKEN_HARPOON);
|
||||
break;
|
||||
case SPELL_HARPOON_SHOT_1:
|
||||
case SPELL_HARPOON_SHOT_2:
|
||||
case SPELL_HARPOON_SHOT_3:
|
||||
case SPELL_HARPOON_SHOT_4:
|
||||
DoCast(SPELL_HARPOON_TRIGGER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
_JustDied();
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
if (instance.GetBossState(BOSS_RAZORSCALE) != EncounterState.InProgress)
|
||||
return;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case ACTION_HARPOON_BUILD:
|
||||
events.ScheduleEvent(EVENT_BUILD_HARPOON_1, 50000);
|
||||
if (me->GetMap()->GetSpawnMode() == DIFFICULTY_25_N)
|
||||
events.ScheduleEvent(EVENT_BUILD_HARPOON_3, 90000);
|
||||
break;
|
||||
case ACTION_PLACE_BROKEN_HARPOON:
|
||||
for (uint8 n = 0; n < RAID_MODE(2, 4); n++)
|
||||
me->SummonGameObject(GO_RAZOR_BROKEN_HARPOON, PosHarpoon[n].GetPositionX(), PosHarpoon[n].GetPositionY(), PosHarpoon[n].GetPositionZ(), 2.286f, 0, 0, 0, 0, 180);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint Diff)
|
||||
{
|
||||
_events.Update(Diff);
|
||||
|
||||
while (uint eventId = _events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_BUILD_HARPOON_1:
|
||||
Talk(EMOTE_HARPOON);
|
||||
if (GameObject * Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, 0.0f, 0.0f, 0.0f, 0.0f, uint32(me->GetRespawnTime())))
|
||||
{
|
||||
if (GameObject * BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) //only nearest broken harpoon
|
||||
BrokenHarpoon->RemoveFromWorld();
|
||||
events.ScheduleEvent(EVENT_BUILD_HARPOON_2, 20000);
|
||||
events.CancelEvent(EVENT_BUILD_HARPOON_1);
|
||||
}
|
||||
return;
|
||||
case EVENT_BUILD_HARPOON_2:
|
||||
Talk(EMOTE_HARPOON);
|
||||
if (GameObject * Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, 0, 0, 0, 0, uint32(me->GetRespawnTime())))
|
||||
{
|
||||
if (GameObject * BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
|
||||
BrokenHarpoon->RemoveFromWorld();
|
||||
events.CancelEvent(EVENT_BUILD_HARPOON_2);
|
||||
}
|
||||
return;
|
||||
case EVENT_BUILD_HARPOON_3:
|
||||
Talk(EMOTE_HARPOON);
|
||||
if (GameObject * Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, 0, 0, 0, 0, uint32(me->GetRespawnTime())))
|
||||
{
|
||||
if (GameObject * BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
|
||||
BrokenHarpoon->RemoveFromWorld();
|
||||
events.ScheduleEvent(EVENT_BUILD_HARPOON_4, 20000);
|
||||
events.CancelEvent(EVENT_BUILD_HARPOON_3);
|
||||
}
|
||||
return;
|
||||
case EVENT_BUILD_HARPOON_4:
|
||||
Talk(EMOTE_HARPOON);
|
||||
if (GameObject * Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, 0, 0, 0, 0, uint32(me->GetRespawnTime())))
|
||||
{
|
||||
if (GameObject * BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f))
|
||||
BrokenHarpoon->RemoveFromWorld();
|
||||
events.CancelEvent(EVENT_BUILD_HARPOON_4);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override CreatureAI Get(Creature creature)
|
||||
{
|
||||
return GetInstanceAI<boss_razorscale_controllerAI>(creature);
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
namespace Scripts.Northrend.Ulduar
|
||||
{
|
||||
struct BossIds
|
||||
{
|
||||
public const uint MaxEncounter = 17;
|
||||
|
||||
public const uint Leviathan = 0;
|
||||
public const uint Ignis = 1;
|
||||
public const uint Razorscale = 2;
|
||||
public const uint Xt002 = 3;
|
||||
public const uint AssemblyOfIron = 4;
|
||||
public const uint Kologarn = 5;
|
||||
public const uint Auriaya = 6;
|
||||
public const uint Mimiron = 7;
|
||||
public const uint Hodir = 8;
|
||||
public const uint Thorim = 9;
|
||||
public const uint Freya = 10;
|
||||
public const uint Brightleaf = 11;
|
||||
public const uint Ironbranch = 12;
|
||||
public const uint Stonebark = 13;
|
||||
public const uint Vezax = 14;
|
||||
public const uint YoggSaron = 15;
|
||||
public const uint Algalon = 16;
|
||||
}
|
||||
|
||||
struct InstanceCreatureIds
|
||||
{
|
||||
// General
|
||||
public const uint Leviathan = 33113;
|
||||
public const uint SalvagedDemolisher = 33109;
|
||||
public const uint SalvagedSiegeEngine = 33060;
|
||||
public const uint SalvagedChopper = 33062;
|
||||
public const uint Ignis = 33118;
|
||||
public const uint Razorscale = 33186;
|
||||
public const uint RazorscaleController = 33233;
|
||||
public const uint SteelforgedDeffender = 33236;
|
||||
public const uint ExpeditionCommander = 33210;
|
||||
public const uint Xt002 = 33293;
|
||||
public const uint XtToyPile = 33337;
|
||||
public const uint Steelbreaker = 32867;
|
||||
public const uint Molgeim = 32927;
|
||||
public const uint Brundir = 32857;
|
||||
public const uint Kologarn = 32930;
|
||||
public const uint FocusedEyebeam = 33632;
|
||||
public const uint FocusedEyebeamRight = 33802;
|
||||
public const uint LeftArm = 32933;
|
||||
public const uint RightArm = 32934;
|
||||
public const uint Rubble = 33768;
|
||||
public const uint Auriaya = 33515;
|
||||
public const uint Mimiron = 33350;
|
||||
public const uint Hodir = 32845;
|
||||
public const uint Thorim = 32865;
|
||||
public const uint Freya = 32906;
|
||||
public const uint Vezax = 33271;
|
||||
public const uint YoggSaron = 33288;
|
||||
public const uint Algalon = 32871;
|
||||
|
||||
//XT002
|
||||
public const uint XS013Scrapbot = 33343;
|
||||
|
||||
// Mimiron
|
||||
public const uint LeviathanMkII = 33432;
|
||||
public const uint Vx001 = 33651;
|
||||
public const uint AerialCommandUnit = 33670;
|
||||
public const uint AssaultBot = 34057;
|
||||
public const uint BombBot = 33836;
|
||||
public const uint JunkBot = 33855;
|
||||
public const uint EmergencyFireBot = 34147;
|
||||
public const uint FrostBomb = 34149;
|
||||
public const uint BurstTarget = 34211;
|
||||
public const uint Flame = 34363;
|
||||
public const uint FlameSpread = 34121;
|
||||
public const uint DBTarget = 33576;
|
||||
public const uint RocketMimironVisual = 34050;
|
||||
public const uint WorldTriggerMimiron = 21252;
|
||||
public const uint Computer = 34143;
|
||||
|
||||
// Freya'S Keepers
|
||||
public const uint Ironbranch = 32913;
|
||||
public const uint Brightleaf = 32915;
|
||||
public const uint Stonebark = 32914;
|
||||
|
||||
// Hodir'S Helper Npcs
|
||||
public const uint TorGreycloud = 32941;
|
||||
public const uint KarGreycloud = 33333;
|
||||
public const uint EiviNightfeather = 33325;
|
||||
public const uint EllieNightfeather = 32901;
|
||||
public const uint SpiritwalkerTara = 33332;
|
||||
public const uint SpiritwalkerYona = 32950;
|
||||
public const uint ElementalistMahfuun = 33328;
|
||||
public const uint ElementalistAvuun = 32900;
|
||||
public const uint AmiraBlazeweaver = 33331;
|
||||
public const uint VeeshaBlazeweaver = 32946;
|
||||
public const uint MissyFlamecuffs = 32893;
|
||||
public const uint SissyFlamecuffs = 33327;
|
||||
public const uint BattlePriestEliza = 32948;
|
||||
public const uint BattlePriestGina = 33330;
|
||||
public const uint FieldMedicPenny = 32897;
|
||||
public const uint FieldMedicJessi = 33326;
|
||||
|
||||
// Freya'S Trash Npcs
|
||||
public const uint CorruptedServitor = 33354;
|
||||
public const uint MisguidedNymph = 33355;
|
||||
public const uint GuardianLasher = 33430;
|
||||
public const uint ForestSwarmer = 33431;
|
||||
public const uint MangroveEnt = 33525;
|
||||
public const uint IronrootLasher = 33526;
|
||||
public const uint NaturesBlade = 33527;
|
||||
public const uint GuardianOfLife = 33528;
|
||||
|
||||
// Freya Achievement Trigger
|
||||
public const uint FreyaAchieveTrigger = 33406;
|
||||
|
||||
// Yogg-Saron
|
||||
public const uint Sara = 33134;
|
||||
public const uint GuardianOfYoggSaron = 33136;
|
||||
public const uint HodirObservationRing = 33213;
|
||||
public const uint FreyaObservationRing = 33241;
|
||||
public const uint ThorimObservationRing = 33242;
|
||||
public const uint MimironObservationRing = 33244;
|
||||
public const uint VoiceOfYoggSaron = 33280;
|
||||
public const uint OminousCloud = 33292;
|
||||
public const uint FreyaYs = 33410;
|
||||
public const uint HodirYs = 33411;
|
||||
public const uint MimironYs = 33412;
|
||||
public const uint ThorimYs = 33413;
|
||||
public const uint SuitOfArmor = 33433;
|
||||
public const uint KingLlane = 33437;
|
||||
public const uint TheLichKing = 33441;
|
||||
public const uint ImmolatedChampion = 33442;
|
||||
public const uint Ysera = 33495;
|
||||
public const uint Neltharion = 33523;
|
||||
public const uint Malygos = 33535;
|
||||
public const uint DeathRay = 33881;
|
||||
public const uint DeathOrb = 33882;
|
||||
public const uint BrainOfYoggSaron = 33890;
|
||||
public const uint InfluenceTentacle = 33943;
|
||||
public const uint TurnedChampion = 33962;
|
||||
public const uint CrusherTentacle = 33966;
|
||||
public const uint ConstrictorTentacle = 33983;
|
||||
public const uint CorruptorTentacle = 33985;
|
||||
public const uint ImmortalGuardian = 33988;
|
||||
public const uint SanityWell = 33991;
|
||||
public const uint DescendIntoMadness = 34072;
|
||||
public const uint MarkedImmortalGuardian = 36064;
|
||||
|
||||
// Algalon The Observer
|
||||
public const uint BrannBronzbeardAlg = 34064;
|
||||
public const uint Azeroth = 34246;
|
||||
public const uint LivingConstellation = 33052;
|
||||
public const uint AlgalonStalker = 33086;
|
||||
public const uint CollapsingStar = 32955;
|
||||
public const uint BlackHole = 32953;
|
||||
public const uint WormHole = 34099;
|
||||
public const uint AlgalonVoidZoneVisualStalker = 34100;
|
||||
public const uint AlgalonStalkerAsteroidTarget01 = 33104;
|
||||
public const uint AlgalonStalkerAsteroidTarget02 = 33105;
|
||||
public const uint UnleashedDarkMatter = 34097;
|
||||
}
|
||||
|
||||
struct InstanceGameObjectIds
|
||||
{
|
||||
// Leviathan
|
||||
public const uint LeviathanDoor = 194905;
|
||||
public const uint LeviathanGate = 194630;
|
||||
|
||||
// Razorscale
|
||||
public const uint MoleMachine = 194316;
|
||||
public const uint RazorHarpoon1 = 194542;
|
||||
public const uint RazorHarpoon2 = 194541;
|
||||
public const uint RazorHarpoon3 = 194543;
|
||||
public const uint RazorHarpoon4 = 194519;
|
||||
public const uint RazorBrokenHarpoon = 194565;
|
||||
|
||||
// Xt-002
|
||||
public const uint Xt002Door = 194631;
|
||||
|
||||
// Assembly Of Iron
|
||||
public const uint IronCouncilDoor = 194554;
|
||||
public const uint ArchivumDoor = 194556;
|
||||
|
||||
// Kologarn
|
||||
public const uint KologarnChestHero = 195047;
|
||||
public const uint KologarnChest = 195046;
|
||||
public const uint KologarnBridge = 194232;
|
||||
public const uint KologarnDoor = 194553;
|
||||
|
||||
// Hodir
|
||||
public const uint HodirEntrance = 194442;
|
||||
public const uint HodirDoor = 194634;
|
||||
public const uint HodirIceDoor = 194441;
|
||||
public const uint HodirRareCacheOfWinter = 194200;
|
||||
public const uint HodirRareCacheOfWinterHero = 194201;
|
||||
public const uint HodirChestHero = 194308;
|
||||
public const uint HodirChest = 194307;
|
||||
|
||||
// Thorim
|
||||
public const uint ThorimChestHero = 194315;
|
||||
public const uint ThorimChest = 194314;
|
||||
|
||||
// Mimiron
|
||||
public const uint MimironTram = 194675;
|
||||
public const uint MimironElevator = 194749;
|
||||
public const uint MimironButton = 194739;
|
||||
public const uint MimironDoor1 = 194774;
|
||||
public const uint MimironDoor2 = 194775;
|
||||
public const uint MimironDoor3 = 194776;
|
||||
public const uint CacheOfInnovation = 194789;
|
||||
public const uint CacheOfInnovationFirefighter = 194957;
|
||||
public const uint CacheOfInnovationHero = 194956;
|
||||
public const uint CacheOfInnovationFirefighterHero = 194958;
|
||||
|
||||
// Vezax
|
||||
public const uint VezaxDoor = 194750;
|
||||
|
||||
// Yogg-Saron
|
||||
public const uint YoggSaronDoor = 194773;
|
||||
public const uint BrainRoomDoor1 = 194635;
|
||||
public const uint BrainRoomDoor2 = 194636;
|
||||
public const uint BrainRoomDoor3 = 194637;
|
||||
|
||||
// Algalon The Observer
|
||||
public const uint CelestialPlanetariumAccess10 = 194628;
|
||||
public const uint CelestialPlanetariumAccess25 = 194752;
|
||||
public const uint DoodadUlSigildoor01 = 194767;
|
||||
public const uint DoodadUlSigildoor02 = 194911;
|
||||
public const uint DoodadUlSigildoor03 = 194910;
|
||||
public const uint DoodadUlUniversefloor01 = 194715;
|
||||
public const uint DoodadUlUniversefloor02 = 194716;
|
||||
public const uint DoodadUlUniverseglobe01 = 194148;
|
||||
public const uint DoodadUlUlduarTrapdoor03 = 194253;
|
||||
public const uint GiftOfTheObserver10 = 194821;
|
||||
public const uint GiftOfTheObserver25 = 194822;
|
||||
}
|
||||
|
||||
struct InstanceEventIds
|
||||
{
|
||||
public const int TowerOfStormDestroyed = 21031;
|
||||
public const int TowerOfFrostDestroyed = 21032;
|
||||
public const int TowerOfFlamesDestroyed = 21033;
|
||||
public const int TowerOfLifeDestroyed = 21030;
|
||||
public const int ActivateSanityWell = 21432;
|
||||
public const int HodirsProtectiveGazeProc = 21437;
|
||||
}
|
||||
|
||||
struct LeviathanActions
|
||||
{
|
||||
public const int TowerOfStormDestroyed = 1;
|
||||
public const int TowerOfFrostDestroyed = 2;
|
||||
public const int TowerOfFlamesDestroyed = 3;
|
||||
public const int TowerOfLifeDestroyed = 4;
|
||||
public const int MoveToCenterPosition = 10;
|
||||
}
|
||||
|
||||
struct InstanceCriteriaIds
|
||||
{
|
||||
public const uint ConSpeedAtory = 21597;
|
||||
public const uint Lumberjacked = 21686;
|
||||
public const uint Disarmed = 21687;
|
||||
public const uint WaitsDreamingStormwind25 = 10321;
|
||||
public const uint WaitsDreamingChamber25 = 10322;
|
||||
public const uint WaitsDreamingIcecrown25 = 10323;
|
||||
public const uint WaitsDreamingStormwind10 = 10324;
|
||||
public const uint WaitsDreamingChamber10 = 10325;
|
||||
public const uint WaitsDreamingIcecrown10 = 10326;
|
||||
public const uint DriveMeCrazy10 = 10185;
|
||||
public const uint DriveMeCrazy25 = 10296;
|
||||
public const uint ThreeLightsInTheDarkness10 = 10410;
|
||||
public const uint ThreeLightsInTheDarkness25 = 10414;
|
||||
public const uint TwoLightsInTheDarkness10 = 10388;
|
||||
public const uint TwoLightsInTheDarkness25 = 10415;
|
||||
public const uint OneLightInTheDarkness10 = 10409;
|
||||
public const uint OneLightInTheDarkness25 = 10416;
|
||||
public const uint AloneInTheDarkness10 = 10412;
|
||||
public const uint AloneInTheDarkness25 = 10417;
|
||||
public const uint HeraldOfTitans = 10678;
|
||||
|
||||
// Champion Of Ulduar
|
||||
public const uint ChampionLeviathan10 = 10042;
|
||||
public const uint ChampionIgnis10 = 10342;
|
||||
public const uint ChampionRazorscale10 = 10340;
|
||||
public const uint ChampionXt002_10 = 10341;
|
||||
public const uint ChampionIronCouncil10 = 10598;
|
||||
public const uint ChampionKologarn10 = 10348;
|
||||
public const uint ChampionAuriaya10 = 10351;
|
||||
public const uint ChampionHodir10 = 10439;
|
||||
public const uint ChampionThorim10 = 10403;
|
||||
public const uint ChampionFreya10 = 10582;
|
||||
public const uint ChampionMimiron10 = 10347;
|
||||
public const uint ChampionVezax10 = 10349;
|
||||
public const uint ChampionYoggSaron10 = 10350;
|
||||
// Conqueror Of Ulduar
|
||||
public const uint ChampionLeviathan25 = 10352;
|
||||
public const uint ChampionIgnis25 = 10355;
|
||||
public const uint ChampionRazorscale25 = 10353;
|
||||
public const uint ChampionXt002_25 = 10354;
|
||||
public const uint ChampionIronCouncil25 = 10599;
|
||||
public const uint ChampionKologarn25 = 10357;
|
||||
public const uint ChampionAuriaya25 = 10363;
|
||||
public const uint ChampionHodir25 = 10719;
|
||||
public const uint ChampionThorim25 = 10404;
|
||||
public const uint ChampionFreya25 = 10583;
|
||||
public const uint ChampionMimiron25 = 10361;
|
||||
public const uint ChampionVezax25 = 10362;
|
||||
public const uint ChampionYoggSaron25 = 10364;
|
||||
}
|
||||
|
||||
struct InstanceData
|
||||
{
|
||||
// Colossus (Leviathan)
|
||||
public const uint Colossus = 20;
|
||||
|
||||
// Razorscale
|
||||
public const uint ExpeditionCommander = 21;
|
||||
public const uint RazorscaleControl = 22;
|
||||
|
||||
// Xt-002
|
||||
public const uint ToyPile0 = 23;
|
||||
public const uint ToyPile1 = 24;
|
||||
public const uint ToyPile2 = 25;
|
||||
public const uint ToyPile3 = 26;
|
||||
|
||||
// Assembly Of Iron
|
||||
public const uint Steelbreaker = 27;
|
||||
public const uint Molgeim = 28;
|
||||
public const uint Brundir = 29;
|
||||
|
||||
// Hodir
|
||||
public const uint HodirRareCache = 30;
|
||||
|
||||
// Mimiron
|
||||
public const uint LeviathanMKII = 31;
|
||||
public const uint VX001 = 32;
|
||||
public const uint AerialCommandUnit = 33;
|
||||
public const uint Computer = 34;
|
||||
public const uint MimironWorldTrigger = 35;
|
||||
public const uint MimironElevator = 36;
|
||||
public const uint MimironTram = 37;
|
||||
public const uint MimironButton = 38;
|
||||
|
||||
// Yogg-Saron
|
||||
public const uint VoiceOfYoggSaron = 39;
|
||||
public const uint Sara = 40;
|
||||
public const uint BrainOfYoggSaron = 41;
|
||||
public const uint FreyaYs = 42;
|
||||
public const uint HodirYs = 43;
|
||||
public const uint ThorimYs = 44;
|
||||
public const uint MimironYs = 45;
|
||||
public const uint Illusion = 46;
|
||||
public const uint DriveMeCrazy = 47;
|
||||
public const uint KeepersCount = 48;
|
||||
|
||||
// Algalon The Observer
|
||||
public const uint AlgalonSummonState = 49;
|
||||
public const uint Sigildoor01 = 50;
|
||||
public const uint Sigildoor02 = 51;
|
||||
public const uint Sigildoor03 = 52;
|
||||
public const uint UniverseFloor01 = 53;
|
||||
public const uint UniverseFloor02 = 54;
|
||||
public const uint UniverseGlobe = 55;
|
||||
public const uint AlgalonTrapdoor = 56;
|
||||
public const uint BrannBronzebeardAlg = 57;
|
||||
|
||||
// Misc
|
||||
public const uint BrannBronzebeardIntro = 58;
|
||||
public const uint LoreKeeperOfNorgannon = 59;
|
||||
public const uint Dellorah = 60;
|
||||
public const uint BronzebeardRadio = 61;
|
||||
}
|
||||
|
||||
struct InstanceWorldStates
|
||||
{
|
||||
public const uint AlgalonDespawnTimer = 4131;
|
||||
public const uint AlgalonTimerEnabled = 4132;
|
||||
}
|
||||
|
||||
struct InstanceAchievementData
|
||||
{
|
||||
// Fl Achievement Boolean
|
||||
public const uint DataUnbroken = 29052906; // 2905, 2906 Are Achievement Ids,
|
||||
public const uint MaxHeraldArmorItemlevel = 226;
|
||||
public const uint MaxHeraldWeaponItemlevel = 232;
|
||||
}
|
||||
|
||||
struct InstanceEvents
|
||||
{
|
||||
public const uint EventDespawnAlgalon = 1;
|
||||
public const uint EventUpdateAlgalonTimer = 2;
|
||||
public const uint ActionInitAlgalon = 6;
|
||||
}
|
||||
|
||||
struct YoggSaronIllusions
|
||||
{
|
||||
public const uint ChamberIllusion = 0;
|
||||
public const uint IcecrownIllusion = 1;
|
||||
public const uint StormwindIllusion = 2;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,884 @@
|
||||
/*
|
||||
* 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 Framework.Dynamic;
|
||||
using Game.AI;
|
||||
using Game.Entities;
|
||||
using Game.Maps;
|
||||
using Game.Scripting;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Scripts.Northrend.Ulduar.Xt002
|
||||
{
|
||||
struct SpellIds
|
||||
{
|
||||
public const uint TympanicTantrum = 62776;
|
||||
public const uint SearingLight = 63018;
|
||||
|
||||
public const uint SummonLifeSpark = 64210;
|
||||
public const uint SummonVoidZone = 64203;
|
||||
|
||||
public const uint GravityBomb = 63024;
|
||||
|
||||
public const uint Heartbreak = 65737;
|
||||
|
||||
// Cast By 33337 At Heartbreak:
|
||||
public const uint RechargePummeler = 62831; // Summons 33344
|
||||
public const uint RechargeScrapbot = 62828; // Summons 33343
|
||||
public const uint RechargeBoombot = 62835; // Summons 33346
|
||||
|
||||
// Cast By 33329 On 33337 (Visual?)
|
||||
public const uint EnergyOrb = 62790; // Triggers 62826 - Needs Spellscript For Periodic Tick To Cast One Of The Random Spells Above
|
||||
|
||||
public const uint HeartHealToFull = 17683;
|
||||
public const uint HeartOverload = 62789;
|
||||
|
||||
public const uint HeartLightningTether = 64799; // Cast On Self?
|
||||
public const uint Enrage = 26662;
|
||||
public const uint Stand = 37752;
|
||||
public const uint Submerge = 37751;
|
||||
|
||||
//------------------Void Zone--------------------
|
||||
public const uint VoidZone = 64203;
|
||||
public const uint Consumption = 64208;
|
||||
|
||||
// Life Spark
|
||||
public const uint ArcanePowerState = 49411;
|
||||
public const uint StaticCharged = 64227;
|
||||
public const uint Shock = 64230;
|
||||
|
||||
//----------------Xt-002 Heart-------------------
|
||||
public const uint ExposedHeart = 63849;
|
||||
public const uint HeartRideVehicle = 63852;
|
||||
public const uint RideVehicleExposed = 63313; //Heart Exposed
|
||||
|
||||
//---------------Xm-024 Pummeller----------------
|
||||
public const uint ArcingSmash = 8374;
|
||||
public const uint Trample = 5568;
|
||||
public const uint Uppercut = 10966;
|
||||
|
||||
// Scrabot:
|
||||
public const uint ScrapbotRideVehicle = 47020;
|
||||
public const uint ScrapRepair = 62832;
|
||||
public const uint Suicide = 7;
|
||||
|
||||
//------------------Boombot-----------------------
|
||||
public const uint AuraBoombot = 65032;
|
||||
public const uint Boom = 62834;
|
||||
|
||||
// Achievement-Related Spells
|
||||
public const uint AchievementCreditNerfScrapbots = 65037;
|
||||
}
|
||||
|
||||
struct XT002Data
|
||||
{
|
||||
public const uint TransferedHealth = 0;
|
||||
public const uint HardMode = 1;
|
||||
public const uint HealthRecovered = 2;
|
||||
public const uint GravityBombCasualty = 3;
|
||||
}
|
||||
|
||||
struct Texts
|
||||
{
|
||||
public const uint Aggro = 0;
|
||||
public const uint HeartOpened = 1;
|
||||
public const uint HeartClosed = 2;
|
||||
public const uint TympanicTantrum = 3;
|
||||
public const uint Slay = 4;
|
||||
public const uint Berserk = 5;
|
||||
public const uint Death = 6;
|
||||
public const uint Summon = 7;
|
||||
public const uint EmoteHeartOpened = 8;
|
||||
public const uint EmoteHeartClosed = 9;
|
||||
public const uint EmoteTympanicTantrum = 10;
|
||||
public const uint EmoteScrapbot = 11;
|
||||
}
|
||||
|
||||
struct Misc
|
||||
{
|
||||
public const uint PhaseOneGroup = 1;
|
||||
public const int ActionHardMode = 1;
|
||||
public const uint AchievMustDeconstructFaster = 21027;
|
||||
|
||||
public const sbyte SeatHeartNormal = 0;
|
||||
public const sbyte SeatHeartExposed = 1;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class boss_xt002 : BossAI
|
||||
{
|
||||
public boss_xt002(Creature creature) : base(creature, BossIds.Xt002)
|
||||
{
|
||||
Initialize();
|
||||
_transferHealth = 0;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_healthRecovered = false;
|
||||
_gravityBombCasualty = false;
|
||||
_hardMode = false;
|
||||
|
||||
_heartExposed = 0;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_Reset();
|
||||
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
me.SetReactState(ReactStates.Aggressive);
|
||||
DoCastSelf(SpellIds.Stand);
|
||||
|
||||
Initialize();
|
||||
|
||||
instance.DoStopCriteriaTimer(CriteriaTimedTypes.Event, Misc.AchievMustDeconstructFaster);
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit who)
|
||||
{
|
||||
Talk(Texts.Aggro);
|
||||
_EnterCombat();
|
||||
|
||||
//Enrage
|
||||
_scheduler.Schedule(TimeSpan.FromMinutes(10), task =>
|
||||
{
|
||||
Talk(Texts.Berserk);
|
||||
DoCastSelf(SpellIds.Enrage);
|
||||
});
|
||||
|
||||
//Gavity Bomb
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(20), Misc.PhaseOneGroup, task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.GravityBomb);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(20));
|
||||
});
|
||||
|
||||
//Searing Light
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(20), Misc.PhaseOneGroup, task =>
|
||||
{
|
||||
Unit target = SelectTarget(SelectAggroTarget.Random, 0);
|
||||
if (target)
|
||||
DoCast(target, SpellIds.SearingLight);
|
||||
|
||||
task.Repeat(TimeSpan.FromSeconds(20));
|
||||
});
|
||||
|
||||
//Tympanic Tantrum
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(30), Misc.PhaseOneGroup, task =>
|
||||
{
|
||||
Talk(Texts.TympanicTantrum);
|
||||
Talk(Texts.EmoteTympanicTantrum);
|
||||
DoCast(SpellIds.TympanicTantrum);
|
||||
task.Repeat(TimeSpan.FromSeconds(30));
|
||||
});
|
||||
|
||||
instance.DoStartCriteriaTimer(CriteriaTimedTypes.Event, Misc.AchievMustDeconstructFaster);
|
||||
}
|
||||
|
||||
public override void DoAction(int action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case Misc.ActionHardMode:
|
||||
_scheduler.Schedule(TimeSpan.FromMilliseconds(1), task =>
|
||||
{
|
||||
SetPhaseOne(true);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void KilledUnit(Unit who)
|
||||
{
|
||||
if (who.GetTypeId() == TypeId.Player)
|
||||
Talk(Texts.Slay);
|
||||
}
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Talk(Texts.Death);
|
||||
_JustDied();
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||
{
|
||||
if (!_hardMode && !me.HasReactState(ReactStates.Passive) && !HealthAbovePct(100 - 25 * (_heartExposed + 1)))
|
||||
ExposeHeart();
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
if (!me.HasReactState(ReactStates.Passive))
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
public override void PassengerBoarded(Unit who, sbyte seatId, bool apply)
|
||||
{
|
||||
if (apply && who.GetEntry() == InstanceCreatureIds.XS013Scrapbot)
|
||||
{
|
||||
// Need this so we can properly determine when to expose heart again in damagetaken hook
|
||||
if (me.GetHealthPct() > (25 * (4 - _heartExposed)))
|
||||
++_heartExposed;
|
||||
|
||||
Talk(Texts.EmoteScrapbot);
|
||||
DoCast(who, SpellIds.ScrapRepair, true);
|
||||
_healthRecovered = true;
|
||||
}
|
||||
|
||||
if (apply && seatId == Misc.SeatHeartExposed)
|
||||
who.CastSpell(who, SpellIds.ExposedHeart); // Channeled
|
||||
}
|
||||
|
||||
public override uint GetData(uint type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case XT002Data.HardMode:
|
||||
return _hardMode ? 1 : 0u;
|
||||
case XT002Data.HealthRecovered:
|
||||
return _healthRecovered ? 1 : 0u;
|
||||
case XT002Data.GravityBombCasualty:
|
||||
return _gravityBombCasualty ? 1 : 0u;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void SetData(uint type, uint data)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case XT002Data.TransferedHealth:
|
||||
_transferHealth = data;
|
||||
break;
|
||||
case XT002Data.GravityBombCasualty:
|
||||
_gravityBombCasualty = (data > 0) ? true : false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ExposeHeart()
|
||||
{
|
||||
Talk(Texts.HeartOpened);
|
||||
Talk(Texts.EmoteHeartOpened);
|
||||
|
||||
DoCastSelf(SpellIds.Submerge); // WIll make creature untargetable
|
||||
me.AttackStop();
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
|
||||
Unit heart = me.GetVehicleKit() ? me.GetVehicleKit().GetPassenger(Misc.SeatHeartNormal) : null;
|
||||
if (heart)
|
||||
{
|
||||
heart.CastSpell(heart, SpellIds.HeartOverload);
|
||||
heart.CastSpell(me, SpellIds.HeartLightningTether);
|
||||
heart.CastSpell(heart, SpellIds.HeartHealToFull, true);
|
||||
heart.CastSpell(me, SpellIds.RideVehicleExposed, true);
|
||||
heart.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
heart.SetFlag(UnitFields.Flags, UnitFlags.Unk29);
|
||||
}
|
||||
_scheduler.DelayGroup(Misc.PhaseOneGroup, TimeSpan.FromSeconds(30));
|
||||
|
||||
// Start "end of phase 2 timer"
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(30), task => { SetPhaseOne(false); });
|
||||
|
||||
_heartExposed++;
|
||||
}
|
||||
|
||||
void SetPhaseOne(bool isHardMode)
|
||||
{
|
||||
if (isHardMode)
|
||||
{
|
||||
me.SetFullHealth();
|
||||
DoCastSelf(SpellIds.Heartbreak, true);
|
||||
me.AddLootMode(LootModes.HardMode1);
|
||||
_hardMode = true;
|
||||
}
|
||||
|
||||
Talk(Texts.HeartClosed);
|
||||
Talk(Texts.EmoteHeartClosed);
|
||||
|
||||
me.RemoveFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
me.SetReactState(ReactStates.Aggressive);
|
||||
DoCastSelf(SpellIds.Stand);
|
||||
|
||||
//_events.RescheduleEvent(EVENT_SEARING_LIGHT, TIMER_SEARING_LIGHT / 2);
|
||||
//_events.RescheduleEvent(EVENT_GRAVITY_BOMB, TIMER_GRAVITY_BOMB);
|
||||
//_events.RescheduleEvent(EVENT_TYMPANIC_TANTRUM, RandomHelper.URand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX));
|
||||
|
||||
Unit heart = me.GetVehicleKit() ? me.GetVehicleKit().GetPassenger(Misc.SeatHeartExposed) : null;
|
||||
if (!heart)
|
||||
return;
|
||||
|
||||
heart.CastSpell(me, SpellIds.HeartRideVehicle, true);
|
||||
heart.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
heart.RemoveFlag(UnitFields.Flags, UnitFlags.Unk29);
|
||||
heart.RemoveAurasDueToSpell(SpellIds.ExposedHeart);
|
||||
|
||||
if (!_hardMode)
|
||||
{
|
||||
if (_transferHealth == 0)
|
||||
_transferHealth = (uint)(heart.GetMaxHealth() - heart.GetHealth());
|
||||
|
||||
if (_transferHealth >= me.GetHealth())
|
||||
_transferHealth = (uint)me.GetHealth() - 1;
|
||||
|
||||
me.ModifyHealth(-(int)_transferHealth);
|
||||
me.LowerPlayerDamageReq(_transferHealth);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievement related
|
||||
bool _healthRecovered; // Did a scrapbot recover XT-002's health during the encounter?
|
||||
bool _hardMode; // Are we in hard mode? Or: was the heart killed during phase 2?
|
||||
bool _gravityBombCasualty; // Did someone die because of Gravity Bomb damage?
|
||||
|
||||
byte _heartExposed;
|
||||
uint _transferHealth;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_xt002_heart : ScriptedAI
|
||||
{
|
||||
public npc_xt002_heart(Creature creature) : base(creature)
|
||||
{
|
||||
_instance = creature.GetInstanceScript();
|
||||
|
||||
SetCombatMovement(false);
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff) { }
|
||||
|
||||
public override void JustDied(Unit killer)
|
||||
{
|
||||
Creature xt002 = _instance != null ? ObjectAccessor.GetCreature(me, _instance.GetGuidData(BossIds.Xt002)) : null;
|
||||
if (!xt002 || xt002.GetAI() == null)
|
||||
return;
|
||||
|
||||
xt002.GetAI().SetData(XT002Data.TransferedHealth, (uint)me.GetHealth());
|
||||
xt002.GetAI().DoAction(Misc.ActionHardMode);
|
||||
}
|
||||
|
||||
InstanceScript _instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_scrapbot : ScriptedAI
|
||||
{
|
||||
public npc_scrapbot(Creature creature) : base(creature)
|
||||
{
|
||||
_instance = me.GetInstanceScript();
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
me.SetReactState(ReactStates.Passive);
|
||||
Creature pXT002 = ObjectAccessor.GetCreature(me, _instance.GetGuidData(BossIds.Xt002));
|
||||
if (pXT002)
|
||||
me.GetMotionMaster().MoveFollow(pXT002, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public override void MovementInform(MovementGeneratorType type, uint id)
|
||||
{
|
||||
ObjectGuid guid = _instance.GetGuidData(BossIds.Xt002);
|
||||
if (type == MovementGeneratorType.Follow && id == guid.GetCounter())
|
||||
{
|
||||
Creature xt002 = ObjectAccessor.GetCreature(me, guid);
|
||||
if (xt002)
|
||||
{
|
||||
if (me.IsWithinMeleeRange(xt002))
|
||||
{
|
||||
DoCast(xt002, SpellIds.ScrapbotRideVehicle);
|
||||
// Unapply vehicle aura again
|
||||
xt002.RemoveAurasDueToSpell(SpellIds.ScrapbotRideVehicle);
|
||||
me.DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstanceScript _instance;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_pummeller : ScriptedAI
|
||||
{
|
||||
public npc_pummeller(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
_instance = creature.GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_scheduler.SetValidator(() => me.IsWithinMeleeRange(me.GetVictim()));
|
||||
|
||||
//Arcing Smash
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(27), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.ArcingSmash);
|
||||
task.Repeat(TimeSpan.FromSeconds(27));
|
||||
});
|
||||
|
||||
//Trample
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(22), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Trample);
|
||||
task.Repeat(TimeSpan.FromSeconds(22));
|
||||
});
|
||||
|
||||
//Uppercut
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(17), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Uppercut);
|
||||
task.Repeat(TimeSpan.FromSeconds(17));
|
||||
});
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
Creature xt002 = ObjectAccessor.GetCreature(me, _instance.GetGuidData(BossIds.Xt002));
|
||||
if (xt002)
|
||||
{
|
||||
Position pos = xt002.GetPosition();
|
||||
me.GetMotionMaster().MovePoint(0, pos);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
InstanceScript _instance;
|
||||
}
|
||||
|
||||
class BoomEvent : BasicEvent
|
||||
{
|
||||
public BoomEvent(Creature me)
|
||||
{
|
||||
_me = me;
|
||||
}
|
||||
|
||||
public override bool Execute(ulong time, uint diff)
|
||||
{
|
||||
// This hack is here because we suspect our implementation of spell effect execution on targets
|
||||
// is done in the wrong order. We suspect that 0 needs to be applied on all targets,
|
||||
// then 1, etc - instead of applying each effect on target1, then target2, etc.
|
||||
// The above situation causes the visual for this spell to be bugged, so we remove the instakill
|
||||
// effect and implement a script hack for that.
|
||||
|
||||
_me.CastSpell(_me, SpellIds.Boom, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
Creature _me;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_boombot : ScriptedAI
|
||||
{
|
||||
public npc_boombot(Creature creature) : base(creature)
|
||||
{
|
||||
Initialize();
|
||||
_instance = creature.GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_boomed = false;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
Initialize();
|
||||
|
||||
DoCast(SpellIds.AuraBoombot); // For achievement
|
||||
|
||||
// HACK/workaround:
|
||||
// these values aren't confirmed - lack of data - and the values in DB are incorrect
|
||||
// these values are needed for correct damage of Boom spell
|
||||
me.SetFloatValue(UnitFields.MinDamage, 15000.0f);
|
||||
me.SetFloatValue(UnitFields.MaxDamage, 18000.0f);
|
||||
|
||||
// @todo proper waypoints?
|
||||
Creature pXT002 = ObjectAccessor.GetCreature(me, _instance.GetGuidData(BossIds.Xt002));
|
||||
if (pXT002)
|
||||
me.GetMotionMaster().MoveFollow(pXT002, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public override void DamageTaken(Unit who, ref uint damage)
|
||||
{
|
||||
if (damage >= (me.GetHealth() - me.GetMaxHealth() * 0.5f) && !_boomed)
|
||||
{
|
||||
_boomed = true; // Prevent recursive calls
|
||||
|
||||
//me.SendSpellInstakillLog(Spells.Boom, me);
|
||||
|
||||
//me.DealDamage(me, me.GetHealth(), null, DamageEffectType.NoDamage, SpellSchoolMask.Normal, null, false);
|
||||
|
||||
damage = 0;
|
||||
|
||||
me.CastSpell(me, SpellIds.Boom, false);
|
||||
|
||||
// Visual only seems to work if the instant kill event is delayed or the spell itself is delayed
|
||||
// Casting done from player and caster source has the same targetinfo flags,
|
||||
// so that can't be the issue
|
||||
// See BoomEvent class
|
||||
// Schedule 1s delayed
|
||||
//me.m_Events.AddEvent(new BoomEvent(me), me.m_Events.CalculateTime(1 * Time.InMilliseconds));
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
// No melee attack
|
||||
}
|
||||
|
||||
InstanceScript _instance;
|
||||
bool _boomed;
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_life_spark : ScriptedAI
|
||||
{
|
||||
public npc_life_spark(Creature creature) : base(creature) { }
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromMilliseconds(1), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Shock);
|
||||
task.Repeat(TimeSpan.FromSeconds(12));
|
||||
});
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
DoCastSelf(SpellIds.ArcanePowerState);
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
public override void EnterCombat(Unit victim)
|
||||
{
|
||||
DoCastSelf(SpellIds.StaticCharged);
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
|
||||
{
|
||||
DoCastVictim(SpellIds.Shock);
|
||||
task.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me.HasUnitState(UnitState.Casting))
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff, DoMeleeAttackIfReady);
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class npc_xt_void_zone : PassiveAI
|
||||
{
|
||||
public npc_xt_void_zone(Creature creature) : base(creature) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
_scheduler.Schedule(TimeSpan.FromSeconds(1), consumption =>
|
||||
{
|
||||
DoCastSelf(SpellIds.Consumption);
|
||||
consumption.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
public override void UpdateAI(uint diff)
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_xt002_searing_light_spawn_life_spark : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.SummonLifeSpark);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
Player player = GetOwner().ToPlayer();
|
||||
if (player)
|
||||
{
|
||||
Unit xt002 = GetCaster();
|
||||
if (xt002)
|
||||
if (xt002.HasAura((uint)aurEff.GetAmount())) // Heartbreak aura indicating hard mode
|
||||
xt002.CastSpell(player, SpellIds.SummonLifeSpark, true);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
AfterEffectRemove.Add(new EffectApplyHandler(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_xt002_gravity_bomb_aura : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.SummonVoidZone);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect aurEff, AuraEffectHandleModes mode)
|
||||
{
|
||||
Player player = GetOwner().ToPlayer();
|
||||
if (player)
|
||||
{
|
||||
Unit xt002 = GetCaster();
|
||||
if (xt002)
|
||||
if (xt002.HasAura((uint)aurEff.GetAmount())) // Heartbreak aura indicating hard mode
|
||||
xt002.CastSpell(player, SpellIds.SummonVoidZone, true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect aurEff)
|
||||
{
|
||||
Unit xt002 = GetCaster();
|
||||
if (!xt002)
|
||||
return;
|
||||
|
||||
Unit owner = GetOwner().ToUnit();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
if ((uint)aurEff.GetAmount() >= owner.GetHealth())
|
||||
if (xt002.GetAI() != null)
|
||||
xt002.GetAI().SetData(XT002Data.GravityBombCasualty, 1);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectPeriodic.Add(new EffectPeriodicHandler(OnPeriodic, 2, AuraType.PeriodicDamage));
|
||||
AfterEffectRemove.Add(new EffectApplyHandler(OnRemove, 0, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_xt002_gravity_bomb_damage : SpellScript
|
||||
{
|
||||
void HandleScript(uint eff)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
if ((uint)GetHitDamage() >= GetHitUnit().GetHealth())
|
||||
if (caster.GetAI() != null)
|
||||
caster.GetAI().SetData(XT002Data.GravityBombCasualty, 1);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.SchoolDamage));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_xt002_heart_overload_periodic : SpellScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spell)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.EnergyOrb, SpellIds.RechargeBoombot, SpellIds.RechargePummeler, SpellIds.RechargeScrapbot);
|
||||
}
|
||||
|
||||
void HandleScript(uint effIndex)
|
||||
{
|
||||
Unit caster = GetCaster();
|
||||
if (caster)
|
||||
{
|
||||
InstanceScript instance = caster.GetInstanceScript();
|
||||
if (instance != null)
|
||||
{
|
||||
Unit toyPile = Global.ObjAccessor.GetUnit(caster, instance.GetGuidData(InstanceData.ToyPile0 + RandomHelper.URand(0, 3)));
|
||||
if (toyPile)
|
||||
{
|
||||
caster.CastSpell(toyPile, SpellIds.EnergyOrb, true);
|
||||
|
||||
// This should probably be incorporated in a dummy effect handler, but I've had trouble getting the correct target
|
||||
// Weighed randomization (approximation)
|
||||
uint[] spells = { SpellIds.RechargeScrapbot, SpellIds.RechargeScrapbot, SpellIds.RechargeScrapbot, SpellIds.RechargePummeler, SpellIds.RechargeBoombot };
|
||||
|
||||
for (byte i = 0; i < 5; ++i)
|
||||
{
|
||||
uint spellId = spells[RandomHelper.IRand(0, 4)];
|
||||
toyPile.CastSpell(toyPile, spellId, true, null, null, instance.GetGuidData(BossIds.Xt002));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Creature creatureBase = caster.GetVehicleCreatureBase();
|
||||
if (creatureBase)
|
||||
creatureBase.GetAI().Talk(Texts.Summon);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHit.Add(new EffectHandler(HandleScript, 0, SpellEffectName.Dummy));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_xt002_tympanic_tantrum : SpellScript
|
||||
{
|
||||
void FilterTargets(List<WorldObject> targets)
|
||||
{
|
||||
targets.RemoveAll(new PlayerOrPetCheck());
|
||||
}
|
||||
|
||||
void RecalculateDamage()
|
||||
{
|
||||
SetHitDamage((int)GetHitUnit().CountPctFromMaxHealth(GetHitDamage()));
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, 0, Targets.UnitSrcAreaEnemy));
|
||||
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, 1, Targets.UnitSrcAreaEnemy));
|
||||
OnHit.Add(new HitHandler(RecalculateDamage));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_xt002_submerged : SpellScript
|
||||
{
|
||||
void HandleScript(uint eff)
|
||||
{
|
||||
Creature target = GetHitCreature();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target.SetFlag(UnitFields.Flags, UnitFlags.NotSelectable);
|
||||
target.SetStandState(UnitStandStateType.Submerged);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.ScriptEffect));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_xt002_321_boombot_aura : AuraScript
|
||||
{
|
||||
public override bool Validate(SpellInfo spellInfo)
|
||||
{
|
||||
return ValidateSpellInfo(SpellIds.AchievementCreditNerfScrapbots);
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo eventInfo)
|
||||
{
|
||||
if (eventInfo.GetActionTarget().GetEntry() != InstanceCreatureIds.XS013Scrapbot)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleProc(AuraEffect aurEff, ProcEventInfo eventInfo)
|
||||
{
|
||||
InstanceScript instance = eventInfo.GetActor().GetInstanceScript();
|
||||
if (instance == null)
|
||||
return;
|
||||
|
||||
instance.DoCastSpellOnPlayers(SpellIds.AchievementCreditNerfScrapbots);
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
DoCheckProc.Add(new CheckProcHandler(CheckProc));
|
||||
OnEffectProc.Add(new EffectProcHandler(HandleProc, 0, AuraType.Dummy));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_nerf_engineering : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_nerf_engineering() : base("achievement_nerf_engineering") { }
|
||||
|
||||
public override bool OnCheck(Player source, Unit target)
|
||||
{
|
||||
if (!target || target.GetAI() == null)
|
||||
return false;
|
||||
|
||||
return target.GetAI().GetData(XT002Data.HealthRecovered) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_heartbreaker : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_heartbreaker() : base("achievement_heartbreaker") { }
|
||||
|
||||
public override bool OnCheck(Player source, Unit target)
|
||||
{
|
||||
if (!target || target.GetAI() == null)
|
||||
return false;
|
||||
|
||||
return target.GetAI().GetData(XT002Data.HardMode) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class achievement_nerf_gravity_bombs : AchievementCriteriaScript
|
||||
{
|
||||
public achievement_nerf_gravity_bombs() : base("achievement_nerf_gravity_bombs") { }
|
||||
|
||||
public override bool OnCheck(Player source, Unit target)
|
||||
{
|
||||
if (!target || target.GetAI() == null)
|
||||
return false;
|
||||
|
||||
return target.GetAI().GetData(XT002Data.GravityBombCasualty) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 Game.Entities;
|
||||
|
||||
namespace Scripts.Northrend.Ulduar
|
||||
{
|
||||
class YoggSaron
|
||||
{
|
||||
public static Position[] ObservationRingKeepersPos =
|
||||
{
|
||||
new Position(1945.682f, 33.34201f, 411.4408f, 5.270895f), // Freya
|
||||
new Position(1945.761f, -81.52171f, 411.4407f, 1.029744f), // Hodir
|
||||
new Position(2028.822f, -65.73573f, 411.4426f, 2.460914f), // Thorim
|
||||
new Position(2028.766f, 17.42014f, 411.4446f, 3.857178f), // Mimiron
|
||||
};
|
||||
public static Position[] YSKeepersPos =
|
||||
{
|
||||
new Position(2036.873f, 25.42513f, 338.4984f, 3.909538f), // Freya
|
||||
new Position(1939.045f, -90.87457f, 338.5426f, 0.994837f), // Hodir
|
||||
new Position(1939.148f, 42.49035f, 338.5427f, 5.235988f), // Thorim
|
||||
new Position(2036.658f, -73.58822f, 338.4985f, 2.460914f), // Mimiron
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
namespace Scripts.Northrend.VioletHold
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.BattleFields;
|
||||
using Game.Conditions;
|
||||
using Game.Entities;
|
||||
using Game.Scripting;
|
||||
|
||||
namespace Scripts.Northrend
|
||||
{
|
||||
[Script]
|
||||
class spell_wintergrasp_defender_teleport : SpellScript
|
||||
{
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
BattleField wg = Global.BattleFieldMgr.GetBattlefieldByBattleId(1);
|
||||
if (wg != null)
|
||||
{
|
||||
Player target = GetExplTargetUnit().ToPlayer();
|
||||
if (target)
|
||||
// check if we are in Wintergrasp at all, SotA uses same teleport spells
|
||||
if ((target.GetZoneId() == 4197 && target.GetTeamId() != wg.GetDefenderTeam()) || target.HasAura(54643))
|
||||
return SpellCastResult.BadTargets;
|
||||
}
|
||||
|
||||
return SpellCastResult.SpellCastOk;
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnCheckCast.Add(new CheckCastHandler(CheckCast));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class spell_wintergrasp_defender_teleport_trigger : SpellScript
|
||||
{
|
||||
void HandleDummy(uint effindex)
|
||||
{
|
||||
Unit target = GetHitUnit();
|
||||
if (target)
|
||||
{
|
||||
WorldLocation loc = target.GetWorldLocation();
|
||||
SetExplTargetDest(loc);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Register()
|
||||
{
|
||||
OnEffectHitTarget.Add(new EffectHandler(HandleDummy, 0, SpellEffectName.Dummy));
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class condition_is_wintergrasp_horde : ConditionScript
|
||||
{
|
||||
public condition_is_wintergrasp_horde() : base("condition_is_wintergrasp_horde") { }
|
||||
|
||||
public override bool OnConditionCheck(Condition condition, ConditionSourceInfo sourceInfo)
|
||||
{
|
||||
BattleField wintergrasp = Global.BattleFieldMgr.GetBattlefieldByBattleId(BattlefieldIds.WG);
|
||||
if (wintergrasp.IsEnabled() && wintergrasp.GetDefenderTeam() == TeamId.Horde)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Script]
|
||||
class condition_is_wintergrasp_alliance : ConditionScript
|
||||
{
|
||||
public condition_is_wintergrasp_alliance() : base("condition_is_wintergrasp_alliance") { }
|
||||
|
||||
public override bool OnConditionCheck(Condition condition, ConditionSourceInfo sourceInfo)
|
||||
{
|
||||
BattleField wintergrasp = Global.BattleFieldMgr.GetBattlefieldByBattleId(BattlefieldIds.WG);
|
||||
if (wintergrasp.IsEnabled() && wintergrasp.GetDefenderTeam() == TeamId.Alliance)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user