diff options
477 files changed, 5357 insertions, 940 deletions
diff --git a/.travis.yml b/.travis.yml index 894fedf4da6..80e237e4d12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,12 +16,14 @@ before_install: - sudo apt-get -qq install libssl-dev libmysqlclient-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev - sudo apt-get -qq install libboost1.55-dev libboost-thread1.55-dev libboost-filesystem1.55-dev libboost-system1.55-dev libboost-program-options1.55-dev libboost-iostreams1.55-dev - export CC=clang-3.5 CXX=clang++-3.5 + - git config user.email "travis@build.bot" && git config user.name "Travis CI" + - git tag -a -m "Travis build" init install: - mysql -uroot -e 'create database test_mysql;' - mkdir bin - cd bin - - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS=1 -DSERVERS=1 -DNOJEM=1 -DWITH_DYNAMIC_LINKING=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" -DCMAKE_INSTALL_PREFIX=check_install + - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS="dynamic" -DSERVERS=1 -DNOJEM=1 -DWITH_DYNAMIC_LINKING=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" -DCMAKE_INSTALL_PREFIX=check_install - cd .. - sudo chmod +x contrib/check_updates.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index dda8f242feb..de08fe3181f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,11 @@ project(TrinityCore) cmake_policy(SET CMP0005 OLD) if(POLICY CMP0043) cmake_policy(SET CMP0043 OLD) # Disable 'Ignore COMPILE_DEFINITIONS_<Config> properties' -endif(POLICY CMP0043) +endif() + +if(POLICY CMP0054) + cmake_policy(SET CMP0054 NEW) # Only interpret if() arguments as variables or keywords when unquoted - prevents intepreting if (SOME_STRING_VARIABLE MATCHES "MSVC") as if (SOME_STRING_VARIABLE MATCHES "1") +endif() # add this options before PROJECT keyword set(CMAKE_DISABLE_SOURCE_CHANGES ON) @@ -40,6 +44,7 @@ endif() include(CheckCXXSourceRuns) include(CheckIncludeFiles) +include(ConfigureScripts) # set default buildoptions and print them include(cmake/options.cmake) diff --git a/cmake/compiler/clang/settings.cmake b/cmake/compiler/clang/settings.cmake index 9a8cb85275e..1cd95bbf703 100644 --- a/cmake/compiler/clang/settings.cmake +++ b/cmake/compiler/clang/settings.cmake @@ -19,7 +19,7 @@ endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-narrowing -Wno-deprecated-register") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1") -if (WITH_DYNAMIC_LINKING) +if (BUILD_SHARED_LIBS) # -fPIC is needed to allow static linking in shared libs. # -fvisibility=hidden sets the default visibility to hidden to prevent exporting of all symbols. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden") diff --git a/cmake/compiler/gcc/settings.cmake b/cmake/compiler/gcc/settings.cmake index d9eda767b8e..c4f97f4ffd4 100644 --- a/cmake/compiler/gcc/settings.cmake +++ b/cmake/compiler/gcc/settings.cmake @@ -35,7 +35,7 @@ if( WITH_COREDEBUG ) message(STATUS "GCC: Debug-flags set (-g3)") endif() -if (WITH_DYNAMIC_LINKING) +if (BUILD_SHARED_LIBS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden -Wno-attributes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden -Wno-attributes") diff --git a/cmake/compiler/msvc/settings.cmake b/cmake/compiler/msvc/settings.cmake index c2eda80512b..afde70b0f79 100644 --- a/cmake/compiler/msvc/settings.cmake +++ b/cmake/compiler/msvc/settings.cmake @@ -31,12 +31,18 @@ else() endif() # Set build-directive (used in core to tell which buildtype we used) -add_definitions(-D_BUILD_DIRECTIVE=\\"$(ConfigurationName)\\") +# msbuild/devenv don't set CMAKE_MAKE_PROGRAM, you can choose build type from a dropdown after generating projects +if("${CMAKE_MAKE_PROGRAM}" MATCHES "MSBuild") + add_definitions(-D_BUILD_DIRECTIVE=\\"$(ConfigurationName)\\") +else() + # while all make-like generators do (nmake, ninja) + add_definitions(-D_BUILD_DIRECTIVE=\\"${CMAKE_BUILD_TYPE}\\") +endif() # multithreaded compiling on VS set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") -if((PLATFORM EQUAL 64) OR (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0) OR WITH_DYNAMIC_LINKING) +if((PLATFORM EQUAL 64) OR (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0) OR BUILD_SHARED_LIBS) # Enable extended object support set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") message(STATUS "MSVC: Enabled increased number of sections in object files") @@ -74,7 +80,7 @@ if(NOT WITH_WARNINGS) message(STATUS "MSVC: Disabled generic compiletime warnings") endif() -if (WITH_DYNAMIC_LINKING) +if (BUILD_SHARED_LIBS) # C4251: needs to have dll-interface to be used by clients of class '...' # C4275: non dll-interface class ...' used as base for dll-interface class '...' set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251 /wd4275") diff --git a/cmake/genrev.cmake b/cmake/genrev.cmake index 5c013756f09..d123153e975 100644 --- a/cmake/genrev.cmake +++ b/cmake/genrev.cmake @@ -24,7 +24,7 @@ else() if(GIT_EXECUTABLE) # Create a revision-string that we can use execute_process( - COMMAND "${GIT_EXECUTABLE}" describe --match init --dirty=+ --abbrev=12 + COMMAND "${GIT_EXECUTABLE}" describe --long --match init --dirty=+ --abbrev=12 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" OUTPUT_VARIABLE rev_info OUTPUT_STRIP_TRAILING_WHITESPACE diff --git a/cmake/macros/ConfigureScripts.cmake b/cmake/macros/ConfigureScripts.cmake new file mode 100644 index 00000000000..5260d3a1afe --- /dev/null +++ b/cmake/macros/ConfigureScripts.cmake @@ -0,0 +1,104 @@ +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# Returns the base path to the script directory in the source directory +function(WarnAboutSpacesInBuildPath) + # Only check win32 since unix doesn't allow spaces in paths + if (WIN32) + string(FIND "${CMAKE_BINARY_DIR}" " " SPACE_INDEX_POS) + + if (SPACE_INDEX_POS GREATER -1) + message("") + message(WARNING " *** WARNING!\n" + " *** Your selected build directory contains spaces!\n" + " *** Please note that this will cause issues!") + endif() + endif() +endfunction() + +# Returns the base path to the script directory in the source directory +function(GetScriptsBasePath variable) + set(${variable} "${CMAKE_SOURCE_DIR}/src/server/scripts" PARENT_SCOPE) +endfunction() + +# Stores the absolut path of the given module in the variable +function(GetPathToScriptModule module variable) + GetScriptsBasePath(SCRIPTS_BASE_PATH) + set(${variable} "${SCRIPTS_BASE_PATH}/${module}" PARENT_SCOPE) +endfunction() + +# Stores the project name of the given module in the variable +function(GetProjectNameOfScriptModule module variable) + string(TOLOWER "scripts_${SCRIPT_MODULE}" GENERATED_NAME) + set(${variable} "${GENERATED_NAME}" PARENT_SCOPE) +endfunction() + +# Creates a list of all script modules +# and stores it in the given variable. +function(GetScriptModuleList variable) + GetScriptsBasePath(BASE_PATH) + file(GLOB LOCALE_SCRIPT_MODULE_LIST RELATIVE + ${BASE_PATH} + ${BASE_PATH}/*) + + set(${variable}) + foreach(SCRIPT_MODULE ${LOCALE_SCRIPT_MODULE_LIST}) + GetPathToScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PATH) + if (IS_DIRECTORY ${SCRIPT_MODULE_PATH}) + list(APPEND ${variable} ${SCRIPT_MODULE}) + endif() + endforeach() + set(${variable} ${${variable}} PARENT_SCOPE) +endfunction() + +# Converts the given script module name into it's +# variable name which holds the linkage type. +function(ScriptModuleNameToVariable module variable) + string(TOUPPER ${module} ${variable}) + set(${variable} "SCRIPTS_${${variable}}") + set(${variable} ${${variable}} PARENT_SCOPE) +endfunction() + +# Stores in the given variable whether dynamic linking is required +function(IsDynamicLinkingRequired variable) + if(SCRIPTS MATCHES "dynamic") + set(IS_DEFAULT_VALUE_DYNAMIC ON) + endif() + + GetScriptModuleList(SCRIPT_MODULE_LIST) + set(IS_REQUIRED OFF) + foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST}) + ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE) + if ((${SCRIPT_MODULE_VARIABLE} STREQUAL "dynamic") OR + (${SCRIPT_MODULE_VARIABLE} STREQUAL "default" AND IS_DEFAULT_VALUE_DYNAMIC)) + set(IS_REQUIRED ON) + break() + endif() + endforeach() + set(${variable} ${IS_REQUIRED} PARENT_SCOPE) +endfunction() + +# Stores the native variable name +function(GetNativeSharedLibraryName module variable) + if(WIN32) + set(${variable} "${module}.dll" PARENT_SCOPE) + else() + set(${variable} "lib${module}.so" PARENT_SCOPE) + endif() +endfunction() + +# Stores the native install path in the variable +function(GetInstallOffset variable) + if(WIN32) + set(${variable} "${CMAKE_INSTALL_PREFIX}/scripts" PARENT_SCOPE) + else() + set(${variable} "${CMAKE_INSTALL_PREFIX}/bin/scripts" PARENT_SCOPE) + endif() +endfunction() diff --git a/cmake/macros/FindPCHSupport.cmake b/cmake/macros/FindPCHSupport.cmake index 6edc8e92890..9cc39a13b04 100644 --- a/cmake/macros/FindPCHSupport.cmake +++ b/cmake/macros/FindPCHSupport.cmake @@ -143,7 +143,7 @@ FUNCTION(ADD_CXX_PCH_XCODE TARGET_NAME_LIST PCH_HEADER PCH_SOURCE) ENDFUNCTION(ADD_CXX_PCH_XCODE) FUNCTION(ADD_CXX_PCH TARGET_NAME_LIST PCH_HEADER PCH_SOURCE) - IF (MSVC) + IF (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") ADD_CXX_PCH_MSVC("${TARGET_NAME_LIST}" ${PCH_HEADER} ${PCH_SOURCE}) ELSEIF ("${CMAKE_GENERATOR}" MATCHES "Xcode") ADD_CXX_PCH_XCODE("${TARGET_NAME_LIST}" ${PCH_HEADER} ${PCH_SOURCE}) diff --git a/cmake/options.cmake b/cmake/options.cmake index 62810b2d3f2..085a45fa03f 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -9,11 +9,30 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. option(SERVERS "Build worldserver and authserver" 1) -option(SCRIPTS "Build core with scripts included" 1) +set(SCRIPTS "static" CACHE STRING "Build core with scripts") +set_property(CACHE SCRIPTS PROPERTY STRINGS none static dynamic minimal-static minimal-dynamic) + +# Build a list of all script modules when -DSCRIPT="custom" is selected +GetScriptModuleList(SCRIPT_MODULE_LIST) +foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST}) + ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE) + set(${SCRIPT_MODULE_VARIABLE} "default" CACHE STRING "Build type of the ${SCRIPT_MODULE} module.") + set_property(CACHE ${SCRIPT_MODULE_VARIABLE} PROPERTY STRINGS default disabled static dynamic) +endforeach() + option(TOOLS "Build map/vmap/mmap extraction/assembler tools" 0) option(USE_SCRIPTPCH "Use precompiled headers when compiling scripts" 1) option(USE_COREPCH "Use precompiled headers when compiling servers" 1) option(WITH_DYNAMIC_LINKING "Enable dynamic library linking." 0) +IsDynamicLinkingRequired(WITH_DYNAMIC_LINKING_FORCED) +if (WITH_DYNAMIC_LINKING AND WITH_DYNAMIC_LINKING_FORCED) + set(WITH_DYNAMIC_LINKING_FORCED OFF) +endif() +if (WITH_DYNAMIC_LINKING OR WITH_DYNAMIC_LINKING_FORCED) + set(BUILD_SHARED_LIBS ON) +else() + set(BUILD_SHARED_LIBS OFF) +endif() option(WITH_WARNINGS "Show all warnings during compile" 0) option(WITH_COREDEBUG "Include additional debug-code in core" 0) set(WITH_SOURCE_TREE "hierarchical" CACHE STRING "Build the source tree for IDE's.") diff --git a/cmake/platform/win/settings.cmake b/cmake/platform/win/settings.cmake index da66daf0832..0c1a103304a 100644 --- a/cmake/platform/win/settings.cmake +++ b/cmake/platform/win/settings.cmake @@ -1,20 +1,9 @@ -# check the CMake preload parameters (commented out by default) +add_definitions(-D_WIN32_WINNT=0x0601) -# overload CMAKE_INSTALL_PREFIX if not being set properly -#if( WIN32 ) -# if( NOT CYGWIN ) -# if( NOT CMAKE_INSTALL_PREFIX ) -# set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/bin") -# endif() -# endif() -#endif() - -if (WIN32) - add_definitions(-D_WIN32_WINNT=0x0601) -endif() - -if ( MSVC ) +if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") include(${CMAKE_SOURCE_DIR}/cmake/compiler/msvc/settings.cmake) -elseif ( MINGW ) +elseif (CMAKE_CXX_PLATFORM_ID MATCHES "MinGW") include(${CMAKE_SOURCE_DIR}/cmake/compiler/mingw/settings.cmake) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + include(${CMAKE_SOURCE_DIR}/cmake/compiler/clang/settings.cmake) endif() diff --git a/cmake/showoptions.cmake b/cmake/showoptions.cmake index e6d709207b3..9229590381a 100644 --- a/cmake/showoptions.cmake +++ b/cmake/showoptions.cmake @@ -23,9 +23,8 @@ else() message("* Build world/authserver : No") endif() -if( SCRIPTS ) - message("* Build with scripts : Yes (default)") - add_definitions(-DSCRIPTS) +if(SCRIPTS AND (NOT SCRIPTS STREQUAL "none")) + message("* Build with scripts : Yes (${SCRIPTS})") else() message("* Build with scripts : No") endif() @@ -70,7 +69,7 @@ else() endif() if( NOT WITH_SOURCE_TREE STREQUAL "no" ) - message("* Show source tree : Yes - \"${WITH_SOURCE_TREE}\"") + message("* Show source tree : Yes (${WITH_SOURCE_TREE})") else() message("* Show source tree : No") endif() @@ -87,7 +86,7 @@ if ( WITHOUT_GIT ) message(" *** version of git for the revision-hash to work, and be allowede to ask for") message(" *** support if needed.") else() - message("* Use GIT revision hash : Yes") + message("* Use GIT revision hash : Yes (default)") endif() if ( NOJEM ) @@ -113,15 +112,18 @@ if ( HELGRIND ) add_definitions(-DHELGRIND) endif() -if (WITH_DYNAMIC_LINKING) +if (BUILD_SHARED_LIBS) message("") message(" *** WITH_DYNAMIC_LINKING - INFO!") message(" *** Will link against shared libraries!") message(" *** Please note that this is an experimental feature!") + if (WITH_DYNAMIC_LINKING_FORCED) + message("") + message(" *** Dynamic linking was enforced through a dynamic script module!") + endif() add_definitions(-DTRINITY_API_USE_DYNAMIC_LINKING) - set(BUILD_SHARED_LIBS ON) -else() - set(BUILD_SHARED_LIBS OFF) + + WarnAboutSpacesInBuildPath() endif() message("") diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt index 0932c7d4058..48be56bc9ef 100644 --- a/dep/CMakeLists.txt +++ b/dep/CMakeLists.txt @@ -8,7 +8,9 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -if( MSVC ) +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + string(REGEX REPLACE "/W[0-4] " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "/W[0-4] " "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") add_definitions(/W0) else() add_definitions(-w) @@ -18,6 +20,7 @@ add_subdirectory(threads) if(SERVERS OR TOOLS) add_subdirectory(boost) + add_subdirectory(process) add_subdirectory(zlib) add_subdirectory(g3dlite) add_subdirectory(recastnavigation) @@ -33,7 +36,6 @@ if(SERVERS) add_subdirectory(mysql) add_subdirectory(readline) add_subdirectory(gsoap) - add_subdirectory(process) add_subdirectory(efsw) endif() diff --git a/dep/boost/CMakeLists.txt b/dep/boost/CMakeLists.txt index 118635c85bd..6cda5fbec4e 100644 --- a/dep/boost/CMakeLists.txt +++ b/dep/boost/CMakeLists.txt @@ -35,19 +35,14 @@ include (CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_IOSTREAMS_LIBRARY}) set(CMAKE_REQUIRED_FLAGS "-std=c++11") -unset(boost_filesystem_copy_links_without_NO_SCOPED_ENUM CACHE) check_cxx_source_compiles(" #include <boost/filesystem/path.hpp> #include <boost/filesystem/operations.hpp> int main() { boost::filesystem::copy_file(boost::filesystem::path(), boost::filesystem::path()); }" boost_filesystem_copy_links_without_NO_SCOPED_ENUM) -unset(CMAKE_REQUIRED_INCLUDES CACHE) -unset(CMAKE_REQUIRED_LIBRARIES CACHE) -unset(CMAKE_REQUIRED_FLAGS CACHE) - -if (NOT boost_filesystem_copy_links_without_NO_SCOPED_ENUM) - set(OPTIONAL_BOOST_NO_SCOPED_ENUMS -DBOOST_NO_CXX11_SCOPED_ENUMS) -endif() +unset(CMAKE_REQUIRED_INCLUDES) +unset(CMAKE_REQUIRED_LIBRARIES) +unset(CMAKE_REQUIRED_FLAGS) add_library(boost INTERFACE) @@ -59,9 +54,17 @@ target_include_directories(boost INTERFACE ${Boost_INCLUDE_DIRS}) -target_compile_definitions(boost - INTERFACE - -DBOOST_DATE_TIME_NO_LIB - -DBOOST_REGEX_NO_LIB - -DBOOST_CHRONO_NO_LIB - ${OPTIONAL_BOOST_NO_SCOPED_ENUMS}) +if (boost_filesystem_copy_links_without_NO_SCOPED_ENUM) + target_compile_definitions(boost + INTERFACE + -DBOOST_DATE_TIME_NO_LIB + -DBOOST_REGEX_NO_LIB + -DBOOST_CHRONO_NO_LIB) +else() + target_compile_definitions(boost + INTERFACE + -DBOOST_DATE_TIME_NO_LIB + -DBOOST_REGEX_NO_LIB + -DBOOST_CHRONO_NO_LIB + -DBOOST_NO_CXX11_SCOPED_ENUMS) +endif() diff --git a/dep/efsw/CMakeLists.txt b/dep/efsw/CMakeLists.txt index 81a1d20b204..eecc5531944 100644 --- a/dep/efsw/CMakeLists.txt +++ b/dep/efsw/CMakeLists.txt @@ -1,4 +1,4 @@ -if (WITH_DYNAMIC_LINKING) +if (BUILD_SHARED_LIBS) set(SRCS src/efsw/DirectorySnapshot.cpp src/efsw/DirectorySnapshotDiff.cpp @@ -81,5 +81,5 @@ if (WITH_DYNAMIC_LINKING) FOLDER "dep") else() - add_library(efsw INTERFACE) + add_library(efsw INTERFACE IMPORTED GLOBAL) endif() diff --git a/issue_template.md b/issue_template.md index fe090da2338..8653726f830 100644 --- a/issue_template.md +++ b/issue_template.md @@ -10,13 +10,15 @@ 2. 3. -**Branch(es)**: 335/6x +**Branch(es)**: 335/6x -**TC hash/commit**: +**TC hash/commit**: -**TDB version**: +**TDB version**: -**Operating system**: +**Operating system**: + +**Linking model**: static/dynamic [//]: # (This template is for problem reports, for other type of reports edit it accordingly) diff --git a/revision_data.h.in.cmake b/revision_data.h.in.cmake index 04c6e2008a1..14faa04a0bc 100644 --- a/revision_data.h.in.cmake +++ b/revision_data.h.in.cmake @@ -7,7 +7,7 @@ #define _SOURCE_DIRECTORY R"(@CMAKE_SOURCE_DIR@)" #define _BUILD_DIRECTORY R"(@BUILDDIR@)" #define _MYSQL_EXECUTABLE R"(@MYSQL_EXECUTABLE@)" - #define _FULL_DATABASE "TDB_full_world_335.60_2015_11_07.sql" + #define _FULL_DATABASE "TDB_full_world_335.61_2016_04_11.sql" #define VER_COMPANYNAME_STR "TrinityCore Developers" #define VER_LEGALCOPYRIGHT_STR "(c)2008-2016 TrinityCore" #define VER_FILEVERSION 0,0,0 diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index 0ac0ffaf9d1..6dc81ab211e 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -1,6 +1,6 @@ -- MySQL dump 10.13 Distrib 5.6.26, for Win64 (x86_64) -- --- Host: localhost Database: auth335 +-- Host: localhost Database: auth -- ------------------------------------------------------ -- Server version 5.6.26-log @@ -486,7 +486,7 @@ CREATE TABLE `updates` ( LOCK TABLES `updates` WRITE; /*!40000 ALTER TABLE `updates` DISABLE KEYS */; -INSERT INTO `updates` VALUES ('2014_11_10_00_auth.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 21:44:12',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_21_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_00_auth.sql','E8C5B74BB45F0F35DEC182C72BACF435C7066FB0','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_01_auth.sql','862961815354DA2746F5F71FBC8155F57CBE75AB','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_02_auth.sql','33E4F94086590768EF5D4855DD43D7DE7C06ADA4','ARCHIVED','2015-03-21 21:44:51',0),('2015_08_21_00_auth.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-10-05 23:16:19',0),('2015_11_07_00_auth.sql','BAF9F6B8F97A30D04BDBBA8127A62A1720F9B904','RELEASED','2015-11-07 15:40:47',0),('2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','RELEASED','2016-01-13 00:00:00',0); +INSERT INTO `updates` VALUES ('2014_11_10_00_auth.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 21:44:12',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_21_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_00_auth.sql','E8C5B74BB45F0F35DEC182C72BACF435C7066FB0','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_01_auth.sql','862961815354DA2746F5F71FBC8155F57CBE75AB','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_02_auth.sql','33E4F94086590768EF5D4855DD43D7DE7C06ADA4','ARCHIVED','2015-03-21 21:44:51',0),('2015_08_21_00_auth.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-10-05 23:16:19',0),('2015_11_07_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2016-04-11 00:42:36',92),('2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','ARCHIVED','2016-01-13 00:00:00',0),('2016_04_11_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','2016-04-11 03:18:17','2016-04-11 03:18:17',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; @@ -549,4 +549,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2015-11-07 14:42:34 +-- Dump completed on 2016-04-11 2:32:16 diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 94841144017..1f071db3781 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -1,6 +1,6 @@ -- MySQL dump 10.13 Distrib 5.6.26, for Win64 (x86_64) -- --- Host: localhost Database: characters335 +-- Host: localhost Database: characters -- ------------------------------------------------------ -- Server version 5.6.26-log @@ -783,7 +783,7 @@ CREATE TABLE `character_instance` ( `guid` int(10) unsigned NOT NULL DEFAULT '0', `instance` int(10) unsigned NOT NULL DEFAULT '0', `permanent` tinyint(3) unsigned NOT NULL DEFAULT '0', - `extendState` TINYINT(2) UNSIGNED NOT NULL DEFAULT '1', + `extendState` tinyint(2) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (`guid`,`instance`), KEY `instance` (`instance`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -2545,7 +2545,7 @@ CREATE TABLE `updates` ( LOCK TABLES `updates` WRITE; /*!40000 ALTER TABLE `updates` DISABLE KEYS */; -INSERT INTO `updates` VALUES ('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_01_characters.sql','894F08B70449A5481FFAF394EE5571D7FC4D8A3A','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_02_characters.sql','97D7BE0CAADC79F3F11B9FD296B8C6CD40FE593B','ARCHIVED','2015-03-21 21:44:51',0),('2015_06_26_00_characters_335.sql','C2CC6E50AFA1ACCBEBF77CC519AAEB09F3BBAEBC','ARCHIVED','2015-07-13 23:49:22',0),('2015_09_28_00_characters_335.sql','F8682A431D50E54BDC4AC0E7DBED21AE8AAB6AD4','ARCHIVED','2015-09-28 21:00:00',0),('2015_08_26_00_characters_335.sql','C7D6A3A00FECA3EBFF1E71744CA40D3076582374','ARCHIVED','2015-08-26 21:00:00',0),('2015_10_06_00_characters.sql','16842FDD7E8547F2260D3312F53EFF8761EFAB35','ARCHIVED','2015-10-06 16:06:38',0),('2015_10_07_00_characters.sql','E15AB463CEBE321001D7BFDEA4B662FF618728FD','ARCHIVED','2015-10-07 23:32:00',0),('2015_10_12_00_characters.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-10-12 15:35:47',0),('2015_10_28_00_characters.sql','622A9CA8FCE690429EBE23BA071A37C7A007BF8B','ARCHIVED','2015-10-19 14:32:22',0),('2015_10_29_00_characters_335.sql','4555A7F35C107E54C13D74D20F141039ED42943E','ARCHIVED','2015-10-29 17:05:43',0),('2015_11_03_00_characters.sql','CC045717B8FDD9733351E52A5302560CD08AAD57','ARCHIVED','2015-10-12 15:23:33',0),('2015_11_07_00_characters.sql','BAF9F6B8F97A30D04BDBBA8127A62A1720F9B904','RELEASED','2015-11-07 15:40:47',0),('2016_02_10_00_characters.sql','F1B4DA202819CABC7319A4470A2D224A34609E97','RELEASED','2016-02-10 00:00:00',0),('2016_03_13_2016_01_05_00_characters.sql','0EAD24977F40DE2476B4567DA2B477867CC0DA1A','RELEASED','2016-03-13 20:03:56',0); +INSERT INTO `updates` VALUES ('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_01_characters.sql','894F08B70449A5481FFAF394EE5571D7FC4D8A3A','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_02_characters.sql','97D7BE0CAADC79F3F11B9FD296B8C6CD40FE593B','ARCHIVED','2015-03-21 21:44:51',0),('2015_06_26_00_characters_335.sql','C2CC6E50AFA1ACCBEBF77CC519AAEB09F3BBAEBC','ARCHIVED','2015-07-13 23:49:22',0),('2015_09_28_00_characters_335.sql','F8682A431D50E54BDC4AC0E7DBED21AE8AAB6AD4','ARCHIVED','2015-09-28 21:00:00',0),('2015_08_26_00_characters_335.sql','C7D6A3A00FECA3EBFF1E71744CA40D3076582374','ARCHIVED','2015-08-26 21:00:00',0),('2015_10_06_00_characters.sql','16842FDD7E8547F2260D3312F53EFF8761EFAB35','ARCHIVED','2015-10-06 16:06:38',0),('2015_10_07_00_characters.sql','E15AB463CEBE321001D7BFDEA4B662FF618728FD','ARCHIVED','2015-10-07 23:32:00',0),('2015_10_12_00_characters.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-10-12 15:35:47',0),('2015_10_28_00_characters.sql','622A9CA8FCE690429EBE23BA071A37C7A007BF8B','ARCHIVED','2015-10-19 14:32:22',0),('2015_10_29_00_characters_335.sql','4555A7F35C107E54C13D74D20F141039ED42943E','ARCHIVED','2015-10-29 17:05:43',0),('2015_11_03_00_characters.sql','CC045717B8FDD9733351E52A5302560CD08AAD57','ARCHIVED','2015-10-12 15:23:33',0),('2015_11_07_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2016-04-11 00:42:36',94),('2016_02_10_00_characters.sql','F1B4DA202819CABC7319A4470A2D224A34609E97','ARCHIVED','2016-02-10 00:00:00',0),('2016_03_13_2016_01_05_00_characters.sql','0EAD24977F40DE2476B4567DA2B477867CC0DA1A','ARCHIVED','2016-03-13 20:03:56',0),('2016_04_11_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 03:18:17',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; @@ -2630,4 +2630,4 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2015-11-07 14:42:34 +-- Dump completed on 2016-04-11 2:32:17 diff --git a/sql/base/dev/world_database.sql b/sql/base/dev/world_database.sql index 02318987448..85e7c2391da 100644 --- a/sql/base/dev/world_database.sql +++ b/sql/base/dev/world_database.sql @@ -1,6 +1,6 @@ -- MySQL dump 10.13 Distrib 5.6.26, for Win64 (x86_64) -- --- Host: localhost Database: world335 +-- Host: localhost Database: world -- ------------------------------------------------------ -- Server version 5.6.26-log @@ -1022,7 +1022,7 @@ CREATE TABLE `game_tele` ( `map` smallint(5) unsigned NOT NULL DEFAULT '0', `name` varchar(100) NOT NULL DEFAULT '', PRIMARY KEY (`id`) -) ENGINE=MyISAM AUTO_INCREMENT=1425 DEFAULT CHARSET=utf8 COMMENT='Tele Command'; +) ENGINE=MyISAM AUTO_INCREMENT=1429 DEFAULT CHARSET=utf8 COMMENT='Tele Command'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -3785,4 +3785,4 @@ CREATE TABLE `waypoints` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2015-11-07 14:42:45 +-- Dump completed on 2016-04-11 2:32:19 diff --git a/sql/updates/auth/2015_11_07_00_auth.sql b/sql/old/3.3.5a/auth/60_2016_04_11/2015_11_07_00_auth.sql index be8a4d21b66..be8a4d21b66 100644 --- a/sql/updates/auth/2015_11_07_00_auth.sql +++ b/sql/old/3.3.5a/auth/60_2016_04_11/2015_11_07_00_auth.sql diff --git a/sql/updates/auth/2016_01_13_00_auth.sql b/sql/old/3.3.5a/auth/60_2016_04_11/2016_01_13_00_auth.sql index c70d4c09468..c70d4c09468 100644 --- a/sql/updates/auth/2016_01_13_00_auth.sql +++ b/sql/old/3.3.5a/auth/60_2016_04_11/2016_01_13_00_auth.sql diff --git a/sql/updates/characters/2015_11_07_00_characters.sql b/sql/old/3.3.5a/characters/60_2016_04_11/2015_11_07_00_characters.sql index be8a4d21b66..be8a4d21b66 100644 --- a/sql/updates/characters/2015_11_07_00_characters.sql +++ b/sql/old/3.3.5a/characters/60_2016_04_11/2015_11_07_00_characters.sql diff --git a/sql/updates/characters/2016_02_10_00_characters.sql b/sql/old/3.3.5a/characters/60_2016_04_11/2016_02_10_00_characters.sql index d49ed155bc8..d49ed155bc8 100644 --- a/sql/updates/characters/2016_02_10_00_characters.sql +++ b/sql/old/3.3.5a/characters/60_2016_04_11/2016_02_10_00_characters.sql diff --git a/sql/updates/characters/2016_03_13_2016_01_05_00_characters.sql b/sql/old/3.3.5a/characters/60_2016_04_11/2016_03_13_2016_01_05_00_characters.sql index 11850067be9..11850067be9 100644 --- a/sql/updates/characters/2016_03_13_2016_01_05_00_characters.sql +++ b/sql/old/3.3.5a/characters/60_2016_04_11/2016_03_13_2016_01_05_00_characters.sql diff --git a/sql/updates/world/2015_11_07_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_07_02_world.sql index 3e23e0e629b..3e23e0e629b 100644 --- a/sql/updates/world/2015_11_07_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_07_02_world.sql diff --git a/sql/updates/world/2015_11_08_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_00_world.sql index fea6f43bc64..fea6f43bc64 100644 --- a/sql/updates/world/2015_11_08_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_00_world.sql diff --git a/sql/updates/world/2015_11_08_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_01_world.sql index f5642f73af4..f5642f73af4 100644 --- a/sql/updates/world/2015_11_08_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_01_world.sql diff --git a/sql/updates/world/2015_11_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_00_world.sql index 6fd5dec39b7..6fd5dec39b7 100644 --- a/sql/updates/world/2015_11_09_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_00_world.sql diff --git a/sql/updates/world/2015_11_09_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_01_world.sql index e9360cf8963..e9360cf8963 100644 --- a/sql/updates/world/2015_11_09_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_01_world.sql diff --git a/sql/updates/world/2015_11_09_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_02_world_335.sql index 84c0fd423ad..84c0fd423ad 100644 --- a/sql/updates/world/2015_11_09_02_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_02_world_335.sql diff --git a/sql/updates/world/2015_11_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_00_world.sql index 6e969f288f1..6e969f288f1 100644 --- a/sql/updates/world/2015_11_10_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_00_world.sql diff --git a/sql/updates/world/2015_11_10_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_01_world.sql index fe9c0b1b8e2..fe9c0b1b8e2 100644 --- a/sql/updates/world/2015_11_10_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_01_world.sql diff --git a/sql/updates/world/2015_11_10_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_02_world.sql index 8ff255defa4..8ff255defa4 100644 --- a/sql/updates/world/2015_11_10_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_02_world.sql diff --git a/sql/updates/world/2015_11_11_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_00_world.sql index 07393641f3f..07393641f3f 100644 --- a/sql/updates/world/2015_11_11_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_00_world.sql diff --git a/sql/updates/world/2015_11_11_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_01_world.sql index 3c1ce85ec17..3c1ce85ec17 100644 --- a/sql/updates/world/2015_11_11_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_01_world.sql diff --git a/sql/updates/world/2015_11_12_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_00_world.sql index 79c2461e5ff..79c2461e5ff 100644 --- a/sql/updates/world/2015_11_12_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_00_world.sql diff --git a/sql/updates/world/2015_11_12_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_01_world.sql index c08ebda2471..c08ebda2471 100644 --- a/sql/updates/world/2015_11_12_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_01_world.sql diff --git a/sql/updates/world/2015_11_20_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_20_00_world.sql index 7c5fe7ea426..7c5fe7ea426 100644 --- a/sql/updates/world/2015_11_20_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_20_00_world.sql diff --git a/sql/updates/world/2015_11_22_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_00_world.sql index 2b70a2c97b6..2b70a2c97b6 100644 --- a/sql/updates/world/2015_11_22_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_00_world.sql diff --git a/sql/updates/world/2015_11_22_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_01_world.sql index ba63c72ba16..ba63c72ba16 100644 --- a/sql/updates/world/2015_11_22_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_01_world.sql diff --git a/sql/updates/world/2015_11_22_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_02_world.sql index 7fcbc7ec9aa..7fcbc7ec9aa 100644 --- a/sql/updates/world/2015_11_22_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_02_world.sql diff --git a/sql/updates/world/2015_11_22_03_world_355.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_03_world_355.sql index 9bf71a146d0..9bf71a146d0 100644 --- a/sql/updates/world/2015_11_22_03_world_355.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_03_world_355.sql diff --git a/sql/updates/world/2015_11_23_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_00_world_335.sql index fffc4531e5e..fffc4531e5e 100644 --- a/sql/updates/world/2015_11_23_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_00_world_335.sql diff --git a/sql/updates/world/2015_11_23_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_01_world_335.sql index 8432c2d14fd..8432c2d14fd 100644 --- a/sql/updates/world/2015_11_23_01_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_01_world_335.sql diff --git a/sql/updates/world/2015_11_23_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_02_world_335.sql index ba569d1420f..ba569d1420f 100644 --- a/sql/updates/world/2015_11_23_02_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_02_world_335.sql diff --git a/sql/updates/world/2015_11_23_03_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_03_world_335.sql index 9ef011f551e..9ef011f551e 100644 --- a/sql/updates/world/2015_11_23_03_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_03_world_335.sql diff --git a/sql/updates/world/2015_11_23_04_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_04_world_335.sql index 845eefeb7ca..845eefeb7ca 100644 --- a/sql/updates/world/2015_11_23_04_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_04_world_335.sql diff --git a/sql/updates/world/2015_11_23_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_05_world.sql index 579af5a5ca1..579af5a5ca1 100644 --- a/sql/updates/world/2015_11_23_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_05_world.sql diff --git a/sql/updates/world/2015_11_24_00_world_355.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_24_00_world_355.sql index 0983d03e649..0983d03e649 100644 --- a/sql/updates/world/2015_11_24_00_world_355.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_24_00_world_355.sql diff --git a/sql/updates/world/2015_11_27_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_27_00_world.sql index 632dec537dd..632dec537dd 100644 --- a/sql/updates/world/2015_11_27_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_27_00_world.sql diff --git a/sql/updates/world/2015_11_28_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_00_world.sql index 0a1dd574fb4..0a1dd574fb4 100644 --- a/sql/updates/world/2015_11_28_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_00_world.sql diff --git a/sql/updates/world/2015_11_28_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_01_world_335.sql index 4bec178ecee..4bec178ecee 100644 --- a/sql/updates/world/2015_11_28_01_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_01_world_335.sql diff --git a/sql/updates/world/2015_11_29_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_00_world.sql index fd64b65bd02..fd64b65bd02 100644 --- a/sql/updates/world/2015_11_29_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_00_world.sql diff --git a/sql/updates/world/2015_11_29_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_01_world.sql index cd46800c5dd..cd46800c5dd 100644 --- a/sql/updates/world/2015_11_29_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_01_world.sql diff --git a/sql/updates/world/2015_12_01_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_01_00_world.sql index 1572245a517..1572245a517 100644 --- a/sql/updates/world/2015_12_01_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_01_00_world.sql diff --git a/sql/updates/world/2015_12_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_04_00_world.sql index ee721273bef..ee721273bef 100644 --- a/sql/updates/world/2015_12_04_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_04_00_world.sql diff --git a/sql/updates/world/2015_12_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_05_00_world.sql index c2c90164a4f..c2c90164a4f 100644 --- a/sql/updates/world/2015_12_05_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_05_00_world.sql diff --git a/sql/updates/world/2015_12_06_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_06_00_world.sql index b60d4d3e88c..b60d4d3e88c 100644 --- a/sql/updates/world/2015_12_06_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_06_00_world.sql diff --git a/sql/updates/world/2015_12_08_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_00_world_335.sql index e742130b1a4..e742130b1a4 100644 --- a/sql/updates/world/2015_12_08_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_00_world_335.sql diff --git a/sql/updates/world/2015_12_08_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_01_world.sql index 9e24acd91db..9e24acd91db 100644 --- a/sql/updates/world/2015_12_08_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_01_world.sql diff --git a/sql/updates/world/2015_12_08_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_02_world.sql index 375d0941adb..375d0941adb 100644 --- a/sql/updates/world/2015_12_08_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_02_world.sql diff --git a/sql/updates/world/2015_12_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_00_world.sql index 6ac4da31404..6ac4da31404 100644 --- a/sql/updates/world/2015_12_09_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_00_world.sql diff --git a/sql/updates/world/2015_12_09_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_01_world.sql index d27bc7ff49a..d27bc7ff49a 100644 --- a/sql/updates/world/2015_12_09_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_01_world.sql diff --git a/sql/updates/world/2015_12_11_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_11_00_world.sql index dc5fd8c40b6..dc5fd8c40b6 100644 --- a/sql/updates/world/2015_12_11_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_11_00_world.sql diff --git a/sql/updates/world/2015_12_14_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_14_00_world.sql index 85faf4448e2..85faf4448e2 100644 --- a/sql/updates/world/2015_12_14_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_14_00_world.sql diff --git a/sql/updates/world/2015_12_15_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_00_world.sql index f27bb448bbd..f27bb448bbd 100644 --- a/sql/updates/world/2015_12_15_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_00_world.sql diff --git a/sql/updates/world/2015_12_15_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_01_world.sql index 86fbec83c38..86fbec83c38 100644 --- a/sql/updates/world/2015_12_15_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_01_world.sql diff --git a/sql/updates/world/2015_12_15_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_02_world.sql index eda5c26550f..eda5c26550f 100644 --- a/sql/updates/world/2015_12_15_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_02_world.sql diff --git a/sql/updates/world/2015_12_15_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_03_world.sql index 99cc9e14646..99cc9e14646 100644 --- a/sql/updates/world/2015_12_15_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_03_world.sql diff --git a/sql/updates/world/2015_12_16_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_00_world.sql index 62d640117f7..62d640117f7 100644 --- a/sql/updates/world/2015_12_16_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_00_world.sql diff --git a/sql/updates/world/2015_12_16_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_01_world.sql index 73c9675e5be..73c9675e5be 100644 --- a/sql/updates/world/2015_12_16_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_01_world.sql diff --git a/sql/updates/world/2015_12_16_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_02_world_335.sql index 20c1ac94a39..20c1ac94a39 100644 --- a/sql/updates/world/2015_12_16_02_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_02_world_335.sql diff --git a/sql/updates/world/2015_12_17_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_17_00_world.sql index 8419473b203..8419473b203 100644 --- a/sql/updates/world/2015_12_17_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_17_00_world.sql diff --git a/sql/updates/world/2015_12_18_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_00_world_335.sql index 3fb3e5a6e1e..3fb3e5a6e1e 100644 --- a/sql/updates/world/2015_12_18_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_00_world_335.sql diff --git a/sql/updates/world/2015_12_18_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_01_world.sql index 2ccc93def23..2ccc93def23 100644 --- a/sql/updates/world/2015_12_18_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_01_world.sql diff --git a/sql/updates/world/2015_12_18_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_02_world.sql index f590d18a8ab..f590d18a8ab 100644 --- a/sql/updates/world/2015_12_18_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_02_world.sql diff --git a/sql/updates/world/2015_12_18_03_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_03_world_335.sql index de778343a0e..de778343a0e 100644 --- a/sql/updates/world/2015_12_18_03_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_03_world_335.sql diff --git a/sql/updates/world/2015_12_18_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_04_world.sql index c8c3352319c..c8c3352319c 100644 --- a/sql/updates/world/2015_12_18_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_04_world.sql diff --git a/sql/updates/world/2015_12_20_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_20_00_world.sql index 7c658877f13..7c658877f13 100644 --- a/sql/updates/world/2015_12_20_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_20_00_world.sql diff --git a/sql/updates/world/2015_12_24_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_24_00_world.sql index 52d83bb63c3..52d83bb63c3 100644 --- a/sql/updates/world/2015_12_24_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_24_00_world.sql diff --git a/sql/updates/world/2015_12_26_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_00_world.sql index 02c0acbedae..02c0acbedae 100644 --- a/sql/updates/world/2015_12_26_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_00_world.sql diff --git a/sql/updates/world/2015_12_26_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_01_world.sql index 92a9d21af25..92a9d21af25 100644 --- a/sql/updates/world/2015_12_26_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_01_world.sql diff --git a/sql/updates/world/2015_12_26_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_02_world.sql index 021dec0be80..021dec0be80 100644 --- a/sql/updates/world/2015_12_26_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_02_world.sql diff --git a/sql/updates/world/2015_12_29_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_00_world.sql index da6de123190..da6de123190 100644 --- a/sql/updates/world/2015_12_29_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_00_world.sql diff --git a/sql/updates/world/2015_12_29_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_01_world.sql index 24b201b4d06..24b201b4d06 100644 --- a/sql/updates/world/2015_12_29_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_01_world.sql diff --git a/sql/updates/world/2015_12_29_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_02_world.sql index 3bfd0ba2a25..3bfd0ba2a25 100644 --- a/sql/updates/world/2015_12_29_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_02_world.sql diff --git a/sql/updates/world/2015_12_29_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_03_world.sql index f928061c269..f928061c269 100644 --- a/sql/updates/world/2015_12_29_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_03_world.sql diff --git a/sql/updates/world/2015_12_29_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_04_world.sql index 22a1ee3edcf..22a1ee3edcf 100644 --- a/sql/updates/world/2015_12_29_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_04_world.sql diff --git a/sql/updates/world/2015_12_29_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_05_world.sql index 056ea4fe230..056ea4fe230 100644 --- a/sql/updates/world/2015_12_29_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_05_world.sql diff --git a/sql/updates/world/2015_12_29_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_06_world.sql index 167c4c23005..167c4c23005 100644 --- a/sql/updates/world/2015_12_29_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_06_world.sql diff --git a/sql/updates/world/2015_12_29_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_07_world.sql index ec71d28c787..ec71d28c787 100644 --- a/sql/updates/world/2015_12_29_07_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_07_world.sql diff --git a/sql/updates/world/2015_12_29_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_08_world.sql index ce874d7a8d2..ce874d7a8d2 100644 --- a/sql/updates/world/2015_12_29_08_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_08_world.sql diff --git a/sql/updates/world/2015_12_29_09_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_09_world.sql index d57785e8d88..d57785e8d88 100644 --- a/sql/updates/world/2015_12_29_09_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_09_world.sql diff --git a/sql/updates/world/2015_12_29_10_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_10_world.sql index 919309dd558..919309dd558 100644 --- a/sql/updates/world/2015_12_29_10_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_10_world.sql diff --git a/sql/updates/world/2015_12_29_11_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_11_world.sql index 930baf15f78..930baf15f78 100644 --- a/sql/updates/world/2015_12_29_11_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_11_world.sql diff --git a/sql/updates/world/2015_12_29_12_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_12_world.sql index c065e1d6a18..c065e1d6a18 100644 --- a/sql/updates/world/2015_12_29_12_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_12_world.sql diff --git a/sql/updates/world/2015_12_29_13_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_13_world.sql index fc182ae49fb..fc182ae49fb 100644 --- a/sql/updates/world/2015_12_29_13_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_13_world.sql diff --git a/sql/updates/world/2015_12_31_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_00_world.sql index b7c310323ed..b7c310323ed 100644 --- a/sql/updates/world/2015_12_31_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_00_world.sql diff --git a/sql/updates/world/2015_12_31_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_01_world.sql index 3bee62963ef..3bee62963ef 100644 --- a/sql/updates/world/2015_12_31_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_01_world.sql diff --git a/sql/updates/world/2016_01_01_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_00_world.sql index 38991837113..38991837113 100644 --- a/sql/updates/world/2016_01_01_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_00_world.sql diff --git a/sql/updates/world/2016_01_01_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_01_world.sql index 025f2c07f9c..025f2c07f9c 100644 --- a/sql/updates/world/2016_01_01_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_01_world.sql diff --git a/sql/updates/world/2016_01_02_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_00_world_335.sql index b46a41bc6e9..b46a41bc6e9 100644 --- a/sql/updates/world/2016_01_02_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_00_world_335.sql diff --git a/sql/updates/world/2016_01_02_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_01_world.sql index b862cc0e644..b862cc0e644 100644 --- a/sql/updates/world/2016_01_02_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_01_world.sql diff --git a/sql/updates/world/2016_01_03_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_00_world_335.sql index 658b180a41a..658b180a41a 100644 --- a/sql/updates/world/2016_01_03_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_00_world_335.sql diff --git a/sql/updates/world/2016_01_03_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_01_world.sql index 3ddb56a9c72..3ddb56a9c72 100644 --- a/sql/updates/world/2016_01_03_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_01_world.sql diff --git a/sql/updates/world/2016_01_03_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_02_world.sql index 79eba012e41..79eba012e41 100644 --- a/sql/updates/world/2016_01_03_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_02_world.sql diff --git a/sql/updates/world/2016_01_03_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_03_world.sql index 1b1766ee557..1b1766ee557 100644 --- a/sql/updates/world/2016_01_03_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_03_world.sql diff --git a/sql/updates/world/2016_01_03_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_04_world.sql index ffe8eb07fd5..ffe8eb07fd5 100644 --- a/sql/updates/world/2016_01_03_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_04_world.sql diff --git a/sql/updates/world/2016_01_03_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_05_world.sql index 4c2fe0817f0..4c2fe0817f0 100644 --- a/sql/updates/world/2016_01_03_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_05_world.sql diff --git a/sql/updates/world/2016_01_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_04_00_world.sql index 57236a6f66e..57236a6f66e 100644 --- a/sql/updates/world/2016_01_04_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_04_00_world.sql diff --git a/sql/updates/world/2016_01_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_00_world.sql index 3f7f01449fc..3f7f01449fc 100644 --- a/sql/updates/world/2016_01_05_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_00_world.sql diff --git a/sql/updates/world/2016_01_05_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_01_world.sql index dc1064a75b9..dc1064a75b9 100644 --- a/sql/updates/world/2016_01_05_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_01_world.sql diff --git a/sql/updates/world/2016_01_05_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_02_world.sql index 64909129e60..64909129e60 100644 --- a/sql/updates/world/2016_01_05_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_02_world.sql diff --git a/sql/updates/world/2016_01_07_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_00_world.sql index d36dda80e50..d36dda80e50 100644 --- a/sql/updates/world/2016_01_07_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_00_world.sql diff --git a/sql/updates/world/2016_01_07_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_01_world.sql index 4a15aa405ec..4a15aa405ec 100644 --- a/sql/updates/world/2016_01_07_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_01_world.sql diff --git a/sql/updates/world/2016_01_07_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_02_world.sql index 7724b42ac9d..7724b42ac9d 100644 --- a/sql/updates/world/2016_01_07_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_02_world.sql diff --git a/sql/updates/world/2016_01_08_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_00_world.sql index 55ed3ddf336..55ed3ddf336 100644 --- a/sql/updates/world/2016_01_08_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_00_world.sql diff --git a/sql/updates/world/2016_01_08_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_01_world.sql index ebf4560d326..ebf4560d326 100644 --- a/sql/updates/world/2016_01_08_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_01_world.sql diff --git a/sql/updates/world/2016_01_08_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_02_world.sql index 28e55dfba3b..28e55dfba3b 100644 --- a/sql/updates/world/2016_01_08_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_02_world.sql diff --git a/sql/updates/world/2016_01_08_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_03_world.sql index 2899c6e06eb..2899c6e06eb 100644 --- a/sql/updates/world/2016_01_08_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_03_world.sql diff --git a/sql/updates/world/2016_01_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_09_00_world.sql index 534e17ccb00..534e17ccb00 100644 --- a/sql/updates/world/2016_01_09_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_09_00_world.sql diff --git a/sql/updates/world/2016_01_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_00_world.sql index 83ed21c8489..83ed21c8489 100644 --- a/sql/updates/world/2016_01_10_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_00_world.sql diff --git a/sql/updates/world/2016_01_10_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_01_world.sql index c79c157a1a1..c79c157a1a1 100644 --- a/sql/updates/world/2016_01_10_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_01_world.sql diff --git a/sql/updates/world/2016_01_10_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_02_world.sql index eca8ef07849..eca8ef07849 100644 --- a/sql/updates/world/2016_01_10_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_02_world.sql diff --git a/sql/updates/world/2016_01_10_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_03_world.sql index 5ac352ffe10..5ac352ffe10 100644 --- a/sql/updates/world/2016_01_10_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_03_world.sql diff --git a/sql/updates/world/2016_01_10_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_04_world.sql index da6eed191ad..da6eed191ad 100644 --- a/sql/updates/world/2016_01_10_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_04_world.sql diff --git a/sql/updates/world/2016_01_10_05_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_05_world_335.sql index 7fb021cc9dd..7fb021cc9dd 100644 --- a/sql/updates/world/2016_01_10_05_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_05_world_335.sql diff --git a/sql/updates/world/2016_01_12_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_00_world.sql index 8ed4099450b..8ed4099450b 100644 --- a/sql/updates/world/2016_01_12_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_00_world.sql diff --git a/sql/updates/world/2016_01_12_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_01_world_335.sql index c3206e70ac4..c3206e70ac4 100644 --- a/sql/updates/world/2016_01_12_01_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_01_world_335.sql diff --git a/sql/updates/world/2016_01_12_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_02_world_335.sql index 354d0bc129d..354d0bc129d 100644 --- a/sql/updates/world/2016_01_12_02_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_02_world_335.sql diff --git a/sql/updates/world/2016_01_12_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_03_world.sql index 6ff3a769918..6ff3a769918 100644 --- a/sql/updates/world/2016_01_12_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_03_world.sql diff --git a/sql/updates/world/2016_01_12_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_04_world.sql index 7cee9220060..7cee9220060 100644 --- a/sql/updates/world/2016_01_12_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_04_world.sql diff --git a/sql/updates/world/2016_01_13_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_13_00_world.sql index cba5d3a18a1..cba5d3a18a1 100644 --- a/sql/updates/world/2016_01_13_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_13_00_world.sql diff --git a/sql/updates/world/2016_01_15_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_15_00_world.sql index b5f3da2dd99..b5f3da2dd99 100644 --- a/sql/updates/world/2016_01_15_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_15_00_world.sql diff --git a/sql/updates/world/2016_01_16_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_00_world_335.sql index 14362432555..14362432555 100644 --- a/sql/updates/world/2016_01_16_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_00_world_335.sql diff --git a/sql/updates/world/2016_01_16_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_01_world.sql index 235378a7a84..235378a7a84 100644 --- a/sql/updates/world/2016_01_16_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_01_world.sql diff --git a/sql/updates/world/2016_01_16_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_02_world.sql index b36d7d69ff6..b36d7d69ff6 100644 --- a/sql/updates/world/2016_01_16_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_02_world.sql diff --git a/sql/updates/world/2016_01_16_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_03_world.sql index 5a06cfaecca..5a06cfaecca 100644 --- a/sql/updates/world/2016_01_16_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_03_world.sql diff --git a/sql/updates/world/2016_01_16_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_04_world.sql index a6bb7ae185c..a6bb7ae185c 100644 --- a/sql/updates/world/2016_01_16_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_04_world.sql diff --git a/sql/updates/world/2016_01_16_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_05_world.sql index 46511cb0de8..46511cb0de8 100644 --- a/sql/updates/world/2016_01_16_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_05_world.sql diff --git a/sql/updates/world/2016_01_17_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_00_world_335.sql index abb3579fb07..abb3579fb07 100644 --- a/sql/updates/world/2016_01_17_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_00_world_335.sql diff --git a/sql/updates/world/2016_01_17_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_01_world.sql index 8e5bcd22a07..8e5bcd22a07 100644 --- a/sql/updates/world/2016_01_17_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_01_world.sql diff --git a/sql/updates/world/2016_01_17_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_02_world.sql index f019b927228..f019b927228 100644 --- a/sql/updates/world/2016_01_17_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_02_world.sql diff --git a/sql/updates/world/2016_01_17_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_03_world.sql index cf43c650888..cf43c650888 100644 --- a/sql/updates/world/2016_01_17_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_03_world.sql diff --git a/sql/updates/world/2016_01_17_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_04_world.sql index 6d72807e0b1..6d72807e0b1 100644 --- a/sql/updates/world/2016_01_17_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_04_world.sql diff --git a/sql/updates/world/2016_01_17_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_05_world.sql index 2d253bae713..2d253bae713 100644 --- a/sql/updates/world/2016_01_17_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_05_world.sql diff --git a/sql/updates/world/2016_01_17_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_06_world.sql index 659f146845a..659f146845a 100644 --- a/sql/updates/world/2016_01_17_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_06_world.sql diff --git a/sql/updates/world/2016_01_17_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_07_world.sql index df588168d38..df588168d38 100644 --- a/sql/updates/world/2016_01_17_07_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_07_world.sql diff --git a/sql/updates/world/2016_01_17_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_08_world.sql index 48cd420a242..48cd420a242 100644 --- a/sql/updates/world/2016_01_17_08_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_08_world.sql diff --git a/sql/updates/world/2016_01_17_09_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_09_world.sql index 85e6f535866..85e6f535866 100644 --- a/sql/updates/world/2016_01_17_09_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_09_world.sql diff --git a/sql/updates/world/2016_01_17_10_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_10_world.sql index 0fdc04eb60f..0fdc04eb60f 100644 --- a/sql/updates/world/2016_01_17_10_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_10_world.sql diff --git a/sql/updates/world/2016_01_17_11_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_11_world.sql index 9ab963a2ff2..9ab963a2ff2 100644 --- a/sql/updates/world/2016_01_17_11_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_11_world.sql diff --git a/sql/updates/world/2016_01_17_12_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_12_world.sql index e4e8ab5e9e2..e4e8ab5e9e2 100644 --- a/sql/updates/world/2016_01_17_12_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_12_world.sql diff --git a/sql/updates/world/2016_01_17_13_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_13_world.sql index 163aa3fb659..163aa3fb659 100644 --- a/sql/updates/world/2016_01_17_13_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_13_world.sql diff --git a/sql/updates/world/2016_01_17_14_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_14_world.sql index c8b9405abff..c8b9405abff 100644 --- a/sql/updates/world/2016_01_17_14_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_14_world.sql diff --git a/sql/updates/world/2016_01_17_15_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_15_world.sql index da949d7100d..da949d7100d 100644 --- a/sql/updates/world/2016_01_17_15_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_15_world.sql diff --git a/sql/updates/world/2016_01_18_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_00_world.sql index 85f41cfc0c5..85f41cfc0c5 100644 --- a/sql/updates/world/2016_01_18_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_00_world.sql diff --git a/sql/updates/world/2016_01_18_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_01_world.sql index 9768ecda6c0..9768ecda6c0 100644 --- a/sql/updates/world/2016_01_18_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_01_world.sql diff --git a/sql/updates/world/2016_01_18_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_02_world.sql index ec9a8748cc8..ec9a8748cc8 100644 --- a/sql/updates/world/2016_01_18_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_02_world.sql diff --git a/sql/updates/world/2016_01_18_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_03_world.sql index 4b8eb4ae0c9..4b8eb4ae0c9 100644 --- a/sql/updates/world/2016_01_18_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_03_world.sql diff --git a/sql/updates/world/2016_01_18_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_04_world.sql index 28ab2d96731..28ab2d96731 100644 --- a/sql/updates/world/2016_01_18_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_04_world.sql diff --git a/sql/updates/world/2016_01_18_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_05_world.sql index 0d28cd17642..0d28cd17642 100644 --- a/sql/updates/world/2016_01_18_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_05_world.sql diff --git a/sql/updates/world/2016_01_18_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_06_world.sql index f8b90c15f54..f8b90c15f54 100644 --- a/sql/updates/world/2016_01_18_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_06_world.sql diff --git a/sql/updates/world/2016_01_19_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_00_world.sql index f210b95c13a..f210b95c13a 100644 --- a/sql/updates/world/2016_01_19_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_00_world.sql diff --git a/sql/updates/world/2016_01_19_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_01_world.sql index a10bc7e278f..a10bc7e278f 100644 --- a/sql/updates/world/2016_01_19_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_01_world.sql diff --git a/sql/updates/world/2016_01_19_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_02_world.sql index 7c71156b248..7c71156b248 100644 --- a/sql/updates/world/2016_01_19_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_02_world.sql diff --git a/sql/updates/world/2016_01_19_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_03_world.sql index 0d559ace044..0d559ace044 100644 --- a/sql/updates/world/2016_01_19_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_03_world.sql diff --git a/sql/updates/world/2016_01_19_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_04_world.sql index f4fe95f5539..f4fe95f5539 100644 --- a/sql/updates/world/2016_01_19_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_04_world.sql diff --git a/sql/updates/world/2016_01_19_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_05_world.sql index 5afd9e2b8a5..5afd9e2b8a5 100644 --- a/sql/updates/world/2016_01_19_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_05_world.sql diff --git a/sql/updates/world/2016_01_19_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_06_world.sql index cece0c623bf..cece0c623bf 100644 --- a/sql/updates/world/2016_01_19_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_06_world.sql diff --git a/sql/updates/world/2016_01_19_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_07_world.sql index e1a72398a5f..e1a72398a5f 100644 --- a/sql/updates/world/2016_01_19_07_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_07_world.sql diff --git a/sql/updates/world/2016_01_19_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_08_world.sql index d078c059201..d078c059201 100644 --- a/sql/updates/world/2016_01_19_08_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_08_world.sql diff --git a/sql/updates/world/2016_01_20_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_00_world.sql index 26ce069edd8..26ce069edd8 100644 --- a/sql/updates/world/2016_01_20_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_00_world.sql diff --git a/sql/updates/world/2016_01_20_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_01_world.sql index b1c6e0de756..b1c6e0de756 100644 --- a/sql/updates/world/2016_01_20_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_01_world.sql diff --git a/sql/updates/world/2016_01_20_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_02_world.sql index d026c3cb478..d026c3cb478 100644 --- a/sql/updates/world/2016_01_20_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_02_world.sql diff --git a/sql/updates/world/2016_01_23_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_23_00_world.sql index 02eaa7c370d..02eaa7c370d 100644 --- a/sql/updates/world/2016_01_23_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_23_00_world.sql diff --git a/sql/updates/world/2016_01_24_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_24_00_world.sql index a28b3fa25b8..a28b3fa25b8 100644 --- a/sql/updates/world/2016_01_24_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_24_00_world.sql diff --git a/sql/updates/world/2016_01_26_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_26_00_world.sql index 71fe8dc21e3..71fe8dc21e3 100644 --- a/sql/updates/world/2016_01_26_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_26_00_world.sql diff --git a/sql/updates/world/2016_01_28_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_00_world_335.sql index 64b32cb2d89..64b32cb2d89 100644 --- a/sql/updates/world/2016_01_28_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_00_world_335.sql diff --git a/sql/updates/world/2016_01_28_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_01_world.sql index 3c4cadb310d..3c4cadb310d 100644 --- a/sql/updates/world/2016_01_28_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_01_world.sql diff --git a/sql/updates/world/2016_01_30_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_00_world_335.sql index 43025f581d7..43025f581d7 100644 --- a/sql/updates/world/2016_01_30_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_00_world_335.sql diff --git a/sql/updates/world/2016_01_30_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_01_world.sql index c9405c4ee61..c9405c4ee61 100644 --- a/sql/updates/world/2016_01_30_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_01_world.sql diff --git a/sql/updates/world/2016_01_30_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_02_world.sql index 25325dddd7a..25325dddd7a 100644 --- a/sql/updates/world/2016_01_30_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_02_world.sql diff --git a/sql/updates/world/2016_01_30_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_03_world.sql index 06c4b0826c0..06c4b0826c0 100644 --- a/sql/updates/world/2016_01_30_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_03_world.sql diff --git a/sql/updates/world/2016_01_30_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_04_world.sql index b90e7b95810..b90e7b95810 100644 --- a/sql/updates/world/2016_01_30_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_04_world.sql diff --git a/sql/updates/world/2016_01_30_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_05_world.sql index 1e341506dfc..1e341506dfc 100644 --- a/sql/updates/world/2016_01_30_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_05_world.sql diff --git a/sql/updates/world/2016_01_31_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_31_00_world.sql index f64d9182784..f64d9182784 100644 --- a/sql/updates/world/2016_01_31_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_31_00_world.sql diff --git a/sql/updates/world/2016_02_02_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_00_world.sql index ce561af3a61..ce561af3a61 100644 --- a/sql/updates/world/2016_02_02_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_00_world.sql diff --git a/sql/updates/world/2016_02_02_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_01_world.sql index f1b181a29e3..f1b181a29e3 100644 --- a/sql/updates/world/2016_02_02_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_01_world.sql diff --git a/sql/updates/world/2016_02_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_04_00_world.sql index 758286544af..758286544af 100644 --- a/sql/updates/world/2016_02_04_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_04_00_world.sql diff --git a/sql/updates/world/2016_02_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_05_00_world.sql index 46f2b488b9a..46f2b488b9a 100644 --- a/sql/updates/world/2016_02_05_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_05_00_world.sql diff --git a/sql/updates/world/2016_02_06_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_00_world.sql index d303a8b5b85..d303a8b5b85 100644 --- a/sql/updates/world/2016_02_06_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_00_world.sql diff --git a/sql/updates/world/2016_02_06_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_01_world.sql index 6812c4af52e..6812c4af52e 100644 --- a/sql/updates/world/2016_02_06_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_01_world.sql diff --git a/sql/updates/world/2016_02_06_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_02_world.sql index b9fd7cd9d63..b9fd7cd9d63 100644 --- a/sql/updates/world/2016_02_06_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_02_world.sql diff --git a/sql/updates/world/2016_02_06_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_03_world.sql index 85f8d3c6ae7..85f8d3c6ae7 100644 --- a/sql/updates/world/2016_02_06_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_03_world.sql diff --git a/sql/updates/world/2016_02_06_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_04_world.sql index 188b3b5f2a7..188b3b5f2a7 100644 --- a/sql/updates/world/2016_02_06_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_04_world.sql diff --git a/sql/updates/world/2016_02_06_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_05_world.sql index 823a8abaca6..823a8abaca6 100644 --- a/sql/updates/world/2016_02_06_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_05_world.sql diff --git a/sql/updates/world/2016_02_06_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_06_world.sql index 37df2ef0868..37df2ef0868 100644 --- a/sql/updates/world/2016_02_06_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_06_world.sql diff --git a/sql/updates/world/2016_02_06_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_07_world.sql index c5d6434321a..c5d6434321a 100644 --- a/sql/updates/world/2016_02_06_07_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_07_world.sql diff --git a/sql/updates/world/2016_02_06_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_08_world.sql index f0855ba348a..f0855ba348a 100644 --- a/sql/updates/world/2016_02_06_08_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_08_world.sql diff --git a/sql/updates/world/2016_02_06_09_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_09_world.sql index bf92b89e1c2..bf92b89e1c2 100644 --- a/sql/updates/world/2016_02_06_09_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_09_world.sql diff --git a/sql/updates/world/2016_02_06_10_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_10_world.sql index 291bd0bb333..291bd0bb333 100644 --- a/sql/updates/world/2016_02_06_10_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_10_world.sql diff --git a/sql/updates/world/2016_02_06_11_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_11_world.sql index cea352fec36..cea352fec36 100644 --- a/sql/updates/world/2016_02_06_11_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_11_world.sql diff --git a/sql/updates/world/2016_02_06_12_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_12_world.sql index df550156bc1..df550156bc1 100644 --- a/sql/updates/world/2016_02_06_12_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_12_world.sql diff --git a/sql/updates/world/2016_02_06_13_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_13_world_335.sql index 22bd5596d98..22bd5596d98 100644 --- a/sql/updates/world/2016_02_06_13_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_13_world_335.sql diff --git a/sql/updates/world/2016_02_06_14_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_14_world.sql index 7bf05b61c71..7bf05b61c71 100644 --- a/sql/updates/world/2016_02_06_14_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_14_world.sql diff --git a/sql/updates/world/2016_02_07_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_00_world.sql index 5a49f8fd310..5a49f8fd310 100644 --- a/sql/updates/world/2016_02_07_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_00_world.sql diff --git a/sql/updates/world/2016_02_07_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_01_world_335.sql index 5f1d5f4280e..5f1d5f4280e 100644 --- a/sql/updates/world/2016_02_07_01_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_01_world_335.sql diff --git a/sql/updates/world/2016_02_07_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_02_world_335.sql index ea4608f3a6b..ea4608f3a6b 100644 --- a/sql/updates/world/2016_02_07_02_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_02_world_335.sql diff --git a/sql/updates/world/2016_02_07_03_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_03_world_335.sql index 8322ff59c4c..8322ff59c4c 100644 --- a/sql/updates/world/2016_02_07_03_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_03_world_335.sql diff --git a/sql/updates/world/2016_02_07_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_04_world.sql index 3a3a7a393d7..3a3a7a393d7 100644 --- a/sql/updates/world/2016_02_07_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_04_world.sql diff --git a/sql/updates/world/2016_02_07_05_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_05_world_335.sql index 794b3d80411..794b3d80411 100644 --- a/sql/updates/world/2016_02_07_05_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_05_world_335.sql diff --git a/sql/updates/world/2016_02_07_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_06_world.sql index 31ecf826660..31ecf826660 100644 --- a/sql/updates/world/2016_02_07_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_06_world.sql diff --git a/sql/updates/world/2016_02_07_07_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_07_world_335.sql index af323a47bda..af323a47bda 100644 --- a/sql/updates/world/2016_02_07_07_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_07_world_335.sql diff --git a/sql/updates/world/2016_02_07_08_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_08_world_335.sql index 2b78a317f95..2b78a317f95 100644 --- a/sql/updates/world/2016_02_07_08_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_08_world_335.sql diff --git a/sql/updates/world/2016_02_07_09_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_09_world.sql index 8057534fbb8..8057534fbb8 100644 --- a/sql/updates/world/2016_02_07_09_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_09_world.sql diff --git a/sql/updates/world/2016_02_07_10_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_10_world.sql index c2e59c15d9c..c2e59c15d9c 100644 --- a/sql/updates/world/2016_02_07_10_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_10_world.sql diff --git a/sql/updates/world/2016_02_07_11_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_11_world.sql index c40b663c205..c40b663c205 100644 --- a/sql/updates/world/2016_02_07_11_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_11_world.sql diff --git a/sql/updates/world/2016_02_07_12_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_12_world.sql index c85265d857d..c85265d857d 100644 --- a/sql/updates/world/2016_02_07_12_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_12_world.sql diff --git a/sql/updates/world/2016_02_07_13_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_13_world.sql index 612fef2274d..612fef2274d 100644 --- a/sql/updates/world/2016_02_07_13_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_13_world.sql diff --git a/sql/updates/world/2016_02_07_14_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_14_world.sql index 6550e53f9c9..6550e53f9c9 100644 --- a/sql/updates/world/2016_02_07_14_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_14_world.sql diff --git a/sql/updates/world/2016_02_07_15_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_15_world.sql index ceec02f881b..ceec02f881b 100644 --- a/sql/updates/world/2016_02_07_15_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_15_world.sql diff --git a/sql/updates/world/2016_02_08_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_00_world_335.sql index 83091035e3c..83091035e3c 100644 --- a/sql/updates/world/2016_02_08_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_00_world_335.sql diff --git a/sql/updates/world/2016_02_08_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_01_world.sql index 9f8fa3dc4ed..9f8fa3dc4ed 100644 --- a/sql/updates/world/2016_02_08_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_01_world.sql diff --git a/sql/updates/world/2016_02_08_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_02_world.sql index 0f22abafe8e..0f22abafe8e 100644 --- a/sql/updates/world/2016_02_08_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_02_world.sql diff --git a/sql/updates/world/2016_02_08_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_03_world.sql index fe429cf42c8..fe429cf42c8 100644 --- a/sql/updates/world/2016_02_08_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_03_world.sql diff --git a/sql/updates/world/2016_02_08_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_04_world.sql index f8a9e2c776a..f8a9e2c776a 100644 --- a/sql/updates/world/2016_02_08_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_04_world.sql diff --git a/sql/updates/world/2016_02_08_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_05_world.sql index d2cc597a6ac..d2cc597a6ac 100644 --- a/sql/updates/world/2016_02_08_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_05_world.sql diff --git a/sql/updates/world/2016_02_08_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_06_world.sql index c9e93889790..c9e93889790 100644 --- a/sql/updates/world/2016_02_08_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_06_world.sql diff --git a/sql/updates/world/2016_02_08_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_07_world.sql index 1d90630d829..1d90630d829 100644 --- a/sql/updates/world/2016_02_08_07_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_07_world.sql diff --git a/sql/updates/world/2016_02_08_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_08_world.sql index ae4f454bc91..ae4f454bc91 100644 --- a/sql/updates/world/2016_02_08_08_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_08_world.sql diff --git a/sql/updates/world/2016_02_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_00_world.sql index c93a1d8fed1..c93a1d8fed1 100644 --- a/sql/updates/world/2016_02_09_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_00_world.sql diff --git a/sql/updates/world/2016_02_09_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_01_world.sql index 7878ea7faa2..7878ea7faa2 100644 --- a/sql/updates/world/2016_02_09_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_01_world.sql diff --git a/sql/updates/world/2016_02_09_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world.sql index 891c8c2ff4b..891c8c2ff4b 100644 --- a/sql/updates/world/2016_02_09_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world.sql diff --git a/sql/updates/world/2016_02_09_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world_335.sql index a8612c5d88d..a8612c5d88d 100644 --- a/sql/updates/world/2016_02_09_02_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world_335.sql diff --git a/sql/updates/world/2016_02_09_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_03_world.sql index bd012f0d172..bd012f0d172 100644 --- a/sql/updates/world/2016_02_09_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_03_world.sql diff --git a/sql/updates/world/2016_02_09_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_04_world.sql index 015ab519557..015ab519557 100644 --- a/sql/updates/world/2016_02_09_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_04_world.sql diff --git a/sql/updates/world/2016_02_09_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_05_world.sql index 3612c270d02..3612c270d02 100644 --- a/sql/updates/world/2016_02_09_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_05_world.sql diff --git a/sql/updates/world/2016_02_09_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_06_world.sql index 03fe998cca5..03fe998cca5 100644 --- a/sql/updates/world/2016_02_09_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_06_world.sql diff --git a/sql/updates/world/2016_02_09_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_07_world.sql index 84d65e2eda5..84d65e2eda5 100644 --- a/sql/updates/world/2016_02_09_07_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_07_world.sql diff --git a/sql/updates/world/2016_02_09_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_08_world.sql index 307a9f9a0b3..307a9f9a0b3 100644 --- a/sql/updates/world/2016_02_09_08_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_08_world.sql diff --git a/sql/updates/world/2016_02_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_00_world.sql index 872861b08dc..872861b08dc 100644 --- a/sql/updates/world/2016_02_10_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_00_world.sql diff --git a/sql/updates/world/2016_02_10_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_01_world.sql index 9ffe2e81c1c..9ffe2e81c1c 100644 --- a/sql/updates/world/2016_02_10_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_01_world.sql diff --git a/sql/updates/world/2016_02_10_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_02_world.sql index 92ee165dd83..92ee165dd83 100644 --- a/sql/updates/world/2016_02_10_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_02_world.sql diff --git a/sql/updates/world/2016_02_10_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_03_world.sql index f52872c3431..f52872c3431 100644 --- a/sql/updates/world/2016_02_10_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_03_world.sql diff --git a/sql/updates/world/2016_02_10_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_04_world.sql index 1349b83f442..1349b83f442 100644 --- a/sql/updates/world/2016_02_10_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_04_world.sql diff --git a/sql/updates/world/2016_02_10_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_05_world.sql index c19dd8feb06..c19dd8feb06 100644 --- a/sql/updates/world/2016_02_10_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_05_world.sql diff --git a/sql/updates/world/2016_02_10_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_06_world.sql index 9e24ab31ce1..9e24ab31ce1 100644 --- a/sql/updates/world/2016_02_10_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_06_world.sql diff --git a/sql/updates/world/2016_02_10_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_07_world.sql index 5feb4f44163..5feb4f44163 100644 --- a/sql/updates/world/2016_02_10_07_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_07_world.sql diff --git a/sql/updates/world/2016_02_11_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_00_world.sql index b130133a2ca..b130133a2ca 100644 --- a/sql/updates/world/2016_02_11_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_00_world.sql diff --git a/sql/updates/world/2016_02_11_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_01_world.sql index ec1c98659e1..ec1c98659e1 100644 --- a/sql/updates/world/2016_02_11_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_01_world.sql diff --git a/sql/updates/world/2016_02_11_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_02_world.sql index 9228e2d99d7..9228e2d99d7 100644 --- a/sql/updates/world/2016_02_11_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_02_world.sql diff --git a/sql/updates/world/2016_02_11_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_03_world.sql index 4dfefb12281..4dfefb12281 100644 --- a/sql/updates/world/2016_02_11_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_03_world.sql diff --git a/sql/updates/world/2016_02_11_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_04_world.sql index 41f648b5f6e..41f648b5f6e 100644 --- a/sql/updates/world/2016_02_11_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_04_world.sql diff --git a/sql/updates/world/2016_02_11_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_05_world.sql index 76b59765d08..76b59765d08 100644 --- a/sql/updates/world/2016_02_11_05_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_05_world.sql diff --git a/sql/updates/world/2016_02_11_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_06_world.sql index bbf9880dca9..bbf9880dca9 100644 --- a/sql/updates/world/2016_02_11_06_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_06_world.sql diff --git a/sql/updates/world/2016_02_11_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_07_world.sql index e34106cb44c..e34106cb44c 100644 --- a/sql/updates/world/2016_02_11_07_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_07_world.sql diff --git a/sql/updates/world/2016_02_12_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_12_00_world.sql index af599148e04..af599148e04 100644 --- a/sql/updates/world/2016_02_12_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_12_00_world.sql diff --git a/sql/updates/world/2016_02_13_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_00_world.sql index 2341e33a8b5..2341e33a8b5 100644 --- a/sql/updates/world/2016_02_13_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_00_world.sql diff --git a/sql/updates/world/2016_02_13_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_01_world.sql index 29f94a9f41d..29f94a9f41d 100644 --- a/sql/updates/world/2016_02_13_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_01_world.sql diff --git a/sql/updates/world/2016_02_13_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_02_world.sql index 5a4633fee41..5a4633fee41 100644 --- a/sql/updates/world/2016_02_13_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_02_world.sql diff --git a/sql/updates/world/2016_02_13_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_03_world.sql index 136a068bd9e..136a068bd9e 100644 --- a/sql/updates/world/2016_02_13_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_03_world.sql diff --git a/sql/updates/world/2016_02_13_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_04_world.sql index 83d95745052..83d95745052 100644 --- a/sql/updates/world/2016_02_13_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_04_world.sql diff --git a/sql/updates/world/2016_02_14_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_00_world.sql index 961ecd74d4d..961ecd74d4d 100644 --- a/sql/updates/world/2016_02_14_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_00_world.sql diff --git a/sql/updates/world/2016_02_14_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_01_world.sql index 2ce06020621..2ce06020621 100644 --- a/sql/updates/world/2016_02_14_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_01_world.sql diff --git a/sql/updates/world/2016_02_14_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_02_world.sql index 1459b702cf0..1459b702cf0 100644 --- a/sql/updates/world/2016_02_14_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_02_world.sql diff --git a/sql/updates/world/2016_02_14_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_03_world.sql index 9a0237725c0..9a0237725c0 100644 --- a/sql/updates/world/2016_02_14_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_03_world.sql diff --git a/sql/updates/world/2016_02_14_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_04_world.sql index 58e0aaee311..58e0aaee311 100644 --- a/sql/updates/world/2016_02_14_04_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_04_world.sql diff --git a/sql/updates/world/2016_02_15_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_15_00_world.sql index 43c2ae69382..43c2ae69382 100644 --- a/sql/updates/world/2016_02_15_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_15_00_world.sql diff --git a/sql/updates/world/2016_02_17_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_00_world.sql index 8f22aaa3e4e..8f22aaa3e4e 100644 --- a/sql/updates/world/2016_02_17_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_00_world.sql diff --git a/sql/updates/world/2016_02_17_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_01_world.sql index 20f3605b197..20f3605b197 100644 --- a/sql/updates/world/2016_02_17_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_01_world.sql diff --git a/sql/updates/world/2016_02_17_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_02_world.sql index 6590396b7d9..6590396b7d9 100644 --- a/sql/updates/world/2016_02_17_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_02_world.sql diff --git a/sql/updates/world/2016_02_18_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_00_world.sql index c20196ddc80..c20196ddc80 100644 --- a/sql/updates/world/2016_02_18_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_00_world.sql diff --git a/sql/updates/world/2016_02_18_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_01_world.sql index c3ffdbb6344..c3ffdbb6344 100644 --- a/sql/updates/world/2016_02_18_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_01_world.sql diff --git a/sql/updates/world/2016_02_18_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_02_world.sql index 414c6fd9c3a..414c6fd9c3a 100644 --- a/sql/updates/world/2016_02_18_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_02_world.sql diff --git a/sql/updates/world/2016_02_19_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_00_world.sql index bee93f7bdd4..bee93f7bdd4 100644 --- a/sql/updates/world/2016_02_19_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_00_world.sql diff --git a/sql/updates/world/2016_02_19_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_01_world_335.sql index f7fee657170..f7fee657170 100644 --- a/sql/updates/world/2016_02_19_01_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_01_world_335.sql diff --git a/sql/updates/world/2016_02_22_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_00_world.sql index d92ea91681a..d92ea91681a 100644 --- a/sql/updates/world/2016_02_22_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_00_world.sql diff --git a/sql/updates/world/2016_02_22_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_01_world.sql index b1345bb1aab..b1345bb1aab 100644 --- a/sql/updates/world/2016_02_22_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_01_world.sql diff --git a/sql/updates/world/2016_02_22_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_02_world.sql index dd62e6dce29..dd62e6dce29 100644 --- a/sql/updates/world/2016_02_22_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_02_world.sql diff --git a/sql/updates/world/2016_02_23_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_00_world.sql index 871ce608f1c..871ce608f1c 100644 --- a/sql/updates/world/2016_02_23_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_00_world.sql diff --git a/sql/updates/world/2016_02_23_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_01_world.sql index 0773487dbc7..0773487dbc7 100644 --- a/sql/updates/world/2016_02_23_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_01_world.sql diff --git a/sql/updates/world/2016_02_23_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_02_world.sql index 9e2c550dd65..9e2c550dd65 100644 --- a/sql/updates/world/2016_02_23_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_02_world.sql diff --git a/sql/updates/world/2016_02_24_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_24_00_world.sql index 06c7c29bd72..06c7c29bd72 100644 --- a/sql/updates/world/2016_02_24_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_24_00_world.sql diff --git a/sql/updates/world/2016_02_25_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_00_world.sql index 346c77bee43..346c77bee43 100644 --- a/sql/updates/world/2016_02_25_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_00_world.sql diff --git a/sql/updates/world/2016_02_25_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_01_world_335.sql index 473cbd506ce..473cbd506ce 100644 --- a/sql/updates/world/2016_02_25_01_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_01_world_335.sql diff --git a/sql/updates/world/2016_02_25_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_02_world.sql index c5355b13c29..c5355b13c29 100644 --- a/sql/updates/world/2016_02_25_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_02_world.sql diff --git a/sql/updates/world/2016_02_26_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_00_world.sql index d08d5055089..d08d5055089 100644 --- a/sql/updates/world/2016_02_26_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_00_world.sql diff --git a/sql/updates/world/2016_02_26_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_01_world.sql index b30b3cba35f..b30b3cba35f 100644 --- a/sql/updates/world/2016_02_26_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_01_world.sql diff --git a/sql/updates/world/2016_02_27_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_27_00_world.sql index b9288b2ddfb..b9288b2ddfb 100644 --- a/sql/updates/world/2016_02_27_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_27_00_world.sql diff --git a/sql/updates/world/2016_02_28_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_28_00_world.sql index 5a5694e0320..5a5694e0320 100644 --- a/sql/updates/world/2016_02_28_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_28_00_world.sql diff --git a/sql/updates/world/2016_02_29_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_00_world.sql index 280f2f901ef..280f2f901ef 100644 --- a/sql/updates/world/2016_02_29_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_00_world.sql diff --git a/sql/updates/world/2016_02_29_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_01_world.sql index 40343440d9a..40343440d9a 100644 --- a/sql/updates/world/2016_02_29_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_01_world.sql diff --git a/sql/updates/world/2016_03_01_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_01_00_world_335.sql index 36c48379190..36c48379190 100644 --- a/sql/updates/world/2016_03_01_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_01_00_world_335.sql diff --git a/sql/updates/world/2016_03_02_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_02_00_world_335.sql index e7a9f60e790..e7a9f60e790 100644 --- a/sql/updates/world/2016_03_02_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_02_00_world_335.sql diff --git a/sql/updates/world/2016_03_03_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_00_world.sql index 473bac4708a..473bac4708a 100644 --- a/sql/updates/world/2016_03_03_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_00_world.sql diff --git a/sql/updates/world/2016_03_03_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_01_world.sql index a242d26efe1..a242d26efe1 100644 --- a/sql/updates/world/2016_03_03_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_01_world.sql diff --git a/sql/updates/world/2016_03_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_00_world.sql index f338d6d0043..f338d6d0043 100644 --- a/sql/updates/world/2016_03_04_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_00_world.sql diff --git a/sql/updates/world/2016_03_04_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_01_world.sql index b02c2eb4e79..b02c2eb4e79 100644 --- a/sql/updates/world/2016_03_04_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_01_world.sql diff --git a/sql/updates/world/2016_03_04_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_02_world_335.sql index db8ca3a9178..db8ca3a9178 100644 --- a/sql/updates/world/2016_03_04_02_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_02_world_335.sql diff --git a/sql/updates/world/2016_03_04_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_03_world.sql index 4d148adde55..4d148adde55 100644 --- a/sql/updates/world/2016_03_04_03_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_03_world.sql diff --git a/sql/updates/world/2016_03_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_05_00_world.sql index 8dde060140d..8dde060140d 100644 --- a/sql/updates/world/2016_03_05_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_05_00_world.sql diff --git a/sql/updates/world/2016_03_06_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_00_world.sql index e991023e514..e991023e514 100644 --- a/sql/updates/world/2016_03_06_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_00_world.sql diff --git a/sql/updates/world/2016_03_06_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_01_world.sql index 183121d6735..183121d6735 100644 --- a/sql/updates/world/2016_03_06_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_01_world.sql diff --git a/sql/updates/world/2016_03_07_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_00_world.sql index b9df4d07bb9..b9df4d07bb9 100644 --- a/sql/updates/world/2016_03_07_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_00_world.sql diff --git a/sql/updates/world/2016_03_07_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_01_world.sql index d74f4296903..d74f4296903 100644 --- a/sql/updates/world/2016_03_07_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_01_world.sql diff --git a/sql/updates/world/2016_03_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_09_00_world.sql index d3ebf1af0ff..d3ebf1af0ff 100644 --- a/sql/updates/world/2016_03_09_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_09_00_world.sql diff --git a/sql/updates/world/2016_03_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_00_world.sql index e3170b27499..e3170b27499 100644 --- a/sql/updates/world/2016_03_10_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_00_world.sql diff --git a/sql/updates/world/2016_03_10_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_01_world.sql index 80b23be82c2..80b23be82c2 100644 --- a/sql/updates/world/2016_03_10_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_01_world.sql diff --git a/sql/updates/world/2016_03_12_2015_11_14_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_12_2015_11_14_00_world.sql index b3e49eb1114..b3e49eb1114 100644 --- a/sql/updates/world/2016_03_12_2015_11_14_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_12_2015_11_14_00_world.sql diff --git a/sql/updates/world/2016_03_13_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_00_world.sql index 0c45636d945..0c45636d945 100644 --- a/sql/updates/world/2016_03_13_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_00_world.sql diff --git a/sql/updates/world/2016_03_13_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_01_world.sql index 12bc205f125..12bc205f125 100644 --- a/sql/updates/world/2016_03_13_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_01_world.sql diff --git a/sql/updates/world/2016_03_15_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_15_00_world.sql index 69e2e3a873b..69e2e3a873b 100644 --- a/sql/updates/world/2016_03_15_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_15_00_world.sql diff --git a/sql/updates/world/2016_03_19_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_00_world.sql index ce96286d585..ce96286d585 100644 --- a/sql/updates/world/2016_03_19_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_00_world.sql diff --git a/sql/updates/world/2016_03_19_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_01_world.sql index 79452fdf43c..79452fdf43c 100644 --- a/sql/updates/world/2016_03_19_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_01_world.sql diff --git a/sql/updates/world/2016_03_19_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_02_world.sql index a0a6ff3619c..a0a6ff3619c 100644 --- a/sql/updates/world/2016_03_19_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_02_world.sql diff --git a/sql/updates/world/2016_03_20_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_00_world.sql index 8120f1be86f..8120f1be86f 100644 --- a/sql/updates/world/2016_03_20_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_00_world.sql diff --git a/sql/updates/world/2016_03_20_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_01_world.sql index f59710f1e32..f59710f1e32 100644 --- a/sql/updates/world/2016_03_20_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_01_world.sql diff --git a/sql/updates/world/2016_03_20_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_02_world.sql index 9b03a9cdea3..9b03a9cdea3 100644 --- a/sql/updates/world/2016_03_20_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_02_world.sql diff --git a/sql/updates/world/2016_03_21_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_21_00_world.sql index 55f6cceaed8..55f6cceaed8 100644 --- a/sql/updates/world/2016_03_21_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_21_00_world.sql diff --git a/sql/updates/world/2016_03_23_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_23_00_world.sql index 9195b652288..9195b652288 100644 --- a/sql/updates/world/2016_03_23_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_23_00_world.sql diff --git a/sql/updates/world/2016_03_24_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_00_world_335.sql index 4d69d8fd3f2..4d69d8fd3f2 100644 --- a/sql/updates/world/2016_03_24_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_00_world_335.sql diff --git a/sql/updates/world/2016_03_24_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_01_world_335.sql index 01d7857519e..01d7857519e 100644 --- a/sql/updates/world/2016_03_24_01_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_01_world_335.sql diff --git a/sql/updates/world/2016_03_24_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_02_world.sql index 199582eb4a0..199582eb4a0 100644 --- a/sql/updates/world/2016_03_24_02_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_02_world.sql diff --git a/sql/updates/world/2016_03_26_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_26_00_world.sql index 58a42dc214d..58a42dc214d 100644 --- a/sql/updates/world/2016_03_26_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_26_00_world.sql diff --git a/sql/updates/world/2016_03_27_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_27_00_world.sql index 9421881c88a..9421881c88a 100644 --- a/sql/updates/world/2016_03_27_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_27_00_world.sql diff --git a/sql/updates/world/2016_03_28_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_00_world.sql index b4a7e2d5a36..b4a7e2d5a36 100644 --- a/sql/updates/world/2016_03_28_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_00_world.sql diff --git a/sql/updates/world/2016_03_28_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_01_world.sql index b4a24b011b3..b4a24b011b3 100644 --- a/sql/updates/world/2016_03_28_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_01_world.sql diff --git a/sql/updates/world/2016_03_29_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_29_00_world_335.sql index e3851e59c8e..e3851e59c8e 100644 --- a/sql/updates/world/2016_03_29_00_world_335.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_29_00_world_335.sql diff --git a/sql/updates/world/2016_04_01_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_00_world.sql index 024bbb6fa5a..024bbb6fa5a 100644 --- a/sql/updates/world/2016_04_01_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_00_world.sql diff --git a/sql/updates/world/2016_04_01_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_01_world.sql index 38a13f0ea84..38a13f0ea84 100644 --- a/sql/updates/world/2016_04_01_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_01_world.sql diff --git a/sql/updates/world/2016_04_02_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_00_world.sql index dc8f4375da0..dc8f4375da0 100644 --- a/sql/updates/world/2016_04_02_00_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_00_world.sql diff --git a/sql/updates/world/2016_04_02_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_01_world.sql index 4bcca1d6250..4bcca1d6250 100644 --- a/sql/updates/world/2016_04_02_01_world.sql +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_01_world.sql diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_02_world.sql new file mode 100644 index 00000000000..89b8032be10 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_02_world.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=63277; +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(63277,65269,2,'General Vezax - Shadow Crash - Haste and reduced mana cost'); diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_00_world.sql new file mode 100644 index 00000000000..8344df664f2 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_00_world.sql @@ -0,0 +1,2 @@ +-- Remove duplicate spawn of "Big Roy" (24785) +DELETE FROM `creature` WHERE `guid`=203496 AND `id`=24785; diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_01_world.sql new file mode 100644 index 00000000000..a150fe2d69e --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_01_world.sql @@ -0,0 +1,36 @@ +DELETE FROM `smart_scripts` WHERE `entryorguid`=24713 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 +(24713, 0, 2, 3, 62, 0, 100, 0, 9335, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, '"Crowleg" Dan - On Gossip Option Select - Close Gossip'), +(24713, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, '"Crowleg" Dan - On Gossip Option Select - Start Attack'); + +DELETE FROM `gossip_menu_option` WHERE `menu_id`=9335; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `OptionBroadcastTextID`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`, `BoxBroadcastTextID`) VALUES +(9335, 0, 0, 'Ummm... the frog says you''re a traitor, "matey."', 25738, 1, 1, 0, 0, 0, 0, NULL, 0); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=9335; + +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(15, 9335, 0, 0, 0, 9, 0, 11479, 0, 0, 0, 0, 0, '', 'Crowleg" Dan - Only show Gossip if player is on quest'); + +UPDATE `gameobject_template` SET `AIName`='SmartGameObjectAI', scriptname='' WHERE `entry` =186944; +DELETE FROM `smart_scripts` WHERE `entryorguid` =186944 AND `source_type`=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 +(186944, 1, 0, 1, 70, 0, 100, 0, 2, 0, 0, 0, 105, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Dirt Mound - On State Changed - Add Go Flag '), +(186944, 1, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 12, 24790, 1, 120000, 1, 0, 0, 8, 0, 0, 0, 688.9122, -3377.737, 67.87585, 1.291544, 'Dirt Mound - On State Changed - Summon Black Conrads Ghost'), +(186944, 1, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 12, 24796, 1, 120000, 1, 0, 0, 8, 0, 0, 0, 691.5706, -3375.863, 68.09953, 1.308997, 'Dirt Mound - On State Changed - Summon Spectral Sailor'), +(186944, 1, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 12, 24796, 1, 120000, 1, 0, 0, 8, 0, 0, 0, 687.27, -3374.881, 67.92136, 1.047198, 'Dirt Mound - On State Changed - Summon Spectral Sailor'); + +DELETE FROM `creature` WHERE `guid`=116177; +UPDATE `gameobject` SET `spawntimesecs`=120 WHERE `guid`=5842; + +DELETE FROM `smart_scripts` WHERE `entryorguid`=23777 AND `source_type`=0 AND `id`IN(6,7); + +UPDATE `smart_scripts` SET `link`=6 WHERE `entryorguid`=23777 AND `source_type`=0 AND `id`=1 AND `link`=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 +(23777, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Proto-Drake Egg - On Reset - Set Passive'), +(23777, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 94, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Proto-Drake Egg - On Reset - Set Dynamic Flags'); + + +UPDATE `creature_template` SET `unit_flags`=0 WHERE `entry`=23777; diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_02_world.sql new file mode 100644 index 00000000000..1a408d3ec6a --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_02_world.sql @@ -0,0 +1,2 @@ +-- Fix respawn time for quest loot GO "Daggerfen Poison Manual" +UPDATE `gameobject` SET `spawntimesecs`=2 WHERE `guid`=22662; diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_04_00_world.sql new file mode 100644 index 00000000000..69da8a7d699 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_04_00_world.sql @@ -0,0 +1,149 @@ +UPDATE `quest_template_addon` SET `RequiredMinRepValue`=9000 WHERE `ID`=9729; + +DELETE FROM `creature_text` WHERE `entry`=17877; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(17877, 0, 0, 'Fhwoor go now, $n. Get ark, come back.', 12, 0, 100, 0, 0, 0, 16439, 0, 'Fhwoor'), +(17877, 1, 0, 'Take moment... get ready.', 12, 0, 100, 0, 0, 0, 16440, 0, 'Fhwoor'), +(17877, 2, 0, 'We go!', 12, 0, 100, 0, 0, 0, 16441, 0, 'Fhwoor'), +(17877, 3, 0, '%s lifts the Ark of Ssslith with ease.', 16, 0, 100, 0, 0, 0, 16442, 0, 'Fhwoor'), +(17877, 4, 0, 'Uh oh...', 12, 0, 100, 0, 0, 0, 16443, 0, 'Fhwoor'), +(17877, 5, 0, 'Ha ha, squishy naga!', 12, 0, 100, 0, 0, 0, 16444, 0, 'Fhwoor'), +(17877, 6, 0, '%s places the Ark of Ssslith on the ground.', 16, 0, 100, 0, 0, 0, 16445, 0, 'Fhwoor'), +(17877, 7, 0, 'Fhwoor do good!', 16, 0, 100, 0, 0, 0, 16446, 0, 'Fhwoor'); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`IN(18154,17877); + +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(17877,18154) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(1787700,1787701) AND `source_type`=9; +DELETE FROM `smart_scripts` WHERE `entryorguid`=18089 AND `source_type`=0 AND `id`>0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=18088 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 +(18154, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 53, 0, 18154, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 'Ssslith - On Just Summoned - Start WP'), +(18088, 0, 2, 0, 54, 0, 100, 0, 0, 0, 0, 0, 53, 0, 18088, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 'Bloodscale Enchantress - On Just Summoned - Start WP'), +(18089, 0, 1, 0, 54, 0, 100, 0, 0, 0, 0, 0, 53, 0, 18089, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 'Bloodscale Slavedriver - On Just Summoned - Start WP'), +(18154, 0, 1, 0, 40, 0, 100, 0, 12, 18154, 0, 0, 66, 0, 0, 0, 0, 0, 0, 19, 17877, 0, 0, 0, 0, 0, 0, 'Ssslith - On Reached WP12 - Face Fhwoor'), +(18088, 0, 3, 0, 40, 0, 100, 0, 6, 18088, 0, 0, 66, 0, 0, 0, 0, 0, 0, 19, 17877, 0, 0, 0, 0, 0, 0, 'Bloodscale Enchantress - On Reached WP12 - Face Fhwoor'), +(18089, 0, 2, 0, 40, 0, 100, 0, 8, 18089, 0, 0, 66, 0, 0, 0, 0, 0, 0, 19, 17877, 0, 0, 0, 0, 0, 0, 'Bloodscale Slavedriver - On Reached WP12 - Face Fhwoor'), +(17877, 0, 0, 1, 19, 0, 100, 0, 9729, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Quest Accept (Fhwoor Smash) - Store Targetlist'), +(17877, 0, 1, 18, 61, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Quest Accept (Fhwoor Smash) - Say Line 0'), +(17877, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 6, 9729, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Death - Fail Quest Fhwoor Smash'), +(17877, 0, 3, 4, 40, 0, 100, 0, 11, 17877, 0, 0, 1, 1, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP11 - Say Line 1'), +(17877, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 54, 20000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP11 - Pause WP (20 seconds)'), +(17877, 0, 5, 0, 40, 0, 100, 0, 12, 17877, 0, 0, 1, 2, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP12 - Say Line 2'), +(17877, 0, 6, 7, 40, 0, 100, 0, 27, 17877, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP27 - Say Line 3'), +(17877, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 54, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP27 - Pause WP (5 seconds)'), +(17877, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 70, 120, 0, 0, 0, 0, 0, 20, 182082, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP27 - Despawn The Ark of Ssslith'), +(17877, 0, 9, 10, 40, 0, 100, 0, 43, 17877, 0, 0, 1, 4, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP43 - Say Line 4'), +(17877, 0, 10, 11, 61, 0, 100, 0, 0, 0, 0, 0, 54, 20000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP43 - Pause WP (20 seconds)'), +(17877, 0, 11, 12, 61, 0, 100, 0, 0, 0, 0, 0, 12, 18154, 1, 300000, 0, 0, 0, 8, 0, 0, 0, 168.5472, 8207.521, 22.9772, 4.467648, 'Fhwoor - On Reached WP43 - Summon Ssslith'), +(17877, 0, 12, 13, 61, 0, 100, 0, 0, 0, 0, 0, 12, 18088, 1, 300000, 0, 0, 0, 8, 0, 0, 0, 172.8663, 8214.886, 22.31137, 4.198237, 'Fhwoor - On Reached WP43 - Summon Bloodscale Enchantress'), +(17877, 0, 13, 0, 61, 0, 100, 0, 0, 0, 0, 0, 12, 18089, 1, 300000, 0, 0, 0, 8, 0, 0, 0, 166.7656, 8215.018, 22.63307, 4.604752, 'Fhwoor - On Reached WP43 - Summon Bloodscale Slavedriver'), +(17877, 0, 14, 0, 11, 0, 100, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Spawn Set Active'), +(17877, 0, 15, 0, 40, 0, 100, 0, 44, 17877, 0, 0, 1, 5, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP44 - Say Line 5'), +(17877, 0, 16, 0, 40, 0, 100, 0, 45, 17877, 0, 0, 59, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP45 - Set Run On'), +(17877, 0, 17, 0, 40, 0, 100, 0, 60, 17877, 0, 0, 80, 1787701, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP60 - Run Script 2'), +(17877, 0, 18, 0, 61, 0, 100, 0, 0, 0, 0, 0, 80, 1787700, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Quest Accept - Run Script 1'), +(17877, 0, 19, 20, 40, 0, 100, 0, 61, 17877, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 2.042035, 'Fhwoor - On Reached WP61 - Set Orientation'), +(17877, 0, 20, 21, 61, 0, 100, 0, 0, 0, 0, 0, 81, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP61 - Set Npc Flags'), +(17877, 0, 21, 22, 61, 0, 100, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP61 - Turn Run Off'), +(17877, 0, 22, 23, 61, 0, 100, 0, 0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP61 - Say Line 7'), +(17877, 0, 23, 24, 61, 0, 100, 0, 0, 0, 0, 0, 2, 1709, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP61 - Set Faction'), +(17877, 0, 24, 0, 61, 0, 100, 0, 0, 0, 0, 0, 15, 9729, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Reached WP61 - Complete Quest'), +(17877, 0, 25, 0, 9, 0, 100, 0, 0, 10, 20000, 30000, 11, 31277, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - On Range - Cast Stomp'), +(1787700, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - Script - Set NPC Flags'), +(1787700, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 2, 250, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - Script - Set Faction'), +(1787700, 9, 2, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 53, 0, 17877, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - Script - Start WP'), +(1787701, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 54, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - Script 2 - Pause WP (5 Seconds)'), +(1787701, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Fhwoor - Script 2 - Say Line 6'), +(1787701, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 50, 182082, 180, 0, 0, 0, 0, 8, 0, 0, 0, 249.717, 8482.185, 22.96521, 3.159062, 'Fhwoor - Script 2 - Summon The Ark of Ssslith'); + +DELETE FROM `waypoints` WHERE `entry`IN(17877,18154,18088,18089); +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +(17877, 1, 213.6417, 8469.281, 23.52778, 'Fhwoor'), +(17877, 2, 194.8211, 8448.552, 24.48719, 'Fhwoor'), +(17877, 3, 181.9171, 8416.949, 23.39253, 'Fhwoor'), +(17877, 4, 162.9771, 8387.255, 22.28007, 'Fhwoor'), +(17877, 5, 169.1168, 8353.966, 21.07829, 'Fhwoor'), +(17877, 6, 179.16, 8325.873, 20.83087, 'Fhwoor'), +(17877, 7, 170.3557, 8302.857, 21.0235, 'Fhwoor'), +(17877, 8, 182.7192, 8270.847, 18.91084, 'Fhwoor'), +(17877, 9, 220.4595, 8241.914, 20.72861, 'Fhwoor'), +(17877, 10, 248.3627, 8210.217, 19.54621, 'Fhwoor'), +(17877, 11, 283.827, 8203.188, 22.15056, 'Fhwoor'), +(17877, 12, 299.8667, 8188.261, 21.42571, 'Fhwoor'), +(17877, 13, 318.4961, 8184.514, 18.0551, 'Fhwoor'), +(17877, 14, 333.9666, 8178.852, 17.66307, 'Fhwoor'), +(17877, 15, 349.5377, 8179.188, 18.45091, 'Fhwoor'), +(17877, 16, 366.4365, 8187.577, 21.90989, 'Fhwoor'), +(17877, 17, 378.7538, 8190.383, 23.30309, 'Fhwoor'), +(17877, 18, 396.7187, 8184.856, 19.38158, 'Fhwoor'), +(17877, 19, 416.5232, 8164.166, 18.35449, 'Fhwoor'), +(17877, 20, 436.7097, 8153.245, 21.59639, 'Fhwoor'), +(17877, 21, 451.9413, 8151.88, 23.76729, 'Fhwoor'), +(17877, 22, 467.4153, 8152.104, 22.10491, 'Fhwoor'), +(17877, 23, 485.0933, 8148.362, 20.20708, 'Fhwoor'), +(17877, 24, 500.4597, 8146.723, 20.18372, 'Fhwoor'), +(17877, 25, 517.5106, 8156.078, 22.14917, 'Fhwoor'), +(17877, 26, 536.4334, 8157.974, 23.6155, 'Fhwoor'), +(17877, 27, 558.9749, 8159.831, 23.83816, 'Fhwoor'), +(17877, 28, 522.1965, 8135.454, 21.15369, 'Fhwoor'), +(17877, 29, 498.0764, 8136.04, 20.90411, 'Fhwoor'), +(17877, 30, 477.8418, 8127.26, 22.5633, 'Fhwoor'), +(17877, 31, 450.433, 8131.167, 21.50137, 'Fhwoor'), +(17877, 32, 431.7549, 8121.7, 18.242, 'Fhwoor'), +(17877, 33, 416.2102, 8120.498, 17.59649, 'Fhwoor'), +(17877, 34, 394.6256, 8120.143, 17.94713, 'Fhwoor'), +(17877, 35, 379.7412, 8113.295, 17.7740, 'Fhwoor'), +(17877, 36, 364.4443, 8105.485, 18.17426, 'Fhwoor'), +(17877, 37, 350.215, 8106.762, 17.74799, 'Fhwoor'), +(17877, 38, 335.0946, 8119.199, 17.49909, 'Fhwoor'), +(17877, 39, 328.1111, 8135.518, 18.31635, 'Fhwoor'), +(17877, 40, 305.7509, 8149.812, 20.04914, 'Fhwoor'), +(17877, 41, 275.4078, 8161.027, 17.7491, 'Fhwoor'), +(17877, 42, 247.4046, 8177.393, 17.72273, 'Fhwoor'), +(17877, 43, 220.5886, 8180.784, 19.78761, 'Fhwoor'), +(17877, 44, 205.7915, 8183.323, 23.08216, 'Fhwoor'), +(17877, 45, 203.9108, 8206.521, 22.37668, 'Fhwoor'), +(17877, 46, 200.2505, 8229.313, 24.96921, 'Fhwoor'), +(17877, 47, 201.1895, 8251.09, 21.10947, 'Fhwoor'), +(17877, 48, 190.4957, 8267.601, 18.47761, 'Fhwoor'), +(17877, 49, 175.0741, 8288.405, 18.58564, 'Fhwoor'), +(17877, 50, 182.4148, 8311.77, 21.29364, 'Fhwoor'), +(17877, 51, 182.5205, 8333.074, 19.87689, 'Fhwoor'), +(17877, 52, 175.5308, 8357.185, 18.46842, 'Fhwoor'), +(17877, 53, 183.5543, 8381.03, 16.24468, 'Fhwoor'), +(17877, 54, 195.2988, 8399.357, 16.50945, 'Fhwoor'), +(17877, 55, 208.5941, 8413.654, 18.89419, 'Fhwoor'), +(17877, 56, 221.3398, 8432.104, 20.17568, 'Fhwoor'), +(17877, 57, 230.968, 8446.415, 21.99157, 'Fhwoor'), +(17877, 58, 227.1291, 8465.446, 19.64525, 'Fhwoor'), +(17877, 59, 231.5279, 8479.356, 17.87813, 'Fhwoor'), +(17877, 60, 246.9482, 8481.803, 22.1418, 'Fhwoor'), +(17877, 61, 231.4028, 8479.942, 18.03377, 'Fhwoor'), +(18154, 1, 169.4304, 8210.07, 22.51478, 'Ssslith'), +(18154, 2, 169.5868, 8209.083, 22.51478, 'Ssslith'), +(18154, 3, 168.75, 8208.333, 22.80278, 'Ssslith'), +(18154, 4, 168.0234, 8205.424, 23.42778, 'Ssslith'), +(18154, 5, 167.709, 8204.166, 23.80278, 'Ssslith'), +(18154, 6, 167.709, 8202.083, 23.80278, 'Ssslith'), +(18154, 7, 167.709, 8200, 23.60022, 'Ssslith'), +(18154, 8, 170.3105, 8196.961, 22.97522, 'Ssslith'), +(18154, 9, 170.834, 8196.354, 22.85022, 'Ssslith'), +(18154, 10, 171.2306, 8194.351, 22.48486, 'Ssslith'), +(18154, 11, 182.8383, 8183.431, 23.90405, 'Ssslith'), +(18154, 12, 188.6353, 8182.512, 23.86377, 'Ssslith'), +(18088, 1, 172.8497, 8215.886, 22.30278, 'Bloodscale Enchantress'), +(18088, 2, 172.8672, 8214.886, 22.30278, 'Bloodscale Enchantress'), +(18088, 3, 172.0461, 8213.434, 22.35161, 'Bloodscale Enchantress'), +(18088, 4, 176.9391, 8193.834, 23.09314, 'Bloodscale Enchantress'), +(18088, 5, 181.4677, 8187.228, 23.00415, 'Bloodscale Enchantress'), +(18088, 6, 185.6965, 8186.558, 23.32629, 'Bloodscale Enchantress'), +(18089, 1, 166.6959, 8216.016, 22.55278, 'Bloodscale Slavedriver'), +(18089, 2, 166.7656, 8215.018, 22.55278, 'Bloodscale Slavedriver'), +(18089, 3, 165.9063, 8207.064, 23.10177, 'Bloodscale Slavedriver'), +(18089, 4, 165.6914, 8205.076, 23.72677, 'Bloodscale Slavedriver'), +(18089, 5, 164.922, 8197.819, 23.50668, 'Bloodscale Slavedriver'), +(18089, 6, 172.0933, 8188.685, 22.47522, 'Bloodscale Slavedriver'), +(18089, 7, 180.3612, 8180.244, 24.05603, 'Bloodscale Slavedriver'), +(18089, 8, 184.59, 8179.574, 24.47522, 'Bloodscale Slavedriver'); diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_00_world.sql new file mode 100644 index 00000000000..f59e70ddb34 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_00_world.sql @@ -0,0 +1,2 @@ +UPDATE `quest_template_addon` SET `RequiredMinRepValue`=42000 WHERE `ID`=9729; +DELETE FROM `smart_scripts` WHERE `entryorguid`=11937 AND `source_type`=0 AND `id`=1 AND `link`=0; diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_01_world.sql new file mode 100644 index 00000000000..eb2609af74d --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_01_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry`=47320; diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_08_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_08_00_world.sql new file mode 100644 index 00000000000..930e599396f --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_08_00_world.sql @@ -0,0 +1,133 @@ +SET @CGUID := 78642; + +DELETE FROM `creature` WHERE `id` IN(17417,17418,17404,17405); +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `MovementType`) VALUES +(@CGUID+0, 17417, 530, 1, 1, 214.6568, 4122.551, 79.8511, 2.251475, 120, 0, 0), -- 17417 (Area: 0) (possible waypoints or random movement) +(@CGUID+1, 17417, 530, 1, 1, 216.0346, 4125.61, 80.22345, 2.251475, 120, 0, 0), -- 17417 (Area: 0) (possible waypoints or random movement) +(@CGUID+2, 17404, 530, 1, 1, 211.6765, 4126.361, 79.04578, 2.391101, 120, 0, 0), -- 17404 (Area: 0) (possible waypoints or random movement) +(@CGUID+3, 17418, 530, 1, 1, 261.5179, 4106.813, 93.315, 2.663978, 120, 0, 0), -- 17418 (Area: 0) +(@CGUID+4, 17418, 530, 1, 1, 260.6302, 4103.529, 93.33371, 2.60972, 120, 0, 0), -- 17418 (Area: 0) +(@CGUID+5, 17405, 530, 1, 1, 230.5075, 4118.714, 83.56195, 2.949606, 120, 0, 0); -- 17405 (Area: 0) (possible waypoints or random movement) + +UPDATE `creature` SET `equipment_id`=1 WHERE `id` IN(17417,17418,17404,17405); + +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`IN(17413,17417,17404,17418,17405); + +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(17413,17417,17404,17418,17405) AND `source_type`=0; + +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(1740400,1740500) AND `source_type`=9; + + +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(-@CGUID-0,-@CGUID-1,-@CGUID-2,-@CGUID-3,-@CGUID-4,-@CGUID-5) 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 +(-@CGUID-0, 0, 0, 1, 11, 0, 100, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Respawn - Set Immune'), +(-@CGUID-0, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Respawn - Set Invisible'), +(-@CGUID-0, 0, 1, 2, 38, 0, 100, 1, 1, 1, 0, 0, 19, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Data Set - Set Immune'), +(-@CGUID-0, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Data Set - Set visible'), +(-@CGUID-0, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 53, 0, 1741700, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Respawn - Start WP'), +(-@CGUID-0, 0, 4, 5, 40, 0, 100, 0, 2, 1741700, 0, 0, 54, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Reached WP3 - Pause WP'), +(-@CGUID-0, 0, 5, 6, 61, 0, 100, 0, 0, 0, 0, 0, 11, 30460, 2, 0, 0, 0, 0, 19, 17404, 0, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Reached WP3 - Cast Kick'), +(-@CGUID-0, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 17404, 0, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Reached WP3 - Set Data on Sedei'), +(-@CGUID-0, 0, 7, 8, 40, 0, 100, 0, 5, 1741700, 0, 0, 45, 3, 3, 0, 0, 0, 0, 10, @CGUID+3, 17418, 0, 0, 0, 0, 0, 'Mag har Escort (1) - On Reached WP6 - Start Attack'), +(-@CGUID-0, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 10, @CGUID+3, 17418, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Reached WP12 - Start Attack'), +(-@CGUID-0, 0, 9, 0, 0, 0, 100, 1, 3000, 3000, 0, 0, 45, 4, 4, 0, 0, 0, 0, 10, @CGUID+3, 17418, 0, 0, 0, 0, 0, 'Mag har Escort (2) - IC - Set Data'), + +(-@CGUID-1, 0, 0, 1, 11, 0, 100, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Respawn - Set Immune'), +(-@CGUID-1, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Respawn - Set Invisible'), +(-@CGUID-1, 0, 1, 2, 38, 0, 100, 1, 1, 1, 0, 0, 19, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Data Set - Set Immune'), +(-@CGUID-1, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Data Set - Set visible'), +(-@CGUID-1, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 53, 0, 1741701, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Respawn - Start WP'), +(-@CGUID-1, 0, 4, 5, 40, 0, 100, 0, 3, 1741701, 0, 0, 54, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Reached WP9 - Pause WP'), +(-@CGUID-1, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Reached WP9 - Say'), +(-@CGUID-1, 0, 6, 7, 40, 0, 100, 0, 10, 1741701, 0, 0, 45, 3, 3, 0, 0, 0, 0, 10, @CGUID+4, 17418, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Reached WP12 - Start Attack'), +(-@CGUID-1, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 10, @CGUID+4, 17418, 0, 0, 0, 0, 0, 'Mag har Escort (2) - On Reached WP12 - Start Attack'), +(-@CGUID-1, 0, 8, 0, 0, 0, 100, 1, 3000, 3000, 0, 0, 45, 4, 4, 0, 0, 0, 0, 10, @CGUID+4, 17418, 0, 0, 0, 0, 0, 'Mag har Escort (2) - IC - Set Data'), + +(-@CGUID-2, 0, 0, 1, 11, 0, 100, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - On Respawn - Set Immune'), +(-@CGUID-2, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - On Respawn - Set Invisible'), +(-@CGUID-2, 0, 1, 2, 38, 0, 100, 1, 1, 1, 0, 0, 19, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - On Data Set - Set Immune'), +(-@CGUID-2, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - On Data Set - Set visible'), +(-@CGUID-2, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 53, 0, 17404, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - On Respawn - Start WP'), +(-@CGUID-2, 0, 4, 0, 38, 0, 100, 0, 2, 2, 0, 0, 80, 1740400, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - On Data Set - Run Script'), +(-@CGUID-2, 0, 5, 0, 40, 0, 100, 0, 3, 17404, 0, 0, 54, 21000, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - On Reached WP3 - Pause WP'), +(-@CGUID-2, 0, 6, 0, 40, 0, 100, 0, 5, 17404, 0, 0, 54, 18000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - On Reached WP5 - Pause WP'), + +(-@CGUID-3, 0, 0, 1, 11, 0, 100, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (1) - On Respawn - Set Immune'), +(-@CGUID-3, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (1) - On Respawn - Set Invisible'), +(-@CGUID-3, 0, 2, 3, 38, 0, 100, 1, 1, 1, 0, 0, 19, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (1) - On Data Set - Set Immune'), +(-@CGUID-3, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (1) - On Data Set - Set visible'), +(-@CGUID-3, 0, 5, 0, 38, 0, 100, 0, 3, 3, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 17417, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (1) - On Data Set - Start Attack'), + +(-@CGUID-4, 0, 0, 1, 11, 0, 100, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (2) - On Respawn - Set Immune'), +(-@CGUID-4, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (2) - On Respawn - Set Invisible'), +(-@CGUID-4, 0, 2, 3, 38, 0, 100, 1, 1, 1, 0, 0, 19, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (2) - On Data Set - Set Immune'), +(-@CGUID-4, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (2) - On Data Set - Set visible'), +(-@CGUID-4, 0, 5, 0, 38, 0, 100, 0, 3, 3, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 17417, 0, 0, 0, 0, 0, 0, 'Laughing Skull Ambusher (2) - On Data Set - Start Attack'), + +(-@CGUID-5, 0, 0, 1, 11, 0, 100, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Krun Spinebreaker - On Respawn - Set Immune'), +(-@CGUID-5, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Krun Spinebreaker - On Respawn - Set Invisible'), +(-@CGUID-5, 0, 1, 2, 38, 0, 100, 1, 1, 1, 0, 0, 19, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Krun Spinebreaker - On Data Set - Set Immune'), +(-@CGUID-5, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Krun Spinebreaker - On Data Set - Set visible'), +(-@CGUID-5, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 53, 1, 17405, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Krun Spinebreaker - On Respawn - Start WP'), +(-@CGUID-5, 0, 4, 0, 40, 0, 100, 0, 3, 17405, 0, 0, 80, 1740500, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Krun Spinebreaker - On Reached WP3 - Run Script'), + +(1740400, 9, 0, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, @CGUID+3, 17418, 0, 0, 0, 0, 0, 'Vindicator Sedai - Script - Set Data'), +(1740400, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, @CGUID+4, 17418, 0, 0, 0, 0, 0, 'Vindicator Sedai - Script - Say'), +(1740400, 9, 2, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - Script - Say'), +(1740400, 9, 3, 0, 0, 0, 100, 0, 15000, 15000, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - Script - Say'), +(1740400, 9, 4, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - Script - Say'), +(1740400, 9, 5, 0, 0, 0, 100, 0, 18000, 18000, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vindicator Sedai - Script - Say'), +(1740400, 9, 6, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, @CGUID+5, 17405, 0, 0, 0, 0, 0, 'Vindicator Sedai - Script - Say'), + +(1740500, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 30462, 2, 0, 0, 0, 0, 19, 17404, 0, 0, 0, 0, 0, 0, 'Krun Spinebreaker - Script - Cast Execute Sedei'), +(1740500, 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, 'Krun Spinebreaker - Script - Say'), +(1740500, 9, 2, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 41, 0, 0, 0, 0, 0, 0, 10, @CGUID+0, 17417, 0, 0, 0, 0, 0, 'Krun Spinebreaker - Script - Despawn Mag har Escort'), +(1740500, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 10, @CGUID+1, 17417, 0, 0, 0, 0, 0, 'Krun Spinebreaker - Script - Despawn Mag har Escort'), +(1740500, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 10, @CGUID+2, 17404, 0, 0, 0, 0, 0, 'Krun Spinebreaker - Script - Despawn Vindicator Sedai'), +(1740500, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 10, @CGUID+3, 17418, 0, 0, 0, 0, 0, 'Krun Spinebreaker - Script - Despawn Laughing Skull Ambusher'), +(1740500, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 10, @CGUID+4, 17418, 0, 0, 0, 0, 0, 'Krun Spinebreaker - Script - Despawn'), +(1740500, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Krun Spinebreaker - Script - Despawn'), + +(17413, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, @CGUID+0, 17417, 0, 0, 0, 0, 0, 'Sedai Quest Credit Marker - On Just Summoned - Set Data on Mag har Escort'), +(17413, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, @CGUID+1, 17417, 0, 0, 0, 0, 0, 'Sedai Quest Credit Marker - On Just Summoned - Set Data on Mag har Escort'), +(17413, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, @CGUID+2, 17404, 0, 0, 0, 0, 0, 'Sedai Quest Credit Marker - On Just Summoned - Set Data on Vindicator Sedei'); + + +DELETE FROM `waypoints` WHERE `entry`IN(17404,17405,1741700,1741701,1741800,1741801); +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +(1741700, 1, 206.7916, 4132.612, 77.49819, 'Mag har Escort (1)'), +(1741700, 2, 199.061, 4142.329, 75.17587, 'Mag har Escort (1)'), -- Kick +(1741700, 3, 203.75, 4134.571, 76.52649, 'Mag har Escort (1)'), +(1741700, 4, 211.582, 4128.351, 79.12319, 'Mag har Escort (1)'), +(1741700, 5, 219.5054, 4125.231, 80.99819, 'Mag har Escort (1)'), +(1741701, 1, 206.2685, 4128.42, 77.62319, 'Mag har Escort (2)'), +(1741701, 2, 200.5664, 4136.248, 75.65149, 'Mag har Escort (2)'), +(1741701, 3, 196.179, 4141.198, 74.30087, 'Mag har Escort (2)'), -- say +(1741701, 4, 203.9766, 4138.813, 76.40149, 'Mag har Escort (2)'), +(1741701, 5, 206.5171, 4135.979, 77.40149, 'Mag har Escort (2)'), +(1741701, 6, 209.2334, 4134.047, 78.15149, 'Mag har Escort (2)'), +(1741701, 7, 209.2334, 4134.047, 78.15149, 'Mag har Escort (2)'), +(1741701, 8, 211.4904, 4132.254, 79.12319, 'Mag har Escort (2)'), +(1741701, 9, 214.5568, 4129.819, 79.74819, 'Mag har Escort (2)'), +(1741701, 10, 219.3728, 4128.506, 81.12319, 'Mag har Escort (2)'), +(17404, 1, 204.9158, 4134.23, 76.90149, 'Vindicator Sedai'), +(17404, 2, 200.7516, 4138.94, 75.52649, 'Vindicator Sedai'), +(17404, 3, 196.6698, 4143.903, 74.30087, 'Vindicator Sedai'), -- Event +(17404, 4, 201.4514, 4139.023, 75.90149, 'Vindicator Sedai'), +(17404, 5, 202.2026, 4138.024, 76.15149, 'Vindicator Sedai'), +(17404, 6, 198.0219, 4143.623, 74.92587, 'Vindicator Sedai'), +(17404, 7, 192.3438, 4150.61, 73.67587, 'Vindicator Sedai'), +(17405, 1, 213.5774, 4129.949, 79.74819, 'Krun Spinebreaker'), +(17405, 2, 203.9323, 4137.877, 76.40149, 'Krun Spinebreaker'), +(17405, 3, 193.1504, 4149.705, 73.80087, 'Krun Spinebreaker'); -- Assasinate + + +DELETE FROM `creature_text` WHERE `entry`IN(17417,17404,17405); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(17417, 0, 0, 'Do not return, draenei scum. Next time we won''t spare your life, unarmed or not!', 12, 0, 100, 0, 0, 0, 13986, 0, 'Mag har Escort'), -- 21:04:49.000 +(17404, 0, 0, 'I''ve failed... peace is impossible.', 12, 0, 100, 0, 0, 0, 13982, 0, 'Vindicator Sedai'), -- 21:04:58.000 +(17404, 1, 0, 'What in the Light''s name...?', 12, 0, 100, 0, 0, 0, 13983, 0, 'Vindicator Sedai'), -- 21:05:13.000 +(17404, 2, 0, 'Fel orcs!', 12, 0, 100, 0, 0, 0, 13984, 0, 'Vindicator Sedai'), -- 21:05:18.000 +(17404, 3, 0, 'The cycle of bloodshed is unending... Is there nothing I can do?', 12, 0, 100, 0, 0, 0, 13985, 0, 'Vindicator Sedai'), -- 21:05:36.000 +(17405, 0, 0, 'You can die!', 12, 0, 100, 0, 0, 0, 13988, 0, 'Krun Spinebreaer'); -- 21:05:48.000 diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_00_world_2016_03_28_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_00_world_2016_03_28_00_world.sql new file mode 100644 index 00000000000..0fc505965a3 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_00_world_2016_03_28_00_world.sql @@ -0,0 +1,3 @@ +DELETE FROM `trinity_string` WHERE `entry`=1030; +INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES +(1030,'Account name cannot contain ''@'' character.'); diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_01_world.sql new file mode 100644 index 00000000000..0c01492d746 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_01_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `creature_addon` WHERE `guid`=203496; diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_02_world.sql new file mode 100644 index 00000000000..60ae64d1715 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_02_world.sql @@ -0,0 +1,44 @@ +-- +/* Spell Bonus Data */ +-- Enchants +DELETE FROM `spell_bonus_data` WHERE `entry` IN (6297,13897,13907,20004,20006,20007,28005,44525,44578,46579,64442,64569); +INSERT INTO `spell_bonus_data` (`entry`,`direct_bonus`,`dot_bonus`,`ap_bonus`,`ap_dot_bonus`,`comments`) VALUES +( 6297, 0, 0, -1, -1, 'Fiery Blaze'), +(13897, 0, 0, -1, -1, 'Fiery Weapon - Fiery Weapon'), +(13907, 0, 0, -1, -1, 'Demonslaying - Smite Demon'), +(20004, 0, 0, -1, -1, 'Lifestealing - Life Steal'), +(20006, 0, 0, -1, -1, 'Unholy Weapon - Unholy Curse'), +(20007, 0, 0, -1, -1, 'Crusader - Holy Strength'), +(28005, 0, 0, -1, -1, 'Battlemaster - Battlemaster'), +(44525, 0, 0, -1, -1, 'Icebreaker - Icebreaker'), +(44578, 0, 0, -1, -1, 'Lifeward - Lifeward'), +(46579, 0, 0, -1, -1, 'Deathfrost - Deathfrost'), +(64442, 0, 0, -1, -1, 'Blade Warding - Blade Warding'), +(64569, 0, 0, -1, -1, 'Blood Draining - Blood Reserve'); + +-- Items +DELETE FROM `spell_bonus_data` WHERE `entry` IN (7712,7714,10577,16614,17484,18798,21992,27655,28788,38395,40972,55756,60526,67714,67760); +INSERT INTO `spell_bonus_data` (`entry`,`direct_bonus`,`dot_bonus`,`ap_bonus`,`ap_dot_bonus`,`comments`) VALUES +( 7712, 0, 0, -1, -1, 'Blazefury Medallion & Fiery Retributer (Fire Strike)'), +( 7714, 0, 0, -1, -1, 'Fiery Plate Gauntlets (Fire Strike)'), +(10577, 0, 0, -1, -1, 'Gauntlets of the Sea (Heal)'), +(16614, 0, 0, -1, -1, 'Storm Gauntlets (Lightning Strike)'), +(17484, 0, 0, -1, -1, 'Skullforge Reaver - Skullforge Brand'), +(18798, 0, 0, -1, -1, 'Freezing Band (Freeze)'), +(21992, 0, 0, -1, -1, 'Thunderfury'), +(27655, 0, 0, -1, -1, 'Heart of Wyrmthalak (Flame Lash)'), +(28788, 0, 0, -1, -1, 'Paladin T3 (8)'), +(38395, 0, 0, -1, -1, 'Warlock - Siphon Essence - T6 2P proc'), +(40972, 0, 0, -1, -1, 'Crystal Spire of Karabor - heal effect'), +(55756, 0, 0, -1, -1, 'Brunnhildar weapons (Chilling Blow)'), +(60526, 0, 0, -1, -1, 'Living Ice Crystals - heal effect'), +(67714, 0, 0, -1, -1, 'Pillar of Flame (Normal)'), +(67760, 0, 0, -1, -1, 'Pillar of Flame (Heroic)'); + +-- Consumables +DELETE FROM `spell_bonus_data` WHERE `entry` IN (28715,38616,43731,43733); +INSERT INTO `spell_bonus_data` (`entry`,`direct_bonus`,`dot_bonus`,`ap_bonus`,`ap_dot_bonus`,`comments`) VALUES +(28715, 0, 0, -1, -1, 'Consumable - Flamecap (Flamecap Fire)'), +(38616, 0, 0, -1, -1, 'Poison - Bloodboil Poison'), +(43731, 0, 0, -1, -1, 'Consumable - Stormchops (Lightning Zap)'), +(43733, 0, 0, -1, -1, 'Consumable - Stormchops (Lightning Zap)'); diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_03_world.sql new file mode 100644 index 00000000000..732e3d83ee5 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_03_world.sql @@ -0,0 +1,5 @@ +-- +DELETE FROM `player_factionchange_reputations` WHERE `alliance_id`= 589; +INSERT INTO `player_factionchange_reputations` (`alliance_id`, `horde_id`) VALUES +(589, 1137); +UPDATE `creature` SET `equipment_id`=0 WHERE `id` IN(17404); diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_04_world.sql new file mode 100644 index 00000000000..01154d2070a --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_04_world.sql @@ -0,0 +1,9 @@ +-- +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=17 AND `SourceEntry` IN (44550, 44610, 44609); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(17, 0, 44550, 0, 0, 29, 0, 24820, 5, 0, 0, 0, 0, '', 'Allow spell Collect Data only on Iron Dwarf Relic 24820'), +(17, 0, 44610, 0, 0, 29, 0, 24824, 5, 0, 0, 0, 0, '', 'Allow spell Collect Data only on Iron Dwarf Relics'), +(17, 0, 44609, 0, 0, 29, 0, 24271, 10, 0, 0, 0, 0, '', 'Allow spell Bluff only on Iron Dwarf'), +(17, 0, 44609, 0, 1, 29, 0, 23673, 10, 0, 0, 0, 0, '', 'Allow spell Bluff only on Iron Dwarf'), +(17, 0, 44609, 0, 2, 29, 0, 23672, 10, 0, 0, 0, 0, '', 'Allow spell Bluff only on Iron Dwarf'), +(17, 0, 44609, 0, 3, 29, 0, 23675, 10, 0, 0, 0, 0, '', 'Allow spell Bluff only on Iron Dwarf'); diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_05_world.sql new file mode 100644 index 00000000000..815540ecef1 --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_05_world.sql @@ -0,0 +1,41 @@ +-- +SET @Oguid:=65714; + +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+29; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`) VALUES +(@OGUID+0, 195256, 530, 1, 1, 1021.34, 7392.52, 36.3235, -2.79252, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+1, 195256, 530, 1, 1, 971.367, 7408.7, 29.5432, -1.25664, 0, 0, 0, 1, 180, 255, 1 ), +(@OGUID+2, 195256, 530, 1, 1, 957.729, 7355.67, 29.1519, 0.436332, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+3, 195256, 530, 1, 1, 1006.33, 7322.55, 41.0474, -1.15192, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+4, 195256, 530, 1, 1, 1003.33, 7430, 28.0768, -0.925024, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+5, 195256, 530, 1, 1, 201.985, 8489.73, 24.4459, 0.645772, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+6, 195256, 530, 1, 1, 265.287, 8514.35, 23.5299, -2.60053, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+7, 195256, 530, 1, 1, 258.263, 8495.36, 23.4081, 2.16421, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+8, 195256, 530, 1, 1, 276.203, 6122.65, 142.509, -0.95993, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+9, 195256, 530, 1, 1, -208.633, 5388.65, 22.9273, -1.72787, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+10,195256, 530, 1, 1, -87.5959, 5535.55, 22.807, 0.575957, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+11,195256, 530, 1, 1, -192.623, 5531.5, 29.4519, -2.51327, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+12,195256, 530, 1, 1, -702.011, 2676.55, 93.484, 1.72787, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+13,195256, 530, 1, 1, -684.19, 2664.04, 90.9786, 0.506145, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+14,195256, 530, 1, 1, -708.662, 2640.04, 91.8499, -2.14675, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+15,195256, 530, 1, 1, -714.397, 2671.54, 93.9279, 2.23402, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+16,195256, 530, 1, 1, -696.738, 4172.8, 58.3883, 1.90241, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+17,195256, 530, 1, 1, -646.139, 4161.18, 66.1437, -2.58308, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+18,195256, 530, 1, 1, -597.076, 4097.25, 91.2013, 2.40855, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+19,195256, 530, 1, 1, -594.825, 4161.75, 65.7298, 2.47837, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+20,195256, 530, 1, 1, -661.823, 4157.85, 66.0003, -0.506145, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+21,195256, 530, 1, 1, -614.866, 4105.14, 90.6122, -0.453785, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+22,195256, 530, 1, 1, -685.76, 4176.18, 57.4531, 1.93731, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+23,195256, 530, 1, 1, -597.71, 4154.32, 65.3473, 2.65289, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+24,195256, 530, 1, 1, -2024.57, 5470.97, 3.92836, -0.296705, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+25,195256, 530, 1, 1, -1809.99, 5404.19, -12.5532, 1.95477, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+26,195256, 530, 1, 1, -2001.4, 5370.28, -8.0344, -2.32129, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+27,195256, 530, 1, 1, -1994.43, 5356.16, -8.06764, -2.93214, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+28,195256, 530, 1, 1, -1896.71, 5355.26, -12.4279, 1.01229, 0, 0, 0, 1, 180, 255, 1), +(@OGUID+29,195256, 530, 1, 1, -1942.76, 5448.9, -12.428, 0.034906, 0, 0, 0, 1, 180, 255, 1); + +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN 80000 AND 80029 AND `eventEntry`=24; + +SET @Event:=24; +DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+29 AND `eventEntry`=24; +INSERT INTO `game_event_gameobject` SELECT @Event, gameobject.guid FROM `gameobject` WHERE gameobject.guid BETWEEN @OGUID+0 AND @OGUID+29; diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_10_00_world.sql new file mode 100644 index 00000000000..d5c24c4a65d --- /dev/null +++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_10_00_world.sql @@ -0,0 +1,20 @@ +UPDATE `creature` SET `unit_flags`=33587968 WHERE `guid`IN(53208,53209,53210,53617,53586,53229,53711,53230,53710); + +DELETE FROM `creature_addon` WHERE `guid` IN(53208,53209,53210,53210,53617,53586,53229,53711,53230,53710); +INSERT INTO `creature_addon` (`guid`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(53208, 0, 0x7, 0x1, ''), -- 23232 - 41290 - 41290 +(53209, 0, 0x7, 0x1, ''), -- 23232 - 41290 - 41290 +(53210, 0, 0x7, 0x1, ''), -- 23232 - 41290 - 41290 +(53617, 0, 0x7, 0x1, ''), -- 23236 +(53586, 0, 0x7, 0x1, ''), -- 23236 +(53229, 0, 0x7, 0x1, ''), -- 23235 +(53711, 0, 0x7, 0x1, ''), -- 23237 +(53230, 0, 0x7, 0x1, ''), -- 23235 +(53710, 0, 0x7, 0x1, ''); -- 23237 + +UPDATE `creature_template` SET `ainame`='SmartAI', `scriptname`='' WHERE `entry` IN(23232); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(23232) 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 +(23232, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 11, 41290, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mutant War Hound - On Reset - Cast Disease Cloud'), +(23232, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 11, 41193, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mutant War Hound - On Death - Cast Cloud of Disease'); diff --git a/sql/updates/auth/2016_04_11_00_auth.sql b/sql/updates/auth/2016_04_11_00_auth.sql new file mode 100644 index 00000000000..be8a4d21b66 --- /dev/null +++ b/sql/updates/auth/2016_04_11_00_auth.sql @@ -0,0 +1 @@ +UPDATE `updates` SET `state`='ARCHIVED'; diff --git a/sql/updates/characters/2016_04_11_00_characters.sql b/sql/updates/characters/2016_04_11_00_characters.sql new file mode 100644 index 00000000000..be8a4d21b66 --- /dev/null +++ b/sql/updates/characters/2016_04_11_00_characters.sql @@ -0,0 +1 @@ +UPDATE `updates` SET `state`='ARCHIVED'; diff --git a/sql/updates/world/2016_04_11_00_world.sql b/sql/updates/world/2016_04_11_00_world.sql new file mode 100644 index 00000000000..2f8d539fe43 --- /dev/null +++ b/sql/updates/world/2016_04_11_00_world.sql @@ -0,0 +1,3 @@ +UPDATE `version` SET `db_version`='TDB 335.61', `cache_id`=61 LIMIT 1; + +UPDATE `updates` SET `state`='ARCHIVED'; diff --git a/sql/updates/world/2016_04_11_01_world_335.sql b/sql/updates/world/2016_04_11_01_world_335.sql new file mode 100644 index 00000000000..a432307d0b1 --- /dev/null +++ b/sql/updates/world/2016_04_11_01_world_335.sql @@ -0,0 +1,2 @@ +-- +UPDATE `gameobject` SET `spawntimesecs` = 5 WHERE `guid` IN (45719, 45720, 45721); diff --git a/sql/updates/world/2016_04_11_02_world_335.sql b/sql/updates/world/2016_04_11_02_world_335.sql new file mode 100644 index 00000000000..93b6000554c --- /dev/null +++ b/sql/updates/world/2016_04_11_02_world_335.sql @@ -0,0 +1,2 @@ +-- +UPDATE `spell_group` SET `spell_id`=56112 WHERE `id`=1061 and`spell_id`=46910; diff --git a/sql/updates/world/2016_04_15_03_world_335.sql b/sql/updates/world/2016_04_15_03_world_335.sql new file mode 100644 index 00000000000..afbe3b3ab63 --- /dev/null +++ b/sql/updates/world/2016_04_15_03_world_335.sql @@ -0,0 +1,2 @@ +-- +UPDATE `smart_scripts` SET `action_type`=51, `action_param1`=0 WHERE `entryorguid`=193100 AND `source_type`=9 AND `id`=7; diff --git a/sql/updates/world/dummy b/sql/updates/world/dummy new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/sql/updates/world/dummy diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 4250df6d1f1..0428738f2dd 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -33,8 +33,8 @@ GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_definitions(-DTRINITY_API_EXPORT_COMMON) add_library(common - ${PRIVATE_SOURCES} ${PRIVATE_PCH_SOURCE} + ${PRIVATE_SOURCES} ) # Do NOT add any extra include directory here, as we don't want the common @@ -71,7 +71,9 @@ target_link_libraries(common openssl valgrind threads - jemalloc) + jemalloc + PRIVATE + process) add_dependencies(common revision_data.h) diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h index afb693553a4..a8d792296bb 100644 --- a/src/common/Collision/Management/MMapManager.h +++ b/src/common/Collision/Management/MMapManager.h @@ -75,7 +75,7 @@ namespace MMAP dtNavMesh const* GetNavMesh(uint32 mapId); uint32 getLoadedTilesCount() const { return loadedTiles; } - uint32 getLoadedMapsCount() const { return loadedMMaps.size(); } + uint32 getLoadedMapsCount() const { return uint32(loadedMMaps.size()); } private: bool loadMapData(uint32 mapId); uint32 packTileID(int32 x, int32 y); diff --git a/src/common/Common.h b/src/common/Common.h index 4ab5ae867b9..aa04abacd30 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -21,28 +21,31 @@ #include "Define.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <cmath> -#include <errno.h> -#include <signal.h> -#include <assert.h> - -#include <set> -#include <unordered_set> +#include <algorithm> +#include <array> +#include <exception> #include <list> -#include <string> #include <map> -#include <unordered_map> +#include <memory> #include <queue> +#include <set> #include <sstream> -#include <algorithm> -#include <memory> +#include <string> +#include <type_traits> +#include <unordered_map> +#include <unordered_set> #include <vector> -#include <array> +#include <cmath> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <ctime> +#include <cerrno> +#include <csignal> + +#include <boost/optional.hpp> +#include <boost/utility/in_place_factory.hpp> #include <boost/functional/hash.hpp> #include "Debugging/Errors.h" @@ -151,6 +154,10 @@ typedef std::vector<std::string> StringVector; #define MAX_QUERY_LEN 32*1024 +//! Optional helper class to wrap optional values within. +template <typename T> +using Optional = boost::optional<T>; + namespace Trinity { //! std::make_unique implementation (TODO: remove this once C++14 is supported) diff --git a/src/common/Logging/Appender.h b/src/common/Logging/Appender.h index 22fe1112239..d24daa2b60d 100644 --- a/src/common/Logging/Appender.h +++ b/src/common/Logging/Appender.h @@ -41,7 +41,7 @@ enum LogLevel const uint8 MaxLogLevels = 6; -enum AppenderType +enum AppenderType : uint8 { APPENDER_NONE, APPENDER_CONSOLE, diff --git a/src/common/Utilities/EventMap.h b/src/common/Utilities/EventMap.h index bb40980181d..6a314a9e633 100644 --- a/src/common/Utilities/EventMap.h +++ b/src/common/Utilities/EventMap.h @@ -122,7 +122,7 @@ public: */ void ScheduleEvent(uint32 eventId, Milliseconds const& time, uint32 group = 0, uint8 phase = 0) { - ScheduleEvent(eventId, time.count(), group, phase); + ScheduleEvent(eventId, uint32(time.count()), group, phase); } /** @@ -145,7 +145,7 @@ public: */ void RescheduleEvent(uint32 eventId, Milliseconds const& time, uint32 group = 0, uint8 phase = 0) { - RescheduleEvent(eventId, time.count(), group, phase); + RescheduleEvent(eventId, uint32(time.count()), group, phase); } /** @@ -169,7 +169,7 @@ public: */ void Repeat(Milliseconds const& time) { - Repeat(time.count()); + Repeat(uint32(time.count())); } /** @@ -190,7 +190,7 @@ public: */ void Repeat(Milliseconds const& minTime, Milliseconds const& maxTime) { - Repeat(minTime.count(), maxTime.count()); + Repeat(uint32(minTime.count()), uint32(maxTime.count())); } /** @@ -218,7 +218,7 @@ public: */ void DelayEvents(Milliseconds const& delay) { - DelayEvents(delay.count()); + DelayEvents(uint32(delay.count())); } /** @@ -239,7 +239,7 @@ public: */ void DelayEvents(Milliseconds const& delay, uint32 group) { - DelayEvents(delay.count(), group); + DelayEvents(uint32(delay.count()), group); } /** diff --git a/src/server/shared/Networking/MessageBuffer.h b/src/common/Utilities/MessageBuffer.h index d68bee181b1..d08c4b25bab 100644 --- a/src/server/shared/Networking/MessageBuffer.h +++ b/src/common/Utilities/MessageBuffer.h @@ -20,6 +20,7 @@ #include "Define.h" #include <vector> +#include <cstring> class MessageBuffer { diff --git a/src/common/Utilities/StartProcess.cpp b/src/common/Utilities/StartProcess.cpp new file mode 100644 index 00000000000..c47c02bbe87 --- /dev/null +++ b/src/common/Utilities/StartProcess.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "StartProcess.h" + +#include <atomic> +#include <thread> +#include <functional> + +#include <boost/algorithm/string/join.hpp> +#include <boost/iostreams/stream.hpp> +#include <boost/iostreams/copy.hpp> +#include <boost/iostreams/concepts.hpp> +#include <boost/iostreams/device/file_descriptor.hpp> +#include <boost/process.hpp> +#include <boost/system/system_error.hpp> + +#include "Common.h" +#include "Log.h" + +using namespace boost::process; +using namespace boost::process::initializers; +using namespace boost::iostreams; + +namespace Trinity { + +template<typename T> +class TCLogSink +{ + T callback_; + +public: + typedef char char_type; + typedef sink_tag category; + + // Requires a callback type which has a void(std::string) signature + TCLogSink(T callback) + : callback_(std::move(callback)) { } + + std::streamsize write(const char* str, std::streamsize size) + { + callback_(std::string(str, size)); + return size; + } +}; + +template<typename T> +auto MakeTCLogSink(T&& callback) + -> TCLogSink<typename std::decay<T>::type> +{ + return { std::forward<T>(callback) }; +} + +template<typename T> +static int CreateChildProcess(T waiter, std::string const& executable, + std::vector<std::string> const& args, + std::string const& logger, std::string const& input, + bool secure) +{ + auto outPipe = create_pipe(); + auto errPipe = create_pipe(); + + Optional<file_descriptor_source> inputSource; + + if (!secure) + { + TC_LOG_TRACE(logger.c_str(), "Starting process \"%s\" with arguments: \"%s\".", + executable.c_str(), boost::algorithm::join(args, " ").c_str()); + } + + // Start the child process + child c = [&] + { + if (!input.empty()) + { + inputSource = file_descriptor_source(input); + + // With binding stdin + return execute(run_exe(boost::filesystem::absolute(executable)), + set_args(args), + bind_stdin(*inputSource), + bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)), + bind_stderr(file_descriptor_sink(errPipe.sink, close_handle))); + } + else + { + // Without binding stdin + return execute(run_exe(boost::filesystem::absolute(executable)), + set_args(args), + bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)), + bind_stderr(file_descriptor_sink(errPipe.sink, close_handle))); + } + }(); + + file_descriptor_source outFd(outPipe.source, close_handle); + file_descriptor_source errFd(errPipe.source, close_handle); + + auto outInfo = MakeTCLogSink([&](std::string msg) + { + TC_LOG_INFO(logger.c_str(), "%s", msg.c_str()); + }); + + auto outError = MakeTCLogSink([&](std::string msg) + { + TC_LOG_ERROR(logger.c_str(), "%s", msg.c_str()); + }); + + copy(outFd, outInfo); + copy(errFd, outError); + + // Call the waiter in the current scope to prevent + // the streams from closing too early on leaving the scope. + int const result = waiter(c); + + if (!secure) + { + TC_LOG_TRACE(logger.c_str(), ">> Process \"%s\" finished with return value %i.", + executable.c_str(), result); + } + + if (inputSource) + inputSource->close(); + + return result; +} + +int StartProcess(std::string const& executable, std::vector<std::string> const& args, + std::string const& logger, std::string input_file, bool secure) +{ + return CreateChildProcess([](child& c) -> int + { + try + { + return wait_for_exit(c); + } + catch (...) + { + return EXIT_FAILURE; + } + }, executable, args, logger, input_file, secure); +} + +class AsyncProcessResultImplementation + : public AsyncProcessResult +{ + std::string const executable; + std::vector<std::string> const args; + std::string const logger; + std::string const input_file; + bool const is_secure; + + std::atomic<bool> was_terminated; + + // Workaround for missing move support in boost < 1.57 + Optional<std::shared_ptr<std::future<int>>> result; + Optional<std::reference_wrapper<child>> my_child; + +public: + explicit AsyncProcessResultImplementation(std::string executable_, std::vector<std::string> args_, + std::string logger_, std::string input_file_, + bool secure) + : executable(std::move(executable_)), args(std::move(args_)), + logger(std::move(logger_)), input_file(input_file_), + is_secure(secure), was_terminated(false) { } + + AsyncProcessResultImplementation(AsyncProcessResultImplementation const&) = delete; + AsyncProcessResultImplementation& operator= (AsyncProcessResultImplementation const&) = delete; + AsyncProcessResultImplementation(AsyncProcessResultImplementation&&) = delete; + AsyncProcessResultImplementation& operator= (AsyncProcessResultImplementation&&) = delete; + + int StartProcess() + { + ASSERT(!my_child, "Process started already!"); + + return CreateChildProcess([&](child& c) -> int + { + int result; + my_child = std::reference_wrapper<child>(c); + + try + { + result = wait_for_exit(c); + } + catch (...) + { + result = EXIT_FAILURE; + } + + my_child.reset(); + return was_terminated ? EXIT_FAILURE : result; + + }, executable, args, logger, input_file, is_secure); + } + + void SetFuture(std::future<int> result_) + { + result = std::make_shared<std::future<int>>(std::move(result_)); + } + + /// Returns the future which contains the result of the process + /// as soon it is finished. + std::future<int>& GetFutureResult() override + { + ASSERT(*result, "The process wasn't started!"); + return **result; + } + + /// Tries to terminate the process + void Terminate() override + { + if (!my_child) + { + was_terminated = true; + try + { + terminate(my_child->get()); + } + catch(...) + { + // Do nothing + } + } + } +}; + +TC_COMMON_API std::shared_ptr<AsyncProcessResult> + StartAsyncProcess(std::string executable, std::vector<std::string> args, + std::string logger, std::string input_file, bool secure) +{ + auto handle = std::make_shared<AsyncProcessResultImplementation>( + std::move(executable), std::move(args), std::move(logger), std::move(input_file), secure); + + handle->SetFuture(std::async(std::launch::async, [handle] { return handle->StartProcess(); })); + return handle; +} + +Optional<std::string> SearchExecutableInPath(std::string const& filename) +{ + try + { + auto result = search_path(filename); + if (result.empty()) + return boost::none; + else + return result; + } + catch (...) + { + return boost::none; + } +} + +} // namespace Trinity diff --git a/src/common/Utilities/StartProcess.h b/src/common/Utilities/StartProcess.h new file mode 100644 index 00000000000..3b380bd4f4e --- /dev/null +++ b/src/common/Utilities/StartProcess.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef Process_h__ +#define Process_h__ + +#include <future> +#include <memory> +#include "Common.h" + +namespace Trinity { + +/// Starts a process with the given arguments and parameters and will block +/// until the process is finished. +/// When an input path is given, the file will be routed to the processes stdin. +/// When the process is marked as secure no arguments are leaked to logs. +/// Note that most executables expect it's name as the first argument. +TC_COMMON_API int StartProcess(std::string const& executable, std::vector<std::string> const& args, + std::string const& logger, std::string input_file = "", + bool secure = false); + +/// Platform and library independent representation +/// of asynchronous process results +class AsyncProcessResult +{ +public: + virtual ~AsyncProcessResult() { } + + /// Returns the future which contains the result of the process + /// as soon it is finished. + virtual std::future<int>& GetFutureResult() = 0; + + /// Tries to terminate the process + virtual void Terminate() = 0; +}; + +/// Starts a process asynchronously with the given arguments and parameters and +/// returns an AsyncProcessResult immediately which is set, when the process exits. +/// When an input path is given, the file will be routed to the processes stdin. +/// When the process is marked as secure no arguments are leaked to logs. +/// Note that most executables expect it's name as the first argument. +TC_COMMON_API std::shared_ptr<AsyncProcessResult> + StartAsyncProcess(std::string executable, std::vector<std::string> args, + std::string logger, std::string input_file = "", + bool secure = false); + +/// Searches for the given executable in the PATH variable +/// and returns a present optional when it was found. +TC_COMMON_API Optional<std::string> SearchExecutableInPath(std::string const& filename); + +} // namespace Trinity + +#endif // Process_h__ diff --git a/src/common/Utilities/TaskScheduler.h b/src/common/Utilities/TaskScheduler.h index c5163ef33d5..6784c968683 100644 --- a/src/common/Utilities/TaskScheduler.h +++ b/src/common/Utilities/TaskScheduler.h @@ -401,7 +401,7 @@ private: auto const milli_max = std::chrono::duration_cast<std::chrono::milliseconds>(max); // TC specific: use SFMT URandom - return std::chrono::milliseconds(urand(milli_min.count(), milli_max.count())); + return std::chrono::milliseconds(urand(uint32(milli_min.count()), uint32(milli_max.count()))); } /// Dispatch remaining tasks diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index 6572280d00b..3d8cda66d48 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -22,6 +22,7 @@ #include "utf8.h" #include "Errors.h" // for ASSERT #include <stdarg.h> +#include <boost/algorithm/string/case_conv.hpp> #if COMPILER == COMPILER_GNU #include <sys/socket.h> @@ -425,7 +426,7 @@ bool utf8ToConsole(const std::string& utf8str, std::string& conStr) return false; conStr.resize(wstr.size()); - CharToOemBuffW(&wstr[0], &conStr[0], wstr.size()); + CharToOemBuffW(&wstr[0], &conStr[0], uint32(wstr.size())); #else // not implemented yet conStr = utf8str; @@ -439,7 +440,7 @@ bool consoleToUtf8(const std::string& conStr, std::string& utf8str) #if PLATFORM == PLATFORM_WINDOWS std::wstring wstr; wstr.resize(conStr.size()); - OemToCharBuffW(&conStr[0], &wstr[0], conStr.size()); + OemToCharBuffW(&conStr[0], &wstr[0], uint32(conStr.size())); return WStrToUtf8(wstr, utf8str); #else @@ -457,7 +458,7 @@ bool Utf8FitTo(const std::string& str, std::wstring const& search) return false; // converting to lower case - wstrToLower( temp ); + wstrToLower(temp); if (temp.find(search) == std::wstring::npos) return false; @@ -476,10 +477,10 @@ void utf8printf(FILE* out, const char *str, ...) void vutf8printf(FILE* out, const char *str, va_list* ap) { #if PLATFORM == PLATFORM_WINDOWS - char temp_buf[32*1024]; - wchar_t wtemp_buf[32*1024]; + char temp_buf[32 * 1024]; + wchar_t wtemp_buf[32 * 1024]; - size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap); + size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap); //vsnprintf returns -1 if the buffer is too small if (temp_len == size_t(-1)) temp_len = 32*1024-1; @@ -487,7 +488,7 @@ void vutf8printf(FILE* out, const char *str, va_list* ap) size_t wtemp_len = 32*1024-1; Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); - CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1); + CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], uint32(wtemp_len + 1)); fprintf(out, "%s", temp_buf); #else vfprintf(out, str, *ap); @@ -528,3 +529,34 @@ std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse return ss.str(); } + +void HexStrToByteArray(std::string const& str, uint8* out, bool reverse /*= false*/) +{ + // string must have even number of characters + if (str.length() & 1) + return; + + int32 init = 0; + int32 end = int32(str.length()); + int8 op = 1; + + if (reverse) + { + init = int32(str.length() - 2); + end = -2; + op = -1; + } + + uint32 j = 0; + for (int32 i = init; i != end; i += 2 * op) + { + char buffer[3] = { str[i], str[i + 1], '\0' }; + out[j++] = uint8(strtoul(buffer, NULL, 16)); + } +} + +bool StringToBool(std::string const& str) +{ + std::string lowerStr = boost::algorithm::to_lower_copy(str); + return lowerStr == "1" || lowerStr == "true" || lowerStr == "yes"; +} diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index cd0a8bae823..cc68f3b2237 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -318,6 +318,9 @@ TC_COMMON_API uint32 CreatePIDFile(std::string const& filename); TC_COMMON_API uint32 GetPID(); TC_COMMON_API std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false); +TC_COMMON_API void HexStrToByteArray(std::string const& str, uint8* out, bool reverse = false); + +TC_COMMON_API bool StringToBool(std::string const& str); // simple class for not-modifyable list template <typename T> diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index 1d40129ec1b..d1f0e4460e9 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -31,8 +31,8 @@ endif() GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(authserver - ${PRIVATE_SOURCES} ${PRIVATE_PCH_SOURCE} + ${PRIVATE_SOURCES} ) if( NOT WIN32 ) diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index 982aca58eee..f044e0cea94 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -924,7 +924,7 @@ void AuthSession::RealmListCallback(PreparedQueryResult result) pkt << uint8(lock); // if 1, then realm locked pkt << uint8(flag); // RealmFlags pkt << name; - pkt << boost::lexical_cast<std::string>(GetAddressForClient(realm, GetRemoteIpAddress())); + pkt << boost::lexical_cast<std::string>(realm.GetAddressForClient(GetRemoteIpAddress())); pkt << float(realm.PopulationLevel); pkt << uint8(characterCounts[realm.Id.Realm]); pkt << uint8(realm.Timezone); // realm category diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist index a97d75b3f57..db60e3b3ece 100644 --- a/src/server/authserver/authserver.conf.dist +++ b/src/server/authserver/authserver.conf.dist @@ -184,6 +184,13 @@ LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" LoginDatabase.WorkerThreads = 1 # +# LoginDatabase.SynchThreads +# Description: The amount of MySQL connections spawned to handle. +# Default: 1 - (LoginDatabase.WorkerThreads) + +LoginDatabase.SynchThreads = 1 + +# ################################################################################################### ################################################################################################### diff --git a/src/server/database/CMakeLists.txt b/src/server/database/CMakeLists.txt index 06772cd5309..bd2fa280ad6 100644 --- a/src/server/database/CMakeLists.txt +++ b/src/server/database/CMakeLists.txt @@ -22,8 +22,8 @@ endif() GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_library(database - ${PRIVATE_SOURCES} ${PRIVATE_PCH_SOURCE} + ${PRIVATE_SOURCES} ) # Do NOT add any extra include directory unless it does not create unneeded extra dependencies, @@ -52,7 +52,6 @@ add_definitions(-DTRINITY_API_EXPORT_DATABASE) target_link_libraries(database PUBLIC common - process mysql) set_target_properties(database diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp index 087a35682aa..ba2a4256919 100644 --- a/src/server/database/Database/DatabaseWorkerPool.cpp +++ b/src/server/database/Database/DatabaseWorkerPool.cpp @@ -234,7 +234,7 @@ void DatabaseWorkerPool<T>::EscapeString(std::string& str) return; char* buf = new char[str.size() * 2 + 1]; - EscapeString(buf, str.c_str(), str.size()); + EscapeString(buf, str.c_str(), uint32(str.size())); str = buf; delete[] buf; } diff --git a/src/server/database/Database/Field.h b/src/server/database/Database/Field.h index fd4ddc79450..123e25dbbf3 100644 --- a/src/server/database/Database/Field.h +++ b/src/server/database/Database/Field.h @@ -323,7 +323,7 @@ class TC_DATABASE_API Field data.value = NULL; } - static size_t SizeForType(MYSQL_FIELD* field) + static uint32 SizeForType(MYSQL_FIELD* field) { switch (field->type) { diff --git a/src/server/database/Database/PreparedStatement.cpp b/src/server/database/Database/PreparedStatement.cpp index 848a923c75d..119f1d4c93b 100644 --- a/src/server/database/Database/PreparedStatement.cpp +++ b/src/server/database/Database/PreparedStatement.cpp @@ -344,7 +344,7 @@ void MySQLPreparedStatement::setString(const uint8 index, const char* value) CheckValidIndex(index); m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; - size_t len = strlen(value) + 1; + uint32 len = uint32(strlen(value) + 1); param->buffer_type = MYSQL_TYPE_VAR_STRING; delete [] static_cast<char *>(param->buffer); param->buffer = new char[len]; diff --git a/src/server/database/Database/QueryResult.cpp b/src/server/database/Database/QueryResult.cpp index f02457f67ca..db9e737830c 100644 --- a/src/server/database/Database/QueryResult.cpp +++ b/src/server/database/Database/QueryResult.cpp @@ -76,7 +76,7 @@ m_length(NULL) std::size_t rowSize = 0; for (uint32 i = 0; i < m_fieldCount; ++i) { - size_t size = Field::SizeForType(&field[i]); + uint32 size = Field::SizeForType(&field[i]); rowSize += size; m_rBind[i].buffer_type = field[i].type; diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp index 5f5b519d2b3..3be81e85715 100644 --- a/src/server/database/Updater/DBUpdater.cpp +++ b/src/server/database/Updater/DBUpdater.cpp @@ -22,19 +22,11 @@ #include "DatabaseLoader.h" #include "Config.h" #include "BuiltInConfig.h" +#include "StartProcess.h" #include <fstream> #include <iostream> #include <unordered_map> -#include <boost/process.hpp> -#include <boost/iostreams/stream.hpp> -#include <boost/iostreams/copy.hpp> -#include <boost/iostreams/device/file_descriptor.hpp> -#include <boost/system/system_error.hpp> - -using namespace boost::process; -using namespace boost::process::initializers; -using namespace boost::iostreams; std::string DBUpdaterUtil::GetCorrectedMySQLExecutable() { @@ -51,19 +43,16 @@ bool DBUpdaterUtil::CheckExecutable() { exe.clear(); - try - { - exe = search_path("mysql"); - } - catch (std::runtime_error&) + if (auto path = Trinity::SearchExecutableInPath("mysql")) { - } + exe = std::move(*path); - if (!exe.empty() && exists(exe)) - { - // Correct the path to the cli - corrected_path() = absolute(exe).generic_string(); - return true; + if (!exe.empty() && exists(exe)) + { + // Correct the path to the cli + corrected_path() = absolute(exe).generic_string(); + return true; + } } TC_LOG_FATAL("sql.updates", "Didn't find executeable mysql binary at \'%s\' or in path, correct the path in the *.conf (\"Updates.MySqlCLIPath\").", @@ -387,44 +376,9 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos if (!database.empty()) args.push_back(database); - // ToDo: use the existing query in memory as virtual file if possible - file_descriptor_source source(path); - - uint32 ret; - try - { - boost::process::pipe outPipe = create_pipe(); - boost::process::pipe errPipe = create_pipe(); - - child c = execute(run_exe( - boost::filesystem::absolute(DBUpdaterUtil::GetCorrectedMySQLExecutable()).generic_string()), - set_args(args), bind_stdin(source), throw_on_error(), - bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)), - bind_stderr(file_descriptor_sink(errPipe.sink, close_handle))); - - file_descriptor_source mysqlOutfd(outPipe.source, close_handle); - file_descriptor_source mysqlErrfd(errPipe.source, close_handle); - - stream<file_descriptor_source> mysqlOutStream(mysqlOutfd); - stream<file_descriptor_source> mysqlErrStream(mysqlErrfd); - - std::stringstream out; - std::stringstream err; - - copy(mysqlOutStream, out); - copy(mysqlErrStream, err); - - TC_LOG_INFO("sql.updates", "%s", out.str().c_str()); - TC_LOG_ERROR("sql.updates", "%s", err.str().c_str()); - - ret = wait_for_exit(c); - } - catch (boost::system::system_error&) - { - ret = EXIT_FAILURE; - } - - source.close(); + // Invokes a mysql process which doesn't leak credentials to logs + int const ret = Trinity::StartProcess(DBUpdaterUtil::GetCorrectedMySQLExecutable(), args, + "sql.updates", path.generic_string(), true); if (ret != EXIT_SUCCESS) { diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index 2d60cdb92ef..6f67867c52b 100644 --- a/src/server/database/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp @@ -354,7 +354,7 @@ uint32 UpdateFetcher::Apply(Path const& path) const _applyFile(path); // Return time the query took to apply - return std::chrono::duration_cast<std::chrono::milliseconds>(Time::now() - begin).count(); + return uint32(std::chrono::duration_cast<std::chrono::milliseconds>(Time::now() - begin).count()); } void UpdateFetcher::UpdateEntry(AppliedFileEntry const& entry, uint32 const speed) const diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 859282891fb..9db36c76bb4 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -489,7 +489,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u // unless target is outside spell range, out of mana, or LOS. bool _allowMove = false; - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(e.action.cast.spell); int32 mana = me->GetPower(POWER_MANA); if (me->GetDistance(*itr) > spellInfo->GetMaxRange(true) || diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index ba1738a523b..86aaf45af88 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -859,7 +859,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) if (!IsSpellValid(e, e.action.cast.spell)) return false; - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(e.action.cast.spell); for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) { if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT2)) diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index ebc814405bf..87f5ff6ce5c 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -1533,7 +1533,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) //! Since no common attributes were found, (not even in titleRewardFlags field) //! we explicitly check by ID. Maybe in the future we could move the achievement_reward //! condition fields to the condition system. - if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->GetByteValue(PLAYER_BYTES_3, 0) : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)]) + if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER) : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)]) if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId)) GetPlayer()->SetTitle(titleEntry); diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp index 5acb56b5173..fd105c5b25f 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp @@ -582,13 +582,13 @@ void AuctionBotSeller::LoadSellerValues(SellerConfiguration& config) break; } - config.SetPriceRatioPerQuality(AUCTION_QUALITY_GRAY, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_WHITE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREEN, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_BLUE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_PURPLE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_ORANGE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_YELLOW, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO) / 100); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_GRAY, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_WHITE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREEN, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_BLUE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_PURPLE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_ORANGE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_YELLOW, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO)); config.SetPriceRatioPerClass(ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_PRICE_RATIO)); config.SetPriceRatioPerClass(ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_PRICE_RATIO)); @@ -701,10 +701,10 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf { uint32 classRatio = config.GetPriceRatioPerClass(ItemClass(itemProto->Class)); uint32 qualityRatio = config.GetPriceRatioPerQuality(AuctionQuality(itemProto->Quality)); - uint32 priceRatio = (classRatio * qualityRatio) / 100; + float priceRatio = (classRatio * qualityRatio) / 10000.0f; - uint32 buyPrice = itemProto->BuyPrice; - uint32 sellPrice = itemProto->SellPrice; + float buyPrice = itemProto->BuyPrice; + float sellPrice = itemProto->SellPrice; if (buyPrice == 0) { @@ -712,11 +712,11 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf buyPrice = sellPrice * GetSellModifier(itemProto); else { - uint32 divisor = ((itemProto->Class == 2 || itemProto->Class == 4) ? 284 : 80); - uint32 tempLevel = (itemProto->ItemLevel == 0 ? 1 : itemProto->ItemLevel); - uint32 tempQuality = (itemProto->Quality == 0 ? 1 : itemProto->Quality); + float divisor = ((itemProto->Class == ITEM_CLASS_WEAPON || itemProto->Class == ITEM_CLASS_ARMOR) ? 284.0f : 80.0f); + float tempLevel = (itemProto->ItemLevel == 0 ? 1.0f : itemProto->ItemLevel); + float tempQuality = (itemProto->Quality == 0 ? 1.0f : itemProto->Quality); - buyPrice = tempLevel * tempQuality * GetBuyModifier(itemProto)* tempLevel / divisor; + buyPrice = tempLevel * tempQuality * static_cast<float>(GetBuyModifier(itemProto))* tempLevel / divisor; } } @@ -725,15 +725,16 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf if (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYPRICE_SELLER)) buyPrice = sellPrice; - - uint32 basePrice = (buyPrice * stackCount * priceRatio) / (itemProto->Class == 6 ? 200 : itemProto->BuyCount) / 100; - uint32 range = basePrice * 0.04; - - buyp = urand(basePrice - range, basePrice + range) + 1; - - basePrice = buyp * .5; + + float basePriceFloat = (buyPrice * stackCount * priceRatio) / (itemProto->Class == 6 ? 200.0f : static_cast<float>(itemProto->BuyCount)) / 100.0f; + float range = basePriceFloat * 0.04f; + + buyp = static_cast<uint32>(frand(basePriceFloat - range, basePriceFloat + range) + 0.5f); + if (buyp == 0) + buyp = 1; + uint32 basePrice = buyp * .5; range = buyp * .4; - bidp = urand(basePrice - range, basePrice + range) + 1; + bidp = urand(static_cast<uint32>(basePrice - range + 0.5f), static_cast<uint32>(basePrice + range + 0.5f)) + 1; } // Determines the stack size to use for the item diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index df0d2b7cc2a..239e59d6dbb 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -23,27 +23,36 @@ GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_definitions(-DTRINITY_API_EXPORT_GAME) -add_library(game - ${PRIVATE_SOURCES} - ${PRIVATE_PCH_SOURCE} -) - CollectIncludeDirectories( ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC_INCLUDES # Exclude ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) +# Provide an interface target for the game project to allow +# dependent projects to build meanwhile. +add_library(game-interface INTERFACE) + +target_include_directories(game-interface + INTERFACE + ${PUBLIC_INCLUDES}) + +target_link_libraries(game-interface + INTERFACE + shared + Detour) + +add_library(game + ${PRIVATE_PCH_SOURCE} + ${PRIVATE_SOURCES}) + target_include_directories(game - PUBLIC - ${PUBLIC_INCLUDES} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(game PUBLIC - shared - Detour + game-interface PRIVATE efsw) diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index f0e98ee8c1f..ec90a5f7efb 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -32,18 +32,19 @@ #include "ScriptMgr.h" #include "ChatLink.h" -bool ChatHandler::load_command_table = true; +// Lazy loading of the command table cache from commands and the +// ScriptMgr should be thread safe since the player commands, +// cli commands and ScriptMgr updates are all dispatched one after +// one inside the world update loop. +static Optional<std::vector<ChatCommand>> commandTableCache; std::vector<ChatCommand> const& ChatHandler::getCommandTable() { - static std::vector<ChatCommand> commandTableCache; - - if (LoadCommandTable()) + if (!commandTableCache) { - SetLoadCommandTable(false); - - std::vector<ChatCommand> cmds = sScriptMgr->GetChatCommands(); - commandTableCache.swap(cmds); + // We need to initialize this at top since SetDataForCommandInTable + // calls getCommandTable() recursively. + commandTableCache = sScriptMgr->GetChatCommands(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_COMMANDS); PreparedQueryResult result = WorldDatabase.Query(stmt); @@ -54,13 +55,18 @@ std::vector<ChatCommand> const& ChatHandler::getCommandTable() Field* fields = result->Fetch(); std::string name = fields[0].GetString(); - SetDataForCommandInTable(commandTableCache, name.c_str(), fields[1].GetUInt16(), fields[2].GetString(), name); + SetDataForCommandInTable(*commandTableCache, name.c_str(), fields[1].GetUInt16(), fields[2].GetString(), name); } while (result->NextRow()); } } - return commandTableCache; + return *commandTableCache; +} + +void ChatHandler::invalidateCommandTable() +{ + commandTableCache.reset(); } char const* ChatHandler::GetTrinityString(uint32 entry) const diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index a061ff63b00..1c9368275ad 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -96,6 +96,7 @@ class TC_GAME_API ChatHandler bool ParseCommands(const char* text); static std::vector<ChatCommand> const& getCommandTable(); + static void invalidateCommandTable(); bool isValidChatMessage(const char* msg); void SendGlobalSysMessage(const char *str); @@ -143,8 +144,6 @@ class TC_GAME_API ChatHandler GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(ObjectGuid::LowType lowguid, uint32 entry); bool HasSentErrorMessage() const { return sentErrorMessage; } void SetSentErrorMessage(bool val){ sentErrorMessage = val; } - static bool LoadCommandTable() { return load_command_table; } - static void SetLoadCommandTable(bool val) { load_command_table = val; } bool ShowHelpForCommand(std::vector<ChatCommand> const& table, const char* cmd); protected: @@ -157,7 +156,6 @@ class TC_GAME_API ChatHandler WorldSession* m_session; // != NULL for chat command call and NULL for CLI command // common global flag - static bool load_command_table; bool sentErrorMessage; }; diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 50e3e64ea2c..afb6255079b 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -440,7 +440,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const if (Unit* unit = object->ToUnit()) { if (ConditionValue1 == 0) - condMeets = (unit->getStandState() == ConditionValue2); + condMeets = (unit->GetStandState() == ConditionValue2); else if (ConditionValue2 == 0) condMeets = unit->IsStandState(); else if (ConditionValue2 == 1) @@ -1242,7 +1242,7 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond) const bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond) const { uint32 conditionEffMask = cond->SourceGroup; - SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->EnsureSpellInfo(cond->SourceEntry)); + SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->AssertSpellInfo(cond->SourceEntry)); std::list<uint32> sharedMasks; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 6c51c71fe7b..5ede70da2a3 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -27,6 +27,9 @@ #include <boost/regex.hpp> #include <map> +#include <fstream> +#include <iostream> +#include <iomanip> typedef std::map<uint16, uint32> AreaFlagByAreaID; typedef std::map<uint32, uint32> AreaFlagByMapID; @@ -73,6 +76,7 @@ DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt); DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt); DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt); DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt); +DBCStorage <CinematicCameraEntry> sCinematicCameraStore(CinematicCameraEntryfmt); DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequencesEntryfmt); DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt); DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore(CreatureDisplayInfoExtrafmt); @@ -217,6 +221,8 @@ DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt); DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt); DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt); +std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore; + typedef std::list<std::string> StoreProblemList; uint32 DBCFileCount = 0; @@ -311,6 +317,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicCameraStore, dbcPath, "CinematicCamera.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoExtraStore, dbcPath, "CreatureDisplayInfoExtra.dbc"); @@ -717,10 +724,250 @@ void LoadDBCStores(const std::string& dataPath) exit(1); } + LoadM2Cameras(dataPath); + TC_LOG_INFO("server.loading", ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); } +// Convert the geomoetry from a spline value, to an actual WoW XYZ +G3D::Vector3 TranslateLocation(G3D::Vector4 const* DBCPosition, G3D::Vector3 const* basePosition, G3D::Vector3 const* splineVector) +{ + G3D::Vector3 work; + float x = basePosition->x + splineVector->x; + float y = basePosition->y + splineVector->y; + float z = basePosition->z + splineVector->z; + float const distance = sqrt((x * x) + (y * y)); + float angle = std::atan2(x, y) - DBCPosition->w; + + if (angle < 0) + angle += 2 * float(M_PI); + + work.x = DBCPosition->x + (distance * sin(angle)); + work.y = DBCPosition->y + (distance * cos(angle)); + work.z = DBCPosition->z + z; + return work; +} + +// Number of cameras not used. Multiple cameras never used in 3.3.5 +bool readCamera(M2Camera const* cam, uint32 buffSize, M2Header const* header, CinematicCameraEntry const* dbcentry) +{ + char const* buffer = reinterpret_cast<char const*>(header); + + FlyByCameraCollection cameras; + FlyByCameraCollection targetcam; + + G3D::Vector4 DBCData; + DBCData.x = dbcentry->base_x; + DBCData.y = dbcentry->base_y; + DBCData.z = dbcentry->base_z; + DBCData.w = dbcentry->base_o; + + // Read target locations, only so that we can calculate orientation + for (uint32 k = 0; k < cam->target_positions.timestamps.number; ++k) + { + // Extract Target positions + if (cam->target_positions.timestamps.offset_elements + sizeof(M2Array) > buffSize) + return false; + M2Array const* targTsArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.timestamps.offset_elements); + if (targTsArray->offset_elements + sizeof(uint32) > buffSize || cam->target_positions.values.offset_elements + sizeof(M2Array) > buffSize) + return false; + uint32 const* targTimestamps = reinterpret_cast<uint32 const*>(buffer + targTsArray->offset_elements); + M2Array const* targArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.values.offset_elements); + + if (targArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) + return false; + M2SplineKey<G3D::Vector3> const* targPositions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + targArray->offset_elements); + + // Read the data for this set + uint32 currPos = targArray->offset_elements; + for (uint32 i = 0; i < targTsArray->number; ++i) + { + if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) + return false; + // Translate co-ordinates + G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->target_position_base, &targPositions->p0); + + // Add to vector + FlyByCamera thisCam; + thisCam.timeStamp = targTimestamps[i]; + thisCam.locations.x = newPos.x; + thisCam.locations.y = newPos.y; + thisCam.locations.z = newPos.z; + thisCam.locations.w = 0.0f; + targetcam.push_back(thisCam); + targPositions++; + currPos += sizeof(M2SplineKey<G3D::Vector3>); + } + } + + // Read camera positions and timestamps (translating first position of 3 only, we don't need to translate the whole spline) + for (uint32 k = 0; k < cam->positions.timestamps.number; ++k) + { + // Extract Camera positions for this set + if (cam->positions.timestamps.offset_elements + sizeof(M2Array) > buffSize) + return false; + M2Array const* posTsArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.timestamps.offset_elements); + if (posTsArray->offset_elements + sizeof(uint32) > buffSize || cam->positions.values.offset_elements + sizeof(M2Array) > buffSize) + return false; + uint32 const* posTimestamps = reinterpret_cast<uint32 const*>(buffer + posTsArray->offset_elements); + M2Array const* posArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.values.offset_elements); + if (posArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) + return false; + M2SplineKey<G3D::Vector3> const* positions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + posArray->offset_elements); + + // Read the data for this set + uint32 currPos = posArray->offset_elements; + for (uint32 i = 0; i < posTsArray->number; ++i) + { + if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) + return false; + // Translate co-ordinates + G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->position_base, &positions->p0); + + // Add to vector + FlyByCamera thisCam; + thisCam.timeStamp = posTimestamps[i]; + thisCam.locations.x = newPos.x; + thisCam.locations.y = newPos.y; + thisCam.locations.z = newPos.z; + + if (targetcam.size() > 0) + { + // Find the target camera before and after this camera + FlyByCamera lastTarget; + FlyByCamera nextTarget; + + // Pre-load first item + lastTarget = targetcam[0]; + nextTarget = targetcam[0]; + for (uint32 j = 0; j < targetcam.size(); ++j) + { + nextTarget = targetcam[j]; + if (targetcam[j].timeStamp > posTimestamps[i]) + break; + + lastTarget = targetcam[j]; + } + + float x = lastTarget.locations.x; + float y = lastTarget.locations.y; + float z = lastTarget.locations.z; + + // Now, the timestamps for target cam and position can be different. So, if they differ we interpolate + if (lastTarget.timeStamp != posTimestamps[i]) + { + uint32 timeDiffTarget = nextTarget.timeStamp - lastTarget.timeStamp; + uint32 timeDiffThis = posTimestamps[i] - lastTarget.timeStamp; + float xDiff = nextTarget.locations.x - lastTarget.locations.x; + float yDiff = nextTarget.locations.y - lastTarget.locations.y; + float zDiff = nextTarget.locations.z - lastTarget.locations.z; + x = lastTarget.locations.x + (xDiff * (float(timeDiffThis) / float(timeDiffTarget))); + y = lastTarget.locations.y + (yDiff * (float(timeDiffThis) / float(timeDiffTarget))); + z = lastTarget.locations.z + (zDiff * (float(timeDiffThis) / float(timeDiffTarget))); + } + float xDiff = x - thisCam.locations.x; + float yDiff = y - thisCam.locations.y; + thisCam.locations.w = std::atan2(yDiff, xDiff); + + if (thisCam.locations.w < 0) + thisCam.locations.w += 2 * float(M_PI); + } + + cameras.push_back(thisCam); + positions++; + currPos += sizeof(M2SplineKey<G3D::Vector3>); + } + } + + sFlyByCameraStore[dbcentry->id] = cameras; + return true; +} + +void LoadM2Cameras(const std::string& dataPath) +{ + sFlyByCameraStore.clear(); + TC_LOG_INFO("server.loading", ">> Loading Cinematic Camera files"); + + uint32 oldMSTime = getMSTime(); + for (uint32 i = 0; i < sCinematicCameraStore.GetNumRows(); ++i) + { + if (CinematicCameraEntry const* dbcentry = sCinematicCameraStore.LookupEntry(i)) + { + std::string filename = dataPath.c_str(); + filename.append(dbcentry->filename); + + // Replace slashes + size_t loc = filename.find("\\"); + while (loc != std::string::npos) + { + filename.replace(loc, 1, "/"); + loc = filename.find("\\"); + } + + // Replace mdx to .m2 + loc = filename.find(".mdx"); + if (loc != std::string::npos) + filename.replace(loc, 4, ".m2"); + + std::ifstream m2file(filename.c_str(), std::ios::in | std::ios::binary); + if (!m2file.is_open()) + continue; + + // Get file size + m2file.seekg(0, std::ios::end); + std::streamoff const fileSize = m2file.tellg(); + + // Reject if not at least the size of the header + if (static_cast<uint32 const>(fileSize) < sizeof(M2Header)) + { + TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File is smaller than header size", filename.c_str()); + m2file.close(); + continue; + } + + // Read 4 bytes (signature) + m2file.seekg(0, std::ios::beg); + char fileCheck[5]; + m2file.read(fileCheck, 4); + fileCheck[4] = 0; + + // Check file has correct magic (MD20) + if (strcmp(fileCheck, "MD20")) + { + TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File identifier not found", filename.c_str()); + m2file.close(); + continue; + } + + // Now we have a good file, read it all into a vector of char's, then close the file. + std::vector<char> buffer(fileSize); + m2file.seekg(0, std::ios::beg); + if (!m2file.read(buffer.data(), fileSize)) + { + m2file.close(); + continue; + } + m2file.close(); + + // Read header + M2Header const* header = reinterpret_cast<M2Header const*>(buffer.data()); + + if (header->ofsCameras + sizeof(M2Camera) > static_cast<uint32 const>(fileSize)) + { + TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.c_str()); + continue; + } + + // Get camera(s) - Main header, then dump them. + M2Camera const* cam = reinterpret_cast<M2Camera const*>(buffer.data() + header->ofsCameras); + if (!readCamera(cam, fileSize, header, dbcentry)) + TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.c_str()); + } + } + TC_LOG_INFO("server.loading", ">> Loaded %u cinematic waypoint sets in %u ms", (uint32)sFlyByCameraStore.size(), GetMSTimeDiffToNow(oldMSTime)); +} + SimpleFactionsList const* GetFactionTeamList(uint32 faction) { FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction); @@ -1017,5 +1264,6 @@ ResponseCodes ValidateName(std::string const& name, LocaleConstant locale) EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender) { - return sEmotesTextSoundMap[EmotesTextSoundKey(emote, race, gender)]; + auto itr = sEmotesTextSoundMap.find(EmotesTextSoundKey(emote, race, gender)); + return itr != sEmotesTextSoundMap.end() ? itr->second : nullptr; } diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index beb0bb514cc..6cad13fdf9a 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -27,6 +27,8 @@ #include <list> typedef std::list<uint32> SimpleFactionsList; +typedef std::vector<FlyByCamera> FlyByCameraCollection; + TC_GAME_API SimpleFactionsList const* GetFactionTeamList(uint32 faction); TC_GAME_API char* GetPetName(uint32 petfamily, uint32 dbclang); @@ -96,6 +98,7 @@ TC_GAME_API extern DBCStorage <CharSectionsEntry> sCharSectionsStore; TC_GAME_API extern DBCStorage <CharTitlesEntry> sCharTitlesStore; TC_GAME_API extern DBCStorage <ChrClassesEntry> sChrClassesStore; TC_GAME_API extern DBCStorage <ChrRacesEntry> sChrRacesStore; +TC_GAME_API extern DBCStorage <CinematicCameraEntry> sCinematicCameraStore; TC_GAME_API extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore; TC_GAME_API extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore; TC_GAME_API extern DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore; @@ -193,7 +196,9 @@ TC_GAME_API extern DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore; //TC_GAME_API extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates TC_GAME_API extern DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore; TC_GAME_API extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore; +TC_GAME_API extern std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore; TC_GAME_API void LoadDBCStores(const std::string& dataPath); +TC_GAME_API void LoadM2Cameras(const std::string& dataPath); #endif diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index b5dc4489148..51b3dcbd38b 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -725,24 +725,22 @@ struct ChrRacesEntry uint32 expansion; // 68 (0 - original race, 1 - tbc addon, ...) }; -/* not used struct CinematicCameraEntry { uint32 id; // 0 index char* filename; // 1 uint32 soundid; // 2 in SoundEntries.dbc or 0 - float start_x; // 3 - float start_y; // 4 - float start_z; // 5 - float unk6; // 6 speed? + float base_x; // 3 + float base_y; // 4 + float base_z; // 5 + float base_o; // 6 }; -*/ struct CinematicSequencesEntry { uint32 Id; // 0 index //uint32 unk1; // 1 always 0 - //uint32 cinematicCamera; // 2 id in CinematicCamera.dbc + uint32 cinematicCamera; // 2 id in CinematicCamera.dbc // 3-9 always 0 }; diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index c61ec997bc2..1accc81714b 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -38,7 +38,8 @@ char const CharTitlesEntryfmt[] = "nxssssssssssssssssxssssssssssssssssxi"; char const ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx"; char const ChrClassesEntryfmt[] = "nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii"; char const ChrRacesEntryfmt[] = "niixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; -char const CinematicSequencesEntryfmt[] = "nxxxxxxxxx"; +char const CinematicCameraEntryfmt[] = "nsiffff"; +char const CinematicSequencesEntryfmt[] = "nxixxxxxxx"; char const CreatureDisplayInfofmt[] = "nixifxxxxxxxxxxx"; char const CreatureDisplayInfoExtrafmt[] = "diixxxxxxxxxxxxxxxxxx"; char const CreatureFamilyfmt[] = "nfifiiiiixssssssssssssssssxx"; diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index fe997bc0343..e72859c23e7 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -40,8 +40,6 @@ namespace lfg LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1), m_options(sWorld->getIntConfig(CONFIG_LFG_OPTIONSMASK)) { - new LFGPlayerScript(); - new LFGGroupScript(); } LFGMgr::~LFGMgr() @@ -1148,7 +1146,7 @@ void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdate for (GuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it) { ObjectGuid guid = *it; - queue.AddToQueue(guid); + queue.AddToQueue(guid, true); } ProposalsStore.erase(itProposal); diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp index 314803d1602..d156158dee6 100644 --- a/src/server/game/DungeonFinding/LFGQueue.cpp +++ b/src/server/game/DungeonFinding/LFGQueue.cpp @@ -117,7 +117,7 @@ std::string LFGQueue::GetDetailedMatchRoles(GuidList const& check) const return o.str(); } -void LFGQueue::AddToQueue(ObjectGuid guid) +void LFGQueue::AddToQueue(ObjectGuid guid, bool reAdd) { LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid); if (itQueue == QueueDataStore.end()) @@ -126,7 +126,10 @@ void LFGQueue::AddToQueue(ObjectGuid guid) return; } - AddToNewQueue(guid); + if (reAdd) + AddToFrontCurrentQueue(guid); + else + AddToNewQueue(guid); } void LFGQueue::RemoveFromQueue(ObjectGuid guid) @@ -171,6 +174,11 @@ void LFGQueue::AddToCurrentQueue(ObjectGuid guid) currentQueueStore.push_back(guid); } +void LFGQueue::AddToFrontCurrentQueue(ObjectGuid guid) +{ + currentQueueStore.push_front(guid); +} + void LFGQueue::RemoveFromCurrentQueue(ObjectGuid guid) { currentQueueStore.remove(guid); diff --git a/src/server/game/DungeonFinding/LFGQueue.h b/src/server/game/DungeonFinding/LFGQueue.h index 7c35c4d04e3..32711e81468 100644 --- a/src/server/game/DungeonFinding/LFGQueue.h +++ b/src/server/game/DungeonFinding/LFGQueue.h @@ -89,7 +89,7 @@ class TC_GAME_API LFGQueue // Add/Remove from queue std::string GetDetailedMatchRoles(GuidList const& check) const; - void AddToQueue(ObjectGuid guid); + void AddToQueue(ObjectGuid guid, bool reAdd = false); void RemoveFromQueue(ObjectGuid guid); void AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const& dungeons, LfgRolesMap const& rolesMap); void RemoveQueueData(ObjectGuid guid); @@ -116,6 +116,7 @@ class TC_GAME_API LFGQueue void AddToNewQueue(ObjectGuid guid); void AddToCurrentQueue(ObjectGuid guid); + void AddToFrontCurrentQueue(ObjectGuid guid); void RemoveFromNewQueue(ObjectGuid guid); void RemoveFromCurrentQueue(ObjectGuid guid); diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 79d36055870..1d2b963b254 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -241,4 +241,10 @@ void LFGGroupScript::OnInviteMember(Group* group, ObjectGuid guid) sLFGMgr->LeaveLfg(leader); } +void AddSC_LFGScripts() +{ + new LFGPlayerScript(); + new LFGGroupScript(); +} + } // namespace lfg diff --git a/src/server/game/DungeonFinding/LFGScripts.h b/src/server/game/DungeonFinding/LFGScripts.h index ec64604a282..9f52668ea61 100644 --- a/src/server/game/DungeonFinding/LFGScripts.h +++ b/src/server/game/DungeonFinding/LFGScripts.h @@ -53,4 +53,6 @@ class TC_GAME_API LFGGroupScript : public GroupScript void OnInviteMember(Group* group, ObjectGuid guid) override; }; +/*keep private*/ void AddSC_LFGScripts(); + } // namespace lfg diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 61d5d7d9459..d5e1e0956b1 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -342,10 +342,10 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) m_creatureInfo = cinfo; // map mode related always // equal to player Race field, but creature does not have race - SetByteValue(UNIT_FIELD_BYTES_0, 0, 0); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_RACE, 0); // known valid are: CLASS_WARRIOR, CLASS_PALADIN, CLASS_ROGUE, CLASS_MAGE - SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class)); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, uint8(cinfo->unit_class)); // Cancel load if no model defined if (!(cinfo->GetFirstValidModelId())) @@ -364,7 +364,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) SetDisplayId(displayID); SetNativeDisplayId(displayID); - SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender); // Load creature equipment if (data && data->equipmentId != 0) @@ -791,6 +791,24 @@ void Creature::DoFleeToGetAssistance() } } +bool Creature::AIM_Destroy() +{ + if (m_AI_locked) + { + TC_LOG_DEBUG("scripts", "AIM_Destroy: failed to destroy, locked."); + return false; + } + + ASSERT(!i_disabledAI, + "The disabled AI wasn't cleared!"); + + delete i_AI; + i_AI = nullptr; + + IsAIEnabled = false; + return true; +} + bool Creature::AIM_Initialize(CreatureAI* ai) { // make sure nothing can change the AI during AI update @@ -800,12 +818,12 @@ bool Creature::AIM_Initialize(CreatureAI* ai) return false; } - UnitAI* oldAI = i_AI; + AIM_Destroy(); Motion_Initialize(); i_AI = ai ? ai : FactorySelector::selectAI(this); - delete oldAI; + IsAIEnabled = true; i_AI->InitializeAI(); // Initialize vehicle @@ -889,7 +907,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u { SetDisplayId(displayID); SetNativeDisplayId(displayID); - SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender); } LastUsedScriptID = GetCreatureTemplate()->ScriptID; @@ -1705,7 +1723,7 @@ void Creature::Respawn(bool force) { SetDisplayId(displayID); SetNativeDisplayId(displayID); - SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender); } GetMotionMaster()->InitDefault(); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index c6b19dbb939..8466dad9e95 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -476,6 +476,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool IsInEvadeMode() const { return HasUnitState(UNIT_STATE_EVADE); } + bool AIM_Destroy(); bool AIM_Initialize(CreatureAI* ai = NULL); void Motion_Initialize(); diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 1acfeacbf83..7f922f89572 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -71,9 +71,15 @@ GameObject::~GameObject() // CleanupsBeforeDelete(); } -bool GameObject::AIM_Initialize() +void GameObject::AIM_Destroy() { delete m_AI; + m_AI = nullptr; +} + +bool GameObject::AIM_Initialize() +{ + AIM_Destroy(); m_AI = FactorySelector::SelectGameObjectAI(this); @@ -1282,8 +1288,8 @@ void GameObject::Use(Unit* user) { if (Player* ChairUser = ObjectAccessor::FindPlayer(itr->second)) { - if (ChairUser->IsSitState() && ChairUser->getStandState() != UNIT_STAND_STATE_SIT && ChairUser->GetExactDist2d(x_i, y_i) < 0.1f) - continue; // This seat is already occupied by ChairUser. NOTE: Not sure if the ChairUser->getStandState() != UNIT_STAND_STATE_SIT check is required. + if (ChairUser->IsSitState() && ChairUser->GetStandState() != UNIT_STAND_STATE_SIT && ChairUser->GetExactDist2d(x_i, y_i) < 0.1f) + continue; // This seat is already occupied by ChairUser. NOTE: Not sure if the ChairUser->GetStandState() != UNIT_STAND_STATE_SIT check is required. else itr->second.Clear(); // This seat is unoccupied. } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 49f94013ac2..2b092427178 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -849,8 +849,10 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject> void UpdateModelPosition(); - protected: + void AIM_Destroy(); bool AIM_Initialize(); + + protected: GameObjectModel* CreateModel(); void UpdateModel(); // updates model in case displayId were changed uint32 m_spellId; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 824f42ad671..45952ba51ac 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -928,6 +928,11 @@ bool Object::HasByteFlag(uint16 index, uint8 offset, uint8 flag) const return (((uint8*)&m_uint32Values[index])[offset] & flag) != 0; } +void Object::ApplyModByteFlag(uint16 index, uint8 offset, uint8 flag, bool apply) +{ + if (apply) SetByteFlag(index, offset, flag); else RemoveByteFlag(index, offset, flag); +} + void Object::SetFlag64(uint16 index, uint64 newFlag) { uint64 oldval = GetUInt64Value(index); @@ -1465,9 +1470,20 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const float WorldObject::GetGridActivationRange() const { if (ToPlayer()) + { + if (ToPlayer()->IsOnCinematic()) + return DEFAULT_VISIBILITY_INSTANCE; return GetMap()->GetVisibilityRange(); + } else if (ToCreature()) return ToCreature()->m_SightDistance; + else if (ToDynObject()) + { + if (isActiveObject()) + return GetMap()->GetVisibilityRange(); + else + return 0.0f; + } else return 0.0f; } @@ -1488,6 +1504,8 @@ float WorldObject::GetSightRange(const WorldObject* target) const { if (target && target->isActiveObject() && !target->ToPlayer()) return MAX_VISIBILITY_DISTANCE; + else if (ToPlayer()->IsOnCinematic()) + return DEFAULT_VISIBILITY_INSTANCE; else return GetMap()->GetVisibilityRange(); } @@ -1497,6 +1515,11 @@ float WorldObject::GetSightRange(const WorldObject* target) const return SIGHT_RANGE_UNIT; } + if (ToDynObject() && isActiveObject()) + { + return GetMap()->GetVisibilityRange(); + } + return 0.0f; } diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 029a8c08fd7..d4c8fc35451 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -160,6 +160,7 @@ class TC_GAME_API Object void RemoveByteFlag(uint16 index, uint8 offset, uint8 newFlag); void ToggleByteFlag(uint16 index, uint8 offset, uint8 flag); bool HasByteFlag(uint16 index, uint8 offset, uint8 flag) const; + void ApplyModByteFlag(uint16 index, uint8 offset, uint8 flag, bool apply); void SetFlag64(uint16 index, uint64 newFlag); void RemoveFlag64(uint16 index, uint64 oldFlag); diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 0da63c5e500..37fb23b38f5 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -213,12 +213,14 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c case SUMMON_PET: petlevel = owner->getLevel(); - SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, uint8(CLASS_MAGE)); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: - SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_WARRIOR); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, GENDER_NONE); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, POWER_FOCUS); SetSheath(SHEATH_STATE_MELEE); SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED); @@ -226,7 +228,6 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c // this enables popup window (pet abandon, cancel) SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); SetPower(POWER_HAPPINESS, fields[12].GetUInt32()); - setPowerType(POWER_FOCUS); break; default: if (!IsPetGhoul()) @@ -822,7 +823,9 @@ bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phas if (cinfo->type == CREATURE_TYPE_BEAST) { - SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_WARRIOR); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, GENDER_NONE); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, POWER_FOCUS); SetSheath(SHEATH_STATE_MELEE); SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index a3602166edf..c58f2c940fc 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -96,6 +96,9 @@ #define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x)) #define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t, p) +#define CINEMATIC_LOOKAHEAD (2 * IN_MILLISECONDS) +#define CINEMATIC_UPDATEDIFF 500 + enum CharacterFlags { CHARACTER_FLAG_NONE = 0x00000000, @@ -535,6 +538,14 @@ Player::Player(WorldSession* session): Unit(true) _activeCheats = CHEAT_NONE; healthBeforeDuel = 0; manaBeforeDuel = 0; + + m_cinematicDiff = 0; + m_lastCinematicCheck = 0; + m_activeCinematicCameraId = 0; + m_cinematicCamera = nullptr; + m_remoteSightPosition = Position(0.0f, 0.0f, 0.0f); + m_CinematicObject = nullptr; + m_achievementMgr = new AchievementMgr(this); m_reputationMgr = new ReputationMgr(this); } @@ -643,9 +654,10 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo return false; } - uint32 RaceClassGender = (createInfo->Race) | (createInfo->Class << 8) | (createInfo->Gender << 16); - - SetUInt32Value(UNIT_FIELD_BYTES_0, (RaceClassGender | (powertype << 24))); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_RACE, createInfo->Race); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, createInfo->Class); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, createInfo->Gender); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, powertype); InitDisplayIds(); if (sWorld->getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || sWorld->getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP) { @@ -658,13 +670,14 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); // -1 is default value - SetUInt32Value(PLAYER_BYTES, (createInfo->Skin | (createInfo->Face << 8) | (createInfo->HairStyle << 16) | (createInfo->HairColor << 24))); - SetUInt32Value(PLAYER_BYTES_2, (createInfo->FacialHair | - (0x00 << 8) | - (0x00 << 16) | - (((GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0) ? REST_STATE_RAF_LINKED : REST_STATE_NOT_RAF_LINKED) << 24))); - SetByteValue(PLAYER_BYTES_3, 0, createInfo->Gender); - SetByteValue(PLAYER_BYTES_3, 3, 0); // BattlefieldArenaFaction (0 or 1) + SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID, createInfo->Skin); + SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID, createInfo->Face); + SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID, createInfo->HairStyle); + SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID, createInfo->HairColor); + SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE, createInfo->FacialHair); + SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, (GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0) ? REST_STATE_RAF_LINKED : REST_STATE_NOT_RAF_LINKED); + SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER, createInfo->Gender); + SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_ARENA_FACTION, 0); SetUInt32Value(PLAYER_GUILDID, 0); SetUInt32Value(PLAYER_GUILDRANK, 0); @@ -1179,7 +1192,7 @@ void Player::SetDrunkValue(uint8 newDrunkValue, uint32 itemId /*= 0*/) m_invisibilityDetect.DelFlag(INVISIBILITY_DRUNK); uint32 newDrunkenState = Player::GetDrunkenstateByValue(newDrunkValue); - SetByteValue(PLAYER_BYTES_3, 1, newDrunkValue); + SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION, newDrunkValue); UpdateObjectVisibility(); if (!isSobering) @@ -1222,7 +1235,15 @@ void Player::Update(uint32 p_time) m_spellModTakingSpell = nullptr; } - //used to implement delayed far teleport + // Update cinematic location, if 500ms have passed and we're doing a cinematic now. + m_cinematicDiff += p_time; + if (m_cinematicCamera && m_activeCinematicCameraId && GetMSTimeDiffToNow(m_lastCinematicCheck) > CINEMATIC_UPDATEDIFF) + { + m_lastCinematicCheck = getMSTime(); + UpdateCinematicLocation(p_time); + } + + //used to implement delayed far teleports SetCanDelayTeleport(true); Unit::Update(p_time); SetCanDelayTeleport(false); @@ -2822,8 +2843,8 @@ void Player::GiveLevel(uint8 level) { ++m_grantableLevels; - if (!HasByteFlag(PLAYER_FIELD_BYTES, 1, 0x01)) - SetByteFlag(PLAYER_FIELD_BYTES, 1, 0x01); + if (!HasByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL, 0x01)) + SetByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL, 0x01); } sScriptMgr->OnPlayerLevelChanged(this, oldLevel); @@ -3841,7 +3862,7 @@ bool Player::Has310Flyer(bool checkAllSpells, uint32 excludeSpellId) if (_spell_idx->second->skillId != SKILL_MOUNTS) break; // We can break because mount spells belong only to one skillline (at least 310 flyers do) - spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + spellInfo = sSpellMgr->AssertSpellInfo(itr->first); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED && spellInfo->Effects[i].CalcValue() == 310) @@ -3861,7 +3882,7 @@ void Player::RemoveArenaSpellCooldowns(bool removeActivePetCooldowns) // remove cooldowns on spells that have < 10 min CD GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS; }, true); @@ -4789,7 +4810,7 @@ Corpse* Player::CreateCorpse() // prevent the existence of 2 corpses for one player SpawnCorpseBones(); - uint32 _pb, _pb2, _cfb1, _cfb2; + uint32 _cfb1, _cfb2; Corpse* corpse = new Corpse((m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH) ? CORPSE_RESURRECTABLE_PVP : CORPSE_RESURRECTABLE_PVE); SetPvPDeath(false); @@ -4802,16 +4823,13 @@ Corpse* Player::CreateCorpse() _corpseLocation.WorldRelocate(*this); - _pb = GetUInt32Value(PLAYER_BYTES); - _pb2 = GetUInt32Value(PLAYER_BYTES_2); - - uint8 skin = (uint8)(_pb); - uint8 face = (uint8)(_pb >> 8); - uint8 hairstyle = (uint8)(_pb >> 16); - uint8 haircolor = (uint8)(_pb >> 24); - uint8 facialhair = (uint8)(_pb2); + uint8 skin = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID); + uint8 face = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID); + uint8 hairstyle = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID); + uint8 haircolor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID); + uint8 facialhair = GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE); - _cfb1 = ((0x00) | (getRace() << 8) | (GetByteValue(PLAYER_BYTES_3, 0) << 16) | (skin << 24)); + _cfb1 = ((0x00) | (getRace() << 8) | (GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER) << 16) | (skin << 24)); _cfb2 = ((face) | (hairstyle << 8) | (haircolor << 16) | (facialhair << 24)); corpse->SetUInt32Value(CORPSE_FIELD_BYTES_1, _cfb1); @@ -6399,11 +6417,13 @@ void Player::SendDirectMessage(WorldPacket const* data) const m_session->SendPacket(data); } -void Player::SendCinematicStart(uint32 CinematicSequenceId) const +void Player::SendCinematicStart(uint32 CinematicSequenceId) { WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4); data << uint32(CinematicSequenceId); SendDirectMessage(&data); + if (const CinematicSequencesEntry* sequence = sCinematicSequencesStore.LookupEntry(CinematicSequenceId)) + SetActiveCinematicCamera(sequence->cinematicCamera); } void Player::SendMovieStart(uint32 MovieId) const @@ -10344,8 +10364,7 @@ InventoryResult Player::CanStoreItem_InBag(uint8 bag, ItemPosCountVec &dest, Ite if (pItem2) { // can be merged at least partly - uint8 res = pItem2->CanBeMergedPartlyWith(pProto); - if (res != EQUIP_ERR_OK) + if (pItem2->CanBeMergedPartlyWith(pProto) != EQUIP_ERR_OK) continue; // descrease at current stacksize @@ -10395,8 +10414,7 @@ InventoryResult Player::CanStoreItem_InInventorySlots(uint8 slot_begin, uint8 sl if (pItem2) { // can be merged at least partly - uint8 res = pItem2->CanBeMergedPartlyWith(pProto); - if (res != EQUIP_ERR_OK) + if (pItem2->CanBeMergedPartlyWith(pProto) != EQUIP_ERR_OK) continue; // descrease at current stacksize @@ -11074,7 +11092,7 @@ InventoryResult Player::CanStoreItems(Item** items, int count, uint32* itemLimit continue; // search free slot in bags - for (int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; ++t) + for (uint8 t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; ++t) { if (Bag* bag = GetBagByPos(t)) { @@ -12599,7 +12617,7 @@ void Player::DestroyConjuredItems(bool update) Item* Player::GetItemByEntry(uint32 entry) const { // in inventory - for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) + for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) if (pItem->GetEntry() == entry) return pItem; @@ -12609,14 +12627,14 @@ Item* Player::GetItemByEntry(uint32 entry) const if (pItem->GetEntry() == entry) return pItem; - for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) + for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) if (Bag* pBag = GetBagByPos(i)) for (uint32 j = 0; j < pBag->GetBagSize(); ++j) if (Item* pItem = pBag->GetItemByPos(j)) if (pItem->GetEntry() == entry) return pItem; - for (int i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; ++i) + for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_BAG_END; ++i) if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) if (pItem->GetEntry() == entry) return pItem; @@ -13809,8 +13827,8 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool TC_LOG_ERROR("entities.player", "Player::ApplyEnchantment: Unknown item enchantment (ID: %u, DisplayType: %u) for player '%s' (%s)", enchant_id, enchant_display_type, GetName().c_str(), GetGUID().ToString().c_str()); break; - } /*switch (enchant_display_type)*/ - } /*for*/ + } + } } // visualize enchantment at player and equipped items @@ -16861,12 +16879,9 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) return false; } - // overwrite some data fields - uint32 bytes0 = 0; - bytes0 |= fields[3].GetUInt8(); // race - bytes0 |= fields[4].GetUInt8() << 8; // class - bytes0 |= gender << 16; // gender - SetUInt32Value(UNIT_FIELD_BYTES_0, bytes0); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_RACE, fields[3].GetUInt8()); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, fields[4].GetUInt8()); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, gender); // check if race/class combination is valid PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass()); @@ -16893,25 +16908,25 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) money = MAX_MONEY_AMOUNT; SetMoney(money); - SetByteValue(PLAYER_BYTES, 0, fields[9].GetUInt8()); - SetByteValue(PLAYER_BYTES, 1, fields[10].GetUInt8()); - SetByteValue(PLAYER_BYTES, 2, fields[11].GetUInt8()); - SetByteValue(PLAYER_BYTES, 3, fields[12].GetUInt8()); - SetByteValue(PLAYER_BYTES_2, 0, fields[13].GetUInt8()); - SetByteValue(PLAYER_BYTES_2, 2, fields[14].GetUInt8()); - SetByteValue(PLAYER_BYTES_2, 3, fields[15].GetUInt8()); - SetByteValue(PLAYER_BYTES_3, 0, fields[5].GetUInt8()); - SetByteValue(PLAYER_BYTES_3, 1, fields[54].GetUInt8()); + SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID, fields[9].GetUInt8()); + SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID, fields[10].GetUInt8()); + SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID, fields[11].GetUInt8()); + SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID, fields[12].GetUInt8()); + SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE, fields[13].GetUInt8()); + SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS, fields[14].GetUInt8()); + SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, fields[15].GetUInt8()); + SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER, fields[5].GetUInt8()); + SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION, fields[54].GetUInt8()); if (!ValidateAppearance( fields[3].GetUInt8(), // race fields[4].GetUInt8(), // class gender, - GetByteValue(PLAYER_BYTES, 2), - GetByteValue(PLAYER_BYTES, 3), - GetByteValue(PLAYER_BYTES, 1), - GetByteValue(PLAYER_BYTES_2, 0), - GetByteValue(PLAYER_BYTES, 0))) + GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID), + GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID), + GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID), + GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE), + GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID))) { TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong Appearance values (Hair/Skin/Color), can't load.", guid.ToString().c_str()); return false; @@ -16925,7 +16940,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) SetUInt32Value(PLAYER_AMMO_ID, fields[68].GetUInt32()); // set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise) - SetByteValue(PLAYER_FIELD_BYTES, 2, fields[70].GetUInt8()); + SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES, fields[70].GetUInt8()); InitDisplayIds(); @@ -17508,7 +17523,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_REFER_A_FRIEND); if (m_grantableLevels > 0) - SetByteValue(PLAYER_FIELD_BYTES, 1, 0x01); + SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL, 0x01); _LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES)); @@ -17715,7 +17730,7 @@ void Player::LoadCorpse(PreparedQueryResult result) { Field* fields = result->Fetch(); _corpseLocation.WorldRelocate(fields[0].GetUInt16(), fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat()); - ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(_corpseLocation.GetMapId())->Instanceable()); + ApplyModByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(_corpseLocation.GetMapId())->Instanceable()); } else ResurrectPlayer(0.5f); @@ -17751,7 +17766,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff) ObjectGuid::LowType bagGuid = fields[11].GetUInt32(); uint8 slot = fields[12].GetUInt8(); - uint8 err = EQUIP_ERR_OK; + InventoryResult err = EQUIP_ERR_OK; // Item is not in bag if (!bagGuid) { @@ -17827,7 +17842,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff) else { TC_LOG_ERROR("entities.player", "Player::_LoadInventory: Player '%s' (%s) has item (%s, entry: %u) which can't be loaded into inventory (Bag %u, slot: %u) by reason %u. Item will be sent by mail.", - GetName().c_str(), GetGUID().ToString().c_str(), item->GetGUID().ToString().c_str(), item->GetEntry(), bagGuid, slot, err); + GetName().c_str(), GetGUID().ToString().c_str(), item->GetGUID().ToString().c_str(), item->GetEntry(), bagGuid, slot, uint32(err)); item->DeleteFromInventoryDB(trans); problematicItems.push_back(item); } @@ -18949,17 +18964,17 @@ void Player::SaveToDB(bool create /*=false*/) stmt->setString(index++, GetName()); stmt->setUInt8(index++, getRace()); stmt->setUInt8(index++, getClass()); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, 0)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect stmt->setUInt8(index++, getLevel()); stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP)); stmt->setUInt32(index++, GetMoney()); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 0)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 1)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 2)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 3)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 0)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 2)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 3)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE)); stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS)); stmt->setUInt16(index++, (uint16)GetMapId()); stmt->setUInt32(index++, (uint32)GetInstanceId()); @@ -19049,7 +19064,7 @@ void Player::SaveToDB(bool create /*=false*/) ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << ' '; stmt->setString(index++, ss.str()); - stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, 2)); + stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES)); stmt->setUInt32(index, m_grantableLevels); } else @@ -19059,17 +19074,17 @@ void Player::SaveToDB(bool create /*=false*/) stmt->setString(index++, GetName()); stmt->setUInt8(index++, getRace()); stmt->setUInt8(index++, getClass()); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, 0)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect stmt->setUInt8(index++, getLevel()); stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP)); stmt->setUInt32(index++, GetMoney()); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 0)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 1)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 2)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 3)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 0)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 2)); - stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 3)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS)); + stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE)); stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS)); if (!IsBeingTeleported()) @@ -19174,7 +19189,7 @@ void Player::SaveToDB(bool create /*=false*/) ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << ' '; stmt->setString(index++, ss.str()); - stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, 2)); + stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES)); stmt->setUInt32(index++, m_grantableLevels); stmt->setUInt8(index++, IsInWorld() && !GetSession()->PlayerLogout() ? 1 : 0); @@ -20894,13 +20909,13 @@ void Player::SetRestBonus(float rest_bonus_new) // update data for client if ((GetsRecruitAFriendBonus(true) && (GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0))) - SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_RAF_LINKED); + SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, REST_STATE_RAF_LINKED); else { if (m_rest_bonus > 10) - SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_RESTED); + SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, REST_STATE_RESTED); else if (m_rest_bonus <= 1) - SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_NOT_RAF_LINKED); + SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, REST_STATE_NOT_RAF_LINKED); } //RestTickUpdate @@ -21234,7 +21249,7 @@ void Player::InitDisplayIds() return; } - uint8 gender = GetByteValue(PLAYER_BYTES_3, 0); + uint8 gender = GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER); switch (gender) { case GENDER_FEMALE: @@ -21842,7 +21857,7 @@ void Player::SetBattlegroundEntryPoint() void Player::SetBGTeam(uint32 team) { m_bgData.bgTeam = team; - SetByteValue(PLAYER_BYTES_3, 3, uint8(team == ALLIANCE ? 1 : 0)); + SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_ARENA_FACTION, uint8(team == ALLIANCE ? 1 : 0)); } uint32 Player::GetBGTeam() const @@ -22543,7 +22558,7 @@ void Player::ApplyEquipCooldown(Item* pItem) continue; // Don't replace longer cooldowns by equip cooldown if we have any. - if (GetSpellHistory()->GetRemainingCooldown(sSpellMgr->EnsureSpellInfo(spellData.SpellId)) > 30 * IN_MILLISECONDS) + if (GetSpellHistory()->GetRemainingCooldown(sSpellMgr->AssertSpellInfo(spellData.SpellId)) > 30 * IN_MILLISECONDS) continue; GetSpellHistory()->AddCooldown(spellData.SpellId, pItem->GetEntry(), std::chrono::seconds(30)); @@ -23237,8 +23252,7 @@ void Player::AutoUnequipOffhandIfNeed(bool force /*= false*/) return; ItemPosCountVec off_dest; - uint8 off_msg = CanStoreItem(NULL_BAG, NULL_SLOT, off_dest, offItem, false); - if (off_msg == EQUIP_ERR_OK) + if (CanStoreItem(NULL_BAG, NULL_SLOT, off_dest, offItem, false) == EQUIP_ERR_OK) { RemoveItem(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND, true); StoreItem(off_dest, offItem, true); @@ -24064,10 +24078,10 @@ uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 n if (level > GT_MAX_LEVEL) level = GT_MAX_LEVEL; // max level in this dbc - uint8 hairstyle = GetByteValue(PLAYER_BYTES, 2); - uint8 haircolor = GetByteValue(PLAYER_BYTES, 3); - uint8 facialhair = GetByteValue(PLAYER_BYTES_2, 0); - uint8 skincolor = GetByteValue(PLAYER_BYTES, 0); + uint8 hairstyle = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID); + uint8 haircolor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID); + uint8 facialhair = GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE); + uint8 skincolor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID); if ((hairstyle == newhairstyle) && (haircolor == newhaircolor) && (facialhair == newfacialhair) && (!newSkin || (newSkin->hair_id == skincolor))) return 0; @@ -26097,6 +26111,9 @@ bool Player::SetCanFly(bool apply, bool packetOnly /*= false*/) if (!packetOnly && !Unit::SetCanFly(apply)) return false; + if (!apply) + SetFallInformation(0, GetPositionZ()); + WorldPacket data(apply ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12); data << GetPackGUID(); data << uint32(0); //! movement counter @@ -26193,6 +26210,125 @@ float Player::GetCollisionHeight(bool mounted) const } } +void Player::BeginCinematic() +{ + // Sanity check for active camera set + if (m_activeCinematicCameraId == 0) + return; + + auto itr = sFlyByCameraStore.find(m_activeCinematicCameraId); + if (itr != sFlyByCameraStore.end()) + { + // Initialize diff, and set camera + m_cinematicDiff = 0; + m_cinematicCamera = &itr->second; + + auto camitr = m_cinematicCamera->begin(); + if (camitr != m_cinematicCamera->end()) + { + Position pos(camitr->locations.x, camitr->locations.y, camitr->locations.z, camitr->locations.w); + if (!pos.IsPositionValid()) + return; + + m_mapRef->LoadGrid(camitr->locations.x, camitr->locations.y); + m_CinematicObject = SummonCreature(VISUAL_WAYPOINT, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000); + if (m_CinematicObject) + { + m_CinematicObject->setActive(true); + SetViewpoint(m_CinematicObject, true); + } + } + } +} + +void Player::EndCinematic() +{ + m_cinematicDiff = 0; + m_cinematicCamera = nullptr; + m_activeCinematicCameraId = 0; + if (m_CinematicObject) + { + if (m_seer && m_seer == m_CinematicObject) + SetViewpoint(m_CinematicObject, false); + m_CinematicObject->AddObjectToRemoveList(); + } +} + +void Player::UpdateCinematicLocation(uint32 /*diff*/) +{ + Position lastPosition; + uint32 lastTimestamp = 0; + Position nextPosition; + uint32 nextTimestamp = 0; + + if (m_cinematicCamera->size() == 0) + return; + + // Obtain direction of travel + for (FlyByCamera cam : *m_cinematicCamera) + { + if (cam.timeStamp > m_cinematicDiff) + { + nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); + nextTimestamp = cam.timeStamp; + break; + } + lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); + lastTimestamp = cam.timeStamp; + } + float angle = lastPosition.GetAngle(&nextPosition); + angle -= lastPosition.GetOrientation(); + if (angle < 0) + angle += 2 * float(M_PI); + + // Look for position around 2 second ahead of us. + int32 workDiff = m_cinematicDiff; + + // Modify result based on camera direction (Humans for example, have the camera point behind) + workDiff += static_cast<int32>(float(CINEMATIC_LOOKAHEAD) * cos(angle)); + + // Get an iterator to the last entry in the cameras, to make sure we don't go beyond the end + FlyByCameraCollection::const_reverse_iterator endItr = m_cinematicCamera->rbegin(); + if (endItr != m_cinematicCamera->rend() && workDiff > static_cast<int32>(endItr->timeStamp)) + workDiff = endItr->timeStamp; + + // Never try to go back in time before the start of cinematic! + if (workDiff < 0) + workDiff = m_cinematicDiff; + + // Obtain the previous and next waypoint based on timestamp + for (FlyByCamera cam : *m_cinematicCamera) + { + if (static_cast<int32>(cam.timeStamp) >= workDiff) + { + nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); + nextTimestamp = cam.timeStamp; + break; + } + lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); + lastTimestamp = cam.timeStamp; + } + + // Never try to go beyond the end of the cinematic + if (workDiff > static_cast<int32>(nextTimestamp)) + workDiff = static_cast<int32>(nextTimestamp); + + // Interpolate the position for this moment in time (or the adjusted moment in time) + uint32 timeDiff = nextTimestamp - lastTimestamp; + uint32 interDiff = workDiff - lastTimestamp; + float xDiff = nextPosition.m_positionX - lastPosition.m_positionX; + float yDiff = nextPosition.m_positionY - lastPosition.m_positionY; + float zDiff = nextPosition.m_positionZ - lastPosition.m_positionZ; + Position interPosition(lastPosition.m_positionX + (xDiff * (float(interDiff)/float(timeDiff))), lastPosition.m_positionY + + (yDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionZ + (zDiff * (float(interDiff) / float(timeDiff)))); + + // Advance (at speed) to this position. The remote sight object is used + // to send update information to player in cinematic + if (m_CinematicObject && interPosition.IsPositionValid()) + m_CinematicObject->MonsterMoveWithSpeed(interPosition.m_positionX, interPosition.m_positionY, interPosition.m_positionZ, 200.0f, false, true); +} + + std::string Player::GetMapAreaAndZoneString() const { uint32 areaId = GetAreaId(); @@ -26288,7 +26424,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy case SUMMON_PET: // this enables pet details window (Shift+P) pet->GetCharmInfo()->SetPetNumber(pet_number, true); - pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048); + pet->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_MAGE); pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); pet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000); pet->SetFullHealth(); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 91a4a403fab..fd0fac69674 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -315,7 +315,7 @@ enum RuneCooldowns RUNE_MISS_COOLDOWN = 1500 // cooldown applied on runes when the spell misses }; -enum RuneType +enum RuneType : uint8 { RUNE_BLOOD = 0, RUNE_UNHOLY = 1, @@ -415,50 +415,48 @@ enum PlayerFlags PLAYER_FLAGS_UNK31 = 0x80000000 }; -// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1) -// can't use enum for uint64 values -#define PLAYER_TITLE_DISABLED UI64LIT(0x0000000000000000) -#define PLAYER_TITLE_NONE UI64LIT(0x0000000000000001) -#define PLAYER_TITLE_PRIVATE UI64LIT(0x0000000000000002) // 1 -#define PLAYER_TITLE_CORPORAL UI64LIT(0x0000000000000004) // 2 -#define PLAYER_TITLE_SERGEANT_A UI64LIT(0x0000000000000008) // 3 -#define PLAYER_TITLE_MASTER_SERGEANT UI64LIT(0x0000000000000010) // 4 -#define PLAYER_TITLE_SERGEANT_MAJOR UI64LIT(0x0000000000000020) // 5 -#define PLAYER_TITLE_KNIGHT UI64LIT(0x0000000000000040) // 6 -#define PLAYER_TITLE_KNIGHT_LIEUTENANT UI64LIT(0x0000000000000080) // 7 -#define PLAYER_TITLE_KNIGHT_CAPTAIN UI64LIT(0x0000000000000100) // 8 -#define PLAYER_TITLE_KNIGHT_CHAMPION UI64LIT(0x0000000000000200) // 9 -#define PLAYER_TITLE_LIEUTENANT_COMMANDER UI64LIT(0x0000000000000400) // 10 -#define PLAYER_TITLE_COMMANDER UI64LIT(0x0000000000000800) // 11 -#define PLAYER_TITLE_MARSHAL UI64LIT(0x0000000000001000) // 12 -#define PLAYER_TITLE_FIELD_MARSHAL UI64LIT(0x0000000000002000) // 13 -#define PLAYER_TITLE_GRAND_MARSHAL UI64LIT(0x0000000000004000) // 14 -#define PLAYER_TITLE_SCOUT UI64LIT(0x0000000000008000) // 15 -#define PLAYER_TITLE_GRUNT UI64LIT(0x0000000000010000) // 16 -#define PLAYER_TITLE_SERGEANT_H UI64LIT(0x0000000000020000) // 17 -#define PLAYER_TITLE_SENIOR_SERGEANT UI64LIT(0x0000000000040000) // 18 -#define PLAYER_TITLE_FIRST_SERGEANT UI64LIT(0x0000000000080000) // 19 -#define PLAYER_TITLE_STONE_GUARD UI64LIT(0x0000000000100000) // 20 -#define PLAYER_TITLE_BLOOD_GUARD UI64LIT(0x0000000000200000) // 21 -#define PLAYER_TITLE_LEGIONNAIRE UI64LIT(0x0000000000400000) // 22 -#define PLAYER_TITLE_CENTURION UI64LIT(0x0000000000800000) // 23 -#define PLAYER_TITLE_CHAMPION UI64LIT(0x0000000001000000) // 24 -#define PLAYER_TITLE_LIEUTENANT_GENERAL UI64LIT(0x0000000002000000) // 25 -#define PLAYER_TITLE_GENERAL UI64LIT(0x0000000004000000) // 26 -#define PLAYER_TITLE_WARLORD UI64LIT(0x0000000008000000) // 27 -#define PLAYER_TITLE_HIGH_WARLORD UI64LIT(0x0000000010000000) // 28 -#define PLAYER_TITLE_GLADIATOR UI64LIT(0x0000000020000000) // 29 -#define PLAYER_TITLE_DUELIST UI64LIT(0x0000000040000000) // 30 -#define PLAYER_TITLE_RIVAL UI64LIT(0x0000000080000000) // 31 -#define PLAYER_TITLE_CHALLENGER UI64LIT(0x0000000100000000) // 32 -#define PLAYER_TITLE_SCARAB_LORD UI64LIT(0x0000000200000000) // 33 -#define PLAYER_TITLE_CONQUEROR UI64LIT(0x0000000400000000) // 34 -#define PLAYER_TITLE_JUSTICAR UI64LIT(0x0000000800000000) // 35 -#define PLAYER_TITLE_CHAMPION_OF_THE_NAARU UI64LIT(0x0000001000000000) // 36 -#define PLAYER_TITLE_MERCILESS_GLADIATOR UI64LIT(0x0000002000000000) // 37 -#define PLAYER_TITLE_OF_THE_SHATTERED_SUN UI64LIT(0x0000004000000000) // 38 -#define PLAYER_TITLE_HAND_OF_ADAL UI64LIT(0x0000008000000000) // 39 -#define PLAYER_TITLE_VENGEFUL_GLADIATOR UI64LIT(0x0000010000000000) // 40 +enum PlayerBytesOffsets +{ + PLAYER_BYTES_OFFSET_SKIN_ID = 0, + PLAYER_BYTES_OFFSET_FACE_ID = 1, + PLAYER_BYTES_OFFSET_HAIR_STYLE_ID = 2, + PLAYER_BYTES_OFFSET_HAIR_COLOR_ID = 3 +}; + +enum PlayerBytes2Offsets +{ + PLAYER_BYTES_2_OFFSET_FACIAL_STYLE = 0, + PLAYER_BYTES_2_OFFSET_PARTY_TYPE = 1, + PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS = 2, + PLAYER_BYTES_2_OFFSET_REST_STATE = 3 +}; + +enum PlayerBytes3Offsets +{ + PLAYER_BYTES_3_OFFSET_GENDER = 0, + PLAYER_BYTES_3_OFFSET_INEBRIATION = 1, + PLAYER_BYTES_3_OFFSET_PVP_TITLE = 2, + PLAYER_BYTES_3_OFFSET_ARENA_FACTION = 3 +}; + +enum PlayerFieldBytesOffsets +{ + PLAYER_FIELD_BYTES_OFFSET_FLAGS = 0, + PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL = 1, + PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES = 2, + PLAYER_FIELD_BYTES_OFFSET_LIFETIME_MAX_PVP_RANK = 3 +}; + +enum PlayerFieldBytes2Offsets +{ + PLAYER_FIELD_BYTES_2_OFFSET_OVERRIDE_SPELLS_ID = 0, // uint16! + PLAYER_FIELD_BYTES_2_OFFSET_IGNORE_POWER_REGEN_PREDICTION_MASK = 2, + PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION = 3 +}; + +static_assert((PLAYER_FIELD_BYTES_2_OFFSET_OVERRIDE_SPELLS_ID & 1) == 0, "PLAYER_FIELD_BYTES_2_OFFSET_OVERRIDE_SPELLS_ID must be aligned to 2 byte boundary"); + +#define PLAYER_BYTES_2_OVERRIDE_SPELLS_UINT16_OFFSET (PLAYER_FIELD_BYTES_2_OFFSET_OVERRIDE_SPELLS_ID / 2) #define KNOWN_TITLES_SIZE 3 #define MAX_TITLE_INDEX (KNOWN_TITLES_SIZE*64) // 3 uint64 fields @@ -584,7 +582,7 @@ enum PlayerSlots #define INVENTORY_SLOT_BAG_0 255 -enum EquipmentSlots // 19 slots +enum EquipmentSlots : uint8 // 19 slots { EQUIPMENT_SLOT_START = 0, EQUIPMENT_SLOT_HEAD = 0, @@ -609,13 +607,13 @@ enum EquipmentSlots // 19 slots EQUIPMENT_SLOT_END = 19 }; -enum InventorySlots // 4 slots +enum InventorySlots : uint8 // 4 slots { INVENTORY_SLOT_BAG_START = 19, INVENTORY_SLOT_BAG_END = 23 }; -enum InventoryPackSlots // 16 slots +enum InventoryPackSlots : uint8 // 16 slots { INVENTORY_SLOT_ITEM_START = 23, INVENTORY_SLOT_ITEM_END = 39 @@ -640,7 +638,7 @@ enum BuyBackSlots // 12 slots BUYBACK_SLOT_END = 86 }; -enum KeyRingSlots // 32 slots +enum KeyRingSlots : uint8 // 32 slots { KEYRING_SLOT_START = 86, KEYRING_SLOT_END = 118 @@ -750,7 +748,7 @@ enum TeleportToOptions }; /// Type of environmental damages -enum EnviromentalDamage +enum EnviromentalDamage : uint8 { DAMAGE_EXHAUSTED = 0, DAMAGE_DROWNING = 1, @@ -902,7 +900,7 @@ enum ReferAFriendError ERR_REFER_A_FRIEND_SUMMON_OFFLINE_S = 0x0D }; -enum PlayerRestState +enum PlayerRestState : uint8 { REST_STATE_RESTED = 0x01, REST_STATE_NOT_RAF_LINKED = 0x02, @@ -1185,8 +1183,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> static bool IsBankPos(uint8 bag, uint8 slot); bool IsValidPos(uint16 pos, bool explicit_pos) const { return IsValidPos(pos >> 8, pos & 255, explicit_pos); } bool IsValidPos(uint8 bag, uint8 slot, bool explicit_pos) const; - uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, 2); } - void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, 2, count); } + uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS); } + void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS, count); } bool HasItemCount(uint32 item, uint32 count = 1, bool inBankAlso = false) const; bool HasItemFitToSpellRequirements(SpellInfo const* spellInfo, Item const* ignoreItem = nullptr) const; bool CanNoReagentCast(SpellInfo const* spellInfo) const; @@ -1911,7 +1909,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> //End of PvP System void SetDrunkValue(uint8 newDrunkValue, uint32 itemId = 0); - uint8 GetDrunkValue() const { return GetByteValue(PLAYER_BYTES_3, 1); } + uint8 GetDrunkValue() const { return GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION); } static DrunkenState GetDrunkenstateByValue(uint8 value); uint32 GetDeathTimer() const { return m_deathTimer; } @@ -2131,7 +2129,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void ResummonPetTemporaryUnSummonedIfAny(); bool IsPetNeedBeTemporaryUnsummoned() const; - void SendCinematicStart(uint32 CinematicSequenceId) const; + void SendCinematicStart(uint32 CinematicSequenceId); void SendMovieStart(uint32 MovieId) const; /*********************************************************/ @@ -2267,6 +2265,17 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> std::string GetMapAreaAndZoneString() const; std::string GetCoordsMapAreaAndZoneString() const; + // Cinematic camera data and remote sight functions + uint32 GetActiveCinematicCamera() const { return m_activeCinematicCameraId; } + void SetActiveCinematicCamera(uint32 cinematicCameraId = 0) { m_activeCinematicCameraId = cinematicCameraId; } + bool IsOnCinematic() const { return (m_cinematicCamera != nullptr); } + void BeginCinematic(); + void EndCinematic(); + void UpdateCinematicLocation(uint32 diff); + + std::string GetMapAreaAndZoneString(); + std::string GetCoordsMapAreaAndZoneString(); + protected: // Gamemaster whisper whitelist GuidList WhisperList; @@ -2592,6 +2601,14 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> uint32 manaBeforeDuel; WorldLocation _corpseLocation; + + // Remote location information + uint32 m_cinematicDiff; + uint32 m_lastCinematicCheck; + uint32 m_activeCinematicCameraId; + FlyByCameraCollection* m_cinematicCamera; + Position m_remoteSightPosition; + Creature* m_CinematicObject; }; TC_GAME_API void AddItemsSetItem(Player* player, Item* item); diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index a8e13a9f7db..82792a49c96 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -1152,7 +1152,7 @@ bool Guardian::UpdateStats(Stats stat) if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue()); } } @@ -1321,7 +1321,7 @@ void Guardian::UpdateAttackPowerAndDamage(bool ranged) if (itr != ToPet()->m_spells.end()) // If pet has Wild Hunt { - SpellInfo const* sProto = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + SpellInfo const* sProto = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value mod += CalculatePct(1.0f, sProto->Effects[1].CalcValue()); } } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 912f0a75ab3..41f6f02b32b 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8715,7 +8715,7 @@ void Unit::setPowerType(Powers new_powertype) if (getPowerType() == new_powertype) return; - SetByteValue(UNIT_FIELD_BYTES_0, 3, new_powertype); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, new_powertype); if (GetTypeId() == TYPEID_PLAYER) { @@ -14721,7 +14721,7 @@ void Unit::SendMovementFlagUpdate(bool self /* = false */) bool Unit::IsSitState() const { - uint8 s = getStandState(); + uint8 s = GetStandState(); return s == UNIT_STAND_STATE_SIT_CHAIR || s == UNIT_STAND_STATE_SIT_LOW_CHAIR || s == UNIT_STAND_STATE_SIT_MEDIUM_CHAIR || s == UNIT_STAND_STATE_SIT_HIGH_CHAIR || @@ -14730,7 +14730,7 @@ bool Unit::IsSitState() const bool Unit::IsStandState() const { - uint8 s = getStandState(); + uint8 s = GetStandState(); return !IsSitState() && s != UNIT_STAND_STATE_SLEEP && s != UNIT_STAND_STATE_KNEEL; } @@ -14767,7 +14767,7 @@ void Unit::SetDisplayId(uint32 modelId) SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId); // Set Gender by modelId if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId)) - SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender); } void Unit::RestoreDisplayId() @@ -16078,7 +16078,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au if (cinfo && cinfo->type == CREATURE_TYPE_DEMON) { // to prevent client crash - SetByteValue(UNIT_FIELD_BYTES_0, 1, (uint8)CLASS_MAGE); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, (uint8)CLASS_MAGE); // just to enable stat window if (GetCharmInfo()) @@ -16180,7 +16180,7 @@ void Unit::RemoveCharmedBy(Unit* charmer) CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate(); if (cinfo && cinfo->type == CREATURE_TYPE_DEMON) { - SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class)); + SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, uint8(cinfo->unit_class)); if (GetCharmInfo()) GetCharmInfo()->SetPetNumber(0, true); else @@ -16698,7 +16698,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const // Based on Hair color if (getRace() == RACE_NIGHTELF) { - uint8 hairColor = GetByteValue(PLAYER_BYTES, 3); + uint8 hairColor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID); switch (hairColor) { case 7: // Violet @@ -16719,7 +16719,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const // Based on Skin color else if (getRace() == RACE_TAUREN) { - uint8 skinColor = GetByteValue(PLAYER_BYTES, 0); + uint8 skinColor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID); // Male if (getGender() == GENDER_MALE) { @@ -16778,7 +16778,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const // Based on Hair color if (getRace() == RACE_NIGHTELF) { - uint8 hairColor = GetByteValue(PLAYER_BYTES, 3); + uint8 hairColor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID); switch (hairColor) { case 0: // Green @@ -16798,7 +16798,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const // Based on Skin color else if (getRace() == RACE_TAUREN) { - uint8 skinColor = GetByteValue(PLAYER_BYTES, 0); + uint8 skinColor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID); // Male if (getGender() == GENDER_MALE) { diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 4841cac84cf..9255ce039f3 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -190,6 +190,30 @@ enum UnitStandFlags UNIT_STAND_FLAGS_ALL = 0xFF }; +enum UnitBytes0Offsets +{ + UNIT_BYTES_0_OFFSET_RACE = 0, + UNIT_BYTES_0_OFFSET_CLASS = 1, + UNIT_BYTES_0_OFFSET_GENDER = 2, + UNIT_BYTES_0_OFFSET_POWER_TYPE = 3, +}; + +enum UnitBytes1Offsets +{ + UNIT_BYTES_1_OFFSET_STAND_STATE = 0, + UNIT_BYTES_1_OFFSET_PET_TALENTS = 1, + UNIT_BYTES_1_OFFSET_VIS_FLAG = 2, + UNIT_BYTES_1_OFFSET_ANIM_TIER = 3 +}; + +enum UnitBytes2Offsets +{ + UNIT_BYTES_2_OFFSET_SHEATH_STATE = 0, + UNIT_BYTES_2_OFFSET_PVP_FLAG = 1, + UNIT_BYTES_2_OFFSET_PET_FLAG = 2, + UNIT_BYTES_2_OFFSET_SHAPESHIFT = 3, +}; + // byte flags value (UNIT_FIELD_BYTES_1, 3) enum UnitBytes1_Flags { @@ -536,7 +560,7 @@ enum UnitMoveType TC_GAME_API extern float baseMoveSpeed[MAX_MOVE_TYPE]; TC_GAME_API extern float playerBaseMoveSpeed[MAX_MOVE_TYPE]; -enum WeaponAttackType +enum WeaponAttackType : uint8 { BASE_ATTACK = 0, OFF_ATTACK = 1, @@ -1043,7 +1067,7 @@ enum ReactStates REACT_AGGRESSIVE = 2 }; -enum CommandStates +enum CommandStates : uint8 { COMMAND_STAY = 0, COMMAND_FOLLOW = 1, @@ -1314,11 +1338,11 @@ class TC_GAME_API Unit : public WorldObject uint8 getLevel() const { return uint8(GetUInt32Value(UNIT_FIELD_LEVEL)); } uint8 getLevelForTarget(WorldObject const* /*target*/) const override { return getLevel(); } void SetLevel(uint8 lvl); - uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, 0); } + uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_RACE); } uint32 getRaceMask() const { return 1 << (getRace()-1); } - uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); } + uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS); } uint32 getClassMask() const { return 1 << (getClass()-1); } - uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); } + uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER); } float GetStat(Stats stat) const { return float(GetUInt32Value(UNIT_FIELD_STAT0+stat)); } void SetStat(Stats stat, int32 val) { SetStatInt32Value(UNIT_FIELD_STAT0+stat, val); } @@ -1347,7 +1371,7 @@ class TC_GAME_API Unit : public WorldObject int32 ModifyHealth(int32 val); int32 GetHealthGain(int32 dVal); - Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); } + Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE)); } void setPowerType(Powers power); uint32 GetPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_POWER1 +power); } uint32 GetMaxPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_MAXPOWER1+power); } @@ -1388,7 +1412,7 @@ class TC_GAME_API Unit : public WorldObject uint32 GetCreatureType() const; uint32 GetCreatureTypeMask() const; - uint8 getStandState() const { return GetByteValue(UNIT_FIELD_BYTES_1, 0); } + uint8 GetStandState() const { return GetByteValue(UNIT_FIELD_BYTES_1, 0); } bool IsSitState() const; bool IsStandState() const; void SetStandState(uint8 state); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index fc7d668ae0b..3efeb1ca273 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4715,7 +4715,7 @@ void ObjectMgr::LoadScripts(ScriptsType type) if (tableName.empty()) return; - if (sScriptMgr->IsScriptScheduled()) // function cannot be called when scripts are in use. + if (sMapMgr->IsScriptScheduled()) // function cannot be called when scripts are in use. return; TC_LOG_INFO("server.loading", "Loading %s...", tableName.c_str()); @@ -5162,7 +5162,7 @@ void ObjectMgr::LoadSpellScriptNames() while (spellInfo) { - _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName))); + _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, std::make_pair(GetScriptId(scriptName), true))); spellInfo = spellInfo->GetNextRankSpell(); } } @@ -5171,7 +5171,7 @@ void ObjectMgr::LoadSpellScriptNames() if (spellInfo->IsRanked()) TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is ranked spell. Perhaps not all ranks are assigned to this script.", scriptName.c_str(), spellId); - _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName))); + _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, std::make_pair(GetScriptId(scriptName), true))); } ++count; @@ -5193,45 +5193,59 @@ void ObjectMgr::ValidateSpellScripts() uint32 count = 0; - for (SpellScriptsContainer::iterator itr = _spellScriptsStore.begin(); itr != _spellScriptsStore.end();) + for (auto spell : _spellScriptsStore) { - SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->first); - std::vector<std::pair<SpellScriptLoader *, SpellScriptsContainer::iterator> > SpellScriptLoaders; - sScriptMgr->CreateSpellScriptLoaders(itr->first, SpellScriptLoaders); - itr = _spellScriptsStore.upper_bound(itr->first); + SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spell.first); - for (std::vector<std::pair<SpellScriptLoader *, SpellScriptsContainer::iterator> >::iterator sitr = SpellScriptLoaders.begin(); sitr != SpellScriptLoaders.end(); ++sitr) + auto const bounds = sObjectMgr->GetSpellScriptsBounds(spell.first); + + for (auto itr = bounds.first; itr != bounds.second; ++itr) { - SpellScript* spellScript = sitr->first->GetSpellScript(); - AuraScript* auraScript = sitr->first->GetAuraScript(); - bool valid = true; - if (!spellScript && !auraScript) - { - TC_LOG_ERROR("scripts", "Functions GetSpellScript() and GetAuraScript() of script `%s` do not return objects - script skipped", GetScriptName(sitr->second->second).c_str()); - valid = false; - } - if (spellScript) - { - spellScript->_Init(&sitr->first->GetName(), spellEntry->Id); - spellScript->_Register(); - if (!spellScript->_Validate(spellEntry)) - valid = false; - delete spellScript; - } - if (auraScript) + if (SpellScriptLoader* spellScriptLoader = sScriptMgr->GetSpellScriptLoader(itr->second.first)) { - auraScript->_Init(&sitr->first->GetName(), spellEntry->Id); - auraScript->_Register(); - if (!auraScript->_Validate(spellEntry)) - valid = false; - delete auraScript; - } - if (!valid) - { - _spellScriptsStore.erase(sitr->second); + ++count; + + std::unique_ptr<SpellScript> spellScript(spellScriptLoader->GetSpellScript()); + std::unique_ptr<AuraScript> auraScript(spellScriptLoader->GetAuraScript()); + + if (!spellScript && !auraScript) + { + TC_LOG_ERROR("scripts", "Functions GetSpellScript() and GetAuraScript() of script `%s` do not return objects - script skipped", GetScriptName(itr->second.first).c_str()); + + itr->second.second = false; + continue; + } + + if (spellScript) + { + spellScript->_Init(&spellScriptLoader->GetName(), spellEntry->Id); + spellScript->_Register(); + + if (!spellScript->_Validate(spellEntry)) + { + itr->second.second = false; + continue; + } + } + + if (auraScript) + { + auraScript->_Init(&spellScriptLoader->GetName(), spellEntry->Id); + auraScript->_Register(); + + if (!auraScript->_Validate(spellEntry)) + { + itr->second.second = false; + continue; + } + } + + // Enable the script when all checks passed + itr->second.second = true; } + else + itr->second.second = false; } - ++count; } TC_LOG_INFO("server.loading", ">> Validated %u scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); @@ -8571,6 +8585,8 @@ void ObjectMgr::LoadScriptNames() { uint32 oldMSTime = getMSTime(); + // We insert an empty placeholder here so we can use the + // script id 0 as dummy for "no script found". _scriptNamesStore.emplace_back(""); QueryResult result = WorldDatabase.Query( @@ -8612,18 +8628,18 @@ void ObjectMgr::LoadScriptNames() std::sort(_scriptNamesStore.begin(), _scriptNamesStore.end()); -#ifdef SCRIPTS - for (size_t i = 1; i < _scriptNamesStore.size(); ++i) - UnusedScriptNames.push_back(_scriptNamesStore[i]); -#endif - TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " ScriptNames in %u ms", _scriptNamesStore.size(), GetMSTimeDiffToNow(oldMSTime)); } +ObjectMgr::ScriptNameContainer const& ObjectMgr::GetAllScriptNames() const +{ + return _scriptNamesStore; +} + std::string const& ObjectMgr::GetScriptName(uint32 id) const { static std::string const empty = ""; - return id < _scriptNamesStore.size() ? _scriptNamesStore[id] : empty; + return (id < _scriptNamesStore.size()) ? _scriptNamesStore[id] : empty; } diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 73c03849699..576a8d2ccac 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -370,7 +370,7 @@ struct ScriptInfo typedef std::multimap<uint32, ScriptInfo> ScriptMap; typedef std::map<uint32, ScriptMap > ScriptMapMap; -typedef std::multimap<uint32, uint32> SpellScriptsContainer; +typedef std::multimap<uint32 /*spell id*/, std::pair<uint32 /*script id*/, bool /*enabled*/>> SpellScriptsContainer; typedef std::pair<SpellScriptsContainer::iterator, SpellScriptsContainer::iterator> SpellScriptsBounds; TC_GAME_API extern ScriptMapMap sSpellScripts; TC_GAME_API extern ScriptMapMap sEventScripts; @@ -1272,6 +1272,7 @@ class TC_GAME_API ObjectMgr bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const; void LoadScriptNames(); + ScriptNameContainer const& GetAllScriptNames() const; std::string const& GetScriptName(uint32 id) const; uint32 GetScriptId(std::string const& name); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 2b4b77dc7a9..19638ec1bf8 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -642,7 +642,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), createInfo->Name.c_str(), newChar.GetGUID().GetCounter()); sScriptMgr->OnPlayerCreate(&newChar); - sWorld->AddCharacterInfo(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.GetByteValue(PLAYER_BYTES_3, 0), newChar.getRace(), newChar.getClass(), newChar.getLevel()); + sWorld->AddCharacterInfo(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER), newChar.getRace(), newChar.getClass(), newChar.getLevel()); newChar.CleanupsBeforeDelete(); delete createInfo; @@ -1242,20 +1242,25 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData) BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair); - if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->GetByteValue(PLAYER_BYTES_3, 0)) + if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)) return; BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair); - if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->GetByteValue(PLAYER_BYTES_3, 0)) + if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)) return; BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(SkinColor); - if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->GetByteValue(PLAYER_BYTES_3, 0))) + if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER))) return; - if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->GetByteValue(PLAYER_BYTES_3, 0), bs_hair->hair_id, Color, _player->GetByteValue(PLAYER_BYTES, 1), bs_facialHair->hair_id, bs_skinColor ? bs_skinColor->hair_id : _player->GetByteValue(PLAYER_BYTES, 0))) + if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER), + bs_hair->hair_id, + Color, + _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID), + bs_facialHair->hair_id, + bs_skinColor ? bs_skinColor->hair_id : _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID))) return; GameObject* go = _player->FindNearestGameObjectOfType(GAMEOBJECT_TYPE_BARBER_CHAIR, 5.0f); @@ -1265,7 +1270,7 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData) return; } - if (_player->getStandState() != UNIT_STAND_STATE_SIT_LOW_CHAIR + go->GetGOInfo()->barberChair.chairheight) + if (_player->GetStandState() != UNIT_STAND_STATE_SIT_LOW_CHAIR + go->GetGOInfo()->barberChair.chairheight) { SendBarberShopResult(BARBER_SHOP_RESULT_NOT_ON_CHAIR); return; @@ -1287,11 +1292,11 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData) _player->ModifyMoney(-int32(cost)); // it isn't free _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost); - _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id)); - _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color)); - _player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id)); + _player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID, uint8(bs_hair->hair_id)); + _player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID, uint8(Color)); + _player->SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE, uint8(bs_facialHair->hair_id)); if (bs_skinColor) - _player->SetByteValue(PLAYER_BYTES, 0, uint8(bs_skinColor->hair_id)); + _player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID, uint8(bs_skinColor->hair_id)); _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 91df877e936..467d3730ab2 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -284,7 +284,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData) continue; uint32 pzoneid = target->GetZoneId(); - uint8 gender = target->GetByteValue(PLAYER_BYTES_3, 0); + uint8 gender = target->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER); bool z_show = true; for (uint32 i = 0; i < zones_count; ++i) @@ -405,7 +405,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/) // not set flags if player can't free move to prevent lost state at logout cancel if (GetPlayer()->CanFreeMove()) { - if (GetPlayer()->getStandState() == UNIT_STAND_STATE_STAND) + if (GetPlayer()->GetStandState() == UNIT_STAND_STATE_STAND) GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); WorldPacket data(SMSG_FORCE_MOVE_ROOT, (8+4)); // guess size @@ -1056,12 +1056,14 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recvData) void WorldSession::HandleCompleteCinematic(WorldPacket& /*recvData*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_COMPLETE_CINEMATIC"); + // If player has sight bound to visual waypoint NPC we should remove it + GetPlayer()->EndCinematic(); } void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recvData*/) { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_NEXT_CINEMATIC_CAMERA"); + // Sent by client when cinematic actually begun. So we begin the server side process + GetPlayer()->BeginCinematic(); } void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData) @@ -1157,7 +1159,7 @@ void WorldSession::HandleSetActionBarToggles(WorldPacket& recvData) return; } - GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, actionBar); + GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES, actionBar); } void WorldSession::HandlePlayedTime(WorldPacket& recvData) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 6be1fd30ae3..e07e10ab00c 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -594,11 +594,11 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData) if (creator->GetTypeId() == TYPEID_PLAYER) { Player* player = creator->ToPlayer(); - data << uint8(player->GetByteValue(PLAYER_BYTES, 0)); // skin - data << uint8(player->GetByteValue(PLAYER_BYTES, 1)); // face - data << uint8(player->GetByteValue(PLAYER_BYTES, 2)); // hair - data << uint8(player->GetByteValue(PLAYER_BYTES, 3)); // haircolor - data << uint8(player->GetByteValue(PLAYER_BYTES_2, 0)); // facialhair + data << uint8(player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID)); + data << uint8(player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID)); + data << uint8(player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID)); + data << uint8(player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID)); + data << uint8(player->GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE)); data << uint32(player->GetGuildId()); // unk static EquipmentSlots const itemSlots[] = diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 1575b50098f..0887d183a8b 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -29,6 +29,8 @@ #include "Pet.h" #include "WorldSession.h" #include "Opcodes.h" +#include "ScriptReloadMgr.h" +#include "ScriptMgr.h" BossBoundaryData::~BossBoundaryData() { @@ -36,6 +38,18 @@ BossBoundaryData::~BossBoundaryData() delete it->Boundary; } +InstanceScript::InstanceScript(Map* map) : instance(map), completedEncounters(0) +{ +#ifdef TRINITY_API_USE_DYNAMIC_LINKING + uint32 scriptId = sObjectMgr->GetInstanceTemplate(map->GetId())->ScriptId; + auto const scriptname = sObjectMgr->GetScriptName(scriptId); + ASSERT(!scriptname.empty()); + // Acquire a strong reference from the script module + // to keep it loaded until this object is destroyed. + module_reference = sScriptMgr->AcquireModuleReferenceOfScriptName(scriptname); +#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING +} + void InstanceScript::SaveToDB() { std::string data = GetSaveData(); diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 949cdf5abcb..3814afe2f4b 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -36,6 +36,7 @@ class Unit; class Player; class GameObject; class Creature; +class ModuleReference; enum EncounterFrameType { @@ -137,7 +138,7 @@ typedef std::map<uint32 /*entry*/, uint32 /*type*/> ObjectInfoMap; class TC_GAME_API InstanceScript : public ZoneScript { public: - explicit InstanceScript(Map* map) : instance(map), completedEncounters(0) { } + explicit InstanceScript(Map* map); virtual ~InstanceScript() { } @@ -289,6 +290,11 @@ class TC_GAME_API InstanceScript : public ZoneScript ObjectInfoMap _gameObjectInfo; ObjectGuidMap _objectGuids; uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets + + #ifdef TRINITY_API_USE_DYNAMIC_LINKING + // Strong reference to the associated script module + std::shared_ptr<ModuleReference> module_reference; + #endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING }; template<class AI, class T> diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index 41feb7b26e2..0afb327d7f0 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -54,7 +54,7 @@ enum RollMask #define MAX_NR_QUEST_ITEMS 32 // unrelated to the number of quest items shown, just for reserve -enum LootMethod +enum LootMethod : uint8 { FREE_FOR_ALL = 0, ROUND_ROBIN = 1, @@ -74,7 +74,7 @@ enum PermissionTypes NONE_PERMISSION = 6 }; -enum LootType +enum LootType : uint8 { LOOT_NONE = 0, diff --git a/src/server/game/Maps/AreaBoundary.h b/src/server/game/Maps/AreaBoundary.h index a8780ddb60f..0973d1a6e86 100644 --- a/src/server/game/Maps/AreaBoundary.h +++ b/src/server/game/Maps/AreaBoundary.h @@ -40,7 +40,7 @@ class TC_GAME_API AreaBoundary { double d_positionX, d_positionY, d_positionZ; DoublePosition(double x = 0.0, double y = 0.0, double z = 0.0, float o = 0.0f) - : Position(x, y, z, o), d_positionX(x), d_positionY(y), d_positionZ(z) { } + : Position(float(x), float(y), float(z), o), d_positionX(x), d_positionY(y), d_positionZ(z) { } DoublePosition(float x, float y = 0.0f, float z = 0.0f, float o = 0.0f) : Position(x, y, z, o), d_positionX(x), d_positionY(y), d_positionZ(z) { } DoublePosition(const Position& pos) diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 8640150d86b..664ed3dc8ec 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -17,6 +17,7 @@ */ #include "Map.h" +#include "MapManager.h" #include "Battleground.h" #include "MMapFactory.h" #include "CellImpl.h" @@ -64,7 +65,7 @@ Map::~Map() } if (!m_scriptSchedule.empty()) - sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); + sMapMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); } @@ -713,6 +714,15 @@ void Map::Update(const uint32 t_diff) VisitNearbyCellsOf(player, grid_object_update, world_object_update); + // If player is using far sight, visit that object too + if (WorldObject* viewPoint = player->GetViewpoint()) + { + if (Creature* viewCreature = viewPoint->ToCreature()) + VisitNearbyCellsOf(viewCreature, grid_object_update, world_object_update); + else if (DynamicObject* viewObject = viewPoint->ToDynObject()) + VisitNearbyCellsOf(viewObject, grid_object_update, world_object_update); + } + // Handle updates for creatures in combat with player and are more than 60 yards away if (player->IsInCombat()) { @@ -2657,8 +2667,8 @@ void Map::UpdateObjectsVisibilityFor(Player* player, Cell cell, CellCoord cellpa cell.SetNoCreate(); TypeContainerVisitor<Trinity::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier); TypeContainerVisitor<Trinity::VisibleNotifier, GridTypeMapContainer > grid_notifier(notifier); - cell.Visit(cellpair, world_notifier, *this, *player, player->GetSightRange()); - cell.Visit(cellpair, grid_notifier, *this, *player, player->GetSightRange()); + cell.Visit(cellpair, world_notifier, *this, *player->m_seer, player->GetSightRange()); + cell.Visit(cellpair, grid_notifier, *this, *player->m_seer, player->GetSightRange()); // send data notifier.SendToSelf(); diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp index c1882b3dc75..79a8b3855e8 100644 --- a/src/server/game/Maps/MapManager.cpp +++ b/src/server/game/Maps/MapManager.cpp @@ -38,10 +38,10 @@ #include "AchievementMgr.h" MapManager::MapManager() + : _nextInstanceId(0), _scheduledScripts(0) { i_gridCleanUpDelay = sWorld->getIntConfig(CONFIG_INTERVAL_GRIDCLEAN); i_timer.SetInterval(sWorld->getIntConfig(CONFIG_INTERVAL_MAPUPDATE)); - _nextInstanceId = 0; } MapManager::~MapManager() { } diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index e74453a1196..a7fdc37d324 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -126,6 +126,11 @@ class TC_GAME_API MapManager template<typename Worker> void DoForAllMapsWithMapId(uint32 mapId, Worker&& worker); + uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; } + uint32 DecreaseScheduledScriptCount() { return --_scheduledScripts; } + uint32 DecreaseScheduledScriptCount(size_t count) { return _scheduledScripts -= count; } + bool IsScriptScheduled() const { return _scheduledScripts > 0; } + private: typedef std::unordered_map<uint32, Map*> MapMapType; typedef std::vector<bool> InstanceIds; @@ -150,6 +155,9 @@ class TC_GAME_API MapManager InstanceIds _instanceIds; uint32 _nextInstanceId; MapUpdater m_updater; + + // atomic op counter for active scripts amount + std::atomic<uint32> _scheduledScripts; }; template<typename Worker> diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Maps/MapScripts.cpp index a01c109b9ca..c5d7bdc64ce 100644 --- a/src/server/game/Scripting/MapScripts.cpp +++ b/src/server/game/Maps/MapScripts.cpp @@ -21,6 +21,7 @@ #include "GridNotifiersImpl.h" #include "GossipDef.h" #include "Map.h" +#include "MapManager.h" #include "ObjectMgr.h" #include "Pet.h" #include "Item.h" @@ -58,7 +59,7 @@ void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, O if (iter->first == 0) immedScript = true; - sScriptMgr->IncreaseScheduledScriptsCount(); + sMapMgr->IncreaseScheduledScriptsCount(); } ///- If one of the effects should be immediate, launch the script execution if (/*start &&*/ immedScript && !i_scriptLock) @@ -86,7 +87,7 @@ void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* sou sa.script = &script; m_scriptSchedule.insert(ScriptScheduleMap::value_type(time_t(sWorld->GetGameTime() + delay), sa)); - sScriptMgr->IncreaseScheduledScriptsCount(); + sMapMgr->IncreaseScheduledScriptsCount(); ///- If effects should be immediate, launch the script execution if (delay == 0 && !i_scriptLock) @@ -878,6 +879,6 @@ void Map::ScriptsProcess() m_scriptSchedule.erase(iter); iter = m_scriptSchedule.begin(); - sScriptMgr->DecreaseScheduledScriptCount(); + sMapMgr->DecreaseScheduledScriptCount(); } } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index dcee5ff7071..ca63137ac93 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -887,7 +887,9 @@ enum TrinityStrings LANG_CHARACTER_DELETED_LIST_LINE_CHAT = 1026, LANG_SQLDRIVER_QUERY_LOGGING_ENABLED = 1027, LANG_SQLDRIVER_QUERY_LOGGING_DISABLED = 1028, - // Room for more level 4 1029-1099 not used + LANG_ACCOUNT_INVALID_BNET_NAME = 1029, // 6.x ONLY + LANG_ACCOUNT_USE_BNET_COMMANDS = 1030, // 6.x enum value name but different text in DB + // Room for more level 4 1031-1099 not used // Level 3 (continue) LANG_ACCOUNT_SETADDON = 1100, diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 77d6f739da6..aa45c5024e6 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -23,7 +23,7 @@ #include "DetourNavMesh.h" #include <cassert> -enum SpellEffIndex +enum SpellEffIndex : uint8 { EFFECT_0 = 0, EFFECT_1 = 1, diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 2a57524cb3c..b01ddcb060d 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -302,6 +302,27 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generate } } +void MotionMaster::MoveCloserAndStop(uint32 id, Unit* target, float distance) +{ + float distanceToTravel = _owner->GetExactDist2d(target) - distance; + if (distanceToTravel > 0.0f) + { + float angle = _owner->GetAngle(target); + float destx = _owner->GetPositionX() + distanceToTravel * std::cos(angle); + float desty = _owner->GetPositionY() + distanceToTravel * std::sin(angle); + MovePoint(id, destx, desty, target->GetPositionZ()); + } + else + { + // we are already close enough. We just need to turn toward the target without changing position. + Movement::MoveSplineInit init(_owner); + init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZMinusOffset()); + init.SetFacing(target); + init.Launch(); + Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE); + } +} + void MotionMaster::MoveLand(uint32 id, Position const& pos) { float x, y, z; diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index d1c6474fb36..7d6d512e88d 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -173,6 +173,12 @@ class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *> { MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath); } void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true); + /* Makes the unit move toward the target until it is at a certain distance from it. The unit then stops. + Only works in 2D. + This method doesn't account for any movement done by the target. in other words, it only works if the target is stationary. + */ + void MoveCloserAndStop(uint32 id, Unit* target, float distance); + // These two movement types should only be used with creatures having landing/takeoff animations void MoveLand(uint32 id, Position const& pos); void MoveTakeoff(uint32 id, Position const& pos); diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp index 7f0695e16b3..aa00d211d6e 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp @@ -33,8 +33,14 @@ void OutdoorPvPMgr::Die() for (OutdoorPvPSet::iterator itr = m_OutdoorPvPSet.begin(); itr != m_OutdoorPvPSet.end(); ++itr) delete *itr; + m_OutdoorPvPSet.clear(); + for (OutdoorPvPDataMap::iterator itr = m_OutdoorPvPDatas.begin(); itr != m_OutdoorPvPDatas.end(); ++itr) delete itr->second; + + m_OutdoorPvPDatas.clear(); + + m_OutdoorPvPMap.clear(); } OutdoorPvPMgr* OutdoorPvPMgr::instance() diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 75b52bb4537..5e3bb4889ab 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -60,7 +60,7 @@ enum QuestFailedReason INVALIDREASON_DAILY_QUEST_COMPLETED_TODAY = 29 // You have completed that daily quest today. }; -enum QuestShareMessages +enum QuestShareMessages : uint8 { QUEST_PARTY_MSG_SHARING_QUEST = 0, QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1, diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 4218746893f..ca1cd71363e 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -17,6 +17,7 @@ */ #include "ScriptMgr.h" +#include "ScriptReloadMgr.h" #include "Config.h" #include "DatabaseEnv.h" #include "DBCStores.h" @@ -34,11 +35,9 @@ #include "WorldPacket.h" #include "WorldSession.h" #include "Chat.h" - -// namespace -// { - UnusedScriptNamesContainer UnusedScriptNames; -// } +#include "MapManager.h" +#include "LFGScripts.h" +#include "InstanceScript.h" // Trait which indicates whether this script type // must be assigned in the database. @@ -67,6 +66,10 @@ struct is_script_database_bound<GameObjectScript> : std::true_type { }; template<> +struct is_script_database_bound<VehicleScript> + : std::true_type { }; + +template<> struct is_script_database_bound<AreaTriggerScript> : std::true_type { }; @@ -94,143 +97,846 @@ template<> struct is_script_database_bound<AchievementCriteriaScript> : std::true_type { }; +enum Spells +{ + SPELL_HOTSWAP_VISUAL_SPELL_EFFECT = 40162 // 59084 +}; + +class ScriptRegistryInterface +{ +public: + ScriptRegistryInterface() { } + virtual ~ScriptRegistryInterface() { } + + ScriptRegistryInterface(ScriptRegistryInterface const&) = delete; + ScriptRegistryInterface(ScriptRegistryInterface&&) = delete; + + ScriptRegistryInterface& operator= (ScriptRegistryInterface const&) = delete; + ScriptRegistryInterface& operator= (ScriptRegistryInterface&&) = delete; + + /// Removes all scripts associated with the given script context. + /// Requires ScriptRegistryBase::SwapContext to be called after all transfers have finished. + virtual void ReleaseContext(std::string const& context) = 0; + + /// Injects and updates the changed script objects. + virtual void SwapContext(bool initialize) = 0; + + /// Removes the scripts used by this registry from the given container. + /// Used to find unused script names. + virtual void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) = 0; + + /// Unloads the script registry. + virtual void Unload() = 0; +}; + +template<class> +class ScriptRegistry; + +class ScriptRegistryCompositum + : public ScriptRegistryInterface +{ + ScriptRegistryCompositum() { } + + template<class> + friend class ScriptRegistry; + + /// Type erasure wrapper for objects + class DeleteableObjectBase + { + public: + DeleteableObjectBase() { } + virtual ~DeleteableObjectBase() { } + + DeleteableObjectBase(DeleteableObjectBase const&) = delete; + DeleteableObjectBase& operator= (DeleteableObjectBase const&) = delete; + }; + + template<typename T> + class DeleteableObject + : public DeleteableObjectBase + { + public: + DeleteableObject(T&& object) + : _object(std::forward<T>(object)) { } + + private: + T _object; + }; + +public: + void SetScriptNameInContext(std::string const& scriptname, std::string const& context) + { + ASSERT(_scriptnames_to_context.find(scriptname) == _scriptnames_to_context.end(), + "Scriptname was assigned to this context already!"); + _scriptnames_to_context.insert(std::make_pair(scriptname, context)); + } + + std::string const& GetScriptContextOfScriptName(std::string const& scriptname) const + { + auto itr = _scriptnames_to_context.find(scriptname); + ASSERT(itr != _scriptnames_to_context.end() && + "Given scriptname doesn't exist!"); + return itr->second; + } + + void ReleaseContext(std::string const& context) final override + { + for (auto const registry : _registries) + registry->ReleaseContext(context); + + // Clear the script names in context after calling the release hooks + // since it's possible that new references to a shared library + // are acquired when releasing. + for (auto itr = _scriptnames_to_context.begin(); + itr != _scriptnames_to_context.end();) + if (itr->second == context) + itr = _scriptnames_to_context.erase(itr); + else + ++itr; + } + + void SwapContext(bool initialize) final override + { + for (auto const registry : _registries) + registry->SwapContext(initialize); + + DoDelayedDelete(); + } + + void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override + { + for (auto const registry : _registries) + registry->RemoveUsedScriptsFromContainer(scripts); + } + + void Unload() final override + { + for (auto const registry : _registries) + registry->Unload(); + } + + template<typename T> + void QueueForDelayedDelete(T&& any) + { + _delayed_delete_queue.push_back( + Trinity::make_unique< + DeleteableObject<typename std::decay<T>::type> + >(std::forward<T>(any)) + ); + } + + static ScriptRegistryCompositum* Instance() + { + static ScriptRegistryCompositum instance; + return &instance; + } + +private: + void Register(ScriptRegistryInterface* registry) + { + _registries.insert(registry); + } + + void DoDelayedDelete() + { + _delayed_delete_queue.clear(); + } + + std::unordered_set<ScriptRegistryInterface*> _registries; + + std::vector<std::unique_ptr<DeleteableObjectBase>> _delayed_delete_queue; + + std::unordered_map< + std::string /*script name*/, + std::string /*context*/ + > _scriptnames_to_context; +}; + +#define sScriptRegistryCompositum ScriptRegistryCompositum::Instance() + +template<typename /*ScriptType*/, bool /*IsDatabaseBound*/> +class SpecializedScriptRegistry; + // This is the global static registry of scripts. -template<class TScript> -class ScriptRegistry +template<class ScriptType> +class ScriptRegistry final + : public SpecializedScriptRegistry< + ScriptType, is_script_database_bound<ScriptType>::value> +{ + ScriptRegistry() + { + sScriptRegistryCompositum->Register(this); + } + +public: + static ScriptRegistry* Instance() + { + static ScriptRegistry instance; + return &instance; + } + + void LogDuplicatedScriptPointerError(ScriptType const* first, ScriptType const* second) + { + // See if the script is using the same memory as another script. If this happens, it means that + // someone forgot to allocate new memory for a script. + TC_LOG_ERROR("scripts", "Script '%s' has same memory pointer as '%s'.", + first->GetName().c_str(), second->GetName().c_str()); + } +}; + +class ScriptRegistrySwapHookBase +{ +public: + ScriptRegistrySwapHookBase() { } + virtual ~ScriptRegistrySwapHookBase() { } + + ScriptRegistrySwapHookBase(ScriptRegistrySwapHookBase const&) = delete; + ScriptRegistrySwapHookBase(ScriptRegistrySwapHookBase&&) = delete; + + ScriptRegistrySwapHookBase& operator= (ScriptRegistrySwapHookBase const&) = delete; + ScriptRegistrySwapHookBase& operator= (ScriptRegistrySwapHookBase&&) = delete; + + /// Called before the actual context release happens + virtual void BeforeReleaseContext(std::string const& /*context*/) { } + + /// Called before SwapContext + virtual void BeforeSwapContext(bool /*initialize*/) { } + + /// Called before Unload + virtual void BeforeUnload() { } +}; + +template<typename ScriptType, typename Base> +class ScriptRegistrySwapHooks + : public ScriptRegistrySwapHookBase +{ +}; + +/// This hook is responsible for swapping OutdoorPvP's +template<typename Base> +class UnsupportedScriptRegistrySwapHooks + : public ScriptRegistrySwapHookBase +{ +public: + void BeforeReleaseContext(std::string const& context) final override + { + auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context); + ASSERT(bounds.first == bounds.second); + } +}; + +/// This hook is responsible for swapping Creature and GameObject AI's +template<typename ObjectType, typename ScriptType, typename Base> +class CreatureGameObjectScriptRegistrySwapHooks + : public ScriptRegistrySwapHookBase { + template<typename W> + class AIFunctionMapWorker + { + public: + template<typename T> + AIFunctionMapWorker(T&& worker) + : _worker(std::forward<T>(worker)) { } + + void Visit(std::unordered_map<ObjectGuid, ObjectType*>& objects) + { + _worker(objects); + } + + template<typename O> + void Visit(std::unordered_map<ObjectGuid, O*>&) { } + + private: + W _worker; + }; + + class AsyncCastHotswapEffectEvent : public BasicEvent + { public: + explicit AsyncCastHotswapEffectEvent(Unit* owner) : owner_(owner) { } + + bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override + { + owner_->CastSpell(owner_, SPELL_HOTSWAP_VISUAL_SPELL_EFFECT, true); + return true; + } + + private: + Unit* owner_; + }; + + // Hook which is called before a creature is swapped + static void UnloadStage1(Creature* creature) + { + if (creature->IsCharmed()) + creature->RemoveCharmedBy(nullptr); + + ASSERT(!creature->IsCharmed(), + "There is a disabled AI which is still loaded."); - typedef std::map<uint32, TScript*> ScriptMap; - typedef typename ScriptMap::iterator ScriptMapIterator; + creature->AI()->EnterEvadeMode(); + } + + static void UnloadStage2(Creature* creature) + { + bool const destroyed = creature->AIM_Destroy(); + ASSERT(destroyed, + "Destroying the AI should never fail here!"); + (void)destroyed; - // The actual list of scripts. This will be accessed concurrently, so it must not be modified - // after server startup. - static ScriptMap ScriptPointerList; - static std::vector<TScript*> Scripts; + ASSERT(!creature->AI(), + "The AI should be null here!"); + } - static void AddScript(TScript* const script, bool addToDeleteContainer = true) + // Hook which is called before a gameobject is swapped + static void UnloadStage1(GameObject* gameobject) + { + gameobject->AI()->Reset(); + } + + static void UnloadStage2(GameObject* gameobject) + { + gameobject->AIM_Destroy(); + + ASSERT(!gameobject->AI(), + "The AI should be null here!"); + } + + // Hook which is called after a creature was swapped + static void LoadStage1(Creature* creature) + { + ASSERT(!creature->AI(), + "The AI should be null here!"); + + if (creature->IsAlive()) + creature->ClearUnitState(UNIT_STATE_EVADE); + + bool const created = creature->AIM_Initialize(); + ASSERT(created, + "Creating the AI should never fail here!"); + (void)created; + } + + static void LoadStage2(Creature* creature) + { + if (!creature->IsAlive()) + return; + + creature->AI()->EnterEvadeMode(); + + // Cast a dummy visual spell asynchronously here to signal + // that the AI was hot swapped + creature->m_Events.AddEvent(new AsyncCastHotswapEffectEvent(creature), + creature->m_Events.CalculateTime(0)); + } + + // Hook which is called after a gameobject was swapped + static void LoadStage1(GameObject* gameobject) + { + ASSERT(!gameobject->AI(), + "The AI should be null here!"); + + gameobject->AIM_Initialize(); + } + + static void LoadStage2(GameObject* gameobject) + { + gameobject->AI()->Reset(); + } + + template<typename T> + void RunOverAllEntities(T fn) + { + auto evaluator = [&](std::unordered_map<ObjectGuid, ObjectType*>& objects) { - ASSERT(script); + for (auto object : objects) + fn(object.second); + }; - // See if the script is using the same memory as another script. If this happens, it means that - // someone forgot to allocate new memory for a script. - for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it) + AIFunctionMapWorker<typename std::decay<decltype(evaluator)>::type> worker(std::move(evaluator)); + TypeContainerVisitor<decltype(worker), MapStoredObjectTypesContainer> visitor(worker); + + sMapMgr->DoForAllMaps([&](Map* map) + { + // Run the worker over all maps + visitor.Visit(map->GetObjectsStore()); + }); + } + +public: + void BeforeReleaseContext(std::string const& context) final override + { + auto ids_to_remove = static_cast<Base*>(this)->GetScriptIDsToRemove(context); + + std::vector<ObjectType*> stage2; + + RunOverAllEntities([&](ObjectType* object) + { + if (ids_to_remove.find(object->GetScriptId()) != ids_to_remove.end()) { - if (it->second == script) - { - TC_LOG_ERROR("scripts", "Script '%s' has same memory pointer as '%s'.", - script->GetName().c_str(), it->second->GetName().c_str()); + UnloadStage1(object); + stage2.push_back(object); + } + }); - return; + for (auto object : stage2) + UnloadStage2(object); + + // Add the new ids which are removed to the global ids to remove set + ids_removed_.insert(ids_to_remove.begin(), ids_to_remove.end()); + } + + void BeforeSwapContext(bool initialize) override + { + // Never swap creature or gameobject scripts when initializing + if (initialize) + return; + + // Add the recently added scripts to the deleted scripts to replace + // default AI's with recently added core scripts. + ids_removed_.insert(static_cast<Base*>(this)->GetRecentlyAddedScriptIDs().begin(), + static_cast<Base*>(this)->GetRecentlyAddedScriptIDs().end()); + + std::vector<ObjectType*> remove; + std::vector<ObjectType*> stage2; + + RunOverAllEntities([&](ObjectType* object) + { + if (ids_removed_.find(object->GetScriptId()) != ids_removed_.end()) + { + if (object->AI()) + { + // Overwrite existing (default) AI's which are replaced by a new script + UnloadStage1(object); + remove.push_back(object); } + + stage2.push_back(object); } + }); + + for (auto object : remove) + UnloadStage2(object); - AddScript(is_script_database_bound<TScript>{}, script); - if (addToDeleteContainer) - Scripts.push_back(script); + for (auto object : stage2) + LoadStage1(object); + + for (auto object : stage2) + LoadStage2(object); + + ids_removed_.clear(); + } + + void BeforeUnload() final override + { + ASSERT(ids_removed_.empty()); + } + +private: + std::unordered_set<uint32> ids_removed_; +}; + +// This hook is responsible for swapping CreatureAI's +template<typename Base> +class ScriptRegistrySwapHooks<CreatureScript, Base> + : public CreatureGameObjectScriptRegistrySwapHooks< + Creature, CreatureScript, Base + > { }; + +// This hook is responsible for swapping GameObjectAI's +template<typename Base> +class ScriptRegistrySwapHooks<GameObjectScript, Base> + : public CreatureGameObjectScriptRegistrySwapHooks< + GameObject, GameObjectScript, Base + > { }; + +/// This hook is responsible for swapping BattlegroundScript's +template<typename Base> +class ScriptRegistrySwapHooks<BattlegroundScript, Base> + : public UnsupportedScriptRegistrySwapHooks<Base> { }; + +/// This hook is responsible for swapping OutdoorPvP's +template<typename Base> +class ScriptRegistrySwapHooks<OutdoorPvPScript, Base> + : public ScriptRegistrySwapHookBase +{ +public: + ScriptRegistrySwapHooks() : swapped(false) { } + + void BeforeReleaseContext(std::string const& context) final override + { + auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context); + + if ((!swapped) && (bounds.first != bounds.second)) + { + swapped = true; + sOutdoorPvPMgr->Die(); } + } - // Gets a script by its ID (assigned by ObjectMgr). - static TScript* GetScriptById(uint32 id) + void BeforeSwapContext(bool initialize) override + { + // Never swap outdoor pvp scripts when initializing + if ((!initialize) && swapped) { - ScriptMapIterator it = ScriptPointerList.find(id); - if (it != ScriptPointerList.end()) - return it->second; + sOutdoorPvPMgr->InitOutdoorPvP(); + swapped = false; + } + } + + void BeforeUnload() final override + { + ASSERT(!swapped); + } + +private: + bool swapped; +}; + +/// This hook is responsible for swapping InstanceMapScript's +template<typename Base> +class ScriptRegistrySwapHooks<InstanceMapScript, Base> + : public ScriptRegistrySwapHookBase +{ +public: + ScriptRegistrySwapHooks() : swapped(false) { } - return NULL; + void BeforeReleaseContext(std::string const& context) final override + { + auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context); + if (bounds.first != bounds.second) + swapped = true; + } + + void BeforeSwapContext(bool /*initialize*/) override + { + swapped = false; + } + + void BeforeUnload() final override + { + ASSERT(!swapped); + } + +private: + bool swapped; +}; + +/// This hook is responsible for swapping SpellScriptLoader's +template<typename Base> +class ScriptRegistrySwapHooks<SpellScriptLoader, Base> + : public ScriptRegistrySwapHookBase +{ +public: + ScriptRegistrySwapHooks() : swapped(false) { } + + void BeforeReleaseContext(std::string const& context) final override + { + auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context); + + if (bounds.first != bounds.second) + swapped = true; + } + + void BeforeSwapContext(bool /*initialize*/) override + { + if (swapped) + { + sObjectMgr->ValidateSpellScripts(); + swapped = false; } + } - private: + void BeforeUnload() final override + { + ASSERT(!swapped); + } + +private: + bool swapped; +}; + +// Database bound script registry +template<typename ScriptType> +class SpecializedScriptRegistry<ScriptType, true> + : public ScriptRegistryInterface, + public ScriptRegistrySwapHooks<ScriptType, ScriptRegistry<ScriptType>> +{ + template<typename> + friend class UnsupportedScriptRegistrySwapHooks; + + template<typename, typename> + friend class ScriptRegistrySwapHooks; + + template<typename, typename, typename> + friend class CreatureGameObjectScriptRegistrySwapHooks; + +public: + SpecializedScriptRegistry() { } + + typedef std::unordered_map< + uint32 /*script id*/, + std::unique_ptr<ScriptType> + > ScriptStoreType; + + typedef typename ScriptStoreType::iterator ScriptStoreIteratorType; + + void ReleaseContext(std::string const& context) final override + { + this->BeforeReleaseContext(context); + + auto const bounds = _ids_of_contexts.equal_range(context); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + _scripts.erase(itr->second); + } + + void SwapContext(bool initialize) final override + { + this->BeforeSwapContext(initialize); + + _recently_added_ids.clear(); + } + + void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override + { + for (auto const& script : _scripts) + scripts.erase(script.second->GetName()); + } + + void Unload() final override + { + this->BeforeUnload(); + + ASSERT(_recently_added_ids.empty(), + "Recently added script ids should be empty here!"); + + _scripts.clear(); + _ids_of_contexts.clear(); + } + + // Adds a database bound script + void AddScript(ScriptType* script) + { + ASSERT(script, + "Tried to call AddScript with a nullpointer!"); + ASSERT(!sScriptMgr->GetCurrentScriptContext().empty(), + "Tried to register a script without being in a valid script context!"); - // Adds a database bound script - static void AddScript(std::true_type, TScript* const script) + std::unique_ptr<ScriptType> script_ptr(script); + + // Get an ID for the script. An ID only exists if it's a script that is assigned in the database + // through a script name (or similar). + if (uint32 const id = sObjectMgr->GetScriptId(script->GetName())) { - // Get an ID for the script. An ID only exists if it's a script that is assigned in the database - // through a script name (or similar). - uint32 id = sObjectMgr->GetScriptId(script->GetName()); - if (id) + // Try to find an existing script. + for (auto const& stored_script : _scripts) { - // Try to find an existing script. - bool existing = false; - for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it) - { - // If the script names match... - if (it->second->GetName() == script->GetName()) - { - // ... It exists. - existing = true; - break; - } - } - - // If the script isn't assigned -> assign it! - if (!existing) - { - ScriptPointerList[id] = script; - sScriptMgr->IncrementScriptCount(); - - #ifdef SCRIPTS - UnusedScriptNamesContainer::iterator itr = std::lower_bound(UnusedScriptNames.begin(), UnusedScriptNames.end(), script->GetName()); - if (itr != UnusedScriptNames.end() && *itr == script->GetName()) - UnusedScriptNames.erase(itr); - #endif - } - else + // If the script names match... + if (stored_script.second->GetName() == script->GetName()) { // If the script is already assigned -> delete it! - TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, so the script can't work.", - script->GetName().c_str()); + TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, " + "so the script can't work.", script->GetName().c_str()); - ABORT(); // Error that should be fixed ASAP. + // Error that should be fixed ASAP. + sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr)); + ABORT(); + return; } } - else - { - // The script uses a script name from database, but isn't assigned to anything. - TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.", script->GetName().c_str()); - } - } - // Adds a non database bound script - static void AddScript(std::false_type, TScript* const script) + // If the script isn't assigned -> assign it! + _scripts.insert(std::make_pair(id, std::move(script_ptr))); + _ids_of_contexts.insert(std::make_pair(sScriptMgr->GetCurrentScriptContext(), id)); + _recently_added_ids.insert(id); + + sScriptRegistryCompositum->SetScriptNameInContext(script->GetName(), + sScriptMgr->GetCurrentScriptContext()); + } + else { - // We're dealing with a code-only script; just add it. - ScriptPointerList[_scriptIdCounter++] = script; - sScriptMgr->IncrementScriptCount(); + // The script uses a script name from database, but isn't assigned to anything. + TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.", + script->GetName().c_str()); + + // Avoid calling "delete script;" because we are currently in the script constructor + // In a valid scenario this will not happen because every script has a name assigned in the database + sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr)); + return; } + } + + // Gets a script by its ID (assigned by ObjectMgr). + ScriptType* GetScriptById(uint32 id) + { + auto const itr = _scripts.find(id); + if (itr != _scripts.end()) + return itr->second.get(); + + return nullptr; + } + + ScriptStoreType& GetScripts() + { + return _scripts; + } - // Counter used for code-only scripts. - static uint32 _scriptIdCounter; +protected: + // Returns the script id's which are registered to a certain context + std::unordered_set<uint32> GetScriptIDsToRemove(std::string const& context) const + { + // Create a set of all ids which are removed + std::unordered_set<uint32> scripts_to_remove; + + auto const bounds = _ids_of_contexts.equal_range(context); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + scripts_to_remove.insert(itr->second); + + return scripts_to_remove; + } + + std::unordered_set<uint32> const& GetRecentlyAddedScriptIDs() const + { + return _recently_added_ids; + } + +private: + ScriptStoreType _scripts; + + // Scripts of a specific context + std::unordered_multimap<std::string /*context*/, uint32 /*id*/> _ids_of_contexts; + + // Script id's which were registered recently + std::unordered_set<uint32> _recently_added_ids; +}; + +/// This hook is responsible for swapping CommandScript's +template<typename Base> +class ScriptRegistrySwapHooks<CommandScript, Base> + : public ScriptRegistrySwapHookBase +{ +public: + void BeforeReleaseContext(std::string const& /*context*/) final override + { + ChatHandler::invalidateCommandTable(); + } + + void BeforeSwapContext(bool /*initialize*/) override + { + ChatHandler::invalidateCommandTable(); + } + + void BeforeUnload() final override + { + ChatHandler::invalidateCommandTable(); + } +}; + +// Database unbound script registry +template<typename ScriptType> +class SpecializedScriptRegistry<ScriptType, false> + : public ScriptRegistryInterface, + public ScriptRegistrySwapHooks<ScriptType, ScriptRegistry<ScriptType>> +{ + template<typename, typename> + friend class ScriptRegistrySwapHooks; + +public: + typedef std::unordered_multimap<std::string /*context*/, std::unique_ptr<ScriptType>> ScriptStoreType; + typedef typename ScriptStoreType::iterator ScriptStoreIteratorType; + + SpecializedScriptRegistry() { } + + void ReleaseContext(std::string const& context) final override + { + this->BeforeReleaseContext(context); + + _scripts.erase(context); + } + + void SwapContext(bool initialize) final override + { + this->BeforeSwapContext(initialize); + } + + void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override + { + for (auto const& script : _scripts) + scripts.erase(script.second->GetName()); + } + + void Unload() final override + { + this->BeforeUnload(); + + _scripts.clear(); + } + + // Adds a non database bound script + void AddScript(ScriptType* script) + { + ASSERT(script, + "Tried to call AddScript with a nullpointer!"); + ASSERT(!sScriptMgr->GetCurrentScriptContext().empty(), + "Tried to register a script without being in a valid script context!"); + + std::unique_ptr<ScriptType> script_ptr(script); + + for (auto const& entry : _scripts) + if (entry.second.get() == script) + { + static_cast<ScriptRegistry<ScriptType>*>(this)-> + LogDuplicatedScriptPointerError(script, entry.second.get()); + + sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr)); + return; + } + + // We're dealing with a code-only script, just add it. + _scripts.insert(std::make_pair(sScriptMgr->GetCurrentScriptContext(), std::move(script_ptr))); + } + + ScriptStoreType& GetScripts() + { + return _scripts; + } + +private: + ScriptStoreType _scripts; }; // Utility macros to refer to the script registry. -#define SCR_REG_MAP(T) ScriptRegistry<T>::ScriptMap -#define SCR_REG_ITR(T) ScriptRegistry<T>::ScriptMapIterator -#define SCR_REG_LST(T) ScriptRegistry<T>::ScriptPointerList -#define SCR_REG_VEC(T) ScriptRegistry<T>::Scripts +#define SCR_REG_MAP(T) ScriptRegistry<T>::ScriptStoreType +#define SCR_REG_ITR(T) ScriptRegistry<T>::ScriptStoreIteratorType +#define SCR_REG_LST(T) ScriptRegistry<T>::Instance()->GetScripts() // Utility macros for looping over scripts. #define FOR_SCRIPTS(T, C, E) \ if (SCR_REG_LST(T).empty()) \ return; \ + \ for (SCR_REG_ITR(T) C = SCR_REG_LST(T).begin(); \ C != SCR_REG_LST(T).end(); ++C) + #define FOR_SCRIPTS_RET(T, C, E, R) \ if (SCR_REG_LST(T).empty()) \ return R; \ + \ for (SCR_REG_ITR(T) C = SCR_REG_LST(T).begin(); \ C != SCR_REG_LST(T).end(); ++C) + #define FOREACH_SCRIPT(T) \ FOR_SCRIPTS(T, itr, end) \ - itr->second + itr->second // Utility macros for finding specific scripts. #define GET_SCRIPT(T, I, V) \ - T* V = ScriptRegistry<T>::GetScriptById(I); \ + T* V = ScriptRegistry<T>::Instance()->GetScriptById(I); \ if (!V) \ return; + #define GET_SCRIPT_RET(T, I, V, R) \ - T* V = ScriptRegistry<T>::GetScriptById(I); \ + T* V = ScriptRegistry<T>::Instance()->GetScriptById(I); \ if (!V) \ return R; @@ -240,8 +946,18 @@ struct TSpellSummary uint8 Effects; // set of enum SelectEffect } *SpellSummary; +ScriptObject::ScriptObject(const char* name) : _name(name) +{ + sScriptMgr->IncreaseScriptCount(); +} + +ScriptObject::~ScriptObject() +{ + sScriptMgr->DecreaseScriptCount(); +} + ScriptMgr::ScriptMgr() - : _scriptCount(0), _scheduledScripts(0), _script_loader_callback(nullptr) + : _scriptCount(0), _script_loader_callback(nullptr) { } @@ -255,6 +971,9 @@ ScriptMgr* ScriptMgr::instance() void ScriptMgr::Initialize() { + ASSERT(sSpellMgr->GetSpellInfo(SPELL_HOTSWAP_VISUAL_SPELL_EFFECT) + && "Reload hotswap spell effect for creatures isn't valid!"); + uint32 oldMSTime = getMSTime(); LoadDatabase(); @@ -263,59 +982,85 @@ void ScriptMgr::Initialize() FillSpellSummary(); + // Load core scripts + SetScriptContext("___static___"); + + // SmartAI AddSC_SmartScripts(); + // LFGScripts + lfg::AddSC_LFGScripts(); + + // Load all static linked scripts through the script loader function. ASSERT(_script_loader_callback, "Script loader callback wasn't registered!"); - _script_loader_callback(); -#ifdef SCRIPTS - for (std::string const& scriptName : UnusedScriptNames) + // Initialize all dynamic scripts + // and finishes the context switch to do + // bulk loading + sScriptReloadMgr->Initialize(); + + // Loads all scripts from the current context + sScriptMgr->SwapScriptContext(true); + + // Print unused script names. + std::unordered_set<std::string> unusedScriptNames( + sObjectMgr->GetAllScriptNames().begin(), + sObjectMgr->GetAllScriptNames().end()); + + // Remove the used scripts from the given container. + sScriptRegistryCompositum->RemoveUsedScriptsFromContainer(unusedScriptNames); + + for (std::string const& scriptName : unusedScriptNames) { - TC_LOG_ERROR("sql.sql", "ScriptName '%s' exists in database, but no core script found!", scriptName.c_str()); + // Avoid complaining about empty script names since the + // script name container contains a placeholder as the 0 element. + if (scriptName.empty()) + continue; + + TC_LOG_ERROR("sql.sql", "ScriptName '%s' exists in database, " + "but no core script found!", scriptName.c_str()); } -#endif - TC_LOG_INFO("server.loading", ">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u C++ scripts in %u ms", + GetScriptCount(), GetMSTimeDiffToNow(oldMSTime)); +} + +void ScriptMgr::SetScriptContext(std::string const& context) +{ + _currentContext = context; +} + +void ScriptMgr::SwapScriptContext(bool initialize) +{ + sScriptRegistryCompositum->SwapContext(initialize); + _currentContext.clear(); +} + +void ScriptMgr::ReleaseScriptContext(std::string const& context) +{ + sScriptRegistryCompositum->ReleaseContext(context); +} + +std::shared_ptr<ModuleReference> + ScriptMgr::AcquireModuleReferenceOfScriptName(std::string const& scriptname) const +{ +#ifdef TRINITY_API_USE_DYNAMIC_LINKING + // Returns the reference to the module of the given scriptname + return ScriptReloadMgr::AcquireModuleReferenceOfContext( + sScriptRegistryCompositum->GetScriptContextOfScriptName(scriptname)); +#else + (void)scriptname; + // Something went wrong when this function is used in + // a static linked context. + WPAbort(); +#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING } void ScriptMgr::Unload() { - #define SCR_CLEAR(T) \ - for (T* scr : SCR_REG_VEC(T)) \ - delete scr; \ - SCR_REG_VEC(T).clear(); - - // Clear scripts for every script type. - SCR_CLEAR(SpellScriptLoader); - SCR_CLEAR(ServerScript); - SCR_CLEAR(WorldScript); - SCR_CLEAR(FormulaScript); - SCR_CLEAR(WorldMapScript); - SCR_CLEAR(InstanceMapScript); - SCR_CLEAR(BattlegroundMapScript); - SCR_CLEAR(ItemScript); - SCR_CLEAR(CreatureScript); - SCR_CLEAR(GameObjectScript); - SCR_CLEAR(AreaTriggerScript); - SCR_CLEAR(BattlegroundScript); - SCR_CLEAR(OutdoorPvPScript); - SCR_CLEAR(CommandScript); - SCR_CLEAR(WeatherScript); - SCR_CLEAR(AuctionHouseScript); - SCR_CLEAR(ConditionScript); - SCR_CLEAR(VehicleScript); - SCR_CLEAR(DynamicObjectScript); - SCR_CLEAR(TransportScript); - SCR_CLEAR(AchievementCriteriaScript); - SCR_CLEAR(PlayerScript); - SCR_CLEAR(AccountScript); - SCR_CLEAR(GuildScript); - SCR_CLEAR(GroupScript); - SCR_CLEAR(UnitScript); - - #undef SCR_CLEAR + sScriptRegistryCompositum->Unload(); delete[] SpellSummary; delete[] UnitAI::AISpellInfo; @@ -413,38 +1158,22 @@ void ScriptMgr::FillSpellSummary() } } -void ScriptMgr::CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector) +template<typename T, typename F> +void CreateSpellOrAuraScripts(uint32 spellId, std::list<T*>& scriptVector, F&& extractor) { SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId); for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr) { - SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second); - if (!tmpscript) + // When the script is disabled continue with the next one + if (!itr->second.second) continue; - SpellScript* script = tmpscript->GetSpellScript(); - - if (!script) - continue; - - script->_Init(&tmpscript->GetName(), spellId); - - scriptVector.push_back(script); - } -} - -void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector) -{ - SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId); - - for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr) - { - SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second); + SpellScriptLoader* tmpscript = sScriptMgr->GetSpellScriptLoader(itr->second.first); if (!tmpscript) continue; - AuraScript* script = tmpscript->GetAuraScript(); + T* script = (*tmpscript.*extractor)(); if (!script) continue; @@ -455,19 +1184,19 @@ void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& script } } -void ScriptMgr::CreateSpellScriptLoaders(uint32 spellId, std::vector<std::pair<SpellScriptLoader*, SpellScriptsContainer::iterator> >& scriptVector) +void ScriptMgr::CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector) { - SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId); - scriptVector.reserve(std::distance(bounds.first, bounds.second)); + CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetSpellScript); +} - for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr) - { - SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second); - if (!tmpscript) - continue; +void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector) +{ + CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetAuraScript); +} - scriptVector.push_back(std::make_pair(tmpscript, itr)); - } +SpellScriptLoader* ScriptMgr::GetSpellScriptLoader(uint32 scriptId) +{ + return ScriptRegistry<SpellScriptLoader>::Instance()->GetScriptById(scriptId); } void ScriptMgr::OnNetworkStart() @@ -1495,56 +2224,62 @@ void ScriptMgr::OnGroupDisband(Group* group) void ScriptMgr::OnHeal(Unit* healer, Unit* reciever, uint32& gain) { FOREACH_SCRIPT(UnitScript)->OnHeal(healer, reciever, gain); + FOREACH_SCRIPT(PlayerScript)->OnHeal(healer, reciever, gain); } void ScriptMgr::OnDamage(Unit* attacker, Unit* victim, uint32& damage) { FOREACH_SCRIPT(UnitScript)->OnDamage(attacker, victim, damage); + FOREACH_SCRIPT(PlayerScript)->OnDamage(attacker, victim, damage); } void ScriptMgr::ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage) { FOREACH_SCRIPT(UnitScript)->ModifyPeriodicDamageAurasTick(target, attacker, damage); + FOREACH_SCRIPT(PlayerScript)->ModifyPeriodicDamageAurasTick(target, attacker, damage); } void ScriptMgr::ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage) { FOREACH_SCRIPT(UnitScript)->ModifyMeleeDamage(target, attacker, damage); + FOREACH_SCRIPT(PlayerScript)->ModifyMeleeDamage(target, attacker, damage); } void ScriptMgr::ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage) { FOREACH_SCRIPT(UnitScript)->ModifySpellDamageTaken(target, attacker, damage); + FOREACH_SCRIPT(PlayerScript)->ModifySpellDamageTaken(target, attacker, damage); } SpellScriptLoader::SpellScriptLoader(const char* name) : ScriptObject(name) { - ScriptRegistry<SpellScriptLoader>::AddScript(this); + ScriptRegistry<SpellScriptLoader>::Instance()->AddScript(this); } ServerScript::ServerScript(const char* name) : ScriptObject(name) { - ScriptRegistry<ServerScript>::AddScript(this); + ScriptRegistry<ServerScript>::Instance()->AddScript(this); } WorldScript::WorldScript(const char* name) : ScriptObject(name) { - ScriptRegistry<WorldScript>::AddScript(this); + ScriptRegistry<WorldScript>::Instance()->AddScript(this); } FormulaScript::FormulaScript(const char* name) : ScriptObject(name) { - ScriptRegistry<FormulaScript>::AddScript(this); + ScriptRegistry<FormulaScript>::Instance()->AddScript(this); } UnitScript::UnitScript(const char* name, bool addToScripts) : ScriptObject(name) { - ScriptRegistry<UnitScript>::AddScript(this, addToScripts); + if (addToScripts) + ScriptRegistry<UnitScript>::Instance()->AddScript(this); } WorldMapScript::WorldMapScript(const char* name, uint32 mapId) @@ -1553,7 +2288,7 @@ WorldMapScript::WorldMapScript(const char* name, uint32 mapId) if (GetEntry() && !GetEntry()->IsWorldMap()) TC_LOG_ERROR("scripts", "WorldMapScript for map %u is invalid.", mapId); - ScriptRegistry<WorldMapScript>::AddScript(this); + ScriptRegistry<WorldMapScript>::Instance()->AddScript(this); } InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId) @@ -1562,7 +2297,7 @@ InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId) if (GetEntry() && !GetEntry()->IsDungeon()) TC_LOG_ERROR("scripts", "InstanceMapScript for map %u is invalid.", mapId); - ScriptRegistry<InstanceMapScript>::AddScript(this); + ScriptRegistry<InstanceMapScript>::Instance()->AddScript(this); } BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId) @@ -1571,122 +2306,117 @@ BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId) if (GetEntry() && !GetEntry()->IsBattleground()) TC_LOG_ERROR("scripts", "BattlegroundMapScript for map %u is invalid.", mapId); - ScriptRegistry<BattlegroundMapScript>::AddScript(this); + ScriptRegistry<BattlegroundMapScript>::Instance()->AddScript(this); } ItemScript::ItemScript(const char* name) : ScriptObject(name) { - ScriptRegistry<ItemScript>::AddScript(this); + ScriptRegistry<ItemScript>::Instance()->AddScript(this); } CreatureScript::CreatureScript(const char* name) : UnitScript(name, false) { - ScriptRegistry<CreatureScript>::AddScript(this); + ScriptRegistry<CreatureScript>::Instance()->AddScript(this); } GameObjectScript::GameObjectScript(const char* name) : ScriptObject(name) { - ScriptRegistry<GameObjectScript>::AddScript(this); + ScriptRegistry<GameObjectScript>::Instance()->AddScript(this); } AreaTriggerScript::AreaTriggerScript(const char* name) : ScriptObject(name) { - ScriptRegistry<AreaTriggerScript>::AddScript(this); + ScriptRegistry<AreaTriggerScript>::Instance()->AddScript(this); } BattlegroundScript::BattlegroundScript(const char* name) : ScriptObject(name) { - ScriptRegistry<BattlegroundScript>::AddScript(this); + ScriptRegistry<BattlegroundScript>::Instance()->AddScript(this); } OutdoorPvPScript::OutdoorPvPScript(const char* name) : ScriptObject(name) { - ScriptRegistry<OutdoorPvPScript>::AddScript(this); + ScriptRegistry<OutdoorPvPScript>::Instance()->AddScript(this); } CommandScript::CommandScript(const char* name) : ScriptObject(name) { - ScriptRegistry<CommandScript>::AddScript(this); + ScriptRegistry<CommandScript>::Instance()->AddScript(this); } WeatherScript::WeatherScript(const char* name) : ScriptObject(name) { - ScriptRegistry<WeatherScript>::AddScript(this); + ScriptRegistry<WeatherScript>::Instance()->AddScript(this); } AuctionHouseScript::AuctionHouseScript(const char* name) : ScriptObject(name) { - ScriptRegistry<AuctionHouseScript>::AddScript(this); + ScriptRegistry<AuctionHouseScript>::Instance()->AddScript(this); } ConditionScript::ConditionScript(const char* name) : ScriptObject(name) { - ScriptRegistry<ConditionScript>::AddScript(this); + ScriptRegistry<ConditionScript>::Instance()->AddScript(this); } VehicleScript::VehicleScript(const char* name) : ScriptObject(name) { - ScriptRegistry<VehicleScript>::AddScript(this); + ScriptRegistry<VehicleScript>::Instance()->AddScript(this); } DynamicObjectScript::DynamicObjectScript(const char* name) : ScriptObject(name) { - ScriptRegistry<DynamicObjectScript>::AddScript(this); + ScriptRegistry<DynamicObjectScript>::Instance()->AddScript(this); } TransportScript::TransportScript(const char* name) : ScriptObject(name) { - ScriptRegistry<TransportScript>::AddScript(this); + ScriptRegistry<TransportScript>::Instance()->AddScript(this); } AchievementCriteriaScript::AchievementCriteriaScript(const char* name) : ScriptObject(name) { - ScriptRegistry<AchievementCriteriaScript>::AddScript(this); + ScriptRegistry<AchievementCriteriaScript>::Instance()->AddScript(this); } PlayerScript::PlayerScript(const char* name) : UnitScript(name, false) { - ScriptRegistry<PlayerScript>::AddScript(this); + ScriptRegistry<PlayerScript>::Instance()->AddScript(this); } AccountScript::AccountScript(const char* name) : ScriptObject(name) { - ScriptRegistry<AccountScript>::AddScript(this); + ScriptRegistry<AccountScript>::Instance()->AddScript(this); } GuildScript::GuildScript(const char* name) : ScriptObject(name) { - ScriptRegistry<GuildScript>::AddScript(this); + ScriptRegistry<GuildScript>::Instance()->AddScript(this); } GroupScript::GroupScript(const char* name) : ScriptObject(name) { - ScriptRegistry<GroupScript>::AddScript(this); + ScriptRegistry<GroupScript>::Instance()->AddScript(this); } -// Instantiate static members of ScriptRegistry. -template<class TScript> std::map<uint32, TScript*> ScriptRegistry<TScript>::ScriptPointerList; -template<class TScript> std::vector<TScript*> ScriptRegistry<TScript>::Scripts; -template<class TScript> uint32 ScriptRegistry<TScript>::_scriptIdCounter = 0; - // Specialize for each script type class like so: template class TC_GAME_API ScriptRegistry<SpellScriptLoader>; template class TC_GAME_API ScriptRegistry<ServerScript>; @@ -1714,13 +2444,3 @@ template class TC_GAME_API ScriptRegistry<GuildScript>; template class TC_GAME_API ScriptRegistry<GroupScript>; template class TC_GAME_API ScriptRegistry<UnitScript>; template class TC_GAME_API ScriptRegistry<AccountScript>; - -// Undefine utility macros. -#undef GET_SCRIPT_RET -#undef GET_SCRIPT -#undef FOREACH_SCRIPT -#undef FOR_SCRIPTS_RET -#undef FOR_SCRIPTS -#undef SCR_REG_LST -#undef SCR_REG_ITR -#undef SCR_REG_MAP diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 337e7de4861..cc1b65fa593 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -46,6 +46,7 @@ class InstanceMap; class InstanceScript; class Item; class Map; +class ModuleReference; class OutdoorPvP; class Player; class Quest; @@ -157,14 +158,8 @@ class TC_GAME_API ScriptObject protected: - ScriptObject(const char* name) - : _name(name) - { - } - - virtual ~ScriptObject() - { - } + ScriptObject(const char* name); + virtual ~ScriptObject(); private: @@ -338,7 +333,8 @@ class TC_GAME_API WorldMapScript : public ScriptObject, public MapScript<Map> WorldMapScript(const char* name, uint32 mapId); }; -class TC_GAME_API InstanceMapScript : public ScriptObject, public MapScript<InstanceMap> +class TC_GAME_API InstanceMapScript + : public ScriptObject, public MapScript<InstanceMap> { protected: @@ -834,15 +830,6 @@ class TC_GAME_API GroupScript : public ScriptObject virtual void OnDisband(Group* /*group*/) { } }; -// Placed here due to ScriptRegistry::AddScript dependency. -#define sScriptMgr ScriptMgr::instance() - -// namespace -// { - typedef std::list<std::string> UnusedScriptNamesContainer; - TC_GAME_API extern UnusedScriptNamesContainer UnusedScriptNames; -// } - // Manages registration, loading, and execution of scripts. class TC_GAME_API ScriptMgr { @@ -852,16 +839,17 @@ class TC_GAME_API ScriptMgr ScriptMgr(); virtual ~ScriptMgr(); + void FillSpellSummary(); + void LoadDatabase(); + + void IncreaseScriptCount() { ++_scriptCount; } + void DecreaseScriptCount() { --_scriptCount; } + public: /* Initialization */ static ScriptMgr* instance(); void Initialize(); - void LoadDatabase(); - void FillSpellSummary(); - - const char* ScriptsVersion() const { return "Integrated Trinity Scripts"; } - void IncrementScriptCount() { ++_scriptCount; } uint32 GetScriptCount() const { return _scriptCount; } typedef void(*ScriptLoaderCallbackType)(); @@ -873,6 +861,27 @@ class TC_GAME_API ScriptMgr _script_loader_callback = script_loader_callback; } + public: /* Script contexts */ + /// Set the current script context, which allows the ScriptMgr + /// to accept new scripts in this context. + /// Requires a SwapScriptContext() call afterwards to load the new scripts. + void SetScriptContext(std::string const& context); + /// Returns the current script context. + std::string const& GetCurrentScriptContext() const { return _currentContext; } + /// Releases all scripts associated with the given script context immediately. + /// Requires a SwapScriptContext() call afterwards to finish the unloading. + void ReleaseScriptContext(std::string const& context); + /// Executes all changed introduced by SetScriptContext and ReleaseScriptContext. + /// It is possible to combine multiple SetScriptContext and ReleaseScriptContext + /// calls for better performance (bulk changes). + void SwapScriptContext(bool initialize = false); + + /// Acquires a strong module reference to the module containing the given script name, + /// which prevents the shared library which contains the script from unloading. + /// The shared library is lazy unloaded as soon as all references to it are released. + std::shared_ptr<ModuleReference> AcquireModuleReferenceOfScriptName( + std::string const& scriptname) const; + public: /* Unloading */ void Unload(); @@ -881,7 +890,7 @@ class TC_GAME_API ScriptMgr void CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector); void CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector); - void CreateSpellScriptLoaders(uint32 spellId, std::vector<std::pair<SpellScriptLoader*, std::multimap<uint32, uint32>::iterator> >& scriptVector); + SpellScriptLoader* GetSpellScriptLoader(uint32 scriptId); public: /* ServerScript */ @@ -1094,21 +1103,14 @@ class TC_GAME_API ScriptMgr void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage); void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage); - public: /* Scheduled scripts */ - - uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; } - uint32 DecreaseScheduledScriptCount() { return --_scheduledScripts; } - uint32 DecreaseScheduledScriptCount(size_t count) { return _scheduledScripts -= count; } - bool IsScriptScheduled() const { return _scheduledScripts > 0; } - private: - uint32 _scriptCount; - //atomic op counter for active scripts amount - std::atomic<uint32> _scheduledScripts; - ScriptLoaderCallbackType _script_loader_callback; + + std::string _currentContext; }; +#define sScriptMgr ScriptMgr::instance() + #endif diff --git a/src/server/game/Scripting/ScriptReloadMgr.cpp b/src/server/game/Scripting/ScriptReloadMgr.cpp new file mode 100644 index 00000000000..aac0e26f02b --- /dev/null +++ b/src/server/game/Scripting/ScriptReloadMgr.cpp @@ -0,0 +1,1520 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ScriptReloadMgr.h" +#include "Errors.h" + +#ifndef TRINITY_API_USE_DYNAMIC_LINKING + +// This method should never be called +std::shared_ptr<ModuleReference> + ScriptReloadMgr::AcquireModuleReferenceOfContext(std::string const& /*context*/) +{ + WPAbort(); +} + +// Returns the empty implemented ScriptReloadMgr +ScriptReloadMgr* ScriptReloadMgr::instance() +{ + static ScriptReloadMgr instance; + return &instance; +} + +#else + +#include <algorithm> +#include <regex> +#include <vector> +#include <future> +#include <memory> +#include <fstream> +#include <type_traits> +#include <unordered_set> +#include <unordered_map> + +#include <boost/algorithm/string/replace.hpp> +#include <boost/filesystem.hpp> +#include <boost/system/system_error.hpp> + +#include "efsw/efsw.hpp" + +#include "Log.h" +#include "Config.h" +#include "BuiltInConfig.h" +#include "ScriptMgr.h" +#include "StartProcess.h" +#include "MPSCQueue.h" +#include "GitRevision.h" + +namespace fs = boost::filesystem; + +#ifdef _WIN32 + #include <windows.h> +#else // Posix + #include <dlfcn.h> +#endif + +// Promote the sScriptReloadMgr to a HotSwapScriptReloadMgr +// in this compilation unit. +#undef sScriptReloadMgr +#define sScriptReloadMgr static_cast<HotSwapScriptReloadMgr*>(ScriptReloadMgr::instance()) + +// Returns "" on Windows and "lib" on posix. +static char const* GetSharedLibraryPrefix() +{ +#ifdef _WIN32 + return ""; +#else // Posix + return "lib"; +#endif +} + +// Returns "dll" on Windows and "so" on posix. +static char const* GetSharedLibraryExtension() +{ +#ifdef _WIN32 + return "dll"; +#else // Posix + return "so"; +#endif +} + +#ifdef _WIN32 +typedef HMODULE HandleType; +#else // Posix +typedef void* HandleType; +#endif + +class SharedLibraryUnloader +{ +public: + SharedLibraryUnloader() + : _path() { } + explicit SharedLibraryUnloader(fs::path const& path) + : _path(path) { } + + void operator() (HandleType handle) const + { + // Unload the associated shared library. +#ifdef _WIN32 + bool success = (FreeLibrary(handle) != 0); +#else // Posix + bool success = (dlclose(handle) == 0); +#endif + + if (!success) + { + TC_LOG_ERROR("scripts.hotswap", "Failed to unload (syscall) the shared library \"%s\".", + _path.generic_string().c_str()); + + return; + } + + boost::system::error_code error; + if (fs::remove(_path, error)) + { + TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded and deleted the shared library \"%s\".", + _path.generic_string().c_str()); + } + else + { + TC_LOG_ERROR("scripts.hotswap", "Failed to delete the shared library \"%s\" (%s).", + _path.generic_string().c_str(), error.message().c_str()); + } + } + +private: + fs::path _path; +}; + +typedef std::unique_ptr<typename std::remove_pointer<HandleType>::type, SharedLibraryUnloader> HandleHolder; + +typedef char const* (*GetScriptModuleRevisionHashType)(); +typedef void (*AddScriptsType)(); +typedef char const* (*GetScriptModuleType)(); +typedef char const* (*GetBuildDirectiveType)(); + +class ScriptModule + : public ModuleReference +{ +public: + explicit ScriptModule(HandleHolder handle, GetScriptModuleRevisionHashType getScriptModuleRevisionHash, + AddScriptsType addScripts, GetScriptModuleType getScriptModule, + GetBuildDirectiveType getBuildDirective, fs::path const& path) + : _handle(std::forward<HandleHolder>(handle)), _getScriptModuleRevisionHash(getScriptModuleRevisionHash), + _addScripts(addScripts), _getScriptModule(getScriptModule), + _getBuildDirective(getBuildDirective), _path(path) { } + + ScriptModule(ScriptModule const&) = delete; + ScriptModule(ScriptModule&& right) = delete; + + ScriptModule& operator= (ScriptModule const&) = delete; + ScriptModule& operator= (ScriptModule&& right) = delete; + + static Optional<std::shared_ptr<ScriptModule>> CreateFromPath(fs::path const& path); + + char const* GetScriptModuleRevisionHash() const override + { + return _getScriptModuleRevisionHash(); + } + + void AddScripts() const + { + return _addScripts(); + } + + char const* GetScriptModule() const override + { + return _getScriptModule(); + } + + char const* GetBuildDirective() const + { + return _getBuildDirective(); + } + + fs::path const& GetModulePath() const override + { + return _path; + } + +private: + HandleHolder _handle; + + GetScriptModuleRevisionHashType _getScriptModuleRevisionHash; + AddScriptsType _addScripts; + GetScriptModuleType _getScriptModule; + GetBuildDirectiveType _getBuildDirective; + + fs::path _path; +}; + +template<typename Fn> +static bool GetFunctionFromSharedLibrary(HandleType handle, std::string const& name, Fn& fn) +{ +#ifdef _WIN32 + fn = reinterpret_cast<Fn>(GetProcAddress(handle, name.c_str())); +#else // Posix + fn = reinterpret_cast<Fn>(dlsym(handle, name.c_str())); +#endif + return fn != nullptr; +} + +// Load a shared library from the given path. +Optional<std::shared_ptr<ScriptModule>> ScriptModule::CreateFromPath(fs::path const& path) +{ +#ifdef _WIN32 + HandleType handle = LoadLibrary(path.generic_string().c_str()); +#else // Posix + HandleType handle = dlopen(path.c_str(), RTLD_LAZY); +#endif + + if (!handle) + { + TC_LOG_ERROR("scripts.hotswap", "Could not load the shared library \"%s\" for reading.", + path.generic_string().c_str()); + return boost::none; + } + + // Use RAII to release the library on failure. + HandleHolder holder(handle, SharedLibraryUnloader(path)); + + GetScriptModuleRevisionHashType getScriptModuleRevisionHash; + AddScriptsType addScripts; + GetScriptModuleType getScriptModule; + GetBuildDirectiveType getBuildDirective; + + if (GetFunctionFromSharedLibrary(handle, "GetScriptModuleRevisionHash", getScriptModuleRevisionHash) && + GetFunctionFromSharedLibrary(handle, "AddScripts", addScripts) && + GetFunctionFromSharedLibrary(handle, "GetScriptModule", getScriptModule) && + GetFunctionFromSharedLibrary(handle, "GetBuildDirective", getBuildDirective)) + return std::make_shared<ScriptModule>(std::move(holder), getScriptModuleRevisionHash, + addScripts, getScriptModule, getBuildDirective, path); + else + { + TC_LOG_ERROR("scripts.hotswap", "Could not extract all required functions from the shared library \"%s\"!", + path.generic_string().c_str()); + + return boost::none; + } +} + +static bool HasValidScriptModuleName(std::string const& name) +{ + // Detects scripts_NAME.dll's / .so's + static std::regex const regex( + Trinity::StringFormat("^%s[sS]cripts_[a-zA-Z0-9_]+\\.%s$", + GetSharedLibraryPrefix(), + GetSharedLibraryExtension())); + + return std::regex_match(name, regex); +} + +/// File watcher responsible for watching shared libraries +class LibraryUpdateListener : public efsw::FileWatchListener +{ +public: + LibraryUpdateListener() { } + virtual ~LibraryUpdateListener() { } + + void handleFileAction(efsw::WatchID /*watchid*/, std::string const& dir, + std::string const& filename, efsw::Action action, std::string oldFilename = "") final override; +}; + +static LibraryUpdateListener libraryUpdateListener; + +/// File watcher responsible for watching source files +class SourceUpdateListener : public efsw::FileWatchListener +{ + fs::path const path_; + + std::string const script_module_name_; + + efsw::WatchID const watcher_id_; + +public: + explicit SourceUpdateListener(fs::path path, std::string script_module_name); + + virtual ~SourceUpdateListener(); + + void handleFileAction(efsw::WatchID /*watchid*/, std::string const& dir, + std::string const& filename, efsw::Action action, std::string oldFilename = "") final override; +}; + +namespace std +{ + template <> + struct hash<fs::path> + { + hash<string> hasher; + + std::size_t operator()(fs::path const& key) const + { + return hasher(key.generic_string()); + } + }; +} + +/// Invokes a synchronous CMake process with the given arguments +template<typename... T> +static int InvokeCMakeCommand(T&&... args) +{ + auto const executable = BuiltInConfig::GetCMakeCommand(); + return Trinity::StartProcess(executable, { + executable, + std::forward<T>(args)... + }, "scripts.hotswap"); +} + +/// Invokes an asynchronous CMake process with the given arguments +template<typename... T> +static std::shared_ptr<Trinity::AsyncProcessResult> InvokeAsyncCMakeCommand(T&&... args) +{ + auto const executable = BuiltInConfig::GetCMakeCommand(); + return Trinity::StartAsyncProcess(executable, { + executable, + std::forward<T>(args)... + }, "scripts.hotswap"); +} + +/// Calculates the C++ project name of the given module which is +/// the lowercase string of scripts_${module}. +static std::string CalculateScriptModuleProjectName(std::string const& module) +{ + std::string module_project = "scripts_" + module; + std::transform(module_project.begin(), module_project.end(), + module_project.begin(), ::tolower); + + return module_project; +} + +/// Returns false when there isn't any attached debugger to the process which +/// could block the rebuild of new shared libraries. +static bool IsDebuggerBlockingRebuild() +{ +#ifdef _WIN32 + if (IsDebuggerPresent()) + return true; +#endif + return false; +} + +/// ScriptReloadMgr which is used when dynamic linking is enabled +/// +/// This class manages shared library loading/unloading through watching +/// the script module directory. Loaded shared libraries are mirrored +/// into a .cache subdirectory to allow lazy unloading as long as +/// the shared library is still used which is useful for scripts +/// which can't be instantly replaced like spells or instances. +/// Several modules which reference different versions can be kept loaded +/// to serve scripts of different versions to entities and spells. +/// +/// Also this class invokes rebuilds as soon as the source of loaded +/// scripts change and installs the modules correctly through CMake. +class HotSwapScriptReloadMgr final + : public ScriptReloadMgr +{ + friend class ScriptReloadMgr; + friend class SourceUpdateListener; + + /// Reflects a queued change on a shared library or shared library + /// which is waiting for processing + enum class ChangeStateRequest : uint8 + { + CHANGE_REQUEST_ADDED, + CHANGE_REQUEST_MODIFIED, + CHANGE_REQUEST_REMOVED + }; + + /// Reflects a running job of an invoked asynchronous external process + enum class BuildJobType : uint8 + { + BUILD_JOB_NONE, + BUILD_JOB_RERUN_CMAKE, + BUILD_JOB_COMPILE, + BUILD_JOB_INSTALL, + }; + + // Represents a job which was invoked through a source or shared library change + class BuildJob + { + // Script module which is processed in the current running job + std::string script_module_name_; + // The C++ project name of the module which is processed + std::string script_module_project_name_; + // The build directive of the current module which is processed + // like "Release" or "Debug". The build directive from the + // previous same module is used if there was any. + std::string script_module_build_directive_; + + // Type of the current running job + BuildJobType type_; + // The async process result of the current job + std::shared_ptr<Trinity::AsyncProcessResult> async_result_; + + public: + explicit BuildJob(std::string script_module_name, std::string script_module_project_name, + std::string script_module_build_directive) + : script_module_name_(std::move(script_module_name)), + script_module_project_name_(std::move(script_module_project_name)), + script_module_build_directive_(std::move(script_module_build_directive)), + type_(BuildJobType::BUILD_JOB_NONE) { } + + bool IsValid() const + { + return type_ != BuildJobType::BUILD_JOB_NONE; + } + + std::string const& GetModuleName() const { return script_module_name_; } + + std::string const& GetProjectName() const { return script_module_project_name_; } + + std::string const& GetBuildDirective() const { return script_module_build_directive_; } + + BuildJobType GetType() const { return type_; } + + std::shared_ptr<Trinity::AsyncProcessResult> const& GetProcess() const + { + ASSERT(async_result_, "Tried to access an empty process handle!"); + return async_result_; + } + + /// Updates the current running job with the given type and async result + void UpdateCurrentJob(BuildJobType type, + std::shared_ptr<Trinity::AsyncProcessResult> async_result) + { + ASSERT(type != BuildJobType::BUILD_JOB_NONE, "None isn't allowed here!"); + ASSERT(async_result, "The async result must not be empty!"); + + type_ = type; + async_result_ = std::move(async_result); + } + }; + + /// Base class for lockfree asynchronous messages to the script reloader + class ScriptReloaderMessage + { + public: + virtual ~ScriptReloaderMessage() { } + + /// Invoke this function to run a message thread safe on the reloader + virtual void operator() (HotSwapScriptReloadMgr* reloader) = 0; + }; + + /// Implementation class which wraps functional types and dispatches + /// it in the overwritten implementation of the reloader messages. + template<typename T> + class ScriptReloaderMessageImplementation + : public ScriptReloaderMessage + { + T dispatcher_; + + public: + explicit ScriptReloaderMessageImplementation(T dispatcher) + : dispatcher_(std::move(dispatcher)) { } + + void operator() (HotSwapScriptReloadMgr* reloader) final override + { + dispatcher_(reloader); + } + }; + + /// Uses the given functional type and creates a asynchronous reloader + /// message on the heap, which requires deletion. + template<typename T> + auto MakeMessage(T&& dispatcher) + -> ScriptReloaderMessageImplementation<typename std::decay<T>::type>* + { + return new ScriptReloaderMessageImplementation<typename std::decay<T>::type> + (std::forward<T>(dispatcher)); + } + +public: + HotSwapScriptReloadMgr() + : _libraryWatcher(-1), _unique_library_name_counter(0), + _last_time_library_changed(0), _last_time_sources_changed(0), + _last_time_user_informed(0), terminate_early(false) { } + + virtual ~HotSwapScriptReloadMgr() + { + // Delete all messages + ScriptReloaderMessage* message; + while (_messages.Dequeue(message)) + delete message; + } + + /// Returns the absolute path to the script module directory + static fs::path GetLibraryDirectory() + { + return fs::absolute(sConfigMgr->GetStringDefault("HotSwap.ScriptDir", "scripts")); + } + + /// Returns the absolute path to the scripts directory in the source tree. + static fs::path GetSourceDirectory() + { + fs::path dir = BuiltInConfig::GetSourceDirectory(); + dir /= "src"; + dir /= "server"; + dir /= "scripts"; + return dir; + } + + /// Initializes the file watchers and loads all existing shared libraries + /// into the running server. + void Initialize() final override + { + if (!sWorld->getBoolConfig(CONFIG_HOTSWAP_ENABLED)) + return; + + if (BuiltInConfig::GetBuildDirectory().find(" ") != std::string::npos) + { + TC_LOG_ERROR("scripts.hotswap", "Your build directory path \"%s\" " + "contains spaces, which isn't allowed for compatibility reasons! " + "You need to create a build directory which doesn't contain any space character " + "in it's path!", + BuiltInConfig::GetBuildDirectory().c_str()); + + return; + } + + { + auto const library_directory = GetLibraryDirectory(); + if (!fs::exists(library_directory) || !fs::is_directory(library_directory)) + { + TC_LOG_ERROR("scripts.hotswap", "Library directory \"%s\" doesn't exist!.", + library_directory.generic_string().c_str()); + return; + } + } + + // Get the cache directory path + fs::path const cache_path = [] + { + auto path = fs::absolute(sScriptReloadMgr->GetLibraryDirectory()); + path /= ".cache"; + return path; + }(); + + // We use the boost filesystem function versions which accept + // an error code to prevent it from throwing exceptions. + boost::system::error_code code; + if ((!fs::exists(cache_path, code) || (fs::remove_all(cache_path, code) > 0)) && + !fs::create_directory(cache_path, code)) + { + TC_LOG_ERROR("scripts.hotswap", "Couldn't create the cache directory \"%s\".", + cache_path.generic_string().c_str()); + return; + } + + // Used to silent compiler warnings + (void)code; + + // Correct the CMake prefix when needed + if (sWorld->getBoolConfig(CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED)) + DoCMakePrefixCorrectionIfNeeded(); + + InitializeDefaultLibraries(); + InitializeFileWatchers(); + } + + /// Needs to be called periodically from the worldserver loop + /// to invoke queued actions like module loading/unloading and script + /// compilation. + /// This method should be invoked from a thread safe point to + /// prevent misbehavior. + void Update() final override + { + // Consume all messages + ScriptReloaderMessage* message; + while (_messages.Dequeue(message)) + { + (*message)(this); + delete message; + } + + DispatchRunningBuildJobs(); + DispatchModuleChanges(); + } + + /// Unloads the manager and cancels all runnings jobs immediately + void Unload() final override + { + if (_libraryWatcher >= 0) + { + _fileWatcher.removeWatch(_libraryWatcher); + _libraryWatcher = -1; + } + + // If a build is in progress cancel it + if (_build_job) + { + _build_job->GetProcess()->Terminate(); + _build_job.reset(); + } + + // Release all strong references to script modules + // to trigger unload actions as early as possible, + // otherwise the worldserver will crash on exit. + _running_script_modules.clear(); + } + + /// Queue's a thread safe message to the reloader which is executed on + /// the next world server update tick. + template<typename T> + void QueueMessage(T&& message) + { + _messages.Enqueue(MakeMessage(std::forward<T>(message))); + } + + /// Queues an action which marks the given shared library as changed + /// which will add, unload or reload it at the next world update tick. + /// This method is thread safe. + void QueueSharedLibraryChanged(fs::path const& path) + { + _last_time_library_changed = getMSTime(); + _libraries_changed.insert(path); + } + + /// Queues a notification that a source file was added + /// This method is thread unsafe. + void QueueAddSourceFile(std::string const& module_name, fs::path const& path) + { + UpdateSourceChangeRequest(module_name, path, ChangeStateRequest::CHANGE_REQUEST_ADDED); + } + + /// Queues a notification that a source file was modified + /// This method is thread unsafe. + void QueueModifySourceFile(std::string const& module_name, fs::path const& path) + { + UpdateSourceChangeRequest(module_name, path, ChangeStateRequest::CHANGE_REQUEST_MODIFIED); + } + + /// Queues a notification that a source file was removed + /// This method is thread unsafe. + void QueueRemoveSourceFile(std::string const& module_name, fs::path const& path) + { + UpdateSourceChangeRequest(module_name, path, ChangeStateRequest::CHANGE_REQUEST_REMOVED); + } + +private: + // Loads all shared libraries which are contained in the + // scripts directory on startup. + void InitializeDefaultLibraries() + { + fs::path const libraryDirectory(GetLibraryDirectory()); + fs::directory_iterator const dir_end; + + uint32 count = 0; + + // Iterate through all shared libraries in the script directory and load it + for (fs::directory_iterator dir_itr(libraryDirectory); dir_itr != dir_end ; ++dir_itr) + if (fs::is_regular_file(dir_itr->path()) && HasValidScriptModuleName(dir_itr->path().filename().generic_string())) + { + TC_LOG_INFO("scripts.hotswap", "Loading script module \"%s\"...", + dir_itr->path().filename().generic_string().c_str()); + + // Don't swap the script context to do bulk loading + ProcessLoadScriptModule(dir_itr->path(), false); + ++count; + } + + TC_LOG_INFO("scripts.hotswap", ">> Loaded %u script modules.", count); + } + + // Initialize all enabled file watchers. + // Needs to be called after InitializeDefaultLibraries()! + void InitializeFileWatchers() + { + _libraryWatcher = _fileWatcher.addWatch(GetLibraryDirectory().generic_string(), &libraryUpdateListener, false); + if (_libraryWatcher >= 0) + { + TC_LOG_INFO("scripts.hotswap", ">> Library reloader is listening on \"%s\".", + GetLibraryDirectory().generic_string().c_str()); + } + else + { + TC_LOG_ERROR("scripts.hotswap", "Failed to initialize the library reloader on \"%s\".", + GetLibraryDirectory().generic_string().c_str()); + } + + _fileWatcher.watch(); + } + + /// Updates the current state of the given source path + void UpdateSourceChangeRequest(std::string const& module_name, + fs::path const& path, + ChangeStateRequest state) + { + _last_time_sources_changed = getMSTime(); + + // Write when there is no module with the given name known + auto module_itr = _sources_changed.find(module_name); + + // When the file was modified it's enough to mark the module as + // dirty by initializing the associated map. + if (module_itr == _sources_changed.end()) + module_itr = _sources_changed.insert(std::make_pair( + module_name, decltype(_sources_changed)::mapped_type{})).first; + + // Leave when the file was just modified as explained above + if (state == ChangeStateRequest::CHANGE_REQUEST_MODIFIED) + return; + + // Insert when the given path isn't existent + auto const itr = module_itr->second.find(path); + if (itr == module_itr->second.end()) + { + module_itr->second.insert(std::make_pair(path, state)); + return; + } + + ASSERT((itr->second == ChangeStateRequest::CHANGE_REQUEST_ADDED) + || (itr->second == ChangeStateRequest::CHANGE_REQUEST_REMOVED), + "Stored value is invalid!"); + + ASSERT((state == ChangeStateRequest::CHANGE_REQUEST_ADDED) + || (state == ChangeStateRequest::CHANGE_REQUEST_REMOVED), + "The given state is invalid!"); + + ASSERT(state != itr->second, + "Tried to apply a state which is stored already!"); + + module_itr->second.erase(itr); + } + + /// Called periodically on the worldserver tick to process all + /// load/unload/reload requests of shared libraries. + void DispatchModuleChanges() + { + // When there are no libraries to change return + if (_libraries_changed.empty()) + return; + + // Wait some time after changes to catch bulk changes + if (GetMSTimeDiffToNow(_last_time_library_changed) < 500) + return; + + for (auto const& path : _libraries_changed) + { + bool const is_running = + _running_script_module_names.find(path) != _running_script_module_names.end(); + + bool const exists = fs::exists(path); + + if (is_running) + { + if (exists) + ProcessReloadScriptModule(path); + else + ProcessUnloadScriptModule(path); + } + else if (exists) + ProcessLoadScriptModule(path); + } + + _libraries_changed.clear(); + } + + void ProcessLoadScriptModule(fs::path const& path, bool swap_context = true) + { + ASSERT(_running_script_module_names.find(path) == _running_script_module_names.end(), + "Can't load a module which is running already!"); + + // Create the cache path and increment the library counter to use an unique name for each library + fs::path cache_path = fs::absolute(sScriptReloadMgr->GetLibraryDirectory()); + cache_path /= ".cache"; + cache_path /= Trinity::StringFormat("%s.%u%s", + path.stem().generic_string().c_str(), + _unique_library_name_counter++, + path.extension().generic_string().c_str()); + + if ([&] + { + boost::system::error_code code; + fs::copy_file(path, cache_path, fs::copy_option::fail_if_exists, code); + return code; + }()) + { + TC_LOG_FATAL("scripts.hotswap", ">> Failed to create cache entry for module \"%s\"!", + path.filename().generic_string().c_str()); + + // Find a better solution for this but it's much better + // to start the core without scripts + std::this_thread::sleep_for(std::chrono::seconds(5)); + ABORT(); + return; + } + + auto module = ScriptModule::CreateFromPath(cache_path); + if (!module) + { + TC_LOG_FATAL("scripts.hotswap", ">> Failed to load script module \"%s\"!", + path.filename().generic_string().c_str()); + + // Find a better solution for this but it's much better + // to start the core without scripts + std::this_thread::sleep_for(std::chrono::seconds(5)); + ABORT(); + return; + } + + // Limit the git revision hash to 7 characters. + std::string module_revision((*module)->GetScriptModuleRevisionHash()); + if (module_revision.size() >= 7) + module_revision = module_revision.substr(0, 7); + + std::string const module_name = (*module)->GetScriptModule(); + TC_LOG_INFO("scripts.hotswap", ">> Loaded script module \"%s\" (\"%s\" - %s).", + path.filename().generic_string().c_str(), module_name.c_str(), module_revision.c_str()); + + if (module_revision.empty()) + { + TC_LOG_WARN("scripts.hotswap", ">> Script module \"%s\" has an empty revision hash!", + path.filename().generic_string().c_str()); + } + else + { + // Trim the revision hash + std::string my_revision_hash = GitRevision::GetHash(); + std::size_t const trim = std::min(module_revision.size(), my_revision_hash.size()); + my_revision_hash = my_revision_hash.substr(0, trim); + module_revision = module_revision.substr(0, trim); + + if (my_revision_hash != module_revision) + { + TC_LOG_WARN("scripts.hotswap", ">> Script module \"%s\" has a different revision hash! " + "Binary incompatibility could lead to unknown behaviour!", path.filename().generic_string().c_str()); + } + } + + { + auto const itr = _running_script_modules.find(module_name); + if (itr != _running_script_modules.end()) + { + TC_LOG_ERROR("scripts.hotswap", ">> Attempt to load a module twice \"%s\" (loaded module is at %s)!", + path.generic_string().c_str(), itr->second.first->GetModulePath().generic_string().c_str()); + + return; + } + } + + sScriptMgr->SetScriptContext(module_name); + (*module)->AddScripts(); + TC_LOG_TRACE("scripts.hotswap", ">> Registered all scripts of module %s.", module_name.c_str()); + + if (swap_context) + sScriptMgr->SwapScriptContext(); + + // Create the source listener + auto listener = Trinity::make_unique<SourceUpdateListener>( + sScriptReloadMgr->GetSourceDirectory() / module_name, + module_name); + + // Store the module + _known_modules_build_directives.insert(std::make_pair(module_name, (*module)->GetBuildDirective())); + _running_script_modules.insert(std::make_pair(module_name, + std::make_pair(std::move(*module), std::move(listener)))); + _running_script_module_names.insert(std::make_pair(path, module_name)); + } + + void ProcessReloadScriptModule(fs::path const& path) + { + ProcessUnloadScriptModule(path, false); + ProcessLoadScriptModule(path); + } + + void ProcessUnloadScriptModule(fs::path const& path, bool finish = true) + { + auto const itr = _running_script_module_names.find(path); + + ASSERT(itr != _running_script_module_names.end(), + "Can't unload a module which isn't running!"); + + // Unload the script context + sScriptMgr->ReleaseScriptContext(itr->second); + + if (finish) + sScriptMgr->SwapScriptContext(); + + TC_LOG_INFO("scripts.hotswap", "Released script module \"%s\" (\"%s\")...", + path.filename().generic_string().c_str(), itr->second.c_str()); + + // Unload the script module + auto ref = _running_script_modules.find(itr->second); + ASSERT(ref != _running_script_modules.end() && + "Expected the script reference to be present!"); + + // Yield a message when there are other owning references to + // the module which prevents it from unloading. + // The module will be unloaded once all scripts provided from the module + // are destroyed. + if (!ref->second.first.unique()) + { + TC_LOG_INFO("scripts.hotswap", + "Script module %s is still used by %lu spell, aura or instance scripts. " + "Will lazy unload the module once all scripts stopped using it, " + "to use the latest version of an edited script unbind yourself from " + "the instance or re-cast the spell.", + ref->second.first->GetScriptModule(), ref->second.first.use_count() - 1); + } + + // Remove the owning reference from the reloader + _running_script_modules.erase(ref); + _running_script_module_names.erase(itr); + } + + /// Called periodically on the worldserver tick to process all recompile + /// requests. This method invokes one build or install job at the time + void DispatchRunningBuildJobs() + { + if (_build_job) + { + // Terminate the current build job when an associated source was changed + // while compiling and the terminate early option is enabled. + if (sWorld->getBoolConfig(CONFIG_HOTSWAP_EARLY_TERMINATION_ENABLED)) + { + if (!terminate_early && _sources_changed.find(_build_job->GetModuleName()) != _sources_changed.end()) + { + /* + FIXME: Currently crashes the server + TC_LOG_INFO("scripts.hotswap", "Terminating the running build of module \"%s\"...", + _build_job->GetModuleName().c_str()); + + _build_job->GetProcess()->Terminate(); + _build_job.reset(); + + // Continue with the default execution path + DispatchRunningBuildJobs(); + return; + */ + + terminate_early = true; + return; + } + } + + // Wait for the current build job to finish, if the job finishes in time + // evaluate it and continue with the next one. + if (_build_job->GetProcess()->GetFutureResult(). + wait_for(std::chrono::seconds(0)) == std::future_status::ready) + ProcessReadyBuildJob(); + else + return; // Return when the job didn't finish in time + + // Skip this cycle when the previous job scheduled a new one + if (_build_job) + return; + } + + // Avoid burst updates through waiting for a short time after changes + if ((_last_time_sources_changed != 0) && + (GetMSTimeDiffToNow(_last_time_sources_changed) < 500)) + return; + + // If the changed sources are empty do nothing + if (_sources_changed.empty()) + return; + + // Wait until are attached debugger were detached. + if (IsDebuggerBlockingRebuild()) + { + if ((_last_time_user_informed == 0) || + (GetMSTimeDiffToNow(_last_time_user_informed) > 7500)) + { + _last_time_user_informed = getMSTime(); + + // Informs the user that the attached debugger is blocking the automatic script rebuild. + TC_LOG_INFO("scripts.hotswap", "Your attached debugger is blocking the TrinityCore " + "automatic script rebuild, please detach it!"); + } + + return; + } + + // Find all source files of a changed script module and removes + // it from the changed source list, invoke the build afterwards. + bool rebuild_buildfiles; + auto module_name = [&] + { + auto itr = _sources_changed.begin(); + auto name = itr->first; + rebuild_buildfiles = !itr->second.empty(); + + if (sLog->ShouldLog("scripts.hotswap", LogLevel::LOG_LEVEL_TRACE)) + for (auto const& entry : itr->second) + { + TC_LOG_TRACE("scripts.hotswap", "Source file %s was %s.", + entry.first.generic_string().c_str(), + ((entry.second == ChangeStateRequest::CHANGE_REQUEST_ADDED) ? + "added" : "removed")); + } + + _sources_changed.erase(itr); + return name; + }(); + + // Erase the added delete history all modules when we + // invoke a cmake rebuild since we add all + // added files of other modules to the build as well + if (rebuild_buildfiles) + { + for (auto& entry : _sources_changed) + entry.second.clear(); + } + + ASSERT(!module_name.empty(), + "The current module name is invalid!"); + + TC_LOG_INFO("scripts.hotswap", "Recompiling Module \"%s\"...", + module_name.c_str()); + + // Calculate the project name of the script module + auto project_name = CalculateScriptModuleProjectName(module_name); + + // Find the best build directive for the module + auto build_directive = [&] () -> std::string + { + auto directive = sConfigMgr->GetStringDefault("HotSwap.ReCompilerBuildType", ""); + if (!directive.empty()) + return directive; + + auto const itr = _known_modules_build_directives.find(module_name); + if (itr != _known_modules_build_directives.end()) + return itr->second; + else // If no build directive of the module was found use the one from the game library + return _BUILD_DIRECTIVE; + }(); + + // Initiate the new build job + _build_job = BuildJob(std::move(module_name), + std::move(project_name), std::move(build_directive)); + + // Rerun CMake when we need to recreate the build files + if (rebuild_buildfiles + && sWorld->getBoolConfig(CONFIG_HOTSWAP_BUILD_FILE_RECREATION_ENABLED)) + DoRerunCMake(); + else + DoCompileCurrentProcessedModule(); + } + + void ProcessReadyBuildJob() + { + ASSERT(_build_job->IsValid(), "Invalid build job!"); + + // Retrieve the result + auto const error = _build_job->GetProcess()->GetFutureResult().get(); + + if (terminate_early) + { + _build_job.reset(); + terminate_early = false; + return; + } + + switch (_build_job->GetType()) + { + case BuildJobType::BUILD_JOB_RERUN_CMAKE: + { + if (!error) + { + TC_LOG_INFO("scripts.hotswap", ">> Successfully updated the build files!"); + } + else + { + TC_LOG_INFO("scripts.hotswap", ">> Failed to update the build files at \"%s\", " + "it's possible that recently added sources are not included " + "in your next builds, rerun CMake manually.", + BuiltInConfig::GetBuildDirectory().c_str()); + } + // Continue with building the changes sources + DoCompileCurrentProcessedModule(); + return; + } + case BuildJobType::BUILD_JOB_COMPILE: + { + if (!error) // Build was successful + { + if (sWorld->getBoolConfig(CONFIG_HOTSWAP_INSTALL_ENABLED)) + { + // Continue with the installation when it's enabled + TC_LOG_INFO("scripts.hotswap", + ">> Successfully build module %s, continue with installing...", + _build_job->GetModuleName().c_str()); + + DoInstallCurrentProcessedModule(); + return; + } + + // Skip the installation because it's disabled in config + TC_LOG_INFO("scripts.hotswap", + ">> Successfully build module %s, skipped the installation.", + _build_job->GetModuleName().c_str()); + } + else // Build wasn't successful + { + TC_LOG_ERROR("scripts.hotswap", + ">> The build of module %s failed! See the log for details.", + _build_job->GetModuleName().c_str()); + } + break; + } + case BuildJobType::BUILD_JOB_INSTALL: + { + if (!error) + { + // Installation was successful + TC_LOG_INFO("scripts.hotswap", ">> Successfully installed module %s.", + _build_job->GetModuleName().c_str()); + } + else + { + // Installation wasn't successful + TC_LOG_INFO("scripts.hotswap", + ">> The installation of module %s failed! See the log for details.", + _build_job->GetModuleName().c_str()); + } + break; + } + default: + break; + } + + // Clear the current job + _build_job.reset(); + } + + /// Reruns CMake asynchronously over the build directory + void DoRerunCMake() + { + ASSERT(_build_job, "There isn't any active build job!"); + + TC_LOG_INFO("scripts.hotswap", "Rerunning CMake because there were sources added or removed..."); + + _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_RERUN_CMAKE, + InvokeAsyncCMakeCommand(BuiltInConfig::GetBuildDirectory())); + } + + /// Invokes a new build of the current active module job + void DoCompileCurrentProcessedModule() + { + ASSERT(_build_job, "There isn't any active build job!"); + + TC_LOG_INFO("scripts.hotswap", "Starting asynchronous build job for module %s...", + _build_job->GetModuleName().c_str()); + + _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_COMPILE, + InvokeAsyncCMakeCommand( + "--build", BuiltInConfig::GetBuildDirectory(), + "--target", _build_job->GetProjectName(), + "--config", _build_job->GetBuildDirective())); + } + + /// Invokes a new asynchronous install of the current active module job + void DoInstallCurrentProcessedModule() + { + ASSERT(_build_job, "There isn't any active build job!"); + + TC_LOG_INFO("scripts.hotswap", "Starting asynchronous install job for module %s...", + _build_job->GetModuleName().c_str()); + + _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_INSTALL, + InvokeAsyncCMakeCommand( + "-DCOMPONENT=" + _build_job->GetProjectName(), + "-DBUILD_TYPE=" + _build_job->GetBuildDirective(), + "-P", fs::absolute("cmake_install.cmake", + BuiltInConfig::GetBuildDirectory()).generic_string())); + } + + /// Sets the CMAKE_INSTALL_PREFIX variable in the CMake cache + /// to point to the current worldserver position, + /// since most users will forget this. + void DoCMakePrefixCorrectionIfNeeded() + { + TC_LOG_INFO("scripts.hotswap", "Correcting your CMAKE_INSTALL_PREFIX in \"%s\"...", + BuiltInConfig::GetBuildDirectory().c_str()); + + auto const cmake_cache_path = fs::absolute("CMakeCache.txt", + BuiltInConfig::GetBuildDirectory()); + + // Stop when the CMakeCache wasn't found + if (![&] + { + boost::system::error_code error; + if (!fs::exists(cmake_cache_path, error)) + { + TC_LOG_ERROR("scripts.hotswap", ">> CMake cache \"%s\" doesn't exist, " + "set the \"BuildDirectory\" option in your worldserver.conf to point" + "to your build directory!", + cmake_cache_path.generic_string().c_str()); + + return false; + } + else + return true; + }()) + return; + + TC_LOG_TRACE("scripts.hotswap", "Checking CMake cache (\"%s\") " + "for the correct CMAKE_INSTALL_PREFIX location...", + cmake_cache_path.generic_string().c_str()); + + std::string cmake_cache_content; + { + std::ifstream in(cmake_cache_path.generic_string()); + if (!in.is_open()) + { + TC_LOG_ERROR("scripts.hotswap", ">> Failed to read the CMake cache at \"%s\"!", + cmake_cache_path.generic_string().c_str()); + + return; + } + + std::ostringstream ss; + ss << in.rdbuf(); + cmake_cache_content = ss.str(); + + in.close(); + } + + static std::string const prefix_key = "CMAKE_INSTALL_PREFIX:PATH="; + + // Extract the value of CMAKE_INSTALL_PREFIX + auto begin = cmake_cache_content.find(prefix_key); + if (begin != std::string::npos) + { + begin += prefix_key.length(); + auto const end = cmake_cache_content.find("\n", begin); + if (end != std::string::npos) + { + fs::path value = cmake_cache_content.substr(begin, end - begin); + + auto current_path = fs::current_path(); + + #ifndef _WIN32 + // The worldserver location is ${CMAKE_INSTALL_PREFIX}/bin + // on all other platforms then windows + current_path = current_path.remove_leaf(); + #endif + + if (value != current_path) + { + // Prevent correction of the install prefix + // when we are starting the core from inside the build tree + bool const is_in_path = [&] + { + fs::path base = BuiltInConfig::GetBuildDirectory(); + fs::path branch = value; + while (!branch.empty()) + { + if (base == branch) + return true; + + branch = branch.remove_leaf(); + } + + return false; + }(); + + if (is_in_path) + return; + + TC_LOG_INFO("scripts.hotswap", ">> Found outdated CMAKE_INSTALL_PREFIX (\"%s\"), " + "worldserver is currently installed at %s...", + value.generic_string().c_str(), current_path.generic_string().c_str()); + } + else + { + TC_LOG_INFO("scripts.hotswap", ">> CMAKE_INSTALL_PREFIX is equal to the current path of execution."); + return; + } + } + } + + TC_LOG_INFO("scripts.hotswap", "Invoking CMake cache correction..."); + + auto const error = InvokeCMakeCommand( + "-DCMAKE_INSTALL_PREFIX:PATH=" + fs::current_path().generic_string(), + BuiltInConfig::GetBuildDirectory()); + + if (error) + { + TC_LOG_ERROR("scripts.hotswap", ">> Failed to update the CMAKE_INSTALL_PREFIX! " + "This could lead to unexpected behaviour!"); + } + else + { + TC_LOG_ERROR("scripts.hotswap", ">> Successfully corrected your CMAKE_INSTALL_PREFIX variable" + "to point at your current path of execution."); + } + } + + // File watcher instance and watcher ID's + efsw::FileWatcher _fileWatcher; + efsw::WatchID _libraryWatcher; + + // Unique library name counter which is used to + // generate unique names for every shared library version. + uint32 _unique_library_name_counter; + + // Queue which is used for thread safe message processing + MPSCQueue<ScriptReloaderMessage> _messages; + + // Change requests to load or unload shared libraries + std::unordered_set<fs::path /*path*/> _libraries_changed; + // The timestamp which indicates the last time a library was changed + uint32 _last_time_library_changed; + + // Contains all running script modules + // The associated shared libraries are unloaded immediately + // on loosing ownership through RAII. + std::unordered_map<std::string /*module name*/, + std::pair<std::shared_ptr<ScriptModule>, std::unique_ptr<SourceUpdateListener>> + > _running_script_modules; + // Container which maps the path of a shared library to it's module name + std::unordered_map<fs::path, std::string /*module name*/> _running_script_module_names; + // Container which maps the module name to it's last known build directive + std::unordered_map<std::string /*module name*/, std::string /*build directive*/> _known_modules_build_directives; + + // Modules which were changed and are queued for recompilation + std::unordered_map<std::string /*module*/, + std::unordered_map<fs::path /*path*/, ChangeStateRequest /*state*/>> _sources_changed; + // Tracks the time since the last module has changed to avoid burst updates + uint32 _last_time_sources_changed; + + // Tracks the last timestamp the user was informed about a certain repeating event. + uint32 _last_time_user_informed; + + // Represents the current build job which is in progress + Optional<BuildJob> _build_job; + + // Is true when the build job dispatcher should stop after + // the current job has finished + bool terminate_early; +}; + +/// Maps efsw actions to strings +static char const* ActionToString(efsw::Action action) +{ + switch (action) + { + case efsw::Action::Add: + return "added"; + case efsw::Action::Delete: + return "deleted"; + case efsw::Action::Moved: + return "moved"; + default: + return "modified"; + } +} + +void LibraryUpdateListener::handleFileAction(efsw::WatchID watchid, std::string const& dir, + std::string const& filename, efsw::Action action, std::string oldFilename) +{ + // TC_LOG_TRACE("scripts.hotswap", "Library listener detected change on possible module \"%s\ (%s)".", filename.c_str(), ActionToString(action)); + + // Split moved actions into a delete and an add action + if (action == efsw::Action::Moved) + { + ASSERT(!oldFilename.empty(), "Old filename doesn't exist!"); + handleFileAction(watchid, dir, oldFilename, efsw::Action::Delete); + handleFileAction(watchid, dir, filename, efsw::Action::Add); + return; + } + + sScriptReloadMgr->QueueMessage([=](HotSwapScriptReloadMgr* reloader) mutable + { + auto const path = fs::absolute( + filename, + sScriptReloadMgr->GetLibraryDirectory()); + + if (!HasValidScriptModuleName(filename)) + return; + + switch (action) + { + case efsw::Actions::Add: + TC_LOG_TRACE("scripts.hotswap", ">> Loading \"%s\" (%s)...", + path.generic_string().c_str(), ActionToString(action)); + reloader->QueueSharedLibraryChanged(path); + break; + case efsw::Actions::Delete: + TC_LOG_TRACE("scripts.hotswap", ">> Unloading \"%s\" (%s)...", + path.generic_string().c_str(), ActionToString(action)); + reloader->QueueSharedLibraryChanged(path); + break; + case efsw::Actions::Modified: + TC_LOG_TRACE("scripts.hotswap", ">> Reloading \"%s\" (%s)...", + path.generic_string().c_str(), ActionToString(action)); + reloader->QueueSharedLibraryChanged(path); + break; + default: + WPAbort(); + break; + } + }); +} + +/// Returns true when the given path has a known C++ file extension +static bool HasCXXSourceFileExtension(fs::path const& path) +{ + static std::regex const regex("^\\.(h|hpp|c|cc|cpp)$"); + return std::regex_match(path.extension().generic_string(), regex); +} + +SourceUpdateListener::SourceUpdateListener(fs::path path, std::string script_module_name) + : path_(std::move(path)), script_module_name_(std::move(script_module_name)), + watcher_id_(sScriptReloadMgr->_fileWatcher.addWatch(path_.generic_string(), this, true)) +{ + if (watcher_id_ >= 0) + { + TC_LOG_TRACE("scripts.hotswap", ">> Attached the source recompiler to \"%s\".", + path_.generic_string().c_str()); + } + else + { + TC_LOG_ERROR("scripts.hotswap", "Failed to initialize thesource recompiler on \"%s\".", + path_.generic_string().c_str()); + } +} + +SourceUpdateListener::~SourceUpdateListener() +{ + if (watcher_id_ >= 0) + { + sScriptReloadMgr->_fileWatcher.removeWatch(watcher_id_); + + TC_LOG_TRACE("scripts.hotswap", ">> Detached the source recompiler from \"%s\".", + path_.generic_string().c_str()); + } +} + +void SourceUpdateListener::handleFileAction(efsw::WatchID watchid, std::string const& dir, + std::string const& filename, efsw::Action action, std::string oldFilename) +{ + // TC_LOG_TRACE("scripts.hotswap", "Source listener detected change on possible file \"%s/%s\" (%s).", dir.c_str(), filename.c_str(), ActionToString(action)); + + // Skip the file change notification if the recompiler is disabled + if (!sWorld->getBoolConfig(CONFIG_HOTSWAP_RECOMPILER_ENABLED)) + return; + + // Split moved actions into a delete and an add action + if (action == efsw::Action::Moved) + { + ASSERT(!oldFilename.empty(), "Old filename doesn't exist!"); + handleFileAction(watchid, dir, oldFilename, efsw::Action::Delete); + handleFileAction(watchid, dir, filename, efsw::Action::Add); + return; + } + + auto const path = fs::absolute( + filename, + dir); + + // Check if the file is a C/C++ source file. + if (!path.has_extension() || !HasCXXSourceFileExtension(path)) + return; + + /// Thread safe part + sScriptReloadMgr->QueueMessage([=](HotSwapScriptReloadMgr* reloader) + { + TC_LOG_TRACE("scripts.hotswap", "Detected source change on module \"%s\", " + "queued for recompilation...", script_module_name_.c_str()); + + switch (action) + { + case efsw::Actions::Add: + TC_LOG_TRACE("scripts.hotswap", "Source file %s of module %s was added.", + path.generic_string().c_str(), script_module_name_.c_str()); + reloader->QueueAddSourceFile(script_module_name_, path); + break; + case efsw::Actions::Delete: + TC_LOG_TRACE("scripts.hotswap", "Source file %s of module %s was deleted.", + path.generic_string().c_str(), script_module_name_.c_str()); + reloader->QueueRemoveSourceFile(script_module_name_, path); + break; + case efsw::Actions::Modified: + TC_LOG_TRACE("scripts.hotswap", "Source file %s of module %s was modified.", + path.generic_string().c_str(), script_module_name_.c_str()); + reloader->QueueModifySourceFile(script_module_name_, path); + break; + default: + WPAbort(); + break; + } + }); +} + +// Returns the module reference of the given context +std::shared_ptr<ModuleReference> + ScriptReloadMgr::AcquireModuleReferenceOfContext(std::string const& context) +{ + auto const itr = sScriptReloadMgr->_running_script_modules.find(context); + if (itr != sScriptReloadMgr->_running_script_modules.end()) + return itr->second.first; + else + return { }; +} + +// Returns the full hot swap implemented ScriptReloadMgr +ScriptReloadMgr* ScriptReloadMgr::instance() +{ + static HotSwapScriptReloadMgr instance; + return &instance; +} + +#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING diff --git a/src/server/game/Scripting/ScriptReloadMgr.h b/src/server/game/Scripting/ScriptReloadMgr.h new file mode 100644 index 00000000000..f9b388f8eb0 --- /dev/null +++ b/src/server/game/Scripting/ScriptReloadMgr.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SCRIPT_RELOADER_H +#define SCRIPT_RELOADER_H + +#include <memory> +#include <string> +#include "Define.h" +#include <boost/filesystem/path.hpp> + +/// Represents a strong reference to a dynamic library which +/// provides C++ scripts. As long as one reference to the library exists +/// the library is kept loaded in the server, which makes it possible to lazy +/// unload several script types on demand (like SpellScripts), and to +/// provide multiple versions of the same script to the script factories. +/// +/// Acquire a new reference through using: +/// `ScriptReloadMgr::AcquireModuleReferenceOfContext` +class ModuleReference +{ +public: + virtual ~ModuleReference() { } + + /// Returns the git revision hash of the referenced script module + virtual char const* GetScriptModuleRevisionHash() const = 0; + /// Returns the name of the referenced script module + virtual char const* GetScriptModule() const = 0; + /// Returns the path to the script module + virtual boost::filesystem::path const& GetModulePath() const = 0; +}; + +/// Provides the whole physical dynamic library unloading capability. +/// Loads, Reloads and Unloads dynamic libraries on changes and +/// informs the ScriptMgr about changes which were made. +/// The ScriptReloadMgr is also responsible for watching the source directory +/// and to invoke a build on changes. +class TC_GAME_API ScriptReloadMgr +{ +protected: + ScriptReloadMgr() { } + +public: + virtual ~ScriptReloadMgr() { } + + /// Initializes the ScriptReloadMgr + virtual void Initialize() { } + + /// Needs to be called periodically to check for updates on script modules. + /// Expects to be invoked in a thread safe way which means it's required that + /// the current thread is the only one which accesses the world data. + virtual void Update() { } + + /// Unloads the ScriptReloadMgr + virtual void Unload() { } + + /// Returns an owning reference to the current module of the given context + static std::shared_ptr<ModuleReference> AcquireModuleReferenceOfContext( + std::string const& context); + + /// Returns the unique ScriptReloadMgr singleton instance + static ScriptReloadMgr* instance(); +}; + +#define sScriptReloadMgr ScriptReloadMgr::instance() + +#endif // SCRIPT_RELOADER_H diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 207908c6d51..5585dc8762b 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1325,7 +1325,7 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode { // apply glow vision if (target->GetTypeId() == TYPEID_PLAYER) - target->SetByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); + target->SetByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); target->m_invisibility.AddFlag(type); target->m_invisibility.AddValue(type, GetAmount()); @@ -1337,7 +1337,7 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode // if not have different invisibility auras. // remove glow vision if (target->GetTypeId() == TYPEID_PLAYER) - target->RemoveByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); + target->RemoveByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); target->m_invisibility.DelFlag(type); } @@ -1409,7 +1409,7 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo target->SetStandFlags(UNIT_STAND_FLAGS_CREEP); if (target->GetTypeId() == TYPEID_PLAYER) - target->SetByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_STEALTH); + target->SetByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_STEALTH); } else { @@ -1421,7 +1421,7 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP); if (target->GetTypeId() == TYPEID_PLAYER) - target->RemoveByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_STEALTH); + target->RemoveByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_STEALTH); } } @@ -2400,7 +2400,7 @@ void AuraEffect::HandleAuraTrackStealthed(AuraApplication const* aurApp, uint8 m if (target->HasAuraType(GetAuraType())) return; } - target->ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_TRACK_STEALTHED, apply); + target->ApplyModByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_TRACK_STEALTHED, apply); } void AuraEffect::HandleAuraModStalked(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4808,7 +4808,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool uint32 spellId = 24659; if (apply && caster) { - SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(spellId); + SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId); for (uint32 i = 0; i < spell->StackAmount; ++i) caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID()); @@ -4823,7 +4823,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool uint32 spellId = 24662; if (apply && caster) { - SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(spellId); + SpellInfo const* spell = sSpellMgr->AssertSpellInfo(spellId); for (uint32 i = 0; i < spell->StackAmount; ++i) caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID()); break; @@ -5248,7 +5248,7 @@ void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 m if (apply) { - target->SetUInt16Value(PLAYER_FIELD_BYTES2, 0, overrideId); + target->SetUInt16Value(PLAYER_FIELD_BYTES2, PLAYER_BYTES_2_OVERRIDE_SPELLS_UINT16_OFFSET, overrideId); if (OverrideSpellDataEntry const* overrideSpells = sOverrideSpellDataStore.LookupEntry(overrideId)) for (uint8 i = 0; i < MAX_OVERRIDE_SPELL; ++i) if (uint32 spellId = overrideSpells->spellId[i]) @@ -5256,7 +5256,7 @@ void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 m } else { - target->SetUInt16Value(PLAYER_FIELD_BYTES2, 0, 0); + target->SetUInt16Value(PLAYER_FIELD_BYTES2, PLAYER_BYTES_2_OVERRIDE_SPELLS_UINT16_OFFSET, 0); if (OverrideSpellDataEntry const* overrideSpells = sOverrideSpellDataStore.LookupEntry(overrideId)) for (uint8 i = 0; i < MAX_OVERRIDE_SPELL; ++i) if (uint32 spellId = overrideSpells->spellId[i]) @@ -5302,9 +5302,9 @@ void AuraEffect::HandlePreventResurrection(AuraApplication const* aurApp, uint8 return; if (apply) - aurApp->GetTarget()->RemoveByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER); + aurApp->GetTarget()->RemoveByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_RELEASE_TIMER); else if (!aurApp->GetTarget()->GetBaseMap()->Instanceable()) - aurApp->GetTarget()->SetByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER); + aurApp->GetTarget()->SetByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_RELEASE_TIMER); } void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const @@ -5974,14 +5974,14 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo); - if (target->GetHealth() < damage) - damage = uint32(target->GetHealth()); - TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s health leech of %s for %u dmg inflicted by %u abs is %u", GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb); caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellInfo()->GetSchoolMask(), absorb, resist, false, 0, crit); + if (target->GetHealth() < damage) + damage = uint32(target->GetHealth()); + // Set trigger flag uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index b2fb2766fb0..fff69ae48df 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4831,6 +4831,10 @@ SpellCastResult Spell::CheckCast(bool strict) m_customError = SpellCustomErrors(condInfo.mLastFailedCondition->ErrorTextId); return SpellCastResult(condInfo.mLastFailedCondition->ErrorType); } + + if (_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) + return SPELL_FAILED_DONT_REPORT; + if (!condInfo.mLastFailedCondition || !condInfo.mLastFailedCondition->ConditionTarget) return SPELL_FAILED_CASTER_AURASTATE; return SPELL_FAILED_BAD_TARGETS; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 2a9db6f0449..3f0ff9a0f19 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -1830,7 +1830,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex) sSpellMgr->GetSetOfSpellsInSpellGroup(SPELL_GROUP_ELIXIR_BATTLE, avalibleElixirs); for (std::set<uint32>::iterator itr = avalibleElixirs.begin(); itr != avalibleElixirs.end();) { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(*itr); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(*itr); if (spellInfo->SpellLevel < m_spellInfo->SpellLevel || spellInfo->SpellLevel > unitTarget->getLevel()) avalibleElixirs.erase(itr++); else if (sSpellMgr->IsSpellMemberOfSpellGroup(*itr, SPELL_GROUP_ELIXIR_SHATTRATH)) @@ -2110,8 +2110,7 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex) else if (player->IsBankPos(pos)) { ItemPosCountVec dest; - uint8 msg = player->CanBankItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true); - if (msg == EQUIP_ERR_OK) + if (player->CanBankItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true) == EQUIP_ERR_OK) { player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true); @@ -2133,7 +2132,7 @@ void Spell::EffectSummonChangeItem(SpellEffIndex effIndex) player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true); - uint8 msg = player->CanEquipItem(m_CastItem->GetSlot(), dest, pNewItem, true); + InventoryResult msg = player->CanEquipItem(m_CastItem->GetSlot(), dest, pNewItem, true); if (msg == EQUIP_ERR_OK || msg == EQUIP_ERR_CANT_DO_RIGHT_NOW) { diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp index adf5fc47c77..4f74197fed2 100644 --- a/src/server/game/Spells/SpellHistory.cpp +++ b/src/server/game/Spells/SpellHistory.cpp @@ -373,7 +373,7 @@ void SpellHistory::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId / player->SendDirectMessage(&data); if (startCooldown) - StartCooldown(sSpellMgr->EnsureSpellInfo(categoryItr->second->SpellId), itemId, spell); + StartCooldown(sSpellMgr->AssertSpellInfo(categoryItr->second->SpellId), itemId, spell); } WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8); @@ -483,7 +483,7 @@ bool SpellHistory::HasCooldown(SpellInfo const* spellInfo, uint32 itemId /*= 0*/ bool SpellHistory::HasCooldown(uint32 spellId, uint32 itemId /*= 0*/, bool ignoreCategoryCooldown /*= false*/) const { - return HasCooldown(sSpellMgr->EnsureSpellInfo(spellId), itemId, ignoreCategoryCooldown); + return HasCooldown(sSpellMgr->AssertSpellInfo(spellId), itemId, ignoreCategoryCooldown); } uint32 SpellHistory::GetRemainingCooldown(SpellInfo const* spellInfo) const @@ -542,7 +542,7 @@ void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTim WorldPacket spellCooldowns; for (uint32 spellId : knownSpells) { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(spellId); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(spellId); if (spellInfo->IsCooldownStartedOnEvent()) continue; @@ -688,7 +688,7 @@ void SpellHistory::RestoreCooldownStateAfterDuel() // add all profession CDs created while in duel (if any) for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end(); ++itr) { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); if (spellInfo->RecoveryTime > 10 * MINUTE * IN_MILLISECONDS || spellInfo->CategoryRecoveryTime > 10 * MINUTE * IN_MILLISECONDS) diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 269a3a90e9d..fea7513b092 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -692,7 +692,7 @@ class TC_GAME_API SpellMgr // SpellInfo object management SpellInfo const* GetSpellInfo(uint32 spellId) const { return spellId < GetSpellInfoStoreSize() ? mSpellInfoMap[spellId] : NULL; } // Use this only with 100% valid spellIds - SpellInfo const* EnsureSpellInfo(uint32 spellId) const + SpellInfo const* AssertSpellInfo(uint32 spellId) const { ASSERT(spellId < GetSpellInfoStoreSize()); SpellInfo const* spellInfo = mSpellInfoMap[spellId]; diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index 6876f8fa7ef..e2598386466 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -16,6 +16,7 @@ */ #include "Spell.h" +#include "ScriptMgr.h" #include "SpellAuras.h" #include "SpellScript.h" #include "SpellMgr.h" @@ -50,6 +51,12 @@ void _SpellScript::_Init(std::string const* scriptname, uint32 spellId) m_currentScriptState = SPELL_SCRIPT_STATE_NONE; m_scriptName = scriptname; m_scriptSpellId = spellId; + +#ifdef TRINITY_API_USE_DYNAMIC_LINKING + // Acquire a strong reference to the binary code + // to keep it loaded until all spells are destroyed. + m_moduleReference = sScriptMgr->AcquireModuleReferenceOfScriptName(*scriptname); +#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING } std::string const* _SpellScript::_GetScriptName() const diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 1d4efd8073d..539bc54cc94 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -22,6 +22,7 @@ #include "SharedDefines.h" #include "SpellAuraDefines.h" #include "Spell.h" +#include "ScriptReloadMgr.h" #include <stack> class Unit; @@ -105,6 +106,16 @@ class TC_GAME_API _SpellScript uint8 m_currentScriptState; std::string const* m_scriptName; uint32 m_scriptSpellId; + + private: + +#ifdef TRINITY_API_USE_DYNAMIC_LINKING + + // Strong reference to keep the binary code loaded + std::shared_ptr<ModuleReference> m_moduleReference; + +#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING + public: // // SpellScript/AuraScript interface base diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 6380aece941..4b64ef0bbd8 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -54,6 +54,7 @@ #include "PoolMgr.h" #include "GitRevision.h" #include "ScriptMgr.h" +#include "ScriptReloadMgr.h" #include "SkillDiscovery.h" #include "SkillExtraItems.h" #include "SmartAI.h" @@ -1319,6 +1320,14 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Creature.Zone.Area.Data", false); m_bool_configs[CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Gameoject.Zone.Area.Data", false); + // HotSwap + m_bool_configs[CONFIG_HOTSWAP_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.Enabled", true); + m_bool_configs[CONFIG_HOTSWAP_RECOMPILER_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnableReCompiler", true); + m_bool_configs[CONFIG_HOTSWAP_EARLY_TERMINATION_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnableEarlyTermination", true); + m_bool_configs[CONFIG_HOTSWAP_BUILD_FILE_RECREATION_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnableBuildFileRecreation", true); + m_bool_configs[CONFIG_HOTSWAP_INSTALL_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnableInstall", true); + m_bool_configs[CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnablePrefixCorrection", true); + // call ScriptMgr if we're reloading the configuration if (reload) sScriptMgr->OnConfigLoad(reload); @@ -1826,6 +1835,8 @@ void World::SetInitialWorldSettings() m_timers[WUPDATE_PINGDB].SetInterval(getIntConfig(CONFIG_DB_PING_INTERVAL)*MINUTE*IN_MILLISECONDS); // Mysql ping time in minutes + m_timers[WUPDATE_CHECK_FILECHANGES].SetInterval(500); + //to set mailtimer to return mails every day between 4 and 5 am //mailtimer is increased when updating auctions //one second is 1000 -(tested on win system) @@ -2109,6 +2120,13 @@ void World::Update(uint32 diff) m_timers[WUPDATE_AHBOT].Reset(); } + /// <li> Handle file changes + if (m_timers[WUPDATE_CHECK_FILECHANGES].Passed()) + { + sScriptReloadMgr->Update(); + m_timers[WUPDATE_CHECK_FILECHANGES].Reset(); + } + /// <li> Handle session updates when the timer has passed ResetTimeDiffRecord(); UpdateSessions(diff); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index a59d9ef882a..abc0ea452ac 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -81,6 +81,7 @@ enum WorldTimers WUPDATE_DELETECHARS, WUPDATE_AHBOT, WUPDATE_PINGDB, + WUPDATE_CHECK_FILECHANGES, WUPDATE_COUNT }; @@ -167,6 +168,12 @@ enum WorldBoolConfigs CONFIG_RESET_DUEL_HEALTH_MANA, CONFIG_BASEMAP_LOAD_GRIDS, CONFIG_INSTANCEMAP_LOAD_GRIDS, + CONFIG_HOTSWAP_ENABLED, + CONFIG_HOTSWAP_RECOMPILER_ENABLED, + CONFIG_HOTSWAP_EARLY_TERMINATION_ENABLED, + CONFIG_HOTSWAP_BUILD_FILE_RECREATION_ENABLED, + CONFIG_HOTSWAP_INSTALL_ENABLED, + CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED, BOOL_CONFIG_VALUE_COUNT }; diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index d12c44c447c..31ba073e77d 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -8,69 +8,232 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# Enable precompiled headers when using the GCC compiler. - -message(STATUS "SCRIPT PREPARATIONS") - -macro(PrepareScripts name out) - file(GLOB_RECURSE found - ${name}/*.h - ${name}/*.cpp - ) - list(APPEND ${out} ${found}) - message(STATUS " -> Prepared: ${name}") -endmacro(PrepareScripts) - -PrepareScripts(Spells PRIVATE_SOURCES) -PrepareScripts(Commands PRIVATE_SOURCES) - -if(SCRIPTS) - PrepareScripts(Custom PRIVATE_SOURCES) - PrepareScripts(World PRIVATE_SOURCES) - PrepareScripts(OutdoorPvP PRIVATE_SOURCES) - PrepareScripts(EasternKingdoms PRIVATE_SOURCES) - PrepareScripts(Kalimdor PRIVATE_SOURCES) - PrepareScripts(Outland PRIVATE_SOURCES) - PrepareScripts(Northrend PRIVATE_SOURCES) - PrepareScripts(Events PRIVATE_SOURCES) - PrepareScripts(Pet PRIVATE_SOURCES) +message("") + +# Make the script module list available in the current scope +GetScriptModuleList(SCRIPT_MODULE_LIST) + +# Make the native install offset available in this scope +GetInstallOffset(INSTALL_OFFSET) + +# Sets the SCRIPTS_${SCRIPT_MODULE} variables +# when using predefined templates for script building +# like dynamic, static, minimal-static... +# Sets SCRIPTS_DEFAULT_LINKAGE +if (SCRIPTS MATCHES "dynamic") + set(SCRIPTS_DEFAULT_LINKAGE "dynamic") +elseif(SCRIPTS MATCHES "static") + set(SCRIPTS_DEFAULT_LINKAGE "static") +else() + set(SCRIPTS_DEFAULT_LINKAGE "disabled") +endif() +# Sets SCRIPTS_USE_WHITELIST +# Sets SCRIPTS_WHITELIST +if (SCRIPTS MATCHES "minimal") + set(SCRIPTS_USE_WHITELIST ON) + # Whitelist which is used when minimal is selected + list(APPEND SCRIPTS_WHITELIST Commands Spells) endif() -message(STATUS "SCRIPT PREPARATION COMPLETE") -message("") +# Set the SCRIPTS_${SCRIPT_MODULE} variables from the +# variables set above +foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST}) + ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE) + if (${SCRIPT_MODULE_VARIABLE} STREQUAL "default") + if(SCRIPTS_USE_WHITELIST) + list(FIND SCRIPTS_WHITELIST "${SCRIPT_MODULE}" INDEX) + if (${INDEX} GREATER -1) + set(${SCRIPT_MODULE_VARIABLE} ${SCRIPTS_DEFAULT_LINKAGE}) + else() + set(${SCRIPT_MODULE_VARIABLE} "disabled") + endif() + else() + set(${SCRIPT_MODULE_VARIABLE} ${SCRIPTS_DEFAULT_LINKAGE}) + endif() + endif() + # Build the Graph values + if (${SCRIPT_MODULE_VARIABLE} MATCHES "dynamic") + GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME) + GetNativeSharedLibraryName(${SCRIPT_MODULE_PROJECT_NAME} SCRIPT_PROJECT_LIBRARY) + list(APPEND GRAPH_KEYS ${SCRIPT_MODULE_PROJECT_NAME}) + set(GRAPH_VALUE_DISPLAY_${SCRIPT_MODULE_PROJECT_NAME} ${SCRIPT_PROJECT_LIBRARY}) + list(APPEND GRAPH_VALUE_CONTAINS_MODULES_${SCRIPT_MODULE_PROJECT_NAME} ${SCRIPT_MODULE}) + elseif(${SCRIPT_MODULE_VARIABLE} MATCHES "static") + list(APPEND GRAPH_KEYS worldserver) + set(GRAPH_VALUE_DISPLAY_worldserver worldserver) + list(APPEND GRAPH_VALUE_CONTAINS_MODULES_worldserver ${SCRIPT_MODULE}) + else() + list(APPEND GRAPH_KEYS disabled) + set(GRAPH_VALUE_DISPLAY_disabled disabled) + list(APPEND GRAPH_VALUE_CONTAINS_MODULES_disabled ${SCRIPT_MODULE}) + endif() +endforeach() -list(APPEND PRIVATE_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.h - ${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.cpp) +list(SORT GRAPH_KEYS) +list(REMOVE_DUPLICATES GRAPH_KEYS) +# Display the script graph +message("* Script configuration (${SCRIPTS}): + |") + +foreach(GRAPH_KEY ${GRAPH_KEYS}) + if (NOT GRAPH_KEY STREQUAL "disabled") + message(" +- ${GRAPH_VALUE_DISPLAY_${GRAPH_KEY}}") + else() + message(" | ${GRAPH_VALUE_DISPLAY_${GRAPH_KEY}}") + endif() + foreach(GRAPH_PROJECT_ENTRY ${GRAPH_VALUE_CONTAINS_MODULES_${GRAPH_KEY}}) + message(" | +- ${GRAPH_PROJECT_ENTRY}") + endforeach() + message(" |") +endforeach() + +# Base sources which are used by every script project if (USE_SCRIPTPCH) - set(PRIVATE_PCH_HEADER PrecompiledHeaders/ScriptPCH.h) - set(PRIVATE_PCH_SOURCE PrecompiledHeaders/ScriptPCH.cpp) + set(PRIVATE_PCH_HEADER ScriptPCH.h) + set(PRIVATE_PCH_SOURCE ScriptPCH.cpp) endif () GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) +# Configures the scriptloader with the given name and stores the output in the LOADER_OUT variable. +# It is possible to expose multiple subdirectories from the same scriptloader through passing +# it to the variable arguments +function(ConfigureScriptLoader SCRIPTLOADER_NAME LOADER_OUT IS_DYNAMIC_SCRIPTLOADER) + # Deduces following variables which are referenced by thge template: + # TRINITY_IS_DYNAMIC_SCRIPTLOADER + # TRINITY_SCRIPTS_FORWARD_DECL + # TRINITY_SCRIPTS_INVOKE + # TRINITY_CURRENT_SCRIPT_PROJECT + + # To generate export macros + set(TRINITY_IS_DYNAMIC_SCRIPTLOADER ${IS_DYNAMIC_SCRIPTLOADER}) + # To generate forward declarations of the loading functions + unset(TRINITY_SCRIPTS_FORWARD_DECL) + unset(TRINITY_SCRIPTS_INVOKE) + # The current script project which is built in + set(TRINITY_CURRENT_SCRIPT_PROJECT ${SCRIPTLOADER_NAME}) + foreach(LOCALE_SCRIPT_MODULE ${ARGN}) + # Determine the loader function ("Add##${NameOfDirectory}##Scripts()") + set(LOADER_FUNCTION + "Add${LOCALE_SCRIPT_MODULE}Scripts()") + # Generate the funciton call and the forward declarations + set(TRINITY_SCRIPTS_FORWARD_DECL + "${TRINITY_SCRIPTS_FORWARD_DECL}void ${LOADER_FUNCTION};\n") + set(TRINITY_SCRIPTS_INVOKE + "${TRINITY_SCRIPTS_INVOKE} ${LOADER_FUNCTION};\n") + endforeach() + set(GENERATED_LOADER ${CMAKE_CURRENT_BINARY_DIR}/gen_scriptloader/${SCRIPTLOADER_NAME}/ScriptLoader.cpp) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.cpp.in.cmake ${GENERATED_LOADER}) + set(${LOADER_OUT} ${GENERATED_LOADER} PARENT_SCOPE) +endfunction() + +# Generates the actual script projects +# Fills the STATIC_SCRIPT_MODULES and DYNAMIC_SCRIPT_MODULE_PROJECTS variables +# which contain the names which scripts are linked statically/dynamically and +# adds the sources of the static modules to the PRIVATE_SOURCES variable. +foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST}) + GetPathToScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PATH) + ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE) + + if ((${SCRIPT_MODULE_VARIABLE} STREQUAL "disabled") OR + (${SCRIPT_MODULE_VARIABLE} STREQUAL "static")) + # Uninstall disabled modules + GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME) + GetNativeSharedLibraryName(${SCRIPT_MODULE_PROJECT_NAME} SCRIPT_MODULE_OUTPUT_NAME) + list(APPEND DISABLED_SCRIPT_MODULE_PROJECTS ${INSTALL_OFFSET}/${SCRIPT_MODULE_OUTPUT_NAME}) + if (${SCRIPT_MODULE_VARIABLE} STREQUAL "static") + # Add the module name to STATIC_SCRIPT_MODULES + list(APPEND STATIC_SCRIPT_MODULES ${SCRIPT_MODULE}) + # Add the module content to the whole static module + CollectSourceFiles(${SCRIPT_MODULE_PATH} PRIVATE_SOURCES) + endif() + elseif(${SCRIPT_MODULE_VARIABLE} STREQUAL "dynamic") + # Generate an own dynamic module which is loadable on runtime + # Add the module content to the whole static module + unset(SCRIPT_MODULE_PRIVATE_SOURCES) + CollectSourceFiles(${SCRIPT_MODULE_PATH} SCRIPT_MODULE_PRIVATE_SOURCES) + # Configure the scriptloader + ConfigureScriptLoader(${SCRIPT_MODULE} SCRIPT_MODULE_PRIVATE_SCRIPTLOADER ON ${SCRIPT_MODULE}) + GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME) + # Add the module name to DYNAMIC_SCRIPT_MODULES + list(APPEND DYNAMIC_SCRIPT_MODULE_PROJECTS ${SCRIPT_MODULE_PROJECT_NAME}) + # Create the script module project + add_library(${SCRIPT_MODULE_PROJECT_NAME} SHARED + ${PRIVATE_PCH_SOURCE} + ${SCRIPT_MODULE_PRIVATE_SOURCES} + ${SCRIPT_MODULE_PRIVATE_SCRIPTLOADER}) + target_link_libraries(${SCRIPT_MODULE_PROJECT_NAME} + PUBLIC + game) + set_target_properties(${SCRIPT_MODULE_PROJECT_NAME} + PROPERTIES + FOLDER + "scripts") + + if(UNIX) + install(TARGETS ${SCRIPT_MODULE_PROJECT_NAME} + DESTINATION ${INSTALL_OFFSET} + COMPONENT ${SCRIPT_MODULE_PROJECT_NAME}) + elseif(WIN32) + install(TARGETS ${SCRIPT_MODULE_PROJECT_NAME} + RUNTIME DESTINATION ${INSTALL_OFFSET} + COMPONENT ${SCRIPT_MODULE_PROJECT_NAME}) + if(MSVC) + # Place the script modules in the script subdirectory + set_target_properties(${SCRIPT_MODULE_PROJECT_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/Debug/scripts + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/Release/scripts + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/bin/RelWithDebInfo/scripts + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}/bin/MinSizeRel/scripts) + endif() + endif() + else() + message(FATAL_ERROR "Unknown value \"${${SCRIPT_MODULE_VARIABLE}}\"!") + endif() +endforeach() + +# Add the dynamic script modules to the worldserver as dependency +set(WORLDSERVER_DYNAMIC_SCRIPT_MODULES_DEPENDENCIES ${DYNAMIC_SCRIPT_MODULE_PROJECTS} PARENT_SCOPE) + +ConfigureScriptLoader("static" SCRIPT_MODULE_PRIVATE_SCRIPTLOADER OFF ${STATIC_SCRIPT_MODULES}) + add_library(scripts STATIC - ${PRIVATE_SOURCES} + ScriptLoader.h ${PRIVATE_PCH_SOURCE} -) + ${SCRIPT_MODULE_PRIVATE_SCRIPTLOADER} + ${PRIVATE_SOURCES}) -target_include_directories(scripts +target_link_libraries(scripts PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE - ${CMAKE_CURRENT_BINARY_DIR}) + game-interface) -target_link_libraries(scripts +target_include_directories(scripts PUBLIC - game) + ${CMAKE_CURRENT_SOURCE_DIR}) set_target_properties(scripts - PROPERTIES - FOLDER - "server") + PROPERTIES + FOLDER + "scripts") # Generate precompiled header if (USE_SCRIPTPCH) - add_cxx_pch(scripts ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) + list(APPEND ALL_SCRIPT_PROJECTS scripts ${DYNAMIC_SCRIPT_MODULE_PROJECTS}) + add_cxx_pch("${ALL_SCRIPT_PROJECTS}" ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) +endif() + +# Remove all shared libraries in the installl directory which +# are contained in the static library already. +if (DISABLED_SCRIPT_MODULE_PROJECTS) + install(CODE " + foreach(SCRIPT_TO_UNINSTALL ${DISABLED_SCRIPT_MODULE_PROJECTS}) + if (EXISTS \"\${SCRIPT_TO_UNINSTALL}\") + message(STATUS \"Uninstalling: \${SCRIPT_TO_UNINSTALL}\") + file(REMOVE \"\${SCRIPT_TO_UNINSTALL}\") + endif() + endforeach() + ") endif() + +message("") diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 6ffb92d9684..4bce2d168a9 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -121,8 +121,14 @@ public: if (!accountName || !password) return false; - AccountOpResult result = sAccountMgr->CreateAccount(std::string(accountName), std::string(password), email); - switch (result) + if (strchr(accountName, '@')) + { + handler->PSendSysMessage(LANG_ACCOUNT_USE_BNET_COMMANDS); + handler->SetSentErrorMessage(true); + return false; + } + + switch (sAccountMgr->CreateAccount(std::string(accountName), std::string(password), email)) { case AccountOpResult::AOR_OK: handler->PSendSysMessage(LANG_ACCOUNT_CREATED, accountName); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 01a048c8795..1d8094885d4 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -124,6 +124,23 @@ public: return false; } + // Dump camera locations + if (CinematicSequencesEntry const* cineSeq = sCinematicSequencesStore.LookupEntry(id)) + { + std::unordered_map<uint32, FlyByCameraCollection>::const_iterator itr = sFlyByCameraStore.find(cineSeq->cinematicCamera); + if (itr != sFlyByCameraStore.end()) + { + handler->PSendSysMessage("Waypoints for sequence %u, camera %u", id, cineSeq->cinematicCamera); + uint32 count = 1 ; + for (FlyByCamera cam : itr->second) + { + handler->PSendSysMessage("%02u - %7ums [%f, %f, %f] Facing %f (%f degrees)", count, cam.timeStamp, cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w, cam.locations.w * (180 / M_PI)); + count++; + } + handler->PSendSysMessage("%u waypoints dumped", itr->second.size()); + } + } + handler->GetSession()->GetPlayer()->SendCinematicStart(id); return true; } diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index 3a062b21c3e..861b45efa95 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -1339,8 +1339,8 @@ public: } // Set gender - target->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); - target->SetByteValue(PLAYER_BYTES_3, 0, gender); + target->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, gender); + target->SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER, gender); // Change display ID target->InitDisplayIds(); diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 56b0dbf43d0..eb28a8adae4 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -251,7 +251,7 @@ public: static bool HandleReloadAllScriptsCommand(ChatHandler* handler, const char* /*args*/) { - if (sScriptMgr->IsScriptScheduled()) + if (sMapMgr->IsScriptScheduled()) { handler->PSendSysMessage("DB scripts used currently, please attempt reload later."); handler->SetSentErrorMessage(true); @@ -393,7 +393,7 @@ public: static bool HandleReloadCommandCommand(ChatHandler* handler, const char* /*args*/) { - handler->SetLoadCommandTable(true); + ChatHandler::invalidateCommandTable(); handler->SendGlobalGMSysMessage("DB table `command` will be reloaded at next chat command use."); return true; } @@ -893,7 +893,7 @@ public: static bool HandleReloadEventScriptsCommand(ChatHandler* handler, const char* args) { - if (sScriptMgr->IsScriptScheduled()) + if (sMapMgr->IsScriptScheduled()) { handler->SendSysMessage("DB scripts used currently, please attempt reload later."); handler->SetSentErrorMessage(true); @@ -913,7 +913,7 @@ public: static bool HandleReloadWpScriptsCommand(ChatHandler* handler, const char* args) { - if (sScriptMgr->IsScriptScheduled()) + if (sMapMgr->IsScriptScheduled()) { handler->SendSysMessage("DB scripts used currently, please attempt reload later."); handler->SetSentErrorMessage(true); @@ -946,7 +946,7 @@ public: static bool HandleReloadSpellScriptsCommand(ChatHandler* handler, const char* args) { - if (sScriptMgr->IsScriptScheduled()) + if (sMapMgr->IsScriptScheduled()) { handler->SendSysMessage("DB scripts used currently, please attempt reload later."); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index 05941120423..ba1dab28350 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -102,7 +102,7 @@ public: player->setFactionForRace(player->getRace()); - player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powerType << 24))); + player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, powerType); // reset only if player not in some form; if (player->GetShapeshiftForm() == FORM_NONE) diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp index 8c781bb9001..b794a653791 100644 --- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -89,7 +89,6 @@ void AddSC_boss_sulfuron(); void AddSC_boss_majordomo(); void AddSC_boss_ragnaros(); void AddSC_instance_molten_core(); -void AddSC_instance_ragefire_chasm(); //Ragefire Chasm void AddSC_the_scarlet_enclave(); //Scarlet Enclave void AddSC_the_scarlet_enclave_c1(); void AddSC_the_scarlet_enclave_c2(); @@ -268,7 +267,6 @@ void AddEasternKingdomsScripts() AddSC_boss_majordomo(); AddSC_boss_ragnaros(); AddSC_instance_molten_core(); - AddSC_instance_ragefire_chasm(); //Ragefire Chasm AddSC_the_scarlet_enclave(); //Scarlet Enclave AddSC_the_scarlet_enclave_c1(); AddSC_the_scarlet_enclave_c2(); diff --git a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp index f1969a063d6..87edf4781d4 100644 --- a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp +++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp @@ -47,6 +47,7 @@ void AddSC_boss_meathook(); void AddSC_culling_of_stratholme(); void AddSC_instance_culling_of_stratholme(); void AddSC_instance_dire_maul(); //Dire Maul +void AddSC_instance_ragefire_chasm(); //Ragefire Chasm void AddSC_boss_celebras_the_cursed(); //Maraudon void AddSC_boss_landslide(); void AddSC_boss_noxxion(); @@ -143,6 +144,7 @@ void AddKalimdorScripts() AddSC_culling_of_stratholme(); AddSC_instance_culling_of_stratholme(); AddSC_instance_dire_maul(); //Dire Maul + AddSC_instance_ragefire_chasm(); //Ragefire Chasm AddSC_boss_celebras_the_cursed(); //Maraudon AddSC_boss_landslide(); AddSC_boss_noxxion(); diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp index 852cd62c277..b113615ca50 100644 --- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp +++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp @@ -552,7 +552,7 @@ public: { if (!HasEscortState(STATE_ESCORT_ESCORTING)) { - if (me->getStandState() == UNIT_STAND_STATE_DEAD) + if (me->GetStandState() == UNIT_STAND_STATE_DEAD) me->SetStandState(UNIT_STAND_STATE_STAND); IsPostEvent = false; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index bc8c7f877a9..3d21388ca11 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -809,7 +809,7 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg : public SpellScriptLoader // this is an additional effect to be executed void PeriodicTick(AuraEffect const* aurEff) { - SpellInfo const* damageSpell = sSpellMgr->EnsureSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE); + SpellInfo const* damageSpell = sSpellMgr->AssertSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE); int32 damage = damageSpell->Effects[EFFECT_0].CalcValue(); float multiplier = 0.3375f + 0.1f * uint32(aurEff->GetTickNumber()/10); // do not convert to 0.01f - we need tick number/10 as INT (damage increases every 10 ticks) damage = int32(damage * multiplier); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index 9b0693ec95e..d77842fff0a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -1843,7 +1843,7 @@ class spell_igb_rocket_pack : public SpellScriptLoader void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { - SpellInfo const* damageInfo = sSpellMgr->EnsureSpellInfo(SPELL_ROCKET_PACK_DAMAGE); + SpellInfo const* damageInfo = sSpellMgr->AssertSpellInfo(SPELL_ROCKET_PACK_DAMAGE); GetTarget()->CastCustomSpell(SPELL_ROCKET_PACK_DAMAGE, SPELLVALUE_BASE_POINT0, 2 * (damageInfo->Effects[EFFECT_0].CalcValue() + aurEff->GetTickNumber() * aurEff->GetAmplitude()), NULL, TRIGGERED_FULL_MASK); GetTarget()->CastSpell(NULL, SPELL_ROCKET_BURST, TRIGGERED_FULL_MASK); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index f4e9d4673f2..280a0aaa13a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -1257,7 +1257,7 @@ class spell_putricide_mutated_plague : public SpellScriptLoader return; uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; - SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(triggerSpell); + SpellInfo const* spell = sSpellMgr->AssertSpellInfo(triggerSpell); spell = sSpellMgr->GetSpellForDifficultyFromSpell(spell, caster); int32 damage = spell->Effects[EFFECT_0].CalcValue(caster); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 309d5d4c62f..0714f2426bc 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -359,9 +359,9 @@ static bool IsEncounterFinished(Unit* who) if (!mkii || !vx001 || !aerial) return false; - if (mkii->getStandState() == UNIT_STAND_STATE_DEAD && - vx001->getStandState() == UNIT_STAND_STATE_DEAD && - aerial->getStandState() == UNIT_STAND_STATE_DEAD) + if (mkii->GetStandState() == UNIT_STAND_STATE_DEAD && + vx001->GetStandState() == UNIT_STAND_STATE_DEAD && + aerial->GetStandState() == UNIT_STAND_STATE_DEAD) { who->Kill(mkii); who->Kill(vx001); diff --git a/src/server/scripts/ScriptLoader.cpp b/src/server/scripts/ScriptLoader.cpp deleted file mode 100644 index 57c848d5981..00000000000 --- a/src/server/scripts/ScriptLoader.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ScriptLoader.h" -#include "World.h" - -void AddSpellsScripts(); -void AddCommandsScripts(); - -#ifdef SCRIPTS -void AddWorldScripts(); -void AddEasternKingdomsScripts(); -void AddKalimdorScripts(); -void AddOutlandScripts(); -void AddNorthrendScripts(); -void AddEventsScripts(); -void AddPetScripts(); -void AddOutdoorPvPScripts(); -void AddCustomScripts(); -#endif - -void AddScripts() -{ - AddSpellsScripts(); - AddCommandsScripts(); -#ifdef SCRIPTS - AddWorldScripts(); - AddEasternKingdomsScripts(); - AddKalimdorScripts(); - AddOutlandScripts(); - AddNorthrendScripts(); - AddEventsScripts(); - AddPetScripts(); - AddOutdoorPvPScripts(); - AddCustomScripts(); -#endif -} diff --git a/src/server/scripts/ScriptLoader.cpp.in.cmake b/src/server/scripts/ScriptLoader.cpp.in.cmake new file mode 100644 index 00000000000..33c336a9a93 --- /dev/null +++ b/src/server/scripts/ScriptLoader.cpp.in.cmake @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This file was created automatically from your script configuration! +// Use CMake to reconfigure this file, never change it on your own! + +#cmakedefine TRINITY_IS_DYNAMIC_SCRIPTLOADER + +#include "Define.h" +#include <vector> +#include <string> + +@TRINITY_SCRIPTS_FORWARD_DECL@ +#ifdef TRINITY_IS_DYNAMIC_SCRIPTLOADER +# include "revision_data.h" +# define TC_SCRIPT_API TC_API_EXPORT +extern "C" { + +/// Exposed in script modules to return the script module revision hash. +TC_SCRIPT_API char const* GetScriptModuleRevisionHash() +{ + return _HASH; +} + +/// Exposed in script module to return the name of the script module +/// contained in this shared library. +TC_SCRIPT_API char const* GetScriptModule() +{ + return "@TRINITY_CURRENT_SCRIPT_PROJECT@"; +} + +#else +# include "ScriptLoader.h" +# define TC_SCRIPT_API +#endif + +/// Exposed in script modules to register all scripts to the ScriptMgr. +TC_SCRIPT_API void AddScripts() +{ +@TRINITY_SCRIPTS_INVOKE@} + +/// Exposed in script modules to get the build directive of the module. +TC_SCRIPT_API char const* GetBuildDirective() +{ + return _BUILD_DIRECTIVE; +} + +#ifdef TRINITY_IS_DYNAMIC_SCRIPTLOADER +} // extern "C" +#endif diff --git a/src/server/scripts/PrecompiledHeaders/ScriptPCH.cpp b/src/server/scripts/ScriptPCH.cpp index 41fecf3c60d..41fecf3c60d 100644 --- a/src/server/scripts/PrecompiledHeaders/ScriptPCH.cpp +++ b/src/server/scripts/ScriptPCH.cpp diff --git a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h b/src/server/scripts/ScriptPCH.h index 1cd25309055..1cd25309055 100644 --- a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h +++ b/src/server/scripts/ScriptPCH.h diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index d210eda9045..724019a1b19 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -226,7 +226,7 @@ class spell_dk_anti_magic_zone : public SpellScriptLoader void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/) { - SpellInfo const* talentSpell = sSpellMgr->EnsureSpellInfo(SPELL_DK_ANTI_MAGIC_SHELL_TALENT); + SpellInfo const* talentSpell = sSpellMgr->AssertSpellInfo(SPELL_DK_ANTI_MAGIC_SHELL_TALENT); amount = talentSpell->Effects[EFFECT_0].CalcValue(GetCaster()); if (Player* player = GetCaster()->ToPlayer()) amount += int32(2 * player->GetTotalAttackPowerValue(BASE_ATTACK)); @@ -1634,7 +1634,7 @@ class spell_dk_will_of_the_necropolis : public SpellScriptLoader { // min pct of hp is stored in effect 0 of talent spell uint8 rank = GetSpellInfo()->GetRank(); - SpellInfo const* talentProto = sSpellMgr->EnsureSpellInfo(sSpellMgr->GetSpellWithRank(SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1, rank)); + SpellInfo const* talentProto = sSpellMgr->AssertSpellInfo(sSpellMgr->GetSpellWithRank(SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1, rank)); int32 remainingHp = int32(GetTarget()->GetHealth() - dmgInfo.GetDamage()); int32 minHp = int32(GetTarget()->CountPctFromMaxHealth(talentProto->Effects[EFFECT_0].CalcValue(GetCaster()))); diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index ce729277e42..8b8c5300a9e 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -1245,7 +1245,7 @@ class spell_gen_defend : public SpellScriptLoader void Register() override { - SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(m_scriptSpellId); + SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId); // Defend spells cast by NPCs (add visuals) if (spell->Effects[EFFECT_0].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) @@ -2148,7 +2148,7 @@ class spell_gen_mounted_charge: public SpellScriptLoader void Register() override { - SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(m_scriptSpellId); + SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId); if (spell->HasEffect(SPELL_EFFECT_SCRIPT_EFFECT)) OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge_SpellScript::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT); diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index a3359fdf6f9..6442eb8acca 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -65,7 +65,7 @@ class spell_love_is_in_the_air_romantic_picnic : public SpellScriptLoader Unit* caster = GetCaster(); // If our player is no longer sit, remove all auras - if (target->getStandState() != UNIT_STAND_STATE_SIT) + if (target->GetStandState() != UNIT_STAND_STATE_SIT) { target->RemoveAura(SPELL_ROMANTIC_PICNIC_ACHIEV); target->RemoveAura(GetAura()); @@ -84,7 +84,7 @@ class spell_love_is_in_the_air_romantic_picnic : public SpellScriptLoader target->VisitNearbyWorldObject(INTERACTION_DISTANCE*2, searcher); for (std::list<Player*>::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr) { - if ((*itr) != target && (*itr)->HasAura(GetId())) // && (*itr)->getStandState() == UNIT_STAND_STATE_SIT) + if ((*itr) != target && (*itr)->HasAura(GetId())) // && (*itr)->GetStandState() == UNIT_STAND_STATE_SIT) { if (caster) { diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 4d7cc277ff6..82d9d134445 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -763,7 +763,7 @@ class spell_hun_readiness : public SpellScriptLoader // immediately finishes the cooldown on your other Hunter abilities except Bestial Wrath GetCaster()->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); ///! If spellId in cooldown map isn't valid, the above will return a null pointer. if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index d08968fbf55..2f4e4fa6f44 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -180,7 +180,7 @@ class spell_mage_cold_snap : public SpellScriptLoader { GetCaster()->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); return spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfo->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && spellInfo->Id != SPELL_MAGE_COLD_SNAP && spellInfo->GetRecoveryTime() > 0; }, true); @@ -405,7 +405,7 @@ class spell_mage_ignite : public SpellScriptLoader { PreventDefaultAction(); - SpellInfo const* igniteDot = sSpellMgr->EnsureSpellInfo(SPELL_MAGE_IGNITE); + SpellInfo const* igniteDot = sSpellMgr->AssertSpellInfo(SPELL_MAGE_IGNITE); int32 pct = 8 * GetSpellInfo()->GetRank(); int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks()); diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 8bd4b3eb070..d9fd36f5fd4 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -1195,7 +1195,7 @@ class spell_pal_light_s_beacon : public SpellScriptLoader if (!procSpell) return; - uint32 healSpellId = procSpell->IsRankOf(sSpellMgr->EnsureSpellInfo(SPELL_PALADIN_HOLY_LIGHT)) ? SPELL_PALADIN_BEACON_OF_LIGHT_HEAL_1 : SPELL_PALADIN_BEACON_OF_LIGHT_HEAL_3; + uint32 healSpellId = procSpell->IsRankOf(sSpellMgr->AssertSpellInfo(SPELL_PALADIN_HOLY_LIGHT)) ? SPELL_PALADIN_BEACON_OF_LIGHT_HEAL_1 : SPELL_PALADIN_BEACON_OF_LIGHT_HEAL_3; uint32 heal = CalculatePct(eventInfo.GetHealInfo()->GetHeal(), aurEff->GetAmount()); Unit* beaconTarget = GetCaster(); diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp index 7393a7d3bcb..cde291cd82b 100644 --- a/src/server/scripts/Spells/spell_pet.cpp +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -916,7 +916,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue()); } @@ -959,7 +959,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value mod += CalculatePct(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); } @@ -989,7 +989,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value mod += CalculatePct(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index ecf5b7b5acf..51f03346df1 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -236,7 +236,7 @@ class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader { PreventDefaultAction(); - SpellInfo const* triggeredSpellInfo = sSpellMgr->EnsureSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL); + SpellInfo const* triggeredSpellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL); int32 heal = int32(CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks()); GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff); } diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index 9b577d4e140..affc4d1c26c 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -450,7 +450,7 @@ class spell_rog_preparation : public SpellScriptLoader Unit* caster = GetCaster(); caster->GetSpellHistory()->ResetCooldowns([caster](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); if (spellInfo->SpellFamilyName != SPELLFAMILY_ROGUE) return false; diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 7cc6fe888e9..a0a6189cbe2 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -271,7 +271,7 @@ class spell_warl_demonic_circle_summon : public SpellScriptLoader // WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST; allowing him to cast the WARLOCK_DEMONIC_CIRCLE_TELEPORT. // If not in range remove the WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST. - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT); if (GetTarget()->IsWithinDist(circle, spellInfo->GetMaxRange(true))) { @@ -362,7 +362,7 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader break; case CREATURE_FAMILY_VOIDWALKER: { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER); int32 hp = int32(targetCreature->CountPctFromMaxHealth(GetCaster()->CalculateSpellDamage(targetCreature, spellInfo, 0))); targetCreature->CastCustomSpell(targetCreature, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER, &hp, NULL, NULL, true); //unitTarget->CastSpell(unitTarget, 54441, true); diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index d224c234cb4..ea9ccc956e5 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -271,7 +271,7 @@ class spell_warr_deep_wounds : public SpellScriptLoader { ApplyPct(damage, 16 * GetSpellInfo()->GetRank()); - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC); uint32 ticks = uint32(spellInfo->GetDuration()) / spellInfo->Effects[EFFECT_0].Amplitude; // Add remaining ticks to damage done diff --git a/src/server/scripts/World/duel_reset.cpp b/src/server/scripts/World/duel_reset.cpp index 7982a5639ec..b04f3ec0aa7 100644 --- a/src/server/scripts/World/duel_reset.cpp +++ b/src/server/scripts/World/duel_reset.cpp @@ -105,7 +105,7 @@ class DuelResetScript : public PlayerScript { SpellHistory::Clock::time_point now = SpellHistory::Clock::now(); uint32 cooldownDuration = itr->second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(itr->second.CooldownEnd - now).count() : 0; - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS && !itr->second.OnHold @@ -119,7 +119,7 @@ class DuelResetScript : public PlayerScript // remove cooldowns on spells that have < 10 min CD and has no onHold player->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS && !itr->second.OnHold; diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt index 1ab340a4f3e..e99a81a084b 100644 --- a/src/server/shared/CMakeLists.txt +++ b/src/server/shared/CMakeLists.txt @@ -24,8 +24,8 @@ GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_definitions(-DTRINITY_API_EXPORT_SHARED) add_library(shared - ${PRIVATE_SOURCES} ${PRIVATE_PCH_SOURCE} + ${PRIVATE_SOURCES} ) CollectIncludeDirectories( diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h index b93bbdaea12..7c2cab1e36a 100644 --- a/src/server/shared/DataStores/DBCStore.h +++ b/src/server/shared/DataStores/DBCStore.h @@ -25,6 +25,121 @@ #include "DatabaseWorkerPool.h" #include "Implementation/WorldDatabase.h" #include "DatabaseEnv.h" +#include <G3D/Vector3.h> +#include <G3D/AABox.h> + + // Structures for M4 file. Source: https://wowdev.wiki +template<typename T> +struct M2SplineKey +{ + T p0; + T p1; + T p2; +}; + +struct M2Header +{ + char Magic[4]; // "MD20" + uint32 Version; // The version of the format. + uint32 lName; // Length of the model's name including the trailing \0 + uint32 ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess. + uint32 GlobalModelFlags; // 0x0001: tilt x, 0x0002: tilt y, 0x0008: add 2 fields in header, 0x0020: load .phys data (MoP+), 0x0080: has _lod .skin files (MoP?+), 0x0100: is camera related. + uint32 nGlobalSequences; + uint32 ofsGlobalSequences; // A list of timestamps. + uint32 nAnimations; + uint32 ofsAnimations; // Information about the animations in the model. + uint32 nAnimationLookup; + uint32 ofsAnimationLookup; // Mapping of global IDs to the entries in the Animation sequences block. + uint32 nBones; // MAX_BONES = 0x100 + uint32 ofsBones; // Information about the bones in this model. + uint32 nKeyBoneLookup; + uint32 ofsKeyBoneLookup; // Lookup table for key skeletal bones. + uint32 nVertices; + uint32 ofsVertices; // Vertices of the model. + uint32 nViews; // Views (LOD) are now in .skins. + uint32 nSubmeshAnimations; + uint32 ofsSubmeshAnimations; // Submesh color and alpha animations definitions. + uint32 nTextures; + uint32 ofsTextures; // Textures of this model. + uint32 nTransparency; + uint32 ofsTransparency; // Transparency of textures. + uint32 nUVAnimation; + uint32 ofsUVAnimation; + uint32 nTexReplace; + uint32 ofsTexReplace; // Replaceable Textures. + uint32 nRenderFlags; + uint32 ofsRenderFlags; // Blending modes / render flags. + uint32 nBoneLookupTable; + uint32 ofsBoneLookupTable; // A bone lookup table. + uint32 nTexLookup; + uint32 ofsTexLookup; // The same for textures. + uint32 nTexUnits; // possibly removed with cata?! + uint32 ofsTexUnits; // And texture units. Somewhere they have to be too. + uint32 nTransLookup; + uint32 ofsTransLookup; // Everything needs its lookup. Here are the transparencies. + uint32 nUVAnimLookup; + uint32 ofsUVAnimLookup; + G3D::AABox BoundingBox; // min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height + float BoundingSphereRadius; + G3D::AABox CollisionBox; + float CollisionSphereRadius; + uint32 nBoundingTriangles; + uint32 ofsBoundingTriangles; // Our bounding volumes. Similar structure like in the old ofsViews. + uint32 nBoundingVertices; + uint32 ofsBoundingVertices; + uint32 nBoundingNormals; + uint32 ofsBoundingNormals; + uint32 nAttachments; + uint32 ofsAttachments; // Attachments are for weapons etc. + uint32 nAttachLookup; + uint32 ofsAttachLookup; // Of course with a lookup. + uint32 nEvents; + uint32 ofsEvents; // Used for playing sounds when dying and a lot else. + uint32 nLights; + uint32 ofsLights; // Lights are mainly used in loginscreens but in wands and some doodads too. + uint32 nCameras; // Format of Cameras changed with version 271! + uint32 ofsCameras; // The cameras are present in most models for having a model in the Character-Tab. + uint32 nCameraLookup; + uint32 ofsCameraLookup; // And lookup-time again. + uint32 nRibbonEmitters; + uint32 ofsRibbonEmitters; // Things swirling around. See the CoT-entrance for light-trails. + uint32 nParticleEmitters; + uint32 ofsParticleEmitters; // Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles. + uint32 nBlendMaps; // This has to deal with blending. Exists IFF (flags & 0x8) != 0. When set, textures blending is overriden by the associated array. See M2/WotLK#Blend_mode_overrides + uint32 ofsBlendMaps; // Same as above. Points to an array of uint16 of nBlendMaps entries -- From WoD information.}; +}; + +struct M2Array +{ + uint32_t number; + uint32 offset_elements; +}; +struct M2Track +{ + uint16_t interpolation_type; + uint16_t global_sequence; + M2Array timestamps; + M2Array values; +}; + +struct M2Camera +{ + uint32_t type; // 0: portrait, 1: characterinfo; -1: else (flyby etc.); referenced backwards in the lookup table. + float fov; // No radians, no degrees. Multiply by 35 to get degrees. + float far_clip; + float near_clip; + M2Track positions; // How the camera's position moves. Should be 3*3 floats. + G3D::Vector3 position_base; + M2Track target_positions; // How the target moves. Should be 3*3 floats. + G3D::Vector3 target_position_base; + M2Track rolldata; // The camera can have some roll-effect. Its 0 to 2*Pi. +}; + +struct FlyByCamera +{ + uint32 timeStamp; + G3D::Vector4 locations; +}; struct SqlDbc { diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index a779075e2ed..d24a91ed458 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -23,16 +23,7 @@ #include "Errors.h" #include "ByteConverter.h" #include "Util.h" - -#include <exception> -#include <list> -#include <map> -#include <string> -#include <vector> #include <cstring> -#include <time.h> -#include <cmath> -#include <type_traits> class MessageBuffer; diff --git a/src/server/shared/Realm/Realm.cpp b/src/server/shared/Realm/Realm.cpp index 0c8f4d1d492..11c52f281a9 100644 --- a/src/server/shared/Realm/Realm.cpp +++ b/src/server/shared/Realm/Realm.cpp @@ -16,3 +16,38 @@ */ #include "Realm.h" + +ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const +{ + ip::address realmIp; + + // Attempt to send best address for client + if (clientAddr.is_loopback()) + { + // Try guessing if realm is also connected locally + if (LocalAddress.is_loopback() || ExternalAddress.is_loopback()) + realmIp = clientAddr; + else + { + // Assume that user connecting from the machine that bnetserver is located on + // has all realms available in his local network + realmIp = LocalAddress; + } + } + else + { + if (clientAddr.is_v4() && + (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) == + (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong())) + { + realmIp = LocalAddress; + } + else + realmIp = ExternalAddress; + } + + ip::tcp::endpoint endpoint(realmIp, Port); + + // Return external IP + return endpoint; +} diff --git a/src/server/shared/Realm/Realm.h b/src/server/shared/Realm/Realm.h index 83a344dd817..241ccd2bca8 100644 --- a/src/server/shared/Realm/Realm.h +++ b/src/server/shared/Realm/Realm.h @@ -37,7 +37,7 @@ enum RealmFlags REALM_FLAG_FULL = 0x80 }; -struct RealmHandle +struct TC_SHARED_API RealmHandle { RealmHandle() : Realm(0) { } RealmHandle(uint32 index) : Realm(index) { } @@ -53,20 +53,20 @@ struct RealmHandle /// Type of server, this is values from second column of Cfg_Configs.dbc enum RealmType { - REALM_TYPE_NORMAL = 0, - REALM_TYPE_PVP = 1, - REALM_TYPE_NORMAL2 = 4, - REALM_TYPE_RP = 6, - REALM_TYPE_RPPVP = 8, + REALM_TYPE_NORMAL = 0, + REALM_TYPE_PVP = 1, + REALM_TYPE_NORMAL2 = 4, + REALM_TYPE_RP = 6, + REALM_TYPE_RPPVP = 8, - MAX_CLIENT_REALM_TYPE = 14, + MAX_CLIENT_REALM_TYPE = 14, - REALM_TYPE_FFA_PVP = 16 // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries - // replaced by REALM_PVP in realm list + REALM_TYPE_FFA_PVP = 16 // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries + // replaced by REALM_PVP in realm list }; // Storage object for a realm -struct Realm +struct TC_SHARED_API Realm { RealmHandle Id; uint32 Build; @@ -75,11 +75,13 @@ struct Realm ip::address LocalSubnetMask; uint16 Port; std::string Name; - uint8 Type; // icon + uint8 Type; RealmFlags Flags; uint8 Timezone; AccountTypes AllowedSecurityLevel; float PopulationLevel; + + ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const; }; #endif // Realm_h__ diff --git a/src/server/authserver/Realms/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp index f1b25d8554d..e941800cd76 100644 --- a/src/server/authserver/Realms/RealmList.cpp +++ b/src/server/shared/Realm/RealmList.cpp @@ -16,20 +16,25 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "Common.h" -#include "Database/DatabaseEnv.h" #include "RealmList.h" -#include <boost/asio/ip/tcp.hpp> +#include "Database/DatabaseEnv.h" +#include "Util.h" -namespace boost { namespace asio { namespace ip { class address; } } } +RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr) +{ +} -RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr) { } RealmList::~RealmList() { - delete _resolver; delete _updateTimer; } +RealmList* RealmList::Instance() +{ + static RealmList instance; + return &instance; +} + // Load the realm list from the database void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval) { @@ -38,7 +43,7 @@ void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInte _resolver = new boost::asio::ip::tcp::resolver(ioService); // Get the content of the realmlist table in the database - UpdateRealms(true, boost::system::error_code()); + UpdateRealms(boost::system::error_code()); } void RealmList::Close() @@ -67,16 +72,22 @@ void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, const std::stri realm.Port = port; } -void RealmList::UpdateRealms(bool init, boost::system::error_code const& error) +void RealmList::UpdateRealms(boost::system::error_code const& error) { if (error) return; - TC_LOG_INFO("server.authserver", "Updating Realm List..."); + TC_LOG_DEBUG("server.authserver", "Updating Realm List..."); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST); PreparedQueryResult result = LoginDatabase.Query(stmt); + std::map<RealmHandle, std::string> existingRealms; + for (auto const& p : _realms) + existingRealms[p.first] = p.second.Name; + + _realms.clear(); + // Circle through results and add them to the realm map if (result) { @@ -95,8 +106,8 @@ void RealmList::UpdateRealms(bool init, boost::system::error_code const& error) boost::asio::ip::tcp::resolver::iterator endPoint = _resolver->resolve(externalAddressQuery, ec); if (endPoint == end || ec) { - TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[2].GetString().c_str()); - return; + TC_LOG_ERROR("server.authserver", "Could not resolve address %s for realm \"%s\" id %u", fields[2].GetString().c_str(), name.c_str(), realmId); + continue; } ip::address externalAddress = (*endPoint).endpoint().address(); @@ -105,8 +116,8 @@ void RealmList::UpdateRealms(bool init, boost::system::error_code const& error) endPoint = _resolver->resolve(localAddressQuery, ec); if (endPoint == end || ec) { - TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[3].GetString().c_str()); - return; + TC_LOG_ERROR("server.authserver", "Could not resolve localAddress %s for realm \"%s\" id %u", fields[3].GetString().c_str(), name.c_str(), realmId); + continue; } ip::address localAddress = (*endPoint).endpoint().address(); @@ -115,8 +126,8 @@ void RealmList::UpdateRealms(bool init, boost::system::error_code const& error) endPoint = _resolver->resolve(localSubmaskQuery, ec); if (endPoint == end || ec) { - TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[4].GetString().c_str()); - return; + TC_LOG_ERROR("server.authserver", "Could not resolve localSubnetMask %s for realm \"%s\" id %u", fields[4].GetString().c_str(), name.c_str(), realmId); + continue; } ip::address localSubmask = (*endPoint).endpoint().address(); @@ -138,8 +149,12 @@ void RealmList::UpdateRealms(bool init, boost::system::error_code const& error) UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop); - if (init) + if (!existingRealms.count(id)) TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); + else + TC_LOG_DEBUG("server.authserver", "Updating realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); + + existingRealms.erase(id); } catch (std::exception& ex) { @@ -150,10 +165,13 @@ void RealmList::UpdateRealms(bool init, boost::system::error_code const& error) while (result->NextRow()); } + for (auto itr = existingRealms.begin(); itr != existingRealms.end(); ++itr) + TC_LOG_INFO("server.authserver", "Removed realm \"%s\".", itr->second.c_str()); + if (_updateInterval) { _updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval)); - _updateTimer->async_wait(std::bind(&RealmList::UpdateRealms, this, false, std::placeholders::_1)); + _updateTimer->async_wait(std::bind(&RealmList::UpdateRealms, this, std::placeholders::_1)); } } diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/shared/Realm/RealmList.h index e35975b215a..3b81337e762 100644 --- a/src/server/authserver/Realms/RealmList.h +++ b/src/server/shared/Realm/RealmList.h @@ -29,16 +29,12 @@ using namespace boost::asio; /// Storage object for the list of realms on the server -class RealmList +class TC_SHARED_API RealmList { public: typedef std::map<RealmHandle, Realm> RealmMap; - static RealmList* instance() - { - static RealmList instance; - return &instance; - } + static RealmList* Instance(); ~RealmList(); @@ -51,7 +47,7 @@ public: private: RealmList(); - void UpdateRealms(bool init, boost::system::error_code const& error); + void UpdateRealms(boost::system::error_code const& error); void UpdateRealm(RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr, ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population); @@ -61,5 +57,5 @@ private: boost::asio::ip::tcp::resolver* _resolver; }; -#define sRealmList RealmList::instance() +#define sRealmList RealmList::Instance() #endif diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index 7fb4c6d2b75..0de8d6054f3 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -29,8 +29,8 @@ endif() GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(worldserver - ${PRIVATE_SOURCES} ${PRIVATE_PCH_SOURCE} + ${PRIVATE_SOURCES} ) if( NOT WIN32 ) @@ -48,6 +48,7 @@ set_target_properties(worldserver PROPERTIES LINK_FLAGS "${worldserver_LINK_FLAG target_link_libraries(worldserver PUBLIC scripts + game gsoap readline) @@ -68,6 +69,11 @@ set_target_properties(worldserver FOLDER "server") +# Add all dynamic projects as dependency to the worldserver +if (WORLDSERVER_DYNAMIC_SCRIPT_MODULES_DEPENDENCIES) + add_dependencies(worldserver ${WORLDSERVER_DYNAMIC_SCRIPT_MODULES_DEPENDENCIES}) +endif() + if( WIN32 ) if ( MSVC ) add_custom_command(TARGET worldserver diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index c047c1fafc3..2b5553b4bb0 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -39,6 +39,7 @@ #include "InstanceSaveMgr.h" #include "ObjectAccessor.h" #include "ScriptMgr.h" +#include "ScriptReloadMgr.h" #include "ScriptLoader.h" #include "OutdoorPvP/OutdoorPvPMgr.h" #include "BattlegroundMgr.h" @@ -271,6 +272,7 @@ extern int main(int argc, char** argv) sOutdoorPvPMgr->Die(); sMapMgr->UnloadAll(); // unload all grids (including locked in memory) sScriptMgr->Unload(); + sScriptReloadMgr->Unload(); // set server offline LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realm.Id.Realm); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 7c512d8ae6e..c2694c640c5 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -12,6 +12,7 @@ # SERVER LOGGING # SERVER SETTINGS # UPDATE SETTINGS +# HOTSWAP SETTINGS # WARDEN SETTINGS # PLAYER INTERACTION # CREATURE SETTINGS @@ -1280,6 +1281,78 @@ Updates.CleanDeadRefMaxCount = 3 ################################################################################################### ################################################################################################### +# HOTSWAP SETTINGS +# +# HotSwap.Enabled (Requires compilation with DYNAMIC_LINKING=1) +# Description: Enables dynamic script hotswapping. +# Reloads scripts on changes. +# Default: 1 - (Enabled) +# 0 - (Disabled) + +HotSwap.Enabled = 1 + +# +# HotSwap.ScriptDir +# Description: Directory containing the script shared libraries (.dll/.so). +# Example: "/usr/local/scripts" +# Default: "scripts" + +HotSwap.ScriptDir = "scripts" + +# HotSwap.EnableReCompiler +# Description: Enables the dynamic script recompiler. +# Watches your script source directories and recompiles the +# script modules on changes. +# Default: 1 - (Enabled) +# 0 - (Disabled) + +HotSwap.EnableReCompiler = 1 + +# HotSwap.EnableEarlyTermination +# Description: Terminate the build of a module when an associated +# source file was changed meanwhile. +# Default: 1 - (Enabled) +# 0 - (Disabled) + +HotSwap.EnableEarlyTermination = 1 + +# HotSwap.EnableBuildFileRecreation +# Description: Recreate build files when sources to a module +# were added or removed. +# Default: 1 - (Enabled) +# 0 - (Disabled) + +HotSwap.EnableBuildFileRecreation = 1 + +# +# HotSwap.EnableInstall +# Description: Enables cmake install after automatic builds have finished +# Default: 1 - (Enabled) +# 0 - (Disabled) + +HotSwap.EnableInstall = 1 + +# +# HotSwap.EnablePrefixCorrection +# Description: Allows the core to automatic set the CMAKE_INSTALL_PREFIX +# to it's current location in the filesystem. +# Default: 1 - (Enabled) +# 0 - (Disabled) + +HotSwap.EnablePrefixCorrection = 1 + +# HotSwap.ReCompilerBuildType +# Description: Defines the build type of the builds invoked by the recompiler. +# Default: "" - Built-in build type of the module is used. +# "Release" - Release builds only +# "Debug" - Debug builds only + +HotSwap.ReCompilerBuildType = "" + +# +################################################################################################### + +################################################################################################### # WARDEN SETTINGS # # Warden.Enabled @@ -3220,7 +3293,6 @@ AuctionHouseBot.Class.Key = 1 AuctionHouseBot.Class.Misc = 5 AuctionHouseBot.Class.Glyph = 3 - # ################################################################################################### @@ -3551,6 +3623,7 @@ Logger.mmaps=3,Server #Logger.rbac=3,Console Server #Logger.scripts=3,Console Server #Logger.scripts.ai=3,Console Server +#Logger.scripts.hotswap=3,Console Server #Logger.server.authserver=3,Console Server #Logger.spells=3,Console Server #Logger.spells.periodic=3,Console Server diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index f3a761fd437..1d84fc75d27 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -53,12 +53,13 @@ char input_path[MAX_PATH_LENGTH] = "."; // ************************************************** enum Extract { - EXTRACT_MAP = 1, - EXTRACT_DBC = 2 + EXTRACT_MAP = 1, + EXTRACT_DBC = 2, + EXTRACT_CAMERA = 4 }; // Select data for extract -int CONF_extract = EXTRACT_MAP | EXTRACT_DBC; +int CONF_extract = EXTRACT_MAP | EXTRACT_DBC | EXTRACT_CAMERA; // This option allow limit minimum height to some value (Allow save some memory) bool CONF_allow_height_limit = true; float CONF_use_minHeight = -500.0f; @@ -103,7 +104,7 @@ void Usage(char* prg) "%s -[var] [value]\n"\ "-i set input path (max %d characters)\n"\ "-o set output path (max %d characters)\n"\ - "-e extract only MAP(1)/DBC(2) - standard: both(3)\n"\ + "-e extract only MAP(1)/DBC(2)/Camera(4) - standard: all(7)\n"\ "-f height stored as int (less map size but lost some accuracy) 1 by default\n"\ "Example: %s -f 0 -i \"c:\\games\\game\"", prg, MAX_PATH_LENGTH - 1, MAX_PATH_LENGTH - 1, prg); exit(1); @@ -151,7 +152,7 @@ void HandleArgs(int argc, char * arg[]) if(c + 1 < argc) // all ok { CONF_extract=atoi(arg[(c++) + 1]); - if(!(CONF_extract > 0 && CONF_extract < 4)) + if(!(CONF_extract > 0 && CONF_extract < 8)) Usage(arg[0]); } else @@ -1025,6 +1026,56 @@ void ExtractDBCFiles(int locale, bool basicLocale) printf("Extracted %u DBC files\n\n", count); } +void ExtractCameraFiles(int locale, bool basicLocale) +{ + printf("Extracting camera files...\n"); + DBCFile camdbc("DBFilesClient\\CinematicCamera.dbc"); + + if (!camdbc.open()) + { + printf("Unable to open CinematicCamera.dbc. Camera extract aborted.\n"); + return; + } + + // get camera file list from DBC + std::vector<std::string> camerafiles; + size_t cam_count = camdbc.getRecordCount(); + + for (uint32 i = 0; i < cam_count; ++i) + { + std::string camFile(camdbc.getRecord(i).getString(1)); + size_t loc = camFile.find(".mdx"); + if (loc != std::string::npos) + camFile.replace(loc, 4, ".m2"); + camerafiles.push_back(std::string(camFile)); + } + + std::string path = output_path; + path += "/Cameras/"; + CreateDir(path); + if (!basicLocale) + { + path += langs[locale]; + path += "/"; + CreateDir(path); + } + + // extract M2s + uint32 count = 0; + for (std::string thisFile : camerafiles) + { + std::string filename = path; + filename += (thisFile.c_str() + strlen("Cameras\\")); + + if (boost::filesystem::exists(filename)) + continue; + + if (ExtractFile(thisFile.c_str(), filename)) + ++count; + } + printf("Extracted %u camera files\n", count); +} + void LoadLocaleMPQFiles(int const locale) { std::string fileName = Trinity::StringFormat("%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]); @@ -1111,6 +1162,19 @@ int main(int argc, char * arg[]) return 0; } + if (CONF_extract & EXTRACT_CAMERA) + { + printf("Using locale: %s\n", langs[FirstLocale]); + + // Open MPQs + LoadLocaleMPQFiles(FirstLocale); + LoadCommonMPQFiles(); + + ExtractCameraFiles(FirstLocale, true); + // Close MPQs + CloseMPQFiles(); + } + if (CONF_extract & EXTRACT_MAP) { printf("Using locale: %s\n", langs[FirstLocale]); |
