mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-23 02:25:38 +01:00
[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:
188
sql/updates/world/3.3.5/2016_09_26_02_world.sql
Normal file
188
sql/updates/world/3.3.5/2016_09_26_02_world.sql
Normal 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)
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user