Start adding missing scripts Part4

This commit is contained in:
hondacrx
2022-07-08 11:43:58 -04:00
parent 7e01c50655
commit f42b21a6de
22 changed files with 3740 additions and 2 deletions
@@ -0,0 +1,209 @@
/*
* Copyright (C) 2012-2020 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;
using System.Collections.Generic;
namespace Scripts.EasternKingdoms.BlackrockMountain.BlackwingLair.Broodlord
{
struct SpellIds
{
public const uint Cleave = 26350;
public const uint Blastwave = 23331;
public const uint Mortalstrike = 24573;
public const uint Knockback = 25778;
public const uint SuppressionAura = 22247; // Suppression Device Spell
}
struct TextIds
{
public const uint SayAggro = 0;
public const uint SayLeash = 1;
}
struct EventIds
{
// Suppression Device Events
public const uint SuppressionCast = 1;
public const uint SuppressionReset = 2;
}
struct ActionIds
{
public const int Deactivate = 0;
}
[Script]
class boss_broodlord : BossAI
{
public boss_broodlord(Creature creature) : base(creature, DataTypes.BroodlordLashlayer) { }
public override void JustEngagedWith(Unit who)
{
base.JustEngagedWith(who);
Talk(TextIds.SayAggro);
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
{
DoCastVictim(SpellIds.Cleave);
task.Repeat(TimeSpan.FromSeconds(7));
});
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
{
DoCastVictim(SpellIds.Blastwave);
task.Repeat(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(16));
});
_scheduler.Schedule(TimeSpan.FromSeconds(20), task =>
{
DoCastVictim(SpellIds.Mortalstrike);
task.Repeat(TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35));
});
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
{
DoCastVictim(SpellIds.Knockback);
if (GetThreat(me.GetVictim()) != 0)
ModifyThreatByPercent(me.GetVictim(), -50);
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30));
});
_scheduler.Schedule(TimeSpan.FromSeconds(1), task =>
{
if (me.GetDistance(me.GetHomePosition()) > 150.0f)
{
Talk(TextIds.SayLeash);
EnterEvadeMode(EvadeReason.Boundary);
}
task.Repeat(TimeSpan.FromSeconds(1));
});
}
public override void JustDied(Unit killer)
{
_JustDied();
List<GameObject> _goList = me.GetGameObjectListWithEntryInGrid(BWLGameObjectIds.SuppressionDevice, 200.0f);
foreach (var go in _goList)
go.GetAI().DoAction(ActionIds.Deactivate);
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
[Script]
class go_suppression_device : GameObjectAI
{
InstanceScript _instance;
bool _active;
public go_suppression_device(GameObject go) : base(go)
{
_instance = go.GetInstanceScript();
_active = true;
}
public override void InitializeAI()
{
if (_instance.GetBossState(DataTypes.BroodlordLashlayer) == EncounterState.Done)
{
Deactivate();
return;
}
_events.ScheduleEvent(EventIds.SuppressionCast, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(5));
}
public override void UpdateAI(uint diff)
{
_events.Update(diff);
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case EventIds.SuppressionCast:
if (me.GetGoState() == GameObjectState.Ready)
{
me.CastSpell(null, SpellIds.SuppressionAura, true);
me.SendCustomAnim(0);
}
_events.ScheduleEvent(EventIds.SuppressionCast, TimeSpan.FromSeconds(5));
break;
case EventIds.SuppressionReset:
Activate();
break;
}
});
}
public override void OnLootStateChanged(uint state, Unit unit)
{
switch ((LootState)state)
{
case LootState.Activated:
Deactivate();
_events.CancelEvent(EventIds.SuppressionCast);
_events.ScheduleEvent(EventIds.SuppressionReset, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(120));
break;
case LootState.JustDeactivated: // This case prevents the Gameobject despawn by Disarm Trap
me.SetLootState(LootState.Ready);
break;
}
}
public override void DoAction(int action)
{
if (action == ActionIds.Deactivate)
{
Deactivate();
_events.CancelEvent(EventIds.SuppressionReset);
}
}
void Activate()
{
if (_active)
return;
_active = true;
if (me.GetGoState() == GameObjectState.Active)
me.SetGoState(GameObjectState.Ready);
me.SetLootState(LootState.Ready);
me.RemoveFlag(GameObjectFlags.NotSelectable);
_events.ScheduleEvent(EventIds.SuppressionCast, TimeSpan.FromSeconds(0));
}
void Deactivate()
{
if (!_active)
return;
_active = false;
me.SetGoState(GameObjectState.Active);
me.SetFlag(GameObjectFlags.NotSelectable);
_events.CancelEvent(EventIds.SuppressionCast);
}
}
}
@@ -0,0 +1,297 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.BlackwingLair
{
struct SpellIds
{
// These spells are actually called elemental shield
// What they do is decrease all damage by 75% then they increase
// One school of damage by 1100%
public const uint FireVulnerability = 22277;
public const uint FrostVulnerability = 22278;
public const uint ShadowVulnerability = 22279;
public const uint NatureVulnerability = 22280;
public const uint ArcaneVulnerability = 22281;
// Other spells
public const uint Incinerate = 23308; //Incinerate 23308; 23309
public const uint Timelapse = 23310; //Time lapse 23310; 23311(old threat mod that was removed in 2.01)
public const uint Corrosiveacid = 23313; //Corrosive Acid 23313; 23314
public const uint Igniteflesh = 23315; //Ignite Flesh 23315; 23316
public const uint Frostburn = 23187; //Frost burn 23187; 23189
// Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them
// Since Scripted spells arn't coded I'll just write a function that does the same thing
public const uint BroodafBlue = 23153; //Blue affliction 23153
public const uint BroodafBlack = 23154; //Black affliction 23154
public const uint BroodafRed = 23155; //Red affliction 23155 (23168 on death)
public const uint BroodafBronze = 23170; //Bronze Affliction 23170
public const uint BroodafGreen = 23169; //Brood Affliction Green 23169
public const uint ChromaticMut1 = 23174; //Spell cast on player if they get all 5 debuffs
public const uint Frenzy = 28371; //The frenzy spell may be wrong
public const uint Enrage = 28747;
}
struct TextIds
{
public const uint EmoteFrenzy = 0;
public const uint EmoteShimmer = 1;
}
[Script]
class boss_chromaggus : BossAI
{
uint Breath1_Spell;
uint Breath2_Spell;
uint CurrentVurln_Spell;
bool Enraged;
public boss_chromaggus(Creature creature) : base(creature, DataTypes.Chromaggus)
{
Initialize();
Breath1_Spell = 0;
Breath2_Spell = 0;
// Select the 2 breaths that we are going to use until despawned
// 5 possiblities for the first breath, 4 for the second, 20 total possiblites
// This way we don't end up casting 2 of the same breath
// Tl Tl would be stupid
switch (RandomHelper.URand(0, 19))
{
// B1 - Incin
case 0:
Breath1_Spell = SpellIds.Incinerate;
Breath2_Spell = SpellIds.Timelapse;
break;
case 1:
Breath1_Spell = SpellIds.Incinerate;
Breath2_Spell = SpellIds.Corrosiveacid;
break;
case 2:
Breath1_Spell = SpellIds.Incinerate;
Breath2_Spell = SpellIds.Igniteflesh;
break;
case 3:
Breath1_Spell = SpellIds.Incinerate;
Breath2_Spell = SpellIds.Frostburn;
break;
// B1 - Tl
case 4:
Breath1_Spell = SpellIds.Timelapse;
Breath2_Spell = SpellIds.Incinerate;
break;
case 5:
Breath1_Spell = SpellIds.Timelapse;
Breath2_Spell = SpellIds.Corrosiveacid;
break;
case 6:
Breath1_Spell = SpellIds.Timelapse;
Breath2_Spell = SpellIds.Igniteflesh;
break;
case 7:
Breath1_Spell = SpellIds.Timelapse;
Breath2_Spell = SpellIds.Frostburn;
break;
//B1 - Acid
case 8:
Breath1_Spell = SpellIds.Corrosiveacid;
Breath2_Spell = SpellIds.Incinerate;
break;
case 9:
Breath1_Spell = SpellIds.Corrosiveacid;
Breath2_Spell = SpellIds.Timelapse;
break;
case 10:
Breath1_Spell = SpellIds.Corrosiveacid;
Breath2_Spell = SpellIds.Igniteflesh;
break;
case 11:
Breath1_Spell = SpellIds.Corrosiveacid;
Breath2_Spell = SpellIds.Frostburn;
break;
//B1 - Ignite
case 12:
Breath1_Spell = SpellIds.Igniteflesh;
Breath2_Spell = SpellIds.Incinerate;
break;
case 13:
Breath1_Spell = SpellIds.Igniteflesh;
Breath2_Spell = SpellIds.Corrosiveacid;
break;
case 14:
Breath1_Spell = SpellIds.Igniteflesh;
Breath2_Spell = SpellIds.Timelapse;
break;
case 15:
Breath1_Spell = SpellIds.Igniteflesh;
Breath2_Spell = SpellIds.Frostburn;
break;
//B1 - Frost
case 16:
Breath1_Spell = SpellIds.Frostburn;
Breath2_Spell = SpellIds.Incinerate;
break;
case 17:
Breath1_Spell = SpellIds.Frostburn;
Breath2_Spell = SpellIds.Timelapse;
break;
case 18:
Breath1_Spell = SpellIds.Frostburn;
Breath2_Spell = SpellIds.Corrosiveacid;
break;
case 19:
Breath1_Spell = SpellIds.Frostburn;
Breath2_Spell = SpellIds.Igniteflesh;
break;
}
EnterEvadeMode();
}
void Initialize()
{
CurrentVurln_Spell = 0; // We use this to store our last vulnerabilty spell so we can remove it later
Enraged = false;
}
public override void Reset()
{
_Reset();
Initialize();
}
public override void JustEngagedWith(Unit who)
{
base.JustEngagedWith(who);
_scheduler.Schedule(TimeSpan.FromSeconds(0), task =>
{
// Remove old vulnerabilty spell
if (CurrentVurln_Spell != 0)
me.RemoveAurasDueToSpell(CurrentVurln_Spell);
// Cast new random vulnerabilty on self
uint spell = RandomHelper.RAND(SpellIds.FireVulnerability, SpellIds.FrostVulnerability, SpellIds.ShadowVulnerability, SpellIds.NatureVulnerability, SpellIds.ArcaneVulnerability);
DoCast(me, spell);
CurrentVurln_Spell = spell;
Talk(TextIds.EmoteShimmer);
task.Repeat(TimeSpan.FromSeconds(45));
});
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
{
DoCastVictim(Breath1_Spell);
task.Repeat(TimeSpan.FromSeconds(60));
});
_scheduler.Schedule(TimeSpan.FromSeconds(60), task =>
{
DoCastVictim(Breath2_Spell);
task.Repeat(TimeSpan.FromSeconds(60));
});
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
{
var players = me.GetMap().GetPlayers();
foreach (var player in players)
{
if (player)
{
DoCast(player, RandomHelper.RAND(SpellIds.BroodafBlue, SpellIds.BroodafBlack, SpellIds.BroodafRed, SpellIds.BroodafBronze, SpellIds.BroodafGreen), new CastSpellExtraArgs(true));
if (player.HasAura(SpellIds.BroodafBlue) &&
player.HasAura(SpellIds.BroodafBlack) &&
player.HasAura(SpellIds.BroodafRed) &&
player.HasAura(SpellIds.BroodafBronze) &&
player.HasAura(SpellIds.BroodafGreen))
{
DoCast(player, SpellIds.ChromaticMut1);
}
}
}
task.Repeat(TimeSpan.FromSeconds(10));
});
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
{
DoCast(me, SpellIds.Frenzy);
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff);
// Enrage if not already enraged and below 20%
if (!Enraged && HealthBelowPct(20))
{
DoCast(me, SpellIds.Enrage);
Enraged = true;
}
DoMeleeAttackIfReady();
}
}
[Script]
class go_chromaggus_lever : GameObjectAI
{
InstanceScript _instance;
public go_chromaggus_lever(GameObject go) : base(go)
{
_instance = go.GetInstanceScript();
}
public override bool OnGossipHello(Player player)
{
if (_instance.GetBossState(DataTypes.Chromaggus) != EncounterState.Done && _instance.GetBossState(DataTypes.Chromaggus) != EncounterState.InProgress)
{
_instance.SetBossState(DataTypes.Chromaggus, EncounterState.InProgress);
Creature creature = _instance.GetCreature(DataTypes.Chromaggus);
if (creature)
creature.GetAI().JustEngagedWith(player);
GameObject go = _instance.GetGameObject(DataTypes.GoChromaggusDoor);
if (go)
_instance.HandleGameObject(ObjectGuid.Empty, true, go);
}
me.SetFlag(GameObjectFlags.NotSelectable | GameObjectFlags.InUse);
me.SetGoState(GameObjectState.Active);
return true;
}
}
}
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2012-2020 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.AI;
using Game.Entities;
using Game.Scripting;
using System;
namespace Scripts.EasternKingdoms.BlackrockMountain.BlackwingLair.Ebonroc
{
struct SpellIds
{
public const uint Shadowflame = 22539;
public const uint Wingbuffet = 23339;
public const uint Shadowofebonroc = 23340;
}
[Script]
class boss_ebonroc : BossAI
{
public boss_ebonroc(Creature creature) : base(creature, DataTypes.Ebonroc) { }
public override void JustEngagedWith(Unit who)
{
base.JustEngagedWith(who);
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20), task =>
{
DoCastVictim(SpellIds.Shadowflame);
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20));
});
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
{
DoCastVictim(SpellIds.Wingbuffet);
task.Repeat(TimeSpan.FromSeconds(30));
});
_scheduler.Schedule(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(10), task =>
{
DoCastVictim(SpellIds.Shadowofebonroc);
task.Repeat(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(10));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2012-2020 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.AI;
using Game.Entities;
using Game.Scripting;
using System;
namespace Scripts.EasternKingdoms.BlackrockMountain.BlackwingLair.Firemaw
{
struct SpellIds
{
public const uint Shadowflame = 22539;
public const uint Wingbuffet = 23339;
public const uint Flamebuffet = 23341;
}
[Script]
class boss_firemaw : BossAI
{
public boss_firemaw(Creature creature) : base(creature, DataTypes.Firemaw) { }
public override void JustEngagedWith(Unit who)
{
base.JustEngagedWith(who);
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20), task =>
{
DoCastVictim(SpellIds.Shadowflame);
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20));
});
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
{
DoCastVictim(SpellIds.Wingbuffet);
if (GetThreat(me.GetVictim()) != 0)
ModifyThreatByPercent(me.GetVictim(), -75);
task.Repeat(TimeSpan.FromSeconds(30));
});
_scheduler.Schedule(TimeSpan.FromSeconds(5), task =>
{
DoCastVictim(SpellIds.Flamebuffet);
task.Repeat(TimeSpan.FromSeconds(5));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}
@@ -0,0 +1,75 @@
/*
* Copyright (C) 2012-2020 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.AI;
using Game.Entities;
using Game.Scripting;
using System;
namespace Scripts.EasternKingdoms.BlackrockMountain.BlackwingLair.Flamegor
{
struct SpellIds
{
public const uint Shadowflame = 22539;
public const uint Wingbuffet = 23339;
public const uint Frenzy = 23342; //This spell periodically triggers fire nova
}
struct TextIds
{
public const uint EmoteFrenzy = 0;
}
[Script]
class boss_flamegor : BossAI
{
public boss_flamegor(Creature creature) : base(creature, DataTypes.Flamegor) { }
public override void JustEngagedWith(Unit who)
{
base.JustEngagedWith(who);
_scheduler.Schedule(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20), task =>
{
DoCastVictim(SpellIds.Shadowflame);
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20));
});
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
{
DoCastVictim(SpellIds.Wingbuffet);
if (GetThreat(me.GetVictim()) != 0)
ModifyThreatByPercent(me.GetVictim(), -75);
task.Repeat(TimeSpan.FromSeconds(30));
});
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
{
Talk(TextIds.EmoteFrenzy);
DoCast(me, SpellIds.Frenzy);
task.Repeat(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(10));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}
@@ -0,0 +1,376 @@
/*
* Copyright (C) 2012-2020 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.AI;
using Game.Entities;
using Game.Scripting;
using System;
using Game.Maps;
using System.Collections.Generic;
using Framework.Constants;
namespace Scripts.EasternKingdoms.BlackrockMountain.BlackwingLair
{
//uint const EncounterCount = 8;
struct DataTypes
{
// Encounter States/Boss GUIDs
public const uint RazorgoreTheUntamed = 0;
public const uint VaelastrazTheCorrupt = 1;
public const uint BroodlordLashlayer = 2;
public const uint Firemaw = 3;
public const uint Ebonroc = 4;
public const uint Flamegor = 5;
public const uint Chromaggus = 6;
public const uint Nefarian = 7;
// Additional Data
public const uint LordVictorNefarius = 8;
// Doors
public const uint GoChromaggusDoor = 9;
}
struct BWLCreatureIds
{
public const uint Razorgore = 12435;
public const uint BlackwingDragon = 12422;
public const uint BlackwingTaskmaster = 12458;
public const uint BlackwingLegionaire = 12416;
public const uint BlackwingWarlock = 12459;
public const uint Vaelastraz = 13020;
public const uint Broodlord = 12017;
public const uint Firemaw = 11983;
public const uint Ebonroc = 14601;
public const uint Flamegor = 11981;
public const uint Chromaggus = 14020;
public const uint VictorNefarius = 10162;
public const uint Nefarian = 11583;
}
struct BWLGameObjectIds
{
public const uint BlackDragonEgg = 177807;
public const uint PortcullisRazorgore = 176965;
public const uint PortcullisVaelastrasz = 179364;
public const uint PortcullisBroodlord = 179365;
public const uint PortcullisThreedragons = 179115;
public const uint PortcullisChromaggus = 179117; //Door after you kill him, not the one for his room
public const uint ChromaggusLever = 179148;
public const uint ChromaggusDoor = 179116;
public const uint PortcullisNefarian = 176966;
public const uint SuppressionDevice = 179784;
}
struct EventIds
{
public const uint RazorSpawn = 1;
public const uint RazorPhaseTwo = 2;
public const uint RespawnNefarius = 3;
}
struct BWLMisc
{
public const uint EncounterCount = 8;
// Razorgore Egg Event
public const int ActionPhaseTwo = 1;
public const uint DataEggEvent = 2;
public static DoorData[] doorData =
{
new DoorData(BWLGameObjectIds.PortcullisRazorgore, DataTypes.RazorgoreTheUntamed, DoorType.Passage),
new DoorData(BWLGameObjectIds.PortcullisVaelastrasz, DataTypes.VaelastrazTheCorrupt, DoorType.Passage),
new DoorData(BWLGameObjectIds.PortcullisBroodlord, DataTypes.BroodlordLashlayer, DoorType.Passage),
new DoorData(BWLGameObjectIds.PortcullisThreedragons, DataTypes.Firemaw, DoorType.Passage),
new DoorData(BWLGameObjectIds.PortcullisThreedragons, DataTypes.Ebonroc, DoorType.Passage),
new DoorData(BWLGameObjectIds.PortcullisThreedragons, DataTypes.Flamegor, DoorType.Passage),
new DoorData(BWLGameObjectIds.PortcullisChromaggus, DataTypes.Chromaggus, DoorType.Passage),
new DoorData(BWLGameObjectIds.PortcullisNefarian, DataTypes.Nefarian, DoorType.Room),
};
public static ObjectData[] creatureData =
{
new ObjectData(BWLCreatureIds.Razorgore, DataTypes.RazorgoreTheUntamed),
new ObjectData(BWLCreatureIds.Vaelastraz, DataTypes.VaelastrazTheCorrupt),
new ObjectData(BWLCreatureIds.Broodlord, DataTypes.BroodlordLashlayer),
new ObjectData(BWLCreatureIds.Firemaw, DataTypes.Firemaw),
new ObjectData(BWLCreatureIds.Ebonroc, DataTypes.Ebonroc),
new ObjectData(BWLCreatureIds.Flamegor, DataTypes.Flamegor),
new ObjectData(BWLCreatureIds.Chromaggus, DataTypes.Chromaggus),
new ObjectData(BWLCreatureIds.Nefarian, DataTypes.Nefarian),
new ObjectData(BWLCreatureIds.VictorNefarius, DataTypes.LordVictorNefarius),
};
public static ObjectData[] gameObjectData =
{
new ObjectData(BWLGameObjectIds.ChromaggusDoor, DataTypes.GoChromaggusDoor),
};
public static Position[] SummonPosition =
{
new Position(-7661.207520f, -1043.268188f, 407.199554f, 6.280452f),
new Position(-7644.145020f, -1065.628052f, 407.204956f, 0.501492f),
new Position(-7624.260742f, -1095.196899f, 407.205017f, 0.544694f),
new Position(-7608.501953f, -1116.077271f, 407.199921f, 0.816443f),
new Position(-7531.841797f, -1063.765381f, 407.199615f, 2.874187f),
new Position(-7547.319336f, -1040.971924f, 407.205078f, 3.789175f),
new Position(-7568.547852f, -1013.112488f, 407.204926f, 3.773467f),
new Position(-7584.175781f, -989.6691289f, 407.199585f, 4.527447f),
};
public static uint[] Entry = { 12422, 12458, 12416, 12420, 12459 };
}
[Script]
class instance_blackwing_lair : InstanceMapScript
{
public instance_blackwing_lair() : base(nameof(instance_blackwing_lair), 469) { }
class instance_blackwing_lair_InstanceMapScript : InstanceScript
{
// Razorgore
byte EggCount;
uint EggEvent;
List<ObjectGuid> EggList = new();
public instance_blackwing_lair_InstanceMapScript(InstanceMap map) : base(map)
{
SetHeaders("BWL");
SetBossNumber(BWLMisc.EncounterCount);
LoadDoorData(BWLMisc.doorData);
LoadObjectData(BWLMisc.creatureData, BWLMisc.gameObjectData);
// Razorgore
EggCount = 0;
EggEvent = 0;
}
public override void OnCreatureCreate(Creature creature)
{
base.OnCreatureCreate(creature);
switch (creature.GetEntry())
{
case BWLCreatureIds.BlackwingDragon:
case BWLCreatureIds.BlackwingTaskmaster:
case BWLCreatureIds.BlackwingLegionaire:
case BWLCreatureIds.BlackwingWarlock:
Creature razor = GetCreature(DataTypes.RazorgoreTheUntamed);
if (razor != null)
{
CreatureAI razorAI = razor.GetAI();
if (razorAI != null)
razorAI.JustSummoned(creature);
}
break;
default:
break;
}
}
public override uint GetGameObjectEntry(ulong spawnId, uint entry)
{
if (entry == BWLGameObjectIds.BlackDragonEgg && GetBossState(DataTypes.Firemaw) == EncounterState.Done)
return 0;
return entry;
}
public override void OnGameObjectCreate(GameObject go)
{
base.OnGameObjectCreate(go);
switch (go.GetEntry())
{
case BWLGameObjectIds.BlackDragonEgg:
EggList.Add(go.GetGUID());
break;
default:
break;
}
}
public override void OnGameObjectRemove(GameObject go)
{
base.OnGameObjectRemove(go);
if (go.GetEntry() == BWLGameObjectIds.BlackDragonEgg)
EggList.Remove(go.GetGUID());
}
public override bool CheckRequiredBosses(uint bossId, Player player = null)
{
if (_SkipCheckRequiredBosses(player))
return true;
switch (bossId)
{
case DataTypes.BroodlordLashlayer:
if (GetBossState(DataTypes.VaelastrazTheCorrupt) != EncounterState.Done)
return false;
break;
case DataTypes.Firemaw:
case DataTypes.Ebonroc:
case DataTypes.Flamegor:
if (GetBossState(DataTypes.BroodlordLashlayer) != EncounterState.Done)
return false;
break;
case DataTypes.Chromaggus:
if (GetBossState(DataTypes.Firemaw) != EncounterState.Done
|| GetBossState(DataTypes.Ebonroc) != EncounterState.Done
|| GetBossState(DataTypes.Flamegor) != EncounterState.Done)
return false;
break;
default:
break;
}
return true;
}
public override bool SetBossState(uint type, EncounterState state)
{
if (!base.SetBossState(type, state))
return false;
switch (type)
{
case DataTypes.RazorgoreTheUntamed:
if (state == EncounterState.Done)
{
foreach (var guid in EggList)
{
GameObject egg = instance.GetGameObject(guid);
if (egg)
egg.SetLootState(LootState.JustDeactivated);
}
}
SetData(BWLMisc.DataEggEvent, (uint)EncounterState.NotStarted);
break;
case DataTypes.Nefarian:
switch (state)
{
case EncounterState.NotStarted:
Creature nefarian = GetCreature(DataTypes.Nefarian);
if (nefarian)
nefarian.DespawnOrUnsummon();
break;
case EncounterState.Fail:
_events.ScheduleEvent(EventIds.RespawnNefarius, TimeSpan.FromMinutes(15));
SetBossState(DataTypes.Nefarian, EncounterState.NotStarted);
break;
default:
break;
}
break;
}
return true;
}
public override void SetData(uint type, uint data)
{
if (type == BWLMisc.DataEggEvent)
{
switch ((EncounterState)data)
{
case EncounterState.InProgress:
_events.ScheduleEvent(EventIds.RazorSpawn, TimeSpan.FromSeconds(45));
EggEvent = data;
EggCount = 0;
break;
case EncounterState.NotStarted:
_events.CancelEvent(EventIds.RazorSpawn);
EggEvent = data;
EggCount = 0;
break;
case EncounterState.Special:
if (++EggCount == 15)
{
Creature razor = GetCreature(DataTypes.RazorgoreTheUntamed);
if (razor)
{
SetData(BWLMisc.DataEggEvent, (uint)EncounterState.Done);
razor.RemoveAurasDueToSpell(42013); // MindControl
DoRemoveAurasDueToSpellOnPlayers(42013, true, true);
}
_events.ScheduleEvent(EventIds.RazorPhaseTwo, TimeSpan.FromSeconds(1));
_events.CancelEvent(EventIds.RazorSpawn);
}
if (EggEvent == (uint)EncounterState.NotStarted)
SetData(BWLMisc.DataEggEvent, (uint)EncounterState.InProgress);
break;
}
}
}
public override void OnUnitDeath(Unit unit)
{
//! Hack, needed because of buggy CreatureAI after charm
if (unit.GetEntry() == BWLCreatureIds.Razorgore && GetBossState(DataTypes.RazorgoreTheUntamed) != EncounterState.Done)
SetBossState(DataTypes.RazorgoreTheUntamed, EncounterState.Done);
}
public override void Update(uint diff)
{
if (_events.Empty())
return;
_events.Update(diff);
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case EventIds.RazorSpawn:
for (uint i = RandomHelper.URand(2, 5); i > 0; --i)
{
Creature summon = instance.SummonCreature(BWLMisc.Entry[RandomHelper.URand(0, 4)], BWLMisc.SummonPosition[RandomHelper.URand(0, 7)]);
if (summon)
summon.GetAI().DoZoneInCombat();
}
_events.ScheduleEvent(EventIds.RazorSpawn, TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(17));
break;
case EventIds.RazorPhaseTwo:
_events.CancelEvent(EventIds.RazorSpawn);
Creature razor = GetCreature(DataTypes.RazorgoreTheUntamed);
if (razor)
razor.GetAI().DoAction(BWLMisc.ActionPhaseTwo);
break;
case EventIds.RespawnNefarius:
Creature nefarius = GetCreature(DataTypes.LordVictorNefarius);
if (nefarius)
{
nefarius.SetActive(true);
nefarius.SetFarVisible(true);
nefarius.Respawn();
nefarius.GetMotionMaster().MoveTargetedHome();
}
break;
}
});
}
}
public override InstanceScript GetInstanceScript(InstanceMap map)
{
return new instance_blackwing_lair_InstanceMapScript(map);
}
}
}
@@ -0,0 +1,592 @@
/*
* Copyright (C) 2012-2020 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;
using System.Collections.Generic;
namespace Scripts.EasternKingdoms.BlackrockMountain.BlackwingLair.VictorNefarius
{
struct SpellIds
{
// Victor Nefarius
// Ubrs Spells
public const uint ChromaticChaos = 16337; // Self Cast hits 10339
public const uint VaelastraszzSpawn = 16354; // Self Cast Depawn one sec after
// Bwl Spells
public const uint Shadowbolt = 22677;
public const uint ShadowboltVolley = 22665;
public const uint ShadowCommand = 22667;
public const uint Fear = 22678;
public const uint NefariansBarrier = 22663;
// Nefarian
public const uint ShadowflameInitial = 22992;
public const uint Shadowflame = 22539;
public const uint Bellowingroar = 22686;
public const uint Veilofshadow = 7068;
public const uint Cleave = 20691;
public const uint Taillash = 23364;
public const uint Mage = 23410; // wild magic
public const uint Warrior = 23397; // beserk
public const uint Druid = 23398; // cat form
public const uint Priest = 23401; // corrupted healing
public const uint Paladin = 23418; // syphon blessing
public const uint Shaman = 23425; // totems
public const uint Warlock = 23427; // infernals
public const uint Hunter = 23436; // bow broke
public const uint Rogue = 23414; // Paralise
public const uint DeathKnight = 49576; // Death Grip
// 19484
// 22664
// 22674
// 22666
}
struct TextIds
{
// Nefarius
// Ubrs
public const uint SayChaosSpell = 9;
public const uint SaySuccess = 10;
public const uint SayFailure = 11;
// Bwl
public const uint SayGamesbegin1 = 12;
public const uint SayGamesbegin2 = 13;
// public const uint SayVaelIntro = 14; Not used - when he corrupts Vaelastrasz
// Nefarian
public const uint SayRandom = 0;
public const uint SayRaiseSkeletons = 1;
public const uint SaySlay = 2;
public const uint SayDeath = 3;
public const uint SayMage = 4;
public const uint SayWarrior = 5;
public const uint SayDruid = 6;
public const uint SayPriest = 7;
public const uint SayPaladin = 8;
public const uint SayShaman = 9;
public const uint SayWarlock = 10;
public const uint SayHunter = 11;
public const uint SayRogue = 12;
public const uint SayDeathKnight = 13;
public const uint GossipId = 6045;
public const uint GossipOptionId = 0;
}
struct CreatureIds
{
public const uint BronzeDrakanoid = 14263;
public const uint BlueDrakanoid = 14261;
public const uint RedDrakanoid = 14264;
public const uint GreenDrakanoid = 14262;
public const uint BlackDrakanoid = 14265;
public const uint ChromaticDrakanoid = 14302;
public const uint BoneConstruct = 14605;
// Ubrs
public const uint Gyth = 10339;
}
struct GameObjectIds
{
public const uint PortcullisActive = 164726;
public const uint PortcullisTobossrooms = 175186;
}
struct MiscConst
{
public const uint NefariusPath2 = 1379671;
public const uint NefariusPath3 = 1379672;
public static Position[] DrakeSpawnLoc = // drakonid
{
new Position(-7591.151855f, -1204.051880f, 476.800476f, 3.0f),
new Position(-7514.598633f, -1150.448853f, 476.796570f, 3.0f)
};
public static Position[] NefarianLoc =
{
new Position(-7449.763672f, -1387.816040f, 526.783691f, 3.0f), // nefarian spawn
new Position(-7535.456543f, -1279.562500f, 476.798706f, 3.0f) // nefarian move
};
public static uint[] Entry = { CreatureIds.BronzeDrakanoid, CreatureIds.BlueDrakanoid, CreatureIds.RedDrakanoid, CreatureIds.GreenDrakanoid, CreatureIds.BlackDrakanoid };
}
struct EventIds
{
// Victor Nefarius
public const uint SpawnAdd = 1;
public const uint ShadowBolt = 2;
public const uint Fear = 3;
public const uint MindControl = 4;
// Nefarian
public const uint Shadowflame = 5;
public const uint Veilofshadow = 6;
public const uint Cleave = 7;
public const uint Taillash = 8;
public const uint Classcall = 9;
// Ubrs
public const uint Chaos1 = 10;
public const uint Chaos2 = 11;
public const uint Path2 = 12;
public const uint Path3 = 13;
public const uint Success1 = 14;
public const uint Success2 = 15;
public const uint Success3 = 16;
}
[Script]
class boss_victor_nefarius : BossAI
{
uint SpawnedAdds;
public boss_victor_nefarius(Creature creature) : base(creature, DataTypes.Nefarian)
{
Initialize();
}
void Initialize()
{
SpawnedAdds = 0;
}
public override void Reset()
{
Initialize();
if (me.GetMapId() == 469)
{
if (!me.FindNearestCreature(BWLCreatureIds.Nefarian, 1000.0f, true))
_Reset();
me.SetVisible(true);
me.SetNpcFlag(NPCFlags.Gossip);
me.SetFaction((uint)FactionTemplates.Friendly);
me.SetStandState(UnitStandStateType.SitHighChair);
me.RemoveAura(SpellIds.NefariansBarrier);
}
}
public override void JustReachedHome()
{
Reset();
}
void BeginEvent(Player target)
{
_JustEngagedWith(target);
Talk(TextIds.SayGamesbegin2);
me.SetFaction((uint)FactionTemplates.DragonflightBlack);
me.RemoveNpcFlag(NPCFlags.Gossip);
DoCast(me, SpellIds.NefariansBarrier);
me.SetStandState(UnitStandStateType.Stand);
me.SetImmuneToPC(false);
AttackStart(target);
_events.ScheduleEvent(EventIds.ShadowBolt, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(10));
_events.ScheduleEvent(EventIds.Fear, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20));
//_events.ScheduleEvent(EventIds.MindControl, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35));
_events.ScheduleEvent(EventIds.SpawnAdd, TimeSpan.FromSeconds(10));
}
public override void SummonedCreatureDies(Creature summon, Unit killer)
{
if (summon.GetEntry() != BWLCreatureIds.Nefarian)
{
summon.UpdateEntry(CreatureIds.BoneConstruct);
summon.SetUnitFlag(UnitFlags.Uninteractible);
summon.SetReactState(ReactStates.Passive);
summon.SetStandState(UnitStandStateType.Dead);
}
}
public override void JustSummoned(Creature summon) { }
public override void SetData(uint type, uint data)
{
if (type == 1 && data == 1)
{
me.StopMoving();
_events.ScheduleEvent(EventIds.Path2, TimeSpan.FromSeconds(9));
}
if (type == 1 && data == 2)
_events.ScheduleEvent(EventIds.Success1, TimeSpan.FromSeconds(5));
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
{
_events.Update(diff);
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case EventIds.Path2:
me.GetMotionMaster().MovePath(MiscConst.NefariusPath2, false);
_events.ScheduleEvent(EventIds.Chaos1, TimeSpan.FromSeconds(7));
break;
case EventIds.Chaos1:
Creature gyth = me.FindNearestCreature(CreatureIds.Gyth, 75.0f, true);
if (gyth)
{
me.SetFacingToObject(gyth);
Talk(TextIds.SayChaosSpell);
}
_events.ScheduleEvent(EventIds.Chaos2, TimeSpan.FromSeconds(2));
break;
case EventIds.Chaos2:
DoCast(SpellIds.ChromaticChaos);
me.SetFacingTo(1.570796f);
break;
case EventIds.Success1:
Unit player = me.SelectNearestPlayer(60.0f);
if (player)
{
me.SetFacingToObject(player);
Talk(TextIds.SaySuccess);
GameObject portcullis1 = me.FindNearestGameObject(GameObjectIds.PortcullisActive, 65.0f);
if (portcullis1)
portcullis1.SetGoState(GameObjectState.Active);
GameObject portcullis2 = me.FindNearestGameObject(GameObjectIds.PortcullisTobossrooms, 80.0f);
if (portcullis2)
portcullis2.SetGoState(GameObjectState.Active);
}
_events.ScheduleEvent(EventIds.Success2, TimeSpan.FromSeconds(4));
break;
case EventIds.Success2:
DoCast(me, SpellIds.VaelastraszzSpawn);
me.DespawnOrUnsummon(TimeSpan.FromSeconds(1));
break;
case EventIds.Path3:
me.GetMotionMaster().MovePath(MiscConst.NefariusPath3, false);
break;
default:
break;
}
});
return;
}
// Only do this if we haven't spawned nefarian yet
if (UpdateVictim() && SpawnedAdds <= 42)
{
_events.Update(diff);
if (me.HasUnitState(UnitState.Casting))
return;
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case EventIds.ShadowBolt:
switch (RandomHelper.URand(0, 1))
{
case 0:
DoCastVictim(SpellIds.ShadowboltVolley);
break;
case 1:
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 40, true);
if (target)
DoCast(target, SpellIds.Shadowbolt);
break;
}
ResetThreatList();
_events.ScheduleEvent(EventIds.ShadowBolt, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(10));
break;
case EventIds.Fear:
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 40, true);
if (target)
DoCast(target, SpellIds.Fear);
_events.ScheduleEvent(EventIds.Fear, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(20));
break;
}
case EventIds.MindControl:
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 40, true);
if (target)
DoCast(target, SpellIds.ShadowCommand);
_events.ScheduleEvent(EventIds.MindControl, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35));
break;
}
case EventIds.SpawnAdd:
for (byte i = 0; i < 2; ++i)
{
uint CreatureID;
if (RandomHelper.URand(0, 2) == 0)
CreatureID = CreatureIds.ChromaticDrakanoid;
else
CreatureID = MiscConst.Entry[RandomHelper.URand(0, 4)];
Creature dragon = me.SummonCreature(CreatureID, MiscConst.DrakeSpawnLoc[i]);
if (dragon)
{
dragon.SetFaction((uint)FactionTemplates.DragonflightBlack);
dragon.GetAI().AttackStart(me.GetVictim());
}
if (++SpawnedAdds >= 42)
{
Creature nefarian = me.SummonCreature(BWLCreatureIds.Nefarian, MiscConst.NefarianLoc[0]);
if (nefarian)
{
nefarian.SetActive(true);
nefarian.SetFarVisible(true);
nefarian.SetCanFly(true);
nefarian.SetDisableGravity(true);
nefarian.CastSpell(null, SpellIds.ShadowflameInitial);
nefarian.GetMotionMaster().MovePoint(1, MiscConst.NefarianLoc[1]);
}
_events.CancelEvent(EventIds.MindControl);
_events.CancelEvent(EventIds.Fear);
_events.CancelEvent(EventIds.ShadowBolt);
me.SetVisible(false);
return;
}
}
_events.ScheduleEvent(EventIds.SpawnAdd, TimeSpan.FromSeconds(4));
break;
}
if (me.HasUnitState(UnitState.Casting))
return;
});
}
}
public override bool OnGossipSelect(Player player, uint menuId, uint gossipListId)
{
if (menuId == TextIds.GossipId && gossipListId == TextIds.GossipOptionId)
{
player.CloseGossipMenu();
Talk(TextIds.SayGamesbegin1);
BeginEvent(player);
}
return false;
}
}
[Script]
class boss_nefarian : BossAI
{
bool canDespawn;
uint DespawnTimer;
bool Phase3;
public boss_nefarian(Creature creature) : base(creature, DataTypes.Nefarian)
{
Initialize();
}
void Initialize()
{
Phase3 = false;
canDespawn = false;
DespawnTimer = 30000;
}
public override void Reset()
{
Initialize();
}
public override void JustReachedHome()
{
canDespawn = true;
}
public override void JustEngagedWith(Unit who)
{
_events.ScheduleEvent(EventIds.Shadowflame, TimeSpan.FromSeconds(12));
_events.ScheduleEvent(EventIds.Fear, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35));
_events.ScheduleEvent(EventIds.Veilofshadow, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35));
_events.ScheduleEvent(EventIds.Cleave, TimeSpan.FromSeconds(7));
//_events.ScheduleEvent(EventIds.Taillash, TimeSpan.FromSeconds(10));
_events.ScheduleEvent(EventIds.Classcall, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35));
Talk(TextIds.SayRandom);
}
public override void JustDied(Unit killer)
{
_JustDied();
Talk(TextIds.SayDeath);
}
public override void KilledUnit(Unit victim)
{
if ((RandomHelper.Rand32() % 5) != 0)
return;
Talk(TextIds.SaySlay, victim);
}
public override void MovementInform(MovementGeneratorType type, uint id)
{
if (type != MovementGeneratorType.Point)
return;
if (id == 1)
{
DoZoneInCombat();
if (me.GetVictim())
AttackStart(me.GetVictim());
}
}
public override void UpdateAI(uint diff)
{
if (canDespawn && DespawnTimer <= diff)
{
instance.SetBossState(DataTypes.Nefarian, EncounterState.Fail);
List<Creature> constructList = me.GetCreatureListWithEntryInGrid(CreatureIds.BoneConstruct, 500.0f);
foreach (var creature in constructList)
creature.DespawnOrUnsummon();
}
else DespawnTimer -= diff;
if (!UpdateVictim())
return;
if (canDespawn)
canDespawn = false;
_events.Update(diff);
if (me.HasUnitState(UnitState.Casting))
return;
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case EventIds.Shadowflame:
DoCastVictim(SpellIds.Shadowflame);
_events.ScheduleEvent(EventIds.Shadowflame, TimeSpan.FromSeconds(12));
break;
case EventIds.Fear:
DoCastVictim(SpellIds.Bellowingroar);
_events.ScheduleEvent(EventIds.Fear, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35));
break;
case EventIds.Veilofshadow:
DoCastVictim(SpellIds.Veilofshadow);
_events.ScheduleEvent(EventIds.Veilofshadow, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(35));
break;
case EventIds.Cleave:
DoCastVictim(SpellIds.Cleave);
_events.ScheduleEvent(EventIds.Cleave, TimeSpan.FromSeconds(7));
break;
case EventIds.Taillash:
// Cast Nyi since we need a better check for behind target
DoCastVictim(SpellIds.Taillash);
_events.ScheduleEvent(EventIds.Taillash, TimeSpan.FromSeconds(10));
break;
case EventIds.Classcall:
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 100.0f, true);
if (target)
switch (target.GetClass())
{
case Class.Mage:
Talk(TextIds.SayMage);
DoCast(me, SpellIds.Mage);
break;
case Class.Warrior:
Talk(TextIds.SayWarrior);
DoCast(me, SpellIds.Warrior);
break;
case Class.Druid:
Talk(TextIds.SayDruid);
DoCast(target, SpellIds.Druid);
break;
case Class.Priest:
Talk(TextIds.SayPriest);
DoCast(me, SpellIds.Priest);
break;
case Class.Paladin:
Talk(TextIds.SayPaladin);
DoCast(me, SpellIds.Paladin);
break;
case Class.Shaman:
Talk(TextIds.SayShaman);
DoCast(me, SpellIds.Shaman);
break;
case Class.Warlock:
Talk(TextIds.SayWarlock);
DoCast(me, SpellIds.Warlock);
break;
case Class.Hunter:
Talk(TextIds.SayHunter);
DoCast(me, SpellIds.Hunter);
break;
case Class.Rogue:
Talk(TextIds.SayRogue);
DoCast(me, SpellIds.Rogue);
break;
case Class.Deathknight:
Talk(TextIds.SayDeathKnight);
DoCast(me, SpellIds.DeathKnight);
break;
default:
break;
}
_events.ScheduleEvent(EventIds.Classcall, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(35));
break;
}
if (me.HasUnitState(UnitState.Casting))
return;
});
// Phase3 begins when health below 20 pct
if (!Phase3 && HealthBelowPct(20))
{
List<Creature> constructList = me.GetCreatureListWithEntryInGrid(CreatureIds.BoneConstruct, 500.0f);
foreach (var creature in constructList)
{
if (creature != null && !creature.IsAlive())
{
creature.Respawn();
DoZoneInCombat(creature);
creature.RemoveUnitFlag(UnitFlags.Uninteractible);
creature.SetReactState(ReactStates.Aggressive);
creature.SetStandState(UnitStandStateType.Stand);
}
}
Phase3 = true;
Talk(TextIds.SayRaiseSkeletons);
}
DoMeleeAttackIfReady();
}
}
}
@@ -0,0 +1,185 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.BlackwingLair.Razorgore
{
struct SpellIds
{
// @todo orb uses the wrong spell, this needs sniffs
public const uint Mindcontrol = 42013;
public const uint Channel = 45537;
public const uint EggDestroy = 19873;
public const uint Cleave = 22540;
public const uint Warstomp = 24375;
public const uint Fireballvolley = 22425;
public const uint Conflagration = 23023;
}
struct TextIds
{
public const uint SayEggsBroken1 = 0;
public const uint SayEggsBroken2 = 1;
public const uint SayEggsBroken3 = 2;
public const uint SayDeath = 3;
}
struct CreatureIds
{
public const uint EliteDrachkin = 12422;
public const uint EliteWarrior = 12458;
public const uint Warrior = 12416;
public const uint Mage = 12420;
public const uint Warlock = 12459;
}
struct GameObjectIds
{
public const uint Egg = 177807;
}
[Script]
class boss_razorgore : BossAI
{
bool secondPhase;
public boss_razorgore(Creature creature) : base(creature, DataTypes.RazorgoreTheUntamed)
{
Initialize();
}
void Initialize()
{
secondPhase = false;
}
public override void Reset()
{
_Reset();
Initialize();
instance.SetData(BWLMisc.DataEggEvent, (uint)EncounterState.NotStarted);
}
public override void JustDied(Unit killer)
{
_JustDied();
Talk(TextIds.SayDeath);
instance.SetData(BWLMisc.DataEggEvent, (uint)EncounterState.NotStarted);
}
void DoChangePhase()
{
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
{
DoCastVictim(SpellIds.Cleave);
task.Repeat(TimeSpan.FromSeconds(7), TimeSpan.FromSeconds(10));
});
_scheduler.Schedule(TimeSpan.FromSeconds(35), task =>
{
DoCastVictim(SpellIds.Warstomp);
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(25));
});
_scheduler.Schedule(TimeSpan.FromSeconds(7), task =>
{
DoCastVictim(SpellIds.Fireballvolley);
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
{
DoCastVictim(SpellIds.Conflagration);
task.Repeat(TimeSpan.FromSeconds(30));
});
secondPhase = true;
me.RemoveAllAuras();
me.SetFullHealth();
}
public override void DoAction(int action)
{
if (action == BWLMisc.ActionPhaseTwo)
DoChangePhase();
}
public override void DamageTaken(Unit who, ref uint damage, DamageEffectType damageType, SpellInfo spellInfo = null)
{
// @todo this is wrong - razorgore should still take damage, he should just nuke the whole room and respawn if he dies during P1
if (!secondPhase)
damage = 0;
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
[Script]
class go_orb_of_domination : GameObjectAI
{
InstanceScript instance;
public go_orb_of_domination(GameObject go) : base(go)
{
instance = go.GetInstanceScript();
}
public override bool OnGossipHello(Player player)
{
if (instance.GetData(BWLMisc.DataEggEvent) != (uint)EncounterState.Done)
{
Creature razorgore = instance.GetCreature(DataTypes.RazorgoreTheUntamed);
if (razorgore)
{
razorgore.Attack(player, true);
player.CastSpell(razorgore, SpellIds.Mindcontrol);
}
}
return true;
}
}
[Script] // 19873 - Destroy Egg
class spell_egg_event : SpellScript
{
void HandleOnHit()
{
InstanceScript instance = GetCaster().GetInstanceScript();
if (instance != null)
instance.SetData(BWLMisc.DataEggEvent, (uint)EncounterState.Special);
}
public override void Register()
{
OnHit.Add(new HitHandler(HandleOnHit));
}
}
}
@@ -0,0 +1,214 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.BlackwingLair.Vaelastrasz
{
struct SpellIds
{
public const uint Essenceofthered = 23513;
public const uint Flamebreath = 23461;
public const uint Firenova = 23462;
public const uint Tailswipe = 15847;
public const uint Burningadrenaline = 18173; //Cast this one. It's what 3.3.5 Dbm expects.
public const uint BurningadrenalineExplosion = 23478;
public const uint Cleave = 19983; //Chain cleave is most likely named something different and contains a dummy effect
}
struct TextIds
{
public const uint SayLine1 = 0;
public const uint SayLine2 = 1;
public const uint SayLine3 = 2;
public const uint SayHalflife = 3;
public const uint SayKilltarget = 4;
public const uint GossipId = 6101;
}
[Script]
class boss_vaelastrasz : BossAI
{
ObjectGuid PlayerGUID;
bool HasYelled;
public boss_vaelastrasz(Creature creature) : base(creature, DataTypes.VaelastrazTheCorrupt)
{
Initialize();
creature.SetNpcFlag(NPCFlags.Gossip);
creature.SetFaction((uint)FactionTemplates.Friendly);
creature.RemoveUnitFlag(UnitFlags.Uninteractible);
}
void Initialize()
{
PlayerGUID.Clear();
HasYelled = false;
}
public override void Reset()
{
_Reset();
me.SetStandState(UnitStandStateType.Dead);
Initialize();
}
public override void JustEngagedWith(Unit who)
{
base.JustEngagedWith(who);
DoCast(me, SpellIds.Essenceofthered);
me.SetHealth(me.CountPctFromMaxHealth(30));
// now drop damage requirement to be able to take loot
me.ResetPlayerDamageReq();
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
{
DoCastVictim(SpellIds.Cleave);
task.Repeat(TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
{
DoCastVictim(SpellIds.Flamebreath);
task.Repeat(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(14));
});
_scheduler.Schedule(TimeSpan.FromSeconds(20), task =>
{
DoCastVictim(SpellIds.Firenova);
task.Repeat(TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(11), task =>
{
//Only cast if we are behind
if (!me.HasInArc(MathF.PI, me.GetVictim()))
{
DoCast(me.GetVictim(), SpellIds.Tailswipe);
}
task.Repeat(TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
{
//selects a random target that isn't the current victim and is a mana user (selects mana users) but not pets
//it also ignores targets who have the aura. We don't want to place the debuff on the same target twice.
Unit target = SelectTarget(SelectTargetMethod.Random, 1, u => { return u && !u.IsPet() && u.GetPowerType() == PowerType.Mana && !u.HasAura(SpellIds.Burningadrenaline); });
if (target != null)
me.CastSpell(target, SpellIds.Burningadrenaline, true);
task.Repeat(TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(45), task =>
{
//Vael has to cast it himself; contrary to the previous commit's comment. Nothing happens otherwise.
me.CastSpell(me.GetVictim(), SpellIds.Burningadrenaline, true);
task.Repeat(TimeSpan.FromSeconds(45));
});
}
void BeginSpeech(Unit target)
{
PlayerGUID = target.GetGUID();
me.RemoveNpcFlag(NPCFlags.Gossip);
_scheduler.Schedule(TimeSpan.FromSeconds(1), task =>
{
Talk(TextIds.SayLine1);
me.SetStandState(UnitStandStateType.Stand);
me.HandleEmoteCommand(Emote.OneshotTalk);
task.Schedule(TimeSpan.FromSeconds(12), speechTask2 =>
{
Talk(TextIds.SayLine2);
me.HandleEmoteCommand(Emote.OneshotTalk);
speechTask2.Schedule(TimeSpan.FromSeconds(12), speechTask3 =>
{
Talk(TextIds.SayLine3);
me.HandleEmoteCommand(Emote.OneshotTalk);
speechTask3.Schedule(TimeSpan.FromSeconds(16), speechTask4 =>
{
me.SetFaction((uint)FactionTemplates.DragonflightBlack);
Player player = Global.ObjAccessor.GetPlayer(me, PlayerGUID);
if (player)
AttackStart(player);
});
});
});
});
}
public override void KilledUnit(Unit victim)
{
if ((RandomHelper.Rand32() % 5) != 0)
return;
Talk(TextIds.SayKilltarget, victim);
}
public override void UpdateAI(uint diff)
{
_scheduler.Update(diff);
if (!UpdateVictim())
return;
if (me.HasUnitState(UnitState.Casting))
return;
// Yell if hp lower than 15%
if (HealthBelowPct(15) && !HasYelled)
{
Talk(TextIds.SayHalflife);
HasYelled = true;
}
DoMeleeAttackIfReady();
}
public override bool OnGossipSelect(Player player, uint menuId, uint gossipListId)
{
if (menuId == TextIds.GossipId && gossipListId == 0)
{
player.CloseGossipMenu();
BeginSpeech(player);
}
return false;
}
}
//Need to define an aurascript for EventBurningadrenaline's death effect.
[Script] // 18173 - Burning Adrenaline
class spell_vael_burning_adrenaline : AuraScript
{
void OnAuraRemoveHandler(AuraEffect aurEff, AuraEffectHandleModes mode)
{
//The tooltip says the on death the AoE occurs. According to information: http://qaliaresponse.stage.lithium.com/t5/WoW-Mayhem/Surviving-Burning-Adrenaline-For-tanks/td-p/48609
//Burning Adrenaline can be survived therefore Blizzard's implementation was an AoE bomb that went off if you were still alive and dealt
//damage to the target. You don't have to die for it to go off. It can go off whether you live or die.
GetTarget().CastSpell(GetTarget(), SpellIds.BurningadrenalineExplosion, true);
}
public override void Register()
{
AfterEffectRemove.Add(new EffectApplyHandler(OnAuraRemoveHandler, 2, AuraType.PeriodicTriggerSpell, AuraEffectHandleModes.Real));
}
}
}
@@ -0,0 +1,113 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.MoltenCore.BaronGeddon
{
struct SpellIds
{
public const uint Inferno = 19695;
public const uint InfernoDmg = 19698;
public const uint IgniteMana = 19659;
public const uint LivingBomb = 20475;
public const uint Armageddon = 20478;
}
struct TextIds
{
public const uint EmoteService = 0;
}
[Script]
class boss_baron_geddon : BossAI
{
public boss_baron_geddon(Creature creature) : base(creature, BossIds.BaronGeddon) { }
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_scheduler.Schedule(TimeSpan.FromSeconds(45), task =>
{
DoCast(me, SpellIds.Inferno);
task.Repeat(TimeSpan.FromSeconds(45));
});
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true, true, -(int)SpellIds.IgniteMana);
if (target)
DoCast(target, SpellIds.IgniteMana);
task.Repeat(TimeSpan.FromSeconds(30));
});
_scheduler.Schedule(TimeSpan.FromSeconds(35), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true);
if (target)
DoCast(target, SpellIds.LivingBomb);
task.Repeat(TimeSpan.FromSeconds(35));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff);
// If we are <2% hp cast Armageddon
if (!HealthAbovePct(2))
{
me.InterruptNonMeleeSpells(true);
DoCast(me, SpellIds.Armageddon);
Talk(TextIds.EmoteService);
return;
}
if (me.HasUnitState(UnitState.Casting))
return;
DoMeleeAttackIfReady();
}
}
[Script] // 19695 - Inferno
class spell_baron_geddon_inferno : AuraScript
{
void OnPeriodic(AuraEffect aurEff)
{
PreventDefaultAction();
int[] damageForTick = { 500, 500, 1000, 1000, 2000, 2000, 3000, 5000 };
CastSpellExtraArgs args = new CastSpellExtraArgs(TriggerCastFlags.FullMask);
args.TriggeringAura = aurEff;
args.AddSpellMod(SpellValueMod.BasePoint0, damageForTick[aurEff.GetTickNumber() - 1]);
GetTarget().CastSpell((WorldObject)null, SpellIds.InfernoDmg, args);
}
public override void Register()
{
OnEffectPeriodic.Add(new EffectPeriodicHandler(OnPeriodic, 0, AuraType.PeriodicTriggerSpell));
}
}
}
@@ -0,0 +1,131 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.MoltenCore.Garr
{
struct SpellIds
{
// Garr
public const uint AntimagicPulse = 19492;
public const uint MagmaShackles = 19496;
public const uint Enrage = 19516;
public const uint SeparationAnxiety = 23492;
// Adds
public const uint Eruption = 19497;
public const uint Immolate = 15732;
}
[Script]
class boss_garr : BossAI
{
public boss_garr(Creature creature) : base(creature, BossIds.Garr) { }
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_scheduler.Schedule(TimeSpan.FromSeconds(25), task =>
{
DoCast(me, SpellIds.AntimagicPulse);
task.Repeat(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
{
DoCast(me, SpellIds.MagmaShackles);
task.Repeat(TimeSpan.FromSeconds(8), TimeSpan.FromSeconds(12));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
[Script]
class npc_firesworn : ScriptedAI
{
public npc_firesworn(Creature creature) : base(creature) { }
void ScheduleTasks()
{
// Timers for this are probably wrong
_scheduler.Schedule(TimeSpan.FromSeconds(4), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0);
if (target)
DoCast(target, SpellIds.Immolate);
task.Repeat(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10));
});
// Separation Anxiety - Periodically check if Garr is nearby
// ...and enrage if he is not.
_scheduler.Schedule(TimeSpan.FromSeconds(3), task =>
{
if (!me.FindNearestCreature(MCCreatureIds.Garr, 20.0f))
DoCastSelf(SpellIds.SeparationAnxiety);
else if (me.HasAura(SpellIds.SeparationAnxiety))
me.RemoveAurasDueToSpell(SpellIds.SeparationAnxiety);
task.Repeat();
});
}
public override void Reset()
{
_scheduler.CancelAll();
}
public override void JustEngagedWith(Unit who)
{
ScheduleTasks();
}
public override void DamageTaken(Unit attacker, ref uint damage, DamageEffectType damageType, SpellInfo spellInfo = null)
{
ulong health10pct = me.CountPctFromMaxHealth(10);
ulong health = me.GetHealth();
if (health - damage < health10pct)
{
damage = 0;
DoCastVictim(SpellIds.Eruption);
me.DespawnOrUnsummon();
}
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2012-2020 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.AI;
using Game.Entities;
using Game.Scripting;
using System;
namespace Scripts.EasternKingdoms.BlackrockMountain.MoltenCore.Gehennas
{
struct SpellIds
{
public const uint GehennasCurse = 19716;
public const uint RainOfFire = 19717;
public const uint ShadowBolt = 19728;
}
[Script]
class boss_gehennas : BossAI
{
public boss_gehennas(Creature creature) : base(creature, BossIds.Gehennas) { }
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
{
DoCastVictim(SpellIds.GehennasCurse);
task.Repeat(TimeSpan.FromSeconds(22), TimeSpan.FromSeconds(30));
});
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0);
if (target)
DoCast(target, SpellIds.RainOfFire);
task.Repeat(TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(12));
});
_scheduler.Schedule(TimeSpan.FromSeconds(6), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 1);
if (target)
DoCast(target, SpellIds.ShadowBolt);
task.Repeat(TimeSpan.FromSeconds(7));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}
@@ -0,0 +1,141 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.MoltenCore.Golemagg
{
struct SpellIds
{
// Golemagg
public const uint Magmasplash = 13879;
public const uint Pyroblast = 20228;
public const uint Earthquake = 19798;
public const uint Enrage = 19953;
public const uint GolemaggTrust = 20553;
// Core Rager
public const uint Mangle = 19820;
}
struct TextIds
{
public const uint EmoteLowhp = 0;
}
[Script]
class boss_golemagg : BossAI
{
public boss_golemagg(Creature creature) : base(creature, BossIds.GolemaggTheIncinerator) { }
public override void Reset()
{
base.Reset();
DoCast(me, SpellIds.Magmasplash, new CastSpellExtraArgs(true));
}
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_scheduler.Schedule(TimeSpan.FromSeconds(7), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0);
if (target)
DoCast(target, SpellIds.Pyroblast);
task.Repeat(TimeSpan.FromSeconds(7));
});
}
public override void DamageTaken(Unit attacker, ref uint damage, DamageEffectType damageType, SpellInfo spellInfo = null)
{
if (!HealthBelowPct(10) || me.HasAura(SpellIds.Enrage))
return;
DoCast(me, SpellIds.Enrage, new CastSpellExtraArgs(true));
_scheduler.Schedule(TimeSpan.FromSeconds(3), task =>
{
DoCastVictim(SpellIds.Earthquake);
task.Repeat(TimeSpan.FromSeconds(3));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
[Script]
class npc_core_rager : ScriptedAI
{
InstanceScript _instance;
public npc_core_rager(Creature creature) : base(creature)
{
_instance = creature.GetInstanceScript();
}
public override void Reset()
{
_scheduler.CancelAll();
}
public override void JustEngagedWith(Unit who)
{
_scheduler.Schedule(TimeSpan.FromSeconds(7), task => // These times are probably wrong
{
DoCastVictim(SpellIds.Mangle);
task.Repeat(TimeSpan.FromSeconds(10));
});
}
public override void DamageTaken(Unit attacker, ref uint damage, DamageEffectType damageType, SpellInfo spellInfo = null)
{
if (HealthAbovePct(50) || _instance == null)
return;
Creature pGolemagg = ObjectAccessor.GetCreature(me, _instance.GetGuidData(BossIds.GolemaggTheIncinerator));
if (pGolemagg)
{
if (pGolemagg.IsAlive())
{
me.AddAura(SpellIds.GolemaggTrust, me);
Talk(TextIds.EmoteLowhp);
me.SetFullHealth();
}
}
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}
@@ -0,0 +1,245 @@
/*
* Copyright (C) 2012-2020 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;
namespace Scripts.EasternKingdoms.BlackrockMountain.MoltenCore
{
struct BossIds
{
public const uint Lucifron = 0;
public const uint Magmadar = 1;
public const uint Gehennas = 2;
public const uint Garr = 3;
public const uint Shazzrah = 4;
public const uint BaronGeddon = 5;
public const uint SulfuronHarbinger = 6;
public const uint GolemaggTheIncinerator = 7;
public const uint MajordomoExecutus = 8;
public const uint Ragnaros = 9;
public const uint MaxEncounter = 10;
}
struct ActionIds
{
public const int StartRagnaros = 0;
public const int StartRagnarosAlt = 1;
}
struct MCCreatureIds
{
public const uint Lucifron = 12118;
public const uint Magmadar = 11982;
public const uint Gehennas = 12259;
public const uint Garr = 12057;
public const uint Shazzrah = 12264;
public const uint BaronGeddon = 12056;
public const uint SulfuronHarbinger = 12098;
public const uint GolemaggTheIncinerator = 11988;
public const uint MajordomoExecutus = 12018;
public const uint Ragnaros = 11502;
public const uint FlamewakerHealer = 11663;
public const uint FlamewakerElite = 11664;
}
struct MCGameObjectIds
{
public const uint CacheOfTheFirelord = 179703;
}
struct MCMiscConst
{
public const uint DataRagnarosAdds = 0;
public static Position[] SummonPositions =
{
new Position(737.850f, -1145.35f, -120.288f, 4.71368f),
new Position(744.162f, -1151.63f, -119.726f, 4.58204f),
new Position(751.247f, -1152.82f, -119.744f, 4.49673f),
new Position(759.206f, -1155.09f, -120.051f, 4.30104f),
new Position(755.973f, -1152.33f, -120.029f, 4.25588f),
new Position(731.712f, -1147.56f, -120.195f, 4.95955f),
new Position(726.499f, -1149.80f, -120.156f, 5.24055f),
new Position(722.408f, -1152.41f, -120.029f, 5.33087f),
new Position(718.994f, -1156.36f, -119.805f, 5.75738f),
new Position(838.510f, -829.840f, -232.000f, 2.00000f),
};
public static Position RagnarosTelePos = new Position(829.159f, -815.773f, -228.972f, 5.30500f);
public static Position RagnarosSummonPos = new Position(838.510f, -829.840f, -232.000f, 2.00000f);
}
[Script]
class instance_molten_core : InstanceMapScript
{
public instance_molten_core() : base(nameof(instance_molten_core), 409) { }
class instance_molten_core_InstanceMapScript : InstanceScript
{
ObjectGuid _golemaggTheIncineratorGUID;
ObjectGuid _majordomoExecutusGUID;
ObjectGuid _cacheOfTheFirelordGUID;
bool _executusSchedule;
byte _ragnarosAddDeaths;
public instance_molten_core_InstanceMapScript(InstanceMap map) : base(map)
{
SetHeaders("MC");
SetBossNumber(BossIds.MaxEncounter);
_executusSchedule = false;
_ragnarosAddDeaths = 0;
}
public override void OnPlayerEnter(Player player)
{
if (_executusSchedule)
SummonMajordomoExecutus();
}
public override void OnCreatureCreate(Creature creature)
{
switch (creature.GetEntry())
{
case MCCreatureIds.GolemaggTheIncinerator:
_golemaggTheIncineratorGUID = creature.GetGUID();
break;
case MCCreatureIds.MajordomoExecutus:
_majordomoExecutusGUID = creature.GetGUID();
break;
default:
break;
}
}
public override void OnGameObjectCreate(GameObject go)
{
switch (go.GetEntry())
{
case MCGameObjectIds.CacheOfTheFirelord:
_cacheOfTheFirelordGUID = go.GetGUID();
break;
default:
break;
}
}
public override void SetData(uint type, uint data)
{
if (type == MCMiscConst.DataRagnarosAdds)
{
if (data == 1)
++_ragnarosAddDeaths;
else if (data == 0)
_ragnarosAddDeaths = 0;
}
}
public override uint GetData(uint type)
{
switch (type)
{
case MCMiscConst.DataRagnarosAdds:
return _ragnarosAddDeaths;
}
return 0;
}
public override ObjectGuid GetGuidData(uint type)
{
switch (type)
{
case BossIds.GolemaggTheIncinerator:
return _golemaggTheIncineratorGUID;
case BossIds.MajordomoExecutus:
return _majordomoExecutusGUID;
}
return ObjectGuid.Empty;
}
public override bool SetBossState(uint bossId, EncounterState state)
{
if (!base.SetBossState(bossId, state))
return false;
if (state == EncounterState.Done && bossId < BossIds.MajordomoExecutus)
if (CheckMajordomoExecutus())
SummonMajordomoExecutus();
if (bossId == BossIds.MajordomoExecutus && state == EncounterState.Done)
DoRespawnGameObject(_cacheOfTheFirelordGUID, TimeSpan.FromDays(7));
return true;
}
void SummonMajordomoExecutus()
{
_executusSchedule = false;
if (!_majordomoExecutusGUID.IsEmpty())
return;
if (GetBossState(BossIds.MajordomoExecutus) != EncounterState.Done)
{
instance.SummonCreature(MCCreatureIds.MajordomoExecutus, MCMiscConst.SummonPositions[0]);
instance.SummonCreature(MCCreatureIds.FlamewakerHealer, MCMiscConst.SummonPositions[1]);
instance.SummonCreature(MCCreatureIds.FlamewakerHealer, MCMiscConst.SummonPositions[2]);
instance.SummonCreature(MCCreatureIds.FlamewakerHealer, MCMiscConst.SummonPositions[3]);
instance.SummonCreature(MCCreatureIds.FlamewakerHealer, MCMiscConst.SummonPositions[4]);
instance.SummonCreature(MCCreatureIds.FlamewakerElite, MCMiscConst.SummonPositions[5]);
instance.SummonCreature(MCCreatureIds.FlamewakerElite, MCMiscConst.SummonPositions[6]);
instance.SummonCreature(MCCreatureIds.FlamewakerElite, MCMiscConst.SummonPositions[7]);
instance.SummonCreature(MCCreatureIds.FlamewakerElite, MCMiscConst.SummonPositions[8]);
}
else
{
TempSummon summon = instance.SummonCreature(MCCreatureIds.MajordomoExecutus, MCMiscConst.RagnarosTelePos);
if (summon)
summon.GetAI().DoAction(ActionIds.StartRagnarosAlt);
}
}
bool CheckMajordomoExecutus()
{
if (GetBossState(BossIds.Ragnaros) == EncounterState.Done)
return false;
for (byte i = 0; i < BossIds.MajordomoExecutus; ++i)
if (GetBossState(i) != EncounterState.Done)
return false;
return true;
}
void ReadSaveDataMore(string data)
{
if (CheckMajordomoExecutus())
_executusSchedule = true;
}
}
public override InstanceScript GetInstanceScript(InstanceMap map)
{
return new instance_molten_core_InstanceMapScript(map);
}
}
}
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2012-2020 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.AI;
using Game.Entities;
using Game.Scripting;
using System;
namespace Scripts.EasternKingdoms.BlackrockMountain.MoltenCore.Lucifron
{
struct SpellIds
{
public const uint ImpendingDoom = 19702;
public const uint LucifronCurse = 19703;
public const uint ShadowShock = 20603;
}
[Script]
class boss_lucifron : BossAI
{
public boss_lucifron(Creature creature) : base(creature, BossIds.Lucifron) { }
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
{
DoCastVictim(SpellIds.ImpendingDoom);
task.Repeat(TimeSpan.FromSeconds(20));
});
_scheduler.Schedule(TimeSpan.FromSeconds(20), task =>
{
DoCastVictim(SpellIds.LucifronCurse);
task.Repeat(TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(6), task =>
{
DoCastVictim(SpellIds.ShadowShock);
task.Repeat(TimeSpan.FromSeconds(6));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2012-2020 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.AI;
using Game.Entities;
using Game.Scripting;
using Game.Spells;
using System;
namespace Scripts.EasternKingdoms.BlackrockMountain.MoltenCore.Magmadar
{
struct SpellIds
{
public const uint Frenzy = 19451;
public const uint MagmaSpit = 19449;
public const uint Panic = 19408;
public const uint LavaBomb = 19428;
}
struct TextIds
{
public const uint EmoteFrenzy = 0;
}
[Script]
class boss_magmadar : BossAI
{
public boss_magmadar(Creature creature) : base(creature, BossIds.Magmadar) { }
public override void Reset()
{
base.Reset();
DoCast(me, SpellIds.MagmaSpit, new CastSpellExtraArgs(true));
}
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
{
Talk(TextIds.EmoteFrenzy);
DoCast(me, SpellIds.Frenzy);
task.Repeat(TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(20), task =>
{
DoCastVictim(SpellIds.Panic);
task.Repeat(TimeSpan.FromSeconds(35));
});
_scheduler.Schedule(TimeSpan.FromSeconds(12), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true, true, -(int)SpellIds.LavaBomb);
if (target)
DoCast(target, SpellIds.LavaBomb);
task.Repeat(TimeSpan.FromSeconds(12));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}
@@ -0,0 +1,160 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.MoltenCore.Majordomo
{
struct SpellIds
{
public const uint SummonRagnaros = 19774;
public const uint BlastWave = 20229;
public const uint Teleport = 20618;
public const uint MagicReflection = 20619;
public const uint AegisOfRagnaros = 20620;
public const uint DamageReflection = 21075;
}
struct TextIds
{
public const uint SayAggro = 0;
public const uint SaySpawn = 1;
public const uint SaySlay = 2;
public const uint SaySpecial = 3;
public const uint SayDefeat = 4;
public const uint SaySummonMaj = 5;
public const uint SayArrival2Maj = 6;
public const uint OptionIdYouChallengedUs = 0;
public const uint MenuOptionYouChallengedUs = 4108;
}
[Script]
class boss_majordomo : BossAI
{
public boss_majordomo(Creature creature) : base(creature, BossIds.MajordomoExecutus) { }
public override void KilledUnit(Unit victim)
{
if (RandomHelper.URand(0, 99) < 25)
Talk(TextIds.SaySlay);
}
public override void JustEngagedWith(Unit who)
{
base.JustEngagedWith(who);
Talk(TextIds.SayAggro);
_scheduler.Schedule(TimeSpan.FromSeconds(30), task =>
{
DoCast(me, SpellIds.MagicReflection);
task.Repeat(TimeSpan.FromSeconds(30));
});
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
{
DoCast(me, SpellIds.DamageReflection);
task.Repeat(TimeSpan.FromSeconds(30));
});
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
{
DoCastVictim(SpellIds.BlastWave);
task.Repeat(TimeSpan.FromSeconds(10));
});
_scheduler.Schedule(TimeSpan.FromSeconds(20), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 1);
if (target)
DoCast(target, SpellIds.Teleport);
task.Repeat(TimeSpan.FromSeconds(20));
});
}
public override void UpdateAI(uint diff)
{
_scheduler.Update(diff);
if (instance.GetBossState(BossIds.MajordomoExecutus) != EncounterState.Done)
{
if (!UpdateVictim())
return;
if (!me.FindNearestCreature(MCCreatureIds.FlamewakerHealer, 100.0f) && !me.FindNearestCreature(MCCreatureIds.FlamewakerElite, 100.0f))
{
instance.UpdateEncounterStateForKilledCreature(me.GetEntry(), me);
me.SetFaction((uint)FactionTemplates.Friendly);
EnterEvadeMode();
Talk(TextIds.SayDefeat);
_JustDied();
_scheduler.Schedule(TimeSpan.FromSeconds(32), task =>
{
me.NearTeleportTo(MCMiscConst.RagnarosTelePos.GetPositionX(), MCMiscConst.RagnarosTelePos.GetPositionY(), MCMiscConst.RagnarosTelePos.GetPositionZ(), MCMiscConst.RagnarosTelePos.GetOrientation());
me.SetNpcFlag(NPCFlags.Gossip);
});
return;
}
if (me.HasUnitState(UnitState.Casting))
return;
if (HealthBelowPct(50))
DoCast(me, SpellIds.AegisOfRagnaros, new CastSpellExtraArgs(true));
DoMeleeAttackIfReady();
}
}
public override void DoAction(int action)
{
if (action == ActionIds.StartRagnaros)
{
me.RemoveNpcFlag(NPCFlags.Gossip);
Talk(TextIds.SaySummonMaj);
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
{
instance.instance.SummonCreature(MCCreatureIds.Ragnaros, MCMiscConst.RagnarosSummonPos);
});
_scheduler.Schedule(TimeSpan.FromSeconds(24), task =>
{
Talk(TextIds.SayArrival2Maj);
});
}
else if (action == ActionIds.StartRagnarosAlt)
{
me.SetFaction((uint)FactionTemplates.Friendly);
me.SetNpcFlag(NPCFlags.Gossip);
}
}
public override bool OnGossipSelect(Player player, uint menuId, uint gossipListId)
{
if (menuId == TextIds.MenuOptionYouChallengedUs && gossipListId == TextIds.OptionIdYouChallengedUs)
{
player.CloseGossipMenu();
DoAction(ActionIds.StartRagnaros);
}
return false;
}
}
}
@@ -0,0 +1,342 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.MoltenCore
{
struct SpellIds
{
public const uint HandOfRagnaros = 19780;
public const uint WrathOfRagnaros = 20566;
public const uint LavaBurst = 21158;
public const uint MagmaBlast = 20565; // Ranged attack
public const uint SonsOfFlameDummy = 21108; // Server side effect
public const uint Ragsubmerge = 21107; // Stealth aura
public const uint Ragemerge = 20568;
public const uint MeltWeapon = 21388;
public const uint ElementalFire = 20564;
public const uint Erruption = 17731;
}
struct TextIds
{
public const uint SaySummonMaj = 0;
public const uint SayArrival1Rag = 1;
public const uint SayArrival2Maj = 2;
public const uint SayArrival3Rag = 3;
public const uint SayArrival5Rag = 4;
public const uint SayReinforcements1 = 5;
public const uint SayReinforcements2 = 6;
public const uint SayHand = 7;
public const uint SayWrath = 8;
public const uint SayKill = 9;
public const uint SayMagmaburst = 10;
}
struct EventIds
{
public const uint Eruption = 1;
public const uint WrathOfRagnaros = 2;
public const uint HandOfRagnaros = 3;
public const uint LavaBurst = 4;
public const uint ElementalFire = 5;
public const uint MagmaBlast = 6;
public const uint Submerge = 7;
public const uint Intro1 = 8;
public const uint Intro2 = 9;
public const uint Intro3 = 10;
public const uint Intro4 = 11;
public const uint Intro5 = 12;
}
[Script]
class boss_ragnaros : BossAI
{
uint _emergeTimer;
byte _introState;
bool _hasYelledMagmaBurst;
bool _hasSubmergedOnce;
bool _isBanished;
public boss_ragnaros(Creature creature) : base(creature, BossIds.Ragnaros)
{
Initialize();
_introState = 0;
me.SetReactState(ReactStates.Passive);
me.SetUnitFlag(UnitFlags.NonAttackable);
SetCombatMovement(false);
}
void Initialize()
{
_emergeTimer = 90000;
_hasYelledMagmaBurst = false;
_hasSubmergedOnce = false;
_isBanished = false;
}
public override void Reset()
{
base.Reset();
Initialize();
me.SetEmoteState(Emote.OneshotNone);
}
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_events.ScheduleEvent(EventIds.Eruption, TimeSpan.FromSeconds(15));
_events.ScheduleEvent(EventIds.WrathOfRagnaros, TimeSpan.FromSeconds(30));
_events.ScheduleEvent(EventIds.HandOfRagnaros, TimeSpan.FromSeconds(25));
_events.ScheduleEvent(EventIds.LavaBurst, TimeSpan.FromSeconds(10));
_events.ScheduleEvent(EventIds.ElementalFire, TimeSpan.FromSeconds(3));
_events.ScheduleEvent(EventIds.MagmaBlast, TimeSpan.FromSeconds(2));
_events.ScheduleEvent(EventIds.Submerge, TimeSpan.FromMinutes(3));
}
public override void KilledUnit(Unit victim)
{
if (RandomHelper.URand(0, 99) < 25)
Talk(TextIds.SayKill);
}
public override void UpdateAI(uint diff)
{
if (_introState != 2)
{
if (_introState == 0)
{
me.HandleEmoteCommand(Emote.OneshotEmerge);
_events.ScheduleEvent(EventIds.Intro1, TimeSpan.FromSeconds(4));
_events.ScheduleEvent(EventIds.Intro2, TimeSpan.FromSeconds(23));
_events.ScheduleEvent(EventIds.Intro3, TimeSpan.FromSeconds(42));
_events.ScheduleEvent(EventIds.Intro4, TimeSpan.FromSeconds(43));
_events.ScheduleEvent(EventIds.Intro5, TimeSpan.FromSeconds(53));
_introState = 1;
}
_events.Update(diff);
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case EventIds.Intro1:
Talk(TextIds.SayArrival1Rag);
break;
case EventIds.Intro2:
Talk(TextIds.SayArrival3Rag);
break;
case EventIds.Intro3:
me.HandleEmoteCommand(Emote.OneshotAttack1h);
break;
case EventIds.Intro4:
Talk(TextIds.SayArrival5Rag);
Creature executus = ObjectAccessor.GetCreature(me, instance.GetGuidData(BossIds.MajordomoExecutus));
if (executus)
Unit.Kill(me, executus);
break;
case EventIds.Intro5:
me.SetReactState(ReactStates.Aggressive);
me.RemoveUnitFlag(UnitFlags.NonAttackable);
me.SetImmuneToPC(false);
_introState = 2;
break;
default:
break;
}
});
}
else
{
if (_isBanished && ((_emergeTimer <= diff) || (instance.GetData(MCMiscConst.DataRagnarosAdds)) > 8))
{
//Become unbanished again
me.SetReactState(ReactStates.Aggressive);
me.SetFaction((uint)FactionTemplates.Monster);
me.RemoveUnitFlag(UnitFlags.Uninteractible);
me.SetEmoteState(Emote.OneshotNone);
me.HandleEmoteCommand(Emote.OneshotEmerge);
Unit target = SelectTarget(SelectTargetMethod.Random, 0);
if (target)
AttackStart(target);
instance.SetData(MCMiscConst.DataRagnarosAdds, 0);
//DoCast(me, SpellRagemerge); //"phase spells" didnt worked correctly so Ive commented them and wrote solution witch doesnt need core support
_isBanished = false;
}
else if (_isBanished)
{
_emergeTimer -= diff;
//Do nothing while banished
return;
}
//Return since we have no target
if (!UpdateVictim())
return;
_events.Update(diff);
_events.ExecuteEvents(eventId =>
{
switch (eventId)
{
case EventIds.Eruption:
DoCastVictim(SpellIds.Erruption);
_events.ScheduleEvent(EventIds.Eruption, TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(45));
break;
case EventIds.WrathOfRagnaros:
DoCastVictim(SpellIds.WrathOfRagnaros);
if (RandomHelper.URand(0, 1) != 0)
Talk(TextIds.SayWrath);
_events.ScheduleEvent(EventIds.WrathOfRagnaros, TimeSpan.FromSeconds(25));
break;
case EventIds.HandOfRagnaros:
DoCast(me, SpellIds.HandOfRagnaros);
if (RandomHelper.URand(0, 1) != 0)
Talk(TextIds.SayHand);
_events.ScheduleEvent(EventIds.HandOfRagnaros, TimeSpan.FromSeconds(20));
break;
case EventIds.LavaBurst:
DoCastVictim(SpellIds.LavaBurst);
_events.ScheduleEvent(EventIds.LavaBurst, TimeSpan.FromSeconds(10));
break;
case EventIds.ElementalFire:
DoCastVictim(SpellIds.ElementalFire);
_events.ScheduleEvent(EventIds.ElementalFire, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(14));
break;
case EventIds.MagmaBlast:
if (!me.IsWithinMeleeRange(me.GetVictim()))
{
DoCastVictim(SpellIds.MagmaBlast);
if (!_hasYelledMagmaBurst)
{
//Say our dialog
Talk(TextIds.SayMagmaburst);
_hasYelledMagmaBurst = true;
}
}
_events.ScheduleEvent(EventIds.MagmaBlast, TimeSpan.FromMilliseconds(2500));
break;
case EventIds.Submerge:
{
if (!_isBanished)
{
//Creature spawning and ragnaros becomming unattackable
//is not very well supported in the core //no it really isnt
//so added normaly spawning and banish workaround and attack again after 90 secs.
me.AttackStop();
ResetThreatList();
me.SetReactState(ReactStates.Passive);
me.InterruptNonMeleeSpells(false);
//Root self
//DoCast(me, 23973);
me.SetFaction((uint)FactionTemplates.Friendly);
me.SetUnitFlag(UnitFlags.Uninteractible);
me.SetEmoteState(Emote.StateSubmerged);
me.HandleEmoteCommand(Emote.OneshotSubmerge);
instance.SetData(MCMiscConst.DataRagnarosAdds, 0);
if (!_hasSubmergedOnce)
{
Talk(TextIds.SayReinforcements1);
// summon 8 elementals
for (byte i = 0; i < 8; ++i)
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0);
if (target != null)
{
Creature summoned = me.SummonCreature(12143, target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), 0.0f, TempSummonType.TimedOrCorpseDespawn, TimeSpan.FromMinutes(15));
if (summoned != null)
summoned.GetAI().AttackStart(target);
}
}
_hasSubmergedOnce = true;
_isBanished = true;
//DoCast(me, SpellRagsubmerge);
_emergeTimer = 90000;
}
else
{
Talk(TextIds.SayReinforcements2);
for (byte i = 0; i < 8; ++i)
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0);
if (target != null)
{
Creature summoned = me.SummonCreature(12143, target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), 0.0f, TempSummonType.TimedOrCorpseDespawn, TimeSpan.FromMinutes(15));
if (summoned != null)
summoned.GetAI().AttackStart(target);
}
}
_isBanished = true;
//DoCast(me, SpellRagsubmerge);
_emergeTimer = 90000;
}
}
_events.ScheduleEvent(EventIds.Submerge, TimeSpan.FromMinutes(3));
break;
}
default:
break;
}
});
DoMeleeAttackIfReady();
}
}
}
[Script]
class npc_son_of_flame : ScriptedAI //didnt work correctly in Eai for me...
{
InstanceScript instance;
public npc_son_of_flame(Creature creature) : base(creature)
{
instance = me.GetInstanceScript();
}
public override void JustDied(Unit killer)
{
instance.SetData(MCMiscConst.DataRagnarosAdds, 1);
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
}
}
@@ -0,0 +1,156 @@
/*
* Copyright (C) 2012-2020 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.EasternKingdoms.BlackrockMountain.MoltenCore.Shazzrah
{
struct SpellIds
{
public const uint ArcaneExplosion = 19712;
public const uint ShazzrahCurse = 19713;
public const uint MagicGrounding = 19714;
public const uint Counterspell = 19715;
public const uint ShazzrahGateDummy = 23138; // Teleports to and attacks a random target.
public const uint ShazzrahGate = 23139;
}
struct EventIds
{
public const uint ArcaneExplosion = 1;
public const uint ArcaneExplosionTriggered = 2;
public const uint ShazzrahCurse = 3;
public const uint MagicGrounding = 4;
public const uint Counterspell = 5;
public const uint ShazzrahGate = 6;
}
[Script]
class boss_shazzrah : BossAI
{
public boss_shazzrah(Creature creature) : base(creature, BossIds.Shazzrah) { }
public override void JustEngagedWith(Unit target)
{
base.JustEngagedWith(target);
_events.ScheduleEvent(EventIds.ArcaneExplosion, TimeSpan.FromSeconds(6));
_events.ScheduleEvent(EventIds.ShazzrahCurse, TimeSpan.FromSeconds(10));
_events.ScheduleEvent(EventIds.MagicGrounding, TimeSpan.FromSeconds(24));
_events.ScheduleEvent(EventIds.Counterspell, TimeSpan.FromSeconds(15));
_events.ScheduleEvent(EventIds.ShazzrahGate, TimeSpan.FromSeconds(45));
}
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.ArcaneExplosion:
DoCastVictim(SpellIds.ArcaneExplosion);
_events.ScheduleEvent(EventIds.ArcaneExplosion, TimeSpan.FromSeconds(4), TimeSpan.FromSeconds(7));
break;
// Triggered subsequent to using "Gate of Shazzrah".
case EventIds.ArcaneExplosionTriggered:
DoCastVictim(SpellIds.ArcaneExplosion);
break;
case EventIds.ShazzrahCurse:
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true, true, -(int)SpellIds.ShazzrahCurse);
if (target)
DoCast(target, SpellIds.ShazzrahCurse);
_events.ScheduleEvent(EventIds.ShazzrahCurse, TimeSpan.FromSeconds(25), TimeSpan.FromSeconds(30));
break;
case EventIds.MagicGrounding:
DoCast(me, SpellIds.MagicGrounding);
_events.ScheduleEvent(EventIds.MagicGrounding, TimeSpan.FromSeconds(35));
break;
case EventIds.Counterspell:
DoCastVictim(SpellIds.Counterspell);
_events.ScheduleEvent(EventIds.Counterspell, TimeSpan.FromSeconds(16), TimeSpan.FromSeconds(20));
break;
case EventIds.ShazzrahGate:
ResetThreatList();
DoCastAOE(SpellIds.ShazzrahGateDummy);
_events.ScheduleEvent(EventIds.ArcaneExplosionTriggered, TimeSpan.FromSeconds(2));
_events.RescheduleEvent(EventIds.ArcaneExplosion, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(6));
_events.ScheduleEvent(EventIds.ShazzrahGate, TimeSpan.FromSeconds(45));
break;
default:
break;
}
if (me.HasUnitState(UnitState.Casting))
return;
});
DoMeleeAttackIfReady();
}
}
[Script] // 23138 - Gate of Shazzrah
class spell_shazzrah_gate_dummy : SpellScript
{
public override bool Validate(SpellInfo spellInfo)
{
return ValidateSpellInfo(SpellIds.ShazzrahGate);
}
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)
{
target.CastSpell(GetCaster(), SpellIds.ShazzrahGate, true);
Creature creature = GetCaster().ToCreature();
if (creature)
creature.GetAI().AttackStart(target); // Attack the target which caster will teleport to.
}
}
public override void Register()
{
OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(FilterTargets, 0, Targets.UnitSrcAreaEnemy));
OnEffectHitTarget.Add(new EffectHandler(HandleScript, 0, SpellEffectName.Dummy));
}
}
}
@@ -0,0 +1,145 @@
/*
* Copyright (C) 2012-2020 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.AI;
using Game.Entities;
using Game.Scripting;
using System;
using System.Collections.Generic;
namespace Scripts.EasternKingdoms.BlackrockMountain.MoltenCore.Sulfuron
{
struct SpellIds
{
// Sulfuron Harbringer
public const uint DarkStrike = 19777;
public const uint DemoralizingShout = 19778;
public const uint Inspire = 19779;
public const uint Knockdown = 19780;
public const uint Flamespear = 19781;
// Adds
public const uint Heal = 19775;
public const uint Shadowwordpain = 19776;
public const uint Immolate = 20294;
}
[Script]
class boss_sulfuron : BossAI
{
public boss_sulfuron(Creature creature) : base(creature, BossIds.SulfuronHarbinger) { }
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_scheduler.Schedule(TimeSpan.FromSeconds(10), task =>
{
DoCast(me, SpellIds.DarkStrike);
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(18));
});
_scheduler.Schedule(TimeSpan.FromSeconds(15), task =>
{
DoCastVictim(SpellIds.DemoralizingShout);
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20));
});
_scheduler.Schedule(TimeSpan.FromSeconds(13), task =>
{
List<Creature> healers = DoFindFriendlyMissingBuff(45.0f, SpellIds.Inspire);
if (!healers.Empty())
DoCast(healers.SelectRandom(), SpellIds.Inspire);
DoCast(me, SpellIds.Inspire);
task.Repeat(TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(26));
});
_scheduler.Schedule(TimeSpan.FromSeconds(6), task =>
{
DoCastVictim(SpellIds.Knockdown);
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(15));
});
_scheduler.Schedule(TimeSpan.FromSeconds(2), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true);
if (target)
DoCast(target, SpellIds.Flamespear);
task.Repeat(TimeSpan.FromSeconds(12), TimeSpan.FromSeconds(16));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
[Script]
class npc_flamewaker_priest : ScriptedAI
{
public npc_flamewaker_priest(Creature creature) : base(creature)
{
}
public override void Reset()
{
_scheduler.CancelAll();
}
public override void JustDied(Unit killer)
{
_scheduler.CancelAll();
}
public override void JustEngagedWith(Unit victim)
{
base.JustEngagedWith(victim);
_scheduler.Schedule(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), task =>
{
Unit target = DoSelectLowestHpFriendly(60.0f, 1);
if (target)
DoCast(target, SpellIds.Heal);
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20));
});
_scheduler.Schedule(TimeSpan.FromSeconds(2), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true, true, -(int)SpellIds.Shadowwordpain);
if (target)
DoCast(target, SpellIds.Shadowwordpain);
task.Repeat(TimeSpan.FromSeconds(18), TimeSpan.FromSeconds(26));
});
_scheduler.Schedule(TimeSpan.FromSeconds(8), task =>
{
Unit target = SelectTarget(SelectTargetMethod.Random, 0, 0.0f, true, true, -(int)SpellIds.Immolate);
if (target)
DoCast(target, SpellIds.Immolate);
task.Repeat(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(25));
});
}
public override void UpdateAI(uint diff)
{
if (!UpdateVictim())
return;
_scheduler.Update(diff, () => DoMeleeAttackIfReady());
}
}
}