Merge branch 'master' into Playerbot
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
-- DB update 2024_02_05_04 -> 2024_02_06_00
|
||||||
|
--
|
||||||
|
UPDATE `creature_template` SET `AIName` = '', `ScriptName` = 'npc_tainted_elemental' WHERE `entry` = 22009;
|
||||||
|
|
||||||
|
DELETE FROM `smart_scripts` WHERE `entryorguid` = 22009 AND `source_type` = 0;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- DB update 2024_02_06_00 -> 2024_02_08_00
|
||||||
|
--
|
||||||
|
DELETE FROM `creature_template_movement` WHERE `CreatureId` = 24224;
|
||||||
|
INSERT INTO `creature_template_movement` (`CreatureId`, `Flight`, `Rooted`) VALUES
|
||||||
|
(24224, 1, 1);
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- DB update 2024_02_08_00 -> 2024_02_08_01
|
||||||
|
--
|
||||||
|
UPDATE `creature_template` SET `spell_school_immune_mask` = `spell_school_immune_mask`|4 WHERE `entry` IN (19514, 19551);
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- DB update 2024_02_08_01 -> 2024_02_08_02
|
||||||
|
DELETE FROM `gossip_menu_option` WHERE `MenuID`=21893;
|
||||||
|
INSERT INTO `gossip_menu_option` (`MenuID`, `OptionID`, `OptionIcon`, `OptionText`, `OptionBroadcastTextID`, `OptionType`, `OptionNpcFlag`, `ActionMenuID`, `ActionPoiID`, `BoxCoded`, `BoxMoney`, `BoxText`, `BoxBroadcastTextID`, `VerifiedBuild`) VALUES
|
||||||
|
(21893, 0, 0, 'Hand over the Southfury moonstone and I\'ll let you go.', 20723, 1, 1, 0, 0, 0, 0, '', 0, 0);
|
||||||
Vendored
+5
-5
@@ -12,10 +12,10 @@
|
|||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(BOOST_DEBUG ON)
|
set(BOOST_DEBUG ON)
|
||||||
if(DEFINED ENV{BOOST_ROOT})
|
if(DEFINED ENV{Boost_ROOT})
|
||||||
set(BOOST_ROOT $ENV{BOOST_ROOT})
|
set(Boost_ROOT $ENV{Boost_ROOT})
|
||||||
list(APPEND BOOST_LIBRARYDIR
|
list(APPEND BOOST_LIBRARYDIR
|
||||||
${BOOST_ROOT}/lib${PLATFORM}-msvc-14.2)
|
${Boost_ROOT}/lib${PLATFORM}-msvc-14.2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
@@ -35,8 +35,8 @@ endif()
|
|||||||
find_package(Boost ${BOOST_REQUIRED_VERSION} REQUIRED system filesystem program_options iostreams regex thread)
|
find_package(Boost ${BOOST_REQUIRED_VERSION} REQUIRED system filesystem program_options iostreams regex thread)
|
||||||
|
|
||||||
if(NOT Boost_FOUND)
|
if(NOT Boost_FOUND)
|
||||||
if(NOT DEFINED ENV{BOOST_ROOT} AND NOT DEFINED Boost_DIR AND NOT DEFINED BOOST_ROOT AND NOT DEFINED BOOSTROOT)
|
if(NOT DEFINED ENV{Boost_ROOT} AND NOT DEFINED Boost_DIR AND NOT DEFINED BOOST_ROOT AND NOT DEFINED BOOSTROOT)
|
||||||
message(FATAL_ERROR "No BOOST_ROOT environment variable could be found! Please make sure it is set and the points to your Boost installation.")
|
message(FATAL_ERROR "No Boost_ROOT environment variable could be found! Please make sure it is set and the points to your Boost installation.")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,29 @@ FindOpenSSL
|
|||||||
|
|
||||||
Find the OpenSSL encryption library.
|
Find the OpenSSL encryption library.
|
||||||
|
|
||||||
|
This module finds an installed OpenSSL library and determines its version.
|
||||||
|
|
||||||
|
.. versionadded:: 3.19
|
||||||
|
When a version is requested, it can be specified as a simple value or as a
|
||||||
|
range. For a detailed description of version range usage and capabilities,
|
||||||
|
refer to the :command:`find_package` command.
|
||||||
|
|
||||||
|
.. versionadded:: 3.18
|
||||||
|
Support for OpenSSL 3.0.
|
||||||
|
|
||||||
Optional COMPONENTS
|
Optional COMPONENTS
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. versionadded:: 3.12
|
||||||
|
|
||||||
This module supports two optional COMPONENTS: ``Crypto`` and ``SSL``. Both
|
This module supports two optional COMPONENTS: ``Crypto`` and ``SSL``. Both
|
||||||
components have associated imported targets, as described below.
|
components have associated imported targets, as described below.
|
||||||
|
|
||||||
Imported Targets
|
Imported Targets
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
This module defines the following :prop_tgt:`IMPORTED` targets:
|
This module defines the following :prop_tgt:`IMPORTED` targets:
|
||||||
|
|
||||||
``OpenSSL::SSL``
|
``OpenSSL::SSL``
|
||||||
@@ -23,6 +37,8 @@ This module defines the following :prop_tgt:`IMPORTED` targets:
|
|||||||
``OpenSSL::Crypto``
|
``OpenSSL::Crypto``
|
||||||
The OpenSSL ``crypto`` library, if found.
|
The OpenSSL ``crypto`` library, if found.
|
||||||
``OpenSSL::applink``
|
``OpenSSL::applink``
|
||||||
|
.. versionadded:: 3.18
|
||||||
|
|
||||||
The OpenSSL ``applink`` components that might be need to be compiled into
|
The OpenSSL ``applink`` components that might be need to be compiled into
|
||||||
projects under MSVC. This target is available only if found OpenSSL version
|
projects under MSVC. This target is available only if found OpenSSL version
|
||||||
is not less than 0.9.8. By linking this target the above OpenSSL targets can
|
is not less than 0.9.8. By linking this target the above OpenSSL targets can
|
||||||
@@ -74,37 +90,116 @@ This module will set the following variables in your project:
|
|||||||
Hints
|
Hints
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
||||||
Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation.
|
The following variables may be set to control search behavior:
|
||||||
Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
|
|
||||||
Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
|
``OPENSSL_ROOT_DIR``
|
||||||
|
Set to the root directory of an OpenSSL installation.
|
||||||
|
|
||||||
|
``OPENSSL_USE_STATIC_LIBS``
|
||||||
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
Set to ``TRUE`` to look for static libraries.
|
||||||
|
|
||||||
|
``OPENSSL_MSVC_STATIC_RT``
|
||||||
|
.. versionadded:: 3.5
|
||||||
|
|
||||||
|
Set to ``TRUE`` to choose the MT version of the lib.
|
||||||
|
|
||||||
|
``ENV{PKG_CONFIG_PATH}``
|
||||||
|
On UNIX-like systems, ``pkg-config`` is used to locate the system OpenSSL.
|
||||||
|
Set the ``PKG_CONFIG_PATH`` environment variable to look in alternate
|
||||||
|
locations. Useful on multi-lib systems.
|
||||||
#]=======================================================================]
|
#]=======================================================================]
|
||||||
|
|
||||||
set(OPENSSL_EXPECTED_VERSION "1.0")
|
|
||||||
|
|
||||||
macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
|
macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
|
||||||
if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND
|
unset(_OpenSSL_extra_static_deps)
|
||||||
|
if(UNIX AND
|
||||||
(("${ssl_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") OR
|
(("${ssl_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") OR
|
||||||
("${crypto_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")))
|
("${crypto_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")))
|
||||||
set(_OpenSSL_has_dependencies TRUE)
|
set(_OpenSSL_has_dependencies TRUE)
|
||||||
|
unset(_OpenSSL_has_dependency_zlib)
|
||||||
|
if(OPENSSL_USE_STATIC_LIBS)
|
||||||
|
set(_OpenSSL_libs "${_OPENSSL_STATIC_LIBRARIES}")
|
||||||
|
set(_OpenSSL_ldflags_other "${_OPENSSL_STATIC_LDFLAGS_OTHER}")
|
||||||
|
else()
|
||||||
|
set(_OpenSSL_libs "${_OPENSSL_LIBRARIES}")
|
||||||
|
set(_OpenSSL_ldflags_other "${_OPENSSL_LDFLAGS_OTHER}")
|
||||||
|
endif()
|
||||||
|
if(_OpenSSL_libs)
|
||||||
|
unset(_OpenSSL_has_dependency_dl)
|
||||||
|
foreach(_OPENSSL_DEP_LIB IN LISTS _OpenSSL_libs)
|
||||||
|
if (_OPENSSL_DEP_LIB STREQUAL "ssl" OR _OPENSSL_DEP_LIB STREQUAL "crypto")
|
||||||
|
# ignoring: these are the targets
|
||||||
|
elseif(_OPENSSL_DEP_LIB STREQUAL CMAKE_DL_LIBS)
|
||||||
|
set(_OpenSSL_has_dependency_dl TRUE)
|
||||||
|
elseif(_OPENSSL_DEP_LIB STREQUAL "z")
|
||||||
|
find_package(ZLIB)
|
||||||
|
set(_OpenSSL_has_dependency_zlib TRUE)
|
||||||
|
else()
|
||||||
|
list(APPEND _OpenSSL_extra_static_deps "${_OPENSSL_DEP_LIB}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
unset(_OPENSSL_DEP_LIB)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(_OpenSSL_has_dependency_dl TRUE)
|
||||||
|
endif()
|
||||||
|
if(_OpenSSL_ldflags_other)
|
||||||
|
unset(_OpenSSL_has_dependency_threads)
|
||||||
|
foreach(_OPENSSL_DEP_LDFLAG IN LISTS _OpenSSL_ldflags_other)
|
||||||
|
if (_OPENSSL_DEP_LDFLAG STREQUAL "-pthread")
|
||||||
|
set(_OpenSSL_has_dependency_threads TRUE)
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
unset(_OPENSSL_DEP_LDFLAG)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(_OpenSSL_has_dependency_threads TRUE)
|
||||||
|
find_package(Threads)
|
||||||
|
endif()
|
||||||
|
unset(_OpenSSL_libs)
|
||||||
|
unset(_OpenSSL_ldflags_other)
|
||||||
else()
|
else()
|
||||||
set(_OpenSSL_has_dependencies FALSE)
|
set(_OpenSSL_has_dependencies FALSE)
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
function(_OpenSSL_add_dependencies libraries_var)
|
function(_OpenSSL_add_dependencies libraries_var)
|
||||||
if(CMAKE_THREAD_LIBS_INIT)
|
if(_OpenSSL_has_dependency_zlib)
|
||||||
|
list(APPEND ${libraries_var} ${ZLIB_LIBRARY})
|
||||||
|
endif()
|
||||||
|
if(_OpenSSL_has_dependency_threads)
|
||||||
list(APPEND ${libraries_var} ${CMAKE_THREAD_LIBS_INIT})
|
list(APPEND ${libraries_var} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
endif()
|
endif()
|
||||||
|
if(_OpenSSL_has_dependency_dl)
|
||||||
list(APPEND ${libraries_var} ${CMAKE_DL_LIBS})
|
list(APPEND ${libraries_var} ${CMAKE_DL_LIBS})
|
||||||
|
endif()
|
||||||
|
list(APPEND ${libraries_var} ${_OpenSSL_extra_static_deps})
|
||||||
set(${libraries_var} ${${libraries_var}} PARENT_SCOPE)
|
set(${libraries_var} ${${libraries_var}} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(_OpenSSL_target_add_dependencies target)
|
function(_OpenSSL_target_add_dependencies target)
|
||||||
if(_OpenSSL_has_dependencies)
|
if(_OpenSSL_has_dependencies)
|
||||||
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads )
|
if(_OpenSSL_has_dependency_zlib)
|
||||||
|
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ZLIB::ZLIB )
|
||||||
|
endif()
|
||||||
|
if(_OpenSSL_has_dependency_threads)
|
||||||
|
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads)
|
||||||
|
endif()
|
||||||
|
if(_OpenSSL_has_dependency_dl)
|
||||||
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS} )
|
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS} )
|
||||||
endif()
|
endif()
|
||||||
|
if(_OpenSSL_extra_static_deps)
|
||||||
|
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${_OpenSSL_extra_static_deps})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(WIN32 AND OPENSSL_USE_STATIC_LIBS)
|
||||||
|
if(WINCE)
|
||||||
|
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2 )
|
||||||
|
else()
|
||||||
|
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ws2_32 )
|
||||||
|
endif()
|
||||||
|
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES crypt32 )
|
||||||
|
endif()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
@@ -115,62 +210,87 @@ endif ()
|
|||||||
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
|
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
|
||||||
if(OPENSSL_USE_STATIC_LIBS)
|
if(OPENSSL_USE_STATIC_LIBS)
|
||||||
set(_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
set(_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
if(WIN32)
|
if(MSVC)
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
else()
|
else()
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
|
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if(CMAKE_SYSTEM_NAME STREQUAL "QNX" AND
|
||||||
|
CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL "7.0" AND CMAKE_SYSTEM_VERSION VERSION_LESS "7.1" AND
|
||||||
|
OpenSSL_FIND_VERSION VERSION_GREATER_EQUAL "1.1" AND OpenSSL_FIND_VERSION VERSION_LESS "1.2")
|
||||||
|
# QNX 7.0.x provides openssl 1.0.2 and 1.1.1 in parallel:
|
||||||
|
# * openssl 1.0.2: libcrypto.so.2 and libssl.so.2, headers under usr/include/openssl
|
||||||
|
# * openssl 1.1.1: libcrypto1_1.so.2.1 and libssl1_1.so.2.1, header under usr/include/openssl1_1
|
||||||
|
# See http://www.qnx.com/developers/articles/rel_6726_0.html
|
||||||
|
set(_OPENSSL_FIND_PATH_SUFFIX "openssl1_1")
|
||||||
|
set(_OPENSSL_NAME_POSTFIX "1_1")
|
||||||
|
else()
|
||||||
|
set(_OPENSSL_FIND_PATH_SUFFIX "include")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (OPENSSL_ROOT_DIR OR NOT "$ENV{OPENSSL_ROOT_DIR}" STREQUAL "")
|
||||||
|
set(_OPENSSL_ROOT_HINTS HINTS ${OPENSSL_ROOT_DIR} ENV OPENSSL_ROOT_DIR)
|
||||||
|
set(_OPENSSL_ROOT_PATHS NO_DEFAULT_PATH)
|
||||||
|
elseif (MSVC)
|
||||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||||
set(_OPENSSL_MSI_INSTALL_GUID "")
|
set(_OPENSSL_MSI_INSTALL_GUIDS "")
|
||||||
if(PLATFORM EQUAL 64)
|
|
||||||
set(_OPENSSL_MSI_INSTALL_GUID "117551DB-A110-4BBD-BB05-CFE0BCB3ED31")
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||||
set(_OPENSSL_ROOT_HINTS
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
set(_arch "Win64-ARM")
|
||||||
${OPENSSL_ROOT_DIR}
|
set(_OPENSSL_MSI_INSTALL_GUIDS "99C28AFA-6419-40B1-B88D-32B810BB4234")
|
||||||
ENV OPENSSL_ROOT_DIR
|
|
||||||
)
|
|
||||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
|
||||||
set(_OPENSSL_ROOT_PATHS
|
|
||||||
"${_programfiles}/OpenSSL"
|
|
||||||
"${_programfiles}/OpenSSL-Win64"
|
|
||||||
"C:/OpenSSL/"
|
|
||||||
"C:/OpenSSL-Win64/"
|
|
||||||
)
|
|
||||||
else()
|
else()
|
||||||
set(_OPENSSL_MSI_INSTALL_GUID "A1EEC576-43B9-4E75-9E02-03DA542D2A38")
|
set(_arch "Win64")
|
||||||
set(_OPENSSL_ROOT_HINTS
|
set(_OPENSSL_MSI_INSTALL_GUIDS "117551DB-A110-4BBD-BB05-CFE0BCB3ED31" "50A9FBE2-0F8C-4D5D-97A4-A63A71C4EA1E")
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
|
||||||
${OPENSSL_ROOT_DIR}
|
|
||||||
ENV OPENSSL_ROOT_DIR
|
|
||||||
)
|
|
||||||
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
|
||||||
set(_OPENSSL_ROOT_PATHS
|
|
||||||
"${_programfiles}/OpenSSL"
|
|
||||||
"${_programfiles}/OpenSSL-Win32"
|
|
||||||
"C:/OpenSSL/"
|
|
||||||
"C:/OpenSSL-Win32/"
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
unset(_programfiles)
|
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
|
||||||
|
set(_OPENSSL_ROOT_HINTS HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]")
|
||||||
|
else()
|
||||||
|
set(_arch "Win32")
|
||||||
|
set(_progfiles_x86 "ProgramFiles(x86)")
|
||||||
|
if(NOT "$ENV{${_progfiles_x86}}" STREQUAL "")
|
||||||
|
# under windows 64 bit machine
|
||||||
|
file(TO_CMAKE_PATH "$ENV{${_progfiles_x86}}" _programfiles)
|
||||||
|
else()
|
||||||
|
# under windows 32 bit machine
|
||||||
|
file(TO_CMAKE_PATH "$ENV{ProgramFiles}" _programfiles)
|
||||||
|
endif()
|
||||||
|
set(_OPENSSL_ROOT_HINTS HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]")
|
||||||
|
set(_OPENSSL_MSI_INSTALL_GUIDS "A1EEC576-43B9-4E75-9E02-03DA542D2A38" "31D2408A-9CAE-4988-9EC3-F40FDE7D6AE5")
|
||||||
|
endif()
|
||||||
|
|
||||||
# If OpenSSL was installed using .msi package instead of .exe, Inno Setup registry values are not written to Uninstall\OpenSSL
|
# If OpenSSL was installed using .msi package instead of .exe, Inno Setup registry values are not written to Uninstall\OpenSSL
|
||||||
# but because it is only a shim around Inno Setup it does write the location of uninstaller which we can use to determine path
|
# but because it is only a shim around Inno Setup it does write the location of uninstaller which we can use to determine path
|
||||||
|
foreach(_OPENSSL_MSI_INSTALL_GUID IN LISTS _OPENSSL_MSI_INSTALL_GUIDS)
|
||||||
get_filename_component(_OPENSSL_MSI_INSTALL_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Inno Setup MSIs\\${_OPENSSL_MSI_INSTALL_GUID};]" DIRECTORY)
|
get_filename_component(_OPENSSL_MSI_INSTALL_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Inno Setup MSIs\\${_OPENSSL_MSI_INSTALL_GUID};]" DIRECTORY)
|
||||||
if(NOT _OPENSSL_MSI_INSTALL_PATH STREQUAL "/")
|
if(NOT _OPENSSL_MSI_INSTALL_PATH STREQUAL "/")
|
||||||
list(INSERT _OPENSSL_ROOT_HINTS 0 ${_OPENSSL_MSI_INSTALL_PATH})
|
list(INSERT _OPENSSL_ROOT_HINTS 2 ${_OPENSSL_MSI_INSTALL_PATH})
|
||||||
endif()
|
endif()
|
||||||
else ()
|
endforeach()
|
||||||
set(_OPENSSL_ROOT_HINTS
|
unset(_OPENSSL_MSI_INSTALL_GUIDS)
|
||||||
${OPENSSL_ROOT_DIR}
|
|
||||||
ENV OPENSSL_ROOT_DIR
|
set(_OPENSSL_ROOT_PATHS
|
||||||
|
PATHS
|
||||||
|
"${_programfiles}/OpenSSL"
|
||||||
|
"${_programfiles}/OpenSSL-${_arch}"
|
||||||
|
"C:/OpenSSL/"
|
||||||
|
"C:/OpenSSL-${_arch}/"
|
||||||
)
|
)
|
||||||
|
unset(_programfiles)
|
||||||
|
unset(_arch)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if(HOMEBREW_PREFIX)
|
||||||
|
list(APPEND _OPENSSL_ROOT_HINTS
|
||||||
|
"${HOMEBREW_PREFIX}/opt/openssl@1.1"
|
||||||
|
"${HOMEBREW_PREFIX}/opt/openssl@3")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(_OPENSSL_ROOT_HINTS_AND_PATHS
|
set(_OPENSSL_ROOT_HINTS_AND_PATHS
|
||||||
HINTS ${_OPENSSL_ROOT_HINTS}
|
${_OPENSSL_ROOT_HINTS}
|
||||||
PATHS ${_OPENSSL_ROOT_PATHS}
|
${_OPENSSL_ROOT_PATHS}
|
||||||
)
|
)
|
||||||
|
|
||||||
find_path(OPENSSL_INCLUDE_DIR
|
find_path(OPENSSL_INCLUDE_DIR
|
||||||
@@ -181,7 +301,7 @@ find_path(OPENSSL_INCLUDE_DIR
|
|||||||
${_OPENSSL_INCLUDEDIR}
|
${_OPENSSL_INCLUDEDIR}
|
||||||
${_OPENSSL_INCLUDE_DIRS}
|
${_OPENSSL_INCLUDE_DIRS}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
include
|
${_OPENSSL_FIND_PATH_SUFFIX}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32 AND NOT CYGWIN)
|
if(WIN32 AND NOT CYGWIN)
|
||||||
@@ -211,8 +331,14 @@ if(WIN32 AND NOT CYGWIN)
|
|||||||
# Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib
|
# Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib
|
||||||
if( "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" )
|
if( "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" )
|
||||||
set(_OPENSSL_MSVC_ARCH_SUFFIX "64")
|
set(_OPENSSL_MSVC_ARCH_SUFFIX "64")
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
|
||||||
|
set(_OPENSSL_MSVC_ARCH_DIRECTORY "arm64")
|
||||||
|
else()
|
||||||
|
set(_OPENSSL_MSVC_ARCH_DIRECTORY "x64")
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
set(_OPENSSL_MSVC_ARCH_SUFFIX "32")
|
set(_OPENSSL_MSVC_ARCH_SUFFIX "32")
|
||||||
|
set(_OPENSSL_MSVC_ARCH_DIRECTORY "x86")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(OPENSSL_USE_STATIC_LIBS)
|
if(OPENSSL_USE_STATIC_LIBS)
|
||||||
@@ -235,6 +361,16 @@ if(WIN32 AND NOT CYGWIN)
|
|||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
find_library(LIB_EAY_DEBUG
|
||||||
|
NAMES
|
||||||
|
libcrypto${_OPENSSL_STATIC_SUFFIX}
|
||||||
|
NAMES_PER_DIR
|
||||||
|
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
"lib/VC/${_OPENSSL_MSVC_ARCH_DIRECTORY}/${_OPENSSL_MSVC_RT_MODE}d"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT LIB_EAY_DEBUG)
|
||||||
find_library(LIB_EAY_DEBUG
|
find_library(LIB_EAY_DEBUG
|
||||||
NAMES
|
NAMES
|
||||||
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
|
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
|
||||||
@@ -259,6 +395,7 @@ if(WIN32 AND NOT CYGWIN)
|
|||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
${_OPENSSL_PATH_SUFFIXES}
|
${_OPENSSL_PATH_SUFFIXES}
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_library(LIB_EAY_RELEASE
|
find_library(LIB_EAY_RELEASE
|
||||||
NAMES
|
NAMES
|
||||||
@@ -283,8 +420,19 @@ if(WIN32 AND NOT CYGWIN)
|
|||||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
${_OPENSSL_PATH_SUFFIXES}
|
${_OPENSSL_PATH_SUFFIXES}
|
||||||
|
"lib/VC/${_OPENSSL_MSVC_ARCH_DIRECTORY}/${_OPENSSL_MSVC_RT_MODE}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
find_library(SSL_EAY_DEBUG
|
||||||
|
NAMES
|
||||||
|
libssl${_OPENSSL_STATIC_SUFFIX}
|
||||||
|
NAMES_PER_DIR
|
||||||
|
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||||
|
PATH_SUFFIXES
|
||||||
|
"lib/VC/${_OPENSSL_MSVC_ARCH_DIRECTORY}/${_OPENSSL_MSVC_RT_MODE}d"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT SSL_EAY_DEBUG)
|
||||||
find_library(SSL_EAY_DEBUG
|
find_library(SSL_EAY_DEBUG
|
||||||
NAMES
|
NAMES
|
||||||
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
|
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
|
||||||
@@ -309,6 +457,7 @@ if(WIN32 AND NOT CYGWIN)
|
|||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
${_OPENSSL_PATH_SUFFIXES}
|
${_OPENSSL_PATH_SUFFIXES}
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_library(SSL_EAY_RELEASE
|
find_library(SSL_EAY_RELEASE
|
||||||
NAMES
|
NAMES
|
||||||
@@ -333,6 +482,7 @@ if(WIN32 AND NOT CYGWIN)
|
|||||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
${_OPENSSL_PATH_SUFFIXES}
|
${_OPENSSL_PATH_SUFFIXES}
|
||||||
|
"lib/VC/${_OPENSSL_MSVC_ARCH_DIRECTORY}/${_OPENSSL_MSVC_RT_MODE}"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
|
set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
|
||||||
@@ -360,6 +510,7 @@ if(WIN32 AND NOT CYGWIN)
|
|||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
"lib/MinGW"
|
"lib/MinGW"
|
||||||
"lib"
|
"lib"
|
||||||
|
"lib64"
|
||||||
)
|
)
|
||||||
|
|
||||||
find_library(SSL_EAY
|
find_library(SSL_EAY
|
||||||
@@ -370,6 +521,7 @@ if(WIN32 AND NOT CYGWIN)
|
|||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
"lib/MinGW"
|
"lib/MinGW"
|
||||||
"lib"
|
"lib"
|
||||||
|
"lib64"
|
||||||
)
|
)
|
||||||
|
|
||||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||||
@@ -411,7 +563,7 @@ else()
|
|||||||
|
|
||||||
find_library(OPENSSL_SSL_LIBRARY
|
find_library(OPENSSL_SSL_LIBRARY
|
||||||
NAMES
|
NAMES
|
||||||
ssl
|
ssl${_OPENSSL_NAME_POSTFIX}
|
||||||
ssleay32
|
ssleay32
|
||||||
ssleay32MD
|
ssleay32MD
|
||||||
NAMES_PER_DIR
|
NAMES_PER_DIR
|
||||||
@@ -420,19 +572,19 @@ else()
|
|||||||
${_OPENSSL_LIBDIR}
|
${_OPENSSL_LIBDIR}
|
||||||
${_OPENSSL_LIBRARY_DIRS}
|
${_OPENSSL_LIBRARY_DIRS}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
lib
|
lib lib64
|
||||||
)
|
)
|
||||||
|
|
||||||
find_library(OPENSSL_CRYPTO_LIBRARY
|
find_library(OPENSSL_CRYPTO_LIBRARY
|
||||||
NAMES
|
NAMES
|
||||||
crypto
|
crypto${_OPENSSL_NAME_POSTFIX}
|
||||||
NAMES_PER_DIR
|
NAMES_PER_DIR
|
||||||
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
${_OPENSSL_ROOT_HINTS_AND_PATHS}
|
||||||
HINTS
|
HINTS
|
||||||
${_OPENSSL_LIBDIR}
|
${_OPENSSL_LIBDIR}
|
||||||
${_OPENSSL_LIBRARY_DIRS}
|
${_OPENSSL_LIBRARY_DIRS}
|
||||||
PATH_SUFFIXES
|
PATH_SUFFIXES
|
||||||
lib
|
lib lib64
|
||||||
)
|
)
|
||||||
|
|
||||||
mark_as_advanced(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
|
mark_as_advanced(OPENSSL_CRYPTO_LIBRARY OPENSSL_SSL_LIBRARY)
|
||||||
@@ -570,14 +722,6 @@ find_package_handle_standard_args(OpenSSL
|
|||||||
mark_as_advanced(OPENSSL_INCLUDE_DIR)
|
mark_as_advanced(OPENSSL_INCLUDE_DIR)
|
||||||
|
|
||||||
if(OPENSSL_FOUND)
|
if(OPENSSL_FOUND)
|
||||||
message(STATUS "Found OpenSSL library: ${OPENSSL_LIBRARIES}")
|
|
||||||
message(STATUS "Found OpenSSL headers: ${OPENSSL_INCLUDE_DIR}")
|
|
||||||
include(EnsureVersion)
|
|
||||||
ENSURE_VERSION("${OPENSSL_EXPECTED_VERSION}" "${OPENSSL_VERSION}" OPENSSL_VERSION_OK)
|
|
||||||
if(NOT OPENSSL_VERSION_OK)
|
|
||||||
message(FATAL_ERROR "AzerothCore needs OpenSSL version ${OPENSSL_EXPECTED_VERSION} but found too new version ${OPENSSL_VERSION}. AzerothCore needs OpenSSL 1.0.x or 1.1.x to work properly. If you still have problems please install OpenSSL 1.0.x if you still have problems search on forum for TCE00022")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT TARGET OpenSSL::Crypto AND
|
if(NOT TARGET OpenSSL::Crypto AND
|
||||||
(EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
|
(EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
|
||||||
EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
|
EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
|
||||||
@@ -642,7 +786,7 @@ if(OPENSSL_FOUND)
|
|||||||
_OpenSSL_target_add_dependencies(OpenSSL::SSL)
|
_OpenSSL_target_add_dependencies(OpenSSL::SSL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if("${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_FIX}" VERSION_GREATER_EQUAL "0.9.8")
|
if("${OPENSSL_VERSION_MAJOR}.${OPENSSL_VERSION_MINOR}.${OPENSSL_VERSION_FIX}" VERSION_GREATER_EQUAL "0.9.8")
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
if(EXISTS "${OPENSSL_INCLUDE_DIR}")
|
if(EXISTS "${OPENSSL_INCLUDE_DIR}")
|
||||||
set(_OPENSSL_applink_paths PATHS ${OPENSSL_INCLUDE_DIR})
|
set(_OPENSSL_applink_paths PATHS ${OPENSSL_INCLUDE_DIR})
|
||||||
@@ -669,3 +813,10 @@ endif()
|
|||||||
if(OPENSSL_USE_STATIC_LIBS)
|
if(OPENSSL_USE_STATIC_LIBS)
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
unset(_OPENSSL_FIND_PATH_SUFFIX)
|
||||||
|
unset(_OPENSSL_NAME_POSTFIX)
|
||||||
|
unset(_OpenSSL_extra_static_deps)
|
||||||
|
unset(_OpenSSL_has_dependency_dl)
|
||||||
|
unset(_OpenSSL_has_dependency_threads)
|
||||||
|
unset(_OpenSSL_has_dependency_zlib)
|
||||||
|
|||||||
@@ -3069,9 +3069,9 @@ Rate.RepairCost = 1
|
|||||||
# Description: Should the player leave their group when they log out?
|
# Description: Should the player leave their group when they log out?
|
||||||
# (It does not affect raids or dungeon finder groups)
|
# (It does not affect raids or dungeon finder groups)
|
||||||
#
|
#
|
||||||
# Default: 1 - (Enabled)
|
# Default: 0 - (Disabled)
|
||||||
|
|
||||||
LeaveGroupOnLogout.Enabled = 1
|
LeaveGroupOnLogout.Enabled = 0
|
||||||
|
|
||||||
#
|
#
|
||||||
# Group.Raid.LevelRestriction
|
# Group.Raid.LevelRestriction
|
||||||
|
|||||||
@@ -227,7 +227,11 @@ bool MySQLConnection::Execute(PreparedStatementBase* stmt)
|
|||||||
|
|
||||||
uint32 _s = getMSTime();
|
uint32 _s = getMSTime();
|
||||||
|
|
||||||
|
#if !defined(MARIADB_VERSION_ID) && (MYSQL_VERSION_ID >= 80300)
|
||||||
|
if (mysql_stmt_bind_named_param(msql_STMT, msql_BIND, m_mStmt->GetParameterCount(), nullptr))
|
||||||
|
#else
|
||||||
if (mysql_stmt_bind_param(msql_STMT, msql_BIND))
|
if (mysql_stmt_bind_param(msql_STMT, msql_BIND))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
uint32 lErrno = mysql_errno(m_Mysql);
|
uint32 lErrno = mysql_errno(m_Mysql);
|
||||||
LOG_ERROR("sql.sql", "SQL(p): {}\n [ERROR]: [{}] {}", m_mStmt->getQueryString(), lErrno, mysql_stmt_error(msql_STMT));
|
LOG_ERROR("sql.sql", "SQL(p): {}\n [ERROR]: [{}] {}", m_mStmt->getQueryString(), lErrno, mysql_stmt_error(msql_STMT));
|
||||||
@@ -275,7 +279,11 @@ bool MySQLConnection::_Query(PreparedStatementBase* stmt, MySQLPreparedStatement
|
|||||||
|
|
||||||
uint32 _s = getMSTime();
|
uint32 _s = getMSTime();
|
||||||
|
|
||||||
|
#if !defined(MARIADB_VERSION_ID) && (MYSQL_VERSION_ID >= 80300)
|
||||||
|
if (mysql_stmt_bind_named_param(msql_STMT, msql_BIND, m_mStmt->GetParameterCount(), nullptr))
|
||||||
|
#else
|
||||||
if (mysql_stmt_bind_param(msql_STMT, msql_BIND))
|
if (mysql_stmt_bind_param(msql_STMT, msql_BIND))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
uint32 lErrno = mysql_errno(m_Mysql);
|
uint32 lErrno = mysql_errno(m_Mysql);
|
||||||
LOG_ERROR("sql.sql", "SQL(p): {}\n [ERROR]: [{}] {}", m_mStmt->getQueryString(), lErrno, mysql_stmt_error(msql_STMT));
|
LOG_ERROR("sql.sql", "SQL(p): {}\n [ERROR]: [{}] {}", m_mStmt->getQueryString(), lErrno, mysql_stmt_error(msql_STMT));
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ bool ArenaSpectator::HandleSpectatorSpectateCommand(ChatHandler* handler, std::s
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->getClass() == CLASS_DEATH_KNIGHT && player->GetMapId() == 609)
|
if (player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TELEPORT) && player->GetMapId() == 609)
|
||||||
{
|
{
|
||||||
handler->PSendSysMessage("Death Knights can't spectate before finishing questline.");
|
handler->PSendSysMessage("Death Knights can't spectate before finishing questline.");
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1055,7 +1055,7 @@ namespace lfg
|
|||||||
baseAP = p->GetTotalAttackPowerValue(BASE_ATTACK);
|
baseAP = p->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||||
rangedAP = p->GetTotalAttackPowerValue(RANGED_ATTACK);
|
rangedAP = p->GetTotalAttackPowerValue(RANGED_ATTACK);
|
||||||
maxPower = 0;
|
maxPower = 0;
|
||||||
if (p->getClass() == CLASS_DRUID)
|
if (p->IsClass(CLASS_DRUID))
|
||||||
maxPower = p->GetMaxPower(POWER_MANA);
|
maxPower = p->GetMaxPower(POWER_MANA);
|
||||||
else
|
else
|
||||||
maxPower = (p->getPowerType() == POWER_RAGE || p->getPowerType() == POWER_RUNIC_POWER) ? p->GetMaxPower(p->getPowerType()) / 10 : p->GetMaxPower(p->getPowerType());
|
maxPower = (p->getPowerType() == POWER_RAGE || p->getPowerType() == POWER_RUNIC_POWER) ? p->GetMaxPower(p->getPowerType()) / 10 : p->GetMaxPower(p->getPowerType());
|
||||||
|
|||||||
@@ -1197,7 +1197,7 @@ bool Creature::isCanTrainingAndResetTalentsOf(Player* player) const
|
|||||||
{
|
{
|
||||||
return player->GetLevel() >= 10
|
return player->GetLevel() >= 10
|
||||||
&& GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS
|
&& GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS
|
||||||
&& player->getClass() == GetCreatureTemplate()->trainer_class;
|
&& player->IsClass((Classes)GetCreatureTemplate()->trainer_class, CLASS_CONTEXT_CLASS_TRAINER);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Creature::IsValidTrainerForPlayer(Player* player, uint32* npcFlags /*= nullptr*/) const
|
bool Creature::IsValidTrainerForPlayer(Player* player, uint32* npcFlags /*= nullptr*/) const
|
||||||
@@ -1211,7 +1211,7 @@ bool Creature::IsValidTrainerForPlayer(Player* player, uint32* npcFlags /*= null
|
|||||||
{
|
{
|
||||||
case TRAINER_TYPE_CLASS:
|
case TRAINER_TYPE_CLASS:
|
||||||
case TRAINER_TYPE_PETS:
|
case TRAINER_TYPE_PETS:
|
||||||
if (m_creatureInfo->trainer_class && m_creatureInfo->trainer_class != player->getClass())
|
if (m_creatureInfo->trainer_class && !player->IsClass((Classes)m_creatureInfo->trainer_class, CLASS_CONTEXT_CLASS_TRAINER))
|
||||||
{
|
{
|
||||||
if (npcFlags)
|
if (npcFlags)
|
||||||
*npcFlags &= ~UNIT_NPC_FLAG_TRAINER_CLASS;
|
*npcFlags &= ~UNIT_NPC_FLAG_TRAINER_CLASS;
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ void Pet::AddToWorld()
|
|||||||
{
|
{
|
||||||
if (Player* owner = GetOwner())
|
if (Player* owner = GetOwner())
|
||||||
{
|
{
|
||||||
if (getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)
|
if (getPetType() == SUMMON_PET && owner->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET))
|
||||||
{
|
{
|
||||||
owner->SetLastPetSpell(GetUInt32Value(UNIT_CREATED_BY_SPELL));
|
owner->SetLastPetSpell(GetUInt32Value(UNIT_CREATED_BY_SPELL));
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
|
|||||||
bool forceLoadFromDB = false;
|
bool forceLoadFromDB = false;
|
||||||
sScriptMgr->OnBeforeLoadPetFromDB(owner, petEntry, petnumber, current, forceLoadFromDB);
|
sScriptMgr->OnBeforeLoadPetFromDB(owner, petEntry, petnumber, current, forceLoadFromDB);
|
||||||
|
|
||||||
if (!forceLoadFromDB && (owner->getClass() == CLASS_DEATH_KNIGHT && !owner->CanSeeDKPet())) // DK Pet exception
|
if (!forceLoadFromDB && (owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET) && !owner->CanSeeDKPet())) // DK Pet exception
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(petInfo->CreatedBySpellId);
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(petInfo->CreatedBySpellId);
|
||||||
@@ -1043,12 +1043,12 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
|||||||
if (petType == MAX_PET_TYPE)
|
if (petType == MAX_PET_TYPE)
|
||||||
{
|
{
|
||||||
// The petType was not overwritten by the hook, continue with default initialization
|
// The petType was not overwritten by the hook, continue with default initialization
|
||||||
if (owner->getClass() == CLASS_WARLOCK ||
|
if (owner->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET) ||
|
||||||
owner->getClass() == CLASS_SHAMAN || // Fire Elemental
|
owner->IsClass(CLASS_SHAMAN, CLASS_CONTEXT_PET) || // Fire Elemental
|
||||||
owner->getClass() == CLASS_DEATH_KNIGHT || // Risen Ghoul
|
owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET) || // Risen Ghoul
|
||||||
owner->getClass() == CLASS_MAGE) // Water Elemental with glyph
|
owner->IsClass(CLASS_MAGE, CLASS_CONTEXT_PET)) // Water Elemental with glyph
|
||||||
petType = SUMMON_PET;
|
petType = SUMMON_PET;
|
||||||
else if (owner->getClass() == CLASS_HUNTER)
|
else if (owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||||
{
|
{
|
||||||
petType = HUNTER_PET;
|
petType = HUNTER_PET;
|
||||||
}
|
}
|
||||||
@@ -1080,7 +1080,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
|||||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
|
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
|
||||||
|
|
||||||
uint32 attackTime = BASE_ATTACK_TIME;
|
uint32 attackTime = BASE_ATTACK_TIME;
|
||||||
if (owner->getClass() != CLASS_HUNTER && cinfo->BaseAttackTime >= 1000)
|
if (!owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET) && cinfo->BaseAttackTime >= 1000)
|
||||||
attackTime = cinfo->BaseAttackTime;
|
attackTime = cinfo->BaseAttackTime;
|
||||||
|
|
||||||
SetAttackTime(BASE_ATTACK, attackTime);
|
SetAttackTime(BASE_ATTACK, attackTime);
|
||||||
@@ -2299,17 +2299,14 @@ bool Pet::IsPermanentPetFor(Player* owner) const
|
|||||||
switch (getPetType())
|
switch (getPetType())
|
||||||
{
|
{
|
||||||
case SUMMON_PET:
|
case SUMMON_PET:
|
||||||
switch (owner->getClass())
|
if (owner->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET))
|
||||||
{
|
|
||||||
case CLASS_WARLOCK:
|
|
||||||
return GetCreatureTemplate()->type == CREATURE_TYPE_DEMON;
|
return GetCreatureTemplate()->type == CREATURE_TYPE_DEMON;
|
||||||
case CLASS_DEATH_KNIGHT:
|
else if (owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET))
|
||||||
return GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD;
|
return GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD;
|
||||||
case CLASS_MAGE:
|
else if (owner->IsClass(CLASS_MAGE, CLASS_CONTEXT_PET))
|
||||||
return GetEntry() == 37994;
|
return GetEntry() == 37994;
|
||||||
default:
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
case HUNTER_PET:
|
case HUNTER_PET:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -204,12 +204,13 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
|
|||||||
if (_victim->GetTypeId() == TYPEID_PLAYER)
|
if (_victim->GetTypeId() == TYPEID_PLAYER)
|
||||||
player->KilledPlayerCredit();
|
player->KilledPlayerCredit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give XP only in PvE or in battlegrounds.
|
// Give XP only in PvE or in battlegrounds.
|
||||||
// Give reputation and kill credit only in PvE.
|
// Give reputation and kill credit only in PvE.
|
||||||
if (!_isPvP || _isBattleGround)
|
if (!_isPvP || _isBattleGround)
|
||||||
{
|
{
|
||||||
float xpRate = _group ? _groupRate * float(player->GetLevel()) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
|
float xpRate = _group ? _groupRate * float(player->GetLevel()) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
|
||||||
sScriptMgr->OnRewardKillRewarder(player, isDungeon, xpRate); // Personal rate is 100%.
|
sScriptMgr->OnRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%.
|
||||||
|
|
||||||
if (_xp)
|
if (_xp)
|
||||||
{
|
{
|
||||||
@@ -290,3 +291,13 @@ void KillRewarder::Reward()
|
|||||||
if (Map* map = _victim->FindMap())
|
if (Map* map = _victim->FindMap())
|
||||||
map->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, _victim->GetEntry(), _victim);
|
map->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, _victim->GetEntry(), _victim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Unit* KillRewarder::GetVictim()
|
||||||
|
{
|
||||||
|
return _victim;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player* KillRewarder::GetKiller()
|
||||||
|
{
|
||||||
|
return _killer;
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ public:
|
|||||||
KillRewarder(Player* killer, Unit* victim, bool isBattleGround);
|
KillRewarder(Player* killer, Unit* victim, bool isBattleGround);
|
||||||
|
|
||||||
void Reward();
|
void Reward();
|
||||||
|
Unit* GetVictim();
|
||||||
|
Player* GetKiller();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _InitXP(Player* player);
|
void _InitXP(Player* player);
|
||||||
|
|||||||
@@ -553,7 +553,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
|||||||
SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
|
SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
|
||||||
|
|
||||||
// set starting level
|
// set starting level
|
||||||
uint32 start_level = getClass() != CLASS_DEATH_KNIGHT
|
uint32 start_level = !IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT)
|
||||||
? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)
|
? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)
|
||||||
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
|
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
|
||||||
|
|
||||||
@@ -568,7 +568,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
|||||||
|
|
||||||
InitRunes();
|
InitRunes();
|
||||||
|
|
||||||
SetUInt32Value(PLAYER_FIELD_COINAGE, getClass() != CLASS_DEATH_KNIGHT
|
SetUInt32Value(PLAYER_FIELD_COINAGE, !IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT)
|
||||||
? sWorld->getIntConfig(CONFIG_START_PLAYER_MONEY)
|
? sWorld->getIntConfig(CONFIG_START_PLAYER_MONEY)
|
||||||
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_MONEY));
|
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_MONEY));
|
||||||
SetHonorPoints(sWorld->getIntConfig(CONFIG_START_HONOR_POINTS));
|
SetHonorPoints(sWorld->getIntConfig(CONFIG_START_HONOR_POINTS));
|
||||||
@@ -587,13 +587,13 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
|||||||
InitPrimaryProfessions(); // to max set before any spell added
|
InitPrimaryProfessions(); // to max set before any spell added
|
||||||
|
|
||||||
// apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods()
|
// apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods()
|
||||||
if (getPowerType() == POWER_MANA)
|
if (HasActivePowerType(POWER_MANA))
|
||||||
{
|
{
|
||||||
UpdateMaxPower(POWER_MANA); // Update max Mana (for add bonus from intellect)
|
UpdateMaxPower(POWER_MANA); // Update max Mana (for add bonus from intellect)
|
||||||
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
|
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getPowerType() == POWER_RUNIC_POWER)
|
if (HasActivePowerType(POWER_RUNIC_POWER))
|
||||||
{
|
{
|
||||||
SetPower(POWER_RUNE, 8);
|
SetPower(POWER_RUNE, 8);
|
||||||
SetMaxPower(POWER_RUNE, 8);
|
SetMaxPower(POWER_RUNE, 8);
|
||||||
@@ -633,7 +633,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
|||||||
switch (iProto->Spells[0].SpellCategory)
|
switch (iProto->Spells[0].SpellCategory)
|
||||||
{
|
{
|
||||||
case SPELL_CATEGORY_FOOD: // food
|
case SPELL_CATEGORY_FOOD: // food
|
||||||
count = getClass() == CLASS_DEATH_KNIGHT ? 10 : 4;
|
count = IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT) ? 10 : 4;
|
||||||
break;
|
break;
|
||||||
case SPELL_CATEGORY_DRINK: // drink
|
case SPELL_CATEGORY_DRINK: // drink
|
||||||
count = 2;
|
count = 2;
|
||||||
@@ -1269,6 +1269,15 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Player::IsClass(Classes unitClass, ClassContext context) const
|
||||||
|
{
|
||||||
|
Optional<bool> scriptResult = sScriptMgr->OnPlayerIsClass(this, unitClass, context);
|
||||||
|
if (scriptResult != std::nullopt)
|
||||||
|
return *scriptResult;
|
||||||
|
else
|
||||||
|
return (getClass() == unitClass);
|
||||||
|
}
|
||||||
|
|
||||||
void Player::ToggleAFK()
|
void Player::ToggleAFK()
|
||||||
{
|
{
|
||||||
ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK);
|
ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK);
|
||||||
@@ -1460,7 +1469,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (getClass() == CLASS_DEATH_KNIGHT && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977))
|
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TELEPORT) && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977))
|
||||||
{
|
{
|
||||||
SendTransferAborted(mapid, TRANSFER_ABORT_UNIQUE_MESSAGE, 1);
|
SendTransferAborted(mapid, TRANSFER_ABORT_UNIQUE_MESSAGE, 1);
|
||||||
return false;
|
return false;
|
||||||
@@ -1745,7 +1754,7 @@ void Player::RegenerateAll()
|
|||||||
Regenerate(POWER_MANA);
|
Regenerate(POWER_MANA);
|
||||||
|
|
||||||
// Runes act as cooldowns, and they don't need to send any data
|
// Runes act as cooldowns, and they don't need to send any data
|
||||||
if (getClass() == CLASS_DEATH_KNIGHT)
|
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||||
{
|
{
|
||||||
// xinef: implement grace
|
// xinef: implement grace
|
||||||
@@ -1775,7 +1784,7 @@ void Player::RegenerateAll()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Regenerate(POWER_RAGE);
|
Regenerate(POWER_RAGE);
|
||||||
if (getClass() == CLASS_DEATH_KNIGHT)
|
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
Regenerate(POWER_RUNIC_POWER);
|
Regenerate(POWER_RUNIC_POWER);
|
||||||
|
|
||||||
m_regenTimerCount -= 2000;
|
m_regenTimerCount -= 2000;
|
||||||
@@ -2019,22 +2028,21 @@ void Player::RegenerateHealth()
|
|||||||
void Player::ResetAllPowers()
|
void Player::ResetAllPowers()
|
||||||
{
|
{
|
||||||
SetHealth(GetMaxHealth());
|
SetHealth(GetMaxHealth());
|
||||||
switch (getPowerType())
|
if (HasActivePowerType(POWER_MANA))
|
||||||
{
|
{
|
||||||
case POWER_MANA:
|
|
||||||
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
|
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
|
||||||
break;
|
}
|
||||||
case POWER_RAGE:
|
if (HasActivePowerType(POWER_RAGE))
|
||||||
|
{
|
||||||
SetPower(POWER_RAGE, 0);
|
SetPower(POWER_RAGE, 0);
|
||||||
break;
|
}
|
||||||
case POWER_ENERGY:
|
if (HasActivePowerType(POWER_ENERGY))
|
||||||
|
{
|
||||||
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
|
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
|
||||||
break;
|
}
|
||||||
case POWER_RUNIC_POWER:
|
if (HasActivePowerType(POWER_RUNIC_POWER))
|
||||||
|
{
|
||||||
SetPower(POWER_RUNIC_POWER, 0);
|
SetPower(POWER_RUNIC_POWER, 0);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2107,7 +2115,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
|
|||||||
|
|
||||||
// pussywizard: many npcs have missing conditions for class training and rogue trainer can for eg. train dual wield to a shaman :/ too many to change in sql and watch in the future
|
// pussywizard: many npcs have missing conditions for class training and rogue trainer can for eg. train dual wield to a shaman :/ too many to change in sql and watch in the future
|
||||||
// pussywizard: this function is not used when talking, but when already taking action (buy spell, reset talents, show spell list)
|
// pussywizard: this function is not used when talking, but when already taking action (buy spell, reset talents, show spell list)
|
||||||
if (npcflagmask & (UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS) && creature->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS && getClass() != creature->GetCreatureTemplate()->trainer_class)
|
if (npcflagmask & (UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS) && creature->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS && !IsClass((Classes)creature->GetCreatureTemplate()->trainer_class, CLASS_CONTEXT_CLASS_TRAINER))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return creature;
|
return creature;
|
||||||
@@ -2714,6 +2722,14 @@ void Player::InitStatsForLevel(bool reapplyMods)
|
|||||||
pet->SynchronizeLevelWithOwner();
|
pet->SynchronizeLevelWithOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Player::HasActivePowerType(Powers power)
|
||||||
|
{
|
||||||
|
if (sScriptMgr->OnPlayerHasActivePowerType(this, power))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return (getPowerType() == power);
|
||||||
|
}
|
||||||
|
|
||||||
void Player::SendInitialSpells()
|
void Player::SendInitialSpells()
|
||||||
{
|
{
|
||||||
uint32 curTime = GameTime::GetGameTimeMS().count();
|
uint32 curTime = GameTime::GetGameTimeMS().count();
|
||||||
@@ -6388,7 +6404,7 @@ void Player::DuelComplete(DuelCompleteType type)
|
|||||||
opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1);
|
opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1);
|
||||||
|
|
||||||
// Credit for quest Death's Challenge
|
// Credit for quest Death's Challenge
|
||||||
if (getClass() == CLASS_DEATH_KNIGHT && opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE)
|
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_QUEST) && opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE)
|
||||||
{
|
{
|
||||||
opponent->CastSpell(opponent, 52994, true);
|
opponent->CastSpell(opponent, 52994, true);
|
||||||
}
|
}
|
||||||
@@ -6784,7 +6800,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
|
// Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
|
||||||
if (getClass() == CLASS_DRUID)
|
if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
|
||||||
{
|
{
|
||||||
int32 dpsMod = 0;
|
int32 dpsMod = 0;
|
||||||
int32 feral_bonus = 0;
|
int32 feral_bonus = 0;
|
||||||
@@ -9841,7 +9857,7 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
|
|||||||
if (apply)
|
if (apply)
|
||||||
{
|
{
|
||||||
m_spellMods[mod->op].push_back(mod);
|
m_spellMods[mod->op].push_back(mod);
|
||||||
if (getClass() == CLASS_MAGE)
|
if (IsClass(CLASS_MAGE, CLASS_CONTEXT_ABILITY))
|
||||||
m_spellMods[mod->op].sort(MageSpellModPred());
|
m_spellMods[mod->op].sort(MageSpellModPred());
|
||||||
else
|
else
|
||||||
m_spellMods[mod->op].sort(SpellModPred());
|
m_spellMods[mod->op].sort(SpellModPred());
|
||||||
@@ -10275,7 +10291,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
|||||||
// only one mount ID for both sides. Probably not good to use 315 in case DBC nodes
|
// only one mount ID for both sides. Probably not good to use 315 in case DBC nodes
|
||||||
// change but I couldn't find a suitable alternative. OK to use class because only DK
|
// change but I couldn't find a suitable alternative. OK to use class because only DK
|
||||||
// can use this taxi.
|
// can use this taxi.
|
||||||
uint32 mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeamId(true), npc == nullptr || (sourcenode == 315 && getClass() == CLASS_DEATH_KNIGHT));
|
uint32 mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeamId(true), npc == nullptr || (sourcenode == 315 && IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TAXI)));
|
||||||
|
|
||||||
// in spell case allow 0 model
|
// in spell case allow 0 model
|
||||||
if ((mount_display_id == 0 && spellid == 0) || sourcepath == 0)
|
if ((mount_display_id == 0 && spellid == 0) || sourcepath == 0)
|
||||||
@@ -11324,7 +11340,7 @@ WorldLocation Player::GetStartPosition() const
|
|||||||
{
|
{
|
||||||
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(true), getClass());
|
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(true), getClass());
|
||||||
uint32 mapId = info->mapId;
|
uint32 mapId = info->mapId;
|
||||||
if (getClass() == CLASS_DEATH_KNIGHT && HasSpell(50977))
|
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT) && HasSpell(50977))
|
||||||
return WorldLocation(0, 2352.0f, -5709.0f, 154.5f, 0.0f);
|
return WorldLocation(0, 2352.0f, -5709.0f, 154.5f, 0.0f);
|
||||||
return WorldLocation(mapId, info->positionX, info->positionY, info->positionZ, 0);
|
return WorldLocation(mapId, info->positionX, info->positionY, info->positionZ, 0);
|
||||||
}
|
}
|
||||||
@@ -11818,7 +11834,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
|
|||||||
{
|
{
|
||||||
skillValue = maxValue;
|
skillValue = maxValue;
|
||||||
}
|
}
|
||||||
else if (getClass() == CLASS_DEATH_KNIGHT)
|
else if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_SKILL))
|
||||||
{
|
{
|
||||||
skillValue = std::min(std::max<uint16>({ 1, uint16((GetLevel() - 1) * 5) }), maxValue);
|
skillValue = std::min(std::max<uint16>({ 1, uint16((GetLevel() - 1) * 5) }), maxValue);
|
||||||
}
|
}
|
||||||
@@ -11851,7 +11867,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
|
|||||||
{
|
{
|
||||||
skillValue = maxValue;
|
skillValue = maxValue;
|
||||||
}
|
}
|
||||||
else if (getClass() == CLASS_DEATH_KNIGHT)
|
else if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_SKILL))
|
||||||
{
|
{
|
||||||
skillValue = std::min(std::max<uint16>({ uint16(1), uint16((GetLevel() - 1) * 5) }), maxValue);
|
skillValue = std::min(std::max<uint16>({ uint16(1), uint16((GetLevel() - 1) * 5) }), maxValue);
|
||||||
}
|
}
|
||||||
@@ -13376,7 +13392,7 @@ static RuneType runeSlotTypes[MAX_RUNES] =
|
|||||||
|
|
||||||
void Player::InitRunes()
|
void Player::InitRunes()
|
||||||
{
|
{
|
||||||
if (getClass() != CLASS_DEATH_KNIGHT)
|
if (!IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_runes = new Runes;
|
m_runes = new Runes;
|
||||||
@@ -13542,7 +13558,7 @@ uint32 Player::CalculateTalentsPoints() const
|
|||||||
uint32 base_talent = GetLevel() < 10 ? 0 : GetLevel() - 9;
|
uint32 base_talent = GetLevel() < 10 ? 0 : GetLevel() - 9;
|
||||||
|
|
||||||
uint32 talentPointsForLevel = 0;
|
uint32 talentPointsForLevel = 0;
|
||||||
if (getClass() != CLASS_DEATH_KNIGHT || GetMapId() != 609)
|
if (!IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TALENT_POINT_CALC) || GetMapId() != 609)
|
||||||
{
|
{
|
||||||
talentPointsForLevel = base_talent;
|
talentPointsForLevel = base_talent;
|
||||||
}
|
}
|
||||||
@@ -14174,19 +14190,21 @@ void Player::ResummonPetTemporaryUnSummonedIfAny()
|
|||||||
|
|
||||||
bool Player::CanResummonPet(uint32 spellid)
|
bool Player::CanResummonPet(uint32 spellid)
|
||||||
{
|
{
|
||||||
if (getClass() == CLASS_DEATH_KNIGHT)
|
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET))
|
||||||
{
|
{
|
||||||
if (CanSeeDKPet())
|
if (CanSeeDKPet())
|
||||||
return true;
|
return true;
|
||||||
else if (spellid == 52150) // Raise Dead
|
else if (spellid == 52150) // Raise Dead
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (getClass() == CLASS_MAGE)
|
|
||||||
|
if (IsClass(CLASS_MAGE, CLASS_CONTEXT_PET))
|
||||||
{
|
{
|
||||||
if (HasSpell(31687) && HasAura(70937)) //Has [Summon Water Elemental] spell and [Glyph of Eternal Water].
|
if (HasSpell(31687) && HasAura(70937)) //Has [Summon Water Elemental] spell and [Glyph of Eternal Water].
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (getClass() == CLASS_HUNTER)
|
|
||||||
|
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -15171,7 +15189,7 @@ void Player::ActivateSpec(uint8 spec)
|
|||||||
AutoUnequipOffhandIfNeed();
|
AutoUnequipOffhandIfNeed();
|
||||||
|
|
||||||
// Xinef: Patch 3.2.0: Switching spec removes paladins spell Righteous Fury (25780)
|
// Xinef: Patch 3.2.0: Switching spec removes paladins spell Righteous Fury (25780)
|
||||||
if (getClass() == CLASS_PALADIN)
|
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_ABILITY))
|
||||||
RemoveAurasDueToSpell(25780);
|
RemoveAurasDueToSpell(25780);
|
||||||
|
|
||||||
// Xinef: Remove talented single target auras at other targets
|
// Xinef: Remove talented single target auras at other targets
|
||||||
|
|||||||
@@ -1112,6 +1112,8 @@ public:
|
|||||||
|
|
||||||
static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data);
|
static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data);
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsClass(Classes playerClass, ClassContext context = CLASS_CONTEXT_NONE) const override;
|
||||||
|
|
||||||
void SetInWater(bool apply);
|
void SetInWater(bool apply);
|
||||||
|
|
||||||
[[nodiscard]] bool IsInWater() const override { return m_isInWater; }
|
[[nodiscard]] bool IsInWater() const override { return m_isInWater; }
|
||||||
@@ -1170,6 +1172,8 @@ public:
|
|||||||
|
|
||||||
void InitStatsForLevel(bool reapplyMods = false);
|
void InitStatsForLevel(bool reapplyMods = false);
|
||||||
|
|
||||||
|
[[nodiscard]] bool HasActivePowerType(Powers power) override;
|
||||||
|
|
||||||
// .cheat command related
|
// .cheat command related
|
||||||
[[nodiscard]] bool GetCommandStatus(uint32 command) const { return _activeCheats & command; }
|
[[nodiscard]] bool GetCommandStatus(uint32 command) const { return _activeCheats & command; }
|
||||||
void SetCommandStatusOn(uint32 command) { _activeCheats |= command; }
|
void SetCommandStatusOn(uint32 command) { _activeCheats |= command; }
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
|
|||||||
canTalk = false;
|
canTalk = false;
|
||||||
break;
|
break;
|
||||||
case GOSSIP_OPTION_STABLEPET:
|
case GOSSIP_OPTION_STABLEPET:
|
||||||
if (getClass() != CLASS_HUNTER)
|
if (!IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||||
canTalk = false;
|
canTalk = false;
|
||||||
break;
|
break;
|
||||||
case GOSSIP_OPTION_QUESTGIVER:
|
case GOSSIP_OPTION_QUESTGIVER:
|
||||||
|
|||||||
@@ -133,8 +133,6 @@ void Player::SetSheath(SheathState sheathed)
|
|||||||
|
|
||||||
uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) const
|
uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) const
|
||||||
{
|
{
|
||||||
uint8 playerClass = getClass();
|
|
||||||
|
|
||||||
uint8 slots[4];
|
uint8 slots[4];
|
||||||
slots[0] = NULL_SLOT;
|
slots[0] = NULL_SLOT;
|
||||||
slots[1] = NULL_SLOT;
|
slots[1] = NULL_SLOT;
|
||||||
@@ -246,23 +244,23 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c
|
|||||||
switch (proto->SubClass)
|
switch (proto->SubClass)
|
||||||
{
|
{
|
||||||
case ITEM_SUBCLASS_ARMOR_LIBRAM:
|
case ITEM_SUBCLASS_ARMOR_LIBRAM:
|
||||||
if (playerClass == CLASS_PALADIN)
|
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||||
break;
|
break;
|
||||||
case ITEM_SUBCLASS_ARMOR_IDOL:
|
case ITEM_SUBCLASS_ARMOR_IDOL:
|
||||||
if (playerClass == CLASS_DRUID)
|
if (IsClass(CLASS_DRUID, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||||
break;
|
break;
|
||||||
case ITEM_SUBCLASS_ARMOR_TOTEM:
|
case ITEM_SUBCLASS_ARMOR_TOTEM:
|
||||||
if (playerClass == CLASS_SHAMAN)
|
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||||
break;
|
break;
|
||||||
case ITEM_SUBCLASS_ARMOR_MISC:
|
case ITEM_SUBCLASS_ARMOR_MISC:
|
||||||
if (playerClass == CLASS_WARLOCK)
|
if (IsClass(CLASS_WARLOCK, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||||
break;
|
break;
|
||||||
case ITEM_SUBCLASS_ARMOR_SIGIL:
|
case ITEM_SUBCLASS_ARMOR_SIGIL:
|
||||||
if (playerClass == CLASS_DEATH_KNIGHT)
|
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2270,16 +2268,13 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const
|
|||||||
// In fact it's a visual bug, everything works properly... I need sniffs of operations with
|
// In fact it's a visual bug, everything works properly... I need sniffs of operations with
|
||||||
// binded to account items from off server.
|
// binded to account items from off server.
|
||||||
|
|
||||||
switch (getClass())
|
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_ARMOR_CLASS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||||
{
|
{
|
||||||
case CLASS_HUNTER:
|
|
||||||
case CLASS_SHAMAN:
|
|
||||||
allowEquip = (itemSkill == SKILL_MAIL);
|
|
||||||
break;
|
|
||||||
case CLASS_PALADIN:
|
|
||||||
case CLASS_WARRIOR:
|
|
||||||
allowEquip = (itemSkill == SKILL_PLATE_MAIL);
|
allowEquip = (itemSkill == SKILL_PLATE_MAIL);
|
||||||
break;
|
}
|
||||||
|
else if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_EQUIP_ARMOR_CLASS) || IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||||
|
{
|
||||||
|
allowEquip = (itemSkill == SKILL_MAIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!allowEquip && GetSkillValue(itemSkill) == 0)
|
if (!allowEquip && GetSkillValue(itemSkill) == 0)
|
||||||
@@ -2394,39 +2389,40 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
|
|||||||
return EQUIP_ERR_CANT_EQUIP_SKILL;
|
return EQUIP_ERR_CANT_EQUIP_SKILL;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 _class = getClass();
|
|
||||||
|
|
||||||
if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0)
|
if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0)
|
||||||
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
|
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
|
||||||
|
|
||||||
if (proto->Class == ITEM_CLASS_ARMOR)
|
if (proto->Class == ITEM_CLASS_ARMOR)
|
||||||
{
|
{
|
||||||
// Check for shields
|
// Check for shields
|
||||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD && !(_class == CLASS_PALADIN || _class == CLASS_WARRIOR || _class == CLASS_SHAMAN))
|
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD && !(
|
||||||
|
IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_SHIELDS)
|
||||||
|
|| IsClass(CLASS_WARRIOR, CLASS_CONTEXT_EQUIP_SHIELDS)
|
||||||
|
|| IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_SHIELDS)))
|
||||||
{
|
{
|
||||||
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
|
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for librams.
|
// Check for librams.
|
||||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_LIBRAM && _class != CLASS_PALADIN)
|
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_LIBRAM && !IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
{
|
{
|
||||||
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHeck for idols.
|
// CHeck for idols.
|
||||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_IDOL && _class != CLASS_DRUID)
|
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_IDOL && !IsClass(CLASS_DRUID, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
{
|
{
|
||||||
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for totems.
|
// Check for totems.
|
||||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_TOTEM && _class != CLASS_SHAMAN)
|
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_TOTEM && !IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
{
|
{
|
||||||
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for sigils.
|
// Check for sigils.
|
||||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SIGIL && _class != CLASS_DEATH_KNIGHT)
|
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SIGIL && !IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_EQUIP_RELIC))
|
||||||
{
|
{
|
||||||
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||||
}
|
}
|
||||||
@@ -2436,33 +2432,33 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
|
|||||||
proto->InventoryType != INVTYPE_CLOAK)
|
proto->InventoryType != INVTYPE_CLOAK)
|
||||||
{
|
{
|
||||||
uint32 subclassToCompare = ITEM_SUBCLASS_ARMOR_CLOTH;
|
uint32 subclassToCompare = ITEM_SUBCLASS_ARMOR_CLOTH;
|
||||||
switch (_class)
|
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_EQUIP_ARMOR_CLASS) || IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||||
{
|
{
|
||||||
case CLASS_WARRIOR:
|
|
||||||
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
|
|
||||||
{
|
|
||||||
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
|
||||||
}
|
|
||||||
[[fallthrough]];
|
|
||||||
case CLASS_DEATH_KNIGHT:
|
|
||||||
case CLASS_PALADIN:
|
|
||||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_PLATE;
|
subclassToCompare = ITEM_SUBCLASS_ARMOR_PLATE;
|
||||||
break;
|
}
|
||||||
case CLASS_HUNTER:
|
else if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||||
case CLASS_SHAMAN:
|
{
|
||||||
|
if ((proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat()))
|
||||||
|
{
|
||||||
|
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
||||||
|
}
|
||||||
|
subclassToCompare = ITEM_SUBCLASS_ARMOR_PLATE;
|
||||||
|
}
|
||||||
|
else if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_EQUIP_ARMOR_CLASS) || IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||||
|
{
|
||||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_MAIL;
|
subclassToCompare = ITEM_SUBCLASS_ARMOR_MAIL;
|
||||||
break;
|
}
|
||||||
case CLASS_ROGUE:
|
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||||
|
{
|
||||||
|
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
|
||||||
|
}
|
||||||
|
else if (IsClass(CLASS_ROGUE, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||||
|
{
|
||||||
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
|
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
|
||||||
{
|
{
|
||||||
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
|
||||||
case CLASS_DRUID:
|
|
||||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
|
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proto->SubClass > subclassToCompare)
|
if (proto->SubClass > subclassToCompare)
|
||||||
@@ -2772,7 +2768,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
|
|||||||
|
|
||||||
if (pProto && IsInCombat() && (pProto->Class == ITEM_CLASS_WEAPON || pProto->InventoryType == INVTYPE_RELIC) && m_weaponChangeTimer == 0)
|
if (pProto && IsInCombat() && (pProto->Class == ITEM_CLASS_WEAPON || pProto->InventoryType == INVTYPE_RELIC) && m_weaponChangeTimer == 0)
|
||||||
{
|
{
|
||||||
uint32 cooldownSpell = getClass() == CLASS_ROGUE ? 6123 : 6119;
|
uint32 cooldownSpell = IsClass(CLASS_ROGUE, CLASS_CONTEXT_WEAPON_SWAP) ? 6123 : 6119;
|
||||||
SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cooldownSpell);
|
SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cooldownSpell);
|
||||||
|
|
||||||
if (!spellProto)
|
if (!spellProto)
|
||||||
@@ -4645,7 +4641,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
|||||||
}
|
}
|
||||||
case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon
|
case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon
|
||||||
{
|
{
|
||||||
if (getClass() == CLASS_SHAMAN)
|
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_ABILITY))
|
||||||
{
|
{
|
||||||
float addValue = 0.0f;
|
float addValue = 0.0f;
|
||||||
if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
|
if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
|
||||||
|
|||||||
@@ -346,16 +346,16 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
|||||||
index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
|
index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
|
||||||
index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
|
index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
|
||||||
|
|
||||||
switch (getClass())
|
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
|
||||||
{
|
{
|
||||||
case CLASS_HUNTER:
|
|
||||||
val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
|
val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
|
||||||
break;
|
}
|
||||||
case CLASS_ROGUE:
|
else if (IsClass(CLASS_ROGUE, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_STATS))
|
||||||
case CLASS_WARRIOR:
|
{
|
||||||
val2 = level + GetStat(STAT_AGILITY) - 10.0f;
|
val2 = level + GetStat(STAT_AGILITY) - 10.0f;
|
||||||
break;
|
}
|
||||||
case CLASS_DRUID:
|
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
|
||||||
|
{
|
||||||
switch (GetShapeshiftForm())
|
switch (GetShapeshiftForm())
|
||||||
{
|
{
|
||||||
case FORM_CAT:
|
case FORM_CAT:
|
||||||
@@ -367,27 +367,23 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
|||||||
val2 = GetStat(STAT_AGILITY) - 10.0f;
|
val2 = GetStat(STAT_AGILITY) - 10.0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
default:
|
else
|
||||||
|
{
|
||||||
val2 = GetStat(STAT_AGILITY) - 10.0f;
|
val2 = GetStat(STAT_AGILITY) - 10.0f;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (getClass())
|
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_STATS) || IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_STATS))
|
||||||
{
|
{
|
||||||
case CLASS_PALADIN:
|
|
||||||
case CLASS_DEATH_KNIGHT:
|
|
||||||
case CLASS_WARRIOR:
|
|
||||||
val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
|
val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
|
||||||
break;
|
}
|
||||||
case CLASS_HUNTER:
|
else if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS) || IsClass(CLASS_SHAMAN, CLASS_CONTEXT_STATS) || IsClass(CLASS_ROGUE, CLASS_CONTEXT_STATS))
|
||||||
case CLASS_SHAMAN:
|
{
|
||||||
case CLASS_ROGUE:
|
|
||||||
val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
|
val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
|
||||||
break;
|
}
|
||||||
case CLASS_DRUID:
|
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
|
||||||
{
|
{
|
||||||
// Check if Predatory Strikes is skilled
|
// Check if Predatory Strikes is skilled
|
||||||
float mLevelMult = 0.0f;
|
float mLevelMult = 0.0f;
|
||||||
@@ -467,13 +463,10 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
|||||||
val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
|
val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case CLASS_MAGE:
|
else if (IsClass(CLASS_MAGE, CLASS_CONTEXT_STATS) || IsClass(CLASS_PRIEST, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARLOCK, CLASS_CONTEXT_STATS))
|
||||||
case CLASS_PRIEST:
|
{
|
||||||
case CLASS_WARLOCK:
|
|
||||||
val2 = GetStat(STAT_STRENGTH) - 10.0f;
|
val2 = GetStat(STAT_STRENGTH) - 10.0f;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -521,7 +514,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
|||||||
UpdateDamagePhysical(BASE_ATTACK);
|
UpdateDamagePhysical(BASE_ATTACK);
|
||||||
if (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon
|
if (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon
|
||||||
UpdateDamagePhysical(OFF_ATTACK);
|
UpdateDamagePhysical(OFF_ATTACK);
|
||||||
if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness
|
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_STATS) || IsClass(CLASS_PALADIN, CLASS_CONTEXT_STATS)) // mental quickness
|
||||||
UpdateSpellDamageAndHealingBonus();
|
UpdateSpellDamageAndHealingBonus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -929,7 +929,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rage from Damage made (only from direct weapon damage)
|
// Rage from Damage made (only from direct weapon damage)
|
||||||
if (attacker && cleanDamage && damagetype == DIRECT_DAMAGE && attacker != victim && attacker->getPowerType() == POWER_RAGE)
|
if (attacker && cleanDamage && damagetype == DIRECT_DAMAGE && attacker != victim && attacker->HasActivePowerType(POWER_RAGE))
|
||||||
{
|
{
|
||||||
uint32 weaponSpeedHitFactor;
|
uint32 weaponSpeedHitFactor;
|
||||||
|
|
||||||
@@ -957,10 +957,10 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
|||||||
// Rage from absorbed damage
|
// Rage from absorbed damage
|
||||||
if (cleanDamage && cleanDamage->absorbed_damage)
|
if (cleanDamage && cleanDamage->absorbed_damage)
|
||||||
{
|
{
|
||||||
if (victim->getPowerType() == POWER_RAGE)
|
if (victim->HasActivePowerType(POWER_RAGE))
|
||||||
victim->RewardRage(cleanDamage->absorbed_damage, 0, false);
|
victim->RewardRage(cleanDamage->absorbed_damage, 0, false);
|
||||||
|
|
||||||
if (attacker && attacker->getPowerType() == POWER_RAGE )
|
if (attacker && attacker->HasActivePowerType(POWER_RAGE))
|
||||||
attacker->RewardRage(cleanDamage->absorbed_damage, 0, true);
|
attacker->RewardRage(cleanDamage->absorbed_damage, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,7 +1083,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rage from damage received
|
// Rage from damage received
|
||||||
if (attacker != victim && victim->getPowerType() == POWER_RAGE)
|
if (attacker != victim && victim->HasActivePowerType(POWER_RAGE))
|
||||||
{
|
{
|
||||||
uint32 rageDamage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
|
uint32 rageDamage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
|
||||||
victim->RewardRage(rageDamage, 0, false);
|
victim->RewardRage(rageDamage, 0, false);
|
||||||
@@ -6996,7 +6996,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
|||||||
// Magic Absorption
|
// Magic Absorption
|
||||||
if (dummySpell->SpellIconID == 459) // only this spell has SpellIconID == 459 and dummy aura
|
if (dummySpell->SpellIconID == 459) // only this spell has SpellIconID == 459 and dummy aura
|
||||||
{
|
{
|
||||||
if (getPowerType() != POWER_MANA)
|
if (!HasActivePowerType(POWER_MANA))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// mana reward
|
// mana reward
|
||||||
@@ -7775,7 +7775,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
|||||||
// Judgement of Wisdom
|
// Judgement of Wisdom
|
||||||
case 20186:
|
case 20186:
|
||||||
{
|
{
|
||||||
if (!victim || !victim->IsAlive() || victim->getPowerType() != POWER_MANA || victim->HasSpellCooldown(20268))
|
if (!victim || !victim->IsAlive() || !victim->HasActivePowerType(POWER_MANA) || victim->HasSpellCooldown(20268))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 2% of base mana
|
// 2% of base mana
|
||||||
@@ -8834,7 +8834,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
|
|||||||
// Convert recently used Blood Rune to Death Rune
|
// Convert recently used Blood Rune to Death Rune
|
||||||
if (Player* player = ToPlayer())
|
if (Player* player = ToPlayer())
|
||||||
{
|
{
|
||||||
if (player->getClass() != CLASS_DEATH_KNIGHT)
|
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// xinef: not true
|
// xinef: not true
|
||||||
@@ -9565,7 +9565,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
|
|||||||
// Item - Death Knight T10 Melee 4P Bonus
|
// Item - Death Knight T10 Melee 4P Bonus
|
||||||
if (auraSpellInfo->Id == 70656)
|
if (auraSpellInfo->Id == 70656)
|
||||||
{
|
{
|
||||||
if (GetTypeId() != TYPEID_PLAYER || getClass() != CLASS_DEATH_KNIGHT)
|
if (GetTypeId() != TYPEID_PLAYER || !IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||||
@@ -9576,7 +9576,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
|
|||||||
else if (auraSpellInfo->SpellIconID == 85)
|
else if (auraSpellInfo->SpellIconID == 85)
|
||||||
{
|
{
|
||||||
Player* plr = ToPlayer();
|
Player* plr = ToPlayer();
|
||||||
if (!plr || plr->getClass() != CLASS_DEATH_KNIGHT || !procSpell)
|
if (!plr || !plr->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY) || !procSpell)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!plr->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
|
if (!plr->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
|
||||||
@@ -13840,7 +13840,7 @@ void Unit::ClearInCombat()
|
|||||||
else if (Player* player = ToPlayer())
|
else if (Player* player = ToPlayer())
|
||||||
{
|
{
|
||||||
player->UpdatePotionCooldown();
|
player->UpdatePotionCooldown();
|
||||||
if (player->getClass() == CLASS_DEATH_KNIGHT)
|
if (player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||||
player->SetGracePeriod(i, 0);
|
player->SetGracePeriod(i, 0);
|
||||||
}
|
}
|
||||||
@@ -16378,7 +16378,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
|||||||
if (procExtra & PROC_EX_DODGE)
|
if (procExtra & PROC_EX_DODGE)
|
||||||
{
|
{
|
||||||
// Update AURA_STATE on dodge
|
// Update AURA_STATE on dodge
|
||||||
if (getClass() != CLASS_ROGUE) // skip Rogue Riposte
|
if (!IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY_REACTIVE)) // skip Rogue Riposte
|
||||||
{
|
{
|
||||||
ModifyAuraState(AURA_STATE_DEFENSE, true);
|
ModifyAuraState(AURA_STATE_DEFENSE, true);
|
||||||
StartReactiveTimer(REACTIVE_DEFENSE);
|
StartReactiveTimer(REACTIVE_DEFENSE);
|
||||||
@@ -16388,7 +16388,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
|||||||
if (procExtra & PROC_EX_PARRY)
|
if (procExtra & PROC_EX_PARRY)
|
||||||
{
|
{
|
||||||
// For Hunters only Counterattack (skip Mongoose bite)
|
// For Hunters only Counterattack (skip Mongoose bite)
|
||||||
if (getClass() == CLASS_HUNTER)
|
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY_REACTIVE))
|
||||||
{
|
{
|
||||||
ModifyAuraState(AURA_STATE_HUNTER_PARRY, true);
|
ModifyAuraState(AURA_STATE_HUNTER_PARRY, true);
|
||||||
StartReactiveTimer(REACTIVE_HUNTER_PARRY);
|
StartReactiveTimer(REACTIVE_HUNTER_PARRY);
|
||||||
@@ -16411,7 +16411,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
|||||||
// Overpower on victim dodge
|
// Overpower on victim dodge
|
||||||
if (procExtra & PROC_EX_DODGE)
|
if (procExtra & PROC_EX_DODGE)
|
||||||
{
|
{
|
||||||
if (getClass() == CLASS_WARRIOR)
|
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE))
|
||||||
{
|
{
|
||||||
AddComboPoints(target, 1);
|
AddComboPoints(target, 1);
|
||||||
StartReactiveTimer(REACTIVE_OVERPOWER);
|
StartReactiveTimer(REACTIVE_OVERPOWER);
|
||||||
@@ -17218,9 +17218,9 @@ void Unit::ClearAllReactives()
|
|||||||
|
|
||||||
if (HasAuraState(AURA_STATE_DEFENSE))
|
if (HasAuraState(AURA_STATE_DEFENSE))
|
||||||
ModifyAuraState(AURA_STATE_DEFENSE, false);
|
ModifyAuraState(AURA_STATE_DEFENSE, false);
|
||||||
if (getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY_REACTIVE) && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
||||||
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
|
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
|
||||||
if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
|
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE) && GetTypeId() == TYPEID_PLAYER)
|
||||||
ClearComboPoints();
|
ClearComboPoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17244,11 +17244,11 @@ void Unit::UpdateReactives(uint32 p_time)
|
|||||||
ModifyAuraState(AURA_STATE_DEFENSE, false);
|
ModifyAuraState(AURA_STATE_DEFENSE, false);
|
||||||
break;
|
break;
|
||||||
case REACTIVE_HUNTER_PARRY:
|
case REACTIVE_HUNTER_PARRY:
|
||||||
if (getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY_REACTIVE) && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
||||||
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
|
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
|
||||||
break;
|
break;
|
||||||
case REACTIVE_OVERPOWER:
|
case REACTIVE_OVERPOWER:
|
||||||
if (getClass() == CLASS_WARRIOR)
|
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE))
|
||||||
{
|
{
|
||||||
ClearComboPoints();
|
ClearComboPoints();
|
||||||
}
|
}
|
||||||
@@ -18113,7 +18113,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
|
|||||||
// Spirit of Redemption
|
// Spirit of Redemption
|
||||||
// if talent known but not triggered (check priest class for speedup check)
|
// if talent known but not triggered (check priest class for speedup check)
|
||||||
bool spiritOfRedemption = false;
|
bool spiritOfRedemption = false;
|
||||||
if (victim->GetTypeId() == TYPEID_PLAYER && victim->getClass() == CLASS_PRIEST && !victim->ToPlayer()->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS))
|
if (victim->GetTypeId() == TYPEID_PLAYER && victim->IsClass(CLASS_PRIEST, CLASS_CONTEXT_ABILITY) && !victim->ToPlayer()->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS))
|
||||||
{
|
{
|
||||||
if (AuraEffect* aurEff = victim->GetAuraEffectDummy(20711))
|
if (AuraEffect* aurEff = victim->GetAuraEffectDummy(20711))
|
||||||
{
|
{
|
||||||
@@ -18723,7 +18723,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
|||||||
GetMotionMaster()->MoveIdle();
|
GetMotionMaster()->MoveIdle();
|
||||||
StopMoving();
|
StopMoving();
|
||||||
|
|
||||||
if (charmer->GetTypeId() == TYPEID_PLAYER && charmer->getClass() == CLASS_WARLOCK && ToCreature()->GetCreatureTemplate()->type == CREATURE_TYPE_DEMON)
|
if (charmer->GetTypeId() == TYPEID_PLAYER && charmer->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET_CHARM) && ToCreature()->GetCreatureTemplate()->type == CREATURE_TYPE_DEMON)
|
||||||
{
|
{
|
||||||
// Disable CreatureAI/SmartAI and switch to CharmAI when charmed by warlock
|
// Disable CreatureAI/SmartAI and switch to CharmAI when charmed by warlock
|
||||||
Creature* charmed = ToCreature();
|
Creature* charmed = ToCreature();
|
||||||
@@ -18789,7 +18789,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
|||||||
playerCharmer->PossessSpellInitialize();
|
playerCharmer->PossessSpellInitialize();
|
||||||
break;
|
break;
|
||||||
case CHARM_TYPE_CHARM:
|
case CHARM_TYPE_CHARM:
|
||||||
if (GetTypeId() == TYPEID_UNIT && charmer->getClass() == CLASS_WARLOCK)
|
if (GetTypeId() == TYPEID_UNIT && charmer->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET_CHARM))
|
||||||
{
|
{
|
||||||
CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
|
CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
|
||||||
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
||||||
@@ -18911,7 +18911,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
|||||||
ClearUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD);
|
ClearUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD);
|
||||||
break;
|
break;
|
||||||
case CHARM_TYPE_CHARM:
|
case CHARM_TYPE_CHARM:
|
||||||
if (GetTypeId() == TYPEID_UNIT && charmer->getClass() == CLASS_WARLOCK)
|
if (GetTypeId() == TYPEID_UNIT && charmer->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET_CHARM))
|
||||||
{
|
{
|
||||||
CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
|
CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
|
||||||
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
||||||
|
|||||||
@@ -440,6 +440,29 @@ enum DamageEffectType : uint8
|
|||||||
SELF_DAMAGE = 5
|
SELF_DAMAGE = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Used for IsClass hook
|
||||||
|
enum ClassContext : uint8
|
||||||
|
{
|
||||||
|
CLASS_CONTEXT_NONE = 0, // Default
|
||||||
|
CLASS_CONTEXT_INIT = 1,
|
||||||
|
CLASS_CONTEXT_TELEPORT = 2,
|
||||||
|
CLASS_CONTEXT_QUEST = 3,
|
||||||
|
CLASS_CONTEXT_STATS = 4,
|
||||||
|
CLASS_CONTEXT_TAXI = 5,
|
||||||
|
CLASS_CONTEXT_SKILL = 6,
|
||||||
|
CLASS_CONTEXT_TALENT_POINT_CALC = 7,
|
||||||
|
CLASS_CONTEXT_ABILITY = 8,
|
||||||
|
CLASS_CONTEXT_ABILITY_REACTIVE = 9,
|
||||||
|
CLASS_CONTEXT_PET = 10,
|
||||||
|
CLASS_CONTEXT_PET_CHARM = 11,
|
||||||
|
CLASS_CONTEXT_EQUIP_RELIC = 12,
|
||||||
|
CLASS_CONTEXT_EQUIP_SHIELDS = 13,
|
||||||
|
CLASS_CONTEXT_EQUIP_ARMOR_CLASS = 14,
|
||||||
|
CLASS_CONTEXT_WEAPON_SWAP = 15,
|
||||||
|
CLASS_CONTEXT_GRAVEYARD = 16,
|
||||||
|
CLASS_CONTEXT_CLASS_TRAINER = 17
|
||||||
|
};
|
||||||
|
|
||||||
// Value masks for UNIT_FIELD_FLAGS
|
// Value masks for UNIT_FIELD_FLAGS
|
||||||
// EnumUtils: DESCRIBE THIS
|
// EnumUtils: DESCRIBE THIS
|
||||||
enum UnitFlags : uint32
|
enum UnitFlags : uint32
|
||||||
@@ -1436,6 +1459,7 @@ public:
|
|||||||
void setRace(uint8 race);
|
void setRace(uint8 race);
|
||||||
[[nodiscard]] uint32 getRaceMask() const { return 1 << (getRace(true) - 1); }
|
[[nodiscard]] uint32 getRaceMask() const { return 1 << (getRace(true) - 1); }
|
||||||
[[nodiscard]] uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); }
|
[[nodiscard]] uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); }
|
||||||
|
[[nodiscard]] virtual bool IsClass(Classes unitClass, [[maybe_unused]] ClassContext context = CLASS_CONTEXT_NONE) const { return (getClass() == unitClass); }
|
||||||
[[nodiscard]] uint32 getClassMask() const { return 1 << (getClass() - 1); }
|
[[nodiscard]] uint32 getClassMask() const { return 1 << (getClass() - 1); }
|
||||||
[[nodiscard]] uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); }
|
[[nodiscard]] uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); }
|
||||||
[[nodiscard]] DisplayRace GetDisplayRaceFromModelId(uint32 modelId) const;
|
[[nodiscard]] DisplayRace GetDisplayRaceFromModelId(uint32 modelId) const;
|
||||||
@@ -1472,6 +1496,7 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
|
[[nodiscard]] Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
|
||||||
void setPowerType(Powers power);
|
void setPowerType(Powers power);
|
||||||
|
[[nodiscard]] virtual bool HasActivePowerType(Powers power) { return getPowerType() == power; }
|
||||||
[[nodiscard]] uint32 GetPower(Powers power) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power); }
|
[[nodiscard]] uint32 GetPower(Powers power) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power); }
|
||||||
[[nodiscard]] uint32 GetMaxPower(Powers power) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_MAXPOWER1) + power); }
|
[[nodiscard]] uint32 GetMaxPower(Powers power) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_MAXPOWER1) + power); }
|
||||||
void SetPower(Powers power, uint32 val, bool withPowerUpdate = true, bool fromRegenerate = false);
|
void SetPower(Powers power, uint32 val, bool withPowerUpdate = true, bool fromRegenerate = false);
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ void Vehicle::Install()
|
|||||||
{
|
{
|
||||||
if (PowerDisplayEntry const* powerDisplay = sPowerDisplayStore.LookupEntry(_vehicleInfo->m_powerDisplayId))
|
if (PowerDisplayEntry const* powerDisplay = sPowerDisplayStore.LookupEntry(_vehicleInfo->m_powerDisplayId))
|
||||||
_me->setPowerType(Powers(powerDisplay->PowerType));
|
_me->setPowerType(Powers(powerDisplay->PowerType));
|
||||||
else if (_me->getClass() == CLASS_ROGUE)
|
else if (_me->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY))
|
||||||
_me->setPowerType(POWER_ENERGY);
|
_me->setPowerType(POWER_ENERGY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1983,7 +1983,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
|
|||||||
return ERR_IN_NON_RANDOM_BG;
|
return ERR_IN_NON_RANDOM_BG;
|
||||||
|
|
||||||
// don't let Death Knights join BG queues when they are not allowed to be teleported yet
|
// don't let Death Knights join BG queues when they are not allowed to be teleported yet
|
||||||
if (member->getClass() == CLASS_DEATH_KNIGHT && member->GetMapId() == 609 && !member->IsGameMaster() && !member->HasSpell(50977))
|
if (member->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TELEPORT) && member->GetMapId() == 609 && !member->IsGameMaster() && !member->HasSpell(50977))
|
||||||
return ERR_GROUP_JOIN_BATTLEGROUND_FAIL;
|
return ERR_GROUP_JOIN_BATTLEGROUND_FAIL;
|
||||||
|
|
||||||
if (!member->GetBGAccessByLevel(bgTemplate->GetBgTypeID()))
|
if (!member->GetBGAccessByLevel(bgTemplate->GetBgTypeID()))
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
|
|||||||
err = ERR_BATTLEGROUND_QUEUED_FOR_RATED;
|
err = ERR_BATTLEGROUND_QUEUED_FOR_RATED;
|
||||||
}
|
}
|
||||||
// don't let Death Knights join BG queues when they are not allowed to be teleported yet
|
// don't let Death Knights join BG queues when they are not allowed to be teleported yet
|
||||||
else if (_player->getClass() == CLASS_DEATH_KNIGHT && _player->GetMapId() == 609 && !_player->IsGameMaster() && !_player->HasSpell(50977))
|
else if (_player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TELEPORT) && _player->GetMapId() == 609 && !_player->IsGameMaster() && !_player->HasSpell(50977))
|
||||||
{
|
{
|
||||||
err = ERR_BATTLEGROUND_NONE;
|
err = ERR_BATTLEGROUND_NONE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData)
|
|||||||
{
|
{
|
||||||
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
|
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
|
||||||
|
|
||||||
bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
bool lootAllowed = creature && creature->IsAlive() == (player->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY) && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||||
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
|
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
|
||||||
{
|
{
|
||||||
player->SendLootError(lguid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL);
|
player->SendLootError(lguid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL);
|
||||||
@@ -162,7 +162,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
|
|||||||
case HighGuid::Vehicle:
|
case HighGuid::Vehicle:
|
||||||
{
|
{
|
||||||
Creature* creature = player->GetMap()->GetCreature(guid);
|
Creature* creature = player->GetMap()->GetCreature(guid);
|
||||||
bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
bool lootAllowed = creature && creature->IsAlive() == (player->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY) && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||||
if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE))
|
if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE))
|
||||||
{
|
{
|
||||||
loot = &creature->loot;
|
loot = &creature->loot;
|
||||||
@@ -382,7 +382,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
|
|||||||
{
|
{
|
||||||
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
|
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
|
||||||
|
|
||||||
bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
bool lootAllowed = creature && creature->IsAlive() == (player->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY) && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||||
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
|
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -1000,11 +1000,11 @@ void ScriptMgr::PetitionShowList(Player* player, Creature* creature, uint32& Cha
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptMgr::OnRewardKillRewarder(Player* player, bool isDungeon, float& rate)
|
void ScriptMgr::OnRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate)
|
||||||
{
|
{
|
||||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||||
{
|
{
|
||||||
script->OnRewardKillRewarder(player, isDungeon, rate);
|
script->OnRewardKillRewarder(player, rewarder, isDungeon, rate);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1046,6 +1046,19 @@ bool ScriptMgr::CanRepopAtGraveyard(Player* player)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<bool> ScriptMgr::OnPlayerIsClass(Player const* player, Classes unitClass, ClassContext context)
|
||||||
|
{
|
||||||
|
if (ScriptRegistry<PlayerScript>::ScriptPointerList.empty())
|
||||||
|
return {};
|
||||||
|
for (auto const& [scriptID, script] : ScriptRegistry<PlayerScript>::ScriptPointerList)
|
||||||
|
{
|
||||||
|
Optional<bool> scriptResult = script->OnPlayerIsClass(player, unitClass, context);
|
||||||
|
if (scriptResult)
|
||||||
|
return scriptResult;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure)
|
void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure)
|
||||||
{
|
{
|
||||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||||
@@ -1054,6 +1067,21 @@ void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ScriptMgr::OnPlayerHasActivePowerType(Player const* player, Powers power)
|
||||||
|
{
|
||||||
|
auto ret = IsValidBoolScript<PlayerScript>([&](PlayerScript* script)
|
||||||
|
{
|
||||||
|
return script->OnPlayerHasActivePowerType(player, power);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (ret && *ret)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptMgr::OnUpdateGatheringSkill(Player *player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32 &gain) {
|
void ScriptMgr::OnUpdateGatheringSkill(Player *player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32 &gain) {
|
||||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
// TODO to remove
|
// TODO to remove
|
||||||
#include "AchievementMgr.h"
|
#include "AchievementMgr.h"
|
||||||
|
#include "KillRewarder.h"
|
||||||
|
|
||||||
class PlayerScript : public ScriptObject
|
class PlayerScript : public ScriptObject
|
||||||
{
|
{
|
||||||
@@ -315,7 +316,7 @@ public:
|
|||||||
|
|
||||||
virtual void PetitionShowList(Player* /*player*/, Creature* /*creature*/, uint32& /*CharterEntry*/, uint32& /*CharterDispayID*/, uint32& /*CharterCost*/) { }
|
virtual void PetitionShowList(Player* /*player*/, Creature* /*creature*/, uint32& /*CharterEntry*/, uint32& /*CharterDispayID*/, uint32& /*CharterCost*/) { }
|
||||||
|
|
||||||
virtual void OnRewardKillRewarder(Player* /*player*/, bool /*isDungeon*/, float& /*rate*/) { }
|
virtual void OnRewardKillRewarder(Player* /*player*/, KillRewarder* /*rewarder*/, bool /*isDungeon*/, float& /*rate*/) { }
|
||||||
|
|
||||||
[[nodiscard]] virtual bool CanGiveMailRewardAtGiveLevel(Player* /*player*/, uint8 /*level*/) { return true; }
|
[[nodiscard]] virtual bool CanGiveMailRewardAtGiveLevel(Player* /*player*/, uint8 /*level*/) { return true; }
|
||||||
|
|
||||||
@@ -323,8 +324,12 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] virtual bool CanRepopAtGraveyard(Player* /*player*/) { return true; }
|
[[nodiscard]] virtual bool CanRepopAtGraveyard(Player* /*player*/) { return true; }
|
||||||
|
|
||||||
|
[[nodiscard]] virtual Optional<bool> OnPlayerIsClass(Player const* /*player*/, Classes /*playerClass*/, ClassContext /*context*/) { return std::nullopt; }
|
||||||
|
|
||||||
virtual void OnGetMaxSkillValue(Player* /*player*/, uint32 /*skill*/, int32& /*result*/, bool /*IsPure*/) { }
|
virtual void OnGetMaxSkillValue(Player* /*player*/, uint32 /*skill*/, int32& /*result*/, bool /*IsPure*/) { }
|
||||||
|
|
||||||
|
[[nodiscard]] virtual bool OnPlayerHasActivePowerType(Player const* /*player*/, Powers /*power*/) { return false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This hook called before gathering skill gain is applied to the character.
|
* @brief This hook called before gathering skill gain is applied to the character.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -430,11 +430,13 @@ public: /* PlayerScript */
|
|||||||
bool CanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item);
|
bool CanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item);
|
||||||
void PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type);
|
void PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type);
|
||||||
void PetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost);
|
void PetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost);
|
||||||
void OnRewardKillRewarder(Player* player, bool isDungeon, float& rate);
|
void OnRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate);
|
||||||
bool CanGiveMailRewardAtGiveLevel(Player* player, uint8 level);
|
bool CanGiveMailRewardAtGiveLevel(Player* player, uint8 level);
|
||||||
void OnDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid);
|
void OnDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid);
|
||||||
bool CanRepopAtGraveyard(Player* player);
|
bool CanRepopAtGraveyard(Player* player);
|
||||||
|
std::optional<bool> OnPlayerIsClass(Player const* player, Classes playerClass, ClassContext context);
|
||||||
void OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure);
|
void OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure);
|
||||||
|
bool OnPlayerHasActivePowerType(Player const* player, Powers power);
|
||||||
void OnUpdateGatheringSkill(Player* player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32& gain);
|
void OnUpdateGatheringSkill(Player* player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32& gain);
|
||||||
void OnUpdateCraftingSkill(Player* player, SkillLineAbilityEntry const* skill, uint32 currentLevel, uint32& gain);
|
void OnUpdateCraftingSkill(Player* player, SkillLineAbilityEntry const* skill, uint32 currentLevel, uint32& gain);
|
||||||
bool OnUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll);
|
bool OnUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll);
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ class WorldSocket;
|
|||||||
enum ArenaTeamInfoType : uint8;
|
enum ArenaTeamInfoType : uint8;
|
||||||
enum AuraRemoveMode : uint8;
|
enum AuraRemoveMode : uint8;
|
||||||
enum BattlegroundDesertionType : uint8;
|
enum BattlegroundDesertionType : uint8;
|
||||||
|
enum ClassContext : uint8;
|
||||||
enum ContentLevels : uint8;
|
enum ContentLevels : uint8;
|
||||||
enum DamageEffectType : uint8;
|
enum DamageEffectType : uint8;
|
||||||
enum EnchantmentSlot : uint8;
|
enum EnchantmentSlot : uint8;
|
||||||
|
|||||||
@@ -2027,7 +2027,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
|
|||||||
if (!target->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
|
if (!target->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
|
||||||
{
|
{
|
||||||
target->SetShapeshiftForm(FORM_NONE);
|
target->SetShapeshiftForm(FORM_NONE);
|
||||||
if (target->getClass() == CLASS_DRUID)
|
if (target->IsClass(CLASS_DRUID, CLASS_CONTEXT_ABILITY))
|
||||||
{
|
{
|
||||||
target->setPowerType(POWER_MANA);
|
target->setPowerType(POWER_MANA);
|
||||||
// Remove movement impairing effects also when shifting out
|
// Remove movement impairing effects also when shifting out
|
||||||
@@ -2106,7 +2106,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
|
|||||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||||
target->ToPlayer()->InitDataForForm();
|
target->ToPlayer()->InitDataForForm();
|
||||||
|
|
||||||
if (target->getClass() == CLASS_DRUID)
|
if (target->IsClass(CLASS_DRUID, CLASS_CONTEXT_ABILITY))
|
||||||
{
|
{
|
||||||
// Dash
|
// Dash
|
||||||
if (AuraEffect* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8))
|
if (AuraEffect* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8))
|
||||||
@@ -6038,7 +6038,7 @@ void AuraEffect::HandleAuraConvertRune(AuraApplication const* aurApp, uint8 mode
|
|||||||
|
|
||||||
Player* player = target->ToPlayer();
|
Player* player = target->ToPlayer();
|
||||||
|
|
||||||
if (player->getClass() != CLASS_DEATH_KNIGHT)
|
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32 runes = m_amount;
|
uint32 runes = m_amount;
|
||||||
@@ -6244,7 +6244,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
|
|||||||
{
|
{
|
||||||
// Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
|
// Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
|
||||||
// Should be manauser
|
// Should be manauser
|
||||||
if (target->getPowerType() != POWER_RAGE)
|
if (!target->HasActivePowerType(POWER_RAGE))
|
||||||
break;
|
break;
|
||||||
uint32 rage = target->GetPower(POWER_RAGE);
|
uint32 rage = target->GetPower(POWER_RAGE);
|
||||||
// Nothing todo
|
// Nothing todo
|
||||||
@@ -6310,7 +6310,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
|
|||||||
{
|
{
|
||||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||||
return;
|
return;
|
||||||
if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
|
if (!target->ToPlayer()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// timer expired - remove death runes
|
// timer expired - remove death runes
|
||||||
@@ -7082,7 +7082,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
|
|||||||
{
|
{
|
||||||
Powers PowerType = Powers(GetMiscValue());
|
Powers PowerType = Powers(GetMiscValue());
|
||||||
|
|
||||||
if (!caster || !caster->IsAlive() || !target->IsAlive() || target->getPowerType() != PowerType)
|
if (!caster || !caster->IsAlive() || !target->IsAlive() || !target->HasActivePowerType(PowerType))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamageOrSchool(GetSpellInfo()))
|
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamageOrSchool(GetSpellInfo()))
|
||||||
@@ -7189,7 +7189,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons
|
|||||||
{
|
{
|
||||||
Powers PowerType = Powers(GetMiscValue());
|
Powers PowerType = Powers(GetMiscValue());
|
||||||
|
|
||||||
if (target->GetTypeId() == TYPEID_PLAYER && target->getPowerType() != PowerType && !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
if (target->GetTypeId() == TYPEID_PLAYER && !target->HasActivePowerType(PowerType) && !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!target->IsAlive() || !target->GetMaxPower(PowerType))
|
if (!target->IsAlive() || !target->GetMaxPower(PowerType))
|
||||||
@@ -7223,7 +7223,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
|
|||||||
{
|
{
|
||||||
Powers PowerType = Powers(GetMiscValue());
|
Powers PowerType = Powers(GetMiscValue());
|
||||||
|
|
||||||
if (!caster || !target->IsAlive() || target->getPowerType() != PowerType)
|
if (!caster || !target->IsAlive() || !target->HasActivePowerType(PowerType))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamageOrSchool(GetSpellInfo()))
|
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamageOrSchool(GetSpellInfo()))
|
||||||
|
|||||||
@@ -1876,7 +1876,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
|
|||||||
break;
|
break;
|
||||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||||
break;
|
break;
|
||||||
if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
|
if (!target->ToPlayer()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// aura removed - remove death runes
|
// aura removed - remove death runes
|
||||||
|
|||||||
@@ -4807,7 +4807,7 @@ void Spell::SendSpellGo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((m_caster->GetTypeId() == TYPEID_PLAYER)
|
if ((m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
&& (m_caster->getClass() == CLASS_DEATH_KNIGHT)
|
&& (m_caster->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
&& m_spellInfo->RuneCostID
|
&& m_spellInfo->RuneCostID
|
||||||
&& m_spellInfo->PowerType == POWER_RUNE)
|
&& m_spellInfo->PowerType == POWER_RUNE)
|
||||||
{
|
{
|
||||||
@@ -5396,7 +5396,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 RuneCostID)
|
|||||||
return SPELL_CAST_OK;
|
return SPELL_CAST_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->getClass() != CLASS_DEATH_KNIGHT)
|
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
return SPELL_CAST_OK;
|
return SPELL_CAST_OK;
|
||||||
|
|
||||||
SpellRuneCostEntry const* src = sSpellRuneCostStore.LookupEntry(RuneCostID);
|
SpellRuneCostEntry const* src = sSpellRuneCostStore.LookupEntry(RuneCostID);
|
||||||
@@ -5437,7 +5437,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 RuneCostID)
|
|||||||
|
|
||||||
void Spell::TakeRunePower(bool didHit)
|
void Spell::TakeRunePower(bool didHit)
|
||||||
{
|
{
|
||||||
if (m_caster->GetTypeId() != TYPEID_PLAYER || m_caster->getClass() != CLASS_DEATH_KNIGHT)
|
if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_caster->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SpellRuneCostEntry const* runeCostData = sSpellRuneCostStore.LookupEntry(m_spellInfo->RuneCostID);
|
SpellRuneCostEntry const* runeCostData = sSpellRuneCostStore.LookupEntry(m_spellInfo->RuneCostID);
|
||||||
@@ -6173,7 +6173,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
// Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects)
|
// Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects)
|
||||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||||
if (Unit* target = m_targets.GetUnitTarget())
|
if (Unit* target = m_targets.GetUnitTarget())
|
||||||
if (target != m_caster && target->getPowerType() != Powers(m_spellInfo->Effects[i].MiscValue))
|
if (target != m_caster && !target->HasActivePowerType(Powers(m_spellInfo->Effects[i].MiscValue)))
|
||||||
return SPELL_FAILED_BAD_TARGETS;
|
return SPELL_FAILED_BAD_TARGETS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -6408,7 +6408,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
return SPELL_FAILED_ALREADY_HAVE_CHARM;
|
return SPELL_FAILED_ALREADY_HAVE_CHARM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARLOCK && strict)
|
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET) && strict)
|
||||||
if (Pet* pet = m_caster->ToPlayer()->GetPet())
|
if (Pet* pet = m_caster->ToPlayer()->GetPet())
|
||||||
pet->CastSpell(pet, 32752, true, nullptr, nullptr, pet->GetGUID()); //starting cast, trigger pet stun (cast by pet so it doesn't attack player)
|
pet->CastSpell(pet, 32752, true, nullptr, nullptr, pet->GetGUID()); //starting cast, trigger pet stun (cast by pet so it doesn't attack player)
|
||||||
|
|
||||||
@@ -6702,7 +6702,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
if (!m_targets.GetUnitTarget())
|
if (!m_targets.GetUnitTarget())
|
||||||
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||||
|
|
||||||
if (m_targets.GetUnitTarget()->getPowerType() != POWER_MANA)
|
if (!m_targets.GetUnitTarget()->HasActivePowerType(POWER_MANA))
|
||||||
return SPELL_FAILED_BAD_TARGETS;
|
return SPELL_FAILED_BAD_TARGETS;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1345,7 +1345,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex)
|
|||||||
|
|
||||||
Powers PowerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
Powers PowerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
||||||
|
|
||||||
if (!unitTarget || !unitTarget->IsAlive() || unitTarget->getPowerType() != PowerType || damage < 0)
|
if (!unitTarget || !unitTarget->IsAlive() || !unitTarget->HasActivePowerType(PowerType) || damage < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// add spell damage bonus
|
// add spell damage bonus
|
||||||
@@ -1424,7 +1424,7 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex)
|
|||||||
|
|
||||||
Powers PowerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
Powers PowerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
||||||
|
|
||||||
if (!unitTarget || !unitTarget->IsAlive() || unitTarget->getPowerType() != PowerType || damage < 0)
|
if (!unitTarget || !unitTarget->IsAlive() || !unitTarget->HasActivePowerType(PowerType) || damage < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
|
// burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
|
||||||
@@ -1877,7 +1877,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
|
|||||||
|
|
||||||
Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
||||||
|
|
||||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && m_spellInfo->SpellFamilyName != SPELLFAMILY_POTION
|
if (unitTarget->GetTypeId() == TYPEID_PLAYER && !unitTarget->HasActivePowerType(power) && m_spellInfo->SpellFamilyName != SPELLFAMILY_POTION
|
||||||
&& !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
&& !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1982,7 +1982,7 @@ void Spell::EffectEnergizePct(SpellEffIndex effIndex)
|
|||||||
|
|
||||||
Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
||||||
|
|
||||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
if (unitTarget->GetTypeId() == TYPEID_PLAYER && !unitTarget->HasActivePowerType(power) && !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32 maxPower = unitTarget->GetMaxPower(power);
|
uint32 maxPower = unitTarget->GetMaxPower(power);
|
||||||
@@ -3077,7 +3077,7 @@ void Spell::EffectTameCreature(SpellEffIndex /*effIndex*/)
|
|||||||
if (creatureTarget->IsPet())
|
if (creatureTarget->IsPet())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_caster->getClass() != CLASS_HUNTER)
|
if (!m_caster->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// cast finish successfully
|
// cast finish successfully
|
||||||
@@ -3209,7 +3209,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
|
|||||||
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||||
|
|
||||||
// Reset cooldowns
|
// Reset cooldowns
|
||||||
if (owner->getClass() != CLASS_HUNTER)
|
if (!owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||||
{
|
{
|
||||||
pet->m_CreatureSpellCooldowns.clear();
|
pet->m_CreatureSpellCooldowns.clear();
|
||||||
owner->PetSpellInitialize();
|
owner->PetSpellInitialize();
|
||||||
@@ -5746,7 +5746,7 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex)
|
|||||||
|
|
||||||
Player* player = m_caster->ToPlayer();
|
Player* player = m_caster->ToPlayer();
|
||||||
|
|
||||||
if (player->getClass() != CLASS_DEATH_KNIGHT)
|
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// needed later
|
// needed later
|
||||||
@@ -5814,7 +5814,7 @@ void Spell::EffectCreateTamedPet(SpellEffIndex effIndex)
|
|||||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->GetPetGUID() || unitTarget->getClass() != CLASS_HUNTER)
|
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->GetPetGUID() || !unitTarget->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue;
|
uint32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue;
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public:
|
|||||||
uint8 oldLevel = playerTarget->GetLevel();
|
uint8 oldLevel = playerTarget->GetLevel();
|
||||||
|
|
||||||
// set starting level
|
// set starting level
|
||||||
uint32 startLevel = playerTarget->getClass() != CLASS_DEATH_KNIGHT
|
uint32 startLevel = !playerTarget->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT)
|
||||||
? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)
|
? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)
|
||||||
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
|
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1029,7 +1029,7 @@ class spell_class_call_handler : public SpellScript
|
|||||||
targets.remove_if([spellInfo](WorldObject const* target) -> bool
|
targets.remove_if([spellInfo](WorldObject const* target) -> bool
|
||||||
{
|
{
|
||||||
Player const* player = target->ToPlayer();
|
Player const* player = target->ToPlayer();
|
||||||
if (!player || player->getClass() == CLASS_DEATH_KNIGHT) // ignore all death knights from whatever spell, for some reason the condition below is not working x.x
|
if (!player || player->IsClass(CLASS_DEATH_KNIGHT)) // ignore all death knights from whatever spell, for some reason the condition below is not working x.x
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,13 @@ enum Spells
|
|||||||
SPELL_SHRED_ARMOR = 43243 // Used by Spirit Lynx
|
SPELL_SHRED_ARMOR = 43243 // Used by Spirit Lynx
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum UniqueEvents
|
||||||
|
{
|
||||||
|
EVENT_BERSERK = 0
|
||||||
|
};
|
||||||
|
|
||||||
enum Hal_CreatureIds
|
enum Hal_CreatureIds
|
||||||
{
|
{
|
||||||
NPC_SPIRIT_LYNX = 24143,
|
|
||||||
NPC_TOTEM = 24224
|
NPC_TOTEM = 24224
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -63,326 +67,274 @@ enum Yells
|
|||||||
SAY_DEATH = 5
|
SAY_DEATH = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_halazzi : public CreatureScript
|
enum Groups
|
||||||
{
|
{
|
||||||
public:
|
GROUP_LYNX = 0,
|
||||||
boss_halazzi() : CreatureScript("boss_halazzi") { }
|
GROUP_HUMAN = 1,
|
||||||
|
GROUP_MERGE = 2
|
||||||
|
};
|
||||||
|
|
||||||
struct boss_halazziAI : public ScriptedAI
|
struct boss_halazzi : public BossAI
|
||||||
|
{
|
||||||
|
boss_halazzi(Creature* creature) : BossAI(creature, DATA_HALAZZIEVENT)
|
||||||
{
|
{
|
||||||
boss_halazziAI(Creature* creature) : ScriptedAI(creature), summons(me)
|
scheduler.SetValidator([this]
|
||||||
{
|
{
|
||||||
instance = creature->GetInstanceScript();
|
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
InstanceScript* instance;
|
|
||||||
SummonList summons;
|
|
||||||
PhaseHalazzi Phase;
|
|
||||||
|
|
||||||
uint32 FrenzyTimer;
|
|
||||||
uint32 SaberlashTimer;
|
|
||||||
uint32 ShockTimer;
|
|
||||||
uint32 TotemTimer;
|
|
||||||
uint32 CheckTimer;
|
|
||||||
uint32 BerserkTimer;
|
|
||||||
uint32 TransformCount;
|
|
||||||
|
|
||||||
ObjectGuid LynxGUID;
|
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
instance->SetData(DATA_HALAZZIEVENT, NOT_STARTED);
|
BossAI::Reset();
|
||||||
summons.DespawnAll();
|
_transformCount = 0;
|
||||||
|
_healthCheckPercentage = 0;
|
||||||
LynxGUID.Clear();
|
_phase = PHASE_NONE;
|
||||||
TransformCount = 0;
|
_lynxFormHealth = me->GetMaxHealth();
|
||||||
BerserkTimer = 600000;
|
_healthPortion = _lynxFormHealth/4;
|
||||||
CheckTimer = 1000;
|
_humanFormHealth = (me->GetMaxHealth())/0.66666666;
|
||||||
|
|
||||||
DoCast(me, SPELL_DUAL_WIELD, true);
|
|
||||||
|
|
||||||
Phase = PHASE_NONE;
|
|
||||||
EnterPhase(PHASE_LYNX);
|
|
||||||
}
|
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override
|
|
||||||
{
|
|
||||||
instance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS);
|
|
||||||
Talk(SAY_AGGRO);
|
|
||||||
EnterPhase(PHASE_LYNX);
|
EnterPhase(PHASE_LYNX);
|
||||||
|
DoCastSelf(SPELL_DUAL_WIELD, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* summon) override
|
void JustSummoned(Creature* summon) override
|
||||||
{
|
{
|
||||||
summon->AI()->AttackStart(me->GetVictim());
|
BossAI::JustSummoned(summon);
|
||||||
if (summon->GetEntry() == NPC_SPIRIT_LYNX)
|
summon->Attack(me->GetVictim(), false);
|
||||||
LynxGUID = summon->GetGUID();
|
summon->SetInCombatWithZone();
|
||||||
summons.Summon(summon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
void JustEngagedWith(Unit* who) override
|
||||||
|
{
|
||||||
|
BossAI::JustEngagedWith(who);
|
||||||
|
Talk(SAY_AGGRO);
|
||||||
|
ScheduleUniqueTimedEvent(10min, [&]
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_BERSERK, true);
|
||||||
|
}, EVENT_BERSERK);
|
||||||
|
EnterPhase(PHASE_LYNX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||||
|
{
|
||||||
|
if (damage >= me->GetHealth() && _phase != PHASE_ENRAGE)
|
||||||
{
|
{
|
||||||
if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE)
|
|
||||||
damage = 0;
|
damage = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_phase == PHASE_LYNX || _phase == PHASE_ENRAGE)
|
||||||
|
{
|
||||||
|
_healthCheckPercentage = 25 * (3 - _transformCount);
|
||||||
|
if (!HealthAbovePct(_healthCheckPercentage))
|
||||||
|
{
|
||||||
|
EnterPhase(PHASE_SPLIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (_phase == PHASE_HUMAN)
|
||||||
|
{
|
||||||
|
if (Creature* lynx = instance->GetCreature(DATA_SPIRIT_LYNX))
|
||||||
|
{
|
||||||
|
if (!HealthAbovePct(20) || !lynx->HealthAbovePct(20))
|
||||||
|
{
|
||||||
|
EnterPhase(PHASE_MERGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//should not really happen
|
||||||
|
EnterEvadeMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SpellHit(Unit*, SpellInfo const* spell) override
|
void SpellHit(Unit*, SpellInfo const* spell) override
|
||||||
{
|
{
|
||||||
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
|
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
|
||||||
|
{
|
||||||
EnterPhase(PHASE_HUMAN);
|
EnterPhase(PHASE_HUMAN);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AttackStart(Unit* who) override
|
void AttackStart(Unit* who) override
|
||||||
{
|
{
|
||||||
if (Phase != PHASE_MERGE)
|
if (_phase != PHASE_MERGE)
|
||||||
ScriptedAI::AttackStart(who);
|
{
|
||||||
|
BossAI::AttackStart(who);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterPhase(PhaseHalazzi NextPhase)
|
void EnterPhase(PhaseHalazzi nextPhase)
|
||||||
{
|
{
|
||||||
switch (NextPhase)
|
switch (nextPhase)
|
||||||
{
|
{
|
||||||
case PHASE_LYNX:
|
case PHASE_LYNX:
|
||||||
case PHASE_ENRAGE:
|
case PHASE_ENRAGE:
|
||||||
if (Phase == PHASE_MERGE)
|
if (_phase == PHASE_MERGE)
|
||||||
{
|
{
|
||||||
DoCast(me, SPELL_TRANSFORM_MERGE, true);
|
DoCastSelf(SPELL_TRANSFORM_MERGE, true);
|
||||||
me->Attack(me->GetVictim(), true);
|
me->RemoveAurasDueToSpell(SPELL_TRANSFORM_SPLIT2);
|
||||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||||
}
|
}
|
||||||
if (Creature* Lynx = ObjectAccessor::GetCreature(*me, LynxGUID))
|
summons.DespawnAll();
|
||||||
Lynx->DisappearAndDie();
|
me->SetMaxHealth(_lynxFormHealth);
|
||||||
me->SetMaxHealth(600000);
|
me->SetHealth(_lynxFormHealth - _healthPortion * _transformCount);
|
||||||
me->SetHealth(600000 - 150000 * TransformCount);
|
scheduler.CancelGroup(GROUP_MERGE);
|
||||||
FrenzyTimer = 16000;
|
scheduler.Schedule(16s, GROUP_LYNX, [this](TaskContext context)
|
||||||
SaberlashTimer = 20000;
|
{
|
||||||
ShockTimer = 10000;
|
DoCastSelf(SPELL_FRENZY);
|
||||||
TotemTimer = 12000;
|
context.Repeat(10s, 15s);
|
||||||
|
}).Schedule(20s, GROUP_LYNX, [this](TaskContext context)
|
||||||
|
{
|
||||||
|
Talk(SAY_SABER);
|
||||||
|
DoCastVictim(SPELL_SABER_LASH, true);
|
||||||
|
context.Repeat(30s);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case PHASE_SPLIT:
|
case PHASE_SPLIT:
|
||||||
Talk(SAY_SPLIT);
|
Talk(SAY_SPLIT);
|
||||||
DoCast(me, SPELL_TRANSFORM_SPLIT, true);
|
DoCastSelf(SPELL_TRANSFORM_SPLIT, true);
|
||||||
break;
|
break;
|
||||||
case PHASE_HUMAN:
|
case PHASE_HUMAN:
|
||||||
//DoCast(me, SPELL_SUMMON_LYNX, true);
|
scheduler.CancelGroup(GROUP_MERGE);
|
||||||
DoSpawnCreature(NPC_SPIRIT_LYNX, 5, 5, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
DoCastSelf(SPELL_SUMMON_LYNX, true);
|
||||||
me->SetMaxHealth(400000);
|
me->SetMaxHealth(_humanFormHealth);
|
||||||
me->SetHealth(400000);
|
me->SetHealth(_humanFormHealth);
|
||||||
ShockTimer = 10000;
|
scheduler.CancelGroup(GROUP_LYNX);
|
||||||
TotemTimer = 12000;
|
scheduler.Schedule(10s, GROUP_HUMAN, [this](TaskContext context)
|
||||||
|
{
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||||
|
{
|
||||||
|
if (target->IsNonMeleeSpellCast(false))
|
||||||
|
{
|
||||||
|
DoCast(target, SPELL_EARTHSHOCK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoCast(target, SPELL_FLAMESHOCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.Repeat(10s, 15s);
|
||||||
|
}).Schedule(12s, GROUP_HUMAN, [this](TaskContext context)
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_SUMMON_TOTEM);
|
||||||
|
context.Repeat(20s);
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case PHASE_MERGE:
|
case PHASE_MERGE:
|
||||||
if (Unit* pLynx = ObjectAccessor::GetUnit(*me, LynxGUID))
|
if (Creature* lynx = instance->GetCreature(DATA_SPIRIT_LYNX))
|
||||||
{
|
{
|
||||||
Talk(SAY_MERGE);
|
Talk(SAY_MERGE);
|
||||||
pLynx->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
scheduler.CancelGroup(GROUP_HUMAN);
|
||||||
pLynx->GetMotionMaster()->Clear();
|
lynx->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||||
pLynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
lynx->GetMotionMaster()->Clear();
|
||||||
|
lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||||
me->GetMotionMaster()->Clear();
|
me->GetMotionMaster()->Clear();
|
||||||
me->GetMotionMaster()->MoveFollow(pLynx, 0, 0);
|
me->GetMotionMaster()->MoveFollow(lynx, 0, 0);
|
||||||
++TransformCount;
|
++_transformCount;
|
||||||
|
scheduler.Schedule(2s, GROUP_MERGE, [this](TaskContext context)
|
||||||
|
{
|
||||||
|
if (Creature* lynx = instance->GetCreature(DATA_SPIRIT_LYNX))
|
||||||
|
{
|
||||||
|
if (me->IsWithinDistInMap(lynx, 6.0f))
|
||||||
|
{
|
||||||
|
if (_transformCount < 3)
|
||||||
|
{
|
||||||
|
EnterPhase(PHASE_LYNX);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EnterPhase(PHASE_ENRAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.Repeat(2s);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Phase = NextPhase;
|
_phase = nextPhase;
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
|
||||||
{
|
|
||||||
if (!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (BerserkTimer <= diff)
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_BERSERK, true);
|
|
||||||
BerserkTimer = 60000;
|
|
||||||
}
|
|
||||||
else BerserkTimer -= diff;
|
|
||||||
|
|
||||||
if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE)
|
|
||||||
{
|
|
||||||
if (SaberlashTimer <= diff)
|
|
||||||
{
|
|
||||||
Talk(SAY_SABER);
|
|
||||||
// A tank with more than 490 defense skills should receive no critical hit
|
|
||||||
//DoCast(me, 41296, true);
|
|
||||||
DoCastVictim(SPELL_SABER_LASH, true);
|
|
||||||
//me->RemoveAurasDueToSpell(41296);
|
|
||||||
SaberlashTimer = 30000;
|
|
||||||
}
|
|
||||||
else SaberlashTimer -= diff;
|
|
||||||
|
|
||||||
if (FrenzyTimer <= diff)
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_FRENZY);
|
|
||||||
FrenzyTimer = urand(10000, 15000);
|
|
||||||
}
|
|
||||||
else FrenzyTimer -= diff;
|
|
||||||
|
|
||||||
if (Phase == PHASE_LYNX)
|
|
||||||
{
|
|
||||||
if (CheckTimer <= diff)
|
|
||||||
{
|
|
||||||
if (HealthBelowPct(25 * (3 - TransformCount)))
|
|
||||||
EnterPhase(PHASE_SPLIT);
|
|
||||||
CheckTimer = 1000;
|
|
||||||
}
|
|
||||||
else CheckTimer -= diff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE)
|
|
||||||
{
|
|
||||||
if (TotemTimer <= diff)
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_SUMMON_TOTEM);
|
|
||||||
TotemTimer = 20000;
|
|
||||||
}
|
|
||||||
else TotemTimer -= diff;
|
|
||||||
|
|
||||||
if (ShockTimer <= diff)
|
|
||||||
{
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
|
||||||
{
|
|
||||||
if (target->IsNonMeleeSpellCast(false))
|
|
||||||
DoCast(target, SPELL_EARTHSHOCK);
|
|
||||||
else
|
|
||||||
DoCast(target, SPELL_FLAMESHOCK);
|
|
||||||
ShockTimer = urand(10000, 15000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else ShockTimer -= diff;
|
|
||||||
|
|
||||||
if (Phase == PHASE_HUMAN)
|
|
||||||
{
|
|
||||||
if (CheckTimer <= diff)
|
|
||||||
{
|
|
||||||
if (!HealthAbovePct(20) /*HealthBelowPct(10)*/)
|
|
||||||
EnterPhase(PHASE_MERGE);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
|
|
||||||
if (Lynx && !Lynx->HealthAbovePct(20) /*Lynx->HealthBelowPct(10)*/)
|
|
||||||
EnterPhase(PHASE_MERGE);
|
|
||||||
}
|
|
||||||
CheckTimer = 1000;
|
|
||||||
}
|
|
||||||
else CheckTimer -= diff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Phase == PHASE_MERGE)
|
|
||||||
{
|
|
||||||
if (CheckTimer <= diff)
|
|
||||||
{
|
|
||||||
Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
|
|
||||||
if (Lynx)
|
|
||||||
{
|
|
||||||
Lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
|
||||||
me->GetMotionMaster()->MoveFollow(Lynx, 0, 0);
|
|
||||||
if (me->IsWithinDistInMap(Lynx, 6.0f))
|
|
||||||
{
|
|
||||||
if (TransformCount < 3)
|
|
||||||
EnterPhase(PHASE_LYNX);
|
|
||||||
else
|
|
||||||
EnterPhase(PHASE_ENRAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CheckTimer = 1000;
|
|
||||||
}
|
|
||||||
else CheckTimer -= diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KilledUnit(Unit* victim) override
|
void KilledUnit(Unit* victim) override
|
||||||
{
|
{
|
||||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
BossAI::KilledUnit(victim);
|
||||||
return;
|
if (victim->IsPlayer())
|
||||||
|
{
|
||||||
Talk(SAY_KILL);
|
Talk(SAY_KILL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustDied(Unit* /*killer*/) override
|
void JustDied(Unit* killer) override
|
||||||
{
|
{
|
||||||
instance->SetData(DATA_HALAZZIEVENT, DONE);
|
BossAI::JustDied(killer);
|
||||||
Talk(SAY_DEATH);
|
Talk(SAY_DEATH);
|
||||||
}
|
}
|
||||||
};
|
private:
|
||||||
|
uint32 _lynxFormHealth;
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
uint32 _humanFormHealth;
|
||||||
{
|
uint32 _healthPortion;
|
||||||
return GetZulAmanAI<boss_halazziAI>(creature);
|
uint8 _transformCount;
|
||||||
}
|
uint32 _healthCheckPercentage;
|
||||||
|
PhaseHalazzi _phase;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Spirits Lynx AI
|
// Spirits Lynx AI
|
||||||
class npc_halazzi_lynx : public CreatureScript
|
struct npc_halazzi_lynx : public ScriptedAI
|
||||||
{
|
{
|
||||||
public:
|
npc_halazzi_lynx(Creature* creature) : ScriptedAI(creature) { }
|
||||||
npc_halazzi_lynx() : CreatureScript("npc_halazzi_lynx") { }
|
|
||||||
|
|
||||||
struct npc_halazzi_lynxAI : public ScriptedAI
|
|
||||||
{
|
|
||||||
npc_halazzi_lynxAI(Creature* creature) : ScriptedAI(creature) { }
|
|
||||||
|
|
||||||
uint32 FrenzyTimer;
|
|
||||||
uint32 shredder_timer;
|
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
|
scheduler.CancelAll();
|
||||||
shredder_timer = 4000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||||
{
|
{
|
||||||
if (damage >= me->GetHealth())
|
if (damage >= me->GetHealth())
|
||||||
|
{
|
||||||
damage = 0;
|
damage = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AttackStart(Unit* who) override
|
void AttackStart(Unit* who) override
|
||||||
{
|
{
|
||||||
if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
|
if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
|
||||||
|
{
|
||||||
ScriptedAI::AttackStart(who);
|
ScriptedAI::AttackStart(who);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void JustEngagedWith(Unit* /*who*/) override {/*DoZoneInCombat();*/ }
|
void JustEngagedWith(Unit* who) override
|
||||||
|
{
|
||||||
|
ScriptedAI::JustEngagedWith(who);
|
||||||
|
|
||||||
|
ScheduleTimedEvent(30s, 50s, [&]
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_LYNX_FRENZY);
|
||||||
|
}, 30s, 50s);
|
||||||
|
ScheduleTimedEvent(4s, [&]{
|
||||||
|
DoCastVictim(SPELL_SHRED_ARMOR);
|
||||||
|
}, 4s);
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (FrenzyTimer <= diff)
|
|
||||||
{
|
|
||||||
DoCast(me, SPELL_LYNX_FRENZY);
|
|
||||||
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
|
|
||||||
}
|
}
|
||||||
else FrenzyTimer -= diff;
|
|
||||||
|
|
||||||
if (shredder_timer <= diff)
|
scheduler.Update(diff);
|
||||||
{
|
|
||||||
DoCastVictim(SPELL_SHRED_ARMOR);
|
|
||||||
shredder_timer = 4000;
|
|
||||||
}
|
|
||||||
else shredder_timer -= diff;
|
|
||||||
|
|
||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetZulAmanAI<npc_halazzi_lynxAI>(creature);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void AddSC_boss_halazzi()
|
void AddSC_boss_halazzi()
|
||||||
{
|
{
|
||||||
new boss_halazzi();
|
RegisterZulAmanCreatureAI(boss_halazzi);
|
||||||
new npc_halazzi_lynx();
|
RegisterZulAmanCreatureAI(npc_halazzi_lynx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -447,9 +447,9 @@ public:
|
|||||||
PlayerAbility_Timer = urand(8000, 10000);
|
PlayerAbility_Timer = urand(8000, 10000);
|
||||||
PlayerClass = target->getClass() - 1;
|
PlayerClass = target->getClass() - 1;
|
||||||
|
|
||||||
if (PlayerClass == CLASS_DRUID - 1)
|
if (target->IsClass(CLASS_DRUID))
|
||||||
PlayerClass = CLASS_DRUID;
|
PlayerClass = CLASS_DRUID;
|
||||||
else if (PlayerClass == CLASS_PRIEST - 1 && target->HasSpell(15473))
|
else if (target->IsClass(CLASS_PRIEST) && target->HasSpell(15473))
|
||||||
PlayerClass = CLASS_PRIEST; // shadow priest
|
PlayerClass = CLASS_PRIEST; // shadow priest
|
||||||
|
|
||||||
SiphonSoul_Timer = 99999; // buff lasts 30 sec
|
SiphonSoul_Timer = 99999; // buff lasts 30 sec
|
||||||
|
|||||||
@@ -55,6 +55,17 @@ static SHostageInfo HostageInfo[] =
|
|||||||
|
|
||||||
Position const HarrisonJonesLoc = {120.687f, 1674.0f, 42.0217f, 1.59044f};
|
Position const HarrisonJonesLoc = {120.687f, 1674.0f, 42.0217f, 1.59044f};
|
||||||
|
|
||||||
|
ObjectData const creatureData[] =
|
||||||
|
{
|
||||||
|
{ NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
ObjectData const gameObjectData[] =
|
||||||
|
{
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
class instance_zulaman : public InstanceMapScript
|
class instance_zulaman : public InstanceMapScript
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -92,6 +103,7 @@ public:
|
|||||||
void Initialize() override
|
void Initialize() override
|
||||||
{
|
{
|
||||||
SetHeaders(DataHeader);
|
SetHeaders(DataHeader);
|
||||||
|
LoadObjectData(creatureData, gameObjectData);
|
||||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||||
|
|
||||||
QuestTimer = 0;
|
QuestTimer = 0;
|
||||||
@@ -135,6 +147,7 @@ public:
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
InstanceScript::OnCreatureCreate(creature);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnGameObjectCreate(GameObject* go) override
|
void OnGameObjectCreate(GameObject* go) override
|
||||||
|
|||||||
@@ -32,9 +32,10 @@ enum DataTypes
|
|||||||
DATA_HALAZZIEVENT = 4,
|
DATA_HALAZZIEVENT = 4,
|
||||||
DATA_HEXLORDEVENT = 5,
|
DATA_HEXLORDEVENT = 5,
|
||||||
DATA_ZULJINEVENT = 6,
|
DATA_ZULJINEVENT = 6,
|
||||||
DATA_CHESTLOOTED = 7,
|
DATA_SPIRIT_LYNX = 7,
|
||||||
TYPE_RAND_VENDOR_1 = 8,
|
DATA_CHESTLOOTED = 8,
|
||||||
TYPE_RAND_VENDOR_2 = 9
|
TYPE_RAND_VENDOR_1 = 9,
|
||||||
|
TYPE_RAND_VENDOR_2 = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CreatureIds
|
enum CreatureIds
|
||||||
@@ -44,7 +45,8 @@ enum CreatureIds
|
|||||||
NPC_ZULJIN = 23863,
|
NPC_ZULJIN = 23863,
|
||||||
NPC_HEXLORD = 24239,
|
NPC_HEXLORD = 24239,
|
||||||
NPC_HALAZZI = 23577,
|
NPC_HALAZZI = 23577,
|
||||||
NPC_NALORAKK = 23576
|
NPC_NALORAKK = 23576,
|
||||||
|
NPC_SPIRIT_LYNX = 24143
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GameobjectIds
|
enum GameobjectIds
|
||||||
@@ -68,4 +70,6 @@ inline AI* GetZulAmanAI(T* obj)
|
|||||||
return GetInstanceAI<AI>(obj, ZulAmanScriptName);
|
return GetInstanceAI<AI>(obj, ZulAmanScriptName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RegisterZulAmanCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetZulAmanAI)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ enum RizzleSprysprocketData
|
|||||||
SAY_RIZZLE_START = 0,
|
SAY_RIZZLE_START = 0,
|
||||||
SAY_RIZZLE_GRENADE = 1,
|
SAY_RIZZLE_GRENADE = 1,
|
||||||
SAY_RIZZLE_FINAL = 2,
|
SAY_RIZZLE_FINAL = 2,
|
||||||
MSG_ESCAPE_NOTICE = 3
|
MSG_ESCAPE_NOTICE = 3,
|
||||||
};
|
GOSSIP_GET_MOONSTONE = 21893
|
||||||
|
|
||||||
#define GOSSIP_GET_MOONSTONE "Hand over the Southfury moonstone and I'll let you go."
|
};
|
||||||
|
|
||||||
Position const WPs[58] =
|
Position const WPs[58] =
|
||||||
{
|
{
|
||||||
@@ -295,7 +295,7 @@ public:
|
|||||||
if (player->GetQuestStatus(QUEST_CHASING_THE_MOONSTONE) != QUEST_STATUS_INCOMPLETE)
|
if (player->GetQuestStatus(QUEST_CHASING_THE_MOONSTONE) != QUEST_STATUS_INCOMPLETE)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_GET_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
AddGossipItemFor(player, GOSSIP_GET_MOONSTONE, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||||
SendGossipMenuFor(player, 10811, creature->GetGUID());
|
SendGossipMenuFor(player, 10811, creature->GetGUID());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public:
|
|||||||
{
|
{
|
||||||
case GOSSIP_ACTION_INFO_DEF + 1:
|
case GOSSIP_ACTION_INFO_DEF + 1:
|
||||||
CloseGossipMenuFor(player);
|
CloseGossipMenuFor(player);
|
||||||
if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_HORDE)
|
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI) && player->GetTeamId() == TEAM_HORDE)
|
||||||
player->ActivateTaxiPathTo(TAXI_PATH_ID_HORDE);
|
player->ActivateTaxiPathTo(TAXI_PATH_ID_HORDE);
|
||||||
break;
|
break;
|
||||||
case GOSSIP_ACTION_INFO_DEF + 2:
|
case GOSSIP_ACTION_INFO_DEF + 2:
|
||||||
@@ -80,30 +80,43 @@ public:
|
|||||||
|
|
||||||
bool OnGossipHello(Player* player, Creature* creature) override
|
bool OnGossipHello(Player* player, Creature* creature) override
|
||||||
{
|
{
|
||||||
if (player->getClass() != CLASS_DRUID)
|
if (player->GetTeamId() != TEAM_HORDE)
|
||||||
{
|
{
|
||||||
SendGossipMenuFor(player, 4916, creature->GetGUID());
|
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_QUEST) && player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
|
||||||
}
|
|
||||||
else if (player->GetTeamId() != TEAM_HORDE)
|
|
||||||
{
|
|
||||||
if (player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
|
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, 4042, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
AddGossipItemFor(player, 4042, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player->IsClass(CLASS_DRUID))
|
||||||
|
{
|
||||||
SendGossipMenuFor(player, 4917, creature->GetGUID());
|
SendGossipMenuFor(player, 4917, creature->GetGUID());
|
||||||
}
|
}
|
||||||
else if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_HORDE)
|
else
|
||||||
|
{
|
||||||
|
SendGossipMenuFor(player, 4916, creature->GetGUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (player->GetTeamId() == TEAM_HORDE)
|
||||||
|
{
|
||||||
|
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI))
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, 4042, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
AddGossipItemFor(player, 4042, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
|
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_QUEST) && player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, 4042, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
AddGossipItemFor(player, 4042, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player->IsClass(CLASS_DRUID))
|
||||||
|
{
|
||||||
SendGossipMenuFor(player, 4918, creature->GetGUID());
|
SendGossipMenuFor(player, 4918, creature->GetGUID());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendGossipMenuFor(player, 4916, creature->GetGUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -176,7 +189,7 @@ public:
|
|||||||
{
|
{
|
||||||
case GOSSIP_ACTION_INFO_DEF + 1:
|
case GOSSIP_ACTION_INFO_DEF + 1:
|
||||||
CloseGossipMenuFor(player);
|
CloseGossipMenuFor(player);
|
||||||
if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_ALLIANCE)
|
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI) && player->GetTeamId() == TEAM_ALLIANCE)
|
||||||
player->ActivateTaxiPathTo(TAXI_PATH_ID_ALLY);
|
player->ActivateTaxiPathTo(TAXI_PATH_ID_ALLY);
|
||||||
break;
|
break;
|
||||||
case GOSSIP_ACTION_INFO_DEF + 2:
|
case GOSSIP_ACTION_INFO_DEF + 2:
|
||||||
@@ -191,30 +204,42 @@ public:
|
|||||||
|
|
||||||
bool OnGossipHello(Player* player, Creature* creature) override
|
bool OnGossipHello(Player* player, Creature* creature) override
|
||||||
{
|
{
|
||||||
if (player->getClass() != CLASS_DRUID)
|
if (player->GetTeamId() != TEAM_ALLIANCE)
|
||||||
{
|
{
|
||||||
SendGossipMenuFor(player, 4913, creature->GetGUID());
|
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_QUEST) && player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
|
||||||
}
|
|
||||||
else if (player->GetTeamId() != TEAM_ALLIANCE)
|
|
||||||
{
|
|
||||||
if (player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
|
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, 4041, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
AddGossipItemFor(player, 4041, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
|
||||||
}
|
}
|
||||||
|
if (player->IsClass(CLASS_DRUID))
|
||||||
|
{
|
||||||
SendGossipMenuFor(player, 4915, creature->GetGUID());
|
SendGossipMenuFor(player, 4915, creature->GetGUID());
|
||||||
}
|
}
|
||||||
else if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_ALLIANCE)
|
else
|
||||||
|
{
|
||||||
|
SendGossipMenuFor(player, 4913, creature->GetGUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (player->GetTeamId() == TEAM_ALLIANCE)
|
||||||
|
{
|
||||||
|
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI))
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, 4041, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
AddGossipItemFor(player, 4041, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
|
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_QUEST) && player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
|
||||||
{
|
{
|
||||||
AddGossipItemFor(player, 4041, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
AddGossipItemFor(player, 4041, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player->IsClass(CLASS_DRUID))
|
||||||
|
{
|
||||||
SendGossipMenuFor(player, 4914, creature->GetGUID());
|
SendGossipMenuFor(player, 4914, creature->GetGUID());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendGossipMenuFor(player, 4913, creature->GetGUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -853,12 +853,12 @@ public:
|
|||||||
{
|
{
|
||||||
if (p->getPowerType() != POWER_MANA)
|
if (p->getPowerType() != POWER_MANA)
|
||||||
return true;
|
return true;
|
||||||
if (p->getClass() == CLASS_HUNTER)
|
if (p->IsClass(CLASS_HUNTER))
|
||||||
return true;
|
return true;
|
||||||
uint8 maxIndex = p->GetMostPointsTalentTree();
|
uint8 maxIndex = p->GetMostPointsTalentTree();
|
||||||
if ((p->getClass() == CLASS_PALADIN && maxIndex >= 1) || (p->getClass() == CLASS_SHAMAN && maxIndex == 1) || (p->getClass() == CLASS_DRUID && maxIndex == 1))
|
if ((p->IsClass(CLASS_PALADIN) && maxIndex >= 1) || (p->IsClass(CLASS_SHAMAN) && maxIndex == 1) || (p->IsClass(CLASS_DRUID) && maxIndex == 1))
|
||||||
return true;
|
return true;
|
||||||
if (_removeHealers == ((p->getClass() == CLASS_DRUID && maxIndex == 2) || (p->getClass() == CLASS_PALADIN && maxIndex == 0) || (p->getClass() == CLASS_PRIEST && maxIndex <= 1) || (p->getClass() == CLASS_SHAMAN && maxIndex == 2)))
|
if (_removeHealers == ((p->IsClass(CLASS_DRUID) && maxIndex == 2) || (p->IsClass(CLASS_PALADIN) && maxIndex == 0) || (p->IsClass(CLASS_PRIEST) && maxIndex <= 1) || (p->IsClass(CLASS_SHAMAN) && maxIndex == 2)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -2856,8 +2856,7 @@ public:
|
|||||||
{
|
{
|
||||||
c->AI()->AttackStart(target);
|
c->AI()->AttackStart(target);
|
||||||
DoZoneInCombat(c);
|
DoZoneInCombat(c);
|
||||||
uint8 Class = target->getClass();
|
if (!target->IsClass(CLASS_DRUID))
|
||||||
if (Class != CLASS_DRUID)
|
|
||||||
if (Player* p = target->ToPlayer())
|
if (Player* p = target->ToPlayer())
|
||||||
{
|
{
|
||||||
if (Item* i = p->GetWeaponForAttack(BASE_ATTACK))
|
if (Item* i = p->GetWeaponForAttack(BASE_ATTACK))
|
||||||
@@ -2869,7 +2868,7 @@ public:
|
|||||||
|
|
||||||
target->CastSpell(c, 60352, true); // Mirror Image, clone visual appearance
|
target->CastSpell(c, 60352, true); // Mirror Image, clone visual appearance
|
||||||
}
|
}
|
||||||
c->AI()->DoAction(Class);
|
c->AI()->DoAction(target->getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ enum Spells
|
|||||||
SPELL_SUMMON_SPOREBAT2 = 38490,
|
SPELL_SUMMON_SPOREBAT2 = 38490,
|
||||||
SPELL_SUMMON_SPOREBAT3 = 38492,
|
SPELL_SUMMON_SPOREBAT3 = 38492,
|
||||||
SPELL_SUMMON_SPOREBAT4 = 38493,
|
SPELL_SUMMON_SPOREBAT4 = 38493,
|
||||||
SPELL_TOXIC_SPORES = 38574
|
SPELL_TOXIC_SPORES = 38574,
|
||||||
|
|
||||||
|
SPELL_POISON_BOLT = 38253
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Misc
|
enum Misc
|
||||||
@@ -91,6 +93,8 @@ struct boss_lady_vashj : public BossAI
|
|||||||
|
|
||||||
ScheduleHealthCheckEvent(70, [&]{
|
ScheduleHealthCheckEvent(70, [&]{
|
||||||
Talk(SAY_PHASE2);
|
Talk(SAY_PHASE2);
|
||||||
|
scheduler.CancelAll();
|
||||||
|
me->CastStop();
|
||||||
me->SetReactState(REACT_PASSIVE);
|
me->SetReactState(REACT_PASSIVE);
|
||||||
me->GetMotionMaster()->MovePoint(POINT_HOME, me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY(), me->GetHomePosition().GetPositionZ(), true, true);
|
me->GetMotionMaster()->MovePoint(POINT_HOME, me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY(), me->GetHomePosition().GetPositionZ(), true, true);
|
||||||
});
|
});
|
||||||
@@ -178,7 +182,6 @@ struct boss_lady_vashj : public BossAI
|
|||||||
me->AddUnitState(UNIT_STATE_ROOT);
|
me->AddUnitState(UNIT_STATE_ROOT);
|
||||||
me->SetFacingTo(me->GetHomePosition().GetOrientation());
|
me->SetFacingTo(me->GetHomePosition().GetOrientation());
|
||||||
instance->SetData(DATA_ACTIVATE_SHIELD, 0);
|
instance->SetData(DATA_ACTIVATE_SHIELD, 0);
|
||||||
scheduler.CancelAll();
|
|
||||||
scheduler.Schedule(2400ms, [this](TaskContext context)
|
scheduler.Schedule(2400ms, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||||
@@ -271,6 +274,42 @@ private:
|
|||||||
std::chrono::seconds _batTimer;
|
std::chrono::seconds _batTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct npc_tainted_elemental : public ScriptedAI
|
||||||
|
{
|
||||||
|
npc_tainted_elemental(Creature* creature) : ScriptedAI(creature) { }
|
||||||
|
|
||||||
|
void Reset() override
|
||||||
|
{
|
||||||
|
scheduler.CancelAll();
|
||||||
|
me->SetInCombatWithZone();
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||||
|
{
|
||||||
|
me->AddThreat(target, 1000.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JustEngagedWith(Unit* /*who*/) override
|
||||||
|
{
|
||||||
|
scheduler.Schedule(100ms, 500ms, [this](TaskContext context)
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_POISON_BOLT);
|
||||||
|
context.Repeat(2350ms, 2650ms);
|
||||||
|
}).Schedule(15s, [this](TaskContext)
|
||||||
|
{
|
||||||
|
me->DespawnOrUnsummon();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAI(uint32 diff) override
|
||||||
|
{
|
||||||
|
if (!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
scheduler.Update(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class spell_lady_vashj_magic_barrier : public AuraScript
|
class spell_lady_vashj_magic_barrier : public AuraScript
|
||||||
{
|
{
|
||||||
PrepareAuraScript(spell_lady_vashj_magic_barrier);
|
PrepareAuraScript(spell_lady_vashj_magic_barrier);
|
||||||
@@ -410,6 +449,7 @@ class spell_lady_vashj_summons : public SpellScript
|
|||||||
void AddSC_boss_lady_vashj()
|
void AddSC_boss_lady_vashj()
|
||||||
{
|
{
|
||||||
RegisterSerpentShrineAI(boss_lady_vashj);
|
RegisterSerpentShrineAI(boss_lady_vashj);
|
||||||
|
RegisterSerpentShrineAI(npc_tainted_elemental);
|
||||||
RegisterSpellScript(spell_lady_vashj_magic_barrier);
|
RegisterSpellScript(spell_lady_vashj_magic_barrier);
|
||||||
RegisterSpellScript(spell_lady_vashj_remove_tainted_cores);
|
RegisterSpellScript(spell_lady_vashj_remove_tainted_cores);
|
||||||
RegisterSpellScript(spell_lady_vashj_summon_sporebat);
|
RegisterSpellScript(spell_lady_vashj_summon_sporebat);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ enum Spells
|
|||||||
SPELL_FLAME_QUILLS = 34229,
|
SPELL_FLAME_QUILLS = 34229,
|
||||||
SPELL_QUILL_MISSILE_1 = 34269, // 21
|
SPELL_QUILL_MISSILE_1 = 34269, // 21
|
||||||
SPELL_QUILL_MISSILE_2 = 34314, // 3
|
SPELL_QUILL_MISSILE_2 = 34314, // 3
|
||||||
|
SPELL_CLEAR_ALL_DEBUFFS = 34098,
|
||||||
SPELL_FLAME_BUFFET = 34121,
|
SPELL_FLAME_BUFFET = 34121,
|
||||||
SPELL_EMBER_BLAST = 34341,
|
SPELL_EMBER_BLAST = 34341,
|
||||||
SPELL_REBIRTH_PHASE2 = 34342,
|
SPELL_REBIRTH_PHASE2 = 34342,
|
||||||
@@ -38,15 +39,18 @@ enum Spells
|
|||||||
SPELL_DIVE_BOMB = 35181
|
SPELL_DIVE_BOMB = 35181
|
||||||
};
|
};
|
||||||
|
|
||||||
const Position alarPoints[7] =
|
// @todo: Alar doesnt seem to move to waypoints but instead to the triggers in p1
|
||||||
|
const Position alarPoints[9] =
|
||||||
{
|
{
|
||||||
{340.15f, 58.65f, 17.71f, 4.60f},
|
{335.638f, 59.4879f, 17.9319f, 4.60f}, //first platform
|
||||||
{388.09f, 31.54f, 20.18f, 1.61f},
|
{388.751007f, 31.731199f, 20.263599f, 1.61f},
|
||||||
{388.18f, -32.85f, 20.18f, 0.52f},
|
{388.790985f, -33.105900f, 20.263599f, 0.52f},
|
||||||
{340.29f, -60.19f, 17.72f, 5.71f},
|
{332.722992f, -61.159f, 17.979099f, 5.71f},
|
||||||
{332.0f, 0.01f, 43.0f, 0.0f},
|
{258.959015f, -38.687099f, 20.262899f, 5.21f},
|
||||||
{331.0f, 0.01f, -2.38f, 0.0f},
|
{259.2277997, 35.879002f, 20.263f, 4.81f}, //sixth platform
|
||||||
{332.0f, 0.01f, 43.0f, 0.0f}
|
{332.0f, 0.01f, 43.0f, 0.0f}, //quill
|
||||||
|
{331.0f, 0.01f, -2.38f, 0.0f}, //middle (p2)
|
||||||
|
{332.0f, 0.01f, 43.0f, 0.0f} // dive
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Misc
|
enum Misc
|
||||||
@@ -56,26 +60,28 @@ enum Misc
|
|||||||
NPC_FLAME_PATCH = 20602,
|
NPC_FLAME_PATCH = 20602,
|
||||||
|
|
||||||
POINT_PLATFORM = 0,
|
POINT_PLATFORM = 0,
|
||||||
POINT_QUILL = 4,
|
POINT_QUILL = 6,
|
||||||
POINT_MIDDLE = 5,
|
POINT_MIDDLE = 7,
|
||||||
POINT_DIVE = 6,
|
POINT_DIVE = 8,
|
||||||
|
|
||||||
EVENT_SWITCH_PLATFORM = 1,
|
EVENT_RELOCATE_MIDDLE = 1,
|
||||||
EVENT_START_QUILLS = 2,
|
EVENT_REBIRTH = 2,
|
||||||
EVENT_RELOCATE_MIDDLE = 3,
|
EVENT_SPELL_BERSERK = 3,
|
||||||
EVENT_REBIRTH = 4,
|
|
||||||
EVENT_SPELL_MELT_ARMOR = 5,
|
|
||||||
EVENT_SPELL_FLAME_PATCH = 6,
|
|
||||||
EVENT_SPELL_CHARGE = 7,
|
|
||||||
EVENT_SPELL_DIVE_BOMB = 8,
|
|
||||||
EVENT_START_DIVE = 9,
|
|
||||||
EVENT_CAST_DIVE_BOMB = 10,
|
|
||||||
EVENT_SUMMON_DIVE_PHOENIX = 11,
|
|
||||||
EVENT_REBIRTH_DIVE = 12,
|
|
||||||
EVENT_SPELL_BERSERK = 13,
|
|
||||||
|
|
||||||
EVENT_MOVE_TO_PHASE_2 = 20,
|
EVENT_MOVE_TO_PHASE_2 = 4,
|
||||||
EVENT_FINISH_DIVE = 21
|
EVENT_FINISH_DIVE = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PlatformMoveDirections
|
||||||
|
{
|
||||||
|
DIRECTION_ANTI_CLOCKWISE = 0,
|
||||||
|
DIRECTION_CLOCKWISE = 1,
|
||||||
|
DIRECTION_ACROSS = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GroupAlar
|
||||||
|
{
|
||||||
|
GROUP_FLAME_BUFFET = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
// Xinef: Ruse of the Ashtongue (10946)
|
// Xinef: Ruse of the Ashtongue (10946)
|
||||||
@@ -85,89 +91,199 @@ enum qruseoftheAshtongue
|
|||||||
QUEST_RUSE_OF_THE_ASHTONGUE = 10946,
|
QUEST_RUSE_OF_THE_ASHTONGUE = 10946,
|
||||||
};
|
};
|
||||||
|
|
||||||
class boss_alar : public CreatureScript
|
struct boss_alar : public BossAI
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
boss_alar() : CreatureScript("boss_alar") { }
|
|
||||||
|
|
||||||
struct boss_alarAI : public BossAI
|
boss_alar(Creature* creature) : BossAI(creature, DATA_ALAR)
|
||||||
{
|
{
|
||||||
boss_alarAI(Creature* creature) : BossAI(creature, DATA_ALAR)
|
|
||||||
{
|
|
||||||
startPath = true;
|
|
||||||
SetCombatMovement(false);
|
SetCombatMovement(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 platform;
|
|
||||||
uint8 noQuillTimes;
|
|
||||||
bool startPath;
|
|
||||||
|
|
||||||
void JustReachedHome() override
|
void JustReachedHome() override
|
||||||
{
|
{
|
||||||
BossAI::JustReachedHome();
|
BossAI::JustReachedHome();
|
||||||
startPath = true;
|
if (me->IsEngaged())
|
||||||
|
{
|
||||||
|
ConstructWaypointsAndMove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
BossAI::Reset();
|
BossAI::Reset();
|
||||||
platform = 0;
|
_canAttackCooldown = true;
|
||||||
noQuillTimes = 0;
|
_baseAttackOverride = false;
|
||||||
|
_spawnPhoenixes = false;
|
||||||
|
_platform = 0;
|
||||||
|
_platformRoll = 0;
|
||||||
|
_noQuillTimes = 0;
|
||||||
|
_platformMoveRepeatTimer = 16s;
|
||||||
me->SetModelVisible(true);
|
me->SetModelVisible(true);
|
||||||
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FIRE, true);
|
|
||||||
me->SetReactState(REACT_AGGRESSIVE);
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
ConstructWaypointsAndMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustEngagedWith(Unit* who) override
|
void JustEngagedWith(Unit* who) override
|
||||||
{
|
{
|
||||||
BossAI::JustEngagedWith(who);
|
BossAI::JustEngagedWith(who);
|
||||||
events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 0);
|
ScheduleTimedEvent(0s, [&]
|
||||||
|
{
|
||||||
|
if (roll_chance_i(20 * _noQuillTimes))
|
||||||
|
{
|
||||||
|
_noQuillTimes = 0;
|
||||||
|
_platform = RAND(0, 5);
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_QUILL, alarPoints[POINT_QUILL], false, true);
|
||||||
|
_platformMoveRepeatTimer = 16s;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_noQuillTimes++ > 0)
|
||||||
|
{
|
||||||
|
me->SetOrientation(alarPoints[_platform].GetOrientation());
|
||||||
|
if (_spawnPhoenixes)
|
||||||
|
{
|
||||||
|
SpawnPhoenixes(3, me);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_PLATFORM, alarPoints[_platform], false, true);
|
||||||
|
_platformRoll = RAND(0, 2);
|
||||||
|
switch(_platformRoll)
|
||||||
|
{
|
||||||
|
case DIRECTION_ANTI_CLOCKWISE:
|
||||||
|
_platform = (_platform+5)%6;
|
||||||
|
_spawnPhoenixes = false;
|
||||||
|
break;
|
||||||
|
case DIRECTION_CLOCKWISE:
|
||||||
|
_platform = (_platform+1)%6;
|
||||||
|
_spawnPhoenixes = false;
|
||||||
|
break;
|
||||||
|
case DIRECTION_ACROSS:
|
||||||
|
_platform = (_platform+3)%6;
|
||||||
|
_spawnPhoenixes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_platformMoveRepeatTimer = 30s;
|
||||||
|
}
|
||||||
|
}, _platformMoveRepeatTimer);
|
||||||
|
ScheduleMainSpellAttack(0s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustDied(Unit* killer) override
|
void JustDied(Unit* killer) override
|
||||||
{
|
{
|
||||||
me->SetModelVisible(true);
|
|
||||||
BossAI::JustDied(killer);
|
BossAI::JustDied(killer);
|
||||||
|
me->SetModelVisible(true);
|
||||||
|
|
||||||
// Xinef: Ruse of the Ashtongue (10946)
|
if (Map* map = me->GetMap())
|
||||||
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
|
{
|
||||||
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
|
map->DoForAllPlayers([&](Player* player)
|
||||||
{
|
{
|
||||||
Player* player = itr->GetSource();
|
|
||||||
if (player->GetQuestStatus(QUEST_RUSE_OF_THE_ASHTONGUE) == QUEST_STATUS_INCOMPLETE)
|
if (player->GetQuestStatus(QUEST_RUSE_OF_THE_ASHTONGUE) == QUEST_STATUS_INCOMPLETE)
|
||||||
|
{
|
||||||
if (player->HasAura(SPELL_ASHTONGUE_RUSE))
|
if (player->HasAura(SPELL_ASHTONGUE_RUSE))
|
||||||
|
{
|
||||||
player->AreaExploredOrEventHappens(QUEST_RUSE_OF_THE_ASHTONGUE);
|
player->AreaExploredOrEventHappens(QUEST_RUSE_OF_THE_ASHTONGUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
void JustSummoned(Creature* summon) override
|
}
|
||||||
{
|
|
||||||
summons.Summon(summon);
|
|
||||||
if (summon->GetEntry() == NPC_EMBER_OF_ALAR)
|
|
||||||
summon->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FIRE, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||||
|
|
||||||
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||||
{
|
{
|
||||||
if (damage >= me->GetHealth() && platform < POINT_MIDDLE)
|
if (damage >= me->GetHealth() && _platform < POINT_MIDDLE)
|
||||||
{
|
{
|
||||||
damage = 0;
|
damage = 0;
|
||||||
if (events.GetNextEventTime(EVENT_REBIRTH) == 0)
|
|
||||||
{
|
|
||||||
me->InterruptNonMeleeSpells(false);
|
me->InterruptNonMeleeSpells(false);
|
||||||
me->SetHealth(me->GetMaxHealth());
|
me->SetHealth(me->GetMaxHealth());
|
||||||
me->SetReactState(REACT_PASSIVE);
|
me->SetReactState(REACT_PASSIVE);
|
||||||
me->CastSpell(me, SPELL_EMBER_BLAST, true);
|
DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS);
|
||||||
|
DoCastSelf(SPELL_EMBER_BLAST, true);
|
||||||
|
scheduler.CancelAll();
|
||||||
|
ScheduleUniqueTimedEvent(8s, [&]{
|
||||||
|
me->SetPosition(alarPoints[POINT_MIDDLE]);
|
||||||
|
}, EVENT_RELOCATE_MIDDLE);
|
||||||
|
ScheduleUniqueTimedEvent(12s, [&]
|
||||||
|
{
|
||||||
|
me->RemoveAurasDueToSpell(SPELL_EMBER_BLAST);
|
||||||
|
DoCastSelf(SPELL_REBIRTH_PHASE2);
|
||||||
|
}, EVENT_MOVE_TO_PHASE_2);
|
||||||
|
ScheduleUniqueTimedEvent(16001ms, [&]{
|
||||||
|
me->SetReactState(REACT_AGGRESSIVE);
|
||||||
|
_platform = POINT_MIDDLE;
|
||||||
|
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||||
|
ScheduleAbilities();
|
||||||
|
}, EVENT_REBIRTH);
|
||||||
|
|
||||||
me->setAttackTimer(BASE_ATTACK, 16000);
|
|
||||||
events.Reset();
|
|
||||||
events.ScheduleEvent(EVENT_RELOCATE_MIDDLE, 8000);
|
|
||||||
events.ScheduleEvent(EVENT_MOVE_TO_PHASE_2, 12000);
|
|
||||||
events.ScheduleEvent(EVENT_REBIRTH, 16001);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScheduleAbilities()
|
||||||
|
{
|
||||||
|
ScheduleTimedEvent(57s, [&]
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_MELT_ARMOR);
|
||||||
|
}, 60s);
|
||||||
|
ScheduleTimedEvent(10s, [&]
|
||||||
|
{
|
||||||
|
DoCastRandomTarget(SPELL_CHARGE, 0, 50.0f);
|
||||||
|
}, 30s);
|
||||||
|
ScheduleTimedEvent(20s, [&]
|
||||||
|
{
|
||||||
|
// find spell from sniffs?
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
||||||
|
{
|
||||||
|
me->SummonCreature(NPC_FLAME_PATCH, *target, TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS);
|
||||||
|
}
|
||||||
|
}, 30s);
|
||||||
|
ScheduleTimedEvent(30s, [&]
|
||||||
|
{
|
||||||
|
me->GetMotionMaster()->MovePoint(POINT_DIVE, alarPoints[POINT_DIVE], false, true);
|
||||||
|
scheduler.DelayAll(15s);
|
||||||
|
}, 30s);
|
||||||
|
ScheduleUniqueTimedEvent(10min, [&]
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_BERSERK);
|
||||||
|
}, EVENT_SPELL_BERSERK);
|
||||||
|
ScheduleMainSpellAttack(0s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpawnPhoenixes(uint8 count, Unit* targetToSpawnAt)
|
||||||
|
{
|
||||||
|
if (targetToSpawnAt)
|
||||||
|
{
|
||||||
|
for (uint8 i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
me->SummonCreature(NPC_EMBER_OF_ALAR, *targetToSpawnAt, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoDiveBomb()
|
||||||
|
{
|
||||||
|
scheduler.Schedule(2s, [this](TaskContext)
|
||||||
|
{
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true))
|
||||||
|
{
|
||||||
|
SpawnPhoenixes(2, target);
|
||||||
|
}
|
||||||
|
}).Schedule(6s, [this](TaskContext)
|
||||||
|
{
|
||||||
|
me->SetModelVisible(true);
|
||||||
|
DoCastSelf(SPELL_REBIRTH_DIVE);
|
||||||
|
}).Schedule(10s, [this](TaskContext)
|
||||||
|
{
|
||||||
|
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||||
|
});
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true))
|
||||||
|
{
|
||||||
|
DoCast(target, SPELL_DIVE_BOMB);
|
||||||
|
me->SetPosition(*target);
|
||||||
|
me->StopMovingOnCurrentPos();
|
||||||
|
}
|
||||||
|
me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementInform(uint32 type, uint32 id) override
|
void MovementInform(uint32 type, uint32 id) override
|
||||||
@@ -175,27 +291,51 @@ public:
|
|||||||
if (type != POINT_MOTION_TYPE)
|
if (type != POINT_MOTION_TYPE)
|
||||||
{
|
{
|
||||||
if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized() && !me->IsInCombat())
|
if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized() && !me->IsInCombat())
|
||||||
startPath = true;
|
{
|
||||||
|
ConstructWaypointsAndMove();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == POINT_PLATFORM)
|
switch(id)
|
||||||
me->setAttackTimer(BASE_ATTACK, 1000);
|
|
||||||
else if (id == POINT_QUILL)
|
|
||||||
events.ScheduleEvent(EVENT_START_QUILLS, 1000);
|
|
||||||
else if (id == POINT_DIVE)
|
|
||||||
{
|
{
|
||||||
events.ScheduleEvent(EVENT_START_DIVE, 1000);
|
case POINT_QUILL:
|
||||||
events.ScheduleEvent(EVENT_CAST_DIVE_BOMB, 5000);
|
scheduler.CancelGroup(GROUP_FLAME_BUFFET);
|
||||||
|
scheduler.Schedule(1s, [this](TaskContext)
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_FLAME_QUILLS);
|
||||||
|
});
|
||||||
|
ScheduleMainSpellAttack(13s);
|
||||||
|
break;
|
||||||
|
case POINT_DIVE:
|
||||||
|
scheduler.Schedule(1s, [this](TaskContext)
|
||||||
|
{
|
||||||
|
DoCastSelf(SPELL_DIVE_BOMB_VISUAL);
|
||||||
|
}).Schedule(5s, [this](TaskContext)
|
||||||
|
{
|
||||||
|
DoDiveBomb();
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void ScheduleMainSpellAttack(std::chrono::seconds timer)
|
||||||
{
|
{
|
||||||
if (startPath)
|
scheduler.Schedule(timer, GROUP_FLAME_BUFFET, [this](TaskContext context)
|
||||||
|
{
|
||||||
|
if (!me->IsWithinMeleeRange(me->GetVictim()) && !me->isMoving())
|
||||||
|
{
|
||||||
|
DoCastVictim(SPELL_FLAME_BUFFET);
|
||||||
|
}
|
||||||
|
context.Repeat(2s);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConstructWaypointsAndMove()
|
||||||
{
|
{
|
||||||
me->StopMoving();
|
me->StopMoving();
|
||||||
startPath = false;
|
|
||||||
if (WaypointPath const* i_path = sWaypointMgr->GetPath(me->GetWaypointPath()))
|
if (WaypointPath const* i_path = sWaypointMgr->GetPath(me->GetWaypointPath()))
|
||||||
{
|
{
|
||||||
Movement::PointsArray pathPoints;
|
Movement::PointsArray pathPoints;
|
||||||
@@ -209,155 +349,26 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UpdateVictim())
|
private:
|
||||||
return;
|
bool _canAttackCooldown;
|
||||||
|
bool _baseAttackOverride;
|
||||||
events.Update(diff);
|
bool _spawnPhoenixes;
|
||||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
uint8 _platform;
|
||||||
return;
|
uint8 _platformRoll;
|
||||||
|
uint8 _noQuillTimes;
|
||||||
switch (events.ExecuteEvent())
|
std::chrono::seconds _platformMoveRepeatTimer;
|
||||||
{
|
|
||||||
case EVENT_SWITCH_PLATFORM:
|
|
||||||
if (roll_chance_i(20 * noQuillTimes))
|
|
||||||
{
|
|
||||||
noQuillTimes = 0;
|
|
||||||
platform = RAND(0, 3);
|
|
||||||
me->GetMotionMaster()->MovePoint(POINT_QUILL, alarPoints[POINT_QUILL], false, true);
|
|
||||||
events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 16000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (noQuillTimes++ > 0)
|
|
||||||
{
|
|
||||||
me->SetOrientation(alarPoints[platform].GetOrientation());
|
|
||||||
me->SummonCreature(NPC_EMBER_OF_ALAR, *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
|
|
||||||
}
|
|
||||||
me->GetMotionMaster()->MovePoint(POINT_PLATFORM, alarPoints[platform], false, true);
|
|
||||||
platform = (platform + 1) % 4;
|
|
||||||
events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 30000);
|
|
||||||
}
|
|
||||||
me->setAttackTimer(BASE_ATTACK, 20000);
|
|
||||||
break;
|
|
||||||
case EVENT_START_QUILLS:
|
|
||||||
me->CastSpell(me, SPELL_FLAME_QUILLS, false);
|
|
||||||
break;
|
|
||||||
case EVENT_RELOCATE_MIDDLE:
|
|
||||||
me->SetPosition(alarPoints[POINT_MIDDLE]);
|
|
||||||
break;
|
|
||||||
case EVENT_MOVE_TO_PHASE_2:
|
|
||||||
me->RemoveAurasDueToSpell(SPELL_EMBER_BLAST);
|
|
||||||
me->CastSpell(me, SPELL_REBIRTH_PHASE2, false);
|
|
||||||
break;
|
|
||||||
case EVENT_REBIRTH:
|
|
||||||
me->SetReactState(REACT_AGGRESSIVE);
|
|
||||||
platform = POINT_MIDDLE;
|
|
||||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
|
||||||
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_MELT_ARMOR, 67000);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_CHARGE, 10000);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_FLAME_PATCH, 20000);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_DIVE_BOMB, 30000);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_MELT_ARMOR:
|
|
||||||
me->CastSpell(me->GetVictim(), SPELL_MELT_ARMOR, false);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_MELT_ARMOR, 60000);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_CHARGE:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
|
||||||
me->CastSpell(target, SPELL_CHARGE, false);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_CHARGE, 30000);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_FLAME_PATCH:
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 50.0f, true))
|
|
||||||
me->SummonCreature(NPC_FLAME_PATCH, *target, TEMPSUMMON_TIMED_DESPAWN, 2 * MINUTE * IN_MILLISECONDS);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_FLAME_PATCH, 30000);
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_DIVE_BOMB:
|
|
||||||
me->GetMotionMaster()->MovePoint(POINT_DIVE, alarPoints[POINT_DIVE], false, true);
|
|
||||||
events.ScheduleEvent(EVENT_SPELL_DIVE_BOMB, 30000);
|
|
||||||
events.DelayEvents(15000);
|
|
||||||
me->setAttackTimer(BASE_ATTACK, 20000);
|
|
||||||
break;
|
|
||||||
case EVENT_START_DIVE:
|
|
||||||
me->CastSpell(me, SPELL_DIVE_BOMB_VISUAL, false);
|
|
||||||
break;
|
|
||||||
case EVENT_CAST_DIVE_BOMB:
|
|
||||||
events.ScheduleEvent(EVENT_SUMMON_DIVE_PHOENIX, 2000);
|
|
||||||
events.ScheduleEvent(EVENT_REBIRTH_DIVE, 6000);
|
|
||||||
events.ScheduleEvent(EVENT_FINISH_DIVE, 10000);
|
|
||||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 90.0f, true))
|
|
||||||
{
|
|
||||||
me->CastSpell(target, SPELL_DIVE_BOMB, false);
|
|
||||||
me->SetPosition(*target);
|
|
||||||
me->StopMovingOnCurrentPos();
|
|
||||||
}
|
|
||||||
|
|
||||||
me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL);
|
|
||||||
break;
|
|
||||||
case EVENT_SUMMON_DIVE_PHOENIX:
|
|
||||||
{
|
|
||||||
Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 10.0f, true);
|
|
||||||
me->SummonCreature(NPC_EMBER_OF_ALAR, target ? *target : *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
|
|
||||||
me->SummonCreature(NPC_EMBER_OF_ALAR, target ? *target : *me, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 6000);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVENT_REBIRTH_DIVE:
|
|
||||||
me->SetModelVisible(true);
|
|
||||||
me->CastSpell(me, SPELL_REBIRTH_DIVE, false);
|
|
||||||
break;
|
|
||||||
case EVENT_FINISH_DIVE:
|
|
||||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
|
||||||
break;
|
|
||||||
case EVENT_SPELL_BERSERK:
|
|
||||||
me->CastSpell(me, SPELL_BERSERK, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me->isAttackReady())
|
|
||||||
{
|
|
||||||
if (me->IsWithinMeleeRange(me->GetVictim()))
|
|
||||||
{
|
|
||||||
me->AttackerStateUpdate(me->GetVictim());
|
|
||||||
me->resetAttackTimer();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
me->resetAttackTimer();
|
|
||||||
ThreatContainer::StorageType const& threatList = me->GetThreatMgr().GetThreatList();
|
|
||||||
for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
|
|
||||||
if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()))
|
|
||||||
if (me->IsWithinMeleeRange(unit))
|
|
||||||
{
|
|
||||||
me->AttackerStateUpdate(unit);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
me->CastSpell(me, SPELL_FLAME_BUFFET, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI(Creature* creature) const override
|
|
||||||
{
|
|
||||||
return GetTheEyeAI<boss_alarAI>(creature);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CastQuill : public BasicEvent
|
class CastQuill : public BasicEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CastQuill(Unit* caster, uint32 spellId) : _caster(caster), _spellId(spellId)
|
CastQuill(Unit* caster, uint32 spellId) : _caster(caster), _spellId(spellId){ }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
||||||
{
|
{
|
||||||
_caster->CastSpell(_caster, _spellId, true);
|
_caster->CastSpell(_caster, _spellId, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Unit* _caster;
|
Unit* _caster;
|
||||||
uint32 _spellId;
|
uint32 _spellId;
|
||||||
@@ -496,7 +507,7 @@ public:
|
|||||||
|
|
||||||
void AddSC_boss_alar()
|
void AddSC_boss_alar()
|
||||||
{
|
{
|
||||||
new boss_alar();
|
RegisterTheEyeAI(boss_alar);
|
||||||
new spell_alar_flame_quills();
|
new spell_alar_flame_quills();
|
||||||
new spell_alar_ember_blast();
|
new spell_alar_ember_blast();
|
||||||
new spell_alar_ember_blast_death();
|
new spell_alar_ember_blast_death();
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ struct boss_high_astromancer_solarian : public BossAI
|
|||||||
|
|
||||||
ScheduleHealthCheckEvent(20, [&]{
|
ScheduleHealthCheckEvent(20, [&]{
|
||||||
scheduler.CancelAll();
|
scheduler.CancelAll();
|
||||||
|
me->ResumeChasingVictim();
|
||||||
scheduler.Schedule(3s, [this](TaskContext context)
|
scheduler.Schedule(3s, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
DoCastVictim(SPELL_VOID_BOLT);
|
DoCastVictim(SPELL_VOID_BOLT);
|
||||||
@@ -109,10 +110,21 @@ struct boss_high_astromancer_solarian : public BossAI
|
|||||||
Talk(SAY_AGGRO);
|
Talk(SAY_AGGRO);
|
||||||
BossAI::JustEngagedWith(who);
|
BossAI::JustEngagedWith(who);
|
||||||
me->CallForHelp(105.0f);
|
me->CallForHelp(105.0f);
|
||||||
|
me->GetMotionMaster()->Clear();
|
||||||
|
|
||||||
scheduler.Schedule(3650ms, [this](TaskContext context)
|
scheduler.Schedule(3650ms, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
DoCastRandomTarget(SPELL_ARCANE_MISSILES, 0, 40.0f);
|
me->GetMotionMaster()->Clear();
|
||||||
|
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, true))
|
||||||
|
{
|
||||||
|
DoCast(target, SPELL_ARCANE_MISSILES);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//no targets in required range
|
||||||
|
me->GetMotionMaster()->MoveChase(me->GetVictim(), 30.0f);
|
||||||
|
me->CastStop();
|
||||||
|
}
|
||||||
context.Repeat(800ms, 7300ms);
|
context.Repeat(800ms, 7300ms);
|
||||||
}).Schedule(21800ms, [this](TaskContext context)
|
}).Schedule(21800ms, [this](TaskContext context)
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,21 @@
|
|||||||
#include "SpellScriptLoader.h"
|
#include "SpellScriptLoader.h"
|
||||||
#include "the_eye.h"
|
#include "the_eye.h"
|
||||||
|
|
||||||
|
ObjectData const creatureData[] =
|
||||||
|
{
|
||||||
|
{ NPC_KAELTHAS, DATA_KAELTHAS },
|
||||||
|
{ NPC_THALADRED, DATA_THALADRED },
|
||||||
|
{ NPC_LORD_SANGUINAR, DATA_LORD_SANGUINAR },
|
||||||
|
{ NPC_CAPERNIAN, DATA_CAPERNIAN },
|
||||||
|
{ NPC_TELONICUS, DATA_TELONICUS },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
ObjectData const gameObjectData[] =
|
||||||
|
{
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
class instance_the_eye : public InstanceMapScript
|
class instance_the_eye : public InstanceMapScript
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -30,6 +45,7 @@ public:
|
|||||||
instance_the_eye_InstanceMapScript(Map* map) : InstanceScript(map)
|
instance_the_eye_InstanceMapScript(Map* map) : InstanceScript(map)
|
||||||
{
|
{
|
||||||
SetHeaders(DataHeader);
|
SetHeaders(DataHeader);
|
||||||
|
LoadObjectData(creatureData, gameObjectData);
|
||||||
SetBossNumber(MAX_ENCOUNTER);
|
SetBossNumber(MAX_ENCOUNTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +82,7 @@ public:
|
|||||||
LordSanguinarGUID = creature->GetGUID();
|
LordSanguinarGUID = creature->GetGUID();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
InstanceScript::OnCreatureCreate(creature);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnGameObjectCreate(GameObject* gobject) override
|
void OnGameObjectCreate(GameObject* gobject) override
|
||||||
@@ -98,14 +115,6 @@ public:
|
|||||||
return AlarGUID;
|
return AlarGUID;
|
||||||
case NPC_KAELTHAS:
|
case NPC_KAELTHAS:
|
||||||
return KaelthasGUID;
|
return KaelthasGUID;
|
||||||
case DATA_KAEL_ADVISOR1:
|
|
||||||
return ThaladredTheDarkenerGUID;
|
|
||||||
case DATA_KAEL_ADVISOR2:
|
|
||||||
return LordSanguinarGUID;
|
|
||||||
case DATA_KAEL_ADVISOR3:
|
|
||||||
return GrandAstromancerCapernianGUID;
|
|
||||||
case DATA_KAEL_ADVISOR4:
|
|
||||||
return MasterEngineerTelonicusGUID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ObjectGuid::Empty;
|
return ObjectGuid::Empty;
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ enum EyeData
|
|||||||
DATA_KAELTHAS = 3,
|
DATA_KAELTHAS = 3,
|
||||||
MAX_ENCOUNTER = 4,
|
MAX_ENCOUNTER = 4,
|
||||||
|
|
||||||
DATA_KAEL_ADVISOR1 = 10,
|
DATA_THALADRED = 10,
|
||||||
DATA_KAEL_ADVISOR2 = 11,
|
DATA_LORD_SANGUINAR = 11,
|
||||||
DATA_KAEL_ADVISOR3 = 12,
|
DATA_CAPERNIAN = 12,
|
||||||
DATA_KAEL_ADVISOR4 = 13
|
DATA_TELONICUS = 13
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EyeNPCs
|
enum EyeNPCs
|
||||||
|
|||||||
@@ -1014,7 +1014,7 @@ class spell_dk_blood_boil : public SpellScript
|
|||||||
bool Load() override
|
bool Load() override
|
||||||
{
|
{
|
||||||
_executed = false;
|
_executed = false;
|
||||||
return GetCaster()->GetTypeId() == TYPEID_PLAYER && GetCaster()->getClass() == CLASS_DEATH_KNIGHT;
|
return GetCaster()->GetTypeId() == TYPEID_PLAYER && GetCaster()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleAfterHit()
|
void HandleAfterHit()
|
||||||
@@ -1258,7 +1258,7 @@ class spell_dk_death_gate : public SpellScript
|
|||||||
|
|
||||||
SpellCastResult CheckClass()
|
SpellCastResult CheckClass()
|
||||||
{
|
{
|
||||||
if (GetCaster()->getClass() != CLASS_DEATH_KNIGHT)
|
if (!GetCaster()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||||
{
|
{
|
||||||
SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_BE_DEATH_KNIGHT);
|
SetCustomCastResultMessage(SPELL_CUSTOM_ERROR_MUST_BE_DEATH_KNIGHT);
|
||||||
return SPELL_FAILED_CUSTOM_ERROR;
|
return SPELL_FAILED_CUSTOM_ERROR;
|
||||||
|
|||||||
@@ -446,7 +446,7 @@ class spell_pet_hit_expertise_scalling : public AuraScript
|
|||||||
{
|
{
|
||||||
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
||||||
{
|
{
|
||||||
if (modOwner->getClass() == CLASS_HUNTER)
|
if (modOwner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
|
||||||
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 8.0f);
|
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 8.0f);
|
||||||
else if (modOwner->getPowerType() == POWER_MANA)
|
else if (modOwner->getPowerType() == POWER_MANA)
|
||||||
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 8.0f);
|
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 8.0f);
|
||||||
@@ -459,7 +459,7 @@ class spell_pet_hit_expertise_scalling : public AuraScript
|
|||||||
{
|
{
|
||||||
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
||||||
{
|
{
|
||||||
if (modOwner->getClass() == CLASS_HUNTER)
|
if (modOwner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
|
||||||
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 17.0f);
|
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 17.0f);
|
||||||
else if (modOwner->getPowerType() == POWER_MANA)
|
else if (modOwner->getPowerType() == POWER_MANA)
|
||||||
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 17.0f);
|
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 17.0f);
|
||||||
@@ -472,7 +472,7 @@ class spell_pet_hit_expertise_scalling : public AuraScript
|
|||||||
{
|
{
|
||||||
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
|
||||||
{
|
{
|
||||||
if (modOwner->getClass() == CLASS_HUNTER)
|
if (modOwner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
|
||||||
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 26.0f);
|
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 26.0f);
|
||||||
else if (modOwner->getPowerType() == POWER_MANA)
|
else if (modOwner->getPowerType() == POWER_MANA)
|
||||||
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 26.0f);
|
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 26.0f);
|
||||||
@@ -1673,7 +1673,7 @@ class spell_gen_pet_summoned : public SpellScript
|
|||||||
Player* player = GetCaster()->ToPlayer();
|
Player* player = GetCaster()->ToPlayer();
|
||||||
if (player->GetLastPetNumber() && player->CanResummonPet(player->GetLastPetSpell()))
|
if (player->GetLastPetNumber() && player->CanResummonPet(player->GetLastPetSpell()))
|
||||||
{
|
{
|
||||||
PetType newPetType = (player->getClass() == CLASS_HUNTER) ? HUNTER_PET : SUMMON_PET;
|
PetType newPetType = (player->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET)) ? HUNTER_PET : SUMMON_PET;
|
||||||
Pet* newPet = new Pet(player, newPetType);
|
Pet* newPet = new Pet(player, newPetType);
|
||||||
if (newPet->LoadPetFromDB(player, 0, player->GetLastPetNumber(), true, 100))
|
if (newPet->LoadPetFromDB(player, 0, player->GetLastPetNumber(), true, 100))
|
||||||
{
|
{
|
||||||
@@ -3545,11 +3545,11 @@ class spell_gen_on_tournament_mount : public AuraScript
|
|||||||
case NPC_ARGENT_WARHORSE:
|
case NPC_ARGENT_WARHORSE:
|
||||||
{
|
{
|
||||||
if (player->HasAchieved(ACHIEVEMENT_CHAMPION_ALLIANCE) || player->HasAchieved(ACHIEVEMENT_CHAMPION_HORDE))
|
if (player->HasAchieved(ACHIEVEMENT_CHAMPION_ALLIANCE) || player->HasAchieved(ACHIEVEMENT_CHAMPION_HORDE))
|
||||||
return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_CHAMPION : SPELL_PENNANT_ARGENT_CRUSADE_CHAMPION;
|
return player->IsClass(CLASS_DEATH_KNIGHT) ? SPELL_PENNANT_EBON_BLADE_CHAMPION : SPELL_PENNANT_ARGENT_CRUSADE_CHAMPION;
|
||||||
else if (player->HasAchieved(ACHIEVEMENT_ARGENT_VALOR))
|
else if (player->HasAchieved(ACHIEVEMENT_ARGENT_VALOR))
|
||||||
return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_VALIANT : SPELL_PENNANT_ARGENT_CRUSADE_VALIANT;
|
return player->IsClass(CLASS_DEATH_KNIGHT) ? SPELL_PENNANT_EBON_BLADE_VALIANT : SPELL_PENNANT_ARGENT_CRUSADE_VALIANT;
|
||||||
else
|
else
|
||||||
return player->getClass() == CLASS_DEATH_KNIGHT ? SPELL_PENNANT_EBON_BLADE_ASPIRANT : SPELL_PENNANT_ARGENT_CRUSADE_ASPIRANT;
|
return player->IsClass(CLASS_DEATH_KNIGHT) ? SPELL_PENNANT_EBON_BLADE_ASPIRANT : SPELL_PENNANT_ARGENT_CRUSADE_ASPIRANT;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -576,7 +576,7 @@ class spell_item_skull_of_impeding_doom : public AuraScript
|
|||||||
|
|
||||||
void CalculateManaLeechAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
void CalculateManaLeechAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||||
{
|
{
|
||||||
if (!GetCaster() || GetCaster()->getPowerType() != POWER_MANA)
|
if (!GetCaster() || !GetCaster()->HasActivePowerType(POWER_MANA))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
amount = GetCaster()->GetMaxPower(POWER_MANA) * 0.12f; // 5 ticks which reduce health by 60%
|
amount = GetCaster()->GetMaxPower(POWER_MANA) * 0.12f; // 5 ticks which reduce health by 60%
|
||||||
@@ -3469,7 +3469,7 @@ class spell_item_refocus : public SpellScript
|
|||||||
{
|
{
|
||||||
Player* caster = GetCaster()->ToPlayer();
|
Player* caster = GetCaster()->ToPlayer();
|
||||||
|
|
||||||
if (!caster || caster->getClass() != CLASS_HUNTER)
|
if (!caster || !caster->IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
caster->RemoveCategoryCooldown(SPELL_CATEGORY_AIMED_MULTI);
|
caster->RemoveCategoryCooldown(SPELL_CATEGORY_AIMED_MULTI);
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ class spell_pal_blessing_of_sanctuary : public AuraScript
|
|||||||
|
|
||||||
bool CheckProc(ProcEventInfo& /*eventInfo*/)
|
bool CheckProc(ProcEventInfo& /*eventInfo*/)
|
||||||
{
|
{
|
||||||
return GetTarget()->getPowerType() == POWER_MANA;
|
return GetTarget()->HasActivePowerType(POWER_MANA);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
|
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
|
||||||
@@ -969,7 +969,7 @@ class spell_pal_lay_on_hands : public SpellScript
|
|||||||
|
|
||||||
// Xinef: Glyph of Divinity
|
// Xinef: Glyph of Divinity
|
||||||
if (Unit* target = GetExplTargetUnit())
|
if (Unit* target = GetExplTargetUnit())
|
||||||
if (target->getPowerType() == POWER_MANA)
|
if (target->HasActivePowerType(POWER_MANA))
|
||||||
_manaAmount = target->GetPower(POWER_MANA);
|
_manaAmount = target->GetPower(POWER_MANA);
|
||||||
|
|
||||||
return SPELL_CAST_OK;
|
return SPELL_CAST_OK;
|
||||||
|
|||||||
@@ -992,7 +992,7 @@ class spell_sha_mana_spring_totem : public SpellScript
|
|||||||
int32 damage = GetEffectValue();
|
int32 damage = GetEffectValue();
|
||||||
if (Unit* target = GetHitUnit())
|
if (Unit* target = GetHitUnit())
|
||||||
if (Unit* caster = GetCaster())
|
if (Unit* caster = GetCaster())
|
||||||
if (target->getPowerType() == POWER_MANA)
|
if (target->HasActivePowerType(POWER_MANA))
|
||||||
caster->CastCustomSpell(target, SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE, &damage, 0, 0, true, 0, 0, GetOriginalCaster()->GetGUID());
|
caster->CastCustomSpell(target, SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE, &damage, 0, 0, true, 0, 0, GetOriginalCaster()->GetGUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1017,7 +1017,7 @@ class spell_sha_mana_tide_totem : public SpellScript
|
|||||||
if (Unit* caster = GetCaster())
|
if (Unit* caster = GetCaster())
|
||||||
if (Unit* unitTarget = GetHitUnit())
|
if (Unit* unitTarget = GetHitUnit())
|
||||||
{
|
{
|
||||||
if (unitTarget->getPowerType() == POWER_MANA)
|
if (unitTarget->HasActivePowerType(POWER_MANA))
|
||||||
{
|
{
|
||||||
int32 effValue = GetEffectValue();
|
int32 effValue = GetEffectValue();
|
||||||
// Glyph of Mana Tide
|
// Glyph of Mana Tide
|
||||||
|
|||||||
Reference in New Issue
Block a user