diff --git a/data/sql/updates/db_world/2023_05_21_01.sql b/data/sql/updates/db_world/2023_05_21_01.sql index c083fbc57..b58814fd6 100644 --- a/data/sql/updates/db_world/2023_05_21_01.sql +++ b/data/sql/updates/db_world/2023_05_21_01.sql @@ -37,7 +37,7 @@ DELETE FROM `spell_script_names` WHERE `spell_id` = 30745; INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (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 (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'), diff --git a/data/sql/updates/db_world/2023_05_24_00.sql b/data/sql/updates/db_world/2023_05_24_00.sql new file mode 100644 index 000000000..026a770b4 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_24_00.sql @@ -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; diff --git a/data/sql/updates/db_world/2023_05_24_01.sql b/data/sql/updates/db_world/2023_05_24_01.sql new file mode 100644 index 000000000..556592729 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_24_01.sql @@ -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); + diff --git a/data/sql/updates/db_world/2023_05_24_02.sql b/data/sql/updates/db_world/2023_05_24_02.sql new file mode 100644 index 000000000..58800c6a3 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_24_02.sql @@ -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)'); + diff --git a/data/sql/updates/db_world/2023_05_24_03.sql b/data/sql/updates/db_world/2023_05_24_03.sql new file mode 100644 index 000000000..6a46b16fc --- /dev/null +++ b/data/sql/updates/db_world/2023_05_24_03.sql @@ -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)); diff --git a/data/sql/updates/db_world/2023_05_28_00.sql b/data/sql/updates/db_world/2023_05_28_00.sql new file mode 100644 index 000000000..0dbedf87b --- /dev/null +++ b/data/sql/updates/db_world/2023_05_28_00.sql @@ -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; diff --git a/data/sql/updates/db_world/2023_05_28_01.sql b/data/sql/updates/db_world/2023_05_28_01.sql new file mode 100644 index 000000000..193e1da04 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_28_01.sql @@ -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; diff --git a/data/sql/updates/db_world/2023_05_28_02.sql b/data/sql/updates/db_world/2023_05_28_02.sql new file mode 100644 index 000000000..6ec4c6375 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_28_02.sql @@ -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'); diff --git a/data/sql/updates/db_world/2023_05_28_03.sql b/data/sql/updates/db_world/2023_05_28_03.sql new file mode 100644 index 000000000..59a980462 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_28_03.sql @@ -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)); diff --git a/data/sql/updates/db_world/2023_05_28_04.sql b/data/sql/updates/db_world/2023_05_28_04.sql new file mode 100644 index 000000000..dc4b29082 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_28_04.sql @@ -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); diff --git a/data/sql/updates/db_world/2023_05_29_00.sql b/data/sql/updates/db_world/2023_05_29_00.sql new file mode 100644 index 000000000..ebbf34e7c --- /dev/null +++ b/data/sql/updates/db_world/2023_05_29_00.sql @@ -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; + diff --git a/data/sql/updates/db_world/2023_05_29_01.sql b/data/sql/updates/db_world/2023_05_29_01.sql new file mode 100644 index 000000000..8cd73d362 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_29_01.sql @@ -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); diff --git a/data/sql/updates/db_world/2023_05_29_02.sql b/data/sql/updates/db_world/2023_05_29_02.sql new file mode 100644 index 000000000..586549ae0 --- /dev/null +++ b/data/sql/updates/db_world/2023_05_29_02.sql @@ -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); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index e089c7c24..929bb626a 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -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) { //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); if (e.event.event_chance <= rnd) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 2ac14ac55..56bf6b4d3 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2446,6 +2446,12 @@ bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction / if (GetCharmerOrOwnerGUID()) 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 if (checkfaction) { diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index 02c4752de..942c69fee 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -72,15 +72,15 @@ enum CreatureFlagsExtra : uint32 CREATURE_FLAG_EXTRA_NO_DODGE = 0x00800000, // xinef: target cannot dodge CREATURE_FLAG_EXTRA_MODULE = 0x01000000, 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_UNUSED_28 = 0x08000000, + CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS = 0x04000000, // Prevents creature from responding to assistance calls + 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_IGNORE_PATHFINDING = 0x20000000, // creature ignore pathfinding CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK = 0x40000000, // creature is immune to knockback effects CREATURE_FLAG_EXTRA_HARD_RESET = 0x80000000, // 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 }; diff --git a/src/server/game/Entities/Creature/enuminfo_CreatureData.cpp b/src/server/game/Entities/Creature/enuminfo_CreatureData.cpp index 273ec592d..85b665f4d 100644 --- a/src/server/game/Entities/Creature/enuminfo_CreatureData.cpp +++ b/src/server/game/Entities/Creature/enuminfo_CreatureData.cpp @@ -57,8 +57,8 @@ AC_API_EXPORT EnumText EnumUtils::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_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_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_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_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" }; @@ -101,8 +101,8 @@ AC_API_EXPORT CreatureFlagsExtra EnumUtils::FromIndex(size_t case 23: return CREATURE_FLAG_EXTRA_NO_DODGE; case 24: return CREATURE_FLAG_EXTRA_MODULE; case 25: return CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE; - case 26: return CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI; - case 27: return CREATURE_FLAG_EXTRA_UNUSED_28; + case 26: return CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS; + case 27: return CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI; case 28: return CREATURE_FLAG_EXTRA_DUNGEON_BOSS; case 29: return CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING; case 30: return CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK; @@ -142,8 +142,8 @@ AC_API_EXPORT size_t EnumUtils::ToIndex(CreatureFlagsExtra v case CREATURE_FLAG_EXTRA_NO_DODGE: return 23; case CREATURE_FLAG_EXTRA_MODULE: return 24; case CREATURE_FLAG_EXTRA_DONT_CALL_ASSISTANCE: return 25; - case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return 26; - case CREATURE_FLAG_EXTRA_UNUSED_28: return 27; + case CREATURE_FLAG_EXTRA_IGNORE_ALL_ASSISTANCE_CALLS: return 26; + case CREATURE_FLAG_DONT_OVERRIDE_ENTRY_SAI: return 27; case CREATURE_FLAG_EXTRA_DUNGEON_BOSS: return 28; case CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING: return 29; case CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK: return 30; diff --git a/src/server/game/Entities/Player/PlayerStorage.cpp b/src/server/game/Entities/Player/PlayerStorage.cpp index 4b5336cfb..3c4feee11 100644 --- a/src/server/game/Entities/Player/PlayerStorage.cpp +++ b/src/server/game/Entities/Player/PlayerStorage.cpp @@ -5284,7 +5284,7 @@ bool Player::LoadFromDB(ObjectGuid playerGuid, CharacterDatabaseQueryHolder cons if (at) Relocate(at->target_X, at->target_Y, at->target_Z, at->target_Orientation); else - RelocateToHomebind(); + RelocateToHomebind(); } // NOW player must have valid map diff --git a/src/server/scripts/Commands/cs_send.cpp b/src/server/scripts/Commands/cs_send.cpp index 65133672b..be2040cfa 100644 --- a/src/server/scripts/Commands/cs_send.cpp +++ b/src/server/scripts/Commands/cs_send.cpp @@ -70,14 +70,21 @@ public: { 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)); - continue; + case 1: + itemCount = 1; // Default to sending 1 item + break; + case 2: + itemCount = *Acore::StringTo(itemTokens.at(1)); + break; + default: + handler->SendSysMessage(Acore::StringFormatFmt("> Incorrect item list format for '{}'", itemString)); + continue; } uint32 itemID = *Acore::StringTo(itemTokens.at(0)); - uint32 itemCount = *Acore::StringTo(itemTokens.at(1)); ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemID); if (!itemTemplate) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp index daef75def..8cfe6d314 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp @@ -19,29 +19,27 @@ #include "ScriptedCreature.h" #include "old_hillsbrad.h" -enum CaptainSkarloc +enum Text { - SAY_ENTER = 0, - SAY_TAUNT = 1, - SAY_SLAY = 2, - SAY_DEATH = 3, + SAY_ENTER = 0, + SAY_TAUNT = 1, + SAY_SLAY = 2, + SAY_DEATH = 3 +}; - SPELL_HOLY_LIGHT = 29427, - SPELL_CLEANSE = 29380, - SPELL_HAMMER_OF_JUSTICE = 13005, - SPELL_HOLY_SHIELD = 31904, - SPELL_DEVOTION_AURA = 8258, - SPELL_CONSECRATION = 38385, +enum Spells +{ + SPELL_HOLY_LIGHT = 29427, + SPELL_CLEANSE = 29380, + SPELL_HAMMER_OF_JUSTICE = 13005, + SPELL_HOLY_SHIELD = 31904, + SPELL_DEVOTION_AURA = 8258, + SPELL_CONSECRATION = 38385 +}; - WAYPOINTS_COUNT = 4, - - EVENT_INITIAL_TALK = 1, - 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 +enum Misc +{ + WAYPOINTS_COUNT = 4 }; const Position startPath[WAYPOINTS_COUNT] = @@ -52,172 +50,174 @@ const Position startPath[WAYPOINTS_COUNT] = {2058.77f, 236.04f, 63.92f, 0.0f} }; -class boss_captain_skarloc : public CreatureScript +struct boss_captain_skarloc : public BossAI { -public: - boss_captain_skarloc() : CreatureScript("boss_captain_skarloc") { } - - CreatureAI* GetAI(Creature* creature) const override + boss_captain_skarloc(Creature* creature) : BossAI(creature, DATA_CAPTAIN_SKARLOC), summons(me) { - return GetOldHillsbradAI(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; - SummonList summons; - - void Reset() override + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + if (Creature* thrall = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(DATA_THRALL_GUID))) { - events.Reset(); - summons.DespawnAll(); + thrall->AI()->JustSummoned(summon); } + summon->SetImmuneToAll(true); + if (summon->GetEntry() == NPC_SKARLOC_MOUNT) + return; - void JustSummoned(Creature* summon) override + if (summons.size() == 1) { - summons.Summon(summon); - 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); + summon->GetMotionMaster()->MovePoint(0, 2060.788f, 237.301f, 63.999f); } - - void InitializeAI() override + else { - ScriptedAI::InitializeAI(); - - 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); + summon->GetMotionMaster()->MovePoint(0, 2056.870f, 234.853f, 63.839f); } + } - 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) - return; + 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); + } - // Xinef: we can rely here on internal counting - if (id == 1) + void MovementInform(uint32 type, uint32 id) override + { + 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); - 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)) + if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr)) { - mount->SetImmuneToNPC(true); - mount->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + summon->SetWalk(true); } } - - if (me->movespline->Finalized()) + if (Creature* mount = me->SummonCreature(NPC_SKARLOC_MOUNT, 2049.12f, 252.31f, 62.855f, me->GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN)) { - 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); - me->SetInCombatWithZone(); - for (SummonList::const_iterator itr = summons.begin(); itr != summons.end(); ++itr) + if (Creature* summon = ObjectAccessor::GetCreature(*me, *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); - - events.ScheduleEvent(EVENT_SPELL_HOLY_LIGHT, 15000); - 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 + DoCastSelf(SPELL_HOLY_LIGHT); + context.Repeat(20s); + }).Schedule(6s, [this](TaskContext context) { - Talk(SAY_SLAY); - } - - 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()) + if (roll_chance_i(33)) { - case EVENT_SPELL_HOLY_LIGHT: - 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; + Talk(SAY_TAUNT); } + 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() { - new boss_captain_skarloc(); + RegisterOldHillsbradCreatureAI(boss_captain_skarloc); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp index 42c4b358f..83093c43d 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp @@ -19,107 +19,98 @@ #include "ScriptedCreature.h" #include "old_hillsbrad.h" -enum EpochHunter +enum Text { - SAY_AGGRO = 5, - SAY_SLAY = 6, - SAY_BREATH = 7, - 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 + SAY_AGGRO = 5, + SAY_SLAY = 6, + SAY_BREATH = 7, + SAY_DEATH = 8 }; -class boss_epoch_hunter : public CreatureScript +enum Spells { -public: - boss_epoch_hunter() : CreatureScript("boss_epoch_hunter") { } + SPELL_SAND_BREATH = 31914, + 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(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 Reset() override + void JustEngagedWith(Unit* /*who*/) override + { + _JustEngagedWith(); + Talk(SAY_AGGRO); + scheduler.Schedule(8s, [this](TaskContext context) { - } - - 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()) + if (roll_chance_i(50)) { - case EVENT_SPELL_SAND_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; + Talk(SAY_BREATH); } + 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() { - new boss_epoch_hunter(); + RegisterOldHillsbradCreatureAI(boss_epoch_hunter); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_lieutenant_drake.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_lieutenant_drake.cpp index dc0d744be..afa6f6eb8 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_lieutenant_drake.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_lieutenant_drake.cpp @@ -21,159 +21,151 @@ #include "SmartScriptMgr.h" #include "old_hillsbrad.h" -enum LieutenantDrake +enum Text { - SAY_ENTER = 0, - SAY_AGGRO = 1, - SAY_SLAY = 2, - SAY_MORTAL = 3, - SAY_SHOUT = 4, - 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 + SAY_ENTER = 0, + SAY_AGGRO = 1, + SAY_SLAY = 2, + SAY_MORTAL = 3, + SAY_SHOUT = 4, + SAY_DEATH = 5 }; -class boss_lieutenant_drake : public CreatureScript +enum Spells { -public: - boss_lieutenant_drake() : CreatureScript("boss_lieutenant_drake") { } + SPELL_WHIRLWIND = 31909, + 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(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; - pathId = me->GetEntry() * 10; - me->GetMotionMaster()->MovePath(pathId, false); + me->GetMotionMaster()->MovePath(pathId, true); } - void Reset() override - { - events.Reset(); - } + if (!UpdateVictim()) + return; - void JustEngagedWith(Unit* /*who*/) override - { - Talk(SAY_AGGRO); + scheduler.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - events.ScheduleEvent(EVENT_WHIRLWIND, 4000); - events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, 14000); - events.ScheduleEvent(EVENT_MORTAL_STRIKE, 9000); - events.ScheduleEvent(EVENT_HAMSTRING, 18000); - events.ScheduleEvent(EVENT_EXPLODING_SHOT, 1000); - } + DoMeleeAttackIfReady(); + } - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - 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; - }; +private: + uint32 pathId; + bool runSecondPath; }; void AddSC_boss_lieutenant_drake() { - new boss_lieutenant_drake(); + RegisterOldHillsbradCreatureAI(boss_lieutenant_drake); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h index 602b5475f..343453a0b 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h @@ -27,6 +27,9 @@ enum DataIds { DATA_ESCORT_PROGRESS = 0, + DATA_LIEUTENANT_DRAKE = 1, + DATA_CAPTAIN_SKARLOC = 2, + DATA_EPOCH_HUNTER = 3, DATA_BOMBS_PLACED = 10, DATA_THRALL_REPOSITION = 11, @@ -95,4 +98,6 @@ inline AI* GetOldHillsbradAI(T* obj) return GetInstanceAI(obj, OldHillsbradScriptName); } +#define RegisterOldHillsbradCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetOldHillsbradAI) + #endif diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp index da71faa29..bcfbcfb9a 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp @@ -19,14 +19,17 @@ #include "ScriptedCreature.h" #include "the_black_morass.h" -enum Enums +enum Text { SAY_AGGRO = 1, SAY_BANISH = 2, SAY_SLAY = 3, SAY_DEATH = 4, - EMOTE_FRENZY = 5, + EMOTE_FRENZY = 5 +}; +enum Spells +{ SPELL_CLEAVE = 40504, SPELL_TIME_STOP = 31422, SPELL_ENRAGE = 37605, diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp index ee0bf883a..98a5d43ef 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp @@ -19,19 +19,21 @@ #include "ScriptedCreature.h" #include "the_black_morass.h" -enum Enums +enum Text { SAY_AGGRO = 1, SAY_BANISH = 2, SAY_SLAY = 3, - SAY_DEATH = 4, + SAY_DEATH = 4 +}; +enum Spells +{ SPELL_ARCANE_BLAST = 31457, SPELL_ARCANE_DISCHARGE = 31472, SPELL_TIME_LAPSE = 31467, SPELL_ATTRACTION = 38540, - - SPELL_BANISH_DRAGON_HELPER = 31550, + SPELL_BANISH_DRAGON_HELPER = 31550 }; struct boss_chrono_lord_deja : public BossAI diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp index e784ce409..7b161e05f 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp @@ -19,13 +19,16 @@ #include "ScriptedCreature.h" #include "the_black_morass.h" -enum Enums +enum Text { SAY_AGGRO = 1, SAY_BANISH = 2, SAY_SLAY = 3, - SAY_DEATH = 4, + SAY_DEATH = 4 +}; +enum Spells +{ SPELL_HASTEN = 31458, SPELL_MORTAL_WOUND = 31464, SPELL_WING_BUFFET = 31475, @@ -46,7 +49,6 @@ struct boss_temporus : public BossAI void JustEngagedWith(Unit* /*who*/) override { _JustEngagedWith(); - scheduler.Schedule(12s, [this](TaskContext context) { DoCastSelf(SPELL_HASTEN); @@ -69,7 +71,6 @@ struct boss_temporus : public BossAI context.Repeat(30s); }); } - OwnTalk(SAY_AGGRO); } @@ -98,7 +99,6 @@ struct boss_temporus : public BossAI return; } } - ScriptedAI::MoveInLineOfSight(who); } }; diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp index 52136278e..c5ad3c1aa 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp @@ -111,6 +111,16 @@ struct boss_grand_warlock_nethekurse : public BossAI }); 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 @@ -121,7 +131,7 @@ struct boss_grand_warlock_nethekurse : public BossAI void SetData(uint32 data, uint32 value) override { - if (data != SETDATA_DATA) + if (data != SETDATA_DATA || me->IsInCombat()) return; 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*/) { me->HandleEmoteCommand(EMOTE_ONESHOT_APPLAUD); - me->GetMotionMaster()->Initialize(); Talk(SAY_PEON_DIES); + scheduler.Schedule(1s, GROUP_RP, [this](TaskContext /*context*/) + { + me->GetMotionMaster()->Initialize(); + }); + if (++PeonKilledCount == 4) { Talk(SAY_INTRO_2); @@ -161,16 +175,14 @@ struct boss_grand_warlock_nethekurse : public BossAI me->GetMotionMaster()->MoveIdle(); 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); - Talk(roleplayData.textId); - me->GetMotionMaster()->Initialize(); - }); + PeonRoleplay roleplayData = Acore::Containers::SelectRandomContainerElement(PeonRoleplayData); + DoCast(me, roleplayData.spellId); + Talk(roleplayData.textId); + me->GetMotionMaster()->Initialize(); }); + context.Repeat(16400ms, 28500ms); }); } @@ -225,6 +237,19 @@ struct boss_grand_warlock_nethekurse : public BossAI } else if (action == ACTION_START_INTRO) { + // Hack: Prevent from pulling from behind door + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + _canAggro = true; + + std::list creatureList; + GetCreatureListWithEntryInGrid(creatureList, me, NPC_PEON, 60.0f); + for (Creature* creature : creatureList) + { + if (creature) + { + creature->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); + } + } IntroRP(); } } @@ -246,6 +271,7 @@ struct boss_grand_warlock_nethekurse : public BossAI private: uint8 PeonEngagedCount = 0; uint8 PeonKilledCount = 0; + bool _canAggro = false; }; class spell_tsh_shadow_bolt : public SpellScript diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp index 71c2760f0..0550943f1 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp @@ -126,6 +126,8 @@ struct boss_warchief_kargath_bladefist : public BossAI { Talk(SAY_DEATH); BossAI::JustDied(killer); + if (Creature* warchiefPortal = instance->GetCreature(DATA_WARCHIEF_PORTAL)) + warchiefPortal->AI()->SetData(DATA_RESET_FIGHT, 0); if (instance) { if (Creature* executioner = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EXECUTIONER))) diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp index 5df8630d0..0996c4f65 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp @@ -17,6 +17,7 @@ #include "CreatureTextMgr.h" #include "InstanceScript.h" +#include "ScriptedCreature.h" #include "ScriptMgr.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 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 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 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 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 { public: @@ -192,6 +408,15 @@ public: void FilterTargets(std::list& unitList) { + Unit* caster = GetCaster(); + if (!caster) + return; + + unitList.remove_if([&](WorldObject* target) -> bool + { + return !target->SelectNearestPlayer(15.0f); + }); + Acore::Containers::RandomResize(unitList, 1); } @@ -223,7 +448,12 @@ public: bool OnTrigger(Player* player, AreaTrigger const* /*areaTrigger*/) override { 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; } @@ -232,6 +462,7 @@ public: void AddSC_instance_shattered_halls() { new instance_shattered_halls(); + RegisterShatteredHallsCreatureAI(npc_shattered_hand_scout); new spell_tsh_shoot_flame_arrow(); new at_shattered_halls_execution(); } diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h index 089c0d2d2..7f46320b4 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h @@ -45,6 +45,11 @@ enum CreatureIds { NPC_GRAND_WARLOCK_NETHEKURSE = 16807, NPC_FEL_ORC_CONVERT = 17083, + NPC_PORUNG = 20923, + NPC_BLOOD_GUARD = 17461, + NPC_SH_ZEALOT = 17462, + NPC_SH_ARCHER = 17427, + // Warchief Kargath NPC_WARCHIEF_KARGATH = 16808, NPC_WARCHIEF_PORTAL = 17611, diff --git a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp index 62377ca8a..5824f3020 100644 --- a/src/server/scripts/Outland/boss_doomlord_kazzak.cpp +++ b/src/server/scripts/Outland/boss_doomlord_kazzak.cpp @@ -22,13 +22,13 @@ enum Texts { - SAY_INTRO = 0, - SAY_AGGRO = 1, - SAY_SURPREME = 2, - SAY_KILL = 3, - SAY_DEATH = 4, - EMOTE_FRENZY = 5, - SAY_RAND = 6 + SAY_INTRO = 0, + SAY_AGGRO = 1, + SAY_SURPREME = 2, + SAY_KILL = 3, + SAY_DEATH = 4, + EMOTE_FRENZY = 5, + SAY_RAND = 6 }; enum Spells @@ -42,19 +42,7 @@ enum Spells SPELL_ENRAGE = 32964, SPELL_CAPTURE_SOUL = 32966, SPELL_TWISTED_REFLECTION = 21063, - 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 + SPELL_BERSERK = 32965 }; class boss_doomlord_kazzak : public CreatureScript @@ -64,21 +52,11 @@ public: struct boss_doomlordkazzakAI : public ScriptedAI { - boss_doomlordkazzakAI(Creature* creature) : ScriptedAI(creature) - { - } + boss_doomlordkazzakAI(Creature* creature) : ScriptedAI(creature) {} void Reset() override { - _events.Reset(); - _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); + _inBerserk = false; } void JustRespawned() override @@ -89,17 +67,58 @@ public: void JustEngagedWith(Unit* /*who*/) override { 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 { - // When Kazzak kills a player (not pets/totems), he regens some health - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoCast(me, SPELL_CAPTURE_SOUL); - - Talk(SAY_KILL); + if (victim->GetTypeId() == TYPEID_PLAYER) + { + Talk(SAY_KILL); + DoCastSelf(SPELL_CAPTURE_SOUL); + } } void JustDied(Unit* /*killer*/) override @@ -109,63 +128,19 @@ public: void UpdateAI(uint32 diff) override { - // Return since we have no target if (!UpdateVictim()) return; - _events.Update(diff); - + _scheduler.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) 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(); } private: - EventMap _events; + TaskScheduler _scheduler; + bool _inBerserk; }; CreatureAI* GetAI(Creature* creature) const override @@ -191,18 +166,18 @@ public: void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/) { if (Unit* owner = GetUnitOwner()) + { amount = CalculatePct(owner->GetPower(POWER_MANA), 5); + } } void OnPeriodic(AuraEffect const* aurEff) { Unit* target = GetTarget(); - if (target->GetPower(POWER_MANA) == 0) { target->CastSpell(target, SPELL_MARK_OF_KAZZAK_DAMAGE, true, nullptr, aurEff); - // Remove aura - SetDuration(0); + SetDuration(0); // Remove aura } } diff --git a/src/server/scripts/Outland/boss_doomwalker.cpp b/src/server/scripts/Outland/boss_doomwalker.cpp index 69a749478..1838b9835 100644 --- a/src/server/scripts/Outland/boss_doomwalker.cpp +++ b/src/server/scripts/Outland/boss_doomwalker.cpp @@ -20,11 +20,11 @@ enum Texts { - SAY_AGGRO = 0, - SAY_EARTHQUAKE = 1, - SAY_OVERRUN = 2, - SAY_SLAY = 3, - SAY_DEATH = 4 + SAY_AGGRO = 0, + SAY_EARTHQUAKE = 1, + SAY_OVERRUN = 2, + SAY_SLAY = 3, + SAY_DEATH = 4 }; enum Spells @@ -38,15 +38,6 @@ enum Spells 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 { public: @@ -54,29 +45,23 @@ public: struct boss_doomwalkerAI : public ScriptedAI { - boss_doomwalkerAI(Creature* creature) : ScriptedAI(creature) - { - } + boss_doomwalkerAI(Creature* creature) : ScriptedAI(creature) {} 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; } void KilledUnit(Unit* victim) override { victim->CastSpell(victim, SPELL_MARK_DEATH, 0); - if (urand(0, 4)) return; - Talk(SAY_SLAY); + if (victim->GetTypeId() == TYPEID_PLAYER) + { + Talk(SAY_SLAY); + } } void JustDied(Unit* /*killer*/) override @@ -87,13 +72,55 @@ public: void JustEngagedWith(Unit* /*who*/) override { 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 { if (who && who->GetTypeId() == TYPEID_PLAYER && me->IsValidAttackTarget(who)) + { if (who->HasAura(SPELL_MARK_DEATH) && !who->HasAura(27827)) // Spirit of Redemption + { who->CastSpell(who, SPELL_AURA_DEATH, 1); + } + } } void UpdateAI(uint32 diff) override @@ -101,59 +128,15 @@ public: if (!UpdateVictim()) return; - _events.Update(diff); - + _scheduler.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) 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(); } private: - EventMap _events; + TaskScheduler _scheduler; bool _inEnrage; }; diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index b3cd980ac..effc40527 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -15,20 +15,7 @@ * with this program. If not, see . */ -/* ScriptData -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 "GameObjectAI.h" #include "Player.h" #include "ScriptMgr.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 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() { // Ours @@ -413,4 +456,5 @@ void AddSC_hellfire_peninsula() new npc_ancestral_wolf(); new npc_wounded_blood_elf(); new npc_fel_guard_hound(); + new go_beacon(); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 9d310a29c..e076a94c5 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -2000,8 +2000,15 @@ public: 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." - AddGossipItemFor(player, GOSSIP_MENU_EXP_NPC, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); // "I wish to start gaining experience again." + if (!player->HasPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN)) + { + 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); return true; }