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));
}
}
}