diff --git a/.travis.yml b/.travis.yml index 6e473dabf8..b10509e242 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,14 +10,18 @@ git: addons: apt: + sources: + - ubuntu-toolchain-r-test + - sourceline: 'ppa:kzemek/boost' packages: - - libboost1.55-dev - - libboost-filesystem1.55-dev - - libboost-iostreams1.55-dev - - libboost-program-options1.55-dev - - libboost-regex1.55-dev - - libboost-system1.55-dev - - libboost-thread1.55-dev + - g++-6 + - libboost1.58-dev + - libboost-filesystem1.58-dev + - libboost-iostreams1.58-dev + - libboost-program-options1.58-dev + - libboost-regex1.58-dev + - libboost-system1.58-dev + - libboost-thread1.58-dev - libssl-dev - libmysqlclient-dev - libreadline6-dev diff --git a/README.md b/README.md index 6f0b978cdd..a97d007689 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,12 @@ website at [TrinityCore.org](https://www.trinitycore.org). + Platform: Linux, Windows or Mac + Processor with SSE2 support -+ Boost ≥ 1.55 (Linux) 1.63 (Windows) ++ Boost ≥ 1.58 (Linux) 1.63 (Windows) + MySQL ≥ 5.1.0 -+ CMake ≥ 3.0.2 (Linux) 3.3.2 (Windows) ++ CMake ≥ 3.2.0 (Linux) 3.3.2 (Windows) + OpenSSL = 1.0.x -+ GCC ≥ 4.9.2 (Linux only) (clang 3.5 heavy recommended) -+ MS Visual Studio ≥ 14 (2015) (Windows only) ++ GCC ≥ 6.3.0 (Linux only) (clang 3.5 heavy recommended) ++ MS Visual Studio ≥ 15 (2017) (Windows only) + zlib ≥ 1.2.7 + ZeroMQ: + apt-get install libzmq-dev (Linux only) diff --git a/cmake/compiler/clang/settings.cmake b/cmake/compiler/clang/settings.cmake index 1cd95bbf70..b826c1dba3 100644 --- a/cmake/compiler/clang/settings.cmake +++ b/cmake/compiler/clang/settings.cmake @@ -16,7 +16,7 @@ endif() # -Wno-narrowing needed to suppress a warning in g3d # -Wno-deprecated-register is needed to suppress 185 gsoap warnings on Unix systems. -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-narrowing -Wno-deprecated-register") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wno-narrowing -Wno-deprecated-register") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1") if (BUILD_SHARED_LIBS) diff --git a/cmake/compiler/gcc/settings.cmake b/cmake/compiler/gcc/settings.cmake index a0c2b73747..52924ba066 100644 --- a/cmake/compiler/gcc/settings.cmake +++ b/cmake/compiler/gcc/settings.cmake @@ -1,14 +1,14 @@ # Set build-directive (used in core to tell which buildtype we used) add_definitions(-D_BUILD_DIRECTIVE='"${CMAKE_BUILD_TYPE}"') -set(GCC_EXPECTED_VERSION 4.9.0) +set(GCC_EXPECTED_VERSION 6.3.0) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS GCC_EXPECTED_VERSION) message(FATAL_ERROR "GCC: TrinityCore requires version ${GCC_EXPECTED_VERSION} to build but found ${CMAKE_CXX_COMPILER_VERSION}") endif() -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -message(STATUS "GCC: Enabled c++11 support") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") +message(STATUS "GCC: Enabled c++14 support") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") message(STATUS "GCC: Enabled C99 support") diff --git a/cmake/macros/FindOpenSSL.cmake b/cmake/macros/FindOpenSSL.cmake index d970ef02f6..2a691ee016 100644 --- a/cmake/macros/FindOpenSSL.cmake +++ b/cmake/macros/FindOpenSSL.cmake @@ -80,30 +80,37 @@ IF(WIN32 AND NOT CYGWIN) # libeay32MD.lib is identical to ../libeay32.lib, and # ssleay32MD.lib is identical to ../ssleay32.lib + # Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib + if( "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" ) + set(_OPENSSL_MSVC_ARCH_SUFFIX "64") + else() + set(_OPENSSL_MSVC_ARCH_SUFFIX "32") + endif() + FIND_LIBRARY(LIB_EAY_DEBUG NAMES - libeay32MDd libeay32 + libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}MDd libeay32MDd libeay32 PATHS ${OPENSSL_ROOT_DIR}/lib/VC ) FIND_LIBRARY(LIB_EAY_RELEASE NAMES - libeay32MD libeay32 + libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}MD libeay32MD libeay32 PATHS ${OPENSSL_ROOT_DIR}/lib/VC ) FIND_LIBRARY(SSL_EAY_DEBUG NAMES - ssleay32MDd ssleay32 ssl + libssl${_OPENSSL_MSVC_ARCH_SUFFIX}MDd ssleay32MDd ssleay32 ssl PATHS ${OPENSSL_ROOT_DIR}/lib/VC ) FIND_LIBRARY(SSL_EAY_RELEASE NAMES - ssleay32MD ssleay32 ssl + libssl${_OPENSSL_MSVC_ARCH_SUFFIX}MD ssleay32MD ssleay32 ssl PATHS ${OPENSSL_ROOT_DIR}/lib/VC ) diff --git a/dep/boost/CMakeLists.txt b/dep/boost/CMakeLists.txt index c5e5ab1711..b556caaaf8 100644 --- a/dep/boost/CMakeLists.txt +++ b/dep/boost/CMakeLists.txt @@ -38,7 +38,7 @@ if (WIN32) # On windows the requirements are higher according to the wiki. set(BOOST_REQUIRED_VERSION 1.59) else() - set(BOOST_REQUIRED_VERSION 1.55) + set(BOOST_REQUIRED_VERSION 1.56) endif() find_package(Boost ${BOOST_REQUIRED_VERSION} REQUIRED system filesystem thread program_options iostreams regex) diff --git a/revision_data.h.in.cmake b/revision_data.h.in.cmake index 99ad8bfe12..4f0288eee4 100644 --- a/revision_data.h.in.cmake +++ b/revision_data.h.in.cmake @@ -4,6 +4,8 @@ #define _DATE "@rev_date@" #define _BRANCH "@rev_branch@" #define _CMAKE_COMMAND R"(@CMAKE_COMMAND@)" + #define _CMAKE_VERSION R"(@CMAKE_VERSION@)" + #define _CMAKE_HOST_SYSTEM R"(@CMAKE_HOST_SYSTEM_NAME@ @CMAKE_HOST_SYSTEM_VERSION@)" #define _SOURCE_DIRECTORY R"(@CMAKE_SOURCE_DIR@)" #define _BUILD_DIRECTORY R"(@BUILDDIR@)" #define _MYSQL_EXECUTABLE R"(@MYSQL_EXECUTABLE@)" diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index 4b4bcc6f29..329d3557a3 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -975,6 +975,7 @@ INSERT INTO `rbac_linked_permissions` VALUES (196,843), (196,866), (196,867), +(196,872), (197,232), (197,236), (197,237), @@ -1868,7 +1869,8 @@ INSERT INTO `rbac_permissions` VALUES (863,'Command: group set maintank'), (864,'Command: group set mainassist'), (865,'Command: npc showloot'), -(867,'Command: reload quest_greeting_locale'); +(867,'Command: reload quest_greeting_locale'), +(872,'Command: server debug'); /*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */; UNLOCK TABLES; @@ -2001,7 +2003,8 @@ INSERT INTO `updates` VALUES ('2017_12_17_00_auth.sql','E2EC5999D5305FC12EA576D08EFB95D1660DCF4D','ARCHIVED','2017-12-17 01:40:04',0), ('2018_01_06_00_auth.sql','CD9B826B9D95697DC412DEF780E814FA3991D6CD','ARCHIVED','2018-01-06 01:40:04',0), ('2018_01_15_00_auth.sql','1C5C28490B27D86EBC14F6034AA4D34E66D5545D','ARCHIVED','2018-01-15 01:40:04',0), -('2018_02_16_00_auth.sql','1AAD2FC649CBE8093ECE5908EBBBB31EC326166A','ARCHIVED','2018-02-16 01:40:04',0); +('2018_02_16_00_auth.sql','1AAD2FC649CBE8093ECE5908EBBBB31EC326166A','ARCHIVED','2018-02-16 01:40:04',0), +('2018_03_06_00_auth_from_335_was_2018_03_06_00_auth.sql','3F8EA885898CE0F9D47043A832602D77','ARCHIVED','2018-02-16 01:40:04',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/base/dev/world_database.sql b/sql/base/dev/world_database.sql index 90f7c57950..3509515db5 100644 --- a/sql/base/dev/world_database.sql +++ b/sql/base/dev/world_database.sql @@ -3616,6 +3616,51 @@ CREATE TABLE `spelleffect_dbc` ( ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `terrain_phase_info` +-- + +DROP TABLE IF EXISTS `terrain_phase_info`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `terrain_phase_info` ( + `Id` int(10) unsigned NOT NULL, + `TerrainSwapMap` int(10) unsigned NOT NULL, + `Comment` varchar(255) DEFAULT NULL, + PRIMARY KEY (`Id`,`TerrainSwapMap`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `terrain_swap_defaults` +-- + +DROP TABLE IF EXISTS `terrain_swap_defaults`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `terrain_swap_defaults` ( + `MapId` int(10) unsigned NOT NULL, + `TerrainSwapMap` int(10) unsigned NOT NULL, + `Comment` varchar(255) DEFAULT NULL, + PRIMARY KEY (`MapId`,`TerrainSwapMap`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `terrain_worldmap` +-- + +DROP TABLE IF EXISTS `terrain_worldmap`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `terrain_worldmap` ( + `TerrainSwapMap` int(10) unsigned NOT NULL, + `WorldMapArea` int(10) unsigned NOT NULL, + `Comment` varchar(255) DEFAULT NULL, + PRIMARY KEY (`TerrainSwapMap`,`WorldMapArea`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `transports` -- diff --git a/sql/updates/auth/4.3.4/2018_03_06_00_auth_from_335_was_2018_03_06_00_auth.sql b/sql/updates/auth/4.3.4/2018_03_06_00_auth_from_335_was_2018_03_06_00_auth.sql new file mode 100644 index 0000000000..ddaf1d13f0 --- /dev/null +++ b/sql/updates/auth/4.3.4/2018_03_06_00_auth_from_335_was_2018_03_06_00_auth.sql @@ -0,0 +1,5 @@ +DELETE FROM `rbac_permissions` WHERE `id`=872; +INSERT INTO `rbac_permissions` (`id`, `name`) VALUES +(872, 'Command: server debug'); +INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES +(196, 872); diff --git a/sql/updates/world/4.3.4/2018_03_06_00_world_from_335_was_2018_03_06_00_world.sql b/sql/updates/world/4.3.4/2018_03_06_00_world_from_335_was_2018_03_06_00_world.sql new file mode 100644 index 0000000000..1df33e4bcf --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_06_00_world_from_335_was_2018_03_06_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_loot_template` SET `QuestRequired`=1 WHERE `Item` IN (24426,24427); diff --git a/sql/updates/world/4.3.4/2018_03_06_01_world_from_335_was_2018_03_06_01_world.sql b/sql/updates/world/4.3.4/2018_03_06_01_world_from_335_was_2018_03_06_01_world.sql new file mode 100644 index 0000000000..d37755f6d9 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_06_01_world_from_335_was_2018_03_06_01_world.sql @@ -0,0 +1,80 @@ +-- +-- Gnomeregan Evacuee +DELETE FROM `smart_scripts` WHERE `entryorguid`=7843 AND `source_type`=0 AND `id`=6; +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 +(7843,0,6,0,6,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Gnomeregan Evacuee - On Just Died - Say Line 0"); + +DELETE FROM `creature_text` WHERE `CreatureID`=7843; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(7843,0,0,"Aaaaahhh! So close to escaping.",12,7,100,0,0,0,3829,0,"Gnomeregan Evacuee"); + +-- Addled Leper +DELETE FROM `smart_scripts` WHERE `entryorguid`=6221 AND `source_type`=0 AND `id`=6; +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 +(6221,0,6,0,4,0,40,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Addled Leper - On Aggro - Say Line 0"); + +DELETE FROM `creature_text` WHERE `CreatureID`=6221; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(6221,0,0,"No gnome will be left behind.",12,7,100,0,0,0,2422,0,"Addled Leper"), +(6221,0,1,"The troggs...they never stop coming. Die trogg! Die!",12,7,100,0,0,0,2423,0,"Addled Leper"), +(6221,0,2,"This sickness clouds my vision, but I know you must be a trogg. Die foul invader!",12,7,100,0,0,0,2424,0,"Addled Leper"), +(6221,0,3,"A foul trogg if ever I saw one. Die!",12,7,100,0,0,0,2425,0,"Addled Leper"); + +-- Leprous Technician +DELETE FROM `smart_scripts` WHERE `entryorguid`=6222 AND `source_type`=0 AND `id`=5; +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 +(6222,0,5,0,4,0,20,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Leprous Technician - On Aggro - Say Line 1"); + +DELETE FROM `creature_text` WHERE `CreatureID`=6222 AND `GroupID`=1; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(6222,1,0,"No gnome will be left behind.",12,7,100,0,0,0,2422,0,"Leprous Technician"), +(6222,1,1,"The troggs...they never stop coming. Die trogg! Die!",12,7,100,0,0,0,2423,0,"Leprous Technician"), +(6222,1,2,"This sickness clouds my vision, but I know you must be a trogg. Die foul invader!",12,7,100,0,0,0,2424,0,"Leprous Technician"), +(6222,1,3,"A foul trogg if ever I saw one. Die!",12,7,100,0,0,0,2425,0,"Leprous Technician"); + +-- Leprous Defender +DELETE FROM `smart_scripts` WHERE `entryorguid`=6223 AND `source_type`=0 AND `id`=5; +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 +(6223,0,5,0,4,0,20,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Leprous Defender - On Aggro - Say Line 1"); + +DELETE FROM `creature_text` WHERE `CreatureID`=6223 AND `GroupID`=1; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(6223,1,0,"No gnome will be left behind.",12,7,100,0,0,0,2422,0,"Leprous Defender"), +(6223,1,1,"The troggs...they never stop coming. Die trogg! Die!",12,7,100,0,0,0,2423,0,"Leprous Defender"), +(6223,1,2,"This sickness clouds my vision, but I know you must be a trogg. Die foul invader!",12,7,100,0,0,0,2424,0,"Leprous Defender"), +(6223,1,3,"A foul trogg if ever I saw one. Die!",12,7,100,0,0,0,2425,0,"Leprous Defender"); + +-- Leprous Assistant +DELETE FROM `smart_scripts` WHERE `entryorguid`=7603 AND `source_type`=0 AND `id`=2; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `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 +(7603,0,2,0,4,0,20,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Leprous Assistant - On Aggro - Say Line 1"); + +DELETE FROM `creature_text` WHERE `CreatureID`=7603 AND `GroupID`=1; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(7603,1,0,"No gnome will be left behind.",12,7,100,0,0,0,2422,0,"Leprous Assistant"), +(7603,1,1,"The troggs...they never stop coming. Die trogg! Die!",12,7,100,0,0,0,2423,0,"Leprous Assistant"), +(7603,1,2,"This sickness clouds my vision, but I know you must be a trogg. Die foul invader!",12,7,100,0,0,0,2424,0,"Leprous Assistant"), +(7603,1,3,"A foul trogg if ever I saw one. Die!",12,7,100,0,0,0,2425,0,"Leprous Assistant"); + +-- Leprous Machinesmith +DELETE FROM `smart_scripts` WHERE `entryorguid`=6224 AND `source_type`=0 AND `id`=4; +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 +(6224,0,4,0,4,0,20,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Leprous Machinesmith - On Aggro - Say Line 1"); + +DELETE FROM `creature_text` WHERE `CreatureID`=6224 AND `GroupID`=1; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(6224,1,0,"No gnome will be left behind.",12,7,100,0,0,0,2422,0,"Leprous Machinesmith"), +(6224,1,1,"The troggs...they never stop coming. Die trogg! Die!",12,7,100,0,0,0,2423,0,"Leprous Machinesmith"), +(6224,1,2,"This sickness clouds my vision, but I know you must be a trogg. Die foul invader!",12,7,100,0,0,0,2424,0,"Leprous Machinesmith"), +(6224,1,3,"A foul trogg if ever I saw one. Die!",12,7,100,0,0,0,2425,0,"Leprous Machinesmith"); + +-- Dark Iron Agent +DELETE FROM `smart_scripts` WHERE `entryorguid`=6212 AND `source_type`=0 AND `id`=1; +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 +(6212,0,1,0,4,0,20,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Dark Iron Agent - On Aggro - Say Line 1"); + +DELETE FROM `creature_text` WHERE `CreatureID`=6212 AND `GroupID`=1; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(6212,1,0,"Never cross a Dark Iron, $C.",12,0,100,0,0,0,1934,0,"Dark Iron Agent"), +(6212,1,1,"Time to die, $C.",12,0,100,0,0,0,1935,0,"Dark Iron Agent"), +(6212,1,2,"Feel the power of the Dark Iron Dwarves!",12,0,100,0,0,0,1936,0,"Dark Iron Agent"); diff --git a/sql/updates/world/4.3.4/2018_03_06_02_world_from_335_was_2018_03_06_02_world_335.sql b/sql/updates/world/4.3.4/2018_03_06_02_world_from_335_was_2018_03_06_02_world_335.sql new file mode 100644 index 0000000000..39dcaadf24 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_06_02_world_from_335_was_2018_03_06_02_world_335.sql @@ -0,0 +1,351 @@ +/* +-- Quest "Escorting Erland" +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=435; + +-- Quest "Return to Quinn" +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=430; + +-- Quest "Ivar the Foul" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=425; + +-- Quest "Wand to Bethor" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=491; + +-- Quest "Supplying the Sepulcher" +DELETE FROM `quest_details` WHERE `ID`=6321; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(6321,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=6321; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=6321; + +-- Quest "Ride to the Undercity" +DELETE FROM `quest_details` WHERE `ID`=6323; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(6323,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=6323; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=6323; + +-- Quest "Michael Garrett" +DELETE FROM `quest_details` WHERE `ID`=6322; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(6322,1,0,0,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=6 WHERE `ID`=6322; + +-- Quest "Return to Podrig" +DELETE FROM `quest_details` WHERE `ID`=6324; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(6324,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=6324; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=6324; + +-- Quest "The Deathstalkers' Report" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=449; + +-- Quest "Speak with Renferrel" +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=3221; + +-- Quest "Delivery to Silverpine Forest" +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=445; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=445; + +-- Quest "Zinge's Delivery" +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=1359; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=1359; + +-- Quest "Sample for Helbrim" +DELETE FROM `quest_details` WHERE `ID`=1358; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(1358,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=1358; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=1358; + +-- Quest "The Dead Fields" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=437; + +-- Quest "Rot Hide Clues" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=439; + +-- Quest "Rot Hide Ichor" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=443; + +-- Quest "Rot Hide Origins" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=444; + +-- Quest "Thule Ravenclaw" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=446; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=446; + +-- Quest "Assault on Fenris Isle" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=442; + +-- Quest "The Engraved Ring" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=440; + +-- Quest "Raleigh and the Undercity" +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=441; +UPDATE `quest_offer_reward` SET `Emote1`=1, `Emote2`=1 WHERE `ID`=441; + +-- Quest "A Husband's Revenge" +DELETE FROM `quest_details` WHERE `ID`=530; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(530,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=530; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=530; + +-- Quest "Prove Your Worth" +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=421; + +-- Quest "Arugal's Folly" +DELETE FROM `quest_details` WHERE `ID`=422; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(422,1,1,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=1 WHERE `ID`=422; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=422; + +-- Quest "Arugal's Folly (Part 2)" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=423; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=423; + +-- Quest "Arugal's Folly (Part 3)" +DELETE FROM `quest_details` WHERE `ID`=424; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(424,1,1,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=424; + +-- Quest "Arugal's Folly (Part 4)" +DELETE FROM `quest_details` WHERE `ID`=99; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(99,1,1,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=99; +UPDATE `quest_offer_reward` SET `Emote1`=21 WHERE `ID`=99; + +-- Quest "Maps and Runes" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=478; + +-- Quest "Dalar's Analysis" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=481; + +-- Quest "Ambermill Investigations" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=479; + +-- Quest "The Weaver" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=480; + +-- Quest "A Recipe For Death" +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=66, `EmoteOnComplete`=66 WHERE `ID`=447; +UPDATE `quest_offer_reward` SET `Emote1`=273 WHERE `ID`=447; + +-- Quest "A Recipe For Death (Part 2)" +DELETE FROM `quest_details` WHERE `ID`=450; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(450,1,1,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=1, `EmoteOnComplete`=1 WHERE `ID`=450; +UPDATE `quest_offer_reward` SET `Emote1`=5 WHERE `ID`=450; + +-- Quest "A Recipe For Death (Part 3)" +DELETE FROM `quest_details` WHERE `ID`=451; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(451,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=451; + +-- Quest "Arugal Must Die" +DELETE FROM `quest_details` WHERE `ID`=1014; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(1014,1,1,5,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=1, `EmoteOnComplete`=1 WHERE `ID`=1014; +UPDATE `quest_offer_reward` SET `Emote1`=4 WHERE `ID`=1014; + +-- Quest "Journey to Hillsbrad Foothills" +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=493; +UPDATE `quest_offer_reward` SET `Emote1`=273 WHERE `ID`=493; + +-- Quest "Time To Strike" +DELETE FROM `quest_details` WHERE `ID`=494; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(494,5,1,0,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=6, `Emote2`=1 WHERE `ID`=494; + +-- Quest "Helcular's Revenge" +DELETE FROM `quest_details` WHERE `ID`=552; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(552,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=552; + +-- Quest "Helcular's Revenge (Part 2)" +DELETE FROM `quest_details` WHERE `ID`=553; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(553,1,0,0,0,0,0,0,0,0); + +-- Quest "Battle of Hillsbrad" +DELETE FROM `quest_details` WHERE `ID`=527; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(527,25,1,1,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=25 WHERE `ID`=527; + +-- Quest "Battle of Hillsbrad (Part 2)" +DELETE FROM `quest_details` WHERE `ID`=528; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(528,1,1,1,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=528; + +-- Quest "Battle of Hillsbrad (Part 3)" +DELETE FROM `quest_details` WHERE `ID`=529; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(529,1,1,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=529; +UPDATE `quest_offer_reward` SET `Emote1`=21 WHERE `ID`=529; + +-- Quest "Battle of Hillsbrad (Part 4)" +DELETE FROM `quest_details` WHERE `ID`=532; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(532,1,1,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=532; +UPDATE `quest_offer_reward` SET `Emote1`=21 WHERE `ID`=532; + +-- Quest "Battle of Hillsbrad (Part 5)" +DELETE FROM `quest_details` WHERE `ID`=539; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(539,1,1,1,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=21 WHERE `ID`=539; + +-- Quest "Battle of Hillsbrad (Part 6)" +DELETE FROM `quest_details` WHERE `ID`=541; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(541,6,5,1,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=21 WHERE `ID`=541; + +-- Quest "Battle of Hillsbrad (Part 7)" +DELETE FROM `quest_details` WHERE `ID`=14351; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(14351,1,66,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnComplete`=5 WHERE `ID`=14351; +UPDATE `quest_offer_reward` SET `Emote1`=6, `Emote2`=1, `Emote3`=1 WHERE `ID`=14351; + +-- Quest "Bracers of Binding" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=557; + +-- Quest "Frostmaw" +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=1136; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=1136; + +-- Quest "The Rescue" +DELETE FROM `quest_details` WHERE `ID`=498; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(498,1,1,1,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=6, `Emote2`=5, `Emote3`=1 WHERE `ID`=498; + +-- Quest "Infiltration" +DELETE FROM `quest_details` WHERE `ID`=533; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(533,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=533; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=533; + +-- Quest "Gol'dir" +DELETE FROM `quest_details` WHERE `ID`=503; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(503,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnComplete`=0 WHERE `ID`=503; +UPDATE `quest_offer_reward` SET `Emote1`=2, `Emote2`=1 WHERE `ID`=503; + +-- Quest "Blackmoore's Legacy" +DELETE FROM `quest_details` WHERE `ID`=506; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(506,1,1,1,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=5 WHERE `ID`=506; + +-- Quest "Lord Aliden Perenolde" +DELETE FROM `quest_details` WHERE `ID`=507; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(507,1,0,0,0,0,0,0,0,0); +UPDATE `quest_offer_reward` SET `Emote1`=20 WHERE `ID`=507; + +-- Quest "Taretha's Gift" +UPDATE `quest_request_items` SET `EmoteOnComplete`=6 WHERE `ID`=508; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=508; + +-- Quest "WANTED: Syndicate Personnel" +UPDATE `quest_offer_reward` SET `Emote1`=21 WHERE `ID`=549; + +-- Quest "WANTED: Baron Vardus" +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=566; +UPDATE `quest_offer_reward` SET `Emote1`=21 WHERE `ID`=566; + +-- Quest "Dangerous!" +UPDATE `quest_offer_reward` SET `Emote1`=21 WHERE `ID`=567; + +-- Quest "Souvenirs of Death" +DELETE FROM `quest_details` WHERE `ID`=546; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(546,1,1,6,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=546; +UPDATE `quest_offer_reward` SET `Emote1`=4 WHERE `ID`=546; + +-- Quest "Humbert's Sword" +DELETE FROM `quest_details` WHERE `ID`=547; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(547,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=547; +UPDATE `quest_offer_reward` SET `Emote1`=4 WHERE `ID`=547; + +-- Quest "Soothing Turtle Bisque" +DELETE FROM `quest_details` WHERE `ID`=7321; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(7321,6,1,1,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6 WHERE `ID`=7321; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=7321; + +-- Quest "Elixir of Suffering" +DELETE FROM `quest_details` WHERE `ID`=496; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(496,1,1,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=1 WHERE `ID`=496; +UPDATE `quest_offer_reward` SET `Emote1`=1 WHERE `ID`=496; + +-- Quest "Elixir of Suffering (Part 2)" +DELETE FROM `quest_details` WHERE `ID`=499; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(499,1,11,0,0,0,0,0,0,0); + +-- Quest "Elixir of Pain" +DELETE FROM `quest_details` WHERE `ID`=501; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(501,1,5,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=1 WHERE `ID`=501; +UPDATE `quest_offer_reward` SET `Emote1`=4 WHERE `ID`=501; + +-- Quest "Elixir of Pain (Part 2)" +DELETE FROM `quest_details` WHERE `ID`=502; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(502,5,1,11,0,0,0,0,0,0); + +-- Quest "Elixir of Agony" +DELETE FROM `quest_details` WHERE `ID`=509; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(509,1,1,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=6, `EmoteOnComplete`=6 WHERE `ID`=509; +UPDATE `quest_offer_reward` SET `Emote1`=1, `Emote2`=11 WHERE `ID`=509; + +-- Quest "Elixir of Agony (Part 2)" +DELETE FROM `quest_details` WHERE `ID`=513; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(513,1,0,0,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnComplete`=5 WHERE `ID`=513; +UPDATE `quest_offer_reward` SET `Emote1`=6, `Emote2`=1 WHERE `ID`=513; + +-- Quest "Elixir of Agony (Part 3)" +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=1 WHERE `ID`=515; +UPDATE `quest_offer_reward` SET `Emote1`=5 WHERE `ID`=515; + +-- Quest "Elixir of Agony (Part 4)" +DELETE FROM `quest_details` WHERE `ID`=517; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(517,1,1,11,0,0,0,0,0,0); +UPDATE `quest_request_items` SET `EmoteOnIncomplete`=1 WHERE `ID`=517; +UPDATE `quest_offer_reward` SET `Emote1`=5 WHERE `ID`=517; + +-- Quest "Elixir of Agony (Part 5)" +DELETE FROM `quest_details` WHERE `ID`=524; +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) VALUES +(524,1,1,11,0,0,0,0,0,0); +*/ diff --git a/sql/updates/world/4.3.4/2018_03_06_03_world_from_335_was_2018_03_06_03_world.sql b/sql/updates/world/4.3.4/2018_03_06_03_world_from_335_was_2018_03_06_03_world.sql new file mode 100644 index 0000000000..1552426bbc --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_06_03_world_from_335_was_2018_03_06_03_world.sql @@ -0,0 +1,94 @@ +-- Stormwind City Guard +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (6800,6801,6802,6803,6804) 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 +(6800,9,0,0,0,0,100,0,0,0,0,0,103,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted On"), +(6800,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6800,9,2,0,0,0,100,0,2000,2000,0,0,5,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Play Emote 'Wave'"), +(6800,9,3,0,0,0,100,0,4000,4000,0,0,66,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6800,9,4,0,0,0,100,0,0,0,0,0,103,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted Off"), +(6801,9,0,0,0,0,100,0,0,0,0,0,103,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted On"), +(6801,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6801,9,2,0,0,0,100,0,2000,2000,0,0,5,66,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Play Emote 'Salute'"), +(6801,9,3,0,0,0,100,0,4000,4000,0,0,66,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6801,9,4,0,0,0,100,0,0,0,0,0,103,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted Off"), +(6802,9,0,0,0,0,100,0,0,0,0,0,103,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted On"), +(6802,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6802,9,2,0,0,0,100,0,2000,2000,0,0,5,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Play Emote 'Bow'"), +(6802,9,3,0,0,0,100,0,4000,4000,0,0,66,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6802,9,4,0,0,0,100,0,0,0,0,0,103,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted Off"), +(6803,9,0,0,0,0,100,0,0,0,0,0,103,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted On"), +(6803,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6803,9,2,0,0,0,100,0,2000,2000,0,0,5,23,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Play Emote 'Flex'"), +(6803,9,3,0,0,0,100,0,4000,4000,0,0,66,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6803,9,4,0,0,0,100,0,0,0,0,0,103,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted Off"), +(6804,9,0,0,0,0,100,0,0,0,0,0,103,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted On"), +(6804,9,1,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,7,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6804,9,2,0,0,0,100,0,2000,2000,0,0,5,25,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Play Emote 'Point'"), +(6804,9,3,0,0,0,100,0,4000,4000,0,0,66,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Orientation"), +(6804,9,4,0,0,0,100,0,0,0,0,0,103,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Guard - On Script - Set Rooted Off"); + +-- Stormwind City Patroller +DELETE FROM `smart_scripts` WHERE `entryorguid`=1976 AND `source_type`=0 AND `id` IN (1,2,3,4,5,6,7,8,9,10,11); +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 +(1976,0,1,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Stormwind City Patroller - In Combat - Cast 'Shoot'"), +(1976,0,2,0,9,0,100,0,0,5,11000,14000,11,12169,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Patroller - Within 0-5 Range - Cast 'Shield Block'"), +(1976,0,3,0,0,0,100,0,5000,9000,8000,13000,11,12170,0,0,0,0,0,2,0,0,0,0,0,0,0,"Stormwind City Patroller - In Combat - Cast 'Revenge'"), +(1976,0,4,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Patroller - On Received Emote 'Wave' - Run Script"), +(1976,0,5,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Patroller - On Received Emote 'Salute' - Run Script"), +(1976,0,6,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Patroller - On Received Emote 'Kiss' - Run Script"), +(1976,0,7,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Patroller - On Received Emote 'Shy' - Run Script"), +(1976,0,8,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Patroller - On Received Emote 'Rude' - Run Script"), +(1976,0,9,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Patroller - On Received Emote 'Chicken' - Run Script"), +(1976,0,10,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind City Patroller - On Received Emote 'Bow' - Run Script"); + +-- Stormwind Royal Guard +DELETE FROM `smart_scripts` WHERE `entryorguid`=1756 AND `source_type`=0 AND `id` IN (1,2,3,4,5,6,7,8,9,10); +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 +(1756,0,1,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Stormwind Royal Guard - In Combat - Cast 'Shoot'"), +(1756,0,2,0,9,0,100,0,0,5,11000,14000,11,12169,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Royal Guard - Within 0-5 Range - Cast 'Shield Block'"), +(1756,0,3,0,0,0,100,0,5000,9000,8000,13000,11,12170,0,0,0,0,0,2,0,0,0,0,0,0,0,"Stormwind Royal Guard - In Combat - Cast 'Revenge'"), +(1756,0,4,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Royal Guard - On Received Emote 'Wave' - Run Script"), +(1756,0,5,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Royal Guard - On Received Emote 'Salute' - Run Script"), +(1756,0,6,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Royal Guard - On Received Emote 'Kiss' - Run Script"), +(1756,0,7,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Royal Guard - On Received Emote 'Shy' - Run Script"), +(1756,0,8,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Royal Guard - On Received Emote 'Rude' - Run Script"), +(1756,0,9,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Royal Guard - On Received Emote 'Chicken' - Run Script"), +(1756,0,10,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Royal Guard - On Received Emote 'Bow' - Run Script"); + +-- Orgrimmar Grunt +DELETE FROM `smart_scripts` WHERE `entryorguid`=3296 AND `source_type`=0 AND `id` IN (1,2,3,4,5,6,7,8,9,10,11); +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 +(3296,0,1,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Orgrimmar Grunt - In Combat - Cast 'Shoot'"), +(3296,0,2,0,0,0,100,0,5000,9000,8000,13000,11,40505,0,0,0,0,0,2,0,0,0,0,0,0,0,"Orgrimmar Grunt - In Combat - Cast 'Cleave'"), +(3296,0,3,0,2,0,100,1,0,30,0,0,11,8599,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - Between 0-30% Health - Cast 'Enrage' (No Repeat)"), +(3296,0,4,0,2,0,100,1,0,30,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - Between 0-30% Health - Say Line 0 (No Repeat)"), +(3296,0,5,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - On Received Emote 'Wave' - Run Script"), +(3296,0,6,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - On Received Emote 'Salute' - Run Script"), +(3296,0,7,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - On Received Emote 'Kiss' - Run Script"), +(3296,0,8,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - On Received Emote 'Shy' - Run Script"), +(3296,0,9,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - On Received Emote 'Rude' - Run Script"), +(3296,0,10,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - On Received Emote 'Chicken' - Run Script"), +(3296,0,11,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Orgrimmar Grunt - On Received Emote 'Bow' - Run Script"); + +DELETE FROM `creature_text` WHERE `CreatureID`=3296 AND `GroupID`=0; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(3296,0,0,"%s becomes enraged!",16,0,100,0,0,0,10677,0,"Orgrimmar Grunt"); + +-- Kor'kron Elite +DELETE FROM `smart_scripts` WHERE `entryorguid`=14304 AND `source_type`=0 AND `id` IN (1,2,3,4,5,6,7,8,9,10,11); +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 +(14304,0,1,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Elite - In Combat - Cast 'Shoot'"), +(14304,0,2,0,0,0,100,0,5000,9000,8000,13000,11,40505,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Elite - In Combat - Cast 'Cleave'"), +(14304,0,3,0,2,0,100,0,0,30,120000,120000,11,8599,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - Between 0-30% Health - Cast 'Enrage'"), +(14304,0,4,0,2,0,100,1,0,30,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - Between 0-30% Health - Say Line 1 (No Repeat)"), +(14304,0,5,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - On Received Emote 'Wave' - Run Script"), +(14304,0,6,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - On Received Emote 'Salute' - Run Script"), +(14304,0,7,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - On Received Emote 'Kiss' - Run Script"), +(14304,0,8,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - On Received Emote 'Shy' - Run Script"), +(14304,0,9,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - On Received Emote 'Rude' - Run Script"), +(14304,0,10,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - On Received Emote 'Chicken' - Run Script"), +(14304,0,11,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Elite - On Received Emote 'Bow' - Run Script"); + +DELETE FROM `creature_text` WHERE `CreatureID`=14304 AND `GroupID`=1; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(14304,1,0,"%s becomes enraged!",16,0,100,0,0,0,10677,0,"Kor'kron Elite"); diff --git a/sql/updates/world/4.3.4/2018_03_06_04_world_from_335_was_2018_03_06_04_world.sql b/sql/updates/world/4.3.4/2018_03_06_04_world_from_335_was_2018_03_06_04_world.sql new file mode 100644 index 0000000000..49a1cc25ff --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_06_04_world_from_335_was_2018_03_06_04_world.sql @@ -0,0 +1,122 @@ +-- Tarren Mill Deathguard +DELETE FROM `smart_scripts` WHERE `entryorguid`=2405 AND `source_type`=0 AND `id` IN (1,2,3,4,5,6,7,8,9,10); +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 +(2405,0,1,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Tarren Mill Deathguard - In Combat - Cast 'Shoot'"), +(2405,0,2,0,9,0,100,0,0,5,11000,14000,11,12169,0,0,0,0,0,1,0,0,0,0,0,0,0,"Tarren Mill Deathguard - Within 0-5 Range - Cast 'Shield Block'"), +(2405,0,3,0,0,0,100,0,5000,9000,8000,13000,11,12170,0,0,0,0,0,2,0,0,0,0,0,0,0,"Tarren Mill Deathguard - In Combat - Cast 'Revenge'"), +(2405,0,4,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Tarren Mill Deathguard - On Received Emote 'Wave' - Run Script"), +(2405,0,5,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Tarren Mill Deathguard - On Received Emote 'Salute' - Run Script"), +(2405,0,6,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Tarren Mill Deathguard - On Received Emote 'Kiss' - Run Script"), +(2405,0,7,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Tarren Mill Deathguard - On Received Emote 'Shy' - Run Script"), +(2405,0,8,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Tarren Mill Deathguard - On Received Emote 'Rude' - Run Script"), +(2405,0,9,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Tarren Mill Deathguard - On Received Emote 'Chicken' - Run Script"), +(2405,0,10,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Tarren Mill Deathguard - On Received Emote 'Bow' - Run Script"); + +UPDATE `creature_text` SET `Language`=33 WHERE `CreatureID`=2405; -- Fix language for Tarren Mill Deathguard's aggro text + +-- Hammerfall Guardian +DELETE FROM `smart_scripts` WHERE `entryorguid`=2621 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 +(2621,0,0,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Hammerfall Guardian - In Combat - Cast 'Shoot'"), +(2621,0,1,0,9,0,100,0,0,5,11000,14000,11,12169,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hammerfall Guardian - Within 0-5 Range - Cast 'Shield Block'"), +(2621,0,2,0,0,0,100,0,5000,9000,8000,13000,11,12170,0,0,0,0,0,2,0,0,0,0,0,0,0,"Hammerfall Guardian - In Combat - Cast 'Revenge'"), +(2621,0,3,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hammerfall Guardian - On Received Emote 'Wave' - Run Script"), +(2621,0,4,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hammerfall Guardian - On Received Emote 'Salute' - Run Script"), +(2621,0,5,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hammerfall Guardian - On Received Emote 'Kiss' - Run Script"), +(2621,0,6,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hammerfall Guardian - On Received Emote 'Shy' - Run Script"), +(2621,0,7,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hammerfall Guardian - On Received Emote 'Rude' - Run Script"), +(2621,0,8,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hammerfall Guardian - On Received Emote 'Chicken' - Run Script"), +(2621,0,9,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Hammerfall Guardian - On Received Emote 'Bow' - Run Script"); + +-- Skyguard Windcharger +DELETE FROM `smart_scripts` WHERE `entryorguid`=23257 AND `source_type`=0 AND `id`=1; +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 +(23257,0,1,0,9,0,100,0,0,20,12000,16000,11,12024,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skyguard Windcharger - Within 0-20 Range - Cast 'Net'"); + +-- Stormwind Marine +DELETE FROM `smart_scripts` WHERE `entryorguid`=20556 AND `source_type`=0 AND `id` IN (2,3,4,5,6,7,8,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 +(20556,0,2,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Stormwind Marine - In Combat - Cast 'Shoot'"), +(20556,0,3,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Marine - On Received Emote 'Wave' - Run Script"), +(20556,0,4,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Marine - On Received Emote 'Salute' - Run Script"), +(20556,0,5,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Marine - On Received Emote 'Kiss' - Run Script"), +(20556,0,6,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Marine - On Received Emote 'Shy' - Run Script"), +(20556,0,7,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Marine - On Received Emote 'Rude' - Run Script"), +(20556,0,8,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Marine - On Received Emote 'Chicken' - Run Script"), +(20556,0,9,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stormwind Marine - On Received Emote 'Bow' - Run Script"); + +UPDATE `creature_template` SET `npcflag`=0, `IconName`=NULL WHERE `entry`=20556; -- They don't give directions and don't have gossip text + +-- Deathguard Elite +DELETE FROM `smart_scripts` WHERE `entryorguid`=7980 AND `source_type`=0 AND `id` IN (1,2,3,4,5,6,7,8,9,10); +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 +(7980,0,1,0,25,0,100,0,0,0,0,0,11,18950,0,0,0,0,0,1,0,0,0,0,0,0,0,"Deathguard Elite - On Reset - Cast 'Invisibility and Stealth Detection'"), +(7980,0,2,0,0,0,100,0,5000,7000,7000,10000,11,14516,0,0,0,0,0,2,0,0,0,0,0,0,0,"Deathguard Elite - In Combat - Cast 'Strike'"), +(7980,0,3,0,9,0,100,0,0,5,12000,16000,11,9080,0,0,0,0,0,2,0,0,0,0,0,0,0,"Deathguard Elite - Within 0-5 Range - Cast 'Hamstring'"), +(7980,0,4,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Deathguard Elite - On Received Emote 'Wave' - Run Script"), +(7980,0,5,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Deathguard Elite - On Received Emote 'Salute' - Run Script"), +(7980,0,6,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Deathguard Elite - On Received Emote 'Kiss' - Run Script"), +(7980,0,7,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Deathguard Elite - On Received Emote 'Shy' - Run Script"), +(7980,0,8,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Deathguard Elite - On Received Emote 'Rude' - Run Script"), +(7980,0,9,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Deathguard Elite - On Received Emote 'Chicken' - Run Script"), +(7980,0,10,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Deathguard Elite - On Received Emote 'Bow' - Run Script"); + +-- Mounted Ironforge Mountaineer +DELETE FROM `smart_scripts` WHERE `entryorguid`=12996 AND `source_type`=0 AND `id` IN (2,3,4,5,6,7,8,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 +(12996,0,2,0,22,0,100,0,101,5000,5000,0,80,6800,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mounted Ironforge Mountaineer - On Received Emote 'Wave' - Run Script"), +(12996,0,3,0,22,0,100,0,78,5000,5000,0,80,6801,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mounted Ironforge Mountaineer - On Received Emote 'Salute' - Run Script"), +(12996,0,4,0,22,0,100,0,58,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mounted Ironforge Mountaineer - On Received Emote 'Kiss' - Run Script"), +(12996,0,5,0,22,0,100,0,84,5000,5000,0,80,6803,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mounted Ironforge Mountaineer - On Received Emote 'Shy' - Run Script"), +(12996,0,6,0,22,0,100,0,77,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mounted Ironforge Mountaineer - On Received Emote 'Rude' - Run Script"), +(12996,0,7,0,22,0,100,0,22,5000,5000,0,80,6804,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mounted Ironforge Mountaineer - On Received Emote 'Chicken' - Run Script"), +(12996,0,8,0,22,0,100,0,17,5000,5000,0,80,6802,0,0,0,0,0,1,0,0,0,0,0,0,0,"Mounted Ironforge Mountaineer - On Received Emote 'Bow' - Run Script"); + +UPDATE `creature_template` SET `gossip_menu_id`=2121 WHERE `entry`=12996; -- Add gossip text + +-- Scout Stronghand +DELETE FROM `smart_scripts` WHERE `entryorguid`=14375 AND `source_type`=0 AND `id` IN (1,2,3); +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 +(14375,0,1,0,9,0,100,0,0,30,8000,12000,11,14030,0,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Stronghand - Within 0-30 Range - Cast 'Hooked Net'"), +(14375,0,2,0,0,0,100,0,5000,7000,5000,9000,11,15572,0,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Stronghand - In Combat - Cast 'Sunder Armor'"), +(14375,0,3,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Stronghand - In Combat - Cast 'Shoot'"); + +-- Expedition Warden +DELETE FROM `smart_scripts` WHERE `entryorguid`=17855 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 +(17855,0,0,0,9,0,100,0,0,20,12000,16000,11,12024,0,0,0,0,0,2,0,0,0,0,0,0,0,"Expedition Warden - Within 0-20 Range - Cast 'Net'"), +(17855,0,1,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Expedition Warden - In Combat - Cast 'Shoot'"), +(17855,0,2,0,4,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Expedition Warden - On Aggro - Cast Say Line 0"); + +DELETE FROM `creature_text` WHERE `CreatureID`=17855; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(17855,0,0,"Taste blade, mongrel!",12,0,100,0,0,0,10950,0,"Expedition Warden"), +(17855,0,1,"Please tell me that you didn't just do what I think you just did. Please tell me that I'm not going to have to hurt you...",12,0,100,0,0,0,10951,0,"Expedition Warden"), +(17855,0,2,"As if we don't have enough problems, you go and create more!",12,0,100,0,0,0,10953,0,"Expedition Warden"), +(17855,0,3,"You dare spill blood on neutral ground? OUT! OUT, I SAY!",12,0,100,0,0,0,10948,0,"Expedition Warden"), +(17855,0,4,"We don't take kindly to miscreants, $r.",12,0,100,0,0,0,10949,0,"Expedition Warden"), +(17855,0,5,"Get a rope!",12,0,100,0,0,0,10952,0,"Expedition Warden"), +(17855,0,6,"Believe me when I tell you this: You're gonna wish you weren't born, sissy!",12,0,100,0,0,0,10954,0,"Expedition Warden"), +(17855,0,7,"Your actions shame us all, $c. I hurt inside as I beat you senseless.",12,0,100,0,0,0,10955,0,"Expedition Warden"); + +-- Scout Manslayer +DELETE FROM `smart_scripts` WHERE `entryorguid`=14376 AND `source_type`=0 AND `id` IN (1,2,3); +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 +(14376,0,1,0,9,0,100,0,0,30,8000,12000,11,14030,0,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Manslayer - Within 0-30 Range - Cast 'Hooked Net'"), +(14376,0,2,0,0,0,100,0,5000,7000,5000,9000,11,15572,0,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Manslayer - In Combat - Cast 'Sunder Armor'"), +(14376,0,3,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Manslayer - In Combat - Cast 'Shoot'"); + +-- Scout Tharr +DELETE FROM `smart_scripts` WHERE `entryorguid`=14377 AND `source_type`=0 AND `id` IN (1,2,3); +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 +(14377,0,1,0,9,0,100,0,0,30,8000,12000,11,14030,0,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Tharr - Within 0-30 Range - Cast 'Hooked Net'"), +(14377,0,2,0,0,0,100,0,5000,7000,5000,9000,11,15572,0,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Tharr - In Combat - Cast 'Sunder Armor'"), +(14377,0,3,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Scout Tharr - In Combat - Cast 'Shoot'"); + +-- Cenarion Hold Infantry +DELETE FROM `smart_scripts` WHERE `entryorguid`=15184 AND `source_type`=0 AND `id`=4; +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 +(15184,0,4,0,0,0,100,0,0,0,2000,4000,11,6660,64,0,0,0,0,2,0,0,0,0,0,0,0,"Cenarion Hold Infantry - In Combat - Cast 'Shoot'"); + +UPDATE `creature_template` SET `flags_extra`=32768 WHERE `entry` IN (1756); +UPDATE `creature_template` SET `faction`=105 WHERE `entry` IN (3084); diff --git a/sql/updates/world/4.3.4/2018_03_06_05_world_from_335_was_2018_03_06_05_world_335.sql b/sql/updates/world/4.3.4/2018_03_06_05_world_from_335_was_2018_03_06_05_world_335.sql new file mode 100644 index 0000000000..73c42760fe --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_06_05_world_from_335_was_2018_03_06_05_world_335.sql @@ -0,0 +1,104 @@ +/* +-- Quest "A Fine Mess" +-- Pooling for Kernobee +SET @GUID := 64977; +SET @POOL := 385; +DELETE FROM `creature` WHERE `guid` BETWEEN @GUID+0 AND @GUID+6; +INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(@GUID+0,7850,90,0,0,1,1,0,0,-637.053,101.836,-194.48,4.76023,7200,0,0,896,0,0,0,0,0,"",0), +(@GUID+1,7850,90,0,0,1,1,0,0,-577.696,28.5626,-197.735,4.76023,7200,0,0,896,0,0,0,0,0,"",0), +(@GUID+2,7850,90,0,0,1,1,0,0,-618.832,153.15,-199.654,6.25451,7200,0,0,896,0,0,0,0,0,"",0), +(@GUID+3,7850,90,0,0,1,1,0,0,-600.079,15.9729,-179.679,5.47311,7200,0,0,896,0,0,0,0,0,"",0), +(@GUID+4,7850,90,0,0,1,1,0,0,-540.499,21.528,-179.737,1.53634,7200,0,0,896,0,0,0,0,0,"",0), +(@GUID+5,7850,90,0,0,1,1,0,0,-533.081,34.7292,-199.0739,1.89563,7200,0,0,896,0,0,0,0,0,"",0), +(@GUID+6,7850,90,0,0,1,1,0,0,-621.389,51.785,-199.647,5.47311,7200,0,0,896,0,0,0,0,0,"",0); + +DELETE FROM `pool_template` WHERE `entry`=@POOL; +INSERT INTO `pool_template` (`entry`, `max_limit`, `description`) VALUES +(@POOL,1,"Kernobee"); + +DELETE FROM `pool_creature` WHERE `pool_entry`=@POOL; +INSERT INTO `pool_creature` (`guid`, `pool_entry`, `chance`, `description`) VALUES +(@GUID+0,@POOL,0,"Kernobee (7850) - Spawn 1"), +(@GUID+1,@POOL,0,"Kernobee (7850) - Spawn 2"), +(@GUID+2,@POOL,0,"Kernobee (7850) - Spawn 3"), +(@GUID+3,@POOL,0,"Kernobee (7850) - Spawn 4"), +(@GUID+4,@POOL,0,"Kernobee (7850) - Spawn 5"), +(@GUID+5,@POOL,0,"Kernobee (7850) - Spawn 6"), +(@GUID+6,@POOL,0,"Kernobee (7850) - Spawn 7"), +(30135,@POOL,0,"Kernobee (7850) - Spawn 8"); + +-- Texts +DELETE FROM `creature_text` WHERE `CreatureID` IN (7850,7897); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(7850,0,0,"I see the exit! Hurry, hurry!",12,0,100,5,0,0,3948,0,"Kernobee"), +(7850,1,0,"%s cheers!",16,0,100,4,0,0,3928,0,"Kernobee"), +(7850,2,0,"Thank you for rescuing me! Word of your deed will not go unnoticed.",12,0,100,0,0,0,3929,0,"Kernobee"), +(7850,3,0,"%s waves goodbye to everyone.",16,0,100,3,0,0,3930,0,"Kernobee"), +(7850,4,0,"Uh oh....",12,0,100,0,0,0,3953,0,"Kernobee"), +(7850,5,0,"Get me out of here!",12,0,100,5,0,0,3881,0,"Kernobee"), +(7897,0,0,"%s activates!",14,0,100,0,0,0,3926,0,"Alarm-a-bomb 2600"), +(7897,1,0,"Self-destruct sequence activated.",14,0,100,0,0,0,3927,0,"Alarm-a-bomb 2600"), +(7897,2,0,"Anti-escape countermeasures activated. Self-destruct in t-minus 20 seconds....",14,0,100,0,0,0,3949,0,"Alarm-a-bomb 2600"), +(7897,3,0,"Alarm-a-bomb unit 2600 has failed. Self-destruct override [ACTIVE]. Cooldown [ACTIVE].",14,0,100,0,0,0,3950,0,"Alarm-a-bomb 2600"); + +-- Kernobee +DELETE FROM `creature_addon` WHERE `guid`=30135; + +UPDATE `creature_template` SET `AIName`="SmartAI", `ScriptName`="" WHERE `entry`=7850; +DELETE FROM `smart_scripts` WHERE `entryorguid`=7850 AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=785000 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 +(7850,0,0,1,19,0,100,0,2904,0,0,0,29,2,180,0,0,0,0,7,0,0,0,0,0,0,0,"Kernobee - On Quest 'A Fine Mess' Taken - Start Follow Player"), +(7850,0,1,2,61,0,100,0,0,0,0,0,64,1,0,0,0,0,0,16,0,0,0,0,0,0,0,"Kernobee - On Quest 'A Fine Mess' Taken - Store Targetlist"), +(7850,0,2,3,61,0,100,0,0,0,0,0,91,7,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kernobee - On Quest 'A Fine Mess' Taken - Remove Flag Standstate 'Dead'"), +(7850,0,3,4,61,0,100,0,0,0,0,0,83,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kernobee - On Quest 'A Fine Mess' Taken - Remove Npc Flag Questgiver"), +(7850,0,4,5,61,0,100,0,0,0,0,0,19,768,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kernobee - On Quest 'A Fine Mess' Taken - Remove Unit Flag 'Immune To NPCs' & 'Immune To Players'"), +(7850,0,5,6,61,0,100,0,0,0,0,0,2,250,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kernobee - On Quest 'A Fine Mess' Taken - Set Faction 250"), +(7850,0,6,7,61,0,100,0,0,0,0,0,1,5,0,0,0,0,0,12,1,0,0,0,0,0,0,"Kernobee - On Quest 'A Fine Mess' Taken - Say Line 5"), +(7850,0,7,0,61,0,100,0,0,0,0,0,45,1,1,0,0,0,0,10,30134,7897,0,0,0,0,0,"Kernobee - On Quest 'A Fine Mess' Taken - Set Data to Alarm-a-bomb 2600"), +(7850,0,8,0,6,0,100,0,0,0,0,0,6,2904,0,0,0,0,0,12,1,0,0,0,0,0,0,"Kernobee - On Death - Fail Quest 'A Fine Mess'"), +(7850,0,9,0,11,0,100,0,0,0,0,0,90,7,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kernobee - On Respawn - Add Flag Standstate 'Dead'"), +(7850,0,10,11,38,0,100,1,1,1,0,0,1,0,0,0,0,0,0,12,1,0,0,0,0,0,0,"Kernobee - On Data Set - Say Line 0"), +(7850,0,11,12,61,0,100,0,0,0,0,0,29,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kernobee - On Data Set - Stop Follow"), +(7850,0,12,13,61,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,-337.215,-0.165544,-152.847,0,"Kernobee - On Data Set - Move to Position"), +(7850,0,13,0,61,0,100,0,0,0,0,0,80,785000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kernobee - On Data Set - Run Script"), +(785000,9,0,0,0,0,100,0,11000,11000,0,0,15,2904,0,0,0,0,0,12,1,0,0,0,0,0,0,"Kernobee - On Script - Quest Credit 'A Fine Mess'"), +(785000,9,1,0,0,0,100,0,0,0,0,0,45,3,3,0,0,0,0,19,7897,0,0,0,0,0,0,"Kernobee - On Script - Set Data to Alarm-a-bomb 2600"), +(785000,9,2,0,0,0,100,0,500,500,0,0,1,1,0,0,0,0,0,12,1,0,0,0,0,0,0,"Kernobee - On Script - Say Line 1"), +(785000,9,3,0,0,0,100,0,4000,4000,0,0,66,0,0,0,0,0,0,12,1,0,0,0,0,0,0,"Kernobee - On Script - Set Orientation"), +(785000,9,4,0,0,0,100,0,1000,1000,0,0,1,2,0,0,0,0,0,12,1,0,0,0,0,0,0,"Kernobee - On Script - Say Line 2"), +(785000,9,5,0,0,0,100,0,5000,5000,0,0,1,3,0,0,0,0,0,12,1,0,0,0,0,0,0,"Kernobee - On Script - Say Line 3"), +(785000,9,6,0,0,0,100,0,3000,3000,0,0,69,0,0,0,0,0,0,8,0,0,0,-297.319,-7.321,-152.849,0,"Kernobee - On Script - Move to Position"), +(785000,9,7,0,0,0,100,0,2000,2000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kernobee - On Script - Despawn"); + +-- Alarm-a-bomb 2600 +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=7897; +DELETE FROM `smart_scripts` WHERE `entryorguid`=7897 AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (789700,789701) 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 +(7897,0,0,0,38,0,100,0,1,1,0,0,80,789700,2,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Data Set - Run Script"), +(7897,0,1,0,38,0,100,1,1,1,0,0,29,2,270,0,0,0,0,19,7850,200,0,0,0,0,0,"Alarm-a-bomb 2600 - On Data Set - Start Follow Kernobee"), +(7897,0,2,0,38,1,100,1,2,2,0,0,45,1,1,0,0,0,0,19,7850,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Data Set - Set Data to Kernobee (Phase 1)"), +(7897,0,3,0,38,1,100,1,3,3,0,0,80,789701,2,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Data Set - Run Script (Phase 1)"), +(789700,9,0,0,0,0,100,0,0,0,0,0,22,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Set Event Phase 1"), +(789700,9,1,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Say Line 0"), +(789700,9,2,0,0,0,100,0,4000,4000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Say Line 1"), +(789700,9,3,0,0,0,100,0,276000,276000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Say Line 2"), +(789700,9,4,0,0,0,100,0,6000,6000,0,0,1,4,0,0,0,0,0,19,7850,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Say Line 4 (Kernobee)"), +(789700,9,5,0,0,0,100,0,14000,14000,0,0,11,9874,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Cast 'Self Destruct'"), +(789700,9,6,0,0,0,100,0,500,500,0,0,51,0,0,0,0,0,0,19,7850,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Kill Kernobee"), +(789700,9,7,0,0,0,100,0,0,0,0,0,37,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Kill Self"), +(789701,9,0,0,0,0,100,0,0,0,0,0,103,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Set Rooted On"), +(789701,9,1,0,0,0,100,0,0,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Say Line 3"), +(789701,9,2,0,0,0,100,0,12000,12000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Alarm-a-bomb 2600 - On Script - Despawn"); + +-- Areatrigger +DELETE FROM `areatrigger_scripts` WHERE `entry`=1105; +INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES +(1105,"SmartTrigger"); + +DELETE FROM `smart_scripts` WHERE `entryorguid`=1105 AND `source_type`=2; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `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 +(1105,2,0,0,46,0,100,0,1105,0,0,0,45,2,2,0,0,0,0,10,30134,7897,0,0,0,0,0,"Areatrigger - On Trigger - Set Data to Alarm-a-bomb 2600"); +*/ diff --git a/sql/updates/world/4.3.4/2018_03_06_06_world_from_335_was_2018_03_06_06_world.sql b/sql/updates/world/4.3.4/2018_03_06_06_world_from_335_was_2018_03_06_06_world.sql new file mode 100644 index 0000000000..24705a2970 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_06_06_world_from_335_was_2018_03_06_06_world.sql @@ -0,0 +1,3 @@ +DELETE FROM `command` WHERE `name`='server debug'; +INSERT INTO `command` (`name`, `permission`, `help`) VALUES +('server debug', 872, 'Syntax: .server debug\n\nShows detailed information about server setup, useful when reporting a bug'); diff --git a/sql/updates/world/4.3.4/2018_03_08_00_world.sql b/sql/updates/world/4.3.4/2018_03_08_00_world.sql new file mode 100644 index 0000000000..83f9ca2a58 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_08_00_world.sql @@ -0,0 +1,22 @@ +ALTER TABLE `creature` + ADD `phaseUseFlags` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `spawnMask`, + ADD `terrainSwapMap` int(11) NOT NULL DEFAULT '-1' AFTER `PhaseGroup`; + +ALTER TABLE `gameobject` + ADD `phaseUseFlags` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `spawnMask`, + ADD `terrainSwapMap` int(11) NOT NULL DEFAULT '-1' AFTER `PhaseGroup`; + +DROP TABLE `terrain_phase_info`; + +ALTER TABLE `transports` ADD `phaseUseFlags` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `name`; + +DELETE FROM `trinity_string` WHERE `entry` IN (101,178,179,180,181,182,183,184,185); +INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES +(101,'Map: %u (%s) Zone: %u (%s) Area: %u (%s)\nX: %f Y: %f Z: %f Orientation: %f'), +(178,'grid[%u,%u]cell[%u,%u] InstanceID: %u\n ZoneX: %f ZoneY: %f\nGroundZ: %f FloorZ: %f Have height data (Map: %u VMap: %u MMap: %u)'), +(179,'PhaseShift:\n* Flags %u, PersonalGuid: %s'), +(180,'* Phases: %s'), +(181,'* VisibleMapIds: %s'), +(182,'* UiWorldMapAreaSwaps: %s'), +(183,'Cosmetic'), +(184,'Personal'); diff --git a/sql/updates/world/4.3.4/2018_03_09_00_world.sql b/sql/updates/world/4.3.4/2018_03_09_00_world.sql new file mode 100644 index 0000000000..3df6776e09 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature` SET `modelid` = 0 WHERE `id` = 30169; diff --git a/sql/updates/world/4.3.4/2018_03_09_01_world_from_335_was_2018_03_07_00_world.sql b/sql/updates/world/4.3.4/2018_03_09_01_world_from_335_was_2018_03_07_00_world.sql new file mode 100644 index 0000000000..31f35f76c1 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_01_world_from_335_was_2018_03_07_00_world.sql @@ -0,0 +1,15 @@ +-- Veil Skith: Darkstone of Terokk +UPDATE `creature` SET `MovementType`=0, `spawndist`=0 WHERE `guid`=65930; +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN (22288); +DELETE FROM `disables` WHERE `sourceType`=0 AND `entry` IN (38729,38736); +UPDATE `conditions` SET `SourceGroup`=1 WHERE `SourceEntry` IN (38729) AND `SourceTypeOrReferenceId`=13 AND `ConditionValue2`=185191; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (38729) AND `ConditionValue2`=22288; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (38736) AND `ConditionValue1`=185191; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,4,38729,0,0, 31,0,3,22288,0,0,0,'',''), +(13,1,38736,0,0, 30,0,185191,15,0,0,0,'',''); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=22288; +DELETE FROM `smart_scripts` WHERE (`entryorguid`=22288 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 +(22288, 0, 0, 0, 8, 0, 100, 0, 38729, 0, 5000, 5000, 41, 0, 30, 0, 0, 0, 0, 20, 185191, 5, 0, 0, 0, 0, 0, "Terokk target - on spellhit - despawn gob"); diff --git a/sql/updates/world/4.3.4/2018_03_09_02_world_from_335_was_2018_03_08_00_world_335.sql b/sql/updates/world/4.3.4/2018_03_09_02_world_from_335_was_2018_03_08_00_world_335.sql new file mode 100644 index 0000000000..21e010a97b --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_02_world_from_335_was_2018_03_08_00_world_335.sql @@ -0,0 +1,26 @@ +/* +-- +DELETE FROM `conditions` WHERE `SourceEntry` IN (28806) AND `SourceTypeOrReferenceId`=13 AND `ConditionValue1`=5; +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=17066 WHERE `SourceEntry` IN (29172) AND `SourceTypeOrReferenceId`=13; +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=17066 WHERE `SourceEntry` IN (29531) AND `SourceTypeOrReferenceId`=13; +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=17066 WHERE `SourceEntry` IN (29831) AND `SourceTypeOrReferenceId`=13; + +DELETE FROM `conditions` WHERE `SourceEntry` IN (30098) AND `SourceTypeOrReferenceId`=17; +DELETE FROM `conditions` WHERE `SourceEntry` IN (30098) AND `SourceTypeOrReferenceId`=13; +INSERT INTO conditions (SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ErrorTextId, ScriptName, COMMENT) VALUES +(13, 2, 30098, 0, 0, 31, 0, 3, 17253, 0, 0, 0, 0, "", ""), +(13, 2, 30098, 0, 0, 29, 0, 17233, 20, 0, 1, 0, 0, "", ""), +(13, 1, 30098, 0, 0, 31, 0, 5, 182483, 0, 0, 0, 0, "", ""), +(13, 4, 30098, 0, 0, 31, 0, 5, 181653, 0, 0, 0, 0, "", ""); + +DELETE FROM `conditions` WHERE `SourceEntry` IN (17233) AND `SourceTypeOrReferenceId`=22; +INSERT INTO conditions (SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ErrorTextId, ScriptName, COMMENT) VALUES +(22, 1, 17233, 0, 0, 6, 0, 67, 0, 0, 1, 0, 0, "", ""); + +UPDATE `event_scripts` SET `datalong2`=55000 WHERE `id`=10561; +DELETE FROM `smart_scripts` WHERE `entryorguid`=17253 AND `source_type`=0 AND `id`=6; +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 +(17253, 0, 6, 0, 52, 0, 100, 0, 7, 17233, 0, 0, 32, 0, 0, 0, 0, 0, 0, 20, 182483, 20, 0, 0, 0, 0, 0, "Defile Uther's Tomb Trigger - On Text 7 Over - reset gob"); +UPDATE smart_scripts SET `target_o`=0.2935 WHERE `entryorguid`=17238 AND `source_type`=0 AND `id`=16; +UPDATE smart_scripts SET `target_type`=21, `target_param1`=50 WHERE `entryorguid`=1723801 AND `source_type`=9 AND `id`=1; +*/ diff --git a/sql/updates/world/4.3.4/2018_03_09_03_world_from_335_was_2018_03_08_01_world.sql b/sql/updates/world/4.3.4/2018_03_09_03_world_from_335_was_2018_03_08_01_world.sql new file mode 100644 index 0000000000..733c143e6e --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_03_world_from_335_was_2018_03_08_01_world.sql @@ -0,0 +1,7 @@ +-- +DELETE FROM `gameobject_template` WHERE `entry`=300077; +DELETE FROM `gameobject_template_addon` WHERE `entry`=300077; +UPDATE `gameobject` SET `id`=182140 WHERE `guid`=99918 AND `id`=300077; +UPDATE `gameobject` SET `id`=182141 WHERE `guid`=99919 AND `id`=300077; +UPDATE `gameobject` SET `id`=182142 WHERE `guid`=99920 AND `id`=300077; +UPDATE `gameobject` SET `id`=182143 WHERE `guid`=99921 AND `id`=300077; diff --git a/sql/updates/world/4.3.4/2018_03_09_04_world_from_335_was_2018_03_08_02_world.sql b/sql/updates/world/4.3.4/2018_03_09_04_world_from_335_was_2018_03_08_02_world.sql new file mode 100644 index 0000000000..0b6b72230f --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_04_world_from_335_was_2018_03_08_02_world.sql @@ -0,0 +1,85 @@ +-- +DELETE FROM `creature` WHERE id=18109; +UPDATE `conditions` SET `SourceGroup`=2 WHERE `SourceEntry` IN (31927) AND `SourceTypeOrReferenceId`=13; + +-- Windyreed Quest Credit (Hut 01) SAI +SET @ENTRY := 18142; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +SET @SPELL_LIVING_FIRE := 31927; -- Living Fire +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) 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 +(@ENTRY,0,0,0,8,0,100,0,@SPELL_LIVING_FIRE,0,20000,20000,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,"Windyreed Quest Credit - On Spellhit - Run Script"), +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,11,31928,0,0,0,0,0,1,0,0,0,0,0,0,0,"Windyreed Quest Credit - Script - cast Living Fire"), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,33,@ENTRY,0,0,0,0,0,7,0,0,0,0,0,0,0,"Windyreed Quest Credit - Script - credit kill"), +(@ENTRY*100,9,2,0,0,0,100,0,7000,7000,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1850.186401,6378.753906,49.132702,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1843.883911,6373.384277,46.005417,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,4,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1845.056030,6383.819336,56.662624,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,5,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1845.103638,6391.827148,53.700901,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,6,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1831.184937,6391.026855,45.671902,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,7,0,0,0,100,0,2000,2000,0,0,51,0,0,0,0,0,0,10,60165,17139,0,0,0,0,0,"Windyreed Quest Credit - Script - Kill Creature Inside Burning Hut"); + +-- Windyreed Quest Credit (Hut 02) SAI +SET @ENTRY := 18143; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +SET @SPELL_LIVING_FIRE := 31927; -- Living Fire +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) 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 +(@ENTRY,0,0,0,8,0,100,0,@SPELL_LIVING_FIRE,0,20000,20000,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,"Windyreed Quest Credit - On Spellhit - Run Script"), +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,11,31928,0,0,0,0,0,1,0,0,0,0,0,0,0,"Windyreed Quest Credit - Script - cast Living Fire"), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,33,@ENTRY,0,0,0,0,0,7,0,0,0,0,0,0,0,"Windyreed Quest Credit - Script - credit kill"), +(@ENTRY*100,9,2,0,0,0,100,0,7000,7000,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1915.344116,6350.488770,52.229897,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1907.135986,6353.901367,48.899532,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,4,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1911.698730,6354.161133,58.254566,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,5,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1926.308350,6360.901855,57.298611,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,6,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1921.458862,6367.373047,59.892593,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,7,0,0,0,100,0,2000,2000,0,0,51,0,0,0,0,0,0,10,60159,17139,0,0,0,0,0,"Windyreed Quest Credit - Script - Kill Creature Inside Burning Hut"); + +-- Windyreed Quest Credit (Hut 03) SAI +SET @ENTRY := 18144; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +SET @SPELL_LIVING_FIRE := 31927; -- Living Fire +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) 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 +(@ENTRY,0,0,0,8,0,100,0,@SPELL_LIVING_FIRE,0,20000,20000,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,"Windyreed Quest Credit - On Spellhit - Run Script"), +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,11,31928,0,0,0,0,0,1,0,0,0,0,0,0,0,"Windyreed Quest Credit - Script - cast Living Fire"), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,33,@ENTRY,0,0,0,0,0,7,0,0,0,0,0,0,0,"Windyreed Quest Credit - Script - credit kill"), +(@ENTRY*100,9,2,0,0,0,100,0,7000,7000,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1969.078369,6278.307129,56.866646,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1977.147461,6277.312988,59.912029,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,5,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1974.763306,6269.175781,51.401920,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,6,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1970.424805,6273.501953,61.741539,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,7,0,0,0,100,0,2000,2000,0,0,51,0,0,0,0,0,0,10,60157,17139,0,0,0,0,0,"Windyreed Quest Credit - Script - Kill Creature Inside Burning Hut"); + +-- Windyreed Quest Credit (Big Hut) SAI +SET @ENTRY := 18110; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +SET @SPELL_LIVING_FIRE := 31927; -- Living Fire +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@ENTRY*100) 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 +(@ENTRY,0,0,0,8,0,100,0,@SPELL_LIVING_FIRE,0,20000,20000,80,@ENTRY*100,0,0,0,0,0,1,0,0,0,0,0,0,0,"Windyreed Quest Credit - On Spellhit - Run Script"), +(@ENTRY*100,9,0,0,0,0,100,0,0,0,0,0,11,31928,0,0,0,0,0,1,0,0,0,0,0,0,0,"Windyreed Quest Credit - Script - cast Living Fire"), +(@ENTRY*100,9,1,0,0,0,100,0,0,0,0,0,33,@ENTRY,0,0,0,0,0,7,0,0,0,0,0,0,0,"Windyreed Quest Credit - Script - credit kill"), +(@ENTRY*100,9,2,0,0,0,100,0,7000,7000,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1816.939941,6283.669922,61.357101,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,3,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1816.94,6283.67,61.3571,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,4,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1819.71,6305.89,63.4012,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,5,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1819.55,6298.08,73.4331,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,6,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1801.45,6308.03,59.2728,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,7,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1808.88,6307.05,72.4877,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,8,0,0,0,100,0,0,0,0,0,50,182146,20,0,0,0,0,8,0,0,0,-1794.54,6300.6,71.2263,0,"Windyreed Quest Credit - Script - Summon Hut Fire (Large)"), +(@ENTRY*100,9,9,0,0,0,100,0,2000,2000,0,0,51,0,0,0,0,0,0,10,60166,17139,0,0,0,0,0,"Windyreed Quest Credit - Script - Kill Creatures Inside Burning Hut"), +(@ENTRY*100,9,10,0,0,0,100,0,0,0,0,0,51,0,0,0,0,0,0,10,60167,17139,0,0,0,0,0,"Windyreed Quest Credit - Script - Kill Creatures Inside Burning Hut"); + +SET @ENTRY := 18109; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@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,1,54,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Living Fire - just summoned - Say text"), +(@ENTRY,0,1,0,61,0,100,0,0,0,0,0,89,7,0,0,0,0,0,1,0,0,0,0,0,0,0,"Living Fire - just summoned - start random movement"), +(@ENTRY,0,2,0,1,0,100,1,20000,20000,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Living Fire - ooc - despawn"); + +DELETE FROM `creature_text` WHERE `CreatureID`=@ENTRY; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(@ENTRY,0,0,"Burn! Burn! Burn!",12,12,100,0,0,0,14778,0,"Living Fire"); diff --git a/sql/updates/world/4.3.4/2018_03_09_05_world_from_335_was_2018_03_08_03_world.sql b/sql/updates/world/4.3.4/2018_03_09_05_world_from_335_was_2018_03_08_03_world.sql new file mode 100644 index 0000000000..e3358c05e9 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_05_world_from_335_was_2018_03_08_03_world.sql @@ -0,0 +1,4 @@ +DELETE FROM `conditions` WHERE `SourceEntry` IN (34387) AND `SourceTypeOrReferenceId`=13; +INSERT INTO conditions (SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ErrorTextId, ScriptName, COMMENT) VALUES +(13, 2, 34387, 0, 0, 31, 0, 3, 19652, 0, 0, 0, 0, "", ""), +(13, 2, 34387, 0, 1, 31, 0, 3, 19717, 0, 0, 0, 0, "", ""); diff --git a/sql/updates/world/4.3.4/2018_03_09_06_world_from_335_was_2018_03_08_04_world.sql b/sql/updates/world/4.3.4/2018_03_09_06_world_from_335_was_2018_03_08_04_world.sql new file mode 100644 index 0000000000..d8f83f2222 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_06_world_from_335_was_2018_03_08_04_world.sql @@ -0,0 +1,18 @@ +-- +DELETE FROM `conditions` WHERE `SourceEntry` IN (36460) AND `SourceTypeOrReferenceId`=13; +INSERT INTO conditions (SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ErrorTextId, ScriptName, COMMENT) VALUES +(13, 4, 36460, 0, 0, 31, 0, 3, 21262, 0, 0, 0, 0, "", ""); + +SET @ENTRY := 21262; +UPDATE `creature_template` SET `AIName`='SmartAI', `flags_extra`=130 WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@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,1,8,0,100,0,36460,0,5000,5000,11,34815,0,0,0,0,0,1,0,0,0,0,0,0,0,"Equipement trigger - On Spellhit - Cast spell"), +(@ENTRY,0,1,2,61,0,100,0,0,0,0,0,41,0,0,0,0,0,0,20,183808,5,0,0,0,0,0,"Equipement trigger - On Spellhit - despawn gob"), +(@ENTRY,0,2,3,61,0,100,0,0,0,0,0,41,0,0,0,0,0,0,20,183807,5,0,0,0,0,0,"Equipement trigger - On Spellhit - despawn gob"), +(@ENTRY,0,3,4,61,0,100,0,0,0,0,0,41,0,0,0,0,0,0,20,183806,5,0,0,0,0,0,"Equipement trigger - On Spellhit - despawn gob"), +(@ENTRY,0,4,0,61,0,100,0,0,0,0,0,41,0,0,0,0,0,0,20,183805,5,0,0,0,0,0,"Equipement trigger - On Spellhit - despawn gob"); + +DELETE FROM `disables` WHERE `sourceType`=0 AND `entry` IN (36460); +INSERT INTO `disables`(`sourceType`,`entry`,`flags`,`comment`) VALUES +(0,36460,64,'Ignore LOS'); diff --git a/sql/updates/world/4.3.4/2018_03_09_07_world_from_335_was_2018_03_08_05_world.sql b/sql/updates/world/4.3.4/2018_03_09_07_world_from_335_was_2018_03_08_05_world.sql new file mode 100644 index 0000000000..bdca574f0a --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_07_world_from_335_was_2018_03_08_05_world.sql @@ -0,0 +1,14 @@ +-- +DELETE FROM `conditions` WHERE `SourceEntry` IN (38250) AND `SourceTypeOrReferenceId`=13; +INSERT INTO conditions (SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ErrorTextId, ScriptName, COMMENT) VALUES +(13, 1, 38250, 0, 0, 31, 0, 3, 22058, 0, 0, 0, 0, "", ""); + +SET @ENTRY := 22061; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (@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,25,0,100,0,0,0,0,0,11,38250,0,0,0,0,0,19,22058,0,0,0,0,0,0,"Shadowmoon Soulstealer - On reset - Cast spell"); + +UPDATE `creature_template_addon` SET `auras`='38376' WHERE `entry` IN (22058); +UPDATE `creature_template_addon` SET `emote`=468, `auras`='38442' WHERE `entry` IN (22081); +DELETE FROM `creature_addon` WHERE `guid` IN (77374, 77375, 77376, 77379, 77380, 77381, 77382, 77383, 77384, 77387, 77389, 77390, 77391, 77392, 77393, 77394); diff --git a/sql/updates/world/4.3.4/2018_03_09_08_world_from_335_was_2018_03_08_06_world.sql b/sql/updates/world/4.3.4/2018_03_09_08_world_from_335_was_2018_03_08_06_world.sql new file mode 100644 index 0000000000..480024a8e7 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_08_world_from_335_was_2018_03_08_06_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=22356 WHERE `SourceEntry` IN (38629) AND `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `ElseGroup`=0; diff --git a/sql/updates/world/4.3.4/2018_03_09_09_world_from_335_was_2018_03_08_07_world.sql b/sql/updates/world/4.3.4/2018_03_09_09_world_from_335_was_2018_03_08_07_world.sql new file mode 100644 index 0000000000..ce67a8f194 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_09_world_from_335_was_2018_03_08_07_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=22395 WHERE `SourceEntry` IN (39124) AND `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1; +UPDATE `creature` SET `position_x`=-4543.57177, `position_y`=1022.8920, `position_z`=9.817793, `orientation`=3.930219 WHERE `id`=21797; diff --git a/sql/updates/world/4.3.4/2018_03_09_10_world_from_335_was_2018_03_08_08_world.sql b/sql/updates/world/4.3.4/2018_03_09_10_world_from_335_was_2018_03_08_08_world.sql new file mode 100644 index 0000000000..2c651fe4b9 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_10_world_from_335_was_2018_03_08_08_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=23037 WHERE `SourceEntry` IN (39974) AND `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1; diff --git a/sql/updates/world/4.3.4/2018_03_09_11_world_from_335_was_2018_03_08_09_world.sql b/sql/updates/world/4.3.4/2018_03_09_11_world_from_335_was_2018_03_08_09_world.sql new file mode 100644 index 0000000000..2fe2522cb3 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_11_world_from_335_was_2018_03_08_09_world.sql @@ -0,0 +1,5 @@ +-- +DELETE FROM `creature` WHERE `guid`=64984; +INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(64984,23746,530,0,0,1,1,0,0,6718.222656, -7594.638672, 126.092712,0.413325,7200,0,0,0,0,0,0,0,0,"",0); +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=23746, `ConditionValue3`=64984 WHERE `SourceEntry` IN (42391) AND `SourceTypeOrReferenceId`=13; diff --git a/sql/updates/world/4.3.4/2018_03_09_12_world_from_335_was_2018_03_08_10_world.sql b/sql/updates/world/4.3.4/2018_03_09_12_world_from_335_was_2018_03_08_10_world.sql new file mode 100644 index 0000000000..a05484272e --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_12_world_from_335_was_2018_03_08_10_world.sql @@ -0,0 +1,5 @@ +-- +DELETE FROM `creature` WHERE `guid`=64985; +INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `ScriptName`, `VerifiedBuild`) VALUES +(64985,25114,530,0,0,1,1,0,0,12664.64160,-6986.25,15.608,1.622840,7200,0,0,0,0,0,0,0,0,"",0); +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=25114 WHERE `SourceEntry` IN (45149) AND `SourceTypeOrReferenceId`=13; \ No newline at end of file diff --git a/sql/updates/world/4.3.4/2018_03_09_13_world_from_335_was_2018_03_08_12_world.sql b/sql/updates/world/4.3.4/2018_03_09_13_world_from_335_was_2018_03_08_12_world.sql new file mode 100644 index 0000000000..1f4c7555b9 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_13_world_from_335_was_2018_03_08_12_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `conditions` SET `ConditionValue1`=4, `ConditionValue2`=0 WHERE `SourceEntry` IN (45368,45371) AND `SourceTypeOrReferenceId`=13; +UPDATE `conditions` SET `ConditionValue1`=3, `ConditionValue2`=17066 WHERE `SourceEntry` IN (46852,46896) AND `SourceTypeOrReferenceId`=13; diff --git a/sql/updates/world/4.3.4/2018_03_09_14_world_from_335_was_2018_03_08_13_world.sql b/sql/updates/world/4.3.4/2018_03_09_14_world_from_335_was_2018_03_08_13_world.sql new file mode 100644 index 0000000000..f4b1c66649 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_14_world_from_335_was_2018_03_08_13_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_addon` SET `bytes1`=33554432 WHERE `guid`= 128739; diff --git a/sql/updates/world/4.3.4/2018_03_09_15_world_from_335_was_2018_03_09_00_world.sql b/sql/updates/world/4.3.4/2018_03_09_15_world_from_335_was_2018_03_09_00_world.sql new file mode 100644 index 0000000000..254201d45d --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_15_world_from_335_was_2018_03_09_00_world.sql @@ -0,0 +1,15 @@ +-- +DELETE FROM `conditions` WHERE `SourceEntry` IN (50790,50791,50802,50803,50825,50826) AND `SourceTypeOrReferenceId`=13; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 50790, 0, 0, 31, 0, 3, 22515, 0, 0, 0, 0, "", ""), +(13, 1, 50791, 0, 0, 31, 0, 3, 22515, 0, 0, 0, 0, "", ""), +(13, 2, 50790, 0, 0, 31, 0, 5, 192163, 0, 0, 0, 0, "", ""), +(13, 2, 50791, 0, 0, 31, 0, 5, 192164, 0, 0, 0, 0, "", ""), +(13, 1, 50802, 0, 0, 31, 0, 3, 22515, 0, 0, 0, 0, "", ""), +(13, 1, 50803, 0, 0, 31, 0, 3, 22515, 0, 0, 0, 0, "", ""), +(13, 2, 50802, 0, 0, 31, 0, 5, 192163, 0, 0, 0, 0, "", ""), +(13, 2, 50803, 0, 0, 31, 0, 5, 192164, 0, 0, 0, 0, "", ""), +(13, 1, 50825, 0, 0, 31, 0, 3, 22515, 0, 0, 0, 0, "", ""), +(13, 1, 50826, 0, 0, 31, 0, 3, 22515, 0, 0, 0, 0, "", ""), +(13, 2, 50825, 0, 0, 31, 0, 5, 192163, 0, 0, 0, 0, "", ""), +(13, 2, 50826, 0, 0, 31, 0, 5, 192164, 0, 0, 0, 0, "", ""); diff --git a/sql/updates/world/4.3.4/2018_03_09_16_world_from_335_was_2018_03_09_01_world.sql b/sql/updates/world/4.3.4/2018_03_09_16_world_from_335_was_2018_03_09_01_world.sql new file mode 100644 index 0000000000..a572869089 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_16_world_from_335_was_2018_03_09_01_world.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `conditions` WHERE SourceEntry IN (44608) AND `SourceTypeOrReferenceId`=13; +UPDATE `conditions` SET `SourceGroup`=1 WHERE `SourceEntry` IN (44213,43986) AND `SourceTypeOrReferenceId`=13; diff --git a/sql/updates/world/4.3.4/2018_03_09_17_world_from_335_was_2018_03_09_02_world.sql b/sql/updates/world/4.3.4/2018_03_09_17_world_from_335_was_2018_03_09_02_world.sql new file mode 100644 index 0000000000..49a6e0d544 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_17_world_from_335_was_2018_03_09_02_world.sql @@ -0,0 +1,69 @@ +-- +-- Shadowlord Deathwail +UPDATE `creature_addon` SET `mount`=20684 WHERE `guid`=77084; -- Fix mount + +/* +DELETE FROM `creature_template_movement` WHERE `CreatureId`=22006; -- Fix inhabit type +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`) VALUES +(22006,1,1,2,0); +*/ + +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=22006; +DELETE FROM `smart_scripts` WHERE `entryorguid`=22006 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 +(22006,0,0,0,6,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Shadowlord Deathwail - On Just Died - Say Line 0"), +(22006,0,1,0,0,0,100,0,0,0,3000,5000,11,12471,64,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowlord Deathwail - In Combat - Cast 'Shadow Bolt'"), +(22006,0,2,0,0,0,100,0,5000,7000,15000,17000,11,15245,0,0,0,0,0,1,0,0,0,0,0,0,0,"Shadowlord Deathwail - In Combat - Cast 'Shadow Bolt Volley'"), +(22006,0,3,0,0,0,100,0,9000,12000,18000,24000,11,32709,0,0,0,0,0,5,0,0,0,0,0,0,0,"Shadowlord Deathwail - In Combat - Cast 'Death Coil'"), +(22006,0,4,0,0,0,100,0,14000,17000,22000,28000,11,27641,0,0,0,0,0,5,0,0,0,0,0,0,0,"Shadowlord Deathwail - In Combat - Cast 'Fear'"); + +DELETE FROM `creature_text` WHERE `CreatureID`=22006; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(22006,0,0,"Master... I've failed you...",14,0,100,0,0,0,19820,0,"Shadowlord Deathwail"); + +-- Shadowmoon Soulstealer +DELETE FROM `smart_scripts` WHERE `entryorguid`=22061 AND `source_type`=0 AND `id` IN (1,2); +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `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 +(22061,0,1,0,25,0,100,0,0,0,0,0,8,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Shadowmoon Soulstealer - On Reset - Set Reactstate Passive"), +(22061,0,2,0,4,0,100,0,0,0,0,0,11,38250,0,0,0,0,0,19,22058,0,0,0,0,0,0,"Shadowmoon Soulstealer - On Aggro - Cast 'Heart of Fury Siphon'"); + +-- Shadowmoon Darkweaver +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=22081; +DELETE FROM `smart_scripts` WHERE `entryorguid`=22081 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 +(22081,0,0,0,0,0,100,0,0,0,3000,5000,11,9613,64,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowmoon Darkweaver - In Combat - Cast 'Shadow Bolt'"), +(22081,0,1,0,9,0,100,0,0,30,15000,18000,11,11962,0,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowmoon Darkweaver - Within 0-30 Range - Cast 'Immolate'"), +(22081,0,2,0,9,0,100,0,0,10,8000,11000,11,35373,0,0,0,0,0,1,0,0,0,0,0,0,0,"Shadowmoon Darkweaver - Within 0-10 Range - Cast 'Shadowfury'"); + +-- Shadowmoon Chosen +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=22084; +DELETE FROM `smart_scripts` WHERE `entryorguid`=22084 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 +(22084,0,0,0,9,0,100,0,0,5,15000,17000,11,38618,0,0,0,0,0,1,0,0,0,0,0,0,0,"Shadowmoon Chosen - Within 0-5 Range - Cast 'Whirlwind'"), +(22084,0,1,0,0,0,100,0,8000,10000,18000,22000,11,10966,0,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowmoon Chosen - In Combat - Cast 'Uppercut'"); + +-- Shadowmoon Slayer +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=22082; +DELETE FROM `smart_scripts` WHERE `entryorguid`=22082 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 +(22082,0,0,1,2,0,100,1,0,30,0,0,11,3019,0,0,0,0,0,1,0,0,0,0,0,0,0,"Shadowmoon Slayer - Between 0-30% Health - Cast 'Frenzy'"), +(22082,0,1,0,61,0,100,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Shadowmoon Slayer - Between 0-30% Health - Say Line 0"), +(22082,0,2,0,0,0,100,0,5000,7000,12000,15000,11,37577,0,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowmoon Slayer - In Combat - Cast 'Debilitating Strike'"); + +DELETE FROM `creature_text` WHERE `CreatureID`=22082; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(22082,0,0,"%s goes into a frenzy!",16,0,100,0,0,0,2384,0,"Shadowmoon Slayer"); + +-- Shadowsworn Drakonid +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=22072; +DELETE FROM `smart_scripts` WHERE `entryorguid`=22072 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 +(22072,0,0,0,0,0,100,0,5000,7000,11000,13000,11,15496,0,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowsworn Drakonid - In Combat - Cast 'Cleave'"), +(22072,0,1,0,0,0,100,0,6000,8000,14000,16000,11,17547,0,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowsworn Drakonid - In Combat - Cast 'Mortal Strike'"), +(22072,0,2,0,0,0,100,0,9000,11000,18000,22000,11,16145,0,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowsworn Drakonid - In Combat - Cast 'Sunder Armor'"); + +-- Shadowmoon Retainer +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=22102; +DELETE FROM `smart_scripts` WHERE `entryorguid`=22102 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 +(22102,0,0,0,0,0,100,0,0,0,2000,4000,11,15547,64,0,0,0,0,2,0,0,0,0,0,0,0,"Shadowmoon Retainer - In Combat - Cast 'Shoot'"); diff --git a/sql/updates/world/4.3.4/2018_03_09_18_world_from_335_was_2018_03_09_04_world.sql b/sql/updates/world/4.3.4/2018_03_09_18_world_from_335_was_2018_03_09_04_world.sql new file mode 100644 index 0000000000..14447f9ba8 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_18_world_from_335_was_2018_03_09_04_world.sql @@ -0,0 +1,2 @@ +-- Ashtongue Deathsworn +UPDATE `smart_scripts` SET `event_type`=54, `comment`="Ashtongue Deathsworn - On Just Summoned - Start Waypoint" WHERE `entryorguid`=21701 AND `source_type`=0 AND `id`=0; diff --git a/sql/updates/world/4.3.4/2018_03_09_19_world_from_335_was_2018_03_09_05_world.sql b/sql/updates/world/4.3.4/2018_03_09_19_world_from_335_was_2018_03_09_05_world.sql new file mode 100644 index 0000000000..745051f211 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_19_world_from_335_was_2018_03_09_05_world.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `gameobject_template_addon` WHERE `entry` BETWEEN 300010 AND 300205; +DELETE FROM `gameobject_template` WHERE `entry` BETWEEN 300010 AND 300205; diff --git a/sql/updates/world/4.3.4/2018_03_09_20_world_from_335_was_2018_03_09_06_world_335.sql b/sql/updates/world/4.3.4/2018_03_09_20_world_from_335_was_2018_03_09_06_world_335.sql new file mode 100644 index 0000000000..bbe9b8709a --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_20_world_from_335_was_2018_03_09_06_world_335.sql @@ -0,0 +1,36 @@ +/* +-- Rhapsody Shindigger +DELETE FROM `creature_text` WHERE `CreatureID`=5634; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(5634,0,0,"Time to brew up a Kalimdor Kocktail! Hiccup!",12,7,100,4,0,0,1950,0,"Rhapsody Shindigger"), +(5634,1,0,"That should do it! Hiccup!",12,7,100,0,0,0,1951,0,"Rhapsody Shindigger"), +(5634,2,0,"%s chugs his drink.",16,0,100,92,0,0,1952,0,"Rhapsody Shindigger"), +(5634,3,0,"Hiccup!",12,7,100,34,0,0,1953,0,"Rhapsody Shindigger"), +(5634,4,0,"Ok, who pushed me down? Was it you, $n? Someone turn the lights back on. Hiccup!",12,7,100,6,0,0,1954,0,"Rhapsody Shindigger"), +(5634,5,0,"One more sip of the ol' fire water and I'll be ready to talk. Hiccup! Cheers!",12,7,100,1,0,0,1955,0,"Rhapsody Shindigger"), +(5634,6,0,"So, $n, I'm ready to tell you what happened in the Swamp of Sorrows. Hiccup!",12,7,100,1,0,0,1956,0,"Rhapsody Shindigger"); + +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=5634; +DELETE FROM `smart_scripts` WHERE `entryorguid`=5634 AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=563400 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 +(5634,0,0,0,20,0,100,0,1452,0,0,0,80,563400,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Quest 'Rhapsody's Kalimdor Kocktail' Finished - Run Script"), +(563400,9,0,0,0,0,100,0,0,0,0,0,83,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Remove Npc Flag Questgiver"), +(563400,9,1,0,0,0,100,0,0,0,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Set Emote State 0"), +(563400,9,2,0,0,0,100,0,1000,1000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Say Line 0"), +(563400,9,3,0,0,0,100,0,3000,3000,0,0,5,33,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Play Emote 33"), +(563400,9,4,0,0,0,100,0,2000,2000,0,0,17,133,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Set Emote State 133"), +(563400,9,5,0,0,0,100,0,8000,8000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Set Emote State 0"), +(563400,9,6,0,0,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Say Line 1"), +(563400,9,7,0,0,0,100,0,3000,3000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Say Line 2"), +(563400,9,8,0,0,0,100,0,3000,3000,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Say Line 3"), +(563400,9,9,0,0,0,100,0,2000,2000,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Say Line 4"), +(563400,9,10,0,0,0,100,0,3500,3500,0,0,5,33,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Play Emote 33"), +(563400,9,11,0,0,0,100,0,1500,1500,0,0,1,5,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Say Line 5"), +(563400,9,12,0,0,0,100,0,4500,4500,0,0,5,92,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Play Emote 92"), +(563400,9,13,0,0,0,100,0,3000,3000,0,0,5,34,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Play Emote 34"), +(563400,9,14,0,0,0,100,0,2000,2000,0,0,1,6,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Say Line 6"), +(563400,9,15,0,0,0,100,0,3000,3500,0,0,5,33,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Play Emote 33"), +(563400,9,16,0,0,0,100,0,2000,2000,0,0,17,93,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Set Emote State 93"), +(563400,9,17,0,0,0,100,0,0,0,0,0,82,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Rhapsody Shindigger - On Script - Add Npc Flag Questgiver"); +*/ diff --git a/sql/updates/world/4.3.4/2018_03_09_21_world_from_335_was_2018_03_09_07_world_335.sql b/sql/updates/world/4.3.4/2018_03_09_21_world_from_335_was_2018_03_09_07_world_335.sql new file mode 100644 index 0000000000..9ad0071afb --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_21_world_from_335_was_2018_03_09_07_world_335.sql @@ -0,0 +1,144 @@ +/* +-- Quest "The Prodigal Lich Returns" +UPDATE `creature_template` SET `speed_walk`=1 WHERE `entry`=5666; + +UPDATE `creature_text` SET `Emote`=0 WHERE `CreatureID`=1498 AND `GroupID`=0; +UPDATE `creature_text` SET `Emote`=2 WHERE `CreatureID`=5666 AND `GroupID` IN (0,2); + +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (149800,566600) 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 +(149800,9,0,0,0,0,100,0,0,0,0,0,83,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Remove Npc Flag Questgiver"), +(149800,9,1,0,0,0,100,0,0,0,0,0,64,1,0,0,0,0,0,7,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Store Targetlist"), +(149800,9,2,0,0,0,100,0,0,0,0,0,11,7762,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Cast 'Summon Gunther's Visage'"), +(149800,9,3,0,0,0,100,0,2000,2000,0,0,12,5666,1,21000,0,0,0,8,0,0,0,1765.81,57.0857,-46.3189,1.591,"Bethor Iceshard - On Script - Summon Creature 'Gunther's Visage'"), +(149800,9,4,0,0,0,100,0,0,0,0,0,100,1,0,0,0,0,0,19,5666,0,0,0,0,0,0,"Bethor Iceshard - On Script - Send Targetlist to 'Guther's Visage'"), +(149800,9,5,0,0,0,100,0,3000,3000,0,0,66,0,0,0,0,0,0,19,5666,0,0,0,0,0,0,"Bethor Iceshard - On Script - Set Orientation"), +(149800,9,6,0,0,0,100,0,18000,18000,0,0,66,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Set Orientation"), +(149800,9,7,0,0,0,100,0,0,0,0,0,82,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Add Npc Flag Questgiver"), +(566600,9,0,0,0,0,100,0,0,0,0,0,53,0,5666,0,0,0,0,1,0,0,0,0,0,0,0,"Gunther's Visage - On Script - Start Waypoint"), +(566600,9,1,0,0,0,100,0,4000,4000,0,0,1,0,0,0,0,0,0,12,1,0,0,0,0,0,0,"Gunther's Visage - On Script - Say Line 0"), +(566600,9,2,0,0,0,100,0,4000,4000,0,0,1,1,0,0,0,0,0,12,1,0,0,0,0,0,0,"Gunther's Visage - On Script - Say Line 1"), +(566600,9,3,0,0,0,100,0,5000,5000,0,0,66,0,0,0,0,0,0,12,1,0,0,0,0,0,0,"Gunther's Visage - On Script - Set Orientation"), +(566600,9,4,0,0,0,100,0,0,0,0,0,1,2,0,0,0,0,0,12,1,0,0,0,0,0,0,"Gunther's Visage - On Script - Say Line 2"), +(566600,9,5,0,0,0,100,0,5000,5000,0,0,1,0,0,0,0,0,0,19,1498,0,0,0,0,0,0,"Gunther's Visage - On Script - Say Line 0 (Bethor Iceshard)"); + +DELETE FROM `waypoints` WHERE `entry`=5666; +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +(5666,1,1766.04,62.8454,-46.3213,""); + +-- Quest "Rot Hide Origins" +DELETE FROM `smart_scripts` WHERE `entryorguid`=149801 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 +(149801,9,0,0,0,0,100,0,0,0,0,0,83,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Remove Npc Flag Questgiver"), +(149801,9,1,0,0,0,100,0,0,0,0,0,11,5017,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Cast 'Divining Trance'"), +(149801,9,2,0,0,0,100,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Say Line 1"), +(149801,9,3,0,0,0,100,0,7000,7000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Say Line 2"), +(149801,9,4,0,0,0,100,0,4000,4000,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Say Line 3"), +(149801,9,5,0,0,0,100,0,0,0,0,0,82,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Bethor Iceshard - On Script - Add Npc Flag Questgiver"); + +-- Quest "The Mind's Eye" +DELETE FROM `smart_scripts` WHERE `entryorguid`=251900 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`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(251900,9,0,0,0,0,100,0,0,0,0,0,0,83,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kin'weelay - On Script - Remove Npc Flag Questgiver"), +(251900,9,1,0,0,0,100,0,0,0,0,0,0,90,8,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kin'weelay - On Script - Set Flag Standstate 'Kneel'"), +(251900,9,2,0,0,0,100,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kin'weelay - On Script - Say Line 0"), +(251900,9,3,0,0,0,100,0,3000,3000,0,0,0,11,2362,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kin'weelay - On Script - Cast Create Spellstone"), +(251900,9,4,0,0,0,100,0,6000,6000,0,0,0,91,8,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kin'weelay - On Script - Remove Flag Standstate 'Kneel'"), +(251900,9,5,0,0,0,100,0,2000,2000,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kin'weelay - On Script - Say Line 1"), +(251900,9,6,0,0,0,100,0,0,0,0,0,0,82,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kin'weelay - On Script - Add Npc Flag Questgiver"); + +-- Quest "Elixir of Suffering (Part 2)" +DELETE FROM `smart_scripts` WHERE `entryorguid`=2230 AND `source_type`=0; -- Umpi +DELETE FROM `smart_scripts` WHERE `entryorguid`=223000 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 +(2230,0,0,0,20,0,100,512,499,0,0,0,80,223000,0,0,0,0,0,1,0,0,0,0,0,0,0,"Umpi - On Quest 'Elixir of Agony (Part 2)' Rewarded - Run Script"), +(2230,0,1,0,20,0,100,512,499,0,0,0,45,1,1,0,0,0,0,19,2216,0,0,0,0,0,0,"Umpi - On Quest 'Elixir of Agony (Part 2)' Rewarded - Set Data to Apothecary Lydon"), +(223000,9,0,0,0,0,100,0,1000,1000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Umpi - On Script - Say Line 0"), +(223000,9,1,0,0,0,100,0,0,0,0,0,11,3240,0,0,0,0,0,1,0,0,0,0,0,0,0,"Umpi - On Script - Cast 'Bloody Explosion'"); + +DELETE FROM `creature_text` WHERE `CreatureID`=2230; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(2230,0,0,"Croak!",12,0,100,0,0,0,579,0,"Umpi"); + +DELETE FROM `smart_scripts` WHERE `entryorguid`=2216 AND `source_type`=0 AND `id`=1; -- Apothecary Lydon +DELETE FROM `smart_scripts` WHERE `entryorguid`=221601 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 +(2216,0,1,0,38,0,100,512,1,1,0,0,80,221601,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apothecary Lydon - On Data Set - Run Script"), +(221601,9,0,0,0,0,100,0,0,0,0,0,66,0,0,0,0,0,0,8,0,0,0,0,0,0,4.15964,"Apothecary Lydon - On Script - Set Orientation"), +(221601,9,1,0,0,0,100,0,2000,2000,0,0,5,11,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apothecary Lydon - On Script - Play Emote 'Laugh'"), +(221601,9,2,0,0,0,100,0,5000,5000,0,0,66,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Apothecary Lydon - On Script - Set Orientation"); + +-- Quest "Elixir of Pain (Part 2)" +DELETE FROM `smart_scripts` WHERE `entryorguid`=2274 AND `source_type`=0 AND `id` IN (0,1,2); -- Stanley +DELETE FROM `smart_scripts` WHERE `entryorguid`=227400 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 +(2274,0,0,0,20,0,100,512,502,0,0,0,80,227400,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stanley - On Quest 'Elixir of Pain (Part 2)' Rewarded - Run Script"), +(227400,9,0,0,0,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stanley - On Script - Say Line 0"), +(227400,9,1,0,0,0,100,0,2000,2000,0,0,36,2275,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stanley - On Script - Update Template To 'Enraged Stanley'"), +(227400,9,2,0,0,0,100,0,0,0,0,0,3,2275,0,0,0,0,0,1,0,0,0,0,0,0,0,"Stanley - On Script - Morph To Creature 'Enraged Stanley'"), +(227400,9,3,0,0,0,100,0,0,0,0,0,49,0,0,0,0,0,0,7,0,0,0,0,0,0,0,"Stanley - On Script - Start Attacking"); + +DELETE FROM `creature_text` WHERE `CreatureID`=2274; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(2274,0,0,"%s sniffs the elixir then eagerly digs in!",16,0,100,0,0,0,580,0,"Stanley"); + +-- Quest "Elixir of Agony (Part 5)" +DELETE FROM `creature_text` WHERE `CreatureID`=2284 AND `GroupID` IN (2,3,4); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(2284,2,0,"%s raises his mug to his eye, and frowns.",16,0,100,0,0,0,561,0,"Captured Farmer"), +(2284,3,0,"%s swaggers heavily.",16,0,100,0,0,0,559,0,"Captured Farmer"), +(2284,4,0,"%s mumbles incoherent words.",16,0,100,1,0,0,560,0,"Captured Farmer"); + +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (172800,1589100,1589200,1589300) 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 +(172800,9,0,0,0,0,100,0,0,0,0,0,50,1729,120,0,0,0,0,8,0,0,0,0.437117,-942.794,61.9384,-2.54818,"Dusty Rug - On Script - Summon Gameobject 'Tainted Keg'"), +(172800,9,1,0,0,0,100,0,0,0,0,0,45,1,1,0,0,0,0,9,2284,0,50,0,0,0,0,"Dusty Rug - On Script - Set Data 1 1"), +(172800,9,2,0,0,0,100,0,1000,1000,0,0,50,1730,119,0,0,0,0,8,0,0,0,0.437117,-942.794,61.9384,-2.54818,"Dusty Rug - On Script - Summon Gameobject 'Tainted Keg Smoke'"), +(1589100,9,0,0,0,0,100,0,3000,3000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Say Line 0"), +(1589100,9,1,0,0,0,100,0,0,0,0,0,69,0,0,0,0,0,0,8,0,0,0,0.426498,-944.53,61.9386,0,"Captured Farmer - On Script - Move To Position"), +(1589100,9,2,0,0,0,100,0,3000,3000,0,0,5,16,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Play Emote 'Kneel'"), +(1589100,9,3,0,0,0,100,0,1000,1000,0,0,5,26,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Play Emote 'Stand'"), +(1589100,9,4,0,0,0,100,0,3000,3000,0,0,17,418,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Set Emote State 'Eat'"), +(1589100,9,5,0,0,0,100,0,6000,6000,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Set Emote State 'None'"), +(1589100,9,6,0,0,0,100,0,0,0,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Say Line 2"), +(1589100,9,7,0,0,0,100,0,2000,2000,0,0,37,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Kill Self"), +(1589200,9,0,0,0,0,100,0,3000,3000,0,0,69,0,0,0,0,0,0,8,0,0,0,-1.4032,-942.653,61.9,0,"Captured Farmer - On Script - Move To Position"), +(1589200,9,1,0,0,0,100,0,3000,3000,0,0,5,16,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Play Emote 'Kneel'"), +(1589200,9,2,0,0,0,100,0,1000,1000,0,0,5,26,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Play Emote 'Stand'"), +(1589200,9,3,0,0,0,100,0,3000,3000,0,0,17,418,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Set Emote State 'Eat'"), +(1589200,9,4,0,0,0,100,0,6000,6000,0,0,17,64,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Set Emote State 'Stun'"), +(1589200,9,5,0,0,0,100,0,0,0,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Say Line 3"), +(1589200,9,6,0,0,0,100,0,4000,4000,0,0,37,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Kill Self"), +(1589300,9,0,0,0,0,100,0,3000,3000,0,0,69,0,0,0,0,0,0,8,0,0,0,0.446124,-941.072,61.91,0,"Captured Farmer - On Script - Move To Position"), +(1589300,9,1,0,0,0,100,0,3000,3000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Say Line 1"), +(1589300,9,2,0,0,0,100,0,0,0,0,0,5,16,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Play Emote 'Kneel'"), +(1589300,9,3,0,0,0,100,0,1000,1000,0,0,5,26,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Play Emote 'Stand'"), +(1589300,9,4,0,0,0,100,0,3000,3000,0,0,17,418,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Set Emote State 'Eat'"), +(1589300,9,5,0,0,0,100,0,7500,7500,0,0,17,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Set Emote State 'None'"), +(1589300,9,6,0,0,0,100,0,500,500,0,0,1,4,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Say Line 4"), +(1589300,9,7,0,0,0,100,0,3000,3000,0,0,37,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Farmer - On Script - Kill Self"); + +-- Quest "The Tower of Althalaxx (Part 4)" +DELETE FROM `smart_scripts` WHERE `entryorguid`=366300 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`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(366300,9,0,0,0,0,100,0,0,0,0,0,0,83,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Delgren the Purifier - On Script - Remove Npc Flag Questgiver"), +(366300,9,1,0,0,0,100,0,1000,1000,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 0"), +(366300,9,2,0,0,0,100,0,4000,4000,0,0,0,5,61,0,0,0,0,0,1,0,0,0,0,0,0,0,"Delgren the Purifier - On Script - Play Emote 61"), +(366300,9,3,0,0,0,100,0,0,0,0,0,0,50,19862,5,0,0,0,0,8,0,0,0,3186.81,189.953,4.57494,3.48778,"Delgren the Purifier - On Script - Summon Object 'Glowing Soulgem'"), +(366300,9,4,0,0,0,100,0,1000,1000,0,0,0,12,4509,8,0,0,0,0,8,0,0,0,3188.2,191.026,4.53698,3.6802,"Delgren the Purifier - On Script - Summon Sargath"), +(366300,9,5,0,0,0,100,0,3000,3000,0,0,0,1,0,0,0,0,0,0,19,4509,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 0 (Sargath)"), +(366300,9,6,0,0,0,100,0,7000,7000,0,0,0,1,1,0,0,0,0,0,19,4509,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 1 (Sargath)"), +(366300,9,7,0,0,0,100,0,7000,7000,0,0,0,1,2,0,0,0,0,0,19,4509,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 2 (Sargath)"), +(366300,9,8,0,0,0,100,0,7000,7000,0,0,0,1,3,0,0,0,0,0,19,4509,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 3 (Sargath)"), +(366300,9,9,0,0,0,100,0,7000,7000,0,0,0,1,4,0,0,0,0,0,19,4509,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 4 (Sargath)"), +(366300,9,10,0,0,0,100,0,7000,7000,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 1"), +(366300,9,11,0,0,0,100,0,7000,7000,0,0,0,1,5,0,0,0,0,0,19,4509,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 5 (Sargath)"), +(366300,9,12,0,0,0,100,0,7000,7000,0,0,0,1,6,0,0,0,0,0,19,4509,0,0,0,0,0,0,"Delgren the Purifier - On Script - Say Line 6 (Sargath)"), +(366300,9,13,0,0,0,100,0,0,0,0,0,0,41,0,0,0,0,0,0,19,4509,0,0,0,0,0,0,"Delgren the Purifier - On Script - Despawn (Sargath)"), +(366300,9,14,0,0,0,100,0,1000,1000,0,0,0,82,2,0,0,0,0,0,1,0,0,0,0,0,0,0,"Delgren the Purifier - On Script - Add Npc Flag Questgiver"); + +-- Quest "Fields of Grief (Part 2)" +DELETE FROM `smart_scripts` WHERE `entryorguid`=1931 AND `source_type`=0 AND `id`=1; +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 +(1931,0,1,0,20,0,100,512,407,0,0,0,59,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Captured Scarlet Zealot - On Quest 'Fields of Grief' Finished - Set Run Off"); +*/ diff --git a/sql/updates/world/4.3.4/2018_03_09_22_world_from_335_was_2018_03_09_08_world_335.sql b/sql/updates/world/4.3.4/2018_03_09_22_world_from_335_was_2018_03_09_08_world_335.sql new file mode 100644 index 0000000000..90ddb599ef --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_22_world_from_335_was_2018_03_09_08_world_335.sql @@ -0,0 +1,23 @@ +/* +-- Junior Apothecary Holland +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=10665; +DELETE FROM `smart_scripts` WHERE `entryorguid`=10665 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 +(10665,0,0,0,1,0,100,0,10000,20000,40000,60000,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Junior Apothecary Holland - Out of Combat - Say Line 0"); + +DELETE FROM `creature_text` WHERE `CreatureID`=10665; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(10665,0,0,"What could be taking so long?",12,1,100,0,0,0,5955,0,"Junior Apothecary Holland"), +(10665,0,1,"How long can it take to pick a handful of weeds?",12,1,100,0,0,0,5956,0,"Junior Apothecary Holland"), +(10665,0,2,"At this rate I could have gathered them myself!",12,1,100,0,0,0,5957,0,"Junior Apothecary Holland"), +(10665,0,3,"If you want something done right, do it yourself!",12,1,100,0,0,0,5958,0,"Junior Apothecary Holland"), +(10665,0,4,"As if I had all eternity.",12,1,100,0,0,0,5959,0,"Junior Apothecary Holland"), +(10665,0,5,"Ah, this must be him now... no? Bah!",12,1,100,0,0,0,5960,0,"Junior Apothecary Holland"), +(10665,0,6,"Maybe I should have just bought some off of Faruza?",12,1,100,0,0,0,5961,0,"Junior Apothecary Holland"), +(10665,0,7,"I had to go and requisition an Abomination... an Abomination!",12,1,100,0,0,0,5962,0,"Junior Apothecary Holland"); + +UPDATE `waypoint_data` SET `action`=0 WHERE `id`=284120; +UPDATE `waypoint_data` SET `delay`=0 WHERE `id`=284120 AND `point` IN (8,12); + +DELETE FROM `waypoint_scripts` WHERE `id` IN (22,1002,1003,1004,1005); +*/ diff --git a/sql/updates/world/4.3.4/2018_03_09_23_world_from_335_was_2018_03_09_09_world.sql b/sql/updates/world/4.3.4/2018_03_09_23_world_from_335_was_2018_03_09_09_world.sql new file mode 100644 index 0000000000..93d6e00b43 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_09_23_world_from_335_was_2018_03_09_09_world.sql @@ -0,0 +1,3 @@ +-- +DELETE FROM `gameobject` WHERE `guid` BETWEEN 99928 AND 99934; +DELETE FROM `gameobject_addon` WHERE `guid` BETWEEN 99928 AND 99934; diff --git a/sql/updates/world/4.3.4/2018_03_10_00_world_from_335_2018_03_10_00_world.sql b/sql/updates/world/4.3.4/2018_03_10_00_world_from_335_2018_03_10_00_world.sql new file mode 100644 index 0000000000..3e7f934b11 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_10_00_world_from_335_2018_03_10_00_world.sql @@ -0,0 +1,125 @@ +-- Duplicates removed +DELETE FROM `creature` WHERE `guid` IN (129516,129555,129532,129520,129556,129545); +DELETE FROM `creature_addon` WHERE `guid` IN (129516,129555,129532,129520,129556,129545); + +-- Death Knight Initiate +UPDATE `creature` SET `modelid`=0, `spawntimesecs` = 30 WHERE `id` = 28406; +UPDATE `creature_addon` SET `auras` = "" WHERE `guid` IN (129492,129493,129494,129495,129496,129497,129498,129499); +UPDATE `creature_addon` SET `path_id` = 1295170 WHERE `guid` IN (129517); +UPDATE `creature_addon` SET `path_id` = 1295180 WHERE `guid` IN (129518); +UPDATE `creature_addon` SET `path_id` = 1295290 WHERE `guid` IN (129529); +UPDATE `creature_addon` SET `path_id` = 1295300 WHERE `guid` IN (129530); +UPDATE `creature_addon` SET `path_id` = 1295310 WHERE `guid` IN (129531); +UPDATE `creature_addon` SET `path_id` = 1295440 WHERE `guid` IN (129544); +UPDATE `creature_addon` SET `path_id` = 1295460 WHERE `guid` IN (129546); +UPDATE `creature_addon` SET `path_id` = 1295470 WHERE `guid` IN (129547); +-- #1 +UPDATE `creature` SET `position_x` = 2409.489, `position_y` = -5729.18, `position_z` = 153.92, `orientation` = 3.8, `spawndist` = 0, `MovementType` = 2 WHERE `guid` = 129547; +DELETE FROM `waypoint_data` WHERE `id`= 1295470; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `action_chance`, `move_type`) VALUES +(1295470,1,2409.489,-5729.18,153.92,2000,0,3.8,100,0), +(1295470,2,2398.24,-5738.1,153.923,0,0,3.51732,100,0), +(1295470,3,2386.8,-5734.52,153.922,0,0,2.57013,100,0), +(1295470,4,2372.86,-5722.17,153.922,0,0,2.26872,100,0), +(1295470,5,2366.02,-5712.39,153.922,0,0,1.78963,100,0), +(1295470,6,2365.51,-5706.24,153.922,0,0,0.855789,100,0), +(1295470,7,2368.78,-5703.15,153.922,10000,0,0.690856,100,0), +(1295470,8,2358.21,-5706.16,153.922,0,0,2.85855,100,0), +(1295470,9,2341.04,-5689.82,153.922,0,0,2.3292,100,0), +(1295470,10,2313.73,-5661.47,152.761,0,0,2.56639,100,0), +(1295470,11,2296.29,-5652.93,147.341,0,0,2.88369,100,0), +(1295470,12,2278.16,-5647.89,143.137,0,0,2.9638,100,0), +(1295470,13,2255.96,-5645.48,136.996,0,0,3.24733,100,0), +(1295470,14,2234.36,-5647.77,130.968,0,0,3.42954,100,0), +(1295470,15,2209.59,-5657.5,122.594,0,0,3.76412,100,0), +(1295470,16,2188.9,-5675.6,113.179,0,0,3.89371,100,0), +(1295470,17,2163.24,-5699.88,104.99,1000,0,3.94476,100,0), +(1295470,18,2149.23,-5715.65,101.528,1000,1188,3.99581,100,0); +-- #2 +UPDATE `creature` SET `position_x` = 2455.27, `position_y` = -5523.46, `position_z` = 376.892, `orientation` = 5.96, `spawndist` = 0, `MovementType` = 2 WHERE `guid` = 129544; +DELETE FROM `waypoint_data` WHERE `id`= 1295440; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `action_chance`, `move_type`) VALUES +(1295440,1,2455.27,-5523.46,376.892,1000,0,5.96,100,0), +(1295440,2,2451.31,-5528.92,376.891,0,0,3.66393,100,0), +(1295440,3,2424.47,-5542.18,376.905,0,0,3.84064,100,0), +(1295440,4,2403.66,-5563.52,377.005,0,0,4.24905,100,0), +(1295440,5,2398.1,-5601.44,376.89,0,0,4.6064,100,0), +(1295440,6,2397.91,-5614.95,377.018,0,0,4.26946,100,0), +(1295440,7,2386.16,-5630.91,377.169,0,0,4.1116,100,0), +(1295440,8,2379.33,-5642.43,382.439,0,0,4.2137,100,0), +(1295440,9,2349.92,-5690.11,382.241,6000,1188,4.12338,100,0); +-- #3 +UPDATE `creature` SET `position_x` = 2416.227, `position_y` = -5557.54, `position_z` = 376.89, `orientation` = 1.72, `MovementType` = 2, `spawndist` = 0 WHERE `guid` = 129518; +DELETE FROM `waypoint_data` WHERE `id`= 1295180; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `action_chance`, `move_type`) VALUES +(1295180,1,2416.227,-5557.54,376.89,1000,0,1.72,100,0), +(1295180,2,2411.56,-5553.34,376.887,0,0,4.06137,100,0), +(1295180,3,2396.85,-5576.58,376.906,0,0,4.57353,100,0), +(1295180,4,2397.55,-5612.24,377.017,0,0,4.15728,100,0), +(1295180,5,2377.61,-5641.62,382.439,0,0,3.72139,100,0), +(1295180,6,2350.25,-5690.08,382.24,3000,1188,3.64364,100,0); +-- #4 +UPDATE `creature` SET `position_x` = 2523.21, `position_y` = -5628.21, `position_z` = 377.004, `orientation` = 1.93, `MovementType` = 2, `spawndist` = 0 WHERE `guid` = 129529; +DELETE FROM `waypoint_data` WHERE `id`= 1295290; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `action_chance`, `move_type`) VALUES +(1295290,1,2523.21,-5628.21,377.004,1000,0,1.93,100,0), +(1295290,2,2517.63,-5625.44,377.01,0,0,3.57347,100,0), +(1295290,3,2480.55,-5653.1,376.997,0,0,3.48315,100,0), +(1295290,4,2454.17,-5656.89,376.903,0,0,3.08653,100,0), +(1295290,5,2426.21,-5647.1,377.148,0,0,2.74566,100,0), +(1295290,6,2397.13,-5648.46,377.169,0,0,3.41325,100,0), +(1295290,7,2385.79,-5652.5,382.439,0,0,3.6638,100,0), +(1295290,8,2370,-5666.09,382.256,0,0,3.98424,100,0), +(1295290,9,2354.86,-5693.19,382.239,5000,1188,4.18451,100,0); +-- #5 +UPDATE `creature` SET `position_x` = 2477.05, `position_y` = -5647.81, `position_z` = 377.006, `orientation` = 5.92, `MovementType` = 2, `spawndist` = 0 WHERE `guid` = 129517; +DELETE FROM `waypoint_data` WHERE `id`= 1295170; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `action_chance`, `move_type`) VALUES +(1295170,1,2477.05,-5647.81,377.006,1000,0,5.92,100,0), +(1295170,2,2478.18,-5653.36,377.01,0,0,3.68083,100,0), +(1295170,3,2465.83,-5657.38,376.892,0,0,3.28028,100,0), +(1295170,4,2420.22,-5645.76,376.89,0,0,3.26536,100,0), +(1295170,5,2397.62,-5648.51,377.168,0,0,3.48684,100,0), +(1295170,6,2386.39,-5653.11,382.439,0,0,3.7311,100,0), +(1295170,7,2369.21,-5667.63,382.253,0,0,4.09474,100,0), +(1295170,8,2353.39,-5690.9,382.239,3000,1188,3.8222,100,0); +-- #6 +UPDATE `creature` SET `position_x` = 2413.64, `position_y` = -5737.27, `position_z` = 153.923, `orientation` = 3.86902, `MovementType` = 2, `spawndist` = 0 WHERE `guid` = 129546; +DELETE FROM `waypoint_data` WHERE `id`= 1295460; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `action_chance`, `move_type`) VALUES +(1295460,1,2413.64,-5737.27,153.923,1000,0,3.86902,100,0), +(1295460,2,2373.33,-5754.69,153.961,0,0,3.34356,100,0), +(1295460,3,2349.31,-5761.49,153.922,5000,0,1.76884,100,0), +(1295460,4,2367,-5771.87,151.392,0,0,6.06104,100,0), +(1295460,5,2380.8,-5774.62,154.028,0,0,6.11209,100,0), +(1295460,6,2416.41,-5776.45,148.509,0,0,6.01155,100,0), +(1295460,7,2430.24,-5787.44,140.563,0,0,5.40444,100,0), +(1295460,8,2437.59,-5808,127.202,0,0,4.96462,100,0), +(1295460,9,2441.6,-5832.16,117.571,0,0,4.86645,100,0), +(1295460,10,2430.39,-5856.4,107.743,1000,0,4.06142,100,0), +(1295460,11,2442.87,-5912.91,102.116,1000,1188,4.90965,100,0); +-- #7 +UPDATE `creature` SET `position_x` = 2352.14, `position_y` = -5757.91, `position_z` = 153.923, `MovementType` = 2, `spawndist` = 0 WHERE `guid` = 129531; +DELETE FROM `waypoint_data` WHERE `id`= 1295310; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `action_chance`, `move_type`) VALUES +(1295310,1,2352.14,-5757.91,153.923,1000,0,3.23752,100,0), +(1295310,2,2352.14,-5757.91,153.923,4000,0,3.23752,100,0), +(1295310,3,2341.61,-5727.9,153.922,0,0,1.55677,100,0), +(1295310,4,2342.13,-5697.18,153.922,0,0,1.84658,100,0), +(1295310,5,2317.47,-5651.82,151.422,0,0,2.33588,100,0), +(1295310,6,2297.54,-5644.36,147.052,0,0,2.94867,100,0), +(1295310,7,2245.47,-5638.62,135.882,0,0,3.22356,100,0), +(1295310,8,2205.02,-5658.24,121.031,0,0,3.8778,100,0), +(1295310,9,2161.18,-5703.33,104.27,1000,0,4.13698,100,0), +(1295310,10,2178.08,-5770.89,101.346,1000,1188,5.00484,100,0); +-- #8 +UPDATE `creature` SET `position_x` = 2368.652588, `position_y` = -5703.335449, `position_z` = 153.922272, `orientation` = 0.69, `MovementType` = 2, `spawndist` = 0 WHERE `guid` = 129530; +DELETE FROM `waypoint_data` WHERE `id`= 1295300; +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `action_chance`, `move_type`) VALUES +(1295300,1,2368.652588,-5703.335449,153.922272,1000,0,0.69,100,0), +(1295300,2,2373.52,-5722.48,153.922,0,0,5.28585,100,0), +(1295300,3,2411.22,-5764.47,152.347,0,0,5.47748,100,0), +(1295300,4,2429.98,-5784.48,142.151,0,0,5.22694,100,0), +(1295300,5,2435.23,-5800.88,131.736,0,0,4.99918,100,0), +(1295300,6,2431.43,-5850.32,109.292,1000,0,4.36615,100,0), +(1295300,7,2417.03,-5895.6,104.705,1000,1188,4.31903,100,0); diff --git a/sql/updates/world/4.3.4/2018_03_10_01_world_from_335_2018_03_10_01_world.sql b/sql/updates/world/4.3.4/2018_03_10_01_world_from_335_2018_03_10_01_world.sql new file mode 100644 index 0000000000..f68bc3ccc0 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_10_01_world_from_335_2018_03_10_01_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `conditions` WHERE `SourceEntry` IN (52683) AND `SourceTypeOrReferenceId`=13 AND `ConditionValue2`=28897; diff --git a/sql/updates/world/4.3.4/2018_03_10_02_world_from_335_2018_03_10_02_world.sql b/sql/updates/world/4.3.4/2018_03_10_02_world_from_335_2018_03_10_02_world.sql new file mode 100644 index 0000000000..f6fc64c66c --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_10_02_world_from_335_2018_03_10_02_world.sql @@ -0,0 +1,40 @@ +-- Quest King of the Mountain +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=16 AND `SourceEntry` IN (31784,31785); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(16,0,31784,0,0,23,0,4513,0,0,0,0,0,'','Geargrinder\'s Jumpbot - Dismount when player is outside intended zone Ymirhein'), +(16,0,31785,0,0,23,0,4513,0,0,0,0,0,'','Thunderbomb\'s Jumpbot - Dismount when player is outside intended zone Ymirhein'); + +DELETE FROM `creature_template_addon` WHERE `entry` IN(31784,31785); +INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES +(31784, 0, 0, 0, 1, 0, 4341), +(31785, 0, 0, 0, 1, 0, 4341); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN(4338,59643); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,59643,0,0,31,0,3,23837,0,0,0,0,'','Spell Plant Horde Battle Standard targets ELM General Purpose Bunny'), +(13,1,4338,0,0,31,0,3,23837,0,0,0,0,'','Spell Plant Alliance Battle Standard targets ELM General Purpose Bunny'); + +DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (31784,31785) AND `spell_id`=46598; +INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES +(31784, 46598, 1, 0), +(31785, 46598, 1, 0); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=18 AND `SourceGroup` IN (31784,31785) AND `SourceEntry` IN(59593,59656,46598); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(18, 31784, 59593, 0, 0, 31, 0, 4, 0, 0, 0, 0, 0, '', 'Only player for SpellClick'), +(18, 31784, 46598, 0, 0, 31, 0, 3, 0, 0, 0, 0, 0, '', 'Only unit for SpellClick'), +(18, 31785, 59656, 0, 0, 31, 0, 4, 0, 0, 0, 0, 0, '', 'Only player for SpellClick'), +(18, 31785, 46598, 0, 0, 31, 0, 3, 0, 0, 0, 0, 0, '', 'Only unit for SpellClick'); + +DELETE FROM `vehicle_template_accessory` WHERE `entry` IN(31784, 31785); +INSERT INTO `vehicle_template_accessory` (`entry`,`accessory_entry`,`seat_id`,`minion`,`description`,`summontype`,`summontimer`) VALUES +(31784,31801,1,1,'Geargrinder\'s Jumpbot',6,30000), +(31785,31801,1,1,'Thunderbomb\'s Jumpbot',6,30000); + +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_q13280_13283_jump_jets'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(4336,'spell_q13280_13283_jump_jets'); + +DELETE FROM `spell_proc` WHERE `SpellId`=4341; +INSERT INTO `spell_proc` (`SpellId`,`SchoolMask`,`SpellFamilyName`,`SpellFamilyMask0`,`SpellFamilyMask1`,`SpellFamilyMask2`,`ProcFlags`,`SpellTypeMask`,`SpellPhaseMask`,`HitMask`,`AttributesMask`,`ProcsPerMinute`,`Chance`,`Cooldown`,`Charges`) VALUES +(4341,0,0,0,0,0,4096,1,1,0,0,0,0,0,0); diff --git a/sql/updates/world/4.3.4/2018_03_12_00_world_from_335_2018_03_10_03_world.sql b/sql/updates/world/4.3.4/2018_03_12_00_world_from_335_2018_03_10_03_world.sql new file mode 100644 index 0000000000..ed65852b8b --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_12_00_world_from_335_2018_03_10_03_world.sql @@ -0,0 +1,21 @@ +/* +DELETE FROM `creature_template_movement` WHERE `CreatureId` IN (2673, 2674, 17578, 16111, 24792, 32543, 32546, 32547, 32542, 32545, 30527, 31143, 31144, 31146, 32541, 32666, 32667); +INSERT INTO `creature_template_movement` (`CreatureId`, `Ground`, `Swim`, `Flight`, `Rooted`) VALUES +(2673, 1, 0, 0, 1), +(2674, 1, 0, 0, 1), +(17578, 1, 0, 0, 1), +(16111, 1, 0, 0, 1), +(24792, 1, 0, 0, 1), +(32543, 1, 0, 0, 1), +(32546, 1, 0, 0, 1), +(32547, 1, 0, 0, 1), +(32542, 1, 0, 0, 1), +(32545, 1, 0, 0, 1), +(30527, 1, 0, 0, 1), +(31143, 1, 0, 0, 1), +(31144, 1, 0, 0, 1), +(31146, 1, 0, 0, 1), +(32541, 1, 0, 0, 1), +(32666, 1, 0, 0, 1), +(32667, 1, 0, 0, 1); +*/ diff --git a/sql/updates/world/4.3.4/2018_03_12_01_world_from_335_2018_03_11_00_world.sql b/sql/updates/world/4.3.4/2018_03_12_01_world_from_335_2018_03_11_00_world.sql new file mode 100644 index 0000000000..9bcf34f711 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_12_01_world_from_335_2018_03_11_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `gameobject` SET `phaseMask`=1, `spawntimesecs`=-1 WHERE `id`=192538; diff --git a/sql/updates/world/4.3.4/2018_03_12_02_world_from_335_2018_03_12_00_world.sql b/sql/updates/world/4.3.4/2018_03_12_02_world_from_335_2018_03_12_00_world.sql new file mode 100644 index 0000000000..8bc1cad596 --- /dev/null +++ b/sql/updates/world/4.3.4/2018_03_12_02_world_from_335_2018_03_12_00_world.sql @@ -0,0 +1,11 @@ +-- +UPDATE `smart_scripts` SET `event_param5`=1 WHERE event_type=10 AND `source_type`=0; +UPDATE `smart_scripts` SET `event_param2`=30, `event_param5`=1 WHERE `entryorguid`=24248 AND `source_type`=0; +UPDATE `smart_scripts` SET `event_flags`=0 WHERE `entryorguid`=24938 AND event_type=10 AND `source_type`=0; +UPDATE `smart_scripts` SET `event_param1`=1 WHERE `entryorguid`in (27376,27378,27379,27381) AND event_type=10 AND `source_type`=0; +UPDATE `smart_scripts` SET `event_param1`=1, `event_param2`=20, `event_param5`=0 WHERE `entryorguid`=30313 AND `event_type`=10 AND `source_type`=0; +UPDATE `creature_template` SET `AIName`="" WHERE `entry`=32582; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (32582) AND `source_type`=0; +UPDATE `smart_scripts` SET `event_flags`=0, `event_param2`=10, `event_param3`=60000, `event_param4`=60000, `event_param5`=1 WHERE `entryorguid`=5917 AND `source_type`=0 AND `id`=0; +UPDATE `smart_scripts` SET `event_flags`=0, `event_param1`=1, `event_param2`=20, `event_param3`=40000, `event_param4`=60000, `event_param5`=1 WHERE `entryorguid`=9021 AND `source_type`=0 AND `id`=0; +UPDATE `smart_scripts` SET `event_param5`=0 WHERE `entryorguid` IN (27246, 2775, 23370, 23760, 24845, 23675, 23673, 23672, 24271, 24364, 24468, 24510, 24527, 24718, 24938,24979,25063,30313) AND event_type=10 AND `source_type`=0; diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp index 750e155da8..f86cccbf0a 100644 --- a/src/common/Collision/DynamicTree.cpp +++ b/src/common/Collision/DynamicTree.cpp @@ -142,11 +142,11 @@ void DynamicMapTree::update(uint32 t_diff) struct DynamicTreeIntersectionCallback { - DynamicTreeIntersectionCallback(std::set const& phases) : _didHit(false), _phases(phases) { } + DynamicTreeIntersectionCallback(PhaseShift const& phaseShift) : _didHit(false), _phaseShift(phaseShift) { } bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance) { - _didHit = obj.intersectRay(r, distance, true, _phases, VMAP::ModelIgnoreFlags::Nothing); + _didHit = obj.intersectRay(r, distance, true, _phaseShift, VMAP::ModelIgnoreFlags::Nothing); return _didHit; } @@ -154,20 +154,20 @@ struct DynamicTreeIntersectionCallback private: bool _didHit; - std::set _phases; + PhaseShift const& _phaseShift; }; -bool DynamicMapTree::getIntersectionTime(std::set const& phases, G3D::Ray const& ray, G3D::Vector3 const& endPos, float& maxDist) const +bool DynamicMapTree::getIntersectionTime(G3D::Ray const& ray, G3D::Vector3 const& endPos, PhaseShift const& phaseShift, float& maxDist) const { float distance = maxDist; - DynamicTreeIntersectionCallback callback(phases); + DynamicTreeIntersectionCallback callback(phaseShift); impl->intersectRay(ray, callback, distance, endPos); if (callback.didHit()) maxDist = distance; return callback.didHit(); } -bool DynamicMapTree::getObjectHitPos(std::set const& phases, G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, G3D::Vector3& resultHitPos, float modifyDist) const +bool DynamicMapTree::getObjectHitPos(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, G3D::Vector3& resultHitPos, float modifyDist, PhaseShift const& phaseShift) const { bool result = false; float maxDist = (endPos - startPos).magnitude(); @@ -182,7 +182,7 @@ bool DynamicMapTree::getObjectHitPos(std::set const& phases, G3D::Vector G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1 G3D::Ray ray(startPos, dir); float dist = maxDist; - if (getIntersectionTime(phases, ray, endPos, dist)) + if (getIntersectionTime(ray, endPos, phaseShift, dist)) { resultHitPos = startPos + dir * dist; if (modifyDist < 0) @@ -205,7 +205,7 @@ bool DynamicMapTree::getObjectHitPos(std::set const& phases, G3D::Vector return result; } -bool DynamicMapTree::isInLineOfSight(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, std::set const& phases) const +bool DynamicMapTree::isInLineOfSight(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, PhaseShift const& phaseShift) const { float maxDist = (endPos - startPos).magnitude(); @@ -213,17 +213,17 @@ bool DynamicMapTree::isInLineOfSight(G3D::Vector3 const& startPos, G3D::Vector3 return true; G3D::Ray r(startPos, (endPos - startPos) / maxDist); - DynamicTreeIntersectionCallback callback(phases); + DynamicTreeIntersectionCallback callback(phaseShift); impl->intersectRay(r, callback, maxDist, endPos); return !callback.didHit(); } -float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, std::set const& phases) const +float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, PhaseShift const& phaseShift) const { G3D::Vector3 v(x, y, z + 0.5f); G3D::Ray r(v, G3D::Vector3(0, 0, -1)); - DynamicTreeIntersectionCallback callback(phases); + DynamicTreeIntersectionCallback callback(phaseShift); impl->intersectZAllignedRay(r, callback, maxSearchDist); if (callback.didHit()) diff --git a/src/common/Collision/DynamicTree.h b/src/common/Collision/DynamicTree.h index 7dd7b14908..4ae49c0059 100644 --- a/src/common/Collision/DynamicTree.h +++ b/src/common/Collision/DynamicTree.h @@ -29,6 +29,7 @@ namespace G3D } class GameObjectModel; +class PhaseShift; struct DynTreeImpl; class TC_COMMON_API DynamicMapTree @@ -40,11 +41,11 @@ public: DynamicMapTree(); ~DynamicMapTree(); - bool isInLineOfSight(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, std::set const& phases) const; - bool getIntersectionTime(std::set const& phases, G3D::Ray const& ray, G3D::Vector3 const& endPos, float& maxDist) const; - bool getObjectHitPos(std::set const& phases, G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, G3D::Vector3& resultHitPos, float modifyDist) const; + bool isInLineOfSight(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, PhaseShift const& phaseShift) const; + bool getIntersectionTime(G3D::Ray const& ray, G3D::Vector3 const& endPos, PhaseShift const& phaseShift, float& maxDist) const; + bool getObjectHitPos(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos, G3D::Vector3& resultHitPos, float modifyDist, PhaseShift const& phaseShift) const; - float getHeight(float x, float y, float z, float maxSearchDist, std::set const& phases) const; + float getHeight(float x, float y, float z, float maxSearchDist, PhaseShift const& phaseShift) const; void insert(const GameObjectModel&); void remove(const GameObjectModel&); diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h index 3f5282c0e3..31ea635a09 100644 --- a/src/common/Collision/Management/IVMapManager.h +++ b/src/common/Collision/Management/IVMapManager.h @@ -126,7 +126,6 @@ namespace VMAP virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const=0; // get both area + liquid data in a single vmap lookup virtual void getAreaAndLiquidData(unsigned int mapId, float x, float y, float z, uint8 reqLiquidType, AreaAndLiquidData& data) const=0; - }; } diff --git a/src/common/Collision/Management/MMapManager.cpp b/src/common/Collision/Management/MMapManager.cpp index 2cabac6309..c1f05becdd 100644 --- a/src/common/Collision/Management/MMapManager.cpp +++ b/src/common/Collision/Management/MMapManager.cpp @@ -19,13 +19,12 @@ #include "MMapManager.h" #include "Log.h" #include "MMapFactory.h" -#include "Config.h" #include "MapDefines.h" namespace MMAP { - static char const* const MAP_FILE_NAME_FORMAT = "%s/mmaps/%03i.mmap"; - static char const* const TILE_FILE_NAME_FORMAT = "%s/mmaps/%03i%02i%02i.mmtile"; + static char const* const MAP_FILE_NAME_FORMAT = "%smmaps/%03i.mmap"; + static char const* const TILE_FILE_NAME_FORMAT = "%smmaps/%03i%02i%02i.mmtile"; // ######################## MMapManager ######################## MMapManager::~MMapManager() @@ -37,11 +36,16 @@ namespace MMAP // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost! } - void MMapManager::InitializeThreadUnsafe(const std::vector& mapIds) + void MMapManager::InitializeThreadUnsafe(std::unordered_map> const& mapData) { + childMapData = mapData; // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime - for (uint32 const& mapId : mapIds) - loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)); + for (std::pair> const& mapId : mapData) + { + loadedMMaps.insert(MMapDataSet::value_type(mapId.first, nullptr)); + for (uint32 childMapId : mapId.second) + parentMapData[childMapId] = mapId.first; + } thread_safe_environment = false; } @@ -56,7 +60,7 @@ namespace MMAP return itr; } - bool MMapManager::loadMapData(uint32 mapId) + bool MMapManager::loadMapData(std::string const& basePath, uint32 mapId) { // we already have this map loaded? MMapDataSet::iterator itr = loadedMMaps.find(mapId); @@ -74,7 +78,7 @@ namespace MMAP } // load and init dtNavMesh - read parameters from file - std::string fileName = Trinity::StringFormat(MAP_FILE_NAME_FORMAT, sConfigMgr->GetStringDefault("DataDir", ".").c_str(), mapId); + std::string fileName = Trinity::StringFormat(MAP_FILE_NAME_FORMAT, basePath.c_str(), mapId); FILE* file = fopen(fileName.c_str(), "rb"); if (!file) { @@ -114,10 +118,25 @@ namespace MMAP return uint32(x << 16 | y); } - bool MMapManager::loadMap(const std::string& /*basePath*/, uint32 mapId, int32 x, int32 y) + bool MMapManager::loadMap(std::string const& basePath, uint32 mapId, int32 x, int32 y) + { + if (!loadMapImpl(basePath, mapId, x, y)) + return false; + + bool success = true; + auto childMaps = childMapData.find(mapId); + if (childMaps != childMapData.end()) + for (uint32 childMapId : childMaps->second) + if (!loadMapImpl(basePath, childMapId, x, y)) + success = false; + + return success; + } + + bool MMapManager::loadMapImpl(std::string const& basePath, uint32 mapId, int32 x, int32 y) { // make sure the mmap is loaded and ready to load tiles - if (!loadMapData(mapId)) + if (!loadMapData(basePath, mapId)) return false; // get this mmap data @@ -130,8 +149,18 @@ namespace MMAP return false; // load this tile :: mmaps/MMMXXYY.mmtile - std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, sConfigMgr->GetStringDefault("DataDir", ".").c_str(), mapId, x, y); + std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, basePath.c_str(), mapId, x, y); FILE* file = fopen(fileName.c_str(), "rb"); + if (!file) + { + auto parentMapItr = parentMapData.find(mapId); + if (parentMapItr != parentMapData.end()) + { + fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, basePath.c_str(), parentMapItr->second, x, y); + file = fopen(fileName.c_str(), "rb"); + } + } + if (!file) { TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName.c_str()); @@ -192,13 +221,62 @@ namespace MMAP } else { - TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %04u%02i%02i.mmtile into navmesh", mapId, x, y); + TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y); dtFree(data); return false; } } + bool MMapManager::loadMapInstance(std::string const& basePath, uint32 mapId, uint32 instanceId) + { + if (!loadMapInstanceImpl(basePath, mapId, instanceId)) + return false; + + bool success = true; + auto childMaps = childMapData.find(mapId); + if (childMaps != childMapData.end()) + for (uint32 childMapId : childMaps->second) + if (!loadMapInstanceImpl(basePath, childMapId, instanceId)) + success = false; + + return success; + } + + bool MMapManager::loadMapInstanceImpl(std::string const& basePath, uint32 mapId, uint32 instanceId) + { + if (!loadMapData(basePath, mapId)) + return false; + + MMapData* mmap = loadedMMaps[mapId]; + if (mmap->navMeshQueries.find(instanceId) != mmap->navMeshQueries.end()) + return true; + + // allocate mesh query + dtNavMeshQuery* query = dtAllocNavMeshQuery(); + ASSERT(query); + if (dtStatusFailed(query->init(mmap->navMesh, 1024))) + { + dtFreeNavMeshQuery(query); + TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + return false; + } + + TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); + mmap->navMeshQueries.insert(std::pair(instanceId, query)); + return true; + } + bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y) + { + auto childMaps = childMapData.find(mapId); + if (childMaps != childMapData.end()) + for (uint32 childMapId : childMaps->second) + unloadMapImpl(childMapId, x, y); + + return unloadMapImpl(mapId, x, y); + } + + bool MMapManager::unloadMapImpl(uint32 mapId, int32 x, int32 y) { // check if we have this map loaded MMapDataSet::const_iterator itr = GetMMapData(mapId); @@ -213,17 +291,16 @@ namespace MMAP // check if we have this tile loaded uint32 packedGridPos = packTileID(x, y); - if (mmap->loadedTileRefs.find(packedGridPos) == mmap->loadedTileRefs.end()) + auto tileRefItr = mmap->loadedTileRefs.find(packedGridPos); + if (tileRefItr == mmap->loadedTileRefs.end()) { // file may not exist, therefore not loaded TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y); return false; } - dtTileRef tileRef = mmap->loadedTileRefs[packedGridPos]; - // unload, and mark as non loaded - if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, nullptr, nullptr))) + if (dtStatusFailed(mmap->navMesh->removeTile(tileRefItr->second, nullptr, nullptr))) { // this is technically a memory leak // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used @@ -233,7 +310,7 @@ namespace MMAP } else { - mmap->loadedTileRefs.erase(packedGridPos); + mmap->loadedTileRefs.erase(tileRefItr); --loadedTiles; TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %04i[%02i, %02i] from %03i", mapId, x, y, mapId); return true; @@ -243,6 +320,16 @@ namespace MMAP } bool MMapManager::unloadMap(uint32 mapId) + { + auto childMaps = childMapData.find(mapId); + if (childMaps != childMapData.end()) + for (uint32 childMapId : childMaps->second) + unloadMapImpl(childMapId); + + return unloadMapImpl(mapId); + } + + bool MMapManager::unloadMapImpl(uint32 mapId) { MMapDataSet::iterator itr = loadedMMaps.find(mapId); if (itr == loadedMMaps.end() || !itr->second) @@ -312,27 +399,14 @@ namespace MMAP dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId) { - MMapDataSet::const_iterator itr = GetMMapData(mapId); + auto itr = GetMMapData(mapId); if (itr == loadedMMaps.end()) return nullptr; - MMapData* mmap = itr->second; - if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) - { - // allocate mesh query - dtNavMeshQuery* query = dtAllocNavMeshQuery(); - ASSERT(query); - if (dtStatusFailed(query->init(mmap->navMesh, 1024))) - { - dtFreeNavMeshQuery(query); - TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - return nullptr; - } + auto queryItr = itr->second->navMeshQueries.find(instanceId); + if (queryItr == itr->second->navMeshQueries.end()) + return nullptr; - TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - mmap->navMeshQueries.insert(std::pair(instanceId, query)); - } - - return mmap->navMeshQueries[instanceId]; + return queryItr->second; } } diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h index dbabeb07d2..a4859ecee4 100644 --- a/src/common/Collision/Management/MMapManager.h +++ b/src/common/Collision/Management/MMapManager.h @@ -64,8 +64,9 @@ namespace MMAP MMapManager() : loadedTiles(0), thread_safe_environment(true) {} ~MMapManager(); - void InitializeThreadUnsafe(const std::vector& mapIds); - bool loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y); + void InitializeThreadUnsafe(std::unordered_map> const& mapData); + bool loadMap(std::string const& basePath, uint32 mapId, int32 x, int32 y); + bool loadMapInstance(std::string const& basePath, uint32 mapId, uint32 instanceId); bool unloadMap(uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId); bool unloadMapInstance(uint32 mapId, uint32 instanceId); @@ -77,13 +78,20 @@ namespace MMAP uint32 getLoadedTilesCount() const { return loadedTiles; } uint32 getLoadedMapsCount() const { return uint32(loadedMMaps.size()); } private: - bool loadMapData(uint32 mapId); + bool loadMapData(std::string const& basePath, uint32 mapId); + bool loadMapImpl(std::string const& basePath, uint32 mapId, int32 x, int32 y); + bool loadMapInstanceImpl(std::string const& basePath, uint32 mapId, uint32 instanceId); + bool unloadMapImpl(uint32 mapId, int32 x, int32 y); + bool unloadMapImpl(uint32 mapId); uint32 packTileID(int32 x, int32 y); MMapDataSet::const_iterator GetMMapData(uint32 mapId) const; MMapDataSet loadedMMaps; uint32 loadedTiles; bool thread_safe_environment; + + std::unordered_map> childMapData; + std::unordered_map parentMapData; }; } diff --git a/src/common/Collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp index 94f8f8beb4..1239a27d66 100644 --- a/src/common/Collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -40,23 +40,35 @@ namespace VMAP thread_safe_environment = true; } - VMapManager2::~VMapManager2(void) + VMapManager2::~VMapManager2() { - for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i) - { + for (auto i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i) delete i->second; - } - for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i) - { + + for (auto i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i) delete i->second.getModel(); - } } - void VMapManager2::InitializeThreadUnsafe(const std::vector& mapIds) + InstanceTreeMap::const_iterator VMapManager2::GetMapTree(uint32 mapId) const + { + // return the iterator if found or end() if not found/NULL + auto itr = iInstanceMapTrees.find(mapId); + if (itr != iInstanceMapTrees.cend() && !itr->second) + itr = iInstanceMapTrees.cend(); + + return itr; + } + + void VMapManager2::InitializeThreadUnsafe(std::unordered_map> const& mapData) { // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime - for (uint32 const& mapId : mapIds) - iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)); + iChildMapData = mapData; + for (std::pair> const& mapId : mapData) + { + iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId.first, nullptr)); + for (uint32 childMapId : mapId.second) + iParentMapData[childMapId] = mapId.first; + } thread_safe_environment = false; } @@ -87,8 +99,15 @@ namespace VMAP int result = VMAP_LOAD_RESULT_IGNORED; if (isMapLoadingEnabled()) { - if (_loadMap(mapId, basePath, x, y)) + if (loadSingleMap(mapId, basePath, x, y)) + { result = VMAP_LOAD_RESULT_OK; + auto childMaps = iChildMapData.find(mapId); + if (childMaps != iChildMapData.end()) + for (uint32 childMapId : childMaps->second) + if (!loadSingleMap(childMapId, basePath, x, y)) + result = VMAP_LOAD_RESULT_ERROR; + } else result = VMAP_LOAD_RESULT_ERROR; } @@ -96,27 +115,17 @@ namespace VMAP return result; } - InstanceTreeMap::const_iterator VMapManager2::GetMapTree(uint32 mapId) const - { - // return the iterator if found or end() if not found/NULL - InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId); - if (itr != iInstanceMapTrees.cend() && !itr->second) - itr = iInstanceMapTrees.cend(); - - return itr; - } - // load one tile (internal use only) - bool VMapManager2::_loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY) + bool VMapManager2::loadSingleMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY) { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); + auto instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree == iInstanceMapTrees.end()) { if (thread_safe_environment) instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first; else ASSERT(false, "Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment", - mapId, tileX, tileY); + mapId, tileX, tileY); } if (!instanceTree->second) @@ -134,12 +143,22 @@ namespace VMAP return instanceTree->second->LoadMapTile(tileX, tileY, this); } - void VMapManager2::unloadMap(unsigned int mapId) + void VMapManager2::unloadMap(unsigned int mapId, int x, int y) { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); + auto childMaps = iChildMapData.find(mapId); + if (childMaps != iChildMapData.end()) + for (uint32 childMapId : childMaps->second) + unloadSingleMap(childMapId, x, y); + + unloadSingleMap(mapId, x, y); + } + + void VMapManager2::unloadSingleMap(uint32 mapId, int x, int y) + { + auto instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree != iInstanceMapTrees.end() && instanceTree->second) { - instanceTree->second->UnloadMap(this); + instanceTree->second->UnloadMapTile(x, y, this); if (instanceTree->second->numLoadedTiles() == 0) { delete instanceTree->second; @@ -148,12 +167,22 @@ namespace VMAP } } - void VMapManager2::unloadMap(unsigned int mapId, int x, int y) + void VMapManager2::unloadMap(unsigned int mapId) { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); + auto childMaps = iChildMapData.find(mapId); + if (childMaps != iChildMapData.end()) + for (uint32 childMapId : childMaps->second) + unloadSingleMap(childMapId); + + unloadSingleMap(mapId); + } + + void VMapManager2::unloadSingleMap(uint32 mapId) + { + auto instanceTree = iInstanceMapTrees.find(mapId); if (instanceTree != iInstanceMapTrees.end() && instanceTree->second) { - instanceTree->second->UnloadMapTile(x, y, this); + instanceTree->second->UnloadMap(this); if (instanceTree->second->numLoadedTiles() == 0) { delete instanceTree->second; @@ -167,15 +196,13 @@ namespace VMAP if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) return true; - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); + auto instanceTree = GetMapTree(mapId); if (instanceTree != iInstanceMapTrees.end()) { Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1); Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2); if (pos1 != pos2) - { return instanceTree->second->isInLineOfSight(pos1, pos2, ignoreFlags); - } } return true; @@ -189,7 +216,7 @@ namespace VMAP { if (isLineOfSightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); + auto instanceTree = GetMapTree(mapId); if (instanceTree != iInstanceMapTrees.end()) { Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1); @@ -219,7 +246,7 @@ namespace VMAP { if (isHeightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_HEIGHT)) { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); + auto instanceTree = GetMapTree(mapId); if (instanceTree != iInstanceMapTrees.end()) { Vector3 pos = convertPositionToInternalRep(x, y, z); @@ -238,7 +265,7 @@ namespace VMAP { if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); + auto instanceTree = GetMapTree(mapId); if (instanceTree != iInstanceMapTrees.end()) { Vector3 pos = convertPositionToInternalRep(x, y, z); @@ -256,7 +283,7 @@ namespace VMAP { if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS)) { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); + auto instanceTree = GetMapTree(mapId); if (instanceTree != iInstanceMapTrees.end()) { LocationInfo info; @@ -290,7 +317,7 @@ namespace VMAP data.areaInfo = boost::in_place(adtId, rootId, groupId, flags); return; } - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); + auto instanceTree = GetMapTree(mapId); if (instanceTree != iInstanceMapTrees.end()) { LocationInfo info; @@ -317,7 +344,7 @@ namespace VMAP //! Critical section, thread safe access to iLoadedModelFiles std::lock_guard lock(LoadedModelFilesLock); - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); + auto model = iLoadedModelFiles.find(filename); if (model == iLoadedModelFiles.end()) { WorldModel* worldmodel = new WorldModel(); @@ -343,7 +370,7 @@ namespace VMAP //! Critical section, thread safe access to iLoadedModelFiles std::lock_guard lock(LoadedModelFilesLock); - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); + auto model = iLoadedModelFiles.find(filename); if (model == iLoadedModelFiles.end()) { VMAP_ERROR_LOG("misc", "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str()); @@ -359,7 +386,7 @@ namespace VMAP LoadResult VMapManager2::existsMap(const char* basePath, unsigned int mapId, int x, int y) { - return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y); + return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y, this); } void VMapManager2::getInstanceMapTree(InstanceTreeMap &instanceMapTree) @@ -367,4 +394,13 @@ namespace VMAP instanceMapTree = iInstanceMapTrees; } + int32 VMapManager2::getParentMapId(uint32 mapId) const + { + auto itr = iParentMapData.find(mapId); + if (itr != iParentMapData.end()) + return int32(itr->second); + + return -1; + } + } // namespace VMAP diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index a45454291c..3782e76001 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -81,13 +81,12 @@ namespace VMAP // Tree to check collision ModelFileMap iLoadedModelFiles; InstanceTreeMap iInstanceMapTrees; + std::unordered_map> iChildMapData; + std::unordered_map iParentMapData; bool thread_safe_environment; // Mutex for iLoadedModelFiles std::mutex LoadedModelFilesLock; - bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); - /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */ - static uint32 GetLiquidFlagsDummy(uint32) { return 0; } static bool IsVMAPDisabledForDummy(uint32 /*entry*/, uint8 /*flags*/) { return false; } @@ -99,13 +98,18 @@ namespace VMAP static std::string getMapFileName(unsigned int mapId); VMapManager2(); - ~VMapManager2(void); + ~VMapManager2(); + + void InitializeThreadUnsafe(std::unordered_map> const& mapData); - void InitializeThreadUnsafe(const std::vector& mapIds); int loadMap(const char* pBasePath, unsigned int mapId, int x, int y) override; + bool loadSingleMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); void unloadMap(unsigned int mapId, int x, int y) override; + void unloadSingleMap(uint32 mapId, int x, int y); + void unloadMap(unsigned int mapId) override; + void unloadSingleMap(uint32 mapId); bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, ModelIgnoreFlags ignoreFlags) override ; /** @@ -132,6 +136,8 @@ namespace VMAP void getInstanceMapTree(InstanceTreeMap &instanceMapTree); + int32 getParentMapId(uint32 mapId) const; + typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType); GetLiquidFlagsFn GetLiquidFlagsPtr; diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index 5f85a08aae..42489dda58 100644 --- a/src/common/Collision/Maps/MapTree.cpp +++ b/src/common/Collision/Maps/MapTree.cpp @@ -236,8 +236,26 @@ namespace VMAP return(height); } + StaticMapTree::TileFileOpenResult StaticMapTree::OpenMapTileFile(std::string const& basePath, uint32 mapID, uint32 tileX, uint32 tileY, VMapManager2* vm) + { + TileFileOpenResult result; + result.Name = basePath + getTileFileName(mapID, tileX, tileY); + result.File = fopen(result.Name.c_str(), "rb"); + if (!result.File) + { + int32 parentMapId = vm->getParentMapId(mapID); + if (parentMapId != -1) + { + result.Name = basePath + getTileFileName(parentMapId, tileX, tileY); + result.File = fopen(result.Name.c_str(), "rb"); + } + } + + return result; + } + //========================================================= - LoadResult StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY) + LoadResult StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY, VMapManager2* vm) { std::string basePath = vmapPath; if (basePath.length() > 0 && basePath[basePath.length()-1] != '/' && basePath[basePath.length()-1] != '\\') @@ -259,8 +277,7 @@ namespace VMAP } if (tiled) { - std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); + FILE* tf = OpenMapTileFile(basePath, mapID, tileX, tileY, vm).File; if (!tf) result = LoadResult::FileNotFound; else @@ -321,6 +338,22 @@ namespace VMAP } } + if (success) + { + success = readChunk(rf, chunk, "SIDX", 4); + uint32 spawnIndicesSize = 0; + uint32 spawnId; + uint32 spawnIndex; + if (success && fread(&spawnIndicesSize, sizeof(uint32), 1, rf) != 1) success = false; + for (uint32 i = 0; i < spawnIndicesSize && success; ++i) + { + if (fread(&spawnId, sizeof(uint32), 1, rf) == 1 && fread(&spawnIndex, sizeof(uint32), 1, rf) == 1) + iSpawnIndices[spawnId] = spawnIndex; + else + success = false; + } + } + fclose(rf); return success; } @@ -359,22 +392,21 @@ namespace VMAP } bool result = true; - std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (tf) + TileFileOpenResult fileResult = OpenMapTileFile(iBasePath, iMapID, tileX, tileY, vm); + if (fileResult.File) { char chunk[8]; - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) + if (!readChunk(fileResult.File, chunk, VMAP_MAGIC, 8)) result = false; uint32 numSpawns = 0; - if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1) + if (result && fread(&numSpawns, sizeof(uint32), 1, fileResult.File) != 1) result = false; for (uint32 i=0; isecond; if (!iLoadedSpawns.count(referencedVal)) { - if (referencedVal > iNTreeValues) + if (referencedVal >= iNTreeValues) { - VMAP_ERROR_LOG("maps", "StaticMapTree::LoadMapTile() : invalid tree element (%u/%u) referenced in tile %s", referencedVal, iNTreeValues, tilefile.c_str()); + VMAP_ERROR_LOG("maps", "StaticMapTree::LoadMapTile() : invalid tree element (%u/%u) referenced in tile %s", referencedVal, iNTreeValues, fileResult.Name.c_str()); continue; } @@ -414,7 +446,7 @@ namespace VMAP } } iLoadedTiles[packTileID(tileX, tileY)] = true; - fclose(tf); + fclose(fileResult.File); } else iLoadedTiles[packTileID(tileX, tileY)] = false; @@ -434,34 +466,33 @@ namespace VMAP } if (tile->second) // file associated with tile { - std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (tf) + TileFileOpenResult fileResult = OpenMapTileFile(iBasePath, iMapID, tileX, tileY, vm); + if (fileResult.File) { bool result=true; char chunk[8]; - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) + if (!readChunk(fileResult.File, chunk, VMAP_MAGIC, 8)) result = false; uint32 numSpawns; - if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) + if (fread(&numSpawns, sizeof(uint32), 1, fileResult.File) != 1) result = false; for (uint32 i=0; ireleaseModelInstance(spawn.name); // update tree - uint32 referencedNode; - - if (fread(&referencedNode, sizeof(uint32), 1, tf) != 1) + auto spawnIndex = iSpawnIndices.find(spawn.ID); + if (spawnIndex == iSpawnIndices.end()) result = false; else { + uint32 referencedNode = spawnIndex->second; if (!iLoadedSpawns.count(referencedNode)) VMAP_ERROR_LOG("misc", "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); else if (--iLoadedSpawns[referencedNode] == 0) @@ -472,7 +503,7 @@ namespace VMAP } } } - fclose(tf); + fclose(fileResult.File); } } iLoadedTiles.erase(tile); diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h index 0c99534dda..7cc56813d9 100644 --- a/src/common/Collision/Maps/MapTree.h +++ b/src/common/Collision/Maps/MapTree.h @@ -51,23 +51,32 @@ namespace VMAP BIH iTree; ModelInstance* iTreeValues; // the tree entries uint32 iNTreeValues; + std::unordered_map iSpawnIndices; // Store all the map tile idents that are loaded for that map // some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed // empty tiles have no tile file, hence map with bool instead of just a set (consistency check) loadedTileMap iLoadedTiles; + std::vector> iLoadedPrimaryTiles; // stores to invalidate tree values, unload map, and to be able to report errors loadedSpawnMap iLoadedSpawns; std::string iBasePath; + struct TileFileOpenResult + { + FILE* File; + std::string Name; + }; + private: + static TileFileOpenResult OpenMapTileFile(std::string const& basePath, uint32 mapID, uint32 tileX, uint32 tileY, VMapManager2* vm); bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const; //bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); } public: static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY); static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX<<16 | tileY; } - static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY) { tileX = ID>>16; tileY = ID&0xFF; } - static LoadResult CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY); + static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY) { tileX = ID >> 16; tileY = ID & 0xFF; } + static LoadResult CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY, VMapManager2* vm); StaticMapTree(uint32 mapID, const std::string &basePath); ~StaticMapTree(); diff --git a/src/common/Collision/Maps/TileAssembler.cpp b/src/common/Collision/Maps/TileAssembler.cpp index 84e759383f..00ac2b263f 100644 --- a/src/common/Collision/Maps/TileAssembler.cpp +++ b/src/common/Collision/Maps/TileAssembler.cpp @@ -84,7 +84,7 @@ namespace VMAP if (entry->second.flags & MOD_M2) { if (!calculateTransformedBound(entry->second)) - break; + continue; } else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ { @@ -92,7 +92,7 @@ namespace VMAP //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); } - mapSpawns.push_back(&(entry->second)); + mapSpawns.push_back(&entry->second); spawnedModelFiles.insert(entry->second.name); } @@ -110,10 +110,6 @@ namespace VMAP } // ===> possibly move this code to StaticMapTree class - std::map modelNodeIdx; - for (uint32 i=0; i(mapSpawns[i]->ID, i)); - // write map tree file std::stringstream mapfilename; mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree"; @@ -139,7 +135,17 @@ namespace VMAP for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob) { - success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); + success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second.Id]); + } + + // spawn id to index map + if (success && fwrite("SIDX", 4, 1, mapfile) != 1) success = false; + uint32 mapSpawnsSize = mapSpawns.size(); + if (success && fwrite(&mapSpawnsSize, sizeof(uint32), 1, mapfile) != 1) success = false; + for (uint32 i = 0; i < mapSpawnsSize; ++i) + { + if (success && fwrite(&mapSpawns[i]->ID, sizeof(uint32), 1, mapfile) != 1) success = false; + if (success && fwrite(&i, sizeof(uint32), 1, mapfile) != 1) success = false; } fclose(mapfile); @@ -151,8 +157,9 @@ namespace VMAP TileMap::iterator tile; for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) { - const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second]; - if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... + if (tile->second.Flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... + continue; + if (tile->second.Flags & MOD_PARENT_SPAWN) // tile belongs to parent map continue; uint32 nSpawns = tileEntries.count(tile->first); std::stringstream tilefilename; @@ -172,16 +179,12 @@ namespace VMAP { if (s) ++tile; - const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second]; + const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second.Id]; success = success && ModelSpawn::writeToFile(tilefile, spawn2); - // MapTree nodes to update when loading tile: - std::map::iterator nIdx = modelNodeIdx.find(spawn2.ID); - if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; } fclose(tilefile); } } - // break; //test, extract only first map; TODO: remvoe this line } // add an object models, listed in temp_gameobject_models file @@ -238,9 +241,9 @@ namespace VMAP printf("spawning Map %u\n", mapID); mapData[mapID] = current = new MapSpawns(); } - else current = (*map_iter).second; + else current = map_iter->second; current->UniqueEntries.insert(pair(spawn.ID, spawn)); - current->TileEntries.insert(pair(StaticMapTree::packTileID(tileX, tileY), spawn.ID)); + current->TileEntries.insert(pair(StaticMapTree::packTileID(tileX, tileY), TileSpawn{ spawn.ID, spawn.flags })); } bool success = (ferror(dirf) == 0); fclose(dirf); diff --git a/src/common/Collision/Maps/TileAssembler.h b/src/common/Collision/Maps/TileAssembler.h index f370bb638b..8c3b3f5b88 100644 --- a/src/common/Collision/Maps/TileAssembler.h +++ b/src/common/Collision/Maps/TileAssembler.h @@ -52,8 +52,14 @@ namespace VMAP void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; } }; + struct TileSpawn + { + uint32 Id; + uint32 Flags; + }; + typedef std::map UniqueEntryMap; - typedef std::multimap TileMap; + typedef std::multimap TileMap; struct TC_COMMON_API MapSpawns { diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp index 9643f02907..219026c12e 100644 --- a/src/common/Collision/Models/GameObjectModel.cpp +++ b/src/common/Collision/Models/GameObjectModel.cpp @@ -152,12 +152,12 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr const& phases, VMAP::ModelIgnoreFlags ignoreFlags) const +bool GameObjectModel::intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift, VMAP::ModelIgnoreFlags ignoreFlags) const { if (!isCollisionEnabled() || !owner->IsSpawned()) return false; - if (!owner->IsInPhase(phases)) + if (!owner->IsInPhase(phaseShift)) return false; float time = ray.intersectionTime(iBound); diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index e0de8ea7a1..a8dd854775 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -26,7 +26,6 @@ #include "Define.h" #include -#include namespace VMAP { @@ -35,6 +34,7 @@ namespace VMAP } class GameObject; +class PhaseShift; struct GameObjectDisplayInfoEntry; class TC_COMMON_API GameObjectModelOwnerBase @@ -42,7 +42,7 @@ class TC_COMMON_API GameObjectModelOwnerBase public: virtual bool IsSpawned() const { return false; } virtual uint32 GetDisplayId() const { return 0; } - virtual bool IsInPhase(std::set const& /*phases*/) const { return false; } + virtual bool IsInPhase(PhaseShift const& /*phaseShift*/) const { return false; } virtual G3D::Vector3 GetPosition() const { return G3D::Vector3::zero(); } virtual float GetOrientation() const { return 0.0f; } virtual float GetScale() const { return 1.0f; } @@ -66,7 +66,7 @@ public: void enableCollision(bool enable) { _collisionEnabled = enable; } bool isCollisionEnabled() const { return _collisionEnabled; } - bool intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, std::set const& phases, VMAP::ModelIgnoreFlags ignoreFlags) const; + bool intersectRay(G3D::Ray const& ray, float& maxDist, bool stopAtFirstHit, PhaseShift const& phaseShift, VMAP::ModelIgnoreFlags ignoreFlags) const; static GameObjectModel* Create(std::unique_ptr modelOwner, std::string const& dataPath); diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h index 80118b9a9c..1a9a2ab3ff 100644 --- a/src/common/Collision/Models/ModelInstance.h +++ b/src/common/Collision/Models/ModelInstance.h @@ -36,8 +36,9 @@ namespace VMAP enum ModelFlags { MOD_M2 = 1, - MOD_WORLDSPAWN = 1<<1, - MOD_HAS_BOUND = 1<<2 + MOD_WORLDSPAWN = 1 << 1, + MOD_HAS_BOUND = 1 << 2, + MOD_PARENT_SPAWN = 1 << 3 }; class TC_COMMON_API ModelSpawn diff --git a/src/common/Collision/VMapDefinitions.h b/src/common/Collision/VMapDefinitions.h index 22885ec385..5410eb2130 100644 --- a/src/common/Collision/VMapDefinitions.h +++ b/src/common/Collision/VMapDefinitions.h @@ -25,8 +25,8 @@ namespace VMAP { - const char VMAP_MAGIC[] = "VMAP_4.4"; - const char RAW_VMAP_MAGIC[] = "VMAP044"; // used in extracted vmap files with raw data + const char VMAP_MAGIC[] = "VMAP_4.5"; + const char RAW_VMAP_MAGIC[] = "VMAP045"; // used in extracted vmap files with raw data const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; // defined in TileAssembler.cpp currently... diff --git a/src/server/shared/DataStores/DBCFileLoader.cpp b/src/common/DataStores/DBCFileLoader.cpp similarity index 100% rename from src/server/shared/DataStores/DBCFileLoader.cpp rename to src/common/DataStores/DBCFileLoader.cpp diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/common/DataStores/DBCFileLoader.h similarity index 92% rename from src/server/shared/DataStores/DBCFileLoader.h rename to src/common/DataStores/DBCFileLoader.h index 708a34156b..377ef8cafc 100644 --- a/src/server/shared/DataStores/DBCFileLoader.h +++ b/src/common/DataStores/DBCFileLoader.h @@ -47,6 +47,13 @@ class TC_SHARED_API DBCFileLoader EndianConvert(val); return val; } + int32 getInt(size_t field) const + { + assert(field < file.fieldCount); + int32 val = *reinterpret_cast(offset + file.GetOffset(field)); + EndianConvert(val); + return val; + } uint8 getUInt8(size_t field) const { assert(field < file.fieldCount); diff --git a/src/common/Debugging/WheatyExceptionReport.cpp b/src/common/Debugging/WheatyExceptionReport.cpp index 657ce5886a..b2f3c692dc 100644 --- a/src/common/Debugging/WheatyExceptionReport.cpp +++ b/src/common/Debugging/WheatyExceptionReport.cpp @@ -55,6 +55,7 @@ inline LPTSTR ErrorMessage(DWORD dw) TCHAR WheatyExceptionReport::m_szLogFileName[MAX_PATH]; TCHAR WheatyExceptionReport::m_szDumpFileName[MAX_PATH]; LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter; +_invalid_parameter_handler WheatyExceptionReport::m_previousCrtHandler; HANDLE WheatyExceptionReport::m_hReportFile; HANDLE WheatyExceptionReport::m_hDumpFile; HANDLE WheatyExceptionReport::m_hProcess; @@ -75,6 +76,7 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor { // Install the unhandled exception filter function m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); + m_previousCrtHandler = _set_invalid_parameter_handler(WheatyCrtHandler); m_hProcess = GetCurrentProcess(); stackOverflowException = false; alreadyCrashed = false; @@ -95,6 +97,8 @@ WheatyExceptionReport::~WheatyExceptionReport() { if (m_previousFilter) SetUnhandledExceptionFilter(m_previousFilter); + if (m_previousCrtHandler) + _set_invalid_parameter_handler(m_previousCrtHandler); ClearSymbols(); } @@ -183,6 +187,11 @@ PEXCEPTION_POINTERS pExceptionInfo) return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/; } +void __cdecl WheatyExceptionReport::WheatyCrtHandler(wchar_t const* /*expression*/, wchar_t const* /*function*/, wchar_t const* /*file*/, unsigned int /*line*/, uintptr_t /*pReserved*/) +{ + RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, nullptr); +} + BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount) { if (!sProcessorName) diff --git a/src/common/Debugging/WheatyExceptionReport.h b/src/common/Debugging/WheatyExceptionReport.h index 6c2406882c..42d4d3e0a2 100644 --- a/src/common/Debugging/WheatyExceptionReport.h +++ b/src/common/Debugging/WheatyExceptionReport.h @@ -155,6 +155,8 @@ class WheatyExceptionReport static LONG WINAPI WheatyUnhandledExceptionFilter( PEXCEPTION_POINTERS pExceptionInfo); + static void __cdecl WheatyCrtHandler(wchar_t const* expression, wchar_t const* function, wchar_t const* file, unsigned int line, uintptr_t pReserved); + static void printTracesForAllThreads(bool); private: // where report info is extracted and generated @@ -192,6 +194,7 @@ class WheatyExceptionReport static TCHAR m_szLogFileName[MAX_PATH]; static TCHAR m_szDumpFileName[MAX_PATH]; static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; + static _invalid_parameter_handler m_previousCrtHandler; static HANDLE m_hReportFile; static HANDLE m_hDumpFile; static HANDLE m_hProcess; diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index 3e578cf1ee..4ed5b69997 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -21,6 +21,16 @@ char const* GitRevision::GetCMakeCommand() return _CMAKE_COMMAND; } +char const* GitRevision::GetCMakeVersion() +{ + return _CMAKE_VERSION; +} + +char const* GitRevision::GetHostOSVersion() +{ + return _CMAKE_HOST_SYSTEM; +} + char const* GitRevision::GetBuildDirectory() { return _BUILD_DIRECTORY; diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h index b4e29cbd54..131078ce86 100644 --- a/src/common/GitRevision.h +++ b/src/common/GitRevision.h @@ -27,6 +27,8 @@ namespace GitRevision TC_COMMON_API char const* GetDate(); TC_COMMON_API char const* GetBranch(); TC_COMMON_API char const* GetCMakeCommand(); + TC_COMMON_API char const* GetCMakeVersion(); + TC_COMMON_API char const* GetHostOSVersion(); TC_COMMON_API char const* GetBuildDirectory(); TC_COMMON_API char const* GetSourceDirectory(); TC_COMMON_API char const* GetMySQLExecutable(); diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h index db762a67d0..c6c9c58b25 100644 --- a/src/common/Utilities/Containers.h +++ b/src/common/Utilities/Containers.h @@ -132,7 +132,7 @@ namespace Trinity * Note: container cannot be empty */ template - auto SelectRandomWeightedContainerElement(C const& container, Fn weightExtractor) -> decltype(std::begin(container)) + inline auto SelectRandomWeightedContainerElement(C const& container, Fn weightExtractor) -> decltype(std::begin(container)) { std::vector weights; weights.reserve(Size(container)); @@ -175,7 +175,7 @@ namespace Trinity * @return true if containers have a common element, false otherwise. */ template - bool Intersects(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) + inline bool Intersects(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) { while (first1 != last1 && first2 != last2) { @@ -190,6 +190,37 @@ namespace Trinity return false; } + /** + * @fn bool Trinity::Containers::Intersects(Iterator first1, Iterator last1, Iterator first2, Iterator last2, Predicate&& equalPred) + * + * @brief Checks if two SORTED containers have a common element + * + * @param first1 Iterator pointing to start of the first container + * @param last1 Iterator pointing to end of the first container + * @param first2 Iterator pointing to start of the second container + * @param last2 Iterator pointing to end of the second container + * @param equalPred Additional predicate to exclude elements + * + * @return true if containers have a common element, false otherwise. + */ + template + inline bool Intersects(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2, Predicate&& equalPred) + { + while (first1 != last1 && first2 != last2) + { + if (*first1 < *first2) + ++first1; + else if (*first2 < *first1) + ++first2; + else if (!equalPred(*first1, *first2)) + ++first1, ++first2; + else + return true; + } + + return false; + } + /** * Returns a pointer to mapped value (or the value itself if map stores pointers) */ @@ -201,7 +232,7 @@ namespace Trinity } template class M, class... Rest> - void MultimapErasePair(M& multimap, K const& key, V const& value) + inline void MultimapErasePair(M& multimap, K const& key, V const& value) { auto range = multimap.equal_range(key); for (auto itr = range.first; itr != range.second; ) diff --git a/src/common/Utilities/EnumClassFlag.h b/src/common/Utilities/EnumClassFlag.h new file mode 100644 index 0000000000..68ee56edb0 --- /dev/null +++ b/src/common/Utilities/EnumClassFlag.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008-2018 TrinityCore + * + * 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 . + */ + +#ifndef EnumClassFlag_h__ +#define EnumClassFlag_h__ + +#include + +template +class EnumClassFlag +{ + static_assert(std::is_enum::value, "EnumClassFlag must be used only with enums"); + +public: + /*implicit*/ EnumClassFlag(T value) : _value(value) { } + + EnumClassFlag& operator&=(EnumClassFlag right) + { + _value = static_cast(static_cast>(_value) & static_cast>(right._value)); + return *this; + } + + friend EnumClassFlag operator&(EnumClassFlag left, EnumClassFlag right) + { + return left &= right; + } + + EnumClassFlag operator|=(EnumClassFlag right) + { + _value = static_cast(static_cast>(_value) | static_cast>(right._value)); + return *this; + } + + friend EnumClassFlag operator|(EnumClassFlag left, EnumClassFlag right) + { + return left |= right; + } + + EnumClassFlag operator~() const + { + return static_cast(~static_cast>(_value)); + } + + void RemoveFlag(EnumClassFlag flag) + { + _value = static_cast(static_cast>(_value) & ~static_cast>(flag._value)); + } + + bool HasFlag(T flag) const + { + return (static_cast>(_value) & static_cast>(flag)) != 0; + } + + operator T() const + { + return _value; + } + + std::underlying_type_t AsUnderlyingType() const + { + return static_cast>(_value); + } + +private: + T _value; +}; + +#endif // EnumClassFlag_h__ diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 748c90935a..167beaa35b 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -29,6 +29,7 @@ #include "Language.h" #include "ObjectDefines.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" #include "SmartAI.h" @@ -1130,7 +1131,12 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - (*itr)->SetInPhase(e.action.ingamePhaseId.id, true, e.action.ingamePhaseId.apply == 1); + { + if (e.action.ingamePhaseId.apply == 1) + PhasingHandler::AddPhase(*itr, e.action.ingamePhaseId.id, true); + else + PhasingHandler::RemovePhase(*itr, e.action.ingamePhaseId.id, true); + } delete targets; break; @@ -1142,11 +1148,13 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!targets) break; - std::set const& phases = GetPhasesForGroup(e.action.ingamePhaseGroup.groupId); - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - for (auto phase : phases) - (*itr)->SetInPhase(phase, true, e.action.ingamePhaseGroup.apply == 1); + { + if (e.action.ingamePhaseGroup.apply == 1) + PhasingHandler::AddPhaseGroup(*itr, e.action.ingamePhaseGroup.groupId, true); + else + PhasingHandler::RemovePhaseGroup(*itr, e.action.ingamePhaseGroup.groupId, true); + } delete targets; break; @@ -3366,6 +3374,8 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if ((e.event.los.noHostile && !me->IsHostileTo(unit)) || (!e.event.los.noHostile && me->IsHostileTo(unit))) { + if (e.event.los.playerOnly && unit->GetTypeId() != TYPEID_PLAYER) + return; RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax); ProcessAction(e, unit); } @@ -3386,6 +3396,8 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if ((e.event.los.noHostile && !me->IsHostileTo(unit)) || (!e.event.los.noHostile && me->IsHostileTo(unit))) { + if (e.event.los.playerOnly && unit->GetTypeId() != TYPEID_PLAYER) + return; RecalcTimer(e, e.event.los.cooldownMin, e.event.los.cooldownMax); ProcessAction(e, unit); } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 389e95ba3e..19dfe811dd 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -1326,7 +1326,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; } - if (phaseGroup && GetPhasesForGroup(phaseGroup).empty()) + if (phaseGroup && GetPhasesForGroup(phaseGroup)) { TC_LOG_ERROR("sql.sql", "SmartScript: SMART_ACTION_SET_INGAME_PHASE_GROUP uses invalid phase group id %u for creature %u, skipped", phaseGroup, e.entryOrGuid); return false; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index a93d0227b8..661616fbb2 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -226,6 +226,7 @@ struct SmartEvent uint32 maxDist; uint32 cooldownMin; uint32 cooldownMax; + uint32 playerOnly; } los; struct diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 928fe49779..23c873c9a8 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -767,6 +767,9 @@ enum RBACPermissions RBAC_PERM_COMMAND_RELOAD_QUEST_GREETING_LOCALE = 867, RBAC_PERM_COMMAND_MODIFY_POWER = 868, // reserved RBAC_PERM_COMMAND_DEBUG_SEND_PLAYER_CHOICE = 869, // reserved + RBAC_PERM_COMMAND_DEBUG_THREATINFO = 870, + RBAC_PERM_COMMAND_DEBUG_INSTANCESPAWN = 871, + RBAC_PERM_COMMAND_SERVER_DEBUG = 872, // // IF YOU ADD NEW PERMISSIONS, ADD THEM IN MASTER BRANCH AS WELL! // diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 0c4deab3b3..9b563b716c 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -1208,7 +1208,7 @@ LocaleConstant ChatHandler::GetSessionDbcLocale() const return m_session->GetSessionDbcLocale(); } -int ChatHandler::GetSessionDbLocaleIndex() const +LocaleConstant ChatHandler::GetSessionDbLocaleIndex() const { return m_session->GetSessionDbLocaleIndex(); } @@ -1304,7 +1304,7 @@ LocaleConstant CliHandler::GetSessionDbcLocale() const return sWorld->GetDefaultDbcLocale(); } -int CliHandler::GetSessionDbLocaleIndex() const +LocaleConstant CliHandler::GetSessionDbLocaleIndex() const { return sObjectMgr->GetDBCLocaleIndex(); } diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 7b6cb6ebe9..ef6c5b2c66 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -112,7 +112,7 @@ class TC_GAME_API ChatHandler virtual std::string GetNameLink() const { return GetNameLink(m_session->GetPlayer()); } virtual bool needReportToTarget(Player* chr) const; virtual LocaleConstant GetSessionDbcLocale() const; - virtual int GetSessionDbLocaleIndex() const; + virtual LocaleConstant GetSessionDbLocaleIndex() const; bool HasLowerSecurity(Player* target, ObjectGuid guid, bool strong = false); bool HasLowerSecurityAccount(WorldSession* target, uint32 account, bool strong = false); @@ -178,7 +178,7 @@ class TC_GAME_API CliHandler : public ChatHandler std::string GetNameLink() const override; bool needReportToTarget(Player* chr) const override; LocaleConstant GetSessionDbcLocale() const override; - int GetSessionDbLocaleIndex() const override; + LocaleConstant GetSessionDbLocaleIndex() const override; private: void* m_callbackArg; diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 9f2a16f3a9..2f0efa9ab1 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -21,6 +21,7 @@ #include "GameEventMgr.h" #include "InstanceScript.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "Player.h" #include "Pet.h" #include "ReputationMgr.h" @@ -402,7 +403,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const } case CONDITION_PHASEID: { - condMeets = object->IsInPhase(ConditionValue1); + condMeets = object->GetPhaseShift().HasPhase(ConditionValue1); break; } case CONDITION_TITLE: @@ -430,7 +431,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const } case CONDITION_TERRAIN_SWAP: { - condMeets = object->IsInTerrainSwap(ConditionValue1); + condMeets = object->GetPhaseShift().HasVisibleMapId(ConditionValue1); break; } case CONDITION_REALM_ACHIEVEMENT: @@ -1040,17 +1041,7 @@ void ConditionMgr::LoadConditions(bool isReload) sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists(); - TC_LOG_INFO("misc", "Re-Loading `terrain_phase_info` Table for Conditions!"); - sObjectMgr->LoadTerrainPhaseInfo(); - - TC_LOG_INFO("misc", "Re-Loading `terrain_swap_defaults` Table for Conditions!"); - sObjectMgr->LoadTerrainSwapDefaults(); - - TC_LOG_INFO("misc", "Re-Loading `terrain_worldmap` Table for Conditions!"); - sObjectMgr->LoadTerrainWorldMaps(); - - TC_LOG_INFO("misc", "Re-Loading `phase_area` Table for Conditions!"); - sObjectMgr->LoadAreaPhases(); + sObjectMgr->UnloadPhaseConditions(); } QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, " @@ -1337,17 +1328,44 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const std::list sharedMasks; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - // check if effect is already a part of some shared mask - bool found = false; - for (std::list::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr) + // additional checks by condition type + if (conditionEffMask & (1 << i)) { - if ((1<ConditionType) { - found = true; - break; + case CONDITION_OBJECT_ENTRY_GUID: + { + uint32 implicitTargetMask = GetTargetFlagMask(spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(spellInfo->Effects[i].TargetB.GetObjectType()); + if ((implicitTargetMask & TARGET_FLAG_UNIT_MASK) && cond->ConditionValue1 != TYPEID_UNIT && cond->ConditionValue1 != TYPEID_PLAYER) + { + TC_LOG_ERROR("sql.sql", "%s in `condition` table - spell %u EFFECT_%u - " + "target requires ConditionValue1 to be either TYPEID_UNIT (%u) or TYPEID_PLAYER (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(i), uint32(TYPEID_UNIT), uint32(TYPEID_PLAYER)); + return false; + } + + if ((implicitTargetMask & TARGET_FLAG_GAMEOBJECT_MASK) && cond->ConditionValue1 != TYPEID_GAMEOBJECT) + { + TC_LOG_ERROR("sql.sql", "%s in `condition` table - spell %u EFFECT_%u - " + "target requires ConditionValue1 to be TYPEID_GAMEOBJECT (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(i), uint32(TYPEID_GAMEOBJECT)); + return false; + } + + if ((implicitTargetMask & TARGET_FLAG_CORPSE_MASK) && cond->ConditionValue1 != TYPEID_CORPSE) + { + TC_LOG_ERROR("sql.sql", "%s in `condition` table - spell %u EFFECT_%u - " + "target requires ConditionValue1 to be TYPEID_CORPSE (%u)", cond->ToString().c_str(), spellInfo->Id, uint32(i), uint32(TYPEID_CORPSE)); + return false; + } + break; + } + default: + break; } } - if (found) + + // check if effect is already a part of some shared mask + auto itr = std::find_if(sharedMasks.begin(), sharedMasks.end(), [i](uint32 mask) { return !!(mask & (1 << i)); }); + if (itr != sharedMasks.end()) continue; // build new shared mask with found effect @@ -1361,14 +1379,14 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const sharedMasks.push_back(sharedMask); } - for (std::list::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr) + for (uint32 effectMask : sharedMasks) { // some effect indexes should have same data - if (uint32 commonMask = *itr & conditionEffMask) + if (uint32 commonMask = effectMask & conditionEffMask) { uint8 firstEffIndex = 0; for (; firstEffIndex < MAX_SPELL_EFFECTS; ++firstEffIndex) - if ((1<= MAX_SPELL_EFFECTS) @@ -1381,7 +1399,7 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const if (sharedList) { // we have overlapping masks in db - if (conditionEffMask != *itr) + if (conditionEffMask != effectMask) { TC_LOG_ERROR("sql.sql", "%s in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - " "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->ToString().c_str(), cond->SourceGroup); @@ -1396,7 +1414,7 @@ bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const bool assigned = false; for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i) { - if ((1<Effects[i].ImplicitTargetConditions = sharedList; assigned = true; @@ -1417,24 +1435,32 @@ bool ConditionMgr::addToPhases(Condition* cond) const { if (!cond->SourceEntry) { - PhaseInfo& p = sObjectMgr->GetAreaPhasesForLoading(); - for (auto phaseItr = p.begin(); phaseItr != p.end(); ++phaseItr) + if (PhaseInfoStruct const* phaseInfo = sObjectMgr->GetPhaseInfo(cond->SourceGroup)) { - for (PhaseInfoStruct& phase : phaseItr->second) + bool found = false; + for (uint32 areaId : phaseInfo->Areas) { - if (phase.Id == cond->SourceGroup) + if (std::vector* phases = const_cast*>(sObjectMgr->GetPhasesForArea(areaId))) { - phase.Conditions.push_back(cond); - return true; + for (PhaseAreaInfo& phase : *phases) + { + if (phase.PhaseInfo->Id == cond->SourceGroup) + { + phase.Conditions.push_back(cond); + found = true; + } + } } } + if (found) + return true; } } - else if (std::vector* phases = sObjectMgr->GetPhasesForAreaForLoading(cond->SourceEntry)) + else if (std::vector* phases = const_cast*>(sObjectMgr->GetPhasesForArea(cond->SourceEntry))) { - for (PhaseInfoStruct& phase : *phases) + for (PhaseAreaInfo& phase : *phases) { - if (phase.Id == cond->SourceGroup) + if (phase.PhaseInfo->Id == cond->SourceGroup) { phase.Conditions.push_back(cond); return true; diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 21f2a4a5d6..e8a8c2f70a 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -466,6 +466,23 @@ enum MountCapabilityFlags MOUNT_CAPABIILTY_FLAG_IGNORE_RESTRICTIONS = 0x20, }; +enum PhaseEntryFlags : uint16 +{ + PHASE_FLAG_NORMAL = 0x08, + PHASE_FLAG_COSMETIC = 0x10, + PHASE_FLAG_PERSONAL = 0x20 +}; + +// PhaseUseFlags fields in different DBCs +enum PhaseUseFlagsValues : uint8 +{ + PHASE_USE_FLAGS_NONE = 0x0, + PHASE_USE_FLAGS_ALWAYS_VISIBLE = 0x1, + PHASE_USE_FLAGS_INVERSE = 0x2, + + PHASE_USE_FLAGS_ALL = PHASE_USE_FLAGS_ALWAYS_VISIBLE | PHASE_USE_FLAGS_INVERSE +}; + enum SkillRaceClassInfoFlags { SKILL_FLAG_NO_SKILLUP_MESSAGE = 0x2, diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 240dc156ed..6a608eff84 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -558,7 +558,7 @@ void LoadDBCStores(const std::string& dataPath) for (uint32 i = 0; i < sPhaseGroupStore.GetNumRows(); ++i) if (PhaseGroupEntry const* group = sPhaseGroupStore.LookupEntry(i)) if (PhaseEntry const* phase = sPhaseStore.LookupEntry(group->PhaseId)) - sPhasesByGroup[group->GroupId].insert(phase->ID); + sPhasesByGroup[group->GroupId].push_back(phase->ID); LoadDBC(availableDbcLocales, bad_dbc_files, sPowerDisplayStore, dbcPath, "PowerDisplay.dbc"); @@ -1360,9 +1360,9 @@ SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, u return NULL; } -std::set const& GetPhasesForGroup(uint32 group) +std::vector const* GetPhasesForGroup(uint32 group) { - return sPhasesByGroup[group]; + return &sPhasesByGroup[group]; } ResponseCodes ValidateName(std::wstring const& name, LocaleConstant locale) diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 05833b0552..448a64759e 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -81,7 +81,7 @@ TC_GAME_API LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty diffic uint32 GetDefaultMapLight(uint32 mapId); -TC_GAME_API std::set const& GetPhasesForGroup(uint32 group); +TC_GAME_API std::vector const* GetPhasesForGroup(uint32 group); typedef std::unordered_multimap SkillRaceClassInfoMap; typedef std::pair SkillRaceClassInfoBounds; @@ -254,7 +254,7 @@ TC_GAME_API extern DBCStorage sUnitPowerBarStore; TC_GAME_API extern DBCStorage sVehicleStore; TC_GAME_API extern DBCStorage sVehicleSeatStore; TC_GAME_API extern DBCStorage sWMOAreaTableStore; -//TC_GAME_API extern DBCStorage sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates +TC_GAME_API extern DBCStorage sWorldMapAreaStore; TC_GAME_API extern DBCStorage sWorldMapOverlayStore; TC_GAME_API extern DBCStorage sWorldSafeLocsStore; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index d96ffdf662..11c81bacaa 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -1604,7 +1604,7 @@ struct PhaseEntry { uint32 ID; // 0 char* Name; // 1 - uint32 flag; // 2 + uint32 Flags; // 2 }; struct PhaseGroupEntry @@ -2737,5 +2737,5 @@ typedef std::vector TaxiPathNodesByPath; #define TaxiMaskSize 114 typedef uint8 TaxiMask[TaxiMaskSize]; -typedef std::unordered_map> PhaseGroupContainer; +typedef std::unordered_map> PhaseGroupContainer; #endif diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp index e362e1d555..42e78d066d 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp @@ -16,6 +16,7 @@ */ #include "ObjectAccessor.h" +#include "PhasingHandler.h" #include "Unit.h" #include "SpellInfo.h" #include "Log.h" @@ -78,7 +79,7 @@ bool AreaTrigger::CreateAreaTrigger(uint32 guidlow, uint32 triggerEntry, Unit* c SetFloatValue(AREATRIGGER_FINAL_POS + 1, pos.GetPositionY()); SetFloatValue(AREATRIGGER_FINAL_POS + 2, pos.GetPositionZ()); - CopyPhaseFrom(caster); + PhasingHandler::InheritPhaseShift(this, caster); if (!GetMap()->AddToMap(this)) return false; diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index f7be38c88e..83df48db00 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -22,6 +22,7 @@ #include "Player.h" #include "UpdateMask.h" #include "ObjectAccessor.h" +#include "PhasingHandler.h" #include "DatabaseEnv.h" #include "World.h" @@ -86,7 +87,7 @@ bool Corpse::Create(ObjectGuid::LowType guidlow, Player* owner) _cellCoord = Trinity::ComputeCellCoord(GetPositionX(), GetPositionY()); - CopyPhaseFrom(owner); + PhasingHandler::InheritPhaseShift(this, owner); return true; } @@ -116,12 +117,12 @@ void Corpse::SaveToDB() stmt->setUInt32(index++, GetInstanceId()); // instanceId trans->Append(stmt); - for (uint32 phaseId : GetPhases()) + for (PhaseShift::PhaseRef const& phase : GetPhaseShift().GetPhases()) { index = 0; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CORPSE_PHASES); stmt->setUInt32(index++, GetOwnerGUID().GetCounter()); // OwnerGuid - stmt->setUInt32(index++, phaseId); // PhaseId + stmt->setUInt32(index++, phase.Id); // PhaseId trans->Append(stmt); } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 22ff2f4b66..dd8a89960a 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -37,6 +37,7 @@ #include "LootMgr.h" #include "MoveSpline.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "Player.h" #include "PoolMgr.h" #include "QuestDef.h" @@ -897,12 +898,11 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 /*phaseMask* ASSERT(map); SetMap(map); - if (data && data->phaseid) - SetInPhase(data->phaseid, false, true); - - if (data && data->phaseGroup) - for (auto ph : GetPhasesForGroup(data->phaseGroup)) - SetInPhase(ph, false, true); + if (data) + { + PhasingHandler::InitDbPhaseShift(GetPhaseShift(), data->phaseUseFlags, data->phaseId, data->phaseGroup); + PhasingHandler::InitDbVisibleMapId(GetPhaseShift(), data->terrainSwapMap); + } CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry); if (!cinfo) @@ -1166,7 +1166,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) data.unit_flags = unit_flags; data.dynamicflags = dynamicflags; - data.phaseid = GetDBPhase() > 0 ? GetDBPhase() : 0; + data.phaseId = GetDBPhase() > 0 ? GetDBPhase() : 0; data.phaseGroup = GetDBPhase() < 0 ? abs(GetDBPhase()) : 0; // update in DB @@ -1185,7 +1185,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) stmt->setUInt16(index++, uint16(mapid)); stmt->setUInt8(index++, spawnMask); stmt->setUInt32(index++, GetPhaseMask()); - stmt->setUInt32(index++, data.phaseid); + stmt->setUInt32(index++, data.phaseId); stmt->setUInt32(index++, data.phaseGroup); stmt->setUInt32(index++, displayId); stmt->setInt32(index++, int32(GetCurrentEquipmentId())); @@ -1446,7 +1446,7 @@ bool Creature::LoadCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool ad m_deathState = DEAD; if (CanFly()) { - float tz = map->GetHeight(GetPhases(), data->posX, data->posY, data->posZ, true, MAX_FALL_DISTANCE); + float tz = map->GetHeight(GetPhaseShift(), data->posX, data->posY, data->posZ, true, MAX_FALL_DISTANCE); if (data->posZ - tz > 0.1f && Trinity::IsValidMapCoord(tz)) Relocate(data->posX, data->posY, tz); } @@ -2731,7 +2731,7 @@ void Creature::UpdateMovementFlags() return; // Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc) - float ground = GetFloorZ(); + float ground = GetMap()->GetHeight(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); bool isInAir = (G3D::fuzzyGt(GetPositionZMinusOffset(), ground + 0.05f) || G3D::fuzzyLt(GetPositionZMinusOffset(), ground - 0.05f)); // Can be underground too, prevent the falling diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 09e65048f6..505cd444b1 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -275,7 +275,8 @@ struct CreatureData CreatureData() : id(0), mapid(0), phaseMask(0), displayid(0), equipmentId(0), posX(0.0f), posY(0.0f), posZ(0.0f), orientation(0.0f), spawntimesecs(0), spawndist(0.0f), currentwaypoint(0), curhealth(0), curmana(0), movementType(0), - spawnMask(0), npcflag(0), unit_flags(0), dynamicflags(0), phaseid(0), phaseGroup(0), ScriptId(0), dbData(true) { } + spawnMask(0), npcflag(0), unit_flags(0), dynamicflags(0), phaseUseFlags(0), + phaseId(0), phaseGroup(0), terrainSwapMap(-1), ScriptId(0), dbData(true) { } uint32 id; // entry in creature_template uint16 mapid; uint32 phaseMask; @@ -295,8 +296,10 @@ struct CreatureData uint32 npcflag; uint32 unit_flags; // enum UnitFlags mask values uint32 dynamicflags; - uint32 phaseid; + uint8 phaseUseFlags; + uint32 phaseId; uint32 phaseGroup; + int32 terrainSwapMap; uint32 ScriptId; bool dbData; }; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 3da93a3553..6ae7016384 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -27,6 +27,7 @@ #include "GroupMgr.h" #include "ObjectMgr.h" #include "OutdoorPvPMgr.h" +#include "PhasingHandler.h" #include "PoolMgr.h" #include "ScriptMgr.h" #include "SpellMgr.h" @@ -907,15 +908,8 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, boo if (!Create(map->GenerateLowGuid(), entry, map, phaseMask, pos, data->rotation, animprogress, go_state, artKit)) return false; - if (data->phaseid) - SetInPhase(data->phaseid, false, true); - - if (data->phaseGroup) - { - // Set the gameobject in all the phases of the phasegroup - for (auto ph : GetPhasesForGroup(data->phaseGroup)) - SetInPhase(ph, false, true); - } + PhasingHandler::InitDbPhaseShift(GetPhaseShift(), data->phaseUseFlags, data->phaseId, data->phaseGroup); + PhasingHandler::InitDbVisibleMapId(GetPhaseShift(), data->terrainSwapMap); if (data->spawntimesecs >= 0) { @@ -2476,7 +2470,6 @@ public: virtual bool IsSpawned() const override { return _owner->isSpawned(); } virtual uint32 GetDisplayId() const override { return _owner->GetDisplayId(); } - virtual bool IsInPhase(std::set const& phases) const override { return _owner->IsInPhase(phases); } virtual G3D::Vector3 GetPosition() const override { return G3D::Vector3(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); } virtual float GetOrientation() const override { return _owner->GetOrientation(); } virtual float GetScale() const override { return _owner->GetObjectScale(); } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index c2076a13ac..5780342bab 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -644,7 +644,8 @@ enum GOState struct GameObjectData { explicit GameObjectData() : id(0), mapid(0), phaseMask(0), posX(0.0f), posY(0.0f), posZ(0.0f), orientation(0.0f), spawntimesecs(0), - animprogress(0), go_state(GO_STATE_ACTIVE), spawnMask(0), artKit(0), phaseid(0), phaseGroup(0), ScriptId(0), dbData(true) { } + animprogress(0), go_state(GO_STATE_ACTIVE), spawnMask(0), artKit(0), phaseUseFlags(0), phaseId(0), + phaseGroup(0), terrainSwapMap(-1), ScriptId(0), dbData(true) { } uint32 id; // entry in gamobject_template uint16 mapid; uint32 phaseMask; @@ -658,8 +659,10 @@ struct GameObjectData GOState go_state; uint8 spawnMask; uint8 artKit; - uint32 phaseid; + uint8 phaseUseFlags; + uint32 phaseId; uint32 phaseGroup; + int32 terrainSwapMap; uint32 ScriptId; bool dbData; }; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index b3fc0bb948..56a2056190 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -45,6 +45,7 @@ #include "TemporarySummon.h" #include "Totem.h" #include "OutdoorPvPMgr.h" +#include "PhasingHandler.h" #include "MovementPacketBuilder.h" #include "DynamicTree.h" #include "Unit.h" @@ -1298,7 +1299,7 @@ void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 void WorldObject::UpdatePositionData() { PositionFullTerrainStatus data; - GetMap()->GetFullTerrainStatusForPosition(GetPositionX(), GetPositionY(), GetPositionZ(), data); + GetMap()->GetFullTerrainStatusForPosition(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), data); ProcessPositionDataChanged(data); } @@ -1314,7 +1315,7 @@ void WorldObject::ProcessPositionDataChanged(PositionFullTerrainStatus const& da void WorldObject::AddToWorld() { Object::AddToWorld(); - GetBaseMap()->GetZoneAndAreaId(m_zoneId, m_areaId, GetPositionX(), GetPositionY(), GetPositionZ()); + GetBaseMap()->GetZoneAndAreaId(GetPhaseShift(), m_zoneId, m_areaId, GetPositionX(), GetPositionY(), GetPositionZ()); } void WorldObject::RemoveFromWorld() @@ -1464,7 +1465,7 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks ch else GetHitSpherePointFor({ ox, oy, oz }, x, y, z); - return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhases(), checks, ignoreFlags); + return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, checks, ignoreFlags); } return true; @@ -1639,7 +1640,7 @@ Position WorldObject::GetRandomPoint(const Position &srcPos, float distance) con void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const { - float new_z = GetMap()->GetHeight(GetPhases(), x, y, z + 2.0f, true); + float new_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z + 2.0f, true); if (new_z > INVALID_HEIGHT) z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface } @@ -1661,8 +1662,8 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const bool canSwim = ToCreature()->CanSwim(); float ground_z = z; float max_z = canSwim - ? GetMap()->GetWaterOrGroundLevel(GetPhases(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK)) - : ((ground_z = GetMap()->GetHeight(GetPhases(), x, y, z, true))); + ? GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK)) + : ((ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true))); if (max_z > INVALID_HEIGHT) { if (z > max_z) @@ -1673,7 +1674,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const } else { - float ground_z = GetMap()->GetHeight(GetPhases(), x, y, z, true); + float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true); if (z < ground_z) z = ground_z; } @@ -1685,7 +1686,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const if (!ToPlayer()->CanFly()) { float ground_z = z; - float max_z = GetMap()->GetWaterOrGroundLevel(GetPhases(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK)); + float max_z = GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK)); if (max_z > INVALID_HEIGHT) { if (z > max_z) @@ -1696,7 +1697,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const } else { - float ground_z = GetMap()->GetHeight(GetPhases(), x, y, z, true); + float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true); if (z < ground_z) z = ground_z; } @@ -1704,7 +1705,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const } default: { - float ground_z = GetMap()->GetHeight(GetPhases(), x, y, z, true); + float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true); if (ground_z > INVALID_HEIGHT) z = ground_z; break; @@ -2118,7 +2119,8 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert } // Set the summon to the summoner's phase - summon->CopyPhaseFrom(summoner); + if (summoner) + PhasingHandler::InheritPhaseShift(summon, summoner); summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId); @@ -2222,7 +2224,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, G3D return nullptr; } - go->CopyPhaseFrom(this); + PhasingHandler::InheritPhaseShift(go, this); go->SetRespawnTime(respawnTime); if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && summonType == GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)) //not sure how to handle this @@ -2448,8 +2450,8 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle) return; } - ground = GetMap()->GetHeight(GetPhases(), destx, desty, MAX_HEIGHT, true); - floor = GetMap()->GetHeight(GetPhases(), destx, desty, pos.m_positionZ, true); + ground = GetMap()->GetHeight(GetPhaseShift(), destx, desty, MAX_HEIGHT, true); + floor = GetMap()->GetHeight(GetPhaseShift(), destx, desty, pos.m_positionZ, true); destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor; float step = dist/10.0f; @@ -2461,8 +2463,8 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle) { destx -= step * std::cos(angle); desty -= step * std::sin(angle); - ground = GetMap()->GetHeight(GetPhases(), destx, desty, MAX_HEIGHT, true); - floor = GetMap()->GetHeight(GetPhases(), destx, desty, pos.m_positionZ, true); + ground = GetMap()->GetHeight(GetPhaseShift(), destx, desty, MAX_HEIGHT, true); + floor = GetMap()->GetHeight(GetPhaseShift(), destx, desty, pos.m_positionZ, true); destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor; } // we have correct destz now @@ -2482,8 +2484,8 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle) // @todo: replace with WorldObject::UpdateAllowedPositionZ float NormalizeZforCollision(WorldObject* obj, float x, float y, float z) { - float ground = obj->GetMap()->GetHeight(obj->GetPhases(), x, y, MAX_HEIGHT, true); - float floor = obj->GetMap()->GetHeight(obj->GetPhases(), x, y, z + 2.0f, true); + float ground = obj->GetMap()->GetHeight(obj->GetPhaseShift(), x, y, MAX_HEIGHT, true); + float floor = obj->GetMap()->GetHeight(obj->GetPhaseShift(), x, y, z + 2.0f, true); float helper = std::fabs(ground - z) <= std::fabs(floor - z) ? ground : floor; if (z > helper) // must be above ground { @@ -2493,7 +2495,7 @@ float NormalizeZforCollision(WorldObject* obj, float x, float y, float z) return z; } LiquidData liquid_status; - ZLiquidStatus res = obj->GetMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquid_status); + ZLiquidStatus res = obj->GetMap()->GetLiquidStatus(obj->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &liquid_status); if (res && liquid_status.level > helper) // water must be above ground { if (liquid_status.level > z) // z is underwater @@ -2520,7 +2522,8 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float } destz = NormalizeZforCollision(this, destx, desty, pos.GetPositionZ()); - bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(GetMapId(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f); + bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(PhasingHandler::GetTerrainMapId(GetPhaseShift(), GetMap(), pos.m_positionX, pos.m_positionY), + pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f); // collision occured if (col) @@ -2532,7 +2535,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float } // check dynamic collision - col = GetMap()->getObjectHitPos(GetPhases(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f); + col = GetMap()->getObjectHitPos(GetPhaseShift(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f); // Collided with a gameobject if (col) @@ -2575,165 +2578,6 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update) UpdateObjectVisibility(); } -bool WorldObject::HasInPhaseList(uint32 phase) -{ - return _phases.find(phase) != _phases.end(); -} - -// Updates Area based phases, does not remove phases from auras -// Phases from gm commands are not taken into calculations, they can be lost!! -void WorldObject::UpdateAreaPhase() -{ - bool updateNeeded = false; - PhaseInfo const& phases = sObjectMgr->GetAreaPhases(); - for (PhaseInfo::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) - { - uint32 areaId = itr->first; - for (PhaseInfoStruct const& phase : itr->second) - { - if (areaId == GetAreaId()) - { - if (sConditionMgr->IsObjectMeetToConditions(this, phase.Conditions)) - { - // add new phase if condition passed, true if it wasnt added before - bool up = SetInPhase(phase.Id, false, true); - if (!updateNeeded && up) - updateNeeded = true; - } - else - { - // condition failed, remove phase, true if there was something removed - bool up = SetInPhase(phase.Id, false, false); - if (!updateNeeded && up) - updateNeeded = true; - } - } - else - { - // not in area, remove phase, true if there was something removed - bool up = SetInPhase(phase.Id, false, false); - if (!updateNeeded && up) - updateNeeded = true; - } - } - } - - // do not remove a phase if it would be removed by an area but we have the same phase from an aura - if (Unit* unit = ToUnit()) - { - Unit::AuraEffectList const& auraPhaseList = unit->GetAuraEffectsByType(SPELL_AURA_PHASE); - for (Unit::AuraEffectList::const_iterator itr = auraPhaseList.begin(); itr != auraPhaseList.end(); ++itr) - { - uint32 phase = uint32((*itr)->GetMiscValueB()); - bool up = SetInPhase(phase, false, true); - if (!updateNeeded && up) - updateNeeded = true; - } - Unit::AuraEffectList const& auraPhaseGroupList = unit->GetAuraEffectsByType(SPELL_AURA_PHASE_GROUP); - for (Unit::AuraEffectList::const_iterator itr = auraPhaseGroupList.begin(); itr != auraPhaseGroupList.end(); ++itr) - { - bool up = false; - uint32 phaseGroup = uint32((*itr)->GetMiscValueB()); - std::set const& phases = GetPhasesForGroup(phaseGroup); - for (uint32 phase : phases) - up = SetInPhase(phase, false, true); - if (!updateNeeded && up) - updateNeeded = true; - } - } - - // only update visibility and send packets if there was a change in the phase list - if (updateNeeded && GetTypeId() == TYPEID_PLAYER && IsInWorld()) - ToPlayer()->GetSession()->SendSetPhaseShift(GetPhases(), GetTerrainSwaps(), GetWorldMapAreaSwaps()); - - // only update visibilty once, to prevent objects appearing for a moment while adding in multiple phases - if (updateNeeded && IsInWorld()) - UpdateObjectVisibility(); -} - -bool WorldObject::SetInPhase(uint32 id, bool update, bool apply) -{ - if (id) - { - if (apply) - { - if (HasInPhaseList(id)) // do not run the updates if we are already in this phase - return false; - - _phases.insert(id); - } - else - { - // if area phase passes the condition we should not remove it (ie: if remove called from aura remove) - // this however breaks the .mod phase command, you wont be able to remove any area based phases with it - PhaseInfo const& phases = sObjectMgr->GetAreaPhases(); - for (PhaseInfo::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) - if (itr->first == GetAreaId() || itr->first == GetZoneId()) - for (PhaseInfoStruct const& phase : itr->second) - if (id == phase.Id) - if (sConditionMgr->IsObjectMeetToConditions(this, phase.Conditions)) - return false; - - if (!HasInPhaseList(id)) // do not run the updates if we are not in this phase - return false; - - _phases.erase(id); - } - } - - RebuildTerrainSwaps(); - - if (update && IsInWorld()) - UpdateObjectVisibility(); - - return true; -} - -void WorldObject::CopyPhaseFrom(WorldObject* obj, bool update) -{ - if (!obj) - return; - - for (uint32 phase : obj->GetPhases()) - SetInPhase(phase, false, true); - - if (update && IsInWorld()) - UpdateObjectVisibility(); -} - -void WorldObject::ClearPhases(bool update) -{ - _phases.clear(); - - RebuildTerrainSwaps(); - - if (update && IsInWorld()) - UpdateObjectVisibility(); -} - -bool WorldObject::IsInPhase(std::set const& phases) const -{ - // PhaseId 169 is the default fallback phase - if (_phases.empty() && phases.empty()) - return true; - - if (_phases.empty() && phases.count(DEFAULT_PHASE) > 0) - return true; - - if (phases.empty() && _phases.count(DEFAULT_PHASE) > 0) - return true; - - return Trinity::Containers::Intersects(_phases.begin(), _phases.end(), phases.begin(), phases.end()); -} - -bool WorldObject::IsInPhase(WorldObject const* obj) const -{ - if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->IsGameMaster()) - return true; - - return IsInPhase(obj->GetPhases()); -} - void WorldObject::PlayDistanceSound(uint32 sound_id, Player* target /*= NULL*/) { WorldPacket data(SMSG_PLAY_OBJECT_SOUND, 4 + 8); @@ -2900,7 +2744,7 @@ float WorldObject::GetFloorZ() const { if (!IsInWorld()) return m_staticFloorZ; - return std::max(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhases(), GetPositionX(), GetPositionY(), GetPositionZ())); + return std::max(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ())); } template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::list&, uint32, float) const; @@ -2962,63 +2806,3 @@ void WorldObject::SetMeleeAnimKitId(uint16 animKitId) data << uint16(animKitId); SendMessageToSet(&data, true); } - -void WorldObject::RebuildTerrainSwaps() -{ - // Clear all terrain swaps, will be rebuilt below - // Reason for this is, multiple phases can have the same terrain swap, we should not remove the swap if another phase still use it - _terrainSwaps.clear(); - - // Check all applied phases for terrain swap and add it only once - for (uint32 phaseId : _phases) - { - if (std::vector const* swaps = sObjectMgr->GetPhaseTerrainSwaps(phaseId)) - { - for (uint32 const& swap : *swaps) - { - // only add terrain swaps for current map - MapEntry const* mapEntry = sMapStore.LookupEntry(swap); - if (!mapEntry || mapEntry->rootPhaseMap != int32(GetMapId())) - continue; - - if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap, this)) - _terrainSwaps.insert(swap); - } - } - } - - // get default terrain swaps, only for current map always - if (std::vector const* mapSwaps = sObjectMgr->GetDefaultTerrainSwaps(GetMapId())) - for (uint32 const& swap : *mapSwaps) - if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap, this)) - _terrainSwaps.insert(swap); - - // online players have a game client with world map display - if (GetTypeId() == TYPEID_PLAYER) - RebuildWorldMapAreaSwaps(); -} - -void WorldObject::RebuildWorldMapAreaSwaps() -{ - // Clear all world map area swaps, will be rebuilt below - _worldMapAreaSwaps.clear(); - - // get ALL default terrain swaps, if we are using it (condition is true) - // send the worldmaparea for it, to see swapped worldmaparea in client from other maps too, not just from our current - TerrainPhaseInfo const& defaults = sObjectMgr->GetDefaultTerrainSwapStore(); - for (TerrainPhaseInfo::const_iterator itr = defaults.begin(); itr != defaults.end(); ++itr) - for (uint32 const& swap : itr->second) - if (std::vector const* uiMapSwaps = sObjectMgr->GetTerrainWorldMaps(swap)) - if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap, this)) - for (uint32 worldMapAreaId : *uiMapSwaps) - _worldMapAreaSwaps.insert(worldMapAreaId); - - // Check all applied phases for world map area swaps - for (uint32 phaseId : _phases) - if (std::vector const* swaps = sObjectMgr->GetPhaseTerrainSwaps(phaseId)) - for (uint32 const& swap : *swaps) - if (std::vector const* uiMapSwaps = sObjectMgr->GetTerrainWorldMaps(swap)) - if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap, this)) - for (uint32 worldMapAreaId : *uiMapSwaps) - _worldMapAreaSwaps.insert(worldMapAreaId); -} diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 0662d7c72c..8bf0e3c3f3 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -24,10 +24,10 @@ #include "UpdateMask.h" #include "GridReference.h" #include "ObjectDefines.h" +#include "PhaseShift.h" #include "Map.h" #include "ModelIgnoreFlags.h" -#include #include #include @@ -48,8 +48,6 @@ #define NOMINAL_MELEE_RANGE 5.0f #define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players -#define DEFAULT_PHASE 169 - enum TempSummonType { TEMPSUMMON_TIMED_OR_DEAD_DESPAWN = 1, // despawns after a specified time OR when the creature disappears @@ -486,21 +484,16 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation uint32 GetInstanceId() const { return m_InstanceId; } virtual void SetPhaseMask(uint32 newPhaseMask, bool update); - virtual bool SetInPhase(uint32 id, bool update, bool apply); - void CopyPhaseFrom(WorldObject* obj, bool update = false); - void UpdateAreaPhase(); - void ClearPhases(bool update = false); - void RebuildTerrainSwaps(); - void RebuildWorldMapAreaSwaps(); - bool HasInPhaseList(uint32 phase); + bool IsInPhase(WorldObject const* obj) const + { + return GetPhaseShift().CanSee(obj->GetPhaseShift()); + } + + PhaseShift& GetPhaseShift() { return _phaseShift; } + PhaseShift const& GetPhaseShift() const { return _phaseShift; } + PhaseShift& GetSuppressedPhaseShift() { return _suppressedPhaseShift; } + PhaseShift const& GetSuppressedPhaseShift() const { return _suppressedPhaseShift; } uint32 GetPhaseMask() const { return m_phaseMask; } - bool IsInPhase(uint32 phase) const { return _phases.find(phase) != _phases.end(); } - bool IsInPhase(std::set const& phases) const; - bool IsInPhase(WorldObject const* obj) const; - bool IsInTerrainSwap(uint32 terrainSwap) const { return _terrainSwaps.find(terrainSwap) != _terrainSwaps.end(); } - std::set const& GetPhases() const { return _phases; } - std::set const& GetTerrainSwaps() const { return _terrainSwaps; } - std::set const& GetWorldMapAreaSwaps() const { return _worldMapAreaSwaps; } int32 GetDBPhase() { return _dbPhase; } // if negative it is used as PhaseGroupId @@ -700,9 +693,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation //uint32 m_mapId; // object at map with map_id uint32 m_InstanceId; // in map copy with instance id uint32 m_phaseMask; // in area phase state - std::set _phases; - std::set _terrainSwaps; - std::set _worldMapAreaSwaps; + PhaseShift _phaseShift; + PhaseShift _suppressedPhaseShift; // contains phases for current area but not applied due to conditions int32 _dbPhase; uint16 m_notifyflags; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index b1ac2513e3..05e061e928 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -21,6 +21,7 @@ #include "Log.h" #include "WorldPacket.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "SpellMgr.h" #include "Pet.h" #include "Formulas.h" @@ -159,7 +160,7 @@ bool Pet::LoadPetData(Player* owner, uint32 petEntry, uint32 petnumber, bool cur if (!Create(guid, map, petEntry, petId)) return false; - CopyPhaseFrom(owner); + PhasingHandler::InheritPhaseShift(this, owner); setPetType(petType); SetFaction(owner->GetFaction()); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b482576944..586487fb8a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -65,6 +65,7 @@ #include "OutdoorPvP.h" #include "OutdoorPvPMgr.h" #include "Pet.h" +#include "PhasingHandler.h" #include "QueryCallback.h" #include "QuestDef.h" #include "ReputationMgr.h" @@ -1957,7 +1958,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati } // remove arena spell coldowns/buffs now to also remove pet's cooldowns before it's temporarily unsummoned - if (mEntry->IsBattleArena()) + if (mEntry->IsBattleArena() && !IsGameMaster()) { RemoveArenaSpellCooldowns(true); RemoveArenaAuras(); @@ -2599,7 +2600,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid, Gameo bool Player::IsUnderWater() const { return IsInWater() && - GetPositionZ() < (GetBaseMap()->GetWaterLevel(GetPositionX(), GetPositionY())-2); + GetPositionZ() < (GetBaseMap()->GetWaterLevel(GetPhaseShift(), GetPositionX(), GetPositionY())-2); } void Player::SetInWater(bool apply) @@ -2663,10 +2664,13 @@ void Player::SetGameMaster(bool on) getHostileRefManager().setOnlineOfflineState(false); CombatStopWithPets(); + PhasingHandler::SetAlwaysVisible(GetPhaseShift(), true); m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GM, GetSession()->GetSecurity()); } else { + PhasingHandler::SetAlwaysVisible(GetPhaseShift(), false); + m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON; SetFactionForRace(getRace()); RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); @@ -6509,7 +6513,7 @@ void Player::CheckAreaExploreAndOutdoor() return; bool isOutdoor; - uint32 areaId = GetBaseMap()->GetAreaId(GetPositionX(), GetPositionY(), GetPositionZ(), &isOutdoor); + uint32 areaId = GetBaseMap()->GetAreaId(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), &isOutdoor); AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(areaId); if (sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK) && !isOutdoor) @@ -7454,7 +7458,7 @@ uint32 Player::GetZoneIdFromDB(ObjectGuid guid) if (!sMapStore.LookupEntry(map)) return 0; - zone = sMapMgr->GetZoneId(map, posx, posy, posz); + zone = sMapMgr->GetZoneId(PhasingHandler::GetEmptyPhaseShift(), map, posx, posy, posz); if (zone > 0) { @@ -7481,7 +7485,7 @@ void Player::UpdateArea(uint32 newArea) UpdatePvPState(true); UpdateAreaDependentAuras(newArea); - UpdateAreaPhase(); + PhasingHandler::OnAreaChange(this); // previously this was in UpdateZone (but after UpdateArea) so nothing will break pvpInfo.IsInNoPvPArea = false; @@ -7581,8 +7585,6 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) UpdateLocalChannels(newZone); UpdateZoneDependentAuras(newZone); - - UpdateAreaPhase(); } //If players are too far away from the duel flag... they lose the duel @@ -16148,7 +16150,7 @@ void Player::SendQuestUpdate(uint32 questId) } UpdateForQuestWorldObjects(); - SendUpdatePhasing(); + PhasingHandler::OnConditionChange(this); } QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver) @@ -23573,6 +23575,8 @@ void Player::SendInitialPacketsAfterAddToMap() else ClearQuestSharingInfo(); } + + PhasingHandler::OnMapChange(this); } void Player::SendUpdateToOutOfRangeGroupMembers() @@ -27670,6 +27674,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy return nullptr; } + PhasingHandler::InheritPhaseShift(pet, this); if (!hasPetData) { Map* map = GetMap(); @@ -28043,16 +28048,6 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext #undef REMOVE_VIOLATING_FLAGS } -void Player::SendUpdatePhasing() -{ - if (!IsInWorld()) - return; - - RebuildTerrainSwaps(); // to set default map swaps - - GetSession()->SendSetPhaseShift(GetPhases(), GetTerrainSwaps(), GetWorldMapAreaSwaps()); -} - void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell) const { WorldPacket data(SMSG_SUPERCEDED_SPELL, 8); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index fbfed7ab2a..0234de3ec7 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2380,6 +2380,7 @@ class TC_GAME_API Player : public Unit, public GridObject // currently visible objects at player client GuidUnorderedSet m_clientGUIDs; + GuidUnorderedSet m_visibleTransports; bool HaveAtClient(Object const* u) const; @@ -2393,8 +2394,6 @@ class TC_GAME_API Player : public Unit, public GridObject void UpdateVisibilityOf(WorldObject* target); void UpdateTriggerVisibility(); - void SendUpdatePhasing(); - template void UpdateVisibilityOf(T* target, UpdateData& data, std::set& visibleNow); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index ba0524c214..6df61e1cc8 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -20,6 +20,7 @@ #include "Transport.h" #include "MapManager.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "ScriptMgr.h" #include "DBCStores.h" #include "GameObjectAI.h" @@ -326,13 +327,8 @@ Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData c return NULL; } - if (data->phaseid) - creature->SetInPhase(data->phaseid, false, true); - else if (data->phaseGroup) - for (auto phase : GetPhasesForGroup(data->phaseGroup)) - creature->SetInPhase(phase, false, true); - else - creature->CopyPhaseFrom(this); + PhasingHandler::InitDbPhaseShift(creature->GetPhaseShift(), data->phaseUseFlags, data->phaseId, data->phaseGroup); + PhasingHandler::InitDbVisibleMapId(creature->GetPhaseShift(), data->terrainSwapMap); if (!map->AddToMap(creature)) { @@ -377,6 +373,9 @@ GameObject* Transport::CreateGOPassenger(ObjectGuid::LowType guid, GameObjectDat return NULL; } + PhasingHandler::InitDbPhaseShift(go->GetPhaseShift(), data->phaseUseFlags, data->phaseId, data->phaseGroup); + PhasingHandler::InitDbVisibleMapId(go->GetPhaseShift(), data->terrainSwapMap); + if (!map->AddToMap(go)) { delete go; @@ -441,12 +440,6 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu } } - std::set phases; - if (summoner) - phases = summoner->GetPhases(); - else - phases = GetPhases(); // If there was no summoner, try to use the transport phases - TempSummon* summon = NULL; switch (mask) { @@ -477,8 +470,7 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu return NULL; } - for (uint32 phase : phases) - summon->SetInPhase(phase, false, true); + PhasingHandler::InheritPhaseShift(summon, summoner ? static_cast(summoner) : static_cast(this)); summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId); diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index 03bd3bcb2c..b3bdcae034 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -27,7 +27,7 @@ struct CreatureData; class TC_GAME_API Transport : public GameObject, public TransportBase { - friend Transport* TransportMgr::CreateTransport(uint32, ObjectGuid::LowType, Map*, uint32, uint32); + friend Transport* TransportMgr::CreateTransport(uint32, ObjectGuid::LowType, Map*, uint8, uint32, uint32); Transport(); public: diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 83da51f31e..71d8bda059 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -46,6 +46,7 @@ #include "PassiveAI.h" #include "PetAI.h" #include "Pet.h" +#include "PhasingHandler.h" #include "Player.h" #include "PlayerAI.h" #include "QuestDef.h" @@ -3147,12 +3148,12 @@ bool Unit::isInAccessiblePlaceFor(Creature const* c) const bool Unit::IsInWater() const { - return GetBaseMap()->IsInWater(GetPositionX(), GetPositionY(), GetPositionZ()); + return GetBaseMap()->IsInWater(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ()); } bool Unit::IsUnderWater() const { - return GetBaseMap()->IsUnderWater(GetPositionX(), GetPositionY(), GetPositionZ()); + return GetBaseMap()->IsUnderWater(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ()); } void Unit::ProcessPositionDataChanged(PositionFullTerrainStatus const& data) @@ -3928,7 +3929,7 @@ void Unit::RemoveAurasWithAttribute(uint32 flags) } } -void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid) +void Unit::RemoveNotOwnSingleTargetAuras(bool onPhaseChange /*= false*/) { // single target auras from other casters // Iterate m_ownedAuras - aura is marked as single target in Unit::AddAura (and pushed to m_ownedAuras). @@ -3945,12 +3946,12 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid) if (aura->GetCasterGUID() != GetGUID() && aura->IsSingleTarget()) { - if (!newPhase && !phaseid) + if (!onPhaseChange) RemoveOwnedAura(iter); else { Unit* caster = aura->GetCaster(); - if (!caster || (newPhase && !caster->IsInPhase(newPhase)) || (!newPhase && !caster->IsInPhase(this))) + if (!caster || !caster->IsInPhase(this)) RemoveOwnedAura(iter); else ++iter; @@ -3965,7 +3966,7 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid) for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();) { Aura* aura = *iter; - if (aura->GetUnitOwner() != this && !aura->GetUnitOwner()->IsInPhase(newPhase)) + if (aura->GetUnitOwner() != this && !aura->GetUnitOwner()->IsInPhase(this)) { aura->Remove(); iter = scAuras.begin(); @@ -5576,7 +5577,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack) //if (GetTypeId() == TYPEID_UNIT) // ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ()); - if (creature && !IsPet()) + if (creature && !IsControlledByPlayer()) { // should not let player enter combat by right clicking target - doesn't helps AddThreat(victim, 0.0f); @@ -8171,7 +8172,7 @@ MountCapabilityEntry const* Unit::GetMountCapability(uint32 mountType) const mountFlags = areaTable->MountFlags; LiquidData liquid; - ZLiquidStatus liquidStatus = GetMap()->GetLiquidStatus(GetPositionX(), GetPositionY(), GetPositionZ(), MAP_ALL_LIQUIDS, &liquid); + ZLiquidStatus liquidStatus = GetMap()->GetLiquidStatus(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ(), MAP_ALL_LIQUIDS, &liquid); isSubmerged = (liquidStatus & LIQUID_MAP_UNDER_WATER) != 0 || HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING); isInWater = (liquidStatus & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; @@ -10089,15 +10090,6 @@ int32 Unit::GetCreatePowers(Powers power) const return 0; } -void Unit::AddToWorld() -{ - if (!IsInWorld()) - { - WorldObject::AddToWorld(); - } - RebuildTerrainSwaps(); -} - void Unit::RemoveFromWorld() { // cleanup @@ -11419,7 +11411,7 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id) return false; } - pet->CopyPhaseFrom(this); + PhasingHandler::InheritPhaseShift(pet, this); pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); // this enables pet details window (Shift+P) @@ -12526,14 +12518,12 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, u return missChance; } -bool Unit::SetInPhase(uint32 id, bool update, bool apply) +void Unit::OnPhaseChange() { - bool res = WorldObject::SetInPhase(id, update, apply); - if (!IsInWorld()) - return res; + return; - if (GetTypeId() == TYPEID_UNIT || (!ToPlayer()->IsGameMaster() && !ToPlayer()->GetSession()->PlayerLogout())) + if (GetTypeId() == TYPEID_UNIT || !ToPlayer()->GetSession()->PlayerLogout()) { HostileRefManager& refManager = getHostileRefManager(); HostileReference* ref = refManager.getFirst(); @@ -12563,19 +12553,6 @@ bool Unit::SetInPhase(uint32 id, bool update, bool apply) unit->getHostileRefManager().setOnlineOfflineState(ToCreature(), unit->IsInPhase(this)); } } - - for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) - if ((*itr)->GetTypeId() == TYPEID_UNIT) - (*itr)->SetInPhase(id, true, apply); - - for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i) - if (m_SummonSlot[i]) - if (Creature* summon = GetMap()->GetCreature(m_SummonSlot[i])) - summon->SetInPhase(id, true, apply); - - RemoveNotOwnSingleTargetAuras(0, true); - - return res; } void Unit::UpdateObjectVisibility(bool forced) @@ -13356,7 +13333,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) Movement::MoveSplineInit init(this); // Creatures without inhabit type air should begin falling after exiting the vehicle - if (GetTypeId() == TYPEID_UNIT && !CanFly() && height > GetMap()->GetWaterOrGroundLevel(GetPhases(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), &height) + 0.1f) + if (GetTypeId() == TYPEID_UNIT && !CanFly() && height > GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), &height) + 0.1f) init.SetFall(); init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), height, false); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index feb65cbcac..aa6e0c641d 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1316,7 +1316,6 @@ class TC_GAME_API Unit : public WorldObject UnitAI* GetAI() { return i_AI; } void SetAI(UnitAI* newAI) { i_AI = newAI; } - void AddToWorld() override; void RemoveFromWorld() override; void CleanupBeforeRemoveFromMap(bool finalCleanup); @@ -1801,7 +1800,7 @@ class TC_GAME_API Unit : public WorldObject void RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, Unit* stealer); void RemoveAurasDueToItemSpell(uint32 spellId, ObjectGuid castItemGuid); void RemoveAurasByType(AuraType auraType, ObjectGuid casterGUID = ObjectGuid::Empty, Aura* except = NULL, bool negative = true, bool positive = true); - void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0, bool phaseid = false); + void RemoveNotOwnSingleTargetAuras(bool onPhaseChange = false); void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = 0); void RemoveAurasWithAttribute(uint32 flags); void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, ObjectGuid casterGUID); @@ -1983,7 +1982,7 @@ class TC_GAME_API Unit : public WorldObject void SetVisible(bool x); // common function for visibility checks for player/creatures with detection code - bool SetInPhase(uint32 id, bool update, bool apply) override; + void OnPhaseChange(); void UpdateObjectVisibility(bool forced = true) override; SpellImmuneContainer m_spellImmune[MAX_SPELL_IMMUNITY]; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 0458339ca3..f6d2974787 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -23,6 +23,7 @@ #include "BattlegroundMgr.h" #include "Chat.h" #include "Common.h" +#include "Containers.h" #include "CreatureAIFactory.h" #include "DatabaseEnv.h" #include "DB2Structure.h" @@ -39,6 +40,7 @@ #include "MapManager.h" #include "Object.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "PoolMgr.h" #include "ReputationMgr.h" #include "ScriptMgr.h" @@ -1880,9 +1882,9 @@ void ObjectMgr::LoadCreatures() // 0 1 2 3 4 5 6 7 8 9 10 QueryResult result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, " // 11 12 13 14 15 16 17 18 19 20 21 22 - "currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, creature.phaseid, " - // 23 24 - "creature.phasegroup, creature.ScriptName " + "currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, creature.phaseUseFlags, " + // 23 24 25 26 + "creature.phaseid, creature.phasegroup, creature.terrainSwapMap, creature.ScriptName " "FROM creature " "LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid " "LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid"); @@ -1901,7 +1903,9 @@ void ObjectMgr::LoadCreatures() if (GetMapDifficultyData(i, Difficulty(k))) spawnMasks[i] |= (1 << k); - _creatureDataStore.rehash(result->GetRowCount()); + PhaseShift phaseShift; + + _creatureDataStore.reserve(result->GetRowCount()); do { @@ -1939,9 +1943,11 @@ void ObjectMgr::LoadCreatures() data.npcflag = fields[19].GetUInt32(); data.unit_flags = fields[20].GetUInt32(); data.dynamicflags = fields[21].GetUInt32(); - data.phaseid = fields[22].GetUInt32(); - data.phaseGroup = fields[23].GetUInt32(); - data.ScriptId = GetScriptId(fields[24].GetString()); + data.phaseUseFlags = fields[22].GetUInt8(); + data.phaseId = fields[23].GetUInt32(); + data.phaseGroup = fields[24].GetUInt32(); + data.terrainSwapMap = fields[25].GetInt32(); + data.ScriptId = GetScriptId(fields[26].GetString()); MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); if (!mapEntry) @@ -2013,7 +2019,7 @@ void ObjectMgr::LoadCreatures() if (std::abs(data.orientation) > 2 * float(M_PI)) { - TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u Entry: %u) with abs(`orientation`) > 2*PI (orientation is expressed in radians), normalized.", guid, data.id); + TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %%u Entry: %u) with abs(`orientation`) > 2*PI (orientation is expressed in radians), normalized.", guid, data.id); data.orientation = Position::NormalizeOrientation(data.orientation); } @@ -2023,23 +2029,52 @@ void ObjectMgr::LoadCreatures() data.phaseMask = 1; } - if (data.phaseGroup && GetPhasesForGroup(data.phaseGroup).empty()) + if (data.phaseUseFlags & ~PHASE_USE_FLAGS_ALL) + { + TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u Entry: %u) has unknown `phaseUseFlags` set, removed unknown value.", guid, data.id); + data.phaseUseFlags &= PHASE_USE_FLAGS_ALL; + } + + if (data.phaseUseFlags & PHASE_USE_FLAGS_ALWAYS_VISIBLE && data.phaseUseFlags & PHASE_USE_FLAGS_INVERSE) + { + TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u Entry: %u) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE," + " removing PHASE_USE_FLAGS_INVERSE.", guid, data.id); + data.phaseUseFlags &= ~PHASE_USE_FLAGS_INVERSE; + } + + if (data.phaseGroup && !GetPhasesForGroup(data.phaseGroup)) { TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: %u Entry: %u) with non-existing `phasegroup` (%u) set, `phasegroup` set to 0", guid, data.id, data.phaseGroup); data.phaseGroup = 0; } - if (data.phaseGroup && data.phaseid) + if (data.phaseGroup && data.phaseId) { TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u Entry: %u) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, data.id); data.phaseGroup = 0; } + if (data.terrainSwapMap != -1) + { + MapEntry const* terrainSwapEntry = sMapStore.LookupEntry(data.terrainSwapMap); + if (!terrainSwapEntry) + { + TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: % Entry: %u) with `terrainSwapMap` %u does not exist, set to -1", guid, data.id, data.terrainSwapMap); + data.terrainSwapMap = -1; + } + else if (terrainSwapEntry->rootPhaseMap != data.mapid) + { + TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: % Entry: %u) with `terrainSwapMap` %u which cannot be used on spawn map, set to -1", guid, data.id, data.terrainSwapMap); + data.terrainSwapMap = -1; + } + } + if (sWorld->getBoolConfig(CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA)) { uint32 zoneId = 0; uint32 areaId = 0; - sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); + PhasingHandler::InitDbVisibleMapId(phaseShift, data.terrainSwapMap); + sMapMgr->GetZoneAndAreaId(phaseShift, zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA); @@ -2193,8 +2228,8 @@ void ObjectMgr::LoadGameobjects() QueryResult result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation, " // 7 8 9 10 11 12 13 14 15 16 17 "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, eventEntry, pool_entry, " - // 18 19 20 - "phaseid, phasegroup, ScriptName " + // 18 19 20 21 22 + "phaseUseFlags, phaseid, phasegroup, terrainSwapMap, ScriptName " "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid " "LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid"); @@ -2212,7 +2247,9 @@ void ObjectMgr::LoadGameobjects() if (GetMapDifficultyData(i, Difficulty(k))) spawnMasks[i] |= (1 << k); - _gameObjectDataStore.rehash(result->GetRowCount()); + PhaseShift phaseShift; + + _gameObjectDataStore.reserve(result->GetRowCount()); do { @@ -2295,22 +2332,52 @@ void ObjectMgr::LoadGameobjects() data.phaseMask = fields[15].GetUInt32(); int16 gameEvent = fields[16].GetInt8(); uint32 PoolId = fields[17].GetUInt32(); - data.phaseid = fields[18].GetUInt32(); - data.phaseGroup = fields[19].GetUInt32(); + data.phaseUseFlags = fields[18].GetUInt8(); + data.phaseId = fields[19].GetUInt32(); + data.phaseGroup = fields[20].GetUInt32(); - if (data.phaseGroup && GetPhasesForGroup(data.phaseGroup).empty()) + if (data.phaseUseFlags & ~PHASE_USE_FLAGS_ALL) + { + TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: " UI64FMTD " Entry: %u) has unknown `phaseUseFlags` set, removed unknown value.", guid, data.id); + data.phaseUseFlags &= PHASE_USE_FLAGS_ALL; + } + + if (data.phaseUseFlags & PHASE_USE_FLAGS_ALWAYS_VISIBLE && data.phaseUseFlags & PHASE_USE_FLAGS_INVERSE) + { + TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: " UI64FMTD " Entry: %u) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE," + " removing PHASE_USE_FLAGS_INVERSE.", guid, data.id); + data.phaseUseFlags &= ~PHASE_USE_FLAGS_INVERSE; + } + + if (data.phaseGroup && !GetPhasesForGroup(data.phaseGroup)) { TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) with non-existing `phasegroup` (%u) set, `phasegroup` set to 0", guid, data.id, data.phaseGroup); data.phaseGroup = 0; } - if (data.phaseGroup && data.phaseid) + if (data.phaseGroup && data.phaseId) { TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: %u Entry: %u) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, data.id); data.phaseGroup = 0; } - data.ScriptId = GetScriptId(fields[20].GetString()); + data.terrainSwapMap = fields[21].GetInt32(); + if (data.terrainSwapMap != -1) + { + MapEntry const* terrainSwapEntry = sMapStore.LookupEntry(data.terrainSwapMap); + if (!terrainSwapEntry) + { + TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: " UI64FMTD " Entry: %u) with `terrainSwapMap` %u does not exist, set to -1", guid, data.id, data.terrainSwapMap); + data.terrainSwapMap = -1; + } + else if (terrainSwapEntry->rootPhaseMap != data.mapid) + { + TC_LOG_ERROR("sql.sql", "Table `gameobject` have gameobject (GUID: " UI64FMTD " Entry: %u) with `terrainSwapMap` %u which cannot be used on spawn map, set to -1", guid, data.id, data.terrainSwapMap); + data.terrainSwapMap = -1; + } + } + + data.ScriptId = GetScriptId(fields[22].GetString()); if (std::abs(data.orientation) > 2 * float(M_PI)) { @@ -2358,7 +2425,8 @@ void ObjectMgr::LoadGameobjects() { uint32 zoneId = 0; uint32 areaId = 0; - sMapMgr->GetZoneAndAreaId(zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); + PhasingHandler::InitDbVisibleMapId(phaseShift, data.terrainSwapMap); + sMapMgr->GetZoneAndAreaId(phaseShift, zoneId, areaId, data.mapid, data.posX, data.posY, data.posZ); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA); @@ -6332,7 +6400,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetDefaultGraveYard(uint32 team) const WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team) const { // search for zone associated closest graveyard - uint32 zoneId = sMapMgr->GetZoneId(MapId, x, y, z); + uint32 zoneId = sMapMgr->GetZoneId(PhasingHandler::GetEmptyPhaseShift(), MapId, x, y, z); if (!zoneId) { @@ -9598,10 +9666,78 @@ void ObjectMgr::LoadFactionChangeTitles() TC_LOG_INFO("server.loading", ">> Loaded %u faction change title pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } +void ObjectMgr::LoadPhases() +{ + for (PhaseEntry const* phase : sPhaseStore) + _phaseInfoById.emplace(std::make_pair(phase->ID, PhaseInfoStruct{ phase->ID, std::unordered_set{} })); + + for (MapEntry const* map : sMapStore) + if (map->rootPhaseMap != -1) + _terrainSwapInfoById.emplace(std::make_pair(map->MapID, TerrainSwapInfo{ map->MapID, std::vector{} })); + + TC_LOG_INFO("server.loading", "Loading Terrain World Map definitions..."); + LoadTerrainWorldMaps(); + + TC_LOG_INFO("server.loading", "Loading Terrain Swap Default definitions..."); + LoadTerrainSwapDefaults(); + + TC_LOG_INFO("server.loading", "Loading Phase Area definitions..."); + LoadAreaPhases(); +} + +void ObjectMgr::UnloadPhaseConditions() +{ + for (auto itr = _phaseInfoByArea.begin(); itr != _phaseInfoByArea.end(); ++itr) + for (PhaseAreaInfo& phase : itr->second) + phase.Conditions.clear(); +} + +void ObjectMgr::LoadTerrainWorldMaps() +{ + uint32 oldMSTime = getMSTime(); + + // 0 1 + QueryResult result = WorldDatabase.Query("SELECT TerrainSwapMap, WorldMapArea FROM `terrain_worldmap`"); + + + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 terrain world maps. DB table `terrain_worldmap` is empty."); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + uint32 mapId = fields[0].GetUInt32(); + uint32 worldMapArea = fields[1].GetUInt32(); + + if (!sMapStore.LookupEntry(mapId)) + { + TC_LOG_ERROR("sql.sql", "TerrainSwapMap %u defined in `terrain_worldmap` does not exist, skipped.", mapId); + continue; + } + + if (!sWorldMapAreaStore.LookupEntry(worldMapArea)) + { + TC_LOG_ERROR("sql.sql", "WorldMapArea %u defined in `terrain_worldmap` does not exist, skipped.", worldMapArea); + continue; + } + + TerrainSwapInfo* terrainSwapInfo = &_terrainSwapInfoById[mapId]; + terrainSwapInfo->Id = mapId; + terrainSwapInfo->UiWorldMapAreaIDSwaps.push_back(worldMapArea); + + ++count; + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u terrain world maps in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); +} + void ObjectMgr::LoadTerrainSwapDefaults() { - _terrainMapDefaultStore.clear(); - uint32 oldMSTime = getMSTime(); // 0 1 @@ -9634,7 +9770,9 @@ void ObjectMgr::LoadTerrainSwapDefaults() continue; } - _terrainMapDefaultStore[mapId].push_back(terrainSwap); + TerrainSwapInfo* terrainSwapInfo = &_terrainSwapInfoById[terrainSwap]; + terrainSwapInfo->Id = terrainSwap; + _terrainSwapInfoByMap[mapId].push_back(terrainSwapInfo); ++count; } while (result->NextRow()); @@ -9642,88 +9780,8 @@ void ObjectMgr::LoadTerrainSwapDefaults() TC_LOG_INFO("server.loading", ">> Loaded %u terrain swap defaults in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); } -void ObjectMgr::LoadTerrainPhaseInfo() -{ - _terrainPhaseInfoStore.clear(); - - uint32 oldMSTime = getMSTime(); - - // 0 1 - QueryResult result = WorldDatabase.Query("SELECT Id, TerrainSwapMap FROM `terrain_phase_info`"); - - if (!result) - { - TC_LOG_INFO("server.loading", ">> Loaded 0 terrain phase infos. DB table `terrain_phase_info` is empty."); - return; - } - - uint32 count = 0; - do - { - Field* fields = result->Fetch(); - - uint32 phaseId = fields[0].GetUInt32(); - - PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseId); - if (!phase) - { - TC_LOG_ERROR("sql.sql", "Phase %u defined in `terrain_phase_info` does not exist, skipped.", phaseId); - continue; - } - - uint32 terrainSwap = fields[1].GetUInt32(); - - _terrainPhaseInfoStore[phaseId].push_back(terrainSwap); - - ++count; - } - while (result->NextRow()); - - TC_LOG_INFO("server.loading", ">> Loaded %u terrain phase infos in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); -} - -void ObjectMgr::LoadTerrainWorldMaps() -{ - _terrainWorldMapStore.clear(); - - uint32 oldMSTime = getMSTime(); - - // 0 1 - QueryResult result = WorldDatabase.Query("SELECT TerrainSwapMap, WorldMapArea FROM `terrain_worldmap`"); - - if (!result) - { - TC_LOG_INFO("server.loading", ">> Loaded 0 terrain world maps. DB table `terrain_worldmap` is empty."); - return; - } - - uint32 count = 0; - do - { - Field* fields = result->Fetch(); - - uint32 mapId = fields[0].GetUInt32(); - - if (!sMapStore.LookupEntry(mapId)) - { - TC_LOG_ERROR("sql.sql", "TerrainSwapMap %u defined in `terrain_worldmap` does not exist, skipped.", mapId); - continue; - } - - uint32 worldMapArea = fields[1].GetUInt32(); - - _terrainWorldMapStore[mapId].push_back(worldMapArea); - - ++count; - } while (result->NextRow()); - - TC_LOG_INFO("server.loading", ">> Loaded %u terrain world maps in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); -} - void ObjectMgr::LoadAreaPhases() { - _phases.clear(); - uint32 oldMSTime = getMSTime(); // 0 1 @@ -9735,23 +9793,93 @@ void ObjectMgr::LoadAreaPhases() return; } + auto getOrCreatePhaseIfMissing = [this](uint32 phaseId) + { + PhaseInfoStruct* phaseInfo = &_phaseInfoById[phaseId]; + phaseInfo->Id = phaseId; + return phaseInfo; + }; + uint32 count = 0; do { Field* fields = result->Fetch(); - - PhaseInfoStruct phase; uint32 area = fields[0].GetUInt32(); + uint32 phaseId = fields[1].GetUInt32(); + if (!sAreaTableStore.LookupEntry(area)) + { + TC_LOG_ERROR("sql.sql", "Area %u defined in `phase_area` does not exist, skipped.", area); + continue; + } - phase.Id = fields[1].GetUInt32(); - _phases[area].push_back(phase); + if (!sPhaseStore.LookupEntry(phaseId)) + { + TC_LOG_ERROR("sql.sql", "Phase %u defined in `phase_area` does not exist, skipped.", phaseId); + continue; + } + + PhaseInfoStruct* phase = getOrCreatePhaseIfMissing(phaseId); + phase->Areas.insert(area); + _phaseInfoByArea[area].emplace_back(phase); ++count; } while (result->NextRow()); + for (auto itr = _phaseInfoByArea.begin(); itr != _phaseInfoByArea.end(); ++itr) + { + for (PhaseAreaInfo& phase : itr->second) + { + uint32 parentAreaId = itr->first; + do + { + AreaTableEntry const* area = sAreaTableStore.LookupEntry(parentAreaId); + if (!area) + break; + + parentAreaId = area->zone; + if (!parentAreaId) + break; + + if (std::vector* parentAreaPhases = Trinity::Containers::MapGetValuePtr(_phaseInfoByArea, parentAreaId)) + for (PhaseAreaInfo& parentAreaPhase : *parentAreaPhases) + if (parentAreaPhase.PhaseInfo->Id == phase.PhaseInfo->Id) + parentAreaPhase.SubAreaExclusions.insert(itr->first); + + } while (true); + } + } + TC_LOG_INFO("server.loading", ">> Loaded %u phase areas in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); } +bool PhaseInfoStruct::IsAllowedInArea(uint32 areaId) const +{ + return std::any_of(Areas.begin(), Areas.end(), [areaId](uint32 areaToCheck) + { + return IsInArea(areaId, areaToCheck); + }); +} + +PhaseInfoStruct const* ObjectMgr::GetPhaseInfo(uint32 phaseId) const +{ + return Trinity::Containers::MapGetValuePtr(_phaseInfoById, phaseId); +} + +std::vector const* ObjectMgr::GetPhasesForArea(uint32 areaId) const +{ + return Trinity::Containers::MapGetValuePtr(_phaseInfoByArea, areaId); +} + +TerrainSwapInfo const* ObjectMgr::GetTerrainSwapInfo(uint32 terrainSwapId) const +{ + return Trinity::Containers::MapGetValuePtr(_terrainSwapInfoById, terrainSwapId); +} + +std::vector const* ObjectMgr::GetTerrainSwapsForMap(uint32 mapId) const +{ + return Trinity::Containers::MapGetValuePtr(_terrainSwapInfoByMap, mapId); +} + GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry) const { GameObjectTemplateContainer::const_iterator itr = _gameObjectTemplateStore.find(entry); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index f89f122bcb..3e90833e61 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -716,15 +716,28 @@ struct HotfixInfo typedef std::vector HotfixData; +struct TerrainSwapInfo +{ + uint32 Id; + std::vector UiWorldMapAreaIDSwaps; +}; + struct PhaseInfoStruct { uint32 Id; - ConditionContainer Conditions; + std::unordered_set Areas; + + bool IsAllowedInArea(uint32 areaId) const; }; -typedef std::unordered_map> TerrainPhaseInfo; // terrain swap -typedef std::unordered_map> TerrainUIPhaseInfo; // worldmaparea swap -typedef std::unordered_map> PhaseInfo; // phase +struct PhaseAreaInfo +{ + PhaseAreaInfo(PhaseInfoStruct const* phaseInfo) : PhaseInfo(phaseInfo) { } + + PhaseInfoStruct const* PhaseInfo; + std::unordered_set SubAreaExclusions; + ConditionContainer Conditions; +}; class PlayerDumpReader; @@ -1073,7 +1086,8 @@ class TC_GAME_API ObjectMgr void LoadTrainerSpell(); void AddSpellToTrainer(uint32 ID, uint32 SpellID, uint32 MoneyCost, uint32 ReqSkillLine, uint32 ReqSkillRank, uint32 ReqLevel, uint32 Index); - void LoadTerrainPhaseInfo(); + void LoadPhases(); + void UnloadPhaseConditions(); void LoadTerrainSwapDefaults(); void LoadTerrainWorldMaps(); void LoadAreaPhases(); @@ -1358,36 +1372,6 @@ class TC_GAME_API ObjectMgr return _gossipMenuItemsStore.equal_range(uiMenuId); } - std::vector const* GetPhaseTerrainSwaps(uint32 phaseid) const - { - auto itr = _terrainPhaseInfoStore.find(phaseid); - return itr != _terrainPhaseInfoStore.end() ? &itr->second : nullptr; - } - std::vector const* GetDefaultTerrainSwaps(uint32 mapid) const - { - auto itr = _terrainMapDefaultStore.find(mapid); - return itr != _terrainMapDefaultStore.end() ? &itr->second : nullptr; - } - std::vector const* GetTerrainWorldMaps(uint32 terrainId) const - { - auto itr = _terrainWorldMapStore.find(terrainId); - return itr != _terrainWorldMapStore.end() ? &itr->second : nullptr; - } - std::vector const* GetPhasesForArea(uint32 area) const - { - auto itr = _phases.find(area); - return itr != _phases.end() ? &itr->second : nullptr; - } - TerrainPhaseInfo const& GetDefaultTerrainSwapStore() const { return _terrainMapDefaultStore; } - PhaseInfo const& GetAreaPhases() const { return _phases; } - // condition loading helpers - std::vector* GetPhasesForAreaForLoading(uint32 area) - { - auto itr = _phases.find(area); - return itr != _phases.end() ? &itr->second : nullptr; - } - PhaseInfo& GetAreaPhasesForLoading() { return _phases; } - // for wintergrasp only GraveYardContainer GraveYardStore; @@ -1506,10 +1490,18 @@ class TC_GAME_API ObjectMgr PageTextContainer _pageTextStore; InstanceTemplateContainer _instanceTemplateStore; - TerrainPhaseInfo _terrainPhaseInfoStore; - TerrainPhaseInfo _terrainMapDefaultStore; - TerrainUIPhaseInfo _terrainWorldMapStore; - PhaseInfo _phases; + public: + PhaseInfoStruct const* GetPhaseInfo(uint32 phaseId) const; + std::vector const* GetPhasesForArea(uint32 areaId) const; + TerrainSwapInfo const* GetTerrainSwapInfo(uint32 terrainSwapId) const; + std::vector const* GetTerrainSwapsForMap(uint32 mapId) const; + + private: + std::unordered_map _phaseInfoById; + std::unordered_map _terrainSwapInfoById; + std::unordered_map> _phaseInfoByArea; + std::unordered_map> _terrainSwapInfoByMap; + private: void LoadScripts(ScriptsType type); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp index 3ff20024d3..4039915efe 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp +++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp @@ -324,7 +324,7 @@ void MessageDistDelivererToHostile::Visit(PlayerMapType &m) for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { Player* target = iter->GetSource(); - if (!target->IsInPhase(i_phaseMask)) + if (!target->IsInPhase(i_source)) continue; if (target->GetExactDist2dSq(i_source) > i_distSq) @@ -349,7 +349,7 @@ void MessageDistDelivererToHostile::Visit(CreatureMapType &m) for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { Creature* target = iter->GetSource(); - if (!target->IsInPhase(i_phaseMask)) + if (!target->IsInPhase(i_source)) continue; if (target->GetExactDist2dSq(i_source) > i_distSq) @@ -371,7 +371,7 @@ void MessageDistDelivererToHostile::Visit(DynamicObjectMapType &m) for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { DynamicObject* target = iter->GetSource(); - if (!target->IsInPhase(i_phaseMask)) + if (!target->IsInPhase(i_source)) continue; if (target->GetExactDist2dSq(i_source) > i_distSq) diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index a3be11ee4d..1ee1123dd4 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -24,6 +24,7 @@ #include "Log.h" #include "ObjectMgr.h" #include "Pet.h" +#include "PhasingHandler.h" #include "Player.h" #include "SocialMgr.h" #include "SpellAuras.h" @@ -984,8 +985,6 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke if (mask == GROUP_UPDATE_FLAG_NONE) return; - std::set const& phases = player->GetPhases(); - if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) // if update power type, update current/max power also mask |= (GROUP_UPDATE_FLAG_CUR_POWER | GROUP_UPDATE_FLAG_MAX_POWER); @@ -1207,12 +1206,7 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke } if (mask & GROUP_UPDATE_FLAG_PHASE) - { - *data << uint32(phases.empty() ? 8 : 0); - *data << uint32(phases.size()); - for (std::set::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) - *data << uint16(*itr); - } + PhasingHandler::FillPartyMemberPhase(data, player->GetPhaseShift()); } /*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ @@ -1236,7 +1230,6 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) Pet* pet = player->GetPet(); Powers powerType = player->getPowerType(); - std::set const& phases = player->GetPhases(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related @@ -1257,7 +1250,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) if (player->GetVehicle()) updateFlags |= GROUP_UPDATE_FLAG_VEHICLE_SEAT; - if (!phases.empty()) + if (!player->GetPhaseShift().GetPhases().empty()) updateFlags |= GROUP_UPDATE_FLAG_PHASE; uint16 playerStatus = MEMBER_STATUS_ONLINE; @@ -1385,12 +1378,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recvData) data << uint32(player->GetVehicle()->GetVehicleInfo()->m_seatID[player->m_movementInfo.transport.seat]); if (updateFlags & GROUP_UPDATE_FLAG_PHASE) - { - data << uint32(phases.empty() ? 8 : 0); - data << uint32(phases.size()); - for (std::set::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) - data << uint16(*itr); - } + PhasingHandler::FillPartyMemberPhase(&data, player->GetPhaseShift()); SendPacket(&data); } diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 72bfb8aea6..34af7a4af4 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1603,54 +1603,6 @@ void WorldSession::HandleReadyForAccountDataTimes(WorldPacket& /*recvData*/) SendAccountDataTimes(GLOBAL_CACHE_MASK); } -void WorldSession::SendSetPhaseShift(std::set const& phaseIds, std::set const& terrainswaps, std::set const& worldMapAreaSwaps) -{ - ObjectGuid guid = _player->GetGUID(); - - WorldPacket data(SMSG_SET_PHASE_SHIFT, 1 + 8 + 4 + 4 + 4 + 4 + 2 * phaseIds.size() + 4 + terrainswaps.size() * 2); - data.WriteBit(guid[2]); - data.WriteBit(guid[3]); - data.WriteBit(guid[1]); - data.WriteBit(guid[6]); - data.WriteBit(guid[4]); - data.WriteBit(guid[5]); - data.WriteBit(guid[0]); - data.WriteBit(guid[7]); - - data.WriteByteSeq(guid[7]); - data.WriteByteSeq(guid[4]); - - data << uint32(worldMapAreaSwaps.size()) * 2; - for (auto mapSwap : worldMapAreaSwaps) - data << uint16(mapSwap); // WorldMapArea.dbc id (controls map display) - - data.WriteByteSeq(guid[1]); - - data << uint32(phaseIds.size() ? 0 : 8); // flags (not phasemask) - - data.WriteByteSeq(guid[2]); - data.WriteByteSeq(guid[6]); - - data << uint32(0); // Inactive terrain swaps - //for (uint8 i = 0; i < inactiveSwapsCount; ++i) - // data << uint16(0); - - data << uint32(phaseIds.size()) * 2; // Phase.dbc ids - for (std::set::const_iterator itr = phaseIds.begin(); itr != phaseIds.end(); ++itr) - data << uint16(*itr); - - data.WriteByteSeq(guid[3]); - data.WriteByteSeq(guid[0]); - - data << uint32(terrainswaps.size()) * 2; // Active terrain swaps - for (std::set::const_iterator itr = terrainswaps.begin(); itr != terrainswaps.end(); ++itr) - data << uint16(*itr); - - data.WriteByteSeq(guid[5]); - - SendPacket(&data); -} - // Battlefield and Battleground void WorldSession::HandleAreaSpiritHealerQueryOpcode(WorldPacket& recvData) { diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 354a3376fd..404f6d5f33 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -373,7 +373,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) { // now client not include swimming flag in case jumping under water - plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); + plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(plrMover->GetPhaseShift(), movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ())); } uint32 mstime = GameTime::GetGameTimeMS(); diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 5073788320..618e73295b 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -266,7 +266,7 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket& /*recvData*/) mapID = corpseMapEntry->entrance_map; x = corpseMapEntry->entrance_x; y = corpseMapEntry->entrance_y; - z = entranceMap->GetHeight(GetPlayer()->GetPhases(), x, y, MAX_HEIGHT); + z = entranceMap->GetHeight(GetPlayer()->GetPhaseShift(), x, y, MAX_HEIGHT); } } } diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index dab0766b5e..e807d22d44 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -27,6 +27,7 @@ #include "Map.h" #include "Player.h" #include "Pet.h" +#include "PhasingHandler.h" #include "WorldSession.h" #include "Opcodes.h" #include "Guild.h" @@ -749,7 +750,7 @@ void InstanceScript::UpdatePhasing() Map::PlayerList const& players = instance->GetPlayers(); for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) if (Player* player = itr->GetSource()) - player->SendUpdatePhasing(); + PhasingHandler::SendToPlayer(player); } void InstanceScript::UpdateCombatResurrection(uint32 diff) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 98b76e9606..11c66afb2b 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -31,6 +31,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Pet.h" +#include "PhasingHandler.h" #include "ScriptMgr.h" #include "Transport.h" #include "Vehicle.h" @@ -71,6 +72,9 @@ Map::~Map() if (!m_scriptSchedule.empty()) sMapMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); + if (m_parentMap != this) + delete m_childTerrainMaps; + MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); } @@ -134,7 +138,7 @@ void Map::LoadMMap(int gx, int gy) if (!DisableMgr::IsPathfindingEnabled(GetId())) return; - bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy); + bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap(sWorld->GetDataPath(), GetId(), gx, gy); if (mmapLoadResult) TC_LOG_DEBUG("mmaps", "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); @@ -164,42 +168,65 @@ void Map::LoadVMap(int gx, int gy) void Map::LoadMap(int gx, int gy, bool reload) { - if (i_InstanceId != 0) + LoadMapImpl(this, gx, gy, reload); + for (Map* childBaseMap : *m_childTerrainMaps) + LoadMapImpl(childBaseMap, gx, gy, reload); +} + +void Map::LoadMapImpl(Map* map, int gx, int gy, bool reload) +{ + if (map->i_InstanceId != 0) { - if (GridMaps[gx][gy]) + if (map->GridMaps[gx][gy]) return; // load grid map for base map - if (!m_parentMap->GridMaps[gx][gy]) - m_parentMap->EnsureGridCreated(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy)); + if (!map->m_parentMap->GridMaps[gx][gy]) + map->m_parentMap->EnsureGridCreated(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy)); - ((MapInstanced*)(m_parentMap))->AddGridMapReference(GridCoord(gx, gy)); - GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy]; + map->m_parentMap->ToMapInstanced()->AddGridMapReference(GridCoord(gx, gy)); + map->GridMaps[gx][gy] = map->m_parentMap->GridMaps[gx][gy]; return; } - if (GridMaps[gx][gy] && !reload) + if (map->GridMaps[gx][gy] && !reload) return; //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?) - if (GridMaps[gx][gy]) + if (map->GridMaps[gx][gy]) { - TC_LOG_DEBUG("maps", "Unloading previously loaded map %u before reloading.", GetId()); - sScriptMgr->OnUnloadGridMap(this, GridMaps[gx][gy], gx, gy); + TC_LOG_DEBUG("maps", "Unloading previously loaded map %u before reloading.", map->GetId()); + sScriptMgr->OnUnloadGridMap(map, map->GridMaps[gx][gy], gx, gy); - delete (GridMaps[gx][gy]); - GridMaps[gx][gy]=NULL; + delete map->GridMaps[gx][gy]; + map->GridMaps[gx][gy] = nullptr; } // map file name - std::string fileName = Trinity::StringFormat("%smaps/%03u%02u%02u.map", sWorld->GetDataPath().c_str(), GetId(), gx, gy); + std::string fileName = Trinity::StringFormat("%smaps/%03u%02u%02u.map", sWorld->GetDataPath().c_str(), map->GetId(), gx, gy); TC_LOG_DEBUG("maps", "Loading map %s", fileName.c_str()); // loading data - GridMaps[gx][gy] = new GridMap(); - if (!GridMaps[gx][gy]->loadData(fileName.c_str())) + map->GridMaps[gx][gy] = new GridMap(); + if (!map->GridMaps[gx][gy]->loadData(fileName.c_str())) TC_LOG_ERROR("maps", "Error loading map file: %s", fileName.c_str()); - sScriptMgr->OnLoadGridMap(this, GridMaps[gx][gy], gx, gy); + sScriptMgr->OnLoadGridMap(map, map->GridMaps[gx][gy], gx, gy); +} + +void Map::UnloadMap(Map* map, int gx, int gy) +{ + if (map->i_InstanceId == 0) + { + if (map->GridMaps[gx][gy]) + { + map->GridMaps[gx][gy]->unloadData(); + delete map->GridMaps[gx][gy]; + } + } + else + static_cast(map->m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy)); + + map->GridMaps[gx][gy] = nullptr; } void Map::LoadMapAndVMap(int gx, int gy) @@ -222,10 +249,10 @@ void Map::LoadAllCells() void Map::InitStateMachine() { - si_GridStates[GRID_STATE_INVALID] = new InvalidState; - si_GridStates[GRID_STATE_ACTIVE] = new ActiveState; - si_GridStates[GRID_STATE_IDLE] = new IdleState; - si_GridStates[GRID_STATE_REMOVAL] = new RemovalState; + si_GridStates[GRID_STATE_INVALID] = new InvalidState(); + si_GridStates[GRID_STATE_ACTIVE] = new ActiveState(); + si_GridStates[GRID_STATE_IDLE] = new IdleState(); + si_GridStates[GRID_STATE_REMOVAL] = new RemovalState(); } void Map::DeleteStateMachine() @@ -245,14 +272,24 @@ m_activeNonPlayersIter(m_activeNonPlayers.end()), _transportsUpdateIter(_transpo i_gridExpiry(expiry), i_scriptLock(false), _defaultLight(GetDefaultMapLight(id)) { - m_parentMap = (_parent ? _parent : this); - for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) + if (_parent) { - for (unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j) + m_parentMap = _parent; + m_childTerrainMaps = m_parentMap->m_childTerrainMaps; + } + else + { + m_parentMap = this; + m_childTerrainMaps = new std::vector(); + } + + for (uint32 x = 0; x < MAX_NUMBER_OF_GRIDS; ++x) + { + for (uint32 y = 0; y < MAX_NUMBER_OF_GRIDS; ++y) { //z code - GridMaps[idx][j] =NULL; - setNGrid(NULL, idx, j); + GridMaps[x][y] = nullptr; + setNGrid(nullptr, x, y); } } @@ -260,7 +297,7 @@ i_scriptLock(false), _defaultLight(GetDefaultMapLight(id)) Map::InitVisibilityDistance(); _weatherUpdateTimer.SetInterval(time_t(1 * IN_MILLISECONDS)); - + MMAP::MMapFactory::createOrGetMMapManager()->loadMapInstance(sWorld->GetDataPath(), GetId(), i_InstanceId); sScriptMgr->OnCreateMap(this); } @@ -542,8 +579,7 @@ bool Map::AddPlayerToMap(Player* player) player->m_clientGUIDs.clear(); player->UpdateObjectVisibility(false); - - player->SendUpdatePhasing(); + PhasingHandler::SendToPlayer(player); if (player->IsAlive()) ConvertCorpseToBones(player->GetGUID()); @@ -606,8 +642,6 @@ bool Map::AddToMap(T* obj) if (obj->isActiveObject()) AddToActive(obj); - obj->RebuildTerrainSwaps(); - //something, such as vehicle, needs to be update immediately //also, trigger needs to cast spell, if not update, cannot see visual obj->UpdateObjectVisibilityOnCreate(); @@ -1611,20 +1645,16 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll) // delete grid map, but don't delete if it is from parent map (and thus only reference) //+++if (GridMaps[gx][gy]) don't check for GridMaps[gx][gy], we might have to unload vmaps { + for (Map* childBaseMap : *m_childTerrainMaps) + UnloadMap(childBaseMap, gx, gy); + + UnloadMap(this, gx, gy); + if (i_InstanceId == 0) { - if (GridMaps[gx][gy]) - { - GridMaps[gx][gy]->unloadData(); - delete GridMaps[gx][gy]; - } VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy); MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId(), gx, gy); } - else - ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy)); - - GridMaps[gx][gy] = NULL; } TC_LOG_DEBUG("maps", "Unloading grid[%u, %u] for map %u finished", x, y, GetId()); return true; @@ -1708,6 +1738,7 @@ GridMap::GridMap() _liquidEntry = nullptr; _liquidFlags = nullptr; _liquidMap = nullptr; + _fileExists = false; } GridMap::~GridMap() @@ -1726,6 +1757,8 @@ bool GridMap::loadData(const char* filename) if (!in) return true; + _fileExists = true; + if (fread(&header, sizeof(header), 1, in) != 1) { fclose(in); @@ -1780,6 +1813,7 @@ void GridMap::unloadData() _liquidFlags = nullptr; _liquidMap = nullptr; _gridGetHeight = &GridMap::getHeightFromFlat; + _fileExists = false; } bool GridMap::loadAreaData(FILE* in, uint32 offset, uint32 /*size*/) @@ -2254,18 +2288,38 @@ inline GridMap* Map::GetGrid(float x, float y) return GridMaps[gx][gy]; } -float Map::GetWaterOrGroundLevel(std::set const& phases, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/) const +GridMap* Map::GetGrid(uint32 mapId, float x, float y) +{ + if (GetId() == mapId) + return GetGrid(x, y); + + // half opt method + int gx = (int)(CENTER_GRID_ID - x / SIZE_OF_GRIDS); //grid x + int gy = (int)(CENTER_GRID_ID - y / SIZE_OF_GRIDS); //grid y + + // ensure GridMap is loaded + EnsureGridCreated(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - gx, (MAX_NUMBER_OF_GRIDS - 1) - gy)); + + GridMap* grid = GridMaps[gx][gy]; + auto childMapItr = std::find_if(m_childTerrainMaps->begin(), m_childTerrainMaps->end(), [mapId](Map* childTerrainMap) { return childTerrainMap->GetId() == mapId; }); + if (childMapItr != m_childTerrainMaps->end() && (*childMapItr)->GridMaps[gx][gy]->fileExists()) + grid = (*childMapItr)->GridMaps[gx][gy]; + + return grid; +} + +float Map::GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground /*= nullptr*/, bool /*swim = false*/) const { if (const_cast(this)->GetGrid(x, y)) { // we need ground level (including grid height version) for proper return water level in point - float ground_z = GetHeight(phases, x, y, z, true, 50.0f); + float ground_z = GetHeight(phaseShift, x, y, z, true, 50.0f); if (ground) *ground = ground_z; LiquidData liquid_status; - ZLiquidStatus res = GetLiquidStatus(x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status); + ZLiquidStatus res = GetLiquidStatus(phaseShift, x, y, ground_z, MAP_ALL_LIQUIDS, &liquid_status); switch (res) { case LIQUID_MAP_ABOVE_WATER: @@ -2280,11 +2334,12 @@ float Map::GetWaterOrGroundLevel(std::set const& phases, float x, float return VMAP_INVALID_HEIGHT_VALUE; } -float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const +float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const { // find raw .map surface under Z coordinates float mapHeight = VMAP_INVALID_HEIGHT_VALUE; - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y); + if (GridMap* gmap = const_cast(this)->GetGrid(terrainMapId, x, y)) { float gridHeight = gmap->getHeight(x, y); // look from a bit higher pos to find the floor, ignore under surface case @@ -2297,7 +2352,7 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); if (vmgr->isHeightCalcEnabled()) - vmapHeight = vmgr->getHeight(GetId(), x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor + vmapHeight = vmgr->getHeight(terrainMapId, x, y, z + 2.0f, maxSearchDist); // look from a bit higher pos to find the floor } // mapHeight set for any above raw ground Z or <= INVALID_HEIGHT @@ -2346,13 +2401,13 @@ inline bool IsOutdoorWMO(uint32 mogpFlags, int32 /*adtId*/, int32 /*rootId*/, in return outdoor; } -bool Map::IsOutdoors(float x, float y, float z) const +bool Map::IsOutdoors(PhaseShift const& phaseShift, float x, float y, float z) const { uint32 mogpFlags; int32 adtId, rootId, groupId; // no wmo found? -> outside by default - if (!GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) + if (!GetAreaInfo(phaseShift, x, y, z, mogpFlags, adtId, rootId, groupId)) return true; AreaTableEntry const* atEntry = nullptr; @@ -2365,14 +2420,15 @@ bool Map::IsOutdoors(float x, float y, float z) const return IsOutdoorWMO(mogpFlags, adtId, rootId, groupId, wmoEntry, atEntry); } -bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const +bool Map::GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const { float vmap_z = z; + uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y); VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); - if (vmgr->getAreaInfo(GetId(), x, y, vmap_z, flags, adtId, rootId, groupId)) + if (vmgr->getAreaInfo(terrainMapId, x, y, vmap_z, flags, adtId, rootId, groupId)) { // check if there's terrain between player height and object height - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(terrainMapId, x, y)) { float _mapheight = gmap->getHeight(x, y); // z + 2.0f condition taken from GetHeight(), not sure if it's such a great choice... @@ -2384,29 +2440,31 @@ bool Map::GetAreaInfo(float x, float y, float z, uint32 &flags, int32 &adtId, in return false; } -uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const +uint32 Map::GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, bool *isOutdoors) const { uint32 mogpFlags; int32 adtId, rootId, groupId; WMOAreaTableEntry const* wmoEntry = nullptr; AreaTableEntry const* atEntry = nullptr; bool haveAreaInfo = false; + uint32 areaId = 0; - if (GetAreaInfo(x, y, z, mogpFlags, adtId, rootId, groupId)) + if (GetAreaInfo(phaseShift, x, y, z, mogpFlags, adtId, rootId, groupId)) { haveAreaInfo = true; wmoEntry = GetWMOAreaTableEntryByTripple(rootId, adtId, groupId); if (wmoEntry) + { + areaId = wmoEntry->areaId; atEntry = sAreaTableStore.LookupEntry(wmoEntry->areaId); + + } } - uint32 areaId = 0; - if (atEntry) - areaId = atEntry->ID; - else + if (!areaId) { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y)) areaId = gmap->getArea(x, y); // this used while not all *.map files generated (instances) @@ -2424,9 +2482,9 @@ uint32 Map::GetAreaId(float x, float y, float z, bool *isOutdoors) const return areaId; } -uint32 Map::GetZoneId(float x, float y, float z) const +uint32 Map::GetZoneId(PhaseShift const& phaseShift, float x, float y, float z) const { - uint32 areaId = GetAreaId(x, y, z); + uint32 areaId = GetAreaId(phaseShift, x, y, z); if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaId)) if (area->zone) return area->zone; @@ -2434,30 +2492,31 @@ uint32 Map::GetZoneId(float x, float y, float z) const return areaId; } -void Map::GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const +void Map::GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z) const { - areaid = zoneid = GetAreaId(x, y, z); + areaid = zoneid = GetAreaId(phaseShift, x, y, z); if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(areaid)) if (area->zone) zoneid = area->zone; } -uint8 Map::GetTerrainType(float x, float y) const +uint8 Map::GetTerrainType(PhaseShift const& phaseShift, float x, float y) const { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y)) return gmap->getTerrainType(x, y); else return 0; } -ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const +ZLiquidStatus Map::GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data) const { ZLiquidStatus result = LIQUID_MAP_NO_WATER; VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); float liquid_level = INVALID_HEIGHT; float ground_level = INVALID_HEIGHT; uint32 liquid_type = 0; - if (vmgr->GetLiquidLevel(GetId(), x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) + uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y); + if (vmgr->GetLiquidLevel(terrainMapId, x, y, z, ReqLiquidType, liquid_level, ground_level, liquid_type)) { TC_LOG_DEBUG("maps", "GetLiquidStatus(): vmap liquid level: %f ground: %f type: %u", liquid_level, ground_level, liquid_type); // Check water level and ground level @@ -2476,7 +2535,7 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp if (liquid_type && liquid_type < 21) { - if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(x, y, z))) + if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId(phaseShift, x, y, z))) { uint32 overrideLiquid = area->LiquidTypeOverride[liquidFlagType]; if (!overrideLiquid && area->zone) @@ -2514,7 +2573,7 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp } } - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(terrainMapId, x, y)) { LiquidData map_data; ZLiquidStatus map_result = gmap->GetLiquidStatus(x, y, z, ReqLiquidType, &map_data); @@ -2535,16 +2594,17 @@ ZLiquidStatus Map::GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidTyp return result; } -void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType) const +void Map::GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType) const { VMAP::IVMapManager* vmgr = VMAP::VMapFactory::createOrGetVMapManager(); VMAP::AreaAndLiquidData vmapData; - vmgr->getAreaAndLiquidData(GetId(), x, y, z, reqLiquidType, vmapData); + uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y); + vmgr->getAreaAndLiquidData(terrainMapId, x, y, z, reqLiquidType, vmapData); if (vmapData.areaInfo) data.areaInfo = boost::in_place(vmapData.areaInfo->adtId, vmapData.areaInfo->rootId, vmapData.areaInfo->groupId, vmapData.areaInfo->mogpFlags); float mapHeight = VMAP_INVALID_HEIGHT; - GridMap* gmap = const_cast(this)->GetGrid(x, y); + GridMap* gmap = const_cast(this)->GetGrid(terrainMapId, x, y); if (gmap) mapHeight = gmap->getHeight(x, y); @@ -2636,32 +2696,32 @@ void Map::GetFullTerrainStatusForPosition(float x, float y, float z, PositionFul } } -float Map::GetWaterLevel(float x, float y) const +float Map::GetWaterLevel(PhaseShift const& phaseShift, float x, float y) const { - if (GridMap* gmap = const_cast(this)->GetGrid(x, y)) + if (GridMap* gmap = const_cast(this)->GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y)) return gmap->getLiquidLevel(x, y); else return 0; } -bool Map::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, std::set const& phases, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const +bool Map::isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const { if ((checks & LINEOFSIGHT_CHECK_VMAP) - && !VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(GetId(), x1, y1, z1, x2, y2, z2, ignoreFlags)) + && !VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(PhasingHandler::GetTerrainMapId(phaseShift, this, x1, y1), x1, y1, z1, x2, y2, z2, ignoreFlags)) return false; if (sWorld->getBoolConfig(CONFIG_CHECK_GOBJECT_LOS) && (checks & LINEOFSIGHT_CHECK_GOBJECT) - && !_dynamicTree.isInLineOfSight({x1, y1, z1}, {x2, y2, z2}, phases)) + && !_dynamicTree.isInLineOfSight({x1, y1, z1}, {x2, y2, z2}, phaseShift)) return false; return true; } -bool Map::getObjectHitPos(std::set const& phases, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist) +bool Map::getObjectHitPos(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist) { G3D::Vector3 startPos(x1, y1, z1); G3D::Vector3 dstPos(x2, y2, z2); G3D::Vector3 resultPos; - bool result = _dynamicTree.getObjectHitPos(phases, startPos, dstPos, resultPos, modifyDist); + bool result = _dynamicTree.getObjectHitPos(startPos, dstPos, resultPos, modifyDist, phaseShift); rx = resultPos.x; ry = resultPos.y; @@ -2669,21 +2729,21 @@ bool Map::getObjectHitPos(std::set const& phases, float x1, float y1, fl return result; } -float Map::GetHeight(std::set const& phases, float x, float y, float z, bool vmap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const +float Map::GetHeight(PhaseShift const& phaseShift, float x, float y, float z, bool vmap /*= true*/, float maxSearchDist /*= DEFAULT_HEIGHT_SEARCH*/) const { - return std::max(GetHeight(x, y, z, vmap, maxSearchDist), GetGameObjectFloor(phases, x, y, z, maxSearchDist)); + return std::max(GetStaticHeight(phaseShift, x, y, z, vmap, maxSearchDist), _dynamicTree.getHeight(x, y, z, maxSearchDist, phaseShift)); } -bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const +bool Map::IsInWater(PhaseShift const& phaseShift, float x, float y, float pZ, LiquidData* data) const { LiquidData liquid_status; LiquidData* liquid_ptr = data ? data : &liquid_status; - return (GetLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; + return (GetLiquidStatus(phaseShift, x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER)) != 0; } -bool Map::IsUnderWater(float x, float y, float z) const +bool Map::IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z) const { - return (GetLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0; + return (GetLiquidStatus(phaseShift, x, y, z, MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER) != 0; } bool Map::CheckGridIntegrity(Creature* c, bool moved) const @@ -2718,6 +2778,7 @@ void Map::SendInitSelf(Player* player) if (Transport* transport = player->GetTransport()) { transport->BuildCreateUpdateBlockForPlayer(&data, player); + player->m_visibleTransports.insert(transport->GetGUID()); } // build data for self presence in world at own client (one time for map) @@ -2725,9 +2786,9 @@ void Map::SendInitSelf(Player* player) // build other passengers at transport also (they always visible and marked as visible and will not send at visibility update at add to map if (Transport* transport = player->GetTransport()) - for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) - if (player != (*itr) && player->HaveAtClient(*itr)) - (*itr)->BuildCreateUpdateBlockForPlayer(&data, player); + for (WorldObject* passenger : transport->GetPassengers()) + if (player != passenger && player->HaveAtClient(passenger)) + passenger->BuildCreateUpdateBlockForPlayer(&data, player); WorldPacket packet; data.BuildPacket(&packet); @@ -2738,9 +2799,14 @@ void Map::SendInitTransports(Player* player) { // Hack to send out transports UpdateData transData(player->GetMapId()); - for (TransportsContainer::const_iterator i = _transports.begin(); i != _transports.end(); ++i) - if (*i != player->GetTransport() && player->IsInPhase(*i)) - (*i)->BuildCreateUpdateBlockForPlayer(&transData, player); + for (Transport* transport : _transports) + { + if (transport != player->GetTransport() && player->IsInPhase(transport)) + { + transport->BuildCreateUpdateBlockForPlayer(&transData, player); + player->m_visibleTransports.insert(transport->GetGUID()); + } + } WorldPacket packet; transData.BuildPacket(&packet); @@ -2751,28 +2817,33 @@ void Map::SendRemoveTransports(Player* player) { // Hack to send out transports UpdateData transData(player->GetMapId()); - for (TransportsContainer::const_iterator i = _transports.begin(); i != _transports.end(); ++i) - if (*i != player->GetTransport()) - (*i)->BuildOutOfRangeUpdateBlock(&transData); + for (Transport* transport : _transports) + { + if (transport != player->GetTransport()) + { + transport->BuildOutOfRangeUpdateBlock(&transData); + player->m_visibleTransports.erase(transport->GetGUID()); + } + } WorldPacket packet; transData.BuildPacket(&packet); player->GetSession()->SendPacket(&packet); } -void Map::SendUpdateTransportVisibility(Player* player, std::set const& previousPhases) +void Map::SendUpdateTransportVisibility(Player* player) { // Hack to send out transports UpdateData transData(player->GetMapId()); - for (TransportsContainer::const_iterator i = _transports.begin(); i != _transports.end(); ++i) + for (Transport* transport : _transports) { - if (*i == player->GetTransport()) - continue; - - if (player->IsInPhase(*i) && !Trinity::Containers::Intersects(previousPhases.begin(), previousPhases.end(), (*i)->GetPhases().begin(), (*i)->GetPhases().end())) - (*i)->BuildCreateUpdateBlockForPlayer(&transData, player); - else if (!player->IsInPhase(*i)) - (*i)->BuildOutOfRangeUpdateBlock(&transData); + if (player->IsInPhase(transport)) + { + if (player->m_visibleTransports.find(transport->GetGUID()) == player->m_visibleTransports.end()) + transport->BuildCreateUpdateBlockForPlayer(&transData, player); + } + else if (player->m_visibleTransports.find(transport->GetGUID()) != player->m_visibleTransports.end()) + transport->BuildOutOfRangeUpdateBlock(&transData); } WorldPacket packet; @@ -3790,8 +3861,8 @@ void Map::LoadCorpseData() continue; } - for (auto phaseId : phases[guid]) - corpse->SetInPhase(phaseId, false, true); + for (uint32 phaseId : phases[guid]) + PhasingHandler::AddPhase(corpse, phaseId, false); AddCorpse(corpse); } while (result->NextRow()); @@ -3876,7 +3947,7 @@ Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i)) bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); - bones->CopyPhaseFrom(corpse); + PhasingHandler::InheritPhaseShift(bones, corpse); AddCorpse(bones); diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index 934ce7c250..9be12e56e5 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -43,6 +43,7 @@ class InstanceScript; class Group; class InstanceSave; class Object; +class PhaseShift; class Weather; class WorldObject; class TempSummon; @@ -216,7 +217,7 @@ class TC_GAME_API GridMap uint8 _liquidOffY; uint8 _liquidWidth; uint8 _liquidHeight; - + bool _fileExists; bool loadAreaData(FILE* in, uint32 offset, uint32 size); bool loadHeightData(FILE* in, uint32 offset, uint32 size); @@ -241,6 +242,7 @@ public: float getLiquidLevel(float x, float y) const; uint8 getTerrainType(float x, float y) const; ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0); + bool fileExists() const { return _fileExists; } }; #pragma pack(push, 1) @@ -350,6 +352,7 @@ class TC_GAME_API Map : public GridRefManager time_t GetGridExpiry(void) const { return i_gridExpiry; } uint32 GetId(void) const { return i_mapEntry->MapID; } + bool HasGrid(int32 gx, int32 gy) const { return GridMaps[gx][gy] && GridMaps[gx][gy]->fileExists(); } static bool ExistMap(uint32 mapid, int gx, int gy); static bool ExistVMap(uint32 mapid, int gx, int gy); @@ -357,25 +360,27 @@ class TC_GAME_API Map : public GridRefManager static void DeleteStateMachine(); Map const* GetParent() const { return m_parentMap; } + void AddChildTerrainMap(Map* map) { m_childTerrainMaps->push_back(map); } + void UnlinkAllChildTerrainMaps() { m_childTerrainMaps->clear(); } // some calls like isInWater should not use vmaps due to processor power // can return INVALID_HEIGHT if under z+2 z coord not found height - float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; + float GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; - void GetFullTerrainStatusForPosition(float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS) const; - ZLiquidStatus GetLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr) const; + void GetFullTerrainStatusForPosition(PhaseShift const& phaseShift, float x, float y, float z, PositionFullTerrainStatus& data, uint8 reqLiquidType = MAP_ALL_LIQUIDS) const; + ZLiquidStatus GetLiquidStatus(PhaseShift const& phaseShift, float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = nullptr) const; - bool GetAreaInfo(float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; - uint32 GetAreaId(float x, float y, float z, bool *isOutdoors = nullptr) const; - uint32 GetZoneId(float x, float y, float z) const; - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const; + bool GetAreaInfo(PhaseShift const& phaseShift, float x, float y, float z, uint32& mogpflags, int32& adtId, int32& rootId, int32& groupId) const; + uint32 GetAreaId(PhaseShift const& phaseShift, float x, float y, float z, bool *isOutdoors = nullptr) const; + uint32 GetZoneId(PhaseShift const& phaseShift, float x, float y, float z) const; + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, float x, float y, float z) const; - bool IsOutdoors(float x, float y, float z) const; + bool IsOutdoors(PhaseShift const& phaseShift, float x, float y, float z) const; - uint8 GetTerrainType(float x, float y) const; - float GetWaterLevel(float x, float y) const; - bool IsInWater(float x, float y, float z, LiquidData* data = nullptr) const; - bool IsUnderWater(float x, float y, float z) const; + uint8 GetTerrainType(PhaseShift const& phaseShift, float x, float y) const; + float GetWaterLevel(PhaseShift const& phaseShift, float x, float y) const; + bool IsInWater(PhaseShift const& phaseShift, float x, float y, float z, LiquidData* data = nullptr) const; + bool IsUnderWater(PhaseShift const& phaseShift, float x, float y, float z) const; void MoveAllCreaturesInMoveList(); void MoveAllGameObjectsInMoveList(); @@ -516,18 +521,18 @@ class TC_GAME_API Map : public GridRefManager BattlegroundMap* ToBattlegroundMap() { if (IsBattlegroundOrArena()) return reinterpret_cast(this); else return NULL; } BattlegroundMap const* ToBattlegroundMap() const { if (IsBattlegroundOrArena()) return reinterpret_cast(this); return NULL; } - float GetWaterOrGroundLevel(std::set const& phases, float x, float y, float z, float* ground = nullptr, bool swim = false) const; - float GetHeight(std::set const& phases, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; - bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, std::set const& phases, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const; + float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false) const; + float GetHeight(PhaseShift const& phaseShifts, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const; + bool isInLineOfSight(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const; void Balance() { _dynamicTree.balance(); } void RemoveGameObjectModel(const GameObjectModel& model) { _dynamicTree.remove(model); } void InsertGameObjectModel(const GameObjectModel& model) { _dynamicTree.insert(model); } bool ContainsGameObjectModel(const GameObjectModel& model) const { return _dynamicTree.contains(model);} - float GetGameObjectFloor(std::set phases, float x, float y, float z, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const + float GetGameObjectFloor(PhaseShift const& phaseShift, float x, float y, float z, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { - return _dynamicTree.getHeight(x, y, z, maxSearchDist, phases); + return _dynamicTree.getHeight(x, y, z, maxSearchDist, phaseShift); } - bool getObjectHitPos(std::set const& phases, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist); + bool getObjectHitPos(PhaseShift const& phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist); virtual uint32 GetOwnerGuildId(uint32 /*team*/ = TEAM_OTHER) const { return 0; } /* @@ -570,7 +575,7 @@ class TC_GAME_API Map : public GridRefManager void SendInitTransports(Player* player); void SendRemoveTransports(Player* player); - void SendUpdateTransportVisibility(Player* player, std::set const& previousPhases); + void SendUpdateTransportVisibility(Player* player); void SendZoneDynamicInfo(uint32 zoneId, Player* player) const; void SendZoneWeather(uint32 zoneId, Player* player) const; void SendZoneWeather(ZoneDynamicInfo const& zoneDynamicInfo, Player* player) const; @@ -612,8 +617,11 @@ class TC_GAME_API Map : public GridRefManager void LoadMapAndVMap(int gx, int gy); void LoadVMap(int gx, int gy); void LoadMap(int gx, int gy, bool reload = false); + static void LoadMapImpl(Map* map, int gx, int gy, bool reload); + static void UnloadMap(Map* map, int gx, int gy); void LoadMMap(int gx, int gy); GridMap* GetGrid(float x, float y); + GridMap* GetGrid(uint32 mapId, float x, float y); void SetTimer(uint32 t) { i_gridExpiry = t < MIN_GRID_DELAY ? MIN_GRID_DELAY : t; } @@ -660,8 +668,6 @@ class TC_GAME_API Map : public GridRefManager void setNGrid(NGridType* grid, uint32 x, uint32 y); void ScriptsProcess(); - void UpdateActiveCells(const float &x, const float &y, const uint32 t_diff); - void SendObjectUpdates(); protected: @@ -706,6 +712,7 @@ class TC_GAME_API Map : public GridRefManager //used for fast base_map (e.g. MapInstanced class object) search for //InstanceMaps and BattlegroundMaps... Map* m_parentMap; + std::vector* m_childTerrainMaps; NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; GridMap* GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index a3bf5179a6..f34349496d 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -56,10 +56,15 @@ void MapManager::Initialize() m_updater.activate(num_threads); } +void MapManager::InitializeParentMapData(std::unordered_map> const& mapData) +{ + _parentMapData = mapData; +} + void MapManager::InitializeVisibilityDistanceInfo() { - for (MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter) - (*iter).second->InitVisibilityDistance(); + for (auto iter = i_maps.begin(); iter != i_maps.end(); ++iter) + iter->second->InitVisibilityDistance(); } MapManager* MapManager::instance() @@ -72,29 +77,46 @@ Map* MapManager::CreateBaseMap(uint32 id) { Map* map = FindBaseMap(id); - if (map == NULL) + if (!map) { - std::lock_guard lock(_mapsLock); - - MapEntry const* entry = sMapStore.LookupEntry(id); - ASSERT(entry); - - if (entry->Instanceable()) - map = new MapInstanced(id, i_gridCleanUpDelay); - else + MapEntry const* entry = sMapStore.AssertEntry(id); + if (entry->rootPhaseMap != -1) { - map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); - map->LoadRespawnTimes(); - map->LoadCorpseData(); + CreateBaseMap(entry->rootPhaseMap); + + // must have been created by parent map + map = FindBaseMap(id); + return ASSERT_NOTNULL(map); } - i_maps[id] = map; + std::lock_guard lock(_mapsLock); + map = CreateBaseMap_i(entry); } ASSERT(map); return map; } +Map* MapManager::CreateBaseMap_i(MapEntry const* mapEntry) +{ + Map* map; + if (mapEntry->Instanceable()) + map = new MapInstanced(mapEntry->MapID, i_gridCleanUpDelay); + else + { + map = new Map(mapEntry->MapID, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); + map->LoadRespawnTimes(); + map->LoadCorpseData(); + } + + i_maps[mapEntry->MapID] = map; + + for (uint32 childMapId : _parentMapData[mapEntry->MapID]) + map->AddChildTerrainMap(CreateBaseMap_i(sMapStore.AssertEntry(childMapId))); + + return map; +} + Map* MapManager::FindBaseNonInstanceMap(uint32 mapId) const { Map* map = FindBaseMap(mapId); @@ -258,6 +280,10 @@ bool MapManager::IsValidMAP(uint32 mapid, bool startUp) void MapManager::UnloadAll() { + // first unlink child maps + for (auto iter = i_maps.begin(); iter != i_maps.end(); ++iter) + iter->second->UnlinkAllChildTerrainMaps(); + for (MapMapType::iterator iter = i_maps.begin(); iter != i_maps.end();) { iter->second->UnloadAll(); diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index ca75b7382f..12cf7c0c9c 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -26,6 +26,7 @@ #include "MapUpdater.h" #include +class PhaseShift; class Transport; struct TransportCreatureProto; @@ -39,23 +40,24 @@ class TC_GAME_API MapManager Map* CreateMap(uint32 mapId, Player* player, uint32 loginInstanceId=0); Map* FindMap(uint32 mapId, uint32 instanceId) const; - uint32 GetAreaId(uint32 mapid, float x, float y, float z) const + uint32 GetAreaId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z) const { Map const* m = const_cast(this)->CreateBaseMap(mapid); - return m->GetAreaId(x, y, z); + return m->GetAreaId(phaseShift, x, y, z); } - uint32 GetZoneId(uint32 mapid, float x, float y, float z) const + uint32 GetZoneId(PhaseShift const& phaseShift, uint32 mapid, float x, float y, float z) const { Map const* m = const_cast(this)->CreateBaseMap(mapid); - return m->GetZoneId(x, y, z); + return m->GetZoneId(phaseShift, x, y, z); } - void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) + void GetZoneAndAreaId(PhaseShift const& phaseShift, uint32& zoneid, uint32& areaid, uint32 mapid, float x, float y, float z) { Map const* m = const_cast(this)->CreateBaseMap(mapid); - m->GetZoneAndAreaId(zoneid, areaid, x, y, z); + m->GetZoneAndAreaId(phaseShift, zoneid, areaid, x, y, z); } void Initialize(void); + void InitializeParentMapData(std::unordered_map> const& mapData); void Update(uint32); void SetGridCleanUpDelay(uint32 t) @@ -142,8 +144,10 @@ class TC_GAME_API MapManager return (iter == i_maps.end() ? NULL : iter->second); } - MapManager(const MapManager &); - MapManager& operator=(const MapManager &); + Map* CreateBaseMap_i(MapEntry const* mapEntry); + + MapManager(MapManager const&) = delete; + MapManager& operator=(MapManager const&) = delete; std::mutex _mapsLock; uint32 i_gridCleanUpDelay; @@ -156,6 +160,9 @@ class TC_GAME_API MapManager // atomic op counter for active scripts amount std::atomic _scheduledScripts; + + // parent map links + std::unordered_map> _parentMapData; }; template diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp index cd3bdb5902..2b096d9c5b 100644 --- a/src/server/game/Maps/TransportMgr.cpp +++ b/src/server/game/Maps/TransportMgr.cpp @@ -20,6 +20,7 @@ #include "InstanceScript.h" #include "MoveSpline.h" #include "MapManager.h" +#include "PhasingHandler.h" TransportTemplate::~TransportTemplate() { @@ -354,7 +355,7 @@ void TransportMgr::AddPathNodeToTransport(uint32 transportEntry, uint32 timeSeg, animNode.Path[timeSeg] = node; } -Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid /*= 0*/, Map* map /*= NULL*/, uint32 phaseid /*= 0*/, uint32 phasegroup /*= 0*/) +Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid /*= 0*/, Map* map /*= nullptr*/, uint8 phaseUseFlags /*= 0*/, uint32 phaseId /*= 0*/, uint32 phaseGroupId /*= 0*/) { // instance case, execute GetGameObjectEntry hook if (map) @@ -395,12 +396,7 @@ Transport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType guid return NULL; } - if (phaseid) - trans->SetInPhase(phaseid, false, true); - - if (phasegroup) - for (auto ph : GetPhasesForGroup(phasegroup)) - trans->SetInPhase(ph, false, true); + PhasingHandler::InitDbPhaseShift(trans->GetPhaseShift(), phaseUseFlags, phaseId, phaseGroupId); if (MapEntry const* mapEntry = sMapStore.LookupEntry(mapId)) { @@ -431,7 +427,7 @@ void TransportMgr::SpawnContinentTransports() uint32 oldMSTime = getMSTime(); - QueryResult result = WorldDatabase.Query("SELECT guid, entry, phaseid, phasegroup FROM transports"); + QueryResult result = WorldDatabase.Query("SELECT guid, entry, phaseUseFlags, phaseid, phasegroup FROM transports"); uint32 count = 0; if (result) @@ -441,12 +437,50 @@ void TransportMgr::SpawnContinentTransports() Field* fields = result->Fetch(); ObjectGuid::LowType guid = fields[0].GetUInt32(); uint32 entry = fields[1].GetUInt32(); - uint32 phaseid = fields[2].GetUInt32(); - uint32 phasegroup = fields[3].GetUInt32(); + uint8 phaseUseFlags = fields[2].GetUInt8(); + uint32 phaseId = fields[3].GetUInt32(); + uint32 phaseGroupId = fields[4].GetUInt32(); + + if (phaseUseFlags & ~PHASE_USE_FLAGS_ALL) + { + TC_LOG_ERROR("sql.sql", "Table `transports` have transport (GUID: " UI64FMTD " Entry: %u) with unknown `phaseUseFlags` set, removed unknown value.", guid, entry); + phaseUseFlags &= PHASE_USE_FLAGS_ALL; + } + + if (phaseUseFlags & PHASE_USE_FLAGS_ALWAYS_VISIBLE && phaseUseFlags & PHASE_USE_FLAGS_INVERSE) + { + TC_LOG_ERROR("sql.sql", "Table `transports` have transport (GUID: " UI64FMTD " Entry: %u) has both `phaseUseFlags` PHASE_USE_FLAGS_ALWAYS_VISIBLE and PHASE_USE_FLAGS_INVERSE," + " removing PHASE_USE_FLAGS_INVERSE.", guid, entry); + phaseUseFlags &= ~PHASE_USE_FLAGS_INVERSE; + } + + if (phaseGroupId && phaseId) + { + TC_LOG_ERROR("sql.sql", "Table `transports` have transport (GUID: " UI64FMTD " Entry: %u) with both `phaseid` and `phasegroup` set, `phasegroup` set to 0", guid, entry); + phaseGroupId = 0; + } + + if (phaseId) + { + if (!sPhaseStore.LookupEntry(phaseId)) + { + TC_LOG_ERROR("sql.sql", "Table `transports` have transport (GUID: " UI64FMTD " Entry: %u) with `phaseid` %u does not exist, set to 0", guid, entry, phaseId); + phaseId = 0; + } + } + + if (phaseGroupId) + { + if (!GetPhasesForGroup(phaseGroupId)) + { + TC_LOG_ERROR("sql.sql", "Table `transports` have transport (GUID: " UI64FMTD " Entry: %u) with `phaseGroup` %u does not exist, set to 0", guid, entry, phaseGroupId); + phaseGroupId = 0; + } + } if (TransportTemplate const* tInfo = GetTransportTemplate(entry)) if (!tInfo->inInstance) - if (CreateTransport(entry, guid, nullptr, phaseid, phasegroup)) + if (CreateTransport(entry, guid, nullptr, phaseUseFlags, phaseId, phaseGroupId)) ++count; } while (result->NextRow()); diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h index 4038d213b3..14025b0fc3 100644 --- a/src/server/game/Maps/TransportMgr.h +++ b/src/server/game/Maps/TransportMgr.h @@ -108,7 +108,7 @@ class TC_GAME_API TransportMgr void LoadTransportTemplates(); // Creates a transport using given GameObject template entry - Transport* CreateTransport(uint32 entry, ObjectGuid::LowType guid = 0, Map* map = nullptr, uint32 phaseid = 0, uint32 phasegroup = 0); + Transport* CreateTransport(uint32 entry, ObjectGuid::LowType guid = 0, Map* map = nullptr, uint8 phaseUseFlags = 0, uint32 phaseId = 0, uint32 phaseGroupId = 0); // Spawns all continent transports, used at core startup void SpawnContinentTransports(); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index d4440de644..1b9781c91e 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -213,7 +213,13 @@ enum TrinityStrings LANG_INVALID_GAMEOBJECT_TYPE = 176, LANG_GAMEOBJECT_DAMAGED = 177, LANG_GRID_POSITION = 178, - // 179-185 used in 6.x branch + LANG_PHASESHIFT_STATUS = 179, + LANG_PHASESHIFT_PHASES = 180, + LANG_PHASESHIFT_VISIBLE_MAP_IDS = 181, + LANG_PHASESHIFT_UI_WORLD_MAP_AREA_SWAPS = 182, + LANG_PHASE_FLAG_COSMETIC = 183, + LANG_PHASE_FLAG_PERSONAL = 184, + // 185 not used LANG_TRANSPORT_POSITION = 186, LANG_PARTIAL_GROUP_SUMMON = 187, // Room for more level 1 188-199 not used diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 6a470f6603..b15310b052 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -486,7 +486,7 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool if (_owner->IsFlying()) point.z = z; else - point.z = _owner->GetMap()->GetHeight(_owner->GetPhases(), point.x, point.y, z); + point.z = _owner->GetMap()->GetHeight(_owner->GetPhaseShift(), point.x, point.y, z); init.Path().push_back(point); } @@ -571,7 +571,7 @@ void MotionMaster::ResumeSplineChain(SplineChainResumeInfo const& info) void MotionMaster::MoveFall(uint32 id /*=0*/) { // use larger distance for vmap height search than in most other cases - float tz = _owner->GetMap()->GetHeight(_owner->GetPhases(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ(), true, MAX_FALL_DISTANCE); + float tz = _owner->GetMap()->GetHeight(_owner->GetPhaseShift(), _owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ(), true, MAX_FALL_DISTANCE); if (tz <= INVALID_HEIGHT) { TC_LOG_DEBUG("misc", "MotionMaster::MoveFall: unable to retrieve a proper height at map %u (x: %f, y: %f, z: %f).", diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index 8fdbd03ec8..0de1fd1987 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -24,6 +24,7 @@ #include "PathGenerator.h" #include "MoveSplineInit.h" #include "MoveSpline.h" +#include "PhasingHandler.h" #include "FleeingMovementGenerator.h" #define MIN_QUIET_DISTANCE 28.0f @@ -115,8 +116,13 @@ void FleeingMovementGenerator::SetTargetLocation(T* owner) GetPoint(owner, destination); // Add LOS check for target point - Position currentPosition = owner->GetPosition(); - if (!VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight(owner->GetMapId(), currentPosition.m_positionX, currentPosition.m_positionY, currentPosition.m_positionZ + 1.0f, destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ() + 1.0f, VMAP::ModelIgnoreFlags::Nothing)) + Position mypos = owner->GetPosition(); + bool isInLOS = VMAP::VMapFactory::createOrGetVMapManager()->isInLineOfSight( + PhasingHandler::GetTerrainMapId(owner->GetPhaseShift(), owner->GetMap(), mypos.m_positionX, mypos.m_positionY), + mypos.m_positionX, mypos.m_positionY, mypos.m_positionZ + 2.0f, destination.m_positionX, destination.m_positionY, + destination.m_positionZ + 2.0f, VMAP::ModelIgnoreFlags::Nothing); + + if (!isInLOS) { _timer.Reset(200); return; diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index d2379f806a..8bd2b5dc9e 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -63,7 +63,7 @@ void RandomMovementGenerator::_setRandomLocation(Creature* creature) // Limit height change const float distanceZ = float(rand_norm()) * travelDistZ/2.0f; destZ = respZ + distanceZ; - float levelZ = map->GetWaterOrGroundLevel(creature->GetPhases(), destX, destY, destZ-2.5f); + float levelZ = map->GetWaterOrGroundLevel(creature->GetPhaseShift(), destX, destY, destZ-2.5f); // Problem here, we must fly above the ground and water, not under. Let's try on next tick if (levelZ >= destZ) @@ -77,17 +77,17 @@ void RandomMovementGenerator::_setRandomLocation(Creature* creature) // The fastest way to get an accurate result 90% of the time. // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. - destZ = map->GetHeight(creature->GetPhases(), destX, destY, respZ+travelDistZ-2.0f, false); + destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ+travelDistZ-2.0f, false); if (std::fabs(destZ - respZ) > travelDistZ) // Map check { // Vmap Horizontal or above - destZ = map->GetHeight(creature->GetPhases(), destX, destY, respZ - 2.0f, true); + destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ - 2.0f, true); if (std::fabs(destZ - respZ) > travelDistZ) { // Vmap Higher - destZ = map->GetHeight(creature->GetPhases(), destX, destY, respZ+travelDistZ-2.0f, true); + destZ = map->GetHeight(creature->GetPhaseShift(), destX, destY, respZ+travelDistZ-2.0f, true); // let's forget this bad coords where a z cannot be find and retry at next tick if (std::fabs(destZ - respZ) > travelDistZ) diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 0d447effab..f8b1291398 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -27,6 +27,7 @@ #include "DetourCommon.h" #include "DetourNavMeshQuery.h" #include "Metric.h" +#include "PhasingHandler.h" ////////////////// PathGenerator ////////////////// PathGenerator::PathGenerator(const Unit* owner) : @@ -39,8 +40,8 @@ PathGenerator::PathGenerator(const Unit* owner) : TC_LOG_DEBUG("maps", "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUID().GetCounter()); - uint32 mapId = _sourceUnit->GetMapId(); - if (DisableMgr::IsPathfindingEnabled(mapId)) + uint32 mapId = PhasingHandler::GetTerrainMapId(_sourceUnit->GetPhaseShift(), _sourceUnit->GetMap(), _sourceUnit->GetPositionX(), _sourceUnit->GetPositionY()); + if (DisableMgr::IsPathfindingEnabled(_sourceUnit->GetMapId())) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); _navMesh = mmap->GetNavMesh(mapId); @@ -185,7 +186,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // Check both start and end points, if they're both in water, then we can *safely* let the creature move for (uint32 i = 0; i < _pathPoints.size(); ++i) { - ZLiquidStatus status = _sourceUnit->GetBaseMap()->GetLiquidStatus(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); + ZLiquidStatus status = _sourceUnit->GetBaseMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); // One of the points is not in the water, cancel movement. if (status == LIQUID_MAP_NO_WATER) { @@ -211,7 +212,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con Creature* owner = (Creature*)_sourceUnit; G3D::Vector3 const& p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) + if (_sourceUnit->GetBaseMap()->IsUnderWater(_sourceUnit->GetPhaseShift(), p.x, p.y, p.z)) { TC_LOG_DEBUG("maps", "++ BuildPolyPath :: underWater case\n"); if (owner->CanSwim()) @@ -648,7 +649,7 @@ void PathGenerator::UpdateFilter() NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) { LiquidData data; - ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); + ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->GetLiquidStatus(_sourceUnit->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &data); if (liquidStatus == LIQUID_MAP_NO_WATER) return NAV_GROUND; diff --git a/src/server/game/Phasing/PhaseShift.cpp b/src/server/game/Phasing/PhaseShift.cpp new file mode 100644 index 0000000000..b2885ae15b --- /dev/null +++ b/src/server/game/Phasing/PhaseShift.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2008-2018 TrinityCore + * + * 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 . + */ + +#include "PhaseShift.h" +#include "Containers.h" + +bool PhaseShift::AddPhase(uint32 phaseId, PhaseFlags flags, std::vector const* areaConditions, int32 references /*= 1*/) +{ + auto insertResult = Phases.emplace(phaseId, flags, nullptr); + ModifyPhasesReferences(insertResult.first, references); + if (areaConditions) + insertResult.first->AreaConditions = areaConditions; + + return insertResult.second; +} + +PhaseShift::EraseResult PhaseShift::RemovePhase(uint32 phaseId) +{ + auto itr = Phases.find(PhaseRef(phaseId, PhaseFlags::None, nullptr)); + if (itr != Phases.end()) + { + ModifyPhasesReferences(itr, -1); + if (!itr->References) + return { Phases.erase(itr), true }; + return { itr, false }; + } + return { Phases.end(), false }; +} + +bool PhaseShift::AddVisibleMapId(uint32 visibleMapId, TerrainSwapInfo const* visibleMapInfo, int32 references /*= 1*/) +{ + auto insertResult = VisibleMapIds.emplace(visibleMapId, VisibleMapIdRef{ 0, visibleMapInfo }); + insertResult.first->second.References += references; + return insertResult.second; +} + +PhaseShift::EraseResult PhaseShift::RemoveVisibleMapId(uint32 visibleMapId) +{ + auto itr = VisibleMapIds.find(visibleMapId); + if (itr != VisibleMapIds.end()) + { + if (!--itr->second.References) + return { VisibleMapIds.erase(itr), true }; + return { itr, false }; + } + return { VisibleMapIds.end(), false }; +} + +bool PhaseShift::AddUiWorldMapAreaIdSwap(uint32 uiWorldMapAreaId, int32 references /*= 1*/) +{ + auto insertResult = UiWorldMapAreaIdSwaps.emplace(uiWorldMapAreaId, UiWorldMapAreaIdSwapRef{ 0 }); + insertResult.first->second.References += references; + return insertResult.second; +} + +PhaseShift::EraseResult PhaseShift::RemoveUiWorldMapAreaIdSwap(uint32 uiWorldMapAreaId) +{ + auto itr = UiWorldMapAreaIdSwaps.find(uiWorldMapAreaId); + if (itr != UiWorldMapAreaIdSwaps.end()) + { + if (!--itr->second.References) + return { UiWorldMapAreaIdSwaps.erase(itr), true }; + return { itr, false }; + } + return { UiWorldMapAreaIdSwaps.end(), false }; +} + +void PhaseShift::Clear() +{ + ClearPhases(); + PersonalGuid.Clear(); + VisibleMapIds.clear(); + UiWorldMapAreaIdSwaps.clear(); +} + +void PhaseShift::ClearPhases() +{ + Flags &= EnumClassFlag(PhaseShiftFlags::AlwaysVisible) | PhaseShiftFlags::Inverse; + Phases.clear(); + NonCosmeticReferences = 0; + CosmeticReferences = 0; + DefaultReferences = 0; + UpdateUnphasedFlag(); +} + +bool PhaseShift::CanSee(PhaseShift const& other) const +{ + if (Flags.HasFlag(PhaseShiftFlags::Unphased) && other.Flags.HasFlag(PhaseShiftFlags::Unphased)) + return true; + if (Flags.HasFlag(PhaseShiftFlags::AlwaysVisible) || other.Flags.HasFlag(PhaseShiftFlags::AlwaysVisible)) + return true; + if (Flags.HasFlag(PhaseShiftFlags::Inverse) && other.Flags.HasFlag(PhaseShiftFlags::Inverse)) + return true; + + PhaseFlags excludePhasesWithFlag = PhaseFlags::None; + if (Flags.HasFlag(PhaseShiftFlags::NoCosmetic) && other.Flags.HasFlag(PhaseShiftFlags::NoCosmetic)) + excludePhasesWithFlag = PhaseFlags::Cosmetic; + + if (!Flags.HasFlag(PhaseShiftFlags::Inverse) && !other.Flags.HasFlag(PhaseShiftFlags::Inverse)) + { + ObjectGuid ownerGuid = PersonalGuid; + ObjectGuid otherPersonalGuid = other.PersonalGuid; + return Trinity::Containers::Intersects(Phases.begin(), Phases.end(), other.Phases.begin(), other.Phases.end(), + [&ownerGuid, &otherPersonalGuid, excludePhasesWithFlag](PhaseRef const& myPhase, PhaseRef const& /*otherPhase*/) + { + return !myPhase.Flags.HasFlag(excludePhasesWithFlag) && (!myPhase.Flags.HasFlag(PhaseFlags::Personal) || ownerGuid == otherPersonalGuid); + }); + } + + auto checkInversePhaseShift = [excludePhasesWithFlag](PhaseShift const& phaseShift, PhaseShift const& excludedPhaseShift) + { + if (phaseShift.Flags.HasFlag(PhaseShiftFlags::Unphased) && !excludedPhaseShift.Flags.HasFlag(PhaseShiftFlags::InverseUnphased)) + return true; + + for (auto itr = phaseShift.Phases.begin(); itr != phaseShift.Phases.end(); ++itr) + { + if (itr->Flags.HasFlag(excludePhasesWithFlag)) + continue; + + auto itr2 = std::find(excludedPhaseShift.Phases.begin(), excludedPhaseShift.Phases.end(), *itr); + if (itr2 == excludedPhaseShift.Phases.end() || itr2->Flags.HasFlag(excludePhasesWithFlag)) + return true; + } + + return false; + }; + + if (other.Flags.HasFlag(PhaseShiftFlags::Inverse)) + return checkInversePhaseShift(*this, other); + + return checkInversePhaseShift(other, *this); +} + +void PhaseShift::ModifyPhasesReferences(PhaseContainer::iterator itr, int32 references) +{ + itr->References += references; + + if (!IsDbPhaseShift) + { + if (itr->Flags.HasFlag(PhaseFlags::Cosmetic)) + CosmeticReferences += references; + else if (itr->Id != DEFAULT_PHASE) + NonCosmeticReferences += references; + else + DefaultReferences += references; + + if (CosmeticReferences) + Flags |= PhaseShiftFlags::NoCosmetic; + else + Flags &= ~EnumClassFlag(PhaseShiftFlags::NoCosmetic); + + UpdateUnphasedFlag(); + } +} + +void PhaseShift::UpdateUnphasedFlag() +{ + EnumClassFlag unphasedFlag = !Flags.HasFlag(PhaseShiftFlags::Inverse) ? PhaseShiftFlags::Unphased : PhaseShiftFlags::InverseUnphased; + Flags &= ~EnumClassFlag(!Flags.HasFlag(PhaseShiftFlags::Inverse) ? PhaseShiftFlags::InverseUnphased : PhaseShiftFlags::Unphased); + if (NonCosmeticReferences && !DefaultReferences) + Flags &= ~unphasedFlag; + else + Flags |= unphasedFlag; +} diff --git a/src/server/game/Phasing/PhaseShift.h b/src/server/game/Phasing/PhaseShift.h new file mode 100644 index 0000000000..8755868ae9 --- /dev/null +++ b/src/server/game/Phasing/PhaseShift.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2008-2018 TrinityCore + * + * 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 . + */ + +#ifndef PhaseShift_h__ +#define PhaseShift_h__ + +#include "Define.h" +#include "EnumClassFlag.h" +#include "ObjectGuid.h" +#include +#include + +class PhasingHandler; +struct Condition; +struct TerrainSwapInfo; + +#define DEFAULT_PHASE 169 + +enum class PhaseShiftFlags : uint32 +{ + None = 0x00, + AlwaysVisible = 0x01, // Ignores all phasing, can see everything and be seen by everything + Inverse = 0x02, // By default having at least one shared phase for two objects means they can see each other + // this flag makes objects see each other if they have at least one non-shared phase + InverseUnphased = 0x04, + Unphased = 0x08, + NoCosmetic = 0x10 // This flag ignores shared cosmetic phases (two players that both have shared cosmetic phase but no other phase cannot see each other) +}; + +enum class PhaseFlags : uint16 +{ + None = 0x0, + Cosmetic = 0x1, + Personal = 0x2 +}; + +class TC_GAME_API PhaseShift +{ +public: + struct PhaseRef + { + PhaseRef(uint32 id, PhaseFlags flags, std::vector const* conditions) + : Id(id), Flags(flags), References(0), AreaConditions(conditions) { } + + uint16 Id; + EnumClassFlag Flags; + int32 References; + std::vector const* AreaConditions; + bool operator<(PhaseRef const& right) const { return Id < right.Id; } + bool operator==(PhaseRef const& right) const { return Id == right.Id; } + }; + struct VisibleMapIdRef + { + int32 References = 0; + TerrainSwapInfo const* VisibleMapInfo = nullptr; + }; + struct UiWorldMapAreaIdSwapRef + { + int32 References = 0; + }; + template + struct EraseResult + { + typename Container::iterator Iterator; + bool Erased; + }; + typedef boost::container::flat_set PhaseContainer; + typedef std::map VisibleMapIdContainer; + typedef std::map UiWorldMapAreaIdSwapContainer; + + bool AddPhase(uint32 phaseId, PhaseFlags flags, std::vector const* areaConditions, int32 references = 1); + EraseResult RemovePhase(uint32 phaseId); + bool HasPhase(uint32 phaseId) const { return Phases.find(PhaseRef(phaseId, PhaseFlags::None, nullptr)) != Phases.end(); } + PhaseContainer const& GetPhases() const { return Phases; } + + bool AddVisibleMapId(uint32 visibleMapId, TerrainSwapInfo const* visibleMapInfo, int32 references = 1); + EraseResult RemoveVisibleMapId(uint32 visibleMapId); + bool HasVisibleMapId(uint32 visibleMapId) const { return VisibleMapIds.find(visibleMapId) != VisibleMapIds.end(); } + VisibleMapIdContainer const& GetVisibleMapIds() const { return VisibleMapIds; } + + bool AddUiWorldMapAreaIdSwap(uint32 uiWorldMapAreaId, int32 references = 1); + EraseResult RemoveUiWorldMapAreaIdSwap(uint32 uiWorldMapAreaId); + bool HasUiWorldMapAreaIdSwap(uint32 uiWorldMapAreaId) const { return UiWorldMapAreaIdSwaps.find(uiWorldMapAreaId) != UiWorldMapAreaIdSwaps.end(); } + UiWorldMapAreaIdSwapContainer const& GetUiWorldMapAreaIdSwaps() const { return UiWorldMapAreaIdSwaps; } + + void Clear(); + void ClearPhases(); + + bool CanSee(PhaseShift const& other) const; + +protected: + friend class PhasingHandler; + + EnumClassFlag Flags = PhaseShiftFlags::Unphased; + ObjectGuid PersonalGuid; + PhaseContainer Phases; + VisibleMapIdContainer VisibleMapIds; + UiWorldMapAreaIdSwapContainer UiWorldMapAreaIdSwaps; + + void ModifyPhasesReferences(PhaseContainer::iterator itr, int32 references); + void UpdateUnphasedFlag(); + int32 NonCosmeticReferences = 0; + int32 CosmeticReferences = 0; + int32 DefaultReferences = 0; + bool IsDbPhaseShift = false; +}; + +#endif // PhaseShift_h__ diff --git a/src/server/game/Phasing/PhasingHandler.cpp b/src/server/game/Phasing/PhasingHandler.cpp new file mode 100644 index 0000000000..8b9e8843db --- /dev/null +++ b/src/server/game/Phasing/PhasingHandler.cpp @@ -0,0 +1,607 @@ +/* + * Copyright (C) 2008-2018 TrinityCore + * + * 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 . + */ + +#include "PhasingHandler.h" +#include "Chat.h" +#include "ConditionMgr.h" +#include "Creature.h" +#include "DBCStores.h" +#include "Language.h" +#include "Map.h" +#include "ObjectMgr.h" +#include "PhaseShift.h" +#include "Player.h" +#include "SpellAuraEffects.h" + +namespace +{ +PhaseShift const Empty; + +inline PhaseFlags GetPhaseFlags(uint32 phaseId) +{ + if (PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseId)) + { + if (phase->Flags & PHASE_FLAG_COSMETIC) + return PhaseFlags::Cosmetic; + + if (phase->Flags & PHASE_FLAG_PERSONAL) + return PhaseFlags::Personal; + } + + return PhaseFlags::None; +} + +template +inline void ForAllControlled(Unit* unit, Func&& func) +{ + for (Unit* controlled : unit->m_Controlled) + if (controlled->GetTypeId() != TYPEID_PLAYER) + func(controlled); + + for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i) + if (!unit->m_SummonSlot[i].IsEmpty()) + if (Creature* summon = unit->GetMap()->GetCreature(unit->m_SummonSlot[i])) + func(summon); +} +} + +void PhasingHandler::AddPhase(WorldObject* object, uint32 phaseId, bool updateVisibility) +{ + bool changed = object->GetPhaseShift().AddPhase(phaseId, GetPhaseFlags(phaseId), nullptr); + + if (Unit* unit = object->ToUnit()) + { + unit->OnPhaseChange(); + ForAllControlled(unit, [&](Unit* controlled) + { + AddPhase(controlled, phaseId, updateVisibility); + }); + unit->RemoveNotOwnSingleTargetAuras(true); + } + + UpdateVisibilityIfNeeded(object, updateVisibility, changed); +} + +void PhasingHandler::RemovePhase(WorldObject* object, uint32 phaseId, bool updateVisibility) +{ + bool changed = object->GetPhaseShift().RemovePhase(phaseId).Erased; + + if (Unit* unit = object->ToUnit()) + { + unit->OnPhaseChange(); + ForAllControlled(unit, [&](Unit* controlled) + { + RemovePhase(controlled, phaseId, updateVisibility); + }); + unit->RemoveNotOwnSingleTargetAuras(true); + } + + UpdateVisibilityIfNeeded(object, updateVisibility, changed); +} + +void PhasingHandler::AddPhaseGroup(WorldObject* object, uint32 phaseGroupId, bool updateVisibility) +{ + std::vector const* phasesInGroup = GetPhasesForGroup(phaseGroupId); + if (!phasesInGroup) + return; + + bool changed = false; + for (uint32 phaseId : *phasesInGroup) + changed = object->GetPhaseShift().AddPhase(phaseId, GetPhaseFlags(phaseId), nullptr) || changed; + + if (Unit* unit = object->ToUnit()) + { + unit->OnPhaseChange(); + ForAllControlled(unit, [&](Unit* controlled) + { + AddPhaseGroup(controlled, phaseGroupId, updateVisibility); + }); + unit->RemoveNotOwnSingleTargetAuras(true); + } + + UpdateVisibilityIfNeeded(object, updateVisibility, changed); +} + +void PhasingHandler::RemovePhaseGroup(WorldObject* object, uint32 phaseGroupId, bool updateVisibility) +{ + std::vector const* phasesInGroup = GetPhasesForGroup(phaseGroupId); + if (!phasesInGroup) + return; + + bool changed = false; + for (uint32 phaseId : *phasesInGroup) + changed = object->GetPhaseShift().RemovePhase(phaseId).Erased || changed; + + if (Unit* unit = object->ToUnit()) + { + unit->OnPhaseChange(); + ForAllControlled(unit, [&](Unit* controlled) + { + RemovePhaseGroup(controlled, phaseGroupId, updateVisibility); + }); + unit->RemoveNotOwnSingleTargetAuras(true); + } + + UpdateVisibilityIfNeeded(object, updateVisibility, changed); +} + +void PhasingHandler::AddVisibleMapId(WorldObject* object, uint32 visibleMapId) +{ + TerrainSwapInfo const* terrainSwapInfo = sObjectMgr->GetTerrainSwapInfo(visibleMapId); + bool changed = object->GetPhaseShift().AddVisibleMapId(visibleMapId, terrainSwapInfo); + + for (uint32 uiWorldMapAreaIDSwap : terrainSwapInfo->UiWorldMapAreaIDSwaps) + changed = object->GetPhaseShift().AddUiWorldMapAreaIdSwap(uiWorldMapAreaIDSwap) || changed; + + if (Unit* unit = object->ToUnit()) + { + ForAllControlled(unit, [&](Unit* controlled) + { + AddVisibleMapId(controlled, visibleMapId); + }); + } + + UpdateVisibilityIfNeeded(object, false, changed); +} + +void PhasingHandler::RemoveVisibleMapId(WorldObject* object, uint32 visibleMapId) +{ + TerrainSwapInfo const* terrainSwapInfo = sObjectMgr->GetTerrainSwapInfo(visibleMapId); + bool changed = object->GetPhaseShift().RemoveVisibleMapId(visibleMapId).Erased; + + for (uint32 uiWorldMapAreaIDSwap : terrainSwapInfo->UiWorldMapAreaIDSwaps) + changed = object->GetPhaseShift().RemoveUiWorldMapAreaIdSwap(uiWorldMapAreaIDSwap).Erased || changed; + + if (Unit* unit = object->ToUnit()) + { + ForAllControlled(unit, [&](Unit* controlled) + { + RemoveVisibleMapId(controlled, visibleMapId); + }); + } + + UpdateVisibilityIfNeeded(object, false, changed); +} + +void PhasingHandler::ResetPhaseShift(WorldObject* object) +{ + object->GetPhaseShift().Clear(); + object->GetSuppressedPhaseShift().Clear(); +} + +void PhasingHandler::InheritPhaseShift(WorldObject* target, WorldObject const* source) +{ + if (!source) + return; + + target->GetPhaseShift() = source->GetPhaseShift(); + target->GetSuppressedPhaseShift() = source->GetSuppressedPhaseShift(); +} + +void PhasingHandler::OnMapChange(WorldObject* object) +{ + PhaseShift& phaseShift = object->GetPhaseShift(); + PhaseShift& suppressedPhaseShift = object->GetSuppressedPhaseShift(); + ConditionSourceInfo srcInfo = ConditionSourceInfo(object); + + object->GetPhaseShift().VisibleMapIds.clear(); + object->GetPhaseShift().UiWorldMapAreaIdSwaps.clear(); + object->GetSuppressedPhaseShift().VisibleMapIds.clear(); + + if (std::vector const* visibleMapIds = sObjectMgr->GetTerrainSwapsForMap(object->GetMapId())) + { + for (TerrainSwapInfo const* visibleMapInfo : *visibleMapIds) + { + if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, visibleMapInfo->Id, srcInfo)) + { + phaseShift.AddVisibleMapId(visibleMapInfo->Id, visibleMapInfo); + for (uint32 uiWorldMapAreaIdSwap : visibleMapInfo->UiWorldMapAreaIDSwaps) + phaseShift.AddUiWorldMapAreaIdSwap(uiWorldMapAreaIdSwap); + } + else + suppressedPhaseShift.AddVisibleMapId(visibleMapInfo->Id, visibleMapInfo); + } + } + + UpdateVisibilityIfNeeded(object, false, true); +} + +void PhasingHandler::OnAreaChange(WorldObject* object) +{ + PhaseShift& phaseShift = object->GetPhaseShift(); + PhaseShift& suppressedPhaseShift = object->GetSuppressedPhaseShift(); + PhaseShift::PhaseContainer oldPhases = std::move(phaseShift.Phases); // for comparison + ConditionSourceInfo srcInfo = ConditionSourceInfo(object); + + object->GetPhaseShift().ClearPhases(); + object->GetSuppressedPhaseShift().ClearPhases(); + + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(object->GetAreaId()); + while (areaEntry) + { + if (std::vector const* newAreaPhases = sObjectMgr->GetPhasesForArea(areaEntry->ID)) + { + for (PhaseAreaInfo const& phaseArea : *newAreaPhases) + { + if (phaseArea.SubAreaExclusions.find(areaEntry->ID) != phaseArea.SubAreaExclusions.end()) + continue; + + uint32 phaseId = phaseArea.PhaseInfo->Id; + if (sConditionMgr->IsObjectMeetToConditions(srcInfo, phaseArea.Conditions)) + phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), &phaseArea.Conditions); + else + suppressedPhaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), &phaseArea.Conditions); + } + } + + areaEntry = sAreaTableStore.LookupEntry(areaEntry->zone); + } + + bool changed = phaseShift.Phases != oldPhases; + if (Unit* unit = object->ToUnit()) + { + for (AuraEffect const* aurEff : unit->GetAuraEffectsByType(SPELL_AURA_PHASE)) + { + uint32 phaseId = uint32(aurEff->GetMiscValueB()); + changed = phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), nullptr) || changed; + } + + for (AuraEffect const* aurEff : unit->GetAuraEffectsByType(SPELL_AURA_PHASE_GROUP)) + if (std::vector const* phasesInGroup = GetPhasesForGroup(uint32(aurEff->GetMiscValueB()))) + for (uint32 phaseId : *phasesInGroup) + changed = phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), nullptr) || changed; + + if (changed) + unit->OnPhaseChange(); + + ForAllControlled(unit, [&](Unit* controlled) + { + InheritPhaseShift(controlled, unit); + }); + + if (changed) + unit->RemoveNotOwnSingleTargetAuras(true); + } + + UpdateVisibilityIfNeeded(object, true, changed); +} + +void PhasingHandler::OnConditionChange(WorldObject* object) +{ + PhaseShift& phaseShift = object->GetPhaseShift(); + PhaseShift& suppressedPhaseShift = object->GetSuppressedPhaseShift(); + PhaseShift newSuppressions; + ConditionSourceInfo srcInfo = ConditionSourceInfo(object); + bool changed = false; + + for (auto itr = phaseShift.Phases.begin(); itr != phaseShift.Phases.end();) + { + if (itr->AreaConditions && !sConditionMgr->IsObjectMeetToConditions(srcInfo, *itr->AreaConditions)) + { + newSuppressions.AddPhase(itr->Id, itr->Flags, itr->AreaConditions, itr->References); + itr = phaseShift.Phases.erase(itr); + } + else + ++itr; + } + + for (auto itr = suppressedPhaseShift.Phases.begin(); itr != suppressedPhaseShift.Phases.end();) + { + if (sConditionMgr->IsObjectMeetToConditions(srcInfo, *ASSERT_NOTNULL(itr->AreaConditions))) + { + changed = phaseShift.AddPhase(itr->Id, itr->Flags, itr->AreaConditions, itr->References) || changed; + itr = suppressedPhaseShift.Phases.erase(itr); + } + else + ++itr; + } + + for (auto itr = phaseShift.VisibleMapIds.begin(); itr != phaseShift.VisibleMapIds.end();) + { + if (!sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, itr->first, srcInfo)) + { + newSuppressions.AddVisibleMapId(itr->first, itr->second.VisibleMapInfo, itr->second.References); + for (uint32 uiWorldMapAreaIdSwap : itr->second.VisibleMapInfo->UiWorldMapAreaIDSwaps) + changed = phaseShift.RemoveUiWorldMapAreaIdSwap(uiWorldMapAreaIdSwap).Erased || changed; + + itr = phaseShift.VisibleMapIds.erase(itr); + } + else + ++itr; + } + + for (auto itr = suppressedPhaseShift.VisibleMapIds.begin(); itr != suppressedPhaseShift.VisibleMapIds.end();) + { + if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, itr->first, srcInfo)) + { + changed = phaseShift.AddVisibleMapId(itr->first, itr->second.VisibleMapInfo, itr->second.References) || changed; + for (uint32 uiWorldMapAreaIdSwap : itr->second.VisibleMapInfo->UiWorldMapAreaIDSwaps) + changed = phaseShift.AddUiWorldMapAreaIdSwap(uiWorldMapAreaIdSwap) || changed; + + itr = suppressedPhaseShift.VisibleMapIds.erase(itr); + } + else + ++itr; + } + + Unit* unit = object->ToUnit(); + if (unit) + { + for (AuraEffect const* aurEff : unit->GetAuraEffectsByType(SPELL_AURA_PHASE)) + { + uint32 phaseId = uint32(aurEff->GetMiscValueB()); + auto eraseResult = newSuppressions.RemovePhase(phaseId); + // if condition was met previously there is nothing to erase + if (eraseResult.Iterator != newSuppressions.Phases.end() || eraseResult.Erased) + phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), nullptr); + } + + for (AuraEffect const* aurEff : unit->GetAuraEffectsByType(SPELL_AURA_PHASE_GROUP)) + { + if (std::vector const* phasesInGroup = GetPhasesForGroup(uint32(aurEff->GetMiscValueB()))) + { + for (uint32 phaseId : *phasesInGroup) + { + auto eraseResult = newSuppressions.RemovePhase(phaseId); + // if condition was met previously there is nothing to erase + if (eraseResult.Iterator != newSuppressions.Phases.end() || eraseResult.Erased) + phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), nullptr); + } + } + } + } + + changed = changed || !newSuppressions.Phases.empty() || !newSuppressions.VisibleMapIds.empty(); + for (auto itr = newSuppressions.Phases.begin(); itr != newSuppressions.Phases.end(); ++itr) + suppressedPhaseShift.AddPhase(itr->Id, itr->Flags, itr->AreaConditions, itr->References); + + for (auto itr = newSuppressions.VisibleMapIds.begin(); itr != newSuppressions.VisibleMapIds.end(); ++itr) + suppressedPhaseShift.AddVisibleMapId(itr->first, itr->second.VisibleMapInfo, itr->second.References); + + if (unit) + { + if (changed) + unit->OnPhaseChange(); + + ForAllControlled(unit, [&](Unit* controlled) + { + InheritPhaseShift(controlled, unit); + }); + + if (changed) + unit->RemoveNotOwnSingleTargetAuras(true); + } + + UpdateVisibilityIfNeeded(object, true, changed); +} + +void PhasingHandler::SendToPlayer(Player const* player, PhaseShift const& phaseShift) +{ + ObjectGuid guid = player->GetGUID(); + + WorldPacket data(SMSG_SET_PHASE_SHIFT, 1 + 8 + 4 + 4 + 4 + 4 + 2 * phaseShift.Phases.size() + 4 + phaseShift.VisibleMapIds.size() * 2); + data.WriteBit(guid[2]); + data.WriteBit(guid[3]); + data.WriteBit(guid[1]); + data.WriteBit(guid[6]); + data.WriteBit(guid[4]); + data.WriteBit(guid[5]); + data.WriteBit(guid[0]); + data.WriteBit(guid[7]); + + data.WriteByteSeq(guid[7]); + data.WriteByteSeq(guid[4]); + + data << uint32(phaseShift.UiWorldMapAreaIdSwaps.size()) * 2; + for (auto itr = phaseShift.UiWorldMapAreaIdSwaps.begin(); itr != phaseShift.UiWorldMapAreaIdSwaps.end(); ++itr) + data << uint16(itr->first); // WorldMapArea.dbc id (controls map display) + + data.WriteByteSeq(guid[1]); + + data << uint32(phaseShift.Flags.AsUnderlyingType()); // flags + + data.WriteByteSeq(guid[2]); + data.WriteByteSeq(guid[6]); + + data << uint32(0); // Inactive terrain swaps + //for (uint8 i = 0; i < inactiveSwapsCount; ++i) + // data << uint16(0); + + data << uint32(phaseShift.Phases.size()) * 2; // Phase.dbc ids + for (auto itr = phaseShift.Phases.begin(); itr != phaseShift.Phases.end(); ++itr) + data << uint16(itr->Id); + + data.WriteByteSeq(guid[3]); + data.WriteByteSeq(guid[0]); + + data << uint32(phaseShift.VisibleMapIds.size()) * 2; // Active terrain swaps + for (auto itr = phaseShift.VisibleMapIds.begin(); itr != phaseShift.VisibleMapIds.end(); ++itr) + data << uint16(itr->first); + + data.WriteByteSeq(guid[5]); + + player->SendDirectMessage(&data); +} + +void PhasingHandler::SendToPlayer(Player const* player) +{ + SendToPlayer(player, player->GetPhaseShift()); +} + +void PhasingHandler::FillPartyMemberPhase(WorldPacket* data, PhaseShift const& phaseShift) +{ + *data << uint32(phaseShift.Flags.AsUnderlyingType()); + *data << uint32(phaseShift.Phases.size()); + for (auto itr = phaseShift.Phases.begin(); itr != phaseShift.Phases.end(); ++itr) + *data << uint16(itr->Id); +} + +PhaseShift const& PhasingHandler::GetEmptyPhaseShift() +{ + return Empty; +} + +void PhasingHandler::InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId) +{ + phaseShift.IsDbPhaseShift = true; + + EnumClassFlag flags = PhaseShiftFlags::None; + if (phaseUseFlags & PHASE_USE_FLAGS_ALWAYS_VISIBLE) + flags = flags | PhaseShiftFlags::AlwaysVisible | PhaseShiftFlags::Unphased; + if (phaseUseFlags & PHASE_USE_FLAGS_INVERSE) + flags |= PhaseShiftFlags::Inverse; + + if (phaseId) + phaseShift.AddPhase(phaseId, GetPhaseFlags(phaseId), nullptr); + else if (std::vector const* phasesInGroup = GetPhasesForGroup(phaseGroupId)) + for (uint32 phaseInGroup : *phasesInGroup) + phaseShift.AddPhase(phaseInGroup, GetPhaseFlags(phaseInGroup), nullptr); + + if (phaseShift.Phases.empty() || phaseShift.HasPhase(DEFAULT_PHASE)) + { + if (flags.HasFlag(PhaseShiftFlags::Inverse)) + flags |= PhaseShiftFlags::InverseUnphased; + else + flags |= PhaseShiftFlags::Unphased; + } + + phaseShift.Flags = flags; +} + +void PhasingHandler::InitDbVisibleMapId(PhaseShift& phaseShift, int32 visibleMapId) +{ + phaseShift.VisibleMapIds.clear(); + if (visibleMapId != -1) + phaseShift.AddVisibleMapId(visibleMapId, sObjectMgr->GetTerrainSwapInfo(visibleMapId)); +} + +bool PhasingHandler::InDbPhaseShift(WorldObject const* object, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId) +{ + PhaseShift phaseShift; + InitDbPhaseShift(phaseShift, phaseUseFlags, phaseId, phaseGroupId); + return object->GetPhaseShift().CanSee(phaseShift); +} + +uint32 PhasingHandler::GetTerrainMapId(PhaseShift const& phaseShift, Map const* map, float x, float y) +{ + if (phaseShift.VisibleMapIds.empty()) + return map->GetId(); + + if (phaseShift.VisibleMapIds.size() == 1) + return phaseShift.VisibleMapIds.begin()->first; + + GridCoord gridCoord = Trinity::ComputeGridCoord(x, y); + int32 gx = (MAX_NUMBER_OF_GRIDS - 1) - gridCoord.x_coord; + int32 gy = (MAX_NUMBER_OF_GRIDS - 1) - gridCoord.y_coord; + + int32 gxbegin = std::max(gx - 1, 0); + int32 gxend = std::min(gx + 1, MAX_NUMBER_OF_GRIDS); + int32 gybegin = std::max(gy - 1, 0); + int32 gyend = std::min(gy + 1, MAX_NUMBER_OF_GRIDS); + + for (auto itr = phaseShift.VisibleMapIds.rbegin(); itr != phaseShift.VisibleMapIds.rend(); ++itr) + for (int32 gxi = gxbegin; gxi < gxend; ++gxi) + for (int32 gyi = gybegin; gyi < gyend; ++gyi) + if (map->HasGrid(gxi, gyi)) + return itr->first; + + return map->GetId(); +} + +void PhasingHandler::SetAlwaysVisible(PhaseShift& phaseShift, bool apply) +{ + if (apply) + phaseShift.Flags |= PhaseShiftFlags::AlwaysVisible; + else + phaseShift.Flags &= ~EnumClassFlag(PhaseShiftFlags::AlwaysVisible); +} + +void PhasingHandler::SetInversed(PhaseShift& phaseShift, bool apply) +{ + if (apply) + phaseShift.Flags |= PhaseShiftFlags::Inverse; + else + phaseShift.Flags &= ~EnumClassFlag(PhaseShiftFlags::Inverse); + + phaseShift.UpdateUnphasedFlag(); +} + +void PhasingHandler::PrintToChat(ChatHandler* chat, PhaseShift const& phaseShift) +{ + chat->PSendSysMessage(LANG_PHASESHIFT_STATUS, phaseShift.Flags.AsUnderlyingType(), phaseShift.PersonalGuid.ToString().c_str()); + if (!phaseShift.Phases.empty()) + { + std::ostringstream phases; + std::string cosmetic = sObjectMgr->GetTrinityString(LANG_PHASE_FLAG_COSMETIC, chat->GetSessionDbLocaleIndex()); + std::string personal = sObjectMgr->GetTrinityString(LANG_PHASE_FLAG_PERSONAL, chat->GetSessionDbLocaleIndex()); + for (PhaseShift::PhaseRef const& phase : phaseShift.Phases) + { + phases << phase.Id; + if (phase.Flags.HasFlag(PhaseFlags::Cosmetic)) + phases << ' ' << '(' << cosmetic << ')'; + if (phase.Flags.HasFlag(PhaseFlags::Personal)) + phases << ' ' << '(' << personal << ')'; + phases << ", "; + } + + chat->PSendSysMessage(LANG_PHASESHIFT_PHASES, phases.str().c_str()); + } + + if (!phaseShift.VisibleMapIds.empty()) + { + std::ostringstream visibleMapIds; + for (PhaseShift::VisibleMapIdContainer::value_type const& visibleMapId : phaseShift.VisibleMapIds) + visibleMapIds << visibleMapId.first << ',' << ' '; + + chat->PSendSysMessage(LANG_PHASESHIFT_VISIBLE_MAP_IDS, visibleMapIds.str().c_str()); + } + + if (!phaseShift.UiWorldMapAreaIdSwaps.empty()) + { + std::ostringstream uiWorldMapAreaIdSwaps; + for (PhaseShift::UiWorldMapAreaIdSwapContainer::value_type const& uiWorldMapAreaIdSwap : phaseShift.UiWorldMapAreaIdSwaps) + uiWorldMapAreaIdSwaps << uiWorldMapAreaIdSwap.first << ',' << ' '; + + chat->PSendSysMessage(LANG_PHASESHIFT_UI_WORLD_MAP_AREA_SWAPS, uiWorldMapAreaIdSwaps.str().c_str()); + } +} + +std::string PhasingHandler::FormatPhases(PhaseShift const& phaseShift) +{ + std::ostringstream phases; + for (PhaseShift::PhaseRef const& phase : phaseShift.Phases) + phases << phase.Id << ','; + + return phases.str(); +} + +void PhasingHandler::UpdateVisibilityIfNeeded(WorldObject* object, bool updateVisibility, bool changed) +{ + if (changed && object->IsInWorld()) + { + if (Player* player = object->ToPlayer()) + SendToPlayer(player); + + if (updateVisibility) + { + if (Player* player = object->ToPlayer()) + player->GetMap()->SendUpdateTransportVisibility(player); + + object->UpdateObjectVisibility(); + } + } +} diff --git a/src/server/game/Phasing/PhasingHandler.h b/src/server/game/Phasing/PhasingHandler.h new file mode 100644 index 0000000000..ba88d2f895 --- /dev/null +++ b/src/server/game/Phasing/PhasingHandler.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008-2018 TrinityCore + * + * 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 . + */ + +#ifndef PhasingHandler_h__ +#define PhasingHandler_h__ + +#include "Define.h" +#include + +class ChatHandler; +class Map; +class PhaseShift; +class Player; +class WorldObject; + +class TC_GAME_API PhasingHandler +{ +public: + static void AddPhase(WorldObject* object, uint32 phaseId, bool updateVisibility); + static void RemovePhase(WorldObject* object, uint32 phaseId, bool updateVisibility); + static void AddPhaseGroup(WorldObject* object, uint32 phaseGroupId, bool updateVisibility); + static void RemovePhaseGroup(WorldObject* object, uint32 phaseGroupId, bool updateVisibility); + + static void AddVisibleMapId(WorldObject* object, uint32 visibleMapId); + static void RemoveVisibleMapId(WorldObject* object, uint32 visibleMapId); + + static void ResetPhaseShift(WorldObject* object); + static void InheritPhaseShift(WorldObject* target, WorldObject const* source); + + static void OnMapChange(WorldObject* object); + static void OnAreaChange(WorldObject* object); + static void OnConditionChange(WorldObject* object); + + static void SendToPlayer(Player const* player, PhaseShift const& phaseShift); + static void SendToPlayer(Player const* player); + static void FillPartyMemberPhase(WorldPacket* data, PhaseShift const& phaseShift); + + static PhaseShift const& GetEmptyPhaseShift(); + static void InitDbPhaseShift(PhaseShift& phaseShift, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId); + static void InitDbVisibleMapId(PhaseShift& phaseShift, int32 visibleMapId); + static bool InDbPhaseShift(WorldObject const* object, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId); + + static uint32 GetTerrainMapId(PhaseShift const& phaseShift, Map const* map, float x, float y); + + static void SetAlwaysVisible(PhaseShift& phaseShift, bool apply); + static void SetInversed(PhaseShift& phaseShift, bool apply); + + static void PrintToChat(ChatHandler* chat, PhaseShift const& phaseShift); + static std::string FormatPhases(PhaseShift const& phaseShift); + +private: + static void UpdateVisibilityIfNeeded(WorldObject* object, bool updateVisibility, bool changed); +}; + +#endif // PhasingHandler_h__ diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index d468b69136..c68f3b7fcd 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -298,7 +298,6 @@ class TC_GAME_API WorldSession void SendPetNameInvalid(uint32 error, std::string const& name, DeclinedName *declinedName); void SendPartyResult(PartyOperation operation, std::string const& member, PartyResult res, uint32 val = 0); void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2, 3); - void SendSetPhaseShift(std::set const& phaseIds, std::set const& terrainswaps, std::set const& worldMapAreaSwaps); void SendQueryTimeResponse(); void SendAuthResponse(uint8 code, bool queued, uint32 queuePos = 0); diff --git a/src/server/game/Skills/Archaeology/ArchaeologySites.cpp b/src/server/game/Skills/Archaeology/ArchaeologySites.cpp index 23be86a883..ec1edcf7ba 100644 --- a/src/server/game/Skills/Archaeology/ArchaeologySites.cpp +++ b/src/server/game/Skills/Archaeology/ArchaeologySites.cpp @@ -119,7 +119,7 @@ void Archaeology::UseSite() float x = _player->GetPositionX() + cos(o) * 2.0f; float y = _player->GetPositionY() + sin(o) * 2.0f; float z = _player->GetPositionZ(); - float ground = _player->GetMap()->GetWaterOrGroundLevel(_player->GetPhases(), x, y, z, &ground, _player->IsInWater()); + float ground = _player->GetMap()->GetWaterOrGroundLevel(_player->GetPhaseShift(), x, y, z, &ground, _player->IsInWater()); G3D::Quat rot = G3D::Matrix3::fromEulerAnglesZYX(angle, 0.f, 0.f); if (std::abs(z - ground) < 1.5f) @@ -140,7 +140,7 @@ void Archaeology::UseSite() float x = _player->GetPositionX() + cos(o) * 2.0f; float y = _player->GetPositionY() + sin(o) * 2.0f; float z = _player->GetPositionZ(); - float ground = _player->GetMap()->GetWaterOrGroundLevel(_player->GetPhases(), x, y, z, &ground, _player->IsInWater()); + float ground = _player->GetMap()->GetWaterOrGroundLevel(_player->GetPhaseShift(), x, y, z, &ground, _player->IsInWater()); // Spawn object _player->SummonGameObject(goId, Position(x, y, ground, o), G3D::Quat(), 60); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 6f060f37a2..49afd99169 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -22,6 +22,7 @@ #include "Log.h" #include "ObjectMgr.h" #include "SpellMgr.h" +#include "PhasingHandler.h" #include "Player.h" #include "Unit.h" #include "ObjectAccessor.h" @@ -1703,8 +1704,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app Unit* target = aurApp->GetTarget(); - std::set const& oldPhases = target->GetPhases(); - target->SetInPhase(GetMiscValueB(), false, apply); + PhasingHandler::AddPhase(target, uint32(GetMiscValueB()), true); // call functions which may have additional effects after chainging state of unit // phase auras normally not expected at BG but anyway better check @@ -1713,17 +1713,6 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app // drop flag at invisibiliy in bg target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); } - - if (Player* player = target->ToPlayer()) - { - if (player->IsInWorld()) - player->GetMap()->SendUpdateTransportVisibility(player, oldPhases); - player->SendUpdatePhasing(); - } - - // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases) - if (target->IsVisible()) - target->UpdateObjectVisibility(); } void AuraEffect::HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -1733,10 +1722,7 @@ void AuraEffect::HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, boo Unit* target = aurApp->GetTarget(); - std::set const& oldPhases = target->GetPhases(); - std::set const& phases = GetPhasesForGroup(GetMiscValueB()); - for (auto phase : phases) - target->SetInPhase(phase, false, apply); + PhasingHandler::AddPhaseGroup(target, uint32(GetMiscValueB()), true); // call functions which may have additional effects after chainging state of unit // phase auras normally not expected at BG but anyway better check @@ -1745,17 +1731,6 @@ void AuraEffect::HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, boo // drop flag at invisibiliy in bg target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); } - - if (Player* player = target->ToPlayer()) - { - if (player->IsInWorld()) - player->GetMap()->SendUpdateTransportVisibility(player, oldPhases); - player->SendUpdatePhasing(); - } - - // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases) - if (target->IsVisible()) - target->UpdateObjectVisibility(); } /**********************/ diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 6b45be7e77..0bf136f861 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1303,10 +1303,10 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici float angle = float(rand_norm()) * static_cast(M_PI * 35.0f / 180.0f) - static_cast(M_PI * 17.5f / 180.0f); m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dist, angle); - float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhases(), x, y, z, true, 50.0f); + float ground = m_caster->GetMap()->GetHeight(m_caster->GetPhaseShift(), x, y, z, true, 50.0f); float liquidLevel = VMAP_INVALID_HEIGHT_VALUE; LiquidData liquidData; - if (m_caster->GetMap()->GetLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &liquidData)) + if (m_caster->GetMap()->GetLiquidStatus(m_caster->GetPhaseShift(), x, y, z, MAP_ALL_LIQUIDS, &liquidData)) liquidLevel = liquidData.level; if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level @@ -5049,11 +5049,11 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint if (m_caster->GetTypeId() == TYPEID_PLAYER && VMAP::VMapFactory::createOrGetVMapManager()->isLineOfSightCalcEnabled()) { if (m_spellInfo->HasAttribute(SPELL_ATTR0_OUTDOORS_ONLY) && - !m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ())) + !m_caster->GetMap()->IsOutdoors(m_caster->GetPhaseShift(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ())) return SPELL_FAILED_ONLY_OUTDOORS; if (m_spellInfo->HasAttribute(SPELL_ATTR0_INDOORS_ONLY) && - m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ())) + m_caster->GetMap()->IsOutdoors(m_caster->GetPhaseShift(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ())) return SPELL_FAILED_ONLY_INDOORS; } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 84df7705cb..194b842764 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -25,6 +25,7 @@ #include "World.h" #include "ObjectMgr.h" #include "SpellMgr.h" +#include "PhasingHandler.h" #include "Player.h" #include "SkillExtraItems.h" #include "Unit.h" @@ -3184,7 +3185,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) return; } - pGameObj->CopyPhaseFrom(m_caster); + PhasingHandler::InheritPhaseShift(pGameObj, m_caster); int32 duration = m_spellInfo->GetDuration(); @@ -3203,6 +3204,8 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) if (GameObject* linkedTrap = pGameObj->GetLinkedTrap()) { + PhasingHandler::InheritPhaseShift(linkedTrap, m_caster); + linkedTrap->SetRespawnTime(duration > 0 ? duration / IN_MILLISECONDS : 0); linkedTrap->SetSpellId(m_spellInfo->Id); @@ -3792,7 +3795,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex) return; } - pGameObj->CopyPhaseFrom(m_caster); + PhasingHandler::InheritPhaseShift(pGameObj, m_caster); pGameObj->SetFaction(m_caster->GetFaction()); pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1); @@ -4153,7 +4156,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) return; } - go->CopyPhaseFrom(m_caster); + PhasingHandler::InheritPhaseShift(go, m_caster); //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()); int32 duration = m_spellInfo->GetDuration(); @@ -4870,7 +4873,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) return; } - pGameObj->CopyPhaseFrom(m_caster); + PhasingHandler::InheritPhaseShift(pGameObj, m_caster); int32 duration = m_spellInfo->GetDuration(); @@ -4930,6 +4933,8 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) if (GameObject* linkedTrap = pGameObj->GetLinkedTrap()) { + PhasingHandler::InheritPhaseShift(linkedTrap, m_caster); + linkedTrap->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0); //linkedTrap->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()); linkedTrap->SetSpellId(m_spellInfo->Id); @@ -5764,7 +5769,7 @@ void Spell::EffectUpdatePlayerPhase(SpellEffIndex /*effIndex*/) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - unitTarget->UpdateAreaPhase(); + PhasingHandler::OnConditionChange(unitTarget); } void Spell::EffectUpdateZoneAurasAndPhases(SpellEffIndex /*effIndex*/) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d8ca90f1f9..3b5db1f9c0 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1513,15 +1513,21 @@ void World::SetInitialWorldSettings() // Load M2 fly by cameras LoadM2Cameras(m_dataPath); - std::vector mapIds; + std::unordered_map> mapData; for (MapEntry const* mapEntry : sMapStore) - mapIds.push_back(mapEntry->MapID); + { + mapData.emplace(std::piecewise_construct, std::forward_as_tuple(mapEntry->MapID), std::forward_as_tuple()); + if (mapEntry->rootPhaseMap != -1) + mapData[mapEntry->rootPhaseMap].push_back(mapEntry->MapID); + } + + sMapMgr->InitializeParentMapData(mapData); if (VMAP::VMapManager2* vmmgr2 = dynamic_cast(VMAP::VMapFactory::createOrGetVMapManager())) - vmmgr2->InitializeThreadUnsafe(mapIds); + vmmgr2->InitializeThreadUnsafe(mapData); MMAP::MMapManager* mmmgr = MMAP::MMapFactory::createOrGetMMapManager(); - mmmgr->InitializeThreadUnsafe(mapIds); + mmmgr->InitializeThreadUnsafe(mapData); TC_LOG_INFO("server.loading", "Initializing PlayerDump tables..."); PlayerDump::InitializeTables(); @@ -1899,17 +1905,7 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions LoadWorldStates(); - TC_LOG_INFO("server.loading", "Loading Terrain Phase definitions..."); - sObjectMgr->LoadTerrainPhaseInfo(); - - TC_LOG_INFO("server.loading", "Loading Terrain Swap Default definitions..."); - sObjectMgr->LoadTerrainSwapDefaults(); - - TC_LOG_INFO("server.loading", "Loading Terrain World Map definitions..."); - sObjectMgr->LoadTerrainWorldMaps(); - - TC_LOG_INFO("server.loading", "Loading Phase Area definitions..."); - sObjectMgr->LoadAreaPhases(); + sObjectMgr->LoadPhases(); TC_LOG_INFO("server.loading", "Loading Conditions..."); sConditionMgr->LoadConditions(); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index c454957e1f..1419271dbc 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -24,6 +24,7 @@ EndScriptData */ #include "ScriptMgr.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "BattlefieldMgr.h" #include "BattlegroundMgr.h" #include "Chat.h" @@ -979,7 +980,7 @@ public: return false; } - v->CopyPhaseFrom(handler->GetSession()->GetPlayer()); + PhasingHandler::InheritPhaseShift(v, handler->GetSession()->GetPlayer()); map->AddToMap(v->ToCreature()); @@ -1008,22 +1009,20 @@ public: if (!t) return false; - std::set terrainswap; - std::set phaseId; - std::set worldMapSwap; + PhaseShift phaseShift; if (uint32 ut = (uint32)atoi(t)) - terrainswap.insert(ut); + phaseShift.AddVisibleMapId(ut, nullptr); if (p) if (uint32 up = (uint32)atoi(p)) - phaseId.insert(up); + phaseShift.AddPhase(up, PhaseFlags::None, nullptr); if (m) if (uint32 um = (uint32)atoi(m)) - worldMapSwap.insert(um); + phaseShift.AddUiWorldMapAreaIdSwap(um); - handler->GetSession()->SendSetPhaseShift(phaseId, terrainswap, worldMapSwap); + PhasingHandler::SendToPlayer(handler->GetSession()->GetPlayer(), phaseShift); return true; } @@ -1462,15 +1461,8 @@ public: std::stringstream phases; - for (uint32 phase : target->GetPhases()) - { - phases << phase << " "; - } + PhasingHandler::PrintToChat(handler, target->GetPhaseShift()); - if (!phases.str().empty()) - handler->PSendSysMessage("Target's current phases: %s", phases.str().c_str()); - else - handler->SendSysMessage("Target is not phased"); return true; } diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 8224b83a33..f5d05e927d 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -24,6 +24,7 @@ EndScriptData */ #include "ScriptMgr.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "MapManager.h" #include "TicketMgr.h" #include "Chat.h" @@ -245,7 +246,7 @@ public: player->SaveRecallPosition(); Map const* map = sMapMgr->CreateBaseMap(mapId); - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + float z = std::max(map->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y)); player->TeleportTo(mapId, x, y, z, player->GetOrientation()); return true; @@ -465,7 +466,7 @@ public: else player->SaveRecallPosition(); - float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + float z = std::max(map->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y)); player->TeleportTo(zoneEntry->mapid, x, y, z, player->GetOrientation()); return true; @@ -513,7 +514,7 @@ public: return false; } Map const* map = sMapMgr->CreateBaseMap(mapId); - z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y)); + z = std::max(map->GetStaticHeight(PhasingHandler::GetEmptyPhaseShift(), x, y, MAX_HEIGHT), map->GetWaterLevel(PhasingHandler::GetEmptyPhaseShift(), x, y)); } // stop flight if need diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 3ad0901731..620b626aa8 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -31,6 +31,7 @@ EndScriptData */ #include "Language.h" #include "Player.h" #include "Opcodes.h" +#include "PhasingHandler.h" class gobject_commandscript : public CommandScript { @@ -147,7 +148,7 @@ public: return false; } - object->CopyPhaseFrom(player); + PhasingHandler::InheritPhaseShift(object, player); if (spawntimeSecs) { diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index e65e21728c..3411472980 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -21,6 +21,7 @@ #include "LFG.h" #include "Player.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "GroupMgr.h" #include "ScriptMgr.h" @@ -331,7 +332,6 @@ public: { // Get ALL the variables! Player* playerTarget; - uint32 phase = 0; ObjectGuid guidTarget; std::string nameTarget; std::string zoneName; @@ -412,11 +412,12 @@ public: // Check if iterator is online. If is... Player* p = ObjectAccessor::FindPlayer((*itr).guid); + std::string phases; if (p) { // ... than, it prints information like "is online", where he is, etc... onlineState = "online"; - phase = (!p->IsGameMaster() ? p->GetPhaseMask() : -1); + phases = PhasingHandler::FormatPhases(p->GetPhaseShift()); LocaleConstant localeConstant = handler->GetSessionDbcLocale(); AreaTableEntry const* area = sAreaTableStore.LookupEntry(p->GetAreaId()); @@ -432,12 +433,11 @@ public: // ... else, everything is set to offline or neutral values. zoneName = ""; onlineState = "Offline"; - phase = 0; } // Now we can print those informations for every single member of each group! handler->PSendSysMessage(LANG_GROUP_PLAYER_NAME_GUID, slot.name.c_str(), onlineState, - zoneName.c_str(), phase, slot.guid.GetCounter(), flags.c_str(), + zoneName.c_str(), phases.c_str(), slot.guid.GetCounter(), flags.c_str(), lfg::GetRolesString(slot.roles).c_str()); } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index a884a55b11..244ebc316e 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -32,6 +32,7 @@ #include "WeatherMgr.h" #include "Player.h" #include "Pet.h" +#include "PhasingHandler.h" #include "LFG.h" #include "GroupMgr.h" #include "MMapFactory.h" @@ -238,8 +239,8 @@ public: Map2ZoneCoordinates(zoneX, zoneY, zoneId); Map const* map = object->GetMap(); - float groundZ = map->GetHeight(object->GetPhases(), object->GetPositionX(), object->GetPositionY(), MAX_HEIGHT); - float floorZ = map->GetHeight(object->GetPhases(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ()); + float groundZ = map->GetHeight(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), MAX_HEIGHT); + float floorZ = map->GetHeight(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ()); GridCoord gridCoord = Trinity::ComputeGridCoord(object->GetPositionX(), object->GetPositionY()); @@ -252,7 +253,7 @@ public: if (haveVMap) { - if (map->IsOutdoors(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ())) + if (map->IsOutdoors(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ())) handler->PSendSysMessage(LANG_GPS_POSITION_OUTDOORS); else handler->PSendSysMessage(LANG_GPS_POSITION_INDOORS); @@ -266,7 +267,6 @@ public: mapId, (mapEntry ? mapEntry->name : unknown), zoneId, (zoneEntry ? zoneEntry->area_name : unknown), areaId, (areaEntry ? areaEntry->area_name : unknown), - object->GetPhaseMask(), StringJoin(object->GetPhases(), ", ").c_str(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation()); if (Transport* transport = object->GetTransport()) handler->PSendSysMessage(LANG_TRANSPORT_POSITION, @@ -277,25 +277,12 @@ public: zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap, haveMMap); LiquidData liquidStatus; - ZLiquidStatus status = map->GetLiquidStatus(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus); + ZLiquidStatus status = map->GetLiquidStatus(object->GetPhaseShift(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), MAP_ALL_LIQUIDS, &liquidStatus); if (status) handler->PSendSysMessage(LANG_LIQUID_STATUS, liquidStatus.level, liquidStatus.depth_level, liquidStatus.entry, liquidStatus.type_flags, status); - if (!object->GetTerrainSwaps().empty()) - { - std::stringstream ss; - for (uint32 swap : object->GetTerrainSwaps()) - ss << swap << " "; - handler->PSendSysMessage("Target's active terrain swaps: %s", ss.str().c_str()); - } - if (!object->GetWorldMapAreaSwaps().empty()) - { - std::stringstream ss; - for (uint32 swap : object->GetWorldMapAreaSwaps()) - ss << swap << " "; - handler->PSendSysMessage("Target's active world map area swaps: %s", ss.str().c_str()); - } + PhasingHandler::PrintToChat(handler, object->GetPhaseShift()); return true; } @@ -453,8 +440,8 @@ public: target->GetContactPoint(_player, x, y, z); _player->TeleportTo(target->GetMapId(), x, y, z, _player->GetAngle(target), TELE_TO_GM_MODE); - - _player->CopyPhaseFrom(target, true); + PhasingHandler::InheritPhaseShift(_player, target); + _player->UpdateObjectVisibility(); } else { @@ -584,7 +571,8 @@ public: float x, y, z; _player->GetClosePoint(x, y, z, target->GetObjectSize()); target->TeleportTo(_player->GetMapId(), x, y, z, target->GetOrientation()); - target->SetPhaseMask(_player->GetPhaseMask(), true); + PhasingHandler::InheritPhaseShift(target, handler->GetSession()->GetPlayer()); + target->UpdateObjectVisibility(); } else { @@ -1608,7 +1596,6 @@ public: // Position data print uint32 mapId; uint32 areaId; - std::set phases; std::string areaName = handler->GetTrinityString(LANG_UNKNOWN); std::string zoneName = handler->GetTrinityString(LANG_UNKNOWN); @@ -1640,7 +1627,6 @@ public: areaId = target->GetAreaId(); alive = target->IsAlive() ? handler->GetTrinityString(LANG_YES) : handler->GetTrinityString(LANG_NO); gender = target->getGender(); - phases = target->GetPhases(); } // get additional information from DB else @@ -1827,9 +1813,9 @@ public: // Output XII. LANG_PINFO_CHR_ALIVE handler->PSendSysMessage(LANG_PINFO_CHR_ALIVE, alive.c_str()); - // Output XIII. LANG_PINFO_CHR_PHASES - if (target && !phases.empty()) - handler->PSendSysMessage(LANG_PINFO_CHR_PHASES, StringJoin(phases, ", ").c_str()); + // Output XIII. phases + if (target) + PhasingHandler::PrintToChat(handler, target->GetPhaseShift()); // Output XIV. LANG_PINFO_CHR_MONEY uint32 gold = money / GOLD; diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 1a3259bb23..1877041e13 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -30,6 +30,7 @@ #include "Player.h" #include "PointMovementGenerator.h" #include "PathGenerator.h" +#include "PhasingHandler.h" #include "MMapFactory.h" #include "Map.h" #include "TargetedMovementGenerator.h" @@ -130,12 +131,16 @@ public: int32 gx = 32 - player->GetPositionX() / SIZE_OF_GRIDS; int32 gy = 32 - player->GetPositionY() / SIZE_OF_GRIDS; + float x, y, z; + player->GetPosition(x, y, z); + handler->PSendSysMessage("%03u%02i%02i.mmtile", player->GetMapId(), gx, gy); handler->PSendSysMessage("gridloc [%i, %i]", gy, gx); // calculate navmesh tile location - dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); - dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(handler->GetSession()->GetPlayer()->GetMapId(), player->GetInstanceId()); + uint32 terrainMapId = PhasingHandler::GetTerrainMapId(player->GetPhaseShift(), player->GetMap(), x, y); + dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(terrainMapId); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(terrainMapId, player->GetInstanceId()); if (!navmesh || !navmeshquery) { handler->PSendSysMessage("NavMesh not loaded for current map."); @@ -143,8 +148,6 @@ public: } float const* min = navmesh->getParams()->orig; - float x, y, z; - player->GetPosition(x, y, z); float location[VERTEX_SIZE] = { y, z, x }; float extents[VERTEX_SIZE] = { 3.0f, 5.0f, 3.0f }; @@ -185,9 +188,10 @@ public: static bool HandleMmapLoadedTilesCommand(ChatHandler* handler, char const* /*args*/) { - uint32 mapid = handler->GetSession()->GetPlayer()->GetMapId(); - dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(mapid); - dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(mapid, handler->GetSession()->GetPlayer()->GetInstanceId()); + Player* player = handler->GetSession()->GetPlayer(); + uint32 terrainMapId = PhasingHandler::GetTerrainMapId(player->GetPhaseShift(), player->GetMap(), player->GetPositionX(), player->GetPositionY()); + dtNavMesh const* navmesh = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(terrainMapId); + dtNavMeshQuery const* navmeshquery = MMAP::MMapFactory::createOrGetMMapManager()->GetNavMeshQuery(terrainMapId, player->GetInstanceId()); if (!navmesh || !navmeshquery) { handler->PSendSysMessage("NavMesh not loaded for current map."); @@ -210,14 +214,15 @@ public: static bool HandleMmapStatsCommand(ChatHandler* handler, char const* /*args*/) { - uint32 mapId = handler->GetSession()->GetPlayer()->GetMapId(); + Player* player = handler->GetSession()->GetPlayer(); + uint32 terrainMapId = PhasingHandler::GetTerrainMapId(player->GetPhaseShift(), player->GetMap(), player->GetPositionX(), player->GetPositionY()); handler->PSendSysMessage("mmap stats:"); - handler->PSendSysMessage(" global mmap pathfinding is %sabled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis"); + handler->PSendSysMessage(" global mmap pathfinding is %sabled", DisableMgr::IsPathfindingEnabled(player->GetMapId()) ? "en" : "dis"); MMAP::MMapManager* manager = MMAP::MMapFactory::createOrGetMMapManager(); handler->PSendSysMessage(" %u maps loaded with %u tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount()); - dtNavMesh const* navmesh = manager->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId()); + dtNavMesh const* navmesh = manager->GetNavMesh(terrainMapId); if (!navmesh) { handler->PSendSysMessage("NavMesh not loaded for current map."); diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index d7a8f3e2ca..0f30a37d78 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -27,6 +27,7 @@ EndScriptData */ #include "ObjectMgr.h" #include "Opcodes.h" #include "Pet.h" +#include "PhasingHandler.h" #include "Player.h" #include "ReputationMgr.h" #include "ScriptMgr.h" @@ -828,9 +829,18 @@ public: if (!*args) return false; - uint32 phaseId = uint32(atoul(args)); + char* phaseText = strtok((char*)args, " "); + if (!phaseText) + return false; - if (!sPhaseStore.LookupEntry(phaseId)) + uint32 phaseId = uint32(strtoul(phaseText, nullptr, 10)); + uint32 visibleMapId = 0; + + char* visibleMapIdText = strtok(nullptr, " "); + if (visibleMapIdText) + visibleMapId = uint32(strtoul(visibleMapIdText, nullptr, 10)); + + if (phaseId && !sPhaseStore.LookupEntry(phaseId)) { handler->SendSysMessage(LANG_PHASE_NOTFOUND); handler->SetSentErrorMessage(true); @@ -838,13 +848,29 @@ public: } Unit* target = handler->getSelectedUnit(); - if (!target) - target = handler->GetSession()->GetPlayer(); + if (visibleMapId) + { + MapEntry const* visibleMap = sMapStore.LookupEntry(visibleMapId); + if (!visibleMap || visibleMap->rootPhaseMap != int32(target->GetMapId())) + { + handler->SendSysMessage(LANG_PHASE_NOTFOUND); + handler->SetSentErrorMessage(true); + return false; + } - target->SetInPhase(phaseId, true, !target->IsInPhase(phaseId)); + if (!target->GetPhaseShift().HasVisibleMapId(visibleMapId)) + PhasingHandler::AddVisibleMapId(target, visibleMapId); + else + PhasingHandler::RemoveVisibleMapId(target, visibleMapId); + } - if (target->GetTypeId() == TYPEID_PLAYER) - target->ToPlayer()->SendUpdatePhasing(); + if (phaseId) + { + if (!target->GetPhaseShift().HasPhase(phaseId)) + PhasingHandler::AddPhase(target, phaseId, true); + else + PhasingHandler::RemovePhase(target, phaseId, true); + } return true; } diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index f5f9aa151a..5f6500b1c9 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -32,6 +32,7 @@ EndScriptData */ #include "CreatureAI.h" #include "Player.h" #include "Pet.h" +#include "PhasingHandler.h" template struct EnumName @@ -287,8 +288,7 @@ public: return false; } - //creature->CopyPhaseFrom(chr); // creature is not directly added to world, only to db, so this is useless here - + PhasingHandler::InheritPhaseShift(creature, chr); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); ObjectGuid::LowType db_guid = creature->GetSpawnId(); @@ -718,18 +718,8 @@ public: if (CreatureData const* data = sObjectMgr->GetCreatureData(target->GetSpawnId())) { - handler->PSendSysMessage(LANG_NPCINFO_PHASES, data->phaseid, data->phaseGroup); - if (data->phaseGroup) - { - std::set _phases = target->GetPhases(); - - if (!_phases.empty()) - { - handler->PSendSysMessage(LANG_NPCINFO_PHASE_IDS); - for (uint32 phaseId : _phases) - handler->PSendSysMessage("%u", phaseId); - } - } + handler->PSendSysMessage(LANG_NPCINFO_PHASES, data->phaseId, data->phaseGroup); + PhasingHandler::PrintToChat(handler, target->GetPhaseShift()); } handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); @@ -1078,12 +1068,8 @@ public: return false; } - creature->ClearPhases(); - - for (uint32 id : GetPhasesForGroup(phaseGroupId)) - creature->SetInPhase(id, false, true); // don't send update here for multiple phases, only send it once after adding all phases - - creature->UpdateObjectVisibility(); + PhasingHandler::ResetPhaseShift(creature); + PhasingHandler::AddPhaseGroup(creature, phaseGroupId, true); creature->SetDBPhase(-int(phaseGroupId)); creature->SaveToDB(); @@ -1114,8 +1100,8 @@ public: return false; } - creature->ClearPhases(); - creature->SetInPhase(phaseID, true, true); + PhasingHandler::ResetPhaseShift(creature); + PhasingHandler::AddPhase(creature, phaseID, true); creature->SetDBPhase(phaseID); creature->SaveToDB(); diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 782af7278b..620f98a93a 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -1142,15 +1142,6 @@ public: return true; } - - static bool HandleReloadPhaseDefinitionsCommand(ChatHandler* handler, const char* /*args*/) - { - TC_LOG_INFO("misc", "Reloading terrain_phase_info table..."); - sObjectMgr->LoadTerrainPhaseInfo(); - handler->SendGlobalGMSysMessage("Terrain phase infos reloaded."); - return true; - } - static bool HandleReloadRBACCommand(ChatHandler* handler, const char* /*args*/) { TC_LOG_INFO("misc", "Reloading RBAC tables..."); diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 037f5f87f7..bc75249276 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -22,16 +22,31 @@ Comment: All server related commands Category: commandscripts EndScriptData */ +#include "ScriptMgr.h" #include "Chat.h" #include "Config.h" +#include "DatabaseEnv.h" +#include "DatabaseLoader.h" +#include "GameTime.h" +#include "GitRevision.h" #include "Language.h" +#include "Log.h" #include "ObjectAccessor.h" #include "Player.h" -#include "ScriptMgr.h" -#include "GitRevision.h" -#include "Util.h" -#include "GameTime.h" +#include "RBAC.h" +#include "Realm.h" #include "UpdateTime.h" +#include "Util.h" +#include "VMapFactory.h" +#include "World.h" +#include "WorldSession.h" + +#include + +#include +#include +#include +#include class server_commandscript : public CommandScript { @@ -77,6 +92,7 @@ public: static std::vector serverCommandTable = { { "corpses", rbac::RBAC_PERM_COMMAND_SERVER_CORPSES, true, &HandleServerCorpsesCommand, "" }, + { "debug", rbac::RBAC_PERM_COMMAND_SERVER_DEBUG, true, &HandleServerDebugCommand, "" }, { "exit", rbac::RBAC_PERM_COMMAND_SERVER_EXIT, true, &HandleServerExitCommand, "" }, { "idlerestart", rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, nullptr, "", serverIdleRestartCommandTable }, { "idleshutdown", rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, nullptr, "", serverIdleShutdownCommandTable }, @@ -102,6 +118,136 @@ public: return true; } + static bool HandleServerDebugCommand(ChatHandler* handler, char const* /*args*/) + { + uint16 worldPort = uint16(sWorld->getIntConfig(CONFIG_PORT_WORLD)); + std::string dbPortOutput; + + { + uint16 dbPort = 0; + if (QueryResult res = LoginDatabase.PQuery("SELECT port FROM realmlist WHERE id = %u", realm.Id.Realm)) + dbPort = (*res)[0].GetUInt16(); + + if (dbPort) + dbPortOutput = Trinity::StringFormat("Realmlist (Realm Id: %u) configured in port %" PRIu16, realm.Id.Realm, dbPort); + else + dbPortOutput = Trinity::StringFormat("Realm Id: %u not found in `realmlist` table. Please check your setup", realm.Id.Realm); + } + + handler->PSendSysMessage("%s", GitRevision::GetFullVersion()); + handler->PSendSysMessage("Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); + handler->PSendSysMessage("Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100); + handler->PSendSysMessage("Using MySQL version: %s", MYSQL_SERVER_VERSION); + handler->PSendSysMessage("Using CMake version: %s", GitRevision::GetCMakeVersion()); + + handler->PSendSysMessage("Compiled on: %s", GitRevision::GetHostOSVersion()); + + uint32 updateFlags = sConfigMgr->GetIntDefault("Updates.EnableDatabases", DatabaseLoader::DATABASE_NONE); + if (!updateFlags) + handler->SendSysMessage("Automatic database updates are disabled for all databases!"); + else + { + static char const* const databaseNames[3 /*TOTAL_DATABASES*/] = + { + "Auth", + "Characters", + "World" + }; + + std::string availableUpdateDatabases; + for (uint32 i = 0; i < 3 /* TOTAL_DATABASES*/; ++i) + { + if (!(updateFlags & (1 << i))) + continue; + + availableUpdateDatabases += databaseNames[i]; + if (i != 3 /*TOTAL_DATABASES*/ - 1) + availableUpdateDatabases += ", "; + } + + handler->PSendSysMessage("Automatic database updates are enabled for the following databases: %s", availableUpdateDatabases.c_str()); + } + + handler->PSendSysMessage("Worldserver listening connections on port %" PRIu16, worldPort); + handler->PSendSysMessage("%s", dbPortOutput.c_str()); + + bool vmapIndoorCheck = sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK); + bool vmapLOSCheck = VMAP::VMapFactory::createOrGetVMapManager()->isLineOfSightCalcEnabled(); + bool vmapHeightCheck = VMAP::VMapFactory::createOrGetVMapManager()->isHeightCalcEnabled(); + + bool mmapEnabled = sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS); + + std::string dataDir = sWorld->GetDataPath(); + std::vector subDirs; + subDirs.emplace_back("maps"); + if (vmapIndoorCheck || vmapLOSCheck || vmapHeightCheck) + { + handler->PSendSysMessage("VMAPs status: Enabled. LineOfSight: %i, getHeight: %i, indoorCheck: %i", vmapLOSCheck, vmapHeightCheck, vmapIndoorCheck); + subDirs.emplace_back("vmaps"); + } + else + handler->SendSysMessage("VMAPs status: Disabled"); + + if (mmapEnabled) + { + handler->SendSysMessage("MMAPs status: Enabled"); + subDirs.emplace_back("mmaps"); + } + else + handler->SendSysMessage("MMAPs status: Disabled"); + + for (std::string const& subDir : subDirs) + { + boost::filesystem::path mapPath(dataDir); + mapPath.append(subDir); + + if (!boost::filesystem::exists(mapPath)) + { + handler->PSendSysMessage("%s directory doesn't exist!. Using path: %s", subDir.c_str(), mapPath.generic_string().c_str()); + continue; + } + + auto end = boost::filesystem::directory_iterator(); + std::size_t folderSize = std::accumulate(boost::filesystem::directory_iterator(mapPath), end, std::size_t(0), [](std::size_t val, boost::filesystem::path const& mapFile) + { + if (boost::filesystem::is_regular_file(mapFile)) + val += boost::filesystem::file_size(mapFile); + return val; + }); + + handler->PSendSysMessage("%s directory located in %s. Total size: " SZFMTD " bytes", subDir.c_str(), mapPath.generic_string().c_str(), folderSize); + } + + LocaleConstant defaultLocale = sWorld->GetDefaultDbcLocale(); + uint32 availableLocalesMask = (1 << defaultLocale); + + for (uint8 i = 0; i < TOTAL_LOCALES; ++i) + { + LocaleConstant locale = static_cast(i); + if (locale == defaultLocale) + continue; + + if (sWorld->GetAvailableDbcLocale(locale) != defaultLocale) + availableLocalesMask |= (1 << locale); + } + + std::string availableLocales; + for (uint8 i = 0; i < TOTAL_LOCALES; ++i) + { + if (!(availableLocalesMask & (1 << i))) + continue; + + availableLocales += localeNames[i]; + if (i != TOTAL_LOCALES - 1) + availableLocales += " "; + } + + handler->PSendSysMessage("Using %s DBC Locale as default. All available DBC locales: %s", localeNames[defaultLocale], availableLocales.c_str()); + + handler->PSendSysMessage("Using World DB: %s", sWorld->GetDBVersion()); + return true; + } + static bool HandleServerInfoCommand(ChatHandler* handler, char const* /*args*/) { uint32 playersNum = sWorld->GetPlayerCount(); @@ -113,7 +259,7 @@ public: std::string uptime = secsToTimeString(GameTime::GetUptime()); uint32 updateTime = sWorldUpdateTime.GetLastUpdateTime(); - handler->SendSysMessage(GitRevision::GetFullVersion()); + handler->PSendSysMessage("%s", GitRevision::GetFullVersion()); handler->PSendSysMessage(LANG_CONNECTED_PLAYERS, playersNum, maxPlayersNum); handler->PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); handler->PSendSysMessage(LANG_UPTIME, uptime.c_str()); diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index be818f6ff4..4eb2c7da7c 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -27,6 +27,7 @@ EndScriptData */ #include "Language.h" #include "MapManager.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "Player.h" #include "ScriptMgr.h" @@ -202,7 +203,7 @@ public: SQLTransaction dummy; Player::SavePositionInDB(WorldLocation(tele->mapId, tele->position_x, tele->position_y, tele->position_z, tele->orientation), - sMapMgr->GetZoneId(tele->mapId, tele->position_x, tele->position_y, tele->position_z), target_guid, dummy); + sMapMgr->GetZoneId(PhasingHandler::GetEmptyPhaseShift(), tele->mapId, tele->position_x, tele->position_y, tele->position_z), target_guid, dummy); } return true; diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index 4327ac4c52..5b1decd298 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -25,6 +25,7 @@ EndScriptData */ #include "Chat.h" #include "Language.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "Player.h" #include "ScriptMgr.h" #include "WaypointManager.h" @@ -667,7 +668,7 @@ public: return false; } - wpCreature->CopyPhaseFrom(chr); + PhasingHandler::InheritPhaseShift(wpCreature, chr); wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); @@ -881,7 +882,7 @@ public: return false; } - wpCreature->CopyPhaseFrom(chr); + PhasingHandler::InheritPhaseShift(wpCreature, chr); // Set "wpguid" column to the visual waypoint stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID); @@ -945,7 +946,7 @@ public: return false; } - creature->CopyPhaseFrom(chr); + PhasingHandler::InheritPhaseShift(creature, chr); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map)) @@ -996,7 +997,7 @@ public: return false; } - creature->CopyPhaseFrom(chr); + PhasingHandler::InheritPhaseShift(creature, chr); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMask()); if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map)) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp index 4a0a96092b..023c71f7d3 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -1172,7 +1172,7 @@ public: float x, y, z; me->GetPosition(x, y, z); - z = me->GetMap()->GetHeight(me->GetPhases(), x, y, z); + z = me->GetMap()->GetHeight(me->GetPhaseShift(), x, y, z); me->GetMotionMaster()->MovePoint(0, x, y, z); me->SetPosition(x, y, z, 0); } @@ -1290,7 +1290,7 @@ public: { float x, y, z; me->GetPosition(x, y, z); - z = me->GetMap()->GetHeight(me->GetPhases(), x, y, z); + z = me->GetMap()->GetHeight(me->GetPhaseShift(), x, y, z); me->GetMotionMaster()->MovePoint(0, x, y, z); me->SetPosition(x, y, z, 0); hyjal_trashAI::JustDied(killer); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp index 09c79fd51d..789dd0189a 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp @@ -270,7 +270,7 @@ public: Position pos = me->GetRandomNearPosition(10.0f); //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + pos.m_positionZ = std::max(me->GetMap()->GetHeight(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY)); if (Creature* summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) return summon; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp index e54b10a592..36a53162a2 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp @@ -305,7 +305,7 @@ public: Position pos = me->GetRandomNearPosition(10.0f); //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + pos.m_positionZ = std::max(me->GetMap()->GetHeight(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(me->GetPhaseShift(), pos.m_positionX, pos.m_positionY)); if (Unit* Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) if (Unit* temp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MEDIVH))) diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp index ab3c6fdd4f..d8eb762965 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp @@ -543,7 +543,7 @@ public: float x = caster->GetPositionX() + dist * std::cos(angle); float y = caster->GetPositionY() + dist * std::sin(angle); - float z = caster->GetMap()->GetHeight(caster->GetPhases(), x, y, caster->GetPositionZ()); + float z = caster->GetMap()->GetHeight(caster->GetPhaseShift(), x, y, caster->GetPositionZ()); const_cast(GetExplTargetDest())->Relocate(x, y, z); GetHitDest()->Relocate(x, y, z); diff --git a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp index 7e80546324..348a7490c9 100644 --- a/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp +++ b/src/server/scripts/Kalimdor/LostCityOfTheTolvir/boss_high_prophet_barim.cpp @@ -18,6 +18,7 @@ #include "ScriptMgr.h" #include "lost_city_of_the_tolvir.h" #include "ObjectMgr.h" +#include "PhasingHandler.h" #include "Player.h" #include "ScriptedCreature.h" #include "SpellAuraEffects.h" @@ -290,8 +291,7 @@ public: if (Creature* barim = _instance->GetCreature(DATA_HIGH_PROPHET_BARIM)) barim->AI()->JustSummoned(me); - for (uint32 id : GetPhasesForGroup(PHASE_GROUP_ENCOUNTER_1)) - me->SetInPhase(id, false, true); + PhasingHandler::AddPhaseGroup(me, PHASE_GROUP_ENCOUNTER_1, true); DoCastSelf(SPELL_REPENTANCE_SCRIPT_1, true); _events.ScheduleEvent(EVENT_COPY_WEAPON, Seconds(2)); @@ -440,7 +440,7 @@ public: me->SetReactState(REACT_PASSIVE); DoZoneInCombat(); DoCastSelf(SPELL_BIRTH, true); - me->SetInPhase(PHASE_ID_REPENTANCE, true, false); + PhasingHandler::AddPhase(me, PHASE_ID_REPENTANCE, true); } void JustEngagedWith(Unit* /*who*/) override @@ -456,8 +456,7 @@ public: if (Creature* barim = _instance->GetCreature(DATA_HIGH_PROPHET_BARIM)) barim->AI()->JustSummoned(summon); - for (uint32 id : GetPhasesForGroup(PHASE_GROUP_ENCOUNTER_1)) - summon->SetInPhase(id, false, true); + PhasingHandler::AddPhaseGroup(summon, PHASE_GROUP_ENCOUNTER_1, true); } void JustDied(Unit* /*killer*/) override diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp index 64bdad2854..18562165e2 100644 --- a/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp +++ b/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp @@ -285,7 +285,7 @@ class boss_high_priestess_azil : public CreatureScript me->RemoveAurasDueToSpell(SPELL_EARTH_FURY_CASTING_VISUAL); me->RemoveAurasDueToSpell(SPELL_EARTH_FURY_ENERGY_SHIELD); Position pos = me->GetPosition(); - pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhases(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); + pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); me->GetMotionMaster()->MovePoint(POINT_GROUND, pos); break; } diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp index cd34681aa3..d1dbe8a65a 100644 --- a/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp +++ b/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp @@ -266,7 +266,7 @@ class boss_slabhide : public CreatureScript case EVENT_LAND: { Position pos = me->GetPosition(); - pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhases(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); + pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); me->GetMotionMaster()->MoveLand(POINT_SLABHIDE_LAND, pos); break; } @@ -479,7 +479,7 @@ public: { Unit* caster = GetCaster(); Position pos = caster->GetPosition(); - pos.m_positionZ = caster->GetMap()->GetHeight(caster->GetPhases(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), true, 100.0f); + pos.m_positionZ = caster->GetMap()->GetHeight(caster->GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), true, 100.0f); dest.Relocate(pos); } diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp index 4a651769fd..0a3c2086d6 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp @@ -88,7 +88,7 @@ class boss_amanitar : public CreatureScript for (uint8 i = 0; i < 30; ++i) { Position pos = me->GetRandomNearPosition(30.0f); - pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhases(), pos.GetPositionX(), pos.GetPositionY(), MAX_HEIGHT) + 2.0f; + pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), MAX_HEIGHT) + 2.0f; if (Creature* trigger = me->SummonCreature(NPC_TRIGGER, pos)) { diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp index b1423e8aa9..af5dc4f8f4 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp @@ -22,6 +22,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ahnkahet.h" +#include "PhasingHandler.h" #include "Player.h" #include "SpellInfo.h" @@ -142,7 +143,7 @@ public: // clone player->CastSpell(summon, SPELL_CLONE_PLAYER, true); // phase the summon - summon->SetInPhase(spellInfo->Effects[EFFECT_0].MiscValueB, true, true); + PhasingHandler::AddPhase(summon, spellInfo->Effects[EFFECT_0].MiscValueB, true); } } ++insanityHandled; @@ -168,9 +169,9 @@ public: instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); // Visible for all players in insanity - me->SetInPhase(169, true, true); for (uint32 i = 173; i <= 177; ++i) - me->SetInPhase(i, true, true); + PhasingHandler::AddPhase(me, i, false); + PhasingHandler::AddPhase(me, 169, true); ResetPlayersPhase(); @@ -208,7 +209,7 @@ public: return; else { - nextPhase = *visage->GetPhases().begin(); + nextPhase = visage->GetPhaseShift().GetPhases().begin()->Id; break; } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index fe2bdd35bf..bea95c5fce 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -627,7 +627,7 @@ class npc_frost_sphere : public CreatureScript if (me->GetHealth() <= damage) { damage = 0; - float floorZ = me->GetMap()->GetHeight(me->GetPhases(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + float floorZ = me->GetMap()->GetHeight(me->GetPhaseShift(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); if (fabs(me->GetPositionZ() - floorZ) < 0.1f) { // we are close to the ground diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index ee9092c97e..30fc14ed5a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -804,7 +804,7 @@ class boss_prince_valanar_icc : public CreatureScript { float x, y, z; summon->GetPosition(x, y, z); - float ground_Z = summon->GetMap()->GetHeight(summon->GetPhases(), x, y, z, true, 500.0f); + float ground_Z = summon->GetMap()->GetHeight(summon->GetPhaseShift(), x, y, z, true, 500.0f); summon->GetMotionMaster()->MovePoint(POINT_KINETIC_BOMB_IMPACT, x, y, ground_Z); summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); break; @@ -1046,7 +1046,7 @@ class npc_kinetic_bomb : public CreatureScript me->SetReactState(REACT_PASSIVE); me->GetPosition(_x, _y, _groundZ); me->DespawnOrUnsummon(60000); - _groundZ = me->GetMap()->GetHeight(me->GetPhases(), _x, _y, _groundZ, true, 500.0f); + _groundZ = me->GetMap()->GetHeight(me->GetPhaseShift(), _x, _y, _groundZ, true, 500.0f); } void DoAction(int32 action) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index 717e2e2ace..04f016e2fb 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -17,6 +17,7 @@ #include "ObjectMgr.h" #include "ScriptMgr.h" +#include "PhasingHandler.h" #include "ScriptedCreature.h" #include "SpellAuraEffects.h" #include "Cell.h" @@ -636,7 +637,7 @@ class npc_the_lich_king_controller : public CreatureScript void JustSummoned(Creature* summon) override { // must not be in dream phase - summon->SetInPhase(173, true, false); + PhasingHandler::RemovePhase(summon, 173, true); if (summon->GetEntry() != NPC_SUPPRESSER) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) summon->AI()->AttackStart(target); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp index 74da060751..586eb7b275 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -294,10 +294,7 @@ class boss_sapphiron : public CreatureScript events.ScheduleEvent(EVENT_TAIL, randtime(Seconds(7), Seconds(10)), 0, PHASE_GROUND); return; case EVENT_DRAIN: - if (events.IsInPhase(PHASE_FLIGHT)) - _delayedDrain = true; - else - CastDrain(); + CastDrain(); return; case EVENT_BLIZZARD: DoCastAOE(SPELL_SUMMON_BLIZZARD); @@ -399,6 +396,9 @@ class boss_sapphiron : public CreatureScript me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->SetReactState(REACT_AGGRESSIVE); return; + case EVENT_DRAIN: + _delayedDrain = true; + break; } } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 8dd67e1ff5..1b6a8c26b3 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -778,7 +778,7 @@ class boss_flame_leviathan_safety_container : public CreatureScript { float x, y, z; me->GetPosition(x, y, z); - z = me->GetMap()->GetHeight(me->GetPhases(), x, y, z); + z = me->GetMap()->GetHeight(me->GetPhaseShift(), x, y, z); me->GetMotionMaster()->MovePoint(0, x, y, z); me->SetPosition(x, y, z, 0); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp index a063663f74..8f7f6492c4 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -872,7 +872,7 @@ class boss_sara : public CreatureScript float angle = frand(0.0f, 2.0f * float(M_PI)); pos.m_positionX = YoggSaronSpawnPos.GetPositionX() + radius * cosf(angle); pos.m_positionY = YoggSaronSpawnPos.GetPositionY() + radius * sinf(angle); - pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhases(), pos.GetPositionX(), pos.GetPositionY(), YoggSaronSpawnPos.GetPositionZ() + 5.0f); + pos.m_positionZ = me->GetMap()->GetHeight(me->GetPhaseShift(), pos.GetPositionX(), pos.GetPositionY(), YoggSaronSpawnPos.GetPositionZ() + 5.0f); me->SummonCreature(NPC_DEATH_RAY, pos, TEMPSUMMON_TIMED_DESPAWN, 20000); } break; diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index f933cc5de8..5a4a0bd9d0 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -38,6 +38,7 @@ EndContentData */ #include "ScriptedGossip.h" #include "ScriptedEscortAI.h" #include "ScriptedFollowerAI.h" +#include "PhasingHandler.h" #include "Player.h" #include "SpellInfo.h" #include "WorldSession.h" @@ -1689,7 +1690,7 @@ public: me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); break; case 20: - me->SetInPhase(170, true, false); + PhasingHandler::RemovePhase(me, 170, true); Talk(SAY_5); me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); player->GroupEventHappens(QUEST_ESCAPING_THE_MIST, me); diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index 7a1150af29..a871f044bf 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -529,7 +529,7 @@ public: bird->KillSelf(); crunchy->GetMotionMaster()->MovePoint(0, bird->GetPositionX(), bird->GetPositionY(), - bird->GetMap()->GetWaterOrGroundLevel(bird->GetPhases(), bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ())); + bird->GetMap()->GetWaterOrGroundLevel(bird->GetPhaseShift(), bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ())); /// @todo Make crunchy perform emote eat when he reaches the bird break; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp index 3a736f2f02..6ea3fabb84 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp @@ -18,6 +18,7 @@ #include "ScriptMgr.h" #include "OutdoorPvPSI.h" #include "WorldPacket.h" +#include "PhasingHandler.h" #include "Player.h" #include "GameObject.h" #include "MapManager.h" @@ -182,8 +183,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId) return true; } - go->CopyPhaseFrom(player); - + PhasingHandler::InheritPhaseShift(go, player); go->SetRespawnTime(0); if (!map->AddToMap(go)) @@ -213,8 +213,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId) return true; } - go->CopyPhaseFrom(player); - + PhasingHandler::InheritPhaseShift(go, player); go->SetRespawnTime(0); if (!map->AddToMap(go)) diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index f3184bf780..73029c4d58 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -75,7 +75,7 @@ public: void Reset() override { - ground = me->GetMap()->GetHeight(me->GetPhases(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZMinusOffset()); + ground = me->GetMap()->GetHeight(me->GetPhaseShift(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZMinusOffset()); SummonInfernal(); events.ScheduleEvent(EVENT_CAST_SUMMON_INFERNAL, urand(1000, 3000)); } diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 090d1ab860..0f9bb95083 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -1000,36 +1000,57 @@ class spell_q12805_lifeblood_dummy : public SpellScriptLoader */ enum BattleStandard { - NPC_KING_OF_THE_MOUNTAINT_KC = 31766, + NPC_KING_OF_THE_MOUNTAINT_KC = 31766, + SPELL_PLANT_HORDE_BATTLE_STANDARD = 59643, + SPELL_HORDE_BATTLE_STANDARD_STATE = 59642, + SPELL_ALLIANCE_BATTLE_STANDARD_STATE = 4339, + SPELL_JUMP_ROCKET_BLAST = 4340 }; -class spell_q13280_13283_plant_battle_standard: public SpellScriptLoader +class spell_q13280_13283_plant_battle_standard : public SpellScript { - public: - spell_q13280_13283_plant_battle_standard() : SpellScriptLoader("spell_q13280_13283_plant_battle_standard") { } + PrepareSpellScript(spell_q13280_13283_plant_battle_standard); - class spell_q13280_13283_plant_battle_standard_SpellScript : public SpellScript - { - PrepareSpellScript(spell_q13280_13283_plant_battle_standard_SpellScript); + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + Unit* target = GetHitUnit(); + uint32 triggeredSpellID = SPELL_ALLIANCE_BATTLE_STANDARD_STATE; - void HandleDummy(SpellEffIndex /*effIndex*/) - { - Unit* caster = GetCaster(); - if (caster->IsVehicle()) - if (Unit* player = caster->GetVehicleKit()->GetPassenger(0)) - player->ToPlayer()->KilledMonsterCredit(NPC_KING_OF_THE_MOUNTAINT_KC); - } + caster->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + if (caster->IsVehicle()) + if (Unit* player = caster->GetVehicleKit()->GetPassenger(0)) + player->ToPlayer()->KilledMonsterCredit(NPC_KING_OF_THE_MOUNTAINT_KC); - void Register() override - { - OnEffectHit += SpellEffectFn(spell_q13280_13283_plant_battle_standard_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; + if (GetSpellInfo()->Id == SPELL_PLANT_HORDE_BATTLE_STANDARD) + triggeredSpellID = SPELL_HORDE_BATTLE_STANDARD_STATE; - SpellScript* GetSpellScript() const override - { - return new spell_q13280_13283_plant_battle_standard_SpellScript(); - } + target->RemoveAllAuras(); + target->CastSpell(target, triggeredSpellID, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_q13280_13283_plant_battle_standard::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_q13280_13283_jump_jets : public SpellScript +{ + PrepareSpellScript(spell_q13280_13283_jump_jets); + + void HandleCast() + { + Unit* caster = GetCaster(); + if (caster->IsVehicle()) + if (Unit* rocketBunny = caster->GetVehicleKit()->GetPassenger(1)) + rocketBunny->CastSpell(rocketBunny, SPELL_JUMP_ROCKET_BLAST, true); + } + + void Register() override + { + OnCast += SpellCastFn(spell_q13280_13283_jump_jets::HandleCast); + } }; enum ChumTheWaterSummons @@ -2897,7 +2918,8 @@ void AddSC_quest_spell_scripts() new spell_q12659_ahunaes_knife(); new spell_q9874_liquid_fire(); new spell_q12805_lifeblood_dummy(); - new spell_q13280_13283_plant_battle_standard(); + RegisterSpellScript(spell_q13280_13283_plant_battle_standard); + RegisterSpellScript(spell_q13280_13283_jump_jets); new spell_q14112_14145_chum_the_water(); new spell_q9452_cast_net(); new spell_q12279_cast_net(); diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 5e6b12d71a..5cc935d694 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -23,6 +23,8 @@ #include "DetourNavMesh.h" #include "IntermediateValues.h" #include "StringFormat.h" +#include "VMapFactory.h" +#include "VMapManager2.h" #include @@ -214,7 +216,7 @@ namespace MMAP _workerThreads.push_back(std::thread(&MapBuilder::WorkerThread, this)); } - m_tiles.sort([](MapTiles a, MapTiles b) + m_tiles.sort([](MapTiles const& a, MapTiles const& b) { return a.m_tiles->size() > b.m_tiles->size(); }); @@ -471,7 +473,12 @@ namespace MMAP /**************************************************************************/ void MapBuilder::buildNavMesh(uint32 mapID, dtNavMesh* &navMesh) { - std::set* tiles = getTileList(mapID); + // if map has a parent we use that to generate dtNavMeshParams - worldserver will load all missing tiles from that map + int32 navMeshParamsMapId = static_cast(VMapFactory::createOrGetVMapManager())->getParentMapId(mapID); + if (navMeshParamsMapId == -1) + navMeshParamsMapId = mapID; + + std::set* tiles = getTileList(navMeshParamsMapId); // old code for non-statically assigned bitmask sizes: ///*** calculate number of bits needed to store tiles & polys ***/ @@ -532,6 +539,7 @@ namespace MMAP if (!file) { dtFreeNavMesh(navMesh); + navMesh = nullptr; char message[1024]; sprintf(message, "[Map %03i] Failed to open %s for writing!\n", mapID, fileName); perror(message); @@ -835,6 +843,7 @@ namespace MMAP // DT_TILE_FREE_DATA tells detour to unallocate memory when the tile // is removed via removeTile() dtStatus dtResult = navMesh->addTile(navData, navDataSize, DT_TILE_FREE_DATA, 0, &tileRef); + if (!tileRef || dtResult != DT_SUCCESS) { printf("%s Failed adding tile to navmesh! \n", tileString.c_str()); diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 4f553302c0..b14e290685 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -101,7 +101,7 @@ namespace MMAP return LISTFILE_DIRECTORY_NOT_FOUND; do { - if ((findFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) + if (strcmp(findFileInfo.cFileName, ".") != 0 && strcmp(findFileInfo.cFileName, "..") != 0) fileList.push_back(std::string(findFileInfo.cFileName)); } while (FindNextFile(hFind, &findFileInfo)); diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index 0013b5e13f..e6e48d9894 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -16,11 +16,15 @@ * with this program. If not, see . */ -#include - -#include "PathCommon.h" #include "MapBuilder.h" +#include "PathCommon.h" #include "Timer.h" +#include "VMapFactory.h" +#include "VMapManager2.h" +#include "DBCFileLoader.h" +#include +#include +#include using namespace MMAP; @@ -34,6 +38,13 @@ bool checkDirectories(bool debugOutput) return false; } + dirFiles.clear(); + if (getDirContents(dirFiles, "dbc") == LISTFILE_DIRECTORY_NOT_FOUND || dirFiles.empty()) + { + printf("'dbc' directory is empty or does not exist\n"); + return false; + } + dirFiles.clear(); if (getDirContents(dirFiles, "vmaps", "*.vmtree") == LISTFILE_DIRECTORY_NOT_FOUND || dirFiles.empty()) { @@ -43,15 +54,24 @@ bool checkDirectories(bool debugOutput) dirFiles.clear(); if (getDirContents(dirFiles, "mmaps") == LISTFILE_DIRECTORY_NOT_FOUND) - return boost::filesystem::create_directory("mmaps"); + { + if (!boost::filesystem::create_directory("mmaps")) + { + printf("'mmaps' directory does not exist and failed to create it\n"); + return false; + } + } dirFiles.clear(); if (debugOutput) { if (getDirContents(dirFiles, "meshes") == LISTFILE_DIRECTORY_NOT_FOUND) { - printf("'meshes' directory does not exist (no place to put debugOutput files)\n"); - return false; + if (!boost::filesystem::create_directory("meshes")) + { + printf("'meshes' directory does not exist and failed to create it (no place to put debugOutput files)\n"); + return false; + } } } @@ -274,9 +294,32 @@ int main(int argc, char** argv) return 0; } + if (!checkDirectories(debugOutput)) return silent ? -3 : finish("Press ENTER to close...", -3); + std::string mapPath = (boost::filesystem::path("dbc") / "Map.dbc").string(); + + std::unordered_map> mapData; + { + DBCFileLoader* loader = new DBCFileLoader(); + char const* mapFmt = "nxxxxxxxxxxxxxxxxxxi"; + if (!loader->Load(mapPath.c_str(), mapFmt)) + { + delete loader; + return silent ? -4 : finish("Failed to load Map.dbc", -4); + } + for (uint32 x = 0; x < loader->GetNumRows(); ++x) + { + mapData.emplace(std::piecewise_construct, std::forward_as_tuple(loader->getRecord(x).getUInt(0)), std::forward_as_tuple()); + int16 parentMapId = int16(loader->getRecord(x).getUInt(19)); + if (parentMapId != -1) + mapData[parentMapId].push_back(loader->getRecord(x).getUInt(0)); + } + + static_cast(VMAP::VMapFactory::createOrGetVMapManager())->InitializeThreadUnsafe(mapData); + } + MapBuilder builder(maxAngle, skipLiquid, skipContinents, skipJunkMaps, skipBattlegrounds, debugOutput, bigBaseUnit, mapnum, offMeshInputPath); @@ -290,6 +333,8 @@ int main(int argc, char** argv) else builder.buildAllMaps(threads); + VMAP::VMapFactory::clear(); + if (!silent) printf("Finished. MMAPS were built in %u ms!\n", GetMSTimeDiffToNow(start)); return 0; diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index a703382c8a..b2e47022fe 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -17,12 +17,11 @@ */ #include "TerrainBuilder.h" - #include "MapBuilder.h" - -#include "VMapManager2.h" #include "MapTree.h" #include "ModelInstance.h" +#include "VMapFactory.h" +#include "VMapManager2.h" // ****************************************** // Map file format defines @@ -137,6 +136,16 @@ namespace MMAP sprintf(mapFileName, "maps/%03u%02u%02u.map", mapID, tileY, tileX); FILE* mapFile = fopen(mapFileName, "rb"); + if (!mapFile) + { + int32 parentMapId = static_cast(VMapFactory::createOrGetVMapManager())->getParentMapId(mapID); + if (parentMapId != -1) + { + sprintf(mapFileName, "maps/%03u%02u%02u.map", parentMapId, tileY, tileX); + mapFile = fopen(mapFileName, "rb"); + } + } + if (!mapFile) return false; @@ -389,7 +398,6 @@ namespace MMAP useTerrain = true; useLiquid = true; uint8 liquidType = MAP_LIQUID_TYPE_NO_WATER; - // FIXME: "warning: the address of ‘liquid_type’ will always evaluate as ‘true’" // if there is no liquid, don't use liquid if (!meshData.liquidVerts.size() || !ltriangles.size()) @@ -631,8 +639,8 @@ namespace MMAP /**************************************************************************/ bool TerrainBuilder::loadVMap(uint32 mapID, uint32 tileX, uint32 tileY, MeshData &meshData) { - IVMapManager* vmapManager = new VMapManager2(); - int result = vmapManager->loadMap("vmaps", mapID, tileX, tileY); + VMapManager2* vmapManager = static_cast(VMapFactory::createOrGetVMapManager()); + int result = vmapManager->loadSingleMap(mapID, "vmaps", tileX, tileY); bool retval = false; do @@ -641,7 +649,7 @@ namespace MMAP break; InstanceTreeMap instanceTrees; - ((VMapManager2*)vmapManager)->getInstanceMapTree(instanceTrees); + vmapManager->getInstanceMapTree(instanceTrees); if (!instanceTrees[mapID]) break; @@ -669,7 +677,7 @@ namespace MMAP worldModel->getGroupModels(groupModels); // all M2s need to have triangle indices reversed - bool isM2 = instance.name.find(".m2") != std::string::npos || instance.name.find(".M2") != std::string::npos; + bool isM2 = (instance.flags & MOD_M2) != 0; // transform data float scale = instance.iScale; @@ -778,8 +786,7 @@ namespace MMAP } while (false); - vmapManager->unloadMap(mapID, tileX, tileY); - delete vmapManager; + vmapManager->unloadSingleMap(mapID, tileX, tileY); return retval; } diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index d6a0a642bc..516fcf3a86 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -79,13 +79,18 @@ char* GetExtension(char* FileName) extern HANDLE WorldMpq; -ADTFile::ADTFile(char* filename) : ADT(WorldMpq, filename, false) +ADTFile::ADTFile(char* filename, bool cache) : ADT(WorldMpq, filename, false) { Adtfilename.append(filename); + cacheable = cache; + dirfileCache = nullptr; } -bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) +bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId) { + if (dirfileCache) + return initFromCache(map_num, tileX, tileY, originalMapId); + if (ADT.isEof ()) return false; @@ -107,14 +112,16 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) //printf("yMap = %s\n", yMap.c_str()); std::string dirname = std::string(szWorkDirWmo) + "/dir_bin"; - FILE *dirfile; - dirfile = fopen(dirname.c_str(), "ab"); + FILE* dirfile = fopen(dirname.c_str(), "ab"); if (!dirfile) { printf("Can't open dirfile!'%s'\n", dirname.c_str()); return false; } + if (cacheable) + dirfileCache = new std::vector(); + while (!ADT.isEof()) { char fourcc[5]; @@ -189,7 +196,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) { uint32 id; ADT.read(&id, 4); - ModelInstance inst(ADT, ModelInstanceNames[id].c_str(), map_num, tileX, tileY, dirfile); + ModelInstance inst(ADT, ModelInstanceNames[id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache); } delete[] ModelInstanceNames; ModelInstanceNames = NULL; @@ -204,7 +211,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) { uint32 id; ADT.read(&id, 4); - WMOInstance inst(ADT, WmoInstanceNames[id].c_str(), map_num, tileX, tileY, dirfile); + WMOInstance inst(ADT, WmoInstanceNames[id].c_str(), map_num, tileX, tileY, originalMapId, dirfile, dirfileCache); } delete[] WmoInstanceNames; @@ -221,7 +228,37 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY) return true; } +bool ADTFile::initFromCache(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId) +{ + if (dirfileCache->empty()) + return true; + + std::string dirname = std::string(szWorkDirWmo) + "/dir_bin"; + FILE* dirfile = fopen(dirname.c_str(), "ab"); + if (!dirfile) + { + printf("Can't open dirfile!'%s'\n", dirname.c_str()); + return false; + } + + for (ADTOutputCache const& cached : *dirfileCache) + { + fwrite(&map_num, sizeof(uint32), 1, dirfile); + fwrite(&tileX, sizeof(uint32), 1, dirfile); + fwrite(&tileY, sizeof(uint32), 1, dirfile); + uint32 flags = cached.Flags; + if (map_num != originalMapId) + flags |= MOD_PARENT_SPAWN; + fwrite(&flags, sizeof(uint32), 1, dirfile); + fwrite(cached.Data.data(), cached.Data.size(), 1, dirfile); + } + + fclose(dirfile); + return true; +} + ADTFile::~ADTFile() { ADT.close(); + delete dirfileCache; } diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index 6567254108..f1f42f3fd4 100644 --- a/src/tools/vmap4_extractor/adtfile.h +++ b/src/tools/vmap4_extractor/adtfile.h @@ -106,31 +106,28 @@ struct MapChunkHeader uint32 effectId; }; +struct ADTOutputCache +{ + uint32 Flags; + std::vector Data; +}; class ADTFile { private: - //size_t mcnk_offsets[256], mcnk_sizes[256]; MPQFile ADT; - //mcell Mcell; std::string Adtfilename; + bool cacheable; + std::vector* dirfileCache; public: - ADTFile(char* filename); + ADTFile(char* filename, bool cache); ~ADTFile(); int nWMO; int nMDX; std::string* WmoInstanceNames; std::string* ModelInstanceNames; - bool init(uint32 map_num, uint32 tileX, uint32 tileY); - //void LoadMapChunks(); - - //uint32 wmo_count; -/* - const mcell& Getmcell() const - { - return Mcell; - } -*/ + bool init(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId); + bool initFromCache(uint32 map_num, uint32 tileX, uint32 tileY, uint32 originalMapId); }; char const* GetPlainName(char const* FileName); diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index 204bca77ca..d797a28a61 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -19,6 +19,7 @@ #include "vmapexport.h" #include "model.h" #include "wmo.h" +#include "adtfile.h" #include "mpqfile.h" #include #include @@ -144,7 +145,7 @@ Vec3D fixCoordSystem2(Vec3D v) return Vec3D(v.x, v.z, v.y); } -ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile) +ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) : id(0), scale(0), flags(0) { float ff[3]; @@ -180,6 +181,8 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID uint32 flags = MOD_M2; if (tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN; + if (mapID != originalMapId) + flags |= MOD_PARENT_SPAWN; //write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, name fwrite(&mapID, sizeof(uint32), 1, pDirfile); @@ -195,6 +198,34 @@ ModelInstance::ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID fwrite(&nlen, sizeof(uint32), 1, pDirfile); fwrite(ModelInstName, sizeof(char), nlen, pDirfile); + if (dirfileCache) + { + dirfileCache->emplace_back(); + ADTOutputCache& cacheModelData = dirfileCache->back(); + cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN; + cacheModelData.Data.resize( + sizeof(uint16) + // adtId + sizeof(uint32) + // id + sizeof(float) * 3 + // pos + sizeof(float) * 3 + // rot + sizeof(float) + // sc + sizeof(uint32) + // nlen + nlen); // ModelInstName + + uint8* cacheData = cacheModelData.Data.data(); +#define CACHE_WRITE(value, size, count, dest) memcpy(dest, value, size * count); dest += size * count; + + CACHE_WRITE(&adtId, sizeof(uint16), 1, cacheData); + CACHE_WRITE(&id, sizeof(uint32), 1, cacheData); + CACHE_WRITE(&pos, sizeof(float), 3, cacheData); + CACHE_WRITE(&rot, sizeof(float), 3, cacheData); + CACHE_WRITE(&sc, sizeof(float), 1, cacheData); + CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData); + CACHE_WRITE(ModelInstName, sizeof(char), nlen, cacheData); + +#undef CACHE_WRITE + } + /* int realx1 = (int) ((float) pos.x / 533.333333f); int realy1 = (int) ((float) pos.z / 533.333333f); int realx2 = (int) ((float) pos.x / 533.333333f); diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h index fea5cb3f7a..283279ea54 100644 --- a/src/tools/vmap4_extractor/model.h +++ b/src/tools/vmap4_extractor/model.h @@ -24,6 +24,7 @@ #include class MPQFile; +struct ADTOutputCache; Vec3D fixCoordSystem(Vec3D v); @@ -59,7 +60,7 @@ public: float sc; ModelInstance() : id(0), scale(0), flags(0), sc(0.0f) {} - ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile); + ModelInstance(MPQFile& f, char const* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); }; diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 33630d635b..fbf6dff323 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #ifdef _WIN32 #include @@ -103,15 +105,15 @@ TCHAR const* LocalesT[LOCALES_COUNT] = _T("itIT"), }; -typedef struct +struct map_info { char name[64]; - unsigned int id; -}map_id; + int32 parent_id; +}; -map_id * map_ids; +std::map map_ids; +std::unordered_set maps_that_are_parents; uint16 *LiqType = 0; -uint32 map_count; char output_path[128]="."; char input_path[1024]="."; bool preciseVectorData = false; @@ -120,7 +122,7 @@ bool preciseVectorData = false; //static const char * szWorkDirMaps = ".\\Maps"; const char* szWorkDirWmo = "./Buildings"; -const char* szRawVMAPMagic = "VMAP044"; +const char* szRawVMAPMagic = "VMAP045"; bool LoadLocaleMPQFile(int locale) { @@ -389,26 +391,49 @@ bool ExtractSingleWmo(std::string& fname) void ParsMapFiles() { - char fn[512]; - //char id_filename[64]; - char id[10]; - for (unsigned int i=0; i wdts; + auto getWDT = [&wdts](uint32 mapId) -> WDTFile* { - sprintf(id,"%03u",map_ids[i].id); - sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name); - WDTFile WDT(fn,map_ids[i].name); - if (WDT.init(id, map_ids[i].id)) + auto itr = wdts.find(mapId); + if (itr == wdts.end()) { - printf("Processing Map %u\n[", map_ids[i].id); - for (int x=0; x<64; ++x) + char fn[512]; + char* name = map_ids[mapId].name; + sprintf(fn, "World\\Maps\\%s\\%s.wdt", name, name); + itr = wdts.emplace(std::piecewise_construct, std::forward_as_tuple(mapId), std::forward_as_tuple(fn, name, maps_that_are_parents.count(mapId) > 0)).first; + if (!itr->second.init(mapId)) { - for (int y=0; y<64; ++y) + wdts.erase(itr); + return nullptr; + } + } + + return &itr->second; + }; + + for (auto itr = map_ids.begin(); itr != map_ids.end(); ++itr) + { + if (WDTFile* WDT = getWDT(itr->first)) + { + WDTFile* parentWDT = itr->second.parent_id >= 0 ? getWDT(itr->second.parent_id) : nullptr; + printf("Processing Map %u\n[", itr->first); + for (int32 x = 0; x < 64; ++x) + { + for (int32 y = 0; y < 64; ++y) { - if (ADTFile *ADT = WDT.GetMap(x,y)) + bool success = false; + if (ADTFile* ADT = WDT->GetMap(x, y)) { - //sprintf(id_filename,"%02u %02u %03u",x,y,map_ids[i].id);//!!!!!!!!! - ADT->init(map_ids[i].id, x, y); - delete ADT; + success = ADT->init(itr->first, x, y, itr->first); + WDT->FreeADT(ADT); + } + if (!success && parentWDT) + { + if (ADTFile* ADT = parentWDT->GetMap(x, y)) + { + ADT->init(itr->first, x, y, itr->second.parent_id); + parentWDT->FreeADT(ADT); + } } } printf("#"); @@ -507,7 +532,7 @@ bool processArgv(int argc, char ** argv, const char *versionString) int main(int argc, char ** argv) { bool success=true; - const char *versionString = "V4.00 2012_02"; + const char *versionString = "V4.05 2018_03"; // Use command line arguments, when some if (!processArgv(argc, argv, versionString)) @@ -564,39 +589,36 @@ int main(int argc, char ** argv) //map.dbc if (success) { - DBCFile * dbc = new DBCFile(LocaleMpq, "DBFilesClient\\Map.dbc"); + DBCFile* dbc = new DBCFile(LocaleMpq, "DBFilesClient\\Map.dbc"); if (!dbc->open()) { delete dbc; printf("FATAL ERROR: Map.dbc not found in data file.\n"); return 1; } - map_count=dbc->getRecordCount (); - map_ids=new map_id[map_count]; - for (unsigned int x=0;xgetRecordCount(); ++x) { - map_ids[x].id = dbc->getRecord(x).getUInt(0); + map_info& m = map_ids[dbc->getRecord(x).getUInt(0)]; const char* map_name = dbc->getRecord(x).getString(1); - size_t max_map_name_length = sizeof(map_ids[x].name); + size_t max_map_name_length = sizeof(m.name); if (strlen(map_name) >= max_map_name_length) { - delete dbc; - delete[] map_ids; - printf("FATAL ERROR: Map name too long.\n"); - return 1; + printf("Fatal error: Map name too long!\n"); + exit(1); } - strncpy(map_ids[x].name, map_name, max_map_name_length); - map_ids[x].name[max_map_name_length - 1] = '\0'; - printf("Map - %s\n", map_ids[x].name); + strncpy(m.name, map_name, max_map_name_length); + m.name[max_map_name_length - 1] = '\0'; + m.parent_id = int16(dbc->getRecord(x).getInt(19)); + if (m.parent_id >= 0) + maps_that_are_parents.insert(m.parent_id); + + printf("Map - %s\n", m.name); } - delete dbc; ParsMapFiles(); - delete [] map_ids; - //nError = ERROR_SUCCESS; - // Extract models, listed in GameObjectDisplayInfo.dbc ExtractGameobjectModels(); } diff --git a/src/tools/vmap4_extractor/vmapexport.h b/src/tools/vmap4_extractor/vmapexport.h index a73d259d52..c798fb496b 100644 --- a/src/tools/vmap4_extractor/vmapexport.h +++ b/src/tools/vmap4_extractor/vmapexport.h @@ -24,8 +24,9 @@ enum ModelFlags { MOD_M2 = 1, - MOD_WORLDSPAWN = 1<<1, - MOD_HAS_BOUND = 1<<2 + MOD_WORLDSPAWN = 1 << 1, + MOD_HAS_BOUND = 1 << 2, + MOD_PARENT_SPAWN = 1 << 3 }; extern const char * szWorkDirWmo; diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index 8948489a90..e5856d9aaf 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -33,60 +33,68 @@ char * wdtGetPlainName(char * FileName) extern HANDLE WorldMpq; -WDTFile::WDTFile(char* file_name, char* file_name1):WDT(WorldMpq, file_name) +WDTFile::WDTFile(char const* filePath, std::string mapName, bool cache) + : _file(WorldMpq, filePath), _mapName(std::move(mapName)) { - filename.append(file_name1,strlen(file_name1)); + if (cache) + { + _adtCache = std::make_unique(); + memset(_adtCache->file, 0, sizeof(_adtCache->file)); + } + else + _adtCache = nullptr; } -bool WDTFile::init(char* /*map_id*/, unsigned int mapID) +WDTFile::~WDTFile() = default; + +bool WDTFile::init(uint32 mapId) { - if (WDT.isEof()) - { - //printf("Can't find WDT file.\n"); + if (_file.isEof()) return false; - } char fourcc[5]; uint32 size; std::string dirname = std::string(szWorkDirWmo) + "/dir_bin"; - FILE *dirfile; - dirfile = fopen(dirname.c_str(), "ab"); + FILE* dirfile = fopen(dirname.c_str(), "ab"); if (!dirfile) { printf("Can't open dirfile!'%s'\n", dirname.c_str()); return false; } - while (!WDT.isEof()) + while (!_file.isEof()) { - WDT.read(fourcc,4); - WDT.read(&size, 4); + _file.read(fourcc, 4); + _file.read(&size, 4); flipcc(fourcc); fourcc[4] = 0; - size_t nextpos = WDT.getPos() + size; + size_t nextpos = _file.getPos() + size; - if (!strcmp(fourcc,"MAIN")) + if (!strcmp(fourcc, "MAIN")) { } - if (!strcmp(fourcc,"MWMO")) + if (!strcmp(fourcc, "MWMO")) { // global map objects if (size) { char *buf = new char[size]; - WDT.read(buf, size); - char *p=buf; - int q = 0; - gWmoInstansName = new std::string[size]; + _file.read(buf, size); + char *p = buf; while (p < buf + size) { - char* s=wdtGetPlainName(p); - FixNameCase(s,strlen(s)); - p=p+strlen(p)+1; - gWmoInstansName[q++] = s; + std::string path(p); + + char* s = wdtGetPlainName(p); + FixNameCase(s, strlen(s)); + FixNameSpaces(s, strlen(s)); + p = p + strlen(p) + 1; + _wmoNames.push_back(s); + + ExtractSingleWmo(path); } delete[] buf; } @@ -96,39 +104,45 @@ bool WDTFile::init(char* /*map_id*/, unsigned int mapID) // global wmo instance data if (size) { - gnWMO = (int)size / 64; + int32 gnWMO = (int)size / 64; for (int i = 0; i < gnWMO; ++i) { int id; - WDT.read(&id, 4); - WMOInstance inst(WDT,gWmoInstansName[id].c_str(), mapID, 65, 65, dirfile); + _file.read(&id, 4); + WMOInstance inst(_file, _wmoNames[id].c_str(), mapId, 65, 65, mapId, dirfile, nullptr); } - - delete[] gWmoInstansName; - gWmoInstansName = NULL; } } - WDT.seek((int)nextpos); + _file.seek((int)nextpos); } - WDT.close(); + _file.close(); fclose(dirfile); return true; } -WDTFile::~WDTFile(void) +ADTFile* WDTFile::GetMap(int32 x, int32 y) { - WDT.close(); -} + if (!(x >= 0 && y >= 0 && x < 64 && y < 64)) + return nullptr; -ADTFile* WDTFile::GetMap(int x, int z) -{ - if (!(x>=0 && z >= 0 && x<64 && z<64)) - return NULL; + if (_adtCache && _adtCache->file[x][y]) + return _adtCache->file[x][y].get(); char name[512]; - sprintf(name,"World\\Maps\\%s\\%s_%d_%d_obj0.adt", filename.c_str(), filename.c_str(), x, z); - return new ADTFile(name); + sprintf(name, "World\\Maps\\%s\\%s_%d_%d_obj0.adt", _mapName.c_str(), _mapName.c_str(), x, y); + ADTFile* adt = new ADTFile(name, _adtCache != nullptr); + if (_adtCache) + _adtCache->file[x][y].reset(adt); + return adt; +} + +void WDTFile::FreeADT(ADTFile* adt) +{ + if (_adtCache) + return; + + delete adt; } diff --git a/src/tools/vmap4_extractor/wdtfile.h b/src/tools/vmap4_extractor/wdtfile.h index 49f10cf306..4456da1d1d 100644 --- a/src/tools/vmap4_extractor/wdtfile.h +++ b/src/tools/vmap4_extractor/wdtfile.h @@ -21,24 +21,32 @@ #include "mpqfile.h" #include +#include class ADTFile; class WDTFile { public: - WDTFile(char* file_name, char* file_name1); - ~WDTFile(void); + WDTFile(char const* file_name, std::string mapName, bool cache); + ~WDTFile(); + bool init(uint32 mapId); - bool init(char* map_id, unsigned int mapID); - ADTFile* GetMap(int x, int z); + ADTFile* GetMap(int32 x, int32 y); + void FreeADT(ADTFile* adt); std::string* gWmoInstansName; int gnWMO; private: - MPQFile WDT; - std::string filename; + MPQFile _file; + std::string _mapName; + std::vector _wmoNames; + struct ADTCache + { + std::unique_ptr file[64][64]; + }; + std::unique_ptr _adtCache; }; #endif diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 2b0bee9417..dbfe3a9c8f 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -18,6 +18,7 @@ #include "vmapexport.h" #include "wmo.h" +#include "adtfile.h" #include "vec3d.h" #include @@ -485,7 +486,7 @@ WMOGroup::~WMOGroup() delete [] LiquBytes; } -WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile) +WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache) : currx(0), curry(0), wmo(NULL), doodadset(0), pos(), indx(0), id(0) { float ff[3]; @@ -549,7 +550,11 @@ WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint float scale = 1.0f; uint32 flags = MOD_HAS_BOUND; - if (tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN; + if (tileX == 65 && tileY == 65) + flags |= MOD_WORLDSPAWN; + if (mapID != originalMapId) + flags |= MOD_PARENT_SPAWN; + //write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name fwrite(&mapID, sizeof(uint32), 1, pDirfile); fwrite(&tileX, sizeof(uint32), 1, pDirfile); @@ -562,10 +567,42 @@ WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint fwrite(&scale, sizeof(float), 1, pDirfile); fwrite(&pos2, sizeof(float), 3, pDirfile); fwrite(&pos3, sizeof(float), 3, pDirfile); - uint32 nlen=strlen(WmoInstName); + uint32 nlen = strlen(WmoInstName); fwrite(&nlen, sizeof(uint32), 1, pDirfile); fwrite(WmoInstName, sizeof(char), nlen, pDirfile); + if (dirfileCache) + { + dirfileCache->emplace_back(); + ADTOutputCache& cacheModelData = dirfileCache->back(); + cacheModelData.Flags = flags & ~MOD_PARENT_SPAWN; + cacheModelData.Data.resize( + sizeof(uint16) + // adtId + sizeof(uint32) + // id + sizeof(float) * 3 + // pos + sizeof(float) * 3 + // rot + sizeof(float) + // scale + sizeof(float) * 3 + // pos2 + sizeof(float) * 3 + // pos3 + sizeof(uint32) + // nlen + nlen); // WmoInstName + + uint8* cacheData = cacheModelData.Data.data(); +#define CACHE_WRITE(value, size, count, dest) memcpy(dest, value, size * count); dest += size * count; + + CACHE_WRITE(&adtId, sizeof(uint16), 1, cacheData); + CACHE_WRITE(&id, sizeof(uint32), 1, cacheData); + CACHE_WRITE(&pos, sizeof(float), 3, cacheData); + CACHE_WRITE(&rot, sizeof(float), 3, cacheData); + CACHE_WRITE(&scale, sizeof(float), 1, cacheData); + CACHE_WRITE(&pos2, sizeof(float), 3, cacheData); + CACHE_WRITE(&pos3, sizeof(float), 3, cacheData); + CACHE_WRITE(&nlen, sizeof(uint32), 1, cacheData); + CACHE_WRITE(WmoInstName, sizeof(char), nlen, cacheData); + +#undef CACHE_WRITE + } + /* fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n", MapName, WmoInstName, diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index a5c4e71d93..d85b2fd2af 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -42,6 +42,7 @@ enum MopyFlags class WMOInstance; class WMOManager; class MPQFile; +struct ADTOutputCache; /* for whatever reason a certain company just can't stick to one coordinate system... */ static inline Vec3D fixCoords(const Vec3D &v){ return Vec3D(v.z, v.x, v.y); } @@ -134,7 +135,7 @@ public: Vec3D pos2, pos3, rot; uint32 indx, id; - WMOInstance(MPQFile&f , char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile); + WMOInstance(MPQFile&f , char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, uint32 originalMapId, FILE* pDirfile, std::vector* dirfileCache); static void reset(); };