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

View File

@@ -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'),

View File

@@ -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;

View File

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

View File

@@ -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)');

View File

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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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');

View File

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

View File

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

View File

@@ -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;

View File

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

View File

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

View File

@@ -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)

View File

@@ -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)
{

View File

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

View File

@@ -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_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<CreatureFlagsExtra>::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<CreatureFlagsExtra>::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;

View File

@@ -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

View File

@@ -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<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 itemCount = *Acore::StringTo<uint32>(itemTokens.at(1));
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(itemID);
if (!itemTemplate)

View File

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

View File

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

View File

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

View File

@@ -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<AI>(obj, OldHillsbradScriptName);
}
#define RegisterOldHillsbradCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetOldHillsbradAI)
#endif

View File

@@ -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,

View File

@@ -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

View File

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

View File

@@ -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<Creature*> 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

View File

@@ -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)))

View File

@@ -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<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
{
public:
@@ -192,6 +408,15 @@ public:
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);
}
@@ -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();
}

View File

@@ -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,

View File

@@ -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
}
}

View File

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

View File

@@ -15,20 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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<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()
{
// 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();
}

View File

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