aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dep/CascLib/src/CascPort.h1
-rw-r--r--dep/PackageList.txt2
-rw-r--r--sql/updates/world/2014_11_08_00_world.sql350
-rw-r--r--sql/updates/world/2014_11_08_01_world.sql58
-rw-r--r--sql/updates/world/2014_11_08_02_world.sql56
-rw-r--r--src/server/bnetserver/CMakeLists.txt1
-rw-r--r--src/server/bnetserver/Packets/PacketManager.cpp2
-rw-r--r--src/server/bnetserver/Realms/RealmList.cpp43
-rw-r--r--src/server/bnetserver/Realms/RealmList.h62
-rw-r--r--src/server/bnetserver/Realms/WorldListener.cpp4
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp26
-rw-r--r--src/server/game/Battlefield/Battlefield.h8
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp22
-rw-r--r--src/server/game/Battlegrounds/Battleground.h7
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp7
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp10
-rw-r--r--src/server/game/CMakeLists.txt1
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateData.cpp4
-rw-r--r--src/server/game/Entities/Player/Player.cpp45
-rw-r--r--src/server/game/Entities/Player/Player.h4
-rw-r--r--src/server/game/Events/GameEventMgr.cpp10
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp10
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp4
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp49
-rw-r--r--src/server/game/Handlers/LFGHandler.cpp4
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp12
-rw-r--r--src/server/game/Server/Packet.cpp158
-rw-r--r--src/server/game/Server/Packet.h8
-rw-r--r--src/server/game/Server/Packets/AuctionHousePackets.cpp6
-rw-r--r--src/server/game/Server/Packets/AuctionHousePackets.h7
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.cpp7
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.h23
-rw-r--r--src/server/game/Server/Packets/BattlegroundPackets.cpp26
-rw-r--r--src/server/game/Server/Packets/BattlegroundPackets.h40
-rw-r--r--src/server/game/Server/Packets/GuildPackets.cpp1
-rw-r--r--src/server/game/Server/Packets/GuildPackets.h3
-rw-r--r--src/server/game/Server/Packets/WorldStatePackets.cpp52
-rw-r--r--src/server/game/Server/Packets/WorldStatePackets.h64
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp34
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h92
-rw-r--r--src/server/game/Server/WorldPacket.h18
-rw-r--r--src/server/game/Server/WorldSession.cpp92
-rw-r--r--src/server/game/Server/WorldSession.h13
-rw-r--r--src/server/game/Server/WorldSocket.cpp192
-rw-r--r--src/server/game/Server/WorldSocket.h22
-rw-r--r--src/server/game/Server/WorldSocketMgr.cpp7
-rw-r--r--src/server/game/Server/WorldSocketMgr.h3
-rw-r--r--src/server/game/Spells/Spell.cpp4
-rw-r--r--src/server/game/World/World.cpp17
-rw-r--r--src/server/game/World/World.h9
-rw-r--r--src/server/scripts/Maelstrom/CMakeLists.txt7
-rw-r--r--src/server/scripts/Maelstrom/Stonecore/boss_corborus.cpp319
-rw-r--r--src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp808
-rw-r--r--src/server/scripts/Maelstrom/Stonecore/boss_ozruk.cpp287
-rw-r--r--src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp599
-rw-r--r--src/server/scripts/Maelstrom/Stonecore/instance_stonecore.cpp262
-rw-r--r--src/server/scripts/Maelstrom/Stonecore/stonecore.cpp442
-rw-r--r--src/server/scripts/Maelstrom/Stonecore/stonecore.h72
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp58
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h49
-rw-r--r--src/server/shared/CMakeLists.txt3
-rw-r--r--src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp15
-rw-r--r--src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h1
-rw-r--r--src/server/shared/Database/Field.cpp12
-rw-r--r--src/server/shared/Database/Field.h6
-rw-r--r--src/server/shared/Database/PreparedStatement.cpp6
-rw-r--r--src/server/shared/Database/QueryResult.cpp2
-rw-r--r--src/server/shared/Networking/SocketMgr.h1
-rw-r--r--src/server/shared/Realm/Realm.cpp53
-rw-r--r--src/server/shared/Realm/Realm.h86
-rw-r--r--src/server/worldserver/Main.cpp64
-rw-r--r--src/server/worldserver/worldserver.conf.dist11
73 files changed, 4447 insertions, 417 deletions
diff --git a/dep/CascLib/src/CascPort.h b/dep/CascLib/src/CascPort.h
index 6d0595ce522..3bf1efde4b8 100644
--- a/dep/CascLib/src/CascPort.h
+++ b/dep/CascLib/src/CascPort.h
@@ -66,6 +66,7 @@
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
+ #include <stddef.h>
// Support for PowerPC on Max OS X
#if (__ppc__ == 1) || (__POWERPC__ == 1) || (_ARCH_PPC == 1)
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index 12e0de314f7..ae4bf880c5b 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -38,7 +38,7 @@ recastnavigation (Recast is state of the art navigation mesh construction toolse
CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014)
https://github.com/ladislav-zezula/CascLib
- Version: d3d17de30a1c5678375049f4cf3301a0a7962780
+ Version: 3e3f4f443cb7b2893cbbe60b0a6efafebf48bc40
zmqpp (C++ binding for 0mq/zmq is a 'high-level' library that hides most of the c-style interface core 0mq provides.)
https://github.com/zeromq/zmqpp
diff --git a/sql/updates/world/2014_11_08_00_world.sql b/sql/updates/world/2014_11_08_00_world.sql
new file mode 100644
index 00000000000..64a59180b46
--- /dev/null
+++ b/sql/updates/world/2014_11_08_00_world.sql
@@ -0,0 +1,350 @@
+-- The Stonecore
+DELETE FROM `instance_template` WHERE `map` = 725;
+INSERT INTO `instance_template` (`map`, `parent`, `script`, `allowMount`) VALUES
+(725, 0, 'instance_stonecore', 0);
+
+DELETE FROM `instance_encounters` WHERE `entry` IN (1056, 1059, 1058, 1057);
+INSERT INTO `instance_encounters` (`entry`, `creditType`, `creditEntry`, `lastEncounterDungeon`, `comment`) VALUES
+(1056, 0, 43438, 0, 'Corborus'),
+(1059, 0, 43214, 0, 'Slabhide'),
+(1058, 0, 42188, 0, 'Ozruk'),
+(1057, 0, 42333, 0, 'High Priestess Azil');
+
+UPDATE `creature_template` SET `mechanic_immune_mask` = 617299839 WHERE `entry` IN (43391, 43438, 43214, 42188, 42333);
+
+-- Script names
+UPDATE `creature_template` SET `ScriptName` = 'boss_corborus' WHERE `entry` = 43438;
+UPDATE `creature_template` SET `ScriptName` = 'boss_slabhide' WHERE `entry` = 43214;
+UPDATE `creature_template` SET `ScriptName` = 'boss_ozruk' WHERE `entry` = 42188;
+UPDATE `creature_template` SET `ScriptName` = 'boss_high_priestess_azil' WHERE `entry` = 42333;
+UPDATE `creature_template` SET `ScriptName` = 'npc_rock_borer' WHERE `entry` = 43917;
+UPDATE `creature_template` SET `ScriptName` = 'npc_sc_millhouse_manastorm' WHERE `entry` = 43391;
+UPDATE `creature_template` SET `ScriptName` = 'npc_lava_fissure' WHERE `entry` = 43242;
+UPDATE `creature_template` SET `ScriptName` = 'npc_stalactite_trigger' WHERE `entry` = 43159;
+UPDATE `creature_template` SET `ScriptName` = 'npc_devout_follower' WHERE `entry` = 42428;
+UPDATE `creature_template` SET `ScriptName` = 'npc_gravity_well' WHERE `entry` = 42499;
+UPDATE `creature_template` SET `ScriptName` = 'npc_seismic_shard' WHERE `entry` = 42355;
+
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (81459, 45313, 93167, 81008, 81035, 81028, 80650, 80654, 80643, 92653, 80647, 92309, 92306, 92300, 92393, 78835, 92429, 79200, 79196, 79251, 79249, 79332, 86862, 86863, 79015);
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(81459, 'spell_force_of_earth'),
+(45313, 'spell_sc_anchor_here'),
+(93167, 'spell_sc_twilight_documents'),
+(81008, 'spell_sc_quake'),
+(81035, 'spell_s81035_stalactite'),
+(81028, 'spell_s81028_s80650_stalactite'),
+(80650, 'spell_s81028_s80650_stalactite'),
+(80654, 'spell_stalactite_mod_dest_height'),
+(80643, 'spell_stalactite_mod_dest_height'),
+(92653, 'spell_stalactite_mod_dest_height'),
+(80647, 'spell_stalactite_mod_dest_height'),
+(92309, 'spell_stalactite_mod_dest_height'),
+(92306, 'spell_s92306_crystal_storm'),
+(92300, 'spell_s92300_crystal_storm'),
+(92393, 'spell_rupture'),
+(78835, 'spell_elementium_spike_shield'),
+(92429, 'spell_elementium_spike_shield'),
+(79200, 'spell_summon_wave_south'),
+(79196, 'spell_summon_wave_west'),
+(79251, 'spell_gravity_well_damage_nearby'),
+(79249, 'spell_gravity_well_damage'),
+(79332, 'spell_gravity_well_pull'),
+(86862, 'spell_seismic_shard_prepare'),
+(86863, 'spell_seismic_shard_change_seat'),
+(79015, 'spell_seismic_shard');
+
+DELETE FROM `areatrigger_scripts` WHERE `entry` IN (6076, 6070);
+INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES
+(6076, 'at_sc_corborus_intro'),
+(6070, 'at_sc_slabhide_intro');
+
+-- Twilight Documents object is spawned by Millhouse.
+DELETE FROM `gameobject` WHERE `id` = 207415;
+
+-- Millhouse Manastorm texts
+DELETE FROM `creature_text` WHERE `entry` IN (43391);
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(43391, 0, 1, 'Follow me if you dare!', 14, 0, 100, 0, 0, 21783, 0, 0, 'Millhouse Manastorm'),
+(43391, 0, 2, 'It''s time for a tactical retreat!', 14, 0, 100, 0, 0, 21784, 0, 0, 'Millhouse Manastorm'),
+(43391, 0, 3, 'You''re gonna be sorry!', 14, 0, 100, 0, 0, 21785, 0, 0, 'Millhouse Manastorm'),
+(43391, 0, 4, 'Don''t say I didn''t warn ya!', 14, 0, 100, 0, 0, 21786, 0, 0, 'Millhouse Manastorm'),
+(43391, 1, 1, 'Ah-ha! I''ve got you right where I want you!', 14, 0, 100, 0, 0, 21787, 0, 0, 'Millhouse Manastorm'),
+(43391, 1, 2, 'Now... witness the full power of Millhouse Manastorm!', 14, 0, 100, 0, 0, 21788, 0, 0, 'Millhouse Manastorm'),
+(43391, 1, 3, 'Prison taught me one very important lesson, well, two if you count how to hold your soap, but yes! SURVIVAL!', 14, 0, 100, 0, 0, 21789, 0, 0, 'Millhouse Manastorm');
+
+-- Creature formations for Millhouse event (340418 -> trash, 340492 -> last group)
+DELETE FROM `creature_formations` WHERE `leaderGUID` IN (340418, 340392, 340492);
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(340418, 340418, 0, 0, 0, 0, 0),
+(340418, 340419, 0, 0, 0, 0, 0),
+(340418, 340421, 0, 0, 0, 0, 0),
+(340418, 340422, 0, 0, 0, 0, 0),
+(340418, 340465, 0, 0, 0, 0, 0),
+(340418, 340466, 0, 0, 0, 0, 0),
+(340418, 340467, 0, 0, 0, 0, 0),
+(340418, 340469, 0, 0, 0, 0, 0),
+(340418, 340476, 0, 0, 0, 0, 0),
+(340418, 340477, 0, 0, 0, 0, 0),
+(340418, 340478, 0, 0, 0, 0, 0),
+(340418, 340479, 0, 0, 0, 0, 0),
+(340492, 340492, 0, 0, 0, 0, 0),
+(340492, 340493, 0, 0, 0, 0, 0),
+(340492, 340494, 0, 0, 0, 0, 0),
+(340492, 340495, 0, 0, 0, 0, 0),
+(340492, 340496, 0, 0, 0, 0, 0),
+(340492, 340497, 0, 0, 0, 0, 0),
+(340492, 340498, 0, 0, 0, 0, 0),
+(340492, 340499, 0, 0, 0, 0, 0),
+(340492, 340500, 0, 0, 0, 0, 0);
+
+-- Stonecore Flayer SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42808;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 42808 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(42808, 0, 0, 0, 1, 0, 100, 0, 0, 0, 60000, 60000, 17, 438, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Flayer - In Combat - Set emote state 438"),
+(42808, 0, 1, 0, 4, 0, 100, 0, 2500, 10000, 10000, 15000, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Flayer - On Aggro - Set emote state 0"),
+(42808, 0, 2, 0, 0, 0, 100, 0, 2500, 10000, 10000, 15000, 11, 79922, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Flayer - In Combat - Cast 'Flay'");
+
+-- Stonecore Earthshaper SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 43537;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 43537 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(43537, 0, 0, 1, 25, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - On Reset - Set Phase 1"),
+(43537, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - Linked - Demorph"),
+(43537, 0, 2, 0, 0, 1, 100, 0, 3000, 3000, 10000, 15000, 11, 81576, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - In Combat (Phase 1) - Cast 'Lava Burst'"),
+(43537, 0, 3, 4, 0, 1, 100, 0, 9000, 9000, 12000, 12000, 11, 81459, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - In Combat (Phase 1) - Cast 'Force of Earth'"),
+(43537, 0, 4, 0, 61, 1, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - Linked - Say Text 0"),
+(43537, 0, 5, 0, 0, 1, 100, 0, 15000, 15000, 10000, 15000, 11, 81530, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - In Combat (Phase 1) - Cast 'Ground Shock'"),
+(43537, 0, 6, 7, 8, 1, 100, 1, 81459, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - Hit by 'Force of Earth' (Phase 1) - Set Phase 2"),
+(43537, 0, 7, 0, 61, 1, 100, 1, 81459, 0, 0, 0, 3, 26693, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - Linked - Morph"),
+(43537, 0, 8, 0, 0, 2, 100, 0, 5000, 5000, 15000, 15000, 11, 81463, 64, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - In Combat (Phase 2) - Cast 'Dust Storm'"),
+(43537, 0, 9, 0, 6, 0, 100, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - On Death - Demorph");
+-- TODO: Demorph 3 seconds after death. Need more sniffs for Force of Earth's dummy.
+
+DELETE FROM `creature_text` WHERE `entry` = 43537 AND `groupid` = 0;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextID`, `comment`) VALUES
+(43537, 0, 0, '%s begins to transform into a Force of Earth!', 16, 0, 100, 0, 0, 0, 46680, 'Stonecore Earthshaper');
+
+-- Stonecore Warbringer SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42696;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 42696 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(42696, 0, 0, 0, 0, 0, 100, 0, 4000, 4000, 12000, 12000, 11, 80158, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Warbringer - In Combat - Cast 'Rage'"),
+(42696, 0, 1, 0, 0, 0, 100, 0, 8000, 8000, 8000, 12000, 11, 15496, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Warbringer - In Combat - Cast 'Cleave'");
+
+-- Stonecore Berserker SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 43430;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 43430 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(43430, 0, 0, 0, 0, 0, 100, 0, 0, 0, 10000, 10000, 11, 81574, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, "Stonecore Warbringer - In Combat - Cast 'Charge'"),
+(43430, 0, 1, 0, 0, 0, 100, 0, 10000, 15000, 10000, 20000, 11, 81568, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Warbringer - In Combat - Cast 'Spinning Slash'");
+
+-- Heroic template of Corborus, Flags on creation (from sniffs)
+UPDATE `creature_template` SET `difficulty_entry_1` = 49642, `unit_flags` = 33088 WHERE `entry` = 43438;
+DELETE FROM `creature_template` WHERE `entry` = 49642;
+INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `femaleName`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `exp_unk`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `type_flags2`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `HealthModifier`, `HealthModifierExtra`, `ManaModifier`, `ManaModifierExtra`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES
+(49642, 0, 0, 0, 0, 0, 33477, 0, 0, 0, 'Corborus (1)', '', '', '', 0, 87, 87, 3, 0, 14, 0, 2.8, 1.14286, 1, 1, 0, 2000, 2000, 1, 1, 1, 33088, 2048, 0, 0, 0, 0, 0, 4, 584, 0, 49642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 35, 1, 1, 1, 1, 1, 1, 0, 52506, 0, 0, 0, 0, 0, 154, 1, 617299839, 1, '', 15595);
+
+-- Corborus loot
+UPDATE `creature_template` SET `lootid` = 43438 WHERE `entry` = 43438;
+UPDATE `creature_template` SET `lootid` = 49642 WHERE `entry` = 49642;
+
+DELETE FROM `creature_loot_template` WHERE `Entry` IN (43438, 49642);
+INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(43438, 1, 43400, 100, 0, 1, 0, 1, 1, NULL),
+(49642, 1, 43401, 100, 0, 1, 0, 1, 1, NULL);
+
+DELETE FROM `reference_loot_template` WHERE `Entry` IN (43400, 43401);
+INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(43400, 55792, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43400, 55793, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43400, 55794, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43400, 55795, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43400, 55796, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43401, 56328, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43401, 56329, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43401, 56330, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43401, 56331, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43401, 56332, 0, 0, 0, 1, 1, 1, 1, NULL);
+
+-- Set UNIT_FLAG_NOT_SELECTABLE to Trashing Charge.
+UPDATE `creature_template` SET `unit_flags` = 33554432 WHERE `entry` = 43743;
+
+-- Crystalspawn Giant SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42810;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 42810 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(42810, 0, 0, 0, 0, 0, 100, 0, 5000, 5000, 12000, 12000, 11, 81008, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Crystalspawn Giant - In Combat - Cast 'Quake'");
+-- (42810, 0, 1, 0, 0, 0, 100, 0, 10000, 10000, 12000, 12000, 11, ?????, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Crystalspawn Giant - In Combat - Cast 'Crystal Shard'");
+-- need Stonecore HC sniffs for this spell
+
+-- Remove one Slabhide spawn, only the flying one is needed
+DELETE FROM `creature` WHERE `id` = 43214;
+INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `PhaseId`, `PhaseGroup`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES
+(340550, 43214, 725, 0, 0, 3, 1, 0, 0, 0, 0, 1191.1, 1154.01, 270.759, 4.69494, 7200, 0, 0, 1, 0, 0, 0, 0, 0, 0);
+
+-- Heroic template of Slabhide, InhabitType correction
+UPDATE `creature_template` SET `difficulty_entry_1` = 49538, `InhabitType` = 7 WHERE `entry` = 43214;
+DELETE FROM `creature_template` WHERE `entry` = 49538;
+INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `femaleName`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `exp_unk`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `type_flags2`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `HealthModifier`, `HealthModifierExtra`, `ManaModifier`, `ManaModifierExtra`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES
+(49538, 0, 0, 0, 0, 0, 36476, 0, 0, 0, 'Slabhide (1)', '', '', '', 0, 87, 87, 3, 0, 16, 0, 2.8, 1.42857, 1, 1, 0, 2000, 2000, 1, 1, 1, 33587264, 2048, 0, 0, 0, 0, 0, 2, 72, 0, 49538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 7, 1.25, 50, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 154, 1, 0, 1, '', 15595);
+
+-- Slabhide loot
+UPDATE `creature_template` SET `lootid` = 43214 WHERE `entry` = 43214;
+UPDATE `creature_template` SET `lootid` = 49538 WHERE `entry` = 49538;
+
+DELETE FROM `creature_loot_template` WHERE `Entry` IN (43214, 49538);
+INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(43214, 1, 43402, 100, 0, 1, 0, 1, 1, 'Slabhide N - Reference Loot'),
+(49538, 1, 43403, 100, 0, 1, 0, 1, 1, 'Slabhide H - Reference Loot'),
+(43214, 63043, 0, 1, 0, 1, 0, 1, 1, 'Slabhide N - Mount Drop'),
+(49538, 63043, 0, 1, 0, 1, 0, 1, 1, 'Slabhide H - Mount Drop');
+
+DELETE FROM `reference_loot_template` WHERE `Entry` IN (43402, 43403);
+INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(43402, 55797, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43402, 55798, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43402, 55799, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43402, 55800, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43402, 55801, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43403, 56333, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43403, 56334, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43403, 56335, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43403, 56336, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43403, 56337, 0, 0, 0, 1, 1, 1, 1, NULL);
+
+-- Set UNIT_FLAG_NOT_SELECTABLE to Stalactite Trigger - Boss, Lava Fissure, .
+UPDATE `creature_template` SET `unit_flags` = 33554432 WHERE `entry` IN (43159, 43242);
+
+-- "Stalactite Trigger - Boss": InhabitType correction
+UPDATE `creature_template` SET `InhabitType` = 7 WHERE `entry` = 43159;
+
+-- Stonecore Magmalord SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42789;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 42789 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(42789, 0, 0, 0, 0, 0, 100, 0, 4000, 8000, 10000, 20000, 11, 80151, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Magmalord - In Combat - Cast '80151'"),
+(42789, 0, 1, 0, 0, 0, 100, 0, 8000, 10000, 10000, 20000, 11, 80038, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Magmalord - In Combat - Cast 'Eruption'");
+
+-- Stonecore Rift Conjurer SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42691;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 42691 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(42691, 0, 0, 0, 0, 0, 100, 0, 0, 0, 2000, 2000, 11, 80279, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Rift Conjurer - In Combat - Cast 'Shadow Bolt'"),
+(42691, 0, 1, 0, 0, 0, 100, 0, 10000, 20000, 20000, 30000, 11, 80308, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Rift Conjurer - In Combat - Cast 'Demon Portal'");
+
+-- Imp SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 43014;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 43014 AND `source_type` = 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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(43014, 0, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 80344, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Imp - In Combat - Cast 'Fel Firebolt'");
+
+-- Stonecore Bruiser SAI
+UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42692;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = 42692 AND `source_type` = 0 OR `entryorguid` = 4269200 AND `source_type` = 9;
+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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(42692, 0, 0, 0, 0, 0, 100, 0, 8000, 10000, 13000, 15000, 80, 4269200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - In Combat - Start Actionlist"),
+(4269200, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 80180, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - Actionlist- Cast 'Body Slam'"),
+(4269200, 9, 1, 0, 0, 0, 100, 0, 2400, 2400, 0, 0, 11, 80180, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - Actionlist - Cast 'Body Slam' again"),
+(4269200, 9, 2, 0, 0, 0, 100, 0, 2400, 2400, 0, 0, 11, 80180, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - Actionlist - Cast 'Body Slam' again"),
+(42692, 0, 1, 0, 0, 0, 100, 0, 14000, 18000, 14000, 18000, 11, 80195, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - In Combat - Cast 'Shockwave'");
+
+-- Heroic template of Ozruk
+UPDATE `creature_template` SET `difficulty_entry_1` = 49654 WHERE `entry` = 42188;
+DELETE FROM `creature_template` WHERE `entry` = 49654;
+INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `femaleName`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `exp_unk`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `type_flags2`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `HealthModifier`, `HealthModifierExtra`, `ManaModifier`, `ManaModifierExtra`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES
+(49654, 0, 0, 0, 0, 0, 36475, 0, 0, 0, 'Ozruk (1)', '', '', '', 0, 87, 87, 3, 0, 14, 0, 1, 1.5873, 1, 1, 0, 2000, 2000, 1, 1, 1, 32832, 134219776, 0, 0, 0, 0, 0, 5, 584, 0, 49654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 867, 0, 0, '', 0, 3, 1, 40, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 617299839, 1, '', 15595);
+
+-- Ozruk texts
+DELETE FROM `creature_text` WHERE `entry` = 42188;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(42188, 0, 0, 'None may pass into the World''s Heart!', 14, 0, 100, 0, 0, 21919, 0, 0, 'Ozruk to Player'),
+(42188, 1, 0, '|TInterface\\Icons\\ability_warrior_shieldreflection.blp:20|tOzruk casts |cFFFF0000|Hspell:78939|h[Elementium Bulwark]|h|r!', 41, 0, 100, 0, 0, 0, 0, 0, 'Ozruk'),
+(42188, 2, 0, 'Break yourselves upon my body. Feel the strength of the earth!', 14, 0, 100, 0, 0, 21921, 0, 0, 'Ozruk'),
+(42188, 3, 0, '%s becomes enraged!', 41, 0, 100, 0, 0, 0, 0, 0, 'Ozruk'),
+(42188, 4, 0, 'A protector has fallen. The World''s Heart lies exposed!', 14, 0, 100, 0, 0, 21922, 0, 0, 'Ozruk to Player');
+
+-- Ozruk loot
+UPDATE `creature_template` SET `lootid` = 42188 WHERE `entry` = 42188;
+UPDATE `creature_template` SET `lootid` = 49654 WHERE `entry` = 49654;
+
+DELETE FROM `creature_loot_template` WHERE `Entry` IN (42188, 49654);
+INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(42188, 1, 43404, 100, 0, 1, 0, 1, 1, 'Ozruk N - Reference Loot'),
+(49654, 1, 43405, 100, 0, 1, 0, 1, 1, 'Ozruk H - Reference Loot');
+
+DELETE FROM `reference_loot_template` WHERE `Entry` IN (43404, 43405);
+INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(43404, 55802, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43404, 55803, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43404, 55804, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43404, 55810, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43404, 55811, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43405, 56338, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43405, 56339, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43405, 56340, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43405, 56341, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43405, 56342, 0, 0, 0, 1, 1, 1, 1, NULL);
+
+-- Set UNIT_FLAG_NOT_SELECTABLE to Rupture Controller and Rupture.
+UPDATE `creature_template` SET `unit_flags` = 33554432 WHERE `entry` IN (49597, 49576);
+
+-- Heroic template of High Priestess Azil
+UPDATE `creature_template` SET `difficulty_entry_1` = 49624 WHERE `entry` = 42333;
+DELETE FROM `creature_template` WHERE `entry` = 49624;
+INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `femaleName`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `exp_unk`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `type_flags2`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `HealthModifier`, `HealthModifierExtra`, `ManaModifier`, `ManaModifierExtra`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES
+(49624, 0, 0, 0, 0, 0, 26448, 0, 0, 0, 'High Priestess Azil (1)', '', '', '', 0, 84, 84, 3, 0, 14, 2, 1.2, 1.42857, 1, 1, 0, 2000, 2000, 1, 1, 1, 32832, 2048, 0, 0, 0, 0, 0, 7, 72, 0, 49624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 903, 0, 0, '', 0, 3, 1, 30, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 721, 1, 617299839, 1, '', 15595);
+
+-- "Stalactite Trigger - Boss": InhabitType correction
+UPDATE `creature_template` SET `InhabitType` = 7 WHERE `entry` IN (42333, 49624);
+
+-- High Priestess Azil texts
+DELETE FROM `creature_text` WHERE `entry` = 42333;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(42333, 0, 0, 'The world will be reborn in flames!', 14, 0, 100, 0, 0, 21634, 0, 0, 'High Priestess Azil to Player'),
+(42333, 1, 0, 'Witness the power bestowed upon me by Deathwing! Feel the fury of earth!', 14, 0, 100, 0, 0, 21628, 0, 0, 'High Priestess Azil to High Priestess Azil'),
+(42333, 2, 0, 'For my death, countless more will fall. The burden is now yours to bear.', 14, 0, 100, 0, 0, 21633, 0, 0, 'High Priestess Azil to Player');
+
+-- High Priestess Azil loot
+UPDATE `creature_template` SET `lootid` = 42333 WHERE `entry` = 42333;
+UPDATE `creature_template` SET `lootid` = 49624 WHERE `entry` = 49624;
+
+DELETE FROM `creature_loot_template` WHERE `Entry` IN (42333, 49624);
+INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(42333, 1, 43406, 100, 0, 1, 0, 1, 1, 'High Priestess Azil N - Reference Loot'),
+(49624, 1, 43407, 100, 0, 1, 0, 1, 1, 'High Priestess Azil H - Reference Loot'),
+(49624, 52078, 0, 100, 0, 1, 0, 1, 1, 'High Priestess Azil H - Chaos Orb');
+
+DELETE FROM `reference_loot_template` WHERE `Entry` IN (43406, 43407);
+INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
+(43406, 55812, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55813, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55814, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55815, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55816, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55817, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55818, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55819, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55820, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43406, 55821, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56343, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56344, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56345, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56346, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56347, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56348, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56349, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56350, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56351, 0, 0, 0, 1, 1, 1, 1, NULL),
+(43407, 56352, 0, 0, 0, 1, 1, 1, 1, NULL);
+
+DELETE FROM `spell_target_position` WHERE `id` IN (79193, 79199, 86860, 86858, 86856);
+INSERT INTO `spell_target_position` (`id`, `effIndex`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`, `VerifiedBuild`) VALUES
+(79193, 0, 725, 1260, 960, 205.443756, 0, 0),
+(79199, 0, 725, 1280, 1050, 210.383057, 0, 0),
+(86860, 0, 725, 1350.75, 919.133, 194.769, 0, 0),
+(86858, 0, 725, 1341.19, 913.399, 197.092, 0, 0),
+(86856, 0, 725, 1361.89, 920.219, 196.308, 0, 0);
+
+-- Set UNIT_FLAG_NOT_SELECTABLE to Gravity Well and Seismic Shard.
+UPDATE `creature_template` SET `unit_flags` = 33554432 WHERE `entry` IN (42499, 42355);
diff --git a/sql/updates/world/2014_11_08_01_world.sql b/sql/updates/world/2014_11_08_01_world.sql
new file mode 100644
index 00000000000..e6969ee08ab
--- /dev/null
+++ b/sql/updates/world/2014_11_08_01_world.sql
@@ -0,0 +1,58 @@
+DELETE FROM `disables` WHERE `entry` IN (10042, 10340, 10341, 10342, 10347, 10348, 10349, 10350, 10351, 10352, 10353, 10354, 10355, 10357, 10361, 10362, 10363, 10364, 10403, 10404, 10439, 10582, 10583, 10598, 10599, 10719) AND `sourceType` = 4;
+
+DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (10042, 10340, 10341, 10342, 10347, 10348, 10349, 10350, 10351, 10352, 10353, 10354, 10355, 10357, 10361, 10362, 10363, 10364, 10403, 10404, 10439, 10582, 10583, 10598, 10599, 10719);
+INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`) VALUES
+-- 10
+(10042, 18, 0),
+(10042, 12, 0),
+(10342, 18, 0),
+(10342, 12, 0),
+(10340, 18, 0),
+(10340, 12, 0),
+(10341, 18, 0),
+(10341, 12, 0),
+(10598, 18, 0),
+(10598, 12, 0),
+(10348, 18, 0),
+(10348, 12, 0),
+(10351, 18, 0),
+(10351, 12, 0),
+(10439, 18, 0),
+(10439, 12, 0),
+(10403, 18, 0),
+(10403, 12, 0),
+(10582, 18, 0),
+(10582, 12, 0),
+(10347, 18, 0),
+(10347, 12, 0),
+(10349, 18, 0),
+(10349, 12, 0),
+(10350, 18, 0),
+(10350, 12, 0),
+-- 25
+(10352, 18, 0),
+(10352, 12, 1),
+(10355, 18, 0),
+(10355, 12, 1),
+(10353, 18, 0),
+(10353, 12, 1),
+(10354, 18, 0),
+(10354, 12, 1),
+(10599, 18, 0),
+(10599, 12, 1),
+(10357, 18, 0),
+(10357, 12, 1),
+(10363, 18, 0),
+(10363, 12, 1),
+(10719, 18, 0),
+(10719, 12, 1),
+(10404, 18, 0),
+(10404, 12, 1),
+(10583, 18, 0),
+(10583, 12, 1),
+(10361, 18, 0),
+(10361, 12, 1),
+(10362, 18, 0),
+(10362, 12, 1),
+(10364, 18, 0),
+(10364, 12, 1);
diff --git a/sql/updates/world/2014_11_08_02_world.sql b/sql/updates/world/2014_11_08_02_world.sql
new file mode 100644
index 00000000000..08f64d64bd3
--- /dev/null
+++ b/sql/updates/world/2014_11_08_02_world.sql
@@ -0,0 +1,56 @@
+UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN(37098,38418,38258);
+UPDATE `creature_template` SET `InhabitType`=5 WHERE `entry`=38058;
+
+-- Skybreaker Protector SAI
+SET @ENTRY := 36998;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,0,0,100,0,4000,4000,8000,10000,11,69965,0,0,0,0,0,1,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Thunderclap'"),
+(@ENTRY,0,1,0,0,0,100,0,7000,7000,21000,23000,11,69902,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Devastate'"),
+(@ENTRY,0,2,0,0,0,100,0,16000,16000,30000,30000,11,69903,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Shield Slam'"),
+(@ENTRY,0,3,0,0,0,100,0,5000,5000,17000,26000,11,69901,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Spell Reflect'"),
+(@ENTRY,0,4,0,0,0,100,0,7000,7000,44000,45000,11,57807,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Sunder Armor'");
+
+-- Kor'kron Defender SAI
+SET @ENTRY := 37032;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,0,0,100,0,4000,4000,8000,10000,11,69965,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Thunderclap'"),
+(@ENTRY,0,1,0,0,0,100,0,7000,7000,21000,23000,11,69902,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Devastate'"),
+(@ENTRY,0,2,0,0,0,100,0,16000,16000,30000,30000,11,69903,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Shield Slam'"),
+(@ENTRY,0,3,0,0,0,100,0,5000,5000,17000,26000,11,69901,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Spell Reflect'"),
+(@ENTRY,0,4,0,0,0,100,0,7000,7000,44000,45000,11,57807,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Sunder Armor'");
+
+-- Blighted Abomination SAI
+SET @ENTRY := 37022;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,0,0,100,0,4000,4000,6000,6000,11,71140,0,0,0,0,0,2,0,0,0,0,0,0,0,"Blighted Abomination - In Combat - Cast 'Scourge Hook'"),
+(@ENTRY,0,1,0,0,0,100,0,10000,11000,10000,11000,11,71150,0,0,0,0,0,1,0,0,0,0,0,0,0,"Blighted Abomination - In Combat - Cast 'Plague Cloud'"),
+(@ENTRY,0,2,0,0,0,100,0,14000,15000,14000,15000,11,40504,0,0,0,0,0,2,0,0,0,0,0,0,0,"Blighted Abomination - In Combat - Cast 'Cleave'");
+
+-- Decaying Colossus SAI
+SET @ENTRY := 36880;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,0,0,100,0,15000,17000,15000,17000,11,71114,0,0,0,0,0,1,0,0,0,0,0,0,0,"Decaying Colossus - In Combat - Cast 'Massive Stomp'");
+
+-- Darkfallen Lieutenant SAI
+SET @ENTRY := 37665;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,0,0,100,0,9000,9000,8000,9000,11,70435,0,0,0,0,0,2,0,0,0,0,0,0,0,"Darkfallen Lieutenant - In Combat - Cast 'Rend Flesh'"),
+(@ENTRY,0,1,0,0,0,100,0,5000,5000,20000,20000,11,70423,0,0,0,0,0,2,0,0,0,0,0,0,0,"Darkfallen Lieutenant - In Combat - Cast 'Vampiric Curse'");
+
+-- Darkfallen Commander SAI
+SET @ENTRY := 37662;
+UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,0,0,100,0,5000,5000,15000,16000,11,70449,0,0,0,0,0,18,45,0,0,0,0,0,0,"Darkfallen Commander - In Combat - Cast 'Vampire Rush'"),
+(@ENTRY,0,1,0,0,0,100,0,5000,5000,25000,25000,11,70750,0,0,0,0,0,1,0,0,0,0,0,0,0,"Darkfallen Commander - In Combat - Cast 'Battle Shout'");
diff --git a/src/server/bnetserver/CMakeLists.txt b/src/server/bnetserver/CMakeLists.txt
index 5b854018d47..5d1edef5b81 100644
--- a/src/server/bnetserver/CMakeLists.txt
+++ b/src/server/bnetserver/CMakeLists.txt
@@ -55,6 +55,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication
${CMAKE_SOURCE_DIR}/src/server/shared/Logging
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Realm
${CMAKE_SOURCE_DIR}/src/server/shared/Threading
${CMAKE_SOURCE_DIR}/src/server/shared/Utilities
${CMAKE_SOURCE_DIR}/src/server/ipc
diff --git a/src/server/bnetserver/Packets/PacketManager.cpp b/src/server/bnetserver/Packets/PacketManager.cpp
index cbfd0c8b2b6..faf38e8a5bc 100644
--- a/src/server/bnetserver/Packets/PacketManager.cpp
+++ b/src/server/bnetserver/Packets/PacketManager.cpp
@@ -79,7 +79,7 @@ Battlenet::PacketManager::PacketManager()
void Battlenet::PacketManager::RegisterAuthenticationPackets()
{
- REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION), "Authentication::LogonRequest3");
+ REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION), "Authentication::LogonRequest");
REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_RESUME_REQUEST, AUTHENTICATION), Authentication::ResumeRequest);
REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_PROOF_RESPONSE, AUTHENTICATION), Authentication::ProofResponse);
REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_LOGON_REQUEST_3, AUTHENTICATION), Authentication::LogonRequest3);
diff --git a/src/server/bnetserver/Realms/RealmList.cpp b/src/server/bnetserver/Realms/RealmList.cpp
index cc7e1d492a8..a876aa93a07 100644
--- a/src/server/bnetserver/Realms/RealmList.cpp
+++ b/src/server/bnetserver/Realms/RealmList.cpp
@@ -24,49 +24,6 @@
#include "RealmList.h"
#include <boost/asio/ip/tcp.hpp>
-Battlenet::RealmId& Battlenet::RealmId::operator=(Battlenet::RealmHandle const& handle)
-{
- Region = handle.Region;
- Battlegroup = handle.Battlegroup;
- Index = handle.Index;
- return *this;
-}
-
-ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const
-{
- ip::address realmIp;
-
- // Attempt to send best address for client
- if (clientAddr.is_loopback())
- {
- // Try guessing if realm is also connected locally
- if (LocalAddress.is_loopback() || ExternalAddress.is_loopback())
- realmIp = clientAddr;
- else
- {
- // Assume that user connecting from the machine that bnetserver is located on
- // has all realms available in his local network
- realmIp = LocalAddress;
- }
- }
- else
- {
- if (clientAddr.is_v4() &&
- (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) ==
- (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()))
- {
- realmIp = LocalAddress;
- }
- else
- realmIp = ExternalAddress;
- }
-
- ip::tcp::endpoint endpoint(realmIp, Port);
-
- // Return external IP
- return endpoint;
-}
-
RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr), _worldListener(nullptr)
{
}
diff --git a/src/server/bnetserver/Realms/RealmList.h b/src/server/bnetserver/Realms/RealmList.h
index dc78a00dfdd..718e26d2564 100644
--- a/src/server/bnetserver/Realms/RealmList.h
+++ b/src/server/bnetserver/Realms/RealmList.h
@@ -20,6 +20,7 @@
#define _REALMLIST_H
#include "Common.h"
+#include "Realm.h"
#include "WorldListener.h"
#include <boost/asio/ip/address.hpp>
#include <boost/asio/ip/tcp.hpp>
@@ -28,67 +29,6 @@
using namespace boost::asio;
-enum RealmFlags
-{
- REALM_FLAG_NONE = 0x00,
- REALM_FLAG_INVALID = 0x01,
- REALM_FLAG_OFFLINE = 0x02,
- REALM_FLAG_SPECIFYBUILD = 0x04,
- REALM_FLAG_UNK1 = 0x08,
- REALM_FLAG_UNK2 = 0x10,
- REALM_FLAG_RECOMMENDED = 0x20,
- REALM_FLAG_NEW = 0x40,
- REALM_FLAG_FULL = 0x80
-};
-
-#pragma pack(push, 1)
-
-namespace Battlenet
-{
- struct RealmHandle;
-
- struct RealmId
- {
- RealmId() : Region(0), Battlegroup(0), Index(0), Build(0) { }
- RealmId(uint8 region, uint8 battlegroup, uint32 index, uint32 build)
- : Region(region), Battlegroup(battlegroup), Index(index), Build(build) { }
-
- uint8 Region;
- uint8 Battlegroup;
- uint32 Index;
- uint32 Build;
-
- bool operator<(RealmId const& r) const
- {
- return memcmp(this, &r, sizeof(RealmId) - sizeof(Build)) < 0;
- }
-
- RealmId& operator=(RealmHandle const& handle);
- };
-}
-
-#pragma pack(pop)
-
-// Storage object for a realm
-struct Realm
-{
- Battlenet::RealmId Id;
- ip::address ExternalAddress;
- ip::address LocalAddress;
- ip::address LocalSubnetMask;
- uint16 Port;
- std::string Name;
- uint8 Type;
- RealmFlags Flags;
- uint8 Timezone;
- AccountTypes AllowedSecurityLevel;
- float PopulationLevel;
- bool Updated;
- bool Keep;
-
- ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const;
-};
-
/// Storage object for the list of realms on the server
class RealmList
{
diff --git a/src/server/bnetserver/Realms/WorldListener.cpp b/src/server/bnetserver/Realms/WorldListener.cpp
index 30886a67310..9c9f1029e87 100644
--- a/src/server/bnetserver/Realms/WorldListener.cpp
+++ b/src/server/bnetserver/Realms/WorldListener.cpp
@@ -98,7 +98,9 @@ void WorldListener::HandleToonOnlineStatusChange(Battlenet::RealmHandle const& r
if (online)
{
Battlenet::WoWRealm::ToonReady* toonReady = new Battlenet::WoWRealm::ToonReady();
- toonReady->Realm = realm;
+ toonReady->Realm.Battlegroup = realm.Battlegroup;
+ toonReady->Realm.Index = realm.Index;
+ toonReady->Realm.Region = realm.Region;
toonReady->Guid = toonHandle.Guid;
toonReady->Name = toonHandle.Name;
session->AsyncWrite(toonReady);
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index c06ade69f01..401844b6151 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -29,6 +29,7 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "WorldPacket.h"
+#include "WorldStatePackets.h"
Battlefield::Battlefield()
{
@@ -351,7 +352,7 @@ void Battlefield::DoPlaySoundToAll(uint32 SoundID)
data << uint32(SoundID);
data << uint64(0);
- BroadcastPacketToWar(data);
+ BroadcastPacketToWar(&data);
}
bool Battlefield::HasPlayer(Player* player) const
@@ -410,28 +411,28 @@ void Battlefield::TeamCastSpell(TeamId team, int32 spellId)
}
}
-void Battlefield::BroadcastPacketToZone(WorldPacket& data) const
+void Battlefield::BroadcastPacketToZone(WorldPacket const* data) const
{
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr))
- player->SendDirectMessage(&data);
+ player->SendDirectMessage(data);
}
-void Battlefield::BroadcastPacketToQueue(WorldPacket& data) const
+void Battlefield::BroadcastPacketToQueue(WorldPacket const* data) const
{
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
for (GuidSet::const_iterator itr = m_PlayersInQueue[team].begin(); itr != m_PlayersInQueue[team].end(); ++itr)
if (Player* player = ObjectAccessor::FindConnectedPlayer(*itr))
- player->SendDirectMessage(&data);
+ player->SendDirectMessage(data);
}
-void Battlefield::BroadcastPacketToWar(WorldPacket& data) const
+void Battlefield::BroadcastPacketToWar(WorldPacket const* data) const
{
for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team)
for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(*itr))
- player->SendDirectMessage(&data);
+ player->SendDirectMessage(data);
}
void Battlefield::SendWarning(uint8 id, WorldObject const* target /*= nullptr*/)
@@ -440,12 +441,13 @@ void Battlefield::SendWarning(uint8 id, WorldObject const* target /*= nullptr*/)
sCreatureTextMgr->SendChat(stalker, id, target);
}
-void Battlefield::SendUpdateWorldState(uint32 field, uint32 value)
+void Battlefield::SendUpdateWorldState(uint32 variable, uint32 value, bool hidden /*= false*/)
{
- for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
- for (GuidSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr)
- if (Player* player = ObjectAccessor::FindPlayer(*itr))
- player->SendUpdateWorldState(field, value);
+ WorldPackets::WorldState::UpdateWorldState worldstate;
+ worldstate.VariableID = variable;
+ worldstate.Value = value;
+ worldstate.Hidden = hidden;
+ BroadcastPacketToZone(worldstate.Write());
}
void Battlefield::RegisterZone(uint32 zoneId)
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
index 29b8f4a5126..03557779ab1 100644
--- a/src/server/game/Battlefield/Battlefield.h
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -200,7 +200,7 @@ class Battlefield : public ZoneScript
virtual bool SetupBattlefield() { return true; }
/// Update data of a worldstate to all players present in zone
- void SendUpdateWorldState(uint32 field, uint32 value);
+ void SendUpdateWorldState(uint32 variable, uint32 value, bool hidden = false);
/**
* \brief Called every time for update bf data and time
@@ -397,9 +397,9 @@ class Battlefield : public ZoneScript
virtual void SendRemoveWorldStates(Player* /*player*/) { }
// use for send a packet for all player list
- void BroadcastPacketToZone(WorldPacket& data) const;
- void BroadcastPacketToQueue(WorldPacket& data) const;
- void BroadcastPacketToWar(WorldPacket& data) const;
+ void BroadcastPacketToZone(WorldPacket const* data) const;
+ void BroadcastPacketToQueue(WorldPacket const* data) const;
+ void BroadcastPacketToWar(WorldPacket const* data) const;
// CapturePoint system
void AddCapturePoint(BfCapturePoint* cp) { m_capturePoints[cp->GetCapturePointEntry()] = cp; }
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 396b549c0bc..be043aa289a 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -37,6 +37,7 @@
#include "SpellAuras.h"
#include "Util.h"
#include "WorldPacket.h"
+#include "WorldStatePackets.h"
#include "Transport.h"
namespace Trinity
@@ -634,14 +635,14 @@ Position const* Battleground::GetTeamStartPosition(TeamId teamId) const
return &StartPosition[teamId];
}
-void Battleground::SendPacketToAll(WorldPacket* packet)
+void Battleground::SendPacketToAll(WorldPacket const* packet) const
{
for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
if (Player* player = _GetPlayer(itr, "SendPacketToAll"))
player->SendDirectMessage(packet);
}
-void Battleground::SendPacketToTeam(uint32 TeamID, WorldPacket* packet, Player* sender, bool self)
+void Battleground::SendPacketToTeam(uint32 TeamID, WorldPacket const* packet, Player* sender, bool self) const
{
for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
@@ -716,18 +717,13 @@ void Battleground::RewardReputationToTeam(uint32 faction_id, uint32 Reputation,
}
}
-void Battleground::UpdateWorldState(uint32 Field, uint32 Value)
+void Battleground::UpdateWorldState(uint32 variable, uint32 value, bool hidden /*= false*/)
{
- WorldPacket data;
- sBattlegroundMgr->BuildUpdateWorldStatePacket(&data, Field, Value);
- SendPacketToAll(&data);
-}
-
-void Battleground::UpdateWorldStateForPlayer(uint32 field, uint32 value, Player* player)
-{
- WorldPacket data;
- sBattlegroundMgr->BuildUpdateWorldStatePacket(&data, field, value);
- player->SendDirectMessage(&data);
+ WorldPackets::WorldState::UpdateWorldState worldstate;
+ worldstate.VariableID = variable;
+ worldstate.Value = value;
+ worldstate.Hidden = hidden;
+ SendPacketToAll(worldstate.Write());
}
void Battleground::EndBattleground(uint32 winner)
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index fc52178c52d..aa0bb6fbb4c 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -347,8 +347,8 @@ class Battleground
// Packet Transfer
// method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!)
virtual void FillInitialWorldStates(WorldPacket& /*data*/) { }
- void SendPacketToTeam(uint32 TeamID, WorldPacket* packet, Player* sender = NULL, bool self = true);
- void SendPacketToAll(WorldPacket* packet);
+ void SendPacketToTeam(uint32 TeamID, WorldPacket const* packet, Player* sender = NULL, bool self = true) const;
+ void SendPacketToAll(WorldPacket const* packet) const;
void SendChatMessage(Creature* source, uint8 textId, WorldObject* target = NULL);
@@ -361,8 +361,7 @@ class Battleground
void RemoveAuraOnTeam(uint32 SpellID, uint32 TeamID);
void RewardHonorToTeam(uint32 Honor, uint32 TeamID);
void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID);
- void UpdateWorldState(uint32 Field, uint32 Value);
- void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player* player);
+ void UpdateWorldState(uint32 variable, uint32 value, bool hidden = false);
virtual void EndBattleground(uint32 winner);
void BlockMovement(Player* player);
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index eae6a831290..e1a3a9b065c 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -426,13 +426,6 @@ void BattlegroundMgr::BuildStatusFailedPacket(WorldPacket* data, Battleground* b
data->WriteByteSeq(unkGuid3[5]);
}
-void BattlegroundMgr::BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value)
-{
- data->Initialize(SMSG_UPDATE_WORLD_STATE, 4+4);
- *data << uint32(field);
- *data << uint32(value);
-}
-
void BattlegroundMgr::BuildPlaySoundPacket(WorldPacket* data, uint32 soundid)
{
data->Initialize(SMSG_PLAY_SOUND, 4 + 8);
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index 23689c03fba..9e330373685 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -74,7 +74,6 @@ class BattlegroundMgr
void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, ObjectGuid guid);
void BuildBattlegroundListPacket(WorldPacket* data, ObjectGuid guid, Player* player, BattlegroundTypeId bgTypeId);
void BuildStatusFailedPacket(WorldPacket* data, Battleground* bg, Player* pPlayer, uint8 QueueSlot, GroupJoinBattlegroundResult result);
- void BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value);
void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType);
void BuildPlaySoundPacket(WorldPacket* data, uint32 soundId);
void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid guid);
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index 034f7c91999..1663f4da049 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -179,9 +179,9 @@ void BattlegroundEY::CheckSomeoneJoinedPoint()
{
//player joined point!
//show progress bar
- UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, player);
- UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[i], player);
- UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, player);
+ player->SendUpdateWorldState(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY);
+ player->SendUpdateWorldState(PROGRESS_BAR_STATUS, m_PointBarStatus[i]);
+ player->SendUpdateWorldState(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW);
//add player to point
m_PlayersNearPoint[i].push_back(m_PlayersNearPoint[EY_POINTS_MAX][j]);
//remove player from "free space"
@@ -222,7 +222,7 @@ void BattlegroundEY::CheckSomeoneLeftPoint()
{
m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]);
m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j);
- this->UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, player);
+ player->SendUpdateWorldState(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW);
}
else
{
@@ -265,7 +265,7 @@ void BattlegroundEY::UpdatePointStatuses()
Player* player = ObjectAccessor::FindPlayer(m_PlayersNearPoint[point][i]);
if (player)
{
- this->UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[point], player);
+ player->SendUpdateWorldState(PROGRESS_BAR_STATUS, m_PointBarStatus[point]);
//if point owner changed we must evoke event!
if (pointOwnerTeamId != m_PointOwnedByTeam[point])
{
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index bcf1a33a626..d18fce9b829 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -128,6 +128,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/shared/Logging
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
${CMAKE_SOURCE_DIR}/src/server/shared/Packets
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Realm
${CMAKE_SOURCE_DIR}/src/server/shared/Threading
${CMAKE_SOURCE_DIR}/src/server/shared/Utilities
${CMAKE_SOURCE_DIR}/src/server/ipc
diff --git a/src/server/game/Entities/Object/Updates/UpdateData.cpp b/src/server/game/Entities/Object/Updates/UpdateData.cpp
index df7f6fdcc77..74f6b62e398 100644
--- a/src/server/game/Entities/Object/Updates/UpdateData.cpp
+++ b/src/server/game/Entities/Object/Updates/UpdateData.cpp
@@ -45,11 +45,11 @@ void UpdateData::AddUpdateBlock(const ByteBuffer &block)
bool UpdateData::BuildPacket(WorldPacket* packet)
{
ASSERT(packet->empty()); // shouldn't happen
- packet->Initialize(SMSG_UPDATE_OBJECT, 2 + 4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos());
+ packet->Initialize(SMSG_UPDATE_OBJECT, 2 + 4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos(), CONNECTION_TYPE_INSTANCE);
*packet << uint32(m_blockCount);
*packet << uint16(m_map);
-
+
if (packet->WriteBit(!m_outOfRangeGUIDs.empty()))
{
*packet << uint16(0);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 99561741931..1ad85c237ac 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -41,6 +41,7 @@
#include "DisableMgr.h"
#include "Formulas.h"
#include "GameEventMgr.h"
+#include "GameObjectAI.h"
#include "GossipDef.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
@@ -55,6 +56,7 @@
#include "Log.h"
#include "MapInstanced.h"
#include "MapManager.h"
+#include "MovementStructures.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
@@ -81,8 +83,7 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
-#include "MovementStructures.h"
-#include "GameObjectAI.h"
+#include "WorldStatePackets.h"
#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)
@@ -6516,7 +6517,7 @@ void Player::SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr)
VisitNearbyWorldObject(GetVisibilityRange(), notifier);
}
-void Player::SendDirectMessage(WorldPacket* data)
+void Player::SendDirectMessage(WorldPacket const* data)
{
m_session->SendPacket(data);
}
@@ -9084,13 +9085,13 @@ void Player::SendNotifyLootItemRemoved(uint8 lootSlot)
GetSession()->SendPacket(&data);
}
-void Player::SendUpdateWorldState(uint32 Field, uint32 Value)
+void Player::SendUpdateWorldState(uint32 variable, uint32 value, bool hidden /*= false*/)
{
- WorldPacket data(SMSG_UPDATE_WORLD_STATE, 4+4+1);
- data << Field;
- data << Value;
- data << uint8(0);
- GetSession()->SendPacket(&data);
+ WorldPackets::WorldState::UpdateWorldState worldstate;
+ worldstate.VariableID = variable;
+ worldstate.Value = value;
+ worldstate.Hidden = hidden;
+ SendDirectMessage(worldstate.Write());
}
void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
@@ -9110,22 +9111,22 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid)
data << uint32(areaid); // area id, new 2.1.0
size_t countPos = data.wpos();
data << uint16(0); // count of uint64 blocks
- data << uint32(0x8d8) << uint32(0x0); // 1
- data << uint32(0x8d7) << uint32(0x0); // 2
- data << uint32(0x8d6) << uint32(0x0); // 3
- data << uint32(0x8d5) << uint32(0x0); // 4
- data << uint32(0x8d4) << uint32(0x0); // 5
- data << uint32(0x8d3) << uint32(0x0); // 6
- // 7 1 - Arena season in progress, 0 - end of season
- data << uint32(0xC77) << uint32(sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS));
- // 8 Arena season id
- data << uint32(0xF3D) << uint32(sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID));
+ data << uint32(2264) << uint32(0); // 1
+ data << uint32(2263) << uint32(0); // 2
+ data << uint32(2262) << uint32(0); // 3
+ data << uint32(2261) << uint32(0); // 4
+ data << uint32(2260) << uint32(0); // 5
+ data << uint32(2259) << uint32(0); // 6
+
+ data << uint32(3191) << uint32(sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS) ? sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) : 0); // 7 Current Season - Arena season in progress
+ // 0 - End of season
+ data << uint32(3901) << uint32(sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) - sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)); // 8 PreviousSeason
if (mapid == 530) // Outland
{
- data << uint32(0x9bf) << uint32(0x0); // 7
- data << uint32(0x9bd) << uint32(0xF); // 8
- data << uint32(0x9bb) << uint32(0xF); // 9
+ data << uint32(2495) << uint32(0x0); // 7
+ data << uint32(2493) << uint32(0xF); // 8
+ data << uint32(2491) << uint32(0xF); // 9
}
// insert <field> <value>
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index e0655a39daa..0f5418e24e7 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2248,8 +2248,8 @@ class Player : public Unit, public GridObject<Player>
void DeleteEquipmentSet(uint64 setGuid);
void SendInitWorldStates(uint32 zone, uint32 area);
- void SendUpdateWorldState(uint32 Field, uint32 Value);
- void SendDirectMessage(WorldPacket* data);
+ void SendUpdateWorldState(uint32 variable, uint32 value, bool hidden = false);
+ void SendDirectMessage(WorldPacket const* data);
void SendBGWeekendWorldStates();
void SendBattlefieldWorldStates();
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 780360dc945..cf46272080e 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -19,7 +19,6 @@
#include "GameEventMgr.h"
#include "World.h"
#include "ObjectMgr.h"
-#include "WorldPacket.h"
#include "PoolMgr.h"
#include "Language.h"
#include "Log.h"
@@ -29,6 +28,7 @@
#include "BattlegroundMgr.h"
#include "UnitAI.h"
#include "GameObjectAI.h"
+#include "WorldStatePackets.h"
bool GameEventMgr::CheckOneGameEvent(uint16 entry) const
{
@@ -1486,9 +1486,11 @@ void GameEventMgr::UpdateWorldStates(uint16 event_id, bool Activate)
BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId);
if (bl && bl->HolidayWorldStateId)
{
- WorldPacket data;
- sBattlegroundMgr->BuildUpdateWorldStatePacket(&data, bl->HolidayWorldStateId, Activate ? 1 : 0);
- sWorld->SendGlobalMessage(&data);
+ WorldPackets::WorldState::UpdateWorldState worldstate;
+ worldstate.VariableID = bl->HolidayWorldStateId;
+ worldstate.Value = Activate;
+ //worldstate.Hidden = false;
+ sWorld->SendGlobalMessage(worldstate.Write());
}
}
}
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 13e390bc362..576ebf4f547 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -2678,7 +2678,7 @@ void ObjectMgr::LoadItemTemplates()
itemTemplate.ItemId = itemId;
itemTemplate.Class = uint32(fields[1].GetUInt8());
itemTemplate.SubClass = uint32(fields[2].GetUInt8());
- itemTemplate.SoundOverrideSubclass = fields[3].GetInt32();
+ itemTemplate.SoundOverrideSubclass = fields[3].GetInt8();
itemTemplate.Name1 = fields[4].GetString();
itemTemplate.DisplayInfoID = fields[5].GetUInt32();
itemTemplate.Quality = uint32(fields[6].GetUInt8());
@@ -6365,11 +6365,11 @@ void ObjectMgr::SetHighestGuids()
result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject");
if (result)
- _gameObjectGuidGenerator.Set((*result)[0].GetUInt32() + 1);
+ _gameObjectGuidGenerator.Set((*result)[0].GetUInt64() + 1);
result = WorldDatabase.Query("SELECT MAX(guid) FROM transports");
if (result)
- _moTransportGuidGenerator.Set((*result)[0].GetUInt32() + 1);
+ _moTransportGuidGenerator.Set((*result)[0].GetUInt64() + 1);
result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse");
if (result)
@@ -8832,8 +8832,8 @@ void ObjectMgr::LoadCreatureClassLevelStats()
}
}
- stats.BaseMana = fields[8].GetUInt16();
- stats.BaseArmor = fields[9].GetUInt16();
+ stats.BaseMana = fields[8].GetUInt32();
+ stats.BaseArmor = fields[9].GetUInt32();
stats.AttackPower = fields[10].GetUInt16();
stats.RangedAttackPower = fields[11].GetUInt16();
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index e35baca3efc..bad38c91e79 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -65,7 +65,7 @@ void WorldSession::SendAuctionHello(ObjectGuid guid, Creature* unit)
if (!ahEntry)
return;
- WorldPacket data(MSG_AUCTION_HELLO, 12);
+ WorldPacket data(SMSG_AUCTION_HELLO, 12);
data << guid;
data << uint32(ahEntry->houseId);
data << uint8(1); // 3.3.3: 1 - AH enabled, 0 - AH disabled
@@ -74,7 +74,7 @@ void WorldSession::SendAuctionHello(ObjectGuid guid, Creature* unit)
void WorldSession::SendAuctionCommandResult(AuctionEntry* auction, uint32 action, uint32 errorCode, uint32 /*bidError = 0*/)
{
- WorldPackets::AuctionHousePackets::AuctionCommandResult auctionCommandResult;
+ WorldPackets::AuctionHouse::AuctionCommandResult auctionCommandResult;
auctionCommandResult.InitializeAuction(auction);
auctionCommandResult.Action = action;
auctionCommandResult.ErrorCode = errorCode;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 6845ebb383b..dd6090a0d62 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -19,7 +19,10 @@
#include "AccountMgr.h"
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
+#include "AuthenticationPackets.h"
#include "Battleground.h"
+#include "BattlegroundPackets.h"
+#include "BattlenetServerManager.h"
#include "CalendarMgr.h"
#include "CharacterPackets.h"
#include "Chat.h"
@@ -50,7 +53,6 @@
#include "World.h"
#include "WorldPacket.h"
#include "WorldSession.h"
-#include "BattlenetServerManager.h"
class LoginQueryHolder : public SQLQueryHolder
{
@@ -761,7 +763,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin&
TC_LOG_DEBUG("network", "WORLD: Recvd Player Logon Message");
- m_playerLoading = true;
+ m_playerLoading = playerLogin.Guid;
TC_LOG_DEBUG("network", "Character %s logging in", playerLogin.Guid.ToString().c_str());
@@ -772,11 +774,32 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin&
return;
}
- LoginQueryHolder* holder = new LoginQueryHolder(GetAccountId(), playerLogin.Guid);
+ boost::system::error_code ignored_error;
+ boost::asio::ip::tcp::endpoint instanceAddress = realm.GetAddressForClient(boost::asio::ip::address::from_string(GetRemoteAddress(), ignored_error));
+ instanceAddress.port(sWorld->getIntConfig(CONFIG_PORT_INSTANCE));
+
+ WorldPackets::Auth::ConnectTo connectTo;
+ connectTo.Key = MAKE_PAIR64(GetAccountId(), CONNECTION_TYPE_INSTANCE);
+ connectTo.Serial = 1;
+ connectTo.Payload.Where = instanceAddress;
+ connectTo.Con = CONNECTION_TYPE_INSTANCE;
+
+ SendPacket(connectTo.Write());
+}
+
+void WorldSession::HandleContinuePlayerLogin()
+{
+ if (!PlayerLoading() || GetPlayer())
+ {
+ KickPlayer();
+ return;
+ }
+
+ LoginQueryHolder* holder = new LoginQueryHolder(GetAccountId(), m_playerLoading);
if (!holder->Initialize())
{
delete holder; // delete all unprocessed queries
- m_playerLoading = false;
+ m_playerLoading.Clear();
return;
}
@@ -809,7 +832,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick
delete pCurrChar; // delete it manually
delete holder; // delete all unprocessed queries
- m_playerLoading = false;
+ m_playerLoading.Clear();
return;
}
@@ -870,6 +893,20 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
TC_LOG_DEBUG("network", "WORLD: Sent motd (SMSG_MOTD)");
}
+ SendSetTimeZoneInformation();
+
+ // Send PVPSeason
+ {
+ WorldPackets::Battleground::PVPSeason season;
+ season.PreviousSeason = sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) - sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS);
+
+ if (sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS))
+ season.CurrentSeason = sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID);
+
+ SendPacket(season.Write());
+ TC_LOG_DEBUG("network", "WORLD: Sent PVPSeason");
+ }
+
// send server info
{
if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1)
@@ -1049,7 +1086,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED))
pCurrChar->SetStandState(UNIT_STAND_STATE_STAND);
- m_playerLoading = false;
+ m_playerLoading.Clear();
// Handle Login-Achievements (should be handled after loading)
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN, 1);
diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp
index 014e9f7b9d6..39e3edb30ed 100644
--- a/src/server/game/Handlers/LFGHandler.cpp
+++ b/src/server/game/Handlers/LFGHandler.cpp
@@ -115,7 +115,9 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData)
{
uint32 dungeon;
recvData >> dungeon;
- newDungeons.insert((dungeon & 0x00FFFFFF)); // remove the type from the dungeon entry
+ dungeon &= 0x00FFFFFF; // remove the type from the dungeon entry
+ if (dungeon)
+ newDungeons.insert(dungeon);
}
TC_LOG_DEBUG("lfg", "CMSG_LFG_JOIN %s roles: %u, Dungeons: %u, Comment: %s",
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 0e43a63c98e..ad727fc17d2 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -677,6 +677,12 @@ void AddSC_zangarmarsh();
// Maelstrom
void AddSC_kezan();
+void AddSC_instance_stonecore(); // Stonecore
+void AddSC_stonecore();
+void AddSC_boss_corborus();
+void AddSC_boss_slabhide();
+void AddSC_boss_ozruk();
+void AddSC_boss_high_priestess_azil();
// Events
void AddSC_event_childrens_week();
@@ -1411,6 +1417,12 @@ void AddMaelstromScripts()
{
#ifdef SCRIPTS
AddSC_kezan();
+ AddSC_instance_stonecore(); // Stonecore
+ AddSC_stonecore();
+ AddSC_boss_corborus();
+ AddSC_boss_slabhide();
+ AddSC_boss_ozruk();
+ AddSC_boss_high_priestess_azil();
#endif
}
diff --git a/src/server/game/Server/Packet.cpp b/src/server/game/Server/Packet.cpp
index 10b472bee67..ee805c18610 100644
--- a/src/server/game/Server/Packet.cpp
+++ b/src/server/game/Server/Packet.cpp
@@ -17,6 +17,164 @@
#include "Packet.h"
+inline bool IsInstanceOnlyOpcode(uint32 opcode)
+{
+ // TODO: Use names when known
+ switch (opcode)
+ {
+ case 0x000F: // Client
+ case 0x0111: // Client
+ case 0x03E4: // Client
+ case 0x0549: // Client
+ case 0x054C: // Client
+ case 0x055A: // Client
+ case 0x056C: // Client
+ case 0x057A: // Client
+ case 0x057B: // Client
+ case 0x05CC: // Client
+ case 0x05EA: // Client
+ case 0x05EC: // Client
+ case 0x05F9: // Client
+ case 0x05FB: // Client
+ case 0x074C: // Client
+ case 0x075B: // Client
+ case 0x076C: // Client
+ case 0x077B: // Client
+ case 0x077C: // Client
+ case 0x07CC: // Client
+ case 0x07DB: // Client
+ case 0x07EC: // Client
+ case 0x07FB: // Client
+ case 0x07FC: // Client
+ case 0x0827: // Client
+ case 0x0935: // Client
+ case 0x0F0C: // ClientSpell
+ case 0x0F10: // ClientSpell
+ case 0x0F1B: // ClientSpell
+ case 0x0F1C: // ClientSpell
+ case 0x0F20: // ClientSpell
+ case 0x0F2C: // ClientSpell
+ case 0x0F2F: // ClientSpell
+ case 0x0F3B: // ClientSpell
+ case 0x0F8B: // ClientSpell
+ case 0x0F8C: // ClientSpell
+ case 0x0F90: // ClientSpell
+ case 0x0F9F: // ClientSpell
+ case 0x0FA0: // ClientSpell
+ case SMSG_ATTACKSTOP: // Client
+ case 0x14C9: // Client
+ case 0x154A: // Client
+ case 0x155A: // Client
+ case 0x155C: // Client
+ case SMSG_QUESTGIVER_STATUS: // ClientQuest
+ case 0x156A: // Client
+ case 0x156B: // Client
+ case 0x157A: // Client
+ case 0x157B: // Client
+ case 0x15DC: // Client
+ case 0x15EB: // Client
+ case 0x15FB: // Client
+ case 0x170C: // ClientSpell
+ case 0x171C: // ClientSpell
+ case 0x171F: // ClientSpell
+ case 0x172C: // ClientSpell
+ case 0x172F: // ClientSpell
+ case 0x173C: // ClientSpell
+ case 0x173F: // ClientSpell
+ case 0x1740: // ClientSpell
+ case 0x1790: // ClientSpell
+ case 0x179B: // ClientSpell
+ case 0x179F: // ClientSpell
+ case SMSG_ATTACKSTART: // Client
+ case 0x1D82: // ClientQuest
+ case 0x1D83: // ClientQuest
+ case 0x1D85: // ClientQuest
+ case 0x1D87: // ClientQuest
+ case 0x1D93: // ClientQuest
+ case 0x1D96: // ClientQuest
+ case 0x1D97: // ClientQuest
+ case 0x1DA1: // ClientQuest
+ case 0x1DA2: // ClientQuest
+ case 0x1DA3: // ClientQuest
+ case 0x1DA4: // ClientQuest
+ case 0x1DA5: // ClientQuest
+ case 0x1DA7: // ClientQuest
+ case SMSG_QUERY_TIME_RESPONSE: // Client
+ case 0x1DC2: // ClientQuest
+ case 0x1DC6: // ClientQuest
+ case 0x1DC7: // ClientQuest
+ case 0x1DD2: // ClientQuest
+ case 0x1DD3: // ClientQuest
+ case 0x1DD6: // ClientQuest
+ case 0x1DD7: // ClientQuest
+ case 0x1DD8: // ClientQuest
+ case 0x1DE4: // ClientQuest
+ case 0x1DE5: // ClientQuest
+ case 0x1DE7: // ClientQuest
+ case 0x1F02: // ClientQuest
+ case 0x1F06: // ClientQuest
+ case 0x1F07: // ClientQuest
+ case 0x1F0C: // ClientSpell
+ case 0x1F12: // ClientQuest
+ case 0x1F13: // ClientQuest
+ case 0x1F16: // ClientQuest
+ case 0x1F17: // ClientQuest
+ case 0x1F18: // ClientQuest
+ case 0x1F1C: // ClientSpell
+ case 0x1F1F: // ClientSpell
+ case 0x1F24: // ClientQuest
+ case 0x1F25: // ClientQuest
+ case 0x1F27: // ClientQuest
+ case 0x1F2C: // ClientSpell
+ case 0x1F2F: // ClientSpell
+ case 0x1F3C: // ClientSpell
+ case 0x1F3F: // ClientSpell
+ case 0x1F40: // ClientSpell
+ case 0x1F44: // ClientQuest
+ case 0x1F48: // ClientQuest
+ case 0x1F51: // ClientQuest
+ case 0x1F55: // ClientQuest
+ case 0x1F57: // ClientQuest
+ case 0x1F61: // ClientQuest
+ case 0x1F63: // ClientQuest
+ case 0x1F64: // ClientQuest
+ case 0x1F65: // ClientQuest
+ case 0x1F67: // ClientQuest
+ case 0x1F85: // ClientQuest
+ case 0x1F86: // ClientQuest
+ case 0x1F87: // ClientQuest
+ case 0x1F90: // ClientSpell
+ case 0x1F92: // ClientQuest
+ case 0x1F94: // ClientQuest
+ case 0x1F96: // ClientQuest
+ case 0x1F97: // ClientQuest
+ case 0x1F9B: // ClientSpell
+ case 0x1F9F: // ClientSpell
+ case 0x1FA1: // ClientQuest
+ case 0x1FA2: // ClientQuest
+ case 0x1FA3: // ClientQuest
+ case 0x1FA4: // ClientQuest
+ case 0x1FA5: // ClientQuest
+ case 0x1FA7: // ClientQuest
+ case 0x1FC2: // ClientQuest
+ case 0x1FC6: // ClientQuest
+ case 0x1FC7: // ClientQuest
+ case 0x1FD2: // ClientQuest
+ case 0x1FD3: // ClientQuest
+ case 0x1FD6: // ClientQuest
+ case 0x1FD7: // ClientQuest
+ case 0x1FD8: // ClientQuest
+ case 0x1FE4: // ClientQuest
+ case 0x1FE5: // ClientQuest
+ case 0x1FE7: // ClientQuest
+ return true;
+ default:
+ return false;
+ }
+}
+
WorldPackets::ServerPacket::ServerPacket(OpcodeServer opcode, size_t initialSize /*= 200*/) : Packet(WorldPacket(opcode, initialSize))
{
+ if (IsInstanceOnlyOpcode(opcode))
+ _connectionIndex = CONNECTION_TYPE_INSTANCE;
}
diff --git a/src/server/game/Server/Packet.h b/src/server/game/Server/Packet.h
index 66061166ede..1a2ba87f90a 100644
--- a/src/server/game/Server/Packet.h
+++ b/src/server/game/Server/Packet.h
@@ -25,7 +25,11 @@ namespace WorldPackets
class Packet
{
public:
- Packet(WorldPacket&& worldPacket) : _worldPacket(std::move(worldPacket)) { }
+ Packet(WorldPacket&& worldPacket) : _worldPacket(std::move(worldPacket))
+ {
+ _connectionIndex = _worldPacket.GetConnection();
+ }
+
virtual ~Packet() = default;
Packet(Packet const& right) = delete;
@@ -35,9 +39,11 @@ namespace WorldPackets
virtual void Read() = 0;
size_t GetSize() const { return _worldPacket.size(); }
+ ConnectionType GetConnection() const { return _connectionIndex; }
protected:
WorldPacket _worldPacket;
+ ConnectionType _connectionIndex;
};
class ServerPacket : public Packet
diff --git a/src/server/game/Server/Packets/AuctionHousePackets.cpp b/src/server/game/Server/Packets/AuctionHousePackets.cpp
index 56fa0ed396b..bb1a10be254 100644
--- a/src/server/game/Server/Packets/AuctionHousePackets.cpp
+++ b/src/server/game/Server/Packets/AuctionHousePackets.cpp
@@ -19,10 +19,10 @@
#include "AuctionHouseMgr.h"
#include "ObjectGuid.h"
-WorldPackets::AuctionHousePackets::AuctionCommandResult::AuctionCommandResult()
+WorldPackets::AuctionHouse::AuctionCommandResult::AuctionCommandResult()
: ServerPacket(SMSG_AUCTION_COMMAND_RESULT, 4 + 4 + 4 + 8 + 4 + 8 + 8 + 8) { }
-void WorldPackets::AuctionHousePackets::AuctionCommandResult::InitializeAuction(AuctionEntry* auction)
+void WorldPackets::AuctionHouse::AuctionCommandResult::InitializeAuction(AuctionEntry* auction)
{
if (auction)
{
@@ -33,7 +33,7 @@ void WorldPackets::AuctionHousePackets::AuctionCommandResult::InitializeAuction(
}
}
-WorldPacket const* WorldPackets::AuctionHousePackets::AuctionCommandResult::Write()
+WorldPacket const* WorldPackets::AuctionHouse::AuctionCommandResult::Write()
{
_worldPacket << uint32(AuctionId);
_worldPacket << uint32(Action);
diff --git a/src/server/game/Server/Packets/AuctionHousePackets.h b/src/server/game/Server/Packets/AuctionHousePackets.h
index bf392246a20..4204c5c6afc 100644
--- a/src/server/game/Server/Packets/AuctionHousePackets.h
+++ b/src/server/game/Server/Packets/AuctionHousePackets.h
@@ -20,13 +20,11 @@
#include "Packet.h"
#include "ObjectGuid.h"
-class ObjectGuid;
-
struct AuctionEntry;
namespace WorldPackets
{
- namespace AuctionHousePackets
+ namespace AuctionHouse
{
class AuctionCommandResult final : public ServerPacket
{
@@ -54,4 +52,5 @@ namespace WorldPackets
};
}
}
-#endif
+
+#endif // AuctionHousePackets_h__
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp
index a57f5f60244..95f2379e82f 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.cpp
+++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp
@@ -585,3 +585,10 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write()
_worldPacket << uint8(Con);
return &_worldPacket;
}
+
+void WorldPackets::Auth::AuthContinuedSession::Read()
+{
+ _worldPacket >> DosResponse;
+ _worldPacket >> Key;
+ _worldPacket.read(Digest, SHA_DIGEST_LENGTH);
+}
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h
index 1d194b0b2a9..70aa38cac8e 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.h
+++ b/src/server/game/Server/Packets/AuthenticationPackets.h
@@ -168,6 +168,29 @@ namespace WorldPackets
BigNumber dmq1;
BigNumber iqmp;
};
+
+ class AuthContinuedSession final : public ClientPacket
+ {
+ public:
+ AuthContinuedSession(WorldPacket&& packet) : ClientPacket(std::move(packet))
+ {
+ memset(Digest, 0, SHA_DIGEST_LENGTH);
+ }
+
+ void Read() override;
+
+ uint64 DosResponse = 0;
+ uint64 Key = 0;
+ uint8 Digest[SHA_DIGEST_LENGTH];
+ };
+
+ class ResumeComms final : public ServerPacket
+ {
+ public:
+ ResumeComms() : ServerPacket(SMSG_RESUME_COMMS, 0) { }
+
+ WorldPacket const* Write() override { return &_worldPacket; }
+ };
}
}
diff --git a/src/server/game/Server/Packets/BattlegroundPackets.cpp b/src/server/game/Server/Packets/BattlegroundPackets.cpp
new file mode 100644
index 00000000000..8a1bec1173b
--- /dev/null
+++ b/src/server/game/Server/Packets/BattlegroundPackets.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "BattlegroundPackets.h"
+
+WorldPacket const* WorldPackets::Battleground::PVPSeason::Write()
+{
+ _worldPacket << uint32(CurrentSeason);
+ _worldPacket << uint32(PreviousSeason);
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/BattlegroundPackets.h b/src/server/game/Server/Packets/BattlegroundPackets.h
new file mode 100644
index 00000000000..77dc8238438
--- /dev/null
+++ b/src/server/game/Server/Packets/BattlegroundPackets.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef BattlegroundPackets_h__
+#define BattlegroundPackets_h__
+
+#include "Packet.h"
+
+namespace WorldPackets
+{
+ namespace Battleground
+ {
+ class PVPSeason final : public ServerPacket
+ {
+ public:
+ PVPSeason() : ServerPacket(SMSG_PVP_SEASON, 8) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 PreviousSeason = 0;
+ uint32 CurrentSeason = 0;
+ };
+ }
+}
+
+#endif // BattlegroundPackets_h__
diff --git a/src/server/game/Server/Packets/GuildPackets.cpp b/src/server/game/Server/Packets/GuildPackets.cpp
index ee864b256bb..b94fb7839bf 100644
--- a/src/server/game/Server/Packets/GuildPackets.cpp
+++ b/src/server/game/Server/Packets/GuildPackets.cpp
@@ -16,7 +16,6 @@
*/
#include "GuildPackets.h"
-#include "ObjectGuid.h"
WorldPackets::Guild::QueryGuildInfo::QueryGuildInfo(WorldPacket&& packet)
: ClientPacket(std::move(packet))
diff --git a/src/server/game/Server/Packets/GuildPackets.h b/src/server/game/Server/Packets/GuildPackets.h
index 17159a017e0..479ceba6280 100644
--- a/src/server/game/Server/Packets/GuildPackets.h
+++ b/src/server/game/Server/Packets/GuildPackets.h
@@ -19,8 +19,7 @@
#define GuildPackets_h__
#include "Packet.h"
-
-class ObjectGuid;
+#include "ObjectGuid.h"
namespace WorldPackets
{
diff --git a/src/server/game/Server/Packets/WorldStatePackets.cpp b/src/server/game/Server/Packets/WorldStatePackets.cpp
new file mode 100644
index 00000000000..7d062841003
--- /dev/null
+++ b/src/server/game/Server/Packets/WorldStatePackets.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "WorldStatePackets.h"
+
+WorldPackets::WorldState::InitWorldStates::InitWorldStates()
+ : ServerPacket(SMSG_INIT_WORLD_STATES, 16) { }
+
+WorldPacket const* WorldPackets::WorldState::InitWorldStates::Write()
+{
+ _worldPacket.reserve(16 + Worldstates.size() * 8);
+
+ _worldPacket << uint32(AreaID);
+ _worldPacket << uint32(SubareaID);
+ _worldPacket << uint32(MapID);
+
+ _worldPacket << uint32(Worldstates.size());
+ for (WorldStateInfo const& wsi : Worldstates)
+ {
+ _worldPacket << uint32(wsi.VariableID);
+ _worldPacket << uint32(wsi.Value);
+ }
+
+ return &_worldPacket;
+}
+
+WorldPackets::WorldState::UpdateWorldState::UpdateWorldState()
+ : ServerPacket(SMSG_UPDATE_WORLD_STATE, 9) { }
+
+WorldPacket const* WorldPackets::WorldState::UpdateWorldState::Write()
+{
+ _worldPacket << uint32(VariableID);
+ _worldPacket << int32(Value);
+ _worldPacket.WriteBit(Hidden);
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/WorldStatePackets.h b/src/server/game/Server/Packets/WorldStatePackets.h
new file mode 100644
index 00000000000..7f9cdfe80de
--- /dev/null
+++ b/src/server/game/Server/Packets/WorldStatePackets.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WorldStatePackets_h__
+#define WorldStatePackets_h__
+
+#include "Packet.h"
+
+namespace WorldPackets
+{
+ namespace WorldState
+ {
+ class InitWorldStates final : public ServerPacket
+ {
+ public:
+ struct WorldStateInfo
+ {
+ WorldStateInfo(uint32 variableID, int32 value)
+ : VariableID(variableID), Value(value) { }
+
+ uint32 VariableID;
+ int32 Value;
+ };
+
+ InitWorldStates();
+
+ WorldPacket const* Write() override;
+
+ uint32 AreaID = 0; ///< ZoneId
+ uint32 SubareaID = 0; ///< AreaId
+ uint32 MapID = 0; ///< MapId
+
+ std::list<WorldStateInfo> Worldstates;
+ };
+
+ class UpdateWorldState final : public ServerPacket
+ {
+ public:
+ UpdateWorldState();
+
+ WorldPacket const* Write() override;
+
+ int32 Value = 0;
+ bool Hidden = false; ///< @todo: research
+ uint32 VariableID = 0;
+ };
+ }
+}
+
+#endif // WorldStatePackets_h__
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index b22dc575c0c..97fc18a1c2f 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -130,6 +130,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_ARENA_TEAM_ROSTER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRosterOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_ATTACKSTOP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleAttackStopOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_ATTACKSWING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleAttackSwingOpcode );
+ DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_HELLO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionHelloOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_LIST_BIDDER_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListBidderItems );
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_LIST_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListItems );
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_LIST_OWNER_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListOwnerItems );
@@ -137,6 +138,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_PLACE_BID, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionPlaceBid );
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_REMOVE_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionRemoveItem );
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_SELL_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionSellItem );
+ DEFINE_OPCODE_HANDLER_OLD(CMSG_AUTH_CONTINUED_SESSION, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess );
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUTH_SESSION, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess );
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUTOBANK_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoBankItemOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_AUTOEQUIP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemOpcode );
@@ -160,6 +162,8 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLEMASTER_JOIN_ARENA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinArena );
DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLEMASTER_JOIN_RATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PAY_GET_PRODUCT_LIST_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PAY_GET_PURCHASE_LIST_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PET_NAME_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_BEGIN_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_BINDER_ACTIVATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBinderActivateOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_BUG, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBugOpcode );
@@ -497,13 +501,13 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEST_NPC_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestNPCQuery );
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEST_POI_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPOIQuery );
DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEST_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestQueryOpcode );
+ DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEUED_MESSAGES_END, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_HANDLER(CMSG_RANDOMIZE_CHAR_NAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::GenerateRandomCharacterName, &WorldSession::HandleRandomizeCharNameOpcode);
DEFINE_OPCODE_HANDLER_OLD(CMSG_READ_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleReadItem );
DEFINE_OPCODE_HANDLER_OLD(CMSG_REALM_SPLIT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRealmSplitOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_RECLAIM_CORPSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleReclaimCorpseOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_REDIRECTION_AUTH_PROOF, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_REFORGE_ITEM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleReforgeItemOpcode );
- DEFINE_HANDLER(CMSG_REORDER_CHARACTERS, STATUS_AUTHED, PROCESS_INPLACE, WorldPackets::Character::ReorderCharacters, &WorldSession::HandleReorderCharacters);
+ DEFINE_HANDLER(CMSG_REORDER_CHARACTERS, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::ReorderCharacters, &WorldSession::HandleReorderCharacters);
DEFINE_OPCODE_HANDLER_OLD(CMSG_REPAIR_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRepairItemOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_REPOP_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRepopRequestOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_REPORT_PVP_AFK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleReportPvPAFK );
@@ -549,6 +553,7 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_FACTION_ATWAR, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionAtWar );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_FACTION_INACTIVE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionInactiveOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_GUILD_BANK_TEXT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetGuildBankTabText );
+ DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_LOOT_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PET_SLOT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PREFERED_CEMETERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
@@ -576,7 +581,8 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_SUBMIT_COMPLAIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SUGGESTION_SUBMIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SUMMON_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSummonResponseOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_SUSPEND_TOKEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER_OLD(CMSG_SUSPEND_COMMS_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
+ DEFINE_OPCODE_HANDLER_OLD(CMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SWAP_INV_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapInvItemOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SWAP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapItem );
DEFINE_OPCODE_HANDLER_OLD(CMSG_SYNC_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
@@ -622,9 +628,6 @@ void OpcodeTable::Initialize()
DEFINE_OPCODE_HANDLER_OLD(CMSG_WORLD_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_WRAP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode );
DEFINE_OPCODE_HANDLER_OLD(CMSG_ZONEUPDATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleZoneUpdateOpcode );
- DEFINE_OPCODE_HANDLER_OLD(MSG_AUCTION_HELLO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionHelloOpcode );
- DEFINE_OPCODE_HANDLER_OLD(MSG_CHANNEL_START, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
- DEFINE_OPCODE_HANDLER_OLD(MSG_CHANNEL_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide );
DEFINE_OPCODE_HANDLER_OLD(MSG_CORPSE_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseQueryOpcode );
DEFINE_OPCODE_HANDLER_OLD(MSG_INSPECT_ARENA_TEAMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectArenaTeamsOpcode );
DEFINE_OPCODE_HANDLER_OLD(MSG_LIST_STABLED_PETS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleListStabledPetsOpcode );
@@ -679,6 +682,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_DATA_TIMES, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_INFO_RESPONSE, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_MOUNT_UPDATE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_RESTRICTED_WARNING, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACHIEVEMENT_DELETED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACHIEVEMENT_EARNED, STATUS_UNHANDLED);
@@ -692,7 +696,6 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AREA_TRIGGER_MESSAGE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AREA_TRIGGER_MOVEMENT_UPDATE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_ERROR, STATUS_UNHANDLED);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_SEASON_WORLD_STATE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_UNIT_DESTROYED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ARENA_TEAM_COMMAND_RESULT, STATUS_UNHANDLED);
@@ -711,6 +714,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_LIST_RESULT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_NOTIFICATION, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_COMMAND_RESULT, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_HELLO, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_PENDING_SALES, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_RESULT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_OWNER_LIST_RESULT, STATUS_UNHANDLED);
@@ -745,8 +749,12 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_INFO_THROTTLED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_JOINED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_LEFT, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_GET_DISTRIBUTION_LIST_RESPONSE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_GET_PRODUCT_LIST_RESPONSE, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_GET_PURCHASE_LIST_RESPONSE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_NAME_QUERY_RESPONSE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDER_CONFIRM, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDPOINTUPDATE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDZONEREPLY, STATUS_UNHANDLED);
@@ -782,6 +790,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_LIST, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_MEMBER_COUNT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_START, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_UPDATE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CREATE, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_UNHANDLED);
@@ -834,6 +844,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_CUSTOM_LOAD_SCREEN, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DAMAGE_CALC_LOG, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DANCE_QUERY_RESPONSE, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_DANCE_STUDIO_CREATE_RESULT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DB_REPLY, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DEATH_RELEASE_LOC, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_DEBUG_RUNE_REGEN, STATUS_UNHANDLED);
@@ -877,7 +888,6 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCEACTIONSHOW, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCED_DEATH_UPDATE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_ANIM, STATUS_UNHANDLED);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_SEND_QUEUED_PACKETS, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_SET_VEHICLE_REC_ID, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORGE_MASTER_SET, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_FRIEND_STATUS, STATUS_UNHANDLED);
@@ -1166,6 +1176,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_CREDIT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_LOG_DATA, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_OPTIONS_ENABLED, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_SEASON, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_TIME_RESPONSE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_OFFER_REWARD, STATUS_UNHANDLED);
@@ -1202,7 +1213,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REALM_SPLIT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REAL_GROUP_UPDATE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RECEIVED_MAIL, STATUS_UNHANDLED);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_REDIRECT_CLIENT, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_REDIRECT_CLIENT, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_EXPIRED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_FAILURE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFORGE_RESULT, STATUS_UNHANDLED);
@@ -1215,6 +1226,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_COMPRESSION_CONTEXT, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_FAILED_NOTIFY, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_COMMS, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_FAILED, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_UNHANDLED);
@@ -1312,7 +1324,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUPERCEDED_SPELL, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUPPRESS_NPC_GREETINGS, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_COMMS, STATUS_UNHANDLED);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_ERROR, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INFO, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INVOLUNTARILY_RESET, STATUS_UNHANDLED);
@@ -1353,7 +1365,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_OBJECT, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_SERVER_PLAYER_POSITION, STATUS_UNHANDLED);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WORLD_STATE, STATUS_UNHANDLED);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WORLD_STATE, STATUS_NEVER);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_ADD, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_REMOVE, STATUS_UNHANDLED);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_UPDATE, STATUS_UNHANDLED);
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index d8ac4b68d9e..879554e8bd6 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -26,6 +26,12 @@
#include "Common.h"
#include <iomanip>
+enum ConnectionType
+{
+ CONNECTION_TYPE_REALM = 0,
+ CONNECTION_TYPE_INSTANCE = 1
+};
+
enum OpcodeMisc : uint32
{
MAX_OPCODE = 0x1FFF,
@@ -70,6 +76,7 @@ enum OpcodeClient : uint32
CMSG_AUCTION_PLACE_BID = 0xBADD,
CMSG_AUCTION_REMOVE_ITEM = 0xBADD,
CMSG_AUCTION_SELL_ITEM = 0xBADD,
+ CMSG_AUTH_CONTINUED_SESSION = 0x0485,
CMSG_AUTH_SESSION = 0x0487,
CMSG_AUTOBANK_ITEM = 0xBADD,
CMSG_AUTOEQUIP_GROUND_ITEM = 0xBADD,
@@ -98,6 +105,8 @@ enum OpcodeClient : uint32
CMSG_BATTLEMASTER_JOIN_RATED = 0xBADD,
CMSG_BATTLEMASTER_HELLO = 0xBADD,
CMSG_BATTLE_PAY_GET_PRODUCT_LIST_QUERY = 0x1389,
+ CMSG_BATTLE_PAY_GET_PURCHASE_LIST_QUERY = 0x120C,
+ CMSG_BATTLE_PET_NAME_QUERY = 0x041C,
CMSG_BEGIN_TRADE = 0xBADD,
CMSG_BINDER_ACTIVATE = 0xBADD,
CMSG_BOT_DETECTED2 = 0xBADD,
@@ -123,7 +132,7 @@ enum OpcodeClient : uint32
CMSG_CALENDAR_GUILD_FILTER = 0xBADD,
CMSG_CALENDAR_REMOVE_EVENT = 0xBADD,
CMSG_CALENDAR_UPDATE_EVENT = 0xBADD,
- CMSG_CANCEL_AURA = 0xBADD,
+ CMSG_CANCEL_AURA = 0x08AE,
CMSG_CANCEL_AUTO_REPEAT_SPELL = 0xBADD,
CMSG_CANCEL_CAST = 0xBADD,
CMSG_CANCEL_CHANNELLING = 0xBADD,
@@ -207,7 +216,7 @@ enum OpcodeClient : uint32
CMSG_EQUIPMENT_SET_USE = 0xBADD,
CMSG_FACTION_BONUS_INFO = 0x0928,
CMSG_FAR_SIGHT = 0xBADD,
- CMSG_FORCE_MOVE_ROOT_ACK = 0xBADD,
+ CMSG_FORCE_MOVE_ROOT_ACK = 0x0B73,
CMSG_FORCE_MOVE_UNROOT_ACK = 0xBADD,
CMSG_GAMEOBJECT_QUERY = 0x03AE,
CMSG_GAMEOBJ_REPORT_USE = 0x082E,
@@ -378,7 +387,7 @@ enum OpcodeClient : uint32
CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK = 0xBADD,
CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK = 0xBADD,
CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK = 0xBADD,
- CMSG_MOVE_GRAVITY_DISABLE_ACK = 0xBADD,
+ CMSG_MOVE_GRAVITY_DISABLE_ACK = 0x0553,
CMSG_MOVE_GRAVITY_ENABLE_ACK = 0xBADD,
CMSG_MOVE_HEARTBEAT = 0x19C1,
CMSG_MOVE_HOVER_ACK = 0xBADD,
@@ -389,7 +398,7 @@ enum OpcodeClient : uint32
CMSG_MOVE_SET_CAN_FLY = 0xBADD,
CMSG_MOVE_SET_CAN_FLY_ACK = 0xBADD,
CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK = 0xBADD,
- CMSG_MOVE_SET_COLLISION_HEIGHT_ACK = 0xBADD,
+ CMSG_MOVE_SET_COLLISION_HEIGHT_ACK = 0x0141,
CMSG_MOVE_SET_RELATIVE_POSITION = 0xBADD,
CMSG_MOVE_SET_VEHICLE_REC_ID_ACK = 0xBADD,
CMSG_MOVE_SPLINE_DONE = 0xBADD,
@@ -462,11 +471,11 @@ enum OpcodeClient : uint32
CMSG_QUEST_NPC_QUERY = 0x0B81,
CMSG_QUEST_POI_QUERY = 0x0BD9,
CMSG_QUEST_QUERY = 0x09A6,
+ CMSG_QUEUED_MESSAGES_END = 0x04DF,
CMSG_RANDOMIZE_CHAR_NAME = 0x1981,
CMSG_READ_ITEM = 0xBADD,
CMSG_REALM_SPLIT = 0xBADD,
CMSG_RECLAIM_CORPSE = 0xBADD,
- CMSG_REDIRECTION_AUTH_PROOF = 0x0485,
CMSG_REFORGE_ITEM = 0xBADD,
CMSG_REORDER_CHARACTERS = 0x0DAA,
CMSG_REPAIR_ITEM = 0xBADD,
@@ -490,7 +499,7 @@ enum OpcodeClient : uint32
CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0xBADD,
CMSG_REQUEST_VEHICLE_PREV_SEAT = 0xBADD,
CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0xBADD,
- CMSG_RESET_FACTION_CHEAT = 0x0C56,
+ CMSG_RESET_FACTION_CHEAT = 0xBADD,
CMSG_RESET_INSTANCES = 0xBADD,
CMSG_RESURRECT_RESPONSE = 0xBADD,
CMSG_RETURN_TO_GRAVEYARD = 0xBADD,
@@ -522,10 +531,11 @@ enum OpcodeClient : uint32
CMSG_SET_FACTION_INACTIVE = 0xBADD,
CMSG_SET_GUILD_BANK_TEXT = 0xBADD,
CMSG_SET_LFG_COMMENT = 0xBADD,
+ CMSG_SET_LOOT_SPECIALIZATION = 0x0226,
CMSG_SET_PET_SLOT = 0xBADD,
CMSG_SET_PLAYER_DECLINED_NAMES = 0xBADD,
CMSG_SET_PREFERED_CEMETERY = 0xBADD,
- CMSG_SET_RAID_DIFFICULTY = 0x04DF,
+ CMSG_SET_RAID_DIFFICULTY = 0xBADD,
CMSG_SET_RELATIVE_POSITION = 0xBADD,
CMSG_SET_SAVED_INSTANCE_EXTEND = 0xBADD,
CMSG_SET_SELECTION = 0x05BD,
@@ -541,7 +551,7 @@ enum OpcodeClient : uint32
CMSG_SHOWING_CLOAK = 0x0132,
CMSG_SHOWING_HELM = 0x11E1,
CMSG_SOCKET_GEMS = 0xBADD,
- CMSG_SPELLCLICK = 0xBADD,
+ CMSG_SPELLCLICK = 0x0BC2,
CMSG_SPIRIT_HEALER_ACTIVATE = 0xBADD,
CMSG_SPLIT_ITEM = 0xBADD,
CMSG_STANDSTATECHANGE = 0xBADD,
@@ -552,7 +562,8 @@ enum OpcodeClient : uint32
CMSG_SUBMIT_COMPLAIN = 0xBADD,
CMSG_SUGGESTION_SUBMIT = 0xBADD,
CMSG_SUMMON_RESPONSE = 0xBADD,
- CMSG_SUSPEND_TOKEN = 0x0142,
+ CMSG_SUSPEND_COMMS_ACK = 0x0C56,
+ CMSG_SUSPEND_TOKEN_RESPONSE = 0x0142,
CMSG_SWAP_INV_ITEM = 0xBADD,
CMSG_SWAP_ITEM = 0xBADD,
CMSG_SYNC_DANCE = 0xBADD,
@@ -570,7 +581,7 @@ enum OpcodeClient : uint32
CMSG_TOTEM_DESTROYED = 0xBADD,
CMSG_TRAINER_BUY_SPELL = 0xBADD,
CMSG_TRAINER_LIST = 0xBADD,
- CMSG_TRANSMOGRIFY_ITEMS = 0xBADD,
+ CMSG_TRANSMOGRIFY_ITEMS = 0x0A85,
CMSG_TRIGGER_CINEMATIC_CHEAT = 0xBADD,
CMSG_TURN_IN_PETITION = 0xBADD,
CMSG_TUTORIAL_CLEAR = 0xBADD,
@@ -590,9 +601,9 @@ enum OpcodeClient : uint32
CMSG_VIOLENCE_LEVEL = 0x098D,
CMSG_VOICE_SESSION_ENABLE = 0xBADD,
CMSG_VOID_STORAGE_QUERY = 0x019E,
- CMSG_VOID_STORAGE_TRANSFER = 0xBADD,
+ CMSG_VOID_STORAGE_TRANSFER = 0x0463,
CMSG_VOID_STORAGE_UNLOCK = 0xBADD,
- CMSG_VOID_SWAP_ITEM = 0xBADD,
+ CMSG_VOID_SWAP_ITEM = 0x0619,
CMSG_WARDEN_DATA = 0x0BA1,
CMSG_WARGAME_ACCEPT = 0xBADD,
CMSG_WARGAME_START = 0xBADD,
@@ -602,9 +613,6 @@ enum OpcodeClient : uint32
CMSG_WORLD_TELEPORT = 0xBADD,
CMSG_WRAP_ITEM = 0xBADD,
CMSG_ZONEUPDATE = 0xBADD,
- MSG_AUCTION_HELLO = 0xBADD,
- MSG_CHANNEL_START = 0xBADD, // SMSG only?
- MSG_CHANNEL_UPDATE = 0xBADD, // SMSG only?
MSG_CORPSE_QUERY = 0xBADD,
MSG_GM_BIND_OTHER = 0xBADD,
MSG_GM_SHOWLABEL = 0xBADD,
@@ -674,6 +682,7 @@ enum OpcodeServer : uint32
{
SMSG_ACCOUNT_DATA_TIMES = 0x0120,
SMSG_ACCOUNT_INFO_RESPONSE = 0xBADD,
+ SMSG_ACCOUNT_MOUNT_UPDATE = 0x0140,
SMSG_ACCOUNT_RESTRICTED_WARNING = 0xBADD,
SMSG_ACHIEVEMENT_DELETED = 0xBADD,
SMSG_ACHIEVEMENT_EARNED = 0xBADD,
@@ -681,7 +690,7 @@ enum OpcodeServer : uint32
SMSG_ACTIVATETAXIREPLY = 0xBADD,
SMSG_ADDON_INFO = 0x1D9F,
SMSG_ADD_RUNE_POWER = 0xBADD,
- SMSG_AI_REACTION = 0xBADD,
+ SMSG_AI_REACTION = 0x0BA1,
SMSG_ALL_ACHIEVEMENT_DATA = 0xBADD,
SMSG_ALL_ACHIEVEMENT_DATA_ACCOUNT = 0x0123,
SMSG_ALL_ACHIEVEMENT_DATA_PLAYER = 0x0030,
@@ -689,7 +698,6 @@ enum OpcodeServer : uint32
SMSG_AREA_TRIGGER_MESSAGE = 0xBADD,
SMSG_AREA_TRIGGER_MOVEMENT_UPDATE = 0xBADD,
SMSG_ARENA_ERROR = 0xBADD,
- SMSG_ARENA_SEASON_WORLD_STATE = 0x09E3,
SMSG_ARENA_UNIT_DESTROYED = 0xBADD,
SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED = 0xBADD,
SMSG_ARENA_TEAM_COMMAND_RESULT = 0xBADD,
@@ -734,7 +742,7 @@ enum OpcodeServer : uint32
SMSG_BATTLEFIELD_MGR_STATE_CHANGE = 0xBADD,
SMSG_BATTLEFIELD_PLAYER_POSITIONS = 0xBADD,
SMSG_BATTLEFIELD_PORT_DENIED = 0xBADD,
- SMSG_BATTLEFIELD_RATED_INFO = 0xBADD,
+ SMSG_BATTLEFIELD_RATED_INFO = 0x1F0A,
SMSG_BATTLEFIELD_STATUS = 0xBADD,
SMSG_BATTLEFIELD_STATUS_QUEUED = 0xBADD,
SMSG_BATTLEFIELD_STATUS_ACTIVE = 0xBADD,
@@ -744,8 +752,12 @@ enum OpcodeServer : uint32
SMSG_BATTLEGROUND_INFO_THROTTLED = 0xBADD,
SMSG_BATTLEGROUND_PLAYER_JOINED = 0xBADD,
SMSG_BATTLEGROUND_PLAYER_LEFT = 0xBADD,
+ SMSG_BATTLE_PAY_GET_DISTRIBUTION_LIST_RESPONSE = 0x0F2A,
SMSG_BATTLE_PAY_GET_PRODUCT_LIST_RESPONSE = 0x12A4,
+ SMSG_BATTLE_PAY_GET_PURCHASE_LIST_RESPONSE = 0x168A,
SMSG_BATTLE_PET_JOURNAL = 0x19A2,
+ SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED = 0x01A3,
+ SMSG_BATTLE_PET_NAME_QUERY_RESPONSE = 0x09EC,
SMSG_BINDER_CONFIRM = 0xBADD,
SMSG_BINDPOINTUPDATE = 0x0A30,
SMSG_BINDZONEREPLY = 0xBADD,
@@ -784,6 +796,8 @@ enum OpcodeServer : uint32
SMSG_CHANNEL_MEMBER_COUNT = 0xBADD,
SMSG_CHANNEL_NOTIFY = 0x0643,
SMSG_CHANNEL_NOTIFY_JOINED = 0x1602,
+ SMSG_CHANNEL_START = 0x016C,
+ SMSG_CHANNEL_UPDATE = 0x19DB,
SMSG_CHARACTER_LOGIN_FAILED = 0xBADD,
SMSG_CHAR_CREATE = 0x0107,
SMSG_CHAR_CUSTOMIZE = 0xBADD,
@@ -842,6 +856,7 @@ enum OpcodeServer : uint32
SMSG_DAMAGE_CALC_LOG = 0xBADD,
SMSG_DAMAGE_DONE_OBSOLETE = 0xBADD,
SMSG_DANCE_QUERY_RESPONSE = 0xBADD,
+ SMSG_DANCE_STUDIO_CREATE_RESULT = 0x178D,
SMSG_DB_REPLY = 0x1939,
SMSG_DEATH_RELEASE_LOC = 0xBADD,
SMSG_DEBUG_RUNE_REGEN = 0xBADD,
@@ -887,7 +902,6 @@ enum OpcodeServer : uint32
SMSG_FORCED_DEATH_UPDATE = 0xBADD,
SMSG_FORCE_ANIM = 0xBADD,
SMSG_FORCE_DISPLAY_UPDATE = 0xBADD,
- SMSG_FORCE_SEND_QUEUED_PACKETS = 0xBADD,
SMSG_FORCE_SET_VEHICLE_REC_ID = 0xBADD,
SMSG_FORGE_MASTER_SET = 0xBADD,
SMSG_FRIEND_STATUS = 0xBADD,
@@ -931,7 +945,7 @@ enum OpcodeServer : uint32
SMSG_GUILD_ACHIEVEMENT_MEMBERS = 0xBADD,
SMSG_GUILD_BANK_LIST = 0xBADD,
SMSG_GUILD_BANK_LOG_QUERY_RESULT = 0xBADD,
- SMSG_GUILD_BANK_MONEY_WITHDRAWN = 0xBADD,
+ SMSG_GUILD_BANK_MONEY_WITHDRAWN = 0x1047,
SMSG_GUILD_BANK_QUERY_TEXT_RESULT = 0xBADD,
SMSG_GUILD_CANCEL = 0xBADD,
SMSG_GUILD_CHALLENGE_COMPLETED = 0xBADD,
@@ -960,7 +974,7 @@ enum OpcodeServer : uint32
SMSG_GUILD_NEWS_DELETED = 0xBADD,
SMSG_GUILD_NEWS_UPDATE = 0xBADD,
SMSG_GUILD_PARTY_STATE_RESPONSE = 0x1225,
- SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0xBADD,
+ SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0x1827,
SMSG_GUILD_QUERY_RESPONSE = 0x1046,
SMSG_GUILD_RANK = 0x1218,
SMSG_GUILD_RANKS_UPDATE = 0xBADD,
@@ -1086,16 +1100,16 @@ enum OpcodeServer : uint32
SMSG_MOVE_COLLISION_DISABLE = 0xBADD,
SMSG_MOVE_COLLISION_ENABLE = 0xBADD,
SMSG_MOVE_FEATHER_FALL = 0xBADD,
- SMSG_MOVE_GRAVITY_DISABLE = 0xBADD,
+ SMSG_MOVE_GRAVITY_DISABLE = 0x02C6,
SMSG_MOVE_GRAVITY_ENABLE = 0xBADD,
SMSG_MOVE_KNOCK_BACK = 0xBADD,
SMSG_MOVE_LAND_WALK = 0xBADD,
SMSG_MOVE_NORMAL_FALL = 0xBADD,
- SMSG_MOVE_ROOT = 0xBADD,
+ SMSG_MOVE_ROOT = 0x1B5A,
SMSG_MOVE_SET_ACTIVE_MOVER = 0xBADD,
SMSG_MOVE_SET_CAN_FLY = 0xBADD,
SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY = 0xBADD,
- SMSG_MOVE_SET_COLLISION_HEIGHT = 0xBADD,
+ SMSG_MOVE_SET_COLLISION_HEIGHT = 0x008D,
SMSG_MOVE_SET_COMPOUND_STATE = 0xBADD,
SMSG_MOVE_SET_FLIGHT_BACK_SPEED = 0xBADD,
SMSG_MOVE_SET_FLIGHT_SPEED = 0xBADD,
@@ -1123,7 +1137,7 @@ enum OpcodeServer : uint32
SMSG_MOVE_UPDATE_RUN_SPEED = 0xBADD,
SMSG_MOVE_UPDATE_SWIM_BACK_SPEED = 0xBADD,
SMSG_MOVE_UPDATE_SWIM_SPEED = 0xBADD,
- SMSG_MOVE_UPDATE_TELEPORT = 0xBADD,
+ SMSG_MOVE_UPDATE_TELEPORT = 0x03D5,
SMSG_MOVE_UPDATE_TURN_RATE = 0xBADD,
SMSG_MOVE_UPDATE_WALK_SPEED = 0xBADD,
SMSG_MOVE_WATER_WALK = 0xBADD,
@@ -1139,7 +1153,7 @@ enum OpcodeServer : uint32
SMSG_NPC_TEXT_UPDATE = 0x1122,
SMSG_NPC_WONT_TALK = 0xBADD,
SMSG_OFFER_PETITION_ERROR = 0xBADD,
- SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0xBADD,
+ SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x053F,
SMSG_OPEN_CONTAINER = 0xBADD,
SMSG_OPEN_LFG_DUNGEON_FINDER = 0xBADD,
SMSG_OVERRIDE_LIGHT = 0xBADD,
@@ -1184,7 +1198,7 @@ enum OpcodeServer : uint32
SMSG_PLAY_MUSIC = 0xBADD,
SMSG_PLAY_OBJECT_SOUND = 0xBADD,
SMSG_PLAY_ONE_SHOT_ANIM_KIT = 0xBADD,
- SMSG_PLAY_SOUND = 0xBADD,
+ SMSG_PLAY_SOUND = 0x02D2,
SMSG_PLAY_SPELL_VISUAL = 0xBADD,
SMSG_PLAY_SPELL_VISUAL_KIT = 0xBADD,
SMSG_PLAY_TIME_WARNING = 0xBADD,
@@ -1197,8 +1211,9 @@ enum OpcodeServer : uint32
SMSG_PVP_CREDIT = 0xBADD,
SMSG_PVP_LOG_DATA = 0xBADD,
SMSG_PVP_OPTIONS_ENABLED = 0xBADD,
+ SMSG_PVP_SEASON = 0x09E3,
SMSG_QUERY_QUESTS_COMPLETED_RESPONSE = 0xBADD,
- SMSG_QUERY_TIME_RESPONSE = 0xBADD,
+ SMSG_QUERY_TIME_RESPONSE = 0x1DB0,
SMSG_QUESTGIVER_OFFER_REWARD = 0xBADD,
SMSG_QUESTGIVER_QUEST_COMPLETE = 0xBADD,
SMSG_QUESTGIVER_QUEST_DETAILS = 0x15B3,
@@ -1248,6 +1263,7 @@ enum OpcodeServer : uint32
SMSG_RESET_FAILED_NOTIFY = 0xBADD,
SMSG_RESISTLOG = 0xBADD,
SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0xBADD,
+ SMSG_RESUME_COMMS = 0x07C9,
SMSG_RESURRECT_FAILED = 0xBADD,
SMSG_RESURRECT_REQUEST = 0xBADD,
SMSG_RESYNC_RUNES = 0xBADD,
@@ -1268,13 +1284,13 @@ enum OpcodeServer : uint32
SMSG_SET_FACTION_STANDING = 0xBADD,
SMSG_SET_FACTION_VISIBLE = 0xBADD,
SMSG_SET_FLAT_SPELL_MODIFIER = 0x1884,
- SMSG_SET_FORCED_REACTIONS = 0xBADD,
+ SMSG_SET_FORCED_REACTIONS = 0x09A9,
SMSG_SET_MELEE_ANIM_KIT = 0xBADD,
SMSG_SET_MOVEMENT_ANIM_KIT = 0xBADD,
SMSG_SET_PCT_SPELL_MODIFIER = 0x113C,
SMSG_SET_PHASE_SHIFT = 0x00D1,
SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0xBADD,
- SMSG_SET_PLAY_HOVER_ANIM = 0xBADD,
+ SMSG_SET_PLAY_HOVER_ANIM = 0x02D4,
SMSG_SET_PROFICIENCY = 0x00D3,
SMSG_SET_PROJECTILE_POSITION = 0xBADD,
SMSG_SET_TIME_ZONE_INFORMATION = 0x153E,
@@ -1304,11 +1320,11 @@ enum OpcodeServer : uint32
SMSG_SPELL_FAILURE = 0xBADD,
SMSG_SPELL_GO = 0x1161,
SMSG_SPELL_START = 0x0803,
- SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0xBADD,
+ SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x0374,
SMSG_SPIRIT_HEALER_CONFIRM = 0xBADD,
SMSG_SPLINE_MOVE_COLLISION_DISABLE = 0xBADD,
SMSG_SPLINE_MOVE_COLLISION_ENABLE = 0xBADD,
- SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0xBADD,
+ SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0x03B2,
SMSG_SPLINE_MOVE_GRAVITY_ENABLE = 0xBADD,
SMSG_SPLINE_MOVE_ROOT = 0xBADD,
SMSG_SPLINE_MOVE_SET_ANIM = 0xBADD,
@@ -1333,10 +1349,10 @@ enum OpcodeServer : uint32
SMSG_SPLINE_MOVE_STOP_SWIM = 0xBADD,
SMSG_SPLINE_MOVE_UNROOT = 0xBADD,
SMSG_SPLINE_MOVE_UNSET_FLYING = 0xBADD,
- SMSG_SPLINE_MOVE_UNSET_HOVER = 0xBADD,
+ SMSG_SPLINE_MOVE_UNSET_HOVER = 0x1959,
SMSG_SPLINE_MOVE_WATER_WALK = 0xBADD,
SMSG_STABLE_RESULT = 0xBADD,
- SMSG_STANDSTATE_UPDATE = 0xBADD,
+ SMSG_STANDSTATE_UPDATE = 0x1311,
SMSG_START_MIRROR_TIMER = 0xBADD,
SMSG_START_TIMER = 0xBADD,
SMSG_STOP_DANCE = 0xBADD,
@@ -1347,7 +1363,7 @@ enum OpcodeServer : uint32
SMSG_SUPERCEDED_SPELL = 0xBADD,
SMSG_SUPPRESS_NPC_GREETINGS = 0xBADD,
SMSG_SUSPEND_COMMS = 0x076A,
- SMSG_SUSPEND_TOKEN_RESPONSE = 0x12A2,
+ SMSG_SUSPEND_TOKEN = 0x12A2,
SMSG_TALENTS_ERROR = 0xBADD,
SMSG_TALENTS_INFO = 0x012D,
SMSG_TALENTS_INVOLUNTARILY_RESET = 0xBADD,
@@ -1398,11 +1414,11 @@ enum OpcodeServer : uint32
SMSG_VOICE_SESSION_LEAVE = 0xBADD,
SMSG_VOICE_SESSION_ROSTER_UPDATE = 0xBADD,
SMSG_VOICE_SET_TALKER_MUTED = 0xBADD,
- SMSG_VOID_ITEM_SWAP_RESPONSE = 0xBADD,
+ SMSG_VOID_ITEM_SWAP_RESPONSE = 0x1131,
SMSG_VOID_STORAGE_CONTENTS = 0x0108,
SMSG_VOID_STORAGE_FAILED = 0xBADD,
- SMSG_VOID_STORAGE_TRANSFER_CHANGES = 0xBADD,
- SMSG_VOID_TRANSFER_RESULT = 0xBADD,
+ SMSG_VOID_STORAGE_TRANSFER_CHANGES = 0x0321,
+ SMSG_VOID_TRANSFER_RESULT = 0x0539,
SMSG_WAIT_QUEUE_FINISH = 0xBADD,
SMSG_WAIT_QUEUE_UPDATE = 0xBADD,
SMSG_WARDEN_DATA = 0x0BEC,
diff --git a/src/server/game/Server/WorldPacket.h b/src/server/game/Server/WorldPacket.h
index e7d6d4fb5b1..65b2f6fcae1 100644
--- a/src/server/game/Server/WorldPacket.h
+++ b/src/server/game/Server/WorldPacket.h
@@ -27,17 +27,18 @@ class WorldPacket : public ByteBuffer
{
public:
// just container for later use
- WorldPacket() : ByteBuffer(0), m_opcode(UNKNOWN_OPCODE)
+ WorldPacket() : ByteBuffer(0), m_opcode(UNKNOWN_OPCODE), _connection(CONNECTION_TYPE_REALM)
{
}
- explicit WorldPacket(uint32 opcode, size_t res = 200) : ByteBuffer(res), m_opcode(opcode) { }
+ WorldPacket(uint32 opcode, size_t res = 200, ConnectionType connection = CONNECTION_TYPE_REALM) : ByteBuffer(res),
+ m_opcode(opcode), _connection(connection) { }
- WorldPacket(WorldPacket&& packet) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode)
+ WorldPacket(WorldPacket&& packet) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode), _connection(packet._connection)
{
}
- WorldPacket(WorldPacket const& right) : ByteBuffer(right), m_opcode(right.m_opcode)
+ WorldPacket(WorldPacket const& right) : ByteBuffer(right), m_opcode(right.m_opcode), _connection(right._connection)
{
}
@@ -46,26 +47,31 @@ class WorldPacket : public ByteBuffer
if (this != &right)
{
m_opcode = right.m_opcode;
+ _connection = right._connection;
ByteBuffer::operator =(right);
}
return *this;
}
- WorldPacket(uint32 opcode, MessageBuffer&& buffer) : ByteBuffer(std::move(buffer)), m_opcode(opcode) { }
+ WorldPacket(uint32 opcode, MessageBuffer&& buffer, ConnectionType connection) : ByteBuffer(std::move(buffer)), m_opcode(opcode), _connection(connection) { }
- void Initialize(uint32 opcode, size_t newres = 200)
+ void Initialize(uint32 opcode, size_t newres = 200, ConnectionType connection = CONNECTION_TYPE_REALM)
{
clear();
_storage.reserve(newres);
m_opcode = opcode;
+ _connection = connection;
}
uint32 GetOpcode() const { return m_opcode; }
void SetOpcode(uint32 opcode) { m_opcode = opcode; }
+ ConnectionType GetConnection() const { return _connection; }
+
protected:
uint32 m_opcode;
+ ConnectionType _connection;
};
#endif
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index 0164ad9a575..f427b91787a 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -106,7 +106,6 @@ WorldSession::WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr
AntiDOS(this),
m_GUIDLow(UI64LIT(0)),
_player(NULL),
- m_Socket(sock),
_security(sec),
_accountId(id),
_battlenetAccountId(battlenetAccountId),
@@ -114,7 +113,6 @@ WorldSession::WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr
_warden(NULL),
_logoutTime(0),
m_inQueue(false),
- m_playerLoading(false),
m_playerLogout(false),
m_playerRecentlyLogout(false),
m_playerSave(false),
@@ -140,17 +138,9 @@ WorldSession::WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query
}
- InitializeQueryCallbackParameters();
+ m_Socket[0] = sock;
- _compressionStream = new z_stream();
- _compressionStream->zalloc = (alloc_func)NULL;
- _compressionStream->zfree = (free_func)NULL;
- _compressionStream->opaque = (voidpf)NULL;
- _compressionStream->avail_in = 0;
- _compressionStream->next_in = NULL;
- int32 z_res = deflateInit2(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION), Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
- if (z_res != Z_OK)
- TC_LOG_ERROR("network", "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res));
+ InitializeQueryCallbackParameters();
}
/// WorldSession destructor
@@ -161,10 +151,13 @@ WorldSession::~WorldSession()
LogoutPlayer (true);
/// - If have unclosed socket, close it
- if (m_Socket)
+ for (uint8 i = 0; i < 2; ++i)
{
- m_Socket->CloseSocket();
- m_Socket = nullptr;
+ if (m_Socket[i])
+ {
+ m_Socket[i]->CloseSocket();
+ m_Socket[i].reset();
+ }
}
delete _warden;
@@ -176,12 +169,6 @@ WorldSession::~WorldSession()
delete packet;
LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); // One-time query
-
- int32 z_res = deflateEnd(_compressionStream);
- if (z_res != Z_OK && z_res != Z_DATA_ERROR) // Z_DATA_ERROR signals that internal state was BUSY
- TC_LOG_ERROR("network", "Can't close packet compression stream (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res));
-
- delete _compressionStream;
}
std::string const & WorldSession::GetPlayerName() const
@@ -205,7 +192,7 @@ std::string WorldSession::GetPlayerInfo() const
/// Send a packet to the client
void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/)
{
- if (!m_Socket)
+ if (!m_Socket[packet->GetConnection()])
return;
if (packet->GetOpcode() == NULL_OPCODE)
@@ -265,38 +252,7 @@ void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/
sScriptMgr->OnPacketSend(this, *packet);
- m_Socket->SendPacket(*packet);
-}
-
-uint32 WorldSession::CompressPacket(uint8* buffer, WorldPacket const& packet)
-{
- uint32 opcode = packet.GetOpcode();
- uint32 bufferSize = deflateBound(_compressionStream, packet.size() + sizeof(opcode));
-
- _compressionStream->next_out = buffer;
- _compressionStream->avail_out = bufferSize;
- _compressionStream->next_in = (Bytef*)&opcode;
- _compressionStream->avail_in = sizeof(uint32);
-
- int32 z_res = deflate(_compressionStream, Z_BLOCK);
- if (z_res != Z_OK)
- {
- TC_LOG_ERROR("network", "Can't compress packet opcode (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg);
- return 0;
- }
-
- _compressionStream->next_in = (Bytef*)packet.contents();
- _compressionStream->avail_in = packet.size();
-
- z_res = deflate(_compressionStream, Z_SYNC_FLUSH);
- if (z_res != Z_OK)
- {
- TC_LOG_ERROR("network", "Can't compress packet data (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg);
- return 0;
- }
-
-
- return bufferSize - _compressionStream->avail_out;
+ m_Socket[packet->GetConnection()]->SendPacket(*packet);
}
/// Add an incoming packet to the queue
@@ -332,7 +288,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
///- Before we process anything:
/// If necessary, kick the player from the character select screen
if (IsConnectionIdle())
- m_Socket->CloseSocket();
+ m_Socket[0]->CloseSocket();
///- Retrieve packets from the receive queue and call the appropriate handlers
/// not process packets if socket already closed
@@ -349,7 +305,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
uint32 processedPackets = 0;
time_t currentTime = time(NULL);
- while (m_Socket && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater))
+ while (m_Socket[0] && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater))
{
if (!AntiDOS.EvaluateOpcode(*packet, currentTime))
KickPlayer();
@@ -458,7 +414,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
break;
}
- if (m_Socket && m_Socket->IsOpen() && _warden)
+ if (m_Socket[0] && m_Socket[0]->IsOpen() && _warden)
_warden->Update();
ProcessQueryCallbacks();
@@ -469,23 +425,24 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
{
time_t currTime = time(NULL);
///- If necessary, log the player out
- if (ShouldLogOut(currTime) && !m_playerLoading)
+ if (ShouldLogOut(currTime) && m_playerLoading.IsEmpty())
LogoutPlayer(true);
- if (m_Socket && GetPlayer() && _warden)
+ if (m_Socket[0] && GetPlayer() && _warden)
_warden->Update();
///- Cleanup socket pointer if need
- if (m_Socket && !m_Socket->IsOpen())
+ if ((m_Socket[0] && !m_Socket[0]->IsOpen()) || (m_Socket[1] && !m_Socket[1]->IsOpen()))
{
expireTime -= expireTime > diff ? diff : expireTime;
if (expireTime < diff || forceExit || !GetPlayer())
{
- m_Socket = nullptr;
+ m_Socket[0].reset();
+ m_Socket[1].reset();
}
}
- if (!m_Socket)
+ if (!m_Socket[0])
return false; //Will remove this session from the world session map
}
@@ -587,7 +544,7 @@ void WorldSession::LogoutPlayer(bool save)
// remove player from the group if he is:
// a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected)
- if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket)
+ if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket[0])
_player->RemoveFromGroup();
//! Send update to group and reset stored max enchanting level
@@ -640,10 +597,13 @@ void WorldSession::LogoutPlayer(bool save)
/// Kick a player out of the World
void WorldSession::KickPlayer()
{
- if (m_Socket)
+ for (uint8 i = 0; i < 2; ++i)
{
- m_Socket->CloseSocket();
- forceExit = true;
+ if (m_Socket[i])
+ {
+ m_Socket[i]->CloseSocket();
+ forceExit = true;
+ }
}
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index c77ad210ebc..83a746c8f44 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -54,7 +54,6 @@ struct DeclinedName;
struct ItemTemplate;
struct MovementInfo;
struct TradeStatusInfo;
-struct z_stream_s;
namespace lfg
{
@@ -228,7 +227,7 @@ class WorldSession
WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
~WorldSession();
- bool PlayerLoading() const { return m_playerLoading; }
+ bool PlayerLoading() const { return !m_playerLoading.IsEmpty(); }
bool PlayerLogout() const { return m_playerLogout; }
bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; }
bool PlayerRecentlyLoggedOut() const { return m_playerRecentlyLogout; }
@@ -238,7 +237,7 @@ class WorldSession
bool IsAddonRegistered(const std::string& prefix) const;
void SendPacket(WorldPacket const* packet, bool forced = false);
- uint32 CompressPacket(uint8* buffer, WorldPacket const& packet);
+ void AddInstanceConnection(std::shared_ptr<WorldSocket> sock) { m_Socket[1] = sock; }
void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3);
void SendNotification(uint32 string_id, ...);
@@ -424,8 +423,6 @@ class WorldSession
uint32 GetRecruiterId() const { return recruiterId; }
bool IsARecruiter() const { return isRecruiter; }
- z_stream_s* GetCompressionStream() { return _compressionStream; }
-
public: // opcodes handlers
void Handle_NULL(WorldPacket& recvPacket); // not used
@@ -441,6 +438,7 @@ class WorldSession
void HandleCharCreateOpcode(WorldPackets::Character::CharacterCreate& charCreate);
void HandleCharCreateCallback(PreparedQueryResult result, WorldPackets::Character::CharacterCreateInfo* createInfo);
void HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& playerLogin);
+ void HandleContinuePlayerLogin();
void HandleLoadScreenOpcode(WorldPacket& recvPacket);
void HandlePlayerLogin(LoginQueryHolder * holder);
void HandleCharRenameOpcode(WorldPacket& recvData);
@@ -1091,7 +1089,7 @@ class WorldSession
ObjectGuid::LowType m_GUIDLow; // set logined or recently logout player (while m_playerRecentlyLogout set)
Player* _player;
- std::shared_ptr<WorldSocket> m_Socket;
+ std::shared_ptr<WorldSocket> m_Socket[2];
std::string m_Address; // Current Remote Address
// std::string m_LAddress; // Last Attempted Remote Adress - we can not set attempted ip for a non-existing session!
@@ -1107,7 +1105,7 @@ class WorldSession
time_t _logoutTime;
bool m_inQueue; // session wait in auth.queue
- bool m_playerLoading; // code processed in LoginPlayer
+ ObjectGuid m_playerLoading; // code processed in LoginPlayer
bool m_playerLogout; // code processed in LogoutPlayer
bool m_playerRecentlyLogout;
bool m_playerSave;
@@ -1124,7 +1122,6 @@ class WorldSession
uint32 recruiterId;
bool isRecruiter;
LockedQueue<WorldPacket*> _recvQueue;
- z_stream_s* _compressionStream;
rbac::RBACData* _RBACData;
uint32 expireTime;
bool forceExit;
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 23bd9a65f88..9cdb05ac79b 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -25,6 +25,7 @@
#include "SHA1.h"
#include "PacketLog.h"
#include "BattlenetAccountMgr.h"
+#include "World.h"
#include <zlib.h>
#include <memory>
@@ -53,12 +54,22 @@ uint32 const SizeOfClientHeader[2][2] =
uint32 const SizeOfServerHeader[2] = { sizeof(uint16) + sizeof(uint32), sizeof(uint32) };
-WorldSocket::WorldSocket(tcp::socket&& socket)
- : Socket(std::move(socket)), _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr), _initialized(false)
+WorldSocket::WorldSocket(tcp::socket&& socket) : Socket(std::move(socket)),
+ _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr),
+ _initialized(false), _type(CONNECTION_TYPE_REALM)
{
_headerBuffer.Resize(SizeOfClientHeader[0][0]);
}
+WorldSocket::~WorldSocket()
+{
+ if (_compressionStream)
+ {
+ deflateEnd(_compressionStream);
+ delete _compressionStream;
+ }
+}
+
void WorldSocket::Start()
{
AsyncRead();
@@ -75,15 +86,13 @@ void WorldSocket::Start()
void WorldSocket::HandleSendAuthSession()
{
- BigNumber seed1;
- BigNumber seed2;
- seed1.SetRand(16 * 8);
- seed2.SetRand(16 * 8);
+ _encryptSeed.SetRand(16 * 8);
+ _decryptSeed.SetRand(16 * 8);
WorldPackets::Auth::AuthChallenge challenge;
challenge.Challenge = _authSeed;
- memcpy(&challenge.DosChallenge[0], seed1.AsByteArray(16).get(), 16);
- memcpy(&challenge.DosChallenge[4], seed2.AsByteArray(16).get(), 16);
+ memcpy(&challenge.DosChallenge[0], _encryptSeed.AsByteArray(16).get(), 16);
+ memcpy(&challenge.DosChallenge[4], _decryptSeed.AsByteArray(16).get(), 16);
challenge.DosZeroBits = 1;
SendPacket(*challenge.Write());
@@ -204,7 +213,7 @@ bool WorldSocket::ReadDataHandler()
std::string opcodeName = GetOpcodeNameForLogging(opcode);
- WorldPacket packet(opcode, std::move(_packetBuffer));
+ WorldPacket packet(opcode, std::move(_packetBuffer), GetConnectionType());
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort());
@@ -217,15 +226,32 @@ bool WorldSocket::ReadDataHandler()
HandlePing(packet);
break;
case CMSG_AUTH_SESSION:
+ {
if (_worldSession)
{
TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str());
break;
}
- HandleAuthSession(packet);
+ WorldPackets::Auth::AuthSession authSession(std::move(packet));
+ authSession.Read();
+ HandleAuthSession(authSession);
+ break;
+ }
+ case CMSG_AUTH_CONTINUED_SESSION:
+ {
+ if (_worldSession)
+ {
+ TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_CONTINUED_SESSION from %s", _worldSession->GetPlayerInfo().c_str());
+ break;
+ }
+
+ WorldPackets::Auth::AuthContinuedSession authSession(std::move(packet));
+ authSession.Read();
+ HandleAuthContinuedSession(authSession);
break;
- /*
+ }
+ /*
case CMSG_KEEP_ALIVE:
TC_LOG_DEBUG("network", "%s", opcodeName.c_str());
sScriptMgr->OnPacketReceive(_worldSession, packet);
@@ -286,6 +312,20 @@ bool WorldSocket::ReadDataHandler()
return false;
}
+ _compressionStream = new z_stream();
+ _compressionStream->zalloc = (alloc_func)NULL;
+ _compressionStream->zfree = (free_func)NULL;
+ _compressionStream->opaque = (voidpf)NULL;
+ _compressionStream->avail_in = 0;
+ _compressionStream->next_in = NULL;
+ int32 z_res = deflateInit2(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION), Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
+ if (z_res != Z_OK)
+ {
+ TC_LOG_ERROR("network", "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res));
+ CloseSocket();
+ return false;
+ }
+
_initialized = true;
_headerBuffer.Resize(SizeOfClientHeader[1][0]);
_packetBuffer.Reset();
@@ -295,6 +335,35 @@ bool WorldSocket::ReadDataHandler()
return true;
}
+void WorldSocket::SendPacket(WorldPacket const& packet)
+{
+ if (!IsOpen())
+ return;
+
+ if (sPacketLog->CanLogPacket())
+ sPacketLog->LogPacket(packet, SERVER_TO_CLIENT, GetRemoteIpAddress(), GetRemotePort());
+
+ TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet.GetOpcode())).c_str());
+
+ uint32 packetSize = packet.size();
+ uint32 sizeOfHeader = SizeOfServerHeader[_authCrypt.IsInitialized()];
+ if (packetSize > 0x400)
+ packetSize = compressBound(packetSize) + sizeof(CompressedWorldPacket);
+
+ std::unique_lock<std::mutex> guard(_writeLock);
+
+#ifndef TC_SOCKET_USE_IOCP
+ if (_writeQueue.empty() && _writeBuffer.GetRemainingSpace() >= sizeOfHeader + packetSize)
+ WritePacketToBuffer(packet, _writeBuffer);
+ else
+#endif
+ {
+ MessageBuffer buffer(sizeOfHeader + packetSize);
+ WritePacketToBuffer(packet, buffer);
+ QueuePacket(std::move(buffer), guard);
+ }
+}
+
void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& buffer)
{
ServerPktHeader header;
@@ -306,7 +375,7 @@ void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer&
uint8* headerPos = buffer.GetWritePointer();
buffer.WriteCompleted(sizeOfHeader);
- if (packetSize > 0x400 && _worldSession)
+ if (packetSize > 0x400)
{
CompressedWorldPacket cmp;
cmp.UncompressedSize = packetSize + 4;
@@ -316,7 +385,7 @@ void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer&
uint8* compressionInfo = buffer.GetWritePointer();
buffer.WriteCompleted(sizeof(CompressedWorldPacket));
- uint32 compressedSize = _worldSession->CompressPacket(buffer.GetWritePointer(), packet);
+ uint32 compressedSize = CompressPacket(buffer.GetWritePointer(), packet);
cmp.CompressedAdler = adler32(0x9827D8F1, buffer.GetWritePointer(), compressedSize);
@@ -344,40 +413,39 @@ void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer&
memcpy(headerPos, &header, sizeOfHeader);
}
-void WorldSocket::SendPacket(WorldPacket const& packet)
+uint32 WorldSocket::CompressPacket(uint8* buffer, WorldPacket const& packet)
{
- if (!IsOpen())
- return;
-
- if (sPacketLog->CanLogPacket())
- sPacketLog->LogPacket(packet, SERVER_TO_CLIENT, GetRemoteIpAddress(), GetRemotePort());
+ uint32 opcode = packet.GetOpcode();
+ uint32 bufferSize = deflateBound(_compressionStream, packet.size() + sizeof(opcode));
- TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet.GetOpcode())).c_str());
+ _compressionStream->next_out = buffer;
+ _compressionStream->avail_out = bufferSize;
+ _compressionStream->next_in = (Bytef*)&opcode;
+ _compressionStream->avail_in = sizeof(uint32);
- uint32 packetSize = packet.size();
- uint32 sizeOfHeader = SizeOfServerHeader[_authCrypt.IsInitialized()];
- if (packetSize > 0x400 && _worldSession)
- packetSize = compressBound(packetSize) + sizeof(CompressedWorldPacket);
+ int32 z_res = deflate(_compressionStream, Z_BLOCK);
+ if (z_res != Z_OK)
+ {
+ TC_LOG_ERROR("network", "Can't compress packet opcode (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg);
+ return 0;
+ }
- std::unique_lock<std::mutex> guard(_writeLock);
+ _compressionStream->next_in = (Bytef*)packet.contents();
+ _compressionStream->avail_in = packet.size();
-#ifndef TC_SOCKET_USE_IOCP
- if (_writeQueue.empty() && _writeBuffer.GetRemainingSpace() >= sizeOfHeader + packetSize)
- WritePacketToBuffer(packet, _writeBuffer);
- else
-#endif
+ z_res = deflate(_compressionStream, Z_SYNC_FLUSH);
+ if (z_res != Z_OK)
{
- MessageBuffer buffer(sizeOfHeader + packetSize);
- WritePacketToBuffer(packet, buffer);
- QueuePacket(std::move(buffer), guard);
+ TC_LOG_ERROR("network", "Can't compress packet data (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg);
+ return 0;
}
+
+
+ return bufferSize - _compressionStream->avail_out;
}
-void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
+void WorldSocket::HandleAuthSession(WorldPackets::Auth::AuthSession& authSession)
{
- WorldPackets::Auth::AuthSession authSession(std::move(recvPacket));
- authSession.Read();
-
uint8 security;
uint32 id;
LocaleConstant locale;
@@ -598,6 +666,56 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
sWorld->AddSession(_worldSession);
}
+void WorldSocket::HandleAuthContinuedSession(WorldPackets::Auth::AuthContinuedSession& authSession)
+{
+ uint32 accountId = PAIR64_LOPART(authSession.Key);
+ _type = ConnectionType(PAIR64_HIPART(authSession.Key));
+ QueryResult result = LoginDatabase.PQuery("SELECT username, sessionkey FROM account WHERE id = %u", accountId);
+ if (!result)
+ {
+ SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
+ DelayedCloseSocket();
+ return;
+ }
+
+ Field* fields = result->Fetch();
+ std::string login = fields[0].GetString();
+ BigNumber k;
+ k.SetHexStr(fields[1].GetCString());
+
+ _authCrypt.Init(&k, _encryptSeed.AsByteArray().get(), _decryptSeed.AsByteArray().get());
+ _headerBuffer.Resize(SizeOfClientHeader[1][1]);
+
+ SHA1Hash sha;
+ sha.UpdateData(login);
+ sha.UpdateBigNumbers(&k, NULL);
+ sha.UpdateData((uint8*)&_authSeed, 4);
+ sha.Finalize();
+
+ if (memcmp(sha.GetDigest(), authSession.Digest, sha.GetLength()))
+ {
+ SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: Authentication failed for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str());
+ DelayedCloseSocket();
+ return;
+ }
+
+ _worldSession = sWorld->FindSession(accountId);
+ if (!_worldSession)
+ {
+ SendAuthResponseError(AUTH_SESSION_EXPIRED);
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: No active session found for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str());
+ DelayedCloseSocket();
+ return;
+ }
+
+ WorldPackets::Auth::ResumeComms resumeComms;
+ SendPacket(*resumeComms.Write());
+
+ _worldSession->AddInstanceConnection(shared_from_this());
+ _worldSession->HandleContinuePlayerLogin();
+}
+
void WorldSocket::SendAuthResponseError(uint8 code)
{
WorldPackets::Auth::AuthResponse response;
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index e0dad0a43a1..16769c68c33 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -31,10 +31,16 @@
#include <boost/asio/buffer.hpp>
using boost::asio::ip::tcp;
+struct z_stream_s;
namespace WorldPackets
{
class ServerPacket;
+ namespace Auth
+ {
+ class AuthSession;
+ class AuthContinuedSession;
+ }
}
#pragma pack(push, 1)
@@ -67,6 +73,7 @@ class WorldSocket : public Socket<WorldSocket>
public:
WorldSocket(tcp::socket&& socket);
+ ~WorldSocket();
WorldSocket(WorldSocket const& right) = delete;
WorldSocket& operator=(WorldSocket const& right) = delete;
@@ -74,7 +81,8 @@ public:
void Start() override;
void SendPacket(WorldPacket const& packet);
- void WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& buffer);
+
+ ConnectionType GetConnectionType() const { return _type; }
protected:
void ReadHandler() override;
@@ -82,16 +90,24 @@ protected:
bool ReadDataHandler();
private:
+ void WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& buffer);
+ uint32 CompressPacket(uint8* buffer, WorldPacket const& packet);
+
void HandleSendAuthSession();
- void HandleAuthSession(WorldPacket& recvPacket);
+ void HandleAuthSession(WorldPackets::Auth::AuthSession& authSession);
+ void HandleAuthContinuedSession(WorldPackets::Auth::AuthContinuedSession& authSession);
void SendAuthResponseError(uint8 code);
void HandlePing(WorldPacket& recvPacket);
void ExtractOpcodeAndSize(ClientPktHeader const* header, uint32& opcode, uint32& size) const;
+ ConnectionType _type;
+
uint32 _authSeed;
WorldPacketCrypt _authCrypt;
+ BigNumber _encryptSeed;
+ BigNumber _decryptSeed;
std::chrono::steady_clock::time_point _LastPingTime;
uint32 _OverSpeedPings;
@@ -101,6 +117,8 @@ private:
MessageBuffer _headerBuffer;
MessageBuffer _packetBuffer;
+ z_stream_s* _compressionStream;
+
bool _initialized;
};
diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp
index 21f62fa265c..5fcd308f376 100644
--- a/src/server/game/Server/WorldSocketMgr.cpp
+++ b/src/server/game/Server/WorldSocketMgr.cpp
@@ -46,6 +46,11 @@ WorldSocketMgr::WorldSocketMgr() : BaseSocketMgr(), _socketSendBufferSize(-1), m
{
}
+WorldSocketMgr::~WorldSocketMgr()
+{
+ delete _instanceAcceptor;
+}
+
bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port)
{
_tcpNoDelay = sConfigMgr->GetBoolDefault("Network.TcpNodelay", true);
@@ -64,8 +69,10 @@ bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string
}
BaseSocketMgr::StartNetwork(service, bindIp, port);
+ _instanceAcceptor = new AsyncAcceptor(service, bindIp, uint16(sWorld->getIntConfig(CONFIG_PORT_INSTANCE)));
_acceptor->AsyncAcceptManaged(&OnSocketAccept);
+ _instanceAcceptor->AsyncAcceptManaged(&OnSocketAccept);
sScriptMgr->OnNetworkStart();
return true;
diff --git a/src/server/game/Server/WorldSocketMgr.h b/src/server/game/Server/WorldSocketMgr.h
index 92a28d0c135..389818b2f9b 100644
--- a/src/server/game/Server/WorldSocketMgr.h
+++ b/src/server/game/Server/WorldSocketMgr.h
@@ -35,6 +35,8 @@ class WorldSocketMgr : public SocketMgr<WorldSocket>
typedef SocketMgr<WorldSocket> BaseSocketMgr;
public:
+ ~WorldSocketMgr();
+
static WorldSocketMgr& Instance()
{
static WorldSocketMgr instance;
@@ -55,6 +57,7 @@ protected:
NetworkThread<WorldSocket>* CreateThreads() const override;
private:
+ AsyncAcceptor* _instanceAcceptor;
int32 _socketSendBufferSize;
int32 m_SockOutUBuff;
bool _tcpNoDelay;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 659e7ad46ef..2dc6aa3f7a7 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -4207,7 +4207,7 @@ void Spell::SendChannelUpdate(uint32 time)
m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
}
- WorldPacket data(MSG_CHANNEL_UPDATE, 8+4);
+ WorldPacket data(SMSG_CHANNEL_UPDATE, 8+4);
data << m_caster->GetPackGUID();
data << uint32(time);
@@ -4221,7 +4221,7 @@ void Spell::SendChannelStart(uint32 duration)
if (m_UniqueTargetInfo.size() + m_UniqueGOTargetInfo.size() == 1) // this is for TARGET_SELECT_CATEGORY_NEARBY
channelTarget = !m_UniqueTargetInfo.empty() ? m_UniqueTargetInfo.front().targetGUID : m_UniqueGOTargetInfo.front().targetGUID;
- WorldPacket data(MSG_CHANNEL_START, (8+4+4));
+ WorldPacket data(SMSG_CHANNEL_START, (8+4+4));
data << m_caster->GetPackGUID();
data << uint32(m_spellInfo->Id);
data << uint32(duration);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 4900b655766..8bc360abf4d 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -650,9 +650,16 @@ void World::LoadConfigSettings(bool reload)
uint32 val = sConfigMgr->GetIntDefault("WorldServerPort", 8085);
if (val != m_int_configs[CONFIG_PORT_WORLD])
TC_LOG_ERROR("server.loading", "WorldServerPort option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_PORT_WORLD]);
+
+ val = sConfigMgr->GetIntDefault("InstanceServerPort", 8086);
+ if (val != m_int_configs[CONFIG_PORT_INSTANCE])
+ TC_LOG_ERROR("server.loading", "InstanceServerPort option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_PORT_INSTANCE]);
}
else
+ {
m_int_configs[CONFIG_PORT_WORLD] = sConfigMgr->GetIntDefault("WorldServerPort", 8085);
+ m_int_configs[CONFIG_PORT_INSTANCE] = sConfigMgr->GetIntDefault("InstanceServerPort", 8086);
+ }
m_int_configs[CONFIG_SOCKET_TIMEOUTTIME] = sConfigMgr->GetIntDefault("SocketTimeOutTime", 900000);
m_int_configs[CONFIG_SESSION_ADD_DELAY] = sConfigMgr->GetIntDefault("SessionAddDelay", 10000);
@@ -1079,11 +1086,11 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_ARENA_RATED_UPDATE_TIMER] = sConfigMgr->GetIntDefault ("Arena.RatedUpdateTimer", 5 * IN_MILLISECONDS);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.Enable", false);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.PlayerOnly", false);
- m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetIntDefault ("Arena.ArenaSeason.ID", 1);
+ m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetIntDefault ("Arena.ArenaSeason.ID", 15);
m_int_configs[CONFIG_ARENA_START_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartRating", 0);
m_int_configs[CONFIG_ARENA_START_PERSONAL_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartPersonalRating", 1000);
m_int_configs[CONFIG_ARENA_START_MATCHMAKER_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartMatchmakerRating", 1500);
- m_bool_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfigMgr->GetBoolDefault("Arena.ArenaSeason.InProgress", true);
+ m_bool_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfigMgr->GetBoolDefault("Arena.ArenaSeason.InProgress", false);
m_bool_configs[CONFIG_ARENA_LOG_EXTENDED_INFO] = sConfigMgr->GetBoolDefault("ArenaLog.ExtendedInfo", false);
m_bool_configs[CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN] = sConfigMgr->GetBoolDefault("OffhandCheckAtSpellUnlearn", true);
@@ -2209,7 +2216,7 @@ void World::ForceGameEventUpdate()
}
/// Send a packet to all players (except self if mentioned)
-void World::SendGlobalMessage(WorldPacket* packet, WorldSession* self, uint32 team)
+void World::SendGlobalMessage(WorldPacket const* packet, WorldSession* self, uint32 team)
{
SessionMap::const_iterator itr;
for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
@@ -2226,7 +2233,7 @@ void World::SendGlobalMessage(WorldPacket* packet, WorldSession* self, uint32 te
}
/// Send a packet to all GMs (except self if mentioned)
-void World::SendGlobalGMMessage(WorldPacket* packet, WorldSession* self, uint32 team)
+void World::SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self, uint32 team)
{
for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
{
@@ -2354,7 +2361,7 @@ void World::SendGlobalText(const char* text, WorldSession* self)
}
/// Send a packet to all players (or players selected team) in the zone (except self if mentioned)
-bool World::SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self, uint32 team)
+bool World::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self, uint32 team)
{
bool foundPlayerToSend = false;
SessionMap::const_iterator itr;
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 3c3e40cc76b..7bf8f5b70e7 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -30,6 +30,7 @@
#include "SharedDefines.h"
#include "QueryResult.h"
#include "Callback.h"
+#include "Realm/Realm.h"
#include <atomic>
#include <map>
@@ -204,6 +205,7 @@ enum WorldIntConfigs
CONFIG_INTERVAL_CHANGEWEATHER,
CONFIG_INTERVAL_DISCONNECT_TOLERANCE,
CONFIG_PORT_WORLD,
+ CONFIG_PORT_INSTANCE,
CONFIG_SOCKET_TIMEOUTTIME,
CONFIG_SESSION_ADD_DELAY,
CONFIG_GAME_TYPE,
@@ -660,9 +662,9 @@ class World
void SendGlobalText(const char* text, WorldSession* self);
void SendGMText(uint32 string_id, ...);
void SendServerMessage(ServerMessageType type, const char *text = "", Player* player = NULL);
- void SendGlobalMessage(WorldPacket* packet, WorldSession* self = nullptr, uint32 team = 0);
- void SendGlobalGMMessage(WorldPacket* packet, WorldSession* self = nullptr, uint32 team = 0);
- bool SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self = nullptr, uint32 team = 0);
+ void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0);
+ void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0);
+ bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0);
void SendZoneText(uint32 zone, const char *text, WorldSession* self = nullptr, uint32 team = 0);
/// Are we in the middle of a shutdown?
@@ -887,6 +889,7 @@ class World
};
extern Battlenet::RealmHandle realmHandle;
+extern Realm realm;
uint32 GetVirtualRealmAddress();
#define sWorld World::instance()
diff --git a/src/server/scripts/Maelstrom/CMakeLists.txt b/src/server/scripts/Maelstrom/CMakeLists.txt
index 79f0789fd3f..8d3f1ee1c69 100644
--- a/src/server/scripts/Maelstrom/CMakeLists.txt
+++ b/src/server/scripts/Maelstrom/CMakeLists.txt
@@ -9,6 +9,13 @@
set(scripts_STAT_SRCS
${scripts_STAT_SRCS}
Maelstrom/kezan.cpp
+ Maelstrom/Stonecore/instance_stonecore.cpp
+ Maelstrom/Stonecore/stonecore.cpp
+ Maelstrom/Stonecore/stonecore.h
+ Maelstrom/Stonecore/boss_corborus.cpp
+ Maelstrom/Stonecore/boss_slabhide.cpp
+ Maelstrom/Stonecore/boss_ozruk.cpp
+ Maelstrom/Stonecore/boss_high_priestess_azil.cpp
)
message(" -> Prepared: The Maelstrom")
diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_corborus.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_corborus.cpp
new file mode 100644
index 00000000000..2d522928fce
--- /dev/null
+++ b/src/server/scripts/Maelstrom/Stonecore/boss_corborus.cpp
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "CreatureGroups.h"
+#include "stonecore.h"
+
+// TO-DO:
+// Find heroic sniffs and script spawning Crystal Shards on heroic mode.
+
+enum Spells
+{
+ // Corborus intro
+ SPELL_TWILIGHT_DOCUMENTS = 93167,
+ SPELL_RING_WYRM_CHARGE = 81237,
+ SPELL_DOOR_BREAK = 81232, // cast by World Trigger 22515
+
+ // Corborus boss
+ SPELL_DAMPENING_WAVE = 82415,
+ SPELL_CRYSTAL_BARRAGE = 86881, // 81638 triggers 81637
+// SPELL_CRYSTAL_BARRAGE_SHARD = 92012, // heroic only, summons Crystal Shard (TO-DO!)
+ SPELL_CLEAR_ALL_DEBUFFS = 34098,
+ SPELL_SUBMERGE = 81629,
+ SPELL_TRASHING_CHARGE_TELEPORT = 81839, // triggers 81864
+// SPELL_TRASHING_CHARGE_TELEPORT_2= 81838, // dummy, targets all players, threat update packet follows
+ SPELL_SUMMON_TRASHING_CHARGE = 81816,
+ SPELL_TRASHING_CHARGE_VISUAL = 81801, // cast time 3.5 sec
+ SPELL_TRASHING_CHARGE_EFFECT = 81828, // 40 yard radius
+ SPELL_EMERGE = 81948,
+
+ // Rock Borer npc (43917)
+ SPELL_ROCK_BORER_EMERGE = 82185,
+ SPELL_ROCK_BORE = 80028,
+};
+
+enum NPCs
+{
+ NPC_TRASHING_CHARGE = 43743,
+// NPC_CRYSTAL_SHARD = 49267, // 49473
+};
+
+enum Events
+{
+ EVENT_NONE,
+
+ // Corborus intro
+ EVENT_CORBORUS_CHARGE,
+ EVENT_CORBORUS_KNOCKBACK,
+ EVENT_CORBORUS_FACEPLAYERS,
+
+ // Corborus boss
+ EVENT_DAMPENING_WAVE,
+ EVENT_CRYSTAL_BARRAGE,
+ EVENT_SUBMERGE,
+ EVENT_TELEPORT,
+ EVENT_TRASHING_CHARGE,
+ EVENT_SUMMON_BEETLE,
+ EVENT_EMERGE,
+ EVENT_ATTACK,
+
+ // Rock Borer
+ EVENT_EMERGED,
+ EVENT_ROCK_BORE,
+};
+
+class boss_corborus : public CreatureScript
+{
+ public:
+ boss_corborus() : CreatureScript("boss_corborus") { }
+
+ struct boss_corborusAI : public BossAI
+ {
+ boss_corborusAI(Creature* creature) : BossAI(creature, DATA_CORBORUS)
+ {
+ stateIntro = NOT_STARTED;
+ }
+
+ void Reset() override
+ {
+ _Reset();
+ countTrashingCharge = 0;
+ events.ScheduleEvent(EVENT_DAMPENING_WAVE, 10000);
+ events.ScheduleEvent(EVENT_CRYSTAL_BARRAGE, 15000);
+ events.ScheduleEvent(EVENT_SUBMERGE, 36000);
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_CORBORUS_INTRO: // Executes Corborus intro event
+ {
+ if (stateIntro != NOT_STARTED)
+ return;
+
+ stateIntro = IN_PROGRESS;
+
+ if (Creature* Millhouse = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MILLHOUSE_MANASTORM)))
+ {
+ Millhouse->InterruptNonMeleeSpells(true);
+ Millhouse->RemoveAllAuras();
+ Millhouse->HandleEmoteCommand(EMOTE_ONESHOT_KNOCKDOWN);
+ }
+
+ events.ScheduleEvent(EVENT_CORBORUS_CHARGE, 1000);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && stateIntro != IN_PROGRESS)
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_CORBORUS_CHARGE:
+ // Face Millhouse and other mobs
+ instance->SetData(DATA_MILLHOUSE_EVENT_FACE, 0);
+
+ // Open rock gate and cast visual from nearby worldtrigger
+ instance->HandleGameObject(instance->GetGuidData(GAMEOBJECT_CORBORUS_ROCKDOOR), true);
+ if (Creature* worldtrigger = me->FindNearestCreature(NPC_WORLDTRIGGER, 60.0f))
+ worldtrigger->CastSpell(worldtrigger, SPELL_DOOR_BREAK, true);
+
+ // Make Corborus charge
+ me->CastSpell(me, SPELL_RING_WYRM_CHARGE, true);
+
+ events.ScheduleEvent(EVENT_CORBORUS_KNOCKBACK, 1000);
+ break;
+ case EVENT_CORBORUS_KNOCKBACK:
+ // Spawn Twilight Documents (quest gameobject)
+ if (Creature* Millhouse = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MILLHOUSE_MANASTORM)))
+ Millhouse->CastSpell(Millhouse, SPELL_TWILIGHT_DOCUMENTS, true);
+
+ // Knockback Millhouse and other mobs
+ instance->SetData(DATA_MILLHOUSE_EVENT_KNOCKBACK, 0);
+
+ events.ScheduleEvent(EVENT_CORBORUS_FACEPLAYERS, 2000);
+ break;
+ case EVENT_CORBORUS_FACEPLAYERS:
+ // Face Corborus to players and set new home position
+ me->SetFacingTo(3.176499f);
+ me->SetHomePosition(1154.55f, 878.843f, 284.963f, 3.176499f);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+
+ // Despawn Millhouse and all trash
+ instance->SetData(DATA_MILLHOUSE_EVENT_DESPAWN, 0);
+
+ stateIntro = DONE;
+ break;
+ case EVENT_DAMPENING_WAVE:
+ DoCastVictim(SPELL_DAMPENING_WAVE);
+ events.ScheduleEvent(EVENT_DAMPENING_WAVE, 15000);
+ break;
+ case EVENT_CRYSTAL_BARRAGE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_CRYSTAL_BARRAGE);
+ events.ScheduleEvent(EVENT_CRYSTAL_BARRAGE, 10000);
+ break;
+ case EVENT_SUBMERGE:
+ events.RescheduleEvent(EVENT_DAMPENING_WAVE, 35000);
+ events.RescheduleEvent(EVENT_CRYSTAL_BARRAGE, 30000);
+ events.RescheduleEvent(EVENT_SUBMERGE, 100000);
+
+ me->SetReactState(REACT_PASSIVE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_CLEAR_ALL_DEBUFFS);
+ me->AttackStop();
+
+ DoCast(me, SPELL_SUBMERGE);
+
+ countTrashingCharge = 0;
+ events.ScheduleEvent(EVENT_TELEPORT, 500);
+ break;
+ case EVENT_TELEPORT:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_TRASHING_CHARGE_TELEPORT);
+ countTrashingCharge += 1;
+ if (countTrashingCharge <= 4)
+ events.ScheduleEvent(EVENT_TRASHING_CHARGE, 1000);
+ else
+ events.ScheduleEvent(EVENT_EMERGE, 2500);
+ break;
+ case EVENT_TRASHING_CHARGE:
+ DoCast(me, SPELL_SUMMON_TRASHING_CHARGE);
+ DoCast(me, SPELL_TRASHING_CHARGE_VISUAL);
+ events.ScheduleEvent(EVENT_TELEPORT, 5000);
+ break;
+ case EVENT_EMERGE:
+ me->RemoveAllAuras();
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_EMERGE);
+ events.ScheduleEvent(EVENT_ATTACK, 2500);
+ break;
+ case EVENT_ATTACK:
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() != NPC_TRASHING_CHARGE)
+ return;
+
+ summon->SetReactState(REACT_PASSIVE);
+ summon->CastSpell(summon, SPELL_TRASHING_CHARGE_EFFECT);
+ summon->DespawnOrUnsummon(6000);
+ }
+
+ private:
+ EncounterState stateIntro;
+ uint32 countTrashingCharge;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_corborusAI>(creature);
+ }
+};
+
+// 43391 - Rock Borer
+class npc_rock_borer : public CreatureScript
+{
+ public:
+ npc_rock_borer() : CreatureScript("npc_rock_borer") { }
+
+ struct npc_rock_borerAI : public ScriptedAI
+ {
+ npc_rock_borerAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->SetDisableGravity(true);
+ me->SetReactState(REACT_PASSIVE);
+ events.ScheduleEvent(EVENT_EMERGED, 1200);
+ events.ScheduleEvent(EVENT_ROCK_BORE, urand(15000, 20000)); // Need sniffs for this timer
+ }
+
+ void IsSummonedBy(Unit* summoner) override
+ {
+ me->SetInCombatState(false, summoner);
+ DoCast(SPELL_ROCK_BORER_EMERGE);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim() && me->GetReactState() != REACT_PASSIVE)
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_EMERGED:
+ me->RemoveAurasDueToSpell(SPELL_ROCK_BORER_EMERGE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ case EVENT_ROCK_BORE:
+ DoCast(SPELL_ROCK_BORE);
+ events.ScheduleEvent(EVENT_ROCK_BORE, urand(15000, 20000)); // Need sniffs for this timer
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_rock_borerAI>(creature);
+ }
+};
+
+void AddSC_boss_corborus()
+{
+ new boss_corborus();
+ new npc_rock_borer();
+}
diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp
new file mode 100644
index 00000000000..477d3baf206
--- /dev/null
+++ b/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp
@@ -0,0 +1,808 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "Player.h"
+#include "Vehicle.h"
+#include "stonecore.h"
+
+enum Spells
+{
+ SPELL_ENERGY_SHIELD = 82858,
+
+ SPELL_CURSE_OF_BLOOD = 79345,
+ SPELL_FORCE_GRIP = 79351,
+ SPELL_SUMMON_GRAVITY_WELL = 79340,
+ SPELL_EARTH_FURY_ENERGY_SHIELD = 79050,
+
+ // Gravity Well
+ SPELL_GRAVITY_WELL_VISUAL = 79245,
+ SPELL_GRAVITY_WELL_AURA_DAMAGE = 79244,
+ SPELL_GRAVITY_WELL_AURA_PULL = 79333,
+
+ SPELL_GRAVITY_WELL_DAMAGE = 79249,
+ SPELL_GRAVITY_WELL_PULL = 79332,
+
+ // Fury of Earth phase
+ SPELL_EARTH_FURY_CASTING_VISUAL = 79002,
+ SPELL_SEISMIC_SHARD_SUMMON_1 = 86860,
+ SPELL_SEISMIC_SHARD_SUMMON_2 = 86858,
+ SPELL_SEISMIC_SHARD_SUMMON_3 = 86856,
+ SPELL_SEISMIC_SHARD_VISUAL = 79009,
+ SPELL_SEISMIC_SHARD_PREPARE = 86862,
+ SPELL_SEISMIC_SHARD_TARGETING = 80511,
+ SPELL_SEISMIC_SHARD_LAUNCH = 79015,
+ SPELL_SEISMIC_SHARD_MISSLE = 79014,
+ SPELL_EJECT_ALL_PASSENGERS = 68576,
+
+ // Add wave spells
+ SPELL_SUMMON_WAVE_SOUTH = 79200,
+ SPELL_SUMMON_WAVE_WEST = 79196,
+ SPELL_SUMMON_ADD_SOUTH = 79193,
+ SPELL_SUMMON_ADD_WEST = 79199,
+};
+
+enum NPCs
+{
+ NPC_DEVOUT_FOLLOWER = 42428,
+ NPC_SEISMIC_SHARD = 42355,
+};
+
+enum Texts
+{
+ SAY_AGGRO = 0,
+ SAY_PHASE_TWO = 1,
+ SAY_DEATH = 2,
+};
+
+enum Events
+{
+ EVENT_NONE,
+
+ EVENT_INTRO_MOVE,
+
+ EVENT_CURSE_OF_BLOOD,
+ EVENT_FORCE_GRIP,
+ EVENT_SUMMON_GRAVITY_WELL,
+ EVENT_ENERGY_SHIELD,
+ EVENT_EARTH_FURY,
+
+ EVENT_SUMMON_WAVE_SOUTH,
+ EVENT_SUMMON_WAVE_WEST,
+
+ EVENT_GRAVITY_WELL_AURA_DAMAGE,
+ EVENT_GRAVITY_WELL_AURA_PULL,
+
+ // Phase 2: Fury of Earth
+ EVENT_EARTH_FURY_FLY_UP,
+ EVENT_EARTH_FURY_FLY_ABOVE_PLATFORM,
+ EVENT_EARTH_FURY_CHECK_SEAT0,
+ EVENT_EARTH_FURY_LAUNCH_SHARD,
+ EVENT_EARTH_FURY_FLY_DOWN,
+ EVENT_START_ATTACK,
+
+ EVENT_LAUNCH,
+ EVENT_SEISMIC_SHARD_MOUNT
+};
+
+enum EventGroups
+{
+ EVENT_GROUP_PHASE_ONE,
+ EVENT_GROUP_ADDS,
+};
+
+enum Points
+{
+ POINT_NONE,
+
+ POINT_INTRO_MOVE,
+ POINT_FLY_UP,
+ POINT_ABOVE_PLATFORM,
+ POINT_PLATFORM,
+ POINT_GROUND,
+};
+
+Position const GroundPos = { 1331.82f, 980.314f, 207.542f };
+Position const AbovePlatformPos = { 1336.21f, 960.813f, 215.0f };
+
+// TO-DO:
+// - Find out why NPCs summoned by boss are usually two times bigger than their normal size.
+// - Find more sniffs and script Force Grip spell (79351)
+
+class boss_high_priestess_azil : public CreatureScript
+{
+ public:
+ boss_high_priestess_azil() : CreatureScript("boss_high_priestess_azil") { }
+
+ struct boss_high_priestess_azilAI : public BossAI
+ {
+ boss_high_priestess_azilAI(Creature* creature) : BossAI(creature, DATA_HIGH_PRIESTESS_AZIL), vehicle(creature->GetVehicleKit())
+ {
+ ASSERT(vehicle);
+ }
+
+ Vehicle* vehicle;
+
+ void Reset() override
+ {
+ _Reset();
+
+ me->SetCanFly(false);
+ me->SetDisableGravity(false);
+ me->SetReactState(REACT_PASSIVE);
+
+ events.ScheduleEvent(EVENT_INTRO_MOVE, 2000);
+ events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, 6000, EVENT_GROUP_PHASE_ONE);
+ events.ScheduleEvent(EVENT_FORCE_GRIP, urand(8000,10000), EVENT_GROUP_PHASE_ONE);
+ events.ScheduleEvent(EVENT_SUMMON_GRAVITY_WELL, 16000, EVENT_GROUP_PHASE_ONE);
+ events.ScheduleEvent(EVENT_ENERGY_SHIELD, urand(35000,36000));
+ events.ScheduleEvent(EVENT_SUMMON_WAVE_SOUTH, 0);
+ events.ScheduleEvent(EVENT_SUMMON_WAVE_WEST, 40000);
+ }
+
+ void EnterCombat(Unit* /*victim*/) override
+ {
+ _EnterCombat();
+
+ DoCast(SPELL_ENERGY_SHIELD);
+ Talk(SAY_AGGRO);
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ me->Say(SAY_DEATH);
+ }
+
+ /*
+ void PassengerBoarded(Unit* who, int8 seatId, bool apply) override
+ {
+ if (!apply || who->GetEntry() != NPC_SEISMIC_SHARD)
+ return;
+
+ Movement::MoveSplineInit init(who);
+ init.DisableTransportPathTransformations();
+ if (seatId == 0)
+ init.MoveTo(12.13748f, 0.0f, 2.442475f);
+ else if (seatId == 1)
+ init.MoveTo(12.13748f, 17.5f, 11.19248f);
+ else
+ init.MoveTo(12.13748f, -17.5f, 11.19248f);
+ init.Launch();
+ }
+ */
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != POINT_MOTION_TYPE && id != POINT_INTRO_MOVE)
+ return;
+
+ switch (id)
+ {
+ case POINT_INTRO_MOVE:
+ me->RemoveAurasDueToSpell(SPELL_ENERGY_SHIELD);
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ case POINT_FLY_UP:
+ me->SetCanFly(true);
+ me->SetDisableGravity(true);
+ events.ScheduleEvent(EVENT_EARTH_FURY_FLY_ABOVE_PLATFORM, 1000);
+ break;
+ case POINT_ABOVE_PLATFORM:
+ me->SetFacingTo(5.218534f);
+ DoCast(SPELL_EARTH_FURY_CASTING_VISUAL);
+ DoCast(SPELL_SEISMIC_SHARD_SUMMON_1);
+ DoCast(SPELL_SEISMIC_SHARD_SUMMON_2);
+ DoCast(SPELL_SEISMIC_SHARD_SUMMON_3);
+ events.ScheduleEvent(EVENT_EARTH_FURY_CHECK_SEAT0, 6700);
+ break;
+ case POINT_GROUND:
+ DoCast(SPELL_EJECT_ALL_PASSENGERS);
+ me->SetCanFly(false);
+ me->SetDisableGravity(false);
+ me->SetReactState(REACT_AGGRESSIVE);
+ // Find more sniffs to correct these timers, this was copied from Reset() void.
+ events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, 6000, EVENT_GROUP_PHASE_ONE);
+ events.ScheduleEvent(EVENT_FORCE_GRIP, urand(8000, 10000), EVENT_GROUP_PHASE_ONE);
+ events.ScheduleEvent(EVENT_SUMMON_GRAVITY_WELL, 16000, EVENT_GROUP_PHASE_ONE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_INTRO_MOVE:
+ me->GetMotionMaster()->MoveJump(GroundPos, me->GetSpeed(MOVE_FLIGHT), 1.918408f, POINT_INTRO_MOVE);
+ break;
+ case EVENT_CURSE_OF_BLOOD:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_CURSE_OF_BLOOD);
+ events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(13000, 15000), EVENT_GROUP_PHASE_ONE);
+ break;
+ case EVENT_FORCE_GRIP:
+ DoCastVictim(SPELL_FORCE_GRIP);
+ events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(13000, 15000), EVENT_GROUP_PHASE_ONE);
+ break;
+ case EVENT_SUMMON_GRAVITY_WELL:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_SUMMON_GRAVITY_WELL);
+ events.ScheduleEvent(EVENT_SUMMON_GRAVITY_WELL, urand(13000, 15000), EVENT_GROUP_PHASE_ONE);
+ break;
+ case EVENT_ENERGY_SHIELD:
+ events.CancelEventGroup(EVENT_GROUP_PHASE_ONE);
+ DoCast(SPELL_EARTH_FURY_ENERGY_SHIELD);
+ events.ScheduleEvent(EVENT_EARTH_FURY, 0);
+ break;
+ case EVENT_EARTH_FURY:
+ countSeismicShard = 3;
+ me->SetReactState(REACT_PASSIVE);
+ me->SetFacingTo(5.862942f);
+ events.ScheduleEvent(EVENT_EARTH_FURY_FLY_UP, 1600);
+ break;
+ case EVENT_EARTH_FURY_FLY_UP:
+ Talk(SAY_PHASE_TWO);
+ me->GetMotionMaster()->MovePoint(POINT_FLY_UP, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 5);
+ break;
+ case EVENT_EARTH_FURY_FLY_ABOVE_PLATFORM:
+ me->GetMotionMaster()->MovePoint(POINT_ABOVE_PLATFORM, AbovePlatformPos);
+ break;
+ case EVENT_EARTH_FURY_CHECK_SEAT0:
+ if (!vehicle->GetPassenger(0))
+ DoCast(SPELL_SEISMIC_SHARD_PREPARE);
+ events.ScheduleEvent(EVENT_EARTH_FURY_LAUNCH_SHARD, 1800);
+ break;
+ case EVENT_EARTH_FURY_LAUNCH_SHARD:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ {
+ me->SetFacingToObject(target);
+ DoCast(target, SPELL_SEISMIC_SHARD_TARGETING);
+ DoCast(SPELL_SEISMIC_SHARD_LAUNCH);
+ countSeismicShard -= 1;
+ }
+ events.ScheduleEvent(countSeismicShard > 0 ? EVENT_EARTH_FURY_CHECK_SEAT0 : EVENT_EARTH_FURY_FLY_DOWN, 4800);
+ break;
+ case EVENT_EARTH_FURY_FLY_DOWN:
+ {
+ me->RemoveAurasDueToSpell(SPELL_EARTH_FURY_CASTING_VISUAL);
+ me->RemoveAurasDueToSpell(SPELL_EARTH_FURY_ENERGY_SHIELD);
+ Position pos = me->GetPosition();
+ pos.m_positionZ = me->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
+ me->GetMotionMaster()->MovePoint(POINT_GROUND, pos);
+ break;
+ }
+ case EVENT_SUMMON_WAVE_SOUTH:
+ if (Creature* worldtrigger = me->FindNearestCreature(NPC_WORLDTRIGGER, 150.0f))
+ worldtrigger->CastSpell(worldtrigger, SPELL_SUMMON_WAVE_SOUTH);
+ events.ScheduleEvent(EVENT_SUMMON_WAVE_SOUTH, 12000);
+ break;
+ case EVENT_SUMMON_WAVE_WEST:
+ if (Creature* worldtrigger = me->FindNearestCreature(NPC_WORLDTRIGGER, 150.0f))
+ worldtrigger->CastSpell(worldtrigger, SPELL_SUMMON_WAVE_WEST);
+ events.ScheduleEvent(EVENT_SUMMON_WAVE_WEST, 20000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ uint8 countSeismicShard;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_high_priestess_azilAI>(creature);
+ }
+};
+
+// 42428 - Devout Follower
+class npc_devout_follower : public CreatureScript
+{
+public:
+ npc_devout_follower() : CreatureScript("npc_devout_follower") { }
+
+ struct npc_devout_followerAI : public ScriptedAI
+ {
+ npc_devout_followerAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void IsSummonedBy(Unit* summoner) override
+ {
+ if (summoner->GetEntry() != NPC_WORLDTRIGGER)
+ return;
+
+ if (Unit* target = me->SelectNearestPlayer(200.0f))
+ {
+ me->AddThreat(target, 0.0f);
+ me->SetInCombatWith(target);
+ target->SetInCombatWith(me);
+ DoStartMovement(target);
+ me->Attack(target, true);
+ }
+ else
+ me->GetMotionMaster()->MovePoint(POINT_NONE, summoner->GetPosition());
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_devout_followerAI>(creature);
+ }
+};
+
+// 42499 - Gravity Well
+class npc_gravity_well : public CreatureScript
+{
+public:
+ npc_gravity_well() : CreatureScript("npc_gravity_well") { }
+
+ struct npc_gravity_wellAI : public ScriptedAI
+ {
+ npc_gravity_wellAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ DoCast(SPELL_GRAVITY_WELL_VISUAL);
+ events.ScheduleEvent(EVENT_GRAVITY_WELL_AURA_DAMAGE, 3200);
+ events.ScheduleEvent(EVENT_GRAVITY_WELL_AURA_PULL, 4500);
+ if (!me->GetMap()->IsHeroic())
+ me->DespawnOrUnsummon(23200);
+ }
+
+ void KilledUnit(Unit* victim) override
+ {
+ if (victim->GetEntry() != NPC_DEVOUT_FOLLOWER)
+ return;
+
+ me->SetObjectScale(me->GetObjectScale() - 0.25f);
+ if (me->GetObjectScale() <= 0.0f)
+ me->DespawnOrUnsummon(1000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_GRAVITY_WELL_AURA_DAMAGE:
+ me->RemoveAurasDueToSpell(SPELL_GRAVITY_WELL_VISUAL);
+ DoCast(SPELL_GRAVITY_WELL_AURA_DAMAGE);
+ break;
+ case EVENT_GRAVITY_WELL_AURA_PULL:
+ DoCast(SPELL_GRAVITY_WELL_AURA_PULL);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_gravity_wellAI>(creature);
+ }
+};
+
+// 42355 - Seismic Shard
+class npc_seismic_shard : public CreatureScript
+{
+public:
+ npc_seismic_shard() : CreatureScript("npc_seismic_shard") { }
+
+ struct npc_seismic_shardAI : public ScriptedAI
+ {
+ npc_seismic_shardAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = creature->GetInstanceScript();
+ me->SetDisableGravity(true);
+ me->SetReactState(REACT_PASSIVE);
+ DoCast(SPELL_SEISMIC_SHARD_VISUAL);
+
+ Movement::MoveSplineInit init(me);
+ FillPath(me->GetPosition(), init.Path());
+ init.SetFly();
+ init.Launch();
+
+ events.ScheduleEvent(EVENT_SEISMIC_SHARD_MOUNT, 2400);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SEISMIC_SHARD_MOUNT:
+ if (Creature* highPriestAzil = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGH_PRIESTESS_AZIL)))
+ if (Vehicle* vehicle = highPriestAzil->GetVehicleKit())
+ me->EnterVehicle(highPriestAzil, vehicle->GetNextEmptySeat(0, false)->first);
+ break;
+ default:
+ break;
+ }
+ }
+
+ }
+
+ private:
+ void FillPath(Position const& pos, Movement::PointsArray& path)
+ {
+ G3D::Vector3 point;
+
+ point.x = pos.GetPositionX();
+ point.y = pos.GetPositionY();
+ point.z = pos.GetPositionZ();
+
+ point.x -= 1.0f;
+ path.push_back(point);
+
+ point.x += 1.0f;
+ path.push_back(point);
+
+ point.z += 25.0f;
+ path.push_back(point);
+
+ path.push_back(point);
+ }
+
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_seismic_shardAI>(creature);
+ }
+};
+
+// 79200 - Summon Follower
+class spell_summon_wave_south : public SpellScriptLoader
+{
+public:
+ spell_summon_wave_south() : SpellScriptLoader("spell_summon_wave_south") { }
+
+ class spell_summon_wave_south_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_summon_wave_south_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ADD_SOUTH))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ for (uint8 i = 0; i < 3; i++)
+ GetCaster()->CastSpell(GetCaster(), SPELL_SUMMON_ADD_SOUTH, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_summon_wave_south_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_summon_wave_south_SpellScript();
+ }
+};
+
+// 79196 - Summon Follower
+class spell_summon_wave_west : public SpellScriptLoader
+{
+public:
+ spell_summon_wave_west() : SpellScriptLoader("spell_summon_wave_west") { }
+
+ class spell_summon_wave_west_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_summon_wave_west_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ADD_WEST))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Unit* caster = GetCaster();
+ for (uint8 i = 0; i < 10; i++)
+ GetCaster()->CastSpell(GetCaster(), SPELL_SUMMON_ADD_WEST, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_summon_wave_west_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_summon_wave_west_SpellScript();
+ }
+};
+
+// 79251 - Gravity Well (casts damage spell on units within 10 yards)
+class PlayerPetOrDevoutFollowerCheck
+{
+public:
+ bool operator()(WorldObject* object) const
+ {
+ // Valid targets are players, pets and Devout Followers
+ if (Creature* creature = object->ToCreature())
+ return (!creature->ToPet() && object->GetEntry() != NPC_DEVOUT_FOLLOWER);
+ return (!object->ToPlayer());
+ }
+};
+
+class spell_gravity_well_damage_nearby : public SpellScriptLoader
+{
+public:
+ spell_gravity_well_damage_nearby() : SpellScriptLoader("spell_gravity_well_damage_nearby") { }
+
+ class spell_gravity_well_damage_nearby_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gravity_well_damage_nearby_SpellScript);
+
+ void SetRadiusMod()
+ {
+ GetSpell()->SetSpellValue(SPELLVALUE_RADIUS_MOD, int32(GetCaster()->GetObjectScale() * 10000 * 2 / 3));
+ }
+
+ void FilterTargets(std::list<WorldObject*>& unitList)
+ {
+ unitList.remove_if(PlayerPetOrDevoutFollowerCheck());
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_GRAVITY_WELL_DAMAGE, true);
+ }
+
+ void Register() override
+ {
+ BeforeCast += SpellCastFn(spell_gravity_well_damage_nearby_SpellScript::SetRadiusMod);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gravity_well_damage_nearby_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnEffectHitTarget += SpellEffectFn(spell_gravity_well_damage_nearby_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_gravity_well_damage_nearby_SpellScript();
+ }
+};
+
+// 79249 - Gravity Well (damage)
+class spell_gravity_well_damage : public SpellScriptLoader
+{
+public:
+ spell_gravity_well_damage() : SpellScriptLoader("spell_gravity_well_damage") { }
+
+ class spell_gravity_well_damage_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gravity_well_damage_SpellScript);
+
+ void CalculateDamage(SpellEffIndex /*effIndex*/)
+ {
+ Unit* target = GetHitUnit();
+ if (!target)
+ return;
+
+ float distance = GetCaster()->GetDistance2d(target);
+
+ if (target->GetEntry() == NPC_DEVOUT_FOLLOWER)
+ SetHitDamage(int32(200000 - (1000 * distance))); //need more research on this formula, damage values from sniffs: 189264, 190318, 190478, 196134, 197672, 199735
+ else
+ SetHitDamage(int32(4000 - (200 * distance)));
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gravity_well_damage_SpellScript::CalculateDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_gravity_well_damage_SpellScript();
+ }
+};
+
+// 79332 - Gravity Well (pull units within 10 yards)
+class PulledRecentlyCheck
+{
+public:
+ bool operator()(WorldObject* object) const
+ {
+ return (object->ToUnit() && object->ToUnit()->HasAura(SPELL_GRAVITY_WELL_PULL));
+ }
+};
+
+class spell_gravity_well_pull : public SpellScriptLoader
+{
+public:
+ spell_gravity_well_pull() : SpellScriptLoader("spell_gravity_well_pull") { }
+
+ class spell_gravity_well_pull_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gravity_well_pull_SpellScript);
+
+ void SetRadiusMod()
+ {
+ GetSpell()->SetSpellValue(SPELLVALUE_RADIUS_MOD, int32(GetCaster()->GetObjectScale() * 10000 * 2 / 3));
+ }
+
+ void FilterTargets(std::list<WorldObject*>& unitList)
+ {
+ unitList.remove_if(PulledRecentlyCheck());
+ }
+
+ void Register() override
+ {
+ BeforeCast += SpellCastFn(spell_gravity_well_pull_SpellScript::SetRadiusMod);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gravity_well_pull_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_gravity_well_pull_SpellScript();
+ }
+};
+
+// 86862 - Seismic Shard (forces target to cast 86863)
+class spell_seismic_shard_prepare : public SpellScriptLoader
+{
+public:
+ spell_seismic_shard_prepare() : SpellScriptLoader("spell_seismic_shard_prepare") { }
+
+ class spell_seismic_shard_prepare_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_seismic_shard_prepare_SpellScript);
+
+ void SetTarget(WorldObject*& target)
+ {
+ target = GetCaster()->FindNearestCreature(NPC_SEISMIC_SHARD, 50.0f);
+ }
+
+ void Register() override
+ {
+ OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_seismic_shard_prepare_SpellScript::SetTarget, EFFECT_0, TARGET_UNIT_NEARBY_ENTRY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_seismic_shard_prepare_SpellScript();
+ }
+};
+
+// 86863 - Seismic Shard (moves shard to seat 0)
+class spell_seismic_shard_change_seat : public SpellScriptLoader
+{
+public:
+ spell_seismic_shard_change_seat() : SpellScriptLoader("spell_seismic_shard_change_seat") { }
+
+ class spell_seismic_shard_change_seat_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_seismic_shard_change_seat_SpellScript);
+
+ void SetTarget(WorldObject*& target)
+ {
+ if (InstanceScript* instance = GetCaster()->GetInstanceScript())
+ target = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_HIGH_PRIESTESS_AZIL));
+ }
+
+ void ChangeSeat(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->ExitVehicle();
+ if (GetHitUnit()->IsVehicle())
+ GetCaster()->EnterVehicle(GetHitUnit(), 0);
+ }
+
+ void Register() override
+ {
+ OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_seismic_shard_change_seat_SpellScript::SetTarget, EFFECT_0, TARGET_UNIT_NEARBY_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_seismic_shard_change_seat_SpellScript::ChangeSeat, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_seismic_shard_change_seat_SpellScript();
+ }
+};
+
+// 79015 - Seismic Shard (launches shard)
+class spell_seismic_shard : public SpellScriptLoader
+{
+public:
+ spell_seismic_shard() : SpellScriptLoader("spell_seismic_shard") { }
+
+ class spell_seismic_shard_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_seismic_shard_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Creature* target = GetHitUnit()->ToCreature();
+ if (!target)
+ return;
+
+ target->ExitVehicle();
+ DynamicObject* dynamicObject = GetCaster()->GetDynObject(SPELL_SEISMIC_SHARD_TARGETING);
+ target->CastSpell(dynamicObject->GetPositionX(), dynamicObject->GetPositionY(), dynamicObject->GetPositionZ(), SPELL_SEISMIC_SHARD_MISSLE, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_seismic_shard_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_seismic_shard_SpellScript();
+ }
+};
+
+void AddSC_boss_high_priestess_azil()
+{
+ new boss_high_priestess_azil();
+ new npc_devout_follower();
+ new npc_gravity_well();
+ new npc_seismic_shard();
+ new spell_summon_wave_south();
+ new spell_summon_wave_west();
+ new spell_gravity_well_damage_nearby();
+ new spell_gravity_well_damage();
+ new spell_gravity_well_pull();
+ new spell_seismic_shard_prepare();
+ new spell_seismic_shard_change_seat();
+ new spell_seismic_shard();
+}
diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_ozruk.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_ozruk.cpp
new file mode 100644
index 00000000000..92c9bba4bc1
--- /dev/null
+++ b/src/server/scripts/Maelstrom/Stonecore/boss_ozruk.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "SpellAuraEffects.h"
+#include "Vehicle.h"
+#include "stonecore.h"
+
+enum Spells
+{
+ SPELL_ELEMENTIUM_BULWARK = 78939,
+ SPELL_GROUND_SLAM = 78903,
+ SPELL_ELEMENTIUM_SPIKE_SHIELD = 78835,
+ SPELL_SHATTER = 78807,
+ SPELL_ENRAGE = 80467,
+
+ // Rupture Controller and Rupture
+ SPELL_RUPTURE = 92393,
+// SPELL_RUPTURE_SUMMON_CENTER? = 95669, // summons rupture 8 yards front
+// SPELL_RUPTURE_SUMMON_LEFT? = 95348, // summons rupture 3 yards left?
+// SPELL_RUPTURE_SUMMON_RIGHT? = 92383, // summons rupture 3 yards right?
+ SPELL_RUPTURE_DAMAGE = 92381,
+};
+
+enum NPCs
+{
+ NPC_BOUNCER_SPIKE = 42189,
+ NPC_RUPTURE_CONTROLLER = 49597,
+ NPC_RUPTURE = 49576,
+};
+
+enum Texts
+{
+ SAY_AGGRO = 0,
+ SAY_ELEMENTIUM_BULWARK = 1,
+ SAY_ELEMENTIUM_SPIKE_SHIELD = 2,
+ SAY_ENRAGE = 3,
+ SAY_DEATH = 4,
+};
+
+enum Events
+{
+ EVENT_NONE,
+
+ EVENT_ELEMENTIUM_BULWARK,
+ EVENT_GROUND_SLAM,
+ EVENT_ELEMENTIUM_SPIKE_SHIELD,
+ EVENT_SHATTER,
+ EVENT_ENRAGE,
+
+ EVENT_START_ATTACK,
+};
+
+// TO-DO:
+// - Find heroic sniffs and spawn Ruptures using spells commented above.
+// - Make Bouncer Spikes enter ozruk without jump animation.
+
+class boss_ozruk : public CreatureScript
+{
+ public:
+ boss_ozruk() : CreatureScript("boss_ozruk") { }
+
+ struct boss_ozrukAI : public BossAI
+ {
+ boss_ozrukAI(Creature* creature) : BossAI(creature, DATA_OZRUK) { }
+
+ void Reset() override
+ {
+ _Reset();
+
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ events.ScheduleEvent(EVENT_ELEMENTIUM_BULWARK, 5000);
+ events.ScheduleEvent(EVENT_GROUND_SLAM, 10000);
+ events.ScheduleEvent(EVENT_ELEMENTIUM_SPIKE_SHIELD, 13000);
+
+ RemoveBouncerSpikes();
+ }
+
+ void EnterCombat(Unit* /*victim*/) override
+ {
+ _EnterCombat();
+
+ Talk(SAY_AGGRO);
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() != NPC_RUPTURE_CONTROLLER)
+ return;
+
+ summon->SetReactState(REACT_PASSIVE);
+ summon->CastSpell(summon, SPELL_RUPTURE, true);
+ summon->DespawnOrUnsummon(10000);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
+ {
+ if (!me->HealthBelowPctDamaged(25, damage) || me->HasAura(SPELL_ENRAGE))
+ return;
+
+ DoCast(me, SPELL_ENRAGE);
+ me->Say(SAY_ENRAGE);
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ me->Say(SAY_DEATH, killer); // receiver is the killer, sniff source!
+
+ RemoveBouncerSpikes();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_ELEMENTIUM_SPIKE_SHIELD))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_ELEMENTIUM_BULWARK:
+ DoCast(me, SPELL_ELEMENTIUM_BULWARK);
+ Talk(SAY_ELEMENTIUM_BULWARK);
+ break;
+ case EVENT_GROUND_SLAM:
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ DoCast(me, SPELL_GROUND_SLAM);
+ events.ScheduleEvent(EVENT_START_ATTACK, 4600);
+ break;
+ case EVENT_ELEMENTIUM_SPIKE_SHIELD:
+ DoCast(me, SPELL_ELEMENTIUM_SPIKE_SHIELD);
+ Talk(SAY_ELEMENTIUM_SPIKE_SHIELD);
+ events.ScheduleEvent(EVENT_SHATTER, 10000);
+ break;
+ case EVENT_SHATTER:
+ RemoveBouncerSpikes();
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ DoCast(me, SPELL_SHATTER);
+ events.ScheduleEvent(EVENT_START_ATTACK, 4600);
+ // Spells are cast in same order everytime after Shatter, so we schedule them here
+ events.ScheduleEvent(EVENT_ELEMENTIUM_BULWARK, urand(3000,4000));
+ events.ScheduleEvent(EVENT_GROUND_SLAM, urand(7000,9000));
+ events.ScheduleEvent(EVENT_ELEMENTIUM_SPIKE_SHIELD, urand(10000,12000));
+ break;
+ case EVENT_START_ATTACK:
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void RemoveBouncerSpikes()
+ {
+ Vehicle* vehicle = me->GetVehicleKit();
+ if (!vehicle)
+ return;
+
+ for (uint8 i = 0; i < vehicle->GetAvailableSeatCount(); i++)
+ if (Unit* passenger = vehicle->GetPassenger(i))
+ if (Creature* creature = passenger->ToCreature())
+ creature->RemoveFromWorld();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_ozrukAI>(creature);
+ }
+};
+
+// 92393 - Rupture
+class spell_rupture : public SpellScriptLoader
+{
+public:
+ spell_rupture() : SpellScriptLoader("spell_rupture") { }
+
+ class spell_rupture_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_rupture_AuraScript);
+
+ void HandleEffectPeriodic(AuraEffect const* aurEff)
+ {
+ Unit* caster = GetCaster();
+
+ float dist = aurEff->GetTickNumber() * 8.0f;
+
+ // probably hack, should use spells (see Spells enum above)
+ Position pos = caster->GetNearPosition(dist, 0.0f);
+ SummonRupture(caster, pos);
+
+ pos = caster->GetNearPosition(dist, 0.2f);
+ SummonRupture(caster, pos);
+
+ pos = caster->GetNearPosition(dist, -0.2f);
+ SummonRupture(caster, pos);
+ }
+
+ void SummonRupture(Unit* caster, Position pos)
+ {
+ Creature* rupture = caster->SummonCreature(NPC_RUPTURE, pos, TEMPSUMMON_TIMED_DESPAWN, 2500);
+ if (!rupture)
+ return;
+
+ rupture->SetReactState(REACT_PASSIVE);
+ rupture->CastSpell(rupture, SPELL_RUPTURE_DAMAGE, true);
+ }
+
+ void Register()
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_rupture_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const
+ {
+ return new spell_rupture_AuraScript();
+ }
+};
+
+// 78835 - Elementium Spike Shield
+class spell_elementium_spike_shield : public SpellScriptLoader
+{
+public:
+ spell_elementium_spike_shield() : SpellScriptLoader("spell_elementium_spike_shield") { }
+
+ class spell_elementium_spike_shield_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_elementium_spike_shield_SpellScript);
+
+ void HandleBouncerSpikes()
+ {
+ Unit* caster = GetCaster();
+ Vehicle* vehicle = caster->GetVehicleKit();
+ if (!vehicle)
+ return;
+
+ for (uint8 i = 0; i < vehicle->GetAvailableSeatCount(); i++)
+ if (Creature* summon = caster->SummonCreature(NPC_BOUNCER_SPIKE, caster->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 10000))
+ summon->EnterVehicle(caster, i);
+ }
+
+ void Register() override
+ {
+ OnCast += SpellCastFn(spell_elementium_spike_shield_SpellScript::HandleBouncerSpikes);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_elementium_spike_shield_SpellScript();
+ }
+};
+
+void AddSC_boss_ozruk()
+{
+ new boss_ozruk();
+ new spell_rupture();
+ new spell_elementium_spike_shield();
+}
diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp
new file mode 100644
index 00000000000..6827312deef
--- /dev/null
+++ b/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp
@@ -0,0 +1,599 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "stonecore.h"
+
+enum Spells
+{
+ SPELL_FACE_RANDOM_PLAYER = 82530,
+
+ // Stalactite Trigger - Trash, On Ground
+ SPELL_STALACTITE_SUMMON_TRIGGER = 81028,
+
+ // Slabhide
+ SPELL_LAVA_FISSURE = 80803,
+ SPELL_SAND_BLAST = 80807,
+ SPELL_STALACTITE_SUMMON = 80656,
+// SPELL_COOLDOWN_5S = 95323, Cooldown: Creature Special 1 (5s)?
+ SPELL_CRYSTAL_STORM = 92305,
+ SPELL_CRYSTAL_STORM_TRIGGER = 92265,
+
+ // Lava Fissure
+ SPELL_LAVA_FISSURE_CRACK = 80798,
+ SPELL_LAVA_FISSURE_ERUPTION = 80800,
+
+ // Stalactite Trigger - Boss
+ SPELL_STALACTITE_SHADE = 80654,
+ SPELL_STALACTITE_MISSLE = 80643,
+ SPELL_STALACTITE_CREATE = 80647,
+};
+
+enum Entries
+{
+ NPC_LAVA_FISSURE = 43242,
+ NPC_STALACTITE_TRIGGER_GROUND = 43357,
+ NPC_STALACTITE_TRIGGER = 43159,
+ GO_STALACTITE = 204337,
+};
+
+enum Actions
+{
+ ACTION_STALACTITE_MISSLE,
+};
+
+enum Events
+{
+ EVENT_NONE,
+
+ // Intro events
+ EVENT_ROAR_EMOTE,
+
+ // Slabhide combat
+ EVENT_HANDLE_ROCK_WALLS,
+ EVENT_LAVA_FISSURE,
+ EVENT_SAND_BLAST,
+ EVENT_AIR_PHASE,
+ EVENT_TAKEOFF,
+ EVENT_STALACTITE,
+ EVENT_LAND,
+ EVENT_ATTACK,
+
+ // Lava Fissure
+ EVENT_LAVA_FISSURE_ERUPTION,
+
+ // Stalactite Trigger - Boss
+ EVENT_STALACTITE_MISSLE,
+};
+
+enum MovementPoints
+{
+ POINT_NONE,
+
+ POINT_SLABHIDE_INTRO,
+ POINT_SLABHIDE_INTRO_LAND,
+
+ POINT_SLABHIDE_MIDDLE,
+ POINT_SLABHIDE_IN_AIR,
+ POINT_SLABHIDE_LAND,
+};
+
+Position const SlabhideIntroPos = { 1292.27f, 1226.16f, 265.573f };
+Position const SlabhideIntroLandPos = { 1292.352f, 1226.478f, 247.6368f, 3.630285f };
+
+Position const SlabhideMiddlePos = { 1280.73f, 1212.31f, 247.3837f };
+Position const SlabhideInAirPos = { 1280.73f, 1212.31f, 257.3837f };
+Position const SlabhideLandPos = { 1282.7f, 1229.77f, 247.155f, 3.82227f };
+
+class boss_slabhide : public CreatureScript
+{
+ public:
+ boss_slabhide() : CreatureScript("boss_slabhide") { }
+
+ struct boss_slabhideAI : public BossAI
+ {
+ boss_slabhideAI(Creature* creature) : BossAI(creature, DATA_SLABHIDE)
+ {
+ me->setActive(true);
+ me->SetCanFly(true);
+ me->SetDisableGravity(true);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->SetReactState(REACT_PASSIVE);
+ instance->SetData(DATA_SLABHIDE_INTRO, NOT_STARTED);
+ }
+
+ void Reset()
+ {
+ if (instance->GetData(DATA_SLABHIDE_INTRO) == NOT_STARTED)
+ return;
+
+ _Reset();
+ DespawnAll();
+
+ me->SetCanFly(false);
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->SetReactState(REACT_AGGRESSIVE);
+ }
+
+ void EnterCombat(Unit* /*victim*/) override
+ {
+ _EnterCombat();
+
+ events.ScheduleEvent(EVENT_HANDLE_ROCK_WALLS, 4000);
+ events.ScheduleEvent(EVENT_LAVA_FISSURE, urand(6000, 8000));
+ events.ScheduleEvent(EVENT_SAND_BLAST, urand(8000, 10000));
+ events.ScheduleEvent(EVENT_AIR_PHASE, 10000);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+
+ // Despawn related npcs and gameobjects
+ DespawnAll();
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_SLABHIDE_INTRO:
+ {
+ if (instance->GetData(DATA_SLABHIDE_INTRO) != NOT_STARTED)
+ return;
+
+ instance->SetData(DATA_SLABHIDE_INTRO, IN_PROGRESS);
+
+ // Execute Slabhide intro event
+ me->GetMotionMaster()->MovePoint(POINT_SLABHIDE_INTRO, SlabhideIntroPos);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 id) override
+ {
+ if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
+ return;
+
+ switch (id)
+ {
+ case POINT_SLABHIDE_INTRO:
+ me->SetFacingTo(SlabhideIntroLandPos.GetOrientation());
+ me->GetMotionMaster()->MoveLand(POINT_SLABHIDE_INTRO_LAND, SlabhideIntroLandPos);
+ break;
+ case POINT_SLABHIDE_INTRO_LAND:
+ me->SetCanFly(false);
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->SetHover(false);
+ me->SetHomePosition(SlabhideIntroLandPos);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetReactState(REACT_AGGRESSIVE);
+ instance->SetData(DATA_SLABHIDE_INTRO, DONE);
+ break;
+ case POINT_SLABHIDE_MIDDLE:
+ events.ScheduleEvent(EVENT_TAKEOFF, 100);
+ break;
+ case POINT_SLABHIDE_IN_AIR:
+ events.ScheduleEvent(EVENT_STALACTITE, 400);
+ break;
+ case POINT_SLABHIDE_LAND:
+ //DoCast(SPELL_COOLDOWN_5S); // unknown purpose
+ events.ScheduleEvent(EVENT_ATTACK, 1200);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_HANDLE_ROCK_WALLS: // Close rock walls
+ instance->SetData(DATA_SLABHIDE_ROCK_WALL, false);
+ break;
+ case EVENT_LAVA_FISSURE:
+ DoCast(SPELL_LAVA_FISSURE);
+ events.ScheduleEvent(EVENT_LAVA_FISSURE, urand(6000, 8000));
+ break;
+ case EVENT_SAND_BLAST:
+ DoCast(SPELL_SAND_BLAST);
+ events.ScheduleEvent(EVENT_SAND_BLAST, urand(8000, 11000));
+ break;
+ case EVENT_AIR_PHASE:
+ events.Reset();
+ me->SetReactState(REACT_PASSIVE);
+ me->AttackStop();
+ me->GetMotionMaster()->MovePoint(POINT_SLABHIDE_MIDDLE, SlabhideMiddlePos);
+ events.ScheduleEvent(EVENT_AIR_PHASE, 60000);
+ break;
+ case EVENT_TAKEOFF:
+ me->GetMotionMaster()->MoveTakeoff(POINT_SLABHIDE_IN_AIR, SlabhideInAirPos);
+ break;
+ case EVENT_STALACTITE:
+ me->SetCanFly(true);
+ me->SetDisableGravity(true);
+ me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->SetHover(true);
+
+ DoCast(SPELL_STALACTITE_SUMMON);
+
+ events.ScheduleEvent(EVENT_LAND, 8000);
+ break;
+ case EVENT_LAND:
+ {
+ Position pos = me->GetPosition();
+ pos.m_positionZ = me->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
+ me->GetMotionMaster()->MoveLand(POINT_SLABHIDE_LAND, pos);
+ break;
+ }
+ case EVENT_ATTACK:
+ me->SetCanFly(false);
+ me->SetDisableGravity(false);
+ me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
+ me->SetHover(false);
+
+ events.ScheduleEvent(EVENT_LAVA_FISSURE, urand(6000, 8000));
+ events.ScheduleEvent(EVENT_SAND_BLAST, urand(8000, 10000));
+ DoCast(SPELL_CRYSTAL_STORM);
+ me->SetReactState(REACT_AGGRESSIVE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ void DespawnAll()
+ {
+ // Despawn stalactite triggers npcs
+ std::list<Creature*> listStalactiteTrigger;
+ me->GetCreatureListWithEntryInGrid(listStalactiteTrigger, NPC_STALACTITE_TRIGGER, 200.0f);
+ if (!listStalactiteTrigger.empty())
+ for (std::list<Creature*>::const_iterator itr = listStalactiteTrigger.begin(); itr != listStalactiteTrigger.end(); ++itr)
+ (*itr)->DespawnOrUnsummon();
+
+ // Despawn stalactite objects
+ std::list<GameObject*> listStalactite;
+ me->GetGameObjectListWithEntryInGrid(listStalactite, GO_STALACTITE, 200.0f);
+ if (!listStalactite.empty())
+ for (std::list<GameObject*>::const_iterator itr = listStalactite.begin(); itr != listStalactite.end(); ++itr)
+ (*itr)->Delete();
+ }
+
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_slabhideAI>(creature);
+ }
+};
+
+// 43242 - Lava Fissure
+class npc_lava_fissure : public CreatureScript
+{
+public:
+ npc_lava_fissure() : CreatureScript("npc_lava_fissure") { }
+
+ struct npc_lava_fissureAI : public ScriptedAI
+ {
+ npc_lava_fissureAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ me->CastSpell(me, SPELL_LAVA_FISSURE_CRACK, true);
+ events.ScheduleEvent(EVENT_LAVA_FISSURE_ERUPTION, 6000);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_LAVA_FISSURE_ERUPTION:
+ me->RemoveAurasDueToSpell(SPELL_LAVA_FISSURE_CRACK);
+ me->CastSpell(me, SPELL_LAVA_FISSURE_ERUPTION, true);
+ me->DespawnOrUnsummon(14000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_lava_fissureAI>(creature);
+ }
+};
+
+// 43159 - Stalactite Trigger - Boss
+class npc_stalactite_trigger : public CreatureScript
+{
+public:
+ npc_stalactite_trigger() : CreatureScript("npc_stalactite_trigger") { }
+
+ struct npc_stalactite_triggerAI : public ScriptedAI
+ {
+ npc_stalactite_triggerAI(Creature* creature) : ScriptedAI(creature)
+ {
+ me->SetReactState(REACT_PASSIVE);
+ me->SetDisableGravity(true);
+ me->CastSpell(me, SPELL_STALACTITE_SHADE, true);
+ events.ScheduleEvent(EVENT_STALACTITE_MISSLE, 5600);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_STALACTITE_MISSLE:
+ DoCast(SPELL_STALACTITE_MISSLE);
+ me->DespawnOrUnsummon(11000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_stalactite_triggerAI>(creature);
+ }
+};
+
+// 81035 - Stalactite (check if player is near to summon stalactite)
+class NotPlayerCheck
+{
+ public:
+ bool operator()(WorldObject* object) const
+ {
+ return (object->GetTypeId() != TYPEID_PLAYER);
+ }
+};
+
+class spell_s81035_stalactite : public SpellScriptLoader
+{
+public:
+ spell_s81035_stalactite() : SpellScriptLoader("spell_s81035_stalactite") { }
+
+ class spell_s81035_stalactite_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_s81035_stalactite_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(NotPlayerCheck());
+ }
+
+ void SummonStalactiteTrigger()
+ {
+ Unit* caster = GetCaster();
+ caster->CastSpell(caster, SPELL_STALACTITE_SUMMON_TRIGGER, true);
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_s81035_stalactite_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnHit += SpellHitFn(spell_s81035_stalactite_SpellScript::SummonStalactiteTrigger);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_s81035_stalactite_SpellScript();
+ }
+};
+
+// 81028 - Stalactite (summons "Stalactite Trigger - Boss", 20 yard radius)
+// 80650 - Stalactite (summons "Stalactite Trigger - Boss", 40 yard radius)
+class spell_s81028_s80650_stalactite : public SpellScriptLoader
+{
+public:
+ spell_s81028_s80650_stalactite() : SpellScriptLoader("spell_s81028_s80650_stalactite") { }
+
+ class spell_s81028_s80650_stalactite_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_s81028_s80650_stalactite_SpellScript);
+
+ void ModDestHeight(SpellDestination& dest)
+ {
+ // All stalactite triggers should have Z position 301.3837f, but no way to relocate (not relocateoffset!) height only.
+ Position offset = { 0.0f, 0.0f, 50.0f, 0.0f };
+ dest.RelocateOffset(offset);
+ }
+
+ void Register() override
+ {
+ OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_s81028_s80650_stalactite_SpellScript::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_RANDOM);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_s81028_s80650_stalactite_SpellScript();
+ }
+};
+
+// 80654 - Stalactite (creates visual shade on ground)
+// 80643/92653 - Stalactite (launches missle to the ground)
+// 80647/92309 - Stalactite (creates stalactite object)
+class spell_stalactite_mod_dest_height : public SpellScriptLoader
+{
+public:
+ spell_stalactite_mod_dest_height() : SpellScriptLoader("spell_stalactite_mod_dest_height") { }
+
+ class spell_stalactite_mod_dest_height_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_stalactite_mod_dest_height_SpellScript);
+
+ void ModDestHeight(SpellDestination& dest)
+ {
+ Unit* caster = GetCaster();
+ Position pos = caster->GetPosition();
+ pos.m_positionZ = caster->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), true, 100.0f);
+ dest.Relocate(pos);
+ }
+
+ void Register() override
+ {
+ OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_stalactite_mod_dest_height_SpellScript::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_stalactite_mod_dest_height_SpellScript();
+ }
+};
+
+// 92306 - Crystal storm (heroic mode check)
+class spell_s92306_crystal_storm : public SpellScriptLoader
+{
+public:
+ spell_s92306_crystal_storm() : SpellScriptLoader("spell_s92306_crystal_storm") { }
+
+ class spell_s92306_crystal_storm_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_s92306_crystal_storm_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_CRYSTAL_STORM_TRIGGER))
+ return false;
+ return true;
+ }
+
+ void HandleDummyEffect(SpellEffIndex /*eff*/)
+ {
+ Unit* caster = GetCaster();
+ if (caster->GetMap()->IsHeroic())
+ caster->CastSpell(caster, SPELL_CRYSTAL_STORM_TRIGGER, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_s92306_crystal_storm_SpellScript::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_s92306_crystal_storm_SpellScript();
+ }
+};
+
+// 92300 - Crystal Storm (damage)
+class BehindObjectCheck
+{
+ public:
+ BehindObjectCheck(Unit* caster, std::list<GameObject*> objectList) : caster(caster), objectList(objectList) { }
+
+ bool operator()(WorldObject* unit)
+ {
+ for (std::list<GameObject*>::const_iterator itr = objectList.begin(); itr != objectList.end(); ++itr)
+ if (!(*itr)->IsInvisibleDueToDespawn() && (*itr)->IsInBetween(caster, unit, 1.5f))
+ return true;
+ return false;
+ }
+
+ private:
+ Unit* caster;
+ std::list<GameObject*> objectList;
+};
+
+class spell_s92300_crystal_storm : public SpellScriptLoader
+{
+public:
+ spell_s92300_crystal_storm() : SpellScriptLoader("spell_s92300_crystal_storm") { }
+
+ class spell_s92300_crystal_storm_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_s92300_crystal_storm_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& unitList)
+ {
+ Unit* caster = GetCaster();
+
+ std::list<GameObject*> goList;
+ caster->GetGameObjectListWithEntryInGrid(goList, GO_STALACTITE, 40.0f);
+ if (goList.empty())
+ return;
+
+ unitList.remove_if(BehindObjectCheck(caster, goList));
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_s92300_crystal_storm_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_s92300_crystal_storm_SpellScript();
+ }
+};
+
+void AddSC_boss_slabhide()
+{
+ new boss_slabhide();
+ new npc_lava_fissure();
+ new npc_stalactite_trigger();
+ new spell_s81035_stalactite();
+ new spell_s81028_s80650_stalactite();
+ new spell_stalactite_mod_dest_height();
+ new spell_s92306_crystal_storm();
+ new spell_s92300_crystal_storm();
+}
diff --git a/src/server/scripts/Maelstrom/Stonecore/instance_stonecore.cpp b/src/server/scripts/Maelstrom/Stonecore/instance_stonecore.cpp
new file mode 100644
index 00000000000..ca5e40ab117
--- /dev/null
+++ b/src/server/scripts/Maelstrom/Stonecore/instance_stonecore.cpp
@@ -0,0 +1,262 @@
+/*
+* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ScriptMgr.h"
+#include "Player.h"
+#include "CreatureGroups.h"
+#include "InstanceScript.h"
+#include "stonecore.h"
+
+#define MAX_ENCOUNTER 4
+
+/* Stonecore encounters:
+0 - Corborus
+1 - Slabhide
+2 - Ozruk
+3 - High Priestess Azil
+*/
+
+// TO-DO:
+// - Find out spell IDs for both Stonecore Teleporters (spellclick).
+
+class instance_stonecore : public InstanceMapScript
+{
+ public:
+ instance_stonecore() : InstanceMapScript(SCScriptName, 725) { }
+
+ struct instance_stonecore_InstanceScript : public InstanceScript
+ {
+ instance_stonecore_InstanceScript(Map* map) : InstanceScript(map)
+ {
+ SetHeaders(DataHeader);
+ SetBossNumber(MAX_ENCOUNTER);
+ }
+
+ void OnGameObjectCreate(GameObject* go) override
+ {
+ switch (go->GetEntry())
+ {
+ case GAMEOBJECT_CORBORUS_ROCKDOOR:
+ corborusRockDoorGUID = go->GetGUID();
+ go->SetGoState(GetBossState(DATA_CORBORUS) != DONE ? GO_STATE_READY : GO_STATE_ACTIVE);
+ break;
+ case GAMEOBJECT_SLABHIDE_ROCK_WALL:
+ slabhideRockWallGUIDs.push_back(go->GetGUID());
+ break;
+ default:
+ break;
+ }
+ }
+
+ void OnCreatureCreate(Creature* creature) override
+ {
+ switch (creature->GetEntry())
+ {
+ case NPC_MILLHOUSE_MANASTORM:
+ millhouseGUID = creature->GetGUID();
+ break;
+ case NPC_CORBORUS:
+ corobrusGUID = creature->GetGUID();
+ break;
+ case NPC_SLABHIDE:
+ slabhideGUID = creature->GetGUID();
+ break;
+ case NPC_HIGH_PRIESTESS_AZIL:
+ highPriestessAzilGUID = creature->GetGUID();
+ break;
+ case NPC_STONECORE_TELEPORTER:
+ case NPC_STONECORE_TELEPORTER_2:
+ if (GetBossState(DATA_SLABHIDE) != DONE)
+ stonecoreTeleporterGUID[creature->GetEntry() - NPC_STONECORE_TELEPORTER] = creature->GetGUID();
+ else // If Slabhide is already dead, no need to store teleporter guids
+ {
+ creature->CastSpell(creature, SPELL_TELEPORTER_ACTIVE_VISUAL, true);
+ creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ }
+ break;
+ default:
+ break;
+ }
+
+ // Check if creature is part of Millhouse event
+ creature->SearchFormation();
+ if (CreatureGroup* group = creature->GetFormation()) // TO-DO: Fix formations
+ {
+ switch (group->GetId())
+ {
+ case CREATURE_FORMATION_MILLHOUSE_EVENT_TRASH:
+ millhouseTrashGUIDs.push_back(creature->GetGUID());
+ break;
+ case CREATURE_FORMATION_MILLHOUSE_EVENT_LAST_GROUP:
+ millhouseLastGroupGUIDs.push_back(creature->GetGUID());
+ creature->SetReactState(REACT_PASSIVE);
+ creature->SetMeleeAnimKitId(ANIM_READY2H);
+ break;
+ }
+ }
+ }
+
+ bool SetBossState(uint32 type, EncounterState state) override
+ {
+ switch (type)
+ {
+ case DATA_SLABHIDE:
+ // Open rock walls (Slabhide AI handles closing because it must be delayed)
+ if (state != IN_PROGRESS)
+ SetData(DATA_SLABHIDE_ROCK_WALL, true);
+
+ // Activate teleporters
+ if (state == DONE)
+ {
+ for (int8 i = 0; i < MAX_STONECORE_TELEPORTERS; i++)
+ {
+ if (Creature* teleporter = instance->GetCreature(stonecoreTeleporterGUID[i]))
+ {
+ teleporter->CastSpell(teleporter, SPELL_TELEPORTER_ACTIVE_VISUAL, true);
+ teleporter->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
+ }
+ }
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return InstanceScript::SetBossState(type, state);
+ }
+
+ uint32 GetData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_SLABHIDE_INTRO:
+ return slabhideIntro;
+ default:
+ break;
+ }
+
+ return 0;
+ }
+
+ void SetData(uint32 type, uint32 data) override
+ {
+ switch (type)
+ {
+ case DATA_MILLHOUSE_EVENT_FACE:
+ MillhouseEvent_Face();
+ break;
+ case DATA_MILLHOUSE_EVENT_KNOCKBACK:
+ MillhouseEvent_Knockback();
+ break;
+ case DATA_MILLHOUSE_EVENT_DESPAWN:
+ MillhouseEvent_Despawn();
+ break;
+ case DATA_SLABHIDE_INTRO:
+ slabhideIntro = EncounterState(data);
+ break;
+ case DATA_SLABHIDE_ROCK_WALL: // Handles rock walls
+ for (std::vector<ObjectGuid>::iterator itr = slabhideRockWallGUIDs.begin(); itr != slabhideRockWallGUIDs.end(); ++itr)
+ HandleGameObject((*itr), data ? true : false);
+ break;
+ default:
+ break;
+ }
+ }
+
+ ObjectGuid GetGuidData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_MILLHOUSE_MANASTORM:
+ return millhouseGUID;
+ case GAMEOBJECT_CORBORUS_ROCKDOOR:
+ return corborusRockDoorGUID;
+ case DATA_CORBORUS:
+ return corobrusGUID;
+ case DATA_SLABHIDE:
+ return slabhideGUID;
+ case DATA_HIGH_PRIESTESS_AZIL:
+ return highPriestessAzilGUID;
+ case NPC_STONECORE_TELEPORTER:
+ case NPC_STONECORE_TELEPORTER_2:
+ return stonecoreTeleporterGUID[type - NPC_STONECORE_TELEPORTER];
+ default:
+ break;
+ }
+
+ return ObjectGuid::Empty;
+ }
+
+ private:
+ // Face Millhouse and other nearby mobs to Corborus
+ void MillhouseEvent_Face()
+ {
+ if (Creature* Millhouse = instance->GetCreature(millhouseGUID))
+ Millhouse->SetFacingTo(1.570796f);
+ for (GuidVector::const_iterator i = millhouseLastGroupGUIDs.begin(); i != millhouseLastGroupGUIDs.end(); ++i)
+ if (Creature* creature = instance->GetCreature(*i))
+ creature->SetFacingTo(1.570796f);
+ }
+
+ // Knock back Millhouse and other mobs
+ void MillhouseEvent_Knockback()
+ {
+ if (Creature* Millhouse = instance->GetCreature(millhouseGUID))
+ Millhouse->CastSpell(Millhouse, SPELL_RING_WYRM_KNOCKBACK, true);
+ for (GuidVector::const_iterator itr = millhouseLastGroupGUIDs.begin(); itr != millhouseLastGroupGUIDs.end(); ++itr)
+ if (Creature* creature = instance->GetCreature(*itr))
+ creature->CastSpell(creature, SPELL_RING_WYRM_KNOCKBACK, true);
+ }
+
+ // Despawn all mobs
+ void MillhouseEvent_Despawn()
+ {
+ if (Creature* Millhouse = instance->GetCreature(millhouseGUID))
+ Millhouse->DespawnOrUnsummon(3000);
+ for (GuidVector::const_iterator itr = millhouseTrashGUIDs.begin(); itr != millhouseTrashGUIDs.end(); ++itr)
+ if (Creature* creature = instance->GetCreature(*itr))
+ creature->DespawnOrUnsummon(3000);
+ for (GuidVector::const_iterator itr = millhouseLastGroupGUIDs.begin(); itr != millhouseLastGroupGUIDs.end(); ++itr)
+ if (Creature* creature = instance->GetCreature(*itr))
+ creature->DespawnOrUnsummon(3000);
+ }
+
+ ObjectGuid millhouseGUID;
+ GuidVector millhouseTrashGUIDs;
+ GuidVector millhouseLastGroupGUIDs;
+ ObjectGuid corborusRockDoorGUID;
+ ObjectGuid corobrusGUID;
+ ObjectGuid slabhideGUID;
+ ObjectGuid highPriestessAzilGUID;
+ ObjectGuid stonecoreTeleporterGUID[2];
+ GuidVector slabhideRockWallGUIDs;
+
+ EncounterState slabhideIntro;
+ };
+
+ InstanceScript* GetInstanceScript(InstanceMap* map) const override
+ {
+ return new instance_stonecore_InstanceScript(map);
+ }
+};
+
+void AddSC_instance_stonecore()
+{
+ new instance_stonecore();
+}
diff --git a/src/server/scripts/Maelstrom/Stonecore/stonecore.cpp b/src/server/scripts/Maelstrom/Stonecore/stonecore.cpp
new file mode 100644
index 00000000000..4ed84732eff
--- /dev/null
+++ b/src/server/scripts/Maelstrom/Stonecore/stonecore.cpp
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ObjectGuid.h"
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "SpellScript.h"
+#include "Player.h"
+#include "stonecore.h"
+
+enum Texts
+{
+ // Millhouse Manastorm
+ SAY_MILLHOUSE_EVENT_1 = 0,
+ SAY_MILLHOUSE_EVENT_2 = 1,
+};
+
+enum NPCs
+{
+ NPC_GENERIC_TRIGGER_LAB = 40350,
+};
+
+enum Spells
+{
+ // Millhouse Manastorm
+ SPELL_SHADOW_BOLT = 81439,
+ SPELL_FROSTBOLT_VOLLEY = 81440,
+ SPELL_SHADOWFURY = 81441,
+ SPELL_FEAR = 81442,
+// SPELL_MILLHOUSE_SAFE_CHECK = 81213, // unknown purpose
+ SPELL_CLEAR_ALL_DEBUFFS = 34098,
+ SPELL_BLUR = 81216,
+ SPELL_ANCHOR_HERE = 45313,
+ SPELL_TIGULE_AND_FORORS_SPECIAL_BLEND = 81220,
+ SPELL_IMPENDING_DOOM = 86838,
+ SPELL_IMPENDING_DOOM_CHANNEL = 86830,
+
+// SPELL_PORTAL_VISUAL = 79754,
+};
+
+enum Events
+{
+ EVENT_NONE,
+
+ // Millhouse Manastorm
+ EVENT_FROSTBOLT_VOLLEY,
+ EVENT_SHADOWFURY,
+ EVENT_FEAR,
+
+ EVENT_READY_FOR_COMBAT,
+ EVENT_CAST_IMPENDING_DOOM,
+ EVENT_INTERRUPT_IMPENDING_DOOM,
+};
+
+enum Phase
+{
+ PHASE_NONE,
+
+ PHASE_MILLHOUSE_GROUP_1,
+ PHASE_MILLHOUSE_GROUP_2,
+ PHASE_MILLHOUSE_GROUP_3,
+ PHASE_MILLHOUSE_GROUP_4,
+
+ PHASE_MASK_MILLHOUSE_GROUP_1 = (1 << (PHASE_MILLHOUSE_GROUP_1 - 1)),
+ PHASE_MASK_MILLHOUSE_GROUP_2 = (1 << (PHASE_MILLHOUSE_GROUP_2 - 1)),
+ PHASE_MASK_MILLHOUSE_GROUP_3 = (1 << (PHASE_MILLHOUSE_GROUP_3 - 1)),
+ PHASE_MASK_MILLHOUSE_GROUP_4 = (1 << (PHASE_MILLHOUSE_GROUP_4 - 1)),
+};
+
+enum MovementPoints
+{
+ POINT_NONE,
+
+ POINT_MILLHOUSE_GROUP_2,
+ POINT_MILLHOUSE_GROUP_3,
+ POINT_MILLHOUSE_GROUP_4,
+};
+
+// Millhouse trash groups
+Position const MillhousePointGroup2 = { 977.3045f, 895.2347f, 306.3298f };
+Position const MillhousePointGroup3 = { 1049.823f, 871.4349f, 295.006f };
+Position const MillhousePointGroup4 = { 1149.04f, 884.431f, 284.9406f };
+
+// 43391 - Millhouse Manastorm
+class npc_sc_millhouse_manastorm : public CreatureScript
+{
+ public:
+ npc_sc_millhouse_manastorm() : CreatureScript("npc_sc_millhouse_manastorm") { }
+
+ struct npc_sc_millhouse_manastormAI : public ScriptedAI
+ {
+ npc_sc_millhouse_manastormAI(Creature* creature) : ScriptedAI(creature),
+ _instance(creature->GetInstanceScript())
+ {
+ events.SetPhase(PHASE_MILLHOUSE_GROUP_1);
+ }
+
+ void ScheduleEvents()
+ {
+ events.ScheduleEvent(EVENT_SHADOWFURY, 3000);
+ events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 5000);
+ events.ScheduleEvent(EVENT_FEAR, 8000);
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
+ {
+ if (damage >= me->GetHealth())
+ damage = me->GetHealth() - 1;
+
+ if (!HealthBelowPct(50) || me->HasAura(SPELL_BLUR))
+ return;
+
+ switch (events.GetPhaseMask())
+ {
+ case PHASE_MASK_MILLHOUSE_GROUP_1:
+ events.Reset();
+ events.SetPhase(PHASE_MILLHOUSE_GROUP_2);
+ me->SetReactState(REACT_PASSIVE);
+ me->InterruptNonMeleeSpells(true);
+ DoCast(me, SPELL_CLEAR_ALL_DEBUFFS);
+ DoCast(me, SPELL_BLUR);
+ Talk(SAY_MILLHOUSE_EVENT_1);
+ me->GetMotionMaster()->MovePoint(POINT_MILLHOUSE_GROUP_2, MillhousePointGroup2);
+ break;
+ case PHASE_MASK_MILLHOUSE_GROUP_2:
+ events.Reset();
+ events.SetPhase(PHASE_MILLHOUSE_GROUP_3);
+ me->SetReactState(REACT_PASSIVE);
+ me->InterruptNonMeleeSpells(true);
+ DoCast(me, SPELL_CLEAR_ALL_DEBUFFS);
+ DoCast(me, SPELL_BLUR);
+ Talk(SAY_MILLHOUSE_EVENT_1);
+ me->GetMotionMaster()->MovePoint(POINT_MILLHOUSE_GROUP_3, MillhousePointGroup3);
+ break;
+ case PHASE_MASK_MILLHOUSE_GROUP_3:
+ events.Reset();
+ events.SetPhase(PHASE_MILLHOUSE_GROUP_4);
+ me->SetReactState(REACT_PASSIVE);
+ me->InterruptNonMeleeSpells(true);
+ DoCast(me, SPELL_CLEAR_ALL_DEBUFFS);
+ DoCast(me, SPELL_BLUR);
+ me->GetMotionMaster()->MovePoint(POINT_MILLHOUSE_GROUP_4, MillhousePointGroup4);
+ break;
+ default:
+ break;
+ }
+
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ }
+
+ void MovementInform(uint32 type, uint32 pointId) override
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ if (pointId < POINT_MILLHOUSE_GROUP_2 || pointId > POINT_MILLHOUSE_GROUP_4)
+ return;
+
+ me->RemoveAllAuras();
+ me->CombatStop(true);
+ me->DeleteThreatList();
+
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ switch (pointId)
+ {
+ case POINT_MILLHOUSE_GROUP_2:
+ if (Creature* worldtrigger = me->FindNearestCreature(NPC_WORLDTRIGGER, 150.0f))
+ me->SetFacingToObject(worldtrigger); // o: 5.497359f (sniff data)
+ me->CastSpell(me, SPELL_ANCHOR_HERE, true);
+ me->AddAura(SPELL_TIGULE_AND_FORORS_SPECIAL_BLEND, me);
+ events.ScheduleEvent(EVENT_READY_FOR_COMBAT, 10000);
+ break;
+ case POINT_MILLHOUSE_GROUP_3:
+ me->SetFacingTo(5.931499f);
+ me->CastSpell(me, SPELL_ANCHOR_HERE, true);
+ me->AddAura(SPELL_TIGULE_AND_FORORS_SPECIAL_BLEND, me);
+ events.ScheduleEvent(EVENT_READY_FOR_COMBAT, 10000);
+ break;
+ case POINT_MILLHOUSE_GROUP_4:
+ me->SetFacingTo(3.455752f);
+ me->CastSpell(me, SPELL_ANCHOR_HERE, true);
+ Talk(SAY_MILLHOUSE_EVENT_2);
+ events.ScheduleEvent(EVENT_CAST_IMPENDING_DOOM, 1000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ // Only update events if Millhouse is aggressive
+ if (me->GetReactState() != REACT_AGGRESSIVE)
+ return;
+
+ events.Update(diff);
+
+ // Impending Doom is exception because it needs to be interrupted.
+ if (me->HasUnitState(UNIT_STATE_CASTING) && !me->GetCurrentSpell(SPELL_IMPENDING_DOOM))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FROSTBOLT_VOLLEY:
+ DoCast(SPELL_FROSTBOLT_VOLLEY);
+ events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 7000);
+ break;
+ case EVENT_SHADOWFURY:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_SHADOWFURY);
+ events.ScheduleEvent(EVENT_SHADOWFURY, 7000);
+ break;
+ case EVENT_FEAR:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
+ DoCast(target, SPELL_FEAR);
+ events.ScheduleEvent(EVENT_FEAR, 18000);
+ break;
+ case EVENT_READY_FOR_COMBAT:
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ me->SetReactState(REACT_AGGRESSIVE);
+ ScheduleEvents();
+ break;
+ case EVENT_CAST_IMPENDING_DOOM:
+ DoCast(SPELL_IMPENDING_DOOM);
+ DoCast(SPELL_IMPENDING_DOOM_CHANNEL);
+ events.ScheduleEvent(EVENT_INTERRUPT_IMPENDING_DOOM, urand(15000,20000));
+ break;
+ case EVENT_INTERRUPT_IMPENDING_DOOM:
+ me->InterruptNonMeleeSpells(true);
+ me->RemoveAllAuras();
+ me->HandleEmoteCommand(EMOTE_ONESHOT_KNOCKDOWN);
+ events.ScheduleEvent(EVENT_CAST_IMPENDING_DOOM, 3000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoSpellAttackIfReady(SPELL_SHADOW_BOLT);
+ }
+
+ private:
+ InstanceScript* _instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_sc_millhouse_manastormAI>(creature);
+ }
+};
+
+// 81459 - Force of Earth
+class spell_force_of_earth : public SpellScriptLoader
+{
+ public:
+ spell_force_of_earth() : SpellScriptLoader("spell_force_of_earth") { }
+
+ class spell_force_of_earth_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_force_of_earth_SpellScript);
+
+ void DummyEffect(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->SetDisplayId(26693); // can be moved to SAI part, need sniffs to see what this dummy does (note: npc 43552)
+ }
+
+ void Register()
+ {
+ OnEffectLaunch += SpellEffectFn(spell_force_of_earth_SpellScript::DummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_force_of_earth_SpellScript();
+ }
+};
+
+// 45313 - Anchor Here
+class spell_sc_anchor_here : public SpellScriptLoader
+{
+public:
+ spell_sc_anchor_here() : SpellScriptLoader("spell_sc_anchor_here") { }
+
+ class spell_sc_anchor_here_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sc_anchor_here_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Creature* creature = GetHitUnit()->ToCreature())
+ creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation());
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_sc_anchor_here_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_sc_anchor_here_SpellScript();
+ }
+};
+
+// 93167 - Twilight Documents
+class spell_sc_twilight_documents : public SpellScriptLoader
+{
+ public:
+ spell_sc_twilight_documents() : SpellScriptLoader("spell_sc_twilight_documents") { }
+
+ class spell_sc_twilight_documents_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sc_twilight_documents_SpellScript);
+
+ bool Validate(SpellInfo const* /*spell*/) override
+ {
+ if (!sObjectMgr->GetGameObjectTemplate(GAMEOBJECT_TWILIGHT_DOCUMENTS))
+ return false;
+ return true;
+ }
+
+ void SetTarget(WorldObject*& target)
+ {
+ target = GetCaster()->FindNearestCreature(NPC_GENERIC_TRIGGER_LAB, 100.0f);
+ }
+
+ void SpawnGameObject(SpellEffIndex /*effIndex*/)
+ {
+ if (WorldLocation* loc = GetHitDest())
+ GetCaster()->SummonGameObject(GAMEOBJECT_TWILIGHT_DOCUMENTS, loc->GetPositionX(), loc->GetPositionY(), loc->GetPositionZ(), loc->GetOrientation(), 0, 0, 0, 0, 7200);
+ }
+
+ void Register() override
+ {
+ OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_sc_twilight_documents_SpellScript::SetTarget, EFFECT_0, TARGET_DEST_NEARBY_ENTRY);
+ OnEffectHit += SpellEffectFn(spell_sc_twilight_documents_SpellScript::SpawnGameObject, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_sc_twilight_documents_SpellScript();
+ }
+};
+
+// 81008 - Quake
+class JumpCheck
+{
+ public:
+ bool operator()(WorldObject* object) const
+ {
+ Player* player = object->ToPlayer();
+ return (player && player->HasUnitState(UNIT_STATE_JUMPING));
+ }
+};
+
+class spell_sc_quake : public SpellScriptLoader
+{
+ public:
+ spell_sc_quake() : SpellScriptLoader("spell_sc_quake") { }
+
+ class spell_sc_quake_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_sc_quake_SpellScript);
+
+ void FilterTargets(std::list<WorldObject*>& unitList)
+ {
+ unitList.remove_if(JumpCheck());
+ }
+
+ void Register() override
+ {
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sc_quake_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_sc_quake_SpellScript();
+ }
+};
+
+class at_sc_corborus_intro : public AreaTriggerScript
+{
+public:
+ at_sc_corborus_intro() : AreaTriggerScript("at_sc_corborus_intro") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (Creature* corborus = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_CORBORUS)))
+ corborus->AI()->DoAction(ACTION_CORBORUS_INTRO);
+ return true;
+ }
+};
+
+class at_sc_slabhide_intro : public AreaTriggerScript
+{
+public:
+ at_sc_slabhide_intro() : AreaTriggerScript("at_sc_slabhide_intro") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
+ {
+ if (InstanceScript* instance = player->GetInstanceScript())
+ if (Creature* slabhide = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_SLABHIDE)))
+ slabhide->AI()->DoAction(ACTION_SLABHIDE_INTRO);
+ return true;
+ }
+};
+
+void AddSC_stonecore()
+{
+ new npc_sc_millhouse_manastorm();
+ new spell_force_of_earth();
+ new spell_sc_anchor_here();
+ new spell_sc_twilight_documents();
+ new spell_sc_quake();
+ new at_sc_corborus_intro();
+ new at_sc_slabhide_intro();
+}
diff --git a/src/server/scripts/Maelstrom/Stonecore/stonecore.h b/src/server/scripts/Maelstrom/Stonecore/stonecore.h
new file mode 100644
index 00000000000..98a9878e0d3
--- /dev/null
+++ b/src/server/scripts/Maelstrom/Stonecore/stonecore.h
@@ -0,0 +1,72 @@
+/*
+* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef DEF_STONECORE_H
+#define DEF_STONECORE_H
+
+#define SCScriptName "instance_stonecore"
+#define DataHeader "SC"
+
+enum DataTypes
+{
+ // Encounter States/Boss GUIDs
+ DATA_CORBORUS,
+ DATA_SLABHIDE,
+ DATA_OZRUK,
+ DATA_HIGH_PRIESTESS_AZIL,
+
+ // Additional Data
+ DATA_MILLHOUSE_MANASTORM,
+ DATA_MILLHOUSE_EVENT_FACE,
+ DATA_MILLHOUSE_EVENT_KNOCKBACK,
+ DATA_MILLHOUSE_EVENT_DESPAWN,
+
+ DATA_SLABHIDE_INTRO,
+ DATA_SLABHIDE_ROCK_WALL,
+};
+
+enum Misc
+{
+ ACTION_CORBORUS_INTRO,
+ ACTION_SLABHIDE_INTRO,
+
+ NPC_WORLDTRIGGER = 22515,
+ NPC_MILLHOUSE_MANASTORM = 43391,
+
+ NPC_CORBORUS = 43438,
+ NPC_SLABHIDE = 43214,
+ NPC_OZRUK = 42188,
+ NPC_HIGH_PRIESTESS_AZIL = 42333,
+
+ // Stonecore Teleporter misc
+ MAX_STONECORE_TELEPORTERS = 2,
+ NPC_STONECORE_TELEPORTER = 51396, // Entrance teleporter
+ NPC_STONECORE_TELEPORTER_2 = 51397, // Slabhide teleporter
+ SPELL_TELEPORTER_ACTIVE_VISUAL = 95298,
+
+ GAMEOBJECT_TWILIGHT_DOCUMENTS = 207415,
+ GAMEOBJECT_CORBORUS_ROCKDOOR = 207343,
+ GAMEOBJECT_SLABHIDE_ROCK_WALL = 204381,
+
+ SPELL_RING_WYRM_KNOCKBACK = 81235,
+
+ // Creature Formation IDs
+ CREATURE_FORMATION_MILLHOUSE_EVENT_TRASH = 340418,
+ CREATURE_FORMATION_MILLHOUSE_EVENT_LAST_GROUP = 340492,
+};
+
+#endif // DEF_STONECORE
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index 5e8273dce67..cdbbf755390 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -83,6 +83,7 @@ class instance_ulduar : public InstanceMapScript
IsDriveMeCrazyEligible = true;
_algalonSummoned = false;
_summonAlgalon = false;
+ _CoUAchivePlayerDeathMask = 0;
memset(_summonObservationRingKeeper, 0, sizeof(_summonObservationRingKeeper));
memset(_summonYSKeeper, 0, sizeof(_summonYSKeeper));
@@ -592,6 +593,19 @@ class instance_ulduar : public InstanceMapScript
void OnUnitDeath(Unit* unit) override
{
+ // Champion/Conqueror of Ulduar
+ if (unit->GetTypeId() == TYPEID_PLAYER)
+ {
+ for (uint8 i = 0; i < BOSS_ALGALON; i++)
+ {
+ if (GetBossState(i) == IN_PROGRESS)
+ {
+ _CoUAchivePlayerDeathMask |= (1 << i);
+ SaveToDB();
+ }
+ }
+ }
+
Creature* creature = unit->ToCreature();
if (!creature)
return;
@@ -1007,6 +1021,45 @@ class instance_ulduar : public InstanceMapScript
case CRITERIA_ALONE_IN_THE_DARKNESS_10:
case CRITERIA_ALONE_IN_THE_DARKNESS_25:
return keepersCount == 0;
+ case CRITERIA_C_O_U_LEVIATHAN_10:
+ case CRITERIA_C_O_U_LEVIATHAN_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_LEVIATHAN)) == 0;
+ case CRITERIA_C_O_U_IGNIS_10:
+ case CRITERIA_C_O_U_IGNIS_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_IGNIS)) == 0;
+ case CRITERIA_C_O_U_RAZORSCALE_10:
+ case CRITERIA_C_O_U_RAZORSCALE_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_RAZORSCALE)) == 0;
+ case CRITERIA_C_O_U_XT002_10:
+ case CRITERIA_C_O_U_XT002_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_XT002)) == 0;
+ case CRITERIA_C_O_U_IRON_COUNCIL_10:
+ case CRITERIA_C_O_U_IRON_COUNCIL_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_ASSEMBLY_OF_IRON)) == 0;
+ case CRITERIA_C_O_U_KOLOGARN_10:
+ case CRITERIA_C_O_U_KOLOGARN_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_KOLOGARN)) == 0;
+ case CRITERIA_C_O_U_AURIAYA_10:
+ case CRITERIA_C_O_U_AURIAYA_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_AURIAYA)) == 0;
+ case CRITERIA_C_O_U_HODIR_10:
+ case CRITERIA_C_O_U_HODIR_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_HODIR)) == 0;
+ case CRITERIA_C_O_U_THORIM_10:
+ case CRITERIA_C_O_U_THORIM_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_THORIM)) == 0;
+ case CRITERIA_C_O_U_FREYA_10:
+ case CRITERIA_C_O_U_FREYA_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_FREYA)) == 0;
+ case CRITERIA_C_O_U_MIMIRON_10:
+ case CRITERIA_C_O_U_MIMIRON_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_MIMIRON)) == 0;
+ case CRITERIA_C_O_U_VEZAX_10:
+ case CRITERIA_C_O_U_VEZAX_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_VEZAX)) == 0;
+ case CRITERIA_C_O_U_YOGG_SARON_10:
+ case CRITERIA_C_O_U_YOGG_SARON_25:
+ return (_CoUAchivePlayerDeathMask & (1 << BOSS_YOGG_SARON)) == 0;
}
return false;
@@ -1018,6 +1071,8 @@ class instance_ulduar : public InstanceMapScript
for (uint8 i = 0; i < 4; ++i)
data << ' ' << uint32(!KeeperGUIDs[i].IsEmpty() ? 1 : 0);
+
+ data << ' ' << _CoUAchivePlayerDeathMask;
}
void ReadSaveDataMore(std::istringstream& data) override
@@ -1056,6 +1111,8 @@ class instance_ulduar : public InstanceMapScript
_summonObservationRingKeeper[2] = true;
if (GetBossState(BOSS_MIMIRON) == DONE && !_summonYSKeeper[3])
_summonObservationRingKeeper[3] = true;
+
+ data >> _CoUAchivePlayerDeathMask;
}
void Update(uint32 diff) override
@@ -1095,6 +1152,7 @@ class instance_ulduar : public InstanceMapScript
bool _summonYSKeeper[4];
uint32 _maxArmorItemLevel;
uint32 _maxWeaponItemLevel;
+ uint32 _CoUAchivePlayerDeathMask;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index 82c4ef140f1..1b4330b0faf 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -36,16 +36,16 @@ enum UlduarBosses
BOSS_ASSEMBLY_OF_IRON = 4,
BOSS_KOLOGARN = 5,
BOSS_AURIAYA = 6,
- BOSS_MIMIRON = 7,
- BOSS_HODIR = 8,
- BOSS_THORIM = 9,
- BOSS_FREYA = 10,
- BOSS_BRIGHTLEAF = 11,
- BOSS_IRONBRANCH = 12,
- BOSS_STONEBARK = 13,
- BOSS_VEZAX = 14,
- BOSS_YOGG_SARON = 15,
- BOSS_ALGALON = 16,
+ BOSS_HODIR = 7,
+ BOSS_THORIM = 8,
+ BOSS_FREYA = 9,
+ BOSS_MIMIRON = 10,
+ BOSS_VEZAX = 11,
+ BOSS_YOGG_SARON = 12,
+ BOSS_ALGALON = 13,
+ BOSS_BRIGHTLEAF = 14,
+ BOSS_IRONBRANCH = 15,
+ BOSS_STONEBARK = 16,
};
enum UlduarNPCs
@@ -295,6 +295,35 @@ enum UlduarAchievementCriteriaIds
CRITERIA_ALONE_IN_THE_DARKNESS_10 = 10412,
CRITERIA_ALONE_IN_THE_DARKNESS_25 = 10417,
CRITERIA_HERALD_OF_TITANS = 10678,
+
+ // Champion of Ulduar
+ CRITERIA_C_O_U_LEVIATHAN_10 = 10042,
+ CRITERIA_C_O_U_IGNIS_10 = 10342,
+ CRITERIA_C_O_U_RAZORSCALE_10 = 10340,
+ CRITERIA_C_O_U_XT002_10 = 10341,
+ CRITERIA_C_O_U_IRON_COUNCIL_10 = 10598,
+ CRITERIA_C_O_U_KOLOGARN_10 = 10348,
+ CRITERIA_C_O_U_AURIAYA_10 = 10351,
+ CRITERIA_C_O_U_HODIR_10 = 10439,
+ CRITERIA_C_O_U_THORIM_10 = 10403,
+ CRITERIA_C_O_U_FREYA_10 = 10582,
+ CRITERIA_C_O_U_MIMIRON_10 = 10347,
+ CRITERIA_C_O_U_VEZAX_10 = 10349,
+ CRITERIA_C_O_U_YOGG_SARON_10 = 10350,
+ // Conqueror of Ulduar
+ CRITERIA_C_O_U_LEVIATHAN_25 = 10352,
+ CRITERIA_C_O_U_IGNIS_25 = 10355,
+ CRITERIA_C_O_U_RAZORSCALE_25 = 10353,
+ CRITERIA_C_O_U_XT002_25 = 10354,
+ CRITERIA_C_O_U_IRON_COUNCIL_25 = 10599,
+ CRITERIA_C_O_U_KOLOGARN_25 = 10357,
+ CRITERIA_C_O_U_AURIAYA_25 = 10363,
+ CRITERIA_C_O_U_HODIR_25 = 10719,
+ CRITERIA_C_O_U_THORIM_25 = 10404,
+ CRITERIA_C_O_U_FREYA_25 = 10583,
+ CRITERIA_C_O_U_MIMIRON_25 = 10361,
+ CRITERIA_C_O_U_VEZAX_25 = 10362,
+ CRITERIA_C_O_U_YOGG_SARON_25 = 10364
};
enum UlduarData
diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt
index 7a02e415d69..1ad85acb601 100644
--- a/src/server/shared/CMakeLists.txt
+++ b/src/server/shared/CMakeLists.txt
@@ -20,6 +20,7 @@ file(GLOB_RECURSE sources_Dynamic Dynamic/*.cpp Dynamic/*.h)
file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h)
file(GLOB_RECURSE sources_Networking Networking/*.cpp Networking/*.h)
file(GLOB_RECURSE sources_Packets Packets/*.cpp Packets/*.h)
+file(GLOB_RECURSE sources_Realm Realm/*.cpp Realm/*.h)
file(GLOB_RECURSE sources_Threading Threading/*.cpp Threading/*.h)
file(GLOB_RECURSE sources_Utilities Utilities/*.cpp Utilities/*.h)
@@ -50,6 +51,7 @@ set(shared_STAT_SRCS
${sources_Logging}
${sources_Networking}
${sources_Packets}
+ ${sources_Realm}
${sources_Threading}
${sources_Utilities}
${sources_localdir}
@@ -72,6 +74,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Logging
${CMAKE_CURRENT_SOURCE_DIR}/Networking
${CMAKE_CURRENT_SOURCE_DIR}/Packets
+ ${CMAKE_CURRENT_SOURCE_DIR}/Realm
${CMAKE_CURRENT_SOURCE_DIR}/Threading
${CMAKE_CURRENT_SOURCE_DIR}/Utilities
${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object
diff --git a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp
index 69198c18df0..b84de24741c 100644
--- a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp
+++ b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp
@@ -29,12 +29,17 @@ WorldPacketCrypt::WorldPacketCrypt() : PacketCrypt(SHA_DIGEST_LENGTH)
void WorldPacketCrypt::Init(BigNumber* K)
{
uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0x08, 0xF1, 0x95, 0x9F, 0x47, 0xE5, 0xD2, 0xDB, 0xA1, 0x3D, 0x77, 0x8F, 0x3F, 0x3E, 0xE7, 0x00 };
- HmacSha1 serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey);
- uint8 *encryptHash = serverEncryptHmac.ComputeHash(K);
-
uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0x40, 0xAA, 0xD3, 0x92, 0x26, 0x71, 0x43, 0x47, 0x3A, 0x31, 0x08, 0xA6, 0xE7, 0xDC, 0x98, 0x2A };
- HmacSha1 clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey);
- uint8 *decryptHash = clientDecryptHmac.ComputeHash(K);
+ Init(K, ServerEncryptionKey, ServerDecryptionKey);
+}
+
+void WorldPacketCrypt::Init(BigNumber* k, uint8 const* serverKey, uint8 const* clientKey)
+{
+ HmacSha1 serverEncryptHmac(SEED_KEY_SIZE, (uint8*)serverKey);
+ uint8 *encryptHash = serverEncryptHmac.ComputeHash(k);
+
+ HmacSha1 clientDecryptHmac(SEED_KEY_SIZE, (uint8*)clientKey);
+ uint8 *decryptHash = clientDecryptHmac.ComputeHash(k);
_clientDecrypt.Init(decryptHash);
_serverEncrypt.Init(encryptHash);
diff --git a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h
index 7ccca11f09d..58c4003418e 100644
--- a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h
+++ b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h
@@ -29,6 +29,7 @@ class WorldPacketCrypt : public PacketCrypt
WorldPacketCrypt();
void Init(BigNumber* K) override;
+ void Init(BigNumber* k, uint8 const* serverKey, uint8 const* clientKey);
};
#endif // _WORLDPACKETCRYPT_H
diff --git a/src/server/shared/Database/Field.cpp b/src/server/shared/Database/Field.cpp
index f1741f98cc3..da547d3a151 100644
--- a/src/server/shared/Database/Field.cpp
+++ b/src/server/shared/Database/Field.cpp
@@ -46,7 +46,7 @@ void Field::SetByteValue(const void* newValue, const size_t newSize, enum_field_
data.raw = true;
}
-void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 length, bool isBinary)
+void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 length)
{
if (data.value)
CleanUp();
@@ -54,15 +54,9 @@ void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32
// This value stores somewhat structured data that needs function style casting
if (newValue)
{
- if (!isBinary)
- {
- data.value = new char[length + 1];
- *(reinterpret_cast<char*>(data.value) + length) = '\0';
- }
- else
- data.value = new char[length];
-
+ data.value = new char[length + 1];
memcpy(data.value, newValue, length);
+ *(reinterpret_cast<char*>(data.value) + length) = '\0';
data.length = length;
}
diff --git a/src/server/shared/Database/Field.h b/src/server/shared/Database/Field.h
index 99f98572a56..352db10c539 100644
--- a/src/server/shared/Database/Field.h
+++ b/src/server/shared/Database/Field.h
@@ -239,9 +239,11 @@ class Field
{
char const* string = GetCString();
if (!string)
- string = "";
+ return "";
+
return std::string(string, data.length);
}
+
return std::string((char*)data.value, data.length);
}
@@ -284,7 +286,7 @@ class Field
#endif
void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length);
- void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length, bool isBinary);
+ void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length);
void CleanUp()
{
diff --git a/src/server/shared/Database/PreparedStatement.cpp b/src/server/shared/Database/PreparedStatement.cpp
index 1f036b5bf0a..3ea3c969a4c 100644
--- a/src/server/shared/Database/PreparedStatement.cpp
+++ b/src/server/shared/Database/PreparedStatement.cpp
@@ -72,6 +72,7 @@ void PreparedStatement::BindParameters()
break;
case TYPE_BINARY:
m_stmt->setBinary(i, statement_data[i].binary, false);
+ break;
case TYPE_NULL:
m_stmt->setNull(i);
break;
@@ -357,7 +358,7 @@ void MySQLPreparedStatement::setBinary(const uint8 index, const std::vector<uint
m_paramsSet[index] = true;
MYSQL_BIND* param = &m_bind[index];
size_t len = value.size();
- param->buffer_type = MYSQL_TYPE_VAR_STRING;
+ param->buffer_type = MYSQL_TYPE_BLOB;
delete [] static_cast<char *>(param->buffer);
param->buffer = new char[len];
param->buffer_length = len;
@@ -365,7 +366,10 @@ void MySQLPreparedStatement::setBinary(const uint8 index, const std::vector<uint
delete param->length;
param->length = new unsigned long(len);
if (isString)
+ {
*param->length -= 1;
+ param->buffer_type = MYSQL_TYPE_VAR_STRING;
+ }
memcpy(param->buffer, value.data(), len);
}
diff --git a/src/server/shared/Database/QueryResult.cpp b/src/server/shared/Database/QueryResult.cpp
index a6d9c64622a..154cf5cda41 100644
--- a/src/server/shared/Database/QueryResult.cpp
+++ b/src/server/shared/Database/QueryResult.cpp
@@ -172,7 +172,7 @@ bool ResultSet::NextRow()
}
for (uint32 i = 0; i < _fieldCount; i++)
- _currentRow[i].SetStructuredValue(row[i], _fields[i].type, lengths[i], (_fields[i].flags & BINARY_FLAG) != 0);
+ _currentRow[i].SetStructuredValue(row[i], _fields[i].type, lengths[i]);
return true;
}
diff --git a/src/server/shared/Networking/SocketMgr.h b/src/server/shared/Networking/SocketMgr.h
index dbe2b8ec902..92c16d96882 100644
--- a/src/server/shared/Networking/SocketMgr.h
+++ b/src/server/shared/Networking/SocketMgr.h
@@ -33,6 +33,7 @@ class SocketMgr
public:
virtual ~SocketMgr()
{
+ delete _acceptor;
delete[] _threads;
}
diff --git a/src/server/shared/Realm/Realm.cpp b/src/server/shared/Realm/Realm.cpp
new file mode 100644
index 00000000000..79b10843773
--- /dev/null
+++ b/src/server/shared/Realm/Realm.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Realm.h"
+
+ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const
+{
+ ip::address realmIp;
+
+ // Attempt to send best address for client
+ if (clientAddr.is_loopback())
+ {
+ // Try guessing if realm is also connected locally
+ if (LocalAddress.is_loopback() || ExternalAddress.is_loopback())
+ realmIp = clientAddr;
+ else
+ {
+ // Assume that user connecting from the machine that bnetserver is located on
+ // has all realms available in his local network
+ realmIp = LocalAddress;
+ }
+ }
+ else
+ {
+ if (clientAddr.is_v4() &&
+ (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) ==
+ (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()))
+ {
+ realmIp = LocalAddress;
+ }
+ else
+ realmIp = ExternalAddress;
+ }
+
+ ip::tcp::endpoint endpoint(realmIp, Port);
+
+ // Return external IP
+ return endpoint;
+}
diff --git a/src/server/shared/Realm/Realm.h b/src/server/shared/Realm/Realm.h
new file mode 100644
index 00000000000..9476f137947
--- /dev/null
+++ b/src/server/shared/Realm/Realm.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef Realm_h__
+#define Realm_h__
+
+#include "Common.h"
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ip/tcp.hpp>
+
+using namespace boost::asio;
+
+enum RealmFlags
+{
+ REALM_FLAG_NONE = 0x00,
+ REALM_FLAG_INVALID = 0x01,
+ REALM_FLAG_OFFLINE = 0x02,
+ REALM_FLAG_SPECIFYBUILD = 0x04,
+ REALM_FLAG_UNK1 = 0x08,
+ REALM_FLAG_UNK2 = 0x10,
+ REALM_FLAG_RECOMMENDED = 0x20,
+ REALM_FLAG_NEW = 0x40,
+ REALM_FLAG_FULL = 0x80
+};
+
+#pragma pack(push, 1)
+
+namespace Battlenet
+{
+ struct RealmHandle;
+
+ struct RealmId
+ {
+ RealmId() : Region(0), Battlegroup(0), Index(0), Build(0) { }
+ RealmId(uint8 region, uint8 battlegroup, uint32 index, uint32 build)
+ : Region(region), Battlegroup(battlegroup), Index(index), Build(build) { }
+
+ uint8 Region;
+ uint8 Battlegroup;
+ uint32 Index;
+ uint32 Build;
+
+ bool operator<(RealmId const& r) const
+ {
+ return memcmp(this, &r, sizeof(RealmId) - sizeof(Build)) < 0;
+ }
+ };
+}
+
+#pragma pack(pop)
+
+// Storage object for a realm
+struct Realm
+{
+ Battlenet::RealmId Id;
+ ip::address ExternalAddress;
+ ip::address LocalAddress;
+ ip::address LocalSubnetMask;
+ uint16 Port;
+ std::string Name;
+ uint8 Type;
+ RealmFlags Flags;
+ uint8 Timezone;
+ AccountTypes AllowedSecurityLevel;
+ float PopulationLevel;
+ bool Updated;
+ bool Keep;
+
+ ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const;
+};
+
+#endif // Realm_h__
diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp
index c5127b8f3e2..821e1f5bd83 100644
--- a/src/server/worldserver/Main.cpp
+++ b/src/server/worldserver/Main.cpp
@@ -30,7 +30,6 @@
#include "OpenSSLCrypto.h"
#include "ProcessPriority.h"
#include "BigNumber.h"
-#include "RealmList.h"
#include "World.h"
#include "MapManager.h"
#include "InstanceSaveMgr.h"
@@ -44,6 +43,7 @@
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
#include "BattlenetServerManager.h"
+#include "Realm/Realm.h"
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <boost/asio/io_service.hpp>
@@ -82,6 +82,7 @@ WorldDatabaseWorkerPool WorldDatabase; ///< Accessor to the
CharacterDatabaseWorkerPool CharacterDatabase; ///< Accessor to the character database
LoginDatabaseWorkerPool LoginDatabase; ///< Accessor to the realm/login database
Battlenet::RealmHandle realmHandle; ///< Id of the realm
+Realm realm;
void SignalHandler(const boost::system::error_code& error, int signalNumber);
void FreezeDetectorHandler(const boost::system::error_code& error);
@@ -92,6 +93,7 @@ void WorldUpdateLoop();
void ClearOnlineAccounts();
void ShutdownCLIThread(std::thread* cliThread);
void ShutdownThreadPool(std::vector<std::thread>& threadPool);
+bool LoadRealmInfo();
variables_map GetConsoleArguments(int argc, char** argv, std::string& cfg_file, std::string& cfg_service);
/// Launch the Trinity server
@@ -192,6 +194,8 @@ extern int main(int argc, char** argv)
// Set server offline (not connectable)
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmHandle.Index);
+ LoadRealmInfo();
+
// Initialize the World
sWorld->SetInitialWorldSettings();
@@ -226,6 +230,8 @@ extern int main(int argc, char** argv)
// Set server online (allow connecting now)
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_INVALID, realmHandle.Index);
+ realm.PopulationLevel = 0.0f;
+ realm.Flags = RealmFlags(realm.Flags & ~uint32(REALM_FLAG_INVALID));
// Start the freeze check callback cycle in 5 seconds (cycle itself is 1 sec)
if (int coreStuckTime = sConfigMgr->GetIntDefault("MaxCoreStuckTime", 0))
@@ -452,6 +458,62 @@ AsyncAcceptor* StartRaSocketAcceptor(boost::asio::io_service& ioService)
return acceptor;
}
+bool LoadRealmInfo()
+{
+ boost::asio::ip::tcp::resolver resolver(_ioService);
+ boost::asio::ip::tcp::resolver::iterator end;
+
+ QueryResult result = LoginDatabase.PQuery("SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild, Region, Battlegroup FROM realmlist WHERE id = %u", realmHandle.Index);
+ if (!result)
+ return false;
+
+ Field* fields = result->Fetch();
+ realm.Name = fields[1].GetString();
+ boost::asio::ip::tcp::resolver::query externalAddressQuery(ip::tcp::v4(), fields[2].GetString(), "");
+
+ boost::system::error_code ec;
+ boost::asio::ip::tcp::resolver::iterator endPoint = resolver.resolve(externalAddressQuery, ec);
+ if (endPoint == end || ec)
+ {
+ TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[2].GetString().c_str());
+ return false;
+ }
+
+ realm.ExternalAddress = (*endPoint).endpoint().address();
+
+ boost::asio::ip::tcp::resolver::query localAddressQuery(ip::tcp::v4(), fields[3].GetString(), "");
+ endPoint = resolver.resolve(localAddressQuery, ec);
+ if (endPoint == end || ec)
+ {
+ TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[3].GetString().c_str());
+ return false;
+ }
+
+ realm.LocalAddress = (*endPoint).endpoint().address();
+
+ boost::asio::ip::tcp::resolver::query localSubmaskQuery(ip::tcp::v4(), fields[4].GetString(), "");
+ endPoint = resolver.resolve(localSubmaskQuery, ec);
+ if (endPoint == end || ec)
+ {
+ TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[4].GetString().c_str());
+ return false;
+ }
+
+ realm.LocalSubnetMask = (*endPoint).endpoint().address();
+
+ realm.Port = fields[5].GetUInt16();
+ realm.Type = fields[6].GetUInt8();
+ realm.Flags = RealmFlags(fields[7].GetUInt8());
+ realm.Timezone = fields[8].GetUInt8();
+ realm.AllowedSecurityLevel = AccountTypes(fields[9].GetUInt8());
+ realm.PopulationLevel = fields[10].GetFloat();
+ realm.Id.Index = fields[0].GetUInt32();
+ realm.Id.Build = fields[11].GetUInt32();
+ realm.Id.Region = fields[12].GetUInt8();
+ realm.Id.Battlegroup = fields[13].GetUInt8();
+ return true;
+}
+
/// Initialize connection to the databases
bool StartDB()
{
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 4d40365451e..e4406e7ecce 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -141,6 +141,13 @@ MaxPingTime = 30
WorldServerPort = 8085
#
+# InstanceServerPort
+# Description: TCP port to for second world connection.
+# Default: 8086
+
+InstanceServerPort = 8086
+
+#
# BindIP
# Description: Bind world server to IP/hostname.
# Default: "0.0.0.0" - (Bind to all IPs on the system)
@@ -2258,9 +2265,9 @@ Arena.QueueAnnouncer.Enable = 0
#
# Arena.ArenaSeason.ID
# Description: Current arena season id shown in clients.
-# Default: 8
+# Default: 15
-Arena.ArenaSeason.ID = 8
+Arena.ArenaSeason.ID = 15
#
# Arena.ArenaSeason.InProgress