[3.3.5] Azjol-Nerub rewrite

* Scripts/AzjolNerub: Complete rewrite.
- Gatewatcher:
  - Trash now actually engages properly one by one
  - Fix trash spell casting
  - Add missing quotes
- Hadronox:
  - Everything. Literally.
- Anub'arak:
  - Fix add spawns
  - Fix impale
  - OK this might as well be "fix everything with every boss". Because that's pretty much what happened.
- General hack cleanup

* Update and rename 9999_99_99_99_AZJOLNERUB.sql to 2016_09_25_01_world.sql

* Update and rename 2016_09_25_01_world.sql to 2016_09_25_02_world.sql

* Rename 2016_09_25_02_world.sql to 2016_09_26_02_world.sql
This commit is contained in:
Treeston
2016-09-26 12:49:32 +02:00
committed by Aokromes
parent 5d5753c8bc
commit 4b990eb7d7
8 changed files with 2822 additions and 898 deletions

View File

@@ -0,0 +1,188 @@
--
SET @CGUID = 87530; -- creature GUIDs (14 creatures)
SET @IMMUNEMASK = (1|2|4|16|32|64|128|256|512|2048|4096|8192|65536|131072|524288|4194304|8388608|67108864|536870912);
-- Correct immunity mask (all bosses)
UPDATE `creature_template` SET `mechanic_immune_mask` = @IMMUNEMASK WHERE `entry` IN (28684,31612);
UPDATE `creature_template` SET `mechanic_immune_mask` = (@IMMUNEMASK|33554432) WHERE `entry` IN (28921,29120,31611,31610);
-- ------------------------- --
-- Krik'thir the Gatewatcher --
-- ------------------------- --
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (52438,52449,52343);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`Comment`) VALUES
(13,1,52438,0,0,31,0,3,22515,0,0,"Summon Skittering Swarmer - Target World Trigger"),
(13,1,52449,0,0,31,0,3,22515,0,0,"Summon Skittering Infector - Target World Trigger"),
(13,1,52343,0,0,31,0,3,28729,0,0,"Krik'thir Subboss Aggro Trigger - Target Watcher Narjil"),
(13,1,52343,0,1,31,0,3,28730,0,0,"Krik'thir Subboss Aggro Trigger - Target Watcher Garsha"),
(13,1,52343,0,2,31,0,3,28731,0,0,"Krik'thir Subboss Aggro Trigger - Target Watcher Silthik");
-- Remove static spawn for Krik'thir's pets
DELETE FROM `creature` WHERE `guid` IN (127234,127232,127227,127226,127231,127226,127225,127228,127233,127236);
DELETE FROM `creature_addon` WHERE `guid` IN (127234,127232,127227,127226,127231,127226,127225,127228,127233,127236);
DELETE FROM `linked_respawn` WHERE `guid` IN (127234,127232,127227,127226,127231,127226,127225,127228,127233,127236);
-- And replace it with creature_summon_groups which allows us to easily respawn them on demand
DELETE FROM `creature_summon_groups` WHERE `summonerId`=28684 AND `summonerType`=0;
INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES
(28684,0,1,28729,511.8097,666.4934,776.2781,0.9773844,6,45000),
(28684,0,1,28732,506.5164,664.3796,776.9759,0.9250245,6,30000),
(28684,0,1,28733,506.1783,669.9266,776.3057,0.8552113,6,30000),
(28684,0,2,28730,526.6636,663.6053,775.8052,1.239184 ,6,45000),
(28684,0,2,28732,531.0308,658.1731,776.2396,1.343904 ,6,30000),
(28684,0,2,28734,521.8148,659.4708,776.3131,1.186824 ,6,30000),
(28684,0,3,28731,543.8261,665.1234,776.2453,1.553343 ,6,45000),
(28684,0,3,28734,550.0461,668.131 ,776.2789,1.658063 ,6,30000),
(28684,0,3,28733,549.6929,662.0067,776.9927,1.64061 ,6,30000);
-- Small minions are now owned by the World Triggers in the room, so they need AI to aggro properly
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_skittering_swarmer" WHERE `entry`=28735;
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_skittering_infector" WHERE `entry`=28736;
-- Krik'thir: Subboss Aggro Trigger
DELETE FROM `spell_script_names` WHERE `scriptname` = "spell_gatewatcher_subboss_trigger";
INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES (52343,"spell_gatewatcher_subboss_trigger");
-- Anub'ar Skirmisher: Fixtate
DELETE FROM `spell_script_names` WHERE `scriptname` = "spell_anub_ar_skirmisher_fixtate";
INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES (52536,"spell_anub_ar_skirmisher_fixtate");
-- Watchers: Web Wrap
DELETE FROM `spell_script_names` WHERE `scriptname` = "spell_gatewatcher_web_wrap";
INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES (52086,"spell_gatewatcher_web_wrap");
UPDATE `creature_template` SET `AIName`='',`ScriptName`="npc_gatewatcher_web_wrap" WHERE `entry`=28619;
-- -------- --
-- Hadronox --
-- -------- --
UPDATE `creature` SET `position_x`=515.5848,`position_y`=544.2007,`position_z`=673.6272,`orientation`=5.740286 WHERE `map`=601 AND `id`=28921;
-- Remove existing world trigger spawns
DELETE FROM `creature` WHERE `guid` BETWEEN 127376 AND 127378;
DELETE FROM `creature_addon` WHERE `guid` BETWEEN 127376 AND 127378;
DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+5;
DELETE FROM `creature_addon` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+5;
-- And re-spawn them
INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`movementtype`) VALUES
(@CGUID+00,23472,601,3,1,530.495 ,597.0955,777.2634,5.986479 ,0,0,0),
(@CGUID+01,23472,601,3,1,530.6029,596.997 ,777.2633,5.427974 ,0,0,0),
(@CGUID+02,23472,601,3,1,530.7466,596.745 ,777.2631,2.303835 ,0,0,0),
(@CGUID+03,23472,601,3,1,583.0908,617.371 ,771.5508,0.6457718,0,0,0),
(@CGUID+04,23472,601,3,1,480.0325,615.5892,773.3531,4.101524 ,0,0,0),
(@CGUID+05,23472,601,3,1,581.4475,608.8407,739.4051,1.727876 ,0,0,0);
INSERT INTO `creature_addon` (`guid`,`auras`) VALUES
(@CGUID+03,"53035 53036 53037"),
(@CGUID+04,"53035 53036 53037"),
(@CGUID+05,"53035 53036 53037");
-- Crusher groups are now spawn groups on Hadronox
DELETE FROM `creature` WHERE `guid` IN (127379,127380,127402);
DELETE FROM `creature_addon` WHERE `guid` IN (127379,127380,127402);
DELETE FROM `linked_respawn` WHERE `guid` IN (127379,127380,127402);
DELETE FROM `creature_summon_groups` WHERE `summonerId`=28921 AND `summonerType`=0;
INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES
(28921,0,1,28922,529.6913,547.1257,731.9155,4.79965 ,6,45000),
(28921,0,1,29117,539.2076,549.7539,732.8668,4.55531 ,6,30000),
(28921,0,1,29118,520.3911,548.7895,732.0118,5.0091 ,6,30000),
(28921,0,2,28922,493.4772,603.3438,760.5628,5.440244,6,45000),
(28921,0,2,29117,490.4421,604.335 ,763.1821,5.625595,6,30000),
(28921,0,2,29119,488.8254,609.2819,767.5876,5.590288,6,30000),
(28921,0,3,28922,566.9789,602.5711,759.6418,3.885966,6,45000),
(28921,0,3,29118,569.348 ,604.9987,763.2137,4.179827,6,30000),
(28921,0,3,29119,572.4737,607.4109,767.1777,3.944169,6,30000);
-- Periodic spawn triggers: Spell scripts
DELETE FROM `spell_script_names` WHERE `scriptname` IN ("spell_hadronox_periodic_summon_champion","spell_hadronox_periodic_summon_crypt_fiend","spell_hadronox_periodic_summon_necromancer");
INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES
(53035,"spell_hadronox_periodic_summon_champion"),
(53037,"spell_hadronox_periodic_summon_crypt_fiend"),
(53036,"spell_hadronox_periodic_summon_necromancer");
-- Assign custom AI to the Anub'ar foes
DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid` IN (29062,29063,29064,29096,29097,29098);
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anub_ar_champion" WHERE `entry` IN (29062,29096);
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anub_ar_crypt_fiend" WHERE `entry` IN (29063,29097);
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anub_ar_necromancer" WHERE `entry` IN (29064,29098);
-- And crusher pack creatures
DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid` IN (28922,29117,29118,29119);
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anub_ar_crusher" WHERE `entry` = 28922;
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anub_ar_crusher_champion" WHERE `entry` = 29117;
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anub_ar_crusher_crypt_fiend" WHERE `entry` = 29118;
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anub_ar_crusher_necromancer" WHERE `entry` = 29119;
-- Hadronox: Leeching Poison
DELETE FROM `spell_script_names` WHERE `scriptname` = "spell_hadronox_leeching_poison";
INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES (53030,"spell_hadronox_leeching_poison"),(59417,"spell_hadronox_leeching_poison");
-- Hadronox: Web Side Doors / Web Front Doors
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (53177,53185);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ConditionTypeOrReference`,`ConditionTarget`,`ElseGroup`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`Comment`) VALUES
(13,1,53177,31,0,0,3,23472,@CGUID+3,"Web Front Door - Target Large AOI World Trigger Top Door 1"),
(13,1,53177,31,0,1,3,23472,@CGUID+4,"Web Front Door - Target Large AOI World Trigger Top Door 2"),
(13,1,53185,31,0,0,3,23472,@CGUID+5,"Web Side Door - Target Large AOI World Trigger Side Door");
DELETE FROM `spell_script_names` WHERE `scriptname`="spell_hadronox_web_doors";
INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES
(53177,"spell_hadronox_web_doors"),
(53185,"spell_hadronox_web_doors");
-- Spell difficulty data
DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (53406,57731,53318);
INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
(53406,53406,59420), -- Hadronox - Web Grab
(53318,53318,59346); -- Crusher - Smash
-- Creature texts
DELETE FROM `creature_text` WHERE `entry` IN (28921,28922);
INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`probability`,`sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
(28921,1,0,"%s moves up the tunnel!",41,100,0,29852,3,"Hadronox HADRONOX_EMOTE_MOVE"),
(28922,1,0,"The gate has been breached! Quickly, divert forces to deal with these invaders!",14,100,13941,29473,3,"Anub'ar Crusher CRUSHER_SAY_AGGRO"),
(28922,2,0,"%s goes into a frenzy!",41,100,0,10645,3,"Anub'ar Crusher CRUSHER_EMOTE_FRENZY");
-- Achievement: Hadronox Denied
DELETE FROM `achievement_criteria_data` WHERE `criteria_id`=4244;
INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`ScriptName`) VALUES
(4244,11,"achievement_hadronox_denied");
DELETE FROM `disables` WHERE `sourceType`=4 AND `entry`=4244;
-- --------- --
-- Anub'arak --
-- --------- --
-- Pound
DELETE FROM `spell_script_names` WHERE `scriptname`="spell_anubarak_pound";
INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES
(53472,"spell_anubarak_pound"),
(59433,"spell_anubarak_pound");
-- Summon Carrion Beetles
DELETE FROM `spell_script_names` WHERE `scriptname`="spell_anubarak_carrion_beetles";
INSERT INTO `spell_script_names` (`spell_id`,`scriptname`) VALUES
(53520,"spell_anubarak_carrion_beetles");
-- New pet AI
DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid` IN (29213,29214,29216,29217,29184);
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anubarak_anub_ar_darter" WHERE `entry` = 29213;
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anubarak_anub_ar_assassin" WHERE `entry` = 29214;
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anubarak_anub_ar_guardian" WHERE `entry` = 29216;
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anubarak_anub_ar_venomancer" WHERE `entry` = 29217;
-- Impale
UPDATE `creature_template` SET `AIName`="",`ScriptName`="npc_anubarak_impale_target" WHERE `entry`=29184;
-- World triggers for Assassin spawns
DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+06 AND @CGUID+13;
INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`movementtype`) VALUES
(@CGUID+06,22515,601,3,1,478.7393,252.8498,250.5435,0.05235988,0,0,0),
(@CGUID+07,22515,601,3,1,621.319 ,268.4819,250.5435,3.333579 ,0,0,0),
(@CGUID+08,22515,601,3,1,622.9042,252.945 ,250.5435,3.124139 ,0,0,0),
(@CGUID+09,22515,601,3,1,478.1486,269.0094,250.5435,6.126106 ,0,0,0),
(@CGUID+10,22515,601,3,1,478.5473,297.0447,250.5435,5.7944933 ,0,0,0),
(@CGUID+11,22515,601,3,1,478.2909,224.8265,250.2346,0.4014257 ,0,0,0),
(@CGUID+12,22515,601,3,1,620.6218,298.2625,250.5435,3.700098 ,0,0,0),
(@CGUID+13,22515,601,3,1,620.7037,224.5618,250.2321,2.530727 ,0,0,0);
-- Guardian spawn trigger
DELETE FROM `creature_summon_groups` WHERE `summonerId`=29120 AND `summonerType`=0;
INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES
(29120,0,1,22515,549.6223,352.0468,240.899,3.455752,8,0);
-- Targeting info for Assassin spawns
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=53609;
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ConditionTypeOrReference`,`ConditionTarget`,`ElseGroup`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`Comment`) VALUES
(13,1,53609,31,0,0,3,22515,@CGUID+06,"Summon Anub'ar Assassin - Target World Trigger"),
(13,1,53609,31,0,1,3,22515,@CGUID+07,"Summon Anub'ar Assassin - Target World Trigger"),
(13,1,53609,31,0,2,3,22515,@CGUID+08,"Summon Anub'ar Assassin - Target World Trigger"),
(13,1,53609,31,0,3,3,22515,@CGUID+09,"Summon Anub'ar Assassin - Target World Trigger"),
(13,1,53609,31,0,4,3,22515,@CGUID+10,"Summon Anub'ar Assassin - Target World Trigger"),
(13,1,53609,31,0,5,3,22515,@CGUID+11,"Summon Anub'ar Assassin - Target World Trigger"),
(13,1,53609,31,0,6,3,22515,@CGUID+12,"Summon Anub'ar Assassin - Target World Trigger"),
(13,1,53609,31,0,7,3,22515,@CGUID+13,"Summon Anub'ar Assassin - Target World Trigger");
-- Difficulty data
DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (53454,53472,53509);
INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`) VALUES
(53454,53454,59446), -- Anub'arak: Impale
(53472,53472,59433), -- Anub'arak: Pound (Stun)
(53509,53509,59432); -- Anub'arak: Pound (Damage)

View File

@@ -89,6 +89,12 @@ public:
return storage_.size();
}
// Clear the underlying storage. This does NOT despawn the creatures - use DespawnAll for that!
void clear()
{
storage_.clear();
}
void Summon(Creature const* summon) { storage_.push_back(summon->GetGUID()); }
void Despawn(Creature const* summon) { storage_.remove(summon->GetGUID()); }
void DespawnEntry(uint32 entry);

View File

@@ -2951,12 +2951,6 @@ void SpellMgr::LoadSpellInfoCorrections()
case 63137: // Force Cast (HACK: Target shouldn't be changed; summon position should be untied from spell destination)
spellInfo->Effects[0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
break;
case 53096: // Quetz'lun's Judgment
case 70743: // AoD Special
case 70614: // AoD Special - Vegard
case 4020: // Safirdrang's Chill
spellInfo->MaxAffectedTargets = 1;
break;
case 42436: // Drink! (Brewfest)
spellInfo->Effects[EFFECT_0].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ANY);
break;
@@ -3061,6 +3055,14 @@ void SpellMgr::LoadSpellInfoCorrections()
case 36327: // Shoot Arcane Explosion Arrow
case 55479: // Force Obedience
case 28560: // Summon Blizzard (Sapphiron)
case 53096: // Quetz'lun's Judgment
case 70743: // AoD Special
case 70614: // AoD Special - Vegard
case 4020: // Safirdrang's Chill
case 52438: // Summon Skittering Swarmer (Force Cast)
case 52449: // Summon Skittering Infector (Force Cast)
case 53609: // Summon Anub'ar Assassin (Force Cast)
case 53457: // Summon Impale Trigger (AoE)
spellInfo->MaxAffectedTargets = 1;
break;
case 36384: // Skartax Purple Beam

View File

@@ -18,7 +18,6 @@
#ifndef AZJOL_NERUB_H_
#define AZJOL_NERUB_H_
#define AzjolNerubScriptName "instance_azjol_nerub"
#define DataHeader "AN"
uint32 const EncounterCount = 3;
@@ -26,14 +25,15 @@ uint32 const EncounterCount = 3;
enum DataTypes
{
// Encounter States/Boss GUIDs
DATA_KRIKTHIR_THE_GATEWATCHER = 0,
DATA_KRIKTHIR = 0,
DATA_HADRONOX = 1,
DATA_ANUBARAK = 2,
// Additional Data
DATA_WATCHER_GASHRA = 3,
DATA_WATCHER_SILTHIK = 4,
DATA_WATCHER_NARJIL = 5
DATA_WATCHER_NARJIL,
DATA_WATCHER_GASHRA,
DATA_WATCHER_SILTHIK,
DATA_ANUBARAK_WALL
};
enum CreatureIds
@@ -47,6 +47,12 @@ enum CreatureIds
NPC_WATCHER_SILTHIK = 28731
};
// These are passed as -action to AI's DoAction to differentiate between them and boss scripts' own actions
enum InstanceActions
{
ACTION_GATEWATCHER_GREET = 1
};
enum GameObjectIds
{
GO_KRIKTHIR_DOOR = 192395,
@@ -55,10 +61,4 @@ enum GameObjectIds
GO_ANUBARAK_DOOR_3 = 192398
};
template<class AI>
AI* GetAzjolNerubAI(Creature* creature)
{
return GetInstanceAI<AI>(creature, AzjolNerubScriptName);
}
#endif // AZJOL_NERUB_H_

View File

@@ -21,61 +21,84 @@
enum Spells
{
SPELL_CARRION_BEETLES = 53520,
SPELL_SUMMON_CARRION_BEETLES = 53521,
SPELL_LEECHING_SWARM = 53467,
SPELL_POUND = 53472,
SPELL_SUBMERGE = 53421,
SPELL_IMPALE_DMG = 53454,
SPELL_IMPALE_SHAKEGROUND = 53455,
SPELL_IMPALE_SPIKE = 53539, //this is not the correct visual effect
//SPELL_IMPALE_TARGET = 53458,
SPELL_EMERGE = 53500,
SPELL_SUBMERGE = 53421,
SPELL_IMPALE_AURA = 53456,
SPELL_IMPALE_VISUAL = 53455,
SPELL_IMPALE_DAMAGE = 53454,
SPELL_LEECHING_SWARM = 53467,
SPELL_POUND = 59433,
SPELL_POUND_DAMAGE = 59432,
SPELL_CARRION_BEETLES = 53520,
SPELL_CARRION_BEETLE = 53521,
SPELL_SUMMON_DARTER = 53599,
SPELL_SUMMON_ASSASSIN = 53609,
SPELL_SUMMON_GUARDIAN = 53614,
SPELL_SUMMON_VENOMANCER = 53615,
SPELL_DART = 59349,
SPELL_BACKSTAB = 52540,
SPELL_ASSASSIN_VISUAL = 53611,
SPELL_SUNDER_ARMOR = 53618,
SPELL_POISON_BOLT = 53617
};
enum Creatures
{
CREATURE_GUARDIAN = 29216,
CREATURE_VENOMANCER = 29217,
CREATURE_DATTER = 29213,
CREATURE_IMPALE_TARGET = 89,
DISPLAY_INVISIBLE = 11686
NPC_WORLD_TRIGGER = 22515,
};
// not in db
enum Yells
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_DEATH = 2,
SAY_LOCUST = 3,
SAY_SUBMERGE = 4,
SAY_INTRO = 5
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_DEATH = 2,
SAY_LOCUST = 3,
SAY_SUBMERGE = 4,
SAY_INTRO = 5
};
enum Events
{
EVENT_POUND = 1,
EVENT_IMPALE,
EVENT_LEECHING_SWARM,
EVENT_CARRION_BEETLES,
EVENT_SUBMERGE, // use event for this so we don't submerge mid-cast
EVENT_DARTER,
EVENT_ASSASSIN,
EVENT_GUARDIAN,
EVENT_VENOMANCER,
EVENT_CLOSE_DOOR
};
enum Actions
{
ACTION_PET_DIED = 1,
ACTION_PET_EVADE
};
enum Misc
{
ACHIEV_TIMED_START_EVENT = 20381,
ACHIEV_GOTTA_GO_START_EVENT = 20381,
};
enum Phases
{
PHASE_MELEE = 0,
PHASE_UNDERGROUND = 1,
IMPALE_PHASE_TARGET = 0,
IMPALE_PHASE_ATTACK = 1,
IMPALE_PHASE_DMG = 2
PHASE_EMERGE = 1,
PHASE_SUBMERGE
};
const Position SpawnPoint[2] =
enum GUIDTypes
{
{ 550.7f, 282.8f, 224.3f, 0.0f },
{ 551.1f, 229.4f, 224.3f, 0.0f },
GUID_TYPE_PET = 0,
GUID_TYPE_IMPALE
};
const Position SpawnPointGuardian[2] =
enum SummonGroups
{
{ 550.348633f, 316.006805f, 234.2947f, 0.0f },
{ 550.188660f, 324.264557f, 237.7412f, 0.0f },
SUMMON_GROUP_WORLD_TRIGGER_GUARDIAN = 1
};
class boss_anub_arak : public CreatureScript
@@ -83,97 +106,58 @@ class boss_anub_arak : public CreatureScript
public:
boss_anub_arak() : CreatureScript("boss_anub_arak") { }
struct boss_anub_arakAI : public ScriptedAI
struct boss_anub_arakAI : public BossAI
{
boss_anub_arakAI(Creature* creature) : ScriptedAI(creature), Summons(me)
{
Initialize();
instance = creature->GetInstanceScript();
GuardianSummoned = false;
VenomancerSummoned = false;
DatterSummoned = false;
UndergroundTimer = 0;
VenomancerTimer = 0;
DatterTimer = 0;
DelayTimer = 0;
}
void Initialize()
{
CarrionBeetlesTimer = 8 * IN_MILLISECONDS;
LeechingSwarmTimer = 20 * IN_MILLISECONDS;
ImpaleTimer = 9 * IN_MILLISECONDS;
PoundTimer = 15 * IN_MILLISECONDS;
Phase = PHASE_MELEE;
UndergroundPhase = 0;
Channeling = false;
ImpalePhase = IMPALE_PHASE_TARGET;
ImpaleTarget.Clear();
}
InstanceScript* instance;
bool Channeling;
bool GuardianSummoned;
bool VenomancerSummoned;
bool DatterSummoned;
uint8 Phase;
uint32 UndergroundPhase;
uint32 CarrionBeetlesTimer;
uint32 LeechingSwarmTimer;
uint32 PoundTimer;
uint32 UndergroundTimer;
uint32 VenomancerTimer;
uint32 DatterTimer;
uint32 DelayTimer;
uint32 ImpaleTimer;
uint32 ImpalePhase;
ObjectGuid ImpaleTarget;
SummonList Summons;
boss_anub_arakAI(Creature* creature) : BossAI(creature, DATA_ANUBARAK), _nextSubmerge(0), _petCount(0), _assassinCount(0), _guardianCount(0), _venomancerCount(0) { }
void Reset() override
{
Initialize();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAura(SPELL_SUBMERGE);
Summons.DespawnAll();
instance->SetBossState(DATA_ANUBARAK, NOT_STARTED);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
BossAI::Reset();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOTTA_GO_START_EVENT);
_nextSubmerge = 75;
_petCount = 0;
}
Creature* DoSummonImpaleTarget(Unit* target)
void EnterCombat(Unit* who) override
{
Position targetPos = target->GetPosition();
BossAI::EnterCombat(who);
if (TempSummon* impaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILLISECONDS))
{
ImpaleTarget = impaleTarget->GetGUID();
impaleTarget->SetReactState(REACT_PASSIVE);
impaleTarget->SetDisplayId(DISPLAY_INVISIBLE);
impaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
impaleTarget->SetControlled(true, UNIT_STATE_ROOT);
return impaleTarget;
}
if (GameObject* door = instance->GetGameObject(DATA_ANUBARAK_WALL))
door->SetGoState(GO_STATE_ACTIVE); // open door for now
return NULL;
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
DelayTimer = 0;
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOTTA_GO_START_EVENT);
events.SetPhase(PHASE_EMERGE);
events.ScheduleEvent(EVENT_CLOSE_DOOR, Seconds(5));
events.ScheduleEvent(EVENT_POUND, randtime(Seconds(2), Seconds(4)), 0, PHASE_EMERGE);
events.ScheduleEvent(EVENT_LEECHING_SWARM, randtime(Seconds(5), Seconds(7)), 0, PHASE_EMERGE);
events.ScheduleEvent(EVENT_CARRION_BEETLES, randtime(Seconds(14), Seconds(17)), 0, PHASE_EMERGE);
// set up world triggers
std::list<TempSummon*> summoned;
me->SummonCreatureGroup(SUMMON_GROUP_WORLD_TRIGGER_GUARDIAN, &summoned);
if (summoned.empty()) // something went wrong
{
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
_guardianTrigger = (*summoned.begin())->GetGUID();
if (Creature* trigger = DoSummon(NPC_WORLD_TRIGGER, me->GetPosition(), 0u, TEMPSUMMON_MANUAL_DESPAWN))
_assassinTrigger = trigger->GetGUID();
else
{
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
}
void DelayEventStart()
void EnterEvadeMode(EvadeReason /*why*/) override
{
instance->SetBossState(DATA_ANUBARAK, IN_PROGRESS);
summons.DespawnAll();
_DespawnAtEvade();
}
void UpdateAI(uint32 diff) override
@@ -181,183 +165,234 @@ public:
if (!UpdateVictim())
return;
if (DelayTimer && DelayTimer > 5000)
DelayEventStart();
else DelayTimer+=diff;
events.Update(diff);
switch (Phase)
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
while (uint32 eventId = events.ExecuteEvent())
{
case PHASE_UNDERGROUND:
if (ImpaleTimer <= diff)
switch (eventId)
{
switch (ImpalePhase)
case EVENT_CLOSE_DOOR:
if (GameObject* door = instance->GetGameObject(DATA_ANUBARAK_WALL))
door->SetGoState(GO_STATE_READY);
break;
case EVENT_POUND:
DoCastVictim(SPELL_POUND);
events.Repeat(randtime(Seconds(26), Seconds(32)));
break;
case EVENT_LEECHING_SWARM:
Talk(SAY_LOCUST);
DoCastAOE(SPELL_LEECHING_SWARM);
events.Repeat(randtime(Seconds(25), Seconds(28)));
break;
case EVENT_CARRION_BEETLES:
DoCastAOE(SPELL_CARRION_BEETLES);
events.Repeat(randtime(Seconds(24), Seconds(27)));
break;
case EVENT_IMPALE:
if (Creature* impaleTarget = ObjectAccessor::GetCreature(*me, _impaleTarget))
DoCast(impaleTarget, SPELL_IMPALE_DAMAGE, true);
break;
case EVENT_SUBMERGE:
Talk(SAY_SUBMERGE);
DoCastSelf(SPELL_SUBMERGE);
break;
case EVENT_DARTER:
{
case IMPALE_PHASE_TARGET:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
std::list<Creature*> triggers;
me->GetCreatureListWithEntryInGrid(triggers, NPC_WORLD_TRIGGER);
if (!triggers.empty())
{
if (Creature* impaleTarget = DoSummonImpaleTarget(target))
impaleTarget->CastSpell(impaleTarget, SPELL_IMPALE_SHAKEGROUND, true);
ImpaleTimer = 3*IN_MILLISECONDS;
ImpalePhase = IMPALE_PHASE_ATTACK;
std::list<Creature*>::iterator it = triggers.begin();
std::advance(it, urand(0, triggers.size()-1));
(*it)->CastSpell(*it, SPELL_SUMMON_DARTER, true);
events.Repeat(Seconds(11));
}
break;
case IMPALE_PHASE_ATTACK:
if (Creature* impaleTarget = ObjectAccessor::GetCreature(*me, ImpaleTarget))
{
impaleTarget->CastSpell(impaleTarget, SPELL_IMPALE_SPIKE, false);
impaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND);
}
ImpalePhase = IMPALE_PHASE_DMG;
ImpaleTimer = 1*IN_MILLISECONDS;
break;
case IMPALE_PHASE_DMG:
if (Creature* impaleTarget = ObjectAccessor::GetCreature(*me, ImpaleTarget))
me->CastSpell(impaleTarget, SPELL_IMPALE_DMG, true);
ImpalePhase = IMPALE_PHASE_TARGET;
ImpaleTimer = 9*IN_MILLISECONDS;
else
EnterEvadeMode(EVADE_REASON_OTHER);
break;
}
} else ImpaleTimer -= diff;
if (!GuardianSummoned)
{
for (uint8 i = 0; i < 2; ++i)
{
if (Creature* Guardian = me->SummonCreature(CREATURE_GUARDIAN, SpawnPointGuardian[i], TEMPSUMMON_CORPSE_DESPAWN, 0))
case EVENT_ASSASSIN:
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _assassinTrigger))
{
Guardian->AddThreat(me->GetVictim(), 0.0f);
DoZoneInCombat(Guardian);
}
}
GuardianSummoned = true;
}
if (!VenomancerSummoned)
{
if (VenomancerTimer <= diff)
{
if (UndergroundPhase > 1)
{
for (uint8 i = 0; i < 2; ++i)
trigger->CastSpell(trigger, SPELL_SUMMON_ASSASSIN, true);
trigger->CastSpell(trigger, SPELL_SUMMON_ASSASSIN, true);
if (_assassinCount > 2)
{
if (Creature* Venomancer = me->SummonCreature(CREATURE_VENOMANCER, SpawnPoint[i], TEMPSUMMON_CORPSE_DESPAWN, 0))
{
Venomancer->AddThreat(me->GetVictim(), 0.0f);
DoZoneInCombat(Venomancer);
}
_assassinCount -= 2;
events.Repeat(Seconds(20));
}
VenomancerSummoned = true;
else
_assassinCount = 0;
}
} else VenomancerTimer -= diff;
}
if (!DatterSummoned)
{
if (DatterTimer <= diff)
{
if (UndergroundPhase > 2)
else // something went wrong
EnterEvadeMode(EVADE_REASON_OTHER);
break;
case EVENT_GUARDIAN:
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _guardianTrigger))
{
for (uint8 i = 0; i < 2; ++i)
trigger->CastSpell(trigger, SPELL_SUMMON_GUARDIAN, true);
trigger->CastSpell(trigger, SPELL_SUMMON_GUARDIAN, true);
if (_guardianCount > 2)
{
if (Creature* Datter = me->SummonCreature(CREATURE_DATTER, SpawnPoint[i], TEMPSUMMON_CORPSE_DESPAWN, 0))
{
Datter->AddThreat(me->GetVictim(), 0.0f);
DoZoneInCombat(Datter);
}
_guardianCount -= 2;
events.Repeat(Seconds(20));
}
DatterSummoned = true;
else
_guardianCount = 0;
}
} else DatterTimer -= diff;
if (me->HasAura(SPELL_LEECHING_SWARM))
me->RemoveAurasDueToSpell(SPELL_LEECHING_SWARM);
else
EnterEvadeMode(EVADE_REASON_OTHER);
break;
case EVENT_VENOMANCER:
if (Creature* trigger = ObjectAccessor::GetCreature(*me, _guardianTrigger))
{
trigger->CastSpell(trigger, SPELL_SUMMON_VENOMANCER, true);
trigger->CastSpell(trigger, SPELL_SUMMON_VENOMANCER, true);
if (_venomancerCount > 2)
{
_venomancerCount -= 2;
events.Repeat(Seconds(20));
}
else
_venomancerCount = 0;
}
else
EnterEvadeMode(EVADE_REASON_OTHER);
break;
default:
break;
}
if (UndergroundTimer <= diff)
{
me->RemoveAura(SPELL_SUBMERGE);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
Phase = PHASE_MELEE;
} else UndergroundTimer -= diff;
break;
case PHASE_MELEE:
if (((UndergroundPhase == 0 && HealthBelowPct(75))
|| (UndergroundPhase == 1 && HealthBelowPct(50))
|| (UndergroundPhase == 2 && HealthBelowPct(25)))
&& !me->HasUnitState(UNIT_STATE_CASTING))
{
GuardianSummoned = false;
VenomancerSummoned = false;
DatterSummoned = false;
UndergroundTimer = 40*IN_MILLISECONDS;
VenomancerTimer = 25*IN_MILLISECONDS;
DatterTimer = 32*IN_MILLISECONDS;
ImpalePhase = 0;
ImpaleTimer = 9*IN_MILLISECONDS;
DoCast(me, SPELL_SUBMERGE, false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE);
Phase = PHASE_UNDERGROUND;
++UndergroundPhase;
}
if (Channeling == true)
{
for (uint8 i = 0; i < 8; ++i)
DoCastVictim(SPELL_SUMMON_CARRION_BEETLES, true);
Channeling = false;
}
else if (CarrionBeetlesTimer <= diff)
{
Channeling = true;
DoCastVictim(SPELL_CARRION_BEETLES);
CarrionBeetlesTimer = 25*IN_MILLISECONDS;
} else CarrionBeetlesTimer -= diff;
if (LeechingSwarmTimer <= diff)
{
DoCast(me, SPELL_LEECHING_SWARM, true);
LeechingSwarmTimer = 19*IN_MILLISECONDS;
} else LeechingSwarmTimer -= diff;
if (PoundTimer <= diff)
{
if (Unit* target = me->GetVictim())
{
if (Creature* pImpaleTarget = DoSummonImpaleTarget(target))
me->CastSpell(pImpaleTarget, SPELL_POUND, false);
}
PoundTimer = 16500;
} else PoundTimer -= diff;
DoMeleeAttackIfReady();
break;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
}
DoMeleeAttackIfReady();
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
Summons.DespawnAll();
instance->SetBossState(DATA_ANUBARAK, DONE);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_SLAY);
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustSummoned(Creature* summon) override
void SetGUID(ObjectGuid guid, int32 type) override
{
Summons.Summon(summon);
switch (type)
{
case GUID_TYPE_PET:
{
if (Creature* creature = ObjectAccessor::GetCreature(*me, guid))
JustSummoned(creature);
else // something has gone horribly wrong
EnterEvadeMode(EVADE_REASON_OTHER);
break;
}
case GUID_TYPE_IMPALE:
_impaleTarget = guid;
events.ScheduleEvent(EVENT_IMPALE, Seconds(4));
break;
}
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_PET_DIED:
if (!_petCount) // underflow check - something has gone horribly wrong
{
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
if (!--_petCount) // last pet died, emerge
{
me->RemoveAurasDueToSpell(SPELL_SUBMERGE);
me->RemoveAurasDueToSpell(SPELL_IMPALE_AURA);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
DoCastSelf(SPELL_EMERGE);
events.SetPhase(PHASE_EMERGE);
events.ScheduleEvent(EVENT_POUND, randtime(Seconds(13), Seconds(18)), 0, PHASE_EMERGE);
events.ScheduleEvent(EVENT_LEECHING_SWARM, randtime(Seconds(3), Seconds(7)), 0, PHASE_EMERGE);
events.ScheduleEvent(EVENT_CARRION_BEETLES, randtime(Seconds(10), Seconds(15)), 0, PHASE_EMERGE);
}
break;
case ACTION_PET_EVADE:
EnterEvadeMode(EVADE_REASON_OTHER);
break;
}
}
void DamageTaken(Unit* /*source*/, uint32& damage) override
{
if (me->HasAura(SPELL_SUBMERGE))
damage = 0;
else
if (_nextSubmerge && me->HealthBelowPctDamaged(_nextSubmerge, damage))
{
events.CancelEvent(EVENT_SUBMERGE);
events.ScheduleEvent(EVENT_SUBMERGE, 0, 0, PHASE_EMERGE);
_nextSubmerge = _nextSubmerge-25;
}
}
void SpellHit(Unit* /*whose*/, SpellInfo const* spell) override
{
if (spell->Id == SPELL_SUBMERGE)
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAurasDueToSpell(SPELL_LEECHING_SWARM);
DoCastSelf(SPELL_IMPALE_AURA, true);
events.SetPhase(PHASE_SUBMERGE);
switch (_nextSubmerge)
{
case 50: // first submerge phase
_assassinCount = 4;
_guardianCount = 2;
_venomancerCount = 0;
break;
case 25: // second submerge phase
_assassinCount = 6;
_guardianCount = 2;
_venomancerCount = 2;
break;
case 0: // third submerge phase
_assassinCount = 6;
_guardianCount = 2;
_venomancerCount = 2;
events.ScheduleEvent(EVENT_DARTER, Seconds(0), 0, PHASE_SUBMERGE);
break;
}
_petCount = _guardianCount + _venomancerCount;
if (_assassinCount)
events.ScheduleEvent(EVENT_ASSASSIN, Seconds(0), 0, PHASE_SUBMERGE);
if (_guardianCount)
events.ScheduleEvent(EVENT_GUARDIAN, Seconds(4), 0, PHASE_SUBMERGE);
if (_venomancerCount)
events.ScheduleEvent(EVENT_VENOMANCER, Seconds(20), 0, PHASE_SUBMERGE);
}
}
private:
ObjectGuid _impaleTarget;
uint32 _nextSubmerge;
uint32 _petCount;
ObjectGuid _guardianTrigger;
ObjectGuid _assassinTrigger;
uint8 _assassinCount;
uint8 _guardianCount;
uint8 _venomancerCount;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -366,7 +401,313 @@ public:
}
};
class npc_anubarak_pet_template : public ScriptedAI
{
public:
npc_anubarak_pet_template(Creature* creature, bool isLarge) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _isLarge(isLarge) { }
void InitializeAI() override
{
ScriptedAI::InitializeAI();
if (Creature* anubarak = _instance->GetCreature(DATA_ANUBARAK))
anubarak->AI()->SetGUID(me->GetGUID(), GUID_TYPE_PET);
else
me->DespawnOrUnsummon();
}
void JustDied(Unit* killer) override
{
ScriptedAI::JustDied(killer);
if (_isLarge)
if (Creature* anubarak = _instance->GetCreature(DATA_ANUBARAK))
anubarak->AI()->DoAction(ACTION_PET_DIED);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (Creature* anubarak = _instance->GetCreature(DATA_ANUBARAK))
anubarak->AI()->DoAction(ACTION_PET_EVADE);
else
me->DespawnOrUnsummon();
}
protected:
InstanceScript* _instance;
private:
bool const _isLarge;
};
class npc_anubarak_anub_ar_darter : public CreatureScript
{
public:
npc_anubarak_anub_ar_darter() : CreatureScript("npc_anubarak_anub_ar_darter") { }
struct npc_anubarak_anub_ar_darterAI : public npc_anubarak_pet_template
{
npc_anubarak_anub_ar_darterAI(Creature* creature) : npc_anubarak_pet_template(creature, false) { }
void InitializeAI() override
{
npc_anubarak_pet_template::InitializeAI();
DoCastAOE(SPELL_DART);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<npc_anubarak_anub_ar_darterAI>(creature);
}
};
class npc_anubarak_anub_ar_assassin : public CreatureScript
{
public:
npc_anubarak_anub_ar_assassin() : CreatureScript("npc_anubarak_anub_ar_assassin") { }
struct npc_anubarak_anub_ar_assassinAI : public npc_anubarak_pet_template
{
npc_anubarak_anub_ar_assassinAI(Creature* creature) : npc_anubarak_pet_template(creature, false), _backstabTimer(6 * IN_MILLISECONDS) { }
bool IsInBounds(Position const& jumpTo, CreatureBoundary const* boundary)
{
if (!boundary)
return true;
for (CreatureBoundary::const_iterator it = boundary->cbegin(); it != boundary->cend(); ++it)
if (!(*it)->IsWithinBoundary(&jumpTo))
return false;
return true;
}
Position GetRandomPositionAround(Creature* anubarak)
{
static float DISTANCE_MIN = 10.0f;
static float DISTANCE_MAX = 30.0f;
double angle = rand_norm() * 2.0 * M_PI;
return { anubarak->GetPositionX() + (float)(frand(DISTANCE_MIN, DISTANCE_MAX)*std::sin(angle)), anubarak->GetPositionY() + (float)(frand(DISTANCE_MIN, DISTANCE_MAX)*std::cos(angle)), anubarak->GetPositionZ() };
}
void InitializeAI() override
{
npc_anubarak_pet_template::InitializeAI();
CreatureBoundary const* boundary = _instance->GetBossBoundary(DATA_ANUBARAK);
if (Creature* anubarak = _instance->GetCreature(DATA_ANUBARAK))
{
Position jumpTo;
do
jumpTo = GetRandomPositionAround(anubarak);
while (!IsInBounds(jumpTo, boundary));
me->GetMotionMaster()->MoveJump(jumpTo, 40.0f, 40.0f);
DoCastSelf(SPELL_ASSASSIN_VISUAL, true);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (diff >= _backstabTimer)
{
if (me->GetVictim() && me->GetVictim()->isInBack(me))
DoCastVictim(SPELL_BACKSTAB);
_backstabTimer = 6 * IN_MILLISECONDS;
}
else
_backstabTimer -= diff;
DoMeleeAttackIfReady();
}
void MovementInform(uint32 /*type*/, uint32 id) override
{
if (id == EVENT_JUMP)
{
me->RemoveAurasDueToSpell(SPELL_ASSASSIN_VISUAL);
DoZoneInCombat();
}
}
private:
uint32 _backstabTimer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<npc_anubarak_anub_ar_assassinAI>(creature);
}
};
class npc_anubarak_anub_ar_guardian : public CreatureScript
{
public:
npc_anubarak_anub_ar_guardian() : CreatureScript("npc_anubarak_anub_ar_guardian") { }
struct npc_anubarak_anub_ar_guardianAI : public npc_anubarak_pet_template
{
npc_anubarak_anub_ar_guardianAI(Creature* creature) : npc_anubarak_pet_template(creature, true), _sunderTimer(6 * IN_MILLISECONDS) { }
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (diff >= _sunderTimer)
{
DoCastVictim(SPELL_SUNDER_ARMOR);
_sunderTimer = 12 * IN_MILLISECONDS;
}
else
_sunderTimer -= diff;
DoMeleeAttackIfReady();
}
private:
uint32 _sunderTimer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<npc_anubarak_anub_ar_guardianAI>(creature);
}
};
class npc_anubarak_anub_ar_venomancer : public CreatureScript
{
public:
npc_anubarak_anub_ar_venomancer() : CreatureScript("npc_anubarak_anub_ar_venomancer") { }
struct npc_anubarak_anub_ar_venomancerAI : public npc_anubarak_pet_template
{
npc_anubarak_anub_ar_venomancerAI(Creature* creature) : npc_anubarak_pet_template(creature, true), _boltTimer(5 * IN_MILLISECONDS) { }
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (diff >= _boltTimer)
{
DoCastVictim(SPELL_POISON_BOLT);
_boltTimer = urandms(2, 3);
}
else
_boltTimer -= diff;
DoMeleeAttackIfReady();
}
private:
uint32 _boltTimer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<npc_anubarak_anub_ar_venomancerAI>(creature);
}
};
class npc_anubarak_impale_target : public CreatureScript
{
public:
npc_anubarak_impale_target() : CreatureScript("npc_anubarak_impale_target") { }
struct npc_anubarak_impale_targetAI : public NullCreatureAI
{
npc_anubarak_impale_targetAI(Creature* creature) : NullCreatureAI(creature) { }
void InitializeAI() override
{
if (Creature* anubarak = me->GetInstanceScript()->GetCreature(DATA_ANUBARAK))
{
DoCastSelf(SPELL_IMPALE_VISUAL);
me->DespawnOrUnsummon(Seconds(6));
anubarak->AI()->SetGUID(me->GetGUID(), GUID_TYPE_IMPALE);
}
else
me->DespawnOrUnsummon();
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<npc_anubarak_impale_targetAI>(creature);
}
};
class spell_anubarak_pound : public SpellScriptLoader
{
public:
spell_anubarak_pound() : SpellScriptLoader("spell_anubarak_pound") { }
class spell_anubarak_pound_SpellScript : public SpellScript
{
PrepareSpellScript(spell_anubarak_pound_SpellScript);
bool Validate(SpellInfo const* /*spell*/) override
{
return sSpellMgr->GetSpellInfo(SPELL_POUND_DAMAGE) != nullptr;
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
GetCaster()->CastSpell(target, SPELL_POUND_DAMAGE, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_anubarak_pound_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_anubarak_pound_SpellScript();
}
};
class spell_anubarak_carrion_beetles : public SpellScriptLoader
{
public:
spell_anubarak_carrion_beetles() : SpellScriptLoader("spell_anubarak_carrion_beetles") { }
class spell_anubarak_carrion_beetles_AuraScript : public AuraScript
{
public:
PrepareAuraScript(spell_anubarak_carrion_beetles_AuraScript);
bool Validate(SpellInfo const* /*spell*/) override
{
return (sSpellMgr->GetSpellInfo(SPELL_CARRION_BEETLE) != nullptr);
}
void HandlePeriodic(AuraEffect const* /*eff*/)
{
GetCaster()->CastSpell(GetCaster(), SPELL_CARRION_BEETLE, true);
GetCaster()->CastSpell(GetCaster(), SPELL_CARRION_BEETLE, true);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_anubarak_carrion_beetles_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_anubarak_carrion_beetles_AuraScript();
}
};
void AddSC_boss_anub_arak()
{
new boss_anub_arak();
new npc_anubarak_anub_ar_darter();
new npc_anubarak_anub_ar_assassin();
new npc_anubarak_anub_ar_guardian();
new npc_anubarak_anub_ar_venomancer();
new npc_anubarak_impale_target();
new spell_anubarak_pound();
new spell_anubarak_carrion_beetles();
}

View File

@@ -21,7 +21,7 @@
DoorData const doorData[] =
{
{ GO_KRIKTHIR_DOOR, DATA_KRIKTHIR_THE_GATEWATCHER, DOOR_TYPE_PASSAGE },
{ GO_KRIKTHIR_DOOR, DATA_KRIKTHIR, DOOR_TYPE_PASSAGE },
{ GO_ANUBARAK_DOOR_1, DATA_ANUBARAK, DOOR_TYPE_ROOM },
{ GO_ANUBARAK_DOOR_2, DATA_ANUBARAK, DOOR_TYPE_ROOM },
{ GO_ANUBARAK_DOOR_3, DATA_ANUBARAK, DOOR_TYPE_ROOM },
@@ -30,17 +30,32 @@ DoorData const doorData[] =
ObjectData const creatureData[] =
{
{ NPC_KRIKTHIR, DATA_KRIKTHIR_THE_GATEWATCHER },
{ NPC_KRIKTHIR, DATA_KRIKTHIR },
{ NPC_HADRONOX, DATA_HADRONOX },
{ NPC_ANUBARAK, DATA_ANUBARAK },
{ NPC_WATCHER_NARJIL, DATA_WATCHER_GASHRA },
{ NPC_WATCHER_GASHRA, DATA_WATCHER_SILTHIK },
{ NPC_WATCHER_SILTHIK, DATA_WATCHER_NARJIL },
{ 0, 0 } // END
};
ObjectData const gameobjectData[] =
{
{ GO_ANUBARAK_DOOR_3, DATA_ANUBARAK_WALL },
{ 0, 0 } // END
};
BossBoundaryData const boundaries =
{
{ DATA_KRIKTHIR, new RectangleBoundary(400.0f, 580.0f, 623.5f, 810.0f) },
{ DATA_HADRONOX, new ZRangeBoundary(666.0f, 776.0f) },
{ DATA_ANUBARAK, new CircleBoundary(Position(550.6178f, 253.5917f), 26.0f) }
};
class instance_azjol_nerub : public InstanceMapScript
{
public:
instance_azjol_nerub() : InstanceMapScript(AzjolNerubScriptName, 601) { }
instance_azjol_nerub() : InstanceMapScript("instance_azjol_nerub", 601) { }
struct instance_azjol_nerub_InstanceScript : public InstanceScript
{
@@ -48,8 +63,19 @@ class instance_azjol_nerub : public InstanceMapScript
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
LoadObjectData(creatureData, nullptr);
LoadObjectData(creatureData, gameobjectData);
}
void OnUnitDeath(Unit* who) override
{
InstanceScript::OnUnitDeath(who);
Creature* creature = who->ToCreature();
if (!creature || creature->IsCritter() || creature->IsControlledByPlayer())
return;
if (Creature* gatewatcher = GetCreature(DATA_KRIKTHIR))
gatewatcher->AI()->DoAction(-ACTION_GATEWATCHER_GREET);
}
};