Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2023-05-29 19:05:17 +08:00
34 changed files with 960 additions and 578 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ DELETE FROM `spell_script_names` WHERE `spell_id` = 30745;
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(30745, 'spell_target_fissures'); (30745, 'spell_target_fissures');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 3) AND (`SourceEntry` = 30745); DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 1) AND (`SourceEntry` = 30745);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 30745, 0, 0, 31, 0, 3, 17083, 151090, 0, 0, 0, '', 'Target Fissures (30745) can only target Fel Orc Convert (17083) of specific guids'), (13, 1, 30745, 0, 0, 31, 0, 3, 17083, 151090, 0, 0, 0, '', 'Target Fissures (30745) can only target Fel Orc Convert (17083) of specific guids'),
(13, 1, 30745, 0, 1, 31, 0, 3, 17083, 151091, 0, 0, 0, '', 'Target Fissures (30745) can only target Fel Orc Convert (17083) of specific guids'), (13, 1, 30745, 0, 1, 31, 0, 3, 17083, 151091, 0, 0, 0, '', 'Target Fissures (30745) can only target Fel Orc Convert (17083) of specific guids'),
@@ -0,0 +1,3 @@
-- DB update 2023_05_23_00 -> 2023_05_24_00
--
UPDATE `creature_template` SET `speed_run` = 1.14286 WHERE `entry` = 4480;
@@ -0,0 +1,5 @@
-- DB update 2023_05_24_00 -> 2023_05_24_01
--
DELETE FROM `creature_template_spell` WHERE `CreatureID`=18847 AND `Index`=2 AND `Spell`=33096;
INSERT INTO `creature_template_spell` (`CreatureID`, `Index`, `Spell`, `VerifiedBuild`) VALUES (18847, 2, 33096, 0);
@@ -0,0 +1,20 @@
-- DB update 2023_05_24_01 -> 2023_05_24_02
--
-- Blackrock Summoner
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 9818);
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(9818, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 0, 11, 12380, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - On Reset - Cast \'Shadow Channeling\' (Phase 1) (Normal Dungeon)'),
(9818, 0, 1, 0, 4, 0, 100, 2, 0, 0, 0, 0, 0, 39, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - On Aggro - Call For Help (Normal Dungeon)'),
(9818, 0, 2, 0, 4, 0, 100, 3, 0, 0, 0, 0, 0, 87, 981800, 981801, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - On Aggro - Summon Random Enemy (No Repeat) (Normal Dungeon)'),
(9818, 0, 3, 0, 0, 0, 100, 2, 50, 100, 3600, 6300, 0, 11, 12466, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - In Combat - Cast \'Fireball\' (Normal Dungeon)'),
(9818, 0, 4, 0, 0, 0, 100, 2, 11400, 11400, 12700, 16700, 0, 11, 15532, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - In Combat - Cast \'Frost Nova\' (Normal Dungeon)'),
(9818, 0, 5, 0, 2, 0, 100, 3, 0, 15, 0, 0, 0, 25, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - Between 0-15% Health - Flee For Assist (No Repeat) (Normal Dungeon)'),
(9818, 0, 6, 0, 1, 0, 100, 2, 0, 8000, 12000, 14000, 0, 5, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - Out of Combat - Play Emote 1 (No Repeat) (Normal Dungeon)');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` IN (981800, 981801));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(981800, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 11, 15792, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - ActionList - Cast \'Summon Blackhand Veteran\' (No Repeat) (Normal Dungeon)'),
(981800, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - ActionList - Say Line 0 (No Repeat) (Normal Dungeon)'),
(981801, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 11, 15794, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - ActionList - Cast \'Summon Blackhand Dreadweaver\' (No Repeat) (Normal Dungeon)'),
(981801, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Blackhand Summoner - ActionList - Say Line 1 (No Repeat) (Normal Dungeon)');
@@ -0,0 +1,9 @@
-- DB update 2023_05_24_02 -> 2023_05_24_03
--
UPDATE `creature_loot_template` SET `GroupId` = 1 WHERE (`Entry` = 17370) AND (`Item` IN (1, 2, 3, 4, 5, 6));
UPDATE `creature_loot_template` SET `Chance` = 5 WHERE (`Entry` = 17370) AND (`Item` IN (1, 2));
UPDATE `creature_loot_template` SET `Chance` = 1 WHERE (`Entry` = 17370) AND (`Item` IN (3, 4, 5, 6));
UPDATE `creature_loot_template` SET `GroupId` = 1 WHERE (`Entry` = 18620) AND (`Item` IN (1, 2, 3, 4, 5, 6, 7));
UPDATE `creature_loot_template` SET `Chance` = 5 WHERE (`Entry` = 18620) AND (`Item` IN (1, 2));
UPDATE `creature_loot_template` SET `Chance` = 1 WHERE (`Entry` = 18620) AND (`Item` IN (3, 4, 5, 6, 7));
@@ -0,0 +1,9 @@
-- DB update 2023_05_24_03 -> 2023_05_28_00
--
UPDATE `smart_scripts` SET `event_param2`=2 WHERE `entryorguid`=-151131 AND `source_type`=0 AND `id`=1003 AND `link`=1004;
UPDATE `smart_scripts` SET `event_param2`=4 WHERE `entryorguid`=-151131 AND `source_type`=0 AND `id`=1005 AND `link`=1006;
UPDATE `smart_scripts` SET `event_param2`=6 WHERE `entryorguid`=-151131 AND `source_type`=0 AND `id`=1007 AND `link`=1008;
UPDATE `smart_scripts` SET `event_param2`=2 WHERE `entryorguid`=-151137 AND `source_type`=0 AND `id`=1003 AND `link`=1004;
UPDATE `smart_scripts` SET `event_param2`=4 WHERE `entryorguid`=-151137 AND `source_type`=0 AND `id`=1005 AND `link`=1006;
UPDATE `smart_scripts` SET `event_param2`=6 WHERE `entryorguid`=-151137 AND `source_type`=0 AND `id`=1007 AND `link`=1008;
@@ -0,0 +1,3 @@
-- DB update 2023_05_28_00 -> 2023_05_28_01
--
UPDATE `creature_loot_template` SET `Chance` = 0.5 WHERE `Reference` = 24093;
@@ -0,0 +1,10 @@
-- DB update 2023_05_28_01 -> 2023_05_28_02
-- Change from old value to new value
UPDATE `creature_template` SET `flags_extra` = `flags_extra`&~67108864|134217728 WHERE `entry` IN (16507,16523,16593,16594,16699,16700,16704,17420,17462,17464,17653,17694,17722,17800,17803,17993,17994,18155,18404,18405,18420,18421,18422,18620,18631,18632,18633,18634,18635,18639,18640,18641,18829,19166,19168,19505,19510,19735,19767,20059,20576,20577,20582,20586,20587,20589,20590,20591,20593,20594,20595,20621,20622,20625,20638,20640,20641,20642,20643,20647,20648,20649,20864,20865,20867,20868,20873,20875,20881,20883,20988,20990,21522,21523,21539,21540,21541,21542,21543,21544,21545,21548,21549,21570,21571,21574,21577,21578,21591,21593,21604,21605,21607,21608,21615,21619);
-- Add new flag
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|67108864 WHERE `entry` IN (17462, 20595, 14834);
-- Misc Fix for ShH
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 17462) AND (`source_type` = 0) AND (`id` IN (2));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(17462, 0, 2, 0, 40, 0, 100, 0, 4, 1746200, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shattered Hand Zealot - On Waypoint Ended - Set In Combat With Zone');
@@ -0,0 +1,10 @@
-- DB update 2023_05_28_02 -> 2023_05_28_03
--
DELETE FROM `smart_scripts` WHERE (`entryorguid` IN (-151090,-151091,-151092,-151093)) AND (`source_type` = 0) AND (`id` IN (0));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(-151090, 0, 1000, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 18, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hack: Fel Orc Convert - On Respawn - Set Flags Not Attackable'),
(-151091, 0, 1000, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 18, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hack: Fel Orc Convert - On Respawn - Set Flags Not Attackable'),
(-151092, 0, 1000, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 18, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hack: Fel Orc Convert - On Respawn - Set Flags Not Attackable'),
(-151093, 0, 1000, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 18, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Hack: Fel Orc Convert - On Respawn - Set Flags Not Attackable');
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|134217728 WHERE (`entry` IN (17083, 20567));
@@ -0,0 +1,24 @@
-- DB update 2023_05_28_03 -> 2023_05_28_04
UPDATE `creature_template` SET `ScriptName` = 'npc_shattered_hand_scout' WHERE `entry` = 17693;
SET @PATH := 17693 * 10;
DELETE FROM `waypoint_data` WHERE `id` = @PATH;
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
(@PATH,1,389.98074,315.4098,1.9338964,NULL,0,1,0,100,0),
(@PATH,2,419.4097,315.15308,1.940825,NULL,0,1,0,100,0),
(@PATH,3,460.31537,316.02213,1.9368871,NULL,0,1,0,100,0),
(@PATH,4,488.62424,315.73007,1.9498857,NULL,0,1,0,100,0);
DELETE FROM `spell_target_position` WHERE `ID` = 30976;
INSERT INTO `spell_target_position` (`ID`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `VerifiedBuild`) VALUES
(30976, 540, 520.062, 255.486, 2.0333333, 48999);
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 1) AND (`SourceEntry` = 30952);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 30952, 0, 0, 31, 0, 3, 17687, 0, 0, 0, 0, '', 'Shoot Flame Arrow (30952) only hit Flame Arrow (17687)');
DELETE FROM `creature_formations` WHERE `memberGUID` IN (151094,151095,151096,151097);
INSERT INTO `creature_formations` (`memberGUID`, `leaderGUID`, `groupAI`) VALUES
(151095,151095,3),
(151096,151095,3),
(151097,151095,3);
@@ -0,0 +1,4 @@
-- DB update 2023_05_28_04 -> 2023_05_29_00
--
UPDATE `creature_template` SET `mechanic_immune_mask` = `mechanic_immune_mask`|16|64|256|1024|2048|4096|65536|8388608|33554432 WHERE `entry` = 21102;
@@ -0,0 +1,3 @@
-- DB update 2023_05_29_00 -> 2023_05_29_01
--
DELETE FROM `creature_template_resistance` WHERE `CreatureID` IN (17034, 17035, 17039, 17053);
@@ -0,0 +1,3 @@
-- DB update 2023_05_29_01 -> 2023_05_29_02
-- Hellfire Beacons
UPDATE `gameobject_template` SET `ScriptName` = 'go_beacon' WHERE `entry` IN (181579, 181580, 181581);
@@ -114,7 +114,7 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3
void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob) void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, uint32 var1, bool bvar, SpellInfo const* spell, GameObject* gob)
{ {
//calc random //calc random
if (e.GetEventType() != SMART_EVENT_LINK && e.event.event_chance < 100 && e.event.event_chance) if (e.event.event_chance < 100 && e.event.event_chance)
{ {
uint32 rnd = urand(1, 100); uint32 rnd = urand(1, 100);
if (e.event.event_chance <= rnd) if (e.event.event_chance <= rnd)
@@ -2446,6 +2446,12 @@ bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction /
if (GetCharmerOrOwnerGUID()) if (GetCharmerOrOwnerGUID())
return false; return false;
/// @todo: Implement aggro range, detection range and assistance range templates
if (m_creatureInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS))
{
return false;
}
// only from same creature faction // only from same creature faction
if (checkfaction) if (checkfaction)
{ {
@@ -72,15 +72,15 @@ enum CreatureFlagsExtra : uint32
CREATURE_FLAG_EXTRA_NO_DODGE = 0x00800000, // xinef: target cannot dodge CREATURE_FLAG_EXTRA_NO_DODGE = 0x00800000, // xinef: target cannot dodge
CREATURE_FLAG_EXTRA_MODULE = 0x01000000, CREATURE_FLAG_EXTRA_MODULE = 0x01000000,
CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE = 0x02000000, // Prevent creatures from calling for assistance on initial aggro CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE = 0x02000000, // Prevent creatures from calling for assistance on initial aggro
CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI = 0x04000000, // Load both ENTRY and GUID specific SAI CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS = 0x04000000, // Prevents creature from responding to assistance calls
CREATURE_FLAG_EXTRA_UNUSED_28 = 0x08000000, CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI = 0x08000000, // Load both ENTRY and GUID specific SAI
CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000, // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB) CREATURE_FLAG_EXTRA_DUNGEON_BOSS = 0x10000000, // creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)
CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING = 0x20000000, // creature ignore pathfinding CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING = 0x20000000, // creature ignore pathfinding
CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK = 0x40000000, // creature is immune to knockback effects CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK = 0x40000000, // creature is immune to knockback effects
CREATURE_FLAG_EXTRA_HARD_RESET = 0x80000000, CREATURE_FLAG_EXTRA_HARD_RESET = 0x80000000,
// Masks // Masks
CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_12 | CREATURE_FLAG_EXTRA_UNUSED_28), // SKIP CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_12), // SKIP
CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS)) // SKIP CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS)) // SKIP
}; };
@@ -57,8 +57,8 @@ AC_API_EXPORT EnumText EnumUtils<CreatureFlagsExtra>::ToString(CreatureFlagsExtr
case CREATURE_FLAG_EXTRA_NO_DODGE: return { "CREATURE_FLAG_EXTRA_NO_DODGE", "CREATURE_FLAG_EXTRA_NO_DODGE", "xinef: target cannot dodge" }; case CREATURE_FLAG_EXTRA_NO_DODGE: return { "CREATURE_FLAG_EXTRA_NO_DODGE", "CREATURE_FLAG_EXTRA_NO_DODGE", "xinef: target cannot dodge" };
case CREATURE_FLAG_EXTRA_MODULE: return { "CREATURE_FLAG_EXTRA_MODULE", "CREATURE_FLAG_EXTRA_MODULE", "Used by module creatures to avoid blizzlike checks." }; case CREATURE_FLAG_EXTRA_MODULE: return { "CREATURE_FLAG_EXTRA_MODULE", "CREATURE_FLAG_EXTRA_MODULE", "Used by module creatures to avoid blizzlike checks." };
case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return { "CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE", "Creature does not call for assistance on initial aggro", "" }; case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return { "CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE", "Creature does not call for assistance on initial aggro", "" };
case CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS: return { "CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS", "Prevents creature from responding to assistance calls", "" };
case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return { "CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI", "Creature entry SAI won't be overriden by GUID SAI", "" }; case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return { "CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI", "Creature entry SAI won't be overriden by GUID SAI", "" };
case CREATURE_FLAG_EXTRA_UNUSED_28: return { "CREATURE_FLAG_EXTRA_UNUSED_28", "CREATURE_FLAG_EXTRA_UNUSED_28", "" };
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return { "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)" }; case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return { "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "CREATURE_FLAG_EXTRA_DUNGEON_BOSS", "creature is a dungeon boss (SET DYNAMICALLY, DO NOT ADD IN DB)" };
case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return { "CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING", "CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING", "creature ignore pathfinding" }; case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return { "CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING", "CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING", "creature ignore pathfinding" };
case CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK: return { "CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK", "CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK", "creature is immune to knockback effects" }; case CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK: return { "CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK", "CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK", "creature is immune to knockback effects" };
@@ -101,8 +101,8 @@ AC_API_EXPORT CreatureFlagsExtra EnumUtils<CreatureFlagsExtra>::FromIndex(size_t
case 23: return CREATURE_FLAG_EXTRA_NO_DODGE; case 23: return CREATURE_FLAG_EXTRA_NO_DODGE;
case 24: return CREATURE_FLAG_EXTRA_MODULE; case 24: return CREATURE_FLAG_EXTRA_MODULE;
case 25: return CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE; case 25: return CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE;
case 26: return CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI; case 26: return CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS;
case 27: return CREATURE_FLAG_EXTRA_UNUSED_28; case 27: return CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI;
case 28: return CREATURE_FLAG_EXTRA_DUNGEON_BOSS; case 28: return CREATURE_FLAG_EXTRA_DUNGEON_BOSS;
case 29: return CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING; case 29: return CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING;
case 30: return CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK; case 30: return CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK;
@@ -142,8 +142,8 @@ AC_API_EXPORT size_t EnumUtils<CreatureFlagsExtra>::ToIndex(CreatureFlagsExtra v
case CREATURE_FLAG_EXTRA_NO_DODGE: return 23; case CREATURE_FLAG_EXTRA_NO_DODGE: return 23;
case CREATURE_FLAG_EXTRA_MODULE: return 24; case CREATURE_FLAG_EXTRA_MODULE: return 24;
case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return 25; case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return 25;
case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return 26; case CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS: return 26;
case CREATURE_FLAG_EXTRA_UNUSED_28: return 27; case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return 27;
case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return 28; case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return 28;
case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return 29; case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return 29;
case CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK: return 30; case CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK: return 30;
@@ -5284,7 +5284,7 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons
if (at) if (at)
Relocate(at->target_X, at->target_Y, at->target_Z, at->target_Orientation); Relocate(at->target_X, at->target_Y, at->target_Z, at->target_Orientation);
else else
RelocateToHomebind(); RelocateToHomebind();
} }
// NOW player must have valid map // NOW player must have valid map
+11 -4
View File
@@ -70,14 +70,21 @@ public:
{ {
auto itemTokens = Acore::Tokenize(itemString, ':', false); auto itemTokens = Acore::Tokenize(itemString, ':', false);
if (itemTokens.size() != 2) uint32 itemCount;
switch (itemTokens.size())
{ {
handler->SendSysMessage(Acore::StringFormatFmt("> Incorrect item list format for '{}'", itemString)); case 1:
continue; itemCount = 1; // Default to sending 1 item
break;
case 2:
itemCount = *Acore::StringTo<uint32>(itemTokens.at(1));
break;
default:
handler->SendSysMessage(Acore::StringFormatFmt("> Incorrect item list format for '{}'", itemString));
continue;
} }
uint32 itemID = *Acore::StringTo<uint32>(itemTokens.at(0)); uint32 itemID = *Acore::StringTo<uint32>(itemTokens.at(0));
uint32 itemCount = *Acore::StringTo<uint32>(itemTokens.at(1));
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemID); ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemID);
if (!itemTemplate) if (!itemTemplate)
@@ -19,29 +19,27 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "old_hillsbrad.h" #include "old_hillsbrad.h"
enum CaptainSkarloc enum Text
{ {
SAY_ENTER = 0, SAY_ENTER = 0,
SAY_TAUNT = 1, SAY_TAUNT = 1,
SAY_SLAY = 2, SAY_SLAY = 2,
SAY_DEATH = 3, SAY_DEATH = 3
};
SPELL_HOLY_LIGHT = 29427, enum Spells
SPELL_CLEANSE = 29380, {
SPELL_HAMMER_OF_JUSTICE = 13005, SPELL_HOLY_LIGHT = 29427,
SPELL_HOLY_SHIELD = 31904, SPELL_CLEANSE = 29380,
SPELL_DEVOTION_AURA = 8258, SPELL_HAMMER_OF_JUSTICE = 13005,
SPELL_CONSECRATION = 38385, SPELL_HOLY_SHIELD = 31904,
SPELL_DEVOTION_AURA = 8258,
SPELL_CONSECRATION = 38385
};
WAYPOINTS_COUNT = 4, enum Misc
{
EVENT_INITIAL_TALK = 1, WAYPOINTS_COUNT = 4
EVENT_START_FIGHT = 2,
EVENT_SPELL_CLEANSE = 10,
EVENT_SPELL_HAMMER = 11,
EVENT_SPELL_HOLY_LIGHT = 12,
EVENT_SPELL_HOLY_SHIELD = 13,
EVENT_SPELL_CONSECRATION = 14
}; };
const Position startPath[WAYPOINTS_COUNT] = const Position startPath[WAYPOINTS_COUNT] =
@@ -52,172 +50,174 @@ const Position startPath[WAYPOINTS_COUNT] =
{2058.77f, 236.04f, 63.92f, 0.0f} {2058.77f, 236.04f, 63.92f, 0.0f}
}; };
class boss_captain_skarloc : public CreatureScript struct boss_captain_skarloc : public BossAI
{ {
public: boss_captain_skarloc(Creature* creature) : BossAI(creature, DATA_CAPTAIN_SKARLOC), summons(me)
boss_captain_skarloc() : CreatureScript("boss_captain_skarloc") { }
CreatureAI* GetAI(Creature* creature) const override
{ {
return GetOldHillsbradAI<boss_captain_skarlocAI>(creature); scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
} }
struct boss_captain_skarlocAI : public ScriptedAI SummonList summons;
void Reset() override
{ {
boss_captain_skarlocAI(Creature* creature) : ScriptedAI(creature), summons(me) { } _Reset();
summons.DespawnAll();
}
EventMap events; void JustSummoned(Creature* summon) override
SummonList summons; {
summons.Summon(summon);
void Reset() override if (Creature* thrall = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(DATA_THRALL_GUID)))
{ {
events.Reset(); thrall->AI()->JustSummoned(summon);
summons.DespawnAll();
} }
summon->SetImmuneToAll(true);
if (summon->GetEntry() == NPC_SKARLOC_MOUNT)
return;
void JustSummoned(Creature* summon) override if (summons.size() == 1)
{ {
summons.Summon(summon); summon->GetMotionMaster()->MovePoint(0, 2060.788f, 237.301f, 63.999f);
if (Creature* thrall = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(DATA_THRALL_GUID)))
thrall->AI()->JustSummoned(summon);
summon->SetImmuneToAll(true);
if (summon->GetEntry() == NPC_SKARLOC_MOUNT)
return;
if (summons.size() == 1)
summon->GetMotionMaster()->MovePoint(0, 2060.788f, 237.301f, 63.999f);
else
summon->GetMotionMaster()->MovePoint(0, 2056.870f, 234.853f, 63.839f);
} }
else
void InitializeAI() override
{ {
ScriptedAI::InitializeAI(); summon->GetMotionMaster()->MovePoint(0, 2056.870f, 234.853f, 63.839f);
Movement::PointsArray path;
path.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
for (uint8 i = 0; i < WAYPOINTS_COUNT; ++i)
path.push_back(G3D::Vector3(startPath[i].GetPositionX(), startPath[i].GetPositionY(), startPath[i].GetPositionZ()));
me->GetMotionMaster()->MoveSplinePath(&path);
me->SetImmuneToAll(true);
me->Mount(SKARLOC_MOUNT_MODEL);
} }
}
void MovementInform(uint32 type, uint32 id) override void InitializeAI() override
{
ScriptedAI::InitializeAI();
Movement::PointsArray path;
path.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
for (uint8 i = 0; i < WAYPOINTS_COUNT; ++i)
{ {
if (type != ESCORT_MOTION_TYPE) path.push_back(G3D::Vector3(startPath[i].GetPositionX(), startPath[i].GetPositionY(), startPath[i].GetPositionZ()));
return; }
me->GetMotionMaster()->MoveSplinePath(&path);
me->SetImmuneToAll(true);
me->Mount(SKARLOC_MOUNT_MODEL);
}
// Xinef: we can rely here on internal counting void MovementInform(uint32 type, uint32 id) override
if (id == 1) {
if (type != ESCORT_MOTION_TYPE)
return;
// Xinef: we can rely here on internal counting
if (id == 1)
{
me->SummonCreature(NPC_DURNHOLDE_MAGE, 2038.549f, 273.303f, 63.420f, 5.30f, TEMPSUMMON_MANUAL_DESPAWN);
me->SummonCreature(NPC_DURNHOLDE_VETERAN, 2032.810f, 269.416f, 63.561f, 5.30f, TEMPSUMMON_MANUAL_DESPAWN);
}
else if (id == 2)
{
me->Dismount();
me->SetWalk(true);
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
{ {
me->SummonCreature(NPC_DURNHOLDE_MAGE, 2038.549f, 273.303f, 63.420f, 5.30f, TEMPSUMMON_MANUAL_DESPAWN); if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
me->SummonCreature(NPC_DURNHOLDE_VETERAN, 2032.810f, 269.416f, 63.561f, 5.30f, TEMPSUMMON_MANUAL_DESPAWN);
}
else if (id == 2)
{
me->Dismount();
me->SetWalk(true);
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
summon->SetWalk(true);
if (Creature* mount = me->SummonCreature(NPC_SKARLOC_MOUNT, 2049.12f, 252.31f, 62.855f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN))
{ {
mount->SetImmuneToNPC(true); summon->SetWalk(true);
mount->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
} }
} }
if (Creature* mount = me->SummonCreature(NPC_SKARLOC_MOUNT, 2049.12f, 252.31f, 62.855f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN))
if (me->movespline->Finalized())
{ {
Talk(SAY_ENTER, 500ms); mount->SetImmuneToNPC(true);
mount->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
}
me->m_Events.AddEventAtOffset([this]() if (me->movespline->Finalized())
{
Talk(SAY_ENTER, 500ms);
me->m_Events.AddEventAtOffset([this]()
{
me->SetImmuneToAll(false);
me->SetInCombatWithZone();
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
{ {
me->SetImmuneToAll(false); if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr))
me->SetInCombatWithZone();
for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr)
{ {
if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr)) if (summon->GetEntry() != NPC_SKARLOC_MOUNT)
{ {
if (summon->GetEntry() != NPC_SKARLOC_MOUNT) summon->SetImmuneToAll(false);
{ summon->SetInCombatWithZone();
summon->SetImmuneToAll(false);
summon->SetInCombatWithZone();
}
} }
} }
}, 8s); }
} }, 8s);
} }
}
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
DoCastSelf(SPELL_DEVOTION_AURA);
scheduler.Schedule(15s, [this](TaskContext context)
{ {
me->CastSpell(me, SPELL_DEVOTION_AURA, true); DoCastSelf(SPELL_HOLY_LIGHT);
context.Repeat(20s);
events.ScheduleEvent(EVENT_SPELL_HOLY_LIGHT, 15000); }).Schedule(6s, [this](TaskContext context)
events.ScheduleEvent(EVENT_SPELL_CLEANSE, 6000);
events.ScheduleEvent(EVENT_SPELL_HAMMER, 20000);
events.ScheduleEvent(EVENT_SPELL_HOLY_SHIELD, 10000);
if (IsHeroic())
events.ScheduleEvent(EVENT_SPELL_CONSECRATION, 1000);
}
void KilledUnit(Unit* /*victim*/) override
{ {
Talk(SAY_SLAY); if (roll_chance_i(33))
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
me->GetInstanceScript()->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_SKARLOC_KILLED);
me->GetInstanceScript()->SetData(DATA_THRALL_ADD_FLAG, 0);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_HOLY_LIGHT: Talk(SAY_TAUNT);
me->CastSpell(me, SPELL_HOLY_LIGHT, false);
events.ScheduleEvent(EVENT_SPELL_HOLY_LIGHT, 20000);
break;
case EVENT_SPELL_CLEANSE:
if (roll_chance_i(33))
Talk(SAY_TAUNT);
me->CastSpell(me, SPELL_CLEANSE, false);
events.ScheduleEvent(EVENT_SPELL_CLEANSE, 10000);
break;
case EVENT_SPELL_HAMMER:
me->CastSpell(me->GetVictim(), SPELL_HAMMER_OF_JUSTICE, false);
events.ScheduleEvent(EVENT_SPELL_HAMMER, 30000);
break;
case EVENT_SPELL_HOLY_SHIELD:
me->CastSpell(me, SPELL_HOLY_SHIELD, false);
events.ScheduleEvent(SPELL_HOLY_SHIELD, 30000);
break;
case EVENT_SPELL_CONSECRATION:
me->CastSpell(me, SPELL_CONSECRATION, false);
events.ScheduleEvent(EVENT_SPELL_CONSECRATION, 20000);
break;
} }
DoCastSelf(SPELL_CLEANSE);
context.Repeat(10s);
}).Schedule(20s, [this](TaskContext context)
{
DoCastVictim(SPELL_HAMMER_OF_JUSTICE);
context.Repeat(30s);
}).Schedule(10s, [this](TaskContext context)
{
DoCastSelf(SPELL_HOLY_SHIELD);
context.Repeat(30s);
});
DoMeleeAttackIfReady(); if (IsHeroic())
{
scheduler.Schedule(1s, [this](TaskContext context)
{
DoCastSelf(SPELL_CONSECRATION);
context.Repeat(20s);
});
} }
}; }
void KilledUnit(Unit* /*victim*/) override
{
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
me->GetInstanceScript()->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_SKARLOC_KILLED);
me->GetInstanceScript()->SetData(DATA_THRALL_ADD_FLAG, 0);
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
}; };
void AddSC_boss_captain_skarloc() void AddSC_boss_captain_skarloc()
{ {
new boss_captain_skarloc(); RegisterOldHillsbradCreatureAI(boss_captain_skarloc);
} }
@@ -19,107 +19,98 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "old_hillsbrad.h" #include "old_hillsbrad.h"
enum EpochHunter enum Text
{ {
SAY_AGGRO = 5, SAY_AGGRO = 5,
SAY_SLAY = 6, SAY_SLAY = 6,
SAY_BREATH = 7, SAY_BREATH = 7,
SAY_DEATH = 8, SAY_DEATH = 8
SPELL_SAND_BREATH = 31914,
SPELL_IMPENDING_DEATH = 31916,
SPELL_MAGIC_DISRUPTION_AURA = 33834,
SPELL_WING_BUFFET = 31475,
EVENT_SPELL_SAND_BREATH = 1,
EVENT_SPELL_IMPENDING_DEATH = 2,
EVENT_SPELL_DISRUPTION = 3,
EVENT_SPELL_WING_BUFFET = 4
}; };
class boss_epoch_hunter : public CreatureScript enum Spells
{ {
public: SPELL_SAND_BREATH = 31914,
boss_epoch_hunter() : CreatureScript("boss_epoch_hunter") { } SPELL_IMPENDING_DEATH = 31916,
SPELL_MAGIC_DISRUPTION_AURA = 33834,
SPELL_WING_BUFFET = 31475
};
CreatureAI* GetAI(Creature* creature) const override struct boss_epoch_hunter : public BossAI
{
boss_epoch_hunter(Creature* creature) : BossAI(creature, DATA_EPOCH_HUNTER)
{ {
return GetOldHillsbradAI<boss_epoch_hunterAI>(creature); scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
} }
struct boss_epoch_hunterAI : public ScriptedAI void Reset() override
{ {
boss_epoch_hunterAI(Creature* creature) : ScriptedAI(creature) { } _Reset();
}
EventMap events; void JustEngagedWith(Unit* /*who*/) override
{
void Reset() override _JustEngagedWith();
Talk(SAY_AGGRO);
scheduler.Schedule(8s, [this](TaskContext context)
{ {
} if (roll_chance_i(50))
void JustEngagedWith(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
events.ScheduleEvent(EVENT_SPELL_SAND_BREATH, 8000);
events.ScheduleEvent(EVENT_SPELL_IMPENDING_DEATH, 2000);
events.ScheduleEvent(EVENT_SPELL_DISRUPTION, 20000);
events.ScheduleEvent(EVENT_SPELL_WING_BUFFET, 14000);
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustDied(Unit* killer) override
{
if (killer && killer == me)
return;
Talk(SAY_DEATH);
me->GetInstanceScript()->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_EPOCH_KILLED);
if (Creature* taretha = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(DATA_TARETHA_GUID)))
taretha->AI()->DoAction(me->GetEntry());
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{ {
case EVENT_SPELL_SAND_BREATH: Talk(SAY_BREATH);
if (roll_chance_i(50))
Talk(SAY_BREATH);
me->CastSpell(me->GetVictim(), SPELL_SAND_BREATH, false);
events.ScheduleEvent(EVENT_SPELL_SAND_BREATH, 20000);
break;
case EVENT_SPELL_IMPENDING_DEATH:
me->CastSpell(me->GetVictim(), SPELL_IMPENDING_DEATH, false);
events.ScheduleEvent(EVENT_SPELL_IMPENDING_DEATH, 30000);
break;
case EVENT_SPELL_WING_BUFFET:
me->CastSpell(me, SPELL_WING_BUFFET, false);
events.ScheduleEvent(EVENT_SPELL_WING_BUFFET, 30000);
break;
case EVENT_SPELL_DISRUPTION:
me->CastSpell(me, SPELL_MAGIC_DISRUPTION_AURA, false);
events.ScheduleEvent(EVENT_SPELL_DISRUPTION, 30000);
break;
} }
DoCastVictim(SPELL_SAND_BREATH);
context.Repeat(20s);
}).Schedule(2s, [this](TaskContext context)
{
DoCastVictim(SPELL_IMPENDING_DEATH);
context.Repeat(30s);
}).Schedule(20s, [this](TaskContext context)
{
DoCastSelf(SPELL_MAGIC_DISRUPTION_AURA);
context.Repeat(30s);
}).Schedule(14s, [this](TaskContext context)
{
DoCastSelf(SPELL_WING_BUFFET);
context.Repeat(30s);
});
}
DoMeleeAttackIfReady(); void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
Talk(SAY_SLAY);
}
void JustDied(Unit* killer) override
{
if (killer && killer == me)
return;
_JustDied();
Talk(SAY_DEATH);
me->GetInstanceScript()->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_EPOCH_KILLED);
if (Creature* taretha = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(DATA_TARETHA_GUID)))
{
taretha->AI()->DoAction(me->GetEntry());
} }
}; }
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
DoMeleeAttackIfReady();
}
}; };
void AddSC_boss_epoch_hunter() void AddSC_boss_epoch_hunter()
{ {
new boss_epoch_hunter(); RegisterOldHillsbradCreatureAI(boss_epoch_hunter);
} }
@@ -21,159 +21,151 @@
#include "SmartScriptMgr.h" #include "SmartScriptMgr.h"
#include "old_hillsbrad.h" #include "old_hillsbrad.h"
enum LieutenantDrake enum Text
{ {
SAY_ENTER = 0, SAY_ENTER = 0,
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_SLAY = 2, SAY_SLAY = 2,
SAY_MORTAL = 3, SAY_MORTAL = 3,
SAY_SHOUT = 4, SAY_SHOUT = 4,
SAY_DEATH = 5, SAY_DEATH = 5
SPELL_WHIRLWIND = 31909,
SPELL_EXPLODING_SHOT = 33792,
SPELL_HAMSTRING = 9080,
SPELL_MORTAL_STRIKE = 31911,
SPELL_FRIGHTENING_SHOUT = 33789,
EVENT_WHIRLWIND = 1,
EVENT_FRIGHTENING_SHOUT = 2,
EVENT_MORTAL_STRIKE = 3,
EVENT_HAMSTRING = 4,
EVENT_EXPLODING_SHOT = 5
}; };
class boss_lieutenant_drake : public CreatureScript enum Spells
{ {
public: SPELL_WHIRLWIND = 31909,
boss_lieutenant_drake() : CreatureScript("boss_lieutenant_drake") { } SPELL_EXPLODING_SHOT = 33792,
SPELL_HAMSTRING = 9080,
SPELL_MORTAL_STRIKE = 31911,
SPELL_FRIGHTENING_SHOUT = 33789
};
CreatureAI* GetAI(Creature* creature) const override struct boss_lieutenant_drake : public BossAI
{
boss_lieutenant_drake(Creature* creature) : BossAI(creature, DATA_LIEUTENANT_DRAKE)
{ {
return GetOldHillsbradAI<boss_lieutenant_drakeAI>(creature); scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
} }
struct boss_lieutenant_drakeAI : public ScriptedAI void InitializeAI() override
{ {
boss_lieutenant_drakeAI(Creature* creature) : ScriptedAI(creature) runSecondPath = false;
pathId = me->GetEntry() * 10;
me->GetMotionMaster()->MovePath(pathId, false);
}
void Reset() override
{
_Reset();
}
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
Talk(SAY_AGGRO);
scheduler.Schedule(4s, [this](TaskContext context)
{ {
DoCastSelf(SPELL_WHIRLWIND);
context.Repeat(25s);
}).Schedule(14s, [this](TaskContext context)
{
if (roll_chance_i(40))
{
Talk(SAY_SHOUT);
}
DoCastSelf(SPELL_FRIGHTENING_SHOUT);
context.Repeat(25s);
}).Schedule(9s, [this](TaskContext context)
{
if (roll_chance_i(40))
{
Talk(SAY_MORTAL);
}
DoCastVictim(SPELL_MORTAL_STRIKE);
context.Repeat(10s);
}).Schedule(18s, [this](TaskContext context)
{
DoCastVictim(SPELL_HAMSTRING);
context.Repeat(25s);
}).Schedule(1s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 40.0f))
{
DoCast(target, SPELL_EXPLODING_SHOT);
}
context.Repeat(25s);
});
}
void KilledUnit(Unit* victim) override
{
if (victim->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_SLAY);
}
}
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
if (InstanceScript* instance = me->GetInstanceScript())
{
instance->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_DRAKE_KILLED);
}
}
void MovementInform(uint32 type, uint32 point) override
{
if (type != WAYPOINT_MOTION_TYPE)
{
return;
} }
void InitializeAI() override if (pathId == me->GetEntry() * 10)
{
switch (point)
{
case 7:
Talk(SAY_ENTER);
break;
case 10:
pathId = (me->GetEntry() * 10) + 1;
runSecondPath = true;
break;
default:
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (runSecondPath)
{ {
runSecondPath = false; runSecondPath = false;
pathId = me->GetEntry() * 10; me->GetMotionMaster()->MovePath(pathId, true);
me->GetMotionMaster()->MovePath(pathId, false);
} }
void Reset() override if (!UpdateVictim())
{ return;
events.Reset();
}
void JustEngagedWith(Unit* /*who*/) override scheduler.Update(diff);
{ if (me->HasUnitState(UNIT_STATE_CASTING))
Talk(SAY_AGGRO); return;
events.ScheduleEvent(EVENT_WHIRLWIND, 4000); DoMeleeAttackIfReady();
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 14000); }
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 9000);
events.ScheduleEvent(EVENT_HAMSTRING, 18000);
events.ScheduleEvent(EVENT_EXPLODING_SHOT, 1000);
}
void KilledUnit(Unit* victim) override private:
{ uint32 pathId;
if (victim->GetTypeId() == TYPEID_PLAYER) bool runSecondPath;
Talk(SAY_SLAY);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
if (InstanceScript* instance = me->GetInstanceScript())
instance->SetData(DATA_ESCORT_PROGRESS, ENCOUNTER_PROGRESS_DRAKE_KILLED);
}
void MovementInform(uint32 type, uint32 point) override
{
if (type != WAYPOINT_MOTION_TYPE)
{
return;
}
if (pathId == me->GetEntry() * 10)
{
switch (point)
{
case 7:
Talk(SAY_ENTER);
break;
case 10:
pathId = (me->GetEntry() * 10) + 1;
runSecondPath = true;
break;
default:
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (runSecondPath)
{
runSecondPath = false;
me->GetMotionMaster()->MovePath(pathId, true);
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
case EVENT_WHIRLWIND:
me->CastSpell(me, SPELL_WHIRLWIND, false);
events.ScheduleEvent(EVENT_WHIRLWIND, 25000);
break;
case EVENT_EXPLODING_SHOT:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 40.0f))
me->CastSpell(target, SPELL_EXPLODING_SHOT, false);
events.ScheduleEvent(EVENT_EXPLODING_SHOT, 25000);
break;
case EVENT_MORTAL_STRIKE:
if (roll_chance_i(40))
Talk(SAY_MORTAL);
me->CastSpell(me->GetVictim(), SPELL_MORTAL_STRIKE, false);
events.ScheduleEvent(EVENT_MORTAL_STRIKE, 10000);
break;
case EVENT_FRIGHTENING_SHOUT:
if (roll_chance_i(40))
Talk(SAY_SHOUT);
me->CastSpell(me, SPELL_FRIGHTENING_SHOUT, false);
events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 25000);
break;
case EVENT_HAMSTRING:
me->CastSpell(me->GetVictim(), SPELL_HAMSTRING, false);
events.ScheduleEvent(EVENT_HAMSTRING, 25000);
break;
}
DoMeleeAttackIfReady();
}
private:
EventMap events;
uint32 pathId;
bool runSecondPath;
};
}; };
void AddSC_boss_lieutenant_drake() void AddSC_boss_lieutenant_drake()
{ {
new boss_lieutenant_drake(); RegisterOldHillsbradCreatureAI(boss_lieutenant_drake);
} }
@@ -27,6 +27,9 @@
enum DataIds enum DataIds
{ {
DATA_ESCORT_PROGRESS = 0, DATA_ESCORT_PROGRESS = 0,
DATA_LIEUTENANT_DRAKE = 1,
DATA_CAPTAIN_SKARLOC = 2,
DATA_EPOCH_HUNTER = 3,
DATA_BOMBS_PLACED = 10, DATA_BOMBS_PLACED = 10,
DATA_THRALL_REPOSITION = 11, DATA_THRALL_REPOSITION = 11,
@@ -95,4 +98,6 @@ inline AI* GetOldHillsbradAI(T* obj)
return GetInstanceAI<AI>(obj, OldHillsbradScriptName); return GetInstanceAI<AI>(obj, OldHillsbradScriptName);
} }
#define RegisterOldHillsbradCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetOldHillsbradAI)
#endif #endif
@@ -19,14 +19,17 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "the_black_morass.h" #include "the_black_morass.h"
enum Enums enum Text
{ {
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_BANISH = 2, SAY_BANISH = 2,
SAY_SLAY = 3, SAY_SLAY = 3,
SAY_DEATH = 4, SAY_DEATH = 4,
EMOTE_FRENZY = 5, EMOTE_FRENZY = 5
};
enum Spells
{
SPELL_CLEAVE = 40504, SPELL_CLEAVE = 40504,
SPELL_TIME_STOP = 31422, SPELL_TIME_STOP = 31422,
SPELL_ENRAGE = 37605, SPELL_ENRAGE = 37605,
@@ -19,19 +19,21 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "the_black_morass.h" #include "the_black_morass.h"
enum Enums enum Text
{ {
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_BANISH = 2, SAY_BANISH = 2,
SAY_SLAY = 3, SAY_SLAY = 3,
SAY_DEATH = 4, SAY_DEATH = 4
};
enum Spells
{
SPELL_ARCANE_BLAST = 31457, SPELL_ARCANE_BLAST = 31457,
SPELL_ARCANE_DISCHARGE = 31472, SPELL_ARCANE_DISCHARGE = 31472,
SPELL_TIME_LAPSE = 31467, SPELL_TIME_LAPSE = 31467,
SPELL_ATTRACTION = 38540, SPELL_ATTRACTION = 38540,
SPELL_BANISH_DRAGON_HELPER = 31550
SPELL_BANISH_DRAGON_HELPER = 31550,
}; };
struct boss_chrono_lord_deja : public BossAI struct boss_chrono_lord_deja : public BossAI
@@ -19,13 +19,16 @@
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "the_black_morass.h" #include "the_black_morass.h"
enum Enums enum Text
{ {
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_BANISH = 2, SAY_BANISH = 2,
SAY_SLAY = 3, SAY_SLAY = 3,
SAY_DEATH = 4, SAY_DEATH = 4
};
enum Spells
{
SPELL_HASTEN = 31458, SPELL_HASTEN = 31458,
SPELL_MORTAL_WOUND = 31464, SPELL_MORTAL_WOUND = 31464,
SPELL_WING_BUFFET = 31475, SPELL_WING_BUFFET = 31475,
@@ -46,7 +49,6 @@ struct boss_temporus : public BossAI
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
_JustEngagedWith(); _JustEngagedWith();
scheduler.Schedule(12s, [this](TaskContext context) scheduler.Schedule(12s, [this](TaskContext context)
{ {
DoCastSelf(SPELL_HASTEN); DoCastSelf(SPELL_HASTEN);
@@ -69,7 +71,6 @@ struct boss_temporus : public BossAI
context.Repeat(30s); context.Repeat(30s);
}); });
} }
OwnTalk(SAY_AGGRO); OwnTalk(SAY_AGGRO);
} }
@@ -98,7 +99,6 @@ struct boss_temporus : public BossAI
return; return;
} }
} }
ScriptedAI::MoveInLineOfSight(who); ScriptedAI::MoveInLineOfSight(who);
} }
}; };
@@ -111,6 +111,16 @@ struct boss_grand_warlock_nethekurse : public BossAI
}); });
instance->SetBossState(DATA_NETHEKURSE, NOT_STARTED); instance->SetBossState(DATA_NETHEKURSE, NOT_STARTED);
if (!_canAggro)
{
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
}
void JustReachedHome() override
{
me->GetMotionMaster()->Initialize();
} }
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
@@ -121,7 +131,7 @@ struct boss_grand_warlock_nethekurse : public BossAI
void SetData(uint32 data, uint32 value) override void SetData(uint32 data, uint32 value) override
{ {
if (data != SETDATA_DATA) if (data != SETDATA_DATA || me->IsInCombat())
return; return;
if (value == SETDATA_PEON_AGGRO && PeonEngagedCount <= 4) if (value == SETDATA_PEON_AGGRO && PeonEngagedCount <= 4)
@@ -137,9 +147,13 @@ struct boss_grand_warlock_nethekurse : public BossAI
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/) scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
{ {
me->HandleEmoteCommand(EMOTE_ONESHOT_APPLAUD); me->HandleEmoteCommand(EMOTE_ONESHOT_APPLAUD);
me->GetMotionMaster()->Initialize();
Talk(SAY_PEON_DIES); Talk(SAY_PEON_DIES);
scheduler.Schedule(1s, GROUP_RP, [this](TaskContext /*context*/)
{
me->GetMotionMaster()->Initialize();
});
if (++PeonKilledCount == 4) if (++PeonKilledCount == 4)
{ {
Talk(SAY_INTRO_2); Talk(SAY_INTRO_2);
@@ -161,16 +175,14 @@ struct boss_grand_warlock_nethekurse : public BossAI
me->GetMotionMaster()->MoveIdle(); me->GetMotionMaster()->MoveIdle();
me->SetFacingTo(4.572762489318847656f); me->SetFacingTo(4.572762489318847656f);
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/) scheduler.Schedule(2500ms, GROUP_RP, [this](TaskContext /*context*/)
{ {
scheduler.Schedule(2500ms, GROUP_RP, [this](TaskContext /*context*/) PeonRoleplay roleplayData = Acore::Containers::SelectRandomContainerElement(PeonRoleplayData);
{ DoCast(me, roleplayData.spellId);
PeonRoleplay roleplayData = Acore::Containers::SelectRandomContainerElement(PeonRoleplayData); Talk(roleplayData.textId);
DoCast(me, roleplayData.spellId); me->GetMotionMaster()->Initialize();
Talk(roleplayData.textId);
me->GetMotionMaster()->Initialize();
});
}); });
context.Repeat(16400ms, 28500ms); context.Repeat(16400ms, 28500ms);
}); });
} }
@@ -225,6 +237,19 @@ struct boss_grand_warlock_nethekurse : public BossAI
} }
else if (action == ACTION_START_INTRO) else if (action == ACTION_START_INTRO)
{ {
// Hack: Prevent from pulling from behind door
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
_canAggro = true;
std::list<Creature*> creatureList;
GetCreatureListWithEntryInGrid(creatureList, me, NPC_PEON, 60.0f);
for (Creature* creature : creatureList)
{
if (creature)
{
creature->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
}
}
IntroRP(); IntroRP();
} }
} }
@@ -246,6 +271,7 @@ struct boss_grand_warlock_nethekurse : public BossAI
private: private:
uint8 PeonEngagedCount = 0; uint8 PeonEngagedCount = 0;
uint8 PeonKilledCount = 0; uint8 PeonKilledCount = 0;
bool _canAggro = false;
}; };
class spell_tsh_shadow_bolt : public SpellScript class spell_tsh_shadow_bolt : public SpellScript
@@ -126,6 +126,8 @@ struct boss_warchief_kargath_bladefist : public BossAI
{ {
Talk(SAY_DEATH); Talk(SAY_DEATH);
BossAI::JustDied(killer); BossAI::JustDied(killer);
if (Creature* warchiefPortal = instance->GetCreature(DATA_WARCHIEF_PORTAL))
warchiefPortal->AI()->SetData(DATA_RESET_FIGHT, 0);
if (instance) if (instance)
{ {
if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER))) if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER)))
@@ -17,6 +17,7 @@
#include "CreatureTextMgr.h" #include "CreatureTextMgr.h"
#include "InstanceScript.h" #include "InstanceScript.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "shattered_halls.h" #include "shattered_halls.h"
@@ -181,6 +182,221 @@ public:
}; };
}; };
enum ScoutMisc
{
SAY_INVADERS_BREACHED = 0,
SAY_PORUNG_ARCHERS = 0,
SAY_PORUNG_READY = 1,
SAY_PORUNG_AIM = 2,
SAY_PORUNG_FIRE = 3,
SPELL_CLEAR_ALL = 28471,
SPELL_SUMMON_ZEALOTS = 30976,
SPELL_SHOOT_FLAME_ARROW = 30952,
POINT_SCOUT_WP_END = 3,
SET_DATA_ARBITRARY_VALUE = 1
};
struct npc_shattered_hand_scout : public ScriptedAI
{
npc_shattered_hand_scout(Creature* creature) : ScriptedAI(creature) { }
void Reset() override
{
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
void MoveInLineOfSight(Unit* who) override
{
if (!me->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE) && me->IsWithinDist2d(who, 50.0f) && who->GetPositionZ() > -3.0f
&& who->IsPlayer())
{
me->SetReactState(REACT_PASSIVE);
DoCastSelf(SPELL_CLEAR_ALL);
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
Talk(SAY_INVADERS_BREACHED);
me->GetMotionMaster()->MovePath(me->GetEntry() * 10, false);
_firstZealots.clear();
std::list<Creature*> creatureList;
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SH_ZEALOT, 15.0f);
for (Creature* creature : creatureList)
{
if (creature)
{
_firstZealots.insert(creature->GetGUID());
}
}
}
}
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*type*/, SpellSchoolMask /*school*/) override
{
if (damage >= me->GetHealth())
{
// Let creature fall to 1 HP but prevent it from dying.
damage = me->GetHealth() - 1;
}
}
void MovementInform(uint32 type, uint32 point) override
{
if (type == WAYPOINT_MOTION_TYPE && point == POINT_SCOUT_WP_END)
{
me->SetVisible(false);
if (Creature* porung = GetPorung())
{
porung->setActive(true);
porung->AI()->DoCastAOE(SPELL_SUMMON_ZEALOTS);
porung->AI()->Talk(SAY_PORUNG_ARCHERS);
_scheduler.Schedule(45s, [this](TaskContext context)
{
if (Creature* porung = GetPorung())
{
porung->AI()->DoCastAOE(SPELL_SUMMON_ZEALOTS);
}
context.Repeat();
});
}
_scheduler.Schedule(1s, [this](TaskContext /*context*/)
{
_zealotGUIDs.clear();
std::list<Creature*> creatureList;
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SH_ZEALOT, 100.0f);
for (Creature* creature : creatureList)
{
if (creature)
{
creature->AI()->SetData(SET_DATA_ARBITRARY_VALUE, SET_DATA_ARBITRARY_VALUE);
_zealotGUIDs.insert(creature->GetGUID());
}
}
for (auto const& guid : _firstZealots)
{
if (Creature* zealot = ObjectAccessor::GetCreature(*me, guid))
{
zealot->SetInCombatWithZone();
}
}
if (Creature* porung = GetPorung())
{
porung->AI()->Talk(SAY_PORUNG_READY, 3600ms);
porung->AI()->Talk(SAY_PORUNG_AIM, 4800ms);
}
_scheduler.Schedule(5800ms, [this](TaskContext /*context*/)
{
std::list<Creature*> creatureList;
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SH_ARCHER, 100.0f);
for (Creature* creature : creatureList)
{
if (creature)
{
creature->AI()->DoCastAOE(SPELL_SHOOT_FLAME_ARROW);
}
}
if (Creature* porung = GetPorung())
{
porung->AI()->Talk(SAY_PORUNG_FIRE, 200ms);
}
_scheduler.Schedule(2s, 9750ms, [this](TaskContext context)
{
if (FireArrows())
{
context.Repeat();
}
if (!me->SelectNearestPlayer(250.0f))
{
me->SetVisible(true);
me->DespawnOrUnsummon(5s, 5s);
for (auto const& guid : _zealotGUIDs)
{
if (Creature* zealot = ObjectAccessor::GetCreature(*me, guid))
{
if (zealot->IsAlive())
{
zealot->DespawnOrUnsummon(5s, 5s);
}
else
{
zealot->Respawn(true);
}
}
}
for (auto const& guid : _firstZealots)
{
if (Creature* zealot = ObjectAccessor::GetCreature(*me, guid))
{
if (zealot->IsAlive())
{
zealot->DespawnOrUnsummon(5s, 5s);
}
else
{
zealot->Respawn(true);
}
}
}
_scheduler.CancelAll();
}
});
});
});
}
}
void UpdateAI(uint32 diff) override
{
_scheduler.Update(diff);
}
bool FireArrows()
{
std::list<Creature*> creatureList;
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SH_ARCHER, 100.0f);
if (creatureList.empty())
{
return false;
}
for (Creature* creature : creatureList)
{
if (creature)
{
creature->AI()->DoCastAOE(SPELL_SHOOT_FLAME_ARROW);
}
}
return true;
}
Creature* GetPorung()
{
return me->FindNearestCreature(IsHeroic() ? NPC_PORUNG : NPC_BLOOD_GUARD, 100.0f);
}
private:
TaskScheduler _scheduler;
GuidSet _zealotGUIDs;
GuidSet _firstZealots;
};
class spell_tsh_shoot_flame_arrow : public SpellScriptLoader class spell_tsh_shoot_flame_arrow : public SpellScriptLoader
{ {
public: public:
@@ -192,6 +408,15 @@ public:
void FilterTargets(std::list<WorldObject*>& unitList) void FilterTargets(std::list<WorldObject*>& unitList)
{ {
Unit* caster = GetCaster();
if (!caster)
return;
unitList.remove_if([&](WorldObject* target) -> bool
{
return !target->SelectNearestPlayer(15.0f);
});
Acore::Containers::RandomResize(unitList, 1); Acore::Containers::RandomResize(unitList, 1);
} }
@@ -223,7 +448,12 @@ public:
bool OnTrigger(Player* player, AreaTrigger const* /*areaTrigger*/) override bool OnTrigger(Player* player, AreaTrigger const* /*areaTrigger*/) override
{ {
if (InstanceScript* instanceScript = player->GetInstanceScript()) if (InstanceScript* instanceScript = player->GetInstanceScript())
instanceScript->SetData(DATA_ENTERED_ROOM, DATA_ENTERED_ROOM); {
if (player->GetMap()->IsHeroic())
{
instanceScript->SetData(DATA_ENTERED_ROOM, DATA_ENTERED_ROOM);
}
}
return true; return true;
} }
@@ -232,6 +462,7 @@ public:
void AddSC_instance_shattered_halls() void AddSC_instance_shattered_halls()
{ {
new instance_shattered_halls(); new instance_shattered_halls();
RegisterShatteredHallsCreatureAI(npc_shattered_hand_scout);
new spell_tsh_shoot_flame_arrow(); new spell_tsh_shoot_flame_arrow();
new at_shattered_halls_execution(); new at_shattered_halls_execution();
} }
@@ -45,6 +45,11 @@ enum CreatureIds
{ {
NPC_GRAND_WARLOCK_NETHEKURSE = 16807, NPC_GRAND_WARLOCK_NETHEKURSE = 16807,
NPC_FEL_ORC_CONVERT = 17083, NPC_FEL_ORC_CONVERT = 17083,
NPC_PORUNG = 20923,
NPC_BLOOD_GUARD = 17461,
NPC_SH_ZEALOT = 17462,
NPC_SH_ARCHER = 17427,
// Warchief Kargath // Warchief Kargath
NPC_WARCHIEF_KARGATH = 16808, NPC_WARCHIEF_KARGATH = 16808,
NPC_WARCHIEF_PORTAL = 17611, NPC_WARCHIEF_PORTAL = 17611,
@@ -22,13 +22,13 @@
enum Texts enum Texts
{ {
SAY_INTRO = 0, SAY_INTRO = 0,
SAY_AGGRO = 1, SAY_AGGRO = 1,
SAY_SURPREME = 2, SAY_SURPREME = 2,
SAY_KILL = 3, SAY_KILL = 3,
SAY_DEATH = 4, SAY_DEATH = 4,
EMOTE_FRENZY = 5, EMOTE_FRENZY = 5,
SAY_RAND = 6 SAY_RAND = 6
}; };
enum Spells enum Spells
@@ -42,19 +42,7 @@ enum Spells
SPELL_ENRAGE = 32964, SPELL_ENRAGE = 32964,
SPELL_CAPTURE_SOUL = 32966, SPELL_CAPTURE_SOUL = 32966,
SPELL_TWISTED_REFLECTION = 21063, SPELL_TWISTED_REFLECTION = 21063,
SPELL_BERSERK = 32965, SPELL_BERSERK = 32965
};
enum Events
{
EVENT_SHADOW_VOLLEY = 1,
EVENT_CLEAVE = 2,
EVENT_THUNDERCLAP = 3,
EVENT_VOID_BOLT = 4,
EVENT_MARK_OF_KAZZAK = 5,
EVENT_ENRAGE = 6,
EVENT_TWISTED_REFLECTION = 7,
EVENT_BERSERK = 8
}; };
class boss_doomlord_kazzak : public CreatureScript class boss_doomlord_kazzak : public CreatureScript
@@ -64,21 +52,11 @@ public:
struct boss_doomlordkazzakAI : public ScriptedAI struct boss_doomlordkazzakAI : public ScriptedAI
{ {
boss_doomlordkazzakAI(Creature* creature) : ScriptedAI(creature) boss_doomlordkazzakAI(Creature* creature) : ScriptedAI(creature) {}
{
}
void Reset() override void Reset() override
{ {
_events.Reset(); _inBerserk = false;
_events.ScheduleEvent(EVENT_SHADOW_VOLLEY, urand(6000, 10000));
_events.ScheduleEvent(EVENT_CLEAVE, 7000);
_events.ScheduleEvent(EVENT_THUNDERCLAP, urand(14000, 18000));
_events.ScheduleEvent(EVENT_VOID_BOLT, 30000);
_events.ScheduleEvent(EVENT_MARK_OF_KAZZAK, 25000);
_events.ScheduleEvent(EVENT_ENRAGE, 60000);
_events.ScheduleEvent(EVENT_TWISTED_REFLECTION, 33000);
_events.ScheduleEvent(EVENT_BERSERK, 180000);
} }
void JustRespawned() override void JustRespawned() override
@@ -89,17 +67,58 @@ public:
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
_scheduler.Schedule(6s, 10s, [this](TaskContext context)
{
DoCastVictim(SPELL_SHADOW_VOLLEY);
context.Repeat(4s, 6s);
}).Schedule(7s, [this](TaskContext context)
{
DoCastVictim(SPELL_CLEAVE);
context.Repeat(8s, 12s);
}).Schedule(14s, 18s, [this](TaskContext context)
{
DoCastVictim(SPELL_THUNDERCLAP);
context.Repeat(10s, 14s);
}).Schedule(30s, [this](TaskContext context)
{
DoCastVictim(SPELL_VOID_BOLT);
context.Repeat(15s, 18s);
}).Schedule(25s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, POWER_MANA, 100.0f, true)))
{
DoCast(target, SPELL_MARK_OF_KAZZAK);
}
context.Repeat(20s);
}).Schedule(1min, [this](TaskContext context)
{
Talk(EMOTE_FRENZY);
DoCastSelf(SPELL_ENRAGE);
context.Repeat(30s);
}).Schedule(33s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
{
DoCast(target, SPELL_TWISTED_REFLECTION);
}
context.Repeat(15s);
}).Schedule(3min, [this](TaskContext /*context*/)
{
if (!_inBerserk)
{
DoCastSelf(SPELL_BERSERK);
_inBerserk = true;
}
});
} }
void KilledUnit(Unit* victim) override void KilledUnit(Unit* victim) override
{ {
// When Kazzak kills a player (not pets/totems), he regens some health if (victim->GetTypeId() == TYPEID_PLAYER)
if (victim->GetTypeId() != TYPEID_PLAYER) {
return; Talk(SAY_KILL);
DoCastSelf(SPELL_CAPTURE_SOUL);
DoCast(me, SPELL_CAPTURE_SOUL); }
Talk(SAY_KILL);
} }
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
@@ -109,63 +128,19 @@ public:
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
{ {
// Return since we have no target
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
_events.Update(diff); _scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING)) if (me->HasUnitState(UNIT_STATE_CASTING))
return; return;
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SHADOW_VOLLEY:
DoCastVictim(SPELL_SHADOW_VOLLEY);
_events.ScheduleEvent(EVENT_SHADOW_VOLLEY, urand(4000, 6000));
break;
case EVENT_CLEAVE:
DoCastVictim(SPELL_CLEAVE);
_events.ScheduleEvent(EVENT_CLEAVE, urand(8000, 12000));
break;
case EVENT_THUNDERCLAP:
DoCastVictim(SPELL_THUNDERCLAP);
_events.ScheduleEvent(EVENT_THUNDERCLAP, urand(10000, 14000));
break;
case EVENT_VOID_BOLT:
DoCastVictim(SPELL_VOID_BOLT);
_events.ScheduleEvent(EVENT_VOID_BOLT, urand(15000, 18000));
break;
case EVENT_MARK_OF_KAZZAK:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, POWER_MANA, 100.0f, true)))
DoCast(target, SPELL_MARK_OF_KAZZAK);
_events.ScheduleEvent(EVENT_MARK_OF_KAZZAK, 20000);
break;
case EVENT_ENRAGE:
Talk(EMOTE_FRENZY);
DoCast(me, SPELL_ENRAGE);
_events.ScheduleEvent(EVENT_ENRAGE, 30000);
break;
case EVENT_TWISTED_REFLECTION:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true))
DoCast(target, SPELL_TWISTED_REFLECTION);
_events.ScheduleEvent(EVENT_TWISTED_REFLECTION, 15000);
break;
case EVENT_BERSERK:
DoCast(me, SPELL_BERSERK);
break;
default:
break;
}
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
private: private:
EventMap _events; TaskScheduler _scheduler;
bool _inBerserk;
}; };
CreatureAI* GetAI(Creature* creature) const override CreatureAI* GetAI(Creature* creature) const override
@@ -191,18 +166,18 @@ public:
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{ {
if (Unit* owner = GetUnitOwner()) if (Unit* owner = GetUnitOwner())
{
amount = CalculatePct(owner->GetPower(POWER_MANA), 5); amount = CalculatePct(owner->GetPower(POWER_MANA), 5);
}
} }
void OnPeriodic(AuraEffect const* aurEff) void OnPeriodic(AuraEffect const* aurEff)
{ {
Unit* target = GetTarget(); Unit* target = GetTarget();
if (target->GetPower(POWER_MANA) == 0) if (target->GetPower(POWER_MANA) == 0)
{ {
target->CastSpell(target, SPELL_MARK_OF_KAZZAK_DAMAGE, true, nullptr, aurEff); target->CastSpell(target, SPELL_MARK_OF_KAZZAK_DAMAGE, true, nullptr, aurEff);
// Remove aura SetDuration(0); // Remove aura
SetDuration(0);
} }
} }
+54 -71
View File
@@ -20,11 +20,11 @@
enum Texts enum Texts
{ {
SAY_AGGRO = 0, SAY_AGGRO = 0,
SAY_EARTHQUAKE = 1, SAY_EARTHQUAKE = 1,
SAY_OVERRUN = 2, SAY_OVERRUN = 2,
SAY_SLAY = 3, SAY_SLAY = 3,
SAY_DEATH = 4 SAY_DEATH = 4
}; };
enum Spells enum Spells
@@ -38,15 +38,6 @@ enum Spells
SPELL_AURA_DEATH = 37131 SPELL_AURA_DEATH = 37131
}; };
enum Events
{
EVENT_ENRAGE = 1,
EVENT_ARMOR = 2,
EVENT_CHAIN = 3,
EVENT_QUAKE = 4,
EVENT_OVERRUN = 5
};
class boss_doomwalker : public CreatureScript class boss_doomwalker : public CreatureScript
{ {
public: public:
@@ -54,29 +45,23 @@ public:
struct boss_doomwalkerAI : public ScriptedAI struct boss_doomwalkerAI : public ScriptedAI
{ {
boss_doomwalkerAI(Creature* creature) : ScriptedAI(creature) boss_doomwalkerAI(Creature* creature) : ScriptedAI(creature) {}
{
}
void Reset() override void Reset() override
{ {
_events.Reset();
_events.ScheduleEvent(EVENT_ENRAGE, 0);
_events.ScheduleEvent(EVENT_ARMOR, urand(5000, 13000));
_events.ScheduleEvent(EVENT_CHAIN, urand(10000, 30000));
_events.ScheduleEvent(EVENT_QUAKE, urand(25000, 35000));
_events.ScheduleEvent(EVENT_OVERRUN, urand(30000, 45000));
_inEnrage = false; _inEnrage = false;
} }
void KilledUnit(Unit* victim) override void KilledUnit(Unit* victim) override
{ {
victim->CastSpell(victim, SPELL_MARK_DEATH, 0); victim->CastSpell(victim, SPELL_MARK_DEATH, 0);
if (urand(0, 4)) if (urand(0, 4))
return; return;
Talk(SAY_SLAY); if (victim->GetTypeId() == TYPEID_PLAYER)
{
Talk(SAY_SLAY);
}
} }
void JustDied(Unit* /*killer*/) override void JustDied(Unit* /*killer*/) override
@@ -87,13 +72,55 @@ public:
void JustEngagedWith(Unit* /*who*/) override void JustEngagedWith(Unit* /*who*/) override
{ {
Talk(SAY_AGGRO); Talk(SAY_AGGRO);
_scheduler.Schedule(1ms, [this](TaskContext context)
{
if (!HealthAbovePct(20))
{
DoCastSelf(SPELL_ENRAGE);
context.Repeat(6s);
_inEnrage = true;
}
}).Schedule(5s, 13s, [this](TaskContext context)
{
DoCastVictim(SPELL_SUNDER_ARMOR);
context.Repeat(10s, 25s);
}).Schedule(10s, 30s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 0.0f, true))
{
DoCast(target, SPELL_CHAIN_LIGHTNING);
}
context.Repeat(7s, 27s);
}).Schedule(25s, 35s, [this](TaskContext context)
{
if (urand(0, 1))
{
return;
}
Talk(SAY_EARTHQUAKE);
if (_inEnrage) // avoid enrage + earthquake
{
me->RemoveAurasDueToSpell(SPELL_ENRAGE);
}
DoCastAOE(SPELL_EARTHQUAKE);
context.Repeat(30s, 55s);
}).Schedule(30s, 45s, [this](TaskContext context)
{
Talk(SAY_OVERRUN);
DoCastVictim(SPELL_OVERRUN);
context.Repeat(25s, 40s);
});
} }
void MoveInLineOfSight(Unit* who) override void MoveInLineOfSight(Unit* who) override
{ {
if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsValidAttackTarget(who)) if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsValidAttackTarget(who))
{
if (who->HasAura(SPELL_MARK_DEATH) && !who->HasAura(27827)) // Spirit of Redemption if (who->HasAura(SPELL_MARK_DEATH) && !who->HasAura(27827)) // Spirit of Redemption
{
who->CastSpell(who, SPELL_AURA_DEATH, 1); who->CastSpell(who, SPELL_AURA_DEATH, 1);
}
}
} }
void UpdateAI(uint32 diff) override void UpdateAI(uint32 diff) override
@@ -101,59 +128,15 @@ public:
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
_events.Update(diff); _scheduler.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING)) if (me->HasUnitState(UNIT_STATE_CASTING))
return; return;
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_ENRAGE:
if (!HealthAbovePct(20))
{
DoCast(me, SPELL_ENRAGE);
_events.ScheduleEvent(EVENT_ENRAGE, 6000);
_inEnrage = true;
}
break;
case EVENT_OVERRUN:
Talk(SAY_OVERRUN);
DoCastVictim(SPELL_OVERRUN);
_events.ScheduleEvent(EVENT_OVERRUN, urand(25000, 40000));
break;
case EVENT_QUAKE:
if (urand(0, 1))
return;
Talk(SAY_EARTHQUAKE);
//remove enrage before casting earthquake because enrage + earthquake = 16000dmg over 8sec and all dead
if (_inEnrage)
me->RemoveAurasDueToSpell(SPELL_ENRAGE);
DoCast(me, SPELL_EARTHQUAKE);
_events.ScheduleEvent(EVENT_QUAKE, urand(30000, 55000));
break;
case EVENT_CHAIN:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 0.0f, true))
DoCast(target, SPELL_CHAIN_LIGHTNING);
_events.ScheduleEvent(EVENT_CHAIN, urand(7000, 27000));
break;
case EVENT_ARMOR:
DoCastVictim(SPELL_SUNDER_ARMOR);
_events.ScheduleEvent(EVENT_ARMOR, urand(10000, 25000));
break;
default:
break;
}
}
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
} }
private: private:
EventMap _events; TaskScheduler _scheduler;
bool _inEnrage; bool _inEnrage;
}; };
@@ -15,20 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* ScriptData #include "GameObjectAI.h"
SDName: Hellfire_Peninsula
SD%Complete: 100
SDComment: Quest support: 9375, 9410, 9418, 10129, 10146, 10162, 10163, 10340, 10346, 10347, 10382 (Special flight paths) "Needs update"
SDCategory: Hellfire Peninsula
EndScriptData */
/* ContentData
npc_aeranas
npc_ancestral_wolf
npc_wounded_blood_elf
npc_fel_guard_hound
EndContentData */
#include "Player.h" #include "Player.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
@@ -403,6 +390,62 @@ public:
} }
}; };
enum Beacon
{
NPC_STONESCHYE_WHELP = 16927,
};
class go_beacon : public GameObjectScript
{
public:
go_beacon() : GameObjectScript("go_beacon") { }
struct go_beaconAI : public GameObjectAI
{
go_beaconAI(GameObject* gameObject) : GameObjectAI(gameObject) { }
std::list<Creature*> creatureList;
void OnStateChanged(uint32 state, Unit* /*unit*/) override
{
if (state == GO_ACTIVATED)
{
me->GetCreaturesWithEntryInRange(creatureList, 40, NPC_STONESCHYE_WHELP);
{
for (Creature* whelp : creatureList)
{
if (whelp->IsAlive() && !whelp->IsInCombat() && whelp->GetMotionMaster()->GetCurrentMovementGeneratorType() != HOME_MOTION_TYPE)
{
whelp->GetMotionMaster()->MovePoint(0, me->GetNearPosition(4.0f, whelp->GetOrientation()));
}
}
}
}
else if (state == GO_JUST_DEACTIVATED)
{
{
for (Creature* whelp : creatureList)
{
if (whelp->IsAlive() && !whelp->IsInCombat() && whelp->GetMotionMaster()->GetCurrentMovementGeneratorType() != HOME_MOTION_TYPE)
{
whelp->GetMotionMaster()->MoveTargetedHome();
}
}
}
}
else
{
creatureList.clear();
}
}
};
GameObjectAI* GetAI(GameObject* go) const override
{
return new go_beaconAI(go);
}
};
void AddSC_hellfire_peninsula() void AddSC_hellfire_peninsula()
{ {
// Ours // Ours
@@ -413,4 +456,5 @@ void AddSC_hellfire_peninsula()
new npc_ancestral_wolf(); new npc_ancestral_wolf();
new npc_wounded_blood_elf(); new npc_wounded_blood_elf();
new npc_fel_guard_hound(); new npc_fel_guard_hound();
new go_beacon();
} }
+9 -2
View File
@@ -2000,8 +2000,15 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override bool OnGossipHello(Player* player, Creature* creature) override
{ {
AddGossipItemFor(player, GOSSIP_MENU_EXP_NPC, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); // "I no longer wish to gain experience." if (!player->HasPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN))
AddGossipItemFor(player, GOSSIP_MENU_EXP_NPC, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); // "I wish to start gaining experience again." {
AddGossipItemFor(player, GOSSIP_MENU_EXP_NPC, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); // "I no longer wish to gain experience."
}
else
{
AddGossipItemFor(player, GOSSIP_MENU_EXP_NPC, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); // "I wish to start gaining experience again."
}
SendGossipMenuFor(player, player->GetGossipTextId(creature), creature); SendGossipMenuFor(player, player->GetGossipTextId(creature), creature);
return true; return true;
} }