aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2023_06_21_00_world.sql488
-rw-r--r--src/server/scripts/ExilesReach/exiles_reach_script_loader.cpp26
-rw-r--r--src/server/scripts/ExilesReach/zone_exiles_reach.cpp1069
3 files changed, 1583 insertions, 0 deletions
diff --git a/sql/updates/world/master/2023_06_21_00_world.sql b/sql/updates/world/master/2023_06_21_00_world.sql
new file mode 100644
index 00000000000..5a72d6e08cb
--- /dev/null
+++ b/sql/updates/world/master/2023_06_21_00_world.sql
@@ -0,0 +1,488 @@
+-- *** Missing Spawns ***
+
+SET @CGUID := 1051980;
+DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+25;
+INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnDifficulties`, `PhaseId`, `PhaseGroup`, `terrainSwapMap`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `VerifiedBuild`) VALUES
+(@CGUID+0,174971,2369,10424,13377,'0',0,0,-1,0,0,-17.644917,-6.061374,9.000128,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+1,174971,2369,10424,13377,'0',0,0,-1,0,0,-16.248755,-2.245914,8.885136,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+2,174971,2369,10424,13377,'0',0,0,-1,0,0,-4.609498,-7.722448,8.843941,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+3,174971,2369,10424,13377,'0',0,0,-1,0,0,-17.633347,5.349984,8.993013,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+4,174971,2369,10424,13377,'0',0,0,-1,0,0,-7.1927896,-1.4265188,9.105859,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+5,174971,2369,10424,13377,'0',0,0,-1,0,0,-3.5559115,-6.8839636,8.878474,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+6,174971,2369,10424,13377,'0',0,0,-1,0,0,-16.220743,-7.592815,8.926627,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+7,174971,2369,10424,13377,'0',0,0,-1,0,0,-17.212137,0.9415215,8.992922,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+8,174971,2369,10424,13377,'0',0,0,-1,0,0,-7.1881604,4.13693,8.805241,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+9,174971,2369,10424,13377,'0',0,0,-1,0,0,-3.8145015,-9.154231,8.854396,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+10,168039,2369,10424,13377,'0',0,0,-1,0,0,-10.630922,-11.896218,8.97435,1.7062142,120,0,0,1,0,0,0,0,45745), -- hBoat
+(@CGUID+11,174971,2261,10424,10639,'0',0,0,-1,0,0,3.8316922,5.474146,5.2092524,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+12,174971,2261,10424,10639,'0',0,0,-1,0,0,2.6647408,6.4705987,5.1801515,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+13,174971,2261,10424,10639,'0',0,0,-1,0,0,9.56842,4.517551,5.1502733,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+14,174971,2261,10424,10639,'0',0,0,-1,0,0,6.701894,6.1971374,5.194476,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+15,174971,2261,10424,10639,'0',0,0,-1,0,0,7.199659,-5.407894,5.216199,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+16,174971,2261,10424,10639,'0',0,0,-1,0,0,0.4600576,-6.25066,5.2069707,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+17,174971,2261,10424,10639,'0',0,0,-1,0,0,3.8914397,-6.136929,5.1904373,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+18,174971,2261,10424,10639,'0',0,0,-1,0,0,0.9357995,5.2422814,5.221966,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+19,174971,2261,10424,10639,'0',0,0,-1,0,0,6.4270716,4.5759077,5.2394466,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+20,174971,2261,10424,10639,'0',0,0,-1,0,0,-9.461674,-4.971889,5.456243,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+21,174971,2261,10424,10639,'0',0,0,-1,0,0,-7.5362535,4.9206376,5.2989116,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+22,174971,2261,10424,10639,'0',0,0,-1,0,0,-6.4343257,-4.8330746,5.2104034,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+23,174971,2261,10424,10639,'0',0,0,-1,0,0,8.676258,-4.551461,5.2418213,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+24,174971,2261,10424,10639,'0',0,0,-1,0,0,-3.2766402,-5.403929,5.293099,0,120,0,0,1,0,0,0,0,45745), -- Spar Point Advertisement
+(@CGUID+25,156403,2261,10424,10639,'0',0,0,-1,0,0,8.402318,-0.14915128,5.2594776,3.2919948,120,0,0,1,0,0,0,0,45745); -- aBoat
+
+DELETE FROM `spawn_group` WHERE `spawnId` BETWEEN @CGUID+0 AND @CGUID+25;
+INSERT INTO `spawn_group` (`groupId`,`spawnType`,`spawnId`) VALUES
+(129,0,@CGUID+0), -- Horde
+(129,0,@CGUID+1),
+(129,0,@CGUID+2),
+(129,0,@CGUID+3),
+(129,0,@CGUID+4),
+(129,0,@CGUID+5),
+(129,0,@CGUID+6),
+(129,0,@CGUID+7),
+(129,0,@CGUID+8),
+(129,0,@CGUID+9),
+(129,0,@CGUID+10),
+(128,0,@CGUID+11), -- Alliance
+(128,0,@CGUID+12),
+(128,0,@CGUID+13),
+(128,0,@CGUID+14),
+(128,0,@CGUID+15),
+(128,0,@CGUID+16),
+(128,0,@CGUID+17),
+(128,0,@CGUID+18),
+(128,0,@CGUID+19),
+(128,0,@CGUID+20),
+(128,0,@CGUID+21),
+(128,0,@CGUID+22),
+(128,0,@CGUID+23),
+(128,0,@CGUID+24),
+(128,0,@CGUID+25);
+
+-- *** Creature Fixes ***
+
+-- Misc creature and template fixes
+UPDATE `creature` SET `equipment_id`=1 WHERE `guid`=1050189;
+UPDATE `creature` SET `spawntimesecs`=120 WHERE `map`=2369 AND `spawntimesecs`=7200;
+UPDATE `creature_template` SET `npcflag`=2 WHERE `entry`=166827;
+UPDATE `creature_template` SET `flags_extra`=128 WHERE `entry` IN (174971,168039);
+UPDATE `creature_template` SET `faction`=35,`unit_flags`=33554432,`unit_flags2`=2048,`unit_flags3`=524320 WHERE `entry`=166814;
+UPDATE `creature_template` SET `faction`=35,`unit_flags`=64,`unit_flags2`=2048,`unit_flags3`=524288 WHERE `entry`=157051;
+
+-- Gryphons had 2 riders
+UPDATE `vehicle_template_accessory` SET `minion`=1 WHERE `entry`=156345;
+
+-- Summon data for sparing partners
+DELETE FROM `creature_summoned_data` WHERE `CreatureID` IN (157051,166814);
+INSERT INTO `creature_summoned_data` (`CreatureID`,`CreatureIDVisibleToSummoner`,`GroundMountDisplayID`,`FlyingMountDisplayID`) VALUES
+(157051,155607,NULL,NULL),
+(166814,166815,NULL,NULL);
+
+-- *** Creature Text ***
+
+DELETE FROM `creature_text` WHERE `CreatureID` IN (156280,160664,166824,166583,166827,157051,166814) AND `GroupID` IN (0,1);
+INSERT INTO `creature_text` (`CreatureID`,`GroupID`,`ID`,`Text`,`Type`,`Language`,`Probability`,`Emote`,`Duration`,`Sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(156280, 0, 0, 'Private Cole will run you through the rest of the drills. I need to discuss this storm with the helmsman.', 12, 0, 100, 0, 0, 152734, 184106, 0, 'Captain Garrick'),
+(156280, 1, 0, 'Everyone below decks! Now!', 12, 0, 100, 0, 0, 152735, 177674, 0, 'Captain Garrick'),
+(160664, 0, 0, 'Captain! We can\'t weather this storm for long!', 12, 0, 100, 0, 0, 152849, 177675, 0, 'Private Cole'),
+(166824, 0, 0, 'Throg will spar with you for now. I must speak to the crew about the rain.', 12, 0, 100, 0, 0, 156952, 199040, 0, 'Warlord Breka Grimaxe'),
+(166583, 0, 0, 'Warlord! This storm will soon overwhelm us!', 12, 0, 100, 0, 0, 156977, 195892, 0, 'Grunt Throg'),
+(166827, 1, 0, 'Soldiers, brace yourselves!', 12, 0, 100, 0, 0, 156953, 195893, 0, 'Warlord Breka Grimaxe'),
+(157051, 0, 0, 'I yield! Well, I\'d say you\'re more than ready for whatever we find on that island.', 12, 0, 100, 4, 0, 152848, 177677, 0, 'Alliance Sparing Partner'),
+(166814, 0, 0, 'I concede! Your strength will see our mission through.', 12, 0, 100, 4, 0, 156976, 195857, 0, 'Horde Sparing Partner');
+
+-- *** Phasing ***
+
+DELETE FROM `phase_area` WHERE `AreaId`=13377 AND `PhaseId` IN (14355);
+INSERT INTO `phase_area` (`AreaId`,`PhaseId`,`Comment`) VALUES
+(13377,14355, 'NPE Horde Ship - Decoration NPCs initial');
+
+DELETE FROM `phase_area` WHERE `AreaId`=10639 AND `PhaseId` IN (14350);
+INSERT INTO `phase_area` (`AreaId`,`PhaseId`,`Comment`) VALUES
+(10639,14350, 'NPE Alliance Ship - Captain Garrick pre Quest 56775 rewarded upper deck');
+
+DELETE FROM `phase_name` WHERE `ID` IN (13861,14349,14350,14353,14355,15284,15287,15514,15516);
+INSERT INTO `phase_name` (`ID`,`Name`) VALUES
+(13861,'Cosmetic - NPE Alliance Ship - Decoration NPCs lower deck storm'),
+(14349,'Cosmetic - NPE Alliance Ship - Captain Garrick deck'),
+(14350,'Cosmetic - NPE Alliance Ship - Captain Garrick upper deck'),
+(14353,'Cosmetic - NPE Alliance Ship - Private Cole on deck initial'),
+(14355,'Cosmetic - NPE Alliance Ship - Decoration NPCs deck'),
+(15284,'Cosmetic - NPE Horde Ship - Grunt Throg deck initial'),
+(15287,'Cosmetic - NPE Horde Ship - Grunt Throg storm'),
+(15514,'Cosmetic - NPE Horde Ship - Decoration NPCs deck initial'),
+(15516,'Cosmetic - NPE Horde Ship - Decoration NPCs deck storm');
+
+-- *** Conditions ***
+
+-- Spawn Conditions for Warlord Breka Grimaxe spawns Phase 1
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=32 AND `SourceGroup`=5 AND `SourceEntry` IN (166573,166824,166827) AND `SourceId`=0;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(32,5,166573,0,0,47,0,59926,11,0,0,0,0,'','Spawn of creature with entry 166573 requires Quest 59926 not rewarded'),
+(32,5,166824,0,0,47,0,59926,64,0,0,0,0,'','Spawn of creature with entry 166824 requires Quest 59926 rewarded'),
+(32,5,166824,0,0,47,0,59928,2,0,1,0,0,'','Spawn of creature with entry 166824 requires Quest 59928 not complete'),
+(32,5,166827,0,0,47,0,59928,2,0,0,0,0,'','Spawn of creature with entry 166827 requires Quest 59928 complete');
+
+-- Phase conditions
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=26 AND `SourceGroup` IN (15284,15514,15287,15516) AND `SourceEntry`=13377;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(26,15284,13377,0,0,47,0,59927,8,0,1,0,0,'','Allow Phase 15284 if Quest 59927 (Stand Your Ground) is not inprogress'),
+(26,15284,13377,0,0,47,0,59928,2,0,1,0,0,'','Allow Phase 15284 if Quest 59928 (Brace for Impact) is not complete'),
+(26,15514,13377,0,0,47,0,59928,2,0,1,0,0,'','Allow Phase 15514 if Quest 59928 (Brace for Impact) is not Complete'),
+(26,15287,13377,0,0,47,0,59928,2,0,0,0,0,'','Allow Phase 15287 if Quest 59928 (Brace for Impact) is complete'),
+(26,15516,13377,0,0,47,0,59928,2,0,0,0,0,'','Allow Phase 15516 if Quest 59928 (Brace for Impact) is Complete');
+
+-- Fix condition showing Alliance quest phase on horde on ship
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=26 AND `SourceGroup` IN (13861,14350,14353) AND `SourceEntry`=10639;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(26,13861,10639,0,0,47,0,54933,2,0,0,0,0,'','Apply Phase 13861 if Quest 54933 (Freeing the Light) is complete'),
+(26,14350,10639,0,0,47,0,56775,64,0,0,0,0,'','Apply Phase 14350 if Quest 56775 (Warming Up) is rewarded'),
+(26,14350,10639,0,0,47,0,58208,2,0,1,0,0,'','Apply Phase 14350 if Quest 58208 (Brace for Impact) is not complete'),
+(26,14353,10639,0,0,47,0,58208,2,0,0,0,0,'','Allow Phase 14353 if Quest 58208 (Brace for Impact) is complete');
+
+UPDATE `conditions` SET `ConditionValue1`=58208, `Comment`='Apply Phase 13861 if Quest 58208 (Brace for Impact) is complete' WHERE `SourceTypeOrReferenceId`=26 AND `SourceGroup`=13861 AND `SourceEntry`=10639;
+
+-- *** Spells ***
+
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (303065,325108);
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(303065,'spell_summon_sparring_partner'),
+(325108,'spell_summon_sparring_partner');
+
+-- Crash movie spell cast on player for "Brace for Impact" quest rewarded Alliance and Horde
+DELETE FROM `spell_area` WHERE `spell` IN (346797,346799);
+INSERT INTO `spell_area` (`spell`,`area`,`quest_start`,`quest_end`,`aura_spell`,`racemask`,`gender`,`flags`,`quest_start_status`,`quest_end_status`) VALUES
+(346797,10453,58208,0,305425,0,2,1,64,0),
+(346799,10453,59928,0,325131,0,2,1,64,0);
+
+-- Wrong storm spell in db
+UPDATE `spell_area` SET `spell`=305421 WHERE `spell`=305422;
+
+-- Teleport spell locations for "Brace for Impact" quest rewarded Alliance and Horde
+DELETE FROM `spell_target_position` WHERE `ID` IN (305425,325131);
+INSERT INTO `spell_target_position` (`ID`,`EffectIndex`,`MapID`,`PositionX`,`PositionY`,`PositionZ`,`VerifiedBuild`) VALUES
+(305425,4,2175,-462.4,-2619.8,0.4,45745),
+(325131,3,2175,-462.4,-2619.8,0.4,45745);
+
+DELETE FROM `spell_script_names` WHERE `spell_id` IN (305464,325136,290901,305445);
+INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
+(305464,'spell_crash_landed_alliance'),
+(325136,'spell_crash_landed_horde'),
+(290901,'spell_attention_exiles_reach_tutorial'),
+(305445,'spell_knocked_down_exiles_reach_beach');
+
+-- *** Scenes ***
+
+-- Add scene scripts
+UPDATE `scene_template` SET `ScriptName`='scene_alliance_and_horde_ship' WHERE `SceneId` IN (2236,2486);
+DELETE FROM `scene_template` WHERE `SceneId` IN (2334,2487);
+INSERT INTO `scene_template` (`SceneId`,`Flags`,`ScriptPackageID`,`Encrypted`,`ScriptName`) VALUES
+(2334,16,2708,0,'scene_alliance_and_horde_crash'), -- Alliance
+(2487,16,2708,0,'scene_alliance_and_horde_crash'); -- Horde
+
+-- *** Conversations ***
+
+DELETE FROM `conversation_actors` WHERE `ConversationId` IN (10768,12818,12798,14422,14423,14424);
+INSERT INTO `conversation_actors` (`ConversationId`,`ConversationActorId`,`ConversationActorGuid`,`Idx`,`CreatureId`,`CreatureDisplayInfoId`,`NoActorObject`,`ActivePlayerObject`,`VerifiedBuild`) VALUES
+(10768,73720,1050145,0,0,0,0,0,45745), -- Alliance
+(10768,75916,1050189,1,0,0,0,0,45745), -- Horde
+(12818,73720,1050145,0,0,0,0,0,45745), -- Alliance
+(12818,75916,1050189,1,0,0,0,0,45745), -- Horde
+(12798,73720,1050145,0,0,0,0,0,45745), -- Alliance
+(12798,75916,1050189,1,0,0,0,0,45745), -- Horde
+(14422,68598,0,0,0,0,0,0,45745), -- Alliance
+(14422,75920,0,1,0,0,0,0,45745), -- Horde
+(14423,68598,0,0,0,0,0,0,45745), -- Alliance
+(14423,75920,0,1,0,0,0,0,45745), -- Horde
+(14424,68598,0,0,0,0,0,0,45745), -- Alliance
+(14424,75920,0,1,0,0,0,0,45745); -- Horde
+
+DELETE FROM `conversation_line_template` WHERE `Id` IN (32717,35650,31445,36093,31382,36096,36099,36100,36101,36102,36103,36104);
+INSERT INTO `conversation_line_template` (`Id`,`UiCameraID`,`ActorIdx`,`Flags`,`VerifiedBuild`) VALUES
+(32717,0,0,0,45745), -- Alliance
+(35650,0,1,0,45745), -- Horde
+(31445,0,0,0,45745), -- Alliance
+(36093,0,1,0,45745), -- Horde
+(31382,0,0,0,45745), -- Alliance
+(36096,0,1,0,45745), -- Horde
+(36099,0,0,0,45745), -- Alliance
+(36100,0,1,0,45745), -- Horde
+(36101,0,0,0,45745), -- Alliance
+(36102,0,1,0,45745), -- Horde
+(36103,0,0,0,45745), -- Alliance
+(36104,0,1,0,45745); -- Horde
+
+DELETE FROM `conversation_template` WHERE `Id` IN (10768,12818,12798,14422,14423,14424);
+INSERT INTO `conversation_template` (`Id`,`FirstLineId`,`TextureKitId`,`ScriptName`,`VerifiedBuild`) VALUES
+(10768,32717,0,'',45745),
+(12818,31445,0,'',45745),
+(12798,31382,0,'',45745),
+(14422,36099,0,'',45745),
+(14423,36101,0,'',45745),
+(14424,36103,0,'',45745);
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=29 AND `SourceEntry` IN (32717,35650,31445,36093,31382,36096,36099,36100,36101,36102,36103,36104);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(29,0,32717,0,0,6,0,469,0,0,0,0,0,'','Allow conversation line 32717 if team is Alliance'),
+(29,0,35650,0,0,6,0,67,0,0,0,0,0,'','Allow conversation line 35650 if team is horde'),
+(29,0,31445,0,0,6,0,469,0,0,0,0,0,'','Allow conversation line 31445 if team is Alliance'),
+(29,0,36093,0,0,6,0,67,0,0,0,0,0,'','Allow conversation line 36093 if team is horde'),
+(29,0,31382,0,0,6,0,469,0,0,0,0,0,'','Allow conversation line 31382 if team is Alliance'),
+(29,0,36096,0,0,6,0,67,0,0,0,0,0,'','Allow conversation line 36096 if team is horde'),
+(29,0,36099,0,0,6,0,469,0,0,0,0,0,'','Allow conversation line 36099 if team is Alliance'),
+(29,0,36100,0,0,6,0,67,0,0,0,0,0,'','Allow conversation line 36100 if team is horde'),
+(29,0,36101,0,0,6,0,469,0,0,0,0,0,'','Allow conversation line 36101 if team is Alliance'),
+(29,0,36102,0,0,6,0,67,0,0,0,0,0,'','Allow conversation line 36102 if team is horde'),
+(29,0,36103,0,0,6,0,469,0,0,0,0,0,'','Allow conversation line 36103 if team is Alliance'),
+(29,0,36104,0,0,6,0,67,0,0,0,0,0,'','Allow conversation line 36104 if team is horde');
+
+-- *** Creature scripts ***
+
+UPDATE `creature_template` SET `ScriptName`="npc_captain_garrick_ship" WHERE entry IN (156280);
+UPDATE `creature_template` SET `ScriptName`="npc_warlord_grimaxe_lower_ship" WHERE entry IN (166824);
+UPDATE `creature_template` SET `ScriptName`="npc_warlord_grimaxe_upper_ship" WHERE entry IN (166827);
+UPDATE `creature_template` SET `ScriptName`='npc_sparring_partner_exiles_reach' WHERE `entry` IN (157051,166814);
+UPDATE `creature_template` SET `ScriptName`="npc_cole_ship" WHERE entry IN (160664);
+UPDATE `creature_template` SET `ScriptName`="npc_throg_ship" WHERE entry IN (166583);
+UPDATE `creature_template` SET `ScriptName`="npc_crew_ship" WHERE entry IN (157042,157043,157044,157046,166585,166590,166794,166799);
+UPDATE `creature_template` SET `ScriptName`="npc_pet_ship" WHERE entry IN (167337,167342,167343,167344,167345,167346,167347,167348,167349,167350,167351,167352,167375);
+
+-- *** Quest scripts ***
+
+DELETE FROM `quest_template_addon` WHERE `ID` IN (56775,59926);
+INSERT INTO `quest_template_addon` (`ID`,`ScriptName`) VALUES
+(56775,'q56775_warming_up'),
+(59926,'q59926_warming_up');
+
+UPDATE `quest_template_addon` SET `ScriptName`='quest_stand_your_ground' WHERE `ID` IN (58209,59927);
+UPDATE `quest_template_addon` SET `ScriptName`='quest_brace_for_impact' WHERE `ID` IN (58208,59928);
+
+-- *** String IDs ***
+
+UPDATE `creature` SET `StringId`="q58209_cole" WHERE `guid`=1050146;
+UPDATE `creature` SET `StringId`="q56775_garrick_lower_deck" WHERE `guid`=1050145;
+UPDATE `creature` SET `StringId`="q56775_garrick_upper_deck" WHERE `guid`=1050589;
+UPDATE `creature` SET `StringId`="q58208_garrick" WHERE `guid`=1050176;
+UPDATE `creature` SET `StringId`="q58208_richter" WHERE `guid`=1050177;
+UPDATE `creature` SET `StringId`="q58208_austin" WHERE `guid`=1050178;
+UPDATE `creature` SET `StringId`="q58208_bjorn" WHERE `guid`=1050179;
+UPDATE `creature` SET `StringId`="q58208_keela" WHERE `guid`=1050180;
+UPDATE `creature` SET `StringId`="q58208_cole" WHERE `guid`=1050181;
+UPDATE `creature` SET `StringId`="q58208_wolf" WHERE `guid`=1050152;
+UPDATE `creature` SET `StringId`="q58208_bear" WHERE `guid`=1050148;
+UPDATE `creature` SET `StringId`="q58208_tiger" WHERE `guid`=1050150;
+UPDATE `creature` SET `StringId`="q58208_bunny" WHERE `guid`=1050154;
+UPDATE `creature` SET `StringId`="q58208_moth" WHERE `guid`=1050156;
+UPDATE `creature` SET `StringId`="q58208_dog" WHERE `guid`=1050158;
+UPDATE `creature` SET `StringId`="q58208_turtle" WHERE `guid`=1050160;
+UPDATE `creature` SET `StringId`="q59927_throg" WHERE `guid`=1050187;
+UPDATE `creature` SET `StringId`="q59926_grimaxe_lower_deck" WHERE `guid`=1050189;
+UPDATE `creature` SET `StringId`="q59926_grimaxe_upper_deck" WHERE `guid`=1050190;
+UPDATE `creature` SET `StringId`="q59928_grimaxe" WHERE `guid`=1050191;
+UPDATE `creature` SET `StringId`="q59928_bo" WHERE `guid`=1050201;
+UPDATE `creature` SET `StringId`="q59928_mithdran" WHERE `guid`=1050199;
+UPDATE `creature` SET `StringId`="q59928_lana" WHERE `guid`=1050198;
+UPDATE `creature` SET `StringId`="q59928_jinhake" WHERE `guid`=1050200;
+UPDATE `creature` SET `StringId`="q59928_throg" WHERE `guid`=1050188;
+UPDATE `creature` SET `StringId`="q59928_wolf" WHERE `guid`=1050203;
+UPDATE `creature` SET `StringId`="q59928_bat" WHERE `guid`=1050205;
+UPDATE `creature` SET `StringId`="q59928_plainstrider" WHERE `guid`=1050207;
+UPDATE `creature` SET `StringId`="q59928_raptor" WHERE `guid`=1050209;
+UPDATE `creature` SET `StringId`="q59928_scorpion" WHERE `guid`=1050213;
+UPDATE `creature` SET `StringId`="q59928_dragonhawk" WHERE `guid`=1050211;
+UPDATE `creature` SET `StringId`="q59928_turtle" WHERE `guid`=1050215;
+
+-- *** Pathing ***
+
+-- Pathing for Captain Garrick post "Quest: Warming Up"
+SET @PATH := 10501450;
+DELETE FROM `waypoint_data` WHERE `id` IN (@PATH,@PATH+1);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-11.810547,0.9602051,5.5279408,NULL,0,0,0,100,0),
+(@PATH+1,1,-0.3022461,-1.409729,5.774313,NULL,0,0,0,100,0),
+(@PATH+1,2,4.697754,-2.659729,5.524313,NULL,0,0,0,100,0),
+(@PATH+1,3,8.697754,-4.159729,5.524313,NULL,0,0,0,100,0),
+(@PATH+1,4,12.447754,-5.159729,5.524313,NULL,0,0,0,100,0),
+(@PATH+1,5,15.947754,-5.409729,6.274313,NULL,0,0,0,100,0),
+(@PATH+1,6,18.947754,-5.409729,9.274313,NULL,0,0,0,100,0),
+(@PATH+1,7,21.197754,-4.659729,9.774313,NULL,0,0,0,100,0),
+(@PATH+1,8,30.197754,-3.659729,11.024313,NULL,0,0,0,100,0),
+(@PATH+1,9,37.706055,-3.779663,12.020686,NULL,0,0,0,100,0),
+(@PATH+1,10,37.83252,-1.4055176,12.501659,NULL,0,0,0,100,0);
+
+-- Pathing for Captain Garrick "Quest: Brace for Impact"
+SET @PATH := 10505890;
+DELETE FROM `waypoint_data` WHERE `id` IN (@PATH,@PATH+1);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,38.556152,-0.6357422,13.232409,NULL,0,1,0,100,0),
+(@PATH,2,35.56421,-1.1977539,12.1479,NULL,0,1,0,100,0),
+(@PATH,3,32.572266,-1.7597656,11.063391,NULL,0,1,0,100,0),
+(@PATH,4,28.660645,-2.8950195,10.562886,NULL,0,1,0,100,0),
+(@PATH,5,22.253174,-4.680664,9.82038,NULL,0,1,0,100,0),
+(@PATH,6,18.129395,-4.897949,8.297633,NULL,0,1,0,100,0),
+(@PATH,7,13.874268,-5.3256836,5.080761,NULL,0,1,0,100,0),
+(@PATH,8,10.271484,-5.2910156,5.001395,NULL,0,1,0,100,0),
+(@PATH,9,4.762451,-3.1137695,5.1861935,NULL,0,1,0,100,0),
+(@PATH+1,1,11.084107,3.9018552,5.28156,NULL,0,1,0,100,0),
+(@PATH+1,2,17.084106,4.9018555,5.53156,NULL,0,1,0,100,0),
+(@PATH+1,3,26.905762,5.4174805,4.876927,NULL,0,1,0,100,0);
+
+-- Pathing for Warlord Breka Grimaxe "Quest: Warming Up"
+SET @PATH := 10501900;
+DELETE FROM `waypoint_data` WHERE `id` IN (@PATH,@PATH+1);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10.602051,8.918945,8.779607,NULL,0,0,0,100,0),
+(@PATH+1,1,2.480713,9.498291,9.528435,NULL,0,1,0,100,0),
+(@PATH+1,2,3.480713,9.748291,9.778435,NULL,0,1,0,100,0),
+(@PATH+1,3,3.730713,9.998291,10.028435,NULL,0,1,0,100,0),
+(@PATH+1,4,5.230713,12.248291,10.778435,NULL,0,1,0,100,0),
+(@PATH+1,5,6.730713,11.748291,12.278435,NULL,0,1,0,100,0),
+(@PATH+1,6,9.230713,10.748291,14.778435,NULL,0,1,0,100,0),
+(@PATH+1,7,12.480713,9.498291,17.778435,NULL,0,1,0,100,0),
+(@PATH+1,8,13.730713,9.498291,18.528435,NULL,0,1,0,100,0),
+(@PATH+1,9,14.480713,9.248291,18.778435,NULL,0,1,0,100,0),
+(@PATH+1,10,15.480713,8.998291,18.778435,NULL,0,1,0,100,0),
+(@PATH+1,11,15.480713,6.748291,18.778435,NULL,0,1,0,100,0),
+(@PATH+1,12,15.730713,5.748291,18.778435,NULL,0,1,0,100,0),
+(@PATH+1,13,15.230713,5.498291,18.778435,NULL,0,1,0,100,0),
+(@PATH+1,14,15.230713,5.248291,18.778435,NULL,0,1,0,100,0),
+(@PATH+1,15,15.980713,4.248291,19.528435,NULL,0,1,0,100,0),
+(@PATH+1,16,18.480713,3.248291,22.028435,NULL,0,1,0,100,0),
+(@PATH+1,17,23.480713,2.248291,26.278435,NULL,0,1,0,100,0),
+(@PATH+1,18,24.480713,0.24829102,26.528435,NULL,0,1,0,100,0),
+(@PATH+1,19,25.730713,-1.751709,27.278435,NULL,0,1,0,100,0),
+(@PATH+1,20,28.730713,-6.001709,27.278435,NULL,0,1,0,100,0),
+(@PATH+1,21,29.730713,-5.751709,27.528435,NULL,0,1,0,100,0),
+(@PATH+1,22,32.730713,-7.501709,30.278435,NULL,0,1,0,100,0),
+(@PATH+1,23,35.480713,-6.751709,33.528435,NULL,0,1,0,100,0),
+(@PATH+1,24,35.980713,-6.501709,33.778435,NULL,0,1,0,100,0),
+(@PATH+1,25,38.730713,-5.501709,34.528435,NULL,0,1,0,100,0),
+(@PATH+1,26,39.980713,-5.001709,35.028435,NULL,0,1,0,100,0),
+(@PATH+1,27,40.980713,-4.751709,36.028435,NULL,0,1,0,100,0),
+(@PATH+1,28,44.480713,-4.001709,39.778435,NULL,0,1,0,100,0),
+(@PATH+1,29,45.563477,-3.4223633,39.777264,NULL,0,1,0,100,0);
+
+-- Pathing for Warlord Breka Grimaxe "Quest: Brace for Impact"
+SET @PATH := 10501910;
+DELETE FROM `waypoint_data` WHERE `id` IN (@PATH,@PATH+1);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,23.386414,-1.0205078,26.200092,NULL,0,1,0,100,0),
+(@PATH,2,14.803528,1.5292969,18.348095,NULL,0,1,0,100,0),
+(@PATH,3,15.010681,5.6401367,18.400091,NULL,0,1,0,100,0),
+(@PATH,4,13.93335,10.104649,18.484093,NULL,0,1,0,100,0),
+(@PATH,5,1.4016113,10.96875,9.103544,NULL,0,1,0,100,0),
+(@PATH+1,1,-5.3898315,-0.84814453,9.203571,NULL,0,1,0,100,0);
+
+-- Sparing Partner "Quest: Stand Your Ground"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501460,10501870);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501460,1,-13.461914,0.69628906,5.677742,NULL,0,0,0,100,0),
+(10501460,2,-13.461914,0.69628906,5.677742,6.143559,1000,0,0,100,0),
+(10501460,3,-13.461914,0.69628906,5.677742,NULL,0,0,0,100,0),
+(10501870,1,-10.846191,11.937012,8.9623165,NULL,0,0,0,100,0),
+(10501870,2,-10.846191,11.937012,8.9623165,4.677482,1000,0,0,100,0),
+(10501870,3,-10.846191,11.937012,8.9623165,NULL,0,0,0,100,0);
+
+-- Pathing for Alliance Pets "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501510);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501510,1,-0.4882717,7.923595,5.247307,NULL,0,1,0,100,0),
+(10501510,2,4.7617283,6.173595,5.247307,NULL,0,1,0,100,0),
+(10501510,3,8.511728,5.173595,5.247307,NULL,0,1,0,100,0),
+(10501510,4,13.511728,3.423595,5.497307,NULL,0,1,0,100,0),
+(10501510,5,14.761728,4.423595,5.497307,NULL,0,1,0,100,0),
+(10501510,6,16.011728,4.673595,5.497307,NULL,0,1,0,100,0),
+(10501510,7,17.261728,5.173595,5.497307,NULL,0,1,0,100,0),
+(10501510,8,17.511728,4.923595,5.747307,NULL,0,1,0,100,0),
+(10501510,9,20.011728,5.173595,5.497307,NULL,0,1,0,100,0),
+(10501510,10,21.511728,4.673595,4.997307,NULL,0,1,0,100,0),
+(10501510,11,23.511728,4.173595,5.247307,NULL,0,1,0,100,0),
+(10501510,12,25.011728,3.923595,5.247307,NULL,0,1,0,100,0),
+(10501510,13,27.011728,2.923595,5.247307,NULL,0,1,0,100,0),
+(10501510,14,31.261728,-1.826405,4.997307,NULL,0,1,0,100,0),
+(10501510,15,31.472656,-2.2216797,4.8911333,NULL,0,1,0,100,0);
+
+-- Pathing for Horde Pets "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10502020);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10502020,1,-8.303954,-4.049614,9.174974,NULL,0,1,0,100,0),
+(10502020,2,-6.053954,-4.299614,9.174974,NULL,0,1,0,100,0),
+(10502020,3,-5.553954,-4.549614,9.174974,NULL,0,1,0,100,0),
+(10502020,4,-3.5539541,-4.549614,9.424974,NULL,0,1,0,100,0),
+(10502020,5,-2.8039541,-4.549614,9.424974,NULL,0,1,0,100,0),
+(10502020,6,-1.7705078,-5.0163574,9.223818,NULL,0,1,0,100,0);
+
+-- Pathing for Quartermaster Richter "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501770);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501770,1,-0.9053688,-5.5730305,5.2387342,NULL,0,1,0,100,0),
+(10501770,2,0.5946312,-1.3230305,5.4887342,NULL,0,1,0,100,0),
+(10501770,3,3.5946312,2.4269695,5.4887342,NULL,0,1,0,100,0),
+(10501770,4,9.844631,4.9269695,5.2387342,NULL,0,1,0,100,0),
+(10501770,5,17.344631,5.6769695,5.4887342,NULL,0,1,0,100,0),
+(10501770,6,24.344631,5.1769695,4.9887342,NULL,0,1,0,100,0),
+(10501770,7,26.844631,4.1769695,4.9887342,NULL,0,1,0,100,0),
+(10501770,8,30.037842,0.7416992,4.877288,NULL,0,1,0,100,0);
+
+-- Pathing for Kee-la "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501800);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501800,1,-9.640718,3.819191,5.6868877,NULL,0,1,0,100,0),
+(10501800,2,-3.890718,3.319191,5.4368877,NULL,0,1,0,100,0),
+(10501800,3,1.609282,3.819191,5.4368877,NULL,0,1,0,100,0),
+(10501800,4,10.359282,4.819191,5.1868877,NULL,0,1,0,100,0),
+(10501800,5,16.609282,5.569191,5.1868877,NULL,0,1,0,100,0),
+(10501800,6,23.859282,5.069191,5.1868877,NULL,0,1,0,100,0),
+(10501800,7,27.859282,4.069191,5.1868877,NULL,0,1,0,100,0),
+(10501800,8,29.109282,-0.43080902,5.1868877,NULL,0,1,0,100,0),
+(10501800,9,27.582764,-0.94091797,4.871175,NULL,0,1,0,100,0);
+
+-- Pathing for Bjorn Stouthands "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501790);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501790,1,7.726696,-7.4220815,5.1850023,NULL,0,1,0,100,0),
+(10501790,2,7.976696,-2.4220815,5.4350023,NULL,0,1,0,100,0),
+(10501790,3,11.726696,3.5779185,5.1850023,NULL,0,1,0,100,0),
+(10501790,4,16.976696,5.5779185,5.1850023,NULL,0,1,0,100,0),
+(10501790,5,21.726696,5.8279185,4.9350023,NULL,0,1,0,100,0),
+(10501790,6,25.476696,5.5779185,4.9350023,NULL,0,1,0,100,0),
+(10501790,7,29.112793,4.151367,4.889695,NULL,0,1,0,100,0);
+
+-- Pathing for Austin Huxworth "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501780);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501780,1,-1.4587336,8.48258,5.233676,NULL,0,1,0,100,0),
+(10501780,2,7.2912664,6.2325807,5.233676,NULL,0,1,0,100,0),
+(10501780,3,19.541267,5.4825807,5.233676,NULL,0,1,0,100,0),
+(10501780,4,27.791267,4.7325807,4.983676,NULL,0,1,0,100,0),
+(10501780,5,30.068604,2.567871,4.8888426,NULL,0,1,0,100,0);
+
+-- Pathing for Private Cole "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501461);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501461,1,30.931396,6.4296875,4.817522,NULL,0,1,0,100,0);
+
+-- Pathing for Grunt Throg "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501871);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501871,1,-3.9334717,1.109375,9.06326,NULL,0,1,0,100,0);
+
+-- Pathing for Bo "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10502010);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10502010,1,1.2434692,5.4038086,9.206478,NULL,0,1,0,100,0);
+
+-- Pathing for Mithdran Dawntracker "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501990);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501990,1,-2.8079834,-3.972168,9.100056,NULL,0,1,0,100,0);
+
+-- Pathing for Lana Jordan "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10501980);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10501980,1,-4.3847656,-2.7675781,9.160941,NULL,0,1,0,100,0);
+
+-- Pathing for Provisoner Jin'hake "Quest: Brace for Impact"
+DELETE FROM `waypoint_data` WHERE `id` IN (10502000);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(10502000,1,-2.8266602,3.7973633,9.252101,NULL,0,1,0,100,0);
diff --git a/src/server/scripts/ExilesReach/exiles_reach_script_loader.cpp b/src/server/scripts/ExilesReach/exiles_reach_script_loader.cpp
new file mode 100644
index 00000000000..9aba87f489e
--- /dev/null
+++ b/src/server/scripts/ExilesReach/exiles_reach_script_loader.cpp
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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/>.
+ */
+
+// This is where scripts' loading functions should be declared:
+void AddSC_zone_exiles_reach();
+
+// The name of this function should match:
+// void Add${NameOfDirectory}Scripts()
+void AddExilesReachScripts()
+{
+ AddSC_zone_exiles_reach();
+}
diff --git a/src/server/scripts/ExilesReach/zone_exiles_reach.cpp b/src/server/scripts/ExilesReach/zone_exiles_reach.cpp
new file mode 100644
index 00000000000..072861e35b4
--- /dev/null
+++ b/src/server/scripts/ExilesReach/zone_exiles_reach.cpp
@@ -0,0 +1,1069 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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 "Conversation.h"
+#include "CreatureAIImpl.h"
+#include "Map.h"
+#include "Object.h"
+#include "Player.h"
+#include "CellImpl.h"
+#include "Containers.h"
+#include "MotionMaster.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
+#include "PassiveAI.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "ScriptSystem.h"
+#include "SpellInfo.h"
+#include "SpellScript.h"
+#include "TemporarySummon.h"
+#include "Transport.h"
+
+template<class privateAI, class publicAI>
+CreatureAI* GetPrivatePublicPairAISelector(Creature* creature)
+{
+ if (creature->IsPrivateObject())
+ return new privateAI(creature);
+ return new publicAI(creature);
+}
+
+#define RegisterPrivatePublicCreatureAIPair(scriptName, privateAI, publicAI) new FactoryCreatureScript<CreatureAI, &GetPrivatePublicPairAISelector<privateAI, publicAI>>(scriptName);
+
+static Creature* FindCreatureIgnorePhase(WorldObject const* obj, std::string_view stringId, float range = 100.0f)
+{
+ return obj->FindNearestCreatureWithOptions(range, FindCreatureOptions().SetIgnorePhases(true).SetStringId(stringId));
+}
+
+ // ********************************************
+ // * Scripting in this section occurs on ship *
+ // ********************************************
+
+enum AttentionExilesReachData
+{
+ SPELL_DEBUG_LOOK_RIGHT = 290903
+};
+
+// 290901 - Attention!
+class spell_attention_exiles_reach_tutorial : public AuraScript
+{
+ PrepareAuraScript(spell_attention_exiles_reach_tutorial);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_DEBUG_LOOK_RIGHT });
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->CastSpell(GetTarget(), SPELL_DEBUG_LOOK_RIGHT, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_attention_exiles_reach_tutorial::OnRemove, EFFECT_0, SPELL_AURA_MOD_ROOT, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+enum WarmingUpData
+{
+ CONVERSATION_WARMING_UP_ACCEPT = 12818,
+ CONVERSATION_WARMING_UP_COMPLETE = 12798,
+};
+
+class BaseQuestWarmingUp : public QuestScript
+{
+public:
+ BaseQuestWarmingUp(const char* name) : QuestScript(name) { }
+
+ void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus)
+ {
+ if (newStatus == QUEST_STATUS_INCOMPLETE)
+ Conversation::CreateConversation(CONVERSATION_WARMING_UP_ACCEPT, player, *player, player->GetGUID(), nullptr);
+ else if (newStatus == QUEST_STATUS_COMPLETE)
+ Conversation::CreateConversation(CONVERSATION_WARMING_UP_COMPLETE, player, *player, player->GetGUID(), nullptr);
+ }
+};
+
+class q56775_warming_up : public BaseQuestWarmingUp
+{
+public:
+ q56775_warming_up() : BaseQuestWarmingUp("q56775_warming_up") { }
+
+ static constexpr float CLONE_ORIENTATION = 5.124503135681152343f;
+ static constexpr float CLONE_Z_OFFSET = 0.308f;
+
+ void OnQuestStatusChange(Player* player, Quest const* quest, QuestStatus oldStatus, QuestStatus newStatus) override
+ {
+ BaseQuestWarmingUp::OnQuestStatusChange(player, quest, oldStatus, newStatus);
+
+ if (newStatus == QUEST_STATUS_REWARDED)
+ {
+ Creature* garrickLowerDeck = FindCreatureIgnorePhase(player, "q56775_garrick_lower_deck", 5.0f);
+ Creature* garrickUpperDeck = FindCreatureIgnorePhase(player, "q56775_garrick_upper_deck", 75.0f);
+ if (!garrickLowerDeck || !garrickUpperDeck)
+ return;
+
+ Position pos(garrickLowerDeck->GetPositionX(), garrickLowerDeck->GetPositionY(), garrickLowerDeck->GetPositionZ() - CLONE_Z_OFFSET, CLONE_ORIENTATION);
+ garrickUpperDeck->SummonPersonalClone(pos, TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, player);
+ }
+ }
+};
+
+class q59926_warming_up : public BaseQuestWarmingUp
+{
+public:
+ q59926_warming_up() : BaseQuestWarmingUp("q59926_warming_up") { }
+
+ void OnQuestStatusChange(Player* player, Quest const* quest, QuestStatus oldStatus, QuestStatus newStatus) override
+ {
+ BaseQuestWarmingUp::OnQuestStatusChange(player, quest, oldStatus, newStatus);
+
+ if (newStatus == QUEST_STATUS_REWARDED)
+ {
+ Creature* grimaxeLowerDeck = FindCreatureIgnorePhase(player, "q59926_grimaxe_lower_deck", 5.0f);
+ Creature* grimaxeUpperDeck = FindCreatureIgnorePhase(player, "q59926_grimaxe_upper_deck", 75.0f);
+ if (!grimaxeLowerDeck || !grimaxeUpperDeck)
+ return;
+
+ grimaxeUpperDeck->SummonPersonalClone(*grimaxeLowerDeck, TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, player);
+ }
+ }
+};
+
+enum WarmingUpCaptainData
+{
+ NPC_WARLORD_BREKA_GRIMAXE2 = 166824,
+ NPC_WARLORD_BREKA_GRIMAXE3 = 166827,
+ NPC_CAPTAIN_GARRICK = 156280,
+
+ PATH_GARRICK_TO_COLE = 10501450,
+ PATH_GARRICK_TO_UPPER_DECK = 10501451,
+ PATH_GRIMAXE_TO_THROG = 10501900,
+ PATH_GRIMAXE_TO_UPPER_DECK = 10501901,
+
+ EVENT_SHIP_CAPTAIN1_SCRIPT1 = 1,
+ EVENT_SHIP_CAPTAIN1_SCRIPT2,
+ EVENT_SHIP_CAPTAIN1_SCRIPT3,
+
+ SAY_SPAR = 0,
+};
+
+// 156280 - Captain Garrick
+// 166824 - Warlord Breka Grimaxe
+struct npc_ship_captain_warming_up_private : public ScriptedAI
+{
+ npc_ship_captain_warming_up_private(Creature* creature) : ScriptedAI(creature), _pathToSparringPartner(0), _pathToUpperDeck(0) { }
+
+ void InitializeAI() override
+ {
+ me->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
+ }
+
+ void JustAppeared() override
+ {
+ if (me->GetEntry() == NPC_CAPTAIN_GARRICK)
+ {
+ _pathToSparringPartner = PATH_GARRICK_TO_COLE;
+ _pathToUpperDeck = PATH_GARRICK_TO_UPPER_DECK;
+ }
+ else if (me->GetEntry() == NPC_WARLORD_BREKA_GRIMAXE2)
+ {
+ _pathToSparringPartner = PATH_GRIMAXE_TO_THROG;
+ _pathToUpperDeck = PATH_GRIMAXE_TO_UPPER_DECK;
+ }
+
+ _events.ScheduleEvent(EVENT_SHIP_CAPTAIN1_SCRIPT1, 1s);
+ }
+
+ void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
+ {
+ if (pathId == _pathToSparringPartner)
+ _events.ScheduleEvent(EVENT_SHIP_CAPTAIN1_SCRIPT2, 0s);
+ else if (pathId == _pathToUpperDeck)
+ me->DespawnOrUnsummon();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHIP_CAPTAIN1_SCRIPT1:
+ Talk(SAY_SPAR);
+ me->GetMotionMaster()->MovePath(_pathToSparringPartner, false);
+ break;
+ case EVENT_SHIP_CAPTAIN1_SCRIPT2:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SALUTE);
+ _events.ScheduleEvent(EVENT_SHIP_CAPTAIN1_SCRIPT3, 3s);
+ break;
+ case EVENT_SHIP_CAPTAIN1_SCRIPT3:
+ me->GetMotionMaster()->MovePath(_pathToUpperDeck, false);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+private:
+ EventMap _events;
+ uint32 _pathToSparringPartner;
+ uint32 _pathToUpperDeck;
+};
+
+enum StandYourGroundData
+{
+ ACTOR_ID_ALLIANCE = 68598,
+ ACTOR_ID_HORDE = 75920,
+
+ CONVERSATION_PREFIGHT = 14422,
+ CONVERSATION_AGGRO = 14423,
+ CONVERSATION_JUMP = 14424,
+
+ EQUIPMENT_SWORD = 108493,
+ EQUIPMENT_AXE = 175161,
+
+ EVENT_MOVE_TO_A_POSITION = 1,
+ EVENT_PREFIGHT_CONVERSATION,
+ EVENT_JUMP_BEHIND,
+ EVENT_WALK_BACK,
+
+ PATH_ALLIANCE_SPARING_PARTNER = 10501460,
+ PATH_HORDE_SPARING_PARTNER = 10501870,
+
+ POSITION_SPARPOINT_ADVERTISMENT = 1,
+ POSITION_SPARPOINT_READY = 2,
+
+ TALK_SPARING_COMPLETE = 0,
+
+ NPC_ALLIANCE_SPARING_PARTNER = 157051,
+ NPC_HORDE_SPARING_PARTNER = 166814,
+ NPC_SPAR_POINT_ADVERTISMENT = 174971,
+ NPC_KILL_CREDIT = 155607,
+
+ SPELL_COMBAT_TRAINING_COMPLETE = 303120,
+ SPELL_JUMP_LEFT = 312757,
+ SPELL_JUMP_BEHIND = 312755,
+ SPELL_COMBAT_TRAINING = 323071,
+ SPELL_UPDATE_PHASE_SHIFT = 82238,
+};
+
+// 58209 - Stand Your Ground
+// 59927 - Stand Your Ground
+class quest_stand_your_ground : public QuestScript
+{
+public:
+ quest_stand_your_ground() : QuestScript("quest_stand_your_ground") { }
+
+ void OnQuestStatusChange(Player* player, Quest const* /*quest*/, QuestStatus /*oldStatus*/, QuestStatus newStatus) override
+ {
+ // Remove aura if player drops quest
+ if (newStatus == QUEST_STATUS_NONE)
+ player->CastSpell(player, SPELL_COMBAT_TRAINING_COMPLETE);
+ }
+};
+
+// 303065 - Summon Cole - Combat Training (DNT)
+// 325108 - Summon Throg - Combat Training (DNT)
+class spell_summon_sparring_partner : public SpellScript
+{
+ PrepareSpellScript(spell_summon_sparring_partner);
+
+ void SelectTarget(WorldObject*& target)
+ {
+ Player* caster = GetCaster()->ToPlayer();
+ if (!caster)
+ return;
+
+ Creature* partner = caster->FindNearestCreatureWithOptions(10.0f, FindCreatureOptions().SetIgnorePhases(true).SetStringId(caster->GetTeam() == ALLIANCE ? "q58209_cole" : "q59927_throg"));
+ if (!partner)
+ return;
+
+ target = partner;
+ }
+
+ void Register() override
+ {
+ OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_summon_sparring_partner::SelectTarget, EFFECT_0, TARGET_DEST_NEARBY_ENTRY_OR_DB);
+ }
+};
+
+// 157051 - Alliance Sparring Partner
+// 166814 - Horde Sparring Partner
+struct npc_sparring_partner_exiles_reach : public ScriptedAI
+{
+ npc_sparring_partner_exiles_reach(Creature* creature) : ScriptedAI(creature), _jumped(false), _actorIndex(0), _actorId(0), _path(0) { }
+
+ void JustAppeared() override
+ {
+ if (me->GetEntry() == NPC_ALLIANCE_SPARING_PARTNER)
+ {
+ SetEquipmentSlots(false, EQUIPMENT_SWORD, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
+ _path = PATH_ALLIANCE_SPARING_PARTNER;
+ _actorId = ACTOR_ID_ALLIANCE;
+ _actorIndex = 0;
+ }
+ else if (me->GetEntry() == NPC_HORDE_SPARING_PARTNER)
+ {
+ SetEquipmentSlots(false, EQUIPMENT_AXE, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
+ _path = PATH_HORDE_SPARING_PARTNER;
+ _actorId = ACTOR_ID_HORDE;
+ _actorIndex = 1;
+ }
+ me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC);
+ _events.ScheduleEvent(EVENT_MOVE_TO_A_POSITION, 1s);
+ }
+
+ void IsSummonedBy(WorldObject* summonerWO) override
+ {
+ Unit* summoner = summonerWO->ToUnit();
+
+ if (!summoner || !summoner->IsPlayer())
+ return;
+
+ _playerGUID = summoner->GetGUID();
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ if (!me->IsAlive())
+ return;
+
+ me->CombatStop(true);
+ EngagementOver();
+ me->ResetPlayerDamageReq();
+ _events.ScheduleEvent(EVENT_WALK_BACK, 1s);
+ }
+
+ void MovementInform(uint32 uiType, uint32 uiId) override
+ {
+ if (uiType != POINT_MOTION_TYPE)
+ return;
+
+ switch (uiId)
+ {
+ case POSITION_SPARPOINT_ADVERTISMENT:
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(POSITION_SPARPOINT_READY, me->GetFirstCollisionPosition(2.0f, (float)rand_norm() * static_cast<float>(2 * M_PI)));
+ break;
+ case POSITION_SPARPOINT_READY:
+ if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
+ me->SetFacingToObject(player);
+ me->RemoveUnitFlag(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_UNINTERACTIBLE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
+ {
+ if (pathId != _path)
+ return;
+
+ if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
+ {
+ me->DespawnOrUnsummon();
+ player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT);
+ player->CastSpell(player, SPELL_COMBAT_TRAINING_COMPLETE);
+ }
+ }
+
+ void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
+ {
+ if (me->GetHealth() <= damage)
+ {
+ damage = 0;
+ me->SetHealth(1);
+ DoStopAttack();
+ me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_UNINTERACTIBLE);
+ _events.CancelEvent(EVENT_JUMP_BEHIND);
+
+ if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
+ {
+ me->SetFacingToObject(player);
+ Talk(TALK_SPARING_COMPLETE, player);
+ player->CastSpell(player, SPELL_COMBAT_TRAINING);
+ player->KilledMonsterCredit(NPC_KILL_CREDIT);
+ }
+ }
+
+ if (me->HealthBelowPctDamaged(65, damage) && !_jumped)
+ {
+ _jumped = true;
+ DoCastVictim(SPELL_JUMP_LEFT, true);
+ StartPrivateConversation(CONVERSATION_JUMP);
+ _events.ScheduleEvent(EVENT_JUMP_BEHIND, 2s);
+ }
+ }
+
+ void JustEngagedWith(Unit* /*who*/) override
+ {
+ StartPrivateConversation(CONVERSATION_AGGRO);
+ }
+
+ void DamageDealt(Unit* target, uint32& damage, DamageEffectType /*damageType*/) override
+ {
+ if (target->GetHealthPct() < 95)
+ damage = 0;
+ }
+
+ void StartPrivateConversation(uint32 conversationId)
+ {
+ if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
+ {
+ Conversation* conversation = Conversation::CreateConversation(conversationId, player, *player, player->GetGUID(), nullptr, false);
+ conversation->AddActor(_actorId, _actorIndex, me->GetGUID());
+ conversation->Start();
+ }
+ }
+
+ Creature* GetRandomSparPoint()
+ {
+ std::list<Creature*> sparPoints;
+ GetCreatureListWithEntryInGrid(sparPoints, me, NPC_SPAR_POINT_ADVERTISMENT, 25.0f);
+ Trinity::Containers::RandomResize(sparPoints, 1);
+
+ if (sparPoints.empty()) // should never happen
+ return nullptr;
+
+ return sparPoints.front();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MOVE_TO_A_POSITION:
+ {
+ if (Creature* sparPoint = GetRandomSparPoint())
+ me->GetMotionMaster()->MovePoint(POSITION_SPARPOINT_ADVERTISMENT, sparPoint->GetPosition());
+
+ _events.ScheduleEvent(EVENT_PREFIGHT_CONVERSATION, 1s);
+ break;
+ }
+ case EVENT_PREFIGHT_CONVERSATION:
+ StartPrivateConversation(CONVERSATION_PREFIGHT);
+ break;
+ case EVENT_JUMP_BEHIND:
+ DoCastVictim(SPELL_JUMP_BEHIND, true);
+ break;
+ case EVENT_WALK_BACK:
+ me->GetMotionMaster()->Clear();
+ me->GetMotionMaster()->MovePath(_path, false);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!UpdateVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+private:
+ EventMap _events;
+ bool _jumped;
+ uint8 _actorIndex;
+ uint32 _actorId;
+ uint32 _path;
+ ObjectGuid _playerGUID;
+};
+
+enum FirstMateStandYourGroundData
+{
+ QUEST_STAND_YOUR_GROUND_ALLIANCE = 58209,
+ QUEST_STAND_YOUR_GROUND_HORDE = 59927,
+
+ SPELL_SUMMON_COLE = 303064,
+ SPELL_SUMMON_THROG = 325107,
+};
+
+// 160664 - Private Cole
+// 166583 - Grunt Throg
+struct npc_first_mate_stand_your_ground : public ScriptedAI
+{
+ npc_first_mate_stand_your_ground(Creature* creature) : ScriptedAI(creature) { }
+
+ void OnQuestAccept(Player* player, Quest const* quest) override
+ {
+ if (quest->GetQuestId() == QUEST_STAND_YOUR_GROUND_ALLIANCE)
+ {
+ player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT);
+ player->CastSpell(player, SPELL_SUMMON_COLE);
+ }
+ else if (quest->GetQuestId() == QUEST_STAND_YOUR_GROUND_HORDE)
+ {
+ player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT);
+ player->CastSpell(player, SPELL_SUMMON_THROG);
+ }
+ }
+};
+
+struct ActorData
+{
+ std::string_view StringId;
+ Position ActorPosition;
+};
+
+static std::vector<ActorData> const ActorDataMap[2] =
+{
+ // TEAM_ALLIANCE
+ {
+ { "q58208_garrick", { 35.5643f, -1.19837f, 12.1479f, 3.3272014f } },
+ { "q58208_richter", { -1.84858f, -8.38776f, 5.10018f, 1.5184366f } },
+ { "q58208_keela", { -15.3642f, 6.5793f, 5.5026f, 3.1415925f } },
+ { "q58208_bjorn", { 12.8406f, -8.49553f, 4.98031f, 4.8520155f } },
+ { "q58208_austin", { -4.48607f, 9.89729f, 5.07851f, 1.5184366f } },
+ { "q58208_cole", { -13.3396f, 0.702157f, 5.57996f, 0.087266445f } },
+ },
+ // TEAM_HORDE
+ {
+ { "q59928_grimaxe", { 25.5237f, 0.283005f, 26.5455f, 3.3526998f } },
+ { "q59928_throg", { -10.8399f, 11.9039f, 8.88028f, 6.2308254f } },
+ { "q59928_mithdran", { -24.4763f, -4.48273f, 9.13471f, 0.62831855f } },
+ { "q59928_lana", { -5.1971f, -15.0268f, 8.992f, 4.712389f } },
+ { "q59928_bo", { -22.1559f, 5.58041f, 9.09176f, 6.143559f } },
+ { "q59928_jinhake", { -31.9464f, 7.5772f, 10.6408f, 6.0737457f } },
+ }
+};
+
+static std::unordered_map<Races, std::string_view> const ActorPetData =
+{
+ { RACE_HUMAN, "q58208_wolf" },
+ { RACE_DWARF, "q58208_bear" },
+ { RACE_NIGHTELF, "q58208_tiger" },
+ { RACE_GNOME, "q58208_bunny" },
+ { RACE_DRAENEI, "q58208_moth" },
+ { RACE_WORGEN, "q58208_dog" },
+ { RACE_PANDAREN_ALLIANCE, "q58208_turtle" },
+ { RACE_ORC, "q59928_wolf" },
+ { RACE_UNDEAD_PLAYER, "q59928_bat" },
+ { RACE_TAUREN, "q59928_plainstrider" },
+ { RACE_TROLL, "q59928_raptor" },
+ { RACE_GOBLIN, "q59928_scorpion" },
+ { RACE_BLOODELF, "q59928_dragonhawk" },
+ { RACE_PANDAREN_HORDE, "q59928_turtle" }
+};
+
+enum BraceForImpactData
+{
+ QUEST_BRACE_FOR_IMPACT_ALLIANCE = 58208,
+ QUEST_BRACE_FOR_IMPACT_HORDE = 59928,
+};
+
+// 58208 - Brace For Impact
+// 59928 - Brace For Impact
+class quest_brace_for_impact : public QuestScript
+{
+public:
+ quest_brace_for_impact() : QuestScript("quest_brace_for_impact") { }
+
+ void OnQuestStatusChange(Player* player, Quest const* quest, QuestStatus /*oldStatus*/, QuestStatus newStatus) override
+ {
+ if (newStatus != QUEST_STATUS_COMPLETE)
+ return;
+
+ TeamId team = TEAM_NEUTRAL;
+ Position petSpawnPos;
+
+ if (quest->GetQuestId() == QUEST_BRACE_FOR_IMPACT_ALLIANCE)
+ {
+ team = TEAM_ALLIANCE;
+ petSpawnPos = { -1.4492f, 8.06887f, 5.10348f, 2.6005409f };
+ }
+ else if (quest->GetQuestId() == QUEST_BRACE_FOR_IMPACT_HORDE)
+ {
+ team = TEAM_HORDE;
+ petSpawnPos = { -22.8374f, -3.08287f, 9.12613f, 3.857178f };
+ }
+
+ if (team == TEAM_NEUTRAL)
+ return;
+
+ SpawnActors(player, team, petSpawnPos);
+ player->CastSpell(player, SPELL_UPDATE_PHASE_SHIFT);
+ }
+
+ void SpawnActors(Player* player, TeamId team, Position petSpawnPos)
+ {
+ for (ActorData const& actor : ActorDataMap[team])
+ SpawnActor(player, FindCreatureIgnorePhase(player, actor.StringId, 50.0f), actor.ActorPosition);
+
+ SpawnPet(player, petSpawnPos);
+ }
+
+ void SpawnPet(Player* player, Position const& position)
+ {
+ if (player->GetClass() != CLASS_HUNTER)
+ return;
+
+ if (std::string_view const* stringId = Trinity::Containers::MapGetValuePtr(ActorPetData, Races(player->GetRace())))
+ {
+ Creature* pet = FindCreatureIgnorePhase(player, *stringId, 25.0f);
+ if (!pet)
+ return;
+
+ SpawnActor(player, pet, position);
+ }
+ }
+
+ void SpawnActor(Player* player, Creature* creature, Position const& position)
+ {
+ TransportBase const* transport = player->GetDirectTransport();
+
+ if (!transport || !creature)
+ return;
+
+ float x, y, z, o;
+ position.GetPosition(x, y, z, o);
+ transport->CalculatePassengerPosition(x, y, z, &o);
+ creature->SummonPersonalClone({ x, y, z, o }, TEMPSUMMON_MANUAL_DESPAWN, 0s, 0, 0, player);
+ }
+};
+
+enum BraceForImpactCaptainData
+{
+ PATH_GARRICK_FROM_UPPER_DECK = 10505890,
+ PATH_GARRICK_TO_LOWER_DECK = 10505891,
+ PATH_GRIMAXE_FROM_UPPER_DECK = 10501910,
+ PATH_GRIMAXE_TO_LOWER_DECK = 10501911,
+
+ EVENT_SHIP_CAPTAIN2_SCRIPT1 = 1,
+ EVENT_SHIP_CAPTAIN2_SCRIPT2,
+
+ SAY_GET_TO_POSITIONS = 1,
+};
+
+// 156280 - Captain Garrick
+// 166827 - Warlord Breka Grimaxe
+struct npc_ship_captain_brace_for_impact_private : public ScriptedAI
+{
+ npc_ship_captain_brace_for_impact_private(Creature* creature) : ScriptedAI(creature), _pathPreTalk(0), _pathPostTalk(0), _waitTime(0s){ }
+
+ void JustAppeared() override
+ {
+ if (me->GetEntry() == NPC_CAPTAIN_GARRICK)
+ {
+ _pathPreTalk = PATH_GARRICK_FROM_UPPER_DECK;
+ _pathPostTalk = PATH_GARRICK_TO_LOWER_DECK;
+ _waitTime = 0s;
+ }
+ else if (me->GetEntry() == NPC_WARLORD_BREKA_GRIMAXE3)
+ {
+ _pathPreTalk = PATH_GRIMAXE_FROM_UPPER_DECK;
+ _pathPostTalk = PATH_GRIMAXE_TO_LOWER_DECK;
+ _waitTime = 1s;
+ }
+
+ me->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
+ me->GetMotionMaster()->MovePath(_pathPreTalk, false);
+ }
+
+ void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
+ {
+ if (pathId == _pathPreTalk)
+ _events.ScheduleEvent(EVENT_SHIP_CAPTAIN2_SCRIPT1, _waitTime);
+ else if (pathId == _pathPostTalk)
+ me->DespawnOrUnsummon();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHIP_CAPTAIN2_SCRIPT1:
+ Talk(SAY_GET_TO_POSITIONS);
+ _events.ScheduleEvent(EVENT_SHIP_CAPTAIN2_SCRIPT2, 3s);
+ break;
+ case EVENT_SHIP_CAPTAIN2_SCRIPT2:
+ me->GetMotionMaster()->MovePath(_pathPostTalk, false);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+private:
+ EventMap _events;
+ uint32 _pathPreTalk;
+ uint32 _pathPostTalk;
+ Seconds _waitTime;
+};
+
+enum BraceForImpactFirstMateData
+{
+ NPC_PRIVATE_COLE = 160664,
+ NPC_GRUNT_THROG = 166583,
+
+ PATH_COLE_BRACE_FOR_IMPACT = 10501461,
+ PATH_THROG_BRACE_FOR_IMPACT = 10501871,
+
+ EVENT_FIRST_MATE_1 = 1,
+ EVENT_FIRST_MATE_2,
+
+ SAY_STORM = 0,
+};
+
+// 160664 - Private Cole
+// 166583 - Grunt Throg
+struct npc_first_mate_brace_for_impact_private : public ScriptedAI
+{
+ npc_first_mate_brace_for_impact_private(Creature* creature) : ScriptedAI(creature), _path(0) { }
+
+ void JustAppeared() override
+ {
+ if (me->GetEntry() == NPC_PRIVATE_COLE)
+ _path = PATH_COLE_BRACE_FOR_IMPACT;
+ else if (me->GetEntry() == NPC_GRUNT_THROG)
+ _path = PATH_THROG_BRACE_FOR_IMPACT;
+
+ _events.ScheduleEvent(EVENT_FIRST_MATE_1, 3s);
+ }
+
+ void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
+ {
+ if (_path && pathId == _path)
+ me->DespawnOrUnsummon();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FIRST_MATE_1:
+ Talk(SAY_STORM);
+ _events.ScheduleEvent(EVENT_FIRST_MATE_2, 4s);
+ break;
+ case EVENT_FIRST_MATE_2:
+ me->GetMotionMaster()->MovePath(_path, false);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+private:
+ EventMap _events;
+ uint32 _path;
+};
+
+enum BraceForImpactCrewData
+{
+ NPC_QUARTERMASTER_RICHTER = 157042,
+ NPC_KEE_LA = 157043,
+ NPC_BJORN_STOUTHANDS = 157044,
+ NPC_AUSTIN_HUXWORTH = 157046,
+
+ NPC_BO = 166585,
+ NPC_MITHDRAN_DAWNTRACKER = 166590,
+ NPC_LANA_JORDAN = 166794,
+ NPC_PROVISONER_JIN_HAKE = 166799,
+
+ PATH_RICHTER_BRACE_FOR_IMPACT = 10501770,
+ PATH_KEE_LA_BRACE_FOR_IMPACT = 10501800,
+ PATH_BJORN_BRACE_FOR_IMPACT = 10501790,
+ PATH_AUSTIN_BRACE_FOR_IMPACT = 10501780,
+
+ PATH_BO_BRACE_FOR_IMPACT = 10502010,
+ PATH_MITHDRAN_BRACE_FOR_IMPACT = 10501990,
+ PATH_LANA_BRACE_FOR_IMPACT = 10501980,
+ PATH_JIN_HAKE_BRACE_FOR_IMPACT = 10502000,
+};
+
+// 157042 - Quartermaster Richter
+// 157043 - Kee-La
+// 157044 - Bjorn Stouthands
+// 157046 - Austin Huxworth
+// 166585 - Bo
+// 166590 - Mithdran Dawntracker
+// 166794 - Lana Jordan
+// 166799 - Provisoner Jin'hake
+struct npc_crew_ship_private : public ScriptedAI
+{
+ npc_crew_ship_private(Creature* creature) : ScriptedAI(creature), _path(0) { }
+
+ uint32 GetPathID()
+ {
+ switch (me->GetEntry())
+ {
+ case NPC_QUARTERMASTER_RICHTER: return PATH_RICHTER_BRACE_FOR_IMPACT;
+ case NPC_KEE_LA: return PATH_KEE_LA_BRACE_FOR_IMPACT;
+ case NPC_BJORN_STOUTHANDS: return PATH_BJORN_BRACE_FOR_IMPACT;
+ case NPC_AUSTIN_HUXWORTH: return PATH_AUSTIN_BRACE_FOR_IMPACT;
+ case NPC_BO: return PATH_BO_BRACE_FOR_IMPACT;
+ case NPC_MITHDRAN_DAWNTRACKER: return PATH_MITHDRAN_BRACE_FOR_IMPACT;
+ case NPC_LANA_JORDAN: return PATH_LANA_BRACE_FOR_IMPACT;
+ case NPC_PROVISONER_JIN_HAKE: return PATH_JIN_HAKE_BRACE_FOR_IMPACT;
+ default: return 0;
+ }
+ }
+
+ void JustAppeared() override
+ {
+ _path = GetPathID();
+ _scheduler.Schedule(Seconds(7), [this](TaskContext)
+ {
+ me->GetMotionMaster()->MovePath(_path, false);
+ });
+ }
+
+ void WaypointPathEnded(uint32 /*nodeId*/, uint32 pathId) override
+ {
+ if (_path && pathId == _path)
+ me->DespawnOrUnsummon();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _scheduler.Update(diff);
+ }
+
+private:
+ TaskScheduler _scheduler;
+ uint32 _path;
+};
+
+enum BraceForImpactPetData
+{
+ EVENT_PET_SHIP_RUN_TO_POSITION = 1,
+
+ MAP_ALLIANCE_SHIP = 2261,
+ MAP_HORDE_SHIP = 2369,
+
+ PATH_PET_ALLIANCE_SHIP = 10501510,
+ PATH_PET_HORDE_SHIP = 10502020
+};
+
+// 167337 - Mechanical Bunny
+// 167342 - Moth
+// 167343 - Dragonhawk
+// 167344 - Scorpion
+// 167345 - Wolf
+// 167346 - Wolf
+// 167347 - Tiger
+// 167348 - Turtle
+// 167349 - Plainstrider
+// 167350 - Raptor
+// 167351 - Bat
+// 167352 - Dog
+// 167375 - Bear
+struct npc_pet_ship_private : public ScriptedAI
+{
+ npc_pet_ship_private(Creature* creature) : ScriptedAI(creature), _path(0) { }
+
+ void JustAppeared() override
+ {
+ if (!me->GetTransport())
+ return;
+
+ int32 transportMap = me->GetTransport()->GetMapIdForSpawning();
+ if (transportMap == MAP_ALLIANCE_SHIP)
+ _path = PATH_PET_ALLIANCE_SHIP;
+ else if (transportMap == MAP_HORDE_SHIP)
+ _path = PATH_PET_HORDE_SHIP;
+
+ if (_path)
+ _events.ScheduleEvent(EVENT_PET_SHIP_RUN_TO_POSITION, 8s);
+ }
+
+ void WaypointPathEnded(uint32 /*nodeId*/, uint32 /*pathId*/) override
+ {
+ me->DespawnOrUnsummon();
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ if (eventId == EVENT_PET_SHIP_RUN_TO_POSITION)
+ me->GetMotionMaster()->MovePath(_path, false);
+ }
+ }
+
+private:
+ EventMap _events;
+ uint32 _path;
+};
+
+enum ExilesReachShipCrashData
+{
+ MOVIE_ALLIANCE_SHIP_CRASH = 895,
+ MOVIE_HORDE_SHIP_CRASH = 931,
+
+ SPELL_ALLIANCE_SHIP_CRASH = 305446,
+ SPELL_HORDE_SHIP_CRASH = 325133,
+ SPELL_BEGIN_TUTORIAL = 295600,
+};
+
+class player_exiles_reach_ship_crash : public PlayerScript
+{
+public:
+ player_exiles_reach_ship_crash() : PlayerScript("player_exiles_reach_ship_crash") { }
+
+ void OnMovieComplete(Player* player, uint32 movieId) override
+ {
+ switch (movieId)
+ {
+ case MOVIE_ALLIANCE_SHIP_CRASH:
+ player->CastSpell(player, SPELL_ALLIANCE_SHIP_CRASH, true);
+ break;
+ case MOVIE_HORDE_SHIP_CRASH:
+ player->CastSpell(player, SPELL_HORDE_SHIP_CRASH, true);
+ break;
+ default:
+ break;
+ }
+ }
+};
+
+class scene_alliance_and_horde_ship : public SceneScript
+{
+public:
+ scene_alliance_and_horde_ship() : SceneScript("scene_alliance_and_horde_ship") { }
+
+ void StartConvo(Player* player)
+ {
+ // This script is used to send conversation to Captian Garrick and Warlord Grimaxe on movement after entering ship
+ player->CastSpell(player, SPELL_BEGIN_TUTORIAL, true);
+ }
+
+ void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
+ {
+ StartConvo(player);
+ }
+
+ void OnSceneCancel(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
+ {
+ StartConvo(player);
+ }
+};
+
+// ***************************************************************
+// * Scripting in this section occurs after teleporting to beach *
+// ***************************************************************
+
+enum KnockedDownExilesReachData
+{
+ SPELL_KNOCKED_DOWN_STUN2 = 344889
+};
+
+// 305445 - Knocked Down!
+class spell_knocked_down_exiles_reach_beach : public AuraScript
+{
+ PrepareAuraScript(spell_knocked_down_exiles_reach_beach);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_KNOCKED_DOWN_STUN2 });
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ GetTarget()->CastSpell(nullptr, SPELL_KNOCKED_DOWN_STUN2, true);
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_knocked_down_exiles_reach_beach::OnRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
+ }
+};
+
+enum ExilesReachShipCrashBeachData
+{
+ SPELL_KNOCKED_DOWN = 305445,
+ SPELL_CRASHED_LANDED_ALLIANCE = 305464,
+ SPELL_CRASHED_LANDED_HORDE = 325136
+};
+
+// Script scene for washed up on beach to cast spells Alliance and Horde
+class scene_alliance_and_horde_crash : public SceneScript
+{
+public:
+ scene_alliance_and_horde_crash() : SceneScript("scene_alliance_and_horde_crash") { }
+
+ void OnSceneTriggerEvent(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/, std::string const& triggerName) override
+ {
+ if (triggerName == "Begin Knockdown Aura")
+ player->CastSpell(player, SPELL_KNOCKED_DOWN, true);
+ }
+
+ void OnSceneComplete(Player* player, uint32 /*sceneInstanceID*/, SceneTemplate const* /*sceneTemplate*/) override
+ {
+ player->CastSpell(player, player->GetTeam() == ALLIANCE ? SPELL_CRASHED_LANDED_ALLIANCE : SPELL_CRASHED_LANDED_HORDE, true);
+ }
+};
+
+CreatureAI* CaptainGarrickShipAISelector(Creature* creature)
+{
+ if (creature->IsPrivateObject())
+ {
+ if (Player* privateObjectOwner = ObjectAccessor::GetPlayer(*creature, creature->GetPrivateObjectOwner()))
+ {
+ if ((privateObjectOwner->GetTeam() == ALLIANCE && privateObjectOwner->GetQuestStatus(QUEST_BRACE_FOR_IMPACT_ALLIANCE) == QUEST_STATUS_NONE))
+ return new npc_ship_captain_warming_up_private(creature);
+ else
+ return new npc_ship_captain_brace_for_impact_private(creature);
+ }
+ }
+
+ return new NullCreatureAI(creature);
+};
+
+void AddSC_zone_exiles_reach()
+{
+ // Ship
+ RegisterSpellScript(spell_attention_exiles_reach_tutorial);
+ new q59926_warming_up();
+ new q56775_warming_up();
+ new quest_stand_your_ground();
+ RegisterCreatureAI(npc_sparring_partner_exiles_reach);
+ RegisterSpellScript(spell_summon_sparring_partner);
+ new FactoryCreatureScript<CreatureAI, &CaptainGarrickShipAISelector>("npc_captain_garrick_ship");
+ RegisterPrivatePublicCreatureAIPair("npc_warlord_grimaxe_lower_ship", npc_ship_captain_warming_up_private, NullCreatureAI);
+ RegisterPrivatePublicCreatureAIPair("npc_warlord_grimaxe_upper_ship", npc_ship_captain_brace_for_impact_private, NullCreatureAI);
+ RegisterPrivatePublicCreatureAIPair("npc_cole_ship", npc_first_mate_brace_for_impact_private, npc_first_mate_stand_your_ground);
+ RegisterPrivatePublicCreatureAIPair("npc_throg_ship", npc_first_mate_brace_for_impact_private, npc_first_mate_stand_your_ground);
+ RegisterPrivatePublicCreatureAIPair("npc_crew_ship", npc_crew_ship_private, NullCreatureAI);
+ RegisterPrivatePublicCreatureAIPair("npc_pet_ship", npc_pet_ship_private, NullCreatureAI);
+ new quest_brace_for_impact();
+
+ new player_exiles_reach_ship_crash();
+ new scene_alliance_and_horde_ship();
+
+ // Beach
+ RegisterSpellScript(spell_knocked_down_exiles_reach_beach);
+ new scene_alliance_and_horde_crash();
+}