Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-02-11 23:45:22 +08:00
54 changed files with 1943 additions and 1547 deletions
@@ -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);
+5 -5
View File
@@ -12,10 +12,10 @@
if(WIN32)
set(BOOST_DEBUG ON)
if(DEFINED ENV{BOOST_ROOT})
set(BOOST_ROOT $ENV{BOOST_ROOT})
if(DEFINED ENV{Boost_ROOT})
set(Boost_ROOT $ENV{Boost_ROOT})
list(APPEND BOOST_LIBRARYDIR
${BOOST_ROOT}/lib${PLATFORM}-msvc-14.2)
${Boost_ROOT}/lib${PLATFORM}-msvc-14.2)
endif()
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)
if(NOT Boost_FOUND)
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.")
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.")
endif()
endif()
+254 -103
View File
@@ -7,15 +7,29 @@ FindOpenSSL
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
^^^^^^^^^^^^^^^^^^^
.. versionadded:: 3.12
This module supports two optional COMPONENTS: ``Crypto`` and ``SSL``. Both
components have associated imported targets, as described below.
Imported Targets
^^^^^^^^^^^^^^^^
.. versionadded:: 3.4
This module defines the following :prop_tgt:`IMPORTED` targets:
``OpenSSL::SSL``
@@ -23,6 +37,8 @@ This module defines the following :prop_tgt:`IMPORTED` targets:
``OpenSSL::Crypto``
The OpenSSL ``crypto`` library, if found.
``OpenSSL::applink``
.. versionadded:: 3.18
The OpenSSL ``applink`` components that might be need to be compiled into
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
@@ -74,36 +90,115 @@ This module will set the following variables in your project:
Hints
^^^^^
Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation.
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.
The following variables may be set to control search behavior:
``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)
if((CMAKE_SYSTEM_NAME STREQUAL "Linux") AND
unset(_OpenSSL_extra_static_deps)
if(UNIX AND
(("${ssl_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$") OR
("${crypto_library}" MATCHES "\\${CMAKE_STATIC_LIBRARY_SUFFIX}$")))
set(_OpenSSL_has_dependencies TRUE)
find_package(Threads)
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)
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()
set(_OpenSSL_has_dependencies FALSE)
endif()
endmacro()
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})
endif()
list(APPEND ${libraries_var} ${CMAKE_DL_LIBS})
if(_OpenSSL_has_dependency_dl)
list(APPEND ${libraries_var} ${CMAKE_DL_LIBS})
endif()
list(APPEND ${libraries_var} ${_OpenSSL_extra_static_deps})
set(${libraries_var} ${${libraries_var}} PARENT_SCOPE)
endfunction()
function(_OpenSSL_target_add_dependencies target)
if(_OpenSSL_has_dependencies)
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES Threads::Threads )
set_property( TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS} )
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} )
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()
@@ -115,62 +210,87 @@ endif ()
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
if(OPENSSL_USE_STATIC_LIBS)
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})
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a )
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
set(_OPENSSL_MSI_INSTALL_GUID "")
if(PLATFORM EQUAL 64)
set(_OPENSSL_MSI_INSTALL_GUID "117551DB-A110-4BBD-BB05-CFE0BCB3ED31")
set(_OPENSSL_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
${OPENSSL_ROOT_DIR}
ENV OPENSSL_ROOT_DIR
)
set(_OPENSSL_MSI_INSTALL_GUIDS "")
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
set(_arch "Win64-ARM")
set(_OPENSSL_MSI_INSTALL_GUIDS "99C28AFA-6419-40B1-B88D-32B810BB4234")
else()
set(_arch "Win64")
set(_OPENSSL_MSI_INSTALL_GUIDS "117551DB-A110-4BBD-BB05-CFE0BCB3ED31" "50A9FBE2-0F8C-4D5D-97A4-A63A71C4EA1E")
endif()
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _programfiles)
set(_OPENSSL_ROOT_PATHS
"${_programfiles}/OpenSSL"
"${_programfiles}/OpenSSL-Win64"
"C:/OpenSSL/"
"C:/OpenSSL-Win64/"
)
set(_OPENSSL_ROOT_HINTS HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]")
else()
set(_OPENSSL_MSI_INSTALL_GUID "A1EEC576-43B9-4E75-9E02-03DA542D2A38")
set(_OPENSSL_ROOT_HINTS
"[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/"
)
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()
unset(_programfiles)
# 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
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 "/")
list(INSERT _OPENSSL_ROOT_HINTS 0 ${_OPENSSL_MSI_INSTALL_PATH})
endif()
else ()
set(_OPENSSL_ROOT_HINTS
${OPENSSL_ROOT_DIR}
ENV OPENSSL_ROOT_DIR
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)
if(NOT _OPENSSL_MSI_INSTALL_PATH STREQUAL "/")
list(INSERT _OPENSSL_ROOT_HINTS 2 ${_OPENSSL_MSI_INSTALL_PATH})
endif()
endforeach()
unset(_OPENSSL_MSI_INSTALL_GUIDS)
set(_OPENSSL_ROOT_PATHS
PATHS
"${_programfiles}/OpenSSL"
"${_programfiles}/OpenSSL-${_arch}"
"C:/OpenSSL/"
"C:/OpenSSL-${_arch}/"
)
unset(_programfiles)
unset(_arch)
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
HINTS ${_OPENSSL_ROOT_HINTS}
PATHS ${_OPENSSL_ROOT_PATHS}
${_OPENSSL_ROOT_HINTS}
${_OPENSSL_ROOT_PATHS}
)
find_path(OPENSSL_INCLUDE_DIR
@@ -181,7 +301,7 @@ find_path(OPENSSL_INCLUDE_DIR
${_OPENSSL_INCLUDEDIR}
${_OPENSSL_INCLUDE_DIRS}
PATH_SUFFIXES
include
${_OPENSSL_FIND_PATH_SUFFIX}
)
if(WIN32 AND NOT CYGWIN)
@@ -210,9 +330,15 @@ if(WIN32 AND NOT CYGWIN)
# Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib
if( "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" )
set(_OPENSSL_MSVC_ARCH_SUFFIX "64")
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()
set(_OPENSSL_MSVC_ARCH_SUFFIX "32")
set(_OPENSSL_MSVC_ARCH_SUFFIX "32")
set(_OPENSSL_MSVC_ARCH_DIRECTORY "x86")
endif()
if(OPENSSL_USE_STATIC_LIBS)
@@ -237,29 +363,40 @@ if(WIN32 AND NOT CYGWIN)
find_library(LIB_EAY_DEBUG
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
# Looking the "libcrypto_static.lib" with a higher priority than "libcrypto.lib" which is the
# import library of "libcrypto.dll".
libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_STATIC_SUFFIX}d
libeay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libeay32${_OPENSSL_STATIC_SUFFIX}d
crypto${_OPENSSL_STATIC_SUFFIX}d
# When OpenSSL is built with the "-static" option, only the static build is produced,
# and it is not suffixed with "_static".
libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_MSVC_RT_MODE}d
libcryptod
libeay32${_OPENSSL_MSVC_RT_MODE}d
libeay32d
cryptod
libcrypto${_OPENSSL_STATIC_SUFFIX}
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
"lib/VC/${_OPENSSL_MSVC_ARCH_DIRECTORY}/${_OPENSSL_MSVC_RT_MODE}d"
)
if(NOT LIB_EAY_DEBUG)
find_library(LIB_EAY_DEBUG
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
# Looking the "libcrypto_static.lib" with a higher priority than "libcrypto.lib" which is the
# import library of "libcrypto.dll".
libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_STATIC_SUFFIX}d
libeay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libeay32${_OPENSSL_STATIC_SUFFIX}d
crypto${_OPENSSL_STATIC_SUFFIX}d
# When OpenSSL is built with the "-static" option, only the static build is produced,
# and it is not suffixed with "_static".
libcrypto${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libcrypto${_OPENSSL_MSVC_RT_MODE}d
libcryptod
libeay32${_OPENSSL_MSVC_RT_MODE}d
libeay32d
cryptod
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
)
endif()
find_library(LIB_EAY_RELEASE
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
@@ -283,33 +420,45 @@ if(WIN32 AND NOT CYGWIN)
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
"lib/VC/${_OPENSSL_MSVC_ARCH_DIRECTORY}/${_OPENSSL_MSVC_RT_MODE}"
)
find_library(SSL_EAY_DEBUG
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
# Looking the "libssl_static.lib" with a higher priority than "libssl.lib" which is the
# import library of "libssl.dll".
libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_STATIC_SUFFIX}d
ssleay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
ssleay32${_OPENSSL_STATIC_SUFFIX}d
ssl${_OPENSSL_STATIC_SUFFIX}d
# When OpenSSL is built with the "-static" option, only the static build is produced,
# and it is not suffixed with "_static".
libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_MSVC_RT_MODE}d
libssld
ssleay32${_OPENSSL_MSVC_RT_MODE}d
ssleay32d
ssld
libssl${_OPENSSL_STATIC_SUFFIX}
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
"lib/VC/${_OPENSSL_MSVC_ARCH_DIRECTORY}/${_OPENSSL_MSVC_RT_MODE}d"
)
if(NOT SSL_EAY_DEBUG)
find_library(SSL_EAY_DEBUG
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
# Looking the "libssl_static.lib" with a higher priority than "libssl.lib" which is the
# import library of "libssl.dll".
libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_STATIC_SUFFIX}d
ssleay32${_OPENSSL_STATIC_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
ssleay32${_OPENSSL_STATIC_SUFFIX}d
ssl${_OPENSSL_STATIC_SUFFIX}d
# When OpenSSL is built with the "-static" option, only the static build is produced,
# and it is not suffixed with "_static".
libssl${_OPENSSL_MSVC_ARCH_SUFFIX}${_OPENSSL_MSVC_RT_MODE}d
libssl${_OPENSSL_MSVC_RT_MODE}d
libssld
ssleay32${_OPENSSL_MSVC_RT_MODE}d
ssleay32d
ssld
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
)
endif()
find_library(SSL_EAY_RELEASE
NAMES
# When OpenSSL is built with default options, the static library name is suffixed with "_static".
@@ -333,6 +482,7 @@ if(WIN32 AND NOT CYGWIN)
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${_OPENSSL_PATH_SUFFIXES}
"lib/VC/${_OPENSSL_MSVC_ARCH_DIRECTORY}/${_OPENSSL_MSVC_RT_MODE}"
)
set(LIB_EAY_LIBRARY_DEBUG "${LIB_EAY_DEBUG}")
@@ -360,6 +510,7 @@ if(WIN32 AND NOT CYGWIN)
PATH_SUFFIXES
"lib/MinGW"
"lib"
"lib64"
)
find_library(SSL_EAY
@@ -370,6 +521,7 @@ if(WIN32 AND NOT CYGWIN)
PATH_SUFFIXES
"lib/MinGW"
"lib"
"lib64"
)
mark_as_advanced(SSL_EAY LIB_EAY)
@@ -411,7 +563,7 @@ else()
find_library(OPENSSL_SSL_LIBRARY
NAMES
ssl
ssl${_OPENSSL_NAME_POSTFIX}
ssleay32
ssleay32MD
NAMES_PER_DIR
@@ -420,19 +572,19 @@ else()
${_OPENSSL_LIBDIR}
${_OPENSSL_LIBRARY_DIRS}
PATH_SUFFIXES
lib
lib lib64
)
find_library(OPENSSL_CRYPTO_LIBRARY
NAMES
crypto
crypto${_OPENSSL_NAME_POSTFIX}
NAMES_PER_DIR
${_OPENSSL_ROOT_HINTS_AND_PATHS}
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_LIBRARY_DIRS}
PATH_SUFFIXES
lib
lib lib64
)
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)
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
(EXISTS "${OPENSSL_CRYPTO_LIBRARY}" OR
EXISTS "${LIB_EAY_LIBRARY_DEBUG}" OR
@@ -642,7 +786,7 @@ if(OPENSSL_FOUND)
_OpenSSL_target_add_dependencies(OpenSSL::SSL)
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(EXISTS "${OPENSSL_INCLUDE_DIR}")
set(_OPENSSL_applink_paths PATHS ${OPENSSL_INCLUDE_DIR})
@@ -669,3 +813,10 @@ endif()
if(OPENSSL_USE_STATIC_LIBS)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_openssl_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
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?
# (It does not affect raids or dungeon finder groups)
#
# Default: 1 - (Enabled)
# Default: 0 - (Disabled)
LeaveGroupOnLogout.Enabled = 1
LeaveGroupOnLogout.Enabled = 0
#
# Group.Raid.LevelRestriction
@@ -227,7 +227,11 @@ bool MySQLConnection::Execute(PreparedStatementBase* stmt)
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))
#endif
{
uint32 lErrno = mysql_errno(m_Mysql);
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();
#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))
#endif
{
uint32 lErrno = mysql_errno(m_Mysql);
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;
}
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.");
return true;
+1 -1
View File
@@ -1055,7 +1055,7 @@ namespace lfg
baseAP = p->GetTotalAttackPowerValue(BASE_ATTACK);
rangedAP = p->GetTotalAttackPowerValue(RANGED_ATTACK);
maxPower = 0;
if (p->getClass() == CLASS_DRUID)
if (p->IsClass(CLASS_DRUID))
maxPower = p->GetMaxPower(POWER_MANA);
else
maxPower = (p->getPowerType() == POWER_RAGE || p->getPowerType() == POWER_RUNIC_POWER) ? p->GetMaxPower(p->getPowerType()) / 10 : p->GetMaxPower(p->getPowerType());
@@ -1196,8 +1196,8 @@ bool Creature::isCanInteractWithBattleMaster(Player* player, bool msg) const
bool Creature::isCanTrainingAndResetTalentsOf(Player* player) const
{
return player->GetLevel() >= 10
&& GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS
&& player->getClass() == GetCreatureTemplate()->trainer_class;
&& GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS
&& player->IsClass((Classes)GetCreatureTemplate()->trainer_class, CLASS_CONTEXT_CLASS_TRAINER);
}
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_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)
*npcFlags &= ~UNIT_NPC_FLAG_TRAINER_CLASS;
+16 -19
View File
@@ -107,7 +107,7 @@ void Pet::AddToWorld()
{
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));
}
@@ -238,7 +238,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
bool forceLoadFromDB = false;
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;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(petInfo->CreatedBySpellId);
@@ -1043,12 +1043,12 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
if (petType == MAX_PET_TYPE)
{
// The petType was not overwritten by the hook, continue with default initialization
if (owner->getClass() == CLASS_WARLOCK ||
owner->getClass() == CLASS_SHAMAN || // Fire Elemental
owner->getClass() == CLASS_DEATH_KNIGHT || // Risen Ghoul
owner->getClass() == CLASS_MAGE) // Water Elemental with glyph
if (owner->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET) ||
owner->IsClass(CLASS_SHAMAN, CLASS_CONTEXT_PET) || // Fire Elemental
owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET) || // Risen Ghoul
owner->IsClass(CLASS_MAGE, CLASS_CONTEXT_PET)) // Water Elemental with glyph
petType = SUMMON_PET;
else if (owner->getClass() == CLASS_HUNTER)
else if (owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
{
petType = HUNTER_PET;
}
@@ -1080,7 +1080,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
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;
SetAttackTime(BASE_ATTACK, attackTime);
@@ -2299,17 +2299,14 @@ bool Pet::IsPermanentPetFor(Player* owner) const
switch (getPetType())
{
case SUMMON_PET:
switch (owner->getClass())
{
case CLASS_WARLOCK:
return GetCreatureTemplate()->type == CREATURE_TYPE_DEMON;
case CLASS_DEATH_KNIGHT:
return GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD;
case CLASS_MAGE:
return GetEntry() == 37994;
default:
return false;
}
if (owner->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET))
return GetCreatureTemplate()->type == CREATURE_TYPE_DEMON;
else if (owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET))
return GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD;
else if (owner->IsClass(CLASS_MAGE, CLASS_CONTEXT_PET))
return GetEntry() == 37994;
else
return false;
case HUNTER_PET:
return true;
default:
@@ -204,12 +204,13 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
if (_victim->GetTypeId() == TYPEID_PLAYER)
player->KilledPlayerCredit();
}
// Give XP only in PvE or in battlegrounds.
// Give reputation and kill credit only in PvE.
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.
sScriptMgr->OnRewardKillRewarder(player, isDungeon, xpRate); // Personal rate is 100%.
sScriptMgr->OnRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%.
if (_xp)
{
@@ -290,3 +291,13 @@ void KillRewarder::Reward()
if (Map* map = _victim->FindMap())
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);
void Reward();
Unit* GetVictim();
Player* GetKiller();
private:
void _InitXP(Player* player);
+55 -37
View File
@@ -553,7 +553,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
// 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_HEROIC_PLAYER_LEVEL);
@@ -568,7 +568,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
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_HEROIC_PLAYER_MONEY));
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
// 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)
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
}
if (getPowerType() == POWER_RUNIC_POWER)
if (HasActivePowerType(POWER_RUNIC_POWER))
{
SetPower(POWER_RUNE, 8);
SetMaxPower(POWER_RUNE, 8);
@@ -633,7 +633,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
switch (iProto->Spells[0].SpellCategory)
{
case SPELL_CATEGORY_FOOD: // food
count = getClass() == CLASS_DEATH_KNIGHT ? 10 : 4;
count = IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT) ? 10 : 4;
break;
case SPELL_CATEGORY_DRINK: // drink
count = 2;
@@ -1269,6 +1269,15 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
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()
{
ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK);
@@ -1460,7 +1469,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
}
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);
return false;
@@ -1745,7 +1754,7 @@ void Player::RegenerateAll()
Regenerate(POWER_MANA);
// 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)
{
// xinef: implement grace
@@ -1775,7 +1784,7 @@ void Player::RegenerateAll()
}
Regenerate(POWER_RAGE);
if (getClass() == CLASS_DEATH_KNIGHT)
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
Regenerate(POWER_RUNIC_POWER);
m_regenTimerCount -= 2000;
@@ -2019,22 +2028,21 @@ void Player::RegenerateHealth()
void Player::ResetAllPowers()
{
SetHealth(GetMaxHealth());
switch (getPowerType())
if (HasActivePowerType(POWER_MANA))
{
case POWER_MANA:
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
break;
case POWER_RAGE:
SetPower(POWER_RAGE, 0);
break;
case POWER_ENERGY:
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
break;
case POWER_RUNIC_POWER:
SetPower(POWER_RUNIC_POWER, 0);
break;
default:
break;
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
}
if (HasActivePowerType(POWER_RAGE))
{
SetPower(POWER_RAGE, 0);
}
if (HasActivePowerType(POWER_ENERGY))
{
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
}
if (HasActivePowerType(POWER_RUNIC_POWER))
{
SetPower(POWER_RUNIC_POWER, 0);
}
}
@@ -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: 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 creature;
@@ -2714,6 +2722,14 @@ void Player::InitStatsForLevel(bool reapplyMods)
pet->SynchronizeLevelWithOwner();
}
bool Player::HasActivePowerType(Powers power)
{
if (sScriptMgr->OnPlayerHasActivePowerType(this, power))
return true;
else
return (getPowerType() == power);
}
void Player::SendInitialSpells()
{
uint32 curTime = GameTime::GetGameTimeMS().count();
@@ -6388,7 +6404,7 @@ void Player::DuelComplete(DuelCompleteType type)
opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1);
// 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);
}
@@ -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)
if (getClass() == CLASS_DRUID)
if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
{
int32 dpsMod = 0;
int32 feral_bonus = 0;
@@ -9841,7 +9857,7 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
if (apply)
{
m_spellMods[mod->op].push_back(mod);
if (getClass() == CLASS_MAGE)
if (IsClass(CLASS_MAGE, CLASS_CONTEXT_ABILITY))
m_spellMods[mod->op].sort(MageSpellModPred());
else
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
// change but I couldn't find a suitable alternative. OK to use class because only DK
// 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
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());
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(mapId, info->positionX, info->positionY, info->positionZ, 0);
}
@@ -11818,7 +11834,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
{
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);
}
@@ -11851,7 +11867,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
{
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);
}
@@ -13376,7 +13392,7 @@ static RuneType runeSlotTypes[MAX_RUNES] =
void Player::InitRunes()
{
if (getClass() != CLASS_DEATH_KNIGHT)
if (!IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
return;
m_runes = new Runes;
@@ -13542,7 +13558,7 @@ uint32 Player::CalculateTalentsPoints() const
uint32 base_talent = GetLevel() < 10 ? 0 : GetLevel() - 9;
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;
}
@@ -14174,19 +14190,21 @@ void Player::ResummonPetTemporaryUnSummonedIfAny()
bool Player::CanResummonPet(uint32 spellid)
{
if (getClass() == CLASS_DEATH_KNIGHT)
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET))
{
if (CanSeeDKPet())
return true;
else if (spellid == 52150) // Raise Dead
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].
return true;
}
else if (getClass() == CLASS_HUNTER)
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
{
return true;
}
@@ -15171,7 +15189,7 @@ void Player::ActivateSpec(uint8 spec)
AutoUnequipOffhandIfNeed();
// 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);
// Xinef: Remove talented single target auras at other targets
+4
View File
@@ -1112,6 +1112,8 @@ public:
static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data);
[[nodiscard]] bool IsClass(Classes playerClass, ClassContext context = CLASS_CONTEXT_NONE) const override;
void SetInWater(bool apply);
[[nodiscard]] bool IsInWater() const override { return m_isInWater; }
@@ -1170,6 +1172,8 @@ public:
void InitStatsForLevel(bool reapplyMods = false);
[[nodiscard]] bool HasActivePowerType(Powers power) override;
// .cheat command related
[[nodiscard]] bool GetCommandStatus(uint32 command) const { return _activeCheats & command; }
void SetCommandStatusOn(uint32 command) { _activeCheats |= command; }
@@ -109,7 +109,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
canTalk = false;
break;
case GOSSIP_OPTION_STABLEPET:
if (getClass() != CLASS_HUNTER)
if (!IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
canTalk = false;
break;
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 playerClass = getClass();
uint8 slots[4];
slots[0] = NULL_SLOT;
slots[1] = NULL_SLOT;
@@ -246,23 +244,23 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c
switch (proto->SubClass)
{
case ITEM_SUBCLASS_ARMOR_LIBRAM:
if (playerClass == CLASS_PALADIN)
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_RELIC))
slots[0] = EQUIPMENT_SLOT_RANGED;
break;
case ITEM_SUBCLASS_ARMOR_IDOL:
if (playerClass == CLASS_DRUID)
if (IsClass(CLASS_DRUID, CLASS_CONTEXT_EQUIP_RELIC))
slots[0] = EQUIPMENT_SLOT_RANGED;
break;
case ITEM_SUBCLASS_ARMOR_TOTEM:
if (playerClass == CLASS_SHAMAN)
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_RELIC))
slots[0] = EQUIPMENT_SLOT_RANGED;
break;
case ITEM_SUBCLASS_ARMOR_MISC:
if (playerClass == CLASS_WARLOCK)
if (IsClass(CLASS_WARLOCK, CLASS_CONTEXT_EQUIP_RELIC))
slots[0] = EQUIPMENT_SLOT_RANGED;
break;
case ITEM_SUBCLASS_ARMOR_SIGIL:
if (playerClass == CLASS_DEATH_KNIGHT)
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_EQUIP_RELIC))
slots[0] = EQUIPMENT_SLOT_RANGED;
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
// 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);
break;
allowEquip = (itemSkill == SKILL_PLATE_MAIL);
}
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)
@@ -2394,39 +2389,40 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
return EQUIP_ERR_CANT_EQUIP_SKILL;
}
uint8 _class = getClass();
if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0)
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
if (proto->Class == ITEM_CLASS_ARMOR)
{
// 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;
}
// 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;
}
// 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;
}
// 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;
}
// 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;
}
@@ -2436,33 +2432,33 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
proto->InventoryType != INVTYPE_CLOAK)
{
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;
break;
case CLASS_HUNTER:
case CLASS_SHAMAN:
subclassToCompare = ITEM_SUBCLASS_ARMOR_MAIL;
break;
case CLASS_ROGUE:
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
{
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
[[fallthrough]];
case CLASS_DRUID:
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
break;
default:
break;
subclassToCompare = ITEM_SUBCLASS_ARMOR_PLATE;
}
else if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
{
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;
}
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())
{
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
}
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
}
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)
{
uint32 cooldownSpell = getClass() == CLASS_ROGUE ? 6123 : 6119;
uint32 cooldownSpell = IsClass(CLASS_ROGUE, CLASS_CONTEXT_WEAPON_SWAP) ? 6123 : 6119;
SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cooldownSpell);
if (!spellProto)
@@ -4645,7 +4641,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
}
case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon
{
if (getClass() == CLASS_SHAMAN)
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_ABILITY))
{
float addValue = 0.0f;
if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
+97 -104
View File
@@ -346,134 +346,127 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
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;
break;
case CLASS_ROGUE:
case CLASS_WARRIOR:
val2 = level + GetStat(STAT_AGILITY) - 10.0f;
break;
case CLASS_DRUID:
switch (GetShapeshiftForm())
{
case FORM_CAT:
case FORM_BEAR:
case FORM_DIREBEAR:
val2 = 0.0f;
break;
default:
val2 = GetStat(STAT_AGILITY) - 10.0f;
break;
}
val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
}
else if (IsClass(CLASS_ROGUE, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_STATS))
{
val2 = level + GetStat(STAT_AGILITY) - 10.0f;
}
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
{
switch (GetShapeshiftForm())
{
case FORM_CAT:
case FORM_BEAR:
case FORM_DIREBEAR:
val2 = 0.0f;
break;
default:
val2 = GetStat(STAT_AGILITY) - 10.0f;
break;
}
}
else
{
val2 = GetStat(STAT_AGILITY) - 10.0f;
}
}
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;
break;
case CLASS_HUNTER:
case CLASS_SHAMAN:
case CLASS_ROGUE:
val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
break;
case CLASS_DRUID:
val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
}
else if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS) || IsClass(CLASS_SHAMAN, CLASS_CONTEXT_STATS) || IsClass(CLASS_ROGUE, CLASS_CONTEXT_STATS))
{
val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
}
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
{
// Check if Predatory Strikes is skilled
float mLevelMult = 0.0f;
float weapon_bonus = 0.0f;
if (IsInFeralForm())
{
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
{
// Check if Predatory Strikes is skilled
float mLevelMult = 0.0f;
float weapon_bonus = 0.0f;
if (IsInFeralForm())
AuraEffect* aurEff = *itr;
if (aurEff->GetSpellInfo()->SpellIconID == 1563)
{
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
switch (aurEff->GetEffIndex())
{
AuraEffect* aurEff = *itr;
if (aurEff->GetSpellInfo()->SpellIconID == 1563)
case 0: // Predatory Strikes (effect 0)
mLevelMult = CalculatePct(1.0f, aurEff->GetAmount());
break;
case 1: // Predatory Strikes (effect 1)
if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND])
{
switch (aurEff->GetEffIndex())
// also gains % attack power from equipped weapon
ItemTemplate const* proto = mainHand->GetTemplate();
if (!proto)
continue;
uint32 ap = proto->getFeralBonus();
// Get AP Bonuses from weapon
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
{
case 0: // Predatory Strikes (effect 0)
mLevelMult = CalculatePct(1.0f, aurEff->GetAmount());
if (i >= proto->StatsCount)
break;
case 1: // Predatory Strikes (effect 1)
if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND])
{
// also gains % attack power from equipped weapon
ItemTemplate const* proto = mainHand->GetTemplate();
if (!proto)
continue;
uint32 ap = proto->getFeralBonus();
// Get AP Bonuses from weapon
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
{
if (i >= proto->StatsCount)
break;
if (proto->ItemStat[i].ItemStatType == ITEM_MOD_ATTACK_POWER)
ap += proto->ItemStat[i].ItemStatValue;
}
// Get AP Bonuses from weapon spells
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
// no spell
if (!proto->Spells[i].SpellId || proto->Spells[i].SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP)
continue;
// check if it is valid spell
SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId);
if (!spellproto)
continue;
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
if (spellproto->Effects[j].ApplyAuraName == SPELL_AURA_MOD_ATTACK_POWER)
ap += spellproto->Effects[j].CalcValue();
}
weapon_bonus = CalculatePct(float(ap), aurEff->GetAmount());
}
break;
default:
break;
if (proto->ItemStat[i].ItemStatType == ITEM_MOD_ATTACK_POWER)
ap += proto->ItemStat[i].ItemStatValue;
}
}
}
}
switch (GetShapeshiftForm())
{
case FORM_CAT:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP;
break;
case FORM_BEAR:
case FORM_DIREBEAR:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + m_baseFeralAP;
break;
case FORM_MOONKIN:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + m_baseFeralAP;
// Get AP Bonuses from weapon spells
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
// no spell
if (!proto->Spells[i].SpellId || proto->Spells[i].SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP)
continue;
// check if it is valid spell
SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId);
if (!spellproto)
continue;
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
if (spellproto->Effects[j].ApplyAuraName == SPELL_AURA_MOD_ATTACK_POWER)
ap += spellproto->Effects[j].CalcValue();
}
weapon_bonus = CalculatePct(float(ap), aurEff->GetAmount());
}
break;
default:
val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
break;
}
}
break;
}
case CLASS_MAGE:
case CLASS_PRIEST:
case CLASS_WARLOCK:
val2 = GetStat(STAT_STRENGTH) - 10.0f;
}
switch (GetShapeshiftForm())
{
case FORM_CAT:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP;
break;
case FORM_BEAR:
case FORM_DIREBEAR:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + m_baseFeralAP;
break;
case FORM_MOONKIN:
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + m_baseFeralAP;
break;
default:
val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
break;
}
}
else if (IsClass(CLASS_MAGE, CLASS_CONTEXT_STATS) || IsClass(CLASS_PRIEST, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARLOCK, CLASS_CONTEXT_STATS))
{
val2 = GetStat(STAT_STRENGTH) - 10.0f;
}
}
@@ -521,7 +514,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
UpdateDamagePhysical(BASE_ATTACK);
if (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon
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();
}
}
+21 -21
View File
@@ -929,7 +929,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
}
// 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;
@@ -957,10 +957,10 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
// Rage from absorbed damage
if (cleanDamage && cleanDamage->absorbed_damage)
{
if (victim->getPowerType() == POWER_RAGE)
if (victim->HasActivePowerType(POWER_RAGE))
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);
}
@@ -1083,7 +1083,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
}
// 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);
victim->RewardRage(rageDamage, 0, false);
@@ -6996,7 +6996,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Magic Absorption
if (dummySpell->SpellIconID == 459) // only this spell has SpellIconID == 459 and dummy aura
{
if (getPowerType() != POWER_MANA)
if (!HasActivePowerType(POWER_MANA))
return false;
// mana reward
@@ -7775,7 +7775,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// Judgement of Wisdom
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;
// 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
if (Player* player = ToPlayer())
{
if (player->getClass() != CLASS_DEATH_KNIGHT)
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
return false;
// xinef: not true
@@ -9565,7 +9565,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
// Item - Death Knight T10 Melee 4P Bonus
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;
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)
{
Player* plr = ToPlayer();
if (!plr || plr->getClass() != CLASS_DEATH_KNIGHT || !procSpell)
if (!plr || !plr->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY) || !procSpell)
return false;
if (!plr->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
@@ -13840,7 +13840,7 @@ void Unit::ClearInCombat()
else if (Player* player = ToPlayer())
{
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)
player->SetGracePeriod(i, 0);
}
@@ -16378,7 +16378,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
if (procExtra & PROC_EX_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);
StartReactiveTimer(REACTIVE_DEFENSE);
@@ -16388,7 +16388,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
if (procExtra & PROC_EX_PARRY)
{
// 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);
StartReactiveTimer(REACTIVE_HUNTER_PARRY);
@@ -16411,7 +16411,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
// Overpower on victim dodge
if (procExtra & PROC_EX_DODGE)
{
if (getClass() == CLASS_WARRIOR)
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE))
{
AddComboPoints(target, 1);
StartReactiveTimer(REACTIVE_OVERPOWER);
@@ -17218,9 +17218,9 @@ void Unit::ClearAllReactives()
if (HasAuraState(AURA_STATE_DEFENSE))
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);
if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE) && GetTypeId() == TYPEID_PLAYER)
ClearComboPoints();
}
@@ -17244,11 +17244,11 @@ void Unit::UpdateReactives(uint32 p_time)
ModifyAuraState(AURA_STATE_DEFENSE, false);
break;
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);
break;
case REACTIVE_OVERPOWER:
if (getClass() == CLASS_WARRIOR)
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE))
{
ClearComboPoints();
}
@@ -18113,7 +18113,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
// Spirit of Redemption
// if talent known but not triggered (check priest class for speedup check)
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))
{
@@ -18723,7 +18723,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
GetMotionMaster()->MoveIdle();
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
Creature* charmed = ToCreature();
@@ -18789,7 +18789,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
playerCharmer->PossessSpellInitialize();
break;
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();
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
@@ -18911,7 +18911,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
ClearUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD);
break;
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();
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
+25
View File
@@ -440,6 +440,29 @@ enum DamageEffectType : uint8
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
// EnumUtils: DESCRIBE THIS
enum UnitFlags : uint32
@@ -1436,6 +1459,7 @@ public:
void setRace(uint8 race);
[[nodiscard]] uint32 getRaceMask() const { return 1 << (getRace(true) - 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]] uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); }
[[nodiscard]] DisplayRace GetDisplayRaceFromModelId(uint32 modelId) const;
@@ -1472,6 +1496,7 @@ public:
[[nodiscard]] Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
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 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);
+1 -1
View File
@@ -72,7 +72,7 @@ void Vehicle::Install()
{
if (PowerDisplayEntry const* powerDisplay = sPowerDisplayStore.LookupEntry(_vehicleInfo->m_powerDisplayId))
_me->setPowerType(Powers(powerDisplay->PowerType));
else if (_me->getClass() == CLASS_ROGUE)
else if (_me->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY))
_me->setPowerType(POWER_ENERGY);
}
+1 -1
View File
@@ -1983,7 +1983,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
return ERR_IN_NON_RANDOM_BG;
// 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;
if (!member->GetBGAccessByLevel(bgTemplate->GetBgTypeID()))
@@ -184,7 +184,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
err = ERR_BATTLEGROUND_QUEUED_FOR_RATED;
}
// 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;
}
+3 -3
View File
@@ -83,7 +83,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData)
{
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))
{
player->SendLootError(lguid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL);
@@ -162,7 +162,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
case HighGuid::Vehicle:
{
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))
{
loot = &creature->loot;
@@ -382,7 +382,7 @@ void WorldSession::DoLootRelease(ObjectGuid 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))
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)
{
script->OnRewardKillRewarder(player, isDungeon, rate);
script->OnRewardKillRewarder(player, rewarder, isDungeon, rate);
});
}
@@ -1046,6 +1046,19 @@ bool ScriptMgr::CanRepopAtGraveyard(Player* player)
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)
{
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) {
ExecuteScript<PlayerScript>([&](PlayerScript* script)
{
@@ -22,6 +22,7 @@
// TODO to remove
#include "AchievementMgr.h"
#include "KillRewarder.h"
class PlayerScript : public ScriptObject
{
@@ -315,7 +316,7 @@ public:
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; }
@@ -323,8 +324,12 @@ public:
[[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*/) { }
[[nodiscard]] virtual bool OnPlayerHasActivePowerType(Player const* /*player*/, Powers /*power*/) { return false; }
/**
* @brief This hook called before gathering skill gain is applied to the character.
*
+3 -1
View File
@@ -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);
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 OnRewardKillRewarder(Player* player, bool isDungeon, float& rate);
void OnRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate);
bool CanGiveMailRewardAtGiveLevel(Player* player, uint8 level);
void OnDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid);
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);
bool OnPlayerHasActivePowerType(Player const* player, Powers power);
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);
bool OnUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll);
@@ -79,6 +79,7 @@ class WorldSocket;
enum ArenaTeamInfoType : uint8;
enum AuraRemoveMode : uint8;
enum BattlegroundDesertionType : uint8;
enum ClassContext : uint8;
enum ContentLevels : uint8;
enum DamageEffectType : uint8;
enum EnchantmentSlot : uint8;
@@ -2027,7 +2027,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (!target->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
{
target->SetShapeshiftForm(FORM_NONE);
if (target->getClass() == CLASS_DRUID)
if (target->IsClass(CLASS_DRUID, CLASS_CONTEXT_ABILITY))
{
target->setPowerType(POWER_MANA);
// 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)
target->ToPlayer()->InitDataForForm();
if (target->getClass() == CLASS_DRUID)
if (target->IsClass(CLASS_DRUID, CLASS_CONTEXT_ABILITY))
{
// Dash
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();
if (player->getClass() != CLASS_DEATH_KNIGHT)
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
return;
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.
// Should be manauser
if (target->getPowerType() != POWER_RAGE)
if (!target->HasActivePowerType(POWER_RAGE))
break;
uint32 rage = target->GetPower(POWER_RAGE);
// Nothing todo
@@ -6310,7 +6310,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
{
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
if (!target->ToPlayer()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
return;
// timer expired - remove death runes
@@ -7082,7 +7082,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
{
Powers PowerType = Powers(GetMiscValue());
if (!caster || !caster->IsAlive() || !target->IsAlive() || target->getPowerType() != PowerType)
if (!caster || !caster->IsAlive() || !target->IsAlive() || !target->HasActivePowerType(PowerType))
return;
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());
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;
if (!target->IsAlive() || !target->GetMaxPower(PowerType))
@@ -7223,7 +7223,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
{
Powers PowerType = Powers(GetMiscValue());
if (!caster || !target->IsAlive() || target->getPowerType() != PowerType)
if (!caster || !target->IsAlive() || !target->HasActivePowerType(PowerType))
return;
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamageOrSchool(GetSpellInfo()))
+1 -1
View File
@@ -1876,7 +1876,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
break;
if (target->GetTypeId() != TYPEID_PLAYER)
break;
if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
if (!target->ToPlayer()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
break;
// aura removed - remove death runes
+6 -6
View File
@@ -4807,7 +4807,7 @@ void Spell::SendSpellGo()
}
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->PowerType == POWER_RUNE)
{
@@ -5396,7 +5396,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 RuneCostID)
return SPELL_CAST_OK;
}
if (player->getClass() != CLASS_DEATH_KNIGHT)
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
return SPELL_CAST_OK;
SpellRuneCostEntry const* src = sSpellRuneCostStore.LookupEntry(RuneCostID);
@@ -5437,7 +5437,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 RuneCostID)
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;
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)
if (m_caster->GetTypeId() == TYPEID_PLAYER)
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;
break;
}
@@ -6408,7 +6408,7 @@ SpellCastResult Spell::CheckCast(bool strict)
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())
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())
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;
break;
+8 -8
View File
@@ -1345,7 +1345,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex)
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;
// add spell damage bonus
@@ -1424,7 +1424,7 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex)
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;
// 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);
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))
return;
@@ -1982,7 +1982,7 @@ void Spell::EffectEnergizePct(SpellEffIndex effIndex)
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;
uint32 maxPower = unitTarget->GetMaxPower(power);
@@ -3077,7 +3077,7 @@ void Spell::EffectTameCreature(SpellEffIndex /*effIndex*/)
if (creatureTarget->IsPet())
return;
if (m_caster->getClass() != CLASS_HUNTER)
if (!m_caster->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
return;
// cast finish successfully
@@ -3209,7 +3209,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
// Reset cooldowns
if (owner->getClass() != CLASS_HUNTER)
if (!owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
{
pet->m_CreatureSpellCooldowns.clear();
owner->PetSpellInitialize();
@@ -5746,7 +5746,7 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex)
Player* player = m_caster->ToPlayer();
if (player->getClass() != CLASS_DEATH_KNIGHT)
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
return;
// needed later
@@ -5814,7 +5814,7 @@ void Spell::EffectCreateTamedPet(SpellEffIndex effIndex)
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
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;
uint32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue;
+1 -1
View File
@@ -140,7 +140,7 @@ public:
uint8 oldLevel = playerTarget->GetLevel();
// 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_HEROIC_PLAYER_LEVEL);
@@ -1029,7 +1029,7 @@ class spell_class_call_handler : public SpellScript
targets.remove_if([spellInfo](WorldObject const* target) -> bool
{
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;
}
@@ -37,9 +37,13 @@ enum Spells
SPELL_SHRED_ARMOR = 43243 // Used by Spirit Lynx
};
enum UniqueEvents
{
EVENT_BERSERK = 0
};
enum Hal_CreatureIds
{
NPC_SPIRIT_LYNX = 24143,
NPC_TOTEM = 24224
};
@@ -63,326 +67,274 @@ enum Yells
SAY_DEATH = 5
};
class boss_halazzi : public CreatureScript
enum Groups
{
public:
boss_halazzi() : CreatureScript("boss_halazzi") { }
GROUP_LYNX = 0,
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);
});
}
void Reset() override
{
BossAI::Reset();
_transformCount = 0;
_healthCheckPercentage = 0;
_phase = PHASE_NONE;
_lynxFormHealth = me->GetMaxHealth();
_healthPortion = _lynxFormHealth/4;
_humanFormHealth = (me->GetMaxHealth())/0.66666666;
EnterPhase(PHASE_LYNX);
DoCastSelf(SPELL_DUAL_WIELD, true);
}
void JustSummoned(Creature* summon) override
{
BossAI::JustSummoned(summon);
summon->Attack(me->GetVictim(), false);
summon->SetInCombatWithZone();
}
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)
{
damage = 0;
}
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
else
{
instance->SetData(DATA_HALAZZIEVENT, NOT_STARTED);
summons.DespawnAll();
LynxGUID.Clear();
TransformCount = 0;
BerserkTimer = 600000;
CheckTimer = 1000;
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);
}
void JustSummoned(Creature* summon) override
{
summon->AI()->AttackStart(me->GetVictim());
if (summon->GetEntry() == NPC_SPIRIT_LYNX)
LynxGUID = summon->GetGUID();
summons.Summon(summon);
}
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE)
damage = 0;
}
void SpellHit(Unit*, SpellInfo const* spell) override
{
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
EnterPhase(PHASE_HUMAN);
}
void AttackStart(Unit* who) override
{
if (Phase != PHASE_MERGE)
ScriptedAI::AttackStart(who);
}
void EnterPhase(PhaseHalazzi NextPhase)
{
switch (NextPhase)
if (_phase == PHASE_LYNX || _phase == PHASE_ENRAGE)
{
case PHASE_LYNX:
case PHASE_ENRAGE:
if (Phase == PHASE_MERGE)
{
DoCast(me, SPELL_TRANSFORM_MERGE, true);
me->Attack(me->GetVictim(), true);
me->GetMotionMaster()->MoveChase(me->GetVictim());
}
if (Creature* Lynx = ObjectAccessor::GetCreature(*me, LynxGUID))
Lynx->DisappearAndDie();
me->SetMaxHealth(600000);
me->SetHealth(600000 - 150000 * TransformCount);
FrenzyTimer = 16000;
SaberlashTimer = 20000;
ShockTimer = 10000;
TotemTimer = 12000;
break;
case PHASE_SPLIT:
Talk(SAY_SPLIT);
DoCast(me, SPELL_TRANSFORM_SPLIT, true);
break;
case PHASE_HUMAN:
//DoCast(me, SPELL_SUMMON_LYNX, true);
DoSpawnCreature(NPC_SPIRIT_LYNX, 5, 5, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
me->SetMaxHealth(400000);
me->SetHealth(400000);
ShockTimer = 10000;
TotemTimer = 12000;
break;
case PHASE_MERGE:
if (Unit* pLynx = ObjectAccessor::GetUnit(*me, LynxGUID))
{
Talk(SAY_MERGE);
pLynx->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
pLynx->GetMotionMaster()->Clear();
pLynx->GetMotionMaster()->MoveFollow(me, 0, 0);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveFollow(pLynx, 0, 0);
++TransformCount;
}
break;
default:
break;
_healthCheckPercentage = 25 * (3 - _transformCount);
if (!HealthAbovePct(_healthCheckPercentage))
{
EnterPhase(PHASE_SPLIT);
}
}
Phase = NextPhase;
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (BerserkTimer <= diff)
else if (_phase == PHASE_HUMAN)
{
DoCast(me, SPELL_BERSERK, true);
BerserkTimer = 60000;
if (Creature* lynx = instance->GetCreature(DATA_SPIRIT_LYNX))
{
if (!HealthAbovePct(20) || !lynx->HealthAbovePct(20))
{
EnterPhase(PHASE_MERGE);
}
}
else
{
//should not really happen
EnterEvadeMode();
}
}
else BerserkTimer -= diff;
}
}
if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE)
{
if (SaberlashTimer <= diff)
void SpellHit(Unit*, SpellInfo const* spell) override
{
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
{
EnterPhase(PHASE_HUMAN);
}
}
void AttackStart(Unit* who) override
{
if (_phase != PHASE_MERGE)
{
BossAI::AttackStart(who);
}
}
void EnterPhase(PhaseHalazzi nextPhase)
{
switch (nextPhase)
{
case PHASE_LYNX:
case PHASE_ENRAGE:
if (_phase == PHASE_MERGE)
{
DoCastSelf(SPELL_TRANSFORM_MERGE, true);
me->RemoveAurasDueToSpell(SPELL_TRANSFORM_SPLIT2);
me->GetMotionMaster()->MoveChase(me->GetVictim());
}
summons.DespawnAll();
me->SetMaxHealth(_lynxFormHealth);
me->SetHealth(_lynxFormHealth - _healthPortion * _transformCount);
scheduler.CancelGroup(GROUP_MERGE);
scheduler.Schedule(16s, GROUP_LYNX, [this](TaskContext context)
{
DoCastSelf(SPELL_FRENZY);
context.Repeat(10s, 15s);
}).Schedule(20s, GROUP_LYNX, [this](TaskContext context)
{
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)
context.Repeat(30s);
});
break;
case PHASE_SPLIT:
Talk(SAY_SPLIT);
DoCastSelf(SPELL_TRANSFORM_SPLIT, true);
break;
case PHASE_HUMAN:
scheduler.CancelGroup(GROUP_MERGE);
DoCastSelf(SPELL_SUMMON_LYNX, true);
me->SetMaxHealth(_humanFormHealth);
me->SetHealth(_humanFormHealth);
scheduler.CancelGroup(GROUP_LYNX);
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);
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;
context.Repeat(10s, 15s);
}).Schedule(12s, GROUP_HUMAN, [this](TaskContext context)
{
DoCastSelf(SPELL_SUMMON_TOTEM);
context.Repeat(20s);
});
break;
case PHASE_MERGE:
if (Creature* lynx = instance->GetCreature(DATA_SPIRIT_LYNX))
{
Talk(SAY_MERGE);
scheduler.CancelGroup(GROUP_HUMAN);
lynx->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
lynx->GetMotionMaster()->Clear();
lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveFollow(lynx, 0, 0);
++_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);
});
}
else CheckTimer -= diff;
}
DoMeleeAttackIfReady();
break;
default:
break;
}
_phase = nextPhase;
}
void KilledUnit(Unit* victim) override
void KilledUnit(Unit* victim) override
{
BossAI::KilledUnit(victim);
if (victim->IsPlayer())
{
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
Talk(SAY_KILL);
}
void JustDied(Unit* /*killer*/) override
{
instance->SetData(DATA_HALAZZIEVENT, DONE);
Talk(SAY_DEATH);
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetZulAmanAI<boss_halazziAI>(creature);
}
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
Talk(SAY_DEATH);
}
private:
uint32 _lynxFormHealth;
uint32 _humanFormHealth;
uint32 _healthPortion;
uint8 _transformCount;
uint32 _healthCheckPercentage;
PhaseHalazzi _phase;
};
// Spirits Lynx AI
class npc_halazzi_lynx : public CreatureScript
struct npc_halazzi_lynx : public ScriptedAI
{
public:
npc_halazzi_lynx() : CreatureScript("npc_halazzi_lynx") { }
npc_halazzi_lynx(Creature* creature) : ScriptedAI(creature) { }
struct npc_halazzi_lynxAI : public ScriptedAI
void Reset() override
{
npc_halazzi_lynxAI(Creature* creature) : ScriptedAI(creature) { }
scheduler.CancelAll();
}
uint32 FrenzyTimer;
uint32 shredder_timer;
void Reset() override
{
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
shredder_timer = 4000;
}
void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (damage >= me->GetHealth())
damage = 0;
}
void AttackStart(Unit* who) override
{
if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
ScriptedAI::AttackStart(who);
}
void JustEngagedWith(Unit* /*who*/) override {/*DoZoneInCombat();*/ }
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
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)
{
DoCastVictim(SPELL_SHRED_ARMOR);
shredder_timer = 4000;
}
else shredder_timer -= diff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* creature) const override
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
{
return GetZulAmanAI<npc_halazzi_lynxAI>(creature);
if (damage >= me->GetHealth())
{
damage = 0;
}
}
void AttackStart(Unit* who) override
{
if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
{
ScriptedAI::AttackStart(who);
}
}
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
{
if (!UpdateVictim())
{
return;
}
scheduler.Update(diff);
DoMeleeAttackIfReady();
}
};
void AddSC_boss_halazzi()
{
new boss_halazzi();
new npc_halazzi_lynx();
RegisterZulAmanCreatureAI(boss_halazzi);
RegisterZulAmanCreatureAI(npc_halazzi_lynx);
}
@@ -447,9 +447,9 @@ public:
PlayerAbility_Timer = urand(8000, 10000);
PlayerClass = target->getClass() - 1;
if (PlayerClass == CLASS_DRUID - 1)
if (target->IsClass(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
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};
ObjectData const creatureData[] =
{
{ NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX },
{ 0, 0 }
};
ObjectData const gameObjectData[] =
{
{ 0, 0 }
};
class instance_zulaman : public InstanceMapScript
{
public:
@@ -92,6 +103,7 @@ public:
void Initialize() override
{
SetHeaders(DataHeader);
LoadObjectData(creatureData, gameObjectData);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
QuestTimer = 0;
@@ -135,6 +147,7 @@ public:
default:
break;
}
InstanceScript::OnCreatureCreate(creature);
}
void OnGameObjectCreate(GameObject* go) override
@@ -32,9 +32,10 @@ enum DataTypes
DATA_HALAZZIEVENT = 4,
DATA_HEXLORDEVENT = 5,
DATA_ZULJINEVENT = 6,
DATA_CHESTLOOTED = 7,
TYPE_RAND_VENDOR_1 = 8,
TYPE_RAND_VENDOR_2 = 9
DATA_SPIRIT_LYNX = 7,
DATA_CHESTLOOTED = 8,
TYPE_RAND_VENDOR_1 = 9,
TYPE_RAND_VENDOR_2 = 10
};
enum CreatureIds
@@ -44,7 +45,8 @@ enum CreatureIds
NPC_ZULJIN = 23863,
NPC_HEXLORD = 24239,
NPC_HALAZZI = 23577,
NPC_NALORAKK = 23576
NPC_NALORAKK = 23576,
NPC_SPIRIT_LYNX = 24143
};
enum GameobjectIds
@@ -68,4 +70,6 @@ inline AI* GetZulAmanAI(T* obj)
return GetInstanceAI<AI>(obj, ZulAmanScriptName);
}
#define RegisterZulAmanCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetZulAmanAI)
#endif
+4 -4
View File
@@ -53,10 +53,10 @@ enum RizzleSprysprocketData
SAY_RIZZLE_START = 0,
SAY_RIZZLE_GRENADE = 1,
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] =
{
@@ -295,7 +295,7 @@ public:
if (player->GetQuestStatus(QUEST_CHASING_THE_MOONSTONE) != QUEST_STATUS_INCOMPLETE)
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());
return true;
+50 -25
View File
@@ -65,7 +65,7 @@ public:
{
case GOSSIP_ACTION_INFO_DEF + 1:
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);
break;
case GOSSIP_ACTION_INFO_DEF + 2:
@@ -80,29 +80,42 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
if (player->getClass() != CLASS_DRUID)
if (player->GetTeamId() != TEAM_HORDE)
{
SendGossipMenuFor(player, 4916, creature->GetGUID());
}
else if (player->GetTeamId() != TEAM_HORDE)
{
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, 4042, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
}
SendGossipMenuFor(player, 4917, creature->GetGUID());
if (player->IsClass(CLASS_DRUID))
{
SendGossipMenuFor(player, 4917, creature->GetGUID());
}
else
{
SendGossipMenuFor(player, 4916, creature->GetGUID());
}
}
else if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_HORDE)
else if (player->GetTeamId() == TEAM_HORDE)
{
AddGossipItemFor(player, 4042, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI))
{
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);
}
SendGossipMenuFor(player, 4918, creature->GetGUID());
if (player->IsClass(CLASS_DRUID))
{
SendGossipMenuFor(player, 4918, creature->GetGUID());
}
else
{
SendGossipMenuFor(player, 4916, creature->GetGUID());
}
}
return true;
}
@@ -176,7 +189,7 @@ public:
{
case GOSSIP_ACTION_INFO_DEF + 1:
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);
break;
case GOSSIP_ACTION_INFO_DEF + 2:
@@ -191,29 +204,41 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
if (player->getClass() != CLASS_DRUID)
if (player->GetTeamId() != TEAM_ALLIANCE)
{
SendGossipMenuFor(player, 4913, creature->GetGUID());
}
else if (player->GetTeamId() != TEAM_ALLIANCE)
{
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, 4041, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
}
SendGossipMenuFor(player, 4915, creature->GetGUID());
if (player->IsClass(CLASS_DRUID))
{
SendGossipMenuFor(player, 4915, creature->GetGUID());
}
else
{
SendGossipMenuFor(player, 4913, creature->GetGUID());
}
}
else if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_ALLIANCE)
else if (player->GetTeamId() == TEAM_ALLIANCE)
{
AddGossipItemFor(player, 4041, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if (player->IsClass(CLASS_DRUID, CLASS_CONTEXT_TAXI))
{
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);
}
SendGossipMenuFor(player, 4914, creature->GetGUID());
if (player->IsClass(CLASS_DRUID))
{
SendGossipMenuFor(player, 4914, creature->GetGUID());
}
else
{
SendGossipMenuFor(player, 4913, creature->GetGUID());
}
}
return true;
}
@@ -853,12 +853,12 @@ public:
{
if (p->getPowerType() != POWER_MANA)
return true;
if (p->getClass() == CLASS_HUNTER)
if (p->IsClass(CLASS_HUNTER))
return true;
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;
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 false;
@@ -2856,8 +2856,7 @@ public:
{
c->AI()->AttackStart(target);
DoZoneInCombat(c);
uint8 Class = target->getClass();
if (Class != CLASS_DRUID)
if (!target->IsClass(CLASS_DRUID))
if (Player* p = target->ToPlayer())
{
if (Item* i = p->GetWeaponForAttack(BASE_ATTACK))
@@ -2869,7 +2868,7 @@ public:
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_SPOREBAT3 = 38492,
SPELL_SUMMON_SPOREBAT4 = 38493,
SPELL_TOXIC_SPORES = 38574
SPELL_TOXIC_SPORES = 38574,
SPELL_POISON_BOLT = 38253
};
enum Misc
@@ -91,6 +93,8 @@ struct boss_lady_vashj : public BossAI
ScheduleHealthCheckEvent(70, [&]{
Talk(SAY_PHASE2);
scheduler.CancelAll();
me->CastStop();
me->SetReactState(REACT_PASSIVE);
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->SetFacingTo(me->GetHomePosition().GetOrientation());
instance->SetData(DATA_ACTIVATE_SHIELD, 0);
scheduler.CancelAll();
scheduler.Schedule(2400ms, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
@@ -271,6 +274,42 @@ private:
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
{
PrepareAuraScript(spell_lady_vashj_magic_barrier);
@@ -410,6 +449,7 @@ class spell_lady_vashj_summons : public SpellScript
void AddSC_boss_lady_vashj()
{
RegisterSerpentShrineAI(boss_lady_vashj);
RegisterSerpentShrineAI(npc_tainted_elemental);
RegisterSpellScript(spell_lady_vashj_magic_barrier);
RegisterSpellScript(spell_lady_vashj_remove_tainted_cores);
RegisterSpellScript(spell_lady_vashj_summon_sporebat);
@@ -28,6 +28,7 @@ enum Spells
SPELL_FLAME_QUILLS = 34229,
SPELL_QUILL_MISSILE_1 = 34269, // 21
SPELL_QUILL_MISSILE_2 = 34314, // 3
SPELL_CLEAR_ALL_DEBUFFS = 34098,
SPELL_FLAME_BUFFET = 34121,
SPELL_EMBER_BLAST = 34341,
SPELL_REBIRTH_PHASE2 = 34342,
@@ -38,15 +39,18 @@ enum Spells
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},
{388.09f, 31.54f, 20.18f, 1.61f},
{388.18f, -32.85f, 20.18f, 0.52f},
{340.29f, -60.19f, 17.72f, 5.71f},
{332.0f, 0.01f, 43.0f, 0.0f},
{331.0f, 0.01f, -2.38f, 0.0f},
{332.0f, 0.01f, 43.0f, 0.0f}
{335.638f, 59.4879f, 17.9319f, 4.60f}, //first platform
{388.751007f, 31.731199f, 20.263599f, 1.61f},
{388.790985f, -33.105900f, 20.263599f, 0.52f},
{332.722992f, -61.159f, 17.979099f, 5.71f},
{258.959015f, -38.687099f, 20.262899f, 5.21f},
{259.2277997, 35.879002f, 20.263f, 4.81f}, //sixth platform
{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
@@ -56,26 +60,28 @@ enum Misc
NPC_FLAME_PATCH = 20602,
POINT_PLATFORM = 0,
POINT_QUILL = 4,
POINT_MIDDLE = 5,
POINT_DIVE = 6,
POINT_QUILL = 6,
POINT_MIDDLE = 7,
POINT_DIVE = 8,
EVENT_SWITCH_PLATFORM = 1,
EVENT_START_QUILLS = 2,
EVENT_RELOCATE_MIDDLE = 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_RELOCATE_MIDDLE = 1,
EVENT_REBIRTH = 2,
EVENT_SPELL_BERSERK = 3,
EVENT_MOVE_TO_PHASE_2 = 20,
EVENT_FINISH_DIVE = 21
EVENT_MOVE_TO_PHASE_2 = 4,
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)
@@ -85,279 +91,284 @@ enum qruseoftheAshtongue
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);
}
uint8 platform;
uint8 noQuillTimes;
bool startPath;
void JustReachedHome() override
{
BossAI::JustReachedHome();
startPath = true;
}
void Reset() override
{
BossAI::Reset();
platform = 0;
noQuillTimes = 0;
me->SetModelVisible(true);
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FIRE, true);
me->SetReactState(REACT_AGGRESSIVE);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
events.ScheduleEvent(EVENT_SWITCH_PLATFORM, 0);
}
void JustDied(Unit* killer) override
{
me->SetModelVisible(true);
BossAI::JustDied(killer);
// Xinef: Ruse of the Ashtongue (10946)
Map::PlayerList const& pl = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
{
Player* player = itr->GetSource();
if (player->GetQuestStatus(QUEST_RUSE_OF_THE_ASHTONGUE) == QUEST_STATUS_INCOMPLETE)
if (player->HasAura(SPELL_ASHTONGUE_RUSE))
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 DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (damage >= me->GetHealth() && platform < POINT_MIDDLE)
{
damage = 0;
if (events.GetNextEventTime(EVENT_REBIRTH) == 0)
{
me->InterruptNonMeleeSpells(false);
me->SetHealth(me->GetMaxHealth());
me->SetReactState(REACT_PASSIVE);
me->CastSpell(me, SPELL_EMBER_BLAST, true);
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 MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE)
{
if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized() && !me->IsInCombat())
startPath = true;
return;
}
if (id == POINT_PLATFORM)
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);
events.ScheduleEvent(EVENT_CAST_DIVE_BOMB, 5000);
}
}
void UpdateAI(uint32 diff) override
{
if (startPath)
{
me->StopMoving();
startPath = false;
if (WaypointPath const* i_path = sWaypointMgr->GetPath(me->GetWaypointPath()))
{
Movement::PointsArray pathPoints;
pathPoints.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
for (uint8 i = 0; i < i_path->size(); ++i)
{
WaypointData const* node = i_path->at(i);
pathPoints.push_back(G3D::Vector3(node->x, node->y, node->z));
}
me->GetMotionMaster()->MoveSplinePath(&pathPoints);
}
}
if (!UpdateVictim())
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch (events.ExecuteEvent())
{
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);
SetCombatMovement(false);
}
void JustReachedHome() override
{
BossAI::JustReachedHome();
if (me->IsEngaged())
{
ConstructWaypointsAndMove();
}
}
void Reset() override
{
BossAI::Reset();
_canAttackCooldown = true;
_baseAttackOverride = false;
_spawnPhoenixes = false;
_platform = 0;
_platformRoll = 0;
_noQuillTimes = 0;
_platformMoveRepeatTimer = 16s;
me->SetModelVisible(true);
me->SetReactState(REACT_AGGRESSIVE);
ConstructWaypointsAndMove();
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
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
{
BossAI::JustDied(killer);
me->SetModelVisible(true);
if (Map* map = me->GetMap())
{
map->DoForAllPlayers([&](Player* player)
{
if (player->GetQuestStatus(QUEST_RUSE_OF_THE_ASHTONGUE) == QUEST_STATUS_INCOMPLETE)
{
if (player->HasAura(SPELL_ASHTONGUE_RUSE))
{
player->AreaExploredOrEventHappens(QUEST_RUSE_OF_THE_ASHTONGUE);
}
}
});
}
}
void MoveInLineOfSight(Unit* /*who*/) override { }
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
{
if (damage >= me->GetHealth() && _platform < POINT_MIDDLE)
{
damage = 0;
me->InterruptNonMeleeSpells(false);
me->SetHealth(me->GetMaxHealth());
me->SetReactState(REACT_PASSIVE);
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);
}
}
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
{
if (type != POINT_MOTION_TYPE)
{
if (type == ESCORT_MOTION_TYPE && me->movespline->Finalized() && !me->IsInCombat())
{
ConstructWaypointsAndMove();
}
return;
}
switch(id)
{
case POINT_QUILL:
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 ScheduleMainSpellAttack(std::chrono::seconds timer)
{
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();
if (WaypointPath const* i_path = sWaypointMgr->GetPath(me->GetWaypointPath()))
{
Movement::PointsArray pathPoints;
pathPoints.push_back(G3D::Vector3(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()));
for (uint8 i = 0; i < i_path->size(); ++i)
{
WaypointData const* node = i_path->at(i);
pathPoints.push_back(G3D::Vector3(node->x, node->y, node->z));
}
me->GetMotionMaster()->MoveSplinePath(&pathPoints);
}
}
private:
bool _canAttackCooldown;
bool _baseAttackOverride;
bool _spawnPhoenixes;
uint8 _platform;
uint8 _platformRoll;
uint8 _noQuillTimes;
std::chrono::seconds _platformMoveRepeatTimer;
};
class CastQuill : public BasicEvent
{
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
{
_caster->CastSpell(_caster, _spellId, true);
return true;
}
private:
Unit* _caster;
uint32 _spellId;
@@ -496,7 +507,7 @@ public:
void AddSC_boss_alar()
{
new boss_alar();
RegisterTheEyeAI(boss_alar);
new spell_alar_flame_quills();
new spell_alar_ember_blast();
new spell_alar_ember_blast_death();
@@ -68,6 +68,7 @@ struct boss_high_astromancer_solarian : public BossAI
ScheduleHealthCheckEvent(20, [&]{
scheduler.CancelAll();
me->ResumeChasingVictim();
scheduler.Schedule(3s, [this](TaskContext context)
{
DoCastVictim(SPELL_VOID_BOLT);
@@ -109,10 +110,21 @@ struct boss_high_astromancer_solarian : public BossAI
Talk(SAY_AGGRO);
BossAI::JustEngagedWith(who);
me->CallForHelp(105.0f);
me->GetMotionMaster()->Clear();
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);
}).Schedule(21800ms, [this](TaskContext context)
{
File diff suppressed because it is too large Load Diff
@@ -20,6 +20,21 @@
#include "SpellScriptLoader.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
{
public:
@@ -30,6 +45,7 @@ public:
instance_the_eye_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
LoadObjectData(creatureData, gameObjectData);
SetBossNumber(MAX_ENCOUNTER);
}
@@ -66,6 +82,7 @@ public:
LordSanguinarGUID = creature->GetGUID();
break;
}
InstanceScript::OnCreatureCreate(creature);
}
void OnGameObjectCreate(GameObject* gobject) override
@@ -98,14 +115,6 @@ public:
return AlarGUID;
case NPC_KAELTHAS:
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;
@@ -36,10 +36,10 @@ enum EyeData
DATA_KAELTHAS = 3,
MAX_ENCOUNTER = 4,
DATA_KAEL_ADVISOR1 = 10,
DATA_KAEL_ADVISOR2 = 11,
DATA_KAEL_ADVISOR3 = 12,
DATA_KAEL_ADVISOR4 = 13
DATA_THALADRED = 10,
DATA_LORD_SANGUINAR = 11,
DATA_CAPERNIAN = 12,
DATA_TELONICUS = 13
};
enum EyeNPCs
+2 -2
View File
@@ -1014,7 +1014,7 @@ class spell_dk_blood_boil : public SpellScript
bool Load() override
{
_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()
@@ -1258,7 +1258,7 @@ class spell_dk_death_gate : public SpellScript
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);
return SPELL_FAILED_CUSTOM_ERROR;
+7 -7
View File
@@ -446,7 +446,7 @@ class spell_pet_hit_expertise_scalling : public AuraScript
{
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);
else if (modOwner->getPowerType() == POWER_MANA)
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 (modOwner->getClass() == CLASS_HUNTER)
if (modOwner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 17.0f);
else if (modOwner->getPowerType() == POWER_MANA)
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 (modOwner->getClass() == CLASS_HUNTER)
if (modOwner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
amount = CalculatePercent(modOwner->m_modRangedHitChance, 8.0f, 26.0f);
else if (modOwner->getPowerType() == POWER_MANA)
amount = CalculatePercent(modOwner->m_modSpellHitChance, 17.0f, 26.0f);
@@ -1673,7 +1673,7 @@ class spell_gen_pet_summoned : public SpellScript
Player* player = GetCaster()->ToPlayer();
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);
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:
{
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))
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
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:
return 0;
+2 -2
View File
@@ -576,7 +576,7 @@ class spell_item_skull_of_impeding_doom : public AuraScript
void CalculateManaLeechAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
if (!GetCaster() || GetCaster()->getPowerType() != POWER_MANA)
if (!GetCaster() || !GetCaster()->HasActivePowerType(POWER_MANA))
return;
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();
if (!caster || caster->getClass() != CLASS_HUNTER)
if (!caster || !caster->IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY))
return;
caster->RemoveCategoryCooldown(SPELL_CATEGORY_AIMED_MULTI);
+2 -2
View File
@@ -483,7 +483,7 @@ class spell_pal_blessing_of_sanctuary : public AuraScript
bool CheckProc(ProcEventInfo& /*eventInfo*/)
{
return GetTarget()->getPowerType() == POWER_MANA;
return GetTarget()->HasActivePowerType(POWER_MANA);
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
@@ -969,7 +969,7 @@ class spell_pal_lay_on_hands : public SpellScript
// Xinef: Glyph of Divinity
if (Unit* target = GetExplTargetUnit())
if (target->getPowerType() == POWER_MANA)
if (target->HasActivePowerType(POWER_MANA))
_manaAmount = target->GetPower(POWER_MANA);
return SPELL_CAST_OK;
+2 -2
View File
@@ -992,7 +992,7 @@ class spell_sha_mana_spring_totem : public SpellScript
int32 damage = GetEffectValue();
if (Unit* target = GetHitUnit())
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());
}
@@ -1017,7 +1017,7 @@ class spell_sha_mana_tide_totem : public SpellScript
if (Unit* caster = GetCaster())
if (Unit* unitTarget = GetHitUnit())
{
if (unitTarget->getPowerType() == POWER_MANA)
if (unitTarget->HasActivePowerType(POWER_MANA))
{
int32 effValue = GetEffectValue();
// Glyph of Mana Tide