diff options
Diffstat (limited to 'src/server/scripts')
252 files changed, 12658 insertions, 7557 deletions
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index a15b6f8ad07..31ba073e77d 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -8,138 +8,232 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# Enable precompiled headers when using the GCC compiler. +message("") -if (USE_SCRIPTPCH) - set(scripts_STAT_PCH_HDR PrecompiledHeaders/ScriptPCH.h) - set(scripts_STAT_PCH_SRC PrecompiledHeaders/ScriptPCH.cpp) -endif () +# Make the script module list available in the current scope +GetScriptModuleList(SCRIPT_MODULE_LIST) + +# Make the native install offset available in this scope +GetInstallOffset(INSTALL_OFFSET) -message(STATUS "SCRIPT PREPARATIONS") -include(Spells/CMakeLists.txt) - -include(Commands/CMakeLists.txt) - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - ../game/AI/ScriptedAI/ScriptedEscortAI.cpp - ../game/AI/ScriptedAI/ScriptedCreature.cpp - ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp - ../game/Maps/AreaBoundary.cpp -) - -if(SCRIPTS) - include(Custom/CMakeLists.txt) - include(World/CMakeLists.txt) - include(OutdoorPvP/CMakeLists.txt) - include(EasternKingdoms/CMakeLists.txt) - include(Kalimdor/CMakeLists.txt) - include(Outland/CMakeLists.txt) - include(Northrend/CMakeLists.txt) - include(Events/CMakeLists.txt) - include(Pet/CMakeLists.txt) +# Sets the SCRIPTS_${SCRIPT_MODULE} variables +# when using predefined templates for script building +# like dynamic, static, minimal-static... +# Sets SCRIPTS_DEFAULT_LINKAGE +if (SCRIPTS MATCHES "dynamic") + set(SCRIPTS_DEFAULT_LINKAGE "dynamic") +elseif(SCRIPTS MATCHES "static") + set(SCRIPTS_DEFAULT_LINKAGE "static") +else() + set(SCRIPTS_DEFAULT_LINKAGE "disabled") +endif() +# Sets SCRIPTS_USE_WHITELIST +# Sets SCRIPTS_WHITELIST +if (SCRIPTS MATCHES "minimal") + set(SCRIPTS_USE_WHITELIST ON) + # Whitelist which is used when minimal is selected + list(APPEND SCRIPTS_WHITELIST Commands Spells) endif() -message(STATUS "SCRIPT PREPARATION COMPLETE") -message("") +# Set the SCRIPTS_${SCRIPT_MODULE} variables from the +# variables set above +foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST}) + ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE) + if (${SCRIPT_MODULE_VARIABLE} STREQUAL "default") + if(SCRIPTS_USE_WHITELIST) + list(FIND SCRIPTS_WHITELIST "${SCRIPT_MODULE}" INDEX) + if (${INDEX} GREATER -1) + set(${SCRIPT_MODULE_VARIABLE} ${SCRIPTS_DEFAULT_LINKAGE}) + else() + set(${SCRIPT_MODULE_VARIABLE} "disabled") + endif() + else() + set(${SCRIPT_MODULE_VARIABLE} ${SCRIPTS_DEFAULT_LINKAGE}) + endif() + endif() + # Build the Graph values + if (${SCRIPT_MODULE_VARIABLE} MATCHES "dynamic") + GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME) + GetNativeSharedLibraryName(${SCRIPT_MODULE_PROJECT_NAME} SCRIPT_PROJECT_LIBRARY) + list(APPEND GRAPH_KEYS ${SCRIPT_MODULE_PROJECT_NAME}) + set(GRAPH_VALUE_DISPLAY_${SCRIPT_MODULE_PROJECT_NAME} ${SCRIPT_PROJECT_LIBRARY}) + list(APPEND GRAPH_VALUE_CONTAINS_MODULES_${SCRIPT_MODULE_PROJECT_NAME} ${SCRIPT_MODULE}) + elseif(${SCRIPT_MODULE_VARIABLE} MATCHES "static") + list(APPEND GRAPH_KEYS worldserver) + set(GRAPH_VALUE_DISPLAY_worldserver worldserver) + list(APPEND GRAPH_VALUE_CONTAINS_MODULES_worldserver ${SCRIPT_MODULE}) + else() + list(APPEND GRAPH_KEYS disabled) + set(GRAPH_VALUE_DISPLAY_disabled disabled) + list(APPEND GRAPH_VALUE_CONTAINS_MODULES_disabled ${SCRIPT_MODULE}) + endif() +endforeach() + +list(SORT GRAPH_KEYS) +list(REMOVE_DUPLICATES GRAPH_KEYS) -include_directories( - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/src/common/ - ${CMAKE_SOURCE_DIR}/src/common/Collision - ${CMAKE_SOURCE_DIR}/src/common/Collision/Management - ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps - ${CMAKE_SOURCE_DIR}/src/common/Collision/Models - ${CMAKE_SOURCE_DIR}/src/common/Configuration - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Logging - ${CMAKE_SOURCE_DIR}/src/common/Threading - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${CMAKE_SOURCE_DIR}/src/server/database/Database - ${CMAKE_SOURCE_DIR}/src/server/game/Accounts - ${CMAKE_SOURCE_DIR}/src/server/game/Achievements - ${CMAKE_SOURCE_DIR}/src/server/game/Addons - ${CMAKE_SOURCE_DIR}/src/server/game/AI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts - ${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse - ${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouseBot - ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield - ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield/Zones - ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds - ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds/Zones - ${CMAKE_SOURCE_DIR}/src/server/game/Chat - ${CMAKE_SOURCE_DIR}/src/server/game/Chat/Channels - ${CMAKE_SOURCE_DIR}/src/server/game/Combat - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/DungeonFinding - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Corpse - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/DynamicObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item/Container - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object/Updates - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Pet - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Player - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Transport - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Unit - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Vehicle - ${CMAKE_SOURCE_DIR}/src/server/game/Events - ${CMAKE_SOURCE_DIR}/src/server/game/Globals - ${CMAKE_SOURCE_DIR}/src/server/game/Grids - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Notifiers - ${CMAKE_SOURCE_DIR}/src/server/game/Groups - ${CMAKE_SOURCE_DIR}/src/server/game/Guilds - ${CMAKE_SOURCE_DIR}/src/server/game/Handlers - ${CMAKE_SOURCE_DIR}/src/server/game/Instances - ${CMAKE_SOURCE_DIR}/src/server/game/Loot - ${CMAKE_SOURCE_DIR}/src/server/game/Mails - ${CMAKE_SOURCE_DIR}/src/server/game/Maps - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous - ${CMAKE_SOURCE_DIR}/src/server/game/Movement - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/MovementGenerators - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP - ${CMAKE_SOURCE_DIR}/src/server/game/Pools - ${CMAKE_SOURCE_DIR}/src/server/game/Quests - ${CMAKE_SOURCE_DIR}/src/server/game/Reputation - ${CMAKE_SOURCE_DIR}/src/server/game/Scripting - ${CMAKE_SOURCE_DIR}/src/server/game/Server - ${CMAKE_SOURCE_DIR}/src/server/game/Server/Protocol - ${CMAKE_SOURCE_DIR}/src/server/game/Skills - ${CMAKE_SOURCE_DIR}/src/server/game/Spells - ${CMAKE_SOURCE_DIR}/src/server/game/Spells/Auras - ${CMAKE_SOURCE_DIR}/src/server/game/Texts - ${CMAKE_SOURCE_DIR}/src/server/game/Tickets - ${CMAKE_SOURCE_DIR}/src/server/game/Tools - ${CMAKE_SOURCE_DIR}/src/server/game/Warden - ${CMAKE_SOURCE_DIR}/src/server/game/Weather - ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${MYSQL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} -) +# Display the script graph +message("* Script configuration (${SCRIPTS}): + |") + +foreach(GRAPH_KEY ${GRAPH_KEYS}) + if (NOT GRAPH_KEY STREQUAL "disabled") + message(" +- ${GRAPH_VALUE_DISPLAY_${GRAPH_KEY}}") + else() + message(" | ${GRAPH_VALUE_DISPLAY_${GRAPH_KEY}}") + endif() + foreach(GRAPH_PROJECT_ENTRY ${GRAPH_VALUE_CONTAINS_MODULES_${GRAPH_KEY}}) + message(" | +- ${GRAPH_PROJECT_ENTRY}") + endforeach() + message(" |") +endforeach() + +# Base sources which are used by every script project +if (USE_SCRIPTPCH) + set(PRIVATE_PCH_HEADER ScriptPCH.h) + set(PRIVATE_PCH_SOURCE ScriptPCH.cpp) +endif () GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) +# Configures the scriptloader with the given name and stores the output in the LOADER_OUT variable. +# It is possible to expose multiple subdirectories from the same scriptloader through passing +# it to the variable arguments +function(ConfigureScriptLoader SCRIPTLOADER_NAME LOADER_OUT IS_DYNAMIC_SCRIPTLOADER) + # Deduces following variables which are referenced by thge template: + # TRINITY_IS_DYNAMIC_SCRIPTLOADER + # TRINITY_SCRIPTS_FORWARD_DECL + # TRINITY_SCRIPTS_INVOKE + # TRINITY_CURRENT_SCRIPT_PROJECT + + # To generate export macros + set(TRINITY_IS_DYNAMIC_SCRIPTLOADER ${IS_DYNAMIC_SCRIPTLOADER}) + # To generate forward declarations of the loading functions + unset(TRINITY_SCRIPTS_FORWARD_DECL) + unset(TRINITY_SCRIPTS_INVOKE) + # The current script project which is built in + set(TRINITY_CURRENT_SCRIPT_PROJECT ${SCRIPTLOADER_NAME}) + foreach(LOCALE_SCRIPT_MODULE ${ARGN}) + # Determine the loader function ("Add##${NameOfDirectory}##Scripts()") + set(LOADER_FUNCTION + "Add${LOCALE_SCRIPT_MODULE}Scripts()") + # Generate the funciton call and the forward declarations + set(TRINITY_SCRIPTS_FORWARD_DECL + "${TRINITY_SCRIPTS_FORWARD_DECL}void ${LOADER_FUNCTION};\n") + set(TRINITY_SCRIPTS_INVOKE + "${TRINITY_SCRIPTS_INVOKE} ${LOADER_FUNCTION};\n") + endforeach() + set(GENERATED_LOADER ${CMAKE_CURRENT_BINARY_DIR}/gen_scriptloader/${SCRIPTLOADER_NAME}/ScriptLoader.cpp) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.cpp.in.cmake ${GENERATED_LOADER}) + set(${LOADER_OUT} ${GENERATED_LOADER} PARENT_SCOPE) +endfunction() + +# Generates the actual script projects +# Fills the STATIC_SCRIPT_MODULES and DYNAMIC_SCRIPT_MODULE_PROJECTS variables +# which contain the names which scripts are linked statically/dynamically and +# adds the sources of the static modules to the PRIVATE_SOURCES variable. +foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST}) + GetPathToScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PATH) + ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE) + + if ((${SCRIPT_MODULE_VARIABLE} STREQUAL "disabled") OR + (${SCRIPT_MODULE_VARIABLE} STREQUAL "static")) + # Uninstall disabled modules + GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME) + GetNativeSharedLibraryName(${SCRIPT_MODULE_PROJECT_NAME} SCRIPT_MODULE_OUTPUT_NAME) + list(APPEND DISABLED_SCRIPT_MODULE_PROJECTS ${INSTALL_OFFSET}/${SCRIPT_MODULE_OUTPUT_NAME}) + if (${SCRIPT_MODULE_VARIABLE} STREQUAL "static") + # Add the module name to STATIC_SCRIPT_MODULES + list(APPEND STATIC_SCRIPT_MODULES ${SCRIPT_MODULE}) + # Add the module content to the whole static module + CollectSourceFiles(${SCRIPT_MODULE_PATH} PRIVATE_SOURCES) + endif() + elseif(${SCRIPT_MODULE_VARIABLE} STREQUAL "dynamic") + # Generate an own dynamic module which is loadable on runtime + # Add the module content to the whole static module + unset(SCRIPT_MODULE_PRIVATE_SOURCES) + CollectSourceFiles(${SCRIPT_MODULE_PATH} SCRIPT_MODULE_PRIVATE_SOURCES) + # Configure the scriptloader + ConfigureScriptLoader(${SCRIPT_MODULE} SCRIPT_MODULE_PRIVATE_SCRIPTLOADER ON ${SCRIPT_MODULE}) + GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME) + # Add the module name to DYNAMIC_SCRIPT_MODULES + list(APPEND DYNAMIC_SCRIPT_MODULE_PROJECTS ${SCRIPT_MODULE_PROJECT_NAME}) + # Create the script module project + add_library(${SCRIPT_MODULE_PROJECT_NAME} SHARED + ${PRIVATE_PCH_SOURCE} + ${SCRIPT_MODULE_PRIVATE_SOURCES} + ${SCRIPT_MODULE_PRIVATE_SCRIPTLOADER}) + target_link_libraries(${SCRIPT_MODULE_PROJECT_NAME} + PUBLIC + game) + set_target_properties(${SCRIPT_MODULE_PROJECT_NAME} + PROPERTIES + FOLDER + "scripts") + + if(UNIX) + install(TARGETS ${SCRIPT_MODULE_PROJECT_NAME} + DESTINATION ${INSTALL_OFFSET} + COMPONENT ${SCRIPT_MODULE_PROJECT_NAME}) + elseif(WIN32) + install(TARGETS ${SCRIPT_MODULE_PROJECT_NAME} + RUNTIME DESTINATION ${INSTALL_OFFSET} + COMPONENT ${SCRIPT_MODULE_PROJECT_NAME}) + if(MSVC) + # Place the script modules in the script subdirectory + set_target_properties(${SCRIPT_MODULE_PROJECT_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/Debug/scripts + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/Release/scripts + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/bin/RelWithDebInfo/scripts + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}/bin/MinSizeRel/scripts) + endif() + endif() + else() + message(FATAL_ERROR "Unknown value \"${${SCRIPT_MODULE_VARIABLE}}\"!") + endif() +endforeach() + +# Add the dynamic script modules to the worldserver as dependency +set(WORLDSERVER_DYNAMIC_SCRIPT_MODULES_DEPENDENCIES ${DYNAMIC_SCRIPT_MODULE_PROJECTS} PARENT_SCOPE) + +ConfigureScriptLoader("static" SCRIPT_MODULE_PRIVATE_SCRIPTLOADER OFF ${STATIC_SCRIPT_MODULES}) + add_library(scripts STATIC - ${scripts_STAT_SRCS} - ${scripts_STAT_PCH_SRC} -) + ScriptLoader.h + ${PRIVATE_PCH_SOURCE} + ${SCRIPT_MODULE_PRIVATE_SCRIPTLOADER} + ${PRIVATE_SOURCES}) + +target_link_libraries(scripts + PUBLIC + game-interface) + +target_include_directories(scripts + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + +set_target_properties(scripts + PROPERTIES + FOLDER + "scripts") # Generate precompiled header if (USE_SCRIPTPCH) - add_cxx_pch(scripts ${scripts_STAT_PCH_HDR} ${scripts_STAT_PCH_SRC}) + list(APPEND ALL_SCRIPT_PROJECTS scripts ${DYNAMIC_SCRIPT_MODULE_PROJECTS}) + add_cxx_pch("${ALL_SCRIPT_PROJECTS}" ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) +endif() + +# Remove all shared libraries in the installl directory which +# are contained in the static library already. +if (DISABLED_SCRIPT_MODULE_PROJECTS) + install(CODE " + foreach(SCRIPT_TO_UNINSTALL ${DISABLED_SCRIPT_MODULE_PROJECTS}) + if (EXISTS \"\${SCRIPT_TO_UNINSTALL}\") + message(STATUS \"Uninstalling: \${SCRIPT_TO_UNINSTALL}\") + file(REMOVE \"\${SCRIPT_TO_UNINSTALL}\") + endif() + endforeach() + ") endif() + +message("") diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt deleted file mode 100644 index d4d75cd175f..00000000000 --- a/src/server/scripts/Commands/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -file(GLOB_RECURSE sources_Commands Commands/*.cpp Commands/*.h) - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - ${sources_Commands} -) - -message(" -> Prepared: Commands") diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index f25e91ee3e6..4bce2d168a9 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -121,10 +121,16 @@ public: if (!accountName || !password) return false; - AccountOpResult result = sAccountMgr->CreateAccount(std::string(accountName), std::string(password), email); - switch (result) + if (strchr(accountName, '@')) + { + handler->PSendSysMessage(LANG_ACCOUNT_USE_BNET_COMMANDS); + handler->SetSentErrorMessage(true); + return false; + } + + switch (sAccountMgr->CreateAccount(std::string(accountName), std::string(password), email)) { - case AOR_OK: + case AccountOpResult::AOR_OK: handler->PSendSysMessage(LANG_ACCOUNT_CREATED, accountName); if (handler->GetSession()) { @@ -134,15 +140,15 @@ public: accountName, email.c_str()); } break; - case AOR_NAME_TOO_LONG: + case AccountOpResult::AOR_NAME_TOO_LONG: handler->SendSysMessage(LANG_ACCOUNT_TOO_LONG); handler->SetSentErrorMessage(true); return false; - case AOR_NAME_ALREADY_EXIST: + case AccountOpResult::AOR_NAME_ALREADY_EXIST: handler->SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); handler->SetSentErrorMessage(true); return false; - case AOR_DB_INTERNAL_ERROR: + case AccountOpResult::AOR_DB_INTERNAL_ERROR: handler->PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR, accountName); handler->SetSentErrorMessage(true); return false; @@ -168,7 +174,7 @@ public: return false; std::string accountName = account; - if (!AccountMgr::normalizeString(accountName)) + if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); @@ -192,14 +198,14 @@ public: AccountOpResult result = AccountMgr::DeleteAccount(accountId); switch (result) { - case AOR_OK: + case AccountOpResult::AOR_OK: handler->PSendSysMessage(LANG_ACCOUNT_DELETED, accountName.c_str()); break; - case AOR_NAME_NOT_EXIST: + case AccountOpResult::AOR_NAME_NOT_EXIST: handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; - case AOR_DB_INTERNAL_ERROR: + case AccountOpResult::AOR_DB_INTERNAL_ERROR: handler->PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR, accountName.c_str()); handler->SetSentErrorMessage(true); return false; @@ -415,7 +421,7 @@ public: AccountOpResult result = AccountMgr::ChangeEmail(handler->GetSession()->GetAccountId(), std::string(email)); switch (result) { - case AOR_OK: + case AccountOpResult::AOR_OK: handler->SendSysMessage(LANG_COMMAND_EMAIL); sScriptMgr->OnEmailChange(handler->GetSession()->GetAccountId()); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Changed Email from [%s] to [%s].", @@ -423,7 +429,7 @@ public: handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), oldEmail, email); break; - case AOR_EMAIL_TOO_LONG: + case AccountOpResult::AOR_EMAIL_TOO_LONG: handler->SendSysMessage(LANG_EMAIL_TOO_LONG); sScriptMgr->OnFailedEmailChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); @@ -505,14 +511,14 @@ public: AccountOpResult result = AccountMgr::ChangePassword(handler->GetSession()->GetAccountId(), std::string(newPassword)); switch (result) { - case AOR_OK: + case AccountOpResult::AOR_OK: handler->SendSysMessage(LANG_COMMAND_PASSWORD); sScriptMgr->OnPasswordChange(handler->GetSession()->GetAccountId()); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Changed Password.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter()); break; - case AOR_PASS_TOO_LONG: + case AccountOpResult::AOR_PASS_TOO_LONG: handler->SendSysMessage(LANG_PASSWORD_TOO_LONG); sScriptMgr->OnFailedPasswordChange(handler->GetSession()->GetAccountId()); handler->SetSentErrorMessage(true); @@ -592,7 +598,7 @@ public: { ///- Convert Account name to Upper Format accountName = account; - if (!AccountMgr::normalizeString(accountName)) + if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); @@ -662,7 +668,7 @@ public: if (isAccountNameGiven) { targetAccountName = arg1; - if (!AccountMgr::normalizeString(targetAccountName) || !AccountMgr::GetId(targetAccountName)) + if (!Utf8ToUpperOnlyLatin(targetAccountName) || !AccountMgr::GetId(targetAccountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, targetAccountName.c_str()); handler->SetSentErrorMessage(true); @@ -750,7 +756,7 @@ public: return false; std::string accountName = account; - if (!AccountMgr::normalizeString(accountName)) + if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); @@ -781,14 +787,14 @@ public: switch (result) { - case AOR_OK: + case AccountOpResult::AOR_OK: handler->SendSysMessage(LANG_COMMAND_PASSWORD); break; - case AOR_NAME_NOT_EXIST: + case AccountOpResult::AOR_NAME_NOT_EXIST: handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; - case AOR_PASS_TOO_LONG: + case AccountOpResult::AOR_PASS_TOO_LONG: handler->SendSysMessage(LANG_PASSWORD_TOO_LONG); handler->SetSentErrorMessage(true); return false; @@ -819,7 +825,7 @@ public: } std::string accountName = account; - if (!AccountMgr::normalizeString(accountName)) + if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); @@ -849,16 +855,16 @@ public: AccountOpResult result = AccountMgr::ChangeEmail(targetAccountId, email); switch (result) { - case AOR_OK: + case AccountOpResult::AOR_OK: handler->SendSysMessage(LANG_COMMAND_EMAIL); TC_LOG_INFO("entities.player.character", "ChangeEmail: Account %s [Id: %u] had it's email changed to %s.", accountName.c_str(), targetAccountId, email); break; - case AOR_NAME_NOT_EXIST: + case AccountOpResult::AOR_NAME_NOT_EXIST: handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; - case AOR_EMAIL_TOO_LONG: + case AccountOpResult::AOR_EMAIL_TOO_LONG: handler->SendSysMessage(LANG_EMAIL_TOO_LONG); handler->SetSentErrorMessage(true); return false; @@ -895,7 +901,7 @@ public: } std::string accountName = account; - if (!AccountMgr::normalizeString(accountName)) + if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); @@ -925,16 +931,16 @@ public: AccountOpResult result = AccountMgr::ChangeRegEmail(targetAccountId, email); switch (result) { - case AOR_OK: + case AccountOpResult::AOR_OK: handler->SendSysMessage(LANG_COMMAND_EMAIL); TC_LOG_INFO("entities.player.character", "ChangeRegEmail: Account %s [Id: %u] had it's Registration Email changed to %s.", accountName.c_str(), targetAccountId, email); break; - case AOR_NAME_NOT_EXIST: + case AccountOpResult::AOR_NAME_NOT_EXIST: handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); return false; - case AOR_EMAIL_TOO_LONG: + case AccountOpResult::AOR_EMAIL_TOO_LONG: handler->SendSysMessage(LANG_EMAIL_TOO_LONG); handler->SetSentErrorMessage(true); return false; diff --git a/src/server/scripts/Commands/cs_ahbot.cpp b/src/server/scripts/Commands/cs_ahbot.cpp index 65e90394261..47553d085b1 100644 --- a/src/server/scripts/Commands/cs_ahbot.cpp +++ b/src/server/scripts/Commands/cs_ahbot.cpp @@ -33,7 +33,7 @@ class ahbot_commandscript : public CommandScript public: ahbot_commandscript(): CommandScript("ahbot_commandscript") {} - std::vector<ChatCommand> GetCommands() const + std::vector<ChatCommand> GetCommands() const override { static std::vector<ChatCommand> ahbotItemsAmountCommandTable = { diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp index 4a1bf71e1d8..ba512dbf8eb 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -171,7 +171,7 @@ public: switch (mode) { case BAN_ACCOUNT: - if (!AccountMgr::normalizeString(nameOrIP)) + if (!Utf8ToUpperOnlyLatin(nameOrIP)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, nameOrIP.c_str()); handler->SetSentErrorMessage(true); @@ -244,7 +244,7 @@ public: return false; std::string accountName = nameStr; - if (!AccountMgr::normalizeString(accountName)) + if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); @@ -712,7 +712,7 @@ public: switch (mode) { case BAN_ACCOUNT: - if (!AccountMgr::normalizeString(nameOrIP)) + if (!Utf8ToUpperOnlyLatin(nameOrIP)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, nameOrIP.c_str()); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index e048aabd4d7..01602e2f24c 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -133,7 +133,7 @@ public: info.name = fields[1].GetString(); info.accountId = fields[2].GetUInt32(); - // account name will be empty for not existed account + // account name will be empty for nonexisting account AccountMgr::GetName(info.accountId, info.accountName); info.deleteDate = time_t(fields[3].GetUInt32()); foundList.push_back(info); @@ -169,11 +169,11 @@ public: if (!handler->GetSession()) handler->PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CONSOLE, - itr->guid.GetCounter(), itr->name.c_str(), itr->accountName.empty() ? "<Not existed>" : itr->accountName.c_str(), + itr->guid.GetCounter(), itr->name.c_str(), itr->accountName.empty() ? "<Not existing>" : itr->accountName.c_str(), itr->accountId, dateStr.c_str()); else handler->PSendSysMessage(LANG_CHARACTER_DELETED_LIST_LINE_CHAT, - itr->guid.GetCounter(), itr->name.c_str(), itr->accountName.empty() ? "<Not existed>" : itr->accountName.c_str(), + itr->guid.GetCounter(), itr->name.c_str(), itr->accountName.empty() ? "<Not existing>" : itr->accountName.c_str(), itr->accountId, dateStr.c_str()); } @@ -193,7 +193,7 @@ public: */ static void HandleCharacterDeletedRestoreHelper(DeletedInfo const& delInfo, ChatHandler* handler) { - if (delInfo.accountName.empty()) // account not exist + if (delInfo.accountName.empty()) // account does not exist { handler->PSendSysMessage(LANG_CHARACTER_DELETED_SKIP_ACCOUNT, delInfo.name.c_str(), delInfo.guid.GetCounter(), delInfo.accountId); return; @@ -436,7 +436,7 @@ public: if (isalpha(levelStr[0])) { nameStr = levelStr; - levelStr = NULL; // current level will used + levelStr = nullptr; // current level will used } Player* target; @@ -660,7 +660,7 @@ public: if (newCharName.empty()) { - // Drop not existed account cases + // Drop nonexisting account cases for (DeletedInfoList::iterator itr = foundList.begin(); itr != foundList.end(); ++itr) HandleCharacterDeletedRestoreHelper(*itr, handler); } @@ -810,7 +810,7 @@ public: if (levelStr && isalpha(levelStr[0])) { nameStr = levelStr; - levelStr = NULL; // current level will used + levelStr = NULL; // current level will be used } Player* target; @@ -854,7 +854,7 @@ public: return false; std::string accountName = accountStr; - if (!AccountMgr::normalizeString(accountName)) + if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index b937fc4e0a4..570f4587ae8 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -34,8 +34,11 @@ EndScriptData */ #include "Transport.h" #include "Language.h" #include "MapManager.h" +#include "M2Stores.h" +#include "BattlefieldMgr.h" #include <fstream> +#include <limits> class debug_commandscript : public CommandScript { @@ -94,7 +97,8 @@ public: { "transport", rbac::RBAC_PERM_COMMAND_DEBUG_TRANSPORT, false, &HandleDebugTransportCommand, "" }, { "loadcells", rbac::RBAC_PERM_COMMAND_DEBUG_LOADCELLS, false, &HandleDebugLoadCellsCommand, "" }, { "boundary", rbac::RBAC_PERM_COMMAND_DEBUG_BOUNDARY, false, &HandleDebugBoundaryCommand, "" }, - { "raidreset", rbac::RBAC_PERM_COMMAND_INSTANCE_UNBIND, false, &HandleDebugRaidResetCommand, "" } + { "raidreset", rbac::RBAC_PERM_COMMAND_INSTANCE_UNBIND, false, &HandleDebugRaidResetCommand, "" }, + { "neargraveyard", rbac::RBAC_PERM_COMMAND_NEARGRAVEYARD, false, &HandleDebugNearGraveyard, "" }, }; static std::vector<ChatCommand> commandTable = { @@ -124,6 +128,23 @@ public: return false; } + // Dump camera locations + if (CinematicSequencesEntry const* cineSeq = sCinematicSequencesStore.LookupEntry(id)) + { + std::unordered_map<uint32, FlyByCameraCollection>::const_iterator itr = sFlyByCameraStore.find(cineSeq->cinematicCamera); + if (itr != sFlyByCameraStore.end()) + { + handler->PSendSysMessage("Waypoints for sequence %u, camera %u", id, cineSeq->cinematicCamera); + uint32 count = 1 ; + for (FlyByCamera cam : itr->second) + { + handler->PSendSysMessage("%02u - %7ums [%f, %f, %f] Facing %f (%f degrees)", count, cam.timeStamp, cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w, cam.locations.w * (180 / M_PI)); + count++; + } + handler->PSendSysMessage("%u waypoints dumped", itr->second.size()); + } + } + handler->GetSession()->GetPlayer()->SendCinematicStart(id); return true; } @@ -830,7 +851,7 @@ public: if (Unit* unit = ref->GetSource()->GetOwner()) { ++count; - handler->PSendSysMessage(" %u. %s (guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), ref->getThreat()); + handler->PSendSysMessage(" %u. %s (current guid %u, DB guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), unit->GetTypeId() == TYPEID_UNIT ? unit->ToCreature()->GetSpawnId() : 0, ref->getThreat()); } ref = ref->next(); } @@ -1045,7 +1066,8 @@ public: return false; uint32 animId = atoi((char*)args); - handler->GetSession()->GetPlayer()->HandleEmoteCommand(animId); + if (Unit* unit = handler->getSelectedUnit()) + unit->HandleEmoteCommand(animId); return true; } @@ -1409,10 +1431,7 @@ public: map = player->GetMap(); handler->PSendSysMessage("Loading all cells (mapId: %u). Current next GameObject %u, Creature %u", map->GetId(), map->GetMaxLowGuid<HighGuid::GameObject>(), map->GetMaxLowGuid<HighGuid::Unit>()); - for (uint32 cellX = 0; cellX < TOTAL_NUMBER_OF_CELLS_PER_MAP; cellX++) - for (uint32 cellY = 0; cellY < TOTAL_NUMBER_OF_CELLS_PER_MAP; cellY++) - map->LoadGrid((cellX + 0.5f - CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL, (cellY + 0.5f - CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL); - + map->LoadAllCells(); handler->PSendSysMessage("Cells loaded (mapId: %u) After load - Next GameObject %u, Creature %u", map->GetId(), map->GetMaxLowGuid<HighGuid::GameObject>(), map->GetMaxLowGuid<HighGuid::Unit>()); return true; } @@ -1436,7 +1455,7 @@ public: duration = 3 * MINUTE; bool doFill = fill_str ? (stricmp(fill_str, "FILL") == 0) : false; - + int32 errMsg = target->AI()->VisualizeBoundary(duration, player, doFill); if (errMsg > 0) handler->PSendSysMessage(errMsg); @@ -1469,6 +1488,53 @@ public: sInstanceSaveMgr->ForceGlobalReset(mEntry->MapID, Difficulty(difficulty)); return true; } + + static bool HandleDebugNearGraveyard(ChatHandler* handler, char const* args) + { + Player* player = handler->GetSession()->GetPlayer(); + const WorldSafeLocsEntry* nearestLoc = nullptr; + + if (stricmp(args, "linked")) + { + if (Battleground* bg = player->GetBattleground()) + nearestLoc = bg->GetClosestGraveYard(player); + else + { + if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(player->GetZoneId())) + nearestLoc = bf->GetClosestGraveYard(player); + else + nearestLoc = sObjectMgr->GetClosestGraveYard(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam()); + } + } + else + { + float x = player->GetPositionX(); + float y = player->GetPositionY(); + float z = player->GetPositionZ(); + float distNearest = std::numeric_limits<float>::max(); + + for (uint32 i = 0; i < sWorldSafeLocsStore.GetNumRows(); ++i) + { + const WorldSafeLocsEntry* loc = sWorldSafeLocsStore.LookupEntry(i); + if (loc && loc->map_id == player->GetMapId()) + { + float dist = (loc->x - x) * (loc->x - x) + (loc->y - y) * (loc->y - y) + (loc->z - z) * (loc->z - z); + if (dist < distNearest) + { + distNearest = dist; + nearestLoc = loc; + } + } + } + } + + if (nearestLoc) + handler->PSendSysMessage(LANG_COMMAND_NEARGRAVEYARD, nearestLoc->ID, nearestLoc->x, nearestLoc->y, nearestLoc->z); + else + handler->PSendSysMessage(LANG_COMMAND_NEARGRAVEYARD_NOTFOUND); + + return true; + } }; void AddSC_debug_commandscript() diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index e03942bc247..ffe8ea67816 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -164,7 +164,7 @@ public: ///- Get the accounts with GM Level >0 PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_GM_ACCOUNTS); stmt->setUInt8(0, uint8(SEC_MODERATOR)); - stmt->setInt32(1, int32(realmID)); + stmt->setInt32(1, int32(realm.Id.Realm)); PreparedQueryResult result = LoginDatabase.Query(stmt); if (result) diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 729dac0ad6f..c4ed6f650b9 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -139,16 +139,12 @@ public: } Player* player = handler->GetSession()->GetPlayer(); - float x = float(player->GetPositionX()); - float y = float(player->GetPositionY()); - float z = float(player->GetPositionZ()); - float o = float(player->GetOrientation()); Map* map = player->GetMap(); GameObject* object = new GameObject; ObjectGuid::LowType guidLow = map->GenerateLowGuid<HighGuid::GameObject>(); - if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) + if (!object->Create(guidLow, objectInfo->entry, map, player->GetPhaseMaskForSpawn(), *player, G3D::Quat(), 255, GO_STATE_READY)) { delete object; return false; @@ -179,7 +175,7 @@ public: /// @todo is it really necessary to add both the real and DB table guid here ? sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow)); - handler->PSendSysMessage(LANG_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), guidLow, x, y, z); + handler->PSendSysMessage(LANG_GAMEOBJECT_ADD, objectId, objectInfo->name.c_str(), guidLow, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); return true; } @@ -201,14 +197,7 @@ public: if (spawntime) spawntm = atoi((char*)spawntime); - float x = player->GetPositionX(); - float y = player->GetPositionY(); - float z = player->GetPositionZ(); - float ang = player->GetOrientation(); - - float rot2 = std::sin(ang/2); - float rot3 = std::cos(ang/2); - + G3D::Quat rotation = G3D::Matrix3::fromEulerAnglesZYX(player->GetOrientation(), 0.f, 0.f); uint32 objectId = atoi(id); if (!sObjectMgr->GetGameObjectTemplate(objectId)) @@ -218,7 +207,7 @@ public: return false; } - player->SummonGameObject(objectId, x, y, z, ang, 0, 0, rot2, rot3, spawntm); + player->SummonGameObject(objectId, *player, rotation, spawntm); return true; } @@ -415,20 +404,30 @@ public: } char* orientation = strtok(NULL, " "); - float o; + float oz = 0.f, oy = 0.f, ox = 0.f; if (orientation) - o = (float)atof(orientation); + { + oz = float(atof(orientation)); + + orientation = strtok(NULL, " "); + if (orientation) + { + oy = float(atof(orientation)); + orientation = strtok(NULL, " "); + if (orientation) + ox = float(atof(orientation)); + } + } else { Player* player = handler->GetSession()->GetPlayer(); - o = player->GetOrientation(); + oz = player->GetOrientation(); } Map* map = object->GetMap(); - - object->Relocate(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), o); - object->UpdateRotationFields(); + object->Relocate(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ()); + object->SetWorldRotationAngles(oz, oy, ox); object->SaveToDB(); // Generate a completely new spawn with new guid diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index 61e6acfb4d8..161ade1a30f 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -1343,7 +1343,7 @@ public: char* limitStr = strtok(NULL, " "); int32 limit = limitStr ? atoi(limitStr) : -1; - if (!AccountMgr::normalizeString + if (!Utf8ToUpperOnlyLatin (account)) return false; diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index c70246f7fb5..16217fbaea6 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -36,6 +36,7 @@ #include "MMapFactory.h" #include "DisableMgr.h" #include "SpellHistory.h" +#include "Transport.h" class misc_commandscript : public CommandScript { @@ -237,6 +238,10 @@ public: areaId, (areaEntry ? areaEntry->area_name[handler->GetSessionDbcLocale()] : unknown), object->GetPhaseMask(), object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation()); + if (Transport* transport = object->GetTransport()) + handler->PSendSysMessage(LANG_TRANSPORT_POSITION, + transport->GetGOInfo()->moTransport.mapID, object->GetTransOffsetX(), object->GetTransOffsetY(), object->GetTransOffsetZ(), object->GetTransOffsetO(), + transport->GetEntry(), transport->GetName().c_str()); handler->PSendSysMessage(LANG_GRID_POSITION, cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), object->GetInstanceId(), zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap, haveMMap); @@ -698,7 +703,7 @@ public: static bool HandleCooldownCommand(ChatHandler* handler, char const* args) { - Player* target = handler->getSelectedPlayerOrSelf(); + Unit* target = handler->getSelectedUnit(); if (!target) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); @@ -706,7 +711,14 @@ public: return false; } - std::string nameLink = handler->GetNameLink(target); + Player* owner = target->GetCharmerOrOwnerPlayerOrPlayerItself(); + if (!owner) + { + owner = handler->GetSession()->GetPlayer(); + target = owner; + } + + std::string nameLink = handler->GetNameLink(owner); if (!*args) { @@ -723,13 +735,13 @@ public: SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellIid); if (!spellInfo) { - handler->PSendSysMessage(LANG_UNKNOWN_SPELL, target == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str()); + handler->PSendSysMessage(LANG_UNKNOWN_SPELL, owner == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str()); handler->SetSentErrorMessage(true); return false; } target->GetSpellHistory()->ResetCooldown(spellIid, true); - handler->PSendSysMessage(LANG_REMOVE_COOLDOWN, spellIid, target == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str()); + handler->PSendSysMessage(LANG_REMOVE_COOLDOWN, spellIid, owner == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str()); } return true; } @@ -791,7 +803,7 @@ public: target->CleanupAfterTaxiFlight(); } - target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO); + target->Recall(); return true; } @@ -1588,7 +1600,7 @@ public: // Query the prepared statement for login data stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO); - stmt->setInt32(0, int32(realmID)); + stmt->setInt32(0, int32(realm.Id.Realm)); stmt->setUInt32(1, accId); PreparedQueryResult result = LoginDatabase.Query(stmt); @@ -1964,7 +1976,7 @@ public: return false; std::string accountName = nameStr; - if (!AccountMgr::normalizeString(accountName)) + if (!Utf8ToUpperOnlyLatin(accountName)) { handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); handler->SetSentErrorMessage(true); @@ -2119,17 +2131,9 @@ public: } return true; } - /* - ComeToMe command REQUIRED for 3rd party scripting library to have access to PointMovementGenerator - Without this function 3rd party scripting library will get linking errors (unresolved external) - when attempting to use the PointMovementGenerator - */ - static bool HandleComeToMeCommand(ChatHandler* handler, char const* args) - { - char const* newFlagStr = strtok((char*)args, " "); - if (!newFlagStr) - return false; + static bool HandleComeToMeCommand(ChatHandler* handler, char const* /*args*/) + { Creature* caster = handler->getSelectedCreature(); if (!caster) { diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index 761b4c9e0e6..e25018cf1bd 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -80,23 +80,32 @@ public: return commandTable; } - //Edit Player HP - static bool HandleModifyHPCommand(ChatHandler* handler, const char* args) + template<typename... Args> + static void NotifyModification(ChatHandler* handler, Unit* target, TrinityStrings resourceMessage, TrinityStrings resourceReportMessage, Args&&... args) + { + if (Player* player = target->ToPlayer()) + { + handler->PSendSysMessage(resourceMessage, handler->GetNameLink(player).c_str(), args...); + if (handler->needReportToTarget(player)) + ChatHandler(player->GetSession()).PSendSysMessage(resourceReportMessage, handler->GetNameLink().c_str(), std::forward<Args>(args)...); + } + } + + static bool CheckModifyResources(ChatHandler* handler, const char* args, Player* target, int32& res, int32& resmax, int8 const multiplier = 1) { if (!*args) return false; - int32 hp = atoi((char*)args); - int32 hpm = atoi((char*)args); + res = atoi((char*)args) * multiplier; + resmax = atoi((char*)args) * multiplier; - if (hp < 1 || hpm < 1 || hpm < hp) + if (res < 1 || resmax < 1 || resmax < res) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } - Player* target = handler->getSelectedPlayerOrSelf(); if (!target) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); @@ -107,164 +116,87 @@ public: if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; - handler->PSendSysMessage(LANG_YOU_CHANGE_HP, handler->GetNameLink(target).c_str(), hp, hpm); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_HP_CHANGED, handler->GetNameLink().c_str(), hp, hpm); - - target->SetMaxHealth(hpm); - target->SetHealth(hp); - return true; } - //Edit Player Mana - static bool HandleModifyManaCommand(ChatHandler* handler, const char* args) + //Edit Player HP + static bool HandleModifyHPCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - int32 mana = atoi((char*)args); - int32 manam = atoi((char*)args); - - if (mana <= 0 || manam <= 0 || manam < mana) + int32 hp, hpmax; + Player* target = handler->getSelectedPlayerOrSelf(); + if (CheckModifyResources(handler, args, target, hp, hpmax)) { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_HP, LANG_YOURS_HP_CHANGED, hp, hpmax); + target->SetMaxHealth(hpmax); + target->SetHealth(hp); + return true; } + return false; + } + //Edit Player Mana + static bool HandleModifyManaCommand(ChatHandler* handler, const char* args) + { + int32 mana, manamax; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + + if (CheckModifyResources(handler, args, target, mana, manamax)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_MANA, LANG_YOURS_MANA_CHANGED, mana, manamax); + target->SetMaxPower(POWER_MANA, manamax); + target->SetPower(POWER_MANA, mana); + return true; } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_MANA, handler->GetNameLink(target).c_str(), mana, manam); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_MANA_CHANGED, handler->GetNameLink().c_str(), mana, manam); - - target->SetMaxPower(POWER_MANA, manam); - target->SetPower(POWER_MANA, mana); - - return true; + return false; } //Edit Player Energy static bool HandleModifyEnergyCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - int32 energy = atoi((char*)args)*10; - int32 energym = atoi((char*)args)*10; - - if (energy <= 0 || energym <= 0 || energym < energy) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + int32 energy, energymax; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + int8 const energyMultiplier = 10; + if (CheckModifyResources(handler, args, target, energy, energymax, energyMultiplier)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_ENERGY, LANG_YOURS_ENERGY_CHANGED, energy / energyMultiplier, energymax / energyMultiplier); + target->SetMaxPower(POWER_ENERGY, energymax); + target->SetPower(POWER_ENERGY, energy); + TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_ENERGY), target->GetMaxPower(POWER_ENERGY)); + return true; } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_ENERGY, handler->GetNameLink(target).c_str(), energy/10, energym/10); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, handler->GetNameLink().c_str(), energy/10, energym/10); - - target->SetMaxPower(POWER_ENERGY, energym); - target->SetPower(POWER_ENERGY, energy); - - TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_ENERGY), target->GetMaxPower(POWER_ENERGY)); - - return true; + return false; } //Edit Player Rage static bool HandleModifyRageCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - int32 rage = atoi((char*)args)*10; - int32 ragem = atoi((char*)args)*10; - - if (rage <= 0 || ragem <= 0 || ragem < rage) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + int32 rage, ragemax; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + int8 const rageMultiplier = 10; + if (CheckModifyResources(handler, args, target, rage, ragemax, rageMultiplier)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_RAGE, LANG_YOURS_RAGE_CHANGED, rage / rageMultiplier, ragemax / rageMultiplier); + target->SetMaxPower(POWER_RAGE, ragemax); + target->SetPower(POWER_RAGE, rage); + return true; } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_RAGE, handler->GetNameLink(target).c_str(), rage/10, ragem/10); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, handler->GetNameLink().c_str(), rage/10, ragem/10); - - target->SetMaxPower(POWER_RAGE, ragem); - target->SetPower(POWER_RAGE, rage); - - return true; + return false; } // Edit Player Runic Power static bool HandleModifyRunicPowerCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - int32 rune = atoi((char*)args)*10; - int32 runem = atoi((char*)args)*10; - - if (rune <= 0 || runem <= 0 || runem < rune) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + int32 rune, runemax; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + int8 const runeMultiplier = 10; + if (CheckModifyResources(handler, args, target, rune, runemax, runeMultiplier)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_RUNIC_POWER, LANG_YOURS_RUNIC_POWER_CHANGED, rune / runeMultiplier, runemax / runeMultiplier); + target->SetMaxPower(POWER_RUNIC_POWER, runemax); + target->SetPower(POWER_RUNIC_POWER, rune); + return true; } - - handler->PSendSysMessage(LANG_YOU_CHANGE_RUNIC_POWER, handler->GetNameLink(target).c_str(), rune/10, runem/10); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_RUNIC_POWER_CHANGED, handler->GetNameLink().c_str(), rune/10, runem/10); - - target->SetMaxPower(POWER_RUNIC_POWER, runem); - target->SetPower(POWER_RUNIC_POWER, rune); - - return true; + return false; } //Edit Player Faction @@ -437,22 +369,20 @@ public: return false; } - //Edit Player Aspeed - static bool HandleModifyASpeedCommand(ChatHandler* handler, const char* args) + static bool CheckModifySpeed(ChatHandler* handler, const char* args, Unit* target, float& speed, float minimumBound, float maximumBound, bool checkInFlight = true) { if (!*args) return false; - float ASpeed = (float)atof((char*)args); + speed = (float)atof((char*)args); - if (ASpeed > 50.0f || ASpeed < 0.1f) + if (speed > maximumBound || speed < minimumBound) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } - Player* target = handler->getSelectedPlayerOrSelf(); if (!target) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); @@ -460,238 +390,107 @@ public: return false; } - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - std::string targetNameLink = handler->GetNameLink(target); - - if (target->IsInFlight()) + if (Player* player = target->ToPlayer()) { - handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; - } - - handler->PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, targetNameLink.c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, handler->GetNameLink().c_str(), ASpeed); + // check online security + if (handler->HasLowerSecurity(player, ObjectGuid::Empty)) + return false; - target->SetSpeed(MOVE_WALK, ASpeed, true); - target->SetSpeed(MOVE_RUN, ASpeed, true); - target->SetSpeed(MOVE_SWIM, ASpeed, true); - //target->SetSpeed(MOVE_TURN, ASpeed, true); - target->SetSpeed(MOVE_FLIGHT, ASpeed, true); + if (player->IsInFlight() && checkInFlight) + { + handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, handler->GetNameLink(player).c_str()); + handler->SetSentErrorMessage(true); + return false; + } + } return true; } - //Edit Player Speed - static bool HandleModifySpeedCommand(ChatHandler* handler, const char* args) + //Edit Player Aspeed + static bool HandleModifyASpeedCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float Speed = (float)atof((char*)args); - - if (Speed > 50.0f || Speed < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float allSpeed; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + if (CheckModifySpeed(handler, args, target, allSpeed, 0.1f, 50.0f)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_ASPEED, LANG_YOURS_ASPEED_CHANGED, allSpeed); + target->SetSpeedRate(MOVE_WALK, allSpeed); + target->SetSpeedRate(MOVE_RUN, allSpeed); + target->SetSpeedRate(MOVE_SWIM, allSpeed); + target->SetSpeedRate(MOVE_FLIGHT, allSpeed); + return true; } + return false; + } - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - std::string targetNameLink = handler->GetNameLink(target); - - if (target->IsInFlight()) + //Edit Player Speed + static bool HandleModifySpeedCommand(ChatHandler* handler, const char* args) + { + float Speed; + Player* target = handler->getSelectedPlayerOrSelf(); + if (CheckModifySpeed(handler, args, target, Speed, 0.1f, 50.0f)) { - handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_SPEED, LANG_YOURS_SPEED_CHANGED, Speed); + target->SetSpeedRate(MOVE_RUN, Speed); + return true; } - - handler->PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, targetNameLink.c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, handler->GetNameLink().c_str(), Speed); - - target->SetSpeed(MOVE_RUN, Speed, true); - - return true; + return false; } //Edit Player Swim Speed static bool HandleModifySwimCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float Swim = (float)atof((char*)args); - - if (Swim > 50.0f || Swim < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float swimSpeed; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + if (CheckModifySpeed(handler, args, target, swimSpeed, 0.1f, 50.0f)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; - } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - std::string targetNameLink = handler->GetNameLink(target); - - if (target->IsInFlight()) - { - handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_SWIM_SPEED, LANG_YOURS_SWIM_SPEED_CHANGED, swimSpeed); + target->SetSpeedRate(MOVE_SWIM, swimSpeed); + return true; } - - handler->PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, targetNameLink.c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, handler->GetNameLink().c_str(), Swim); - - target->SetSpeed(MOVE_SWIM, Swim, true); - - return true; + return false; } - //Edit Player Walk Speed + //Edit Player Backwards Walk Speed static bool HandleModifyBWalkCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float BSpeed = (float)atof((char*)args); - - if (BSpeed > 50.0f || BSpeed < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float backSpeed; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + if (CheckModifySpeed(handler, args, target, backSpeed, 0.1f, 50.0f)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; - } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - std::string targetNameLink = handler->GetNameLink(target); - - if (target->IsInFlight()) - { - handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_BACK_SPEED, LANG_YOURS_BACK_SPEED_CHANGED, backSpeed); + target->SetSpeedRate(MOVE_RUN_BACK, backSpeed); + return true; } - - handler->PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, targetNameLink.c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, handler->GetNameLink().c_str(), BSpeed); - - target->SetSpeed(MOVE_RUN_BACK, BSpeed, true); - - return true; + return false; } //Edit Player Fly static bool HandleModifyFlyCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float FSpeed = (float)atof((char*)args); - - if (FSpeed > 50.0f || FSpeed < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float flySpeed; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + if (CheckModifySpeed(handler, args, target, flySpeed, 0.1f, 50.0f, false)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_FLY_SPEED, LANG_YOURS_FLY_SPEED_CHANGED, flySpeed); + target->SetSpeedRate(MOVE_FLIGHT, flySpeed); + return true; } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, handler->GetNameLink(target).c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, handler->GetNameLink().c_str(), FSpeed); - - target->SetSpeed(MOVE_FLIGHT, FSpeed, true); - - return true; + return false; } //Edit Player or Creature Scale static bool HandleModifyScaleCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float Scale = (float)atof((char*)args); - if (Scale > 10.0f || Scale < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float Scale; Unit* target = handler->getSelectedUnit(); - if (!target) + if (CheckModifySpeed(handler, args, target, Scale, 0.1f, 10.0f, false)) { - handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - handler->SetSentErrorMessage(true); - return false; - } - - if (Player* player = target->ToPlayer()) - { - // check online security - if (handler->HasLowerSecurity(player, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, handler->GetNameLink(player).c_str()); - if (handler->needReportToTarget(player)) - ChatHandler(player->GetSession()).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, handler->GetNameLink().c_str(), Scale); + NotifyModification(handler, target, LANG_YOU_CHANGE_SIZE, LANG_YOURS_SIZE_CHANGED, Scale); + target->SetObjectScale(Scale); + return true; } - - target->SetObjectScale(Scale); - - return true; + return false; } //Enable Player mount @@ -932,9 +731,7 @@ public: if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; - handler->PSendSysMessage(LANG_YOU_GIVE_MOUNT, handler->GetNameLink(target).c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_MOUNT_GIVED, handler->GetNameLink().c_str()); + NotifyModification(handler, target, LANG_YOU_GIVE_MOUNT, LANG_MOUNT_GIVED); target->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); target->Mount(mId); @@ -988,10 +785,7 @@ public: TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_MONEY), targetMoney, moneyToAdd, newmoney); if (newmoney <= 0) { - handler->PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, handler->GetNameLink(target).c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, handler->GetNameLink().c_str()); - + NotifyModification(handler, target, LANG_YOU_TAKE_ALL_MONEY, LANG_YOURS_ALL_MONEY_GONE); target->SetMoney(0); } else @@ -1339,8 +1133,8 @@ public: } // Set gender - target->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); - target->SetByteValue(PLAYER_BYTES_3, 0, gender); + target->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, gender); + target->SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER, gender); // Change display ID target->InitDisplayIds(); diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index fbd199b99db..38aa96a6a66 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -113,7 +113,7 @@ EnumName<UnitFlags> const unitFlags[MAX_UNIT_FLAGS] = { CREATE_NAMED_ENUM(UNIT_FLAG_SERVER_CONTROLLED), CREATE_NAMED_ENUM(UNIT_FLAG_NON_ATTACKABLE), - CREATE_NAMED_ENUM(UNIT_FLAG_DISABLE_MOVE), + CREATE_NAMED_ENUM(UNIT_FLAG_REMOVE_CLIENT_CONTROL), CREATE_NAMED_ENUM(UNIT_FLAG_PVP_ATTACKABLE), CREATE_NAMED_ENUM(UNIT_FLAG_RENAME), CREATE_NAMED_ENUM(UNIT_FLAG_PREPARATION), @@ -125,7 +125,7 @@ EnumName<UnitFlags> const unitFlags[MAX_UNIT_FLAGS] = CREATE_NAMED_ENUM(UNIT_FLAG_PET_IN_COMBAT), CREATE_NAMED_ENUM(UNIT_FLAG_PVP), CREATE_NAMED_ENUM(UNIT_FLAG_SILENCED), - CREATE_NAMED_ENUM(UNIT_FLAG_UNK_14), + CREATE_NAMED_ENUM(UNIT_FLAG_CANNOT_SWIM), CREATE_NAMED_ENUM(UNIT_FLAG_UNK_15), CREATE_NAMED_ENUM(UNIT_FLAG_UNK_16), CREATE_NAMED_ENUM(UNIT_FLAG_PACIFIED), @@ -220,14 +220,15 @@ public: { "whisper", rbac::RBAC_PERM_COMMAND_NPC_WHISPER, false, &HandleNpcWhisperCommand, "" }, { "yell", rbac::RBAC_PERM_COMMAND_NPC_YELL, false, &HandleNpcYellCommand, "" }, { "tame", rbac::RBAC_PERM_COMMAND_NPC_TAME, false, &HandleNpcTameCommand, "" }, - { "add", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, NULL, "", npcAddCommandTable }, - { "delete", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, NULL, "", npcDeleteCommandTable }, - { "follow", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, NULL, "", npcFollowCommandTable }, - { "set", rbac::RBAC_PERM_COMMAND_NPC_SET, false, NULL, "", npcSetCommandTable }, + { "add", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, nullptr, "", npcAddCommandTable }, + { "delete", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, nullptr, "", npcDeleteCommandTable }, + { "follow", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, nullptr, "", npcFollowCommandTable }, + { "set", rbac::RBAC_PERM_COMMAND_NPC_SET, false, nullptr, "", npcSetCommandTable }, + { "evade", rbac::RBAC_PERM_COMMAND_NPC_EVADE, false, &HandleNpcEvadeCommand, "" }, }; static std::vector<ChatCommand> commandTable = { - { "npc", rbac::RBAC_PERM_COMMAND_NPC, false, NULL, "", npcCommandTable }, + { "npc", rbac::RBAC_PERM_COMMAND_NPC, false, nullptr, "", npcCommandTable }, }; return commandTable; } @@ -318,17 +319,17 @@ public: uint32 itemId = item_int; - char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 + char* fmaxcount = strtok(nullptr, " "); //add maxcount, default: 0 uint32 maxcount = 0; if (fmaxcount) maxcount = atoul(fmaxcount); - char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 + char* fincrtime = strtok(nullptr, " "); //add incrtime, default: 0 uint32 incrtime = 0; if (fincrtime) incrtime = atoul(fincrtime); - char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 + char* fextendedcost = strtok(nullptr, " "); //add ExtendedCost, default: 0 uint32 extendedcost = fextendedcost ? atoul(fextendedcost) : 0; Creature* vendor = handler->getSelectedCreature(); if (!vendor) @@ -361,7 +362,7 @@ public: return false; char* guidStr = strtok((char*)args, " "); - char* waitStr = strtok((char*)NULL, " "); + char* waitStr = strtok((char*)nullptr, " "); ObjectGuid::LowType lowGuid = atoi((char*)guidStr); @@ -446,36 +447,24 @@ public: } Creature* creature = handler->getSelectedCreature(); - if (!creature) + if (!creature || creature->IsPet()) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } - if (creature->IsPet()) - { - if (((Pet*)creature)->getPetType() == HUNTER_PET) - { - creature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr->GetXPForLevel(lvl)/4); - creature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); - } - ((Pet*)creature)->GivePetLevel(lvl); - } - else - { - creature->SetMaxHealth(100 + 30*lvl); - creature->SetHealth(100 + 30*lvl); - creature->SetLevel(lvl); - creature->SaveToDB(); - } + creature->SetMaxHealth(100 + 30*lvl); + creature->SetHealth(100 + 30*lvl); + creature->SetLevel(lvl); + creature->SaveToDB(); return true; } static bool HandleNpcDeleteCommand(ChatHandler* handler, char const* args) { - Creature* unit = NULL; + Creature* unit = nullptr; if (*args) { @@ -628,7 +617,7 @@ public: return false; char* arg1 = strtok((char*)args, " "); - char* arg2 = strtok((char*)NULL, ""); + char* arg2 = strtok((char*)nullptr, ""); if (!arg1 || !arg2) return false; @@ -926,8 +915,8 @@ public: // later switched on/off according to special events (like escort // quests, etc) char* guid_str = strtok((char*)args, " "); - char* type_str = strtok((char*)NULL, " "); - char* dontdel_str = strtok((char*)NULL, " "); + char* type_str = strtok((char*)nullptr, " "); + char* dontdel_str = strtok((char*)nullptr, " "); bool doNotDelete = false; @@ -935,7 +924,7 @@ public: return false; ObjectGuid::LowType lowguid = 0; - Creature* creature = NULL; + Creature* creature = nullptr; if (dontdel_str) { @@ -961,7 +950,7 @@ public: { //TC_LOG_ERROR("misc", "DEBUG: type_str, NODEL "); doNotDelete = true; - type_str = NULL; + type_str = nullptr; } } } @@ -1001,7 +990,7 @@ public: } // now lowguid is low guid really existed creature - // and creature point (maybe) to this creature or NULL + // and creature point (maybe) to this creature or nullptr MovementGeneratorType move_type; @@ -1260,7 +1249,7 @@ public: } char* receiver_str = strtok((char*)args, " "); - char* text = strtok(NULL, ""); + char* text = strtok(nullptr, ""); if (!receiver_str || !text) { @@ -1319,7 +1308,16 @@ public: if (!*args) return false; - char* charID = handler->extractKeyFromLink((char*)args, "Hcreature_entry"); + bool loot = false; + char const* spawntype_str = strtok((char*)args, " "); + char const* entry_str = strtok(nullptr, ""); + if (stricmp(spawntype_str, "LOOT") == 0) + loot = true; + else if (stricmp(spawntype_str, "NOLOOT") == 0) + loot = false; + else + entry_str = args; + char* charID = handler->extractKeyFromLink((char*)entry_str, "Hcreature_entry"); if (!charID) return false; @@ -1332,7 +1330,7 @@ public: if (!sObjectMgr->GetCreatureTemplate(id)) return false; - chr->SummonCreature(id, *chr, TEMPSUMMON_CORPSE_DESPAWN, 120); + chr->SummonCreature(id, *chr, loot ? TEMPSUMMON_CORPSE_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN, 30 * IN_MILLISECONDS); return true; } @@ -1404,6 +1402,51 @@ public: return true; } + static bool HandleNpcEvadeCommand(ChatHandler* handler, char const* args) + { + Creature* creatureTarget = handler->getSelectedCreature(); + if (!creatureTarget || creatureTarget->IsPet()) + { + handler->PSendSysMessage(LANG_SELECT_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + if (!creatureTarget->IsAIEnabled) + { + handler->PSendSysMessage(LANG_CREATURE_NOT_AI_ENABLED); + handler->SetSentErrorMessage(true); + return false; + } + + char* type_str = args ? strtok((char*)args, " ") : nullptr; + char* force_str = args ? strtok(nullptr, " ") : nullptr; + + CreatureAI::EvadeReason why = CreatureAI::EVADE_REASON_OTHER; + bool force = false; + if (type_str) + { + if (stricmp(type_str, "NO_HOSTILES") == 0 || stricmp(type_str, "EVADE_REASON_NO_HOSTILES") == 0) + why = CreatureAI::EVADE_REASON_NO_HOSTILES; + else if (stricmp(type_str, "BOUNDARY") == 0 || stricmp(type_str, "EVADE_REASON_BOUNDARY") == 0) + why = CreatureAI::EVADE_REASON_BOUNDARY; + else if (stricmp(type_str, "SEQUENCE_BREAK") == 0 || stricmp(type_str, "EVADE_REASON_SEQUENCE_BREAK") == 0) + why = CreatureAI::EVADE_REASON_SEQUENCE_BREAK; + else if (stricmp(type_str, "FORCE") == 0) + force = true; + + if (!force && force_str) + if (stricmp(force_str, "FORCE") == 0) + force = true; + } + + if (force) + creatureTarget->ClearUnitState(UNIT_STATE_EVADE); + creatureTarget->AI()->EnterEvadeMode(why); + + return true; + } + static bool HandleNpcAddFormationCommand(ChatHandler* handler, char const* args) { if (!*args) @@ -1515,7 +1558,7 @@ public: if (!pSlotID) return false; - char* pItemID = strtok(NULL, " "); + char* pItemID = strtok(nullptr, " "); if (!pItemID) return false; diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp index 4f0a179142d..a86de766117 100644 --- a/src/server/scripts/Commands/cs_pet.cpp +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -22,6 +22,19 @@ #include "ObjectMgr.h" #include "ScriptMgr.h" +static inline Pet* GetSelectedPlayerPetOrOwn(ChatHandler* handler) +{ + if (Unit* target = handler->getSelectedUnit()) + { + if (target->GetTypeId() == TYPEID_PLAYER) + return target->ToPlayer()->GetPet(); + if (target->IsPet()) + return target->ToPet(); + return nullptr; + } + Player* player = handler->GetSession()->GetPlayer(); + return player ? player->GetPet() : nullptr; +} class pet_commandscript : public CommandScript { public: @@ -34,6 +47,7 @@ public: { "create", rbac::RBAC_PERM_COMMAND_PET_CREATE, false, &HandlePetCreateCommand, "" }, { "learn", rbac::RBAC_PERM_COMMAND_PET_LEARN, false, &HandlePetLearnCommand, "" }, { "unlearn", rbac::RBAC_PERM_COMMAND_PET_UNLEARN, false, &HandlePetUnlearnCommand, "" }, + { "level", rbac::RBAC_PERM_COMMAND_PET_LEVEL, false, &HandlePetLevelCommand, "" }, }; static std::vector<ChatCommand> commandTable = @@ -54,11 +68,11 @@ public: return false; } - CreatureTemplate const* creatrueTemplate = creatureTarget->GetCreatureTemplate(); - // Creatures with family 0 crashes the server - if (!creatrueTemplate->family) + CreatureTemplate const* creatureTemplate = creatureTarget->GetCreatureTemplate(); + // Creatures with family CREATURE_FAMILY_NONE crashes the server + if (creatureTemplate->family == CREATURE_FAMILY_NONE) { - handler->PSendSysMessage("This creature cannot be tamed. (family id: 0)."); + handler->PSendSysMessage("This creature cannot be tamed. Family id: 0 (CREATURE_FAMILY_NONE)."); handler->SetSentErrorMessage(true); return false; } @@ -119,12 +133,11 @@ public: if (!*args) return false; - Player* player = handler->GetSession()->GetPlayer(); - Pet* pet = player->GetPet(); + Pet* pet = GetSelectedPlayerPetOrOwn(handler); if (!pet) { - handler->PSendSysMessage("You have no pet"); + handler->SendSysMessage(LANG_SELECT_PLAYER_OR_PET); handler->SetSentErrorMessage(true); return false; } @@ -162,11 +175,10 @@ public: if (!*args) return false; - Player* player = handler->GetSession()->GetPlayer(); - Pet* pet = player->GetPet(); + Pet* pet = GetSelectedPlayerPetOrOwn(handler); if (!pet) { - handler->PSendSysMessage("You have no pet"); + handler->SendSysMessage(LANG_SELECT_PLAYER_OR_PET); handler->SetSentErrorMessage(true); return false; } @@ -180,6 +192,37 @@ public: return true; } + + static bool HandlePetLevelCommand(ChatHandler* handler, char const* args) + { + Pet* pet = GetSelectedPlayerPetOrOwn(handler); + Player* owner = pet ? pet->GetOwner() : nullptr; + if (!pet || !owner) + { + handler->SendSysMessage(LANG_SELECT_PLAYER_OR_PET); + handler->SetSentErrorMessage(true); + return false; + } + + int32 level = args ? atoi(args) : 0; + if (level == 0) + level = owner->getLevel() - pet->getLevel(); + if (level == 0 || level < -STRONG_MAX_LEVEL || level > STRONG_MAX_LEVEL) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + int32 newLevel = pet->getLevel() + level; + if (newLevel < 1) + newLevel = 1; + else if (newLevel > owner->getLevel()) + newLevel = owner->getLevel(); + + pet->GivePetLevel(newLevel); + return true; + } }; void AddSC_pet_commandscript() diff --git a/src/server/scripts/Commands/cs_rbac.cpp b/src/server/scripts/Commands/cs_rbac.cpp index f7c2d21c12d..64692c4d0ed 100644 --- a/src/server/scripts/Commands/cs_rbac.cpp +++ b/src/server/scripts/Commands/cs_rbac.cpp @@ -49,7 +49,7 @@ class rbac_commandscript : public CommandScript public: rbac_commandscript() : CommandScript("rbac_commandscript") { } - std::vector<ChatCommand> GetCommands() const + std::vector<ChatCommand> GetCommands() const override { static std::vector<ChatCommand> rbacAccountCommandTable = { @@ -139,7 +139,7 @@ public: { accountName = param1; - if (AccountMgr::normalizeString(accountName)) + if (Utf8ToUpperOnlyLatin(accountName)) accountId = AccountMgr::GetId(accountName); if (!accountId) @@ -157,7 +157,7 @@ public: if (!rdata) { - data->rbac = new rbac::RBACData(accountId, accountName, realmID, AccountMgr::GetSecurity(accountId, realmID)); + data->rbac = new rbac::RBACData(accountId, accountName, realm.Id.Realm, AccountMgr::GetSecurity(accountId, realm.Id.Realm)); data->rbac->LoadFromDB(); data->needDelete = true; } diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 56b0dbf43d0..4470fa7de42 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -91,7 +91,7 @@ public: { "disenchant_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesDisenchantCommand, "" }, { "event_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS, true, &HandleReloadEventScriptsCommand, "" }, { "fishing_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_FISHING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesFishingCommand, "" }, - { "game_graveyard_zone", rbac::RBAC_PERM_COMMAND_RELOAD_GAME_GRAVEYARD_ZONE, true, &HandleReloadGameGraveyardZoneCommand, "" }, + { "graveyard_zone", rbac::RBAC_PERM_COMMAND_RELOAD_GRAVEYARD_ZONE, true, &HandleReloadGameGraveyardZoneCommand, "" }, { "game_tele", rbac::RBAC_PERM_COMMAND_RELOAD_GAME_TELE, true, &HandleReloadGameTeleCommand, "" }, { "gameobject_questender", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTENDER, true, &HandleReloadGOQuestEnderCommand, "" }, { "gameobject_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesGameobjectCommand, "" }, @@ -251,7 +251,7 @@ public: static bool HandleReloadAllScriptsCommand(ChatHandler* handler, const char* /*args*/) { - if (sScriptMgr->IsScriptScheduled()) + if (sMapMgr->IsScriptScheduled()) { handler->PSendSysMessage("DB scripts used currently, please attempt reload later."); handler->SetSentErrorMessage(true); @@ -393,7 +393,7 @@ public: static bool HandleReloadCommandCommand(ChatHandler* handler, const char* /*args*/) { - handler->SetLoadCommandTable(true); + ChatHandler::invalidateCommandTable(); handler->SendGlobalGMSysMessage("DB table `command` will be reloaded at next chat command use."); return true; } @@ -893,7 +893,7 @@ public: static bool HandleReloadEventScriptsCommand(ChatHandler* handler, const char* args) { - if (sScriptMgr->IsScriptScheduled()) + if (sMapMgr->IsScriptScheduled()) { handler->SendSysMessage("DB scripts used currently, please attempt reload later."); handler->SetSentErrorMessage(true); @@ -913,7 +913,7 @@ public: static bool HandleReloadWpScriptsCommand(ChatHandler* handler, const char* args) { - if (sScriptMgr->IsScriptScheduled()) + if (sMapMgr->IsScriptScheduled()) { handler->SendSysMessage("DB scripts used currently, please attempt reload later."); handler->SetSentErrorMessage(true); @@ -946,7 +946,7 @@ public: static bool HandleReloadSpellScriptsCommand(ChatHandler* handler, const char* args) { - if (sScriptMgr->IsScriptScheduled()) + if (sMapMgr->IsScriptScheduled()) { handler->SendSysMessage("DB scripts used currently, please attempt reload later."); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index 05941120423..ba1dab28350 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -102,7 +102,7 @@ public: player->setFactionForRace(player->getRace()); - player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powerType << 24))); + player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, powerType); // reset only if player not in some form; if (player->GetShapeshiftForm() == FORM_NONE) diff --git a/src/server/scripts/Commands/cs_script_loader.cpp b/src/server/scripts/Commands/cs_script_loader.cpp new file mode 100644 index 00000000000..449e7053942 --- /dev/null +++ b/src/server/scripts/Commands/cs_script_loader.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +void AddSC_account_commandscript(); +void AddSC_achievement_commandscript(); +void AddSC_ahbot_commandscript(); +void AddSC_arena_commandscript(); +void AddSC_ban_commandscript(); +void AddSC_bf_commandscript(); +void AddSC_cast_commandscript(); +void AddSC_character_commandscript(); +void AddSC_cheat_commandscript(); +void AddSC_debug_commandscript(); +void AddSC_deserter_commandscript(); +void AddSC_disable_commandscript(); +void AddSC_event_commandscript(); +void AddSC_gm_commandscript(); +void AddSC_go_commandscript(); +void AddSC_gobject_commandscript(); +void AddSC_group_commandscript(); +void AddSC_guild_commandscript(); +void AddSC_honor_commandscript(); +void AddSC_instance_commandscript(); +void AddSC_learn_commandscript(); +void AddSC_lfg_commandscript(); +void AddSC_list_commandscript(); +void AddSC_lookup_commandscript(); +void AddSC_message_commandscript(); +void AddSC_misc_commandscript(); +void AddSC_mmaps_commandscript(); +void AddSC_modify_commandscript(); +void AddSC_npc_commandscript(); +void AddSC_pet_commandscript(); +void AddSC_quest_commandscript(); +void AddSC_rbac_commandscript(); +void AddSC_reload_commandscript(); +void AddSC_reset_commandscript(); +void AddSC_send_commandscript(); +void AddSC_server_commandscript(); +void AddSC_tele_commandscript(); +void AddSC_ticket_commandscript(); +void AddSC_titles_commandscript(); +void AddSC_wp_commandscript(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddCommandsScripts() +{ + AddSC_account_commandscript(); + AddSC_achievement_commandscript(); + AddSC_ahbot_commandscript(); + AddSC_arena_commandscript(); + AddSC_ban_commandscript(); + AddSC_bf_commandscript(); + AddSC_cast_commandscript(); + AddSC_character_commandscript(); + AddSC_cheat_commandscript(); + AddSC_debug_commandscript(); + AddSC_deserter_commandscript(); + AddSC_disable_commandscript(); + AddSC_event_commandscript(); + AddSC_gm_commandscript(); + AddSC_go_commandscript(); + AddSC_gobject_commandscript(); + AddSC_group_commandscript(); + AddSC_guild_commandscript(); + AddSC_honor_commandscript(); + AddSC_instance_commandscript(); + AddSC_learn_commandscript(); + AddSC_lookup_commandscript(); + AddSC_lfg_commandscript(); + AddSC_list_commandscript(); + AddSC_message_commandscript(); + AddSC_misc_commandscript(); + AddSC_mmaps_commandscript(); + AddSC_modify_commandscript(); + AddSC_npc_commandscript(); + AddSC_quest_commandscript(); + AddSC_pet_commandscript(); + AddSC_rbac_commandscript(); + AddSC_reload_commandscript(); + AddSC_reset_commandscript(); + AddSC_send_commandscript(); + AddSC_server_commandscript(); + AddSC_tele_commandscript(); + AddSC_ticket_commandscript(); + AddSC_titles_commandscript(); + AddSC_wp_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_send.cpp b/src/server/scripts/Commands/cs_send.cpp index 672db3a3ab0..31544543426 100644 --- a/src/server/scripts/Commands/cs_send.cpp +++ b/src/server/scripts/Commands/cs_send.cpp @@ -74,7 +74,7 @@ public: std::string subject = msgSubject; std::string text = msgText; - // from console show not existed sender + // from console, use non-existing sender MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUID().GetCounter() : 0, MAIL_STATIONERY_GM); /// @todo Fix poor design @@ -173,7 +173,7 @@ public: } } - // from console show not existed sender + // from console show nonexisting sender MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUID().GetCounter() : 0, MAIL_STATIONERY_GM); // fill mail @@ -185,7 +185,7 @@ public: { if (Item* item = Item::CreateItem(itr->first, itr->second, handler->GetSession() ? handler->GetSession()->GetPlayer() : 0)) { - item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted + item->SaveToDB(trans); // Save to prevent being lost at next mail load. If send fails, the item will be deleted. draft.AddItem(item); } } @@ -233,7 +233,7 @@ public: std::string subject = msgSubject; std::string text = msgText; - // from console show not existed sender + // from console show nonexisting sender MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUID().GetCounter() : 0, MAIL_STATIONERY_GM); SQLTransaction trans = CharacterDatabase.BeginTransaction(); @@ -260,7 +260,7 @@ public: if (!msgStr) return false; - ///- Check that he is not logging out. + /// - Check if player is logging out. if (player->GetSession()->isLogingOut()) { handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 83bc2e47674..47239dba720 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -29,6 +29,7 @@ EndScriptData */ #include "Player.h" #include "ScriptMgr.h" #include "GitRevision.h" +#include "Util.h" class server_commandscript : public CommandScript { @@ -52,12 +53,14 @@ public: static std::vector<ChatCommand> serverRestartCommandTable = { { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_RESTART_CANCEL, true, &HandleServerShutDownCancelCommand, "" }, + { "force", rbac::RBAC_PERM_COMMAND_SERVER_RESTART_FORCE, true, &HandleServerForceRestartCommand, "" }, { "" , rbac::RBAC_PERM_COMMAND_SERVER_RESTART, true, &HandleServerRestartCommand, "" }, }; static std::vector<ChatCommand> serverShutdownCommandTable = { { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN_CANCEL, true, &HandleServerShutDownCancelCommand, "" }, + { "force", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN_FORCE, true, &HandleServerForceShutDownCommand, "" }, { "" , rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, &HandleServerShutDownCommand, "" }, }; @@ -73,19 +76,19 @@ public: { { "corpses", rbac::RBAC_PERM_COMMAND_SERVER_CORPSES, true, &HandleServerCorpsesCommand, "" }, { "exit", rbac::RBAC_PERM_COMMAND_SERVER_EXIT, true, &HandleServerExitCommand, "" }, - { "idlerestart", rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, NULL, "", serverIdleRestartCommandTable }, - { "idleshutdown", rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, NULL, "", serverIdleShutdownCommandTable }, + { "idlerestart", rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, nullptr, "", serverIdleRestartCommandTable }, + { "idleshutdown", rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, nullptr, "", serverIdleShutdownCommandTable }, { "info", rbac::RBAC_PERM_COMMAND_SERVER_INFO, true, &HandleServerInfoCommand, "" }, { "motd", rbac::RBAC_PERM_COMMAND_SERVER_MOTD, true, &HandleServerMotdCommand, "" }, { "plimit", rbac::RBAC_PERM_COMMAND_SERVER_PLIMIT, true, &HandleServerPLimitCommand, "" }, - { "restart", rbac::RBAC_PERM_COMMAND_SERVER_RESTART, true, NULL, "", serverRestartCommandTable }, - { "shutdown", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, NULL, "", serverShutdownCommandTable }, - { "set", rbac::RBAC_PERM_COMMAND_SERVER_SET, true, NULL, "", serverSetCommandTable }, + { "restart", rbac::RBAC_PERM_COMMAND_SERVER_RESTART, true, nullptr, "", serverRestartCommandTable }, + { "shutdown", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, nullptr, "", serverShutdownCommandTable }, + { "set", rbac::RBAC_PERM_COMMAND_SERVER_SET, true, nullptr, "", serverSetCommandTable }, }; static std::vector<ChatCommand> commandTable = { - { "server", rbac::RBAC_PERM_COMMAND_SERVER, true, NULL, "", serverCommandTable }, + { "server", rbac::RBAC_PERM_COMMAND_SERVER, true, nullptr, "", serverCommandTable }, }; return commandTable; } @@ -192,19 +195,34 @@ public: return true; } - static bool HandleServerShutDownCommand(ChatHandler* /*handler*/, char const* args) + static bool IsOnlyUser(WorldSession* mySession) { - return ShutdownServer(args, 0, SHUTDOWN_EXIT_CODE); + // check if there is any session connected from a different address + std::string myAddr = mySession ? mySession->GetRemoteAddress() : ""; + SessionMap const& sessions = sWorld->GetAllSessions(); + for (SessionMap::value_type const& session : sessions) + if (session.second && myAddr != session.second->GetRemoteAddress()) + return false; + return true; + } + static bool HandleServerShutDownCommand(ChatHandler* handler, char const* args) + { + return ShutdownServer(args, IsOnlyUser(handler->GetSession()) ? SHUTDOWN_MASK_FORCE : 0, SHUTDOWN_EXIT_CODE); } - static bool HandleServerRestartCommand(ChatHandler* /*handler*/, char const* args) + static bool HandleServerRestartCommand(ChatHandler* handler, char const* args) { - return ShutdownServer(args, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); + return ShutdownServer(args, IsOnlyUser(handler->GetSession()) ? (SHUTDOWN_MASK_FORCE | SHUTDOWN_MASK_RESTART) : SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); } - static bool HandleServerIdleRestartCommand(ChatHandler* /*handler*/, char const* args) + static bool HandleServerForceShutDownCommand(ChatHandler* /*handler*/, char const* args) { - return ShutdownServer(args, SHUTDOWN_MASK_RESTART | SHUTDOWN_MASK_IDLE, RESTART_EXIT_CODE); + return ShutdownServer(args, SHUTDOWN_MASK_FORCE, SHUTDOWN_EXIT_CODE); + } + + static bool HandleServerForceRestartCommand(ChatHandler* /*handler*/, char const* args) + { + return ShutdownServer(args, SHUTDOWN_MASK_FORCE | SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); } static bool HandleServerIdleShutDownCommand(ChatHandler* /*handler*/, char const* args) @@ -212,6 +230,11 @@ public: return ShutdownServer(args, SHUTDOWN_MASK_IDLE, SHUTDOWN_EXIT_CODE); } + static bool HandleServerIdleRestartCommand(ChatHandler* /*handler*/, char const* args) + { + return ShutdownServer(args, SHUTDOWN_MASK_RESTART | SHUTDOWN_MASK_IDLE, RESTART_EXIT_CODE); + } + // Exit the realm static bool HandleServerExitCommand(ChatHandler* handler, char const* /*args*/) { @@ -256,8 +279,8 @@ public: return false; char* type = strtok((char*)args, " "); - char* name = strtok(NULL, " "); - char* level = strtok(NULL, " "); + char* name = strtok(nullptr, " "); + char* level = strtok(nullptr, " "); if (!type || !name || !level || *name == '\0' || *level == '\0' || (*type != 'a' && *type != 'l')) return false; @@ -313,10 +336,26 @@ private: return false; // #delay [#exit_code] [reason] + int32 delay = 0; char* delayStr = strtok((char*)args, " "); - if (!delayStr || !isNumeric(delayStr)) + if (!delayStr) return false; + if (isNumeric(delayStr)) + { + delay = atoi(delayStr); + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((delay == 0 && (delayStr[0] != '0' || delayStr[1] != '\0')) || delay < 0) + return false; + } + else + { + delay = TimeStringToSecs(std::string(delayStr)); + + if (delay == 0) + return false; + } + char* exitCodeStr = nullptr; char reason[256] = { 0 }; @@ -337,17 +376,15 @@ private: } } - int32 delay = atoi(delayStr); - - // Prevent interpret wrong arg value as 0 secs shutdown time - if ((delay == 0 && (delayStr[0] != '0' || delayStr[1] != '\0')) || delay < 0) - return false; - int32 exitCode = defaultExitCode; if (exitCodeStr) if (!ParseExitCode(exitCodeStr, exitCode)) return false; + // Override parameter "delay" with the configuration value if there are still players connected and "force" parameter was not specified + if (delay < (int32)sWorld->getIntConfig(CONFIG_FORCE_SHUTDOWN_THRESHOLD) && !(shutdownMask & SHUTDOWN_MASK_FORCE)) + delay = (int32)sWorld->getIntConfig(CONFIG_FORCE_SHUTDOWN_THRESHOLD); + sWorld->ShutdownServ(delay, shutdownMask, static_cast<uint8>(exitCode), std::string(reason)); return true; diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index c5c85f5f3cc..26f712eb8ef 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -95,7 +95,7 @@ public: ObjectGuid targetGuid = sObjectMgr->GetPlayerGUIDByName(target); uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(targetGuid); // Target must exist and have administrative rights - if (!AccountMgr::HasPermission(accountId, rbac::RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realmID)) + if (!AccountMgr::HasPermission(accountId, rbac::RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET, realm.Id.Realm)) { handler->SendSysMessage(LANG_COMMAND_TICKETASSIGNERROR_A); return true; @@ -119,7 +119,7 @@ public: // Assign ticket SQLTransaction trans = SQLTransaction(NULL); - ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(AccountMgr::GetSecurity(accountId, realmID))); + ticket->SetAssignedTo(targetGuid, AccountMgr::IsAdminAccount(AccountMgr::GetSecurity(accountId, realm.Id.Realm))); ticket->SaveToDB(trans); sTicketMgr->UpdateLastChange(); @@ -199,7 +199,12 @@ public: ticket->SaveToDB(trans); sTicketMgr->UpdateLastChange(); - std::string msg = ticket->FormatMessageString(*handler, NULL, ticket->GetAssignedToName().c_str(), NULL, NULL, NULL); + std::string msg = [&] { + std::string const assignedName = ticket->GetAssignedToName(); + return ticket->FormatMessageString(*handler, nullptr, + assignedName.empty() ? nullptr : assignedName.c_str(), nullptr, nullptr, nullptr); + }(); + msg += handler->PGetParseString(LANG_COMMAND_TICKETLISTADDCOMMENT, player ? player->GetName().c_str() : "Console", comment); handler->SendGlobalGMSysMessage(msg.c_str()); @@ -387,7 +392,7 @@ public: { ObjectGuid guid = ticket->GetAssignedToGUID(); uint32 accountId = sObjectMgr->GetPlayerAccountIdByGUID(guid); - security = AccountMgr::GetSecurity(accountId, realmID); + security = AccountMgr::GetSecurity(accountId, realm.Id.Realm); } // Check security diff --git a/src/server/scripts/Commands/cs_titles.cpp b/src/server/scripts/Commands/cs_titles.cpp index 2f5d7b8364c..6309e7279c9 100644 --- a/src/server/scripts/Commands/cs_titles.cpp +++ b/src/server/scripts/Commands/cs_titles.cpp @@ -225,7 +225,7 @@ public: if (CharTitlesEntry const* tEntry = sCharTitlesStore.LookupEntry(i)) titles2 &= ~(uint64(1) << tEntry->bit_index); - titles &= ~titles2; // remove not existed titles + titles &= ~titles2; // remove non-existing titles target->SetUInt64Value(PLAYER__FIELD_KNOWN_TITLES, titles); handler->SendSysMessage(LANG_DONE); diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index ef61c231104..424f94f7385 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -561,29 +561,24 @@ public: // -> variable lowguid is filled with the GUID of the NPC uint32 pathid = 0; uint32 point = 0; - uint32 wpGuid = 0; Creature* target = handler->getSelectedCreature(); PreparedStatement* stmt = NULL; + // User did select a visual waypoint? if (!target || target->GetEntry() != VISUAL_WAYPOINT) { handler->SendSysMessage("|cffff33ffERROR: You must select a waypoint.|r"); return false; } - // The visual waypoint - wpGuid = target->GetGUID().GetCounter(); - - // User did select a visual waypoint? - // Check the creature stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_BY_WPGUID); - stmt->setUInt32(0, wpGuid); + stmt->setUInt32(0, target->GetSpawnId()); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) { - handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID().GetCounter()); + handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetSpawnId()); // Select waypoint number from database // Since we compare float values, we have to deal with // some difficulties. @@ -599,11 +594,11 @@ public: stmt->setString(3, maxDiff); stmt->setFloat(4, target->GetPositionZ()); stmt->setString(5, maxDiff); - PreparedQueryResult queryResult = WorldDatabase.Query(stmt); + result = WorldDatabase.Query(stmt); - if (!queryResult) + if (!result) { - handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid); + handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetSpawnId()); return true; } } @@ -631,13 +626,8 @@ public: { handler->PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid); - if (wpGuid != 0) - if (Creature* wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HighGuid::Unit, VISUAL_WAYPOINT, wpGuid))) - { - wpCreature->CombatStop(); - wpCreature->DeleteFromDB(); - wpCreature->AddObjectToRemoveList(); - } + target->DeleteFromDB(); + target->AddObjectToRemoveList(); stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_WAYPOINT_DATA); stmt->setUInt32(0, pathid); @@ -659,51 +649,40 @@ public: Player* chr = handler->GetSession()->GetPlayer(); Map* map = chr->GetMap(); + // What to do: + // Move the visual spawnpoint + // Respawn the owner of the waypoints + target->DeleteFromDB(); + target->AddObjectToRemoveList(); + + // re-create + Creature* wpCreature = new Creature(); + if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) { - // What to do: - // Move the visual spawnpoint - // Respawn the owner of the waypoints - if (wpGuid != 0) - { - if (Creature* wpCreature = map->GetCreature(ObjectGuid(HighGuid::Unit, VISUAL_WAYPOINT, wpGuid))) - { - wpCreature->CombatStop(); - wpCreature->DeleteFromDB(); - wpCreature->AddObjectToRemoveList(); - } - // re-create - Creature* wpCreature2 = new Creature(); - if (!wpCreature2->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) - { - handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - delete wpCreature2; - wpCreature2 = NULL; - return false; - } + handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + delete wpCreature; + return false; + } - wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - /// @todo Should we first use "Create" then use "LoadFromDB"? - if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetSpawnId(), map)) - { - handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - delete wpCreature2; - wpCreature2 = NULL; - return false; - } - //sMapMgr->GetMap(npcCreature->GetMapId())->Add(wpCreature2); - } + wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); + /// @todo Should we first use "Create" then use "LoadFromDB"? + if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map)) + { + handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + delete wpCreature; + return false; + } - stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POSITION); - stmt->setFloat(0, chr->GetPositionX()); - stmt->setFloat(1, chr->GetPositionY()); - stmt->setFloat(2, chr->GetPositionZ()); - stmt->setUInt32(3, pathid); - stmt->setUInt32(4, point); - WorldDatabase.Execute(stmt); + stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_POSITION); + stmt->setFloat(0, chr->GetPositionX()); + stmt->setFloat(1, chr->GetPositionY()); + stmt->setFloat(2, chr->GetPositionZ()); + stmt->setUInt32(3, pathid); + stmt->setUInt32(4, point); + WorldDatabase.Execute(stmt); - handler->PSendSysMessage(LANG_WAYPOINT_CHANGED); - } + handler->PSendSysMessage(LANG_WAYPOINT_CHANGED); return true; } // move @@ -897,14 +876,15 @@ public: return false; } + wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + // Set "wpguid" column to the visual waypoint stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID); - stmt->setInt32(0, int32(wpCreature->GetGUID().GetCounter())); + stmt->setInt32(0, int32(wpCreature->GetSpawnId())); stmt->setUInt32(1, pathid); stmt->setUInt32(2, point); WorldDatabase.Execute(stmt); - wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map)) { diff --git a/src/server/scripts/Custom/CMakeLists.txt b/src/server/scripts/Custom/CMakeLists.txt deleted file mode 100644 index 595ff801813..00000000000 --- a/src/server/scripts/Custom/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# file(GLOB_RECURSE sources_Custom Custom/*.cpp Custom/*.h) - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} -# ${sources_Custom} -) - -message(" -> Prepared: Custom") diff --git a/src/server/scripts/Custom/custom_script_loader.cpp b/src/server/scripts/Custom/custom_script_loader.cpp new file mode 100644 index 00000000000..dd4b5e99d77 --- /dev/null +++ b/src/server/scripts/Custom/custom_script_loader.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: + + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddCustomScripts() +{ +} diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp index 9cd724e5596..7b07c9272da 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp @@ -415,112 +415,12 @@ public: }; }; -// npc_kharan_mighthammer -enum KharamQuests -{ - QUEST_4001 = 4001, - QUEST_4342 = 4342 -}; - -#define GOSSIP_ITEM_KHARAN_1 "I need to know where the princess are, Kharan!" -#define GOSSIP_ITEM_KHARAN_2 "All is not lost, Kharan!" -#define GOSSIP_ITEM_KHARAN_3 "Gor'shak is my friend, you can trust me." -#define GOSSIP_ITEM_KHARAN_4 "Not enough, you need to tell me more." -#define GOSSIP_ITEM_KHARAN_5 "So what happened?" -#define GOSSIP_ITEM_KHARAN_6 "Continue..." -#define GOSSIP_ITEM_KHARAN_7 "So you suspect that someone on the inside was involved? That they were tipped off?" -#define GOSSIP_ITEM_KHARAN_8 "Continue with your story please." -#define GOSSIP_ITEM_KHARAN_9 "Indeed." -#define GOSSIP_ITEM_KHARAN_10 "The door is open, Kharan. You are a free man." - -class npc_kharan_mighthammer : public CreatureScript -{ -public: - npc_kharan_mighthammer() : CreatureScript("npc_kharan_mighthammer") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->SEND_GOSSIP_MENU(2475, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->SEND_GOSSIP_MENU(2476, creature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - player->SEND_GOSSIP_MENU(2477, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - player->SEND_GOSSIP_MENU(2478, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - player->SEND_GOSSIP_MENU(2479, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - player->SEND_GOSSIP_MENU(2480, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8); - player->SEND_GOSSIP_MENU(2481, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+8: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); - player->SEND_GOSSIP_MENU(2482, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+9: - player->CLOSE_GOSSIP_MENU(); - if (player->GetTeam() == HORDE) - player->AreaExploredOrEventHappens(QUEST_4001); - else - player->AreaExploredOrEventHappens(QUEST_4342); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_4001) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - if (player->GetQuestStatus(4342) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - - if (player->GetTeam() == HORDE) - player->SEND_GOSSIP_MENU(2473, creature->GetGUID()); - else - player->SEND_GOSSIP_MENU(2474, creature->GetGUID()); - - return true; - } -}; - // npc_lokhtos_darkbargainer -enum LokhtosItems +enum Lokhtos { + QUEST_A_BINDING_CONTRACT = 7604, + ITEM_SULFURON_INGOT = 17203, ITEM_THRORIUM_BROTHERHOOD_CONTRACT = 18628, - ITEM_SULFURON_INGOT = 17203 -}; - -enum LokhtosQuests -{ - QUEST_A_BINDING_CONTRACT = 7604 -}; - -enum LokhtosSpells -{ SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT_DND = 23059 }; @@ -570,67 +470,12 @@ public: } }; -// npc_dughal_stormwing -enum DughalQuests -{ - QUEST_JAIL_BREAK = 4322 -}; - -#define SAY_DUGHAL_FREE "Thank you, $N! I'm free!!!" -#define GOSSIP_DUGHAL "You're free, Dughal! Get out of here!" - -// npc_marshal_windsor -#define SAY_WINDSOR_AGGRO1 "You locked up the wrong Marshal. Prepare to be destroyed!" -#define SAY_WINDSOR_AGGRO2 "I bet you're sorry now, aren't you !?!!" -#define SAY_WINDSOR_AGGRO3 "You better hold me back $N or they are going to feel some prison house beatings." -#define SAY_WINDSOR_1 "Let's get a move on. My gear should be in the storage area up this way..." -#define SAY_WINDSOR_4_1 "Check that cell, $N. If someone is alive in there, we need to get them out." -#define SAY_WINDSOR_4_2 "Get him out of there!" -#define SAY_WINDSOR_4_3 "Good work! We're almost there, $N. This way." -#define SAY_WINDSOR_6 "This is it, $N. My stuff should be in that room. Cover me, I'm going in!" -#define SAY_WINDSOR_9 "Ah, there it is!" - -enum MarshalWindsor -{ - NPC_REGINALD_WINDSOR = 9682 -}; - -// npc_marshal_reginald_windsor -#define SAY_REGINALD_WINDSOR_0_1 "Can you feel the power, $N??? It's time to ROCK!" -#define SAY_REGINALD_WINDSOR_0_2 "Now we just have to free Tobias and we can get out of here. This way!" -#define SAY_REGINALD_WINDSOR_5_1 "Open it." -#define SAY_REGINALD_WINDSOR_5_2 "I never did like those two. Let's get moving." -#define SAY_REGINALD_WINDSOR_7_1 "Open it and be careful this time!" -#define SAY_REGINALD_WINDSOR_7_2 "That intolerant dirtbag finally got what was coming to him. Good riddance!" -#define SAY_REGINALD_WINDSOR_7_3 "Alright, let's go." -#define SAY_REGINALD_WINDSOR_13_1 "Open it. We need to hurry up. I can smell those Dark Irons coming a mile away and I can tell you one thing, they're COMING!" -#define SAY_REGINALD_WINDSOR_13_2 "Administering fists of fury on Crest Killer!" -#define SAY_REGINALD_WINDSOR_13_3 "He has to be in the last cell. Unless... they killed him." -#define SAY_REGINALD_WINDSOR_14_1 "Get him out of there!" -#define SAY_REGINALD_WINDSOR_14_2 "Excellent work, $N. Let's find the exit. I think I know the way. Follow me!" -#define SAY_REGINALD_WINDSOR_20_1 "We made it!" -#define SAY_REGINALD_WINDSOR_20_2 "Meet me at Maxwell's encampment. We'll go over the next stages of the plan there and figure out a way to decode my tablets without the decryption ring." - -enum MarshalReginaldWindor -{ - NPC_SHILL_DINGER = 9678, - NPC_CREST_KILLER = 9680 -}; - // npc_rocknot -enum RocknotSays -{ - SAY_GOT_BEER = 0 -}; - -enum RocknotSpells -{ - SPELL_DRUNKEN_RAGE = 14872 -}; - -enum RocknotQuests +enum Rocknot { - QUEST_ALE = 4295 + SAY_GOT_BEER = 0, + QUEST_ALE = 4295, + SPELL_DRUNKEN_RAGE = 14872 }; class npc_rocknot : public CreatureScript @@ -771,7 +616,6 @@ void AddSC_blackrock_depths() new at_ring_of_law(); new npc_grimstone(); new npc_phalanx(); - new npc_kharan_mighthammer(); new npc_lokhtos_darkbargainer(); new npc_rocknot(); } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp index 817aaf0a253..f962a019da6 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp @@ -187,6 +187,12 @@ public: events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(17000, 19000)); } + void IsSummonedBy(Unit* /*summoner*/) override + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + DoZoneInCombat(); + } + void JustDied(Unit* /*killer*/) override { _JustDied(); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp index 4a6fee12098..995fc44abd0 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp @@ -206,9 +206,10 @@ public: Talk(SAY_GAMESBEGIN_2); me->setFaction(103); - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); DoCast(me, SPELL_NEFARIANS_BARRIER); me->SetStandState(UNIT_STAND_STATE_STAND); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); AttackStart(target); events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(3000, 10000)); events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000)); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp index e58bded801b..e97b7cba388 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp @@ -32,6 +32,7 @@ enum Say enum Spells { + // @todo orb uses the wrong spell, this needs sniffs SPELL_MINDCONTROL = 42013, SPELL_CHANNEL = 45537, SPELL_EGG_DESTROY = 19873, @@ -103,7 +104,7 @@ public: secondPhase = true; me->RemoveAllAuras(); - me->SetHealth(me->GetMaxHealth()); + me->SetFullHealth(); } void DoAction(int32 action) override @@ -114,6 +115,7 @@ public: void DamageTaken(Unit* /*who*/, uint32& damage) override { + // @todo this is wrong - razorgore should still take damage, he should just nuke the whole room and respawn if he dies during P1 if (!secondPhase) damage = 0; } @@ -146,6 +148,7 @@ public: break; case EVENT_CONFLAGRATION: DoCastVictim(SPELL_CONFLAGRATION); + // @todo is this even necessary? pretty sure AI ignores targets with disorient by default if (me->GetVictim() && me->EnsureVictim()->HasAura(SPELL_CONFLAGRATION)) if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) me->TauntApply(target); @@ -175,10 +178,10 @@ public: { if (InstanceScript* instance = go->GetInstanceScript()) if (instance->GetData(DATA_EGG_EVENT) != DONE) - if (Creature* razor = instance->GetCreature(DATA_RAZORGORE_THE_UNTAMED)) + if (Creature* razorgore = instance->GetCreature(DATA_RAZORGORE_THE_UNTAMED)) { - razor->Attack(player, true); - player->CastSpell(razor, SPELL_MINDCONTROL); + razorgore->Attack(player, true); + player->CastSpell(razorgore, SPELL_MINDCONTROL); } return true; } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp index 51bb314968d..ffec32c0619 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp @@ -27,6 +27,8 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "molten_core.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" enum Emotes { @@ -36,9 +38,10 @@ enum Emotes enum Spells { SPELL_INFERNO = 19695, + SPELL_INFERNO_DMG = 19698, SPELL_IGNITE_MANA = 19659, SPELL_LIVING_BOMB = 20475, - SPELL_ARMAGEDDON = 20479, + SPELL_ARMAGEDDON = 20478, }; enum Events @@ -119,7 +122,36 @@ class boss_baron_geddon : public CreatureScript } }; +class spell_baron_geddon_inferno : public SpellScriptLoader +{ + public: + spell_baron_geddon_inferno() : SpellScriptLoader("spell_baron_geddon_inferno") { } + + class spell_baron_geddon_inferno_AuraScript : public AuraScript + { + PrepareAuraScript(spell_baron_geddon_inferno_AuraScript); + + void OnPeriodic(AuraEffect const* aurEff) + { + PreventDefaultAction(); + int32 damageForTick[8] = { 500, 500, 1000, 1000, 2000, 2000, 3000, 5000 }; + GetTarget()->CastCustomSpell(SPELL_INFERNO_DMG, SPELLVALUE_BASE_POINT0, damageForTick[aurEff->GetTickNumber() - 1], (Unit*)nullptr, TRIGGERED_FULL_MASK, nullptr, aurEff); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_baron_geddon_inferno_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_baron_geddon_inferno_AuraScript(); + } +}; + void AddSC_boss_baron_geddon() { new boss_baron_geddon(); + new spell_baron_geddon_inferno(); } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp index 9b487f7b5f9..8cff67d9f28 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp @@ -44,16 +44,20 @@ enum Texts enum Spells { - SPELL_MAGIC_REFLECTION = 20619, - SPELL_DAMAGE_REFLECTION = 21075, + SPELL_SUMMON_RAGNAROS = 19774, SPELL_BLAST_WAVE = 20229, - SPELL_AEGIS_OF_RAGNAROS = 20620, SPELL_TELEPORT = 20618, - SPELL_SUMMON_RAGNAROS = 19774, + SPELL_MAGIC_REFLECTION = 20619, + SPELL_AEGIS_OF_RAGNAROS = 20620, + SPELL_DAMAGE_REFLECTION = 21075 }; -#define GOSSIP_HELLO 4995 -#define GOSSIP_SELECT "Tell me more." +enum Extras +{ + OPTION_ID_YOU_CHALLENGED_US = 0, + FACTION_FRIENDLY = 35, + MENU_OPTION_YOU_CHALLENGED_US = 4108 +}; enum Events { @@ -64,7 +68,7 @@ enum Events EVENT_OUTRO_1 = 5, EVENT_OUTRO_2 = 6, - EVENT_OUTRO_3 = 7, + EVENT_OUTRO_3 = 7 }; class boss_majordomo : public CreatureScript @@ -106,7 +110,7 @@ class boss_majordomo : public CreatureScript if (!me->FindNearestCreature(NPC_FLAMEWAKER_HEALER, 100.0f) && !me->FindNearestCreature(NPC_FLAMEWAKER_ELITE, 100.0f)) { instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, me->GetEntry(), me); - me->setFaction(35); + me->setFaction(FACTION_FRIENDLY); EnterEvadeMode(); Talk(SAY_DEFEAT); _JustDied(); @@ -184,25 +188,20 @@ class boss_majordomo : public CreatureScript } else if (action == ACTION_START_RAGNAROS_ALT) { - me->setFaction(35); + me->setFaction(FACTION_FRIENDLY); me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); } } - }; - bool OnGossipHello(Player* player, Creature* creature) override - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(GOSSIP_HELLO, creature->GetGUID()); - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 /*action*/) override - { - player->CLOSE_GOSSIP_MENU(); - creature->AI()->DoAction(ACTION_START_RAGNAROS); - return true; - } + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + if (menuId == MENU_OPTION_YOU_CHALLENGED_US && gossipListId == OPTION_ID_YOU_CHALLENGED_US) + { + player->CLOSE_GOSSIP_MENU(); + DoAction(ACTION_START_RAGNAROS); + } + } + }; CreatureAI* GetAI(Creature* creature) const override { diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index e0cae87051f..a89a6b491e8 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -159,7 +159,7 @@ class boss_ragnaros : public CreatureScript break; case EVENT_INTRO_5: me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); _introState = 2; break; default: diff --git a/src/server/scripts/EasternKingdoms/CMakeLists.txt b/src/server/scripts/EasternKingdoms/CMakeLists.txt deleted file mode 100644 index 8e6616347f9..00000000000 --- a/src/server/scripts/EasternKingdoms/CMakeLists.txt +++ /dev/null @@ -1,204 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - EasternKingdoms/zone_ghostlands.cpp - EasternKingdoms/AlteracValley/boss_galvangar.cpp - EasternKingdoms/AlteracValley/boss_balinda.cpp - EasternKingdoms/AlteracValley/boss_drekthar.cpp - EasternKingdoms/AlteracValley/boss_vanndar.cpp - EasternKingdoms/AlteracValley/alterac_valley.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.h - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp - EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_pyroguard_emberseer.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_drakkisath.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_warmaster_voone.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_mother_smolderweb.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_quartermaster_zigris.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_halycon.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_overlord_wyrmthalak.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_shadow_hunter_voshgajin.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_gyth.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_highlord_omokk.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_the_beast.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_gizrul_the_slavener.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_urok_doomhowl.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_lord_valthalak.cpp - EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h - EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_gehennas.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_lucifron.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_golemagg.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_garr.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/molten_core.h - EasternKingdoms/BlackrockMountain/MoltenCore/instance_molten_core.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp - EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp - EasternKingdoms/Scholomance/boss_the_ravenian.cpp - EasternKingdoms/Scholomance/boss_instructor_malicia.cpp - EasternKingdoms/Scholomance/boss_death_knight_darkreaver.cpp - EasternKingdoms/Scholomance/boss_illucia_barov.cpp - EasternKingdoms/Scholomance/scholomance.h - EasternKingdoms/Scholomance/boss_vectus.cpp - EasternKingdoms/Scholomance/boss_jandice_barov.cpp - EasternKingdoms/Scholomance/boss_kormok.cpp - EasternKingdoms/Scholomance/boss_lord_alexei_barov.cpp - EasternKingdoms/Scholomance/boss_doctor_theolen_krastinov.cpp - EasternKingdoms/Scholomance/boss_darkmaster_gandling.cpp - EasternKingdoms/Scholomance/instance_scholomance.cpp - EasternKingdoms/Scholomance/boss_lorekeeper_polkelt.cpp - EasternKingdoms/Scholomance/boss_ras_frostwhisper.cpp - EasternKingdoms/Scholomance/boss_kirtonos_the_herald.cpp - EasternKingdoms/zone_isle_of_queldanas.cpp - EasternKingdoms/ZulGurub/boss_hakkar.cpp - EasternKingdoms/ZulGurub/boss_mandokir.cpp - EasternKingdoms/ZulGurub/boss_marli.cpp - EasternKingdoms/ZulGurub/boss_hazzarah.cpp - EasternKingdoms/ZulGurub/boss_jeklik.cpp - EasternKingdoms/ZulGurub/boss_grilek.cpp - EasternKingdoms/ZulGurub/zulgurub.h - EasternKingdoms/ZulGurub/boss_renataki.cpp - EasternKingdoms/ZulGurub/boss_arlokk.cpp - EasternKingdoms/ZulGurub/boss_gahzranka.cpp - EasternKingdoms/ZulGurub/boss_venoxis.cpp - EasternKingdoms/ZulGurub/instance_zulgurub.cpp - EasternKingdoms/ZulGurub/boss_jindo.cpp - EasternKingdoms/ZulGurub/boss_wushoolay.cpp - EasternKingdoms/ZulGurub/boss_thekal.cpp - EasternKingdoms/zone_wetlands.cpp - EasternKingdoms/zone_arathi_highlands.cpp - EasternKingdoms/Gnomeregan/instance_gnomeregan.cpp - EasternKingdoms/Gnomeregan/gnomeregan.cpp - EasternKingdoms/Gnomeregan/gnomeregan.h - EasternKingdoms/zone_redridge_mountains.cpp - EasternKingdoms/ScarletEnclave/chapter2.cpp - EasternKingdoms/ScarletEnclave/chapter5.cpp - EasternKingdoms/ScarletEnclave/chapter1.cpp - EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp - EasternKingdoms/zone_eastern_plaguelands.cpp - EasternKingdoms/Stratholme/boss_baroness_anastari.cpp - EasternKingdoms/Stratholme/boss_nerubenkan.cpp - EasternKingdoms/Stratholme/instance_stratholme.cpp - EasternKingdoms/Stratholme/boss_dathrohan_balnazzar.cpp - EasternKingdoms/Stratholme/boss_timmy_the_cruel.cpp - EasternKingdoms/Stratholme/boss_baron_rivendare.cpp - EasternKingdoms/Stratholme/boss_magistrate_barthilas.cpp - EasternKingdoms/Stratholme/boss_order_of_silver_hand.cpp - EasternKingdoms/Stratholme/boss_ramstein_the_gorger.cpp - EasternKingdoms/Stratholme/boss_cannon_master_willey.cpp - EasternKingdoms/Stratholme/boss_maleki_the_pallid.cpp - EasternKingdoms/Stratholme/boss_postmaster_malown.cpp - EasternKingdoms/Stratholme/stratholme.h - EasternKingdoms/Stratholme/stratholme.cpp - EasternKingdoms/zone_tirisfal_glades.cpp - EasternKingdoms/SunkenTemple/sunken_temple.cpp - EasternKingdoms/SunkenTemple/sunken_temple.h - EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp - EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp - EasternKingdoms/MagistersTerrace/magisters_terrace.h - EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp - EasternKingdoms/MagistersTerrace/instance_magisters_terrace.cpp - EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp - EasternKingdoms/MagistersTerrace/boss_vexallus.cpp - EasternKingdoms/MagistersTerrace/magisters_terrace.cpp - EasternKingdoms/Uldaman/uldaman.cpp - EasternKingdoms/Uldaman/boss_ironaya.cpp - EasternKingdoms/Uldaman/uldaman.h - EasternKingdoms/Uldaman/instance_uldaman.cpp - EasternKingdoms/Uldaman/boss_archaedas.cpp - EasternKingdoms/zone_swamp_of_sorrows.cpp - EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp - EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp - EasternKingdoms/SunwellPlateau/sunwell_plateau.h - EasternKingdoms/SunwellPlateau/boss_muru.cpp - EasternKingdoms/SunwellPlateau/instance_sunwell_plateau.cpp - EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp - EasternKingdoms/SunwellPlateau/boss_brutallus.cpp - EasternKingdoms/SunwellPlateau/sunwell_plateau.cpp - EasternKingdoms/SunwellPlateau/boss_felmyst.cpp - EasternKingdoms/zone_stranglethorn_vale.cpp - EasternKingdoms/Deadmines/deadmines.h - EasternKingdoms/Deadmines/deadmines.cpp - EasternKingdoms/Deadmines/boss_mr_smite.cpp - EasternKingdoms/Deadmines/instance_deadmines.cpp - EasternKingdoms/zone_duskwood.cpp - EasternKingdoms/ScarletMonastery/boss_azshir_the_sleepless.cpp - EasternKingdoms/ScarletMonastery/boss_mograine_and_whitemane.cpp - EasternKingdoms/ScarletMonastery/boss_bloodmage_thalnos.cpp - EasternKingdoms/ScarletMonastery/boss_interrogator_vishas.cpp - EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp - EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp - EasternKingdoms/ScarletMonastery/boss_houndmaster_loksey.cpp - EasternKingdoms/ScarletMonastery/scarlet_monastery.h - EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp - EasternKingdoms/ScarletMonastery/boss_arcanist_doan.cpp - EasternKingdoms/ScarletMonastery/boss_herod.cpp - EasternKingdoms/ScarletMonastery/boss_scorn.cpp - EasternKingdoms/zone_undercity.cpp - EasternKingdoms/zone_loch_modan.cpp - EasternKingdoms/ShadowfangKeep/shadowfang_keep.cpp - EasternKingdoms/ShadowfangKeep/instance_shadowfang_keep.cpp - EasternKingdoms/ShadowfangKeep/shadowfang_keep.h - EasternKingdoms/zone_burning_steppes.cpp - EasternKingdoms/zone_blasted_lands.cpp - EasternKingdoms/zone_stormwind_city.cpp - EasternKingdoms/ZulAman/boss_halazzi.cpp - EasternKingdoms/ZulAman/boss_hexlord.cpp - EasternKingdoms/ZulAman/boss_zuljin.cpp - EasternKingdoms/ZulAman/boss_akilzon.cpp - EasternKingdoms/ZulAman/instance_zulaman.cpp - EasternKingdoms/ZulAman/boss_janalai.cpp - EasternKingdoms/ZulAman/boss_nalorakk.cpp - EasternKingdoms/ZulAman/zulaman.cpp - EasternKingdoms/ZulAman/zulaman.h - EasternKingdoms/zone_hinterlands.cpp - EasternKingdoms/zone_western_plaguelands.cpp - EasternKingdoms/zone_silverpine_forest.cpp - EasternKingdoms/Karazhan/instance_karazhan.cpp - EasternKingdoms/Karazhan/boss_nightbane.cpp - EasternKingdoms/Karazhan/karazhan.cpp - EasternKingdoms/Karazhan/boss_curator.cpp - EasternKingdoms/Karazhan/boss_shade_of_aran.cpp - EasternKingdoms/Karazhan/boss_netherspite.cpp - EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp - EasternKingdoms/Karazhan/boss_midnight.cpp - EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp - EasternKingdoms/Karazhan/bosses_opera.cpp - EasternKingdoms/Karazhan/boss_moroes.cpp - EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp - EasternKingdoms/Karazhan/karazhan.h - EasternKingdoms/TheStockade/instance_the_stockade.cpp -) - -message(" -> Prepared: Eastern Kingdoms") diff --git a/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp b/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp index 541ddc0e1c8..8f246ab9bf0 100644 --- a/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp +++ b/src/server/scripts/EasternKingdoms/Deadmines/boss_mr_smite.cpp @@ -25,17 +25,25 @@ EndScriptData */ #include "ScriptedCreature.h" #include "deadmines.h" -enum Spels +enum Spells { SPELL_TRASH = 3391, SPELL_SMITE_STOMP = 6432, SPELL_SMITE_SLAM = 6435, - SPELL_NIMBLE_REFLEXES = 6264, + SPELL_NIMBLE_REFLEXES = 6264 +}; +enum Equips +{ EQUIP_SWORD = 5191, - EQUIP_MACE = 7230, + EQUIP_AXE = 5196, + EQUIP_MACE = 7230 +}; - SAY_AGGRO = 0, +enum Texts +{ + SAY_PHASE_1 = 2, + SAY_PHASE_2 = 3 }; class boss_mr_smite : public CreatureScript @@ -66,6 +74,8 @@ public: uiPhase = 0; uiTimer = 0; + + uiIsMoving = false; } InstanceScript* instance; @@ -79,16 +89,19 @@ public: uint32 uiPhase; uint32 uiTimer; + bool uiIsMoving; + void Reset() override { Initialize(); SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetReactState(REACT_AGGRESSIVE); } void EnterCombat(Unit* /*who*/) override { - Talk(SAY_AGGRO); } bool bCheckChances() @@ -105,38 +118,52 @@ public: if (!UpdateVictim()) return; - /*START ACID-AI*/ - if (uiTrashTimer <= uiDiff) + if (!uiIsMoving) // halt abilities in between phases { - if (bCheckChances()) - DoCast(me, SPELL_TRASH); - uiTrashTimer = urand(6000, 15500); - } else uiTrashTimer -= uiDiff; + if (uiTrashTimer <= uiDiff) + { + if (bCheckChances()) + DoCast(me, SPELL_TRASH); + uiTrashTimer = urand(6000, 15500); + } + else uiTrashTimer -= uiDiff; - if (uiSlamTimer <= uiDiff) - { - if (bCheckChances()) - DoCastVictim(SPELL_SMITE_SLAM); - uiSlamTimer = 11000; - } else uiSlamTimer -= uiDiff; + if (uiSlamTimer <= uiDiff) + { + if (bCheckChances()) + DoCastVictim(SPELL_SMITE_SLAM); + uiSlamTimer = 11000; + } + else uiSlamTimer -= uiDiff; - if (uiNimbleReflexesTimer <= uiDiff) - { - if (bCheckChances()) - DoCast(me, SPELL_NIMBLE_REFLEXES); - uiNimbleReflexesTimer = urand(27300, 60100); - } else uiNimbleReflexesTimer -= uiDiff; - /*END ACID-AI*/ + if (uiNimbleReflexesTimer <= uiDiff) + { + if (bCheckChances()) + DoCast(me, SPELL_NIMBLE_REFLEXES); + uiNimbleReflexesTimer = urand(27300, 60100); + } + else uiNimbleReflexesTimer -= uiDiff; + } if ((uiHealth == 0 && !HealthAbovePct(66)) || (uiHealth == 1 && !HealthAbovePct(33))) { ++uiHealth; DoCastAOE(SPELL_SMITE_STOMP, false); SetCombatMovement(false); - if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SMITE_CHEST))) + me->AttackStop(); + me->InterruptNonMeleeSpells(false); + me->SetReactState(REACT_PASSIVE); + uiTimer = 2500; + uiPhase = 1; + + switch (uiHealth) { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(1, go->GetPositionX() - 3.0f, go->GetPositionY(), go->GetPositionZ()); + case 1: + Talk(SAY_PHASE_1); + break; + case 2: + Talk(SAY_PHASE_2); + break; } } @@ -147,21 +174,36 @@ public: switch (uiPhase) { case 1: - me->HandleEmoteCommand(EMOTE_STATE_KNEEL); //dosen't work? - uiTimer = 1000; - uiPhase = 2; + { + if (uiIsMoving) + break; + + if (GameObject* go = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_SMITE_CHEST))) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(1, go->GetPositionX() - 1.5f, go->GetPositionY() + 1.4f, go->GetPositionZ()); + uiIsMoving = true; + } break; + } case 2: if (uiHealth == 1) - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); + SetEquipmentSlots(false, EQUIP_AXE, EQUIP_AXE, EQUIP_NO_CHANGE); else SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); uiTimer = 500; uiPhase = 3; break; case 3: + me->SetStandState(UNIT_STAND_STATE_STAND); + uiTimer = 750; + uiPhase = 4; + break; + case 4: + me->SetReactState(REACT_AGGRESSIVE); SetCombatMovement(true); me->GetMotionMaster()->MoveChase(me->GetVictim(), me->m_CombatDistance); + uiIsMoving = false; uiPhase = 0; break; } @@ -176,8 +218,11 @@ public: if (uiType != POINT_MOTION_TYPE) return; - uiTimer = 1500; - uiPhase = 1; + me->SetFacingTo(5.47f); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + + uiTimer = 2000; + uiPhase = 2; } }; }; diff --git a/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h index dff4243617e..01ebabb160e 100644 --- a/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h +++ b/src/server/scripts/EasternKingdoms/Deadmines/deadmines.h @@ -26,6 +26,7 @@ enum CannonState CANNON_GUNPOWDER_USED, CANNON_BLAST_INITIATED, PIRATES_ATTACK, + SMITE_ALARMED, EVENT_DONE }; @@ -48,4 +49,16 @@ enum GameObjects GO_DOOR_LEVER = 101833, GO_MR_SMITE_CHEST = 144111 }; + +enum CreaturesIds +{ + NPC_MR_SMITE = 646 +}; + +enum InstanceTexts +{ + SAY_ALARM1 = 0, + SAY_ALARM2 = 1 +}; + #endif diff --git a/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp b/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp index 6714b243765..7599cf38f08 100644 --- a/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp +++ b/src/server/scripts/EasternKingdoms/Deadmines/instance_deadmines.cpp @@ -32,18 +32,14 @@ EndScriptData */ enum Sounds { SOUND_CANNONFIRE = 1400, - SOUND_DESTROYDOOR = 3079, - SOUND_MR_SMITE_ALARM1 = 5775, - SOUND_MR_SMITE_ALARM2 = 5777 + SOUND_DESTROYDOOR = 3079 }; -#define SAY_MR_SMITE_ALARM1 "You there, check out that noise!" -#define SAY_MR_SMITE_ALARM2 "We're under attack! A vast, ye swabs! Repel the invaders!" - enum Misc { DATA_CANNON_BLAST_TIMER = 3000, - DATA_PIRATES_DELAY_TIMER = 1000 + DATA_PIRATES_DELAY_TIMER = 1000, + DATA_SMITE_ALARM_DELAY_TIMER = 5000 }; class instance_deadmines : public InstanceMapScript @@ -63,6 +59,7 @@ class instance_deadmines : public InstanceMapScript State = CANNON_NOT_USED; CannonBlast_Timer = 0; PiratesDelay_Timer = 0; + SmiteAlarmDelay_Timer = 0; } ObjectGuid FactoryDoorGUID; @@ -72,10 +69,12 @@ class instance_deadmines : public InstanceMapScript ObjectGuid DefiasPirate1GUID; ObjectGuid DefiasPirate2GUID; ObjectGuid DefiasCompanionGUID; + ObjectGuid MrSmiteGUID; uint32 State; uint32 CannonBlast_Timer; uint32 PiratesDelay_Timer; + uint32 SmiteAlarmDelay_Timer; ObjectGuid uiSmiteChestGUID; virtual void Update(uint32 diff) override @@ -91,22 +90,20 @@ class instance_deadmines : public InstanceMapScript { case CANNON_GUNPOWDER_USED: CannonBlast_Timer = DATA_CANNON_BLAST_TIMER; - // it's a hack - Mr. Smite should do that but his too far away - //pIronCladDoor->SetName("Mr. Smite"); - //pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM1, LANG_UNIVERSAL, NULL); - pIronCladDoor->PlayDirectSound(SOUND_MR_SMITE_ALARM1); State = CANNON_BLAST_INITIATED; break; case CANNON_BLAST_INITIATED: PiratesDelay_Timer = DATA_PIRATES_DELAY_TIMER; + SmiteAlarmDelay_Timer = DATA_SMITE_ALARM_DELAY_TIMER; if (CannonBlast_Timer <= diff) { SummonCreatures(); ShootCannon(); BlastOutDoor(); LeverStucked(); - //pIronCladDoor->MonsterYell(SAY_MR_SMITE_ALARM2, LANG_UNIVERSAL, NULL); - pIronCladDoor->PlayDirectSound(SOUND_MR_SMITE_ALARM2); + instance->LoadGrid(-22.8f, -797.24f); // Loads Mr. Smite's grid. + if (Creature* smite = instance->GetCreature(MrSmiteGUID)) // goes off when door blows up + smite->AI()->Talk(SAY_ALARM1); State = PIRATES_ATTACK; } else CannonBlast_Timer -= diff; break; @@ -114,9 +111,17 @@ class instance_deadmines : public InstanceMapScript if (PiratesDelay_Timer <= diff) { MoveCreaturesInside(); - State = EVENT_DONE; + State = SMITE_ALARMED; } else PiratesDelay_Timer -= diff; break; + case SMITE_ALARMED: + if (SmiteAlarmDelay_Timer <= diff) + { + if (Creature* smite = instance->GetCreature(MrSmiteGUID)) + smite->AI()->Talk(SAY_ALARM2); + State = EVENT_DONE; + } else SmiteAlarmDelay_Timer -= diff; + break; } } @@ -180,6 +185,18 @@ class instance_deadmines : public InstanceMapScript pDoorLever->SetUInt32Value(GAMEOBJECT_FLAGS, 4); } + void OnCreatureCreate(Creature* creature) override + { + switch (creature->GetEntry()) + { + case NPC_MR_SMITE: + MrSmiteGUID = creature->GetGUID(); + break; + default: + break; + } + } + void OnGameObjectCreate(GameObject* go) override { switch (go->GetEntry()) diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index 05d964124b1..c8eb645845b 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -305,7 +305,7 @@ public: me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[9], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); break; case 2: - if (GameObject* go = me->SummonGameObject(183410, -533.140f, -105.322f, -156.016f, 0, 0, 0, 0, 0, 1)) + if (GameObject* go = me->SummonGameObject(183410, -533.140f, -105.322f, -156.016f, 0.f, G3D::Quat(), 1)) { GoSummonList.push_back(go->GetGUID()); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); //We can't use it! @@ -320,7 +320,7 @@ public: Talk(SAY_BLASTMASTER_7); break; case 4: - if (GameObject* go = me->SummonGameObject(183410, -542.199f, -96.854f, -155.790f, 0, 0, 0, 0, 0, 1)) + if (GameObject* go = me->SummonGameObject(183410, -542.199f, -96.854f, -155.790f, 0.f, G3D::Quat(), 1)) { GoSummonList.push_back(go->GetGUID()); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); @@ -334,7 +334,7 @@ public: me->SummonCreature(NPC_CAVERNDEEP_AMBUSHER, SpawnPosition[14], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); break; case 6: - if (GameObject* go = me->SummonGameObject(183410, -507.820f, -103.333f, -151.353f, 0, 0, 0, 0, 0, 1)) + if (GameObject* go = me->SummonGameObject(183410, -507.820f, -103.333f, -151.353f, 0.f, G3D::Quat(), 1)) { GoSummonList.push_back(go->GetGUID()); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); //We can't use it! @@ -342,7 +342,7 @@ public: } break; case 7: - if (GameObject* go = me->SummonGameObject(183410, -511.829f, -86.249f, -151.431f, 0, 0, 0, 0, 0, 1)) + if (GameObject* go = me->SummonGameObject(183410, -511.829f, -86.249f, -151.431f, 0.f, G3D::Quat(), 1)) { GoSummonList.push_back(go->GetGUID()); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); //We can't use it! @@ -354,9 +354,9 @@ public: me->SummonCreature(NPC_CHOMPER, SpawnPosition[16], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1800000); break; case 9: - me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[17].GetPositionX(), SpawnPosition[17].GetPositionY(), SpawnPosition[17].GetPositionZ(), SpawnPosition[17].GetOrientation(), 0, 0, 0, 0, 7200); - me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[18].GetPositionX(), SpawnPosition[18].GetPositionY(), SpawnPosition[18].GetPositionZ(), SpawnPosition[18].GetOrientation(), 0, 0, 0, 0, 7200); - me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[19].GetPositionX(), SpawnPosition[19].GetPositionY(), SpawnPosition[19].GetPositionZ(), SpawnPosition[19].GetOrientation(), 0, 0, 0, 0, 7200); + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[17], G3D::Quat(), 7200); + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[18], G3D::Quat(), 7200); + me->SummonGameObject(GO_RED_ROCKET, SpawnPosition[19], G3D::Quat(), 7200); break; } } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp index 9f4a31fdbbc..b694c074879 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_maiden_of_virtue.cpp @@ -50,19 +50,9 @@ class boss_maiden_of_virtue : public CreatureScript public: boss_maiden_of_virtue() : CreatureScript("boss_maiden_of_virtue") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_maiden_of_virtueAI(creature); - } - struct boss_maiden_of_virtueAI : public BossAI { - boss_maiden_of_virtueAI(Creature* creature) : BossAI(creature, TYPE_MAIDEN) { } - - void Reset() override - { - _Reset(); - } + boss_maiden_of_virtueAI(Creature* creature) : BossAI(creature, DATA_MAIDEN_OF_VIRTUE) { } void KilledUnit(Unit* /*Victim*/) override { @@ -132,6 +122,11 @@ public: DoMeleeAttackIfReady(); } }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_maiden_of_virtueAI(creature); + } }; void AddSC_boss_maiden_of_virtue() diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp index ced8dd8f37e..ce3e68d9c48 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp @@ -26,26 +26,44 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellInfo.h" +#include "karazhan.h" -enum Midnight +enum Texts { - SAY_MIDNIGHT_KILL = 0, - SAY_APPEAR = 1, - SAY_MOUNT = 2, - - SAY_KILL = 0, - SAY_DISARMED = 1, - SAY_DEATH = 2, - SAY_RANDOM = 3, - - SPELL_SHADOWCLEAVE = 29832, - SPELL_INTANGIBLE_PRESENCE = 29833, - SPELL_BERSERKER_CHARGE = 26561, //Only when mounted + SAY_KILL = 0, + SAY_RANDOM = 1, + SAY_DISARMED = 2, + SAY_MIDNIGHT_KILL = 3, + SAY_APPEAR = 4, + SAY_MOUNT = 5, + + SAY_DEATH = 3, + + // Midnight + EMOTE_CALL_ATTUMEN = 0, + EMOTE_MOUNT_UP = 1 +}; - MOUNTED_DISPLAYID = 16040, +enum Spells +{ + // Attumen + SPELL_SHADOWCLEAVE = 29832, + SPELL_INTANGIBLE_PRESENCE = 29833, + SPELL_SPAWN_SMOKE = 10389, + SPELL_CHARGE = 29847, + + // Midnight + SPELL_KNOCKDOWN = 29711, + SPELL_SUMMON_ATTUMEN = 29714, + SPELL_MOUNT = 29770, + SPELL_SUMMON_ATTUMEN_MOUNTED = 29799 +}; - //Attumen (@todo Use the summoning spell instead of Creature id. It works, but is not convenient for us) - SUMMON_ATTUMEN = 15550, +enum Phases +{ + PHASE_NONE, + PHASE_ATTUMEN_ENGAGES, + PHASE_MOUNTED }; class boss_attumen : public CreatureScript @@ -53,72 +71,212 @@ class boss_attumen : public CreatureScript public: boss_attumen() : CreatureScript("boss_attumen") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_attumenAI(creature); - } - - struct boss_attumenAI : public ScriptedAI + struct boss_attumenAI : public BossAI { - boss_attumenAI(Creature* creature) : ScriptedAI(creature) + boss_attumenAI(Creature* creature) : BossAI(creature, DATA_ATTUMEN) { Initialize(); - - Phase = 1; - - CleaveTimer = urand(10000, 15000); - CurseTimer = 30000; - RandomYellTimer = urand(30000, 60000); //Occasionally yell - ChargeTimer = 20000; - } + } void Initialize() { - ResetTimer = 0; - Midnight.Clear(); + _midnightGUID.Clear(); + _phase = PHASE_NONE; } - ObjectGuid Midnight; - uint8 Phase; - uint32 CleaveTimer; - uint32 CurseTimer; - uint32 RandomYellTimer; - uint32 ChargeTimer; //only when mounted - uint32 ResetTimer; - void Reset() override { Initialize(); + BossAI::Reset(); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (Creature* midnight = ObjectAccessor::GetCreature(*me, _midnightGUID)) + BossAI::_DespawnAtEvade(Seconds(10), midnight); + + me->DespawnOrUnsummon(); } - void EnterEvadeMode(EvadeReason why) override + void ScheduleTasks() override { - ScriptedAI::EnterEvadeMode(why); - ResetTimer = 2000; + scheduler.Schedule(Seconds(15), Seconds(25), [this](TaskContext task) + { + DoCastVictim(SPELL_SHADOWCLEAVE); + task.Repeat(Seconds(15), Seconds(25)); + }); + + scheduler.Schedule(Seconds(25), Seconds(45), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target,SPELL_INTANGIBLE_PRESENCE); + + task.Repeat(Seconds(25), Seconds(45)); + }); + + scheduler.Schedule(Seconds(30), Seconds(60), [this](TaskContext task) + { + Talk(SAY_RANDOM); + task.Repeat(Seconds(30), Seconds(60)); + }); } - void EnterCombat(Unit* /*who*/) override { } + void DamageTaken(Unit* /*attacker*/, uint32 &damage) override + { + // Attumen does not die until he mounts Midnight, let health fall to 1 and prevent further damage. + if (damage >= me->GetHealth() && _phase != PHASE_MOUNTED) + damage = me->GetHealth() - 1; + + if (_phase == PHASE_ATTUMEN_ENGAGES && me->HealthBelowPctDamaged(25, damage)) + { + _phase = PHASE_NONE; + + if (Creature* midnight = ObjectAccessor::GetCreature(*me, _midnightGUID)) + midnight->AI()->DoCastAOE(SPELL_MOUNT, true); + } + } void KilledUnit(Unit* /*victim*/) override { Talk(SAY_KILL); } - void JustDied(Unit* /*killer*/) override + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_ATTUMEN_MOUNTED) + if (Creature* midnight = ObjectAccessor::GetCreature(*me, _midnightGUID)) + { + if (midnight->GetHealth() > me->GetHealth()) + summon->SetHealth(midnight->GetHealth()); + else + summon->SetHealth(me->GetHealth()); + + summon->AI()->DoZoneInCombat(); + summon->AI()->SetGUID(_midnightGUID, NPC_MIDNIGHT); + } + + BossAI::JustSummoned(summon); + } + + void IsSummonedBy(Unit* summoner) override + { + if (summoner->GetEntry() == NPC_MIDNIGHT) + _phase = PHASE_ATTUMEN_ENGAGES; + + if (summoner->GetEntry() == NPC_ATTUMEN_UNMOUNTED) + { + _phase = PHASE_MOUNTED; + DoCastSelf(SPELL_SPAWN_SMOKE); + + scheduler.Schedule(Seconds(10), Seconds(25), [this](TaskContext task) + { + Unit* target = nullptr; + ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList(); + std::vector<Unit*> target_list; + + for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr) + { + target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); + if (target && !target->IsWithinDist(me, 8.00f, false) && target->IsWithinDist(me, 25.0f, false)) + target_list.push_back(target); + + target = nullptr; + } + + if (!target_list.empty()) + target = Trinity::Containers::SelectRandomContainerElement(target_list); + + DoCast(target, SPELL_CHARGE); + task.Repeat(Seconds(10), Seconds(25)); + }); + + scheduler.Schedule(Seconds(25), Seconds(35), [this](TaskContext task) + { + DoCastVictim(SPELL_KNOCKDOWN); + task.Repeat(Seconds(25), Seconds(35)); + }); + } + } + + void JustDied(Unit* killer) override { Talk(SAY_DEATH); - if (Unit* midnight = ObjectAccessor::GetUnit(*me, Midnight)) + if (Unit* midnight = ObjectAccessor::GetUnit(*me, _midnightGUID)) midnight->KillSelf(); + + BossAI::JustDied(killer); } - void UpdateAI(uint32 diff) override; + void SetGUID(ObjectGuid guid, int32 data) override + { + if (data == NPC_MIDNIGHT) + _midnightGUID = guid; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && _phase != PHASE_NONE) + return; + + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } void SpellHit(Unit* /*source*/, const SpellInfo* spell) override { if (spell->Mechanic == MECHANIC_DISARM) Talk(SAY_DISARMED); + + if (spell->Id == SPELL_MOUNT) + { + if (Creature* midnight = ObjectAccessor::GetCreature(*me, _midnightGUID)) + { + _phase = PHASE_NONE; + scheduler.CancelAll(); + + midnight->AttackStop(); + midnight->RemoveAllAttackers(); + midnight->SetReactState(REACT_PASSIVE); + midnight->GetMotionMaster()->MoveChase(me); + midnight->AI()->Talk(EMOTE_MOUNT_UP); + + me->AttackStop(); + me->RemoveAllAttackers(); + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MoveChase(midnight); + Talk(SAY_MOUNT); + + scheduler.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* midnight = ObjectAccessor::GetCreature(*me, _midnightGUID)) + { + if (me->IsWithinMeleeRange(midnight)) + { + DoCastAOE(SPELL_SUMMON_ATTUMEN_MOUNTED); + me->SetVisible(false); + midnight->SetVisible(false); + } + else + { + midnight->GetMotionMaster()->MoveChase(me); + me->GetMotionMaster()->MoveChase(midnight); + task.Repeat(Seconds(3)); + } + } + }); + } + } } + + private: + ObjectGuid _midnightGUID; + uint8 _phase; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_attumenAI(creature); + } }; class boss_midnight : public CreatureScript @@ -126,210 +284,102 @@ class boss_midnight : public CreatureScript public: boss_midnight() : CreatureScript("boss_midnight") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_midnightAI(creature); - } - - struct boss_midnightAI : public ScriptedAI + struct boss_midnightAI : public BossAI { - boss_midnightAI(Creature* creature) : ScriptedAI(creature) + boss_midnightAI(Creature* creature) : BossAI(creature, DATA_ATTUMEN) { Initialize(); } void Initialize() { - Phase = 1; - Attumen.Clear(); - Mount_Timer = 0; + _phase = PHASE_NONE; } - ObjectGuid Attumen; - uint8 Phase; - uint32 Mount_Timer; - void Reset() override { Initialize(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + BossAI::Reset(); me->SetVisible(true); + me->SetReactState(REACT_DEFENSIVE); } - void EnterCombat(Unit* /*who*/) override { } - - void KilledUnit(Unit* /*victim*/) override - { - if (Phase == 2) - { - if (Unit* unit = ObjectAccessor::GetUnit(*me, Attumen)) - Talk(SAY_MIDNIGHT_KILL, unit); - } - } - - void UpdateAI(uint32 diff) override + void DamageTaken(Unit* /*attacker*/, uint32 &damage) override { - if (!UpdateVictim()) - return; + // Midnight never dies, let health fall to 1 and prevent further damage. + if (damage >= me->GetHealth()) + damage = me->GetHealth() - 1; - if (Phase == 1 && HealthBelowPct(95)) + if (_phase == PHASE_NONE && me->HealthBelowPctDamaged(95, damage)) { - Phase = 2; - if (Creature* attumen = me->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000)) - { - Attumen = attumen->GetGUID(); - attumen->AI()->AttackStart(me->GetVictim()); - SetMidnight(attumen, me->GetGUID()); - Talk(SAY_APPEAR, attumen); - } + _phase = PHASE_ATTUMEN_ENGAGES; + Talk(EMOTE_CALL_ATTUMEN); + DoCastAOE(SPELL_SUMMON_ATTUMEN); } - else if (Phase == 2 && HealthBelowPct(25)) + else if (_phase == PHASE_ATTUMEN_ENGAGES && me->HealthBelowPctDamaged(25, damage)) { - if (Unit* pAttumen = ObjectAccessor::GetUnit(*me, Attumen)) - Mount(pAttumen); + _phase = PHASE_MOUNTED; + DoCastAOE(SPELL_MOUNT, true); } - else if (Phase == 3) + } + + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_ATTUMEN_UNMOUNTED) { - if (Mount_Timer) - { - if (Mount_Timer <= diff) - { - Mount_Timer = 0; - me->SetVisible(false); - me->GetMotionMaster()->MoveIdle(); - if (Unit* pAttumen = ObjectAccessor::GetUnit(*me, Attumen)) - { - pAttumen->SetDisplayId(MOUNTED_DISPLAYID); - pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pAttumen->GetVictim()) - { - pAttumen->GetMotionMaster()->MoveChase(pAttumen->GetVictim()); - pAttumen->SetTarget(pAttumen->EnsureVictim()->GetGUID()); - } - pAttumen->SetObjectScale(1); - } - } else Mount_Timer -= diff; - } + _attumenGUID = summon->GetGUID(); + summon->AI()->SetGUID(me->GetGUID(), NPC_MIDNIGHT); + summon->AI()->AttackStart(me->GetVictim()); + summon->AI()->Talk(SAY_APPEAR); } - if (Phase != 3) - DoMeleeAttackIfReady(); + BossAI::JustSummoned(summon); } - void Mount(Unit* pAttumen) + void EnterCombat(Unit* who) override { - Talk(SAY_MOUNT, pAttumen); - Phase = 3; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - float angle = me->GetAngle(pAttumen); - float distance = me->GetDistance2d(pAttumen); - float newX = me->GetPositionX() + std::cos(angle)*(distance/2); - float newY = me->GetPositionY() + std::sin(angle)*(distance/2); - float newZ = 50; - //me->Relocate(newX, newY, newZ, angle); - //me->SendMonsterMove(newX, newY, newZ, 0, true, 1000); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, newX, newY, newZ); - distance += 10; - newX = me->GetPositionX() + std::cos(angle)*(distance/2); - newY = me->GetPositionY() + std::sin(angle)*(distance/2); - pAttumen->GetMotionMaster()->Clear(); - pAttumen->GetMotionMaster()->MovePoint(0, newX, newY, newZ); - //pAttumen->Relocate(newX, newY, newZ, -angle); - //pAttumen->SendMonsterMove(newX, newY, newZ, 0, true, 1000); - Mount_Timer = 1000; + BossAI::EnterCombat(who); + + scheduler.Schedule(Seconds(15), Seconds(25), [this](TaskContext task) + { + DoCastVictim(SPELL_KNOCKDOWN); + task.Repeat(Seconds(15), Seconds(25)); + }); } - void SetMidnight(Creature* pAttumen, ObjectGuid value) + void EnterEvadeMode(EvadeReason /*why*/) override { - ENSURE_AI(boss_attumen::boss_attumenAI, pAttumen->AI())->Midnight = value; + BossAI::_DespawnAtEvade(Seconds(10)); } - }; -}; -void boss_attumen::boss_attumenAI::UpdateAI(uint32 diff) -{ - if (ResetTimer) - { - if (ResetTimer <= diff) + void KilledUnit(Unit* /*victim*/) override { - ResetTimer = 0; - Unit* pMidnight = ObjectAccessor::GetUnit(*me, Midnight); - if (pMidnight) + if (_phase == PHASE_ATTUMEN_ENGAGES) { - pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pMidnight->SetVisible(true); + if (Unit* unit = ObjectAccessor::GetUnit(*me, _attumenGUID)) + Talk(SAY_MIDNIGHT_KILL, unit); } - Midnight.Clear(); - me->SetVisible(false); - me->KillSelf(); - } else ResetTimer -= diff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) - return; - - if (CleaveTimer <= diff) - { - DoCastVictim(SPELL_SHADOWCLEAVE); - CleaveTimer = urand(10000, 15000); - } else CleaveTimer -= diff; + } - if (CurseTimer <= diff) - { - DoCastVictim(SPELL_INTANGIBLE_PRESENCE); - CurseTimer = 30000; - } else CurseTimer -= diff; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() || _phase == PHASE_MOUNTED) + return; - if (RandomYellTimer <= diff) - { - Talk(SAY_RANDOM); - RandomYellTimer = urand(30000, 60000); - } else RandomYellTimer -= diff; + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } - if (me->GetUInt32Value(UNIT_FIELD_DISPLAYID) == MOUNTED_DISPLAYID) - { - if (ChargeTimer <= diff) - { - Unit* target = NULL; - ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList(); - std::vector<Unit*> target_list; - for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr) - { - target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (target && !target->IsWithinDist(me, ATTACK_DISTANCE, false)) - target_list.push_back(target); - target = NULL; - } - if (!target_list.empty()) - target = *(target_list.begin() + rand32() % target_list.size()); + private: + ObjectGuid _attumenGUID; + uint8 _phase; + }; - DoCast(target, SPELL_BERSERKER_CHARGE); - ChargeTimer = 20000; - } else ChargeTimer -= diff; - } - else + CreatureAI* GetAI(Creature* creature) const override { - if (HealthBelowPct(25)) - { - Creature* pMidnight = ObjectAccessor::GetCreature(*me, Midnight); - if (pMidnight && pMidnight->GetTypeId() == TYPEID_UNIT) - { - ENSURE_AI(boss_midnight::boss_midnightAI, (pMidnight->AI()))->Mount(me); - me->SetHealth(pMidnight->GetHealth()); - DoResetThreat(); - } - } + return new boss_midnightAI(creature); } - - DoMeleeAttackIfReady(); -} +}; void AddSC_boss_attumen() { diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp index 79e36442f4b..29c78d3b388 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp @@ -143,12 +143,12 @@ public: if (me->IsAlive()) SpawnAdds(); - instance->SetData(TYPE_MOROES, NOT_STARTED); + instance->SetBossState(DATA_MOROES, NOT_STARTED); } void StartEvent() { - instance->SetData(TYPE_MOROES, IN_PROGRESS); + instance->SetBossState(DATA_MOROES, IN_PROGRESS); DoZoneInCombat(); } @@ -171,7 +171,7 @@ public: { Talk(SAY_DEATH); - instance->SetData(TYPE_MOROES, DONE); + instance->SetBossState(DATA_MOROES, DONE); DeSpawnAdds(); @@ -257,12 +257,6 @@ public: if (!UpdateVictim()) return; - if (!instance->GetData(TYPE_MOROES)) - { - EnterEvadeMode(); - return; - } - if (!Enrage && HealthBelowPct(30)) { DoCast(me, SPELL_FRENZY); @@ -304,7 +298,7 @@ public: if (Blind_Timer <= diff) { std::list<Unit*> targets; - SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetMeleeReach()*5, true); + SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetCombatReach()*5, true); for (std::list<Unit*>::const_iterator i = targets.begin(); i != targets.end(); ++i) if (!me->IsWithinMeleeRange(*i)) { @@ -347,7 +341,7 @@ struct boss_moroes_guestAI : public ScriptedAI void Reset() override { - instance->SetData(TYPE_MOROES, NOT_STARTED); + instance->SetBossState(DATA_MOROES, NOT_STARTED); } void AcquireGUID() @@ -373,7 +367,7 @@ struct boss_moroes_guestAI : public ScriptedAI void UpdateAI(uint32 /*diff*/) override { - if (!instance->GetData(TYPE_MOROES)) + if (instance->GetBossState(DATA_MOROES) != IN_PROGRESS) EnterEvadeMode(); DoMeleeAttackIfReady(); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp index 6f5f2b8f65f..6ff20e66f7f 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp @@ -138,15 +138,15 @@ public: { Initialize(); - me->SetSpeed(MOVE_RUN, 2.0f); + me->SetSpeedRate(MOVE_RUN, 2.0f); me->SetDisableGravity(true); me->SetWalk(false); me->setActive(true); - if (instance->GetData(TYPE_NIGHTBANE) == DONE || instance->GetData(TYPE_NIGHTBANE) == IN_PROGRESS) + if (instance->GetBossState(DATA_NIGHTBANE) == DONE || instance->GetBossState(DATA_NIGHTBANE) == IN_PROGRESS) me->DisappearAndDie(); else - instance->SetData(TYPE_NIGHTBANE, NOT_STARTED); + instance->SetBossState(DATA_NIGHTBANE, NOT_STARTED); HandleTerraceDoors(true); @@ -165,10 +165,10 @@ public: void EnterCombat(Unit* /*who*/) override { - instance->SetData(TYPE_NIGHTBANE, IN_PROGRESS); + instance->SetBossState(DATA_NIGHTBANE, IN_PROGRESS); HandleTerraceDoors(false); - Talk(YELL_AGGRO); + Talk(YELL_AGGRO); } void AttackStart(Unit* who) override @@ -179,7 +179,7 @@ public: void JustDied(Unit* /*killer*/) override { - instance->SetData(TYPE_NIGHTBANE, DONE); + instance->SetBossState(DATA_NIGHTBANE, DONE); HandleTerraceDoors(true); } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp index 450678a0f86..17a23a0b2e7 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp @@ -154,7 +154,7 @@ public: Initialize(); // Not in progress - instance->SetData(TYPE_ARAN, NOT_STARTED); + instance->SetBossState(DATA_ARAN, NOT_STARTED); instance->HandleGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR), true); } @@ -167,7 +167,7 @@ public: { Talk(SAY_DEATH); - instance->SetData(TYPE_ARAN, DONE); + instance->SetBossState(DATA_ARAN, DONE); instance->HandleGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR), true); } @@ -175,7 +175,7 @@ public: { Talk(SAY_AGGRO); - instance->SetData(TYPE_ARAN, IN_PROGRESS); + instance->SetBossState(DATA_ARAN, IN_PROGRESS); instance->HandleGameObject(instance->GetGuidData(DATA_GO_LIBRARY_DOOR), false); } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp index 7bc835dcced..2e33f0933e3 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp @@ -61,7 +61,6 @@ enum Creatures NPC_DEMONCHAINS = 17248, NPC_FIENDISHIMP = 17267, NPC_PORTAL = 17265, - NPC_KILREK = 17229 }; @@ -316,7 +315,7 @@ public: Initialize(); - instance->SetData(TYPE_TERESTIAN, NOT_STARTED); + instance->SetBossState(DATA_TERESTIAN, NOT_STARTED); me->RemoveAurasDueToSpell(SPELL_BROKEN_PACT); @@ -371,7 +370,7 @@ public: Talk(SAY_DEATH); - instance->SetData(TYPE_TERESTIAN, DONE); + instance->SetBossState(DATA_TERESTIAN, DONE); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp index d4d0e6fa70d..2e4ac11d3fa 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp @@ -674,6 +674,12 @@ public: void Initialize() { + // Hello, developer from the future! It's me again! + // This time, you're fixing Karazhan scripts. Awesome. These are a mess of hacks. An amalgamation of hacks, so to speak. Maybe even a Patchwerk thereof. + // Anyway, I digress. + // @todo This line below is obviously a hack. Duh. I'm just coming in here to hackfix the encounter to actually be completable. + // It needs a rewrite. Badly. Please, take good care of it. + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); CycloneTimer = 30000; ChainLightningTimer = 10000; } @@ -701,20 +707,12 @@ public: void EnterCombat(Unit* /*who*/) override { Talk(SAY_CRONE_AGGRO); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); } void JustDied(Unit* /*killer*/) override { Talk(SAY_CRONE_DEATH); - - instance->SetData(TYPE_OPERA, DONE); - instance->HandleGameObject(instance->GetGuidData(DATA_GO_STAGEDOORLEFT), true); - instance->HandleGameObject(instance->GetGuidData(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + instance->SetBossState(DATA_OPERA_PERFORMANCE, DONE); } void UpdateAI(uint32 diff) override @@ -722,9 +720,6 @@ public: if (!UpdateVictim()) return; - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (CycloneTimer <= diff) { if (Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, float(urand(0, 9)), float(urand(0, 9)), 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000)) @@ -802,46 +797,43 @@ enum RedRidingHood SAY_WOLF_AGGRO = 0, SAY_WOLF_SLAY = 1, SAY_WOLF_HOOD = 2, + OPTION_WHAT_PHAT_LEWTS_YOU_HAVE = 7443, SOUND_WOLF_DEATH = 9275, SPELL_LITTLE_RED_RIDING_HOOD = 30768, SPELL_TERRIFYING_HOWL = 30752, SPELL_WIDE_SWIPE = 30761, - CREATURE_BIG_BAD_WOLF = 17521, + CREATURE_BIG_BAD_WOLF = 17521 }; - -#define GOSSIP_GRANDMA "What phat lewtz you have grandmother?" - - - class npc_grandmother : public CreatureScript { -public: - npc_grandmother() : CreatureScript("npc_grandmother") { } + public: + npc_grandmother() : CreatureScript("npc_grandmother") { } - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF) + struct npc_grandmotherAI : public ScriptedAI { - if (Creature* pBigBadWolf = creature->SummonCreature(CREATURE_BIG_BAD_WOLF, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS)) - pBigBadWolf->AI()->AttackStart(player); + npc_grandmotherAI(Creature* creature) : ScriptedAI(creature) { } - creature->DespawnOrUnsummon(); - } + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + if (menuId == OPTION_WHAT_PHAT_LEWTS_YOU_HAVE && gossipListId == 0) + { + player->CLOSE_GOSSIP_MENU(); - return true; - } + if (Creature* pBigBadWolf = me->SummonCreature(CREATURE_BIG_BAD_WOLF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS)) + pBigBadWolf->AI()->AttackStart(player); - bool OnGossipHello(Player* player, Creature* creature) override - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GRANDMA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - player->SEND_GOSSIP_MENU(8990, creature->GetGUID()); + me->DespawnOrUnsummon(); + } + } + }; - return true; - } + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_grandmotherAI(creature); + } }; class boss_bigbadwolf : public CreatureScript @@ -908,13 +900,7 @@ public: void JustDied(Unit* /*killer*/) override { DoPlaySoundToSet(me, SOUND_WOLF_DEATH); - - instance->SetData(TYPE_OPERA, DONE); - instance->HandleGameObject(instance->GetGuidData(DATA_GO_STAGEDOORLEFT), true); - instance->HandleGameObject(instance->GetGuidData(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + instance->SetBossState(DATA_OPERA_PERFORMANCE, DONE); } void UpdateAI(uint32 diff) override @@ -1158,12 +1144,7 @@ public: void JustDied(Unit* /*killer*/) override { Talk(SAY_JULIANNE_DEATH02); - - instance->SetData(TYPE_OPERA, DONE); - instance->HandleGameObject(instance->GetGuidData(DATA_GO_STAGEDOORLEFT), true); - instance->HandleGameObject(instance->GetGuidData(DATA_GO_STAGEDOORRIGHT), true); - if (GameObject* pSideEntrance = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + instance->SetBossState(DATA_OPERA_PERFORMANCE, DONE); } void KilledUnit(Unit* /*victim*/) override @@ -1316,13 +1297,7 @@ public: void JustDied(Unit* /*killer*/) override { Talk(SAY_ROMULO_DEATH); - - instance->SetData(TYPE_OPERA, DONE); - instance->HandleGameObject(instance->GetGuidData(DATA_GO_STAGEDOORLEFT), true); - instance->HandleGameObject(instance->GetGuidData(DATA_GO_STAGEDOORRIGHT), true); - - if (GameObject* pSideEntrance = instance->instance->GetGameObject(instance->GetGuidData(DATA_GO_SIDE_ENTRANCE_DOOR))) - pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + instance->SetBossState(DATA_OPERA_PERFORMANCE, DONE); } void KilledUnit(Unit* /*victim*/) override diff --git a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp index b725f421c8f..ad403e6aeed 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/instance_karazhan.cpp @@ -27,8 +27,6 @@ EndScriptData */ #include "InstanceScript.h" #include "karazhan.h" -#define MAX_ENCOUNTER 12 - /* 0 - Attumen + Midnight (optional) 1 - Moroes @@ -47,8 +45,8 @@ EndScriptData */ const Position OptionalSpawn[] = { { -10960.981445f, -1940.138428f, 46.178097f, 4.12f }, // Hyakiss the Lurker - { -10899.903320f, -2085.573730f, 49.474449f, 1.38f }, // Rokad the Ravager - { -10945.769531f, -2040.153320f, 49.474438f, 0.077f } // Shadikith the Glider + { -10945.769531f, -2040.153320f, 49.474438f, 0.077f }, // Shadikith the Glider + { -10899.903320f, -2085.573730f, 49.474449f, 1.38f } // Rokad the Ravager }; class instance_karazhan : public InstanceMapScript @@ -66,53 +64,27 @@ public: instance_karazhan_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + SetBossNumber(EncounterCount); // 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered. - m_uiOperaEvent = urand(1, 3); - m_uiOzDeathCount = 0; + OperaEvent = urand(EVENT_OZ, EVENT_RAJ); + OzDeathCount = 0; OptionalBossCount = 0; } - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string strSaveData; - - uint32 m_uiOperaEvent; - uint32 m_uiOzDeathCount; - uint32 OptionalBossCount; - - ObjectGuid m_uiCurtainGUID; - ObjectGuid m_uiStageDoorLeftGUID; - ObjectGuid m_uiStageDoorRightGUID; - ObjectGuid m_uiKilrekGUID; - ObjectGuid m_uiTerestianGUID; - ObjectGuid m_uiMoroesGUID; - ObjectGuid m_uiLibraryDoor; // Door at Shade of Aran - ObjectGuid m_uiMassiveDoor; // Door at Netherspite - ObjectGuid m_uiSideEntranceDoor; // Side Entrance - ObjectGuid m_uiGamesmansDoor; // Door before Chess - ObjectGuid m_uiGamesmansExitDoor; // Door after Chess - ObjectGuid m_uiNetherspaceDoor; // Door at Malchezaar - ObjectGuid MastersTerraceDoor[2]; - ObjectGuid ImageGUID; - ObjectGuid DustCoveredChest; - - bool IsEncounterInProgress() const override - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - void OnCreatureCreate(Creature* creature) override { switch (creature->GetEntry()) { - case 17229: m_uiKilrekGUID = creature->GetGUID(); break; - case 15688: m_uiTerestianGUID = creature->GetGUID(); break; - case 15687: m_uiMoroesGUID = creature->GetGUID(); break; + case NPC_KILREK: + KilrekGUID = creature->GetGUID(); + break; + case NPC_TERESTIAN_ILLHOOF: + TerestianGUID = creature->GetGUID(); + break; + case NPC_MOROES: + MoroesGUID = creature->GetGUID(); + break; } } @@ -132,130 +104,129 @@ public: case NPC_PHASE_HOUND: case NPC_DREADBEAST: case NPC_SHADOWBEAST: - SetData(TYPE_OPTIONAL_BOSS, NOT_STARTED); - break; - default: - break; - } - } - - void SetData(uint32 type, uint32 uiData) override - { - switch (type) - { - case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break; - case TYPE_MOROES: - if (m_auiEncounter[1] == DONE) - break; - m_auiEncounter[1] = uiData; - break; - case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break; - case TYPE_OPTIONAL_BOSS: - m_auiEncounter[3] = uiData; - if (uiData == NOT_STARTED) + if (GetBossState(DATA_OPTIONAL_BOSS) == TO_BE_DECIDED) { ++OptionalBossCount; - if (OptionalBossCount == 50) + if (OptionalBossCount == OPTIONAL_BOSS_REQUIRED_DEATH_COUNT) { - switch (urand(0, 2)) + switch (urand(NPC_HYAKISS_THE_LURKER, NPC_ROKAD_THE_RAVAGER)) { - case 0: + case NPC_HYAKISS_THE_LURKER: instance->SummonCreature(NPC_HYAKISS_THE_LURKER, OptionalSpawn[0]); break; - case 1: - instance->SummonCreature(NPC_ROKAD_THE_RAVAGER, OptionalSpawn[1]); + case NPC_SHADIKITH_THE_GLIDER: + instance->SummonCreature(NPC_SHADIKITH_THE_GLIDER, OptionalSpawn[1]); break; - case 2: - instance->SummonCreature(NPC_SHADIKITH_THE_GLIDER, OptionalSpawn[2]); + case NPC_ROKAD_THE_RAVAGER: + instance->SummonCreature(NPC_ROKAD_THE_RAVAGER, OptionalSpawn[2]); break; } } } break; - case TYPE_OPERA: - m_auiEncounter[4] = uiData; - if (uiData == DONE) - UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, 16812, NULL); - break; - case TYPE_CURATOR: m_auiEncounter[5] = uiData; break; - case TYPE_ARAN: m_auiEncounter[6] = uiData; break; - case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break; - case TYPE_NETHERSPITE: m_auiEncounter[8] = uiData; break; - case TYPE_CHESS: - if (uiData == DONE) - DoRespawnGameObject(DustCoveredChest, DAY); - m_auiEncounter[9] = uiData; - break; - case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break; - case TYPE_NIGHTBANE: - if (m_auiEncounter[11] != DONE) - m_auiEncounter[11] = uiData; - break; - case DATA_OPERA_OZ_DEATHCOUNT: - if (uiData == SPECIAL) - ++m_uiOzDeathCount; - else if (uiData == IN_PROGRESS) - m_uiOzDeathCount = 0; + default: break; } + } - if (uiData == DONE) + void SetData(uint32 type, uint32 data) override + { + switch (type) { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' - << m_auiEncounter[3] << ' ' << m_auiEncounter[4] << ' ' << m_auiEncounter[5] << ' ' << m_auiEncounter[6] << ' ' - << m_auiEncounter[7] << ' ' << m_auiEncounter[8] << ' ' << m_auiEncounter[9] << ' ' << m_auiEncounter[10] << ' ' << m_auiEncounter[11]; + case DATA_OPERA_OZ_DEATHCOUNT: + if (data == SPECIAL) + ++OzDeathCount; + else if (data == IN_PROGRESS) + OzDeathCount = 0; + break; + } + } - strSaveData = saveStream.str(); + bool SetBossState(uint32 type, EncounterState state) override + { + if (!InstanceScript::SetBossState(type, state)) + return false; - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; + switch (type) + { + case DATA_OPERA_PERFORMANCE: + if (state == DONE) + { + HandleGameObject(StageDoorLeftGUID, true); + HandleGameObject(StageDoorRightGUID, true); + if (GameObject* sideEntrance = instance->GetGameObject(SideEntranceDoor)) + sideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, 16812, NULL); + } + break; + case DATA_CHESS: + if (state == DONE) + DoRespawnGameObject(DustCoveredChest, DAY); + break; + default: + break; } + + return true; } - void SetGuidData(uint32 identifier, ObjectGuid data) override + void SetGuidData(uint32 type, ObjectGuid data) override { - switch (identifier) - { - case DATA_IMAGE_OF_MEDIVH: ImageGUID = data; - } + if (type == DATA_IMAGE_OF_MEDIVH) + ImageGUID = data; } void OnGameObjectCreate(GameObject* go) override { switch (go->GetEntry()) { - case 183932: m_uiCurtainGUID = go->GetGUID(); break; - case 184278: - m_uiStageDoorLeftGUID = go->GetGUID(); - if (m_auiEncounter[4] == DONE) + case GO_STAGE_CURTAIN: + CurtainGUID = go->GetGUID(); + break; + case GO_STAGE_DOOR_LEFT: + StageDoorLeftGUID = go->GetGUID(); + if (GetBossState(DATA_OPERA_PERFORMANCE) == DONE) go->SetGoState(GO_STATE_ACTIVE); break; - case 184279: - m_uiStageDoorRightGUID = go->GetGUID(); - if (m_auiEncounter[4] == DONE) + case GO_STAGE_DOOR_RIGHT: + StageDoorRightGUID = go->GetGUID(); + if (GetBossState(DATA_OPERA_PERFORMANCE) == DONE) go->SetGoState(GO_STATE_ACTIVE); break; - case 184517: m_uiLibraryDoor = go->GetGUID(); break; - case 185521: m_uiMassiveDoor = go->GetGUID(); break; - case 184276: m_uiGamesmansDoor = go->GetGUID(); break; - case 184277: m_uiGamesmansExitDoor = go->GetGUID(); break; - case 185134: m_uiNetherspaceDoor = go->GetGUID(); break; - case 184274: MastersTerraceDoor[0] = go->GetGUID(); break; - case 184280: MastersTerraceDoor[1] = go->GetGUID(); break; - case 184275: - m_uiSideEntranceDoor = go->GetGUID(); - if (m_auiEncounter[4] == DONE) + case GO_PRIVATE_LIBRARY_DOOR: + LibraryDoor = go->GetGUID(); + break; + case GO_MASSIVE_DOOR: + MassiveDoor = go->GetGUID(); + break; + case GO_GAMESMAN_HALL_DOOR: + GamesmansDoor = go->GetGUID(); + break; + case GO_GAMESMAN_HALL_EXIT_DOOR: + GamesmansExitDoor = go->GetGUID(); + break; + case GO_NETHERSPACE_DOOR: + NetherspaceDoor = go->GetGUID(); + break; + case GO_MASTERS_TERRACE_DOOR: + MastersTerraceDoor[0] = go->GetGUID(); + break; + case GO_MASTERS_TERRACE_DOOR2: + MastersTerraceDoor[1] = go->GetGUID(); + break; + case GO_SIDE_ENTRANCE_DOOR: + SideEntranceDoor = go->GetGUID(); + if (GetBossState(DATA_OPERA_PERFORMANCE) == DONE) go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); else go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); break; - case 185119: DustCoveredChest = go->GetGUID(); break; + case GO_DUST_COVERED_CHEST: + DustCoveredChest = go->GetGUID(); + break; } - switch (m_uiOperaEvent) + switch (OperaEvent) { /// @todo Set Object visibilities for Opera based on performance case EVENT_OZ: @@ -269,77 +240,77 @@ public: } } - std::string GetSaveData() override - { - return strSaveData; - } - - uint32 GetData(uint32 uiData) const override + uint32 GetData(uint32 type) const override { - switch (uiData) + switch (type) { - case TYPE_ATTUMEN: return m_auiEncounter[0]; - case TYPE_MOROES: return m_auiEncounter[1]; - case TYPE_MAIDEN: return m_auiEncounter[2]; - case TYPE_OPTIONAL_BOSS: return m_auiEncounter[3]; - case TYPE_OPERA: return m_auiEncounter[4]; - case TYPE_CURATOR: return m_auiEncounter[5]; - case TYPE_ARAN: return m_auiEncounter[6]; - case TYPE_TERESTIAN: return m_auiEncounter[7]; - case TYPE_NETHERSPITE: return m_auiEncounter[8]; - case TYPE_CHESS: return m_auiEncounter[9]; - case TYPE_MALCHEZZAR: return m_auiEncounter[10]; - case TYPE_NIGHTBANE: return m_auiEncounter[11]; - case DATA_OPERA_PERFORMANCE: return m_uiOperaEvent; - case DATA_OPERA_OZ_DEATHCOUNT: return m_uiOzDeathCount; + case DATA_OPERA_PERFORMANCE: + return OperaEvent; + case DATA_OPERA_OZ_DEATHCOUNT: + return OzDeathCount; } return 0; } - ObjectGuid GetGuidData(uint32 uiData) const override + ObjectGuid GetGuidData(uint32 type) const override { - switch (uiData) + switch (type) { - case DATA_KILREK: return m_uiKilrekGUID; - case DATA_TERESTIAN: return m_uiTerestianGUID; - case DATA_MOROES: return m_uiMoroesGUID; - case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID; - case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID; - case DATA_GO_CURTAINS: return m_uiCurtainGUID; - case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor; - case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor; - case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor; - case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor; - case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor; - case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor; - case DATA_MASTERS_TERRACE_DOOR_1: return MastersTerraceDoor[0]; - case DATA_MASTERS_TERRACE_DOOR_2: return MastersTerraceDoor[1]; - case DATA_IMAGE_OF_MEDIVH: return ImageGUID; + case DATA_KILREK: + return KilrekGUID; + case DATA_TERESTIAN: + return TerestianGUID; + case DATA_MOROES: + return MoroesGUID; + case DATA_GO_STAGEDOORLEFT: + return StageDoorLeftGUID; + case DATA_GO_STAGEDOORRIGHT: + return StageDoorRightGUID; + case DATA_GO_CURTAINS: + return CurtainGUID; + case DATA_GO_LIBRARY_DOOR: + return LibraryDoor; + case DATA_GO_MASSIVE_DOOR: + return MassiveDoor; + case DATA_GO_SIDE_ENTRANCE_DOOR: + return SideEntranceDoor; + case DATA_GO_GAME_DOOR: + return GamesmansDoor; + case DATA_GO_GAME_EXIT_DOOR: + return GamesmansExitDoor; + case DATA_GO_NETHER_DOOR: + return NetherspaceDoor; + case DATA_MASTERS_TERRACE_DOOR_1: + return MastersTerraceDoor[0]; + case DATA_MASTERS_TERRACE_DOOR_2: + return MastersTerraceDoor[1]; + case DATA_IMAGE_OF_MEDIVH: + return ImageGUID; } return ObjectGuid::Empty; } - void Load(char const* chrIn) override - { - if (!chrIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(chrIn); - std::istringstream loadStream(chrIn); - - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] - >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } + private: + uint32 OperaEvent; + uint32 OzDeathCount; + uint32 OptionalBossCount; + ObjectGuid CurtainGUID; + ObjectGuid StageDoorLeftGUID; + ObjectGuid StageDoorRightGUID; + ObjectGuid KilrekGUID; + ObjectGuid TerestianGUID; + ObjectGuid MoroesGUID; + ObjectGuid LibraryDoor; // Door at Shade of Aran + ObjectGuid MassiveDoor; // Door at Netherspite + ObjectGuid SideEntranceDoor; // Side Entrance + ObjectGuid GamesmansDoor; // Door before Chess + ObjectGuid GamesmansExitDoor; // Door after Chess + ObjectGuid NetherspaceDoor; // Door at Malchezaar + ObjectGuid MastersTerraceDoor[2]; + ObjectGuid ImageGUID; + ObjectGuid DustCoveredChest; }; }; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp index aa2da8cc391..ace15cc2a7e 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp @@ -168,7 +168,7 @@ public: void StartEvent() { - instance->SetData(TYPE_OPERA, IN_PROGRESS); + instance->SetBossState(DATA_OPERA_PERFORMANCE, IN_PROGRESS); //resets count for this event, in case earlier failed if (m_uiEventId == EVENT_OZ) @@ -377,7 +377,7 @@ public: if (InstanceScript* instance = creature->GetInstanceScript()) { // Check for death of Moroes and if opera event is not done already - if (instance->GetData(TYPE_MOROES) == DONE && instance->GetData(TYPE_OPERA) != DONE) + if (instance->GetBossState(DATA_MOROES) == DONE && instance->GetBossState(DATA_OPERA_PERFORMANCE) != DONE) { player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); @@ -562,7 +562,7 @@ public: arca->GetMotionMaster()->MovePoint(0, -11010.82f, -1761.18f, 156.47f); arca->setActive(true); arca->InterruptNonMeleeSpells(true); - arca->SetSpeed(MOVE_FLIGHT, 2.0f); + arca->SetSpeedRate(MOVE_FLIGHT, 2.0f); } return 10000; case 13: diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h index 4d86492257c..2dc3750dc5b 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.h @@ -21,27 +21,26 @@ #define DataHeader "KZ" +uint32 const EncounterCount = 12; + enum DataTypes { - TYPE_ATTUMEN = 1, - TYPE_MOROES = 2, - TYPE_MAIDEN = 3, - TYPE_OPTIONAL_BOSS = 4, - TYPE_OPERA = 5, - TYPE_CURATOR = 6, - TYPE_ARAN = 7, - TYPE_TERESTIAN = 8, - TYPE_NETHERSPITE = 9, - TYPE_CHESS = 10, - TYPE_MALCHEZZAR = 11, - TYPE_NIGHTBANE = 12, + DATA_ATTUMEN = 0, + DATA_MOROES = 1, + DATA_MAIDEN_OF_VIRTUE = 2, + DATA_OPTIONAL_BOSS = 3, + DATA_OPERA_PERFORMANCE = 4, + DATA_CURATOR = 5, + DATA_ARAN = 6, + DATA_TERESTIAN = 7, + DATA_NETHERSPITE = 8, + DATA_CHESS = 9, + DATA_MALCHEZZAR = 10, + DATA_NIGHTBANE = 11, - DATA_OPERA_PERFORMANCE = 13, DATA_OPERA_OZ_DEATHCOUNT = 14, DATA_KILREK = 15, - DATA_TERESTIAN = 16, - DATA_MOROES = 17, DATA_GO_CURTAINS = 18, DATA_GO_STAGEDOORLEFT = 19, DATA_GO_STAGEDOORRIGHT = 20, @@ -69,6 +68,11 @@ enum MiscCreatures NPC_HYAKISS_THE_LURKER = 16179, NPC_ROKAD_THE_RAVAGER = 16181, NPC_SHADIKITH_THE_GLIDER = 16180, + NPC_TERESTIAN_ILLHOOF = 15688, + NPC_MOROES = 15687, + NPC_ATTUMEN_UNMOUNTED = 15550, + NPC_ATTUMEN_MOUNTED = 16152, + NPC_MIDNIGHT = 16151, // Trash NPC_COLDMIST_WIDOW = 16171, @@ -78,6 +82,29 @@ enum MiscCreatures NPC_GREATER_SHADOWBAT = 16174, NPC_PHASE_HOUND = 16178, NPC_DREADBEAST = 16177, - NPC_SHADOWBEAST = 16176 + NPC_SHADOWBEAST = 16176, + NPC_KILREK = 17229 +}; + +enum GameObjectIds +{ + GO_STAGE_CURTAIN = 183932, + GO_STAGE_DOOR_LEFT = 184278, + GO_STAGE_DOOR_RIGHT = 184279, + GO_PRIVATE_LIBRARY_DOOR = 184517, + GO_MASSIVE_DOOR = 185521, + GO_GAMESMAN_HALL_DOOR = 184276, + GO_GAMESMAN_HALL_EXIT_DOOR = 184277, + GO_NETHERSPACE_DOOR = 185134, + GO_MASTERS_TERRACE_DOOR = 184274, + GO_MASTERS_TERRACE_DOOR2 = 184280, + GO_SIDE_ENTRANCE_DOOR = 184275, + GO_DUST_COVERED_CHEST = 185119 }; + +enum Misc +{ + OPTIONAL_BOSS_REQUIRED_DEATH_COUNT = 50 +}; + #endif diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index b809128e731..ebe406c8909 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -405,7 +405,7 @@ public: Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); if (Orb && target) { - Orb->SetSpeed(MOVE_RUN, 0.5f); + Orb->SetSpeedRate(MOVE_RUN, 0.5f); Orb->AddThreat(target, 1000000.0f); Orb->AI()->AttackStart(target); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index 81044a0dbb1..3cf78b79f67 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -396,7 +396,7 @@ class npc_eye_of_acherus : public CreatureScript if (Player* owner = me->GetCharmerOrOwner()->ToPlayer()) { for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) - me->SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true); + me->SetSpeedRate(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i))); Talk(TALK_MOVE_START, owner); } me->GetMotionMaster()->MovePath(me->GetEntry() * 100, false); @@ -419,7 +419,7 @@ class npc_eye_of_acherus : public CreatureScript { owner->RemoveAura(SPELL_EYE_FLIGHT_BOOST); for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) - me->SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true); + me->SetSpeedRate(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i))); Talk(TALK_CONTROL, owner); } @@ -703,7 +703,7 @@ class npc_dark_rider_of_acherus : public CreatureScript TargetGUID = who->GetGUID(); me->SetWalk(true); - me->SetSpeed(MOVE_RUN, 0.4f); + me->SetSpeedRate(MOVE_RUN, 0.4f); me->GetMotionMaster()->MoveChase(who); me->SetTarget(TargetGUID); Intro = true; @@ -1050,7 +1050,7 @@ class npc_scarlet_miner_cart : public CreatureScript // Not 100% correct, but movement is smooth. Sometimes miner walks faster // than normal, this speed is fast enough to keep up at those times. - me->SetSpeed(MOVE_RUN, 1.25f); + me->SetSpeedRate(MOVE_RUN, 1.25f); me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index e336ff24382..ea6d2cb0b6f 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -923,7 +923,7 @@ public: if (ObjectAccessor::GetCreature(*me, uiLichKingGUID)) DoCast(me, SPELL_MOGRAINE_CHARGE); // jumping charge // doesn't make it looks well, so workarounds, Darion charges, looks better - me->SetSpeed(MOVE_RUN, 3.0f); + me->SetSpeedRate(MOVE_RUN, 3.0f); me->SetWalk(false); SetHoldState(false); JumpToNextStep(0); @@ -935,7 +935,7 @@ public: temp->HandleEmoteCommand(EMOTE_ONESHOT_KICK); temp->AI()->Talk(SAY_LIGHT_OF_DAWN46); } - me->SetSpeed(MOVE_RUN, 6.0f); + me->SetSpeedRate(MOVE_RUN, 6.0f); me->SetStandState(UNIT_STAND_STATE_DEAD); SetHoldState(false); // Darion got kicked by lich king JumpToNextStep(0); @@ -997,7 +997,7 @@ public: Unit* temp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->setFaction(me->getFaction()); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); uiDefenderGUID[0] = temp->GetGUID(); @@ -1005,7 +1005,7 @@ public: temp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->setFaction(me->getFaction()); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); uiEarthshatterGUID[0] = temp->GetGUID(); @@ -1014,7 +1014,7 @@ public: { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); temp->AI()->Talk(SAY_LIGHT_OF_DAWN50); } @@ -1022,7 +1022,7 @@ public: { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->HandleEmoteCommand(EMOTE_STATE_ATTACK_UNARMED); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); } @@ -1030,7 +1030,7 @@ public: { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); } } @@ -1044,33 +1044,33 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiMaxwellGUID)) { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[14]); } if (Creature* temp = ObjectAccessor::GetCreature(*me, uiKorfaxGUID)) { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[11]); } if (Creature* temp = ObjectAccessor::GetCreature(*me, uiEligorGUID)) { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[17]); } if (Creature* temp = ObjectAccessor::GetCreature(*me, uiDefenderGUID[0])) { - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f })); } if (Creature* temp = ObjectAccessor::GetCreature(*me, uiEarthshatterGUID[0])) { - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f })); } @@ -1093,7 +1093,7 @@ public: break; case 46: // Darion stand up, "not today" - me->SetSpeed(MOVE_RUN, 1.0f); + me->SetSpeedRate(MOVE_RUN, 1.0f); me->SetWalk(true); me->SetStandState(UNIT_STAND_STATE_STAND); Talk(SAY_LIGHT_OF_DAWN53); @@ -1116,7 +1116,7 @@ public: case 48: // Show the cleansing effect (dawn of light) //if (GameObject* go = me->GetMap()->GetGameObject(uiDawnofLightGUID)) // go->SetPhaseMask(128, true); - me->SummonGameObject(GO_LIGHT_OF_DAWN, 2283.896f, -5287.914f, 83.066f, 0, 0, 0, 0, 0, 30); + me->SummonGameObject(GO_LIGHT_OF_DAWN, 2283.896f, -5287.914f, 83.066f, 0.f, G3D::Quat(), 30); if (Creature* temp = ObjectAccessor::GetCreature(*me, uiTirionGUID)) { if (temp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER)) @@ -1153,7 +1153,7 @@ public: temp->AI()->Talk(EMOTE_LIGHT_OF_DAWN16); temp->CastSpell(temp, SPELL_TIRION_CHARGE, false); // jumping charge temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - temp->SetSpeed(MOVE_RUN, 3.0f); // workarounds, make Tirion still running + temp->SetSpeedRate(MOVE_RUN, 3.0f); // workarounds, make Tirion still running temp->SetWalk(false); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2]); if (Creature* lktemp = ObjectAccessor::GetCreature(*me, uiLichKingGUID)) @@ -1171,7 +1171,7 @@ public: case 54: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiLichKingGUID)) { - temp->SetSpeed(MOVE_RUN, 1.0f); + temp->SetSpeedRate(MOVE_RUN, 1.0f); me->SetWalk(true); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29]); // 26 } @@ -1208,7 +1208,7 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiTirionGUID)) // Tirion runs to Darion { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - temp->SetSpeed(MOVE_RUN, 1.0f); + temp->SetSpeedRate(MOVE_RUN, 1.0f); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[6]); } JumpToNextStep(2500); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp index 53b6d2be8dd..9abd0c049d8 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/zone_the_scarlet_enclave.cpp @@ -109,7 +109,7 @@ public: FlyBackTimer = 4500; break; case 2: - if (!player->isResurrectRequested()) + if (!player->IsResurrectRequested()) { me->HandleEmoteCommand(EMOTE_ONESHOT_CUSTOM_SPELL_01); DoCast(player, SPELL_REVIVE, true); diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp index dff0a66cec0..734b70933aa 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp @@ -134,8 +134,6 @@ static char const* Text[]= "Now, know demise!" }; -#define EMOTE_LAUGHS "Headless Horseman laughs" // needs assigned to db. - class npc_wisp_invis : public CreatureScript { public: @@ -347,7 +345,6 @@ public: Creature* speaker = DoSpawnCreature(HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 1000); if (speaker) speaker->CastSpell(speaker, SPELL_HEAD_SPEAKS, false); - me->TextEmote(EMOTE_LAUGHS); } else laugh -= diff; } @@ -453,7 +450,7 @@ public: me->SetVisible(false); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->SetDisableGravity(true); - me->SetSpeed(MOVE_WALK, 5.0f, true); + me->SetSpeedRate(MOVE_WALK, 5.0f); wp_reached = false; count = 0; say_timer = 3000; @@ -724,7 +721,6 @@ public: if (laugh <= diff) { laugh = urand(11000, 22000); - me->TextEmote(EMOTE_LAUGHS); DoPlaySoundToSet(me, RandomLaugh[rand32() % 3]); } else laugh -= diff; @@ -898,12 +894,12 @@ public: if (instance->GetBossState(DATA_HORSEMAN_EVENT) == IN_PROGRESS) return false; - player->AreaExploredOrEventHappens(11405); - if (Creature* horseman = go->SummonCreature(HH_MOUNTED, FlightPoint[20].x, FlightPoint[20].y, FlightPoint[20].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->PlayerGUID = player->GetGUID(); - ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->FlyMode(); - } + player->AreaExploredOrEventHappens(11405); + if (Creature* horseman = go->SummonCreature(HH_MOUNTED, FlightPoint[20].x, FlightPoint[20].y, FlightPoint[20].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 0)) + { + ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->PlayerGUID = player->GetGUID(); + ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->FlyMode(); + } return true; } }; diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp index 118d28e2142..241710627b0 100644 --- a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp +++ b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp @@ -35,15 +35,25 @@ enum Gameobject GO_ATALAI_STATUE4 = 148833, GO_ATALAI_STATUE5 = 148834, GO_ATALAI_STATUE6 = 148835, - GO_ATALAI_IDOL = 148836, GO_ATALAI_LIGHT1 = 148883, GO_ATALAI_LIGHT2 = 148937 - }; enum CreatureIds { - NPC_MALFURION_STORMRAGE = 15362 + NPC_ATALALARION = 8580 +}; + +static Position const atalalarianPos = { -466.5134f, 95.19822f, -189.6463f, 0.03490658f }; +static uint8 const nStatues = 6; +static Position const statuePositions[nStatues] +{ + { -515.553f, 95.25821f, -173.707f, 0.0f }, + { -419.8487f, 94.48368f, -173.707f, 0.0f }, + { -491.4003f, 135.9698f, -173.707f, 0.0f }, + { -491.4909f, 53.48179f, -173.707f, 0.0f }, + { -443.8549f, 136.1007f, -173.707f, 0.0f }, + { -443.4171f, 53.83124f, -173.707f, 0.0f } }; class instance_sunken_temple : public InstanceMapScript @@ -77,7 +87,6 @@ public: ObjectGuid GOAtalaiStatue4; ObjectGuid GOAtalaiStatue5; ObjectGuid GOAtalaiStatue6; - ObjectGuid GOAtalaiIdol; uint32 State; @@ -98,7 +107,6 @@ public: case GO_ATALAI_STATUE4: GOAtalaiStatue4 = go->GetGUID(); break; case GO_ATALAI_STATUE5: GOAtalaiStatue5 = go->GetGUID(); break; case GO_ATALAI_STATUE6: GOAtalaiStatue6 = go->GetGUID(); break; - case GO_ATALAI_IDOL: GOAtalaiIdol = go->GetGUID(); break; } } @@ -155,7 +163,10 @@ public: if (s1 && s2 && s3 && s4 && s5 && !s6) { if (GameObject* pAtalaiStatue6 = instance->GetGameObject(GOAtalaiStatue6)) + { UseStatue(pAtalaiStatue6); + UseLastStatue(pAtalaiStatue6); + } s6 = true; State = 0; } @@ -165,22 +176,17 @@ public: void UseStatue(GameObject* go) { - go->SummonGameObject(GO_ATALAI_LIGHT1, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ(), 0, 0, 0, 0, 0, 0); + go->SummonGameObject(GO_ATALAI_LIGHT1, *go, G3D::Quat(), 0); go->SetUInt32Value(GAMEOBJECT_FLAGS, 4); } - /* - void UseLastStatue(GameObject* go) - { - AtalaiStatue1->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue1->GetPositionX(), AtalaiStatue1->GetPositionY(), AtalaiStatue1->GetPositionZ(), 0, 0, 0, 0, 0, 100); - AtalaiStatue2->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue2->GetPositionX(), AtalaiStatue2->GetPositionY(), AtalaiStatue2->GetPositionZ(), 0, 0, 0, 0, 0, 100); - AtalaiStatue3->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue3->GetPositionX(), AtalaiStatue3->GetPositionY(), AtalaiStatue3->GetPositionZ(), 0, 0, 0, 0, 0, 100); - AtalaiStatue4->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue4->GetPositionX(), AtalaiStatue4->GetPositionY(), AtalaiStatue4->GetPositionZ(), 0, 0, 0, 0, 0, 100); - AtalaiStatue5->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue5->GetPositionX(), AtalaiStatue5->GetPositionY(), AtalaiStatue5->GetPositionZ(), 0, 0, 0, 0, 0, 100); - AtalaiStatue6->SummonGameObject(GO_ATALAI_LIGHT2, AtalaiStatue6->GetPositionX(), AtalaiStatue6->GetPositionY(), AtalaiStatue6->GetPositionZ(), 0, 0, 0, 0, 0, 100); - go->SummonGameObject(148838, -488.997, 96.61, -189.019, -1.52, 0, 0, 0, 0, 100); - } - */ + void UseLastStatue(GameObject* go) + { + for (uint8 i = 0; i < nStatues; ++i) + go->SummonGameObject(GO_ATALAI_LIGHT2, statuePositions[i], G3D::Quat(), 0); + + go->SummonCreature(NPC_ATALALARION, atalalarianPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200); + } void SetData(uint32 type, uint32 data) override { diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp index d9b481d7b6d..fded249f9ca 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp @@ -249,7 +249,7 @@ public: me->CastStop(SPELL_FOG_BREATH); me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); me->StopMoving(); - me->SetSpeed(MOVE_RUN, 2.0f); + me->SetSpeedRate(MOVE_RUN, 2.0f); events.ScheduleEvent(EVENT_CLEAVE, urand(5000, 10000)); events.ScheduleEvent(EVENT_CORROSION, urand(10000, 20000)); @@ -530,7 +530,7 @@ public: npc_felmyst_vaporAI(Creature* creature) : ScriptedAI(creature) { me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetSpeed(MOVE_RUN, 0.8f); + me->SetSpeedRate(MOVE_RUN, 0.8f); } void Reset() override { } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index d86b3707606..040d8cb2a37 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -143,11 +143,7 @@ enum Spells SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated }; -/*** Error messages ***/ -#define ERROR_KJ_NOT_SUMMONED "TSCR ERROR: Unable to summon Kil'Jaeden for some reason" - /*** Others ***/ -#define FLOOR_Z 28.050388f #define SHIELD_ORB_Z 45.000f enum Phase @@ -1365,7 +1361,7 @@ public: DoCastVictim(SPELL_SR_SHOOT, false); uiTimer[2] = urand(4000, 6000); } - if (me->IsWithinMeleeRange(me->GetVictim(), 6)) + if (me->IsWithinMeleeRange(me->GetVictim())) { if (uiTimer[0] <= diff) { diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp index 04d23cd7d4e..6c84677708e 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -15,88 +15,119 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Muru -SD%Complete: 80 -SDComment: all sounds, black hole effect triggers to often (46228) -*/ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "sunwell_plateau.h" -#include "Player.h" -#include "SpellInfo.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" -// Muru & Entropius's spells enum Spells { - SPELL_ENRAGE = 26662, - // Muru's spells - SPELL_NEGATIVE_ENERGY = 46009, //(this trigger 46008) - SPELL_DARKNESS = 45999, - SPELL_OPEN_ALL_PORTALS = 46177, - SPELL_OPEN_PORTAL = 45977, - SPELL_OPEN_PORTAL_2 = 45976, - SPELL_SUMMON_BERSERKER = 46037, - SPELL_SUMNON_FURY_MAGE = 46038, - SPELL_SUMMON_VOID_SENTINEL = 45988, - SPELL_SUMMON_ENTROPIUS = 46217, + SPELL_OPEN_PORTAL_PERIODIC = 45994, + SPELL_DARKNESS_PERIODIC = 45998, + SPELL_NEGATIVE_ENERGY_PERIODIC = 46009, + SPELL_SUMMON_VOID_SPAWN = 46071, + SPELL_SUMMON_BLOOD_ELVES_SCRIPT = 46050, + SPELL_SUMMON_BLOOD_ELVES_PERIODIC = 46041, + SPELL_OPEN_ALL_PORTALS = 46177, + SPELL_SUMMON_ENTROPIUS = 46217, + SPELL_ENRAGE = 26662, + SPELL_SUMMON_DARK_FIEND_0 = 46000, + SPELL_SUMMON_DARK_FIEND_1 = 46001, + SPELL_SUMMON_DARK_FIEND_2 = 46002, + SPELL_SUMMON_DARK_FIEND_3 = 46003, + SPELL_SUMMON_DARK_FIEND_4 = 46004, + SPELL_SUMMON_DARK_FIEND_5 = 46005, + SPELL_SUMMON_DARK_FIEND_6 = 46006, + SPELL_SUMMON_DARK_FIEND_7 = 46007, + SPELL_SUMMON_BERSERKER = 46037, + SPELL_SUMMON_BERSERKER_2 = 46040, + SPELL_SUMMON_FURY_MAGE = 46038, + SPELL_SUMMON_FURY_MAGE_2 = 46039, // Entropius's spells - SPELL_DARKNESS_E = 46269, - SPELL_BLACKHOLE = 46282, - SPELL_NEGATIVE_ENERGY_E = 46284, - SPELL_ENTROPIUS_SPAWN = 46223, - - // Shadowsword Berserker's spells - SPELL_FLURRY = 46160, - SPELL_DUAL_WIELD = 29651, + SPELL_ENTROPIUS_COSMETIC_SPAWN = 46223, + SPELL_DARKNESS_E = 46269, + SPELL_NEGATIVE_ENERGY_PERIODIC_E = 46284, + SPELL_BLACKHOLE = 46282, + SPELL_SUMMON_DARKFIEND_E = 46263, + + // Myruu's Portal Target + SPELL_SUMMON_VOID_SENTINEL_SUMMONER = 45978, + SPELL_SUMMON_VOID_SENTINEL_SUMMONER_VISUAL = 45989, + SPELL_SUMMON_VOID_SENTINEL = 45988, + SPELL_TRANSFORM_VISUAL_MISSILE = 46205, + TRANSFORM_VISUAL_MISSILE_1 = 46208, + TRANSFORM_VISUAL_MISSILE_2 = 46178, + SPELL_OPEN_PORTAL = 45977, + SPELL_OPEN_PORTAL_2 = 45976, - // Shadowsword Fury Mage's spells - SPELL_FEL_FIREBALL = 46101, - SPELL_SPELL_FURY = 46102, + //Dark Fiend Spells + SPELL_DARKFIEND_DAMAGE = 45944, + SPELL_DARKFIEND_VISUAL = 45936, + SPELL_DARKFIEND_SKIN = 45934, // Void Sentinel's spells - SPELL_SHADOW_PULSE = 46087, - SPELL_VOID_BLAST = 46161, + SPELL_SHADOW_PULSE_PERIODIC = 46086, + SPELL_VOID_BLAST = 46161, - // Void Spawn's spells - SPELL_SHADOW_BOLT_VOLLEY = 46082, + //Black Hole Spells + SPELL_BLACKHOLE_SUMMON_VISUAL = 46242, + SPELL_BLACKHOLE_SUMMON_VISUAL_2 = 46247, + SPELL_BLACKHOLE_PASSIVE = 46228, + SPELL_BLACK_HOLE_VISUAL_2 = 46235 +}; - //Dark Fiend Spells - SPELL_DARKFIEND_AOE = 45944, - SPELL_DARKFIEND_VISUAL = 45936, - SPELL_DARKFIEND_SKIN = 45934, +enum Phases +{ + PHASE_ONE = 1, + PHASE_TWO = 2 +}; - //Black Hole Spells - SPELL_BLACKHOLE_SPAWN = 46242, - SPELL_BLACKHOLE_GROW = 46228 +enum Misc +{ + MAX_VOID_SPAWNS = 6, + MAX_SUMMON_BLOOD_ELVES = 4, + MAX_SUMMON_DARK_FIEND = 8 }; -enum Events +uint32 const SummonDarkFiendSpells[MAX_SUMMON_DARK_FIEND] = { - // M'uru - EVENT_DARKNESS = 1, - EVENT_SUMMON_HUMANOIDS, - EVENT_SUMMON_SENTINEL, - EVENT_PHASE_TRANSITION, // Delayed phase transition. - EVENT_ENRAGE, - - // Entropius - EVENT_SUMMON_BLACK_HOLE + SPELL_SUMMON_DARK_FIEND_0, + SPELL_SUMMON_DARK_FIEND_1, + SPELL_SUMMON_DARK_FIEND_2, + SPELL_SUMMON_DARK_FIEND_3, + SPELL_SUMMON_DARK_FIEND_4, + SPELL_SUMMON_DARK_FIEND_5, + SPELL_SUMMON_DARK_FIEND_6, + SPELL_SUMMON_DARK_FIEND_7 }; -enum Phases +uint32 const SummonBloodElvesSpells[MAX_SUMMON_BLOOD_ELVES] = { - PHASE_ONE = 1, - PHASE_TWO, + SPELL_SUMMON_BERSERKER, + SPELL_SUMMON_BERSERKER_2, + SPELL_SUMMON_FURY_MAGE, + SPELL_SUMMON_FURY_MAGE_2 }; -enum CreatureGroups +class VoidSpawnSummon : public BasicEvent { - CREATURE_GROUP_HUMANOIDS, - CREATURE_GROUP_DARKFIENDS + public: + explicit VoidSpawnSummon(Creature* owner) + : _owner(owner) + { + } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) + { + _owner->CastSpell((Unit*)nullptr, SPELL_SUMMON_VOID_SENTINEL, true); + return true; + } + + private: + Creature* _owner; }; class boss_entropius : public CreatureScript @@ -110,53 +141,78 @@ public: void Reset() override { - DoCastAOE(SPELL_NEGATIVE_ENERGY_E); + _Reset(); + DoCast(me, SPELL_ENTROPIUS_COSMETIC_SPAWN, true); } - void EnterCombat(Unit* /*who*/) override + void ScheduleTasks() override { - _EnterCombat(); - DoCastAOE(SPELL_NEGATIVE_ENERGY_E, true); - DoCast(me, SPELL_ENTROPIUS_SPAWN); - events.ScheduleEvent(EVENT_SUMMON_BLACK_HOLE, 15000); + scheduler.Schedule(Milliseconds(2000), [this](TaskContext /*context*/) + { + DoResetPortals(); + DoCastAOE(SPELL_NEGATIVE_ENERGY_PERIODIC_E, true); + }); + + scheduler.Schedule(Seconds(15), [this](TaskContext context) + { + DoCastAOE(SPELL_DARKNESS_E, true); + DoCastAOE(SPELL_BLACKHOLE, true); + + context.Repeat(); + }); } - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - switch (summoned->GetEntry()) + switch (summon->GetEntry()) { case NPC_DARK_FIENDS: - summoned->CastSpell(summoned, SPELL_DARKFIEND_VISUAL); + summon->CastSpell(summon, SPELL_DARKFIEND_VISUAL); break; case NPC_DARKNESS: - summoned->AddUnitState(UNIT_STATE_STUNNED); - float x, y, z, o; - summoned->GetHomePosition(x, y, z, o); - me->SummonCreature(NPC_DARK_FIENDS, x, y, z, o, TEMPSUMMON_CORPSE_DESPAWN, 0); + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_BLACKHOLE); + summon->CastSpell(summon, SPELL_SUMMON_DARKFIEND_E, true); break; } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true)); - summons.Summon(summoned); + summons.Summon(summon); } - void ExecuteEvent(uint32 eventId) override + void EnterEvadeMode(EvadeReason /*why*/) override { - if (eventId == EVENT_SUMMON_BLACK_HOLE) - { - if (Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(random, SPELL_DARKNESS_E); - if (Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - random->CastSpell(random, SPELL_BLACKHOLE); - events.ScheduleEvent(EVENT_SUMMON_BLACK_HOLE, 15000); - } + if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MURU))) + muru->AI()->EnterEvadeMode(); + + DoResetPortals(); + summons.DespawnAll(); + me->DespawnOrUnsummon(); } - void EnterEvadeMode(EvadeReason /*why*/) override + void JustDied(Unit* /*killer*/) override { + _JustDied(); + if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MURU))) - muru->AI()->Reset(); // Reset encounter. - me->DisappearAndDie(); - summons.DespawnAll(); + muru->DisappearAndDie(); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + scheduler.Update(diff, [this] + { + DoMeleeAttackIfReady(); + }); + } + + void DoResetPortals() + { + std::list<Creature*> portals; + me->GetCreatureListWithEntryInGrid(portals, NPC_MURU_PORTAL_TARGET, 100.0f); + for (Creature* portal : portals) + portal->RemoveAllAuras(); } }; @@ -181,101 +237,96 @@ public: void Initialize() { - DarkFiend = false; - HasEnraged = false; - EntropiusGUID.Clear(); + _hasEnraged = false; + _phase = PHASE_ONE; + _entropiusGUID.Clear(); } void Reset() override { - Initialize(); _Reset(); + Initialize(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetVisible(true); } + void EnterEvadeMode(EvadeReason /*why*/) override + { + BossAI::EnterEvadeMode(); + if (Creature* entropius = ObjectAccessor::GetCreature(*me, _entropiusGUID)) + entropius->AI()->EnterEvadeMode(); + } + + void ScheduleTasks() override + { + scheduler.Schedule(Minutes(10), [this](TaskContext /*context*/) + { + if (Creature* entropius = ObjectAccessor::GetCreature(*me, _entropiusGUID)) + entropius->CastSpell(entropius, SPELL_ENRAGE); + DoCast(me, SPELL_ENRAGE); + _hasEnraged = true; + }); + + scheduler.Schedule(Seconds(10), [this](TaskContext /*context*/) + { + DoCast(me, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true); + DoCast(me, SPELL_SUMMON_BLOOD_ELVES_PERIODIC, true); + }); + } + void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.SetPhase(PHASE_ONE); - events.ScheduleEvent(EVENT_ENRAGE, 600000); - events.ScheduleEvent(EVENT_DARKNESS, 45000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON_HUMANOIDS, 10000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON_SENTINEL, 31500, 0, PHASE_ONE); - DoCastAOE(SPELL_NEGATIVE_ENERGY); + DoCast(me, SPELL_OPEN_PORTAL_PERIODIC, true); + DoCast(me, SPELL_DARKNESS_PERIODIC, true); + DoCast(me, SPELL_NEGATIVE_ENERGY_PERIODIC, true); } void DamageTaken(Unit* /*done_by*/, uint32 &damage) override { - if (damage >= me->GetHealth() && events.IsInPhase(PHASE_ONE)) + if (damage >= me->GetHealth()) { - damage = 0; + damage = me->GetHealth() - 1; + if (_phase != PHASE_ONE) + return; + + _phase = PHASE_TWO; me->RemoveAllAuras(); - DoCast(me, SPELL_OPEN_ALL_PORTALS); + DoCast(me, SPELL_OPEN_ALL_PORTALS, true); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - events.SetPhase(PHASE_TWO); - events.ScheduleEvent(EVENT_PHASE_TRANSITION, 2000); + + scheduler.Schedule(Seconds(6), [this](TaskContext /*context*/) + { + DoCast(me, SPELL_SUMMON_ENTROPIUS, true); + }); } } - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - switch (summoned->GetEntry()) + if (summon->GetEntry() == NPC_ENTROPIUS) { - case NPC_ENTROPIUS: - me->SetVisible(false); - EntropiusGUID = summoned->GetGUID(); - if (HasEnraged) // If we hit phase transition while enraged, enrage Entropius as well. - summoned->CastSpell(summoned, SPELL_ENRAGE); - break; - case NPC_DARK_FIENDS: - summoned->CastSpell(summoned, SPELL_DARKFIEND_VISUAL); - break; + me->SetVisible(false); + _entropiusGUID = summon->GetGUID(); + if (_hasEnraged) + summon->CastSpell(summon, SPELL_ENRAGE, true); + return; } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true)); - summons.Summon(summoned); + BossAI::JustSummoned(summon); } - void ExecuteEvent(uint32 eventId) override + void UpdateAI(uint32 diff) override { - switch (eventId) - { - case EVENT_DARKNESS: - if (!DarkFiend) - { - DarkFiend = true; - DoCastAOE(SPELL_DARKNESS); - } - else - me->SummonCreatureGroup(CREATURE_GROUP_DARKFIENDS); - events.ScheduleEvent(EVENT_DARKNESS, DarkFiend ? 3000 : 42000, 0, PHASE_ONE); - break; - case EVENT_SUMMON_HUMANOIDS: - me->SummonCreatureGroup(CREATURE_GROUP_HUMANOIDS); - events.ScheduleEvent(EVENT_SUMMON_HUMANOIDS, 60000, 0, PHASE_ONE); - break; - case EVENT_SUMMON_SENTINEL: - DoCastAOE(SPELL_OPEN_PORTAL_2); - events.ScheduleEvent(EVENT_SUMMON_SENTINEL, 30000, 0, PHASE_ONE); - break; - case EVENT_PHASE_TRANSITION: - DoCast(me, SPELL_SUMMON_ENTROPIUS); - break; - case EVENT_ENRAGE: - if (Creature* entropius = ObjectAccessor::GetCreature(*me, EntropiusGUID)) - entropius->CastSpell(entropius, SPELL_ENRAGE); - DoCast(me, SPELL_ENRAGE); - HasEnraged = true; - break; - default: - break; - } + if (!UpdateVictim()) + return; + + scheduler.Update(diff); } private: - bool DarkFiend; - bool HasEnraged; - ObjectGuid EntropiusGUID; + ObjectGuid _entropiusGUID; + bool _hasEnraged; + uint8 _phase; }; CreatureAI* GetAI(Creature* creature) const override @@ -289,89 +340,50 @@ class npc_muru_portal : public CreatureScript public: npc_muru_portal() : CreatureScript("npc_muru_portal") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_muru_portalAI>(creature); - } - struct npc_muru_portalAI : public ScriptedAI { - npc_muru_portalAI(Creature* creature) : ScriptedAI(creature), Summons(creature) - { - Initialize(); - SetCombatMovement(false); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - SummonTimer = 5000; - - InAction = false; - SummonSentinel = false; - } - - InstanceScript* instance; - - SummonList Summons; - - bool SummonSentinel; - bool InAction; - - uint32 SummonTimer; - - void Reset() override - { - Initialize(); + npc_muru_portalAI(Creature* creature) : ScriptedAI(creature) { } - me->AddUnitState(UNIT_STATE_STUNNED); - - Summons.DespawnAll(); - } - - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - if (Player* target = ObjectAccessor::GetPlayer(*me, instance->GetGuidData(DATA_PLAYER_GUID))) - summoned->AI()->AttackStart(target); + DoCast(summon, SPELL_SUMMON_VOID_SENTINEL_SUMMONER_VISUAL, true); - Summons.Summon(summoned); + summon->m_Events.AddEvent(new VoidSpawnSummon(summon), summon->m_Events.CalculateTime(1500)); } - void SpellHit(Unit* /*caster*/, const SpellInfo* Spell) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o); - InAction = true; - switch (Spell->Id) + switch (spell->Id) { case SPELL_OPEN_ALL_PORTALS: - DoCastAOE(SPELL_OPEN_PORTAL); + DoCastAOE(SPELL_OPEN_PORTAL, true); + DoCastAOE(SPELL_TRANSFORM_VISUAL_MISSILE, true); break; case SPELL_OPEN_PORTAL_2: - DoCastAOE(SPELL_OPEN_PORTAL); - SummonSentinel = true; + DoCastAOE(SPELL_OPEN_PORTAL, true); + _scheduler.Schedule(Seconds(6), [this](TaskContext /*context*/) + { + DoCastAOE(SPELL_SUMMON_VOID_SENTINEL_SUMMONER, true); + }); + break; + default: break; } } void UpdateAI(uint32 diff) override { - if (!SummonSentinel) - { - if (InAction && instance->GetBossState(DATA_MURU) == NOT_STARTED) - Reset(); - return; - } - - if (SummonTimer <= diff) - { - DoCastAOE(SPELL_SUMMON_VOID_SENTINEL, false); - SummonTimer = 5000; - SummonSentinel = false; - } else SummonTimer -= diff; + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_muru_portalAI>(creature); + } }; class npc_dark_fiend : public CreatureScript @@ -379,11 +391,6 @@ class npc_dark_fiend : public CreatureScript public: npc_dark_fiend() : CreatureScript("npc_dark_fiend") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_dark_fiendAI(creature); - } - struct npc_dark_fiendAI : public ScriptedAI { npc_dark_fiendAI(Creature* creature) : ScriptedAI(creature) @@ -393,54 +400,56 @@ public: void Initialize() { - WaitTimer = 2000; - InAction = false; - } + me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); + me->SetReactState(REACT_PASSIVE); + DoCast(me, SPELL_DARKFIEND_SKIN, true); - uint32 WaitTimer; - bool InAction; + _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/) + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - void Reset() override - { - Initialize(); + if (Creature* _summoner = ObjectAccessor::GetCreature(*me, _summonerGUID)) + if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0)) + AttackStart(target); + }); - me->AddUnitState(UNIT_STATE_STUNNED); + _scheduler.Schedule(Seconds(3), [this](TaskContext context) + { + if (me->IsWithinDist(me->GetVictim(), 5.0f) && me->HasAura(SPELL_DARKFIEND_SKIN)) + { + DoCastAOE(SPELL_DARKFIEND_DAMAGE, false); + me->DisappearAndDie(); + } + + context.Repeat(Milliseconds(500)); + }); } - void SpellHit(Unit* /*caster*/, const SpellInfo* Spell) override + void IsSummonedBy(Unit* summoner) override { - for (uint8 i = 0; i < 3; ++i) - if (Spell->Effects[i].Effect == 38) - me->DisappearAndDie(); + _summonerGUID = summoner->GetGUID(); } - void UpdateAI(uint32 diff) override + bool CanAIAttack(Unit const* /*target*/) const override { - if (!UpdateVictim()) - return; + return me->HasAura(SPELL_DARKFIEND_SKIN); + } - if (WaitTimer <= diff) - { - if (!InAction) - { - me->ClearUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_DARKFIEND_SKIN, false); - AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)); - InAction = true; - WaitTimer = 500; - } - else - { - if (me->IsWithinDist(me->GetVictim(), 5)) - { - DoCastAOE(SPELL_DARKFIEND_AOE, false); - me->DisappearAndDie(); - } - WaitTimer = 500; - } - } else WaitTimer -= diff; + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; + ObjectGuid _summonerGUID; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_dark_fiendAI>(creature); + } }; class npc_void_sentinel : public CreatureScript @@ -448,63 +457,54 @@ class npc_void_sentinel : public CreatureScript public: npc_void_sentinel() : CreatureScript("npc_void_sentinel") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_void_sentinelAI(creature); - } - struct npc_void_sentinelAI : public ScriptedAI { npc_void_sentinelAI(Creature* creature) : ScriptedAI(creature) { - Initialize(); + _instance = me->GetInstanceScript(); } - void Initialize() + void IsSummonedBy(Unit* /*summoner*/) override { - PulseTimer = 3000; - VoidBlastTimer = 45000; //is this a correct timer? + if (Creature* muru = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_MURU))) + muru->AI()->JustSummoned(me); } - uint32 PulseTimer; - uint32 VoidBlastTimer; - - void Reset() override + void EnterCombat(Unit* /*who*/) override { - Initialize(); + DoCast(me, SPELL_SHADOW_PULSE_PERIODIC, true); - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, 71, o); + _scheduler.Schedule(Seconds(45), [this](TaskContext context) + { + DoCastVictim(SPELL_VOID_BLAST, false); + + context.Repeat(); + }); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { - for (uint8 i = 0; i < 8; ++i) - if (Creature* temp = me->SummonCreature(NPC_VOID_SPAWN, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand32() % 6), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000)) - temp->AI()->AttackStart(killer); + for (uint8 i = 0; i < MAX_VOID_SPAWNS; ++i) + DoCastAOE(SPELL_SUMMON_VOID_SPAWN, true); } void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) - return; - - if (PulseTimer <= diff) - { - DoCastAOE(SPELL_SHADOW_PULSE, true); - PulseTimer = 3000; - } else PulseTimer -= diff; - - if (VoidBlastTimer <= diff) + _scheduler.Update(diff, [this] { - DoCastVictim(SPELL_VOID_BLAST, false); - VoidBlastTimer = 45000; - } else VoidBlastTimer -= diff; - - DoMeleeAttackIfReady(); + DoMeleeAttackIfReady(); + }); } + + private: + TaskScheduler _scheduler; + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_void_sentinelAI>(creature); + } }; class npc_blackhole : public CreatureScript @@ -512,84 +512,220 @@ class npc_blackhole : public CreatureScript public: npc_blackhole() : CreatureScript("npc_blackhole") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_blackholeAI>(creature); - } - struct npc_blackholeAI : public ScriptedAI { npc_blackholeAI(Creature* creature) : ScriptedAI(creature) { - Initialize(); - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } - void Initialize() - { - DespawnTimer = 15000; - SpellTimer = 5000; - Phase = 0; - NeedForAHack = 0; - } - - InstanceScript* instance; - - uint32 DespawnTimer; - uint32 SpellTimer; - uint8 Phase; - uint8 NeedForAHack; - void Reset() override { - Initialize(); + me->SetReactState(REACT_PASSIVE); + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL); - me->AddUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_SPAWN, true); - } + _scheduler.Schedule(Seconds(15), [this](TaskContext /*context*/) + { + me->DisappearAndDie(); + }); - void UpdateAI(uint32 diff) override - { - if (SpellTimer <= diff) + _scheduler.Schedule(Seconds(1), [this](TaskContext context) { - Unit* Victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID)); - switch (NeedForAHack) + switch (context.GetRepeatCounter()) { case 0: - me->ClearUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_GROW, false); - if (Victim) - AttackStart(Victim); - SpellTimer = 700; - NeedForAHack = 2; + me->SetReactState(REACT_AGGRESSIVE); + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL_2); + if (Unit* victim = ObjectAccessor::GetUnit(*me, _instance->GetGuidData(DATA_PLAYER_GUID))) + AttackStart(victim); + context.Repeat(Milliseconds(1200)); break; case 1: - me->AddAura(SPELL_BLACKHOLE_GROW, me); - NeedForAHack = 2; - SpellTimer = 600; + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL); + context.Repeat(Seconds(2)); break; case 2: - SpellTimer = 400; - NeedForAHack = 3; - me->RemoveAura(SPELL_BLACKHOLE_GROW); + DoCast(SPELL_BLACKHOLE_PASSIVE); + DoCast(SPELL_BLACK_HOLE_VISUAL_2); + break; + default: break; - case 3: - SpellTimer = urand(400, 900); - NeedForAHack = 1; - if (Unit* Temp = me->GetVictim()) - { - if (Temp->GetPositionZ() > 73 && Victim) - AttackStart(Victim); - } else - return; } - } else SpellTimer -= diff; + }); + } - if (DespawnTimer <= diff) - me->DisappearAndDie(); - else DespawnTimer -= diff; + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_blackholeAI>(creature); + } +}; + +class spell_summon_blood_elves_script : SpellScriptLoader +{ + public: + spell_summon_blood_elves_script() : SpellScriptLoader("spell_summon_blood_elves_script") { } + + class spell_summon_blood_elves_script_SpellScript : public SpellScript + { + PrepareSpellScript(spell_summon_blood_elves_script_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + for (uint8 i = 0; i < MAX_SUMMON_BLOOD_ELVES; ++i) + if (!sSpellMgr->GetSpellInfo(SummonBloodElvesSpells[i])) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + for (uint8 i = 0; i < MAX_SUMMON_BLOOD_ELVES; ++i) + GetCaster()->CastSpell((Unit*)nullptr, SummonBloodElvesSpells[urand(0,3)], true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_summon_blood_elves_script_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_summon_blood_elves_script_SpellScript(); + } +}; + +class spell_muru_darkness : SpellScriptLoader +{ + public: + spell_muru_darkness() : SpellScriptLoader("spell_muru_darkness") { } + + class spell_muru_darkness_SpellScript : public SpellScript + { + PrepareSpellScript(spell_muru_darkness_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + for (uint8 i = 0; i < MAX_SUMMON_DARK_FIEND; ++i) + if (!sSpellMgr->GetSpellInfo(SummonDarkFiendSpells[i])) + return false; + return true; + } + + void HandleAfterCast() + { + for (uint8 i = 0; i < MAX_SUMMON_DARK_FIEND; ++i) + GetCaster()->CastSpell((Unit*)nullptr, SummonDarkFiendSpells[i], true); + } + + void Register() override + { + AfterCast += SpellCastFn(spell_muru_darkness_SpellScript::HandleAfterCast); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_muru_darkness_SpellScript(); + } +}; + +class spell_dark_fiend_skin : public SpellScriptLoader +{ + public: + spell_dark_fiend_skin() : SpellScriptLoader("spell_dark_fiend_skin") { } + + class spell_dark_fiend_skin_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dark_fiend_skin_AuraScript); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + return; + + if (Creature* target = GetTarget()->ToCreature()) + { + target->SetReactState(REACT_PASSIVE); + target->AttackStop(); + target->StopMoving(); + target->CastSpell(target, SPELL_DARKFIEND_VISUAL, true); + target->DespawnOrUnsummon(3000); + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_dark_fiend_skin_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dark_fiend_skin_AuraScript(); + } +}; + +class spell_transform_visual_missile_periodic : public SpellScriptLoader +{ + public: + spell_transform_visual_missile_periodic() : SpellScriptLoader("spell_transform_visual_missile_periodic") { } + + class spell_transform_visual_missile_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_transform_visual_missile_periodic_AuraScript); + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + GetTarget()->CastSpell((Unit*)nullptr, RAND(TRANSFORM_VISUAL_MISSILE_1, TRANSFORM_VISUAL_MISSILE_2), true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_transform_visual_missile_periodic_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_transform_visual_missile_periodic_AuraScript(); + } +}; + +class spell_summon_blood_elves_periodic : public SpellScriptLoader +{ + public: + spell_summon_blood_elves_periodic() : SpellScriptLoader("spell_summon_blood_elves_periodic") { } + + class spell_summon_blood_elves_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_summon_blood_elves_periodic_AuraScript); + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + GetTarget()->CastSpell((Unit*)nullptr, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_blood_elves_periodic_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_summon_blood_elves_periodic_AuraScript(); + } }; void AddSC_boss_muru() @@ -600,4 +736,9 @@ void AddSC_boss_muru() new npc_dark_fiend(); new npc_void_sentinel(); new npc_blackhole(); + new spell_summon_blood_elves_script(); + new spell_muru_darkness(); + new spell_dark_fiend_skin(); + new spell_transform_visual_missile_periodic(); + new spell_summon_blood_elves_periodic(); } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h index c6b4ae753a5..7ea0fc4bc7d 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h @@ -97,7 +97,8 @@ enum CreatureIds NPC_FURY_MAGE = 25799, NPC_VOID_SENTINEL = 25772, NPC_VOID_SPAWN = 25824, - NPC_BLACK_HOLE = 25855 + NPC_BLACK_HOLE = 25855, + NPC_MURU_PORTAL_TARGET = 25770 }; enum GameObjectIds diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp index a5fed30a6c6..68391c65655 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp @@ -98,7 +98,7 @@ class boss_archaedas : public CreatureScript instance->SetData(0, 5); // respawn any dead minions me->setFaction(35); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->AddAura(SPELL_FREEZE_ANIM, me); } @@ -111,7 +111,7 @@ class boss_archaedas : public CreatureScript DoCast(minion, SPELL_AWAKEN_VAULT_WALKER, flag); minion->CastSpell(minion, SPELL_ARCHAEDAS_AWAKEN, true); minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); minion->setFaction(14); minion->RemoveAura(SPELL_MINION_FREEZE_ANIM); } @@ -121,7 +121,7 @@ class boss_archaedas : public CreatureScript { me->setFaction(14); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); } void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override @@ -261,7 +261,7 @@ class npc_archaedas_minions : public CreatureScript me->setFaction(35); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->RemoveAllAuras(); me->AddAura(SPELL_MINION_FREEZE_ANIM, me); } @@ -271,7 +271,7 @@ class npc_archaedas_minions : public CreatureScript me->setFaction (14); me->RemoveAllAuras(); me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); bAmIAwake = true; } @@ -350,7 +350,7 @@ class npc_stonekeepers : public CreatureScript { me->setFaction(35); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->RemoveAllAuras(); me->AddAura(SPELL_MINION_FREEZE_ANIM, me); } @@ -359,7 +359,7 @@ class npc_stonekeepers : public CreatureScript { me->setFaction(14); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); } void UpdateAI(uint32 /*diff*/) override diff --git a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp index 8c78fb7ff1b..28a3a4eb4e0 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp @@ -147,7 +147,7 @@ class instance_uldaman : public InstanceMapScript creature->setFaction(35); creature->RemoveAllAuras(); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); creature->AddAura(SPELL_MINION_FREEZE_ANIM, creature); } @@ -178,7 +178,7 @@ class instance_uldaman : public InstanceMapScript Creature* target = instance->GetCreature(*i); if (!target || !target->IsAlive()) continue; - target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); target->setFaction(14); target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); target->RemoveAura(SPELL_MINION_FREEZE_ANIM); @@ -202,7 +202,7 @@ class instance_uldaman : public InstanceMapScript Creature* target = instance->GetCreature(*i); if (!target || !target->IsAlive() || target->getFaction() == 14) continue; - target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); target->setFaction(14); target->RemoveAura(SPELL_MINION_FREEZE_ANIM); @@ -268,7 +268,7 @@ class instance_uldaman : public InstanceMapScript return; ironaya->setFaction(415); - ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); ironaya->GetMotionMaster()->Clear(); diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp index 791f68bae31..72e76ba52bf 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp @@ -425,7 +425,7 @@ class npc_akilzon_eagle : public CreatureScript if (Unit* target = ObjectAccessor::GetUnit(*me, TargetGUID)) DoCast(target, SPELL_EAGLE_SWOOP, true); TargetGUID.Clear(); - me->SetSpeed(MOVE_RUN, 1.2f); + me->SetSpeedRate(MOVE_RUN, 1.2f); EagleSwoop_Timer = urand(5000, 10000); } } @@ -454,7 +454,7 @@ class npc_akilzon_eagle : public CreatureScript { target->GetContactPoint(me, x, y, z); z += 2; - me->SetSpeed(MOVE_RUN, 5.0f); + me->SetSpeedRate(MOVE_RUN, 5.0f); TargetGUID = target->GetGUID(); } me->GetMotionMaster()->MovePoint(0, x, y, z); diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp index cc55f758a22..5ec57fc44b6 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp @@ -29,109 +29,104 @@ EndScriptData */ #include "SpellAuraEffects.h" #include "zulaman.h" -#define YELL_AGGRO "Da shadow gonna fall on you... " -#define SOUND_YELL_AGGRO 12041 -#define YELL_SPIRIT_BOLTS "Your soul gonna bleed!" -#define SOUND_YELL_SPIRIT_BOLTS 12047 -#define YELL_DRAIN_POWER "Darkness comin\' for you" -#define SOUND_YELL_DRAIN_POWER 12046 -#define YELL_KILL_ONE "Dis a nightmare ya don\' wake up from!" -#define SOUND_YELL_KILL_ONE 12043 -#define YELL_KILL_TWO "Azzaga choogo zinn!" -#define SOUND_YELL_KILL_TWO 12044 -#define YELL_DEATH "Dis not... da end of me..." -#define SOUND_YELL_DEATH 12051 - +enum Yells +{ + YELL_AGGRO = 0, + YELL_KILL_ONE = 1, + YELL_KILL_TWO = 2, + YELL_DRAIN_POWER = 3, + YELL_SPIRIT_BOLTS = 4, + YELL_DEATH = 5 +}; enum Creatures { - NPC_TEMP_TRIGGER = 23920 + NPC_TEMP_TRIGGER = 23920 }; enum Spells { - SPELL_SPIRIT_BOLTS = 43383, - SPELL_DRAIN_POWER = 44131, - SPELL_SIPHON_SOUL = 43501, + SPELL_SPIRIT_BOLTS = 43383, + SPELL_DRAIN_POWER = 44131, + SPELL_SIPHON_SOUL = 43501, // Druid - SPELL_DR_THORNS = 43420, - SPELL_DR_LIFEBLOOM = 43421, - SPELL_DR_MOONFIRE = 43545, + SPELL_DR_THORNS = 43420, + SPELL_DR_LIFEBLOOM = 43421, + SPELL_DR_MOONFIRE = 43545, // Hunter - SPELL_HU_EXPLOSIVE_TRAP = 43444, - SPELL_HU_FREEZING_TRAP = 43447, - SPELL_HU_SNAKE_TRAP = 43449, + SPELL_HU_EXPLOSIVE_TRAP = 43444, + SPELL_HU_FREEZING_TRAP = 43447, + SPELL_HU_SNAKE_TRAP = 43449, // Mage - SPELL_MG_FIREBALL = 41383, - SPELL_MG_FROST_NOVA = 43426, - SPELL_MG_ICE_LANCE = 43427, - SPELL_MG_FROSTBOLT = 43428, + SPELL_MG_FIREBALL = 41383, + SPELL_MG_FROST_NOVA = 43426, + SPELL_MG_ICE_LANCE = 43427, + SPELL_MG_FROSTBOLT = 43428, // Paladin - SPELL_PA_CONSECRATION = 43429, - SPELL_PA_AVENGING_WRATH = 43430, - SPELL_PA_HOLY_LIGHT = 43451, + SPELL_PA_CONSECRATION = 43429, + SPELL_PA_AVENGING_WRATH = 43430, + SPELL_PA_HOLY_LIGHT = 43451, // Priest - SPELL_PR_HEAL = 41372, - SPELL_PR_MIND_BLAST = 41374, - SPELL_PR_SW_DEATH = 41375, - SPELL_PR_PSYCHIC_SCREAM = 43432, - SPELL_PR_MIND_CONTROL = 43550, - SPELL_PR_PAIN_SUPP = 44416, + SPELL_PR_HEAL = 41372, + SPELL_PR_MIND_BLAST = 41374, + SPELL_PR_SW_DEATH = 41375, + SPELL_PR_PSYCHIC_SCREAM = 43432, + SPELL_PR_MIND_CONTROL = 43550, + SPELL_PR_PAIN_SUPP = 44416, // Rogue - SPELL_RO_BLIND = 43433, - SPELL_RO_SLICE_DICE = 43457, - SPELL_RO_WOUND_POISON = 43461, + SPELL_RO_BLIND = 43433, + SPELL_RO_SLICE_DICE = 43457, + SPELL_RO_WOUND_POISON = 43461, // Shaman - SPELL_SH_CHAIN_LIGHT = 43435, - SPELL_SH_FIRE_NOVA = 43436, - SPELL_SH_HEALING_WAVE = 43548, + SPELL_SH_CHAIN_LIGHT = 43435, + SPELL_SH_FIRE_NOVA = 43436, + SPELL_SH_HEALING_WAVE = 43548, // Warlock - SPELL_WL_CURSE_OF_DOOM = 43439, - SPELL_WL_RAIN_OF_FIRE = 43440, - SPELL_WL_UNSTABLE_AFFL = 43522, - SPELL_WL_UNSTABLE_AFFL_DISPEL = 43523, + SPELL_WL_CURSE_OF_DOOM = 43439, + SPELL_WL_RAIN_OF_FIRE = 43440, + SPELL_WL_UNSTABLE_AFFL = 43522, + SPELL_WL_UNSTABLE_AFFL_DISPEL = 43523, // Warrior - SPELL_WR_MORTAL_STRIKE = 43441, - SPELL_WR_WHIRLWIND = 43442, - SPELL_WR_SPELL_REFLECT = 43443, + SPELL_WR_MORTAL_STRIKE = 43441, + SPELL_WR_WHIRLWIND = 43442, + SPELL_WR_SPELL_REFLECT = 43443, // Thurg - SPELL_BLOODLUST = 43578, - SPELL_CLEAVE = 15496, + SPELL_BLOODLUST = 43578, + SPELL_CLEAVE = 15496, // Gazakroth - SPELL_FIREBOLT = 43584, + SPELL_FIREBOLT = 43584, // Alyson Antille - SPELL_FLASH_HEAL = 43575, - SPELL_DISPEL_MAGIC = 43577, + SPELL_FLASH_HEAL = 43575, + SPELL_DISPEL_MAGIC = 43577, // Lord Raadan - SPELL_FLAME_BREATH = 43582, - SPELL_THUNDERCLAP = 43583, + SPELL_FLAME_BREATH = 43582, + SPELL_THUNDERCLAP = 43583, // Darkheart - SPELL_PSYCHIC_WAIL = 43590, + SPELL_PSYCHIC_WAIL = 43590, // Slither - SPELL_VENOM_SPIT = 43579, + SPELL_VENOM_SPIT = 43579, // Fenstalker - SPELL_VOLATILE_INFECTION = 43586, + SPELL_VOLATILE_INFECTION = 43586, // Koragg - SPELL_COLD_STARE = 43593, - SPELL_MIGHTY_BLOW = 43592 - + SPELL_COLD_STARE = 43593, + SPELL_MIGHTY_BLOW = 43592 }; #define ORIENT 1.5696f @@ -306,8 +301,7 @@ class boss_hexlord_malacrass : public CreatureScript instance->SetData(DATA_HEXLORDEVENT, IN_PROGRESS); DoZoneInCombat(); - me->Yell(YELL_AGGRO, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_AGGRO); + Talk(YELL_AGGRO); for (uint8 i = 0; i < 4; ++i) { @@ -327,12 +321,10 @@ class boss_hexlord_malacrass : public CreatureScript switch (urand(0, 1)) { case 0: - me->Yell(YELL_KILL_ONE, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); + Talk(YELL_KILL_ONE); break; case 1: - me->Yell(YELL_KILL_TWO, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); + Talk(YELL_KILL_TWO); break; } } @@ -341,8 +333,7 @@ class boss_hexlord_malacrass : public CreatureScript { instance->SetData(DATA_HEXLORDEVENT, DONE); - me->Yell(YELL_DEATH, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_DEATH); + Talk(YELL_DEATH); for (uint8 i = 0; i < 4; ++i) { @@ -415,8 +406,7 @@ class boss_hexlord_malacrass : public CreatureScript if (DrainPower_Timer <= diff) { DoCast(me, SPELL_DRAIN_POWER, true); - me->Yell(YELL_DRAIN_POWER, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_DRAIN_POWER); + Talk(YELL_DRAIN_POWER); DrainPower_Timer = urand(40000, 55000); // must cast in 60 sec, or buff/debuff will disappear } else DrainPower_Timer -= diff; @@ -427,8 +417,7 @@ class boss_hexlord_malacrass : public CreatureScript else { DoCast(me, SPELL_SPIRIT_BOLTS, false); - me->Yell(YELL_SPIRIT_BOLTS, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_SPIRIT_BOLTS); + Talk(YELL_SPIRIT_BOLTS); SpiritBolts_Timer = 40000; SiphonSoul_Timer = 10000; // ready to drain PlayerAbility_Timer = 99999; diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index 37505a8b74d..188f9d0cc03 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -30,21 +30,41 @@ EndScriptData */ #include "GridNotifiersImpl.h" #include "CellImpl.h" -enum Spells +enum Yells { - SPELL_BERSERK = 45078, + YELL_NALORAKK_WAVE1 = 0, + YELL_NALORAKK_WAVE2 = 1, + YELL_NALORAKK_WAVE3 = 2, + YELL_NALORAKK_WAVE4 = 3, + YELL_AGGRO = 4, + YELL_SURGE = 5, + YELL_SHIFTEDTOBEAR = 6, + YELL_SHIFTEDTOTROLL = 7, + YELL_BERSERK = 8, + YELL_KILL_ONE = 9, + YELL_KILL_TWO = 10, + YELL_DEATH = 11 + +// Not yet implemented +// YELL_NALORAKK_EVENT1 = 12, +// YELL_NALORAKK_EVENT2 = 13 +}; +enum Spells +{ // Troll form - SPELL_BRUTALSWIPE = 42384, - SPELL_MANGLE = 42389, - SPELL_MANGLEEFFECT = 44955, - SPELL_SURGE = 42402, - SPELL_BEARFORM = 42377, + SPELL_BRUTALSWIPE = 42384, + SPELL_MANGLE = 42389, + SPELL_MANGLEEFFECT = 44955, + SPELL_SURGE = 42402, + SPELL_BEARFORM = 42377, // Bear form - SPELL_LACERATINGSLASH = 42395, - SPELL_RENDFLESH = 42397, - SPELL_DEAFENINGROAR = 42398 + SPELL_LACERATINGSLASH = 42395, + SPELL_RENDFLESH = 42397, + SPELL_DEAFENINGROAR = 42398, + + SPELL_BERSERK = 45078 }; // Trash Waves @@ -57,45 +77,9 @@ float NalorakkWay[8][3] = {-79.929f, 1395.958f, 27.31f}, {-80.072f, 1374.555f, 40.87f}, // waypoint 3 {-80.072f, 1314.398f, 40.87f}, - {-80.072f, 1295.775f, 48.60f} // waypoint 4 + {-80.072f, 1295.775f, 48.60f} // waypoint 4 }; -#define YELL_NALORAKK_WAVE1 "Get da move on, guards! It be killin' time!" -#define SOUND_NALORAKK_WAVE1 12066 -#define YELL_NALORAKK_WAVE2 "Guards, go already! Who you more afraid of, dem... or me?" -#define SOUND_NALORAKK_WAVE2 12067 -#define YELL_NALORAKK_WAVE3 "Ride now! Ride out dere and bring me back some heads!" -#define SOUND_NALORAKK_WAVE3 12068 -#define YELL_NALORAKK_WAVE4 "I be losin' me patience! Go on: make dem wish dey was never born!" -#define SOUND_NALORAKK_WAVE4 12069 - -//Unimplemented SoundIDs -/* -#define SOUND_NALORAKK_EVENT1 12078 -#define SOUND_NALORAKK_EVENT2 12079 -*/ - -//General defines -#define YELL_AGGRO "You be dead soon enough!" -#define SOUND_YELL_AGGRO 12070 -#define YELL_KILL_ONE "Mua-ha-ha! Now whatchoo got to say?" -#define SOUND_YELL_KILL_ONE 12075 -#define YELL_KILL_TWO "Da Amani gonna rule again!" -#define SOUND_YELL_KILL_TWO 12076 -#define YELL_DEATH "I... be waitin' on da udda side...." -#define SOUND_YELL_DEATH 12077 -#define YELL_BERSERK "You had your chance, now it be too late!" //Never seen this being used, so just guessing from what I hear. -#define SOUND_YELL_BERSERK 12074 -#define YELL_SURGE "I bring da pain!" -#define SOUND_YELL_SURGE 12071 - -#define YELL_SHIFTEDTOTROLL "Make way for Nalorakk!" -#define SOUND_YELL_TOTROLL 12073 - - -#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!" -#define SOUND_YELL_TOBEAR 12072 - class boss_nalorakk : public CreatureScript { public: @@ -158,7 +142,7 @@ class boss_nalorakk : public CreatureScript me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); inMove = false; waitTimer = 0; - me->SetSpeed(MOVE_RUN, 2); + me->SetSpeedRate(MOVE_RUN, 2); me->SetWalk(false); }else { @@ -227,8 +211,7 @@ class boss_nalorakk : public CreatureScript case 0: if (me->IsWithinDistInMap(who, 50)) { - me->Yell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1); + Talk(YELL_NALORAKK_WAVE1); (*me).GetMotionMaster()->MovePoint(1, NalorakkWay[1][0], NalorakkWay[1][1], NalorakkWay[1][2]); MovePhase ++; @@ -240,8 +223,7 @@ class boss_nalorakk : public CreatureScript case 2: if (me->IsWithinDistInMap(who, 40)) { - me->Yell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2); + Talk(YELL_NALORAKK_WAVE2); (*me).GetMotionMaster()->MovePoint(3, NalorakkWay[3][0], NalorakkWay[3][1], NalorakkWay[3][2]); MovePhase ++; @@ -253,8 +235,7 @@ class boss_nalorakk : public CreatureScript case 5: if (me->IsWithinDistInMap(who, 40)) { - me->Yell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3); + Talk(YELL_NALORAKK_WAVE3); (*me).GetMotionMaster()->MovePoint(6, NalorakkWay[6][0], NalorakkWay[6][1], NalorakkWay[6][2]); MovePhase ++; @@ -268,8 +249,7 @@ class boss_nalorakk : public CreatureScript { SendAttacker(who); - me->Yell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4); + Talk(YELL_NALORAKK_WAVE4); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -287,8 +267,7 @@ class boss_nalorakk : public CreatureScript { instance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS); - me->Yell(YELL_AGGRO, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_AGGRO); + Talk(YELL_AGGRO); DoZoneInCombat(); } @@ -296,8 +275,7 @@ class boss_nalorakk : public CreatureScript { instance->SetData(DATA_NALORAKKEVENT, DONE); - me->Yell(YELL_DEATH, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_DEATH); + Talk(YELL_DEATH); } void KilledUnit(Unit* /*victim*/) override @@ -305,12 +283,10 @@ class boss_nalorakk : public CreatureScript switch (urand(0, 1)) { case 0: - me->Yell(YELL_KILL_ONE, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE); + Talk(YELL_KILL_ONE); break; case 1: - me->Yell(YELL_KILL_TWO, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO); + Talk(YELL_KILL_TWO); break; } } @@ -373,8 +349,7 @@ class boss_nalorakk : public CreatureScript if (Berserk_Timer <= diff) { DoCast(me, SPELL_BERSERK, true); - me->Yell(YELL_BERSERK, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_BERSERK); + Talk(YELL_BERSERK); Berserk_Timer = 600000; } else Berserk_Timer -= diff; @@ -383,8 +358,7 @@ class boss_nalorakk : public CreatureScript if (inBearForm) { // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); - me->Yell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_TOTROLL); + Talk(YELL_SHIFTEDTOTROLL); me->RemoveAurasDueToSpell(SPELL_BEARFORM); Surge_Timer = urand(15000, 20000); BrutalSwipe_Timer = urand(7000, 12000); @@ -395,8 +369,7 @@ class boss_nalorakk : public CreatureScript else { // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0); - me->Yell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_TOBEAR); + Talk(YELL_SHIFTEDTOBEAR); DoCast(me, SPELL_BEARFORM, true); LaceratingSlash_Timer = 2000; // dur 18s RendFlesh_Timer = 3000; // dur 5s @@ -426,8 +399,7 @@ class boss_nalorakk : public CreatureScript if (Surge_Timer <= diff) { - me->Yell(YELL_SURGE, LANG_UNIVERSAL); - DoPlaySoundToSet(me, SOUND_YELL_SURGE); + Talk(YELL_SURGE); Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true); if (target) DoCast(target, SPELL_SURGE); diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp index 96c0798ae05..a1c2369cf66 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp @@ -347,7 +347,7 @@ class boss_zuljin : public CreatureScript Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true); Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true); Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Vortex->SetSpeed(MOVE_RUN, 1.0f); + Vortex->SetSpeedRate(MOVE_RUN, 1.0f); Vortex->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0)); DoZoneInCombat(Vortex); } @@ -438,7 +438,7 @@ class boss_zuljin : public CreatureScript { if (me->GetVictim()) TankGUID = me->EnsureVictim()->GetGUID(); - me->SetSpeed(MOVE_RUN, 5.0f); + me->SetSpeedRate(MOVE_RUN, 5.0f); AttackStart(target); // change victim Claw_Rage_Timer = 0; Claw_Loop_Timer = 500; @@ -462,7 +462,7 @@ class boss_zuljin : public CreatureScript if (Claw_Counter == 12) { Claw_Rage_Timer = urand(15000, 20000); - me->SetSpeed(MOVE_RUN, 1.2f); + me->SetSpeedRate(MOVE_RUN, 1.2f); AttackStart(ObjectAccessor::GetUnit(*me, TankGUID)); TankGUID.Clear(); return; @@ -487,7 +487,7 @@ class boss_zuljin : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { TankGUID = me->EnsureVictim()->GetGUID(); - me->SetSpeed(MOVE_RUN, 5.0f); + me->SetSpeedRate(MOVE_RUN, 5.0f); AttackStart(target); // change victim Lynx_Rush_Timer = 0; Claw_Counter = 0; @@ -510,7 +510,7 @@ class boss_zuljin : public CreatureScript if (Claw_Counter == 9) { Lynx_Rush_Timer = urand(15000, 20000); - me->SetSpeed(MOVE_RUN, 1.2f); + me->SetSpeedRate(MOVE_RUN, 1.2f); AttackStart(ObjectAccessor::GetUnit(*me, TankGUID)); TankGUID.Clear(); } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp index 972acdc3f9f..9b668169dca 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp @@ -162,7 +162,7 @@ class npc_zulaman_hostage : public CreatureScript { if (HostageEntry[i] == entry) { - creature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0); + creature->SummonGameObject(ChestEntry[i], Position(x - 2, y, z, 0.f), G3D::Quat(), 0); break; } } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index 8c179af2adf..3697b0876c8 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -148,6 +148,11 @@ class boss_mandokir : public CreatureScript instance->SaveToDB(); } + void JustReachedHome() override + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + } + void EnterCombat(Unit* /*who*/) override { _EnterCombat(); @@ -194,9 +199,9 @@ class boss_mandokir : public CreatureScript me->SetWalk(false); if (id == POINT_MANDOKIR_END) { - me->SetHomePosition(PosMandokir[0]); + me->SetHomePosition(PosMandokir[1]); + me->GetMotionMaster()->MoveTargetedHome(); instance->SetBossState(DATA_MANDOKIR, NOT_STARTED); - me->DespawnOrUnsummon(6000); // No idea how to respawn on wipe. } } } diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp new file mode 100644 index 00000000000..adcb4f9fc9a --- /dev/null +++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +void AddSC_alterac_valley(); //Alterac Valley +void AddSC_boss_balinda(); +void AddSC_boss_drekthar(); +void AddSC_boss_galvangar(); +void AddSC_boss_vanndar(); +void AddSC_blackrock_depths(); //Blackrock Depths +void AddSC_boss_ambassador_flamelash(); +void AddSC_boss_draganthaurissan(); +void AddSC_boss_general_angerforge(); +void AddSC_boss_high_interrogator_gerstahn(); +void AddSC_boss_magmus(); +void AddSC_boss_moira_bronzebeard(); +void AddSC_boss_tomb_of_seven(); +void AddSC_instance_blackrock_depths(); +void AddSC_boss_drakkisath(); //Blackrock Spire +void AddSC_boss_halycon(); +void AddSC_boss_highlordomokk(); +void AddSC_boss_mothersmolderweb(); +void AddSC_boss_overlordwyrmthalak(); +void AddSC_boss_shadowvosh(); +void AddSC_boss_thebeast(); +void AddSC_boss_warmastervoone(); +void AddSC_boss_quatermasterzigris(); +void AddSC_boss_pyroguard_emberseer(); +void AddSC_boss_gyth(); +void AddSC_boss_rend_blackhand(); +void AddSC_boss_gizrul_the_slavener(); +void AddSC_boss_urok_doomhowl(); +void AddSC_boss_lord_valthalak(); +void AddSC_instance_blackrock_spire(); +void AddSC_boss_razorgore(); //Blackwing lair +void AddSC_boss_vaelastrasz(); +void AddSC_boss_broodlord(); +void AddSC_boss_firemaw(); +void AddSC_boss_ebonroc(); +void AddSC_boss_flamegor(); +void AddSC_boss_chromaggus(); +void AddSC_boss_nefarian(); +void AddSC_instance_blackwing_lair(); +void AddSC_deadmines(); //Deadmines +void AddSC_instance_deadmines(); +void AddSC_boss_mr_smite(); +void AddSC_gnomeregan(); //Gnomeregan +void AddSC_instance_gnomeregan(); +void AddSC_boss_attumen(); //Karazhan +void AddSC_boss_curator(); +void AddSC_boss_maiden_of_virtue(); +void AddSC_boss_shade_of_aran(); +void AddSC_boss_malchezaar(); +void AddSC_boss_terestian_illhoof(); +void AddSC_boss_moroes(); +void AddSC_bosses_opera(); +void AddSC_boss_netherspite(); +void AddSC_instance_karazhan(); +void AddSC_karazhan(); +void AddSC_boss_nightbane(); +void AddSC_boss_felblood_kaelthas(); // Magister's Terrace +void AddSC_boss_selin_fireheart(); +void AddSC_boss_vexallus(); +void AddSC_boss_priestess_delrissa(); +void AddSC_instance_magisters_terrace(); +void AddSC_magisters_terrace(); +void AddSC_boss_lucifron(); //Molten core +void AddSC_boss_magmadar(); +void AddSC_boss_gehennas(); +void AddSC_boss_garr(); +void AddSC_boss_baron_geddon(); +void AddSC_boss_shazzrah(); +void AddSC_boss_golemagg(); +void AddSC_boss_sulfuron(); +void AddSC_boss_majordomo(); +void AddSC_boss_ragnaros(); +void AddSC_instance_molten_core(); +void AddSC_the_scarlet_enclave(); //Scarlet Enclave +void AddSC_the_scarlet_enclave_c1(); +void AddSC_the_scarlet_enclave_c2(); +void AddSC_the_scarlet_enclave_c5(); +void AddSC_boss_arcanist_doan(); //Scarlet Monastery +void AddSC_boss_azshir_the_sleepless(); +void AddSC_boss_bloodmage_thalnos(); +void AddSC_boss_headless_horseman(); +void AddSC_boss_herod(); +void AddSC_boss_high_inquisitor_fairbanks(); +void AddSC_boss_houndmaster_loksey(); +void AddSC_boss_interrogator_vishas(); +void AddSC_boss_scorn(); +void AddSC_instance_scarlet_monastery(); +void AddSC_boss_mograine_and_whitemane(); +void AddSC_boss_darkmaster_gandling(); //Scholomance +void AddSC_boss_death_knight_darkreaver(); +void AddSC_boss_theolenkrastinov(); +void AddSC_boss_illuciabarov(); +void AddSC_boss_instructormalicia(); +void AddSC_boss_jandicebarov(); +void AddSC_boss_kormok(); +void AddSC_boss_lordalexeibarov(); +void AddSC_boss_lorekeeperpolkelt(); +void AddSC_boss_rasfrost(); +void AddSC_boss_theravenian(); +void AddSC_boss_vectus(); +void AddSC_boss_kirtonos_the_herald(); +void AddSC_instance_scholomance(); +void AddSC_shadowfang_keep(); //Shadowfang keep +void AddSC_instance_shadowfang_keep(); +void AddSC_boss_magistrate_barthilas(); //Stratholme +void AddSC_boss_maleki_the_pallid(); +void AddSC_boss_nerubenkan(); +void AddSC_boss_cannon_master_willey(); +void AddSC_boss_baroness_anastari(); +void AddSC_boss_ramstein_the_gorger(); +void AddSC_boss_timmy_the_cruel(); +void AddSC_boss_postmaster_malown(); +void AddSC_boss_baron_rivendare(); +void AddSC_boss_dathrohan_balnazzar(); +void AddSC_boss_order_of_silver_hand(); +void AddSC_instance_stratholme(); +void AddSC_stratholme(); +void AddSC_sunken_temple(); // Sunken Temple +void AddSC_instance_sunken_temple(); +void AddSC_instance_sunwell_plateau(); //Sunwell Plateau +void AddSC_boss_kalecgos(); +void AddSC_boss_brutallus(); +void AddSC_boss_felmyst(); +void AddSC_boss_eredar_twins(); +void AddSC_boss_muru(); +void AddSC_boss_kiljaeden(); +void AddSC_sunwell_plateau(); +void AddSC_boss_archaedas(); //Uldaman +void AddSC_boss_ironaya(); +void AddSC_uldaman(); +void AddSC_instance_uldaman(); +void AddSC_instance_the_stockade(); //The Stockade +void AddSC_boss_akilzon(); //Zul'Aman +void AddSC_boss_halazzi(); +void AddSC_boss_hex_lord_malacrass(); +void AddSC_boss_janalai(); +void AddSC_boss_nalorakk(); +void AddSC_boss_zuljin(); +void AddSC_instance_zulaman(); +void AddSC_zulaman(); +void AddSC_boss_jeklik(); //Zul'Gurub +void AddSC_boss_venoxis(); +void AddSC_boss_marli(); +void AddSC_boss_mandokir(); +void AddSC_boss_gahzranka(); +void AddSC_boss_thekal(); +void AddSC_boss_arlokk(); +void AddSC_boss_jindo(); +void AddSC_boss_hakkar(); +void AddSC_boss_grilek(); +void AddSC_boss_hazzarah(); +void AddSC_boss_renataki(); +void AddSC_boss_wushoolay(); +void AddSC_instance_zulgurub(); +//void AddSC_alterac_mountains(); +void AddSC_arathi_highlands(); +void AddSC_blasted_lands(); +void AddSC_burning_steppes(); +void AddSC_duskwood(); +void AddSC_eastern_plaguelands(); +void AddSC_ghostlands(); +void AddSC_hinterlands(); +void AddSC_isle_of_queldanas(); +void AddSC_redridge_mountains(); +void AddSC_silverpine_forest(); +void AddSC_stormwind_city(); +void AddSC_stranglethorn_vale(); +void AddSC_swamp_of_sorrows(); +void AddSC_tirisfal_glades(); +void AddSC_undercity(); +void AddSC_western_plaguelands(); +void AddSC_wetlands(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddEasternKingdomsScripts() +{ + AddSC_alterac_valley(); //Alterac Valley + AddSC_boss_balinda(); + AddSC_boss_drekthar(); + AddSC_boss_galvangar(); + AddSC_boss_vanndar(); + AddSC_blackrock_depths(); //Blackrock Depths + AddSC_boss_ambassador_flamelash(); + AddSC_boss_draganthaurissan(); + AddSC_boss_general_angerforge(); + AddSC_boss_high_interrogator_gerstahn(); + AddSC_boss_magmus(); + AddSC_boss_moira_bronzebeard(); + AddSC_boss_tomb_of_seven(); + AddSC_instance_blackrock_depths(); + AddSC_boss_drakkisath(); //Blackrock Spire + AddSC_boss_halycon(); + AddSC_boss_highlordomokk(); + AddSC_boss_mothersmolderweb(); + AddSC_boss_overlordwyrmthalak(); + AddSC_boss_shadowvosh(); + AddSC_boss_thebeast(); + AddSC_boss_warmastervoone(); + AddSC_boss_quatermasterzigris(); + AddSC_boss_pyroguard_emberseer(); + AddSC_boss_gyth(); + AddSC_boss_rend_blackhand(); + AddSC_boss_gizrul_the_slavener(); + AddSC_boss_urok_doomhowl(); + AddSC_boss_lord_valthalak(); + AddSC_instance_blackrock_spire(); + AddSC_boss_razorgore(); //Blackwing lair + AddSC_boss_vaelastrasz(); + AddSC_boss_broodlord(); + AddSC_boss_firemaw(); + AddSC_boss_ebonroc(); + AddSC_boss_flamegor(); + AddSC_boss_chromaggus(); + AddSC_boss_nefarian(); + AddSC_instance_blackwing_lair(); + AddSC_deadmines(); //Deadmines + AddSC_boss_mr_smite(); + AddSC_instance_deadmines(); + AddSC_gnomeregan(); //Gnomeregan + AddSC_instance_gnomeregan(); + AddSC_boss_attumen(); //Karazhan + AddSC_boss_curator(); + AddSC_boss_maiden_of_virtue(); + AddSC_boss_shade_of_aran(); + AddSC_boss_malchezaar(); + AddSC_boss_terestian_illhoof(); + AddSC_boss_moroes(); + AddSC_bosses_opera(); + AddSC_boss_netherspite(); + AddSC_instance_karazhan(); + AddSC_karazhan(); + AddSC_boss_nightbane(); + AddSC_boss_felblood_kaelthas(); // Magister's Terrace + AddSC_boss_selin_fireheart(); + AddSC_boss_vexallus(); + AddSC_boss_priestess_delrissa(); + AddSC_instance_magisters_terrace(); + AddSC_magisters_terrace(); + AddSC_boss_lucifron(); //Molten core + AddSC_boss_magmadar(); + AddSC_boss_gehennas(); + AddSC_boss_garr(); + AddSC_boss_baron_geddon(); + AddSC_boss_shazzrah(); + AddSC_boss_golemagg(); + AddSC_boss_sulfuron(); + AddSC_boss_majordomo(); + AddSC_boss_ragnaros(); + AddSC_instance_molten_core(); + AddSC_the_scarlet_enclave(); //Scarlet Enclave + AddSC_the_scarlet_enclave_c1(); + AddSC_the_scarlet_enclave_c2(); + AddSC_the_scarlet_enclave_c5(); + AddSC_boss_arcanist_doan(); //Scarlet Monastery + AddSC_boss_azshir_the_sleepless(); + AddSC_boss_bloodmage_thalnos(); + AddSC_boss_headless_horseman(); + AddSC_boss_herod(); + AddSC_boss_high_inquisitor_fairbanks(); + AddSC_boss_houndmaster_loksey(); + AddSC_boss_interrogator_vishas(); + AddSC_boss_scorn(); + AddSC_instance_scarlet_monastery(); + AddSC_boss_mograine_and_whitemane(); + AddSC_boss_darkmaster_gandling(); //Scholomance + AddSC_boss_death_knight_darkreaver(); + AddSC_boss_theolenkrastinov(); + AddSC_boss_illuciabarov(); + AddSC_boss_instructormalicia(); + AddSC_boss_jandicebarov(); + AddSC_boss_kormok(); + AddSC_boss_lordalexeibarov(); + AddSC_boss_lorekeeperpolkelt(); + AddSC_boss_rasfrost(); + AddSC_boss_theravenian(); + AddSC_boss_vectus(); + AddSC_boss_kirtonos_the_herald(); + AddSC_instance_scholomance(); + AddSC_shadowfang_keep(); //Shadowfang keep + AddSC_instance_shadowfang_keep(); + AddSC_boss_magistrate_barthilas(); //Stratholme + AddSC_boss_maleki_the_pallid(); + AddSC_boss_nerubenkan(); + AddSC_boss_cannon_master_willey(); + AddSC_boss_baroness_anastari(); + AddSC_boss_ramstein_the_gorger(); + AddSC_boss_timmy_the_cruel(); + AddSC_boss_postmaster_malown(); + AddSC_boss_baron_rivendare(); + AddSC_boss_dathrohan_balnazzar(); + AddSC_boss_order_of_silver_hand(); + AddSC_instance_stratholme(); + AddSC_stratholme(); + AddSC_sunken_temple(); // Sunken Temple + AddSC_instance_sunken_temple(); + AddSC_instance_sunwell_plateau(); //Sunwell Plateau + AddSC_boss_kalecgos(); + AddSC_boss_brutallus(); + AddSC_boss_felmyst(); + AddSC_boss_eredar_twins(); + AddSC_boss_muru(); + AddSC_boss_kiljaeden(); + AddSC_sunwell_plateau(); + AddSC_instance_the_stockade(); //The Stockade + AddSC_boss_archaedas(); //Uldaman + AddSC_boss_ironaya(); + AddSC_uldaman(); + AddSC_instance_uldaman(); + AddSC_boss_akilzon(); //Zul'Aman + AddSC_boss_halazzi(); + AddSC_boss_hex_lord_malacrass(); + AddSC_boss_janalai(); + AddSC_boss_nalorakk(); + AddSC_boss_zuljin(); + AddSC_instance_zulaman(); + AddSC_zulaman(); + AddSC_boss_jeklik(); //Zul'Gurub + AddSC_boss_venoxis(); + AddSC_boss_marli(); + AddSC_boss_mandokir(); + AddSC_boss_gahzranka(); + AddSC_boss_thekal(); + AddSC_boss_arlokk(); + AddSC_boss_jindo(); + AddSC_boss_hakkar(); + AddSC_boss_grilek(); + AddSC_boss_hazzarah(); + AddSC_boss_renataki(); + AddSC_boss_wushoolay(); + AddSC_instance_zulgurub(); + //AddSC_alterac_mountains(); + AddSC_arathi_highlands(); + AddSC_blasted_lands(); + AddSC_burning_steppes(); + AddSC_duskwood(); + AddSC_eastern_plaguelands(); + AddSC_ghostlands(); + AddSC_hinterlands(); + AddSC_isle_of_queldanas(); + AddSC_redridge_mountains(); + AddSC_silverpine_forest(); + AddSC_stormwind_city(); + AddSC_stranglethorn_vale(); + AddSC_swamp_of_sorrows(); + AddSC_tirisfal_glades(); + AddSC_undercity(); + AddSC_western_plaguelands(); + AddSC_wetlands(); +} diff --git a/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp b/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp index df61a010f84..73b397553a5 100644 --- a/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp +++ b/src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp @@ -19,7 +19,7 @@ /* ScriptData SDName: Burning_Steppes SD%Complete: 100 -SDComment: Quest support: 4224, 4866 +SDComment: Quest support: 4866 SDCategory: Burning Steppes EndScriptData */ @@ -36,25 +36,11 @@ EndContentData */ ## npc_ragged_john ######*/ -#define GOSSIP_HELLO "Official buisness, John. I need some information about Marsha Windsor. Tell me about the last time you saw him." -#define GOSSIP_SELECT1 "So what did you do?" -#define GOSSIP_SELECT2 "Start making sense, dwarf. I don't want to have anything to do with your cracker, your pappy, or any sort of 'discreditin'." -#define GOSSIP_SELECT3 "Ironfoe?" -#define GOSSIP_SELECT4 "Interesting... continue John." -#define GOSSIP_SELECT5 "So that's how Windsor died..." -#define GOSSIP_SELECT6 "So how did he die?" -#define GOSSIP_SELECT7 "Ok so where the hell is he? Wait a minute! Are you drunk?" -#define GOSSIP_SELECT8 "WHY is he in Blackrock Depths?" -#define GOSSIP_SELECT9 "300? So the Dark Irons killed him and dragged him into the Depths?" -#define GOSSIP_SELECT10 "Ahh... Ironfoe" -#define GOSSIP_SELECT11 "Thanks, Ragged John. Your story was very uplifting and informative" - enum RaggedJohn { - QUEST_THE_TRUE_MASTERS = 4224, - QUEST_MOTHERS_MILK = 4866, - SPELL_MOTHERS_MILK = 16468, - SPELL_WICKED_MILKING = 16472 + QUEST_MOTHERS_MILK = 4866, + SPELL_MOTHERS_MILK = 16468, + SPELL_WICKED_MILKING = 16472 }; class npc_ragged_john : public CreatureScript @@ -86,72 +72,13 @@ public: void EnterCombat(Unit* /*who*/) override { } }; - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(2714, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(2715, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(2716, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - player->SEND_GOSSIP_MENU(2717, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(2718, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - player->SEND_GOSSIP_MENU(2719, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - player->SEND_GOSSIP_MENU(2720, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); - player->SEND_GOSSIP_MENU(2721, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+8: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); - player->SEND_GOSSIP_MENU(2722, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+9: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); - player->SEND_GOSSIP_MENU(2723, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+10: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - player->SEND_GOSSIP_MENU(2725, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(QUEST_THE_TRUE_MASTERS); - break; - } - return true; - } - bool OnGossipHello(Player* player, Creature* creature) override { if (creature->IsQuestGiver()) + { player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_THE_TRUE_MASTERS) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - player->SEND_GOSSIP_MENU(2713, creature->GetGUID()); + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + } return true; } diff --git a/src/server/scripts/EasternKingdoms/zone_eastern_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_eastern_plaguelands.cpp index ce0ebf4d129..4cc72715868 100644 --- a/src/server/scripts/EasternKingdoms/zone_eastern_plaguelands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_eastern_plaguelands.cpp @@ -19,7 +19,7 @@ /* ScriptData SDName: Eastern_Plaguelands SD%Complete: 100 -SDComment: Quest support: 5211, 5742. Special vendor Augustus the Touched +SDComment: Quest support: 5211. Special vendor Augustus the Touched SDCategory: Eastern Plaguelands EndScriptData */ @@ -27,7 +27,6 @@ EndScriptData */ npc_ghoul_flayer npc_augustus_the_touched npc_darrowshire_spirit -npc_tirion_fordring EndContentData */ #include "ScriptMgr.h" @@ -133,63 +132,9 @@ public: }; }; -/*###### -## npc_tirion_fordring -######*/ - -#define GOSSIP_HELLO "I am ready to hear your tale, Tirion." -#define GOSSIP_SELECT1 "Thank you, Tirion. What of your identity?" -#define GOSSIP_SELECT2 "That is terrible." -#define GOSSIP_SELECT3 "I will, Tirion." - -class npc_tirion_fordring : public CreatureScript -{ -public: - npc_tirion_fordring() : CreatureScript("npc_tirion_fordring") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(4493, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(4494, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - player->SEND_GOSSIP_MENU(4495, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(5742); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(5742) == QUEST_STATUS_INCOMPLETE && player->getStandState() == UNIT_STAND_STATE_SIT) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - void AddSC_eastern_plaguelands() { new npc_ghoul_flayer(); new npc_augustus_the_touched(); new npc_darrowshire_spirit(); - new npc_tirion_fordring(); } diff --git a/src/server/scripts/EasternKingdoms/zone_loch_modan.cpp b/src/server/scripts/EasternKingdoms/zone_loch_modan.cpp deleted file mode 100644 index 151f8270c47..00000000000 --- a/src/server/scripts/EasternKingdoms/zone_loch_modan.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -/* ScriptData -SDName: Loch_Modan -SD%Complete: 100 -SDComment: Quest support: 3181 -SDCategory: Loch Modan -EndScriptData */ - -/* ContentData -npc_mountaineer_pebblebitty -EndContentData */ - -#include "ScriptMgr.h" -#include "ScriptedCreature.h" -#include "ScriptedGossip.h" -#include "Player.h" - -/*###### -## npc_mountaineer_pebblebitty -######*/ - -#define GOSSIP_MP "Open the gate please, i need to get to Searing Gorge" - -#define GOSSIP_MP1 "But i need to get there, now open the gate!" -#define GOSSIP_MP2 "Ok, so what is this other way?" -#define GOSSIP_MP3 "Doesn't matter, i'm invulnerable." -#define GOSSIP_MP4 "Yes..." -#define GOSSIP_MP5 "Ok, i'll try to remember that." -#define GOSSIP_MP6 "A key? Ok!" - -class npc_mountaineer_pebblebitty : public CreatureScript -{ -public: - npc_mountaineer_pebblebitty() : CreatureScript("npc_mountaineer_pebblebitty") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(1833, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(1834, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - player->SEND_GOSSIP_MENU(1835, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(1836, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - player->SEND_GOSSIP_MENU(1837, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - player->SEND_GOSSIP_MENU(1838, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - player->CLOSE_GOSSIP_MENU(); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (!player->GetQuestRewardStatus(3181) == 1) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_MP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - -void AddSC_loch_modan() -{ - new npc_mountaineer_pebblebitty(); -} diff --git a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp index 2d6d4da5aef..4a585bcb267 100644 --- a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp +++ b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp @@ -19,14 +19,12 @@ /* ScriptData SDName: Stormwind_City SD%Complete: 100 -SDComment: Quest support: 1640, 1447, 4185, 11223, 434. +SDComment: Quest support: 1640, 1447, 434. SDCategory: Stormwind City EndScriptData */ /* ContentData -npc_archmage_malin npc_bartleby -npc_lady_katrana_prestor npc_tyrion npc_tyrion_spybot npc_marzon_silent_blade @@ -40,50 +38,13 @@ EndContentData */ #include "Player.h" /*###### -## npc_archmage_malin -######*/ - -#define GOSSIP_ITEM_MALIN "Can you send me to Theramore? I have an urgent message for Lady Jaina from Highlord Bolvar." - -class npc_archmage_malin : public CreatureScript -{ -public: - npc_archmage_malin() : CreatureScript("npc_archmage_malin") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF) - { - player->CLOSE_GOSSIP_MENU(); - creature->CastSpell(player, 42711, true); - } - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(11223) == QUEST_STATUS_COMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MALIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - -/*###### ## npc_bartleby ######*/ enum Bartleby { - FACTION_ENEMY = 168, - QUEST_BEAT = 1640 + FACTION_ENEMY = 168, + QUEST_BEAT = 1640 }; class npc_bartleby : public CreatureScript @@ -148,71 +109,18 @@ public: }; /*###### -## npc_lady_katrana_prestor -######*/ - -#define GOSSIP_ITEM_KAT_1 "Pardon the intrusion, Lady Prestor, but Highlord Bolvar suggested that I seek your advice." -#define GOSSIP_ITEM_KAT_2 "My apologies, Lady Prestor." -#define GOSSIP_ITEM_KAT_3 "Begging your pardon, Lady Prestor. That was not my intent." -#define GOSSIP_ITEM_KAT_4 "Thank you for your time, Lady Prestor." - -class npc_lady_katrana_prestor : public CreatureScript -{ -public: - npc_lady_katrana_prestor() : CreatureScript("npc_lady_katrana_prestor") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(2694, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(2695, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(2696, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(4185); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(4185) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - player->SEND_GOSSIP_MENU(2693, creature->GetGUID()); - - return true; - } -}; - -/*###### ## npc_lord_gregor_lescovar ######*/ enum LordGregorLescovar { - SAY_GUARD_2 = 0, - SAY_LESCOVAR_2 = 0, - SAY_LESCOVAR_3 = 1, - SAY_LESCOVAR_4 = 2, - SAY_MARZON_1 = 0, - SAY_MARZON_2 = 1, - SAY_TYRION_2 = 1, + SAY_GUARD_2 = 0, + SAY_LESCOVAR_2 = 0, + SAY_LESCOVAR_3 = 1, + SAY_LESCOVAR_4 = 2, + SAY_MARZON_1 = 0, + SAY_MARZON_2 = 1, + SAY_TYRION_2 = 1, NPC_STORMWIND_ROYAL = 1756, NPC_MARZON_BLADE = 1755, @@ -650,9 +558,7 @@ public: void AddSC_stormwind_city() { - new npc_archmage_malin(); new npc_bartleby(); - new npc_lady_katrana_prestor(); new npc_tyrion(); new npc_tyrion_spybot(); new npc_lord_gregor_lescovar(); diff --git a/src/server/scripts/Events/CMakeLists.txt b/src/server/scripts/Events/CMakeLists.txt deleted file mode 100644 index 1c9e5cfe8e1..00000000000 --- a/src/server/scripts/Events/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -file(GLOB_RECURSE sources_Events Events/*.cpp Events/*.h) - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - ${sources_Events} -) - -message(" -> Prepared: Events") diff --git a/src/server/scripts/Events/childrens_week.cpp b/src/server/scripts/Events/childrens_week.cpp index 4b93f5b4fbb..f61e175b8fc 100644 --- a/src/server/scripts/Events/childrens_week.cpp +++ b/src/server/scripts/Events/childrens_week.cpp @@ -639,6 +639,12 @@ class npc_elder_kekek : public CreatureScript } }; +enum TheEtymidian +{ + SAY_ACTIVATION = 0, + QUEST_THE_ACTIVATION_RUNE = 12547 +}; + /*###### ## npc_the_etymidian ## @todo A red crystal as a gift for the great one should be spawned during the event. @@ -668,10 +674,20 @@ class npc_the_etymidian : public CreatureScript Initialize(); } + void sQuestReward(Player* /*player*/, Quest const* quest, uint32 /*opt*/) override + { + if (quest->GetQuestId() != QUEST_THE_ACTIVATION_RUNE) + return; + + Talk(SAY_ACTIVATION); + } + void MoveInLineOfSight(Unit* who) override { if (!phase && who && who->GetDistance2d(me) < 10.0f) + { if (Player* player = who->ToPlayer()) + { if (player->GetQuestStatus(QUEST_MEETING_A_GREAT_ONE) == QUEST_STATUS_INCOMPLETE) { playerGUID = player->GetGUID(); @@ -679,6 +695,8 @@ class npc_the_etymidian : public CreatureScript if (orphanGUID) phase = 1; } + } + } } void UpdateAI(uint32 diff) override @@ -734,7 +752,6 @@ class npc_the_etymidian : public CreatureScript int8 phase; ObjectGuid playerGUID; ObjectGuid orphanGUID; - }; CreatureAI* GetAI(Creature* creature) const override diff --git a/src/server/scripts/Events/events_script_loader.cpp b/src/server/scripts/Events/events_script_loader.cpp new file mode 100644 index 00000000000..625c08f5389 --- /dev/null +++ b/src/server/scripts/Events/events_script_loader.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +void AddSC_event_childrens_week(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddEventsScripts() +{ + AddSC_event_childrens_week(); +} diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp index b0d6e782052..03c957fa221 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp @@ -174,7 +174,7 @@ public: if (state == DONE) if (GameObject* go = instance->GetGameObject(shrineOfGelihastGUID)) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - break; + break; case DATA_AKU_MAI: if (state == DONE) if (GameObject* go = instance->GetGameObject(altarOfTheDeepsGUID)) diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt deleted file mode 100644 index 2d1b4b49649..00000000000 --- a/src/server/scripts/Kalimdor/CMakeLists.txt +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - Kalimdor/zone_stonetalon_mountains.cpp - Kalimdor/zone_silithus.cpp - Kalimdor/zone_moonglade.cpp - Kalimdor/RazorfenDowns/razorfen_downs.cpp - Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp - Kalimdor/RazorfenDowns/boss_tuten_kash.cpp - Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp - Kalimdor/RazorfenDowns/boss_glutton.cpp - Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp - Kalimdor/RazorfenDowns/razorfen_downs.h - Kalimdor/ZulFarrak/zulfarrak.cpp - Kalimdor/ZulFarrak/instance_zulfarrak.cpp - Kalimdor/ZulFarrak/boss_zum_rah.cpp - Kalimdor/ZulFarrak/zulfarrak.h - Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp - Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h - Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp - Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp - Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp - Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h - Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h - Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h - Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp - Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp - Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite_corruptor.cpp - Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm_the_fleshcrafter.cpp - Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp - Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp - Kalimdor/CavernsOfTime/CullingOfStratholme/boss_chrono_lord_epoch.cpp - Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp - Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp - Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h - Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.h - Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp - Kalimdor/CavernsOfTime/TheBlackMorass/boss_chrono_lord_deja.cpp - Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp - Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp - Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp - Kalimdor/BlackfathomDeeps/boss_kelris.cpp - Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp - Kalimdor/BlackfathomDeeps/boss_gelihast.cpp - Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp - Kalimdor/BlackfathomDeeps/boss_aku_mai.cpp - Kalimdor/BlackfathomDeeps/blackfathom_deeps.h - Kalimdor/zone_azuremyst_isle.cpp - Kalimdor/zone_orgrimmar.cpp - Kalimdor/zone_desolace.cpp - Kalimdor/zone_feralas.cpp - Kalimdor/Maraudon/boss_princess_theradras.cpp - Kalimdor/Maraudon/boss_landslide.cpp - Kalimdor/Maraudon/boss_celebras_the_cursed.cpp - Kalimdor/Maraudon/boss_noxxion.cpp - Kalimdor/Maraudon/instance_maraudon.cpp - Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp - Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp - Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp - Kalimdor/TempleOfAhnQiraj/mob_anubisath_sentinel.cpp - Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp - Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp - Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp - Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp - Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h - Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp - Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp - Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp - Kalimdor/zone_darkshore.cpp - Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp - Kalimdor/RuinsOfAhnQiraj/instance_ruins_of_ahnqiraj.cpp - Kalimdor/RuinsOfAhnQiraj/boss_rajaxx.cpp - Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp - Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp - Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp - Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h - Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp - Kalimdor/zone_bloodmyst_isle.cpp - Kalimdor/zone_thunder_bluff.cpp - Kalimdor/zone_azshara.cpp - Kalimdor/RazorfenKraul/razorfen_kraul.h - Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp - Kalimdor/RazorfenKraul/razorfen_kraul.cpp - Kalimdor/zone_the_barrens.cpp - Kalimdor/zone_ungoro_crater.cpp - Kalimdor/WailingCaverns/wailing_caverns.h - Kalimdor/WailingCaverns/instance_wailing_caverns.cpp - Kalimdor/WailingCaverns/wailing_caverns.cpp - Kalimdor/zone_durotar.cpp - Kalimdor/zone_felwood.cpp - Kalimdor/boss_azuregos.cpp - Kalimdor/zone_tanaris.cpp - Kalimdor/zone_dustwallow_marsh.cpp - Kalimdor/zone_winterspring.cpp - Kalimdor/zone_thousand_needles.cpp - Kalimdor/zone_ashenvale.cpp - Kalimdor/OnyxiasLair/boss_onyxia.cpp - Kalimdor/OnyxiasLair/onyxias_lair.h - Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp - Kalimdor/RagefireChasm/instance_ragefire_chasm.cpp - Kalimdor/DireMaul/instance_dire_maul.cpp -) - -message(" -> Prepared: Kalimdor") diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp index 6b2142a8095..c326710e820 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp @@ -650,7 +650,7 @@ void hyjalAI::SpawnVeins() return; for (uint8 i = 0; i < 7; ++i) { - GameObject* gem = me->SummonGameObject(GO_ANCIENT_VEIN, VeinPos[i][0], VeinPos[i][1], VeinPos[i][2], VeinPos[i][3], VeinPos[i][4], VeinPos[i][5], VeinPos[i][6], VeinPos[i][7], 0); + GameObject* gem = me->SummonGameObject(GO_ANCIENT_VEIN, VeinPos[i][0], VeinPos[i][1], VeinPos[i][2], VeinPos[i][3], G3D::Quat(VeinPos[i][4], VeinPos[i][5], VeinPos[i][6], VeinPos[i][7]), 0); if (gem) VeinGUID[i]=gem->GetGUID(); } @@ -662,7 +662,7 @@ void hyjalAI::SpawnVeins() return; for (uint8 i = 7; i < 14; ++i) { - GameObject* gem = me->SummonGameObject(GO_ANCIENT_VEIN, VeinPos[i][0], VeinPos[i][1], VeinPos[i][2], VeinPos[i][3], VeinPos[i][4], VeinPos[i][5], VeinPos[i][6], VeinPos[i][7], 0); + GameObject* gem = me->SummonGameObject(GO_ANCIENT_VEIN, VeinPos[i][0], VeinPos[i][1], VeinPos[i][2], VeinPos[i][3], G3D::Quat(VeinPos[i][4], VeinPos[i][5], VeinPos[i][6], VeinPos[i][7]), 0); if (gem) VeinGUID[i] = gem->GetGUID(); } @@ -725,7 +725,7 @@ void hyjalAI::UpdateAI(uint32 diff) HideNearPos(me->GetPositionX(), me->GetPositionY()); HideNearPos(5037.76f, -1889.71f); for (uint8 i = 0; i < 92; ++i)//summon fires - me->SummonGameObject(GO_ROARING_FLAME, AllianceFirePos[i][0], AllianceFirePos[i][1], AllianceFirePos[i][2], AllianceFirePos[i][3], AllianceFirePos[i][4], AllianceFirePos[i][5], AllianceFirePos[i][6], AllianceFirePos[i][7], 0); + me->SummonGameObject(GO_ROARING_FLAME, AllianceFirePos[i][0], AllianceFirePos[i][1], AllianceFirePos[i][2], AllianceFirePos[i][3], G3D::Quat(AllianceFirePos[i][4], AllianceFirePos[i][5], AllianceFirePos[i][6], AllianceFirePos[i][7]), 0); } else me->SetVisible(true); @@ -738,7 +738,7 @@ void hyjalAI::UpdateAI(uint32 diff) HideNearPos(5563, -2763.19f); HideNearPos(5542.2f, -2629.36f); for (uint8 i = 0; i < 65; ++i)//summon fires - me->SummonGameObject(GO_ROARING_FLAME, HordeFirePos[i][0], HordeFirePos[i][1], HordeFirePos[i][2], HordeFirePos[i][3], HordeFirePos[i][4], HordeFirePos[i][5], HordeFirePos[i][6], HordeFirePos[i][7], 0); + me->SummonGameObject(GO_ROARING_FLAME, HordeFirePos[i][0], HordeFirePos[i][1], HordeFirePos[i][2], HordeFirePos[i][3], G3D::Quat(HordeFirePos[i][4], HordeFirePos[i][5], HordeFirePos[i][6], HordeFirePos[i][7]), 0); } else me->SetVisible(true); @@ -1042,7 +1042,7 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) { case 0://alliance for (uint8 i = 0; i < 92; ++i)//summon fires - me->SummonGameObject(GO_ROARING_FLAME, AllianceFirePos[i][0], AllianceFirePos[i][1], AllianceFirePos[i][2], AllianceFirePos[i][3], AllianceFirePos[i][4], AllianceFirePos[i][5], AllianceFirePos[i][6], AllianceFirePos[i][7], 0); + me->SummonGameObject(GO_ROARING_FLAME, AllianceFirePos[i][0], AllianceFirePos[i][1], AllianceFirePos[i][2], AllianceFirePos[i][3], G3D::Quat(AllianceFirePos[i][4], AllianceFirePos[i][5], AllianceFirePos[i][6], AllianceFirePos[i][7]), 0); for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls { @@ -1083,7 +1083,7 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) break; case 1://horde for (uint8 i = 0; i < 65; ++i)//summon fires - me->SummonGameObject(GO_ROARING_FLAME, HordeFirePos[i][0], HordeFirePos[i][1], HordeFirePos[i][2], HordeFirePos[i][3], HordeFirePos[i][4], HordeFirePos[i][5], HordeFirePos[i][6], HordeFirePos[i][7], 0); + me->SummonGameObject(GO_ROARING_FLAME, HordeFirePos[i][0], HordeFirePos[i][1], HordeFirePos[i][2], HordeFirePos[i][3], G3D::Quat(HordeFirePos[i][4], HordeFirePos[i][5], HordeFirePos[i][6], HordeFirePos[i][7]), 0); for (uint8 i = 0; i < 26; ++i)//summon infernals { diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h index 55b85801652..54d3c53039e 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h @@ -121,15 +121,15 @@ struct hyjalAI : public npc_escortAI void Initialize(); - void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat + void Reset() override; // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat - void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER); // Send creature back to spawn location and evade. + void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override; // Send creature back to spawn location and evade. - void EnterCombat(Unit* /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack + void EnterCombat(Unit* /*who*/) override; // Used to reset cooldowns for our spells and to inform the raid that we're under attack - void UpdateAI(uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells. + void UpdateAI(uint32 diff) override; // Called to summon waves, check for boss deaths and to cast our spells. - void JustDied(Unit* /*killer*/); // Called on death, informs the raid that they have failed. + void JustDied(Unit* /*killer*/) override; // Called on death, informs the raid that they have failed. void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal { @@ -140,13 +140,13 @@ struct hyjalAI : public npc_escortAI void SpawnVeins(); void DeSpawnVeins(); - void JustSummoned(Creature* summoned); - void SummonedCreatureDespawn(Creature* summoned); + void JustSummoned(Creature* summoned) override; + void SummonedCreatureDespawn(Creature* summoned) override; void HideNearPos(float x, float y); void RespawnNearPos(float x, float y); - void WaypointReached(uint32 waypointId); + void WaypointReached(uint32 waypointId) override; void DoOverrun(uint32 faction, const uint32 diff); - void MoveInLineOfSight(Unit* who); + void MoveInLineOfSight(Unit* who) override; void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h index 5275c07f63a..f29851e7cea 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h @@ -25,11 +25,11 @@ struct hyjal_trashAI : public npc_escortAI { hyjal_trashAI(Creature* creature); - void UpdateAI(uint32 diff); + void UpdateAI(uint32 diff) override; - void JustDied(Unit* /*killer*/); + void JustDied(Unit* /*killer*/) override; - void DamageTaken(Unit* done_by, uint32 &damage); + void DamageTaken(Unit* done_by, uint32 &damage) override; public: InstanceScript* instance; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp index 074ea781838..f76e65c3423 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp @@ -1256,7 +1256,7 @@ class npc_crate_helper : public CreatureScript instance->SetData(DATA_CRATE_COUNT, instance->GetData(DATA_CRATE_COUNT) + 1); if (GameObject* crate = me->FindNearestGameObject(GO_SUSPICIOUS_CRATE, 5.0f)) { - crate->SummonGameObject(GO_PLAGUED_CRATE, crate->GetPositionX(), crate->GetPositionY(), crate->GetPositionZ(), crate->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, DAY); + crate->SummonGameObject(GO_PLAGUED_CRATE, *crate, G3D::Quat(), DAY); crate->Delete(); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp index 44cbdec2cb5..8e53ab06ca5 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp @@ -479,12 +479,12 @@ public: void DoMount() { me->Mount(SKARLOC_MOUNT_MODEL); - me->SetSpeed(MOVE_RUN, SPEED_MOUNT); + me->SetSpeedRate(MOVE_RUN, SPEED_MOUNT); } void DoUnmount() { me->Dismount(); - me->SetSpeed(MOVE_RUN, SPEED_RUN); + me->SetSpeedRate(MOVE_RUN, SPEED_RUN); } void EnterCombat(Unit* /*who*/) override { @@ -535,12 +535,12 @@ public: if (!UpdateVictim()) return; - /// @todo add his abilities'n-crap here - if (!LowHp && HealthBelowPct(20)) - { - Talk(SAY_TH_RANDOM_LOW_HP); - LowHp = true; - } + /// @todo add his abilities'n-crap here + if (!LowHp && HealthBelowPct(20)) + { + Talk(SAY_TH_RANDOM_LOW_HP); + LowHp = true; + } } }; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp index 8715f3ca0f6..4d0f80d502d 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp @@ -106,33 +106,33 @@ public: if (!UpdateVictim()) return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - switch (eventId) - { - case EVENT_SANDBREATH: - DoCastVictim(SPELL_SAND_BREATH); - events.ScheduleEvent(EVENT_SANDBREATH, urand(15000, 25000)); - break; - case EVENT_TIMESTOP: - DoCastVictim(SPELL_TIME_STOP); - events.ScheduleEvent(EVENT_TIMESTOP, urand(20000, 35000)); - break; - case EVENT_FRENZY: - Talk(EMOTE_FRENZY); - DoCast(me, SPELL_ENRAGE); - events.ScheduleEvent(EVENT_FRENZY, urand(20000, 35000)); - break; - default: - break; - } + case EVENT_SANDBREATH: + DoCastVictim(SPELL_SAND_BREATH); + events.ScheduleEvent(EVENT_SANDBREATH, urand(15000, 25000)); + break; + case EVENT_TIMESTOP: + DoCastVictim(SPELL_TIME_STOP); + events.ScheduleEvent(EVENT_TIMESTOP, urand(20000, 35000)); + break; + case EVENT_FRENZY: + Talk(EMOTE_FRENZY); + DoCast(me, SPELL_ENRAGE); + events.ScheduleEvent(EVENT_FRENZY, urand(20000, 35000)); + break; + default: + break; } - DoMeleeAttackIfReady(); + } + DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp index 2befdabe550..844ce239bdf 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp @@ -107,36 +107,36 @@ public: if (!UpdateVictim()) return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - switch (eventId) - { - case EVENT_HASTE: - DoCast(me, SPELL_HASTE); - events.ScheduleEvent(EVENT_HASTE, urand(20000, 25000)); - break; - case EVENT_MORTAL_WOUND: - DoCast(me, SPELL_MORTAL_WOUND); - events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 20000)); - break; - case EVENT_WING_BUFFET: - DoCast(me, SPELL_WING_BUFFET); - events.ScheduleEvent(EVENT_WING_BUFFET, urand(20000, 30000)); - break; - case EVENT_SPELL_REFLECTION: // Only in Heroic - DoCast(me, SPELL_REFLECT); - events.ScheduleEvent(EVENT_SPELL_REFLECTION, urand(25000, 35000)); - break; - default: - break; - } + case EVENT_HASTE: + DoCast(me, SPELL_HASTE); + events.ScheduleEvent(EVENT_HASTE, urand(20000, 25000)); + break; + case EVENT_MORTAL_WOUND: + DoCast(me, SPELL_MORTAL_WOUND); + events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 20000)); + break; + case EVENT_WING_BUFFET: + DoCast(me, SPELL_WING_BUFFET); + events.ScheduleEvent(EVENT_WING_BUFFET, urand(20000, 30000)); + break; + case EVENT_SPELL_REFLECTION: // Only in Heroic + DoCast(me, SPELL_REFLECT); + events.ScheduleEvent(EVENT_SPELL_REFLECTION, urand(25000, 35000)); + break; + default: + break; } - DoMeleeAttackIfReady(); + } + DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp b/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp index 00a622f1319..558b6c10a61 100644 --- a/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp +++ b/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp @@ -25,20 +25,49 @@ gets instead the deserter debuff. #include "ScriptMgr.h" #include "InstanceScript.h" +// Bosses (East) +// 0 - Pusillin +// 1 - Lethtendris +// 2 - Hydrospawn +// 3 - Zevrim Thornhoof +// 4 - Alzzin the Wildshaper + +// West +// 5 - Tendris Warpwood +// 6 - Magister Kalendris +// 7 - Tsu'zee +// 8 - Illyanna Ravenoak +// 9 - Immol'thar +// 10 - Prince Tortheldrin + +// North +// 11 - Guard Mol'dar +// 12 - Stomper Kreeg +// 13 - Guard Fengus +// 14 - Guard Slip'kik +// 15 - Captain Kromcrush +// 16 - King Gordok + +uint8 const EncounterCount = 17; + class instance_dire_maul : public InstanceMapScript { public: instance_dire_maul() : InstanceMapScript("instance_dire_maul", 429) { } + struct instance_dire_maul_InstanceMapScript : public InstanceScript + { + instance_dire_maul_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + } + }; + InstanceScript* GetInstanceScript(InstanceMap* map) const override { return new instance_dire_maul_InstanceMapScript(map); } - struct instance_dire_maul_InstanceMapScript : public InstanceScript - { - instance_dire_maul_InstanceMapScript(Map* map) : InstanceScript(map) { } - }; }; void AddSC_instance_dire_maul() diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index 7da15b1fdce..71ebe870e3d 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -205,7 +205,7 @@ public: PointData = GetMoveData(); MovePoint = PointData->LocIdEnd; - me->SetSpeed(MOVE_FLIGHT, 1.5f); + me->SetSpeedRate(MOVE_FLIGHT, 1.5f); me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation); } } @@ -220,7 +220,7 @@ public: PointData = GetMoveData(); if (PointData) { - me->SetSpeed(MOVE_FLIGHT, 1.0f); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); me->GetMotionMaster()->MovePoint(PointData->LocId, PointData->fX, PointData->fY, PointData->fZ); } break; @@ -250,7 +250,7 @@ public: if (Creature * trigger = me->SummonCreature(NPC_TRIGGER, MiddleRoomLocation, TEMPSUMMON_CORPSE_DESPAWN)) triggerGUID = trigger->GetGUID(); me->GetMotionMaster()->MoveTakeoff(11, Phase2Floating); - me->SetSpeed(MOVE_FLIGHT, 1.0f); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); Talk(SAY_PHASE_2_TRANS); instance->SetData(DATA_ONYXIA_PHASE, Phase); events.ScheduleEvent(EVENT_WHELP_SPAWN, 5000); diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp index b579f9fc608..e8b101b5057 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp +++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp @@ -204,7 +204,7 @@ public: case EVENT_COMPLETE: { DoCast(me, SPELL_IDOM_ROOM_CAMERA_SHAKE); - me->SummonGameObject(GO_BELNISTRASZS_BRAZIER, 2577.196f, 947.0781f, 53.16757f, 2.356195f, 0, 0, 0.9238796f, 0.3826832f, 3600); + me->SummonGameObject(GO_BELNISTRASZS_BRAZIER, 2577.196f, 947.0781f, 53.16757f, 2.356195f, G3D::Quat(0.f, 0.f, 0.9238796f, 0.3826832f), 3600); std::list<WorldObject*> ClusterList; Trinity::AllWorldObjectsInRange objects(me, 50.0f); Trinity::WorldObjectListSearcher<Trinity::AllWorldObjectsInRange> searcher(me, ClusterList, objects); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index b192ff8ef4d..a220468e513 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -190,11 +190,7 @@ class boss_ossirian : public CreatureScript if (Creature* Trigger = me->GetMap()->SummonCreature(NPC_OSSIRIAN_TRIGGER, CrystalCoordinates[CrystalIterator])) { TriggerGUID = Trigger->GetGUID(); - if (GameObject* Crystal = Trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL, - CrystalCoordinates[CrystalIterator].GetPositionX(), - CrystalCoordinates[CrystalIterator].GetPositionY(), - CrystalCoordinates[CrystalIterator].GetPositionZ(), - 0, 0, 0, 0, 0, uint32(-1))) + if (GameObject* Crystal = Trigger->SummonGameObject(GO_OSSIRIAN_CRYSTAL, CrystalCoordinates[CrystalIterator], G3D::Quat(), uint32(-1))) { CrystalGUID = Crystal->GetGUID(); ++CrystalIterator; diff --git a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp new file mode 100644 index 00000000000..87edf4781d4 --- /dev/null +++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +void AddSC_blackfathom_deeps(); //Blackfathom Depths +void AddSC_boss_gelihast(); +void AddSC_boss_kelris(); +void AddSC_boss_aku_mai(); +void AddSC_instance_blackfathom_deeps(); +void AddSC_hyjal(); //CoT Battle for Mt. Hyjal +void AddSC_boss_archimonde(); +void AddSC_instance_mount_hyjal(); +void AddSC_hyjal_trash(); +void AddSC_boss_rage_winterchill(); +void AddSC_boss_anetheron(); +void AddSC_boss_kazrogal(); +void AddSC_boss_azgalor(); +void AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad +void AddSC_boss_epoch_hunter(); +void AddSC_boss_lieutenant_drake(); +void AddSC_instance_old_hillsbrad(); +void AddSC_old_hillsbrad(); +void AddSC_boss_aeonus(); //CoT The Black Morass +void AddSC_boss_chrono_lord_deja(); +void AddSC_boss_temporus(); +void AddSC_the_black_morass(); +void AddSC_instance_the_black_morass(); +void AddSC_boss_epoch(); //CoT Culling Of Stratholme +void AddSC_boss_infinite_corruptor(); +void AddSC_boss_salramm(); +void AddSC_boss_mal_ganis(); +void AddSC_boss_meathook(); +void AddSC_culling_of_stratholme(); +void AddSC_instance_culling_of_stratholme(); +void AddSC_instance_dire_maul(); //Dire Maul +void AddSC_instance_ragefire_chasm(); //Ragefire Chasm +void AddSC_boss_celebras_the_cursed(); //Maraudon +void AddSC_boss_landslide(); +void AddSC_boss_noxxion(); +void AddSC_boss_ptheradras(); +void AddSC_instance_maraudon(); +void AddSC_boss_onyxia(); //Onyxia's Lair +void AddSC_instance_onyxias_lair(); +void AddSC_boss_tuten_kash(); //Razorfen Downs +void AddSC_boss_mordresh_fire_eye(); +void AddSC_boss_glutton(); +void AddSC_boss_amnennar_the_coldbringer(); +void AddSC_razorfen_downs(); +void AddSC_instance_razorfen_downs(); +void AddSC_razorfen_kraul(); //Razorfen Kraul +void AddSC_instance_razorfen_kraul(); +void AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj +void AddSC_boss_rajaxx(); +void AddSC_boss_moam(); +void AddSC_boss_buru(); +void AddSC_boss_ayamiss(); +void AddSC_boss_ossirian(); +void AddSC_instance_ruins_of_ahnqiraj(); +void AddSC_boss_cthun(); //Temple of ahn'qiraj +void AddSC_boss_viscidus(); +void AddSC_boss_fankriss(); +void AddSC_boss_huhuran(); +void AddSC_bug_trio(); +void AddSC_boss_sartura(); +void AddSC_boss_skeram(); +void AddSC_boss_twinemperors(); +void AddSC_boss_ouro(); +void AddSC_npc_anubisath_sentinel(); +void AddSC_instance_temple_of_ahnqiraj(); +void AddSC_wailing_caverns(); //Wailing caverns +void AddSC_instance_wailing_caverns(); +void AddSC_boss_zum_rah(); //Zul'Farrak +void AddSC_zulfarrak(); +void AddSC_instance_zulfarrak(); + +void AddSC_ashenvale(); +void AddSC_azshara(); +void AddSC_azuremyst_isle(); +void AddSC_bloodmyst_isle(); +void AddSC_boss_azuregos(); +void AddSC_darkshore(); +void AddSC_desolace(); +void AddSC_durotar(); +void AddSC_dustwallow_marsh(); +void AddSC_felwood(); +void AddSC_feralas(); +void AddSC_moonglade(); +void AddSC_orgrimmar(); +void AddSC_silithus(); +void AddSC_stonetalon_mountains(); +void AddSC_tanaris(); +void AddSC_the_barrens(); +void AddSC_thousand_needles(); +void AddSC_thunder_bluff(); +void AddSC_ungoro_crater(); +void AddSC_winterspring(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddKalimdorScripts() +{ + AddSC_blackfathom_deeps(); //Blackfathom Depths + AddSC_boss_gelihast(); + AddSC_boss_kelris(); + AddSC_boss_aku_mai(); + AddSC_instance_blackfathom_deeps(); + AddSC_hyjal(); //CoT Battle for Mt. Hyjal + AddSC_boss_archimonde(); + AddSC_instance_mount_hyjal(); + AddSC_hyjal_trash(); + AddSC_boss_rage_winterchill(); + AddSC_boss_anetheron(); + AddSC_boss_kazrogal(); + AddSC_boss_azgalor(); + AddSC_boss_captain_skarloc(); //CoT Old Hillsbrad + AddSC_boss_epoch_hunter(); + AddSC_boss_lieutenant_drake(); + AddSC_instance_old_hillsbrad(); + AddSC_old_hillsbrad(); + AddSC_boss_aeonus(); //CoT The Black Morass + AddSC_boss_chrono_lord_deja(); + AddSC_boss_temporus(); + AddSC_the_black_morass(); + AddSC_instance_the_black_morass(); + AddSC_boss_epoch(); //CoT Culling Of Stratholme + AddSC_boss_infinite_corruptor(); + AddSC_boss_salramm(); + AddSC_boss_mal_ganis(); + AddSC_boss_meathook(); + AddSC_culling_of_stratholme(); + AddSC_instance_culling_of_stratholme(); + AddSC_instance_dire_maul(); //Dire Maul + AddSC_instance_ragefire_chasm(); //Ragefire Chasm + AddSC_boss_celebras_the_cursed(); //Maraudon + AddSC_boss_landslide(); + AddSC_boss_noxxion(); + AddSC_boss_ptheradras(); + AddSC_instance_maraudon(); + AddSC_boss_onyxia(); //Onyxia's Lair + AddSC_instance_onyxias_lair(); + AddSC_boss_tuten_kash(); //Razorfen Downs + AddSC_boss_mordresh_fire_eye(); + AddSC_boss_glutton(); + AddSC_boss_amnennar_the_coldbringer(); + AddSC_razorfen_downs(); + AddSC_instance_razorfen_downs(); + AddSC_razorfen_kraul(); //Razorfen Kraul + AddSC_instance_razorfen_kraul(); + AddSC_boss_kurinnaxx(); //Ruins of ahn'qiraj + AddSC_boss_rajaxx(); + AddSC_boss_moam(); + AddSC_boss_buru(); + AddSC_boss_ayamiss(); + AddSC_boss_ossirian(); + AddSC_instance_ruins_of_ahnqiraj(); + AddSC_boss_cthun(); //Temple of ahn'qiraj + AddSC_boss_viscidus(); + AddSC_boss_fankriss(); + AddSC_boss_huhuran(); + AddSC_bug_trio(); + AddSC_boss_sartura(); + AddSC_boss_skeram(); + AddSC_boss_twinemperors(); + AddSC_boss_ouro(); + AddSC_npc_anubisath_sentinel(); + AddSC_instance_temple_of_ahnqiraj(); + AddSC_wailing_caverns(); //Wailing caverns + AddSC_instance_wailing_caverns(); + AddSC_boss_zum_rah(); //Zul'Farrak + AddSC_zulfarrak(); + AddSC_instance_zulfarrak(); + + AddSC_ashenvale(); + AddSC_azshara(); + AddSC_azuremyst_isle(); + AddSC_bloodmyst_isle(); + AddSC_boss_azuregos(); + AddSC_darkshore(); + AddSC_desolace(); + AddSC_durotar(); + AddSC_dustwallow_marsh(); + AddSC_felwood(); + AddSC_feralas(); + AddSC_moonglade(); + AddSC_orgrimmar(); + AddSC_silithus(); + AddSC_stonetalon_mountains(); + AddSC_tanaris(); + AddSC_the_barrens(); + AddSC_thousand_needles(); + AddSC_thunder_bluff(); + AddSC_ungoro_crater(); + AddSC_winterspring(); +} diff --git a/src/server/scripts/Kalimdor/zone_azshara.cpp b/src/server/scripts/Kalimdor/zone_azshara.cpp index 1ed95c16a0d..4847ac46542 100644 --- a/src/server/scripts/Kalimdor/zone_azshara.cpp +++ b/src/server/scripts/Kalimdor/zone_azshara.cpp @@ -404,7 +404,7 @@ public: DoCast(me, SPELL_PERIODIC_DEPTH_CHARGE); me->SetHover(true); me->SetSwim(true); - me->SetSpeed(MOVE_RUN, 0.85f, true); + me->SetSpeedRate(MOVE_RUN, 0.85f); me->GetMotionMaster()->MovementExpired(); me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP]); Escape = true; diff --git a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp index 273e81d83c0..a7b2b156128 100644 --- a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp +++ b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp @@ -240,11 +240,6 @@ class npc_sironas : public CreatureScript public: npc_sironas() : CreatureScript("npc_sironas") { } - CreatureAI* GetAI(Creature* creature) const - { - return new npc_sironasAI(creature); - } - struct npc_sironasAI : public ScriptedAI { npc_sironasAI(Creature* creature) : ScriptedAI(creature) { } @@ -343,6 +338,11 @@ public: GuidList _beamGuidList; EventMap _events; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_sironasAI(creature); + } }; /*###### @@ -354,11 +354,6 @@ class npc_demolitionist_legoso : public CreatureScript public: npc_demolitionist_legoso() : CreatureScript("npc_demolitionist_legoso") { } - CreatureAI* GetAI(Creature* creature) const - { - return new npc_demolitionist_legosoAI(creature); - } - struct npc_demolitionist_legosoAI : public npc_escortAI { npc_demolitionist_legosoAI(Creature* creature) : npc_escortAI(creature) @@ -513,7 +508,7 @@ public: _explosivesGuids.clear(); for (uint8 i = 0; i != MAX_EXPLOSIVES; ++i) { - if (GameObject* explosive = me->SummonGameObject(GO_DRAENEI_EXPLOSIVES_1, ExplosivesPos[0][i].m_positionX, ExplosivesPos[0][i].m_positionY, ExplosivesPos[0][i].m_positionZ, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0)) + if (GameObject* explosive = me->SummonGameObject(GO_DRAENEI_EXPLOSIVES_1, ExplosivesPos[0][i], G3D::Quat(), 0)) _explosivesGuids.push_back(explosive->GetGUID()); } me->HandleEmoteCommand(EMOTE_ONESHOT_NONE); // reset anim state @@ -609,7 +604,7 @@ public: _explosivesGuids.clear(); for (uint8 i = 0; i != MAX_EXPLOSIVES; ++i) { - if (GameObject* explosive = me->SummonGameObject(GO_DRAENEI_EXPLOSIVES_2, ExplosivesPos[1][i].m_positionX, ExplosivesPos[1][i].m_positionY, ExplosivesPos[1][i].m_positionZ, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0)) + if (GameObject* explosive = me->SummonGameObject(GO_DRAENEI_EXPLOSIVES_2, ExplosivesPos[1][i], G3D::Quat(), 0)) _explosivesGuids.push_back(explosive->GetGUID()); } Talk(SAY_LEGOSO_15); @@ -812,6 +807,11 @@ public: GuidList _explosivesGuids; EventMap _events; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_demolitionist_legosoAI(creature); + } }; void AddSC_bloodmyst_isle() diff --git a/src/server/scripts/Kalimdor/zone_desolace.cpp b/src/server/scripts/Kalimdor/zone_desolace.cpp index 621e0b0a585..3f4a905147f 100644 --- a/src/server/scripts/Kalimdor/zone_desolace.cpp +++ b/src/server/scripts/Kalimdor/zone_desolace.cpp @@ -66,7 +66,6 @@ public: npc_aged_dying_ancient_kodoAI(Creature* creature) : ScriptedAI(creature) { } void MoveInLineOfSight(Unit* who) override - { if (who->GetEntry() == NPC_SMEED && me->IsWithinDistInMap(who, 10.0f) && !me->HasAura(SPELL_KODO_KOMBO_GOSSIP)) { @@ -90,7 +89,7 @@ public: me->UpdateEntry(NPC_TAMED_KODO); me->CombatStop(); me->DeleteThreatList(); - me->SetSpeed(MOVE_RUN, 0.6f, true); + me->SetSpeedRate(MOVE_RUN, 0.6f); me->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, me->GetFollowAngle()); me->setActive(true); } @@ -226,37 +225,9 @@ public: } }; -/*###### -## go_demon_portal -######*/ - -enum DemonPortal -{ - NPC_DEMON_GUARDIAN = 11937, - QUEST_PORTAL_OF_THE_LEGION = 5581 -}; - -class go_demon_portal : public GameObjectScript -{ - public: - go_demon_portal() : GameObjectScript("go_demon_portal") { } - - bool OnGossipHello(Player* player, GameObject* go) override - { - if (player->GetQuestStatus(QUEST_PORTAL_OF_THE_LEGION) == QUEST_STATUS_INCOMPLETE && !go->FindNearestCreature(NPC_DEMON_GUARDIAN, 5.0f, true)) - { - if (Creature* guardian = player->SummonCreature(NPC_DEMON_GUARDIAN, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ(), 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0)) - guardian->AI()->AttackStart(player); - } - - return true; - } -}; - void AddSC_desolace() { new npc_aged_dying_ancient_kodo(); new go_iruxos(); new npc_dalinda(); - new go_demon_portal(); } diff --git a/src/server/scripts/Kalimdor/zone_durotar.cpp b/src/server/scripts/Kalimdor/zone_durotar.cpp index 05caf9cca3a..62a041e7798 100644 --- a/src/server/scripts/Kalimdor/zone_durotar.cpp +++ b/src/server/scripts/Kalimdor/zone_durotar.cpp @@ -483,8 +483,8 @@ class spell_mount_check : public SpellScriptLoader else if (!owner->IsMounted() && target->IsMounted()) target->Dismount(); - target->SetSpeed(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN)); - target->SetSpeed(MOVE_WALK, owner->GetSpeedRate(MOVE_WALK)); + target->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN)); + target->SetSpeedRate(MOVE_WALK, owner->GetSpeedRate(MOVE_WALK)); } void Register() override diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp index 9df9f0b604a..be49778ee4a 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -24,7 +24,6 @@ SDCategory: Dustwallow Marsh EndScriptData */ /* ContentData -npc_lady_jaina_proudmoore npc_nat_pagle npc_private_hendel npc_cassa_crimsonwing - handled by npc_taxi @@ -39,49 +38,6 @@ EndContentData */ #include "WorldSession.h" /*###### -## npc_lady_jaina_proudmoore -######*/ - -enum LadyJaina -{ - QUEST_JAINAS_AUTOGRAPH = 558, - SPELL_JAINAS_AUTOGRAPH = 23122 -}; - -#define GOSSIP_ITEM_JAINA "I know this is rather silly but i have a young ward who is a bit shy and would like your autograph." - -class npc_lady_jaina_proudmoore : public CreatureScript -{ -public: - npc_lady_jaina_proudmoore() : CreatureScript("npc_lady_jaina_proudmoore") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_SENDER_INFO) - { - player->SEND_GOSSIP_MENU(7012, creature->GetGUID()); - player->CastSpell(player, SPELL_JAINAS_AUTOGRAPH, false); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_JAINAS_AUTOGRAPH) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_JAINA, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } - -}; - -/*###### ## npc_nat_pagle ######*/ @@ -417,7 +373,6 @@ class spell_energize_aoe : public SpellScriptLoader void AddSC_dustwallow_marsh() { - new npc_lady_jaina_proudmoore(); new npc_nat_pagle(); new npc_private_hendel(); new npc_zelfrax(); diff --git a/src/server/scripts/Kalimdor/zone_felwood.cpp b/src/server/scripts/Kalimdor/zone_felwood.cpp index bce9d62105c..2b42db4b697 100644 --- a/src/server/scripts/Kalimdor/zone_felwood.cpp +++ b/src/server/scripts/Kalimdor/zone_felwood.cpp @@ -19,12 +19,12 @@ /* ScriptData SDName: Felwood SD%Complete: 95 -SDComment: Quest support: 4101, 4102 +SDComment: Quest support: 7632 SDCategory: Felwood EndScriptData */ /* ContentData -npcs_riverbreeze_and_silversky +at_ancient_leaf EndContentData */ #include "ScriptMgr.h" @@ -33,74 +33,6 @@ EndContentData */ #include "Player.h" /*###### -## npcs_riverbreeze_and_silversky -######*/ - -#define GOSSIP_ITEM_BEACON "Please make me a Cenarion Beacon" - -enum RiverbreezeAndSilversky -{ - SPELL_CENARION_BEACON = 15120, - - NPC_ARATHANDRIS_SILVERSKY = 9528, - NPC_MAYBESS_RIVERBREEZE = 9529, - - QUEST_CLEASING_FELWOOD_A = 4101, - QUEST_CLEASING_FELWOOD_H = 4102 -}; - -class npcs_riverbreeze_and_silversky : public CreatureScript -{ -public: - npcs_riverbreeze_and_silversky() : CreatureScript("npcs_riverbreeze_and_silversky") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - player->CLOSE_GOSSIP_MENU(); - creature->CastSpell(player, SPELL_CENARION_BEACON, false); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - uint32 creatureId = creature->GetEntry(); - - if (creatureId == NPC_ARATHANDRIS_SILVERSKY) - { - if (player->GetQuestRewardStatus(QUEST_CLEASING_FELWOOD_A)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(2848, creature->GetGUID()); - } else if (player->GetTeam() == HORDE) - player->SEND_GOSSIP_MENU(2845, creature->GetGUID()); - else - player->SEND_GOSSIP_MENU(2844, creature->GetGUID()); - } - - if (creatureId == NPC_MAYBESS_RIVERBREEZE) - { - if (player->GetQuestRewardStatus(QUEST_CLEASING_FELWOOD_H)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(2849, creature->GetGUID()); - } else if (player->GetTeam() == ALLIANCE) - player->SEND_GOSSIP_MENU(2843, creature->GetGUID()); - else - player->SEND_GOSSIP_MENU(2842, creature->GetGUID()); - } - - return true; - } -}; - -/*###### ## at_ancient_leaf ######*/ @@ -138,6 +70,5 @@ class at_ancient_leaf : public AreaTriggerScript void AddSC_felwood() { - new npcs_riverbreeze_and_silversky(); new at_ancient_leaf(); } diff --git a/src/server/scripts/Kalimdor/zone_feralas.cpp b/src/server/scripts/Kalimdor/zone_feralas.cpp index 3e67a95b503..3c6ab633f66 100644 --- a/src/server/scripts/Kalimdor/zone_feralas.cpp +++ b/src/server/scripts/Kalimdor/zone_feralas.cpp @@ -19,10 +19,15 @@ /* ScriptData SDName: Feralas SD%Complete: 100 -SDComment: Quest support: 2767, Special vendor Gregan Brewspewer +SDComment: Quest support: 2767, 2987 SDCategory: Feralas EndScriptData */ +/* ContentData +npc_oox22fe +spell_gordunni_trap +EndContentData */ + #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedEscortAI.h" @@ -32,44 +37,6 @@ EndScriptData */ #include "WorldSession.h" /*###### -## npc_gregan_brewspewer -######*/ - -#define GOSSIP_HELLO "Buy somethin', will ya?" - -class npc_gregan_brewspewer : public CreatureScript -{ -public: - npc_gregan_brewspewer() : CreatureScript("npc_gregan_brewspewer") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - player->SEND_GOSSIP_MENU(2434, creature->GetGUID()); - } - if (action == GOSSIP_ACTION_TRADE) - player->GetSession()->SendListInventory(creature->GetGUID()); - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (creature->IsVendor() && player->GetQuestStatus(3909) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(2433, creature->GetGUID()); - return true; - } - -}; - -/*###### ## npc_oox22fe ######*/ @@ -183,6 +150,10 @@ public: }; +/*###### +## spell_gordunni_trap +######*/ + enum GordunniTrap { GO_GORDUNNI_DIRT_MOUND = 144064, @@ -199,12 +170,12 @@ class spell_gordunni_trap : public SpellScriptLoader void HandleDummy() { - if (Unit* caster = GetCaster()) - if (GameObject* chest = caster->SummonGameObject(GO_GORDUNNI_DIRT_MOUND, caster->GetPositionX(), caster->GetPositionY(), caster->GetPositionZ(), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0)) - { - chest->SetSpellId(GetSpellInfo()->Id); - caster->RemoveGameObject(chest, false); - } + Unit* caster = GetCaster(); + if (GameObject* chest = caster->SummonGameObject(GO_GORDUNNI_DIRT_MOUND, *caster, G3D::Quat(), 0)) + { + chest->SetSpellId(GetSpellInfo()->Id); + caster->RemoveGameObject(chest, false); + } } void Register() override @@ -225,7 +196,6 @@ class spell_gordunni_trap : public SpellScriptLoader void AddSC_feralas() { - new npc_gregan_brewspewer(); new npc_oox22fe(); new spell_gordunni_trap(); } diff --git a/src/server/scripts/Kalimdor/zone_moonglade.cpp b/src/server/scripts/Kalimdor/zone_moonglade.cpp index 99a209b5f0a..531c657e1cb 100644 --- a/src/server/scripts/Kalimdor/zone_moonglade.cpp +++ b/src/server/scripts/Kalimdor/zone_moonglade.cpp @@ -19,15 +19,14 @@ /* ScriptData SDName: Moonglade SD%Complete: 100 -SDComment: Quest support: 30, 272, 5929, 5930, 10965. Special Flight Paths for Druid class. +SDComment: Quest support: 10965 SDCategory: Moonglade EndScriptData */ /* ContentData -npc_bunthen_plainswind -npc_silva_filnaveth npc_clintar_spirit -npc_clintar_dreamwalker +npc_omen +npc_giant_spotlight EndContentData */ #include "ScriptMgr.h" @@ -42,128 +41,6 @@ EndContentData */ #include "CellImpl.h" /*###### -## npc_bunthen_plainswind -######*/ - -enum Bunthen -{ - QUEST_SEA_LION_HORDE = 30, - QUEST_SEA_LION_ALLY = 272, - TAXI_PATH_ID_ALLY = 315, - TAXI_PATH_ID_HORDE = 316 -}; - -#define GOSSIP_ITEM_THUNDER "I'd like to fly to Thunder Bluff." -#define GOSSIP_ITEM_AQ_END "Do you know where I can find Half Pendant of Aquatic Endurance?" - -class npc_bunthen_plainswind : public CreatureScript -{ -public: - npc_bunthen_plainswind() : CreatureScript("npc_bunthen_plainswind") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF + 1: - player->CLOSE_GOSSIP_MENU(); - if (player->getClass() == CLASS_DRUID && player->GetTeam() == HORDE) - player->ActivateTaxiPathTo(TAXI_PATH_ID_HORDE); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - player->SEND_GOSSIP_MENU(5373, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - player->SEND_GOSSIP_MENU(5376, creature->GetGUID()); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->getClass() != CLASS_DRUID) - player->SEND_GOSSIP_MENU(4916, creature->GetGUID()); - else if (player->GetTeam() != HORDE) - { - if (player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - player->SEND_GOSSIP_MENU(4917, creature->GetGUID()); - } - else if (player->getClass() == CLASS_DRUID && player->GetTeam() == HORDE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THUNDER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - - player->SEND_GOSSIP_MENU(4918, creature->GetGUID()); - } - return true; - } - -}; - -/*###### -## npc_silva_filnaveth -######*/ - -#define GOSSIP_ITEM_RUTHERAN "I'd like to fly to Rut'theran Village." -#define GOSSIP_ITEM_AQ_AGI "Do you know where I can find Half Pendant of Aquatic Agility?" - -class npc_silva_filnaveth : public CreatureScript -{ -public: - npc_silva_filnaveth() : CreatureScript("npc_silva_filnaveth") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF + 1: - player->CLOSE_GOSSIP_MENU(); - if (player->getClass() == CLASS_DRUID && player->GetTeam() == ALLIANCE) - player->ActivateTaxiPathTo(TAXI_PATH_ID_ALLY); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - player->SEND_GOSSIP_MENU(5374, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - player->SEND_GOSSIP_MENU(5375, creature->GetGUID()); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->getClass() != CLASS_DRUID) - player->SEND_GOSSIP_MENU(4913, creature->GetGUID()); - else if (player->GetTeam() != ALLIANCE) - { - if (player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - player->SEND_GOSSIP_MENU(4915, creature->GetGUID()); - } - else if (player->getClass() == CLASS_DRUID && player->GetTeam() == ALLIANCE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTHERAN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - if (player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - - player->SEND_GOSSIP_MENU(4914, creature->GetGUID()); - } - return true; - } - -}; - -/*###### ## npc_clintar_spirit ######*/ @@ -652,8 +529,6 @@ public: void AddSC_moonglade() { - new npc_bunthen_plainswind(); - new npc_silva_filnaveth(); new npc_clintar_spirit(); new npc_omen(); new npc_giant_spotlight(); diff --git a/src/server/scripts/Kalimdor/zone_orgrimmar.cpp b/src/server/scripts/Kalimdor/zone_orgrimmar.cpp index ac26aa1f811..9c531c1f1be 100644 --- a/src/server/scripts/Kalimdor/zone_orgrimmar.cpp +++ b/src/server/scripts/Kalimdor/zone_orgrimmar.cpp @@ -32,6 +32,9 @@ EndContentData */ #include "ScriptedCreature.h" #include "ScriptedGossip.h" #include "Player.h" +#include "Cell.h" +#include "CellImpl.h" +#include "GridNotifiers.h" /*###### ## npc_shenthul @@ -143,20 +146,30 @@ public: enum ThrallWarchief { - QUEST_6566 = 6566, - - SPELL_CHAIN_LIGHTNING = 16033, - SPELL_SHOCK = 16034 + GOSSIP_MENU_OPTION_ID_ALL = 0, + + OPTION_PLEASE_SHARE_YOUR = 3664, + OPTION_WHAT_DISCOVERIES = 3665, + OPTION_USURPER = 3666, + OPTION_WITH_ALL_DUE_RESPECT = 3667, + OPTION_I_I_DID_NOT_THINK_OF = 3668, + OPTION_I_LIVE_ONLY_TO_SERVE = 3669, + OPTION_OF_COURSE_WARCHIEF = 3670, + + GOSSIP_MEMBERS_OF_THE_HORDE = 4477, + GOSSIP_THE_SHATTERED_HAND = 5733, + GOSSIP_IT_WOULD_APPEAR_AS = 5734, + GOSSIP_THE_BROOD_MOTHER = 5735, + GOSSIP_SO_MUCH_TO_LEARN = 5736, + GOSSIP_I_DO_NOT_FAULT_YOU = 5737, + GOSSIP_NOW_PAY_ATTENTION = 5738, + + QUEST_WHAT_THE_WIND_CARRIES = 6566, + + SPELL_CHAIN_LIGHTNING = 16033, + SPELL_SHOCK = 16034 }; -#define GOSSIP_HTW "Please share your wisdom with me, Warchief." -#define GOSSIP_STW1 "What discoveries?" -#define GOSSIP_STW2 "Usurper?" -#define GOSSIP_STW3 "With all due respect, Warchief - why not allow them to be destroyed? Does this not strengthen our position?" -#define GOSSIP_STW4 "I... I did not think of it that way, Warchief." -#define GOSSIP_STW5 "I live only to serve, Warchief! My life is empty and meaningless without your guidance." -#define GOSSIP_STW6 "Of course, Warchief!" - /// @todo verify abilities/timers class npc_thrall_warchief : public CreatureScript { @@ -169,32 +182,32 @@ public: switch (action) { case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->SEND_GOSSIP_MENU(5733, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(OPTION_WHAT_DISCOVERIES, GOSSIP_MENU_OPTION_ID_ALL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + player->SEND_GOSSIP_MENU(GOSSIP_THE_SHATTERED_HAND, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->SEND_GOSSIP_MENU(5734, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(OPTION_USURPER, GOSSIP_MENU_OPTION_ID_ALL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + player->SEND_GOSSIP_MENU(GOSSIP_IT_WOULD_APPEAR_AS, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - player->SEND_GOSSIP_MENU(5735, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(OPTION_WITH_ALL_DUE_RESPECT, GOSSIP_MENU_OPTION_ID_ALL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + player->SEND_GOSSIP_MENU(GOSSIP_THE_BROOD_MOTHER, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - player->SEND_GOSSIP_MENU(5736, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(OPTION_I_I_DID_NOT_THINK_OF, GOSSIP_MENU_OPTION_ID_ALL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + player->SEND_GOSSIP_MENU(GOSSIP_SO_MUCH_TO_LEARN, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF+5: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); - player->SEND_GOSSIP_MENU(5737, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(OPTION_I_LIVE_ONLY_TO_SERVE, GOSSIP_MENU_OPTION_ID_ALL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6); + player->SEND_GOSSIP_MENU(GOSSIP_I_DO_NOT_FAULT_YOU, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF+6: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_STW6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); - player->SEND_GOSSIP_MENU(5738, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(OPTION_OF_COURSE_WARCHIEF, GOSSIP_MENU_OPTION_ID_ALL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7); + player->SEND_GOSSIP_MENU(GOSSIP_NOW_PAY_ATTENTION, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF+7: player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(QUEST_6566); + player->AreaExploredOrEventHappens(QUEST_WHAT_THE_WIND_CARRIES); break; } return true; @@ -205,10 +218,10 @@ public: if (creature->IsQuestGiver()) player->PrepareQuestMenu(creature->GetGUID()); - if (player->GetQuestStatus(QUEST_6566) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HTW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if (player->GetQuestStatus(QUEST_WHAT_THE_WIND_CARRIES) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM_DB(OPTION_PLEASE_SHARE_YOUR, GOSSIP_MENU_OPTION_ID_ALL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + player->SEND_GOSSIP_MENU(GOSSIP_MEMBERS_OF_THE_HORDE, creature->GetGUID()); return true; } @@ -263,8 +276,555 @@ public: }; +/* --------- Herald of War ------------- */ +enum CitizenEntries +{ + NPC_GRYSHKA = 31433, + NPC_OLVIA = 31425, + NPC_SANA = 31429, + NPC_FELIKA = 31427, + NPC_THATHUNG = 31430, + NPC_KAJA = 31423 +}; + +enum SceneEvents +{ + EVENT_SCENE_1 = 1, + EVENT_SCENE_2 = 2, + EVENT_SCENE_3 = 3, + EVENT_SCENE_4 = 4, + EVENT_SCENE_5 = 5, + EVENT_SCENE_6 = 6, + EVENT_SCENE_7 = 7, + EVENT_SCENE_8 = 8, + EVENT_SCENE_9 = 9, + EVENT_SCENE_10 = 10, + EVENT_SCENE_11 = 11, + EVENT_SCENE_12 = 12, + EVENT_SCENE_13 = 13, + EVENT_RESET = 14 +}; + +enum CitizenTalk +{ + SAY_GRYSHKA_1 = 0, // When can we reopen our shops? I'm losing gold here! + SAY_GRYSHKA_2 = 1, // "This is an outrage!" + SAY_OLVIA_1 = 0, // Where is the Warchief? + SAY_OLVIA_2 = 1, // What are all these Forsaken doing here? + SAY_FELIKA_1 = 0, // What is going on? + SAY_FELIKA_2 = 1, // This is an outrage! + SAY_THATHUNG = 0, // What is going on? + SAY_KAJA = 0, // Why is Thrall allowing this to happen to our city? + SAY_SANA = 0, // We demand answers! + SAY_RUNTHAK_1 = 0, // SILENCE! + SAY_RUNTHAK_2 = 1, // We are on the brink of all out war with the Alliance! + SAY_RUNTHAK_3 = 2, // Tragic events have unfolded in Northrend. The Warchief is doing all that he can to keep us safe. + SAY_RUNTHAK_4 = 3 // All services and shops are to remain closed until further notice! That is all! +}; + +class npc_overlord_runthak_orgrimmar : public CreatureScript +{ +public: + npc_overlord_runthak_orgrimmar() : CreatureScript("npc_overlord_runthak_orgrimmar") { } + + struct npc_overlord_runthak_orgrimmarAI : public ScriptedAI + { + npc_overlord_runthak_orgrimmarAI(Creature* creature) : ScriptedAI(creature) + { + inProgress = false; + } + + void Reset() override + { + inProgress = false; + me->GetMotionMaster()->MovePath(me->GetSpawnId() * 10, true); + events.Reset(); + } + + void MoveInLineOfSight(Unit* who) override + { + if (who->GetTypeId() == TYPEID_PLAYER && who->IsWithinDist(me, 20.0f) && !inProgress) + { + inProgress = true; + events.ScheduleEvent(EVENT_SCENE_1, 2000); + } + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventID = events.ExecuteEvent()) + { + switch (eventID) + { + case EVENT_SCENE_1: + GetCitizenGuids(); + me->GetMotionMaster()->MoveIdle(); + if (Creature* gryshka = ObjectAccessor::GetCreature(*me, gryshkaGUID)) + { + me->SetFacingTo(me->GetAngle(gryshka->GetPositionX(), gryshka->GetPositionY())); + gryshka->AI()->Talk(SAY_GRYSHKA_1); + } + events.ScheduleEvent(EVENT_SCENE_2, 4500); + break; + case EVENT_SCENE_2: + if (Creature* olvia = ObjectAccessor::GetCreature(*me, olviaGUID)) + olvia->AI()->Talk(SAY_OLVIA_1); + events.ScheduleEvent(EVENT_SCENE_3, 4500); + break; + case EVENT_SCENE_3: + if (Creature* felika = ObjectAccessor::GetCreature(*me, felikaGUID)) + felika->AI()->Talk(SAY_FELIKA_1); + events.ScheduleEvent(EVENT_SCENE_4, 4500); + break; + case EVENT_SCENE_4: + if (Creature* thathung = ObjectAccessor::GetCreature(*me, thungGUID)) + thathung->AI()->Talk(SAY_THATHUNG); + events.ScheduleEvent(EVENT_SCENE_5, 4500); + break; + case EVENT_SCENE_5: + if (Creature* sana = ObjectAccessor::GetCreature(*me, sanaGUID)) + sana->AI()->Talk(SAY_SANA); + events.ScheduleEvent(EVENT_SCENE_6, 4500); + break; + case EVENT_SCENE_6: + if (Creature* gryshka = ObjectAccessor::GetCreature(*me, gryshkaGUID)) + gryshka->AI()->Talk(SAY_GRYSHKA_2); + events.ScheduleEvent(EVENT_SCENE_7, 4500); + break; + case EVENT_SCENE_7: + if (Creature* kaja = ObjectAccessor::GetCreature(*me, kajaGUID)) + kaja->AI()->Talk(SAY_KAJA); + events.ScheduleEvent(EVENT_SCENE_8, 4500); + break; + case EVENT_SCENE_8: + if (Creature* felika = ObjectAccessor::GetCreature(*me, felikaGUID)) + felika->AI()->Talk(SAY_FELIKA_2); + events.ScheduleEvent(EVENT_SCENE_9, 4500); + break; + case EVENT_SCENE_9: + if (Creature* olvia = ObjectAccessor::GetCreature(*me, olviaGUID)) + olvia->AI()->Talk(SAY_OLVIA_2); + events.ScheduleEvent(EVENT_SCENE_10, 4500); + break; + case EVENT_SCENE_10: + Talk(SAY_RUNTHAK_1); + events.ScheduleEvent(EVENT_SCENE_11, 1500); + break; + case EVENT_SCENE_11: + Talk(SAY_RUNTHAK_2); + events.ScheduleEvent(EVENT_SCENE_12, 4500); + break; + case EVENT_SCENE_12: + Talk(SAY_RUNTHAK_3); + events.ScheduleEvent(EVENT_SCENE_13, 4500); + break; + case EVENT_SCENE_13: + Talk(SAY_RUNTHAK_4); + events.ScheduleEvent(EVENT_RESET, 25000); + break; + case EVENT_RESET: + Reset(); + break; + default: + break; + } + } + } + + void GetCitizenGuids() + { + // if one GUID is empty it means all the others are empty as well so we should store them + // otherwise do not call for grid search since someone else already activated event once before and guids are stored + if (gryshkaGUID.IsEmpty()) + { + std::list<Unit*> citizenList; + Trinity::AnyFriendlyUnitInObjectRangeCheck checker(me, me, 25.0f); + Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(me, citizenList, checker); + me->VisitNearbyObject(20.0f, searcher); + for (Unit* target : citizenList) + { + switch (target->GetEntry()) + { + case NPC_GRYSHKA: + gryshkaGUID = target->GetGUID(); + break; + case NPC_OLVIA: + olviaGUID = target->GetGUID(); + break; + case NPC_SANA: + sanaGUID = target->GetGUID(); + break; + case NPC_FELIKA: + felikaGUID = target->GetGUID(); + break; + case NPC_THATHUNG: + thungGUID = target->GetGUID(); + break; + case NPC_KAJA: + kajaGUID = target->GetGUID(); + break; + default: + break; + } + } + } + } + + private: + EventMap events; + bool inProgress; + ObjectGuid gryshkaGUID; + ObjectGuid olviaGUID; + ObjectGuid sanaGUID; + ObjectGuid felikaGUID; + ObjectGuid thungGUID; + ObjectGuid kajaGUID; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_overlord_runthak_orgrimmarAI(creature); + } +}; + +// Phased out thrall during herald of war chain quest +enum HeraldEntries +{ + NPC_PORTAL_STORMWIND = 31640, + NPC_JAINA_PROUDMOORE = 31418, + NPC_BANSHEE_SYLVANAS = 31419, + NPC_KORKRON_GUARD = 31417, + NPC_THRALL_HERALD = 31412, + + GO_PORTAL_UNDERCITY = 193425 +}; + +enum HeraldMisc +{ + QUEST_HERALD_OF_WAR = 13257, + GUARDS_SIZE = 4 +}; + +enum HeraldActions +{ + ACTION_START_SCENE = 0 +}; + +enum HeraldSpell +{ + SPELL_JAINA_SPAWNIN = 55761 +}; + +enum HeraldTalk +{ + SAY_THRALL_0 = 0, // Kor'kron, stand down! + SAY_THRALL_1 = 1, // Jaina... + SAY_THRALL_2 = 2, // Jaina, what happened at the Wrathgate. It was a betrayal from within... + SAY_THRALL_3 = 3, // The Horde has lost the Undercity. + SAY_THRALL_4 = 4, // We now prepare to lay siege to the city and bring the perpetrators of this unforgivable crime to justice. + SAY_THRALL_5 = 5, // If we are forced into a conflict, the Lich King will destroy our divided forces in Northrend. + SAY_THRALL_6 = 6, // We will make this right, Jaina. Tell your king all that you have learned here. + SAY_THRALL_7 = 7, // Kor'kron, prepare transport to the Undercity. + + SAY_SYLVANAS_0 = 0, // Lady Proudmoore, the Warchief speaks the truth. This subterfuge was set in motion by Varimathras and Grand Apothecary Putress. It was not the Horde's doing. + SAY_SYLVANAS_1 = 1, // As the combined Horde and Alliance forces began their assault upon the Wrath Gate, an uprising broke out in the Undercity. Varimathras and hordes of his demonic brethren attacked. Hundreds of my people were slain in the coup. I barely managed to escape with my life. + + SAY_JAINA_0 = 0, // Thrall, what has happened? The King is preparing for war... + SAY_JAINA_1 = 1, // I will deliver this information to King Wrynn, Thrall, but... + SAY_JAINA_2 = 2, // Bolvar was like a brother to him. In the King's absence, Bolvar kept the Alliance united. He found strength for our people in our darkest hours. He watched over Anduin, raising him as his own. + SAY_JAINA_3 = 3, // I fear that the rage will consume him, Thrall. I remain hopeful that reason will prevail, but we must prepare for the worst... for war. + SAY_JAINA_4 = 4 // Farewell, Warchief. I pray that the next time we meet it will be as allies. +}; + +enum HeraldEvents +{ + EVENT_HERALD_SCENE1 = 1, + EVENT_HERALD_SCENE2 = 2, + EVENT_HERALD_SCENE3 = 3, + EVENT_HERALD_SCENE4 = 4, + EVENT_HERALD_SCENE5 = 5, + EVENT_HERALD_SCENE6 = 6, + EVENT_HERALD_SCENE7 = 7, + EVENT_HERALD_SCENE8 = 8, + EVENT_HERALD_SCENE9 = 9, + EVENT_HERALD_SCENE10 = 10, + EVENT_HERALD_SCENE11 = 11, + EVENT_HERALD_SCENE12 = 12, + EVENT_HERALD_SCENE13 = 13, + EVENT_HERALD_SCENE14 = 14, + EVENT_HERALD_SCENE15 = 15, + EVENT_HERALD_RESET = 16 +}; + +Position const GuardsSpawnPosition[GUARDS_SIZE] = +{ + { 1909.39f, -4144.21f, 40.6368f, 0.042239f }, + { 1910.73f, -4155.26f, 40.6316f, 0.615577f }, + { 1934.01f, -4141.40f, 40.6375f, 3.61109f }, + { 1931.11f, -4156.38f, 40.6130f, 2.19737f } +}; + +Position const GuardsMovePosition[GUARDS_SIZE] = +{ + { 1917.461670f, -4147.514160f, 40.636799f, 5.89346f }, + { 1916.181274f, -4152.295898f, 40.629120f, 0.497757f }, + { 1926.435425f, -4146.397461f, 40.618534f, 3.846709f }, + { 1926.519165f, -4153.216797f, 40.614975f, 2.570434f } +}; + +Position const MiscMovePositions[3] = +{ + { 1921.719604f, -4143.051270f, 40.623356f, 1.657789f }, // jaina move + { 1921.151855f, -4139.343750f, 40.583084f, 4.732627f }, // thrall move + { 1918.732422f, -4139.619629f, 40.607685f, 4.803311f } // sylvanas move +}; + +Position const PortalSpawnPosition = { 1921.752441f, -4151.148438f, 40.623848f, 1.714324f }; + +class npc_thrall_herald_of_war : public CreatureScript +{ +public: + npc_thrall_herald_of_war() : CreatureScript("npc_thrall_herald_of_war") { } + + struct npc_thrall_herald_of_warAI : public ScriptedAI + { + npc_thrall_herald_of_warAI(Creature* creature) : ScriptedAI(creature) + { + spawnedGuards = false; + sceneInProgress = false; + } + + void Reset() override + { + events.Reset(); + me->GetMotionMaster()->MovePath(me->GetSpawnId() * 10, true); + sceneInProgress = false; + + if (!spawnedGuards) + { + spawnedGuards = true; + for (uint8 i = 0; i < GUARDS_SIZE; i++) + { + if (Creature* korkronGuard = me->SummonCreature(NPC_KORKRON_GUARD, GuardsSpawnPosition[i])) + guardsGUIDs[i] = korkronGuard->GetGUID(); + } + } + } + + void MovementInform(uint32 type, uint32 pointId) override + { + if (type != POINT_MOTION_TYPE) + return; + + if (pointId == 2) + me->GetMotionMaster()->MovePath(me->GetSpawnId() * 10, true); + } + + void DoAction(int32 actionId) override + { + if (actionId == ACTION_START_SCENE && !sceneInProgress) + { + me->GetMotionMaster()->MoveIdle(); + sceneInProgress = true; + + if (Creature* jaina = me->SummonCreature(NPC_JAINA_PROUDMOORE, PortalSpawnPosition)) + { + me->SetFacingTo(me->GetAngle(jaina->GetPositionX(), jaina->GetPositionY())); + jainaGUID = jaina->GetGUID(); + jaina->CastSpell(jaina, SPELL_JAINA_SPAWNIN); + } + + if (Creature* stormwindPortal = me->SummonCreature(NPC_PORTAL_STORMWIND, PortalSpawnPosition)) + { + stormwindPortal->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + stormwindPortalGUID = stormwindPortal->GetGUID(); + } + + for (uint8 i = 0; i < GUARDS_SIZE; i++) + { + if (Creature* guards = ObjectAccessor::GetCreature(*me, guardsGUIDs[i])) + { + guards->SetWalk(false); + guards->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); + guards->GetMotionMaster()->MovePoint(1, GuardsMovePosition[i]); + } + } + + if (Creature* sylvanas = me->FindNearestCreature(NPC_BANSHEE_SYLVANAS, 25.0f)) + sylvanasGUID = sylvanas->GetGUID(); + + events.ScheduleEvent(EVENT_HERALD_SCENE1, 4000); + } + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventID = events.ExecuteEvent()) + { + switch (eventID) + { + case EVENT_HERALD_SCENE1: + Talk(SAY_THRALL_0); + me->GetMotionMaster()->MovePoint(1, MiscMovePositions[1]); + if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID)) + { + jaina->SetWalk(true); + jaina->GetMotionMaster()->MovePoint(1, MiscMovePositions[0]); + } + + for (uint8 i = 0; i < GUARDS_SIZE; i++) + { + if (Creature* guard = ObjectAccessor::GetCreature(*me, guardsGUIDs[i])) + { + guard->GetMotionMaster()->MoveTargetedHome(); + guard->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + } + } + events.ScheduleEvent(EVENT_HERALD_SCENE2, 3000); + break; + case EVENT_HERALD_SCENE2: + Talk(SAY_THRALL_1); + if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID)) + me->SetFacingTo(me->GetAngle(jaina->GetPositionX(), jaina->GetPositionY())); + events.ScheduleEvent(EVENT_HERALD_SCENE3, 3500); + break; + case EVENT_HERALD_SCENE3: + if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID)) + jaina->AI()->Talk(SAY_JAINA_0); + events.ScheduleEvent(EVENT_HERALD_SCENE4, 5500); + break; + case EVENT_HERALD_SCENE4: + Talk(SAY_THRALL_2); + if (Creature* sylvanas = ObjectAccessor::GetCreature(*me, sylvanasGUID)) + { + sylvanas->SetStandState(UNIT_STAND_STATE_STAND); + sylvanas->SetWalk(true); + sylvanas->GetMotionMaster()->MovePoint(1, MiscMovePositions[2]); + } + events.ScheduleEvent(EVENT_HERALD_SCENE5, 6500); + break; + case EVENT_HERALD_SCENE5: + if (Creature* sylvanas = ObjectAccessor::GetCreature(*me, sylvanasGUID)) + sylvanas->AI()->Talk(SAY_SYLVANAS_0); + events.ScheduleEvent(EVENT_HERALD_SCENE6, 10000); + break; + case EVENT_HERALD_SCENE6: + if (Creature* sylvanas = ObjectAccessor::GetCreature(*me, sylvanasGUID)) + sylvanas->AI()->Talk(SAY_SYLVANAS_1); + events.ScheduleEvent(EVENT_HERALD_SCENE7, 20000); + break; + case EVENT_HERALD_SCENE7: + Talk(SAY_THRALL_3); + events.ScheduleEvent(EVENT_HERALD_SCENE8, 4500); + break; + case EVENT_HERALD_SCENE8: + Talk(SAY_THRALL_4); + events.ScheduleEvent(EVENT_HERALD_SCENE9, 10000); + break; + case EVENT_HERALD_SCENE9: + Talk(SAY_THRALL_5); + events.ScheduleEvent(EVENT_HERALD_SCENE10, 8000); + break; + case EVENT_HERALD_SCENE10: + Talk(SAY_THRALL_6); + events.ScheduleEvent(EVENT_HERALD_SCENE11, 9000); + break; + case EVENT_HERALD_SCENE11: + if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID)) + jaina->AI()->Talk(SAY_JAINA_1); + events.ScheduleEvent(EVENT_HERALD_SCENE12, 6000); + break; + case EVENT_HERALD_SCENE12: + if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID)) + jaina->AI()->Talk(SAY_JAINA_2); + events.ScheduleEvent(EVENT_HERALD_SCENE13, 14000); + break; + case EVENT_HERALD_SCENE13: + if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID)) + jaina->AI()->Talk(SAY_JAINA_3); + events.ScheduleEvent(EVENT_HERALD_SCENE14, 10000); + break; + case EVENT_HERALD_SCENE14: + if (Creature* jaina = ObjectAccessor::GetCreature(*me, jainaGUID)) + { + jaina->AI()->Talk(SAY_JAINA_4); + jaina->SetWalk(true); + jaina->GetMotionMaster()->MovePoint(2, jaina->GetHomePosition()); + jaina->DespawnOrUnsummon(5000); + } + events.ScheduleEvent(EVENT_HERALD_SCENE15, 7000); + break; + case EVENT_HERALD_SCENE15: + { + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(2, me->GetHomePosition()); + Talk(SAY_THRALL_7); + + if (Creature* sylvanas = ObjectAccessor::GetCreature(*me, sylvanasGUID)) + { + sylvanas->SetWalk(true); + sylvanas->GetMotionMaster()->MovePoint(2, sylvanas->GetHomePosition()); + } + + if (Creature* portal = ObjectAccessor::GetCreature(*me, stormwindPortalGUID)) + portal->DespawnOrUnsummon(); + + events.ScheduleEvent(EVENT_HERALD_RESET, 60000); + break; + } + case EVENT_HERALD_RESET: + Reset(); + break; + default: + break; + } + } + } + + private: + EventMap events; + ObjectGuid guardsGUIDs[GUARDS_SIZE]; + ObjectGuid jainaGUID; + ObjectGuid sylvanasGUID; + ObjectGuid stormwindPortalGUID; + bool spawnedGuards; + bool sceneInProgress; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_thrall_herald_of_warAI(creature); + } +}; + +class areatrigger_orgrimmar_herald_of_war : public AreaTriggerScript +{ +public: + areatrigger_orgrimmar_herald_of_war() : AreaTriggerScript("areatrigger_orgrimmar_herald_of_war") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override + { + if (player->IsAlive() && player->GetQuestStatus(QUEST_HERALD_OF_WAR) == QUEST_STATUS_COMPLETE) + { + if (Creature* thrall = player->FindNearestCreature(NPC_THRALL_HERALD, 50.0f)) + { + thrall->AI()->DoAction(ACTION_START_SCENE); + return true; + } + } + return false; + } +}; + void AddSC_orgrimmar() { new npc_shenthul(); new npc_thrall_warchief(); + new npc_overlord_runthak_orgrimmar(); + new npc_thrall_herald_of_war(); + new areatrigger_orgrimmar_herald_of_war(); } diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp index cc285ab991e..db7bd62c5d1 100644 --- a/src/server/scripts/Kalimdor/zone_silithus.cpp +++ b/src/server/scripts/Kalimdor/zone_silithus.cpp @@ -19,13 +19,20 @@ /* ScriptData SDName: Silithus SD%Complete: 100 -SDComment: Quest support: 8304, 8507. +SDComment: Quest support: 8348,8352,8361,8519 SDCategory: Silithus EndScriptData */ /* ContentData -npcs_rutgar_and_frankal -quest_a_pawn_on_the_eternal_pawn +A Pawn on the Eternal Board - creatures, gameobjects and defines +quest_a_pawn_on_the_eternal_board +npc_qiraj_war_spawn : Adds that are summoned in the Qiraj gates battle. +npc_anachronos_the_ancient : Creature that controls the event. +npc_anachronos_quest_trigger: controls the spawning of the BG War mobs. +go_crystalline_tear : GameObject that begins the event and hands out quest +TO DO: get correct spell IDs and timings for spells cast upon dragon transformations +TO DO: Dragons should use the HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF) after transformation, + but for some unknown reason it doesn't work. EndContentData */ #include "ScriptMgr.h" @@ -34,195 +41,66 @@ EndContentData */ #include "Group.h" #include "Player.h" -/*### -## npcs_rutgar_and_frankal -###*/ - -//gossip item text best guess -#define GOSSIP_ITEM1 "I seek information about Natalia" - -#define GOSSIP_ITEM2 "That sounds dangerous!" -#define GOSSIP_ITEM3 "What did you do?" -#define GOSSIP_ITEM4 "Who?" -#define GOSSIP_ITEM5 "Women do that. What did she demand?" -#define GOSSIP_ITEM6 "What do you mean?" -#define GOSSIP_ITEM7 "What happened next?" - -#define GOSSIP_ITEM11 "Yes, please continue" -#define GOSSIP_ITEM12 "What language?" -#define GOSSIP_ITEM13 "The Priestess attacked you?!" -#define GOSSIP_ITEM14 "I should ask the monkey about this" -#define GOSSIP_ITEM15 "Then what..." - -enum RutgarAndFrankal //trigger creatures to kill -{ - TRIGGER_FRANKAL = 15221, - TRIGGER_RUTGAR = 15222 -}; - -class npcs_rutgar_and_frankal : public CreatureScript -{ -public: - npcs_rutgar_and_frankal() : CreatureScript("npcs_rutgar_and_frankal") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(7755, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(7756, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(7757, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - player->SEND_GOSSIP_MENU(7758, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(7759, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 5: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - player->SEND_GOSSIP_MENU(7760, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 6: - player->SEND_GOSSIP_MENU(7761, creature->GetGUID()); - //'kill' our trigger to update quest status - player->KilledMonsterCredit(TRIGGER_RUTGAR); - break; - - case GOSSIP_ACTION_INFO_DEF + 9: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - player->SEND_GOSSIP_MENU(7762, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 10: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - player->SEND_GOSSIP_MENU(7763, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 11: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); - player->SEND_GOSSIP_MENU(7764, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 12: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); - player->SEND_GOSSIP_MENU(7765, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 13: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); - player->SEND_GOSSIP_MENU(7766, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 14: - player->SEND_GOSSIP_MENU(7767, creature->GetGUID()); - //'kill' our trigger to update quest status - player->KilledMonsterCredit(TRIGGER_FRANKAL); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(8304) == QUEST_STATUS_INCOMPLETE && - creature->GetEntry() == 15170 && - !player->GetReqKillOrCastCurrentCount(8304, TRIGGER_RUTGAR)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - if (player->GetQuestStatus(8304) == QUEST_STATUS_INCOMPLETE && - creature->GetEntry() == 15171 && - player->GetReqKillOrCastCurrentCount(8304, TRIGGER_RUTGAR)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9); - - player->SEND_GOSSIP_MENU(7754, creature->GetGUID()); - - return true; - } - -}; - -/*#### -# quest_a_pawn_on_the_eternal_board (Defines) -####*/ -enum EternalBoard -{ - QUEST_A_PAWN_ON_THE_ETERNAL_BOARD = 8519, - - FACTION_HOSTILE = 14, - FACTION_FRIENDLY = 35, - - C_ANACHRONOS = 15381, - C_FANDRAL_STAGHELM = 15382, - C_ARYGOS = 15380, - C_MERITHRA = 15378, - C_CAELESTRASZ = 15379, - - ANACHRONOS_SAY_1 = 0, - ANACHRONOS_SAY_2 = 1, - ANACHRONOS_SAY_3 = 2, - ANACHRONOS_SAY_4 = 3, - ANACHRONOS_SAY_5 = 4, - ANACHRONOS_SAY_6 = 5, - ANACHRONOS_SAY_7 = 6, - ANACHRONOS_SAY_8 = 7, - ANACHRONOS_SAY_9 = 8, - ANACHRONOS_SAY_10 = 9, - ANACHRONOS_EMOTE_1 = 10, - ANACHRONOS_EMOTE_2 = 11, - ANACHRONOS_EMOTE_3 = 12, - - FANDRAL_SAY_1 = 0, - FANDRAL_SAY_2 = 1, - FANDRAL_SAY_3 = 2, - FANDRAL_SAY_4 = 3, - FANDRAL_SAY_5 = 4, - FANDRAL_SAY_6 = 5, - FANDRAL_EMOTE_1 = 6, - FANDRAL_EMOTE_2 = 7, - - CAELESTRASZ_SAY_1 = 0, - CAELESTRASZ_SAY_2 = 1, - CAELESTRASZ_YELL_1 = 2, - - ARYGOS_SAY_1 = 0, - ARYGOS_YELL_1 = 1, - ARYGOS_EMOTE_1 = 2, - - MERITHRA_SAY_1 = 0, - MERITHRA_SAY_2 = 1, - MERITHRA_YELL_1 = 2, - MERITHRA_EMOTE_1 = 3, - - GO_GATE_OF_AHN_QIRAJ = 176146, - GO_GLYPH_OF_AHN_QIRAJ = 176148, - GO_ROOTS_OF_AHN_QIRAJ = 176147 -}; /*##### # Quest: A Pawn on the Eternal Board #####*/ -/* ContentData -A Pawn on the Eternal Board - creatures, gameobjects and defines -npc_qiraj_war_spawn : Adds that are summoned in the Qiraj gates battle. -npc_anachronos_the_ancient : Creature that controls the event. -npc_anachronos_quest_trigger: controls the spawning of the BG War mobs. -go_crystalline_tear : GameObject that begins the event and hands out quest -TO DO: get correct spell IDs and timings for spells cast upon dragon transformations -TO DO: Dragons should use the HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF) after transformation, but for some unknown reason it doesnt work. -EndContentData */ - -#define EVENT_AREA_RADIUS 65 //65yds -#define EVENT_COOLDOWN 500000 //in ms. appear after event completed or failed (should be = Adds despawn time) +enum EternalBoard +{ + QUEST_A_PAWN_ON_THE_ETERNAL_BOARD = 8519, + + FACTION_HOSTILE = 14, + FACTION_FRIENDLY = 35, + + EVENT_AREA_RADIUS = 65, // 65yds + EVENT_COOLDOWN = 500000, // in ms. appears after event completed or failed (should be = Adds despawn time) + + NPC_ANACHRONOS = 15381, + NPC_FANDRAL_STAGHELM = 15382, + NPC_ARYGOS = 15380, + NPC_MERITHRA_OF_THE_DREAM = 15378, + NPC_CAELESTRASZ = 15379, + + ANACHRONOS_SAY_1 = 0, + ANACHRONOS_SAY_2 = 1, + ANACHRONOS_SAY_3 = 2, + ANACHRONOS_SAY_4 = 3, + ANACHRONOS_SAY_5 = 4, + ANACHRONOS_SAY_6 = 5, + ANACHRONOS_SAY_7 = 6, + ANACHRONOS_SAY_8 = 7, + ANACHRONOS_SAY_9 = 8, + ANACHRONOS_SAY_10 = 9, + ANACHRONOS_EMOTE_1 = 10, + ANACHRONOS_EMOTE_2 = 11, + ANACHRONOS_EMOTE_3 = 12, + + FANDRAL_SAY_1 = 0, + FANDRAL_SAY_2 = 1, + FANDRAL_SAY_3 = 2, + FANDRAL_SAY_4 = 3, + FANDRAL_SAY_5 = 4, + FANDRAL_SAY_6 = 5, + FANDRAL_EMOTE_1 = 6, + FANDRAL_EMOTE_2 = 7, + + CAELESTRASZ_SAY_1 = 0, + CAELESTRASZ_SAY_2 = 1, + CAELESTRASZ_YELL_1 = 2, + + ARYGOS_SAY_1 = 0, + ARYGOS_YELL_1 = 1, + ARYGOS_EMOTE_1 = 2, + + MERITHRA_SAY_1 = 0, + MERITHRA_SAY_2 = 1, + MERITHRA_YELL_1 = 2, + MERITHRA_EMOTE_1 = 3, + + GO_GATE_OF_AHN_QIRAJ = 176146, + GO_GLYPH_OF_AHN_QIRAJ = 176148, + GO_ROOTS_OF_AHN_QIRAJ = 176147 +}; struct QuestCinematic { @@ -233,59 +111,59 @@ struct QuestCinematic // Creature 0 - Anachronos, 1 - Fandral, 2 - Arygos, 3 - Merithra, 4 - Caelestrasz static QuestCinematic EventAnim[]= { - {ANACHRONOS_SAY_1, 0, 2000}, - {FANDRAL_SAY_1, 1, 4000}, - {MERITHRA_EMOTE_1, 3, 500}, - {MERITHRA_SAY_1, 3, 500}, - {ARYGOS_EMOTE_1, 2, 2000}, + {ANACHRONOS_SAY_1, 0, 2000}, + {FANDRAL_SAY_1, 1, 4000}, + {MERITHRA_EMOTE_1, 3, 500}, + {MERITHRA_SAY_1, 3, 500}, + {ARYGOS_EMOTE_1, 2, 2000}, {CAELESTRASZ_SAY_1, 4, 8000}, - {MERITHRA_SAY_2, 3, 6000}, + {MERITHRA_SAY_2, 3, 6000}, {0, 3, 2000}, - {MERITHRA_YELL_1, 3, 2500}, - {0, 3, 3000}, //Morph - {0, 3, 4000}, //EmoteLiftoff - {0, 3, 4000}, // spell - {0, 3, 1250}, //fly - {0, 3, 250}, //remove flags + {MERITHRA_YELL_1, 3, 2500}, + {0, 3, 3000}, //Morph + {0, 3, 4000}, //EmoteLiftoff + {0, 3, 4000}, // spell + {0, 3, 1250}, //fly + {0, 3, 250}, //remove flags {ARYGOS_SAY_1, 2, 3000}, {0, 3, 2000}, {ARYGOS_YELL_1, 2, 3000}, - {0, 3, 3000}, //Morph - {0, 3, 4000}, //EmoteLiftoff - {0, 3, 4000}, // spell - {0, 3, 1000}, //fly - {0, 3, 1000}, //remove flags + {0, 3, 3000}, //Morph + {0, 3, 4000}, //EmoteLiftoff + {0, 3, 4000}, // spell + {0, 3, 1000}, //fly + {0, 3, 1000}, //remove flags {CAELESTRASZ_SAY_2, 4, 5000}, {0, 3, 3000}, {CAELESTRASZ_YELL_1, 4, 3000}, - {0, 3, 3000}, //Morph - {0, 3, 4000}, //EmoteLiftoff - {0, 3, 2500}, // spell + {0, 3, 3000}, //Morph + {0, 3, 4000}, //EmoteLiftoff + {0, 3, 2500}, // spell {ANACHRONOS_SAY_2, 0, 2000}, - {0, 3, 250}, //fly - {0, 3, 25}, //remove flags + {0, 3, 250}, //fly + {0, 3, 25}, //remove flags {FANDRAL_SAY_2, 1, 3000}, - {ANACHRONOS_SAY_3, 0, 10000}, //Both run through the armies - {0, 3, 2000}, // Sands will stop - {0, 3, 8000}, // Summon Gate + {ANACHRONOS_SAY_3, 0, 10000}, //Both run through the armies + {0, 3, 2000}, // Sands will stop + {0, 3, 8000}, // Summon Gate {ANACHRONOS_SAY_4, 0, 4000}, - {0, 0, 2000}, //spell 1-> Arcane cosmetic (Mobs freeze) - {0, 0, 5000}, //Spell 2-> Arcane long cosmetic (barrier appears) (Barrier -> Glyphs) - {0, 0, 7000}, //BarrieR - {0, 0, 4000}, //Glyphs + {0, 0, 2000}, //spell 1-> Arcane cosmetic (Mobs freeze) + {0, 0, 5000}, //Spell 2-> Arcane long cosmetic (barrier appears) (Barrier -> Glyphs) + {0, 0, 7000}, //BarrieR + {0, 0, 4000}, //Glyphs {ANACHRONOS_SAY_5, 0, 2000}, - {0, 0, 4000}, // Roots - {FANDRAL_SAY_3, 1, 3000}, //Root Text - {FANDRAL_EMOTE_1, 1, 3000}, //falls knee + {0, 0, 4000}, // Roots + {FANDRAL_SAY_3, 1, 3000}, //Root Text + {FANDRAL_EMOTE_1, 1, 3000}, //falls knee {ANACHRONOS_SAY_6, 0, 3000}, {ANACHRONOS_SAY_7, 0, 3000}, {ANACHRONOS_SAY_8, 0, 8000}, - {ANACHRONOS_EMOTE_1, 0, 1000}, //Give Scepter + {ANACHRONOS_EMOTE_1, 0, 1000}, //Give Scepter {FANDRAL_SAY_4, 1, 3000}, - {FANDRAL_SAY_5, 1, 3000}, //->Equip hammer~Scepter, throw it at door - {FANDRAL_EMOTE_2, 1, 3000}, //Throw hammer at door. + {FANDRAL_SAY_5, 1, 3000}, //->Equip hammer~Scepter, throw it at door + {FANDRAL_EMOTE_2, 1, 3000}, //Throw hammer at door. {ANACHRONOS_SAY_9, 0, 3000}, - {FANDRAL_SAY_6, 1, 3000}, //fandral goes away + {FANDRAL_SAY_6, 1, 3000}, //fandral goes away {ANACHRONOS_EMOTE_2, 0, 3000}, {ANACHRONOS_EMOTE_3, 0, 3000}, {0, 0, 2000}, @@ -348,30 +226,30 @@ Position const SpawnLocation[] = {-8078.0f, 1518.0f, 2.61f, 3.141592f}, //Kaldorei Infantry {-8082.0f, 1516.0f, 2.61f, 3.141592f}, //Kaldorei Infantry - {-8088.0f, 1510.0f, 2.61f, 0.0f}, //Anubisath Conqueror - {-8084.0f, 1520.0f, 2.61f, 0.0f}, //Anubisath Conqueror - {-8088.0f, 1530.0f, 2.61f, 0.0f}, //Anubisath Conqueror - - {-8080.0f, 1513.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8082.0f, 1523.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8085.0f, 1518.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8082.0f, 1516.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8085.0f, 1520.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8080.0f, 1528.0f, 2.61f, 0.0f}, //Qiraj Wasp - - {-8082.0f, 1513.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8079.0f, 1523.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8080.0f, 1531.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8079.0f, 1516.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8082.0f, 1520.0f, 2.61f, 0.0f}, //Qiraj Wasp - {-8080.0f, 1518.0f, 2.61f, 0.0f}, //Qiraj Wasp - - {-8081.0f, 1514.0f, 2.61f, 0.0f}, //Qiraj Tank - {-8081.0f, 1520.0f, 2.61f, 0.0f}, //Qiraj Tank - {-8081.0f, 1526.0f, 2.61f, 0.0f}, //Qiraj Tank - {-8081.0f, 1512.0f, 2.61f, 0.0f}, //Qiraj Tank - {-8082.0f, 1520.0f, 2.61f, 0.0f}, //Qiraj Tank - {-8081.0f, 1528.0f, 2.61f, 0.0f}, //Qiraj Tank + {-8088.0f, 1510.0f, 2.61f, 0.0f}, //Anubisath Conqueror + {-8084.0f, 1520.0f, 2.61f, 0.0f}, //Anubisath Conqueror + {-8088.0f, 1530.0f, 2.61f, 0.0f}, //Anubisath Conqueror + + {-8080.0f, 1513.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8082.0f, 1523.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8085.0f, 1518.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8082.0f, 1516.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8085.0f, 1520.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8080.0f, 1528.0f, 2.61f, 0.0f}, //Qiraj Wasp + + {-8082.0f, 1513.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8079.0f, 1523.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8080.0f, 1531.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8079.0f, 1516.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8082.0f, 1520.0f, 2.61f, 0.0f}, //Qiraj Wasp + {-8080.0f, 1518.0f, 2.61f, 0.0f}, //Qiraj Wasp + + {-8081.0f, 1514.0f, 2.61f, 0.0f}, //Qiraj Tank + {-8081.0f, 1520.0f, 2.61f, 0.0f}, //Qiraj Tank + {-8081.0f, 1526.0f, 2.61f, 0.0f}, //Qiraj Tank + {-8081.0f, 1512.0f, 2.61f, 0.0f}, //Qiraj Tank + {-8082.0f, 1520.0f, 2.61f, 0.0f}, //Qiraj Tank + {-8081.0f, 1528.0f, 2.61f, 0.0f}, //Qiraj Tank {-8082.0f, 1513.0f, 2.61f, 3.141592f}, //Anubisath Conqueror {-8082.0f, 1520.0f, 2.61f, 3.141592f}, //Anubisath Conqueror @@ -402,14 +280,36 @@ struct SpawnSpells static SpawnSpells SpawnCast[4] = { - {100000, 2000, 33652}, // Stop Time + {100000, 2000, 33652}, // Stoned {38500, 300000, 28528}, // Poison Cloud {58000, 300000, 35871}, // Frost Debuff (need correct spell) {80950, 300000, 42075}, // Fire Explosion (need correct spell however this one looks cool) }; + /*##### # npc_anachronos_the_ancient ######*/ + +enum AnachronosTheAncient +{ + NPC_QIRAJI_WASP = 15414, + NPC_QIRAJI_TANK = 15422, + NPC_KALDOREI_INFANTRY = 15423, + NPC_ANUBISATH_CONQUEROR = 15424, + SPELL_ARCANE_CHANNELING = 23017, + SPELL_NOXIOUS_BREATH = 24818, + SPELL_GREEN_DRAGON_TRANSFORM_DND = 25105, + SPELL_RED_DRAGON_TRANSFORM_DND = 25106, + SPELL_BLUE_DRAGON_TRANSFORM_DND = 25107, + SPELL_TIME_STOP = 25158, + SPELL_CALL_PRISMATIC_BARRIER = 25159, + SPELL_CALL_GLYPHS_OF_WARDING = 25166, + SPELL_CALL_ANCIENTS = 25167, + SPELL_THROW_HAMMER = 33806, + SPELL_FROST_BREATH = 50505, + SPELL_FLAME_BREATH = 54293 +}; + class npc_anachronos_the_ancient : public CreatureScript { public: @@ -464,10 +364,10 @@ public: if (!player) return; - Creature* Fandral = player->FindNearestCreature(C_FANDRAL_STAGHELM, 100.0f); - Creature* Arygos = player->FindNearestCreature(C_ARYGOS, 100.0f); - Creature* Caelestrasz = player->FindNearestCreature(C_CAELESTRASZ, 100.0f); - Creature* Merithra = player->FindNearestCreature(C_MERITHRA, 100.0f); + Creature* Fandral = player->FindNearestCreature(NPC_FANDRAL_STAGHELM, 100.0f); + Creature* Arygos = player->FindNearestCreature(NPC_ARYGOS, 100.0f); + Creature* Caelestrasz = player->FindNearestCreature(NPC_CAELESTRASZ, 100.0f); + Creature* Merithra = player->FindNearestCreature(NPC_MERITHRA_OF_THE_DREAM, 100.0f); if (!Fandral || !Arygos || !Caelestrasz || !Merithra) return; @@ -509,7 +409,7 @@ public: Merithra->AI()->Talk(MERITHRA_YELL_1); break; case 9: - Merithra->CastSpell(Merithra, 25105, true); + Merithra->CastSpell(Merithra, SPELL_GREEN_DRAGON_TRANSFORM_DND, true); break; case 10: Merithra->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); @@ -517,7 +417,7 @@ public: Merithra->GetMotionMaster()->MoveCharge(-8065, 1530, 6.61f, 3); break; case 11: - Merithra->CastSpell(Merithra, 24818, false); + Merithra->CastSpell(Merithra, SPELL_NOXIOUS_BREATH, false); break; case 12: Merithra->GetMotionMaster()->MoveCharge(-8100, 1530, 50, 42); @@ -536,7 +436,7 @@ public: Arygos->AI()->Talk(ARYGOS_YELL_1); break; case 17: - Arygos->CastSpell(Arygos, 25107, true); + Arygos->CastSpell(Arygos, SPELL_BLUE_DRAGON_TRANSFORM_DND, true); break; case 18: Arygos->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); @@ -544,7 +444,7 @@ public: Arygos->GetMotionMaster()->MoveCharge(-8065, 1530, 6.61f, 42); break; case 19: - Arygos->CastSpell(Arygos, 50505, false); + Arygos->CastSpell(Arygos, SPELL_FROST_BREATH, false); break; case 20: Arygos->GetMotionMaster()->MoveCharge(-8095, 1530, 50, 42); @@ -563,15 +463,15 @@ public: Caelestrasz->AI()->Talk(CAELESTRASZ_YELL_1); break; case 25: - Caelestrasz->CastSpell(Caelestrasz, 25106, true); + Caelestrasz->CastSpell(Caelestrasz, SPELL_RED_DRAGON_TRANSFORM_DND, true); break; case 26: - Caelestrasz->HandleEmoteCommand(254); + Caelestrasz->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); Caelestrasz->SetDisableGravity(true); Caelestrasz->GetMotionMaster()->MoveCharge(-8065, 1530, 7.61f, 4); break; case 27: - Caelestrasz->CastSpell(Caelestrasz, 54293, false); + Caelestrasz->CastSpell(Caelestrasz, SPELL_FLAME_BREATH, false); break; case 28: Talk(ANACHRONOS_SAY_2, Fandral); @@ -596,29 +496,29 @@ public: Caelestrasz->GetMotionMaster()->MoveCharge(-8050, 1473, 65, 15); break; //Text: sands will stop case 34: - DoCast(player, 23017, true);//Arcane Channeling + DoCast(player, SPELL_ARCANE_CHANNELING, true);//Arcane Channeling break; case 35: - me->CastSpell(-8088, 1520.43f, 2.67f, 25158, true); + me->CastSpell(-8088, 1520.43f, 2.67f, SPELL_TIME_STOP, true); break; case 36: - DoCast(player, 25159, true); + DoCast(player, SPELL_CALL_PRISMATIC_BARRIER, true); break; case 37: - me->SummonGameObject(GO_GATE_OF_AHN_QIRAJ, -8130, 1525, 17.5f, 0, 0, 0, 0, 0, 0); + me->SummonGameObject(GO_GATE_OF_AHN_QIRAJ, Position(-8130.f, 1525.f, 17.5f, 0.f), G3D::Quat(), 0); break; case 38: - DoCast(player, 25166, true); - me->SummonGameObject(GO_GLYPH_OF_AHN_QIRAJ, -8130, 1525, 17.5f, 0, 0, 0, 0, 0, 0); + DoCast(player, SPELL_CALL_GLYPHS_OF_WARDING, true); + me->SummonGameObject(GO_GLYPH_OF_AHN_QIRAJ, Position(-8130.f, 1525.f, 17.5f, 0.f), G3D::Quat(), 0); break; case 39: Talk(ANACHRONOS_SAY_5, Fandral); break; case 40: - Fandral->CastSpell(me, 25167, true); + Fandral->CastSpell(me, SPELL_CALL_ANCIENTS, true); break; case 41: - Fandral->SummonGameObject(GO_ROOTS_OF_AHN_QIRAJ, -8130, 1525, 17.5f, 0, 0, 0, 0, 0, 0); + Fandral->SummonGameObject(GO_ROOTS_OF_AHN_QIRAJ, Position(-8130.f, 1525.f, 17.5f, 0.f), G3D::Quat(), 0); Fandral->AI()->Talk(FANDRAL_SAY_3); break; case 42: @@ -649,11 +549,11 @@ public: break; case 50: Fandral->AI()->Talk(FANDRAL_EMOTE_2); - Fandral->CastSpell(-8127, 1525, 17.5f, 33806, true); + Fandral->CastSpell(-8127, 1525, 17.5f, SPELL_THROW_HAMMER, true); break; case 51: { - uint32 entries[4] = { 15423, 15424, 15414, 15422 }; + uint32 entries[4] = { NPC_KALDOREI_INFANTRY, NPC_ANUBISATH_CONQUEROR, NPC_QIRAJI_WASP, NPC_QIRAJI_TANK }; Unit* mob = NULL; for (uint8 i = 0; i < 4; ++i) { @@ -661,7 +561,7 @@ public: while (mob) { mob->RemoveFromWorld(); - mob = player->FindNearestCreature(15423, 50); + mob = player->FindNearestCreature(NPC_KALDOREI_INFANTRY, 50); } } break; @@ -706,7 +606,7 @@ public: me->SetDisplayId(15500); break; case 63: - me->HandleEmoteCommand(254); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); me->SetDisableGravity(true); break; case 64: @@ -746,6 +646,13 @@ public: # npc_qiraj_war_spawn ######*/ +enum QirajWarSpawn +{ + SPELL_STONED_CHANNEL_CAST_VISUAL = 15533, + SPELL_SUMMON_POISON_CLOUD = 24319, + SPELL_STONED = 33652 +}; + class npc_qiraj_war_spawn : public CreatureScript { public: @@ -793,22 +700,22 @@ public: { if (!Timers) { - if (me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) //all but Kaldorei Soldiers + if (me->GetEntry() == NPC_ANUBISATH_CONQUEROR || me->GetEntry() == NPC_QIRAJI_TANK || me->GetEntry() == NPC_QIRAJI_WASP) //all but Kaldorei Soldiers { SpellTimer1 = SpawnCast[1].Timer1; SpellTimer2 = SpawnCast[2].Timer1; SpellTimer3 = SpawnCast[3].Timer1; } - if (me->GetEntry() == 15423 || me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) + if (me->GetEntry() == NPC_KALDOREI_INFANTRY || me->GetEntry() == NPC_ANUBISATH_CONQUEROR || me->GetEntry() == NPC_QIRAJI_TANK || me->GetEntry() == NPC_QIRAJI_WASP) SpellTimer4 = SpawnCast[0].Timer1; Timers = true; } - if (me->GetEntry() == 15424 || me->GetEntry() == 15422|| me->GetEntry() == 15414) + if (me->GetEntry() == NPC_ANUBISATH_CONQUEROR || me->GetEntry() == NPC_QIRAJI_TANK || me->GetEntry() == NPC_QIRAJI_WASP) { if (SpellTimer1 <= diff) { DoCast(me, SpawnCast[1].SpellId); - DoCast(me, 24319); + DoCast(me, SPELL_SUMMON_POISON_CLOUD); SpellTimer1 = SpawnCast[1].Timer2; } else SpellTimer1 -= diff; if (SpellTimer2 <= diff) @@ -822,38 +729,38 @@ public: SpellTimer3 = SpawnCast[3].Timer2; } else SpellTimer3 -= diff; } - if (me->GetEntry() == 15423 || me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) + if (me->GetEntry() == NPC_KALDOREI_INFANTRY || me->GetEntry() == NPC_ANUBISATH_CONQUEROR || me->GetEntry() == NPC_QIRAJI_TANK || me->GetEntry() == NPC_QIRAJI_WASP) { if (SpellTimer4 <= diff) { me->RemoveAllAttackers(); me->AttackStop(); - DoCast(me, 15533); + DoCast(me, SPELL_STONED_CHANNEL_CAST_VISUAL); SpellTimer4 = SpawnCast[0].Timer2; } else SpellTimer4 -= diff; } if (!hasTarget) { Unit* target = NULL; - if (me->GetEntry() == 15424 || me->GetEntry() == 15422 || me->GetEntry() == 15414) - target = me->FindNearestCreature(15423, 20, true); - if (me->GetEntry() == 15423) + if (me->GetEntry() == NPC_ANUBISATH_CONQUEROR || me->GetEntry() == NPC_QIRAJI_TANK || me->GetEntry() == NPC_QIRAJI_WASP) + target = me->FindNearestCreature(NPC_KALDOREI_INFANTRY, 20, true); + if (me->GetEntry() == NPC_KALDOREI_INFANTRY) { uint8 tar = urand(0, 2); if (tar == 0) - target = me->FindNearestCreature(15422, 20, true); + target = me->FindNearestCreature(NPC_QIRAJI_TANK, 20, true); else if (tar == 1) - target = me->FindNearestCreature(15424, 20, true); + target = me->FindNearestCreature(NPC_ANUBISATH_CONQUEROR, 20, true); else if (tar == 2) - target = me->FindNearestCreature(15414, 20, true); + target = me->FindNearestCreature(NPC_QIRAJI_WASP, 20, true); } hasTarget = true; if (target) AttackStart(target); } - if (!(me->FindNearestCreature(15379, 60))) - DoCast(me, 33652); + if (!(me->FindNearestCreature(NPC_CAELESTRASZ, 60))) + DoCast(me, SPELL_STONED); if (!UpdateVictim()) { @@ -932,7 +839,7 @@ public: if (Creature* spawn = me->SummonCreature(WavesInfo[WaveCount].CreatureId, SpawnLocation[i], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, desptimer)) { - if (spawn->GetEntry() == 15423) + if (spawn->GetEntry() == NPC_KALDOREI_INFANTRY) spawn->SetUInt32Value(UNIT_FIELD_DISPLAYID, 15427 + rand32() % 4); if (i >= 30) WaveCount = 1; if (i >= 33) WaveCount = 2; @@ -1040,6 +947,14 @@ void npc_qiraj_war_spawn::npc_qiraj_war_spawnAI::JustDied(Unit* /*slayer*/) # go_crystalline_tear ######*/ +enum CrystallineTear +{ + ARYGOS_GNOME_FORM = 15418, + CAELESTRASZ_NIGHT_ELF_FORM = 15419, + MERITHRA_NIGHT_ELF_FORM = 15420, + ANACHRONOS_QUEST_TRIGGER_INVISIBLE = 15454 +}; + class go_crystalline_tear : public GameObjectScript { public: @@ -1049,35 +964,35 @@ public: { if (quest->GetQuestId() == QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) { - if (Creature* trigger = go->FindNearestCreature(15454, 100)) + if (Creature* trigger = go->FindNearestCreature(ANACHRONOS_QUEST_TRIGGER_INVISIBLE, 100)) { - Unit* Merithra = trigger->SummonCreature(15378, -8034.535f, 1535.14f, 2.61f, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); - Unit* Caelestrasz = trigger->SummonCreature(15379, -8032.767f, 1533.148f, 2.61f, 1.5f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); - Unit* Arygos = trigger->SummonCreature(15380, -8034.52f, 1537.843f, 2.61f, 5.7f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); - /* Unit* Fandral = */ trigger->SummonCreature(15382, -8028.462f, 1535.843f, 2.61f, 3.141592f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); - Creature* Anachronos = trigger->SummonCreature(15381, -8028.75f, 1538.795f, 2.61f, 4, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); + Unit* Merithra = trigger->SummonCreature(NPC_MERITHRA_OF_THE_DREAM, -8034.535f, 1535.14f, 2.61f, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); + Unit* Caelestrasz = trigger->SummonCreature(NPC_CAELESTRASZ, -8032.767f, 1533.148f, 2.61f, 1.5f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); + Unit* Arygos = trigger->SummonCreature(NPC_ARYGOS, -8034.52f, 1537.843f, 2.61f, 5.7f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); + /* Unit* Fandral = */ trigger->SummonCreature(NPC_FANDRAL_STAGHELM, -8028.462f, 1535.843f, 2.61f, 3.141592f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); + Creature* Anachronos = trigger->SummonCreature(NPC_ANACHRONOS, -8028.75f, 1538.795f, 2.61f, 4, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 220000); if (Merithra) { - Merithra->SetUInt32Value(UNIT_NPC_FLAGS, 0); + Merithra->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); Merithra->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - Merithra->SetUInt32Value(UNIT_FIELD_DISPLAYID, 15420); + Merithra->SetUInt32Value(UNIT_FIELD_DISPLAYID, MERITHRA_NIGHT_ELF_FORM); Merithra->setFaction(35); } if (Caelestrasz) { - Caelestrasz->SetUInt32Value(UNIT_NPC_FLAGS, 0); + Caelestrasz->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); Caelestrasz->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - Caelestrasz->SetUInt32Value(UNIT_FIELD_DISPLAYID, 15419); + Caelestrasz->SetUInt32Value(UNIT_FIELD_DISPLAYID, CAELESTRASZ_NIGHT_ELF_FORM); Caelestrasz->setFaction(35); } if (Arygos) { - Arygos->SetUInt32Value(UNIT_NPC_FLAGS, 0); + Arygos->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); Arygos->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); - Arygos->SetUInt32Value(UNIT_FIELD_DISPLAYID, 15418); + Arygos->SetUInt32Value(UNIT_FIELD_DISPLAYID, ARYGOS_GNOME_FORM); Arygos->setFaction(35); } @@ -1107,112 +1022,107 @@ public: enum WSSpells { - SPELL_PUNISHMENT = 24803, - SPELL_SPAWN_IN = 25035, - - AURA_TWILIGHT_SET = 24746, - AURA_MEDALLION = 24748, - AURA_RING = 24782, - - SPELL_TEMPLAR_RANDOM = 24745, - SPELL_TEMPLAR_FIRE = 24747, - SPELL_TEMPLAR_AIR = 24757, - SPELL_TEMPLAR_EARTH = 24759, - SPELL_TEMPLAR_WATER = 24761, - - SPELL_DUKE_RANDOM = 24762, - SPELL_DUKE_FIRE = 24766, - SPELL_DUKE_AIR = 24769, - SPELL_DUKE_EARTH = 24771, - SPELL_DUKE_WATER = 24773, - - SPELL_ROYAL_RANDOM = 24785, - SPELL_ROYAL_FIRE = 24787, - SPELL_ROYAL_AIR = 24791, - SPELL_ROYAL_EARTH = 24792, - SPELL_ROYAL_WATER = 24793 + AURA_TWILIGHT_SET = 24746, + AURA_MEDALLION = 24748, + AURA_RING = 24782, + + SPELL_TEMPLAR_RANDOM = 24745, + SPELL_TEMPLAR_FIRE = 24747, + SPELL_TEMPLAR_AIR = 24757, + SPELL_TEMPLAR_EARTH = 24759, + SPELL_TEMPLAR_WATER = 24761, + + SPELL_DUKE_RANDOM = 24762, + SPELL_DUKE_FIRE = 24766, + SPELL_DUKE_AIR = 24769, + SPELL_DUKE_EARTH = 24771, + SPELL_DUKE_WATER = 24773, + + SPELL_ROYAL_RANDOM = 24785, + SPELL_ROYAL_FIRE = 24787, + SPELL_ROYAL_AIR = 24791, + SPELL_ROYAL_EARTH = 24792, + SPELL_ROYAL_WATER = 24793, + + SPELL_PUNISHMENT = 24803, + SPELL_SPAWN_IN = 25035 }; enum WSGossip { - GOSSIPID_LESSER_WS = 6540, - GOSSIPID_WS = 6542, - GOSSIPID_GREATER_WS = 6543 + OPTION_ID_WS_RANDOM = 0, + OPTION_ID_1_CRIMSON = 1, + OPTION_ID_2_AZURE = 2, + OPTION_ID_3_EARTHEN = 3, + OPTION_ID_4_HOARY = 4, + OPTION_ID_1_CYNDERS = 1, + OPTION_ID_2_FATHOMS = 2, + OPTION_ID_3_SHARDS = 3, + OPTION_ID_4_ZEPHYRS = 4, + OPTION_ID_1_SKALDRENOX = 1, + OPTION_ID_2_SKWOL = 2, + OPTION_ID_3_KAZUM = 3, + OPTION_ID_4_WHIRLAXIS = 4, + GOSSIP_ID_LESSER_WS = 6540, + GOSSIP_ID_WIND_STONE = 6542, + GOSSIP_ID_GREATER_WS = 6543 }; enum WSCreatures { - NPC_TEMPLAR_FIRE = 15209, - NPC_TEMPLAR_WATER = 15211, - NPC_TEMPLAR_AIR = 15212, - NPC_TEMPLAR_EARTH = 15307, - - NPC_DUKE_FIRE = 15206, - NPC_DUKE_WATER = 15207, - NPC_DUKE_EARTH = 15208, - NPC_DUKE_AIR = 15220, - - NPC_ROYAL_FIRE = 15203, - NPC_ROYAL_AIR = 15204, - NPC_ROYAL_EARTH = 15205, - NPC_ROYAL_WATER = 15305 + NPC_TEMPLAR_FIRE = 15209, + NPC_TEMPLAR_WATER = 15211, + NPC_TEMPLAR_AIR = 15212, + NPC_TEMPLAR_EARTH = 15307, + + NPC_DUKE_FIRE = 15206, + NPC_DUKE_WATER = 15207, + NPC_DUKE_EARTH = 15208, + NPC_DUKE_AIR = 15220, + + NPC_ROYAL_FIRE = 15203, + NPC_ROYAL_AIR = 15204, + NPC_ROYAL_EARTH = 15205, + NPC_ROYAL_WATER = 15305 }; enum WSItems { - ITEM_TEMPLAR_FIRE = 20416, - ITEM_TEMPLAR_EARTH = 20419, - ITEM_TEMPLAR_WATER = 20420, - ITEM_TEMPLAR_AIR = 20418, - - ITEM_DUKE_FIRE = 20432, - ITEM_DUKE_EARTH = 20435, - ITEM_DUKE_WATER = 20436, - ITEM_DUKE_AIR = 20433, - - ITEM_ROYAL_FIRE = 20447, - ITEM_ROYAL_EARTH = 20449, - ITEM_ROYAL_WATER = 20450, - ITEM_ROYAL_AIR = 20448, + ITEM_TEMPLAR_FIRE = 20416, + ITEM_TEMPLAR_AIR = 20418, + ITEM_TEMPLAR_EARTH = 20419, + ITEM_TEMPLAR_WATER = 20420, + + ITEM_DUKE_FIRE = 20432, + ITEM_DUKE_AIR = 20433, + ITEM_DUKE_EARTH = 20435, + ITEM_DUKE_WATER = 20436, + + ITEM_ROYAL_FIRE = 20447, + ITEM_ROYAL_AIR = 20448, + ITEM_ROYAL_EARTH = 20449, + ITEM_ROYAL_WATER = 20450 }; enum WS { - TEMPLAR = 0, - DUKE = 1, - ROYAL = 2, - - FIRE = 0x1, - WATER = 0x2, - EARTH = 0x4, - AIR = 0x8 -}; + TEMPLAR = 0, + DUKE = 1, + ROYAL = 2, + + FIRE = 0x1, + WATER = 0x2, + EARTH = 0x4, + AIR = 0x8 +}; enum WSTexts { - SAY_TEMPLAR_AGGRO = 0, - SAY_DUKE_AGGRO = 0, - YELL_ROYAL_AGGRO = 0 + SAY_TEMPLAR_AGGRO = 0, + SAY_DUKE_AGGRO = 0, + YELL_ROYAL_AGGRO = 0 }; -#define GOSSIP_TEMPLAR_RANDOM "I am no cultist, you monster! Come to me and face your destruction!" -#define GOSSIP_TEMPLAR_FIRE "Crimson Templar! I hold your signet! Heed my call!" -#define GOSSIP_TEMPLAR_EARTH "Earthen Templar! I hold your signet! Heed my call!" -#define GOSSIP_TEMPLAR_AIR "Hoary Templar! I hold your signet! Heed my call!" -#define GOSSIP_TEMPLAR_WATER "Azure Templar! I hold your signet! Heed my call!" - -#define GOSSIP_DUKE_RANDOM "You will listen to this, vile duke! I am not your Twilight's Hammer lapdog! I am here to challenge you! Come! Come, and meet your death..." -#define GOSSIP_DUKE_FIRE "Duke of Cynders! I hold your signet! Heed my call!" -#define GOSSIP_DUKE_EARTH "The Duke of Shards! I hold your signet! Heed my call!" -#define GOSSIP_DUKE_AIR "The Duke of Zephyrs! I hold your signet! Heed my call!" -#define GOSSIP_DUKE_WATER "The Duke of Fathoms! I hold your signet! Heed my call!" - -#define GOSSIP_ROYAL_RANDOM "The day of the judgement has come, fiend! I challenge you to battle!" -#define GOSSIP_ROYAL_FIRE "Prince Skaldrenox! I hold your signet! Heed my call!" -#define GOSSIP_ROYAL_EARTH "Baron Kazum! I hold your signet! Heed my call!" -#define GOSSIP_ROYAL_AIR "High Marshal Whirlaxis! I hold your signet! Heed my call!" -#define GOSSIP_ROYAL_WATER "Lord Skwol! I hold your signet! Heed my call!" - class go_wind_stone : public GameObjectScript { public: @@ -1294,7 +1204,7 @@ class go_wind_stone : public GameObjectScript case NPC_TEMPLAR_WATER: case NPC_TEMPLAR_AIR: case NPC_TEMPLAR_EARTH: - summons->AI()->Talk(SAY_TEMPLAR_AGGRO); + summons->AI()->Talk(SAY_TEMPLAR_AGGRO, player); break; case NPC_DUKE_FIRE: @@ -1323,10 +1233,10 @@ class go_wind_stone : public GameObjectScript uint32 gossipId = go->GetGOInfo()->GetGossipMenuId(); switch (gossipId) { - case GOSSIPID_LESSER_WS: + case GOSSIP_ID_LESSER_WS: { if (rank >= 1) // 1 or 2 or 3 - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEMPLAR_RANDOM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_LESSER_WS, OPTION_ID_WS_RANDOM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); else { go->CastSpell(player, SPELL_PUNISHMENT); @@ -1335,19 +1245,19 @@ class go_wind_stone : public GameObjectScript uint8 item = GetItems(player, TEMPLAR); if (item & FIRE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEMPLAR_FIRE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_LESSER_WS, OPTION_ID_1_CRIMSON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); if (item & WATER) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEMPLAR_WATER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_LESSER_WS, OPTION_ID_2_AZURE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); if (item & EARTH) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEMPLAR_EARTH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_LESSER_WS, OPTION_ID_3_EARTHEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); if (item & AIR) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TEMPLAR_AIR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_LESSER_WS, OPTION_ID_4_HOARY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); break; } - case GOSSIPID_WS: + case GOSSIP_ID_WIND_STONE: { if (rank >= 2) // 2 or 3 - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUKE_RANDOM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_WIND_STONE, OPTION_ID_WS_RANDOM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); else { go->CastSpell(player, SPELL_PUNISHMENT); @@ -1356,19 +1266,19 @@ class go_wind_stone : public GameObjectScript uint8 item = GetItems(player, DUKE); if (item & FIRE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUKE_FIRE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_WIND_STONE, OPTION_ID_1_CYNDERS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); if (item & WATER) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUKE_WATER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_WIND_STONE, OPTION_ID_2_FATHOMS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); if (item & EARTH) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUKE_EARTH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_WIND_STONE, OPTION_ID_3_SHARDS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); if (item & AIR) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUKE_AIR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_WIND_STONE, OPTION_ID_4_ZEPHYRS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); break; } - case GOSSIPID_GREATER_WS: + case GOSSIP_ID_GREATER_WS: { if (rank == 3) // 3 - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ROYAL_RANDOM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_GREATER_WS, OPTION_ID_WS_RANDOM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); else { go->CastSpell(player, SPELL_PUNISHMENT); @@ -1377,13 +1287,13 @@ class go_wind_stone : public GameObjectScript uint8 item = GetItems(player, ROYAL); if (item & FIRE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ROYAL_FIRE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_GREATER_WS, OPTION_ID_1_SKALDRENOX, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); if (item & WATER) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ROYAL_WATER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_GREATER_WS, OPTION_ID_2_SKWOL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); if (item & EARTH) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ROYAL_EARTH, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_GREATER_WS, OPTION_ID_3_KAZUM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); if (item & AIR) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ROYAL_AIR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_ID_GREATER_WS, OPTION_ID_4_WHIRLAXIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 15); break; } default: @@ -1462,6 +1372,5 @@ void AddSC_silithus() new npc_anachronos_quest_trigger(); new npc_anachronos_the_ancient(); new npc_qiraj_war_spawn(); - new npcs_rutgar_and_frankal(); new go_wind_stone(); } diff --git a/src/server/scripts/Kalimdor/zone_tanaris.cpp b/src/server/scripts/Kalimdor/zone_tanaris.cpp index 22b4c86cbcd..966bbaec1da 100644 --- a/src/server/scripts/Kalimdor/zone_tanaris.cpp +++ b/src/server/scripts/Kalimdor/zone_tanaris.cpp @@ -19,15 +19,13 @@ /* ScriptData SDName: Tanaris SD%Complete: 80 -SDComment: Quest support: 648, 1560, 2954, 4005, 10277, 10279(Special flight path). +SDComment: Quest support: 648, 1560, 4005, 10277 SDCategory: Tanaris EndScriptData */ /* ContentData npc_aquementas npc_custodian_of_time -npc_steward_of_time -npc_stone_watcher_of_norgannon npc_OOX17 npc_tooga EndContentData */ @@ -298,116 +296,6 @@ public: }; /*###### -## npc_steward_of_time -######*/ - -#define GOSSIP_ITEM_FLIGHT "Please take me to the master's lair." - -class npc_steward_of_time : public CreatureScript -{ -public: - npc_steward_of_time() : CreatureScript("npc_steward_of_time") { } - - bool OnQuestAccept(Player* player, Creature* /*creature*/, Quest const* quest) override - { - if (quest->GetQuestId() == 10279) //Quest: To The Master's Lair - player->CastSpell(player, 34891, true); //(Flight through Caverns) - - return false; - } - - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF + 1) - player->CastSpell(player, 34891, true); //(Flight through Caverns) - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(10279) == QUEST_STATUS_INCOMPLETE || player->GetQuestRewardStatus(10279)) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(9978, creature->GetGUID()); - } - else - player->SEND_GOSSIP_MENU(9977, creature->GetGUID()); - - return true; - } - -}; - -/*###### -## npc_stone_watcher_of_norgannon -######*/ - -#define GOSSIP_ITEM_NORGANNON_1 "What function do you serve?" -#define GOSSIP_ITEM_NORGANNON_2 "What are the Plates of Uldum?" -#define GOSSIP_ITEM_NORGANNON_3 "Where are the Plates of Uldum?" -#define GOSSIP_ITEM_NORGANNON_4 "Excuse me? We've been \"reschedueled for visitations\"? What does that mean?!" -#define GOSSIP_ITEM_NORGANNON_5 "So, what's inside Uldum?" -#define GOSSIP_ITEM_NORGANNON_6 "I will return when i have the Plates of Uldum." - -class npc_stone_watcher_of_norgannon : public CreatureScript -{ -public: - npc_stone_watcher_of_norgannon() : CreatureScript("npc_stone_watcher_of_norgannon") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(1675, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->SEND_GOSSIP_MENU(1676, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->SEND_GOSSIP_MENU(1677, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - player->SEND_GOSSIP_MENU(1678, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - player->SEND_GOSSIP_MENU(1679, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(2954); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(2954) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - player->SEND_GOSSIP_MENU(1674, creature->GetGUID()); - - return true; - } - -}; - -/*###### ## npc_OOX17 ######*/ @@ -672,8 +560,6 @@ void AddSC_tanaris() { new npc_aquementas(); new npc_custodian_of_time(); - new npc_steward_of_time(); - new npc_stone_watcher_of_norgannon(); new npc_OOX17(); new npc_tooga(); } diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp index 852cd62c277..7a963d066b6 100644 --- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp +++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp @@ -43,38 +43,37 @@ EndContentData */ ## npc_beaten_corpse ######*/ -#define GOSSIP_CORPSE "Examine corpse in detail..." - enum BeatenCorpse { - QUEST_LOST_IN_BATTLE = 4921 + GOSSIP_OPTION_ID_BEATEN_CORPSE = 0, + GOSSIP_MENU_OPTION_INSPECT_BODY = 2871 }; class npc_beaten_corpse : public CreatureScript { -public: - npc_beaten_corpse() : CreatureScript("npc_beaten_corpse") { } + public: + npc_beaten_corpse() : CreatureScript("npc_beaten_corpse") { } - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF +1) + struct npc_beaten_corpseAI : public ScriptedAI { - player->SEND_GOSSIP_MENU(3558, creature->GetGUID()); - player->TalkedToCreature(creature->GetEntry(), creature->GetGUID()); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_COMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CORPSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + npc_beaten_corpseAI(Creature* creature) : ScriptedAI(creature) + { + } - player->SEND_GOSSIP_MENU(3557, creature->GetGUID()); - return true; - } + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + if (menuId == GOSSIP_MENU_OPTION_INSPECT_BODY && gossipListId == GOSSIP_OPTION_ID_BEATEN_CORPSE) + { + player->CLOSE_GOSSIP_MENU(); + player->TalkedToCreature(me->GetEntry(), me->GetGUID()); + } + } + }; + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_beaten_corpseAI(creature); + } }; /*###### @@ -552,7 +551,7 @@ public: { if (!HasEscortState(STATE_ESCORT_ESCORTING)) { - if (me->getStandState() == UNIT_STAND_STATE_DEAD) + if (me->GetStandState() == UNIT_STAND_STATE_DEAD) me->SetStandState(UNIT_STAND_STATE_STAND); IsPostEvent = false; diff --git a/src/server/scripts/Kalimdor/zone_thousand_needles.cpp b/src/server/scripts/Kalimdor/zone_thousand_needles.cpp index 85c3a621239..2a606856af6 100644 --- a/src/server/scripts/Kalimdor/zone_thousand_needles.cpp +++ b/src/server/scripts/Kalimdor/zone_thousand_needles.cpp @@ -19,7 +19,7 @@ /* ScriptData SDName: Thousand Needles SD%Complete: 100 -SDComment: Support for Quest: 1950, 4770, 4904, 4966, 5151. +SDComment: Support for Quest: 4770, 4904, 4966, 5151. SDCategory: Thousand Needles EndScriptData */ @@ -27,7 +27,6 @@ EndScriptData */ npc_kanati npc_lakota_windsong npc_swiftmountain -npc_plucky npc_enraged_panther go_panther_cage EndContentData */ @@ -44,10 +43,9 @@ EndContentData */ enum Kanati { - SAY_KAN_START = 0, - - QUEST_PROTECT_KANATI = 4966, - NPC_GALAK_ASS = 10720 + SAY_KAN_START = 0, + QUEST_PROTECT_KANATI = 4966, + NPC_GALAK_ASS = 10720 }; Position const GalakLoc = {-4867.387695f, -1357.353760f, -48.226f, 0.0f}; @@ -112,19 +110,19 @@ public: enum Lakota { - SAY_LAKO_START = 0, - SAY_LAKO_LOOK_OUT = 1, - SAY_LAKO_HERE_COME = 2, - SAY_LAKO_MORE = 3, - SAY_LAKO_END = 4, - - QUEST_FREE_AT_LAST = 4904, - NPC_GRIM_BANDIT = 10758, - FACTION_ESCORTEE_LAKO = 232, //guessed - - ID_AMBUSH_1 = 0, - ID_AMBUSH_2 = 2, - ID_AMBUSH_3 = 4 + SAY_LAKO_START = 0, + SAY_LAKO_LOOK_OUT = 1, + SAY_LAKO_HERE_COME = 2, + SAY_LAKO_MORE = 3, + SAY_LAKO_END = 4, + + QUEST_FREE_AT_LAST = 4904, + NPC_GRIM_BANDIT = 10758, + FACTION_ESCORTEE_LAKO = 232, //guessed + + ID_AMBUSH_1 = 0, + ID_AMBUSH_2 = 2, + ID_AMBUSH_3 = 4 }; Position const BanditLoc[6] = @@ -183,6 +181,7 @@ public: DoSpawnBandits(ID_AMBUSH_3); break; case 45: + Talk(SAY_LAKO_END); if (Player* player = GetPlayerForEscort()) player->GroupEventHappens(QUEST_FREE_AT_LAST, me); break; @@ -195,7 +194,6 @@ public: me->SummonCreature(NPC_GRIM_BANDIT, BanditLoc[i+AmbushId], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); } }; - }; /*###### @@ -204,13 +202,13 @@ public: enum Packa { - SAY_START = 0, - SAY_WYVERN = 1, - SAY_COMPLETE = 2, + SAY_START = 0, + SAY_WYVERN = 1, + SAY_COMPLETE = 2, - QUEST_HOMEWARD = 4770, - NPC_WYVERN = 4107, - FACTION_ESCORTEE = 232 //guessed + QUEST_HOMEWARD = 4770, + NPC_WYVERN = 4107, + FACTION_ESCORTEE = 232 //guessed }; Position const WyvernLoc[3] = @@ -275,137 +273,10 @@ public: }; }; -/*##### -# npc_plucky -######*/ - -#define GOSSIP_P "Please tell me the Phrase.." - -enum Plucky -{ - FACTION_FRIENDLY = 35, - QUEST_SCOOP = 1950, - SPELL_PLUCKY_HUMAN = 9192, - SPELL_PLUCKY_CHICKEN = 9220 -}; - -class npc_plucky : public CreatureScript -{ -public: - npc_plucky() : CreatureScript("npc_plucky") { } - - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->CLOSE_GOSSIP_MENU(); - player->CompleteQuest(QUEST_SCOOP); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(QUEST_SCOOP) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_P, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(738, creature->GetGUID()); - - return true; - } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_pluckyAI(creature); - } - - struct npc_pluckyAI : public ScriptedAI - { - npc_pluckyAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - NormFaction = creature->getFaction(); - } - - void Initialize() - { - ResetTimer = 120000; - } - - uint32 NormFaction; - uint32 ResetTimer; - - void Reset() override - { - Initialize(); - - if (me->getFaction() != NormFaction) - me->setFaction(NormFaction); - - if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - DoCast(me, SPELL_PLUCKY_CHICKEN, false); - } - - void ReceiveEmote(Player* player, uint32 TextEmote) override - { - if (player->GetQuestStatus(QUEST_SCOOP) == QUEST_STATUS_INCOMPLETE) - { - if (TextEmote == TEXT_EMOTE_BECKON) - { - me->setFaction(FACTION_FRIENDLY); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - DoCast(me, SPELL_PLUCKY_HUMAN, false); - } - } - - if (TextEmote == TEXT_EMOTE_CHICKEN) - { - if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - return; - else - { - me->setFaction(FACTION_FRIENDLY); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - DoCast(me, SPELL_PLUCKY_HUMAN, false); - me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); - } - } - } - - void UpdateAI(uint32 Diff) override - { - if (me->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP)) - { - if (ResetTimer <= Diff) - { - if (!me->GetVictim()) - EnterEvadeMode(); - else - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - return; - } - else - ResetTimer -= Diff; - } - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - }; - -}; - enum PantherCage { - ENRAGED_PANTHER = 10992 + QUEST_HYPERCAPACITOR_GIZMO = 5151, + ENRAGED_PANTHER = 10992 }; class go_panther_cage : public GameObjectScript @@ -416,7 +287,7 @@ public: bool OnGossipHello(Player* player, GameObject* go) override { go->UseDoorOrButton(); - if (player->GetQuestStatus(5151) == QUEST_STATUS_INCOMPLETE) + if (player->GetQuestStatus(QUEST_HYPERCAPACITOR_GIZMO) == QUEST_STATUS_INCOMPLETE) { if (Creature* panther = go->FindNearestCreature(ENRAGED_PANTHER, 5, true)) { @@ -466,7 +337,6 @@ void AddSC_thousand_needles() new npc_kanati(); new npc_lakota_windsong(); new npc_paoka_swiftmountain(); - new npc_plucky(); new npc_enraged_panther(); new go_panther_cage(); } diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp index ab09dd45710..2f97b5a8055 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp @@ -16,7 +16,8 @@ */ /* - * Comment: Complete - BUT THE TRIGGER NEEDS DATA WHETHER THE PRISON OF TALDARAM IS OFFLINE ! + * Comment: Visuals missing, de-germanize code, wow 3.3.5a-ize + * Patch 3.3.2 (2010-01-02): Jedoga Shadowseeker now only ascends once during the encounter. */ #include "ScriptMgr.h" @@ -454,11 +455,11 @@ public: float distance = me->GetDistance(JedogaPosition[1]); if (distance < 9.0f) - me->SetSpeed(MOVE_WALK, 0.5f, true); + me->SetSpeedRate(MOVE_WALK, 0.5f); else if (distance < 15.0f) - me->SetSpeed(MOVE_WALK, 0.75f, true); + me->SetSpeedRate(MOVE_WALK, 0.75f); else if (distance < 20.0f) - me->SetSpeed(MOVE_WALK, 1.0f, true); + me->SetSpeedRate(MOVE_WALK, 1.0f); me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index e25f64f61aa..04b62f77e9a 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -178,7 +178,7 @@ class boss_prince_taldaram : public CreatureScript if (Unit* embraceTarget = GetEmbraceTarget()) { me->GetMotionMaster()->Clear(); - me->SetSpeed(MOVE_WALK, 2.0f, true); + me->SetSpeedRate(MOVE_WALK, 2.0f); me->GetMotionMaster()->MoveChase(embraceTarget); } events.ScheduleEvent(EVENT_VANISHED, 1300); @@ -188,7 +188,7 @@ class boss_prince_taldaram : public CreatureScript DoCast(embraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR); Talk(SAY_FEED); me->GetMotionMaster()->Clear(); - me->SetSpeed(MOVE_WALK, 1.0f, true); + me->SetSpeedRate(MOVE_WALK, 1.0f); me->GetMotionMaster()->MoveChase(me->GetVictim()); events.ScheduleEvent(EVENT_FEEDING, 20000); break; diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp index 16cfb30e2dc..2df0fceab9c 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp @@ -156,7 +156,7 @@ public: ImpaleTarget = impaleTarget->GetGUID(); impaleTarget->SetReactState(REACT_PASSIVE); impaleTarget->SetDisplayId(DISPLAY_INVISIBLE); - impaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + impaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); return impaleTarget; } diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt deleted file mode 100644 index 1dc453ad416..00000000000 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ /dev/null @@ -1,199 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - Northrend/zone_wintergrasp.cpp - Northrend/isle_of_conquest.cpp - Northrend/zone_storm_peaks.cpp - Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp - Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp - Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h - Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp - Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp - Northrend/Ulduar/HallsOfLightning/boss_loken.cpp - Northrend/Ulduar/Ulduar/boss_general_vezax.cpp - Northrend/Ulduar/Ulduar/boss_thorim.cpp - Northrend/Ulduar/Ulduar/boss_ignis.cpp - Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp - Northrend/Ulduar/Ulduar/instance_ulduar.cpp - Northrend/Ulduar/Ulduar/boss_auriaya.cpp - Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp - Northrend/Ulduar/Ulduar/boss_hodir.cpp - Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp - Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp - Northrend/Ulduar/Ulduar/boss_xt002.cpp - Northrend/Ulduar/Ulduar/boss_mimiron.cpp - Northrend/Ulduar/Ulduar/ulduar.h - Northrend/Ulduar/Ulduar/boss_freya.cpp - Northrend/Ulduar/Ulduar/boss_razorscale.cpp - Northrend/Ulduar/Ulduar/boss_kologarn.cpp - Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp - Northrend/Ulduar/HallsOfStone/halls_of_stone.h - Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp - Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp - Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp - Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp - Northrend/ChamberOfAspects/ObsidianSanctum/instance_obsidian_sanctum.cpp - Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.h - Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp - Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp - Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp - Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.h - Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp - Northrend/ChamberOfAspects/RubySanctum/boss_baltharus_the_warborn.cpp - Northrend/ChamberOfAspects/RubySanctum/boss_saviana_ragefire.cpp - Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp - Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp - Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h - Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp - Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp - Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp - Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp - Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp - Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp - Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp - Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp - Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h - Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp - Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp - Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp - Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp - Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp - Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h - Northrend/Nexus/EyeOfEternity/boss_malygos.cpp - Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp - Northrend/Nexus/EyeOfEternity/eye_of_eternity.h - Northrend/Nexus/Oculus/boss_eregos.cpp - Northrend/Nexus/Oculus/boss_drakos.cpp - Northrend/Nexus/Oculus/oculus.h - Northrend/Nexus/Oculus/boss_varos.cpp - Northrend/Nexus/Oculus/boss_urom.cpp - Northrend/Nexus/Oculus/oculus.cpp - Northrend/Nexus/Oculus/instance_oculus.cpp - Northrend/Nexus/Nexus/boss_nexus_commanders.cpp - Northrend/Nexus/Nexus/boss_ormorok.cpp - Northrend/Nexus/Nexus/boss_magus_telestra.cpp - Northrend/Nexus/Nexus/instance_nexus.cpp - Northrend/Nexus/Nexus/boss_keristrasza.cpp - Northrend/Nexus/Nexus/boss_anomalus.cpp - Northrend/Nexus/Nexus/nexus.h - Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp - Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp - Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp - Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h - Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp - Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp - Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp - Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp - Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h - Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp - Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp - Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp - Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp - Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp - Northrend/Naxxramas/boss_loatheb.cpp - Northrend/Naxxramas/boss_anubrekhan.cpp - Northrend/Naxxramas/boss_maexxna.cpp - Northrend/Naxxramas/boss_patchwerk.cpp - Northrend/Naxxramas/boss_gothik.cpp - Northrend/Naxxramas/boss_faerlina.cpp - Northrend/Naxxramas/boss_gluth.cpp - Northrend/Naxxramas/boss_four_horsemen.cpp - Northrend/Naxxramas/naxxramas.h - Northrend/Naxxramas/boss_kelthuzad.cpp - Northrend/Naxxramas/boss_heigan.cpp - Northrend/Naxxramas/boss_thaddius.cpp - Northrend/Naxxramas/boss_razuvious.cpp - Northrend/Naxxramas/boss_sapphiron.cpp - Northrend/Naxxramas/instance_naxxramas.cpp - Northrend/Naxxramas/boss_grobbulus.cpp - Northrend/Naxxramas/boss_noth.cpp - Northrend/zone_crystalsong_forest.cpp - Northrend/VaultOfArchavon/boss_archavon.cpp - Northrend/VaultOfArchavon/boss_koralon.cpp - Northrend/VaultOfArchavon/vault_of_archavon.h - Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp - Northrend/VaultOfArchavon/boss_emalon.cpp - Northrend/VaultOfArchavon/boss_toravon.cpp - Northrend/zone_sholazar_basin.cpp - Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp - Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp - Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp - Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp - Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp - Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h - Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp - Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp - Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h - Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp - Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp - Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp - Northrend/zone_dragonblight.cpp - Northrend/zone_grizzly_hills.cpp - Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h - Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp - Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp - Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp - Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp - Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp - Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp - Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp - Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp - Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp - Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp - Northrend/AzjolNerub/Ahnkahet/ahnkahet.h - Northrend/VioletHold/boss_zuramat.cpp - Northrend/VioletHold/instance_violet_hold.cpp - Northrend/VioletHold/boss_lavanthor.cpp - Northrend/VioletHold/boss_cyanigosa.cpp - Northrend/VioletHold/violet_hold.h - Northrend/VioletHold/boss_ichoron.cpp - Northrend/VioletHold/boss_moragg.cpp - Northrend/VioletHold/boss_xevozz.cpp - Northrend/VioletHold/boss_erekem.cpp - Northrend/VioletHold/violet_hold.cpp - Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp - Northrend/IcecrownCitadel/icecrown_citadel.cpp - Northrend/IcecrownCitadel/icecrown_citadel.h - Northrend/IcecrownCitadel/icecrown_citadel_teleport.cpp - Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp - Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp - Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp - Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp - Northrend/IcecrownCitadel/boss_festergut.cpp - Northrend/IcecrownCitadel/boss_rotface.cpp - Northrend/IcecrownCitadel/boss_professor_putricide.cpp - Northrend/IcecrownCitadel/boss_blood_prince_council.cpp - Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp - Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp - Northrend/IcecrownCitadel/boss_sindragosa.cpp - Northrend/IcecrownCitadel/boss_the_lich_king.cpp - Northrend/zone_zuldrak.cpp - Northrend/zone_icecrown.cpp - Northrend/Gundrak/boss_slad_ran.cpp - Northrend/Gundrak/instance_gundrak.cpp - Northrend/Gundrak/boss_drakkari_colossus.cpp - Northrend/Gundrak/gundrak.h - Northrend/Gundrak/boss_gal_darah.cpp - Northrend/Gundrak/boss_moorabi.cpp - Northrend/Gundrak/boss_eck.cpp - Northrend/zone_borean_tundra.cpp - Northrend/zone_howling_fjord.cpp - Northrend/zone_dalaran.cpp - Northrend/DraktharonKeep/boss_trollgore.cpp - Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp - Northrend/DraktharonKeep/boss_novos.cpp - Northrend/DraktharonKeep/drak_tharon_keep.h - Northrend/DraktharonKeep/boss_tharon_ja.cpp - Northrend/DraktharonKeep/boss_king_dred.cpp -) - -message(" -> Prepared: Northrend") diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 7b8ca41772f..d6682e272fd 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -137,7 +137,8 @@ enum Events EVENT_CHECK_CORPOREALITY = 13, EVENT_SHADOW_PULSARS_SHOOT = 14, EVENT_TRIGGER_BERSERK = 15, - EVENT_TWILIGHT_MENDING = 16 + EVENT_TWILIGHT_MENDING = 16, + EVENT_ACTIVATE_EMBERS = 17 }; enum Actions @@ -150,7 +151,9 @@ enum Actions ACTION_MONITOR_CORPOREALITY = 3, // Orb Carrier - ACTION_SHOOT = 4 + ACTION_WARNING_SHOOT = 4, + ACTION_SHOOT = 5, + ACTION_ACTIVATE_EMBERS = 6 }; enum Phases @@ -168,8 +171,7 @@ enum Misc DATA_MATERIAL_DAMAGE_TAKEN = 2, DATA_STACKS_DISPELLED = 3, DATA_FIGHT_PHASE = 4, - DATA_EVADE_METHOD = 5, - DATA_SPAWNED_FLAMES = 6, + DATA_SPAWNED_FLAMES = 5, }; enum OrbCarrierSeats @@ -189,6 +191,7 @@ enum CorporealityEvent }; Position const HalionSpawnPos = {3156.67f, 533.8108f, 72.98822f, 3.159046f}; +Position const HalionRespawnPos = {3156.625f, 533.2674f, 72.97205f, 0.0f}; uint8 const MAX_CORPOREALITY_STATE = 11; @@ -212,132 +215,39 @@ CorporealityEntry const _corporealityReference[MAX_CORPOREALITY_STATE] = { {74831, 74836} }; -struct generic_halionAI : public BossAI -{ - generic_halionAI(Creature* creature, uint32 bossId) : BossAI(creature, bossId), _canEvade(false) { } - - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - me->AddAura(SPELL_TWILIGHT_PRECISION, me); - _canEvade = false; - events.ScheduleEvent(EVENT_CLEAVE, urand(8000, 10000)); - events.ScheduleEvent(EVENT_TAIL_LASH, 10000); - events.ScheduleEvent(EVENT_BREATH, urand(10000, 15000)); - } - - void Reset() override - { - _canEvade = false; - _Reset(); - } - - void JustReachedHome() override - { - instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); - _JustReachedHome(); - } - - void ExecuteEvent(uint32 eventId) override - { - switch (eventId) - { - case EVENT_CLEAVE: - DoCastVictim(SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, urand(8000, 10000)); - break; - case EVENT_TAIL_LASH: - DoCastAOE(SPELL_TAIL_LASH); - events.ScheduleEvent(EVENT_TAIL_LASH, 10000); - break; - case EVENT_BREATH: - DoCast(me, me->GetEntry() == NPC_HALION ? SPELL_FLAME_BREATH : SPELL_DARK_BREATH); - events.ScheduleEvent(EVENT_BREATH, urand(10000, 12000)); - break; - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING)) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - ExecuteEvent(eventId); - - DoMeleeAttackIfReady(); - } - - void SetData(uint32 index, uint32 dataValue) override - { - switch (index) - { - case DATA_EVADE_METHOD: - _canEvade = (dataValue == 1); - break; - default: - break; - } - } - - void SpellHit(Unit* /*who*/, SpellInfo const* spellInfo) override - { - if (spellInfo->Id == SPELL_TWILIGHT_MENDING) - Talk(SAY_REGENERATE); - } - -protected: - bool _canEvade; -}; - class boss_halion : public CreatureScript { public: boss_halion() : CreatureScript("boss_halion") { } - struct boss_halionAI : public generic_halionAI + struct boss_halionAI : public BossAI { - boss_halionAI(Creature* creature) : generic_halionAI(creature, DATA_HALION) - { - me->SetHomePosition(HalionSpawnPos); - } - - void Reset() override - { - generic_halionAI::Reset(); - me->SetReactState(REACT_DEFENSIVE); - me->RemoveAurasDueToSpell(SPELL_TWILIGHT_PHASING); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } + boss_halionAI(Creature* creature) : BossAI(creature, DATA_HALION) { } void EnterEvadeMode(EvadeReason why) override { - if (why == EVADE_REASON_BOUNDARY) + if (why == EVADE_REASON_BOUNDARY || events.IsInPhase(PHASE_ONE)) if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) - controller->AI()->EnterEvadeMode(); - - // Phase 1: We always can evade. Phase 2 & 3: We can evade if and only if the controller tells us to. - if (events.IsInPhase(PHASE_ONE) || _canEvade) - generic_halionAI::EnterEvadeMode(why); + controller->AI()->EnterEvadeMode(why); } - void EnterCombat(Unit* who) override + void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); events.Reset(); events.SetPhase(PHASE_ONE); - generic_halionAI::EnterCombat(who); + _EnterCombat(); + me->AddAura(SPELL_TWILIGHT_PRECISION, me); + events.ScheduleEvent(EVENT_ACTIVATE_FIREWALL, Seconds(5)); + events.ScheduleEvent(EVENT_BREATH, randtime(Seconds(5), Seconds(15))); + events.ScheduleEvent(EVENT_CLEAVE, randtime(Seconds(6), Seconds(10))); + events.ScheduleEvent(EVENT_TAIL_LASH, randtime(Seconds(7), Seconds(12))); + events.ScheduleEvent(EVENT_FIERY_COMBUSTION, randtime(Seconds(15), Seconds(18))); + events.ScheduleEvent(EVENT_METEOR_STRIKE, Seconds(18)); instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 1); - instance->SetBossState(DATA_HALION, IN_PROGRESS); - - events.ScheduleEvent(EVENT_ACTIVATE_FIREWALL, 5000); - events.ScheduleEvent(EVENT_METEOR_STRIKE, urand(20000, 25000)); - events.ScheduleEvent(EVENT_FIERY_COMBUSTION, urand(15000, 18000)); if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) controller->AI()->SetData(DATA_FIGHT_PHASE, PHASE_ONE); @@ -388,58 +298,76 @@ class boss_halion : public CreatureScript } } + void SpellHit(Unit* /*who*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_TWILIGHT_MENDING) + Talk(SAY_REGENERATE); + } + void UpdateAI(uint32 diff) override { if (events.IsInPhase(PHASE_TWO)) return; - generic_halionAI::UpdateAI(diff); - } + if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING)) + return; - void ExecuteEvent(uint32 eventId) override - { - switch (eventId) + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_ACTIVATE_FIREWALL: - // Flame ring is activated 5 seconds after starting encounter, DOOR_TYPE_ROOM is only instant. - for (uint8 i = DATA_FLAME_RING; i <= DATA_TWILIGHT_FLAME_RING; ++i) - if (GameObject* flameRing = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(i))) - instance->HandleGameObject(instance->GetGuidData(DATA_FLAME_RING), false, flameRing); - break; - case EVENT_METEOR_STRIKE: + switch (eventId) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_TWILIGHT_REALM)) + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, randtime(Seconds(8), Seconds(10))); + break; + case EVENT_TAIL_LASH: + DoCastAOE(SPELL_TAIL_LASH); + events.ScheduleEvent(EVENT_TAIL_LASH, randtime(Seconds(11), Seconds(16))); + break; + case EVENT_BREATH: + DoCast(me, SPELL_FLAME_BREATH); + events.ScheduleEvent(EVENT_BREATH, randtime(Seconds(16), Seconds(25))); + break; + case EVENT_ACTIVATE_FIREWALL: + // Flame ring is activated 5 seconds after starting encounter, DOOR_TYPE_ROOM is only instant. + for (uint8 i = DATA_FLAME_RING; i <= DATA_TWILIGHT_FLAME_RING; ++i) + if (GameObject* flameRing = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(i))) + instance->HandleGameObject(instance->GetGuidData(DATA_FLAME_RING), false, flameRing); + break; + case EVENT_METEOR_STRIKE: { - _meteorStrikePos = target->GetPosition(); - me->CastSpell(_meteorStrikePos.GetPositionX(), _meteorStrikePos.GetPositionY(), _meteorStrikePos.GetPositionZ(), SPELL_METEOR_STRIKE, true, NULL, NULL, me->GetGUID()); - Talk(SAY_METEOR_STRIKE); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_TWILIGHT_REALM)) + { + _meteorStrikePos = target->GetPosition(); + me->CastSpell(_meteorStrikePos.GetPositionX(), _meteorStrikePos.GetPositionY(), _meteorStrikePos.GetPositionZ(), SPELL_METEOR_STRIKE, true, nullptr, nullptr, me->GetGUID()); + Talk(SAY_METEOR_STRIKE); + } + events.ScheduleEvent(EVENT_METEOR_STRIKE, Seconds(38)); + break; } - events.ScheduleEvent(EVENT_METEOR_STRIKE, 40000); - break; - } - case EVENT_FIERY_COMBUSTION: - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_TWILIGHT_REALM)) - DoCast(target, SPELL_FIERY_COMBUSTION); - events.ScheduleEvent(EVENT_FIERY_COMBUSTION, 25000); - break; + case EVENT_FIERY_COMBUSTION: + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_TWILIGHT_REALM)) + me->CastSpell(target, SPELL_FIERY_COMBUSTION, TRIGGERED_IGNORE_SET_FACING); + events.ScheduleEvent(EVENT_FIERY_COMBUSTION, Seconds(25)); + break; + } + default: + break; } - default: - generic_halionAI::ExecuteEvent(eventId); - break; } + + DoMeleeAttackIfReady(); } void SetData(uint32 index, uint32 value) override { - switch (index) - { - case DATA_FIGHT_PHASE: - events.SetPhase(value); - break; - default: - generic_halionAI::SetData(index, value); - } + if (index != DATA_FIGHT_PHASE) + return; + + events.SetPhase(value); } private: @@ -459,9 +387,9 @@ class boss_twilight_halion : public CreatureScript public: boss_twilight_halion() : CreatureScript("boss_twilight_halion") { } - struct boss_twilight_halionAI : public generic_halionAI + struct boss_twilight_halionAI : public BossAI { - boss_twilight_halionAI(Creature* creature) : generic_halionAI(creature, DATA_TWILIGHT_HALION) + boss_twilight_halionAI(Creature* creature) : BossAI(creature, DATA_TWILIGHT_HALION) { Creature* halion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION)); if (!halion) @@ -470,26 +398,29 @@ class boss_twilight_halion : public CreatureScript // Using AddAura because no spell cast packet in sniffs. halion->AddAura(SPELL_COPY_DAMAGE, me); // We use explicit targeting here to avoid conditions + SPELL_ATTR6_CANT_TARGET_SELF. me->AddAura(SPELL_COPY_DAMAGE, halion); - me->AddAura(SPELL_DUSK_SHROUD, me); + DoCast(me, SPELL_DUSK_SHROUD, true); me->SetHealth(halion->GetHealth()); me->SetPhaseMask(0x20, true); - me->SetReactState(REACT_AGGRESSIVE); + me->SetReactState(REACT_DEFENSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + events.ScheduleEvent(EVENT_TAIL_LASH, Seconds(12)); + events.ScheduleEvent(EVENT_SOUL_CONSUMPTION, Seconds(15)); } - void EnterCombat(Unit* who) override + void EnterCombat(Unit* /*who*/) override { - events.Reset(); events.SetPhase(PHASE_TWO); - generic_halionAI::EnterCombat(who); - - events.ScheduleEvent(EVENT_SOUL_CONSUMPTION, 20000); + _EnterCombat(); + me->AddAura(SPELL_TWILIGHT_PRECISION, me); + events.ScheduleEvent(EVENT_CLEAVE, Seconds(3)); + events.ScheduleEvent(EVENT_BREATH, Seconds(12)); instance->SendEncounterUnit(ENCOUNTER_FRAME_ENGAGE, me, 2); } - // Never evade + void Reset() override { } void EnterEvadeMode(EvadeReason /*why*/) override { } void KilledUnit(Unit* victim) override @@ -522,6 +453,10 @@ class boss_twilight_halion : public CreatureScript void DamageTaken(Unit* attacker, uint32& damage) override { + //Needed because we already have UNIT_FLAG_IN_COMBAT, otherwise EnterCombat won't ever be called + if (!events.IsInPhase(PHASE_TWO) && !events.IsInPhase(PHASE_THREE)) + EnterCombat(attacker); + if (me->HealthBelowPctDamaged(50, damage) && events.IsInPhase(PHASE_TWO)) { events.SetPhase(PHASE_THREE); @@ -542,7 +477,7 @@ class boss_twilight_halion : public CreatureScript } } - void SpellHit(Unit* who, SpellInfo const* spell) override + void SpellHit(Unit* /*who*/, SpellInfo const* spell) override { switch (spell->Id) { @@ -550,25 +485,51 @@ class boss_twilight_halion : public CreatureScript if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) controller->AI()->DoAction(ACTION_MONITOR_CORPOREALITY); break; + case SPELL_TWILIGHT_MENDING: + Talk(SAY_REGENERATE); + break; default: - generic_halionAI::SpellHit(who, spell); break; } } - void ExecuteEvent(uint32 eventId) override + void UpdateAI(uint32 diff) override { - switch (eventId) + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_SOUL_CONSUMPTION: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, SPELL_TWILIGHT_REALM)) - DoCast(target, SPELL_SOUL_CONSUMPTION); - events.ScheduleEvent(EVENT_SOUL_CONSUMPTION, 20000); - break; - default: - generic_halionAI::ExecuteEvent(eventId); - break; + switch (eventId) + { + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, randtime(Seconds(7), Seconds(10))); + break; + case EVENT_TAIL_LASH: + DoCastAOE(SPELL_TAIL_LASH); + events.ScheduleEvent(EVENT_TAIL_LASH, randtime(Seconds(12), Seconds(16))); + break; + case EVENT_BREATH: + DoCast(me, SPELL_DARK_BREATH); + events.ScheduleEvent(EVENT_BREATH, randtime(Seconds(10), Seconds(14))); + break; + case EVENT_SOUL_CONSUMPTION: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, SPELL_TWILIGHT_REALM)) + me->CastSpell(target, SPELL_SOUL_CONSUMPTION, TRIGGERED_IGNORE_SET_FACING); + events.ScheduleEvent(EVENT_SOUL_CONSUMPTION, Seconds(20)); + break; + default: + break; + } } + + DoMeleeAttackIfReady(); } }; @@ -589,7 +550,6 @@ class npc_halion_controller : public CreatureScript _instance(creature->GetInstanceScript()), _summons(me) { Initialize(); - me->SetPhaseMask(me->GetPhaseMask() | 0x20, true); } void Initialize() @@ -599,6 +559,15 @@ class npc_halion_controller : public CreatureScript _twilightDamageTaken = 0; } + void JustRespawned() override + { + if (_instance->GetGuidData(DATA_HALION)) + return; + + Reset(); + me->GetMap()->SummonCreature(NPC_HALION, HalionRespawnPos); + } + void Reset() override { _summons.DespawnAll(); @@ -626,21 +595,36 @@ class npc_halion_controller : public CreatureScript _twilightDamageTaken = 0; _materialDamageTaken = 0; - _events.ScheduleEvent(EVENT_TRIGGER_BERSERK, 8 * MINUTE * IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_TRIGGER_BERSERK, Minutes(8)); } - void JustReachedHome() override + void EnterEvadeMode(EvadeReason /*why*/) override { if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_TWILIGHT_HALION))) + { twilightHalion->DespawnOrUnsummon(); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, twilightHalion); + } if (Creature* halion = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION))) { - halion->AI()->SetData(DATA_EVADE_METHOD, 1); - halion->AI()->EnterEvadeMode(); + halion->DespawnOrUnsummon(); + _instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, halion); } _instance->SetBossState(DATA_HALION, FAIL); + _summons.DespawnAll(); + + uint32 corpseDelay = me->GetCorpseDelay(); + uint32 respawnDelay = me->GetRespawnDelay(); + + me->SetCorpseDelay(1); + me->SetRespawnDelay(30); + + me->DespawnOrUnsummon(); + + me->SetCorpseDelay(corpseDelay); + me->SetRespawnDelay(respawnDelay); } void DoAction(int32 action) override @@ -650,7 +634,16 @@ class npc_halion_controller : public CreatureScript case ACTION_INTRO_HALION: _events.Reset(); _events.SetPhase(PHASE_INTRO); - _events.ScheduleEvent(EVENT_START_INTRO, 2000); + _events.ScheduleEvent(EVENT_START_INTRO, Seconds(2)); + break; + case ACTION_INTRO_HALION_2: + if (_instance->GetGuidData(DATA_HALION)) + return; + + for (uint8 i = DATA_BURNING_TREE_1; i <= DATA_BURNING_TREE_4; ++i) + if (GameObject* tree = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(i))) + _instance->HandleGameObject(_instance->GetGuidData(i), true, tree); + me->GetMap()->SummonCreature(NPC_HALION, HalionRespawnPos); break; case ACTION_MONITOR_CORPOREALITY: { @@ -678,8 +671,12 @@ class npc_halion_controller : public CreatureScript _instance->DoUpdateWorldState(WORLDSTATE_CORPOREALITY_MATERIAL, 50); _instance->DoUpdateWorldState(WORLDSTATE_CORPOREALITY_TWILIGHT, 50); - _events.ScheduleEvent(EVENT_CHECK_CORPOREALITY, 7500); + _events.ScheduleEvent(EVENT_CHECK_CORPOREALITY, Seconds(7)); + break; } + case ACTION_ACTIVATE_EMBERS: + _events.ScheduleEvent(EVENT_ACTIVATE_EMBERS, Seconds(6)); + break; default: break; } @@ -692,7 +689,7 @@ class npc_halion_controller : public CreatureScript // combat state. if (!_events.IsInPhase(PHASE_INTRO) && me->IsInCombat() && !UpdateVictim()) { - EnterEvadeMode(); + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return; } @@ -704,29 +701,31 @@ class npc_halion_controller : public CreatureScript { case EVENT_START_INTRO: DoCast(me, SPELL_COSMETIC_FIRE_PILLAR, true); - _events.ScheduleEvent(EVENT_INTRO_PROGRESS_1, 4000); + _events.ScheduleEvent(EVENT_INTRO_PROGRESS_1, Seconds(4)); break; case EVENT_INTRO_PROGRESS_1: for (uint8 i = DATA_BURNING_TREE_3; i <= DATA_BURNING_TREE_4; ++i) if (GameObject* tree = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(i))) _instance->HandleGameObject(_instance->GetGuidData(i), true, tree); - _events.ScheduleEvent(EVENT_INTRO_PROGRESS_2, 4000); + _events.ScheduleEvent(EVENT_INTRO_PROGRESS_2, Seconds(4)); break; case EVENT_INTRO_PROGRESS_2: for (uint8 i = DATA_BURNING_TREE_1; i <= DATA_BURNING_TREE_2; ++i) if (GameObject* tree = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(i))) _instance->HandleGameObject(_instance->GetGuidData(i), true, tree); - _events.ScheduleEvent(EVENT_INTRO_PROGRESS_3, 4000); + _events.ScheduleEvent(EVENT_INTRO_PROGRESS_3, Seconds(4)); break; case EVENT_INTRO_PROGRESS_3: DoCast(me, SPELL_FIERY_EXPLOSION); + if (_instance->GetGuidData(DATA_HALION)) + return; if (Creature* halion = me->GetMap()->SummonCreature(NPC_HALION, HalionSpawnPos)) halion->AI()->Talk(SAY_INTRO); break; case EVENT_TWILIGHT_MENDING: if (ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION))) // Just check if physical Halion is spawned if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_TWILIGHT_HALION))) - twilightHalion->CastSpell((Unit*)NULL, SPELL_TWILIGHT_MENDING, true); + twilightHalion->CastSpell((Unit*)nullptr, SPELL_TWILIGHT_MENDING, true); break; case EVENT_TRIGGER_BERSERK: for (uint8 i = DATA_HALION; i <= DATA_TWILIGHT_HALION; i++) @@ -734,17 +733,16 @@ class npc_halion_controller : public CreatureScript halion->CastSpell(halion, SPELL_BERSERK, true); break; case EVENT_SHADOW_PULSARS_SHOOT: - if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_TWILIGHT_HALION))) - twilightHalion->AI()->Talk(SAY_SPHERE_PULSE); - if (Creature* orbCarrier = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_ORB_CARRIER))) - orbCarrier->AI()->DoAction(ACTION_SHOOT); - - _events.ScheduleEvent(EVENT_SHADOW_PULSARS_SHOOT, 29000); + orbCarrier->AI()->DoAction(ACTION_WARNING_SHOOT); + _events.ScheduleEvent(EVENT_SHADOW_PULSARS_SHOOT, Seconds(30)); break; case EVENT_CHECK_CORPOREALITY: UpdateCorporeality(); - _events.ScheduleEvent(EVENT_CHECK_CORPOREALITY, 5000); + _events.ScheduleEvent(EVENT_CHECK_CORPOREALITY, Seconds(5)); + break; + case EVENT_ACTIVATE_EMBERS: + _summons.DoZoneInCombat(NPC_LIVING_EMBER); break; default: break; @@ -770,7 +768,7 @@ class npc_halion_controller : public CreatureScript DoZoneInCombat(); break; case PHASE_TWO: - _events.ScheduleEvent(EVENT_SHADOW_PULSARS_SHOOT, 29000); + _events.ScheduleEvent(EVENT_SHADOW_PULSARS_SHOOT, Seconds(35)); break; default: break; @@ -793,7 +791,7 @@ class npc_halion_controller : public CreatureScript uint8 oldValue = _materialCorporealityValue; if (_twilightDamageTaken == 0 || _materialDamageTaken == 0) { - _events.ScheduleEvent(EVENT_TWILIGHT_MENDING, 100); + _events.ScheduleEvent(EVENT_TWILIGHT_MENDING, Milliseconds(100)); _twilightDamageTaken = 0; _materialDamageTaken = 0; return; @@ -833,7 +831,7 @@ class npc_halion_controller : public CreatureScript } case CORPOREALITY_TWILIGHT_MENDING: { - _events.ScheduleEvent(EVENT_TWILIGHT_MENDING, 100); + _events.ScheduleEvent(EVENT_TWILIGHT_MENDING, Milliseconds(100)); _materialDamageTaken = 0; _twilightDamageTaken = 0; return; @@ -889,52 +887,73 @@ class npc_orb_carrier : public CreatureScript struct npc_orb_carrierAI : public ScriptedAI { npc_orb_carrierAI(Creature* creature) : ScriptedAI(creature), - instance(creature->GetInstanceScript()) + _instance(creature->GetInstanceScript()) { ASSERT(creature->GetVehicleKit()); } - void UpdateAI(uint32 /*diff*/) override + void UpdateAI(uint32 diff) override { /// According to sniffs this spell is cast every 1 or 2 seconds. /// However, refreshing it looks bad, so just cast the spell if /// we are not channeling it. if (!me->HasUnitState(UNIT_STATE_CASTING)) - me->CastSpell((Unit*)NULL, SPELL_TRACK_ROTATION, false); + me->CastSpell((Unit*)nullptr, SPELL_TRACK_ROTATION, false); + + scheduler.Update(diff); /// Workaround: This is here because even though the above spell has SPELL_ATTR1_CHANNEL_TRACK_TARGET, /// we are having two creatures involded here. This attribute is handled clientside, meaning the client /// sends orientation update itself. Here, no packet is sent, and the creature does not rotate. By /// forcing the carrier to always be facing the rotation focus, we ensure everything works as it should. - if (Creature* rotationFocus = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ORB_ROTATION_FOCUS))) + if (Creature* rotationFocus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_ORB_ROTATION_FOCUS))) me->SetFacingToObject(rotationFocus); // setInFront } void DoAction(int32 action) override { - if (action == ACTION_SHOOT) + switch (action) { - Vehicle* vehicle = me->GetVehicleKit(); - Unit* southOrb = vehicle->GetPassenger(SEAT_SOUTH); - Unit* northOrb = vehicle->GetPassenger(SEAT_NORTH); - if (southOrb && northOrb) + case ACTION_WARNING_SHOOT: { - if (northOrb->GetTypeId() == TYPEID_UNIT) + Vehicle* vehicle = me->GetVehicleKit(); + Unit* northOrb = vehicle->GetPassenger(SEAT_NORTH); + if (northOrb && northOrb->GetTypeId() == TYPEID_UNIT) northOrb->ToCreature()->AI()->Talk(EMOTE_WARN_LASER); - TriggerCutter(northOrb, southOrb); + + scheduler.Schedule(Seconds(5), [this](TaskContext /*context*/) + { + DoAction(ACTION_SHOOT); + }); + break; } + case ACTION_SHOOT: + { + Vehicle* vehicle = me->GetVehicleKit(); + Unit* southOrb = vehicle->GetPassenger(SEAT_SOUTH); + Unit* northOrb = vehicle->GetPassenger(SEAT_NORTH); + if (southOrb && northOrb) + TriggerCutter(northOrb, southOrb); - if (!IsHeroic()) - return; + if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_TWILIGHT_HALION))) + twilightHalion->AI()->Talk(SAY_SPHERE_PULSE); + + if (!IsHeroic()) + return; - Unit* eastOrb = vehicle->GetPassenger(SEAT_EAST); - Unit* westOrb = vehicle->GetPassenger(SEAT_WEST); - if (eastOrb && westOrb) - TriggerCutter(eastOrb, westOrb); + Unit* eastOrb = vehicle->GetPassenger(SEAT_EAST); + Unit* westOrb = vehicle->GetPassenger(SEAT_WEST); + if (eastOrb && westOrb) + TriggerCutter(eastOrb, westOrb); + break; + } + default: + break; } } private: - InstanceScript* instance; + InstanceScript* _instance; + TaskScheduler scheduler; void TriggerCutter(Unit* caster, Unit* target) { @@ -987,12 +1006,12 @@ class npc_meteor_strike_initial : public CreatureScript controller->AI()->JustSummoned(me); DoCast(me, SPELL_METEOR_STRIKE_COUNTDOWN); - DoCast(me, SPELL_BIRTH_NO_VISUAL); // Unknown purpose + DoCast(me, SPELL_BIRTH_NO_VISUAL); if (HalionAI* halionAI = CAST_AI(HalionAI, owner->AI())) { Position const* ownerPos = halionAI->GetMeteorStrikePosition(); - float randomAdjustment = frand(0.0f, static_cast<float>(M_PI / 5.0f)); + float randomAdjustment = frand(static_cast<float>(M_PI / 5.0f), static_cast<float>(M_PI / 2.0f)); float angle[4]; angle[0] = me->GetAngle(ownerPos); angle[1] = angle[0] + randomAdjustment; @@ -1006,10 +1025,7 @@ class npc_meteor_strike_initial : public CreatureScript me->SetOrientation(angle[i]); Position newPos = me->GetNearPosition(10.0f, 0.0f); // Exact distance if (Creature* meteor = me->SummonCreature(NPC_METEOR_STRIKE_NORTH + i, newPos, TEMPSUMMON_TIMED_DESPAWN, 30000)) - { - meteor->SetOrientation(angle[i]); _meteorList.push_back(meteor); - } } } } @@ -1046,7 +1062,7 @@ class npc_meteor_strike : public CreatureScript { DoCast(me, SPELL_METEOR_STRIKE_FIRE_AURA_2, true); me->setActive(true); - _events.ScheduleEvent(EVENT_SPAWN_METEOR_FLAME, 500); + _events.ScheduleEvent(EVENT_SPAWN_METEOR_FLAME, Milliseconds(500)); } } @@ -1110,7 +1126,7 @@ class npc_meteor_strike_flame : public CreatureScript void SetGUID(ObjectGuid guid, int32 /*id = 0 */) override { _rootOwnerGuid = guid; - _events.ScheduleEvent(EVENT_SPAWN_METEOR_FLAME, 800); + _events.ScheduleEvent(EVENT_SPAWN_METEOR_FLAME, Milliseconds(800)); } void IsSummonedBy(Unit* /*summoner*/) override @@ -1202,7 +1218,7 @@ class npc_combustion_consumption : public CreatureScript if (type != DATA_STACKS_DISPELLED || !_damageSpell || !_explosionSpell || !summoner) return; - me->CastCustomSpell(SPELL_SCALE_AURA, SPELLVALUE_AURA_STACK, stackAmount, me); + me->CastCustomSpell(SPELL_SCALE_AURA, SPELLVALUE_AURA_STACK, stackAmount + 1, me); DoCast(me, _damageSpell); int32 damage = 1200 + (stackAmount * 1290); // Needs more research. @@ -1240,17 +1256,32 @@ class npc_living_inferno : public CreatureScript // SMSG_SPELL_GO for the living ember stuff isn't even sent to the client - Blizzard on drugs. if (me->GetMap()->GetDifficulty() == RAID_DIFFICULTY_25MAN_HEROIC) - me->CastSpell(me, SPELL_SPAWN_LIVING_EMBERS, true); + scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/) + { + me->CastSpell(me, SPELL_SPAWN_LIVING_EMBERS, true); + }); if (InstanceScript* instance = me->GetInstanceScript()) if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) + { + controller->AI()->DoAction(ACTION_ACTIVATE_EMBERS); controller->AI()->JustSummoned(me); + } } void JustDied(Unit* /*killer*/) override { me->DespawnOrUnsummon(1); } + + void UpdateAI(uint32 diff) override + { + scheduler.Update(diff); + ScriptedAI::UpdateAI(diff); + } + + private: + TaskScheduler scheduler; }; CreatureAI* GetAI(Creature* creature) const override @@ -1266,27 +1297,7 @@ class npc_living_ember : public CreatureScript struct npc_living_emberAI : public ScriptedAI { - npc_living_emberAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - _enrageTimer = 0; - } - - void Initialize() - { - _hasEnraged = false; - } - - void Reset() override - { - Initialize(); - } - - void EnterCombat(Unit* /*who*/) override - { - _enrageTimer = 20000; - _hasEnraged = false; - } + npc_living_emberAI(Creature* creature) : ScriptedAI(creature) { } void IsSummonedBy(Unit* /*summoner*/) override { @@ -1299,25 +1310,6 @@ class npc_living_ember : public CreatureScript { me->DespawnOrUnsummon(1); } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim() || me->HasUnitState(UNIT_STATE_CASTING)) - return; - - if (!_hasEnraged && _enrageTimer <= diff) - { - _hasEnraged = true; - DoCast(me, SPELL_BERSERK); - } - else _enrageTimer -= diff; - - DoMeleeAttackIfReady(); - } - - private: - uint32 _enrageTimer; - bool _hasEnraged; }; CreatureAI* GetAI(Creature* creature) const override @@ -1473,6 +1465,47 @@ class spell_halion_combustion_consumption : public SpellScriptLoader uint32 _spellID; }; +class spell_halion_combustion_consumption_periodic : public SpellScriptLoader +{ + public: + spell_halion_combustion_consumption_periodic() : SpellScriptLoader("spell_halion_combustion_consumption_periodic") { } + + class spell_halion_combustion_consumption_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_halion_combustion_consumption_periodic_AuraScript); + + bool Validate(SpellInfo const* spellInfo) override + { + if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell)) + return false; + return true; + } + + void HandleTick(AuraEffect const* aurEff) + { + PreventDefaultAction(); + Unit* caster = GetCaster(); + if (!caster) + return; + + uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; + int32 radius = caster->GetObjectScale() * M_PI * 10000 / 3; + + caster->CastCustomSpell(triggerSpell, SPELLVALUE_RADIUS_MOD, radius, (Unit*)nullptr, TRIGGERED_FULL_MASK, nullptr, aurEff, caster->GetGUID()); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_halion_combustion_consumption_periodic_AuraScript::HandleTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_halion_combustion_consumption_periodic_AuraScript(); + } +}; + class spell_halion_marks : public SpellScriptLoader { public: @@ -1511,7 +1544,7 @@ class spell_halion_marks : public SpellScriptLoader return; // Stacks marker - GetTarget()->CastCustomSpell(_summonSpellId, SPELLVALUE_BASE_POINT1, aurEff->GetBase()->GetStackAmount(), GetTarget(), TRIGGERED_FULL_MASK, NULL, NULL, GetCasterGUID()); + GetTarget()->CastCustomSpell(_summonSpellId, SPELLVALUE_BASE_POINT1, aurEff->GetBase()->GetStackAmount(), GetTarget(), TRIGGERED_FULL_MASK, nullptr, nullptr, GetCasterGUID()); } void Register() override @@ -1819,6 +1852,35 @@ class spell_halion_spawn_living_embers : public SpellScriptLoader } }; +class spell_halion_blazing_aura : public SpellScriptLoader +{ + public: + spell_halion_blazing_aura() : SpellScriptLoader("spell_halion_blazing_aura") { } + + class spell_halion_blazing_aura_SpellScript : public SpellScript + { + PrepareSpellScript(spell_halion_blazing_aura_SpellScript); + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetHitUnit()->CastSpell(GetHitUnit(), GetSpellInfo()->Effects[EFFECT_1].TriggerSpell); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_halion_blazing_aura_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_FORCE_CAST); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_halion_blazing_aura_SpellScript(); + } +}; + + + void AddSC_boss_halion() { new boss_halion(); @@ -1840,6 +1902,7 @@ void AddSC_boss_halion() new spell_halion_combustion_consumption("spell_halion_fiery_combustion", SPELL_MARK_OF_COMBUSTION); new spell_halion_marks("spell_halion_mark_of_combustion", SPELL_FIERY_COMBUSTION_SUMMON, SPELL_FIERY_COMBUSTION); new spell_halion_marks("spell_halion_mark_of_consumption", SPELL_SOUL_CONSUMPTION_SUMMON, SPELL_SOUL_CONSUMPTION); + new spell_halion_combustion_consumption_periodic(); new spell_halion_damage_aoe_summon(); new spell_halion_twilight_realm_handlers("spell_halion_leave_twilight_realm", SPELL_SOUL_CONSUMPTION, false); new spell_halion_twilight_realm_handlers("spell_halion_enter_twilight_realm", SPELL_FIERY_COMBUSTION, true); @@ -1848,4 +1911,5 @@ void AddSC_boss_halion() new spell_halion_twilight_cutter(); new spell_halion_clear_debuffs(); new spell_halion_spawn_living_embers(); + new spell_halion_blazing_aura(); } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp index a6cd8362db3..be85d3dc99c 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/instance_ruby_sanctum.cpp @@ -23,7 +23,7 @@ #include "WorldPacket.h" #include "ruby_sanctum.h" -BossBoundaryData const boundaries = +BossBoundaryData const boundaries = { { DATA_GENERAL_ZARITHRIAN, new EllipseBoundary(Position(3013.409f, 529.492f), 45.0, 100.0) }, { DATA_HALION, new CircleBoundary(Position(3156.037f, 533.2656f), 48.5) } @@ -53,11 +53,11 @@ class instance_ruby_sanctum : public InstanceMapScript void OnPlayerEnter(Player* /*player*/) override { - if (!GetGuidData(DATA_HALION_CONTROLLER) && GetBossState(DATA_HALION) != DONE && GetBossState(DATA_GENERAL_ZARITHRIAN) == DONE) + if (!GetGuidData(DATA_HALION) && GetBossState(DATA_HALION) != DONE && GetBossState(DATA_GENERAL_ZARITHRIAN) == DONE) { instance->LoadGrid(HalionControllerSpawnPos.GetPositionX(), HalionControllerSpawnPos.GetPositionY()); - if (Creature* halionController = instance->SummonCreature(NPC_HALION_CONTROLLER, HalionControllerSpawnPos)) - halionController->AI()->DoAction(ACTION_INTRO_HALION); + if (Creature* halionController = instance->GetCreature(GetGuidData(DATA_HALION_CONTROLLER))) + halionController->AI()->DoAction(ACTION_INTRO_HALION_2); } } @@ -161,6 +161,12 @@ class instance_ruby_sanctum : public InstanceMapScript } } + void OnCreatureRemove(Creature* creature) override + { + if (creature->GetEntry() == NPC_HALION) + HalionGUID = ObjectGuid::Empty; + } + void OnUnitDeath(Unit* unit) override { Creature* creature = unit->ToCreature(); @@ -170,7 +176,7 @@ class instance_ruby_sanctum : public InstanceMapScript if (creature->GetEntry() == NPC_GENERAL_ZARITHRIAN && GetBossState(DATA_HALION) != DONE) { instance->LoadGrid(HalionControllerSpawnPos.GetPositionX(), HalionControllerSpawnPos.GetPositionY()); - if (Creature* halionController = instance->SummonCreature(NPC_HALION_CONTROLLER, HalionControllerSpawnPos)) + if (Creature* halionController = instance->GetCreature(GetGuidData(DATA_HALION_CONTROLLER))) halionController->AI()->DoAction(ACTION_INTRO_HALION); } } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp index ae4a5e2a69a..9235b75d53e 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.cpp @@ -18,6 +18,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" +#include "SpellScript.h" #include "ruby_sanctum.h" #include "Player.h" @@ -45,6 +46,11 @@ enum Events EVENT_XERESTRASZA_EVENT_7 = 7, }; +enum Spells +{ + SPELL_RALLY = 75416 +}; + Position const xerestraszaMovePos = {3151.236f, 379.8733f, 86.31996f, 0.0f}; class npc_xerestrasza : public CreatureScript @@ -165,8 +171,53 @@ class at_baltharus_plateau : public AreaTriggerScript } }; +// 75415 - Rallying Shout +class spell_ruby_sanctum_rallying_shout : public SpellScriptLoader +{ + public: + spell_ruby_sanctum_rallying_shout() : SpellScriptLoader("spell_ruby_sanctum_rallying_shout") { } + + class spell_ruby_sanctum_rallying_shout_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ruby_sanctum_rallying_shout_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_RALLY)) + return false; + return true; + } + + void CountTargets(std::list<WorldObject*>& targets) + { + _targetCount = targets.size(); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (_targetCount && !GetCaster()->HasAura(SPELL_RALLY)) + GetCaster()->CastCustomSpell(SPELL_RALLY, SPELLVALUE_AURA_STACK, _targetCount, GetCaster(), TRIGGERED_FULL_MASK); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ruby_sanctum_rallying_shout_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnEffectHit += SpellEffectFn(spell_ruby_sanctum_rallying_shout_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + + private: + uint32 _targetCount = 0; + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ruby_sanctum_rallying_shout_SpellScript(); + } +}; + void AddSC_ruby_sanctum() { new npc_xerestrasza(); new at_baltharus_plateau(); + new spell_ruby_sanctum_rallying_shout(); } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.h b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.h index 69c27a22ea0..333fef1dc85 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.h +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/ruby_sanctum.h @@ -56,6 +56,7 @@ enum SharedActions ACTION_INTRO_BALTHARUS = -3975101, ACTION_BALTHARUS_DEATH = -3975102, ACTION_INTRO_HALION = -4014601, + ACTION_INTRO_HALION_2 = -4014602, }; enum CreaturesIds diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp index 00900d440c9..f6726d60db3 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp @@ -180,7 +180,7 @@ public: { pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f); pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, G3D::Quat(), 90000); } } } @@ -203,7 +203,7 @@ public: { pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f); pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, G3D::Quat(), 90000); } break; case BOSS_ARGENT_CHALLENGE_P: @@ -212,7 +212,7 @@ public: { pAnnouncer->GetMotionMaster()->MovePoint(0, 748.309f, 619.487f, 411.171f); pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, 0, 0, 0, 0, 90000); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT, 746.59f, 618.49f, 411.09f, 1.42f, G3D::Quat(), 90000); } break; } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index c89510211b9..dfe0cacdef7 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -222,10 +222,10 @@ class boss_anubarak_trial : public CreatureScript instance->SetBossState(BOSS_ANUBARAK, FAIL); //Summon Scarab Swarms neutral at random places for (int i = 0; i < 10; i++) - if (Creature* temp = me->SummonCreature(NPC_SCARAB, AnubarakLoc[1].GetPositionX()+urand(0, 50)-25, AnubarakLoc[1].GetPositionY()+urand(0, 50)-25, AnubarakLoc[1].GetPositionZ())) + if (Creature* scarab = me->SummonCreature(NPC_SCARAB, AnubarakLoc[1].GetPositionX()+urand(0, 50)-25, AnubarakLoc[1].GetPositionY()+urand(0, 50)-25, AnubarakLoc[1].GetPositionZ())) { - temp->setFaction(31); - temp->GetMotionMaster()->MoveRandom(10); + scarab->setFaction(31); + scarab->GetMotionMaster()->MoveRandom(10); } } @@ -804,7 +804,7 @@ class npc_anubarak_spike : public CreatureScript void StartChase(Unit* who) { DoCast(who, SPELL_MARK); - me->SetSpeed(MOVE_RUN, 0.5f); + me->SetSpeedRate(MOVE_RUN, 0.5f); // make sure the Spine will really follow the one he should me->getThreatManager().clearReferences(); me->SetInCombatWithZone(); @@ -881,9 +881,9 @@ class spell_anubarak_leeching_swarm : public SpellScriptLoader if (lifeLeeched < 250) lifeLeeched = 250; // Damage - caster->CastCustomSpell(target, SPELL_LEECHING_SWARM_DMG, &lifeLeeched, 0, 0, false); + caster->CastCustomSpell(target, SPELL_LEECHING_SWARM_DMG, &lifeLeeched, 0, 0, true); // Heal - caster->CastCustomSpell(caster, SPELL_LEECHING_SWARM_HEAL, &lifeLeeched, 0, 0, false); + caster->CastCustomSpell(caster, SPELL_LEECHING_SWARM_HEAL, &lifeLeeched, 0, 0, true); } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp index 6c1b516c7de..ee44e1391b4 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -453,22 +453,22 @@ class boss_toc_champion_controller : public CreatureScript for (uint8 i = 0; i < vChampionEntries.size(); ++i) { uint8 pos = urand(0, vChampionJumpTarget.size()-1); - if (Creature* temp = me->SummonCreature(vChampionEntries[i], vChampionJumpOrigin[urand(0, vChampionJumpOrigin.size()-1)], TEMPSUMMON_MANUAL_DESPAWN)) + if (Creature* champion = me->SummonCreature(vChampionEntries[i], vChampionJumpOrigin[urand(0, vChampionJumpOrigin.size()-1)], TEMPSUMMON_MANUAL_DESPAWN)) { - _summons.Summon(temp); - temp->SetReactState(REACT_PASSIVE); - temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); + _summons.Summon(champion); + champion->SetReactState(REACT_PASSIVE); + champion->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); if (playerTeam == ALLIANCE) { - temp->SetHomePosition(vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 0); - temp->GetMotionMaster()->MoveJump(vChampionJumpTarget[pos], 20.0f, 20.0f); - temp->SetOrientation(0); + champion->SetHomePosition(vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 0); + champion->GetMotionMaster()->MoveJump(vChampionJumpTarget[pos], 20.0f, 20.0f); + champion->SetOrientation(0); } else { - temp->SetHomePosition((ToCCommonLoc[1].GetPositionX()*2)-vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 3); - temp->GetMotionMaster()->MoveJump((ToCCommonLoc[1].GetPositionX() * 2) - vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), vChampionJumpTarget[pos].GetOrientation(), 20.0f, 20.0f); - temp->SetOrientation(3); + champion->SetHomePosition((ToCCommonLoc[1].GetPositionX()*2)-vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), 3); + champion->GetMotionMaster()->MoveJump((ToCCommonLoc[1].GetPositionX() * 2) - vChampionJumpTarget[pos].GetPositionX(), vChampionJumpTarget[pos].GetPositionY(), vChampionJumpTarget[pos].GetPositionZ(), vChampionJumpTarget[pos].GetOrientation(), 20.0f, 20.0f); + champion->SetOrientation(3); } } vChampionJumpTarget.erase(vChampionJumpTarget.begin()+pos); @@ -485,10 +485,10 @@ class boss_toc_champion_controller : public CreatureScript case 1: for (SummonList::iterator i = _summons.begin(); i != _summons.end(); ++i) { - if (Creature* temp = ObjectAccessor::GetCreature(*me, *i)) + if (Creature* summon = ObjectAccessor::GetCreature(*me, *i)) { - temp->SetReactState(REACT_AGGRESSIVE); - temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); + summon->SetReactState(REACT_AGGRESSIVE); + summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); } } break; @@ -640,12 +640,12 @@ struct boss_faction_championsAI : public BossAI if (TeamInInstance == ALLIANCE) { - if (Creature* temp = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_VARIAN))) - temp->AI()->Talk(SAY_KILL_PLAYER); + if (Creature* varian = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_VARIAN))) + varian->AI()->Talk(SAY_KILL_PLAYER); } else - if (Creature* temp = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GARROSH))) - temp->AI()->Talk(SAY_KILL_PLAYER); + if (Creature* garrosh = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GARROSH))) + garrosh->AI()->Talk(SAY_KILL_PLAYER); } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 2fba0c2af42..93823987d78 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -67,10 +67,12 @@ enum BossSpells SPELL_SHIVAN_SLASH = 67098, SPELL_SPINNING_STRIKE = 66283, SPELL_MISTRESS_KISS = 66336, - SPELL_FEL_INFERNO = 67047, - SPELL_FEL_STREAK = 66494, SPELL_LORD_HITTIN = 66326, // special effect preventing more specific spells be cast on the same player within 10 seconds - SPELL_MISTRESS_KISS_DAMAGE_SILENCE = 66359 + SPELL_MISTRESS_KISS_DAMAGE_SILENCE = 66359, + + // Felflame Infernal + SPELL_FEL_STREAK_VISUAL = 66493, + SPELL_FEL_STREAK = 66494, }; enum Events @@ -116,7 +118,7 @@ class boss_jaraxxus : public CreatureScript _JustReachedHome(); instance->SetBossState(BOSS_JARAXXUS, FAIL); DoCast(me, SPELL_JARAXXUS_CHAINS); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); } void KilledUnit(Unit* who) override @@ -305,18 +307,17 @@ class npc_fel_infernal : public CreatureScript { npc_fel_infernalAI(Creature* creature) : ScriptedAI(creature) { - Initialize(); _instance = creature->GetInstanceScript(); } - void Initialize() - { - _felStreakTimer = 30 * IN_MILLISECONDS; - } - void Reset() override { - Initialize(); + _scheduler.Schedule(Seconds(2), [this](TaskContext context) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_FEL_STREAK_VISUAL); + context.Repeat(Seconds(15)); + }); me->SetInCombatWithZone(); } @@ -328,23 +329,20 @@ class npc_fel_infernal : public CreatureScript return; } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + if (!UpdateVictim()) return; - if (_felStreakTimer <= diff) + _scheduler.Update(diff, [this] { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) - DoCast(target, SPELL_FEL_STREAK); - _felStreakTimer = 30*IN_MILLISECONDS; - } - else - _felStreakTimer -= diff; - - DoMeleeAttackIfReady(); + DoMeleeAttackIfReady(); + }); } private: - uint32 _felStreakTimer; InstanceScript* _instance; + TaskScheduler _scheduler; }; CreatureAI* GetAI(Creature* creature) const override @@ -579,6 +577,39 @@ class spell_mistress_kiss_area : public SpellScriptLoader } }; +class spell_fel_streak_visual : public SpellScriptLoader +{ +public: + spell_fel_streak_visual() : SpellScriptLoader("spell_fel_streak_visual") { } + + class spell_fel_streak_visual_SpellScript : public SpellScript + { + PrepareSpellScript(spell_fel_streak_visual_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_FEL_STREAK)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_fel_streak_visual_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_fel_streak_visual_SpellScript(); + } +}; + void AddSC_boss_jaraxxus() { new boss_jaraxxus(); @@ -590,4 +621,5 @@ void AddSC_boss_jaraxxus() new spell_mistress_kiss(); new spell_mistress_kiss_area(); + new spell_fel_streak_visual(); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index e3720503d0a..b2283ec6fde 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -25,6 +25,7 @@ #include "Vehicle.h" #include "Player.h" #include "SpellScript.h" +#include "SpellAuraEffects.h" enum Yells { @@ -33,6 +34,7 @@ enum Yells // Acidmaw & Dreadscale EMOTE_ENRAGE = 0, + SAY_SPECIAL = 1, // Icehowl EMOTE_TRAMPLE_START = 0, @@ -78,22 +80,29 @@ enum BossSpells SPELL_FIRE_BOMB_DOT = 66318, SPELL_HEAD_CRACK = 66407, - //Acidmaw & Dreadscale + //Acidmaw & Dreadscale Generic + SPELL_SWEEP = 66794, + SUMMON_SLIME_POOL = 66883, + SPELL_EMERGE = 66947, + SPELL_SUBMERGE = 66948, + SPELL_ENRAGE = 68335, + SPELL_SLIME_POOL_EFFECT = 66882, //In 60s it diameter grows from 10y to 40y (r=r+0.25 per second) + SPELL_GROUND_VISUAL_0 = 66969, + SPELL_GROUND_VISUAL_1 = 68302, + SPELL_HATE_TO_ZERO = 63984, + //Acidmaw SPELL_ACID_SPIT = 66880, SPELL_PARALYTIC_SPRAY = 66901, - SPELL_ACID_SPEW = 66819, - SPELL_PARALYTIC_BITE = 66824, - SPELL_SWEEP_0 = 66794, - SUMMON_SLIME_POOL = 66883, - SPELL_FIRE_SPIT = 66796, + SPELL_PARALYTIC_BITE = 66824, //Paralytic Toxin + SPELL_ACID_SPEW = 66818, + SPELL_PARALYSIS = 66830, + SPELL_PARALYTIC_TOXIN = 66823, + //Dreadscale + SPELL_BURNING_BITE = 66879, // Burning Bile SPELL_MOLTEN_SPEW = 66821, - SPELL_BURNING_BITE = 66879, + SPELL_FIRE_SPIT = 66796, SPELL_BURNING_SPRAY = 66902, - SPELL_SWEEP_1 = 67646, - SPELL_EMERGE_0 = 66947, - SPELL_SUBMERGE_0 = 66948, - SPELL_ENRAGE = 68335, - SPELL_SLIME_POOL_EFFECT = 66882, //In 60s it diameter grows from 10y to 40y (r=r+0.25 per second) + SPELL_BURNING_BILE = 66869, //Icehowl SPELL_FEROCIOUS_BUTT = 66770, @@ -182,7 +191,7 @@ class boss_gormok : public CreatureScript { case 0: instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR)); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); me->SetReactState(REACT_AGGRESSIVE); me->SetInCombatWithZone(); break; @@ -549,7 +558,7 @@ struct boss_jormungarAI : public BossAI if (!Enraged && instance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL) { - me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); + me->RemoveAurasDueToSpell(SPELL_SUBMERGE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); DoCast(SPELL_ENRAGE); Enraged = true; @@ -586,10 +595,11 @@ struct boss_jormungarAI : public BossAI case EVENT_SUMMON_ACIDMAW: if (Creature* acidmaw = me->SummonCreature(NPC_ACIDMAW, ToCCommonLoc[9].GetPositionX(), ToCCommonLoc[9].GetPositionY(), ToCCommonLoc[9].GetPositionZ(), 5, TEMPSUMMON_MANUAL_DESPAWN)) { - acidmaw->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + acidmaw->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); acidmaw->SetReactState(REACT_AGGRESSIVE); acidmaw->SetInCombatWithZone(); - acidmaw->CastSpell(acidmaw, SPELL_EMERGE_0); + acidmaw->CastSpell(acidmaw, SPELL_EMERGE); + acidmaw->CastSpell(acidmaw, SPELL_GROUND_VISUAL_1, true); } return; case EVENT_SPRAY: @@ -598,7 +608,7 @@ struct boss_jormungarAI : public BossAI events.ScheduleEvent(EVENT_SPRAY, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY); return; case EVENT_SWEEP: - DoCastAOE(SPELL_SWEEP_0); + DoCastAOE(SPELL_SWEEP); events.ScheduleEvent(EVENT_SWEEP, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY); return; default: @@ -608,13 +618,14 @@ struct boss_jormungarAI : public BossAI if (events.IsInPhase(PHASE_MOBILE)) DoMeleeAttackIfReady(); if (events.IsInPhase(PHASE_STATIONARY)) - DoSpellAttackIfReady(SpitSpell); + DoCastVictim(SpitSpell); } void Submerge() { - DoCast(me, SPELL_SUBMERGE_0); - me->RemoveAurasDueToSpell(SPELL_EMERGE_0); + DoCast(me, SPELL_SUBMERGE); + DoCast(me, SPELL_GROUND_VISUAL_0, true); + me->RemoveAurasDueToSpell(SPELL_EMERGE); me->SetInCombatWithZone(); events.SetPhase(PHASE_SUBMERGED); events.ScheduleEvent(EVENT_EMERGE, 5*IN_MILLISECONDS, 0, PHASE_SUBMERGED); @@ -625,17 +636,20 @@ struct boss_jormungarAI : public BossAI void Emerge() { - DoCast(me, SPELL_EMERGE_0); + DoCast(me, SPELL_EMERGE); + DoCastAOE(SPELL_HATE_TO_ZERO, true); me->SetDisplayId(ModelMobile); - me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0); + me->RemoveAurasDueToSpell(SPELL_SUBMERGE); + me->RemoveAurasDueToSpell(SPELL_GROUND_VISUAL_0); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); // if the worm was mobile before submerging, make him stationary now if (WasMobile) { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); SetCombatMovement(false); me->SetDisplayId(ModelStationary); + me->CastSpell(me, SPELL_GROUND_VISUAL_1, true); events.SetPhase(PHASE_STATIONARY); events.ScheduleEvent(EVENT_SUBMERGE, 45*IN_MILLISECONDS, 0, PHASE_STATIONARY); events.ScheduleEvent(EVENT_SPIT, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_STATIONARY); @@ -644,10 +658,11 @@ struct boss_jormungarAI : public BossAI } else { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); SetCombatMovement(true); me->GetMotionMaster()->MoveChase(me->GetVictim()); me->SetDisplayId(ModelMobile); + me->RemoveAurasDueToSpell(SPELL_GROUND_VISUAL_1); events.SetPhase(PHASE_MOBILE); events.ScheduleEvent(EVENT_SUBMERGE, 45*IN_MILLISECONDS, 0, PHASE_MOBILE); events.ScheduleEvent(EVENT_BITE, urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS), 0, PHASE_MOBILE); @@ -737,7 +752,7 @@ class boss_dreadscale : public CreatureScript { case 0: instance->DoCloseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR)); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); me->SetReactState(REACT_AGGRESSIVE); me->SetInCombatWithZone(); break; @@ -910,7 +925,7 @@ class boss_icehowl : public CreatureScript break; case 2: instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR)); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); me->SetReactState(REACT_AGGRESSIVE); me->SetInCombatWithZone(); break; @@ -1008,7 +1023,7 @@ class boss_icehowl : public CreatureScript me->SetTarget(_trampleTargetGUID); _trampleCast = false; SetCombatMovement(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); events.ScheduleEvent(EVENT_TRAMPLE, 4*IN_MILLISECONDS); @@ -1092,7 +1107,7 @@ class boss_icehowl : public CreatureScript Talk(EMOTE_TRAMPLE_FAIL); } _movementStarted = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); SetCombatMovement(true); me->GetMotionMaster()->MovementExpired(); me->GetMotionMaster()->Clear(); @@ -1122,6 +1137,148 @@ class boss_icehowl : public CreatureScript } }; +class spell_jormungars_paralytic_toxin : public SpellScriptLoader +{ +public: + spell_jormungars_paralytic_toxin() : SpellScriptLoader("spell_jormungars_paralytic_toxin") { } + + class spell_jormungars_paralytic_toxin_AuraScript : public AuraScript + { + PrepareAuraScript(spell_jormungars_paralytic_toxin_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PARALYSIS)) + return false; + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Unit* caster = GetCaster(); + if (caster && caster->GetEntry() == NPC_ACIDMAW) + { + if (Creature* acidMaw = caster->ToCreature()) + acidMaw->AI()->Talk(SAY_SPECIAL, GetTarget()); + } + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(SPELL_PARALYSIS); + } + + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) + { + if (!canBeRecalculated) + amount = aurEff->GetAmount(); + + canBeRecalculated = false; + } + + void HandleDummy(AuraEffect const* /*aurEff*/) + { + if (AuraEffect* slowEff = GetEffect(EFFECT_0)) + { + int32 newAmount = slowEff->GetAmount() - 10; + if (newAmount < -100) + newAmount = -100; + slowEff->ChangeAmount(newAmount); + + if (newAmount <= -100 && !GetTarget()->HasAura(SPELL_PARALYSIS)) + GetTarget()->CastSpell(GetTarget(), SPELL_PARALYSIS, true, NULL, slowEff, GetCasterGUID()); + } + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_jormungars_paralytic_toxin_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_jormungars_paralytic_toxin_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL); + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_jormungars_paralytic_toxin_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_jormungars_paralytic_toxin_AuraScript::HandleDummy, EFFECT_2, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_jormungars_paralytic_toxin_AuraScript(); + } +}; + +class spell_jormungars_snakes_spray : public SpellScriptLoader +{ +public: + spell_jormungars_snakes_spray(const char* name, uint32 spellId) : SpellScriptLoader(name), _spellId(spellId) { } + + class spell_jormungars_snakes_spray_SpellScript : public SpellScript + { + PrepareSpellScript(spell_jormungars_snakes_spray_SpellScript); + + public: + spell_jormungars_snakes_spray_SpellScript(uint32 spellId) : SpellScript(), _spellId(spellId) { } + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(_spellId)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Player* target = GetHitPlayer()) + GetCaster()->CastSpell(target, _spellId, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_jormungars_snakes_spray_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } + + private: + uint32 _spellId; + }; + + SpellScript* GetSpellScript() const override + { + return new spell_jormungars_snakes_spray_SpellScript(_spellId); + } + +private: + uint32 _spellId; +}; + +class spell_jormungars_paralysis : public SpellScriptLoader +{ +public: + spell_jormungars_paralysis() : SpellScriptLoader("spell_jormungars_paralysis") { } + + class spell_jormungars_paralysis_AuraScript : public AuraScript + { + PrepareAuraScript(spell_jormungars_paralysis_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + if (InstanceScript* instance = caster->GetInstanceScript()) + if (instance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_IN_PROGRESS || instance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL) + return; + + Remove(); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_jormungars_paralysis_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_jormungars_paralysis_AuraScript(); + } +}; + void AddSC_boss_northrend_beasts() { new boss_gormok(); @@ -1132,6 +1289,10 @@ void AddSC_boss_northrend_beasts() new boss_acidmaw(); new boss_dreadscale(); new npc_slime_pool(); + new spell_jormungars_paralytic_toxin(); + new spell_jormungars_snakes_spray("spell_jormungars_burning_spray", SPELL_BURNING_BILE); + new spell_jormungars_snakes_spray("spell_jormungars_paralytic_spray", SPELL_PARALYTIC_TOXIN); + new spell_jormungars_paralysis(); new boss_icehowl(); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index eb1e769c07e..c6ac59218ea 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -132,7 +132,7 @@ class OrbsDespawner : public BasicEvent { } - bool Execute(uint64 /*currTime*/, uint32 /*diff*/) + bool Execute(uint64 /*currTime*/, uint32 /*diff*/) override { Trinity::CreatureWorker<OrbsDespawner> worker(_creature, *this); _creature->VisitNearbyGridObject(5000.0f, worker); @@ -440,10 +440,8 @@ class boss_fjola : public CreatureScript // Allocate an unique random stage to each position in the array. for (int i = 0; i < MAX_STAGES - 1; ++i) { - int random = i + (rand32() % (MAX_STAGES - i)); - int temp = Stage[i]; - Stage[i] = Stage[random]; - Stage[random] = temp; + int random = i + urand(0, MAX_STAGES - i); + std::swap(Stage[i], Stage[random]); } } private: @@ -804,8 +802,8 @@ class spell_valkyr_essences : public SpellScriptLoader else { owner->CastSpell(owner, poweringUp, true); - if (Aura* pTemp = owner->GetAura(poweringUp)) - pTemp->ModStackAmount(stacksCount); + if ((pAura = owner->GetAura(poweringUp))) + pAura->ModStackAmount(stacksCount); } } } @@ -829,8 +827,8 @@ class spell_valkyr_essences : public SpellScriptLoader else { owner->CastSpell(owner, poweringUp, true); - if (Aura* pTemp = owner->GetAura(poweringUp)) - pTemp->ModStackAmount(stacksCount); + if ((pAura = owner->GetAura(poweringUp))) + pAura->ModStackAmount(stacksCount); } } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index b1a0f0217c4..eb4840f3b8b 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -314,7 +314,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript if (tributeChest) if (Creature* tirion = instance->GetCreature(TirionGUID)) - if (GameObject* chest = tirion->SummonGameObject(tributeChest, 805.62f, 134.87f, 142.16f, 3.27f, 0, 0, 0, 0, WEEK)) + if (GameObject* chest = tirion->SummonGameObject(tributeChest, 805.62f, 134.87f, 142.16f, 3.27f, G3D::Quat(), WEEK)) chest->SetRespawnTime(chest->GetRespawnDelay()); break; } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index 0ffe74932e0..8ea292d1de5 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -174,7 +174,7 @@ class npc_announcer_toc10 : public CreatureScript if (Creature* jaraxxus = ObjectAccessor::GetCreature(*player, instance->GetGuidData(NPC_JARAXXUS))) { jaraxxus->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS); - jaraxxus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + jaraxxus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); jaraxxus->SetReactState(REACT_DEFENSIVE); jaraxxus->SetInCombatWithZone(); } @@ -360,11 +360,11 @@ class npc_fizzlebang_toc : public CreatureScript { Talk(SAY_STAGE_1_06, killer); _instance->SetData(TYPE_EVENT, 1180); - if (Creature* temp = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS))) + if (Creature* jaraxxus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS))) { - temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - temp->SetReactState(REACT_AGGRESSIVE); - temp->SetInCombatWithZone(); + jaraxxus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); + jaraxxus->SetReactState(REACT_AGGRESSIVE); + jaraxxus->SetInCombatWithZone(); } } @@ -457,18 +457,18 @@ class npc_fizzlebang_toc : public CreatureScript break; case 1140: Talk(SAY_STAGE_1_04); - if (Creature* temp = me->SummonCreature(NPC_JARAXXUS, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 5.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) + if (Creature* jaraxxus = me->SummonCreature(NPC_JARAXXUS, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 5.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) { - temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - temp->SetReactState(REACT_PASSIVE); - temp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY()-10, ToCCommonLoc[1].GetPositionZ()); + jaraxxus->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC); + jaraxxus->SetReactState(REACT_PASSIVE); + jaraxxus->GetMotionMaster()->MovePoint(0, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY()-10, ToCCommonLoc[1].GetPositionZ()); } _instance->SetData(TYPE_EVENT, 1142); _updateTimer = 5*IN_MILLISECONDS; break; case 1142: - if (Creature* temp = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS))) - temp->SetTarget(me->GetGUID()); + if (Creature* jaraxxus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS))) + jaraxxus->SetTarget(me->GetGUID()); if (Creature* pTrigger = ObjectAccessor::GetCreature(*me, _triggerGUID)) pTrigger->DespawnOrUnsummon(); if (Creature* pPortal = ObjectAccessor::GetCreature(*me, _portalGUID)) @@ -477,19 +477,19 @@ class npc_fizzlebang_toc : public CreatureScript _updateTimer = 10*IN_MILLISECONDS; break; case 1144: - if (Creature* temp = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS))) - temp->AI()->Talk(SAY_STAGE_1_05); + if (Creature* jaraxxus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS))) + jaraxxus->AI()->Talk(SAY_STAGE_1_05); _instance->SetData(TYPE_EVENT, 1150); _updateTimer = 5*IN_MILLISECONDS; break; case 1150: - if (Creature* temp = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS))) + if (Creature* jaraxxus = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(NPC_JARAXXUS))) { //1-shot Fizzlebang - temp->CastSpell(me, 67888, false); - me->SetInCombatWith(temp); - temp->AddThreat(me, 1000.0f); - temp->AI()->AttackStart(me); + jaraxxus->CastSpell(me, 67888, false); // 67888 - Fel Lightning + me->SetInCombatWith(jaraxxus); + jaraxxus->AddThreat(me, 1000.0f); + jaraxxus->AI()->AttackStart(me); } _instance->SetData(TYPE_EVENT, 1160); _updateTimer = 3*IN_MILLISECONDS; @@ -561,11 +561,11 @@ class npc_tirion_toc : public CreatureScript { _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR)); - if (Creature* temp = me->SummonCreature(NPC_GORMOK, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30*IN_MILLISECONDS)) + if (Creature* gormok = me->SummonCreature(NPC_GORMOK, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30*IN_MILLISECONDS)) { - temp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ()); - temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - temp->SetReactState(REACT_PASSIVE); + gormok->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ()); + gormok->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + gormok->SetReactState(REACT_PASSIVE); } } _updateTimer = 3*IN_MILLISECONDS; @@ -582,11 +582,11 @@ class npc_tirion_toc : public CreatureScript if (_instance->GetBossState(BOSS_BEASTS) != DONE) { _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR)); - if (Creature* temp = me->SummonCreature(NPC_DREADSCALE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_MANUAL_DESPAWN)) + if (Creature* dreadscale = me->SummonCreature(NPC_DREADSCALE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_MANUAL_DESPAWN)) { - temp->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ()); - temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - temp->SetReactState(REACT_PASSIVE); + dreadscale->GetMotionMaster()->MovePoint(0, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ()); + dreadscale->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + dreadscale->SetReactState(REACT_PASSIVE); } } _updateTimer = 5*IN_MILLISECONDS; @@ -600,9 +600,9 @@ class npc_tirion_toc : public CreatureScript if (_instance->GetBossState(BOSS_BEASTS) != DONE) { _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR)); - if (Creature* temp = me->SummonCreature(NPC_ICEHOWL, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5, TEMPSUMMON_DEAD_DESPAWN)) + if (Creature* icehowl = me->SummonCreature(NPC_ICEHOWL, ToCSpawnLoc[0].GetPositionX(), ToCSpawnLoc[0].GetPositionY(), ToCSpawnLoc[0].GetPositionZ(), 5, TEMPSUMMON_DEAD_DESPAWN)) { - temp->GetMotionMaster()->MovePoint(2, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ()); + icehowl->GetMotionMaster()->MovePoint(2, ToCCommonLoc[5].GetPositionX(), ToCCommonLoc[5].GetPositionY(), ToCCommonLoc[5].GetPositionZ()); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); me->SetReactState(REACT_PASSIVE); } @@ -698,34 +698,34 @@ class npc_tirion_toc : public CreatureScript break; case 4010: Talk(SAY_STAGE_3_02); - if (Creature* temp = me->SummonCreature(NPC_LIGHTBANE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) + if (Creature* lightbane = me->SummonCreature(NPC_LIGHTBANE, ToCSpawnLoc[1].GetPositionX(), ToCSpawnLoc[1].GetPositionY(), ToCSpawnLoc[1].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) { - temp->SetVisible(false); - temp->SetReactState(REACT_PASSIVE); - temp->SummonCreature(NPC_LIGHT_ESSENCE, TwinValkyrsLoc[0].GetPositionX(), TwinValkyrsLoc[0].GetPositionY(), TwinValkyrsLoc[0].GetPositionZ()); - temp->SummonCreature(NPC_LIGHT_ESSENCE, TwinValkyrsLoc[1].GetPositionX(), TwinValkyrsLoc[1].GetPositionY(), TwinValkyrsLoc[1].GetPositionZ()); + lightbane->SetVisible(false); + lightbane->SetReactState(REACT_PASSIVE); + lightbane->SummonCreature(NPC_LIGHT_ESSENCE, TwinValkyrsLoc[0].GetPositionX(), TwinValkyrsLoc[0].GetPositionY(), TwinValkyrsLoc[0].GetPositionZ()); + lightbane->SummonCreature(NPC_LIGHT_ESSENCE, TwinValkyrsLoc[1].GetPositionX(), TwinValkyrsLoc[1].GetPositionY(), TwinValkyrsLoc[1].GetPositionZ()); } - if (Creature* temp = me->SummonCreature(NPC_DARKBANE, ToCSpawnLoc[2].GetPositionX(), ToCSpawnLoc[2].GetPositionY(), ToCSpawnLoc[2].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) + if (Creature* darkbane = me->SummonCreature(NPC_DARKBANE, ToCSpawnLoc[2].GetPositionX(), ToCSpawnLoc[2].GetPositionY(), ToCSpawnLoc[2].GetPositionZ(), 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME)) { - temp->SetVisible(false); - temp->SetReactState(REACT_PASSIVE); - temp->SummonCreature(NPC_DARK_ESSENCE, TwinValkyrsLoc[2].GetPositionX(), TwinValkyrsLoc[2].GetPositionY(), TwinValkyrsLoc[2].GetPositionZ()); - temp->SummonCreature(NPC_DARK_ESSENCE, TwinValkyrsLoc[3].GetPositionX(), TwinValkyrsLoc[3].GetPositionY(), TwinValkyrsLoc[3].GetPositionZ()); + darkbane->SetVisible(false); + darkbane->SetReactState(REACT_PASSIVE); + darkbane->SummonCreature(NPC_DARK_ESSENCE, TwinValkyrsLoc[2].GetPositionX(), TwinValkyrsLoc[2].GetPositionY(), TwinValkyrsLoc[2].GetPositionZ()); + darkbane->SummonCreature(NPC_DARK_ESSENCE, TwinValkyrsLoc[3].GetPositionX(), TwinValkyrsLoc[3].GetPositionY(), TwinValkyrsLoc[3].GetPositionZ()); } _updateTimer = 3*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 4015); break; case 4015: _instance->DoUseDoorOrButton(_instance->GetGuidData(GO_MAIN_GATE_DOOR)); - if (Creature* temp = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_LIGHTBANE))) + if (Creature* lightbane = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_LIGHTBANE))) { - temp->GetMotionMaster()->MovePoint(1, ToCCommonLoc[8].GetPositionX(), ToCCommonLoc[8].GetPositionY(), ToCCommonLoc[8].GetPositionZ()); - temp->SetVisible(true); + lightbane->GetMotionMaster()->MovePoint(1, ToCCommonLoc[8].GetPositionX(), ToCCommonLoc[8].GetPositionY(), ToCCommonLoc[8].GetPositionZ()); + lightbane->SetVisible(true); } - if (Creature* temp = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_DARKBANE))) + if (Creature* darkbane = ObjectAccessor::GetCreature((*me), _instance->GetGuidData(NPC_DARKBANE))) { - temp->GetMotionMaster()->MovePoint(1, ToCCommonLoc[9].GetPositionX(), ToCCommonLoc[9].GetPositionY(), ToCCommonLoc[9].GetPositionZ()); - temp->SetVisible(true); + darkbane->GetMotionMaster()->MovePoint(1, ToCCommonLoc[9].GetPositionX(), ToCCommonLoc[9].GetPositionY(), ToCCommonLoc[9].GetPositionZ()); + darkbane->SetVisible(true); } _updateTimer = 10*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 4016); @@ -754,9 +754,9 @@ class npc_tirion_toc : public CreatureScript _instance->SetData(TYPE_EVENT, 0); break; case 6000: - me->SummonCreature(NPC_TIRION_FORDRING, EndSpawnLoc[0].GetPositionX(), EndSpawnLoc[0].GetPositionY(), EndSpawnLoc[0].GetPositionZ()); - me->SummonCreature(NPC_ARGENT_MAGE, EndSpawnLoc[1].GetPositionX(), EndSpawnLoc[1].GetPositionY(), EndSpawnLoc[1].GetPositionZ()); - me->SummonGameObject(GO_PORTAL_TO_DALARAN, EndSpawnLoc[2].GetPositionX(), EndSpawnLoc[2].GetPositionY(), EndSpawnLoc[2].GetPositionZ(), 5, 0, 0, 0, 0, 0); + me->SummonCreature(NPC_TIRION_FORDRING, EndSpawnLoc[0]); + me->SummonCreature(NPC_ARGENT_MAGE, EndSpawnLoc[1]); + me->SummonGameObject(GO_PORTAL_TO_DALARAN, EndSpawnLoc[2], G3D::Quat(), 0); _updateTimer = 20*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 6005); break; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h index 90b9781954f..d53d6705400 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h @@ -140,9 +140,9 @@ const Position AnubarakLoc[]= const Position EndSpawnLoc[]= { - {648.9167f, 131.0208f, 141.6161f, 0}, // 0 - Highlord Tirion Fordring - {649.1614f, 142.0399f, 141.3057f, 0}, // 1 - Argent Mage - {644.6250f, 149.2743f, 140.6015f, 0} // 2 - Portal to Dalaran + {648.9167f, 131.0208f, 141.6161f, 0.f}, // 0 - Highlord Tirion Fordring + {649.1614f, 142.0399f, 141.3057f, 0.f}, // 1 - Argent Mage + {644.6250f, 149.2743f, 140.6015f, 5.f} // 2 - Portal to Dalaran }; enum WorldStateIds diff --git a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp index ce722e391d1..292f1d7074f 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/boss_novos.cpp @@ -198,8 +198,6 @@ public: { if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); if (me->HasUnitState(UNIT_STATE_CASTING)) me->CastStop(); } @@ -207,8 +205,6 @@ public: { if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC)) - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); DoCast(SPELL_ARCANE_FIELD); } } diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp index 055d0a07f41..94d1d93225c 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp @@ -144,7 +144,7 @@ class boss_devourer_of_souls : public CreatureScript void Reset() override { _Reset(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->SetDisplayId(DISPLAY_ANGER); me->SetReactState(REACT_AGGRESSIVE); @@ -297,7 +297,7 @@ class boss_devourer_of_souls : public CreatureScript me->SetTarget(ObjectGuid::Empty); me->GetMotionMaster()->Clear(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); wailingSoulTick = 15; events.DelayEvents(18000); // no other events during wailing souls @@ -317,7 +317,7 @@ class boss_devourer_of_souls : public CreatureScript { me->SetReactState(REACT_AGGRESSIVE); me->SetDisplayId(DISPLAY_ANGER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->GetMotionMaster()->MoveChase(me->GetVictim()); events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000, 70000)); } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 4c2b92da0ea..6b20ae6a373 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -1921,6 +1921,7 @@ class npc_frostsworn_general : public CreatureScript { if (Creature* reflection = me->SummonCreature(NPC_REFLECTION, *target, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000)) { + reflection->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); target->CastSpell(reflection, SPELL_CLONE, true); target->CastSpell(reflection, SPELL_GHOST_VISUAL, true); reflection->AI()->AttackStart(target); @@ -2155,6 +2156,7 @@ struct npc_escape_event_trash : public ScriptedAI DoZoneInCombat(me, 0.0f); if (Creature* leader = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_ESCAPE_LEADER))) { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->SetInCombatWith(leader); leader->SetInCombatWith(me); me->AddThreat(leader, 0.0f); @@ -2580,7 +2582,7 @@ class npc_quel_delar_sword : public CreatureScript void Reset() override { _events.Reset(); - me->SetSpeed(MOVE_FLIGHT, 4.5f, true); + me->SetSpeedRate(MOVE_FLIGHT, 4.5f); DoCast(SPELL_WHIRLWIND_VISUAL); if (_intro) _events.ScheduleEvent(EVENT_QUEL_DELAR_INIT, 0); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index 03f12e46bc3..b24a36da3fb 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -418,7 +418,7 @@ class boss_krick : public CreatureScript case EVENT_OUTRO_6: if (Creature* tyrannus = ObjectAccessor::GetCreature(*me, _instanceScript->GetGuidData(DATA_TYRANNUS_EVENT))) { - tyrannus->SetSpeed(MOVE_FLIGHT, 3.5f, true); + tyrannus->SetSpeedRate(MOVE_FLIGHT, 3.5f); tyrannus->GetMotionMaster()->MovePoint(1, outroPos[4]); _tyrannusGUID = tyrannus->GetGUID(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp index 96bd0aaa35e..5410f403ab9 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -22,6 +22,7 @@ #include "pit_of_saron.h" #include "Vehicle.h" #include "Player.h" +#include "PlayerAI.h" enum Yells { @@ -438,9 +439,10 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader if (GetTarget()->GetTypeId() != TYPEID_PLAYER) return; - oldAI = GetTarget()->GetAI(); - oldAIState = GetTarget()->IsAIEnabled; - GetTarget()->SetAI(new player_overlord_brandAI(GetTarget()->ToPlayer(), GetCasterGUID())); + Player* pTarget = GetTarget()->ToPlayer(); + oldAI = pTarget->AI(); + oldAIState = pTarget->IsAIEnabled; + GetTarget()->SetAI(new player_overlord_brandAI(pTarget, GetCasterGUID())); GetTarget()->IsAIEnabled = true; } @@ -450,7 +452,7 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader return; GetTarget()->IsAIEnabled = oldAIState; - UnitAI* thisAI = GetTarget()->GetAI(); + PlayerAI* thisAI = GetTarget()->ToPlayer()->AI(); GetTarget()->SetAI(oldAI); delete thisAI; } @@ -461,7 +463,7 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader AfterEffectRemove += AuraEffectRemoveFn(spell_tyrannus_overlord_brand_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } - UnitAI* oldAI; + PlayerAI* oldAI; bool oldAIState; }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index f59701b9c25..51711f9ded5 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -160,7 +160,7 @@ class StandUpEvent : public BasicEvent public: StandUpEvent(Creature& owner) : BasicEvent(), _owner(owner) { } - bool Execute(uint64 /*eventTime*/, uint32 /*diff*/) + bool Execute(uint64 /*eventTime*/, uint32 /*diff*/) override { _owner.HandleEmoteCommand(EMOTE_ONESHOT_ROAR); _owner.SetReactState(REACT_AGGRESSIVE); @@ -1069,7 +1069,7 @@ class npc_blood_queen_lana_thel : public CreatureScript if (Creature* summon = DoSummon(NPC_FLOATING_TRIGGER, triggerPos, 15000, TEMPSUMMON_TIMED_DESPAWN)) { summon->CastSpell(summon, SPELL_OOC_INVOCATION_VISUAL, true); - summon->SetSpeed(MOVE_FLIGHT, 0.15f, true); // todo: creature is swimming, check if this is blizzlike or not. + summon->SetSpeedRate(MOVE_FLIGHT, 0.15f); // todo: creature is swimming, check if this is blizzlike or not. summon->GetMotionMaster()->MovePoint(0, triggerEndPos); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index bc8c7f877a9..3d21388ca11 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -809,7 +809,7 @@ class spell_blood_queen_pact_of_the_darkfallen_dmg : public SpellScriptLoader // this is an additional effect to be executed void PeriodicTick(AuraEffect const* aurEff) { - SpellInfo const* damageSpell = sSpellMgr->EnsureSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE); + SpellInfo const* damageSpell = sSpellMgr->AssertSpellInfo(SPELL_PACT_OF_THE_DARKFALLEN_DAMAGE); int32 damage = damageSpell->Effects[EFFECT_0].CalcValue(); float multiplier = 0.3375f + 0.1f * uint32(aurEff->GetTickNumber()/10); // do not convert to 0.01f - we need tick number/10 as INT (damage increases every 10 ticks) damage = int32(damage * multiplier); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index 9b0693ec95e..73a7de36580 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -1843,7 +1843,7 @@ class spell_igb_rocket_pack : public SpellScriptLoader void HandleRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) { - SpellInfo const* damageInfo = sSpellMgr->EnsureSpellInfo(SPELL_ROCKET_PACK_DAMAGE); + SpellInfo const* damageInfo = sSpellMgr->AssertSpellInfo(SPELL_ROCKET_PACK_DAMAGE); GetTarget()->CastCustomSpell(SPELL_ROCKET_PACK_DAMAGE, SPELLVALUE_BASE_POINT0, 2 * (damageInfo->Effects[EFFECT_0].CalcValue() + aurEff->GetTickNumber() * aurEff->GetAmplitude()), NULL, TRIGGERED_FULL_MASK); GetTarget()->CastSpell(NULL, SPELL_ROCKET_BURST, TRIGGERED_FULL_MASK); } @@ -2461,6 +2461,33 @@ class spell_igb_teleport_players_on_victory : public SpellScriptLoader } }; +// 71201 - Battle Experience - proc should never happen, handled in script +class spell_igb_battle_experience_check : public SpellScriptLoader +{ +public: + spell_igb_battle_experience_check() : SpellScriptLoader("spell_igb_battle_experience_check") { } + + class spell_igb_battle_experience_check_AuraScript : public AuraScript + { + PrepareAuraScript(spell_igb_battle_experience_check_AuraScript); + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + return false; + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_igb_battle_experience_check_AuraScript::CheckProc); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_igb_battle_experience_check_AuraScript(); + } +}; + class achievement_im_on_a_boat : public AchievementCriteriaScript { public: @@ -2500,5 +2527,6 @@ void AddSC_boss_icecrown_gunship_battle() new spell_igb_gunship_fall_teleport(); new spell_igb_check_for_players(); new spell_igb_teleport_players_on_victory(); + new spell_igb_battle_experience_check(); new achievement_im_on_a_boat(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index d3cf6495aa7..b3a11b8eb31 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -203,7 +203,7 @@ class DaranavanMoveEvent : public BasicEvent public: DaranavanMoveEvent(Creature& darnavan) : _darnavan(darnavan) { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { _darnavan.GetMotionMaster()->MovePoint(POINT_DESPAWN, SummonPositions[6]); return true; @@ -421,7 +421,7 @@ class boss_lady_deathwhisper : public CreatureScript void UpdateAI(uint32 diff) override { - if ((!UpdateVictim() && !events.IsInPhase(PHASE_INTRO))) + if (!UpdateVictim() && !events.IsInPhase(PHASE_INTRO)) return; events.Update(diff); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 056231285e2..9f20799df82 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -142,7 +142,7 @@ class boss_lord_marrowgar : public CreatureScript void Reset() override { _Reset(); - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); me->RemoveAurasDueToSpell(SPELL_BONE_STORM); me->RemoveAurasDueToSpell(SPELL_BERSERK); events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000); @@ -224,7 +224,7 @@ class boss_lord_marrowgar : public CreatureScript case EVENT_BONE_STORM_BEGIN: if (Aura* pStorm = me->GetAura(SPELL_BONE_STORM)) pStorm->SetDuration(int32(_boneStormDuration)); - me->SetSpeed(MOVE_RUN, _baseSpeed*3.0f, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed*3.0f); Talk(SAY_BONE_STORM); events.ScheduleEvent(EVENT_BONE_STORM_END, _boneStormDuration+1); // no break here @@ -242,7 +242,7 @@ class boss_lord_marrowgar : public CreatureScript if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) me->GetMotionMaster()->MovementExpired(); me->GetMotionMaster()->MoveChase(me->GetVictim()); - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); events.CancelEvent(EVENT_BONE_STORM_MOVE); events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000); if (!IsHeroic()) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 2db9d206a00..fe6e4081326 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -369,21 +369,21 @@ class boss_professor_putricide : public CreatureScript { case POINT_FESTERGUT: instance->SetBossState(DATA_FESTERGUT, IN_PROGRESS); // needed here for delayed gate close - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); DoAction(ACTION_FESTERGUT_GAS); if (Creature* festergut = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FESTERGUT))) festergut->CastSpell(festergut, SPELL_GASEOUS_BLIGHT_LARGE, false, NULL, NULL, festergut->GetGUID()); break; case POINT_ROTFACE: instance->SetBossState(DATA_ROTFACE, IN_PROGRESS); // needed here for delayed gate close - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); DoAction(ACTION_ROTFACE_OOZE); events.ScheduleEvent(EVENT_ROTFACE_OOZE_FLOOD, 25000, 0, PHASE_ROTFACE); break; case POINT_TABLE: // stop attack me->GetMotionMaster()->MoveIdle(); - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); if (GameObject* table = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_PUTRICIDE_TABLE))) me->SetFacingToObject(table); // operating on new phase already @@ -418,7 +418,7 @@ class boss_professor_putricide : public CreatureScript { case ACTION_FESTERGUT_COMBAT: SetPhase(PHASE_FESTERGUT); - me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f); me->GetMotionMaster()->MovePoint(POINT_FESTERGUT, festergutWatchPos); me->SetReactState(REACT_PASSIVE); DoZoneInCombat(me); @@ -435,7 +435,7 @@ class boss_professor_putricide : public CreatureScript case ACTION_ROTFACE_COMBAT: { SetPhase(PHASE_ROTFACE); - me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f); me->GetMotionMaster()->MovePoint(POINT_ROTFACE, rotfaceWatchPos); me->SetReactState(REACT_PASSIVE); _oozeFloodStage = 0; @@ -477,7 +477,7 @@ class boss_professor_putricide : public CreatureScript events.ScheduleEvent(EVENT_ROTFACE_DIES, 4500, 0, PHASE_ROTFACE); break; case ACTION_CHANGE_PHASE: - me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f); events.DelayEvents(30000); me->AttackStop(); if (!IsHeroic()) @@ -562,7 +562,7 @@ class boss_professor_putricide : public CreatureScript void UpdateAI(uint32 diff) override { - if ((!(events.IsInPhase(PHASE_ROTFACE) || events.IsInPhase(PHASE_FESTERGUT)) && !UpdateVictim())) + if (!(events.IsInPhase(PHASE_ROTFACE) || events.IsInPhase(PHASE_FESTERGUT)) && !UpdateVictim()) return; events.Update(diff); @@ -776,7 +776,7 @@ class npc_volatile_ooze : public CreatureScript { } - void CastMainSpell() + void CastMainSpell() override { me->CastSpell(me, SPELL_VOLATILE_OOZE_ADHESIVE, false); } @@ -800,7 +800,7 @@ class npc_gas_cloud : public CreatureScript _newTargetSelectTimer = 0; } - void CastMainSpell() + void CastMainSpell() override { me->CastCustomSpell(SPELL_GASEOUS_BLOAT, SPELLVALUE_AURA_STACK, 10, me, false); } @@ -1257,7 +1257,7 @@ class spell_putricide_mutated_plague : public SpellScriptLoader return; uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; - SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(triggerSpell); + SpellInfo const* spell = sSpellMgr->AssertSpellInfo(triggerSpell); spell = sSpellMgr->GetSpellForDifficultyFromSpell(spell, caster); int32 damage = spell->Effects[EFFECT_0].CalcValue(caster); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index 683dd976b7a..bf69a49055c 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -856,14 +856,14 @@ class spell_rotface_vile_gas_trigger : public SpellScriptLoader GetCaster()->CastSpell(GetHitUnit(), SPELL_VILE_GAS_TRIGGER_SUMMON); } - void Register() + void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_vile_gas_trigger_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); OnEffectHitTarget += SpellEffectFn(spell_rotface_vile_gas_trigger_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; - SpellScript* GetSpellScript() const + SpellScript* GetSpellScript() const override { return new spell_rotface_vile_gas_trigger_SpellScript(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index ac094588d35..aa5060e83b4 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -134,6 +134,7 @@ enum FrostwingData DATA_WHELP_MARKER = 2, DATA_LINKED_GAMEOBJECT = 3, DATA_TRAPPED_PLAYER = 4, + DATA_IS_THIRD_PHASE = 5 }; enum MovementPoints @@ -168,7 +169,7 @@ class FrostwyrmLandEvent : public BasicEvent public: FrostwyrmLandEvent(Creature& owner, Position const& dest) : _owner(owner), _dest(dest) { } - bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) + bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override { _owner.GetMotionMaster()->MoveLand(POINT_FROSTWYRM_LAND, _dest); return true; @@ -184,7 +185,7 @@ class FrostBombExplosion : public BasicEvent public: FrostBombExplosion(Creature* owner, ObjectGuid sindragosaGUID) : _owner(owner), _sindragosaGUID(sindragosaGUID) { } - bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) + bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override { _owner->CastSpell((Unit*)NULL, SPELL_FROST_BOMB, false, NULL, NULL, _sindragosaGUID); _owner->RemoveAurasDueToSpell(SPELL_FROST_BOMB_VISUAL); @@ -196,20 +197,19 @@ class FrostBombExplosion : public BasicEvent ObjectGuid _sindragosaGUID; }; -class FrostBeaconSelector +class FrostBeaconSelector : NonTankTargetSelector { public: - FrostBeaconSelector(Unit* source) : _source(source) { } + FrostBeaconSelector(Unit* source) : NonTankTargetSelector(source, true) { } - bool operator()(Unit* target) const + bool operator()(WorldObject* target) const { - return target->GetTypeId() == TYPEID_PLAYER && - target != _source->GetVictim() && - !target->HasAura(SPELL_ICE_TOMB_UNTARGETABLE); - } + if (Unit* unitTarget = target->ToUnit()) + return !NonTankTargetSelector::operator()(unitTarget) || + unitTarget->HasAura(SPELL_ICE_TOMB_UNTARGETABLE); - private: - Unit* _source; + return false; + } }; class boss_sindragosa : public CreatureScript @@ -315,7 +315,7 @@ class boss_sindragosa : public CreatureScript me->SetCanFly(true); me->SetDisableGravity(true); me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); - me->SetSpeed(MOVE_FLIGHT, 4.0f); + me->SetSpeedRate(MOVE_FLIGHT, 4.0f); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); float moveTime = me->GetExactDist(&SindragosaFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); @@ -326,9 +326,15 @@ class boss_sindragosa : public CreatureScript uint32 GetData(uint32 type) const override { - if (type == DATA_MYSTIC_BUFFET_STACK) - return _mysticBuffetStack; - return 0xFFFFFFFF; + switch (type) + { + case DATA_MYSTIC_BUFFET_STACK: + return _mysticBuffetStack; + case DATA_IS_THIRD_PHASE: + return _isThirdPhase; + default: + return 0xFFFFFFFF; + } } void MovementInform(uint32 type, uint32 point) override @@ -345,7 +351,7 @@ class boss_sindragosa : public CreatureScript me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->SetHomePosition(SindragosaLandPos); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetSpeed(MOVE_FLIGHT, 2.5f); + me->SetSpeedRate(MOVE_FLIGHT, 2.5f); // Sindragosa enters combat as soon as she lands DoZoneInCombat(); @@ -419,7 +425,6 @@ class boss_sindragosa : public CreatureScript if (spellId == spell->Id) if (Aura const* mysticBuffet = target->GetAura(spell->Id)) _mysticBuffetStack = std::max<uint8>(_mysticBuffetStack, mysticBuffet->GetStackAmount()); - } void UpdateAI(uint32 diff) override @@ -494,11 +499,7 @@ class boss_sindragosa : public CreatureScript me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE_FAR, SindragosaAirPosFar); break; case EVENT_ICE_TOMB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, FrostBeaconSelector(me))) - { - Talk(EMOTE_WARN_FROZEN_ORB, target); - me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, 1, nullptr, TRIGGERED_FULL_MASK); - } + me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, 1, nullptr, TRIGGERED_FULL_MASK); events.ScheduleEvent(EVENT_ICE_TOMB, urand(16000, 23000)); break; case EVENT_FROST_BOMB: @@ -603,6 +604,7 @@ class npc_ice_tomb : public CreatureScript _trappedPlayerGUID.Clear(); player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_DAMAGE); player->RemoveAurasDueToSpell(SPELL_ASPHYXIATION); + player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE); } } @@ -696,7 +698,7 @@ class npc_spinestalker : public CreatureScript return; me->setActive(true); - me->SetSpeed(MOVE_FLIGHT, 2.0f); + me->SetSpeedRate(MOVE_FLIGHT, 2.0f); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); float moveTime = me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); @@ -833,7 +835,7 @@ class npc_rimefang : public CreatureScript return; me->setActive(true); - me->SetSpeed(MOVE_FLIGHT, 2.0f); + me->SetSpeedRate(MOVE_FLIGHT, 2.0f); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); float moveTime = me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); @@ -1283,9 +1285,9 @@ class spell_sindragosa_ice_tomb : public SpellScriptLoader public: spell_sindragosa_ice_tomb() : SpellScriptLoader("spell_sindragosa_ice_tomb_trap") { } - class spell_sindragosa_ice_tomb_SpellScript : public SpellScript + class spell_sindragosa_ice_tomb_AuraScript : public AuraScript { - PrepareSpellScript(spell_sindragosa_ice_tomb_SpellScript); + PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript); bool Validate(SpellInfo const* /*spell*/) override { @@ -1296,46 +1298,42 @@ class spell_sindragosa_ice_tomb : public SpellScriptLoader return true; } - void SummonTomb() + void PeriodicTick(AuraEffect const* aurEff) { - Position pos = GetHitUnit()->GetPosition(); - if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICE_TOMB, pos)) + PreventDefaultAction(); + + if (aurEff->GetTickNumber() == 1) { - summon->AI()->SetGUID(GetHitUnit()->GetGUID(), DATA_TRAPPED_PLAYER); - if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0)) + if (Unit* caster = GetCaster()) { - go->SetSpellId(SPELL_ICE_TOMB_DAMAGE); - summon->AddGameObject(go); + Position pos = GetTarget()->GetPosition(); + + if (TempSummon* summon = caster->SummonCreature(NPC_ICE_TOMB, pos)) + { + summon->AI()->SetGUID(GetTarget()->GetGUID(), DATA_TRAPPED_PLAYER); + GetTarget()->CastSpell(GetTarget(), SPELL_ICE_TOMB_UNTARGETABLE); + if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos, G3D::Quat(), 0)) + { + go->SetSpellId(SPELL_ICE_TOMB_DAMAGE); + summon->AddGameObject(go); + } + } } } } - void Register() override + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - AfterHit += SpellHitFn(spell_sindragosa_ice_tomb_SpellScript::SummonTomb); - } - }; - - class spell_sindragosa_ice_tomb_AuraScript : public AuraScript - { - PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript); - - void PeriodicTick(AuraEffect const* /*aurEff*/) - { - PreventDefaultAction(); + GetTarget()->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE); } void Register() override { OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_ice_tomb_AuraScript::PeriodicTick, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + AfterEffectRemove += AuraEffectRemoveFn(spell_sindragosa_ice_tomb_AuraScript::HandleRemove, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); } }; - SpellScript* GetSpellScript() const override - { - return new spell_sindragosa_ice_tomb_SpellScript(); - } - AuraScript* GetAuraScript() const override { return new spell_sindragosa_ice_tomb_AuraScript(); @@ -1576,6 +1574,41 @@ class spell_frostwarden_handler_focus_fire : public SpellScriptLoader } }; +class spell_sindragosa_ice_tomb_target : public SpellScriptLoader +{ +public: + spell_sindragosa_ice_tomb_target() : SpellScriptLoader("spell_sindragosa_ice_tomb_target") { } + + class spell_sindragosa_ice_tomb_target_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sindragosa_ice_tomb_target_SpellScript); + + void FilterTargets(std::list<WorldObject*>& unitList) + { + Unit* caster = GetCaster(); + unitList.remove_if(FrostBeaconSelector(caster)); + } + + void HandleSindragosaTalk(SpellEffIndex /*effIndex*/) + { + if (Creature* creatureCaster = GetCaster()->ToCreature()) + if (creatureCaster->GetAI()->GetData(DATA_IS_THIRD_PHASE)) + creatureCaster->AI()->Talk(EMOTE_WARN_FROZEN_ORB, GetHitUnit()); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_ice_tomb_target_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectLaunchTarget += SpellEffectFn(spell_sindragosa_ice_tomb_target_SpellScript::HandleSindragosaTalk, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_sindragosa_ice_tomb_target_SpellScript(); + } +}; + class at_sindragosa_lair : public AreaTriggerScript { public: @@ -1641,6 +1674,7 @@ void AddSC_boss_sindragosa() new spell_frostwarden_handler_focus_fire(); new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY, TRIGGERED_IGNORE_SET_FACING); new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb_dummy", SPELL_FROST_BEACON); + new spell_sindragosa_ice_tomb_target(); new at_sindragosa_lair(); new achievement_all_you_can_eat(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index a598b09c71b..de8d65693b9 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -285,6 +285,7 @@ enum Phases #define PHASE_TWO_THREE (events.IsInPhase(PHASE_TWO) ? PHASE_TWO : PHASE_THREE) Position const CenterPosition = {503.6282f, -2124.655f, 840.8569f, 0.0f}; +Position const TirionSpawn = {505.2118f, -2124.353f, 840.9403f, 3.141593f}; Position const TirionIntro = {489.2970f, -2124.840f, 840.8569f, 0.0f}; Position const TirionCharge = {482.9019f, -2124.479f, 840.8570f, 0.0f}; Position const LichKingIntro[3] = @@ -436,7 +437,7 @@ class StartMovementEvent : public BasicEvent { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { _owner->SetReactState(REACT_AGGRESSIVE); if (Creature* _summoner = ObjectAccessor::GetCreature(*_owner, _summonerGuid)) @@ -458,7 +459,7 @@ class VileSpiritActivateEvent : public BasicEvent { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { _owner->SetReactState(REACT_AGGRESSIVE); _owner->CastSpell(_owner, SPELL_VILE_SPIRIT_MOVE_SEARCH, true); @@ -478,7 +479,7 @@ class TriggerWickedSpirit : public BasicEvent { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { _owner->CastCustomSpell(SPELL_TRIGGER_VILE_SPIRIT_HEROIC, SPELLVALUE_MAX_TARGETS, 1, NULL, true); @@ -514,13 +515,34 @@ class boss_the_lich_king : public CreatureScript _vileSpiritExplosions = 0; } - void Reset() override + void InitializeAI() override + { + SetupEncounter(); + } + + void JustRespawned() override + { + SetupEncounter(); + } + + void SetupEncounter() { _Reset(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->SetReactState(REACT_PASSIVE); events.SetPhase(PHASE_INTRO); Initialize(); SetEquipmentSlots(true); + + // Reset The Frozen Throne gameobjects + FrozenThroneResetWorker reset; + Trinity::GameObjectWorker<FrozenThroneResetWorker> worker(me, reset); + me->VisitNearbyGridObject(333.0f, worker); + + // Reset any light override + me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000); + + me->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING_LK, TirionSpawn, TEMPSUMMON_MANUAL_DESPAWN); } void JustDied(Unit* /*killer*/) override @@ -556,40 +578,21 @@ class boss_the_lich_king : public CreatureScript events.ScheduleEvent(EVENT_SHADOW_TRAP, 15500, 0, PHASE_ONE); } - void JustReachedHome() override - { - _JustReachedHome(); - instance->SetBossState(DATA_THE_LICH_KING, NOT_STARTED); - - // Reset The Frozen Throne gameobjects - FrozenThroneResetWorker reset; - Trinity::GameObjectWorker<FrozenThroneResetWorker> worker(me, reset); - me->VisitNearbyGridObject(333.0f, worker); - - // Restore Tirion's gossip only after The Lich King fully resets to prevent - // restarting the encounter while LK still runs back to spawn point - if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - // Reset any light override - me->GetMap()->SetZoneOverrideLight(AREA_THE_FROZEN_THRONE, 0, 5000); - } - bool CanAIAttack(Unit const* target) const override { // The Lich King must not select targets in frostmourne room if he killed everyone outside return !target->HasAura(SPELL_IN_FROSTMOURNE_ROOM) && BossAI::CanAIAttack(target); } - void EnterEvadeMode(EvadeReason why) override + void EnterEvadeMode(EvadeReason /*why*/) override { - instance->SetBossState(DATA_THE_LICH_KING, FAIL); - BossAI::EnterEvadeMode(why); if (Creature* tirion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGHLORD_TIRION_FORDRING))) - tirion->AI()->EnterEvadeMode(); + tirion->DespawnOrUnsummon(); DoCastAOE(SPELL_KILL_FROSTMOURNE_PLAYERS); EntryCheckPredicate pred(NPC_STRANGULATE_VEHICLE); summons.DoAction(ACTION_TELEPORT_BACK, pred); + summons.DespawnAll(); + _DespawnAtEvade(); } void KilledUnit(Unit* victim) override @@ -761,7 +764,7 @@ class boss_the_lich_king : public CreatureScript { summons.Summon(summon); summon->SetReactState(REACT_PASSIVE); - summon->SetSpeed(MOVE_FLIGHT, 0.5f); + summon->SetSpeedRate(MOVE_FLIGHT, 0.5f); summon->GetMotionMaster()->MoveRandom(10.0f); if (!events.IsInPhase(PHASE_FROSTMOURNE)) summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15000)); @@ -770,6 +773,8 @@ class boss_the_lich_king : public CreatureScript case NPC_STRANGULATE_VEHICLE: summons.Summon(summon); return; + case NPC_HIGHLORD_TIRION_FORDRING_LK: + return; default: break; } @@ -1153,6 +1158,7 @@ class npc_tirion_fordring_tft : public CreatureScript _events.Reset(); if (_instance->GetBossState(DATA_THE_LICH_KING) == DONE) me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->LoadEquipment(1); } void MovementInform(uint32 type, uint32 id) override @@ -1443,7 +1449,7 @@ class npc_valkyr_shadowguard : public CreatureScript _events.Reset(); me->SetReactState(REACT_PASSIVE); DoCast(me, SPELL_WINGS_OF_THE_DAMNED, false); - me->SetSpeed(MOVE_FLIGHT, 0.642857f, true); + me->SetSpeedRate(MOVE_FLIGHT, 0.642857f); } void IsSummonedBy(Unit* /*summoner*/) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index 4f35f848927..b07de3457bd 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -179,7 +179,7 @@ class DelayedCastEvent : public BasicEvent { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { _trigger->CastSpell(_trigger, _spellId, false, NULL, NULL, _originalCaster); if (_despawnTime) @@ -201,7 +201,7 @@ class AuraRemoveEvent : public BasicEvent { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { _trigger->RemoveAurasDueToSpell(_spellId); return true; @@ -219,7 +219,7 @@ class ValithriaDespawner : public BasicEvent { } - bool Execute(uint64 /*currTime*/, uint32 /*diff*/) + bool Execute(uint64 /*currTime*/, uint32 /*diff*/) override { Trinity::CreatureWorker<ValithriaDespawner> worker(_creature, *this); _creature->VisitNearbyGridObject(333.0f, worker); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 25ca99f6a20..abb9c025771 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -365,7 +365,7 @@ class CaptainSurviveTalk : public BasicEvent public: explicit CaptainSurviveTalk(Creature const& owner) : _owner(owner) { } - bool Execute(uint64 /*currTime*/, uint32 /*diff*/) + bool Execute(uint64 /*currTime*/, uint32 /*diff*/) override { _owner.AI()->Talk(SAY_CAPTAIN_SURVIVE_TALK); return true; diff --git a/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp b/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp new file mode 100644 index 00000000000..71d90da21a1 --- /dev/null +++ b/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "BattlegroundIC.h" + +enum BossSpells +{ + SPELL_BRUTAL_STRIKE = 58460, + SPELL_DAGGER_THROW = 67280, + SPELL_CRUSHING_LEAP = 68506, + SPELL_RAGE = 66776 +}; + +enum BossEvents +{ + EVENT_BRUTAL_STRIKE = 1, + EVENT_DAGGER_THROW = 2, + EVENT_CRUSHING_LEAP = 3, + EVENT_CHECK_RANGE = 4 +}; + +class boss_ioc_horde_alliance : public CreatureScript +{ +public: + boss_ioc_horde_alliance() : CreatureScript("boss_ioc_horde_alliance") { } + + struct boss_ioc_horde_allianceAI : public ScriptedAI + { + boss_ioc_horde_allianceAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() override + { + _events.Reset(); + + uint32 _npcGuard; + if (me->GetEntry() == NPC_HIGH_COMMANDER_HALFORD_WYRMBANE) + _npcGuard = NPC_SEVEN_TH_LEGION_INFANTRY; + else + _npcGuard = NPC_KOR_KRON_GUARD; + + std::list<Creature*> guardsList; + me->GetCreatureListWithEntryInGrid(guardsList, _npcGuard, 100.0f); + for (std::list<Creature*>::const_iterator itr = guardsList.begin(); itr != guardsList.end(); ++itr) + (*itr)->Respawn(); + }; + + void EnterCombat(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_BRUTAL_STRIKE, 5 * IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_DAGGER_THROW, 7 * IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_CHECK_RANGE, 1 * IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_CRUSHING_LEAP, 15 * IN_MILLISECONDS); + } + + void SpellHit(Unit* caster, SpellInfo const* /*spell*/) override + { + if (caster->IsVehicle()) + me->Kill(caster); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BRUTAL_STRIKE: + DoCastVictim(SPELL_BRUTAL_STRIKE); + _events.ScheduleEvent(EVENT_BRUTAL_STRIKE, 5 * IN_MILLISECONDS); + break; + case EVENT_DAGGER_THROW: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) + DoCast(target, SPELL_DAGGER_THROW); + _events.ScheduleEvent(EVENT_DAGGER_THROW, 7 * IN_MILLISECONDS); + break; + case EVENT_CRUSHING_LEAP: + DoCastVictim(SPELL_CRUSHING_LEAP); + _events.ScheduleEvent(EVENT_CRUSHING_LEAP, 25 * IN_MILLISECONDS); + break; + case EVENT_CHECK_RANGE: + if (me->GetDistance(me->GetHomePosition()) > 25.0f) + DoCast(me, SPELL_RAGE); + else + me->RemoveAurasDueToSpell(SPELL_RAGE); + _events.ScheduleEvent(EVENT_CHECK_RANGE, 1 * IN_MILLISECONDS); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_ioc_horde_allianceAI(creature); + } +}; + +void AddSC_boss_ioc_horde_alliance() +{ + new boss_ioc_horde_alliance(); +} diff --git a/src/server/scripts/Northrend/isle_of_conquest.cpp b/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp index 68121e940c9..f7e83ff1f42 100644 --- a/src/server/scripts/Northrend/isle_of_conquest.cpp +++ b/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp @@ -210,7 +210,7 @@ class StartLaunchEvent : public BasicEvent { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { Player* player = sObjectMgr->GetPlayerByLowGUID(_lowGuid); if (!player || !player->GetVehicle()) @@ -259,6 +259,58 @@ class spell_ioc_launch : public SpellScriptLoader } }; +enum SeaforiumBombSpells +{ + SPELL_SEAFORIUM_BLAST = 66676, + SPELL_HUGE_SEAFORIUM_BLAST = 66672, + SPELL_A_BOMB_INABLE_CREDIT = 68366, + SPELL_A_BOMB_INATION_CREDIT = 68367 +}; + +class spell_ioc_seaforium_blast_credit : public SpellScriptLoader +{ + public: + spell_ioc_seaforium_blast_credit() : SpellScriptLoader("spell_ioc_seaforium_blast_credit") { } + + class spell_ioc_seaforium_blast_credit_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ioc_seaforium_blast_credit_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_A_BOMB_INABLE_CREDIT) || !sSpellMgr->GetSpellInfo(SPELL_A_BOMB_INATION_CREDIT)) + return false; + return true; + } + + void HandleAchievementCredit(SpellEffIndex /*effIndex*/) + { + uint32 _creditSpell = 0; + Unit* caster = GetOriginalCaster(); + if (!caster) + return; + + if (GetSpellInfo()->Id == SPELL_SEAFORIUM_BLAST) + _creditSpell = SPELL_A_BOMB_INABLE_CREDIT; + else if (GetSpellInfo()->Id == SPELL_HUGE_SEAFORIUM_BLAST) + _creditSpell = SPELL_A_BOMB_INATION_CREDIT; + + if (GetHitGObj() && GetHitGObj()->IsDestructibleBuilding()) + caster->CastSpell(caster, _creditSpell, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ioc_seaforium_blast_credit_SpellScript::HandleAchievementCredit, EFFECT_1, SPELL_EFFECT_GAMEOBJECT_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_ioc_seaforium_blast_credit_SpellScript(); + } +}; + void AddSC_isle_of_conquest() { new npc_four_car_garage(); @@ -266,4 +318,5 @@ void AddSC_isle_of_conquest() new spell_ioc_gunship_portal(); new spell_ioc_parachute_ic(); new spell_ioc_launch(); + new spell_ioc_seaforium_blast_credit(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index e8c4216b00e..60c60640c04 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -162,13 +162,13 @@ public: summons.DoZoneInCombat(); events.SetPhase(PHASE_NORMAL); - events.ScheduleEvent(EVENT_IMPALE, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_NORMAL); - events.ScheduleEvent(EVENT_SCARABS, urand(20 * IN_MILLISECONDS, 30 * IN_MILLISECONDS), 0, PHASE_NORMAL); - events.ScheduleEvent(EVENT_LOCUST, urand(80,120) * IN_MILLISECONDS, 0, PHASE_NORMAL); - events.ScheduleEvent(EVENT_BERSERK, 10 * MINUTE * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_IMPALE, randtime(Seconds(10), Seconds(20)), 0, PHASE_NORMAL); + events.ScheduleEvent(EVENT_SCARABS, randtime(Seconds(20), Seconds(30)), 0, PHASE_NORMAL); + events.ScheduleEvent(EVENT_LOCUST, Minutes(1)+randtime(Seconds(40), Seconds(60)), 0, PHASE_NORMAL); + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); if (!Is25ManRaid()) - events.ScheduleEvent(EVENT_SPAWN_GUARD, urand(15, 20) * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_SPAWN_GUARD, randtime(Seconds(15), Seconds(20))); } void UpdateAI(uint32 diff) override @@ -189,11 +189,9 @@ public: else EnterEvadeMode(); - events.ScheduleEvent(EVENT_IMPALE, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_NORMAL); + events.Repeat(randtime(Seconds(10), Seconds(20))); break; case EVENT_SCARABS: - events.ScheduleEvent(EVENT_SCARABS, urand(40 * IN_MILLISECONDS, 60 * IN_MILLISECONDS), 0, PHASE_NORMAL); - if (!guardCorpses.empty()) { if (ObjectGuid target = Trinity::Containers::SelectRandomContainerElement(guardCorpses)) @@ -204,27 +202,28 @@ public: creatureTarget->DespawnOrUnsummon(); } } + events.Repeat(randtime(Seconds(40), Seconds(60))); break; case EVENT_LOCUST: Talk(EMOTE_LOCUST); + events.SetPhase(PHASE_SWARM); DoCast(me, SPELL_LOCUST_SWARM); - events.ScheduleEvent(EVENT_SPAWN_GUARD, 3 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_LOCUST_ENDS, RAID_MODE(19, 23) * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_LOCUST, 90000); - events.SetPhase(PHASE_SWARM); + events.ScheduleEvent(EVENT_SPAWN_GUARD, Seconds(3)); + events.ScheduleEvent(EVENT_LOCUST_ENDS, RAID_MODE(Seconds(19), Seconds(23))); + events.Repeat(Minutes(1)+Seconds(30)); break; case EVENT_LOCUST_ENDS: - events.ScheduleEvent(EVENT_IMPALE, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_NORMAL); - events.ScheduleEvent(EVENT_SCARABS, urand(20 * IN_MILLISECONDS, 30 * IN_MILLISECONDS), 0, PHASE_NORMAL); events.SetPhase(PHASE_NORMAL); + events.ScheduleEvent(EVENT_IMPALE, randtime(Seconds(10), Seconds(20)), 0, PHASE_NORMAL); + events.ScheduleEvent(EVENT_SCARABS, randtime(Seconds(20), Seconds(30)), 0, PHASE_NORMAL); break; case EVENT_SPAWN_GUARD: me->SummonCreatureGroup(GROUP_SINGLE_SPAWN); break; case EVENT_BERSERK: DoCast(me, SPELL_BERSERK, true); - events.ScheduleEvent(EVENT_BERSERK, 600000); + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); break; } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index 39c41c935bf..8a7bdd293ba 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -100,9 +100,9 @@ class boss_faerlina : public CreatureScript _EnterCombat(); Talk(SAY_AGGRO); summons.DoZoneInCombat(); - events.ScheduleEvent(EVENT_POISON, urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS)); - events.ScheduleEvent(EVENT_FIRE, urand(6 * IN_MILLISECONDS, 18 * IN_MILLISECONDS)); - events.ScheduleEvent(EVENT_FRENZY, urand(60 * IN_MILLISECONDS, 80 * IN_MILLISECONDS)); + events.ScheduleEvent(EVENT_POISON, randtime(Seconds(10), Seconds(15))); + events.ScheduleEvent(EVENT_FIRE, randtime(Seconds(6), Seconds(18))); + events.ScheduleEvent(EVENT_FRENZY, Minutes(1)+randtime(Seconds(0), Seconds(20))); } void Reset() override @@ -111,9 +111,9 @@ class boss_faerlina : public CreatureScript _frenzyDispels = 0; } - void KilledUnit(Unit* /*victim*/) override + void KilledUnit(Unit* victim) override { - if (!urand(0, 2)) + if (victim->GetTypeId() == TYPEID_PLAYER) Talk(SAY_SLAY); } @@ -158,21 +158,21 @@ class boss_faerlina : public CreatureScript case EVENT_POISON: if (!me->HasAura(SPELL_WIDOWS_EMBRACE_HELPER)) DoCastAOE(SPELL_POISON_BOLT_VOLLEY); - events.ScheduleEvent(EVENT_POISON, urand(8000, 15000)); + events.Repeat(randtime(Seconds(8), Seconds(15))); break; case EVENT_FIRE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) DoCast(target, SPELL_RAIN_OF_FIRE); - events.ScheduleEvent(EVENT_FIRE, urand(6000, 18000)); + events.Repeat(randtime(Seconds(6), Seconds(18))); break; case EVENT_FRENZY: if (Aura* widowsEmbrace = me->GetAura(SPELL_WIDOWS_EMBRACE_HELPER)) - events.ScheduleEvent(EVENT_FRENZY, widowsEmbrace->GetDuration()+1 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_FRENZY, Milliseconds(widowsEmbrace->GetDuration()+1)); else { DoCast(SPELL_FRENZY); Talk(EMOTE_FRENZY); - events.ScheduleEvent(EVENT_FRENZY, urand(60 * IN_MILLISECONDS, 80 * IN_MILLISECONDS)); + events.Repeat(Minutes(1) + randtime(Seconds(0), Seconds(20))); } break; } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp index a7a89f44d81..0de1c4785b8 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -285,7 +285,7 @@ struct boss_four_horsemen_baseAI : public BossAI void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_HORSEMEN) != NOT_STARTED) // another horseman already did it + if (instance->GetBossState(BOSS_HORSEMEN) == IN_PROGRESS || instance->GetBossState(BOSS_HORSEMEN) == DONE) // another horseman already did it return; Talk(SAY_AGGRO); BeginEncounter(); @@ -411,9 +411,9 @@ class boss_four_horsemen_baron : public CreatureScript else AttackStart(threat.getHostilTarget()); - events.ScheduleEvent(EVENT_BERSERK, 10 * MINUTE * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_MARK, 24 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_UNHOLYSHADOW, urandms(3,7)); + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); + events.ScheduleEvent(EVENT_MARK, Seconds(24)); + events.ScheduleEvent(EVENT_UNHOLYSHADOW, randtime(Seconds(3), Seconds(7))); } void _UpdateAI(uint32 diff) override @@ -431,11 +431,11 @@ class boss_four_horsemen_baron : public CreatureScript break; case EVENT_MARK: DoCastAOE(SPELL_BARON_MARK, true); - events.ScheduleEvent(EVENT_MARK, 12 * IN_MILLISECONDS); + events.Repeat(Seconds(12)); break; case EVENT_UNHOLYSHADOW: DoCastVictim(SPELL_UNHOLY_SHADOW); - events.ScheduleEvent(EVENT_UNHOLYSHADOW, urandms(10,30)); + events.Repeat(randtime(Seconds(10), Seconds(30))); break; } } @@ -484,9 +484,9 @@ class boss_four_horsemen_thane : public CreatureScript else AttackStart(threat.getHostilTarget()); - events.ScheduleEvent(EVENT_BERSERK, 10 * MINUTE * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_MARK, 24 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_METEOR, urandms(10,15)); + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); + events.ScheduleEvent(EVENT_MARK, Seconds(24)); + events.ScheduleEvent(EVENT_METEOR, randtime(Seconds(10), Seconds(25))); } void _UpdateAI(uint32 diff) override { @@ -503,7 +503,7 @@ class boss_four_horsemen_thane : public CreatureScript break; case EVENT_MARK: DoCastAOE(SPELL_THANE_MARK, true); - events.ScheduleEvent(EVENT_MARK, 12 * IN_MILLISECONDS); + events.Repeat(Seconds(12)); break; case EVENT_METEOR: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, true)) @@ -511,7 +511,7 @@ class boss_four_horsemen_thane : public CreatureScript DoCast(target, SPELL_METEOR); _shouldSay = true; } - events.ScheduleEvent(EVENT_METEOR, urandms(13,17)); + events.Repeat(randtime(Seconds(13), Seconds(17))); break; } } @@ -550,9 +550,9 @@ class boss_four_horsemen_lady : public CreatureScript boss_four_horsemen_ladyAI(Creature* creature) : boss_four_horsemen_baseAI(creature, LADY, ladyPath) { } void BeginFighting() override { - events.ScheduleEvent(EVENT_BERSERK, 10 * MINUTE * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_MARK, 24 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_VOIDZONE, urandms(5,10)); + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); + events.ScheduleEvent(EVENT_MARK, Seconds(24)); + events.ScheduleEvent(EVENT_VOIDZONE, randtime(Seconds(5), Seconds(10))); } void _UpdateAI(uint32 diff) override @@ -578,7 +578,7 @@ class boss_four_horsemen_lady : public CreatureScript break; case EVENT_MARK: DoCastAOE(SPELL_LADY_MARK, true); - events.ScheduleEvent(EVENT_MARK, 15 * IN_MILLISECONDS); + events.Repeat(Seconds(15)); break; case EVENT_VOIDZONE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true)) @@ -586,7 +586,7 @@ class boss_four_horsemen_lady : public CreatureScript DoCast(target, SPELL_VOID_ZONE, true); Talk(SAY_SPECIAL); } - events.ScheduleEvent(EVENT_VOIDZONE, urandms(12, 18)); + events.Repeat(randtime(Seconds(12), Seconds(18))); break; } } @@ -620,9 +620,9 @@ class boss_four_horsemen_sir : public CreatureScript boss_four_horsemen_sirAI(Creature* creature) : boss_four_horsemen_baseAI(creature, SIR, sirPath), _shouldSay(true) { } void BeginFighting() override { - events.ScheduleEvent(EVENT_BERSERK, 10 * MINUTE * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_MARK, 24 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_HOLYWRATH, urandms(13,18)); + events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); + events.ScheduleEvent(EVENT_MARK, Seconds(24)); + events.ScheduleEvent(EVENT_HOLYWRATH, randtime(Seconds(13), Seconds(18))); } void _UpdateAI(uint32 diff) override @@ -648,7 +648,7 @@ class boss_four_horsemen_sir : public CreatureScript break; case EVENT_MARK: DoCastAOE(SPELL_SIR_MARK, true); - events.ScheduleEvent(EVENT_MARK, 15 * IN_MILLISECONDS); + events.Repeat(Seconds(15)); break; case EVENT_HOLYWRATH: if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true)) @@ -656,7 +656,7 @@ class boss_four_horsemen_sir : public CreatureScript DoCast(target, SPELL_HOLY_WRATH, true); _shouldSay = true; } - events.ScheduleEvent(EVENT_HOLYWRATH, urandms(10,18)); + events.Repeat(randtime(Seconds(10), Seconds(18))); break; } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index ec47b0db101..6ec9af68723 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -18,38 +18,74 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "naxxramas.h" +#include "SpellScript.h" +#include <math.h> -enum Spells +enum Texts { - SPELL_MORTAL_WOUND = 25646, - SPELL_ENRAGE = 28371, - SPELL_DECIMATE = 28374, - SPELL_BERSERK = 26662, - SPELL_INFECTED_WOUND = 29306 + EMOTE_SPOTS_ONE = 0, + EMOTE_DECIMATE = 1, + EMOTE_ENRAGE = 2, + EMOTE_DEVOURS_ALL = 3, + EMOTE_BERSERKER = 4 }; -enum Creatures +enum Spells { - NPC_ZOMBIE = 16360 + // Gluth + SPELL_MORTAL_WOUND = 54378, // spell effect dummy unused. what its supposed to do is unkown. + SPELL_ENRAGE = 28371, // 54427 in 25 man. + SPELL_DECIMATE = 28374, // 54426 in 25 man. Effect0 is handled by SpellScript (see below) and 2 rows in conditions table. Effect2 is handled by SpellScript (see below). + SPELL_DECIMATE_DMG = 28375, + SPELL_BERSERK = 26662, + SPELL_ZOMBIE_CHOW_SEARCH_SINGLE = 28239, // Insta kill spell. Single target. See spell script below. + SPELL_ZOMBIE_CHOW_SEARCH_MULTI = 28404, // Insta kill spell. Affect all zombies 10 yards around Gluth's center. See one row conditions table + spell script below. + + // Zombies + SPELL_INFECTED_WOUND = 29307 // Used by the zombies on self. }; Position const PosSummon[3] = { - {3267.9f, -3172.1f, 297.42f, 0.94f}, - {3253.2f, -3132.3f, 297.42f, 0}, - {3308.3f, -3185.8f, 297.42f, 1.58f}, + { 3270.132f, -3169.948f, 297.5891f, 5.88176f }, + { 3307.298f, -3183.449f, 297.5891f, 5.742133f }, + { 3255.708f, -3135.677f, 297.5891f, 1.867502f } }; enum Events { - EVENT_WOUND = 1, + EVENT_WOUND = 1, EVENT_ENRAGE, EVENT_DECIMATE, EVENT_BERSERK, EVENT_SUMMON, + EVENT_SEARCH_ZOMBIE_SINGLE, + EVENT_KILL_ZOMBIE_SINGLE, + EVENT_SEARCH_ZOMBIE_MULTI }; -#define EMOTE_NEARBY " spots a nearby zombie to devour!" +enum States +{ + STATE_GLUTH_NORMAL = 1, + STATE_GLUTH_EATING = 2, + + STATE_ZOMBIE_NORMAL = 1, + STATE_ZOMBIE_DECIMATED = 2, + STATE_ZOMBIE_TOBE_EATEN = 3 +}; + +enum SummonGroups +{ + SUMMON_GROUP_CHOW_10MAN = 1, + SUMMON_GROUP_CHOW_25MAN = 2 +}; + +enum Misc +{ + EVENT_GLUTH_ZOMBIE_BEHAVIOR = 10495, // unused. event handled by spell_gluth_decimate_SpellScript::HandleEvent + DATA_ZOMBIE_STATE = 1, + ACTION_DECIMATE_EVENT = 2, +}; class boss_gluth : public CreatureScript { @@ -58,99 +94,390 @@ public: CreatureAI* GetAI(Creature* creature) const override { - return new boss_gluthAI(creature); + return GetInstanceAI<boss_gluthAI>(creature); } struct boss_gluthAI : public BossAI { - boss_gluthAI(Creature* creature) : BossAI(creature, BOSS_GLUTH) - { - // Do not let Gluth be affected by zombies' debuff - me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true); - } - void MoveInLineOfSight(Unit* who) override + boss_gluthAI(Creature* creature) : BossAI(creature, BOSS_GLUTH), state(STATE_GLUTH_NORMAL) {} + + void Reset() override { - if (who->GetEntry() == NPC_ZOMBIE && me->IsWithinDistInMap(who, 7)) - { - SetGazeOn(who); - /// @todo use a script text - me->TextEmote(EMOTE_NEARBY, nullptr, true); - } - else - BossAI::MoveInLineOfSight(who); + _Reset(); + zombieToBeEatenGUID.Clear(); + state = STATE_GLUTH_NORMAL; + me->SetReactState(REACT_AGGRESSIVE); + me->SetSpeed(UnitMoveType::MOVE_RUN, 12.0f); } void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.ScheduleEvent(EVENT_WOUND, 10000); - events.ScheduleEvent(EVENT_ENRAGE, 15000); - events.ScheduleEvent(EVENT_DECIMATE, 105000); - events.ScheduleEvent(EVENT_BERSERK, 8*60000); - events.ScheduleEvent(EVENT_SUMMON, 15000); + events.ScheduleEvent(EVENT_WOUND, Seconds(10)); + events.ScheduleEvent(EVENT_ENRAGE, randtime(Seconds(16), Seconds(22))); + events.ScheduleEvent(EVENT_DECIMATE, randtime(Minutes(1)+Seconds(50), Minutes(2))); + events.ScheduleEvent(EVENT_BERSERK, Minutes(8)); + events.ScheduleEvent(EVENT_SUMMON, Seconds(15)); + events.ScheduleEvent(EVENT_SEARCH_ZOMBIE_SINGLE, Seconds(12)); } - void JustSummoned(Creature* summon) override + void SummonedCreatureDies(Creature* summoned, Unit* /* who */) override { - if (summon->GetEntry() == NPC_ZOMBIE) - summon->AI()->AttackStart(me); - summons.Summon(summon); + summons.Despawn(summoned); // needed or else dead zombies not despawned yet will still be in the list } void UpdateAI(uint32 diff) override { - if (!UpdateVictimWithGaze()) + if (!UpdateVictim() || !CheckInRoom()) return; events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_WOUND: + if (state == STATE_GLUTH_EATING) + { + events.Repeat(Seconds(3)); + break; + } + DoCastVictim(SPELL_MORTAL_WOUND); - events.ScheduleEvent(EVENT_WOUND, 10000); + events.Repeat(Seconds(10)); break; case EVENT_ENRAGE: - /// @todo Add missing text + if (state == STATE_GLUTH_EATING) + { + events.Repeat(Seconds(5)); + break; + } + + Talk(EMOTE_ENRAGE); DoCast(me, SPELL_ENRAGE); - events.ScheduleEvent(EVENT_ENRAGE, 15000); + events.Repeat(randtime(Seconds(16), Seconds(22))); break; case EVENT_DECIMATE: - /// @todo Add missing text + if (state == STATE_GLUTH_EATING) + { + events.Repeat(Seconds(4)); + break; + } + + Talk(EMOTE_DECIMATE); DoCastAOE(SPELL_DECIMATE); - events.ScheduleEvent(EVENT_DECIMATE, 105000); + for (int i = 1; i <= 20; i++) + events.ScheduleEvent(EVENT_SEARCH_ZOMBIE_MULTI, Seconds(3*i)); + events.ScheduleEvent(EVENT_DECIMATE, randtime(Minutes(1)+Seconds(50), Minutes(2))); break; case EVENT_BERSERK: + Talk(EMOTE_BERSERKER); DoCast(me, SPELL_BERSERK); - events.ScheduleEvent(EVENT_BERSERK, 5*60000); + events.Repeat(Minutes(5)); //refresh the hard enrage buff break; case EVENT_SUMMON: - for (int32 i = 0; i < RAID_MODE(1, 2); ++i) - DoSummon(NPC_ZOMBIE, PosSummon[rand32() % RAID_MODE(1, 3)]); - events.ScheduleEvent(EVENT_SUMMON, 10000); + if (Is25ManRaid()) // one wave each 10s. one wave=1 zombie in 10man and 2 zombies in 25man. + me->SummonCreatureGroup(SUMMON_GROUP_CHOW_25MAN); + else + me->SummonCreatureGroup(SUMMON_GROUP_CHOW_10MAN); + events.Repeat(Seconds(10)); + break; + case EVENT_SEARCH_ZOMBIE_SINGLE: + { + Creature* zombie = nullptr; + for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr) + { + zombie=ObjectAccessor::GetCreature(*me, *itr); + if (!zombie || !zombie->IsAlive() || !zombie->IsWithinDistInMap(me, 10.0)) + zombie = nullptr; + } + + if (zombie) + { + zombieToBeEatenGUID = zombie->GetGUID(); // save for later use + + // the soon-to-be-eaten zombie should stop moving and stop attacking + zombie->AI()->SetData(DATA_ZOMBIE_STATE, STATE_ZOMBIE_TOBE_EATEN); + + // gluth should stop AAs on his primary target and turn toward the zombie (2 yards away). He then pauses for a few seconds. + me->SetSpeed(MOVE_RUN, 36.0f); + + me->SetReactState(ReactStates::REACT_PASSIVE); + me->AttackStop(); + + Talk(EMOTE_SPOTS_ONE); + + //me->SetTarget(ObjectGuid::Empty); + + me->GetMotionMaster()->MoveCloserAndStop(1, zombie, 2.0f); + + state = STATE_GLUTH_EATING; + } + + events.Repeat(RAID_MODE(Seconds(7), Seconds(5))); + break; + } + case EVENT_KILL_ZOMBIE_SINGLE: + { + Creature* zombieToBeEaten = ObjectAccessor::GetCreature(*me, zombieToBeEatenGUID); + if (zombieToBeEaten && zombieToBeEaten->IsAlive() && zombieToBeEaten->IsWithinDistInMap(me, 10.0)) + DoCast(zombieToBeEaten, SPELL_ZOMBIE_CHOW_SEARCH_SINGLE); // do the killing + healing in done inside by spell script see below. + + zombieToBeEatenGUID = ObjectGuid::Empty; + state = STATE_GLUTH_NORMAL; + me->SetSpeed(UnitMoveType::MOVE_RUN, 12.0f); + + // and then return on primary target + me->SetReactState(REACT_AGGRESSIVE); + + break; + } + case EVENT_SEARCH_ZOMBIE_MULTI: + { + if (state == STATE_GLUTH_EATING) // skip and simply wait for the next occurence + break; + + Creature* zombie = nullptr; + for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr) + { + zombie = ObjectAccessor::GetCreature(*me, *itr); + if (zombie && zombie->IsAlive() && zombie->GetExactDist2d(me) > 18.0) + zombie = nullptr; + } + + if (zombie) // cast the aoe spell only if at least one zombie is found nearby + { + Talk(EMOTE_DEVOURS_ALL); + DoCastAOE(SPELL_ZOMBIE_CHOW_SEARCH_MULTI); + } break; + } } } - if (me->GetVictim() && me->EnsureVictim()->GetEntry() == NPC_ZOMBIE) + DoMeleeAttackIfReady(); + } + + void MovementInform(uint32 /*type*/, uint32 id) override + { + if (id == 1){ + me->GetMotionMaster()->MoveIdle(); + events.ScheduleEvent(EVENT_KILL_ZOMBIE_SINGLE, Seconds(1)); + } + + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_DECIMATE_EVENT: + for (ObjectGuid zombieGuid : summons) + { + Creature* zombie = ObjectAccessor::GetCreature(*me, zombieGuid); + if (zombie && zombie->IsAlive()) + zombie->AI()->SetData(DATA_ZOMBIE_STATE, STATE_ZOMBIE_DECIMATED); + } + break; + } + } + + private: + ObjectGuid zombieToBeEatenGUID; + uint8 state; + }; + +}; + +// spell 28374 (10man) / 54426 (25man) - Decimate +class spell_gluth_decimate : public SpellScriptLoader +{ +public: + spell_gluth_decimate() : SpellScriptLoader("spell_gluth_decimate") { } + + class spell_gluth_decimate_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gluth_decimate_SpellScript); + + // handles the damaging effect of the decimate spell. + void HandleScriptEffect(SpellEffIndex /* index */) + { + if (Unit *unit = GetHitUnit()) { - if (me->IsWithinMeleeRange(me->GetVictim())) + int32 damage = int32(unit->GetHealth()) - int32(unit->CountPctFromMaxHealth(5)); + if (damage > 0) + GetCaster()->CastCustomSpell(SPELL_DECIMATE_DMG, SPELLVALUE_BASE_POINT0, damage, unit); + } + } + + // handles the change of zombies behavior after the decimate spell + void HandleEvent(SpellEffIndex /* index */) + { + GetCaster()->GetAI()->DoAction(ACTION_DECIMATE_EVENT); + } + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return (sSpellMgr->GetSpellInfo(SPELL_DECIMATE_DMG) != nullptr); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gluth_decimate_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + OnEffectHit += SpellEffectFn(spell_gluth_decimate_SpellScript::HandleEvent, EFFECT_2, SPELL_EFFECT_SEND_EVENT); + } + + bool Load() override + { + return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH; + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gluth_decimate_SpellScript(); + } + +}; + +// used by both 28239 & 28404 (single target and aoe zombie-kill spell) to heal Gluth on each target hit. + +class spell_gluth_zombiechow_search : public SpellScriptLoader +{ +public: + spell_gluth_zombiechow_search() : SpellScriptLoader("spell_gluth_zombiechow_search") { } + + class spell_gluth_zombiechow_search_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gluth_zombiechow_search_SpellScript); + + void HealForEachTargetHit() + { + GetCaster()->ModifyHealth(int32(GetCaster()->CountPctFromMaxHealth(5))); + } + + void Register() override + { + AfterHit += SpellHitFn(spell_gluth_zombiechow_search_SpellScript::HealForEachTargetHit); + } + + bool Load() override + { + return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH; + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gluth_zombiechow_search_SpellScript(); + } + +}; + +// creature 16360 (10man) / 30303 (25man) +class npc_zombie_chow : public CreatureScript +{ +public: + + npc_zombie_chow() : CreatureScript("npc_zombie_chow") { } + + struct npc_zombie_chowAI : public ScriptedAI + { + npc_zombie_chowAI(Creature* creature) : ScriptedAI(creature) + { + GluthGUID = creature->GetInstanceScript()->GetGuidData(DATA_GLUTH); + + DoCast(me, SPELL_INFECTED_WOUND); + timer = 0; + state = STATE_ZOMBIE_NORMAL; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (state == STATE_ZOMBIE_DECIMATED) + { + timer += diff; + if (Creature* gluth = ObjectAccessor::GetCreature(*me, GluthGUID)) { - me->Kill(me->GetVictim()); - me->ModifyHealth(int32(me->CountPctFromMaxHealth(5))); + // Putting this in the UpdateAI loop fixes an issue where death gripping a decimated zombie would make the zombie stand still until the rest of the fight. + // Also fix the issue where if one or more zombie is rooted when decimates hits (and MovePoint() is called), the zombie teleport to the boss. pretty weird behavior. + if (timer > 1600 && me->GetExactDist2d(gluth) > 10.0f && me->CanFreeMove()) // it takes about 1600 ms for the animation to cycle. This way, the animation looks relatively smooth. + { + me->GetMotionMaster()->MovePoint(0, gluth->GetPosition()); // isn't dynamic. So, to take into account Gluth's movement, it must be called periodicly. + timer = 0; + } + + if (me->GetExactDist2d(gluth) <= 10.0f) + me->StopMoving(); } } - else + else if (state == STATE_ZOMBIE_NORMAL) DoMeleeAttackIfReady(); } + + void SetData(uint32 id, uint32 value) override + { + if (id == DATA_ZOMBIE_STATE) // change of state + { + state = value; + if (value == STATE_ZOMBIE_DECIMATED) + { + me->SetReactState(ReactStates::REACT_PASSIVE); + me->AttackStop(); + me->SetTarget(ObjectGuid::Empty); + // at this point, the zombie should be non attacking and non moving. + + me->SetWalk(true); // it doesnt seem to work with MoveFollow() (but it does work with MovePoint()). + + timer = 1000; + } + else if (value == STATE_ZOMBIE_TOBE_EATEN) + { + // forced to stand still + me->GetMotionMaster()->Clear(); + me->StopMoving(); + + // and loose aggro behavior + me->SetReactState(ReactStates::REACT_PASSIVE); + me->AttackStop(); + me->SetTarget(ObjectGuid::Empty); + + me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_GRIP, true); // not sure if this is blizz-like but this is very convenient + } + } + } + + uint32 GetData(uint32 index) const override + { + if (index == DATA_ZOMBIE_STATE) + return state; + return 0; + } + + private: + uint32 timer; + uint8 state; + ObjectGuid GluthGUID; }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_zombie_chowAI>(creature); + } }; void AddSC_boss_gluth() { new boss_gluth(); + new spell_gluth_decimate(); + new spell_gluth_zombiechow_search(); + new npc_zombie_chow(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index 81f1e071da0..30c05c9dca9 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -65,7 +65,7 @@ enum Spells /* gothik phase two spells */ SPELL_HARVEST_SOUL = 28679, SPELL_SHADOW_BOLT = 29317, - + /* visual spells */ SPELL_ANCHOR_1_TRAINEE = 27892, SPELL_ANCHOR_1_DK = 27928, @@ -324,13 +324,13 @@ class boss_gothik : public CreatureScript { _EnterCombat(); events.SetPhase(PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON, 25 * IN_MILLISECONDS, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_DOORS_UNLOCK, 205 * IN_MILLISECONDS, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_PHASE_TWO, 270 * IN_MILLISECONDS, 0, PHASE_ONE); + events.ScheduleEvent(EVENT_SUMMON, Seconds(25), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_DOORS_UNLOCK, Minutes(3) + Seconds(25), 0, PHASE_ONE); + events.ScheduleEvent(EVENT_PHASE_TWO, Minutes(4) + Seconds(30), 0, PHASE_ONE); Talk(SAY_INTRO_1); - events.ScheduleEvent(EVENT_INTRO_2, 4 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_INTRO_3, 9 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_INTRO_4, 14 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_INTRO_2, Seconds(4)); + events.ScheduleEvent(EVENT_INTRO_3, Seconds(9)); + events.ScheduleEvent(EVENT_INTRO_4, Seconds(14)); instance->SetData(DATA_GOTHIK_GATE, GO_STATE_READY); _gateIsOpen = false; } @@ -373,10 +373,14 @@ class boss_gothik : public CreatureScript instance->SetData(DATA_GOTHIK_GATE, GO_STATE_ACTIVE); Talk(EMOTE_GATE_OPENED); _gateIsOpen = true; - + for (ObjectGuid summonGuid : summons) + { if (Creature* summon = ObjectAccessor::GetCreature(*me, summonGuid)) summon->AI()->DoAction(ACTION_GATE_OPENED); + if (summons.empty()) // ACTION_GATE_OPENED may cause an evade, despawning summons and invalidating our iterator + break; + } } void DamageTaken(Unit* /*who*/, uint32& damage) override @@ -440,7 +444,7 @@ class boss_gothik : public CreatureScript TC_LOG_INFO("scripts", "GothikAI: Wave count %d is out of range for difficulty %d.", _waveCount, GetDifficulty()); break; } - + std::list<Creature*> triggers; me->GetCreatureListWithEntryInGrid(triggers, NPC_TRIGGER, 150.0f); for (GothikWaveEntry entry : RAID_MODE(waves10, waves25)[_waveCount].first) @@ -466,7 +470,7 @@ class boss_gothik : public CreatureScript default: targetDBGuid = 0; } - + for (Creature* trigger : triggers) if (trigger && trigger->GetSpawnId() == targetDBGuid) { @@ -476,7 +480,7 @@ class boss_gothik : public CreatureScript } if (uint8 timeToNext = RAID_MODE(waves10, waves25)[_waveCount].second) - events.ScheduleEvent(EVENT_SUMMON, timeToNext * IN_MILLISECONDS, 0, PHASE_ONE); + events.Repeat(Seconds(timeToNext)); ++_waveCount; break; @@ -493,9 +497,9 @@ class boss_gothik : public CreatureScript break; case EVENT_PHASE_TWO: events.SetPhase(PHASE_TWO); - events.ScheduleEvent(EVENT_TELEPORT, 20 * IN_MILLISECONDS, 0, PHASE_TWO); - events.ScheduleEvent(EVENT_HARVEST, 15 * IN_MILLISECONDS, 0, PHASE_TWO); - events.ScheduleEvent(EVENT_RESUME_ATTACK, 2 * IN_MILLISECONDS, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_TELEPORT, Seconds(20), 0, PHASE_TWO); + events.ScheduleEvent(EVENT_HARVEST, Seconds(15), 0, PHASE_TWO); + events.ScheduleEvent(EVENT_RESUME_ATTACK, Seconds(2), 0, PHASE_TWO); Talk(SAY_PHASE_TWO); Talk(EMOTE_PHASE_TWO); me->SetReactState(REACT_PASSIVE); @@ -514,23 +518,23 @@ class boss_gothik : public CreatureScript _lastTeleportDead = !_lastTeleportDead; events.CancelEvent(EVENT_BOLT); - events.ScheduleEvent(EVENT_TELEPORT, 20 * IN_MILLISECONDS, 0, PHASE_TWO); events.ScheduleEvent(EVENT_RESUME_ATTACK, 2 * IN_MILLISECONDS, 0, PHASE_TWO); + events.Repeat(Seconds(20)); } break; case EVENT_HARVEST: DoCastAOE(SPELL_HARVEST_SOUL, true); // triggered allows this to go "through" shadow bolt - events.ScheduleEvent(EVENT_HARVEST, 15 * IN_MILLISECONDS, 0, PHASE_TWO); + events.Repeat(Seconds(15)); break; case EVENT_RESUME_ATTACK: me->SetReactState(REACT_AGGRESSIVE); - events.ScheduleEvent(EVENT_BOLT, 0, 0, PHASE_TWO); + events.ScheduleEvent(EVENT_BOLT, Seconds(0), 0, PHASE_TWO); // return to the start of this method so victim side etc is re-evaluated return UpdateAI(0u); // tail recursion for efficiency case EVENT_BOLT: DoCastVictim(SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_BOLT, 1 * IN_MILLISECONDS, 0, PHASE_TWO); + events.Repeat(Seconds(2)); break; case EVENT_INTRO_2: Talk(SAY_INTRO_2); @@ -544,7 +548,7 @@ class boss_gothik : public CreatureScript } } } - + private: uint32 _waveCount; bool _gateCanOpen; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index a1d8f6e5e02..cf38d659d40 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -57,10 +57,10 @@ class boss_grobbulus : public CreatureScript void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.ScheduleEvent(EVENT_CLOUD, 15000); - events.ScheduleEvent(EVENT_INJECT, 20000); - events.ScheduleEvent(EVENT_SPRAY, urand(15000, 30000)); // not sure - events.ScheduleEvent(EVENT_BERSERK, 12 * 60000); + events.ScheduleEvent(EVENT_CLOUD, Seconds(15)); + events.ScheduleEvent(EVENT_INJECT, Seconds(20)); + events.ScheduleEvent(EVENT_SPRAY, randtime(Seconds(15), Seconds(30))); // not sure + events.ScheduleEvent(EVENT_BERSERK, Minutes(12)); } void SpellHitTarget(Unit* target, SpellInfo const* spell) override @@ -82,19 +82,19 @@ class boss_grobbulus : public CreatureScript { case EVENT_CLOUD: DoCastAOE(SPELL_POISON_CLOUD); - events.ScheduleEvent(EVENT_CLOUD, 15000); + events.Repeat(Seconds(15)); return; case EVENT_BERSERK: DoCastAOE(SPELL_BERSERK, true); return; case EVENT_SPRAY: DoCastAOE(SPELL_SLIME_SPRAY); - events.ScheduleEvent(EVENT_SPRAY, urand(15000, 30000)); + events.Repeat(randtime(Seconds(15), Seconds(30))); return; case EVENT_INJECT: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_MUTATING_INJECTION)) DoCast(target, SPELL_MUTATING_INJECTION); - events.ScheduleEvent(EVENT_INJECT, 8000 + uint32(120 * me->GetHealthPct())); + events.Repeat(Seconds(8) + Milliseconds(uint32(std::round(120 * me->GetHealthPct())))); return; default: break; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp index 9b9619fe5b9..41d718d188d 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp @@ -27,6 +27,7 @@ enum Spells SPELL_SPELL_DISRUPTION = 29310, SPELL_PLAGUE_CLOUD = 29350, SPELL_TELEPORT_SELF = 30211, + SPELL_ERUPTION = 29371 }; enum Yells @@ -60,6 +61,15 @@ enum Misc DATA_SAFETY_DANCE = 19962139 }; +static const uint32 firstEruptionDBGUID = 84980; +static const uint8 numSections = 4; +static const uint8 numEruptions[numSections] = { // count of sequential GO DBGUIDs in the respective section of the room + 15, + 25, + 23, + 13 +}; + class boss_heigan : public CreatureScript { public: @@ -72,7 +82,7 @@ public: struct boss_heiganAI : public BossAI { - boss_heiganAI(Creature* creature) : BossAI(creature, BOSS_HEIGAN), eruptSection(0), eruptDirection(false), safetyDance(false) { } + boss_heiganAI(Creature* creature) : BossAI(creature, BOSS_HEIGAN), _safeSection(0), _danceDirection(false), _safetyDance(false) { } void Reset() override { @@ -82,15 +92,16 @@ public: void KilledUnit(Unit* who) override { - Talk(SAY_SLAY); - if (who->GetTypeId() == TYPEID_PLAYER) - safetyDance = false; + { + Talk(SAY_SLAY); + _safetyDance = false; + } } uint32 GetData(uint32 type) const override { - return (type == DATA_SAFETY_DANCE && safetyDance) ? 1u : 0u; + return (type == DATA_SAFETY_DANCE && _safetyDance) ? 1u : 0u; } void JustDied(Unit* /*killer*/) override @@ -104,13 +115,27 @@ public: _EnterCombat(); Talk(SAY_AGGRO); - eruptSection = 3; - events.ScheduleEvent(EVENT_DISRUPT, urand(15 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_FIGHT); - events.ScheduleEvent(EVENT_FEVER, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_FIGHT); - events.ScheduleEvent(EVENT_DANCE, 90 * IN_MILLISECONDS, 0, PHASE_FIGHT); - events.ScheduleEvent(EVENT_ERUPT, 15 * IN_MILLISECONDS, 0, PHASE_FIGHT); + _safeSection = 0; + events.ScheduleEvent(EVENT_DISRUPT, randtime(Seconds(15), Seconds(20)), 0, PHASE_FIGHT); + events.ScheduleEvent(EVENT_FEVER, randtime(Seconds(10), Seconds(20)), 0, PHASE_FIGHT); + events.ScheduleEvent(EVENT_DANCE, Minutes(1) + Seconds(30), 0, PHASE_FIGHT); + events.ScheduleEvent(EVENT_ERUPT, Seconds(15), 0, PHASE_FIGHT); + + _safetyDance = true; - safetyDance = true; + // figure out the current GUIDs of our eruption tiles and which segment they belong in + std::unordered_multimap<uint32, GameObject*> const& mapGOs = me->GetMap()->GetGameObjectBySpawnIdStore(); + uint32 spawnId = firstEruptionDBGUID; + for (uint8 section = 0; section < numSections; ++section) + { + _eruptTiles[section].clear(); + for (uint8 i = 0; i < numEruptions[section]; ++i) + { + std::pair<std::unordered_multimap<uint32, GameObject*>::const_iterator, std::unordered_multimap<uint32, GameObject*>::const_iterator> tileIt = mapGOs.equal_range(spawnId++); + for (std::unordered_multimap<uint32, GameObject*>::const_iterator it = tileIt.first; it != tileIt.second; ++it) + _eruptTiles[section].push_back(it->second->GetGUID()); + } + } } void UpdateAI(uint32 diff) override @@ -126,52 +151,56 @@ public: { case EVENT_DISRUPT: DoCastAOE(SPELL_SPELL_DISRUPTION); - events.ScheduleEvent(EVENT_DISRUPT, 11 * IN_MILLISECONDS); + events.Repeat(Seconds(11)); break; case EVENT_FEVER: DoCastAOE(SPELL_DECREPIT_FEVER); - events.ScheduleEvent(EVENT_FEVER, urand(20 * IN_MILLISECONDS, 25 * IN_MILLISECONDS)); + events.Repeat(randtime(Seconds(20), Seconds(25))); break; case EVENT_DANCE: events.SetPhase(PHASE_DANCE); Talk(SAY_TAUNT); Talk(EMOTE_DANCE); - eruptSection = 3; + _safeSection = 0; me->SetReactState(REACT_PASSIVE); me->AttackStop(); me->StopMoving(); DoCast(SPELL_TELEPORT_SELF); DoCastAOE(SPELL_PLAGUE_CLOUD); - events.ScheduleEvent(EVENT_DANCE_END, 45 * IN_MILLISECONDS, 0, PHASE_DANCE); - events.ScheduleEvent(EVENT_ERUPT, 10 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_DANCE_END, Seconds(45), 0, PHASE_DANCE); + events.ScheduleEvent(EVENT_ERUPT, Seconds(10)); break; case EVENT_DANCE_END: events.SetPhase(PHASE_FIGHT); Talk(EMOTE_DANCE_END); - eruptSection = 3; - events.ScheduleEvent(EVENT_DISRUPT, urand(10, 25) * IN_MILLISECONDS, 0, PHASE_FIGHT); - events.ScheduleEvent(EVENT_FEVER, urand(15, 20) * IN_MILLISECONDS, 0, PHASE_FIGHT); - events.ScheduleEvent(EVENT_DANCE, 90 * IN_MILLISECONDS, 0, PHASE_FIGHT); - events.ScheduleEvent(EVENT_ERUPT, 15 * IN_MILLISECONDS, 0, PHASE_FIGHT); + _safeSection = 0; + events.ScheduleEvent(EVENT_DISRUPT, randtime(Seconds(10), Seconds(25)), 0, PHASE_FIGHT); + events.ScheduleEvent(EVENT_FEVER, randtime(Seconds(15), Seconds(20)), 0, PHASE_FIGHT); + events.ScheduleEvent(EVENT_DANCE, Minutes(1) + Seconds(30), 0, PHASE_FIGHT); + events.ScheduleEvent(EVENT_ERUPT, Seconds(15), 0, PHASE_FIGHT); me->CastStop(); me->SetReactState(REACT_AGGRESSIVE); DoZoneInCombat(); break; case EVENT_ERUPT: - instance->SetData(DATA_HEIGAN_ERUPT, eruptSection); TeleportCheaters(); - - if (eruptSection == 0) - eruptDirection = true; - else if (eruptSection == 3) - eruptDirection = false; - - eruptDirection ? ++eruptSection : --eruptSection; - - if (events.IsInPhase(PHASE_DANCE)) - events.ScheduleEvent(EVENT_ERUPT, 3 * IN_MILLISECONDS, 0, PHASE_DANCE); - else - events.ScheduleEvent(EVENT_ERUPT, 10 * IN_MILLISECONDS, 0, PHASE_FIGHT); + for (uint8 section = 0; section < numSections; ++section) + if (section != _safeSection) + for (ObjectGuid tileGUID : _eruptTiles[section]) + if (GameObject* tile = ObjectAccessor::GetGameObject(*me, tileGUID)) + { + tile->SendCustomAnim(0); + tile->CastSpell(nullptr, SPELL_ERUPTION); + } + + if (_safeSection == 0) + _danceDirection = true; + else if (_safeSection == numSections-1) + _danceDirection = false; + + _danceDirection ? ++_safeSection : --_safeSection; + + events.Repeat(events.IsInPhase(PHASE_DANCE) ? Seconds(3) : Seconds(10)); break; } } @@ -180,10 +209,11 @@ public: } private: - uint32 eruptSection; - bool eruptDirection; + std::vector<ObjectGuid> _eruptTiles[numSections]; // populated on encounter start - bool safetyDance; // is achievement still possible? (= no player deaths yet) + uint32 _safeSection; // 0 is next to the entrance + bool _danceDirection; // true is counter-clockwise, false is clock-wise + bool _safetyDance; // is achievement still possible? (= no player deaths yet) }; }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 47807ec28cb..42efdfbfe67 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -309,7 +309,7 @@ public: _Reset(); me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE); ResetPlayerScale(); spawns.DespawnAll(); @@ -356,7 +356,7 @@ public: } DoCast(me, SPELL_KELTHUZAD_CHANNEL, false); Talk(SAY_SUMMON_MINIONS); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE); me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4); me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4); events.SetPhase(PHASE_ONE); @@ -426,7 +426,7 @@ public: Talk(SAY_AGGRO); Talk(EMOTE_PHASE_TWO); spawns.DespawnAll(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE); me->CastStop(); DoStartMovement(me->GetVictim()); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp index 086d21120e8..c6c9c76bed4 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp @@ -24,7 +24,6 @@ enum Spells { SPELL_NECROTIC_AURA = 55593, - SPELL_WARN_NECROTIC_AURA = 59481, SPELL_SUMMON_SPORE = 29234, SPELL_DEATHBLOOM = 29865, SPELL_INEVITABLE_DOOM = 29204, @@ -42,11 +41,12 @@ enum Texts enum Events { - EVENT_NECROTIC_AURA = 1, - EVENT_DEATHBLOOM = 2, - EVENT_INEVITABLE_DOOM = 3, - EVENT_SPORE = 4, - EVENT_NECROTIC_AURA_FADING = 5, + EVENT_NECROTIC_AURA = 1, + EVENT_DEATHBLOOM, + EVENT_INEVITABLE_DOOM, + EVENT_SPORE, + EVENT_NECROTIC_AURA_FADING, + EVENT_NECROTIC_AURA_FADED }; enum Achievement @@ -82,10 +82,10 @@ class boss_loatheb : public CreatureScript void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.ScheduleEvent(EVENT_NECROTIC_AURA, 17 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_DEATHBLOOM, 5 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SPORE, RAID_MODE(36,18) * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 2 * MINUTE * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_NECROTIC_AURA, Seconds(17)); + events.ScheduleEvent(EVENT_DEATHBLOOM, Seconds(5)); + events.ScheduleEvent(EVENT_SPORE, Seconds(18)); + events.ScheduleEvent(EVENT_INEVITABLE_DOOM, Minutes(2)); } void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override @@ -94,13 +94,6 @@ class boss_loatheb : public CreatureScript summon->CastSpell(summon,SPELL_FUNGAL_CREEP,true); } - void SummonedCreatureDespawn(Creature* summon) override - { - summons.Despawn(summon); - if (summon->IsAlive()) - summon->CastSpell(summon,SPELL_FUNGAL_CREEP,true); - } - uint32 GetData(uint32 id) const override { return (_sporeLoserData && id == DATA_ACHIEVEMENT_SPORE_LOSER) ? 1u : 0u; @@ -119,34 +112,33 @@ class boss_loatheb : public CreatureScript { case EVENT_NECROTIC_AURA: DoCastAOE(SPELL_NECROTIC_AURA); - DoCast(me, SPELL_WARN_NECROTIC_AURA); - events.ScheduleEvent(EVENT_NECROTIC_AURA, 20 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_NECROTIC_AURA_FADING, 14 * IN_MILLISECONDS); + Talk(SAY_NECROTIC_AURA_APPLIED); + events.ScheduleEvent(EVENT_NECROTIC_AURA_FADING, Seconds(14)); + events.ScheduleEvent(EVENT_NECROTIC_AURA_FADED, Seconds(17)); + events.Repeat(Seconds(20)); break; case EVENT_DEATHBLOOM: DoCastAOE(SPELL_DEATHBLOOM); - events.ScheduleEvent(EVENT_DEATHBLOOM, 30 * IN_MILLISECONDS); + events.Repeat(Seconds(30)); break; case EVENT_INEVITABLE_DOOM: _doomCounter++; DoCastAOE(SPELL_INEVITABLE_DOOM); if (_doomCounter > 6) - { - if (_doomCounter & 1) // odd - events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 14 * IN_MILLISECONDS); - else - events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 17 * IN_MILLISECONDS); - } + events.Repeat((_doomCounter & 1) ? Seconds(14) : Seconds(17)); else - events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 30 * IN_MILLISECONDS); + events.Repeat(30); break; case EVENT_SPORE: DoCast(me, SPELL_SUMMON_SPORE, false); - events.ScheduleEvent(EVENT_SPORE, RAID_MODE(36,18) * IN_MILLISECONDS); + events.Repeat(RAID_MODE(Seconds(36), Seconds(15))); break; case EVENT_NECROTIC_AURA_FADING: Talk(SAY_NECROTIC_AURA_FADING); break; + case EVENT_NECROTIC_AURA_FADED: + Talk(SAY_NECROTIC_AURA_REMOVED); + break; default: break; } @@ -177,49 +169,6 @@ class achievement_spore_loser : public AchievementCriteriaScript } }; -typedef boss_loatheb::boss_loathebAI LoathebAI; - -class spell_loatheb_necrotic_aura_warning : public SpellScriptLoader -{ - public: - spell_loatheb_necrotic_aura_warning() : SpellScriptLoader("spell_loatheb_necrotic_aura_warning") { } - - class spell_loatheb_necrotic_aura_warning_AuraScript : public AuraScript - { - PrepareAuraScript(spell_loatheb_necrotic_aura_warning_AuraScript); - - bool Validate(SpellInfo const* /*spell*/) override - { - if (!sSpellStore.LookupEntry(SPELL_WARN_NECROTIC_AURA)) - return false; - return true; - } - - void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (GetTarget()->IsAIEnabled) - ENSURE_AI(LoathebAI, GetTarget()->GetAI())->Talk(SAY_NECROTIC_AURA_APPLIED); - } - - void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) - { - if (GetTarget()->IsAIEnabled) - ENSURE_AI(LoathebAI, GetTarget()->GetAI())->Talk(SAY_NECROTIC_AURA_REMOVED); - } - - void Register() override - { - AfterEffectApply += AuraEffectApplyFn(spell_loatheb_necrotic_aura_warning_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - AfterEffectRemove += AuraEffectRemoveFn(spell_loatheb_necrotic_aura_warning_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_loatheb_necrotic_aura_warning_AuraScript(); - } -}; - class spell_loatheb_deathbloom : public SpellScriptLoader { public: @@ -260,6 +209,5 @@ void AddSC_boss_loatheb() { new boss_loatheb(); new achievement_spore_loser(); - new spell_loatheb_necrotic_aura_warning(); new spell_loatheb_deathbloom(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp index 9d8f1365afb..9502193884a 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -73,6 +73,8 @@ struct WebTargetSelector : public std::unary_function<Unit*, bool> WebTargetSelector(Unit* maexxna) : _maexxna(maexxna) {} bool operator()(Unit const* target) const { + if (target->GetTypeId() != TYPEID_PLAYER) // never web nonplayers (pets, guardians, etc.) + return false; if (_maexxna->GetVictim() == target) // never target tank return false; if (target->HasAura(SPELL_WEB_WRAP)) // never target targets that are already webbed @@ -101,11 +103,11 @@ public: void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.ScheduleEvent(EVENT_WRAP, 20 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SPRAY, 40 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SHOCK, urandms(5, 10)); - events.ScheduleEvent(EVENT_POISON, urandms(10, 15)); - events.ScheduleEvent(EVENT_SUMMON, 30 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_WRAP, Seconds(20)); + events.ScheduleEvent(EVENT_SPRAY, Seconds(40)); + events.ScheduleEvent(EVENT_SHOCK, randtime(Seconds(5), Seconds(10))); + events.ScheduleEvent(EVENT_POISON, randtime(Seconds(10), Seconds(15))); + events.ScheduleEvent(EVENT_SUMMON, Seconds(30)); } void Reset() override @@ -153,28 +155,28 @@ public: } } } - events.ScheduleEvent(EVENT_WRAP, 40000); + events.Repeat(Seconds(40)); break; } case EVENT_SPRAY: Talk(EMOTE_WEB_SPRAY); DoCastAOE(SPELL_WEB_SPRAY); - events.ScheduleEvent(EVENT_SPRAY, 40000); + events.Repeat(Seconds(40)); break; case EVENT_SHOCK: DoCastAOE(SPELL_POISON_SHOCK); - events.ScheduleEvent(EVENT_SHOCK, urandms(10, 20)); + events.Repeat(randtime(Seconds(10), Seconds(20))); break; case EVENT_POISON: DoCastVictim(SPELL_NECROTIC_POISON); - events.ScheduleEvent(EVENT_POISON, urandms(10, 20)); + events.Repeat(randtime(Seconds(10), Seconds(20))); break; case EVENT_SUMMON: Talk(EMOTE_SPIDERS); uint8 amount = urand(8, 10); for (uint8 i = 0; i < amount; ++i) DoSummon(NPC_SPIDERLING, me, 4.0f, 5 * IN_MILLISECONDS, TEMPSUMMON_CORPSE_TIMED_DESPAWN); - events.ScheduleEvent(EVENT_SUMMON, 40000); + events.Repeat(Seconds(40)); break; } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index 8ee3936dee3..2108b4ce102 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -131,25 +131,25 @@ public: Reset(); else { - uint8 secondsGround; + uint8 timeGround; switch (balconyCount) { case 0: - secondsGround = 90; + timeGround = 90; break; case 1: - secondsGround = 110; + timeGround = 110; break; case 2: default: - secondsGround = 180; + timeGround = 180; } - events.ScheduleEvent(EVENT_GROUND_ATTACKABLE, 2 * IN_MILLISECONDS, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_BALCONY, secondsGround * IN_MILLISECONDS, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_CURSE, urand(10,25) * IN_MILLISECONDS, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_WARRIOR, urand(20,30) * IN_MILLISECONDS, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_GROUND_ATTACKABLE, Seconds(2), 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_BALCONY, Seconds(timeGround), 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_CURSE, randtime(Seconds(10), Seconds(25)), 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_WARRIOR, randtime(Seconds(20), Seconds(30)), 0, PHASE_GROUND); if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - events.ScheduleEvent(EVENT_BLINK, urand(20,30) * IN_MILLISECONDS, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_BLINK, randtime(Seconds(20), Seconds(30)), 0, PHASE_GROUND); } } @@ -220,7 +220,7 @@ public: case EVENT_CURSE: { DoCastAOE(SPELL_CURSE); - events.ScheduleEvent(EVENT_CURSE, urand(50, 70) * IN_MILLISECONDS, 0, PHASE_GROUND); + events.Repeat(randtime(Seconds(50), Seconds(70))); break; } case EVENT_WARRIOR: @@ -229,7 +229,7 @@ public: CastSummon(RAID_MODE(2, 3), 0, 0); - events.ScheduleEvent(EVENT_WARRIOR, 40 * IN_MILLISECONDS, 0, PHASE_GROUND); + events.Repeat(Seconds(40)); break; case EVENT_BLINK: DoCastAOE(SPELL_CRIPPLE, true); @@ -237,7 +237,7 @@ public: DoResetThreat(); justBlinked = true; - events.ScheduleEvent(EVENT_BLINK, 40000, 0, PHASE_GROUND); + events.Repeat(Seconds(40)); break; case EVENT_BALCONY: events.SetPhase(PHASE_BALCONY); @@ -247,24 +247,24 @@ public: me->StopMoving(); me->RemoveAllAuras(); - events.ScheduleEvent(EVENT_BALCONY_TELEPORT, 3 * IN_MILLISECONDS, 0, PHASE_BALCONY); - events.ScheduleEvent(EVENT_WAVE, urand(5 * IN_MILLISECONDS, 8 * IN_MILLISECONDS), 0, PHASE_BALCONY); + events.ScheduleEvent(EVENT_BALCONY_TELEPORT, Seconds(3), 0, PHASE_BALCONY); + events.ScheduleEvent(EVENT_WAVE, randtime(Seconds(5), Seconds(8)), 0, PHASE_BALCONY); - uint8 secondsBalcony; + uint8 timeBalcony; switch (balconyCount) { case 0: - secondsBalcony = 70; + timeBalcony = 70; break; case 1: - secondsBalcony = 97; + timeBalcony = 97; break; case 2: default: - secondsBalcony = 120; + timeBalcony = 120; break; } - events.ScheduleEvent(EVENT_GROUND, secondsBalcony * IN_MILLISECONDS, 0, PHASE_BALCONY); + events.ScheduleEvent(EVENT_GROUND, Seconds(timeBalcony), 0, PHASE_BALCONY); break; case EVENT_BALCONY_TELEPORT: Talk(EMOTE_TELEPORT_1); @@ -287,7 +287,7 @@ public: CastSummon(0, RAID_MODE(5, 10), RAID_MODE(5, 10)); break; } - events.ScheduleEvent(EVENT_WAVE, urand(30, 45) * IN_MILLISECONDS, 0, PHASE_BALCONY); + events.Repeat(randtime(Seconds(30), Seconds(45))); break; case EVENT_GROUND: ++balconyCount; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp index b8ce402a939..cfa6e2e9f30 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp @@ -97,8 +97,8 @@ public: _EnterCombat(); Enraged = false; Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_HATEFUL, 1 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_BERSERK, 6 * MINUTE * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_HATEFUL, Seconds(1)); + events.ScheduleEvent(EVENT_BERSERK, Minutes(6)); instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); } @@ -167,17 +167,17 @@ public: if (thirdThreatTarget) me->getThreatManager().addThreat(thirdThreatTarget, HATEFUL_THREAT_AMT); // this will only ever be used in 25m - events.ScheduleEvent(EVENT_HATEFUL, 1 * IN_MILLISECONDS); + events.Repeat(Seconds(1)); break; } case EVENT_BERSERK: DoCast(me, SPELL_BERSERK, true); Talk(EMOTE_BERSERK); - events.ScheduleEvent(EVENT_SLIME, 2 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_SLIME, Seconds(2)); break; case EVENT_SLIME: - DoCastVictim(SPELL_SLIME_BOLT, true); - events.ScheduleEvent(EVENT_SLIME, 2 * IN_MILLISECONDS); + DoCastAOE(SPELL_SLIME_BOLT, true); + events.Repeat(Seconds(2)); break; } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp index 1d12f64a949..548f8086eb8 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp @@ -104,6 +104,9 @@ public: void JustDied(Unit* /*killer*/) override { + for (ObjectGuid summonGuid : summons) + if (Creature* summon = ObjectAccessor::GetCreature(*me, summonGuid)) + summon->RemoveCharmAuras(); Talk(SAY_DEATH); DoCastAOE(SPELL_HOPELESS, true); @@ -117,10 +120,10 @@ public: me->StopMoving(); summons.DoZoneInCombat(); Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_ATTACK, 7 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_STRIKE, 21 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SHOUT, 16 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_KNIFE, 10 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_ATTACK, Seconds(7)); + events.ScheduleEvent(EVENT_STRIKE, Seconds(21)); + events.ScheduleEvent(EVENT_SHOUT, Seconds(16)); + events.ScheduleEvent(EVENT_KNIFE, Seconds(10)); } void UpdateAI(uint32 diff) override @@ -141,16 +144,16 @@ public: break; case EVENT_STRIKE: DoCastVictim(SPELL_UNBALANCING_STRIKE); - events.ScheduleEvent(EVENT_STRIKE, 6 * IN_MILLISECONDS); + events.Repeat(Seconds(6)); return; case EVENT_SHOUT: DoCastAOE(SPELL_DISRUPTING_SHOUT); - events.ScheduleEvent(EVENT_SHOUT, 16 * IN_MILLISECONDS); + events.Repeat(Seconds(16)); return; case EVENT_KNIFE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f)) DoCast(target, SPELL_JAGGED_KNIFE); - events.ScheduleEvent(EVENT_KNIFE, urandms(10,15)); + events.Repeat(randtime(Seconds(10), Seconds(15))); return; } } @@ -174,7 +177,10 @@ class npc_dk_understudy : public CreatureScript struct npc_dk_understudyAI : public ScriptedAI { - npc_dk_understudyAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), bloodStrikeTimer(0) { } + npc_dk_understudyAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), bloodStrikeTimer(0) + { + creature->LoadEquipment(1); + } void EnterCombat(Unit* /*who*/) override { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp index 68b9e252150..0c9a236e196 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -16,7 +16,9 @@ */ #include "ScriptMgr.h" +#include "GameObjectAI.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "Player.h" #include "SpellInfo.h" #include "naxxramas.h" @@ -31,25 +33,24 @@ enum Yells enum Spells { - SPELL_FROST_AURA = 28531, - SPELL_CLEAVE = 19983, - SPELL_TAIL_SWEEP = 55697, - SPELL_SUMMON_BLIZZARD = 28560, - SPELL_LIFE_DRAIN = 28542, - SPELL_ICEBOLT = 28522, - SPELL_FROST_BREATH = 29318, - SPELL_FROST_EXPLOSION = 28524, - SPELL_FROST_MISSILE = 30101, - SPELL_BERSERK = 26662, - SPELL_DIES = 29357, - SPELL_CHILL = 28547, - SPELL_CHECK_RESISTS = 60539, + SPELL_FROST_AURA = 28531, + SPELL_CLEAVE = 19983, + SPELL_TAIL_SWEEP = 55697, + SPELL_SUMMON_BLIZZARD = 28560, + SPELL_LIFE_DRAIN = 28542, + SPELL_ICEBOLT = 28522, + SPELL_FROST_BREATH_ANTICHEAT = 29318, // damage effect ignoring LoS on the entrance platform to prevent cheese + SPELL_FROST_BREATH = 28524, // damage effect below sapphiron + SPELL_FROST_MISSILE = 30101, // visual only + SPELL_BERSERK = 26662, + SPELL_DIES = 29357, + SPELL_CHECK_RESISTS = 60539, + SPELL_SAPPHIRON_WING_BUFFET = 29328 }; enum Phases { - PHASE_NULL = 0, - PHASE_BIRTH, + PHASE_BIRTH = 1, PHASE_GROUND, PHASE_FLIGHT }; @@ -72,9 +73,15 @@ enum Events EVENT_CHECK_RESISTS }; +enum Actions +{ + ACTION_BIRTH = 1 +}; + enum Misc { NPC_BLIZZARD = 16474, + NPC_WING_BUFFET = 17025, GO_ICEBLOCK = 181247, // The Hundred Club @@ -92,77 +99,74 @@ class boss_sapphiron : public CreatureScript struct boss_sapphironAI : public BossAI { boss_sapphironAI(Creature* creature) : - BossAI(creature, BOSS_SAPPHIRON), _iceboltCount(0), _map(me->GetMap()) + BossAI(creature, BOSS_SAPPHIRON) { Initialize(); } void Initialize() { - _phase = PHASE_NULL; - + _delayedDrain = false; _canTheHundredClub = true; } void InitializeAI() override { + if (instance->GetBossState(BOSS_SAPPHIRON) == DONE) + return; + _canTheHundredClub = true; - float x, y, z; - me->GetPosition(x, y, z); - me->SummonGameObject(GO_BIRTH, x, y, z, 0, 0, 0, 0, 0, 0); - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); + if (!instance->GetData(DATA_HAD_SAPPHIRON_BIRTH)) + { + me->SetVisible(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetReactState(REACT_PASSIVE); + } BossAI::InitializeAI(); } void Reset() override { - _Reset(); - - if (_phase == PHASE_FLIGHT) + if (events.IsInPhase(PHASE_FLIGHT)) { - ClearIceBlock(); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ICEBOLT); me->SetReactState(REACT_AGGRESSIVE); if (me->IsHovering()) { me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); me->SetHover(false); } - me->SetDisableGravity(false); } + _Reset(); Initialize(); } + void DamageTaken(Unit* /*who*/, uint32& damage) override + { + if (damage < me->GetHealth() || !events.IsInPhase(PHASE_FLIGHT)) + return; + damage = me->GetHealth()-1; // don't die during air phase + } + void EnterCombat(Unit* /*who*/) override { _EnterCombat(); me->CastSpell(me, SPELL_FROST_AURA, true); - DoCast(me, SPELL_CHECK_RESISTS); - events.ScheduleEvent(EVENT_CHECK_RESISTS, 30 * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_BERSERK, 15 * MINUTE * IN_MILLISECONDS); - EnterPhaseGround(); + events.SetPhase(PHASE_GROUND); + events.ScheduleEvent(EVENT_CHECK_RESISTS, Seconds(0)); + events.ScheduleEvent(EVENT_BERSERK, Minutes(15)); + EnterPhaseGround(true); } void SpellHitTarget(Unit* target, SpellInfo const* spell) override { switch(spell->Id) { - case SPELL_ICEBOLT: - { - IceBlockMap::iterator itr = _iceblocks.find(target->GetGUID()); - if (itr != _iceblocks.end() && !itr->second) - { - if (GameObject* iceblock = me->SummonGameObject(GO_ICEBLOCK, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, 0, 0, 0, 0, 25)) - itr->second = iceblock->GetGUID(); - } - break; - } case SPELL_CHECK_RESISTS: if (target && target->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE) _canTheHundredClub = false; @@ -179,41 +183,37 @@ class boss_sapphiron : public CreatureScript void MovementInform(uint32 /*type*/, uint32 id) override { if (id == 1) - events.ScheduleEvent(EVENT_LIFTOFF, 0); + events.ScheduleEvent(EVENT_LIFTOFF, Seconds(0), 0, PHASE_FLIGHT); } void DoAction(int32 param) override { - if (param == DATA_SAPPHIRON_BIRTH) + if (param == ACTION_BIRTH) { - _phase = PHASE_BIRTH; - events.ScheduleEvent(EVENT_BIRTH, 23 * IN_MILLISECONDS); + events.SetPhase(PHASE_BIRTH); + events.ScheduleEvent(EVENT_BIRTH, Seconds(23)); } } - void EnterPhaseGround() + void EnterPhaseGround(bool initial) { - _phase = PHASE_GROUND; me->SetReactState(REACT_AGGRESSIVE); - events.SetPhase(PHASE_GROUND); - events.ScheduleEvent(EVENT_CLEAVE, urand(5, 15) * IN_MILLISECONDS, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_TAIL, urand(5, 15) * IN_MILLISECONDS, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_DRAIN, 24 * IN_MILLISECONDS, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_BLIZZARD, urand(5, 10) * IN_MILLISECONDS, 0, PHASE_GROUND); - events.ScheduleEvent(EVENT_FLIGHT, 45 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_CLEAVE, randtime(Seconds(5), Seconds(15)), 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_TAIL, randtime(Seconds(7), Seconds(10)), 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_BLIZZARD, randtime(Seconds(5), Seconds(10)), 0, PHASE_GROUND); + if (initial) + { + events.ScheduleEvent(EVENT_DRAIN, randtime(Seconds(22), Seconds(28))); + events.ScheduleEvent(EVENT_FLIGHT, Seconds(48) + Milliseconds(500), 0, PHASE_GROUND); + } + else + events.ScheduleEvent(EVENT_FLIGHT, Minutes(1), 0, PHASE_GROUND); } - void ClearIceBlock() + inline void CastDrain() { - for (IceBlockMap::const_iterator itr = _iceblocks.begin(); itr != _iceblocks.end(); ++itr) - { - if (Player* player = ObjectAccessor::GetPlayer(*me, itr->first)) - player->RemoveAura(SPELL_ICEBOLT); - - if (GameObject* go = ObjectAccessor::GetGameObject(*me, itr->second)) - go->Delete(); - } - _iceblocks.clear(); + DoCastAOE(SPELL_LIFE_DRAIN); + events.ScheduleEvent(EVENT_DRAIN, randtime(Seconds(22), Seconds(28))); } uint32 GetData(uint32 data) const override @@ -226,15 +226,12 @@ class boss_sapphiron : public CreatureScript void UpdateAI(uint32 diff) override { - if (!_phase) - return; - events.Update(diff); - if (_phase != PHASE_BIRTH && !UpdateVictim()) + if (!events.IsInPhase(PHASE_BIRTH) && !UpdateVictim()) return; - if (_phase == PHASE_GROUND) + if (events.IsInPhase(PHASE_GROUND)) { while (uint32 eventId = events.ExecuteEvent()) { @@ -242,7 +239,10 @@ class boss_sapphiron : public CreatureScript { case EVENT_CHECK_RESISTS: DoCast(me, SPELL_CHECK_RESISTS); - events.ScheduleEvent(EVENT_CHECK_RESISTS, 30 * IN_MILLISECONDS); + events.Repeat(Seconds(30)); + return; + case EVENT_GROUND: + EnterPhaseGround(false); return; case EVENT_BERSERK: Talk(EMOTE_ENRAGE); @@ -250,27 +250,26 @@ class boss_sapphiron : public CreatureScript return; case EVENT_CLEAVE: DoCastVictim(SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, urand(5, 15) * IN_MILLISECONDS, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_CLEAVE, randtime(Seconds(5), Seconds(15)), 0, PHASE_GROUND); return; case EVENT_TAIL: DoCastAOE(SPELL_TAIL_SWEEP); - events.ScheduleEvent(EVENT_TAIL, urand(5, 15) * IN_MILLISECONDS, 0, PHASE_GROUND); + events.ScheduleEvent(EVENT_TAIL, randtime(Seconds(7), Seconds(10)), 0, PHASE_GROUND); return; case EVENT_DRAIN: - DoCastAOE(SPELL_LIFE_DRAIN); - events.ScheduleEvent(EVENT_DRAIN, 24 * IN_MILLISECONDS, 0, PHASE_GROUND); + if (events.IsInPhase(PHASE_FLIGHT)) + _delayedDrain = true; + else + CastDrain(); return; case EVENT_BLIZZARD: - { - if (Creature* summon = DoSummon(NPC_BLIZZARD, me, 0.0f, urand(25, 30) * IN_MILLISECONDS, TEMPSUMMON_TIMED_DESPAWN)) - summon->GetMotionMaster()->MoveRandom(40); - events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(20, 7) * IN_MILLISECONDS, 0, PHASE_GROUND); + DoCastAOE(SPELL_SUMMON_BLIZZARD); + events.ScheduleEvent(EVENT_BLIZZARD, RAID_MODE(Seconds(20), Seconds(7)), 0, PHASE_GROUND); break; - } case EVENT_FLIGHT: if (HealthAbovePct(10)) { - _phase = PHASE_FLIGHT; + _delayedDrain = false; events.SetPhase(PHASE_FLIGHT); me->SetReactState(REACT_PASSIVE); me->AttackStop(); @@ -293,61 +292,69 @@ class boss_sapphiron : public CreatureScript { case EVENT_CHECK_RESISTS: DoCast(me, SPELL_CHECK_RESISTS); - events.ScheduleEvent(EVENT_CHECK_RESISTS, 30 * IN_MILLISECONDS); + events.Repeat(Seconds(30)); return; case EVENT_LIFTOFF: + { Talk(EMOTE_AIR_PHASE); - me->SetDisableGravity(true); + if (Creature* buffet = DoSummon(NPC_WING_BUFFET, me, 0.0f, 0, TEMPSUMMON_MANUAL_DESPAWN)) + _buffet = buffet->GetGUID(); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); me->SetHover(true); - events.ScheduleEvent(EVENT_ICEBOLT, 1500); - _iceboltCount = RAID_MODE(2, 3); + events.ScheduleEvent(EVENT_ICEBOLT, Seconds(7), 0, PHASE_FLIGHT); + + _iceboltTargets.clear(); + std::list<Unit*> targets; + SelectTargetList(targets, RAID_MODE(2, 3), SELECT_TARGET_RANDOM, 200.0f, true); + for (Unit* target : targets) + if (target) + _iceboltTargets.push_back(target->GetGUID()); return; + } case EVENT_ICEBOLT: { - std::vector<Unit*> targets; - std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - if ((*i)->getTarget()->GetTypeId() == TYPEID_PLAYER && !(*i)->getTarget()->HasAura(SPELL_ICEBOLT)) - targets.push_back((*i)->getTarget()); - - if (targets.empty()) - _iceboltCount = 0; - else + if (_iceboltTargets.empty()) { - std::vector<Unit*>::const_iterator itr = targets.begin(); - advance(itr, rand32() % targets.size()); - _iceblocks.insert(std::make_pair((*itr)->GetGUID(), ObjectGuid::Empty)); - DoCast(*itr, SPELL_ICEBOLT); - --_iceboltCount; + events.ScheduleEvent(EVENT_BREATH, Seconds(2), 0, PHASE_FLIGHT); + return; } - - if (_iceboltCount) - events.ScheduleEvent(EVENT_ICEBOLT, 1 * IN_MILLISECONDS); + ObjectGuid target = _iceboltTargets.back(); + if (Player* pTarget = ObjectAccessor::GetPlayer(*me, target)) + if (pTarget->IsAlive()) + DoCast(pTarget, SPELL_ICEBOLT); + _iceboltTargets.pop_back(); + + if (_iceboltTargets.empty()) + events.ScheduleEvent(EVENT_BREATH, Seconds(2), 0, PHASE_FLIGHT); else - events.ScheduleEvent(EVENT_BREATH, 1 * IN_MILLISECONDS); + events.Repeat(Seconds(3)); return; } case EVENT_BREATH: { Talk(EMOTE_BREATH); DoCastAOE(SPELL_FROST_MISSILE); - events.ScheduleEvent(EVENT_EXPLOSION, 8 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_EXPLOSION, Seconds(8), 0, PHASE_FLIGHT); return; } case EVENT_EXPLOSION: - CastExplosion(); - ClearIceBlock(); - events.ScheduleEvent(EVENT_LAND, 3 * IN_MILLISECONDS); + DoCastAOE(SPELL_FROST_BREATH); + DoCastAOE(SPELL_FROST_BREATH_ANTICHEAT); + events.ScheduleEvent(EVENT_LAND, Seconds(3) + Milliseconds(500), 0, PHASE_FLIGHT); return; case EVENT_LAND: + if (_delayedDrain) + CastDrain(); + if (Creature* cBuffet = ObjectAccessor::GetCreature(*me, _buffet)) + { + cBuffet->DespawnOrUnsummon(1 * IN_MILLISECONDS); + _buffet.Clear(); + } me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); Talk(EMOTE_GROUND_PHASE); me->SetHover(false); - me->SetDisableGravity(false); - events.ScheduleEvent(EVENT_GROUND, 1500); - return; - case EVENT_GROUND: - EnterPhaseGround(); + events.SetPhase(PHASE_GROUND); + events.ScheduleEvent(EVENT_GROUND, Seconds(3) + Milliseconds(500), 0, PHASE_GROUND); return; case EVENT_BIRTH: me->SetVisible(true); @@ -359,56 +366,261 @@ class boss_sapphiron : public CreatureScript } } - void CastExplosion() + private: + std::vector<ObjectGuid> _iceboltTargets; + ObjectGuid _buffet; + bool _delayedDrain; + bool _canTheHundredClub; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new boss_sapphironAI(creature); + } +}; + +class go_sapphiron_birth : public GameObjectScript +{ + public: + go_sapphiron_birth() : GameObjectScript("go_sapphiron_birth") { } + + struct go_sapphiron_birthAI : public GameObjectAI + { + go_sapphiron_birthAI(GameObject* go) : GameObjectAI(go), instance(go->GetInstanceScript()) { } + + void OnStateChanged(uint32 state, Unit* who) override + { + if (state == GO_ACTIVATED) + { + if (who) + { + if (Creature* sapphiron = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_SAPPHIRON))) + sapphiron->AI()->DoAction(ACTION_BIRTH); + instance->SetData(DATA_HAD_SAPPHIRON_BIRTH, 1u); + } + } + else if (state == GO_JUST_DEACTIVATED) + { // prevent ourselves from going back to _READY and resetting the client anim + go->SetRespawnTime(0); + go->Delete(); + } + } + + InstanceScript* instance; + }; + + GameObjectAI* GetAI(GameObject* go) const override + { + return GetInstanceAI<go_sapphiron_birthAI>(go); + } +}; + + +class spell_sapphiron_change_blizzard_target : public SpellScriptLoader +{ + public: + spell_sapphiron_change_blizzard_target() : SpellScriptLoader("spell_sapphiron_change_blizzard_target") { } + + class spell_sapphiron_change_blizzard_target_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sapphiron_change_blizzard_target_AuraScript); + + void HandlePeriodic(AuraEffect const* /*eff*/) + { + TempSummon* me = GetTarget()->ToTempSummon(); + if (Creature* owner = me ? me->GetSummonerCreatureBase() : nullptr) + { + Unit* newTarget = owner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true); + if (!newTarget) + newTarget = owner->getAttackerForHelper(); + if (newTarget) + me->GetMotionMaster()->MoveFollow(newTarget, 0.1f, 0.0f); + else + { + me->StopMoving(); + me->GetMotionMaster()->Clear(); + } + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_sapphiron_change_blizzard_target_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_sapphiron_change_blizzard_target_AuraScript(); + } +}; + +class spell_sapphiron_icebolt : public SpellScriptLoader +{ + public: + spell_sapphiron_icebolt() : SpellScriptLoader("spell_sapphiron_icebolt") { } + + class spell_sapphiron_icebolt_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sapphiron_icebolt_AuraScript); + + void HandleApply(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->ApplySpellImmune(SPELL_ICEBOLT, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FROST, true); + } + + void HandleRemove(AuraEffect const* /*eff*/, AuraEffectHandleModes /*mode*/) + { + if (_block) + if (GameObject* oBlock = ObjectAccessor::GetGameObject(*GetTarget(), _block)) + oBlock->Delete(); + GetTarget()->ApplySpellImmune(SPELL_ICEBOLT, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_FROST, false); + } + + void HandlePeriodic(AuraEffect const* /*eff*/) + { + if (_block) + return; + if (GetTarget()->isMoving()) + return; + float x, y, z; + GetTarget()->GetPosition(x, y, z); + if (GameObject* block = GetTarget()->SummonGameObject(GO_ICEBLOCK, x, y, z, 0.f, G3D::Quat(), 25)) + _block = block->GetGUID(); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_sapphiron_icebolt_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_sapphiron_icebolt_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_sapphiron_icebolt_AuraScript::HandlePeriodic, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + + ObjectGuid _block; + }; + + AuraScript* GetAuraScript() const override + { + return new spell_sapphiron_icebolt_AuraScript(); + } +}; + +// @hack Hello, developer from the future! How has your day been? +// Anyway, this is, as you can undoubtedly see, a hack to emulate line of sight checks on a spell that abides line of sight anyway. +// In the current core, line of sight is not properly checked for people standing behind an ice block. This is not a good thing and kills people. +// Thus, we have this hack to check for ice block LoS in a "safe" way. Kind of. It's inaccurate, but in a good way (tends to save people when it shouldn't in edge cases). +// If LoS handling is better in whatever the current revision is when you read this, please get rid of the hack. Thanks! +class spell_sapphiron_frost_breath : public SpellScriptLoader +{ + public: + spell_sapphiron_frost_breath() : SpellScriptLoader("spell_sapphiron_frost_breath") { } + + class spell_sapphiron_frost_breath_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sapphiron_frost_breath_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + return !!sSpellMgr->GetSpellInfo(SPELL_FROST_BREATH); + } + + void HandleTargets(std::list<WorldObject*>& targetList) { - DoZoneInCombat(); // make sure everyone is in threatlist - std::vector<Unit*> targets; - std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) + std::list<GameObject*> blocks; + if (GetCaster()) + GetCaster()->GetGameObjectListWithEntryInGrid(blocks, GO_ICEBLOCK, 200.0f); + + std::vector<Unit*> toRemove; + toRemove.reserve(3); + std::list<WorldObject*>::iterator it = targetList.begin(); + while (it != targetList.end()) { - Unit* target = (*i)->getTarget(); - if (target->GetTypeId() != TYPEID_PLAYER) + Unit* target = (*it)->ToUnit(); + if (!target) + { + it = targetList.erase(it); continue; + } if (target->HasAura(SPELL_ICEBOLT)) { - target->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); - targets.push_back(target); + it = targetList.erase(it); + toRemove.push_back(target); + continue; + } + + bool found = false; + for (GameObject* block : blocks) + if (block->IsInBetween(GetCaster(), target, 2.0f) && GetCaster()->GetExactDist2d(block) + 5 >= GetCaster()->GetExactDist2d(target)) + { + found = true; + break; + } + if (found) + { + it = targetList.erase(it); continue; } + ++it; + } + + for (Unit* block : toRemove) + block->RemoveAura(SPELL_ICEBOLT); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sapphiron_frost_breath_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ENEMY); + } + }; - for (IceBlockMap::const_iterator itr = _iceblocks.begin(); itr != _iceblocks.end(); ++itr) + SpellScript* GetSpellScript() const override + { + return new spell_sapphiron_frost_breath_SpellScript(); + } +}; + +class spell_sapphiron_summon_blizzard : public SpellScriptLoader +{ + public: + spell_sapphiron_summon_blizzard() : SpellScriptLoader("spell_sapphiron_summon_blizzard") { } + + class spell_sapphiron_summon_blizzard_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sapphiron_summon_blizzard_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + return !!sSpellMgr->GetSpellInfo(SPELL_SUMMON_BLIZZARD); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (Creature* blizzard = GetCaster()->SummonCreature(NPC_BLIZZARD, *target, TEMPSUMMON_TIMED_DESPAWN, urandms(25, 30))) { - if (GameObject* go = ObjectAccessor::GetGameObject(*me, itr->second)) + blizzard->CastSpell(nullptr, blizzard->m_spells[0], TRIGGERED_NONE); + if (Creature* creatureCaster = GetCaster()->ToCreature()) { - if (go->IsInBetween(me, target, 2.0f) - && me->GetExactDist2d(target->GetPositionX(), target->GetPositionY()) - me->GetExactDist2d(go->GetPositionX(), go->GetPositionY()) < 5.0f) + if (Unit* newTarget = creatureCaster->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true)) { - target->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, true); - targets.push_back(target); - break; + blizzard->GetMotionMaster()->MoveFollow(newTarget, 0.1f, 0.0f); + return; } } + blizzard->GetMotionMaster()->MoveFollow(target, 0.1f, 0.0f); } - } - - me->CastSpell(me, SPELL_FROST_EXPLOSION, true); - - for (std::vector<Unit*>::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - (*itr)->ApplySpellImmune(0, IMMUNITY_ID, SPELL_FROST_EXPLOSION, false); } - private: - Phases _phase; - uint32 _iceboltCount; - IceBlockMap _iceblocks; - bool _canTheHundredClub; - Map* _map; + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_sapphiron_summon_blizzard_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } }; - CreatureAI* GetAI(Creature* creature) const override + SpellScript* GetSpellScript() const override { - return new boss_sapphironAI(creature); + return new spell_sapphiron_summon_blizzard_SpellScript(); } }; @@ -426,5 +638,10 @@ class achievement_the_hundred_club : public AchievementCriteriaScript void AddSC_boss_sapphiron() { new boss_sapphiron(); + new go_sapphiron_birth(); + new spell_sapphiron_change_blizzard_target(); + new spell_sapphiron_icebolt(); + new spell_sapphiron_frost_breath(); + new spell_sapphiron_summon_blizzard(); new achievement_the_hundred_club(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index 7330f90e585..2cf3a4664dd 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -109,6 +109,10 @@ enum PetSpells SPELL_MAGNETIC_PULL = 54517, SPELL_MAGNETIC_PULL_EFFECT = 28337, + // @hack feugen/stalagg use this in P1 after gripping tanks to prevent mmaps from pathing them off the platform once they approach the ramp + // developer from the future, if you read this and mmaps in the room has been fixed, then get rid of the hackfix, please + SPELL_ROOT_SELF = 75215, + SPELL_TESLA_SHOCK = 28099 }; @@ -166,10 +170,12 @@ public: struct boss_thaddiusAI : public BossAI { public: - boss_thaddiusAI(Creature* creature) : BossAI(creature, BOSS_THADDIUS), stalaggAlive(true), feugenAlive(true), ballLightningEnabled(false), shockingEligibility(true) + boss_thaddiusAI(Creature* creature) : BossAI(creature, BOSS_THADDIUS), stalaggAlive(true), feugenAlive(true), ballLightningUnlocked(false), ballLightningEnabled(false), shockingEligibility(true) {} + + void InitializeAI() override { if (instance->GetBossState(BOSS_THADDIUS) != DONE) - { + { events.SetPhase(PHASE_NOT_ENGAGED); SetCombatMovement(false); @@ -184,12 +190,33 @@ public: Talk(SAY_SLAY); } - void Reset() override + void Reset() override { } + + void EnterEvadeMode(EvadeReason why) override { + if (!ballLightningEnabled && why == EVADE_REASON_NO_HOSTILES) + { + ballLightningEnabled = true; + return; // try again + } if (events.IsInPhase(PHASE_TRANSITION) || (events.IsInPhase(PHASE_THADDIUS) && me->IsAlive())) BeginResetEncounter(); } + bool CanAIAttack(Unit const* who) const override + { + if (ballLightningEnabled || me->IsWithinMeleeRange(who)) + return BossAI::CanAIAttack(who); + else + return false; + } + + void JustRespawned() override + { + if (events.IsInPhase(PHASE_RESETTING)) + ResetEncounter(); + } + void JustDied(Unit* /*killer*/) override { _JustDied(); @@ -217,18 +244,25 @@ public: case ACTION_FEUGEN_AGGRO: case ACTION_STALAGG_AGGRO: if (events.IsInPhase(PHASE_RESETTING)) - return BeginResetEncounter(); + { + BeginResetEncounter(); + return; + } if (!events.IsInPhase(PHASE_NOT_ENGAGED)) return; events.SetPhase(PHASE_PETS); shockingEligibility = true; - + if (!instance->CheckRequiredBosses(BOSS_THADDIUS)) - return BeginResetEncounter(); + { + BeginResetEncounter(); + return; + } instance->SetBossState(BOSS_THADDIUS, IN_PROGRESS); me->setActive(true); + DoZoneInCombat(); if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) stalagg->setActive(true); if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) @@ -239,7 +273,7 @@ public: feugen->AI()->DoAction(ACTION_FEUGEN_REVIVING_FX); feugenAlive = false; if (stalaggAlive) - events.ScheduleEvent(EVENT_REVIVE_FEUGEN, 5 * IN_MILLISECONDS, 0, PHASE_PETS); + events.ScheduleEvent(EVENT_REVIVE_FEUGEN, Seconds(5), 0, PHASE_PETS); else Transition(); @@ -249,7 +283,7 @@ public: stalagg->AI()->DoAction(ACTION_STALAGG_REVIVING_FX); stalaggAlive = false; if (feugenAlive) - events.ScheduleEvent(EVENT_REVIVE_STALAGG, 5 * IN_MILLISECONDS, 0, PHASE_PETS); + events.ScheduleEvent(EVENT_REVIVE_STALAGG, Seconds(5), 0, PHASE_PETS); else Transition(); @@ -274,9 +308,9 @@ public: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - events.ScheduleEvent(EVENT_TRANSITION_1, 10 * IN_MILLISECONDS, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_TRANSITION_2, 12 * IN_MILLISECONDS, 0, PHASE_TRANSITION); - events.ScheduleEvent(EVENT_TRANSITION_3, 14 * IN_MILLISECONDS, 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_TRANSITION_1, Seconds(10), 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_TRANSITION_2, Seconds(12), 0, PHASE_TRANSITION); + events.ScheduleEvent(EVENT_TRANSITION_3, Seconds(14), 0, PHASE_TRANSITION); } void BeginResetEncounter(bool initial = false) @@ -286,16 +320,12 @@ public: if (events.IsInPhase(PHASE_RESETTING)) return; - if (initial) // signal shorter spawn timer to instance script - instance->SetBossState(BOSS_THADDIUS, SPECIAL); - instance->ProcessEvent(me, EVENT_THADDIUS_BEGIN_RESET); - instance->SetBossState(BOSS_THADDIUS, NOT_STARTED); - // remove polarity shift debuffs on reset instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POSITIVE_CHARGE_APPLY); instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_NEGATIVE_CHARGE_APPLY); me->DespawnOrUnsummon(); + me->SetRespawnTime(initial ? 5 : 30); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); events.SetPhase(PHASE_RESETTING); @@ -312,11 +342,9 @@ public: feugenAlive = true; stalaggAlive = true; - me->Respawn(true); _Reset(); events.SetPhase(PHASE_NOT_ENGAGED); - - me->CastSpell(me, SPELL_THADDIUS_INACTIVE_VISUAL, true); + me->SetReactState(REACT_PASSIVE); if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) feugen->AI()->DoAction(ACTION_RESET_ENCOUNTER); @@ -361,16 +389,20 @@ public: break; case EVENT_TRANSITION_3: // thaddius becomes active me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true); - ballLightningEnabled = false; + ballLightningUnlocked = false; me->RemoveAura(SPELL_THADDIUS_INACTIVE_VISUAL); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); if (Unit* closest = SelectTarget(SELECT_TARGET_NEAREST, 0, 500.0f)) AttackStart(closest); else // if there is no nearest target, then there is no target, meaning we should reset - return BeginResetEncounter(); + { + BeginResetEncounter(); + return; + } if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) feugen->AI()->DoAction(ACTION_TRANSITION_3); @@ -381,20 +413,20 @@ public: Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_ENABLE_BALL_LIGHTNING, 5 * IN_MILLISECONDS, 0, PHASE_THADDIUS); - events.ScheduleEvent(EVENT_SHIFT, 10 * IN_MILLISECONDS, 0, PHASE_THADDIUS); - events.ScheduleEvent(EVENT_CHAIN, urand(10, 20) * IN_MILLISECONDS, 0, PHASE_THADDIUS); - events.ScheduleEvent(EVENT_BERSERK, 6 * MINUTE * IN_MILLISECONDS, 0, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_ENABLE_BALL_LIGHTNING, Seconds(5), 0, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_SHIFT, Seconds(10), 0, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_CHAIN, randtime(Seconds(10), Seconds(20)), 0, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_BERSERK, Minutes(6), 0, PHASE_THADDIUS); break; case EVENT_ENABLE_BALL_LIGHTNING: - ballLightningEnabled = true; + ballLightningUnlocked = true; break; case EVENT_SHIFT: me->CastStop(); // shift overrides all other spells DoCastAOE(SPELL_POLARITY_SHIFT); - events.ScheduleEvent(EVENT_SHIFT_TALK, 3 * IN_MILLISECONDS, PHASE_THADDIUS); - events.ScheduleEvent(EVENT_SHIFT, 30 * IN_MILLISECONDS, PHASE_THADDIUS); + events.ScheduleEvent(EVENT_SHIFT_TALK, Seconds(3), PHASE_THADDIUS); + events.ScheduleEvent(EVENT_SHIFT, Seconds(30), PHASE_THADDIUS); break; case EVENT_SHIFT_TALK: Talk(SAY_ELECT); @@ -402,12 +434,12 @@ public: break; case EVENT_CHAIN: if (me->FindCurrentSpellBySpellId(SPELL_POLARITY_SHIFT)) // delay until shift is over - events.ScheduleEvent(EVENT_CHAIN, 3 * IN_MILLISECONDS, 0, PHASE_THADDIUS); + events.Repeat(Seconds(3)); else { me->CastStop(); DoCastVictim(SPELL_CHAIN_LIGHTNING); - events.ScheduleEvent(EVENT_CHAIN, urand(10, 20) * IN_MILLISECONDS, PHASE_THADDIUS); + events.Repeat(randtime(Seconds(10), Seconds(20))); } break; case EVENT_BERSERK: @@ -418,22 +450,24 @@ public: break; } } - - if (events.IsInPhase(PHASE_THADDIUS)) + if (events.IsInPhase(PHASE_THADDIUS) && !me->HasUnitState(UNIT_STATE_CASTING) && me->isAttackReady()) { if (me->IsWithinMeleeRange(me->GetVictim())) + { + ballLightningEnabled = false; DoMeleeAttackIfReady(); - else - if (ballLightningEnabled) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_BALL_LIGHTNING); + } + else if (ballLightningUnlocked) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_BALL_LIGHTNING); } } private: bool stalaggAlive; bool feugenAlive; - bool ballLightningEnabled; + bool ballLightningUnlocked; // whether the initial ball lightning grace period has expired and we should proceed to exterminate with extreme prejudice + bool ballLightningEnabled; // switch that is flipped to true if we try to evade due to no eligible targets in melee range bool shockingEligibility; }; @@ -521,7 +555,7 @@ public: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Talk(EMOTE_FEIGN_REVIVE); isFeignDeath = false; - + refreshBeam = true; // force beam refresh if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) @@ -586,7 +620,7 @@ public: damage = 0; return; } - + isFeignDeath = true; isOverloading = false; @@ -652,7 +686,7 @@ public: else { DoCast(me, SPELL_STALAGG_POWERSURGE); - powerSurgeTimer = urand(25, 30) * IN_MILLISECONDS; + powerSurgeTimer = urandms(25, 30); } } else @@ -790,7 +824,7 @@ public: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Talk(EMOTE_FEIGN_REVIVE); isFeignDeath = false; - + refreshBeam = true; // force beam refresh if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) @@ -836,7 +870,7 @@ public: Talk(SAY_FEUGEN_AGGRO); if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) - thaddius->AI()->DoAction(ACTION_STALAGG_AGGRO); + thaddius->AI()->DoAction(ACTION_FEUGEN_AGGRO); if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) if (!stalagg->IsInCombat()) @@ -922,7 +956,7 @@ public: magneticPullTimer = 20 * IN_MILLISECONDS; } else magneticPullTimer -= uiDiff; - + if (staticFieldTimer <= uiDiff) { DoCast(me, SPELL_FEUGEN_STATICFIELD); @@ -971,7 +1005,7 @@ public: ObjectGuid _myCoil; ObjectGuid _myCoilGO; - + bool isOverloading; bool refreshBeam; bool isFeignDeath; @@ -1094,7 +1128,7 @@ class spell_thaddius_polarity_charge : public SpellScriptLoader SpellScript* GetSpellScript() const override { - return new spell_thaddius_polarity_charge_SpellScript; + return new spell_thaddius_polarity_charge_SpellScript(); } }; @@ -1169,7 +1203,7 @@ class spell_thaddius_magnetic_pull : public SpellScriptLoader Unit* feugen = GetCaster(); if (!feugen || feugen->GetEntry() != NPC_FEUGEN) return; - + Unit* stalagg = ObjectAccessor::GetCreature(*feugen, feugen->GetInstanceScript()->GetGuidData(DATA_STALAGG)); if (!stalagg) return; @@ -1212,6 +1246,10 @@ class spell_thaddius_magnetic_pull : public SpellScriptLoader feugenTank->CastSpell(stalaggTank, SPELL_MAGNETIC_PULL_EFFECT, true); stalaggTank->CastSpell(feugenTank, SPELL_MAGNETIC_PULL_EFFECT, true); + // @hack prevent mmaps clusterfucks from breaking tesla while tanks are midair + feugen->AddAura(SPELL_ROOT_SELF, feugen); + stalagg->AddAura(SPELL_ROOT_SELF, stalagg); + // and make both attack their respective new tanks if (feugen->GetAI()) feugen->GetAI()->AttackStart(stalaggTank); diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index c8a4eb7fbc8..720549de0b2 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -20,7 +20,7 @@ #include "InstanceScript.h" #include "naxxramas.h" -BossBoundaryData const boundaries = +BossBoundaryData const boundaries = { /* Arachnid Quarter */ { BOSS_ANUBREKHAN, new CircleBoundary(Position(3273.376709f, -3475.876709f), Position(3195.668213f, -3475.930176f)) }, @@ -100,36 +100,6 @@ ObjectData const objectData[] = { 0, 0, } }; -// from P2 teleport spell stored target -float const HeiganPos[2] = { 2793.86f, -3707.38f }; -float const HeiganEruptionSlope[3] = -{ - (-3703.303223f - HeiganPos[1]) / (2777.494141f - HeiganPos[0]), // between right center and far right - (-3696.948242f - HeiganPos[1]) / (2785.624268f - HeiganPos[0]), // between left and right halves - (-3691.880615f - HeiganPos[1]) / (2790.280029f - HeiganPos[0]) // between far left and left center -}; - -// 0 H x -// 1 ^ -// 2 | -// 3 y<--o -inline uint32 GetEruptionSection(float x, float y) -{ - y -= HeiganPos[1]; - if (y < 1.0f) - return 0; - - x -= HeiganPos[0]; - if (x > -1.0f) - return 3; - - float slope = y/x; - for (uint32 i = 0; i < 3; ++i) - if (slope > HeiganEruptionSlope[i]) - return i; - return 3; -} - class instance_naxxramas : public InstanceMapScript { public: @@ -149,9 +119,13 @@ class instance_naxxramas : public InstanceMapScript hadAnubRekhanGreet = false; hadFaerlinaGreet = false; hadThaddiusGreet = false; + hadSapphironBirth = false; CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT; playerDied = 0; + + nextFroggerWave = 0; + events.ScheduleEvent(EVENT_SUMMON_FROGGER_WAVE, Seconds(1)); } void OnCreatureCreate(Creature* creature) override @@ -182,6 +156,9 @@ class instance_naxxramas : public InstanceMapScript case NPC_SIR: SirGUID = creature->GetGUID(); break; + case NPC_GLUTH: + GluthGUID = creature->GetGUID(); + break; case NPC_HEIGAN: HeiganGUID = creature->GetGUID(); break; @@ -208,28 +185,8 @@ class instance_naxxramas : public InstanceMapScript } } - void ProcessEvent(WorldObject* /*source*/, uint32 eventId) override - { - switch (eventId) - { - case EVENT_THADDIUS_BEGIN_RESET: - if (GetBossState(BOSS_THADDIUS) == SPECIAL) // this is the initial spawn, we want a shorter spawn time - events.ScheduleEvent(EVENT_THADDIUS_RESET, 5 * IN_MILLISECONDS); - else - events.ScheduleEvent(EVENT_THADDIUS_RESET, 30 * IN_MILLISECONDS); - break; - } - } - void OnGameObjectCreate(GameObject* go) override { - if (go->GetGOInfo()->displayId == 6785 || go->GetGOInfo()->displayId == 1287) - { - uint32 section = GetEruptionSection(go->GetPositionX(), go->GetPositionY()); - HeiganEruptionGUID[section].insert(go->GetGUID()); - return; - } - switch (go->GetEntry()) { case GO_GOTHIK_GATE: @@ -273,37 +230,18 @@ class instance_naxxramas : public InstanceMapScript if (GetBossState(BOSS_HORSEMEN) == DONE) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); break; - default: - break; - } - - InstanceScript::OnGameObjectCreate(go); - } - - void OnGameObjectRemove(GameObject* go) override - { - if (go->GetGOInfo()->displayId == 6785 || go->GetGOInfo()->displayId == 1287) - { - uint32 section = GetEruptionSection(go->GetPositionX(), go->GetPositionY()); - HeiganEruptionGUID[section].erase(go->GetGUID()); - return; - } - - switch (go->GetEntry()) - { case GO_BIRTH: - if (SapphironGUID) + if (hadSapphironBirth || GetBossState(BOSS_SAPPHIRON) == DONE) { - if (Creature* sapphiron = instance->GetCreature(SapphironGUID)) - sapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH); - return; + hadSapphironBirth = true; + go->Delete(); } break; default: break; } - InstanceScript::OnGameObjectRemove(go); + InstanceScript::OnGameObjectCreate(go); } void OnUnitDeath(Unit* unit) override @@ -328,9 +266,6 @@ class instance_naxxramas : public InstanceMapScript { switch (id) { - case DATA_HEIGAN_ERUPT: - HeiganErupt(value); - break; case DATA_GOTHIK_GATE: if (GameObject* gate = instance->GetGameObject(GothikGateGUID)) gate->SetGoState(GOState(value)); @@ -347,6 +282,9 @@ class instance_naxxramas : public InstanceMapScript case DATA_HAD_THADDIUS_GREET: hadThaddiusGreet = (value == 1u); break; + case DATA_HAD_SAPPHIRON_BIRTH: + hadSapphironBirth = (value == 1u); + break; default: break; } @@ -364,6 +302,8 @@ class instance_naxxramas : public InstanceMapScript return hadFaerlinaGreet ? 1u : 0u; case DATA_HAD_THADDIUS_GREET: return hadThaddiusGreet ? 1u : 0u; + case DATA_HAD_SAPPHIRON_BIRTH: + return hadSapphironBirth ? 1u : 0u; default: break; } @@ -393,12 +333,16 @@ class instance_naxxramas : public InstanceMapScript return SirGUID; case DATA_HEIGAN: return HeiganGUID; + case DATA_GLUTH: + return GluthGUID; case DATA_FEUGEN: return FeugenGUID; case DATA_STALAGG: return StalaggGUID; case DATA_THADDIUS: return ThaddiusGUID; + case DATA_SAPPHIRON: + return SapphironGUID; case DATA_KELTHUZAD: return KelthuzadGUID; case DATA_KELTHUZAD_PORTAL01: @@ -431,7 +375,7 @@ class instance_naxxramas : public InstanceMapScript if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_ARACHNID)) teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); + events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, Seconds(6)); } break; case BOSS_LOATHEB: @@ -440,7 +384,7 @@ class instance_naxxramas : public InstanceMapScript if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_PLAGUE)) teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); + events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, Seconds(6)); } break; case BOSS_THADDIUS: @@ -449,12 +393,12 @@ class instance_naxxramas : public InstanceMapScript if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_CONSTRUCT)) teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); + events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, Seconds(6)); } break; case BOSS_GOTHIK: if (state == DONE) - events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ, 10000); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ, Seconds(10)); break; case BOSS_HORSEMEN: if (state == DONE) @@ -468,12 +412,12 @@ class instance_naxxramas : public InstanceMapScript if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_MILITARY)) teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000); + events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, Seconds(6)); } break; case BOSS_SAPPHIRON: if (state == DONE) - events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD, Seconds(6)); break; default: break; @@ -493,37 +437,37 @@ class instance_naxxramas : public InstanceMapScript case EVENT_DIALOGUE_GOTHIK_KORTHAZZ: if (Creature* korthazz = instance->GetCreature(ThaneGUID)) korthazz->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN); - events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK, 5000); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK, Seconds(5)); break; case EVENT_DIALOGUE_GOTHIK_ZELIEK: if (Creature* zeliek = instance->GetCreature(SirGUID)) zeliek->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN); - events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX, Seconds(6)); break; case EVENT_DIALOGUE_GOTHIK_BLAUMEUX: if (Creature* blaumeux = instance->GetCreature(LadyGUID)) blaumeux->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN); - events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE, Seconds(6)); break; case EVENT_DIALOGUE_GOTHIK_RIVENDARE: if (Creature* rivendare = instance->GetCreature(BaronGUID)) rivendare->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN); - events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX2, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX2, Seconds(6)); break; case EVENT_DIALOGUE_GOTHIK_BLAUMEUX2: if (Creature* blaumeux = instance->GetCreature(LadyGUID)) blaumeux->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2); - events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK2, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK2, Seconds(6)); break; case EVENT_DIALOGUE_GOTHIK_ZELIEK2: if (Creature* zeliek = instance->GetCreature(SirGUID)) zeliek->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2); - events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ2, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ2, Seconds(6)); break; case EVENT_DIALOGUE_GOTHIK_KORTHAZZ2: if (Creature* korthazz = instance->GetCreature(ThaneGUID)) korthazz->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2); - events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE2, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE2, Seconds(6)); break; case EVENT_DIALOGUE_GOTHIK_RIVENDARE2: if (Creature* rivendare = instance->GetCreature(BaronGUID)) @@ -536,66 +480,53 @@ class instance_naxxramas : public InstanceMapScript kelthuzad->AI()->Talk(CurrentWingTaunt); ++CurrentWingTaunt; break; + case EVENT_SUMMON_FROGGER_WAVE: + { + std::list<TempSummon*> spawns; + instance->SummonCreatureGroup(nextFroggerWave, &spawns); + if (!spawns.empty()) + (*spawns.begin())->GetMotionMaster()->MovePath(10 * NPC_FROGGER + nextFroggerWave, false); + events.Repeat(Seconds(1) + Milliseconds(666)); + nextFroggerWave = (nextFroggerWave+1) % 3; + break; + } case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD: if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD); HandleGameObject(KelthuzadDoorGUID, false); - events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING, Seconds(6)); break; case EVENT_DIALOGUE_SAPPHIRON_LICHKING: if (Creature* lichKing = instance->GetCreature(LichKingGUID)) lichKing->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_LICH_KING); - events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2, 16000); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2, Seconds(16)); break; case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2: if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD2); - events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING2, 9000); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING2, Seconds(9)); break; case EVENT_DIALOGUE_SAPPHIRON_LICHKING2: if (Creature* lichKing = instance->GetCreature(LichKingGUID)) lichKing->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_LICH_KING2); - events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3, 12000); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3, Seconds(12)); break; case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3: if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD3); - events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4, 6000); + events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4, Seconds(6)); break; case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4: if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID)) kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD4); HandleGameObject(KelthuzadDoorGUID, true); break; - case EVENT_THADDIUS_RESET: - if (GetBossState(BOSS_THADDIUS) != DONE) - if (Creature* thaddius = instance->GetCreature(ThaddiusGUID)) - thaddius->AI()->DoAction(-1); - break; default: break; } } } - void HeiganErupt(uint32 section) - { - for (uint32 i = 0; i < 4; ++i) - { - if (i == section) - continue; - - for (ObjectGuid guid : HeiganEruptionGUID[i]) - { - if (GameObject* heiganEruption = instance->GetGameObject(guid)) - { - heiganEruption->SendCustomAnim(heiganEruption->GetGoAnimProgress()); - heiganEruption->CastSpell(NULL, SPELL_ERUPTION); - } - } - } - } - // This Function is called in CheckAchievementCriteriaMeet and CheckAchievementCriteriaMeet is called before SetBossState(bossId, DONE), // so to check if all bosses are done the checker must exclude 1 boss, the last done, if there is at most 1 encouter in progress when is // called this function then all bosses are done. The one boss that check is the boss that calls this function, so it is dead. @@ -653,7 +584,6 @@ class instance_naxxramas : public InstanceMapScript /* The Plague Quarter */ // Heigan the Unclean - GuidSet HeiganEruptionGUID[4]; ObjectGuid HeiganGUID; /* The Military Quarter */ @@ -670,6 +600,8 @@ class instance_naxxramas : public InstanceMapScript ObjectGuid HorsemenChestGUID; /* The Construct Quarter */ + // Gluth + ObjectGuid GluthGUID; // Thaddius ObjectGuid ThaddiusGUID; ObjectGuid FeugenGUID; @@ -688,11 +620,14 @@ class instance_naxxramas : public InstanceMapScript bool hadAnubRekhanGreet; bool hadFaerlinaGreet; bool hadThaddiusGreet; + bool hadSapphironBirth; uint8 CurrentWingTaunt; /* The Immortal / The Undying */ uint32 playerDied; + int8 nextFroggerWave; + EventMap events; }; diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index c0caa86e93f..75e7314c5d0 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -43,12 +43,11 @@ enum Encounter enum Data { - DATA_HEIGAN_ERUPT, DATA_GOTHIK_GATE, - DATA_SAPPHIRON_BIRTH, DATA_HAD_ANUBREKHAN_GREET, DATA_HAD_FAERLINA_GREET, DATA_HAD_THADDIUS_GREET, + DATA_HAD_SAPPHIRON_BIRTH, DATA_HORSEMEN_CHECK_ACHIEVEMENT_CREDIT, DATA_ABOMINATION_KILLED, @@ -69,10 +68,12 @@ enum Data64 DATA_LADY, DATA_BARON, DATA_SIR, + DATA_GLUTH, DATA_THADDIUS, DATA_HEIGAN, DATA_FEUGEN, DATA_STALAGG, + DATA_SAPPHIRON, DATA_KELTHUZAD, DATA_KELTHUZAD_PORTAL01, DATA_KELTHUZAD_PORTAL02, @@ -92,6 +93,7 @@ enum CreaturesIds NPC_LADY = 16065, NPC_BARON = 30549, NPC_SIR = 16063, + NPC_GLUTH = 15932, NPC_HEIGAN = 15936, NPC_THADDIUS = 15928, NPC_FEUGEN = 15930, @@ -105,7 +107,8 @@ enum CreaturesIds NPC_DK_UNDERSTUDY = 16803, NPC_BIGGLESWORTH = 16998, NPC_LICH_KING = 16980, - NPC_OLD_WORLD_TRIGGER = 15384 + NPC_OLD_WORLD_TRIGGER = 15384, + NPC_FROGGER = 16027 }; enum GameObjectsIds @@ -158,12 +161,6 @@ enum GameObjectsIds GO_NAXX_PORTAL_MILITARY = 181578 }; -enum SpellIds -{ - SPELL_ERUPTION = 29371, - SPELL_SLIME = 28801 -}; - enum InstanceEvents { // Dialogue that happens after Gothik's death. @@ -176,13 +173,12 @@ enum InstanceEvents EVENT_DIALOGUE_GOTHIK_KORTHAZZ2, EVENT_DIALOGUE_GOTHIK_RIVENDARE2, - // Thaddius AI requesting timed encounter (re-)spawn - EVENT_THADDIUS_BEGIN_RESET, - EVENT_THADDIUS_RESET, - // Dialogue that happens after each wing. EVENT_KELTHUZAD_WING_TAUNT, + // Periodic Frogger summon + EVENT_SUMMON_FROGGER_WAVE, + // Dialogue that happens after Sapphiron's death. EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD, EVENT_DIALOGUE_SAPPHIRON_LICHKING, diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 277ca793a8f..914a1a8bbb0 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -376,8 +376,10 @@ public: me->SetDisableGravity(true); me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // TO DO: find what in core is making boss slower than in retail (when correct speed data) or find missing movement flag update or forced spline change - me->SetSpeed(MOVE_FLIGHT, _flySpeed * 0.25f); + me->SetSpeedRate(MOVE_FLIGHT, _flySpeed * 0.25f); if (_despawned) DoAction(ACTION_HANDLE_RESPAWN); @@ -464,7 +466,7 @@ public: pos.m_positionZ = alexstraszaBunny->GetPositionZ(); alexstraszaBunny->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 30.0f, alexstraszaBunny->GetAngle(me)); me->GetMotionMaster()->MoveLand(POINT_LAND_P_ONE, pos); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); me->SetReactState(REACT_AGGRESSIVE); me->SetInCombatWithZone(); events.ScheduleEvent(EVENT_LAND_START_ENCOUNTER, 7*IN_MILLISECONDS, 1, PHASE_NOT_STARTED); @@ -603,9 +605,7 @@ public: me->SetRespawnDelay(respawnDelay); // Set speed to normal value - me->SetSpeed(MOVE_FLIGHT, _flySpeed); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetSpeedRate(MOVE_FLIGHT, _flySpeed); me->RemoveAllAuras(); me->CombatStop(); // Sometimes threat can remain, so it's a safety measure @@ -1001,14 +1001,7 @@ public: _JustDied(); Talk(SAY_DEATH); if (Creature* alexstraszaGiftBoxBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_GIFT_BOX_BUNNY_GUID))) - { - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_10, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(), - HeartOfMagicSpawnPos.GetPositionZ(), HeartOfMagicSpawnPos.GetOrientation(), 0.0f, 0.0f, 0.0f, 1.0f, 0); - else if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_25, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(), - HeartOfMagicSpawnPos.GetPositionZ(), HeartOfMagicSpawnPos.GetOrientation(), 0.0f, 0.0f, 0.0f, 1.0f, 0); - } + alexstraszaGiftBoxBunny->SummonGameObject(RAID_MODE(GO_HEART_OF_MAGIC_10, GO_HEART_OF_MAGIC_25), HeartOfMagicSpawnPos, G3D::Quat(), 0); me->SummonCreature(NPC_ALEXSTRASZA, AlexstraszaSpawnPos, TEMPSUMMON_MANUAL_DESPAWN); me->DespawnOrUnsummon(5*IN_MILLISECONDS); @@ -1165,7 +1158,7 @@ public: _instance = creature->GetInstanceScript(); me->SetReactState(REACT_PASSIVE); // TO DO: These were a bit faster than what they should be. Not sure what is the reason. - me->SetSpeed(MOVE_FLIGHT, 1.25f); + me->SetSpeedRate(MOVE_FLIGHT, 1.25f); } void Initialize() @@ -1224,13 +1217,15 @@ public: void DoAction(int32 /*action*/) override { if (Vehicle* vehicleTemp = me->GetVehicleKit()) + { if (vehicleTemp->GetPassenger(0) && vehicleTemp->GetPassenger(0)->GetTypeId() == TYPEID_PLAYER) { vehicleTemp->RemoveAllPassengers(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } + } - me->DespawnOrUnsummon(3*IN_MILLISECONDS); + me->DespawnOrUnsummon(3*IN_MILLISECONDS); } void MovementInform(uint32 type, uint32 id) override @@ -1274,7 +1269,7 @@ public: me->SetReactState(REACT_PASSIVE); // TO DO: Something is wrong with calculations for flying creatures that are on WP/Cyclic path. // They should get the same difference as to when at ground from run creature switch to walk. - me->SetSpeed(MOVE_FLIGHT, 0.45f); + me->SetSpeedRate(MOVE_FLIGHT, 0.45f); } void Reset() override @@ -1566,7 +1561,7 @@ public: { me->DespawnOrUnsummon(2050); me->SetOrientation(2.5f); - me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); Position pos = me->GetPosition(); pos.m_positionX += 10.0f; pos.m_positionY += 10.0f; @@ -2437,9 +2432,9 @@ class spell_alexstrasza_gift_beam_visual : public SpellScriptLoader if (Creature* target = GetTarget()->ToCreature()) { if (target->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_10, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0); + _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_10, *target, G3D::Quat(), 0); else if (target->GetMap()->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_25, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0); + _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_25, *target, G3D::Quat(), 0); } } diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index e87115dd8e2..eb8a92f7b28 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -86,9 +86,7 @@ public: void SpawnGameObject(uint32 entry, Position const& pos) { GameObject* go = new GameObject(); - if (!go->Create(instance->GenerateLowGuid<HighGuid::GameObject>(), entry, instance, - PHASEMASK_NORMAL, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), - 0, 0, 0, 0, 120, GO_STATE_READY)) + if (!go->Create(instance->GenerateLowGuid<HighGuid::GameObject>(), entry, instance, PHASEMASK_NORMAL, pos, G3D::Quat(), 255, GO_STATE_READY)) { delete go; return; diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index e1a4a6ed7b8..3d9ea97b136 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -375,7 +375,7 @@ class npc_ruby_emerald_amber_drake : public CreatureScript { me->DespawnOrUnsummon(2050); me->SetOrientation(2.5f); - me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); Talk(SAY_DRAKES_TAKEOFF); Position pos = me->GetPosition(); Position offset = { 10.0f, 10.0f, 12.0f, 0.0f }; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index a98da2c6e3d..55295a534e1 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -113,7 +113,7 @@ public: Initialize(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL); if (!me->IsVisible()) me->SetVisible(true); @@ -152,7 +152,7 @@ public: me->AttackStop(); me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); @@ -174,7 +174,7 @@ public: { if (pSpark->IsAlive()) { - pSpark->SetSpeed(MOVE_RUN, 2.0f); + pSpark->SetSpeedRate(MOVE_RUN, 2.0f); pSpark->GetMotionMaster()->Clear(); pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); } @@ -236,7 +236,7 @@ public: else if (lSparkList.empty()) { me->SetVisible(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL); DoCast(me, SPELL_SPARK_DESPAWN, false); @@ -355,7 +355,7 @@ public: { Position pos = ionar->GetPosition(); - me->SetSpeed(MOVE_RUN, 2.0f); + me->SetSpeedRate(MOVE_RUN, 2.0f); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 89868fc7bf2..b2a1bb70077 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -1164,6 +1164,7 @@ class spell_algalon_trigger_3_adds : public SpellScriptLoader void Register() override { OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_algalon_trigger_3_adds_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 6dfc3bf01e7..98827fb3e00 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -334,7 +334,8 @@ class boss_flame_leviathan : public CreatureScript void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { if (spell->Id == SPELL_START_THE_ENGINE) - ASSERT_NOTNULL(me->GetVehicleKit())->InstallAllAccessories(false); + if (Vehicle* vehicleKit = me->GetVehicleKit()) + vehicleKit->InstallAllAccessories(false); if (spell->Id == SPELL_ELECTROSHOCK) me->InterruptSpell(CURRENT_CHANNELED_SPELL); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 05beacca638..fa59c021cad 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -171,8 +171,7 @@ enum FreyaNpcs enum FreyaActions { - ACTION_ELDER_DEATH = 1, - ACTION_ELDER_FREYA_KILLED = 2 + ACTION_ELDER_FREYA_KILLED = 1 }; enum FreyaEvents @@ -619,7 +618,7 @@ class boss_freya : public CreatureScript Elder->AttackStop(); Elder->CombatStop(true); Elder->DeleteThreatList(); - Elder->GetAI()->DoAction(ACTION_ELDER_FREYA_KILLED); + Elder->AI()->DoAction(ACTION_ELDER_FREYA_KILLED); } } } @@ -705,19 +704,10 @@ class boss_elder_brightleaf : public CreatureScript Talk(SAY_ELDER_SLAY); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { _JustDied(); Talk(SAY_ELDER_DEATH); - - if (killer->GetTypeId() == TYPEID_PLAYER) - { - if (Creature* Ironbranch = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_IRONBRANCH))) - Ironbranch->AI()->DoAction(ACTION_ELDER_DEATH); - - if (Creature* Stonebark = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_STONEBARK))) - Stonebark->AI()->DoAction(ACTION_ELDER_DEATH); - } } void EnterCombat(Unit* /*who*/) override @@ -812,19 +802,10 @@ class boss_elder_stonebark : public CreatureScript Talk(SAY_ELDER_SLAY); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { _JustDied(); Talk(SAY_ELDER_DEATH); - - if (killer->GetTypeId() == TYPEID_PLAYER) - { - if (Creature* Ironbranch = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_IRONBRANCH))) - Ironbranch->AI()->DoAction(ACTION_ELDER_DEATH); - - if (Creature* Brightleaf = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF))) - Brightleaf->AI()->DoAction(ACTION_ELDER_DEATH); - } } void EnterCombat(Unit* /*who*/) override @@ -925,19 +906,10 @@ class boss_elder_ironbranch : public CreatureScript Talk(SAY_ELDER_SLAY); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { _JustDied(); Talk(SAY_ELDER_DEATH); - - if (killer->GetTypeId() == TYPEID_PLAYER) - { - if (Creature* Brightleaf = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF))) - Brightleaf->AI()->DoAction(ACTION_ELDER_DEATH); - - if (Creature* Stonebark = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_STONEBARK))) - Stonebark->AI()->DoAction(ACTION_ELDER_DEATH); - } } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 09d95b34521..cbd24141bdf 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -415,7 +415,7 @@ class npc_saronite_vapors : public CreatureScript if (damage >= me->GetHealth()) { damage = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->SetStandState(UNIT_STAND_STATE_DEAD); me->SetHealth(me->GetMaxHealth()); me->RemoveAllAuras(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index c35a5936822..c03a1c6fbc1 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -30,6 +30,8 @@ Destroying of Toasty Fires */ +/* @todo Hodir aggro behavior is wonky. He gets set to _PASSIVE, but never to _AGGRESSIVE unless you kill an ice block which doesn't spawn unless you have*/ + enum HodirYells { SAY_AGGRO = 0, @@ -184,7 +186,7 @@ class npc_flash_freeze : public CreatureScript Initialize(); instance = me->GetInstanceScript(); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); } void Initialize() @@ -259,7 +261,7 @@ class npc_ice_block : public CreatureScript { instance = me->GetInstanceScript(); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); } InstanceScript* instance; @@ -269,7 +271,7 @@ class npc_ice_block : public CreatureScript void IsSummonedBy(Unit* summoner) override { targetGUID = summoner->GetGUID(); - summoner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + summoner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); me->SetInCombatWith(summoner); me->AddThreat(summoner, 250.0f); summoner->AddThreat(me, 250.0f); @@ -285,7 +287,7 @@ class npc_ice_block : public CreatureScript { if (Creature* Helper = ObjectAccessor::GetCreature(*me, targetGUID)) { - Helper->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + Helper->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR))) { @@ -375,7 +377,7 @@ class boss_hodir : public CreatureScript Talk(SAY_SLAY); } - void DamageTaken(Unit* /*who*/, uint32& damage) override + void DamageTaken(Unit* who, uint32& damage) override { if (damage >= me->GetHealth()) { @@ -388,7 +390,7 @@ class boss_hodir : public CreatureScript me->RemoveAllAttackers(); me->AttackStop(); me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->InterruptNonMeleeSpells(true); me->StopMoving(); me->GetMotionMaster()->Clear(); @@ -403,6 +405,12 @@ class boss_hodir : public CreatureScript _JustDied(); } + else if (!me->IsInCombat()) + { + me->SetReactState(REACT_AGGRESSIVE); + me->AI()->DoZoneInCombat(); + me->AI()->AttackStart(who); + } } void UpdateAI(uint32 diff) override @@ -539,7 +547,7 @@ class npc_icicle : public CreatureScript { Initialize(); me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE); me->SetReactState(REACT_PASSIVE); } @@ -593,7 +601,7 @@ class npc_snowpacked_icicle : public CreatureScript { Initialize(); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); me->SetReactState(REACT_PASSIVE); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp index cd214a0114f..a50643c5deb 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp @@ -178,7 +178,7 @@ class boss_ignis : public CreatureScript { summon->setFaction(16); summon->SetReactState(REACT_AGGRESSIVE); - summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_DISABLE_MOVE); + summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_IMMUNE_TO_PC); } summon->AI()->AttackStart(me->GetVictim()); @@ -375,7 +375,7 @@ class npc_scorch_ground : public CreatureScript npc_scorch_groundAI(Creature* creature) : ScriptedAI(creature) { Initialize(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE |UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL |UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); creature->SetDisplayId(16925); //model 2 in db cannot overwrite wdb fields } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index 470ad388fff..45d4fa58a03 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -104,7 +104,7 @@ class boss_kologarn : public CreatureScript left(false), right(false) { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); DoCast(SPELL_KOLOGARN_REDUCE_PARRY); SetCombatMovement(false); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index e694433c614..a965f8b39ff 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -359,9 +359,9 @@ static bool IsEncounterFinished(Unit* who) if (!mkii || !vx001 || !aerial) return false; - if (mkii->getStandState() == UNIT_STAND_STATE_DEAD && - vx001->getStandState() == UNIT_STAND_STATE_DEAD && - aerial->getStandState() == UNIT_STAND_STATE_DEAD) + if (mkii->GetStandState() == UNIT_STAND_STATE_DEAD && + vx001->GetStandState() == UNIT_STAND_STATE_DEAD && + aerial->GetStandState() == UNIT_STAND_STATE_DEAD) { who->Kill(mkii); who->Kill(vx001); @@ -644,10 +644,10 @@ class boss_mimiron : public CreatureScript { if (Creature* computer = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_COMPUTER))) computer->AI()->DoAction(DO_DEACTIVATE_COMPUTER); - me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION_FIREFIGHTER, GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, 0.f, 0.f, 0.9999619f, 0.008734641f, 604800); + me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION_FIREFIGHTER, GO_CACHE_OF_INNOVATION_FIREFIGHTER_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, G3D::Quat(0.f, 0.f, 0.9999619f, 0.008734641f), 604800); } else - me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION, GO_CACHE_OF_INNOVATION_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, 0.f, 0.f, 0.9999619f, 0.008734641f, 604800); + me->SummonGameObject(RAID_MODE(GO_CACHE_OF_INNOVATION, GO_CACHE_OF_INNOVATION_HERO), 2744.040f, 2569.352f, 364.3135f, 3.124123f, G3D::Quat(0.f, 0.f, 0.9999619f, 0.008734641f), 604800); events.ScheduleEvent(EVENT_OUTTRO_3, 11000); break; case EVENT_OUTTRO_3: @@ -703,7 +703,7 @@ class boss_leviathan_mk_ii : public CreatureScript if (Unit* turret = me->GetVehicleKit()->GetPassenger(3)) turret->KillSelf(); - me->SetSpeed(MOVE_RUN, 1.5f, true); + me->SetSpeedRate(MOVE_RUN, 1.5f); me->GetMotionMaster()->MovePoint(WP_MKII_P1_IDLE, VehicleRelocation[WP_MKII_P1_IDLE]); } else if (events.IsInPhase(PHASE_VOL7RON)) @@ -972,7 +972,7 @@ class boss_vx_001 : public CreatureScript events.ScheduleEvent(EVENT_FLAME_SUPPRESSANT_VX, 6000); // Missing break intended. case DO_START_VX001: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); me->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); // Remove emotestate. //me->SetUInt32Value(UNIT_FIELD_BYTES_1, 33554432); Blizzard handles hover animation like this it seems. @@ -1145,7 +1145,7 @@ class boss_aerial_command_unit : public CreatureScript events.ScheduleEvent(EVENT_SUMMON_FIRE_BOTS, 1000, 0, PHASE_AERIAL_COMMAND_UNIT); // Missing break intended. case DO_START_AERIAL: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); me->SetReactState(REACT_AGGRESSIVE); events.SetPhase(PHASE_AERIAL_COMMAND_UNIT); @@ -2759,7 +2759,7 @@ class achievement_setup_boom : public AchievementCriteriaScript public: achievement_setup_boom() : AchievementCriteriaScript("achievement_setup_boom") { } - bool OnCheck(Player* /*source*/, Unit* target) + bool OnCheck(Player* /*source*/, Unit* target) override { return target && target->GetAI()->GetData(DATA_SETUP_BOMB); } @@ -2770,7 +2770,7 @@ class achievement_setup_mine : public AchievementCriteriaScript public: achievement_setup_mine() : AchievementCriteriaScript("achievement_setup_mine") { } - bool OnCheck(Player* /*source*/, Unit* target) + bool OnCheck(Player* /*source*/, Unit* target) override { return target && target->GetAI()->GetData(DATA_SETUP_MINE); } @@ -2781,7 +2781,7 @@ class achievement_setup_rocket : public AchievementCriteriaScript public: achievement_setup_rocket() : AchievementCriteriaScript("achievement_setup_rocket") { } - bool OnCheck(Player* /*source*/, Unit* target) + bool OnCheck(Player* /*source*/, Unit* target) override { return target && target->GetAI()->GetData(DATA_SETUP_ROCKET); } @@ -2792,7 +2792,7 @@ class achievement_firefighter : public AchievementCriteriaScript public: achievement_firefighter() : AchievementCriteriaScript("achievement_firefighter") { } - bool OnCheck(Player* /*source*/, Unit* target) + bool OnCheck(Player* /*source*/, Unit* target) override { return target && target->GetAI()->GetData(DATA_FIREFIGHTER); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp index f5337b2dca5..a0ea2bd3d57 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp @@ -242,7 +242,7 @@ class boss_razorscale_controller : public CreatureScript break; case ACTION_PLACE_BROKEN_HARPOON: for (uint8 n = 0; n < RAID_MODE(2, 4); n++) - me->SummonGameObject(GO_RAZOR_BROKEN_HARPOON, PosHarpoon[n].GetPositionX(), PosHarpoon[n].GetPositionY(), PosHarpoon[n].GetPositionZ(), 2.286f, 0, 0, 0, 0, 180); + me->SummonGameObject(GO_RAZOR_BROKEN_HARPOON, PosHarpoon[n].GetPositionX(), PosHarpoon[n].GetPositionY(), PosHarpoon[n].GetPositionZ(), 2.286f, G3D::Quat(), 180); break; } } @@ -257,7 +257,7 @@ class boss_razorscale_controller : public CreatureScript { case EVENT_BUILD_HARPOON_1: Talk(EMOTE_HARPOON); - if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, 0.0f, 0.0f, 0.0f, 0.0f, uint32(me->GetRespawnTime()))) + if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_1, PosHarpoon[0].GetPositionX(), PosHarpoon[0].GetPositionY(), PosHarpoon[0].GetPositionZ(), 4.790f, G3D::Quat(), uint32(me->GetRespawnTime()))) { if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) //only nearest broken harpoon BrokenHarpoon->RemoveFromWorld(); @@ -267,7 +267,7 @@ class boss_razorscale_controller : public CreatureScript return; case EVENT_BUILD_HARPOON_2: Talk(EMOTE_HARPOON); - if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, 0, 0, 0, 0, uint32(me->GetRespawnTime()))) + if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_2, PosHarpoon[1].GetPositionX(), PosHarpoon[1].GetPositionY(), PosHarpoon[1].GetPositionZ(), 4.659f, G3D::Quat(), uint32(me->GetRespawnTime()))) { if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) BrokenHarpoon->RemoveFromWorld(); @@ -276,7 +276,7 @@ class boss_razorscale_controller : public CreatureScript return; case EVENT_BUILD_HARPOON_3: Talk(EMOTE_HARPOON); - if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, 0, 0, 0, 0, uint32(me->GetRespawnTime()))) + if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_3, PosHarpoon[2].GetPositionX(), PosHarpoon[2].GetPositionY(), PosHarpoon[2].GetPositionZ(), 5.382f, G3D::Quat(), uint32(me->GetRespawnTime()))) { if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) BrokenHarpoon->RemoveFromWorld(); @@ -286,7 +286,7 @@ class boss_razorscale_controller : public CreatureScript return; case EVENT_BUILD_HARPOON_4: Talk(EMOTE_HARPOON); - if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, 0, 0, 0, 0, uint32(me->GetRespawnTime()))) + if (GameObject* Harpoon = me->SummonGameObject(GO_RAZOR_HARPOON_4, PosHarpoon[3].GetPositionX(), PosHarpoon[3].GetPositionY(), PosHarpoon[3].GetPositionZ(), 4.266f, G3D::Quat(), uint32(me->GetRespawnTime()))) { if (GameObject* BrokenHarpoon = Harpoon->FindNearestGameObject(GO_RAZOR_BROKEN_HARPOON, 5.0f)) BrokenHarpoon->RemoveFromWorld(); @@ -366,7 +366,7 @@ class boss_razorscale : public CreatureScript _EnterCombat(); if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL))) controller->AI()->DoAction(ACTION_HARPOON_BUILD); - me->SetSpeed(MOVE_FLIGHT, 3.0f, true); + me->SetSpeedRate(MOVE_FLIGHT, 3.0f); me->SetReactState(REACT_PASSIVE); phase = PHASE_GROUND; events.SetPhase(PHASE_GROUND); @@ -550,7 +550,7 @@ class boss_razorscale : public CreatureScript me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); me->SetReactState(REACT_AGGRESSIVE); me->RemoveAurasDueToSpell(SPELL_HARPOON_TRIGGER); - me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); PermaGround = true; DoCastAOE(SPELL_FLAMEBREATH); events.ScheduleEvent(EVENT_FLAME, 15000, 0, PHASE_PERMAGROUND); @@ -677,7 +677,7 @@ class npc_expedition_commander : public CreatureScript if (Creature* summonedEngineer = me->SummonCreature(NPC_ENGINEER, PosEngSpawn, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000)) { summonedEngineer->SetWalk(false); - summonedEngineer->SetSpeed(MOVE_RUN, 0.5f); + summonedEngineer->SetSpeedRate(MOVE_RUN, 0.5f); summonedEngineer->SetHomePosition(PosEngRepair[n]); summonedEngineer->GetMotionMaster()->MoveTargetedHome(); Engineer[n] = summonedEngineer->GetGUID(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp index 8cb20eadc9f..f3aeec85af2 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp @@ -637,7 +637,7 @@ class BoomEvent : public BasicEvent { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { // This hack is here because we suspect our implementation of spell effect execution on targets // is done in the wrong order. We suspect that EFFECT_0 needs to be applied on all targets, diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp index 7da67171b5c..675268b4e93 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -230,6 +230,9 @@ enum Spells // Descend Into Madness SPELL_TELEPORT_PORTAL_VISUAL = 64416, + SPELL_TELEPORT_TO_STORMWIND_ILLUSION = 63989, + SPELL_TELEPORT_TO_CHAMBER_ILLUSION = 63997, + SPELL_TELEPORT_TO_ICECROWN_ILLUSION = 63998, // Illusions SPELL_GRIM_REPRISAL = 63305, @@ -395,6 +398,14 @@ enum MiscData { ACHIEV_TIMED_START_EVENT = 21001, SOUND_LUNATIC_GAZE = 15757, + MAX_ILLUSION_ROOMS = 3 +}; + +uint32 const IllusionSpells[MAX_ILLUSION_ROOMS] +{ + SPELL_TELEPORT_TO_CHAMBER_ILLUSION, + SPELL_TELEPORT_TO_ICECROWN_ILLUSION, + SPELL_TELEPORT_TO_STORMWIND_ILLUSION }; class StartAttackEvent : public BasicEvent @@ -405,7 +416,7 @@ class StartAttackEvent : public BasicEvent { } - bool Execute(uint64 /*time*/, uint32 /*diff*/) + bool Execute(uint64 /*time*/, uint32 /*diff*/) override { _owner->SetReactState(REACT_AGGRESSIVE); if (Creature* _summoner = ObjectAccessor::GetCreature(*_owner, _summonerGuid)) @@ -1419,7 +1430,11 @@ class npc_descend_into_madness : public CreatureScript { if (!result) return; + clicker->RemoveAurasDueToSpell(SPELL_BRAIN_LINK); + uint32 illusion = _instance->GetData(DATA_ILLUSION); + if (illusion < MAX_ILLUSION_ROOMS) + DoCast(clicker, IllusionSpells[illusion], true); me->DespawnOrUnsummon(); } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp index 1af45f3031a..3dec0c60991 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp @@ -102,7 +102,7 @@ public: Sequence[i] = Phase(i); /// This ensures a random order and only executes each phase once. - std::random_shuffle(Sequence, Sequence + PHASE_GORTOK_PALEHOOF); + Trinity::Containers::RandomShuffle(Sequence); uiArcingSmashTimer = 15000; uiImpaleTimer = 12000; @@ -118,7 +118,7 @@ public: uint32 uiWhiteringRoarTimer; Phase currentPhase; uint8 AddCount; - Phase Sequence[4]; + std::array<Phase, 4> Sequence; void Reset() override { @@ -746,7 +746,7 @@ public: //! HACK: Creature's can't have MOVEMENTFLAG_FLYING me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL); - me->SetSpeed(MOVE_FLIGHT, 0.5f); + me->SetSpeedRate(MOVE_FLIGHT, 0.5f); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index d7b65093898..7615217a794 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -209,7 +209,7 @@ public: Initialize(); Summons.DespawnAll(); - me->SetSpeed(MOVE_FLIGHT, 3.0f); + me->SetSpeedRate(MOVE_FLIGHT, 3.0f); if ((ObjectAccessor::GetCreature(*me, m_uiGraufGUID) == NULL) && !me->IsMounted()) me->SummonCreature(NPC_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f); instance->SetBossState(DATA_SKADI_THE_RUTHLESS, NOT_STARTED); diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp index 8f2d5a61770..28ca7f4ef3b 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp @@ -19,9 +19,9 @@ #include "InstanceScript.h" #include "utgarde_pinnacle.h" -BossBoundaryData const boundaries = +BossBoundaryData const boundaries = { - { DATA_KING_YMIRON, new RectangleBoundary(340.0f, 450.0f, -412.0f, -275.0f) } + { DATA_KING_YMIRON, new RectangleBoundary(340.0f, 443.0f, -412.0f, -275.0f) } }; DoorData const doorData[] = diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp index b89c11147b6..df3fa266191 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp @@ -115,6 +115,7 @@ class boss_archavon : public CreatureScript DoCastVictim(SPELL_STOMP); events.ScheduleEvent(EVENT_IMPALE, 3000); events.ScheduleEvent(EVENT_STOMP, 45000); + Talk(EMOTE_LEAP, me->GetVictim()); break; case EVENT_IMPALE: DoCastVictim(SPELL_IMPALE); diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp index 06ebcbdc2fb..e7305e53808 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp @@ -247,7 +247,7 @@ class npc_frozen_orb_stalker : public CreatureScript npc_frozen_orb_stalkerAI(Creature* creature) : ScriptedAI(creature) { creature->SetVisible(false); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); creature->SetReactState(REACT_PASSIVE); instance = creature->GetInstanceScript(); diff --git a/src/server/scripts/Northrend/northrend_script_loader.cpp b/src/server/scripts/Northrend/northrend_script_loader.cpp new file mode 100644 index 00000000000..d84bb1c4072 --- /dev/null +++ b/src/server/scripts/Northrend/northrend_script_loader.cpp @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +void AddSC_boss_slad_ran(); +void AddSC_boss_moorabi(); +void AddSC_boss_drakkari_colossus(); +void AddSC_boss_gal_darah(); +void AddSC_boss_eck(); +void AddSC_instance_gundrak(); + +// Azjol-Nerub - Azjol-Nerub +void AddSC_boss_krik_thir(); +void AddSC_boss_hadronox(); +void AddSC_boss_anub_arak(); +void AddSC_instance_azjol_nerub(); + +// Azjol-Nerub - Ahn'kahet +void AddSC_boss_elder_nadox(); +void AddSC_boss_taldaram(); +void AddSC_boss_amanitar(); +void AddSC_boss_jedoga_shadowseeker(); +void AddSC_boss_volazj(); +void AddSC_instance_ahnkahet(); + +// Drak'Tharon Keep +void AddSC_boss_trollgore(); +void AddSC_boss_novos(); +void AddSC_boss_king_dred(); +void AddSC_boss_tharon_ja(); +void AddSC_instance_drak_tharon_keep(); + +void AddSC_boss_argent_challenge(); //Trial of the Champion +void AddSC_boss_black_knight(); +void AddSC_boss_grand_champions(); +void AddSC_instance_trial_of_the_champion(); +void AddSC_trial_of_the_champion(); +void AddSC_boss_anubarak_trial(); //Trial of the Crusader +void AddSC_boss_faction_champions(); +void AddSC_boss_jaraxxus(); +void AddSC_boss_northrend_beasts(); +void AddSC_boss_twin_valkyr(); +void AddSC_trial_of_the_crusader(); +void AddSC_instance_trial_of_the_crusader(); +void AddSC_boss_anubrekhan(); //Naxxramas +void AddSC_boss_maexxna(); +void AddSC_boss_patchwerk(); +void AddSC_boss_grobbulus(); +void AddSC_boss_razuvious(); +void AddSC_boss_kelthuzad(); +void AddSC_boss_loatheb(); +void AddSC_boss_noth(); +void AddSC_boss_gluth(); +void AddSC_boss_sapphiron(); +void AddSC_boss_four_horsemen(); +void AddSC_boss_faerlina(); +void AddSC_boss_heigan(); +void AddSC_boss_gothik(); +void AddSC_boss_thaddius(); +void AddSC_instance_naxxramas(); +void AddSC_boss_nexus_commanders(); // The Nexus Nexus +void AddSC_boss_magus_telestra(); +void AddSC_boss_anomalus(); +void AddSC_boss_ormorok(); +void AddSC_boss_keristrasza(); +void AddSC_instance_nexus(); +void AddSC_boss_drakos(); //The Nexus The Oculus +void AddSC_boss_urom(); +void AddSC_boss_varos(); +void AddSC_boss_eregos(); +void AddSC_instance_oculus(); +void AddSC_oculus(); +void AddSC_boss_malygos(); // The Nexus: Eye of Eternity +void AddSC_instance_eye_of_eternity(); +void AddSC_boss_sartharion(); //Obsidian Sanctum +void AddSC_obsidian_sanctum(); +void AddSC_instance_obsidian_sanctum(); +void AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning +void AddSC_boss_loken(); +void AddSC_boss_ionar(); +void AddSC_boss_volkhan(); +void AddSC_instance_halls_of_lightning(); +void AddSC_boss_maiden_of_grief(); //Ulduar Halls of Stone +void AddSC_boss_krystallus(); +void AddSC_boss_sjonnir(); +void AddSC_instance_halls_of_stone(); +void AddSC_halls_of_stone(); +void AddSC_boss_auriaya(); //Ulduar Ulduar +void AddSC_boss_flame_leviathan(); +void AddSC_boss_ignis(); +void AddSC_boss_razorscale(); +void AddSC_boss_xt002(); +void AddSC_boss_kologarn(); +void AddSC_boss_assembly_of_iron(); +void AddSC_boss_general_vezax(); +void AddSC_boss_mimiron(); +void AddSC_boss_hodir(); +void AddSC_boss_freya(); +void AddSC_boss_yogg_saron(); +void AddSC_boss_algalon_the_observer(); +void AddSC_instance_ulduar(); + +// Utgarde Keep - Utgarde Keep +void AddSC_boss_keleseth(); +void AddSC_boss_skarvald_dalronn(); +void AddSC_boss_ingvar_the_plunderer(); +void AddSC_instance_utgarde_keep(); +void AddSC_utgarde_keep(); + +// Utgarde Keep - Utgarde Pinnacle +void AddSC_boss_svala(); +void AddSC_boss_palehoof(); +void AddSC_boss_skadi(); +void AddSC_boss_ymiron(); +void AddSC_instance_utgarde_pinnacle(); + +// Vault of Archavon +void AddSC_boss_archavon(); +void AddSC_boss_emalon(); +void AddSC_boss_koralon(); +void AddSC_boss_toravon(); +void AddSC_instance_vault_of_archavon(); + +void AddSC_boss_cyanigosa(); //Violet Hold +void AddSC_boss_erekem(); +void AddSC_boss_ichoron(); +void AddSC_boss_lavanthor(); +void AddSC_boss_moragg(); +void AddSC_boss_xevozz(); +void AddSC_boss_zuramat(); +void AddSC_instance_violet_hold(); +void AddSC_violet_hold(); +void AddSC_instance_forge_of_souls(); //Forge of Souls +void AddSC_forge_of_souls(); +void AddSC_boss_bronjahm(); +void AddSC_boss_devourer_of_souls(); +void AddSC_instance_pit_of_saron(); //Pit of Saron +void AddSC_pit_of_saron(); +void AddSC_boss_garfrost(); +void AddSC_boss_ick(); +void AddSC_boss_tyrannus(); +void AddSC_instance_halls_of_reflection(); // Halls of Reflection +void AddSC_halls_of_reflection(); +void AddSC_boss_falric(); +void AddSC_boss_marwyn(); +void AddSC_boss_lord_marrowgar(); // Icecrown Citadel +void AddSC_boss_lady_deathwhisper(); +void AddSC_boss_icecrown_gunship_battle(); +void AddSC_boss_deathbringer_saurfang(); +void AddSC_boss_festergut(); +void AddSC_boss_rotface(); +void AddSC_boss_professor_putricide(); +void AddSC_boss_blood_prince_council(); +void AddSC_boss_blood_queen_lana_thel(); +void AddSC_boss_valithria_dreamwalker(); +void AddSC_boss_sindragosa(); +void AddSC_boss_the_lich_king(); +void AddSC_icecrown_citadel_teleport(); +void AddSC_instance_icecrown_citadel(); +void AddSC_icecrown_citadel(); +void AddSC_instance_ruby_sanctum(); // Ruby Sanctum +void AddSC_ruby_sanctum(); +void AddSC_boss_baltharus_the_warborn(); +void AddSC_boss_saviana_ragefire(); +void AddSC_boss_general_zarithrian(); +void AddSC_boss_halion(); +void AddSC_isle_of_conquest(); // Isle of Conquest +void AddSC_boss_ioc_horde_alliance(); + +void AddSC_dalaran(); +void AddSC_borean_tundra(); +void AddSC_dragonblight(); +void AddSC_grizzly_hills(); +void AddSC_howling_fjord(); +void AddSC_icecrown(); +void AddSC_sholazar_basin(); +void AddSC_storm_peaks(); +void AddSC_wintergrasp(); +void AddSC_zuldrak(); +void AddSC_crystalsong_forest(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddNorthrendScripts() +{ + AddSC_boss_slad_ran(); //Gundrak + AddSC_boss_moorabi(); + AddSC_boss_drakkari_colossus(); + AddSC_boss_gal_darah(); + AddSC_boss_eck(); + AddSC_instance_gundrak(); + + // Azjol-Nerub - Ahn'kahet + AddSC_boss_elder_nadox(); + AddSC_boss_taldaram(); + AddSC_boss_amanitar(); + AddSC_boss_jedoga_shadowseeker(); + AddSC_boss_volazj(); + AddSC_instance_ahnkahet(); + + // Azjol-Nerub - Azjol-Nerub + AddSC_boss_krik_thir(); + AddSC_boss_hadronox(); + AddSC_boss_anub_arak(); + AddSC_instance_azjol_nerub(); + + // Drak'Tharon Keep + AddSC_boss_trollgore(); + AddSC_boss_novos(); + AddSC_boss_king_dred(); + AddSC_boss_tharon_ja(); + AddSC_instance_drak_tharon_keep(); + + AddSC_boss_argent_challenge(); //Trial of the Champion + AddSC_boss_black_knight(); + AddSC_boss_grand_champions(); + AddSC_instance_trial_of_the_champion(); + AddSC_trial_of_the_champion(); + AddSC_boss_anubarak_trial(); //Trial of the Crusader + AddSC_boss_faction_champions(); + AddSC_boss_jaraxxus(); + AddSC_trial_of_the_crusader(); + AddSC_boss_twin_valkyr(); + AddSC_boss_northrend_beasts(); + AddSC_instance_trial_of_the_crusader(); + AddSC_boss_anubrekhan(); //Naxxramas + AddSC_boss_maexxna(); + AddSC_boss_patchwerk(); + AddSC_boss_grobbulus(); + AddSC_boss_razuvious(); + AddSC_boss_kelthuzad(); + AddSC_boss_loatheb(); + AddSC_boss_noth(); + AddSC_boss_gluth(); + AddSC_boss_sapphiron(); + AddSC_boss_four_horsemen(); + AddSC_boss_faerlina(); + AddSC_boss_heigan(); + AddSC_boss_gothik(); + AddSC_boss_thaddius(); + AddSC_instance_naxxramas(); + AddSC_boss_nexus_commanders(); // The Nexus Nexus + AddSC_boss_magus_telestra(); + AddSC_boss_anomalus(); + AddSC_boss_ormorok(); + AddSC_boss_keristrasza(); + AddSC_instance_nexus(); + AddSC_boss_drakos(); //The Nexus The Oculus + AddSC_boss_urom(); + AddSC_boss_varos(); + AddSC_boss_eregos(); + AddSC_instance_oculus(); + AddSC_oculus(); + AddSC_boss_malygos(); // The Nexus: Eye of Eternity + AddSC_instance_eye_of_eternity(); + AddSC_boss_sartharion(); //Obsidian Sanctum + AddSC_obsidian_sanctum(); + AddSC_instance_obsidian_sanctum(); + AddSC_boss_bjarngrim(); //Ulduar Halls of Lightning + AddSC_boss_loken(); + AddSC_boss_ionar(); + AddSC_boss_volkhan(); + AddSC_instance_halls_of_lightning(); + AddSC_boss_maiden_of_grief(); //Ulduar Halls of Stone + AddSC_boss_krystallus(); + AddSC_boss_sjonnir(); + AddSC_instance_halls_of_stone(); + AddSC_halls_of_stone(); + AddSC_boss_auriaya(); //Ulduar Ulduar + AddSC_boss_flame_leviathan(); + AddSC_boss_ignis(); + AddSC_boss_razorscale(); + AddSC_boss_xt002(); + AddSC_boss_general_vezax(); + AddSC_boss_assembly_of_iron(); + AddSC_boss_kologarn(); + AddSC_boss_mimiron(); + AddSC_boss_hodir(); + AddSC_boss_freya(); + AddSC_boss_yogg_saron(); + AddSC_boss_algalon_the_observer(); + AddSC_instance_ulduar(); + + // Utgarde Keep - Utgarde Keep + AddSC_boss_keleseth(); + AddSC_boss_skarvald_dalronn(); + AddSC_boss_ingvar_the_plunderer(); + AddSC_instance_utgarde_keep(); + AddSC_utgarde_keep(); + + // Utgarde Keep - Utgarde Pinnacle + AddSC_boss_svala(); + AddSC_boss_palehoof(); + AddSC_boss_skadi(); + AddSC_boss_ymiron(); + AddSC_instance_utgarde_pinnacle(); + + // Vault of Archavon + AddSC_boss_archavon(); + AddSC_boss_emalon(); + AddSC_boss_koralon(); + AddSC_boss_toravon(); + AddSC_instance_vault_of_archavon(); + + AddSC_boss_cyanigosa(); //Violet Hold + AddSC_boss_erekem(); + AddSC_boss_ichoron(); + AddSC_boss_lavanthor(); + AddSC_boss_moragg(); + AddSC_boss_xevozz(); + AddSC_boss_zuramat(); + AddSC_instance_violet_hold(); + AddSC_violet_hold(); + AddSC_instance_forge_of_souls(); //Forge of Souls + AddSC_forge_of_souls(); + AddSC_boss_bronjahm(); + AddSC_boss_devourer_of_souls(); + AddSC_instance_pit_of_saron(); //Pit of Saron + AddSC_pit_of_saron(); + AddSC_boss_garfrost(); + AddSC_boss_ick(); + AddSC_boss_tyrannus(); + AddSC_instance_halls_of_reflection(); // Halls of Reflection + AddSC_halls_of_reflection(); + AddSC_boss_falric(); + AddSC_boss_marwyn(); + AddSC_boss_lord_marrowgar(); // Icecrown Citadel + AddSC_boss_lady_deathwhisper(); + AddSC_boss_icecrown_gunship_battle(); + AddSC_boss_deathbringer_saurfang(); + AddSC_boss_festergut(); + AddSC_boss_rotface(); + AddSC_boss_professor_putricide(); + AddSC_boss_blood_prince_council(); + AddSC_boss_blood_queen_lana_thel(); + AddSC_boss_valithria_dreamwalker(); + AddSC_boss_sindragosa(); + AddSC_boss_the_lich_king(); + AddSC_icecrown_citadel_teleport(); + AddSC_instance_icecrown_citadel(); + AddSC_icecrown_citadel(); + AddSC_instance_ruby_sanctum(); // Ruby Sanctum + AddSC_ruby_sanctum(); + AddSC_boss_baltharus_the_warborn(); + AddSC_boss_saviana_ragefire(); + AddSC_boss_general_zarithrian(); + AddSC_boss_halion(); + AddSC_isle_of_conquest(); // Isle of Conquest + AddSC_boss_ioc_horde_alliance(); + + AddSC_dalaran(); + AddSC_borean_tundra(); + AddSC_dragonblight(); + AddSC_grizzly_hills(); + AddSC_howling_fjord(); + AddSC_icecrown(); + AddSC_sholazar_basin(); + AddSC_storm_peaks(); + AddSC_wintergrasp(); + AddSC_zuldrak(); + AddSC_crystalsong_forest(); +} diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 698fd510411..d9315315c58 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -2274,7 +2274,8 @@ public: void DoAction(int32 /*iParam*/) override { me->StopMoving(); - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID)) me->SetFacingToObject(player); uiEventTimer = 3000; @@ -2303,7 +2304,6 @@ public: switch (me->GetEntry()) { case NPC_SALTY_JOHN_THORPE: - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); Talk(SAY_HIDDEN_CULTIST_1); uiEventTimer = 5000; uiEventPhase = 2; @@ -2314,7 +2314,8 @@ public: uiEventPhase = 2; break; case NPC_TOM_HEGGER: - Talk(SAY_HIDDEN_CULTIST_3); + if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID)) + Talk(SAY_HIDDEN_CULTIST_3, player); uiEventTimer = 5000; uiEventPhase = 2; break; diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp index 2ec2af80624..d7ff1e5cb4d 100644 --- a/src/server/scripts/Northrend/zone_dragonblight.cpp +++ b/src/server/scripts/Northrend/zone_dragonblight.cpp @@ -360,7 +360,7 @@ class npc_commander_eligor_dawnbringer : public CreatureScript uint8 talkWing; }; - CreatureAI* GetAI(Creature* creature) const + CreatureAI* GetAI(Creature* creature) const override { return new npc_commander_eligor_dawnbringerAI(creature); } @@ -695,7 +695,7 @@ class npc_torturer_lecraft : public CreatureScript ObjectGuid _playerGUID; }; - CreatureAI* GetAI(Creature* creature) const + CreatureAI* GetAI(Creature* creature) const override { return new npc_torturer_lecraftAI(creature); } diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 59802165a94..adade245c2b 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -22,6 +22,7 @@ #include "Player.h" #include "SpellScript.h" #include "CreatureTextMgr.h" +#include "CombatAI.h" /*###### ## Quest 12027: Mr. Floppy's Perilous Adventure @@ -854,6 +855,260 @@ class spell_infected_worgen_bite : public SpellScriptLoader } }; +/*###### +## Quest: Riding the Red Rocket +######*/ + +enum RedRocket +{ + SPELL_VEHICLE_WARHEAD_FUSE = 49107, + SPELL_ALLIANCE_KILL_CREDIT_TORPEDO = 49510, + SPELL_HORDE_KILL_CREDIT_TORPEDO = 49340, + NPC_HORDE_LUMBERBOAT = 27702, + NPC_ALLIANCE_LUMBERBOAT = 27688, + SPELL_DETONATE = 49250 +}; + +class npc_rocket_propelled_warhead : public CreatureScript +{ +public: + npc_rocket_propelled_warhead() : CreatureScript("npc_rocket_propelled_warhead") { } + + struct npc_rocket_propelled_warheadAI : public VehicleAI + { + npc_rocket_propelled_warheadAI(Creature* creature) : VehicleAI(creature) + { + _finished = false; + _faction = ALLIANCE; + } + + void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override + { + if (apply && who->ToPlayer()) + { + DoCast(me, SPELL_VEHICLE_WARHEAD_FUSE); + _faction = who->ToPlayer()->GetTeam(); + } + } + + void JustReachedHome() override + { + _finished = false; + me->SetVisible(true); + me->GetMotionMaster()->Clear(true); + } + + void DoAction(int32 /*action*/) override + { + FinishQuest(false, _faction); + } + + void SpellHit(Unit* caster, SpellInfo const* /*spellInfo*/) override + { + if (caster->GetEntry() == NPC_HORDE_LUMBERBOAT || caster->GetEntry() == NPC_ALLIANCE_LUMBERBOAT) + FinishQuest(true, _faction); + } + + void FinishQuest(bool success, uint32 faction) + { + if (_finished) + return; + + _finished = true; + + if (success) + DoCast(me, faction == ALLIANCE ? SPELL_ALLIANCE_KILL_CREDIT_TORPEDO : SPELL_HORDE_KILL_CREDIT_TORPEDO); + + DoCast(me, SPELL_DETONATE); + me->RemoveAllAuras(); + me->SetVisible(false); + me->GetMotionMaster()->MoveTargetedHome(); + } + + private: + uint32 _faction; + bool _finished; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_rocket_propelled_warheadAI(creature); + } +}; + +enum WarheadSpells +{ + SPELL_WARHEAD_Z_CHECK = 61678, + SPELL_WARHEAD_SEEKING_LUMBERSHIP = 49331, + SPELL_WARHEAD_FUSE = 49181 +}; +// 49107 - Vehicle: Warhead Fuse +class spell_vehicle_warhead_fuse : public SpellScriptLoader +{ +public: + spell_vehicle_warhead_fuse() : SpellScriptLoader("spell_vehicle_warhead_fuse") { } + + class spell_vehicle_warhead_fuse_SpellScript : public SpellScript + { + PrepareSpellScript(spell_vehicle_warhead_fuse_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARHEAD_Z_CHECK) || !sSpellMgr->GetSpellInfo(SPELL_WARHEAD_SEEKING_LUMBERSHIP) || !sSpellMgr->GetSpellInfo(SPELL_WARHEAD_FUSE)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + + caster->CastSpell(caster, SPELL_WARHEAD_Z_CHECK, true); + caster->CastSpell(caster, SPELL_WARHEAD_SEEKING_LUMBERSHIP, true); + caster->CastSpell(caster, SPELL_WARHEAD_FUSE, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_vehicle_warhead_fuse_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_vehicle_warhead_fuse_SpellScript(); + } +}; + +enum WarheadDenonate +{ + SPELL_PARACHUTE = 66154, + SPELL_TORPEDO_EXPLOSION = 49290, + NPC_ALLIANCE_LUMBERBOAT_EXPLOSIONS = 27689 +}; +// 49250 - Detonate +class spell_warhead_detonate : public SpellScriptLoader +{ +public: + spell_warhead_detonate() : SpellScriptLoader("spell_warhead_detonate") { } + + class spell_warhead_detonate_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warhead_detonate_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PARACHUTE) || !sSpellMgr->GetSpellInfo(SPELL_TORPEDO_EXPLOSION)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + Player* player = GetHitPlayer(); + if (!player) + return; + + player->ExitVehicle(); + float horizontalSpeed = 3.0f; + float verticalSpeed = 40.0f; + player->KnockbackFrom(caster->GetPositionX(), caster->GetPositionY(), horizontalSpeed, verticalSpeed); + caster->CastSpell(player, SPELL_PARACHUTE, true); + + std::list<Creature*> explosionBunnys; + caster->GetCreatureListWithEntryInGrid(explosionBunnys, NPC_ALLIANCE_LUMBERBOAT_EXPLOSIONS, 90.0f); + for (std::list<Creature*>::const_iterator itr = explosionBunnys.begin(); itr != explosionBunnys.end(); ++itr) + (*itr)->CastSpell((*itr), SPELL_TORPEDO_EXPLOSION, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_warhead_detonate_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_warhead_detonate_SpellScript(); + } +}; + +// 61678 - Z Check +class spell_z_check : public SpellScriptLoader +{ +public: + spell_z_check() : SpellScriptLoader("spell_z_check") { } + + class spell_z_check_AuraScript : public AuraScript + { + PrepareAuraScript(spell_z_check_AuraScript); + + public: + spell_z_check_AuraScript() + { + _posZ = 0.0f; + } + + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + _posZ = GetTarget()->GetPositionZ(); + } + + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + + if (_posZ != GetTarget()->GetPositionZ()) + if (Creature* target = GetTarget()->ToCreature()) + target->AI()->DoAction(0); + } + + private: + float _posZ; + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_z_check_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_z_check_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_z_check_AuraScript(); + } +}; + +// 49181 - Warhead Fuse +class spell_warhead_fuse : public SpellScriptLoader +{ +public: + spell_warhead_fuse() : SpellScriptLoader("spell_warhead_fuse") { } + + class spell_warhead_fuse_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warhead_fuse_AuraScript); + + void HandleOnEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* rocketUnit = GetTarget()->GetVehicleBase()) + if (Creature* rocketCrea = rocketUnit->ToCreature()) + rocketCrea->AI()->DoAction(0); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_warhead_fuse_AuraScript::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_warhead_fuse_AuraScript(); + } +}; + void AddSC_grizzly_hills() { new npc_emily(); @@ -866,4 +1121,9 @@ void AddSC_grizzly_hills() new npc_lake_frog(); new spell_shredder_delivery(); new spell_infected_worgen_bite(); + new npc_rocket_propelled_warhead(); + new spell_z_check(); + new spell_warhead_detonate(); + new spell_vehicle_warhead_fuse(); + new spell_warhead_fuse(); } diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index 1e020edd10a..3d801cc2fbb 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -712,7 +712,7 @@ enum BorrowedTechnologyAndVolatility SPELL_PING_BUNNY = 59375, SPELL_IMMOLATION = 54690, SPELL_EXPLOSION = 59335, - SPELL_RIDE = 56687, + SPELL_RIDE = 59319, // Points POINT_GRAB_DECOY = 1, diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index f2edccd99b5..41785f76d9a 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -253,7 +253,7 @@ public: case 1: Talk(SAY_WP_3); me->CastSpell(5918.33f, 5372.91f, -98.770f, SPELL_EXPLODE_CRYSTAL, true); - me->SummonGameObject(184743, 5918.33f, 5372.91f, -98.770f, 0, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN); //approx 3 to 4 seconds + me->SummonGameObject(184743, 5918.33f, 5372.91f, -98.770f, 0, G3D::Quat(), TEMPSUMMON_MANUAL_DESPAWN); //approx 3 to 4 seconds me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); break; case 2: @@ -264,7 +264,7 @@ public: break; case 8: me->CastSpell(5887.37f, 5379.39f, -91.289f, SPELL_EXPLODE_CRYSTAL, true); - me->SummonGameObject(184743, 5887.37f, 5379.39f, -91.289f, 0, 0, 0, 0, 0, TEMPSUMMON_MANUAL_DESPAWN); //approx 3 to 4 seconds + me->SummonGameObject(184743, 5887.37f, 5379.39f, -91.289f, 0, G3D::Quat(), TEMPSUMMON_MANUAL_DESPAWN); //approx 3 to 4 seconds me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH); break; case 9: @@ -780,7 +780,7 @@ public: bird->KillSelf(); crunchy->GetMotionMaster()->MovePoint(0, bird->GetPositionX(), bird->GetPositionY(), - bird->GetMap()->GetWaterOrGroundLevel(bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ())); + bird->GetMap()->GetWaterOrGroundLevel(bird->GetPhaseMask(), bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ())); /// @todo Make crunchy perform emote eat when he reaches the bird break; diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index e5263a8630a..490c72c5cba 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -516,7 +516,7 @@ public: if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) voice->AI()->Talk(SAY_VOICE_1, player); } - if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_1, 7860.273f, -1383.622f, 1538.302f, -1.658062f, 0, 0, -0.737277f, 0.6755905f, 0)) + if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_1, 7860.273f, -1383.622f, 1538.302f, -1.658062f, G3D::Quat(0.f, 0.f, -0.737277f, 0.6755905f), 0)) objectGUID[objectCounter++] = go->GetGUID(); events.ScheduleEvent(EVENT_SCRIPT_5, 6000); break; @@ -524,7 +524,7 @@ public: if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID)) voice->AI()->Talk(SAY_VOICE_2, player); - if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_2, 7875.67f, -1387.266f, 1538.323f, -2.373644f, 0, 0, -0.9271832f, 0.3746083f, 0)) + if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_2, 7875.67f, -1387.266f, 1538.323f, -2.373644f, G3D::Quat(0.f, 0.f, -0.9271832f, 0.3746083f), 0)) objectGUID[objectCounter++] = go->GetGUID(); events.ScheduleEvent(EVENT_SCRIPT_6, 6000); break; @@ -532,7 +532,7 @@ public: if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID)) voice->AI()->Talk(SAY_VOICE_3, player); - if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_3, 7879.212f, -1401.175f, 1538.279f, 2.967041f, 0, 0, 0.9961939f, 0.08716504f, 0)) + if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_3, 7879.212f, -1401.175f, 1538.279f, 2.967041f, G3D::Quat(0.f, 0.f, 0.9961939f, 0.08716504f), 0)) objectGUID[objectCounter++] = go->GetGUID(); events.ScheduleEvent(EVENT_SCRIPT_7, 6000); break; @@ -540,7 +540,7 @@ public: if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID)) voice->AI()->Talk(SAY_VOICE_4, player); - if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_4, 7868.944f, -1411.18f, 1538.213f, 2.111848f, 0, 0, 0.8703556f, 0.4924237f, 0)) + if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_4, 7868.944f, -1411.18f, 1538.213f, 2.111848f, G3D::Quat(0.f, 0.f, 0.8703556f, 0.4924237f), 0)) objectGUID[objectCounter++] = go->GetGUID(); events.ScheduleEvent(EVENT_SCRIPT_8, 6000); break; @@ -548,7 +548,7 @@ public: if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID)) voice->AI()->Talk(SAY_VOICE_5, player); - if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_5, 7855.11f, -1406.839f, 1538.42f, 1.151916f, 0, 0, 0.5446386f, 0.8386708f, 0)) + if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_5, 7855.11f, -1406.839f, 1538.42f, 1.151916f, G3D::Quat(0.f, 0.f, 0.5446386f, 0.8386708f), 0)) objectGUID[objectCounter] = go->GetGUID(); events.ScheduleEvent(EVENT_SCRIPT_9, 6000); break; diff --git a/src/server/scripts/OutdoorPvP/CMakeLists.txt b/src/server/scripts/OutdoorPvP/CMakeLists.txt deleted file mode 100644 index 91ce4ce4186..00000000000 --- a/src/server/scripts/OutdoorPvP/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - OutdoorPvP/OutdoorPvPTF.cpp - OutdoorPvP/OutdoorPvPSI.cpp - OutdoorPvP/OutdoorPvPSI.h - OutdoorPvP/OutdoorPvPZM.cpp - OutdoorPvP/OutdoorPvPNA.cpp - OutdoorPvP/OutdoorPvPHP.cpp - OutdoorPvP/OutdoorPvPTF.h - OutdoorPvP/OutdoorPvPEP.h - OutdoorPvP/OutdoorPvPEP.cpp - OutdoorPvP/OutdoorPvPHP.h - OutdoorPvP/OutdoorPvPZM.h - OutdoorPvP/OutdoorPvPNA.h -) - -message(" -> Prepared: Outdoor PVP Zones") diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.h b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.h index 71dbd139ea0..4fd608ccd1c 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.h @@ -96,9 +96,9 @@ class OPvPCapturePointHP : public OPvPCapturePoint public: OPvPCapturePointHP(OutdoorPvP* pvp, OutdoorPvPHPTowerType type); - void ChangeState(); + void ChangeState() override; - void FillInitialWorldStates(WorldPacket & data); + void FillInitialWorldStates(WorldPacket & data) override; private: OutdoorPvPHPTowerType m_TowerType; @@ -109,18 +109,18 @@ class OutdoorPvPHP : public OutdoorPvP public: OutdoorPvPHP(); - bool SetupOutdoorPvP(); + bool SetupOutdoorPvP() override; - void HandlePlayerEnterZone(Player* player, uint32 zone); - void HandlePlayerLeaveZone(Player* player, uint32 zone); + void HandlePlayerEnterZone(Player* player, uint32 zone) override; + void HandlePlayerLeaveZone(Player* player, uint32 zone) override; - bool Update(uint32 diff); + bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket &data); + void FillInitialWorldStates(WorldPacket &data) override; - void SendRemoveWorldStates(Player* player); + void SendRemoveWorldStates(Player* player) override; - void HandleKillImpl(Player* player, Unit* killed); + void HandleKillImpl(Player* player, Unit* killed) override; uint32 GetAllianceTowersControlled() const; void SetAllianceTowersControlled(uint32 count); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h index 4ed47c42206..80878828d44 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h @@ -311,18 +311,18 @@ class OutdoorPvPNA : public OutdoorPvP public: OutdoorPvPNA(); - bool SetupOutdoorPvP(); + bool SetupOutdoorPvP() override; - void HandlePlayerEnterZone(Player* player, uint32 zone); - void HandlePlayerLeaveZone(Player* player, uint32 zone); + void HandlePlayerEnterZone(Player* player, uint32 zone) override; + void HandlePlayerLeaveZone(Player* player, uint32 zone) override; - bool Update(uint32 diff); + bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket &data); + void FillInitialWorldStates(WorldPacket &data) override; - void SendRemoveWorldStates(Player* player); + void SendRemoveWorldStates(Player* player) override; - void HandleKillImpl(Player* player, Unit* killed); + void HandleKillImpl(Player* player, Unit* killed) override; private: OPvPCapturePointNA * m_obj; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp index a0b9351fb75..05ed405cc6e 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp @@ -163,7 +163,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId) GameObject* go = new GameObject; Map* map = player->GetMap(); - if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), SI_SILITHYST_MOUND, map, player->GetPhaseMask(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) + if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), SI_SILITHYST_MOUND, map, player->GetPhaseMask(), *player, G3D::Quat(), 255, GO_STATE_READY)) { delete go; return true; @@ -192,7 +192,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId) GameObject* go = new GameObject; Map* map = player->GetMap(); - if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), SI_SILITHYST_MOUND, map, player->GetPhaseMask(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) + if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), SI_SILITHYST_MOUND, map, player->GetPhaseMask(), *player, G3D::Quat(), 255, GO_STATE_READY)) { delete go; return true; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.h b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.h index f28fea926fc..fae2ea9738e 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.h @@ -56,22 +56,22 @@ class OutdoorPvPSI : public OutdoorPvP public: OutdoorPvPSI(); - bool SetupOutdoorPvP(); + bool SetupOutdoorPvP() override; - void HandlePlayerEnterZone(Player* player, uint32 zone); - void HandlePlayerLeaveZone(Player* player, uint32 zone); + void HandlePlayerEnterZone(Player* player, uint32 zone) override; + void HandlePlayerLeaveZone(Player* player, uint32 zone) override; - bool Update(uint32 diff); + bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket &data); + void FillInitialWorldStates(WorldPacket &data) override; - void SendRemoveWorldStates(Player* player); + void SendRemoveWorldStates(Player* player) override; - bool HandleAreaTrigger(Player* player, uint32 trigger); + bool HandleAreaTrigger(Player* player, uint32 trigger) override; - bool HandleDropFlag(Player* player, uint32 spellId); + bool HandleDropFlag(Player* player, uint32 spellId) override; - bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go); + bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go) override; void UpdateWorldState(); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPScriptLoader.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPScriptLoader.cpp new file mode 100644 index 00000000000..ebf29910046 --- /dev/null +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPScriptLoader.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +void AddSC_outdoorpvp_ep(); +void AddSC_outdoorpvp_hp(); +void AddSC_outdoorpvp_na(); +void AddSC_outdoorpvp_si(); +void AddSC_outdoorpvp_tf(); +void AddSC_outdoorpvp_zm(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddOutdoorPvPScripts() +{ + AddSC_outdoorpvp_ep(); + AddSC_outdoorpvp_hp(); + AddSC_outdoorpvp_na(); + AddSC_outdoorpvp_si(); + AddSC_outdoorpvp_tf(); + AddSC_outdoorpvp_zm(); +} diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.h b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.h index 237fee3283b..ebbccfd63cb 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.h @@ -132,11 +132,11 @@ class OPvPCapturePointTF : public OPvPCapturePoint public: OPvPCapturePointTF(OutdoorPvP* pvp, OutdoorPvPTF_TowerType type); - bool Update(uint32 diff); + bool Update(uint32 diff) override; - void ChangeState(); + void ChangeState() override; - void FillInitialWorldStates(WorldPacket & data); + void FillInitialWorldStates(WorldPacket & data) override; void UpdateTowerState(); @@ -151,16 +151,16 @@ class OutdoorPvPTF : public OutdoorPvP public: OutdoorPvPTF(); - bool SetupOutdoorPvP(); + bool SetupOutdoorPvP() override; - void HandlePlayerEnterZone(Player* player, uint32 zone); - void HandlePlayerLeaveZone(Player* player, uint32 zone); + void HandlePlayerEnterZone(Player* player, uint32 zone) override; + void HandlePlayerLeaveZone(Player* player, uint32 zone) override; - bool Update(uint32 diff); + bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket &data); + void FillInitialWorldStates(WorldPacket &data) override; - void SendRemoveWorldStates(Player* player); + void SendRemoveWorldStates(Player* player) override; uint32 GetAllianceTowersControlled() const; void SetAllianceTowersControlled(uint32 count); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h index e71fbf79280..352e6f108ea 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h @@ -161,9 +161,9 @@ class OPvPCapturePointZM_Beacon : public OPvPCapturePoint public: OPvPCapturePointZM_Beacon(OutdoorPvP* pvp, ZM_BeaconType type); - void ChangeState(); + void ChangeState() override; - void FillInitialWorldStates(WorldPacket & data); + void FillInitialWorldStates(WorldPacket & data) override; void UpdateTowerState(); @@ -218,18 +218,18 @@ class OutdoorPvPZM : public OutdoorPvP public: OutdoorPvPZM(); - bool SetupOutdoorPvP(); + bool SetupOutdoorPvP() override; - void HandlePlayerEnterZone(Player* player, uint32 zone); - void HandlePlayerLeaveZone(Player* player, uint32 zone); + void HandlePlayerEnterZone(Player* player, uint32 zone) override; + void HandlePlayerLeaveZone(Player* player, uint32 zone) override; - bool Update(uint32 diff); + bool Update(uint32 diff) override; - void FillInitialWorldStates(WorldPacket &data); + void FillInitialWorldStates(WorldPacket &data) override; - void SendRemoveWorldStates(Player* player); + void SendRemoveWorldStates(Player* player) override; - void HandleKillImpl(Player* player, Unit* killed); + void HandleKillImpl(Player* player, Unit* killed) override; uint32 GetAllianceTowersControlled() const; void SetAllianceTowersControlled(uint32 count); diff --git a/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp index 9c16379c9f1..236f5bac403 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp @@ -64,12 +64,11 @@ public: return GetInstanceAI<boss_gurtogg_bloodboilAI>(creature); } - struct boss_gurtogg_bloodboilAI : public ScriptedAI + struct boss_gurtogg_bloodboilAI : public BossAI { - boss_gurtogg_bloodboilAI(Creature* creature) : ScriptedAI(creature) + boss_gurtogg_bloodboilAI(Creature* creature) : BossAI(creature, DATA_GURTOGG_BLOODBOIL) { Initialize(); - instance = creature->GetInstanceScript(); } void Initialize() @@ -91,8 +90,6 @@ public: Phase1 = true; } - InstanceScript* instance; - ObjectGuid TargetGUID; float TargetThreat; @@ -112,8 +109,7 @@ public: void Reset() override { - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, NOT_STARTED); - + _Reset(); Initialize(); me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); @@ -122,9 +118,8 @@ public: void EnterCombat(Unit* /*who*/) override { - DoZoneInCombat(); Talk(SAY_AGGRO); - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, IN_PROGRESS); + _EnterCombat(); } void KilledUnit(Unit* /*victim*/) override @@ -134,9 +129,8 @@ public: void JustDied(Unit* /*killer*/) override { - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, DONE); - Talk(SAY_DEATH); + _JustDied(); } void RevertThreatOnTarget(ObjectGuid guid) diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 7902c585509..a63d984d849 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -473,12 +473,11 @@ class boss_illidan_stormrage : public CreatureScript public: boss_illidan_stormrage() : CreatureScript("boss_illidan_stormrage") { } - struct boss_illidan_stormrageAI : public ScriptedAI + struct boss_illidan_stormrageAI : public BossAI { - boss_illidan_stormrageAI(Creature* creature) : ScriptedAI(creature), Summons(me) + boss_illidan_stormrageAI(Creature* creature) : BossAI(creature, DATA_ILLIDAN_STORMRAGE) { Initialize(); - instance = creature->GetInstanceScript(); DoCast(me, SPELL_DUAL_WIELD, true); } @@ -519,7 +518,7 @@ public: EnterPhase(PHASE_FLIGHT_SEQUENCE); } } - Summons.Despawn(summon); + summons.Despawn(summon); } void MovementInform(uint32 /*MovementType*/, uint32 /*Data*/) override @@ -539,6 +538,7 @@ public: void EnterCombat(Unit* /*who*/) override { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->setActive(true); DoZoneInCombat(); } @@ -561,10 +561,10 @@ public: { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE); - for (uint8 i = DATA_GO_ILLIDAN_DOOR_R; i < DATA_GO_ILLIDAN_DOOR_L + 1; ++i) instance->HandleGameObject(instance->GetGuidData(i), true); + + _JustDied(); } void KilledUnit(Unit* victim) override @@ -585,7 +585,7 @@ public: void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override { - if (spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades! + if (spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warglaives! { if (!me->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); @@ -673,7 +673,7 @@ public: Timer[EVENT_TALK_SEQUENCE] = 100; me->RemoveAllAuras(); me->InterruptNonMeleeSpells(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); me->GetMotionMaster()->Clear(false); me->AttackStop(); break; @@ -745,7 +745,7 @@ public: if (!Trigger) return; - Trigger->SetSpeed(MOVE_WALK, 3); + Trigger->SetSpeedRate(MOVE_WALK, 3); Trigger->SetWalk(true); Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z); @@ -791,99 +791,99 @@ public: { switch (FlightCount) { - case 1: // lift off - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->SetDisableGravity(true); - me->StopMoving(); - Talk(SAY_ILLIDAN_TAKEOFF); - Timer[EVENT_FLIGHT_SEQUENCE] = 3000; - break; - case 2: // move to center - me->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); // +5, for SPELL_THROW_GLAIVE bug - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 3: // throw one glaive - { - uint8 i=1; - Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Glaive) + case 1: // lift off + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->SetDisableGravity(true); + me->StopMoving(); + Talk(SAY_ILLIDAN_TAKEOFF); + Timer[EVENT_FLIGHT_SEQUENCE] = 3000; + break; + case 2: // move to center + me->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); // +5, for SPELL_THROW_GLAIVE bug + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 3: // throw one glaive { - GlaiveGUID[i] = Glaive->GetGUID(); - Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Glaive->SetDisplayId(MODEL_INVISIBLE); - Glaive->setFaction(me->getFaction()); - DoCast(Glaive, SPELL_THROW_GLAIVE2); + uint8 i=1; + Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Glaive) + { + GlaiveGUID[i] = Glaive->GetGUID(); + Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Glaive->SetDisplayId(MODEL_INVISIBLE); + Glaive->setFaction(me->getFaction()); + DoCast(Glaive, SPELL_THROW_GLAIVE2); + } } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 700; - break; - case 4: // throw another - SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - { - uint8 i=0; - Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (Glaive) + Timer[EVENT_FLIGHT_SEQUENCE] = 700; + break; + case 4: // throw another + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); { - GlaiveGUID[i] = Glaive->GetGUID(); - Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Glaive->SetDisplayId(MODEL_INVISIBLE); - Glaive->setFaction(me->getFaction()); - DoCast(Glaive, SPELL_THROW_GLAIVE, true); + uint8 i=0; + Creature* Glaive = me->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (Glaive) + { + GlaiveGUID[i] = Glaive->GetGUID(); + Glaive->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Glaive->SetDisplayId(MODEL_INVISIBLE); + Glaive->setFaction(me->getFaction()); + DoCast(Glaive, SPELL_THROW_GLAIVE, true); + } } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 5000; - break; - case 5: // summon flames - SummonFlamesOfAzzinoth(); - Timer[EVENT_FLIGHT_SEQUENCE] = 3000; - break; - case 6: // fly to hover point - me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 7: // return to center - me->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); - Timer[EVENT_FLIGHT_SEQUENCE] = 0; - break; - case 8: // glaive return - for (uint8 i = 0; i < 2; ++i) - { - if (GlaiveGUID[i]) + Timer[EVENT_FLIGHT_SEQUENCE] = 5000; + break; + case 5: // summon flames + SummonFlamesOfAzzinoth(); + Timer[EVENT_FLIGHT_SEQUENCE] = 3000; + break; + case 6: // fly to hover point + me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 7: // return to center + me->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); + Timer[EVENT_FLIGHT_SEQUENCE] = 0; + break; + case 8: // glaive return + for (uint8 i = 0; i < 2; ++i) { - Unit* Glaive = ObjectAccessor::GetUnit(*me, GlaiveGUID[i]); - if (Glaive) + if (GlaiveGUID[i]) { - Glaive->CastSpell(me, SPELL_GLAIVE_RETURNS, false); // Make it look like the Glaive flies back up to us - Glaive->SetDisplayId(MODEL_INVISIBLE); // disappear but not die for now + Unit* Glaive = ObjectAccessor::GetUnit(*me, GlaiveGUID[i]); + if (Glaive) + { + Glaive->CastSpell(me, SPELL_GLAIVE_RETURNS, false); // Make it look like the Glaive flies back up to us + Glaive->SetDisplayId(MODEL_INVISIBLE); // disappear but not die for now + } } } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 2000; - break; - case 9: // land - me->SetDisableGravity(false); - me->StopMoving(); - me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); - for (uint8 i = 0; i < 2; ++i) - { - if (GlaiveGUID[i]) + Timer[EVENT_FLIGHT_SEQUENCE] = 2000; + break; + case 9: // land + me->SetDisableGravity(false); + me->StopMoving(); + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + for (uint8 i = 0; i < 2; ++i) { - if (Creature* glaive = ObjectAccessor::GetCreature(*me, GlaiveGUID[i])) - glaive->DespawnOrUnsummon(); + if (GlaiveGUID[i]) + { + if (Creature* glaive = ObjectAccessor::GetCreature(*me, GlaiveGUID[i])) + glaive->DespawnOrUnsummon(); - GlaiveGUID[i].Clear(); + GlaiveGUID[i].Clear(); + } } - } - Timer[EVENT_FLIGHT_SEQUENCE] = 2000; - break; - case 10: // attack - DoResetThreat(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - EnterPhase(PHASE_NORMAL_2); - break; - default: - break; + Timer[EVENT_FLIGHT_SEQUENCE] = 2000; + break; + case 10: // attack + DoResetThreat(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + EnterPhase(PHASE_NORMAL_2); + break; + default: + break; } ++FlightCount; } @@ -913,23 +913,23 @@ public: switch (TransformCount) { - case 2: - DoResetThreat(); - break; - case 4: - EnterPhase(PHASE_DEMON); - break; - case 7: - DoResetThreat(); - break; - case 9: - if (MaievGUID) - EnterPhase(PHASE_NORMAL_MAIEV); // Depending on whether we summoned Maiev, we switch to either phase 5 or 3 - else - EnterPhase(PHASE_NORMAL_2); - break; - default: - break; + case 2: + DoResetThreat(); + break; + case 4: + EnterPhase(PHASE_DEMON); + break; + case 7: + DoResetThreat(); + break; + case 9: + if (MaievGUID) + EnterPhase(PHASE_NORMAL_MAIEV); // Depending on whether we summoned Maiev, we switch to either phase 5 or 3 + else + EnterPhase(PHASE_NORMAL_2); + break; + default: + break; } if (Phase == PHASE_TRANSFORM_SEQUENCE) Timer[EVENT_TRANSFORM_SEQUENCE] = DemonTransformation[TransformCount].timer; @@ -957,37 +957,37 @@ public: switch (Phase) { - case PHASE_NORMAL: - if (HealthBelowPct(65)) - EnterPhase(PHASE_FLIGHT_SEQUENCE); - break; + case PHASE_NORMAL: + if (HealthBelowPct(65)) + EnterPhase(PHASE_FLIGHT_SEQUENCE); + break; - case PHASE_NORMAL_2: - if (HealthBelowPct(30)) - EnterPhase(PHASE_TALK_SEQUENCE); - break; + case PHASE_NORMAL_2: + if (HealthBelowPct(30)) + EnterPhase(PHASE_TALK_SEQUENCE); + break; - case PHASE_NORMAL_MAIEV: - if (HealthBelowPct(1)) - EnterPhase(PHASE_TALK_SEQUENCE); - break; + case PHASE_NORMAL_MAIEV: + if (HealthBelowPct(1)) + EnterPhase(PHASE_TALK_SEQUENCE); + break; - case PHASE_TALK_SEQUENCE: - if (Event == EVENT_TALK_SEQUENCE) - HandleTalkSequence(); - break; + case PHASE_TALK_SEQUENCE: + if (Event == EVENT_TALK_SEQUENCE) + HandleTalkSequence(); + break; - case PHASE_FLIGHT_SEQUENCE: - if (Event == EVENT_FLIGHT_SEQUENCE) - HandleFlightSequence(); - break; + case PHASE_FLIGHT_SEQUENCE: + if (Event == EVENT_FLIGHT_SEQUENCE) + HandleFlightSequence(); + break; - case PHASE_TRANSFORM_SEQUENCE: - if (Event == EVENT_TRANSFORM_SEQUENCE) - HandleTransformSequence(); - break; - default: - break; + case PHASE_TRANSFORM_SEQUENCE: + if (Event == EVENT_TRANSFORM_SEQUENCE) + HandleTransformSequence(); + break; + default: + break; } if (me->IsNonMeleeSpellCast(false)) @@ -998,63 +998,63 @@ public: switch (Event) { // PHASE_NORMAL - case EVENT_BERSERK: - Talk(SAY_ILLIDAN_ENRAGE); - DoCast(me, SPELL_BERSERK, true); - Timer[EVENT_BERSERK] = 5000; // The buff actually lasts forever. - break; - - case EVENT_TAUNT: - Talk(SAY_ILLIDAN_TAUNT); - Timer[EVENT_TAUNT] = urand(25000, 35000); - break; - - case EVENT_SHEAR: - // no longer exists in 3.0f.2 - // DoCastVictim(SPELL_SHEAR); - Timer[EVENT_SHEAR] = 25000 + (rand32() % 16 * 1000); - break; - - case EVENT_FLAME_CRASH: - DoCastVictim(SPELL_FLAME_CRASH); - Timer[EVENT_FLAME_CRASH] = urand(30000, 40000); - break; - - case EVENT_PARASITIC_SHADOWFIEND: - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true)) - DoCast(target, SPELL_PARASITIC_SHADOWFIEND, true); - Timer[EVENT_PARASITIC_SHADOWFIEND] = urand(35000, 45000); - } - break; - - case EVENT_PARASITE_CHECK: - Timer[EVENT_PARASITE_CHECK] = 0; - break; - - case EVENT_DRAW_SOUL: - DoCastVictim(SPELL_DRAW_SOUL); - Timer[EVENT_DRAW_SOUL] = urand(50000, 60000); - break; - - // PHASE_NORMAL_2 - case EVENT_AGONIZING_FLAMES: - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES); - Timer[EVENT_AGONIZING_FLAMES] = 0; - break; - - case EVENT_TRANSFORM_NORMAL: - EnterPhase(PHASE_TRANSFORM_SEQUENCE); - break; - - // PHASE_NORMAL_MAIEV - case EVENT_ENRAGE: - DoCast(me, SPELL_ENRAGE); - Timer[EVENT_ENRAGE] = 0; - break; - - default: - break; + case EVENT_BERSERK: + Talk(SAY_ILLIDAN_ENRAGE); + DoCast(me, SPELL_BERSERK, true); + Timer[EVENT_BERSERK] = 5000; // The buff actually lasts forever. + break; + + case EVENT_TAUNT: + Talk(SAY_ILLIDAN_TAUNT); + Timer[EVENT_TAUNT] = urand(25000, 35000); + break; + + case EVENT_SHEAR: + // no longer exists in 3.0f.2 + // DoCastVictim(SPELL_SHEAR); + Timer[EVENT_SHEAR] = 25000 + (rand32() % 16 * 1000); + break; + + case EVENT_FLAME_CRASH: + DoCastVictim(SPELL_FLAME_CRASH); + Timer[EVENT_FLAME_CRASH] = urand(30000, 40000); + break; + + case EVENT_PARASITIC_SHADOWFIEND: + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 200, true)) + DoCast(target, SPELL_PARASITIC_SHADOWFIEND, true); + Timer[EVENT_PARASITIC_SHADOWFIEND] = urand(35000, 45000); + } + break; + + case EVENT_PARASITE_CHECK: + Timer[EVENT_PARASITE_CHECK] = 0; + break; + + case EVENT_DRAW_SOUL: + DoCastVictim(SPELL_DRAW_SOUL); + Timer[EVENT_DRAW_SOUL] = urand(50000, 60000); + break; + + // PHASE_NORMAL_2 + case EVENT_AGONIZING_FLAMES: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES); + Timer[EVENT_AGONIZING_FLAMES] = 0; + break; + + case EVENT_TRANSFORM_NORMAL: + EnterPhase(PHASE_TRANSFORM_SEQUENCE); + break; + + // PHASE_NORMAL_MAIEV + case EVENT_ENRAGE: + DoCast(me, SPELL_ENRAGE); + Timer[EVENT_ENRAGE] = 0; + break; + + default: + break; } DoMeleeAttackIfReady(); } @@ -1063,32 +1063,32 @@ public: { switch (Event) { - case EVENT_FIREBALL: - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL); - Timer[EVENT_FIREBALL] = 3000; - break; - - case EVENT_DARK_BARRAGE: - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE); - Timer[EVENT_DARK_BARRAGE] = 0; - break; - - case EVENT_EYE_BLAST: - CastEyeBlast(); - Timer[EVENT_EYE_BLAST] = 0; - break; - - case EVENT_MOVE_POINT: - Phase = PHASE_FLIGHT_SEQUENCE; - Timer[EVENT_FLIGHT_SEQUENCE] = 0; // do not start Event when changing hover point - HoverPoint += (rand32() % 3 + 1); - if (HoverPoint > 3) - HoverPoint -= 4; - me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); - break; - - default: - break; + case EVENT_FIREBALL: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL); + Timer[EVENT_FIREBALL] = 3000; + break; + + case EVENT_DARK_BARRAGE: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE); + Timer[EVENT_DARK_BARRAGE] = 0; + break; + + case EVENT_EYE_BLAST: + CastEyeBlast(); + Timer[EVENT_EYE_BLAST] = 0; + break; + + case EVENT_MOVE_POINT: + Phase = PHASE_FLIGHT_SEQUENCE; + Timer[EVENT_FLIGHT_SEQUENCE] = 0; // do not start Event when changing hover point + HoverPoint += (rand32() % 3 + 1); + if (HoverPoint > 3) + HoverPoint -= 4; + me->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); + break; + + default: + break; } } @@ -1096,29 +1096,29 @@ public: { switch (Event) { - case EVENT_SHADOW_BLAST: - me->GetMotionMaster()->Clear(false); - if (me->GetVictim() && (!me->IsWithinDistInMap(me->GetVictim(), 50) || !me->IsWithinLOSInMap(me->GetVictim()))) - me->GetMotionMaster()->MoveChase(me->GetVictim(), 30); - else - me->GetMotionMaster()->MoveIdle(); - DoCastVictim(SPELL_SHADOW_BLAST); - Timer[EVENT_SHADOW_BLAST] = 4000; - break; - case EVENT_SHADOWDEMON: - DoCast(me, SPELL_SUMMON_SHADOWDEMON); - Timer[EVENT_SHADOWDEMON] = 0; - Timer[EVENT_FLAME_BURST] += 10000; - break; - case EVENT_FLAME_BURST: - DoCast(me, SPELL_FLAME_BURST); - Timer[EVENT_FLAME_BURST] = 15000; - break; - case EVENT_TRANSFORM_DEMON: - EnterPhase(PHASE_TRANSFORM_SEQUENCE); - break; - default: - break; + case EVENT_SHADOW_BLAST: + me->GetMotionMaster()->Clear(false); + if (me->GetVictim() && (!me->IsWithinDistInMap(me->GetVictim(), 50) || !me->IsWithinLOSInMap(me->GetVictim()))) + me->GetMotionMaster()->MoveChase(me->GetVictim(), 30); + else + me->GetMotionMaster()->MoveIdle(); + DoCastVictim(SPELL_SHADOW_BLAST); + Timer[EVENT_SHADOW_BLAST] = 4000; + break; + case EVENT_SHADOWDEMON: + DoCast(me, SPELL_SUMMON_SHADOWDEMON); + Timer[EVENT_SHADOWDEMON] = 0; + Timer[EVENT_FLAME_BURST] += 10000; + break; + case EVENT_FLAME_BURST: + DoCast(me, SPELL_FLAME_BURST); + Timer[EVENT_FLAME_BURST] = 15000; + break; + case EVENT_TRANSFORM_DEMON: + EnterPhase(PHASE_TRANSFORM_SEQUENCE); + break; + default: + break; } } } @@ -1128,7 +1128,6 @@ public: uint32 Timer[EVENT_ENRAGE + 1]; PhaseIllidan Phase; private: - InstanceScript* instance; EventIllidan Event; uint32 TalkCount; uint32 TransformCount; @@ -1137,7 +1136,6 @@ public: ObjectGuid MaievGUID; ObjectGuid FlameGUID[2]; ObjectGuid GlaiveGUID[2]; - SummonList Summons; }; CreatureAI* GetAI(Creature* creature) const override @@ -1148,7 +1146,7 @@ public: /********************************** End of Illidan AI* *****************************************/ -/******* Functions and vars for Akama's AI* *****/ +/******* Functions and vars for Maiev's AI* *****/ class boss_maiev_shadowsong : public CreatureScript { public: @@ -1301,15 +1299,17 @@ public: EventMaiev Event = EVENT_MAIEV_NULL; for (uint8 i = 1; i <= MaxTimer; ++i) + { if (Timer[i]) { if (Timer[i] <= diff) Event = (EventMaiev)i; else Timer[i] -= diff; } + } - switch (Event) - { + switch (Event) + { case EVENT_MAIEV_STEALTH: { me->SetFullHealth(); @@ -1345,21 +1345,21 @@ public: break; default: break; - } + } - if (HealthBelowPct(50)) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) - ENSURE_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID()); - me->AttackStop(); - Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute - MaxTimer = 1; - } + if (HealthBelowPct(50)) + { + me->SetVisible(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) + ENSURE_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID()); + me->AttackStop(); + Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute + MaxTimer = 1; + } - if (Phase == PHASE_NORMAL_MAIEV) - DoMeleeAttackIfReady(); + if (Phase == PHASE_NORMAL_MAIEV) + DoMeleeAttackIfReady(); } private: @@ -1375,6 +1375,7 @@ public: } }; +/******* Functions and vars for Akama's AI* *****/ class npc_akama_illidan : public CreatureScript { public: @@ -1432,7 +1433,7 @@ public: KillAllElites(); - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values.. + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); // Database sometimes has strange values.. me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); me->setActive(false); me->SetVisible(false); @@ -1524,7 +1525,7 @@ public: void BeginWalk() { me->SetWalk(false); - me->SetSpeed(MOVE_RUN, 1.0f); + me->SetSpeedRate(MOVE_RUN, 1.0f); me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); } @@ -1809,7 +1810,7 @@ public: void boss_illidan_stormrage::boss_illidan_stormrageAI::Reset() { - instance->SetBossState(DATA_ILLIDAN_STORMRAGE, NOT_STARTED); + _Reset(); if (Creature* akama = ObjectAccessor::GetCreature(*me, AkamaGUID)) { @@ -1828,12 +1829,11 @@ void boss_illidan_stormrage::boss_illidan_stormrageAI::Reset() SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); me->SetDisableGravity(false); me->setActive(false); - Summons.DespawnAll(); } void boss_illidan_stormrage::boss_illidan_stormrageAI::JustSummoned(Creature* summon) { - Summons.Summon(summon); + summons.Summon(summon); switch (summon->GetEntry()) { case PARASITIC_SHADOWFIEND: @@ -1926,7 +1926,7 @@ void boss_illidan_stormrage::boss_illidan_stormrageAI::HandleTalkSequence() break; case 15: DoCast(me, SPELL_DEATH); // Animate his kneeling + stun him - Summons.DespawnAll(); + summons.DespawnAll(); break; case 17: if (Creature* akama = ObjectAccessor::GetCreature(*me, AkamaGUID)) diff --git a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp index aaf72512ae9..9412067f77e 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp @@ -149,7 +149,7 @@ public: void TeleportPlayers() { - uint32 random = urand(0, 7); + uint32 random = urand(0, 6); float X = TeleportPoint[random].x; float Y = TeleportPoint[random].y; float Z = TeleportPoint[random].z; @@ -210,7 +210,7 @@ public: break; case EVENT_PRISMATIC_SHIELD: // Random Prismatic Shield every 15 seconds. - DoCast(me, PrismaticAuras[urand(0, 6)]); + DoCast(me, PrismaticAuras[urand(0, 5)]); events.ScheduleEvent(EVENT_PRISMATIC_SHIELD, 15000); break; case EVENT_FATAL_ATTRACTION: diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp index afc7d3d0fd7..d89437c2816 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -135,12 +135,11 @@ public: return GetInstanceAI<boss_reliquary_of_soulsAI>(creature); } - struct boss_reliquary_of_soulsAI : public ScriptedAI + struct boss_reliquary_of_soulsAI : public BossAI { - boss_reliquary_of_soulsAI(Creature* creature) : ScriptedAI(creature) + boss_reliquary_of_soulsAI(Creature* creature) : BossAI(creature, DATA_RELIQUARY_OF_SOULS) { Initialize(); - instance = creature->GetInstanceScript(); Counter = 0; Timer = 0; SoulCount = 0; @@ -152,8 +151,6 @@ public: Phase = 0; } - InstanceScript* instance; - ObjectGuid EssenceGUID; uint32 Phase; @@ -165,7 +162,7 @@ public: void Reset() override { - instance->SetBossState(DATA_RELIQUARY_OF_SOULS, NOT_STARTED); + _Reset(); if (EssenceGUID) { @@ -202,8 +199,7 @@ public: void EnterCombat(Unit* who) override { me->AddThreat(who, 10000.0f); - DoZoneInCombat(); - instance->SetBossState(DATA_RELIQUARY_OF_SOULS, IN_PROGRESS); + _EnterCombat(); Phase = 1; Counter = 0; @@ -246,11 +242,6 @@ public: } } - void JustDied(Unit* /*killer*/) override - { - instance->SetBossState(DATA_RELIQUARY_OF_SOULS, DONE); - } - void UpdateAI(uint32 diff) override { if (!Phase) diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index 7e1215488e1..c9e08176ad6 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -15,45 +15,45 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* -Name: Boss_Shade_of_Akama -%Complete: 80 -Comment: WIP A few more adds to script, ending script, and bugs. -Category: Black Temple -*/ - #include "ObjectMgr.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "PassiveAI.h" #include "ScriptedGossip.h" #include "GridNotifiers.h" #include "black_temple.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" enum Says { - // Akama Ending cinematic text + // Akama SAY_BROKEN_FREE_0 = 0, SAY_BROKEN_FREE_1 = 1, - SAY_BROKEN_FREE_2 = 2 + SAY_BROKEN_FREE_2 = 2, + SAY_LOW_HEALTH = 3, + SAY_DEAD = 4, + // Ashtongue Broken + SAY_BROKEN_SPECIAL = 0, + SAY_BROKEN_HAIL = 1 }; enum Spells { // Akama - SPELL_STEALTH = 34189, // On Spawn - SPELL_AKAMA_SOUL_CHANNEL = 40447, // Cast on self hits Shade - SPELL_FIXATE = 40607, // Cast on self hits Shade - SPELL_CHAIN_LIGHTNING = 39945, // Combat - SPELL_DESTRUCTIVE_POISON = 40874, // Combat + SPELL_STEALTH = 34189, + SPELL_AKAMA_SOUL_CHANNEL = 40447, + SPELL_FIXATE = 40607, + SPELL_CHAIN_LIGHTNING = 39945, + SPELL_DESTRUCTIVE_POISON = 40874, + SPELL_AKAMA_SOUL_EXPEL = 40902, // Shade - SPELL_THREAT = 41602, // self cast hits Akama - SPELL_SHADE_OF_AKAMA_TRIGGER = 40955, // Cast on death - SPELL_AKAMA_SOUL_EXPEL_CHANNEL = 40927, // must hit shade - SPELL_AKAMA_SOUL_EXPEL = 40902, // the one he cast + SPELL_THREAT = 41602, + SPELL_SHADE_OF_AKAMA_TRIGGER = 40955, + SPELL_AKAMA_SOUL_EXPEL_CHANNEL = 40927, // Ashtongue Channeler SPELL_SHADE_SOUL_CHANNEL = 40401, SPELL_SHADE_SOUL_CHANNEL_2 = 40520, - SPELL_SHADOWFORM = 40973, // Cast on Shade // Creature Spawner SPELL_ASHTONGUE_WAVE_B = 42035, SPELL_SUMMON_ASHTONGUE_SORCERER = 40476, @@ -78,11 +78,6 @@ enum Spells enum Creatures { NPC_ASHTONGUE_CHANNELER = 23421, - NPC_ASHTONGUE_SORCERER = 23215, - NPC_ASHTONGUE_DEFENDER = 23216, - NPC_ASHTONGUE_ELEMENTALIST = 23523, - NPC_ASHTONGUE_ROGUE = 23318, - NPC_ASHTONGUE_SPIRITBINDER = 23524, NPC_ASHTONGUE_BROKEN = 23319, NPC_CREATURE_SPAWNER_AKAMA = 23210 }; @@ -95,60 +90,114 @@ enum Factions enum Actions { - ACTION_CHANNELER_DIED = 1, - ACTION_START_SPAWNING = 2, - ACTION_STOP_SPAWNING = 3, - ACTION_DESPAWN_ALL_SPAWNS = 4, + ACTION_START_SPAWNING = 0, + ACTION_STOP_SPAWNING = 1, + ACTION_DESPAWN_ALL_SPAWNS = 2, + ACTION_SHADE_OF_AKAMA_DEAD = 3, + ACTION_BROKEN_SPECIAL = 4, + ACTION_BROKEN_EMOTE = 5, + ACTION_BROKEN_HAIL = 6 }; enum Events { // Akama - EVENT_SHADE_START = 1, - EVENT_SHADE_CHANNEL = 2, - EVENT_FIXATE = 3, - EVENT_CHAIN_LIGHTNING = 4, - EVENT_DESTRUCTIVE_POISON = 5, - // Shade - EVENT_RESET_ENCOUNTER = 6, - EVENT_FIND_CHANNELERS_SPAWNERS = 7, - EVENT_SET_CHANNELERS_SPAWNERS = 8, - EVENT_START_ATTACK_AKAMA = 9, - EVENT_ADD_THREAT = 10, + EVENT_SHADE_START = 1, + EVENT_SHADE_CHANNEL = 2, + EVENT_FIXATE = 3, + EVENT_CHAIN_LIGHTNING = 4, + EVENT_DESTRUCTIVE_POISON = 5, + EVENT_START_BROKEN_FREE = 6, + EVENT_START_SOUL_EXPEL = 7, + EVENT_EVADE_CHECK = 8, + EVENT_BROKEN_FREE_1 = 9, + EVENT_BROKEN_FREE_2 = 10, + EVENT_BROKEN_FREE_3 = 11, + EVENT_BROKEN_FREE_4 = 12, + // Shade of Akama + EVENT_INITIALIZE_SPAWNERS = 13, + EVENT_START_CHANNELERS_AND_SPAWNERS = 14, + EVENT_ADD_THREAT = 15, // Creature spawner - EVENT_SPAWN_WAVE_B = 11, - EVENT_SUMMON_ASHTONGUE_SORCERER = 12, - EVENT_SUMMON_ASHTONGUE_DEFENDER = 13, - // Channeler - EVENT_CHANNEL = 14, - // Ashtongue Sorcerer - EVENT_SORCERER_CHANNEL = 15, + EVENT_SPAWN_WAVE_B = 16, + EVENT_SUMMON_ASHTONGUE_SORCERER = 17, + EVENT_SUMMON_ASHTONGUE_DEFENDER = 18, // Ashtongue Defender - EVENT_DEBILITATING_STRIKE = 16, - EVENT_HEROIC_STRIKE = 17, - EVENT_SHIELD_BASH = 18, - EVENT_WINDFURY = 29, + EVENT_DEBILITATING_STRIKE = 19, + EVENT_HEROIC_STRIKE = 20, + EVENT_SHIELD_BASH = 21, + EVENT_WINDFURY = 22, // Ashtongue Rogue - EVENT_DEBILITATING_POISON = 20, - EVENT_EVISCERATE = 21, + EVENT_DEBILITATING_POISON = 23, + EVENT_EVISCERATE = 24, // Ashtongue Elementalist - EVENT_RAIN_OF_FIRE = 22, - EVENT_LIGHTNING_BOLT = 23, + EVENT_RAIN_OF_FIRE = 25, + EVENT_LIGHTNING_BOLT = 26, // Ashtongue Spiritbinder - EVENT_SPIRIT_HEAL = 24 + EVENT_SPIRIT_HEAL = 27, + EVENT_SPIRIT_MEND_RESET = 28, + EVENT_CHAIN_HEAL_RESET = 29 }; -G3D::Vector3 const ShadeWP = { 512.4877f, 400.7993f, 112.7837f }; +enum Misc +{ + AKAMA_CHANNEL_WAYPOINT = 0, + AKAMA_INTRO_WAYPOINT = 1, + + SUMMON_GROUP_RESET = 1 +}; -G3D::Vector3 const AkamaWP[] = +Position const AkamaWP[2] = { { 517.4877f, 400.7993f, 112.7837f }, { 468.4435f, 401.1062f, 118.5379f } }; -// ######################################################## -// Shade of Akama -// ######################################################## +Position const BrokenPos[18] = +{ + { 495.5628f, 462.7089f, 112.8169f, 4.1808090f }, + { 498.3421f, 463.8384f, 112.8673f, 4.5634810f }, + { 501.6708f, 463.8806f, 112.8673f, 3.7157850f }, + { 532.4264f, 448.4718f, 112.8563f, 3.9813020f }, + { 532.9113f, 451.6227f, 112.8671f, 4.6479530f }, + { 532.8243f, 453.9475f, 112.8671f, 4.7032810f }, + { 521.5317f, 402.3790f, 112.8671f, 3.1138120f }, + { 521.9184f, 404.6848f, 112.8671f, 4.0787760f }, + { 522.4290f, 406.5160f, 112.8671f, 3.3869470f }, + { 521.0833f, 393.1852f, 112.8611f, 3.0750830f }, + { 521.9014f, 395.6381f, 112.8671f, 4.0157140f }, + { 522.2610f, 397.7423f, 112.8671f, 3.4417790f }, + { 532.4565f, 345.3987f, 112.8585f, 1.7232640f }, + { 532.5565f, 346.8792f, 112.8671f, 1.8325960f }, + { 532.5491f, 348.6840f, 112.8671f, 0.2054047f }, + { 501.4669f, 338.5967f, 112.8504f, 1.7038430f }, + { 499.0937f, 337.9894f, 112.8673f, 1.8586250f }, + { 496.8722f, 338.0152f, 112.8673f, 0.5428222f } +}; + +Position const BrokenWP[18] = +{ + { 479.1884f, 434.8635f, 112.7838f }, + { 479.7349f, 435.9843f, 112.7838f }, + { 480.5328f, 436.8310f, 112.7838f }, + { 493.1714f, 420.1136f, 112.7838f }, + { 494.7830f, 417.4830f, 112.7838f }, + { 492.9280f, 423.1891f, 112.7838f }, + { 491.8618f, 403.2035f, 112.7838f }, + { 491.7784f, 400.2046f, 112.7838f }, + { 491.9451f, 406.2023f, 112.7838f }, + { 488.3535f, 395.3652f, 112.7838f }, + { 488.8324f, 392.3267f, 112.7838f }, + { 489.2300f, 398.3135f, 112.7838f }, + { 491.9286f, 383.0433f, 112.7838f }, + { 491.1526f, 380.0966f, 112.7839f }, + { 493.6747f, 385.5407f, 112.7838f }, + { 476.2499f, 369.0865f, 112.7839f }, + { 473.7637f, 367.8766f, 112.7839f }, + { 478.8986f, 370.1895f, 112.7839f } +}; + +static float const MIDDLE_OF_ROOM = 400.0f; class boss_shade_of_akama : public CreatureScript { @@ -160,233 +209,144 @@ public: boss_shade_of_akamaAI(Creature* creature) : BossAI(creature, DATA_SHADE_OF_AKAMA) { Initialize(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } void Initialize() { - combatStarted = false; - akamaReached = false; - HasKilledAkama = false; - HasKilledAkamaAndReseting = false; + _spawners.clear(); + _isInPhaseOne = true; } void Reset() override { - _Reset(); - if (!HasKilledAkamaAndReseting) - { - for (GuidList::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr)) - Channeler->DespawnOrUnsummon(); - - for (GuidList::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr) - if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr)) - Spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS); - - events.ScheduleEvent(EVENT_FIND_CHANNELERS_SPAWNERS, 3000); - events.ScheduleEvent(EVENT_RESET_ENCOUNTER, 5000); - } - + Initialize(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); me->SetWalk(true); - Initialize(); + events.ScheduleEvent(EVENT_INITIALIZE_SPAWNERS, Seconds(1)); + me->SummonCreatureGroup(SUMMON_GROUP_RESET); } - void EnterCombat(Unit* /*who*/) override { } - - void AttackStart(Unit* who) override + void EnterEvadeMode(EvadeReason /*why*/) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - { - if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - if (Akama->IsAlive()) - ScriptedAI::AttackStart(Akama); - } - else - ScriptedAI::AttackStart(who); - } + _Reset(); - void DoAction(int32 actionId) override - { - if (actionId == ACTION_CHANNELER_DIED) - me->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2); + for (ObjectGuid const& spawnerGuid : _spawners) + if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid)) + spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS); - UpdateSpeed(); + _DespawnAtEvade(); } void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { if (spell->Id == SPELL_AKAMA_SOUL_CHANNEL) { - combatStarted = true; - events.ScheduleEvent(EVENT_START_ATTACK_AKAMA, 500); - events.ScheduleEvent(EVENT_SET_CHANNELERS_SPAWNERS, 1000); + events.ScheduleEvent(EVENT_START_CHANNELERS_AND_SPAWNERS, Seconds(1)); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - me->AddThreat(Akama, 10000000.0f); + events.ScheduleEvent(EVENT_EVADE_CHECK, Seconds(10)); + if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) + AttackStart(akama); } - else if (spell->Id == SPELL_SHADE_SOUL_CHANNEL_2) - UpdateSpeed(); + + if (spell->Id == SPELL_AKAMA_SOUL_EXPEL) + DoCastSelf(SPELL_AKAMA_SOUL_EXPEL_CHANNEL); } - void UpdateSpeed() + void MovementInform(uint32 motionType, uint32 /*pointId*/) override { - float moveSpeed = 0.2f; - - if (me->GetAuraCount(SPELL_SHADE_SOUL_CHANNEL_2) <= 3) + if (_isInPhaseOne && motionType == CHASE_MOTION_TYPE) { - moveSpeed = (2.0f - (0.6f * me->GetAuraCount(SPELL_SHADE_SOUL_CHANNEL_2))); - me->SetSpeed(MOVE_WALK, moveSpeed / 2.5f); - me->SetSpeed(MOVE_RUN, (moveSpeed * 2) / 7); - me->ClearUnitState(UNIT_STATE_ROOT); + _isInPhaseOne = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetWalk(false); + events.ScheduleEvent(EVENT_ADD_THREAT, Milliseconds(100)); + + for (ObjectGuid const& spawnerGuid : _spawners) + if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid)) + spawner->AI()->DoAction(ACTION_STOP_SPAWNING); } - else - me->AddUnitState(UNIT_STATE_ROOT); } - void UpdateAI(uint32 diff) override + void JustDied(Unit* /*killer*/) override { - if (HasKilledAkamaAndReseting) - return; + DoCastSelf(SPELL_SHADE_OF_AKAMA_TRIGGER); + + if (Creature* akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) + akama->AI()->DoAction(ACTION_SHADE_OF_AKAMA_DEAD); + for (ObjectGuid const& spawnerGuid : _spawners) + if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid)) + spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS); + + events.Reset(); + summons.DespawnEntry(NPC_ASHTONGUE_CHANNELER); + instance->SetBossState(DATA_SHADE_OF_AKAMA, DONE); + } + + void EnterEvadeModeIfNeeded() + { + Map::PlayerList const &players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + if (Player* player = i->GetSource()) + if (player->IsAlive() && !player->IsGameMaster() && CheckBoundary(player)) + return; + + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); + } + + void UpdateAI(uint32 diff) override + { events.Update(diff); - if (!combatStarted) - { - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_RESET_ENCOUNTER: - if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - if (!Akama->IsAlive()) - Akama->Respawn(); - break; - case EVENT_FIND_CHANNELERS_SPAWNERS: - { - std::list<Creature*> ChannelerList; - me->GetCreatureListWithEntryInGrid(ChannelerList, NPC_ASHTONGUE_CHANNELER, 15.0f); - - if (!ChannelerList.empty()) - for (std::list<Creature*>::const_iterator itr = ChannelerList.begin(); itr != ChannelerList.end(); ++itr) - { - Channelers.push_back((*itr)->GetGUID()); - if ((*itr)->isDead()) - (*itr)->Respawn(); - } - - std::list<Creature*> SpawnerList; - me->GetCreatureListWithEntryInGrid(SpawnerList, NPC_CREATURE_SPAWNER_AKAMA, 90.0f); - - if (!SpawnerList.empty()) - for (std::list<Creature*>::const_iterator itr = SpawnerList.begin(); itr != SpawnerList.end(); ++itr) - Spawners.push_back((*itr)->GetGUID()); - - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); - break; - } - default: - break; - } - } - } - else + if (!UpdateVictim()) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - while (uint32 eventId = events.ExecuteEvent()) + switch (eventId) { - switch (eventId) + case EVENT_INITIALIZE_SPAWNERS: { - case EVENT_SET_CHANNELERS_SPAWNERS: - { - for (GuidList::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr)) - Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - for (GuidList::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr) - if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr)) - Spawner->AI()->DoAction(ACTION_START_SPAWNING); - break; - } - case EVENT_START_ATTACK_AKAMA: - me->GetMotionMaster()->MovePoint(0, ShadeWP.x, ShadeWP.y, ShadeWP.z, false); - events.ScheduleEvent(EVENT_START_ATTACK_AKAMA, 1000); - break; - case EVENT_ADD_THREAT: - DoCast(SPELL_THREAT); - events.ScheduleEvent(EVENT_ADD_THREAT, 3500); - break; - default: - break; - } - } + std::list<Creature*> SpawnerList; + me->GetCreatureListWithEntryInGrid(SpawnerList, NPC_CREATURE_SPAWNER_AKAMA); + for (Creature* spawner : SpawnerList) + _spawners.push_back(spawner->GetGUID()); - if (HasKilledAkama) - { - if (!HasKilledAkamaAndReseting) - { - HasKilledAkamaAndReseting = true; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - instance->SetBossState(DATA_SHADE_OF_AKAMA, NOT_STARTED); - me->RemoveAllAurasExceptType(SPELL_AURA_DUMMY); - me->DeleteThreatList(); - me->CombatStop(); - me->GetMotionMaster()->MoveTargetedHome(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - combatStarted = false; - - if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - Akama->DespawnOrUnsummon(); - - for (GuidList::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr)) - Channeler->DespawnOrUnsummon(); - - for (GuidList::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr) - if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr)) - Spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS); - - events.ScheduleEvent(EVENT_FIND_CHANNELERS_SPAWNERS, 10000); - events.ScheduleEvent(EVENT_RESET_ENCOUNTER, 20000); + break; } - } - - if (!akamaReached) - { - if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) + case EVENT_START_CHANNELERS_AND_SPAWNERS: { - if (me->IsWithinDist(Akama, 2.0f, false)) - { - akamaReached = true; - me->GetMotionMaster()->Clear(true); - me->GetMotionMaster()->MoveIdle(); - me->SetWalk(false); + for (ObjectGuid const& summonGuid : summons) + if (Creature* channeler = ObjectAccessor::GetCreature(*me, summonGuid)) + channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + for (ObjectGuid const& spawnerGuid : _spawners) + if (Creature* spawner = ObjectAccessor::GetCreature(*me, spawnerGuid)) + spawner->AI()->DoAction(ACTION_START_SPAWNING); - events.CancelEvent(EVENT_START_ATTACK_AKAMA); - events.ScheduleEvent(EVENT_ADD_THREAT, 100); - - for (GuidList::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr) - if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr)) - Spawner->AI()->DoAction(ACTION_STOP_SPAWNING); - } + break; } + case EVENT_ADD_THREAT: + DoCast(SPELL_THREAT); + events.Repeat(Seconds(3) + Milliseconds(500)); + break; + case EVENT_EVADE_CHECK: + EnterEvadeModeIfNeeded(); + events.Repeat(Seconds(10)); + break; + default: + break; } - else - DoMeleeAttackIfReady(); } + + DoMeleeAttackIfReady(); } - public: - bool HasKilledAkama; private: - GuidList Channelers; - GuidList Spawners; - bool akamaReached; - bool combatStarted; - bool HasKilledAkamaAndReseting; + GuidVector _spawners; + bool _isInPhaseOne; }; CreatureAI* GetAI(Creature* creature) const override @@ -395,10 +355,6 @@ public: } }; -// ######################################################## -// Akama -// ######################################################## - class npc_akama_shade : public CreatureScript { public: @@ -406,117 +362,188 @@ public: struct npc_akamaAI : public ScriptedAI { - npc_akamaAI(Creature* creature) : ScriptedAI(creature) + npc_akamaAI(Creature* creature) : ScriptedAI(creature), _summons(me) { Initialize(); - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } void Initialize() { - StartChannel = false; - StartCombat = false; - HasYelledOnce = false; - ShadeHasDied = false; + _isInCombat = false; + _hasYelledOnce = false; + _chosen.Clear(); + _summons.DespawnAll(); + _events.Reset(); } void Reset() override { - me->setFaction(FACTION_FRIENDLY); - DoCast(me, SPELL_STEALTH); Initialize(); + me->setFaction(FACTION_FRIENDLY); + DoCastSelf(SPELL_STEALTH); - if (instance->GetBossState(DATA_SHADE_OF_AKAMA) != DONE) + if (_instance->GetBossState(DATA_SHADE_OF_AKAMA) != DONE) me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); } - void JustDied(Unit* /*killer*/) override + void JustSummoned(Creature* summon) override { - if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA))) - if (Shade->IsAlive()) - ENSURE_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->HasKilledAkama = true; - me->GetMotionMaster()->Clear(true); - me->GetMotionMaster()->MoveIdle(); + _summons.Summon(summon); } + void EnterEvadeMode(EvadeReason /*why*/) override { } + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - if (spell->Id == SPELL_THREAT && !StartCombat) + if (spell->Id == SPELL_THREAT && !_isInCombat) { - me->ClearUnitState(UNIT_STATE_ROOT); - me->RemoveAura(SPELL_AKAMA_SOUL_CHANNEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA))) - Shade->RemoveAura(SPELL_AKAMA_SOUL_CHANNEL); - StartCombat = true; + _isInCombat = true; + me->SetWalk(false); + me->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL); + if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA))) + { + shade->RemoveAurasDueToSpell(SPELL_AKAMA_SOUL_CHANNEL); + AttackStart(shade); + _events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, Seconds(2)); + _events.ScheduleEvent(EVENT_DESTRUCTIVE_POISON, Seconds(5)); + } } } - void EnterCombat(Unit* /*who*/) override + void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override { - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 2000); - events.ScheduleEvent(EVENT_DESTRUCTIVE_POISON, 5000); + if (me->HealthBelowPct(20) && !_hasYelledOnce) + { + _hasYelledOnce = true; + Talk(SAY_LOW_HEALTH); + } } - void UpdateAI(uint32 diff) override + void DoAction(int32 actionId) override { - if (StartChannel) + if (actionId == ACTION_SHADE_OF_AKAMA_DEAD) { - events.Update(diff); + _isInCombat = false; + me->CombatStop(true); + me->setFaction(FACTION_FRIENDLY); + me->SetWalk(true); + _events.Reset(); + me->GetMotionMaster()->MovePoint(AKAMA_INTRO_WAYPOINT, AkamaWP[1]); + } + } - while (uint32 eventId = events.ExecuteEvent()) + void MovementInform(uint32 motionType, uint32 pointId) override + { + if (motionType != POINT_MOTION_TYPE) + return; + + if (pointId == AKAMA_CHANNEL_WAYPOINT) + _events.ScheduleEvent(EVENT_SHADE_CHANNEL, Seconds(1)); + + else if (pointId == AKAMA_INTRO_WAYPOINT) + { + me->SetWalk(false); + me->SetFacingTo(0.08726646f); + _events.ScheduleEvent(EVENT_START_SOUL_EXPEL, Seconds(1)); + } + } + + void SummonBrokens() + { + for (uint8 i = 0; i < 18; i++) + { + if (TempSummon* summoned = me->SummonCreature(NPC_ASHTONGUE_BROKEN, BrokenPos[i])) { - switch (eventId) - { - case EVENT_SHADE_START: - instance->SetBossState(DATA_SHADE_OF_AKAMA, IN_PROGRESS); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->RemoveAura(SPELL_STEALTH); - me->SetWalk(true); - me->GetMotionMaster()->MovePoint(0, AkamaWP[0].x, AkamaWP[0].y, AkamaWP[0].z, false); - events.ScheduleEvent(EVENT_SHADE_CHANNEL, 10000); - break; - case EVENT_SHADE_CHANNEL: - me->AddUnitState(UNIT_STATE_ROOT); - me->SetFacingTo(3.118662f); - DoCast(me, SPELL_AKAMA_SOUL_CHANNEL); - me->setFaction(FACTION_COMBAT); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - events.ScheduleEvent(EVENT_FIXATE, 5000); - break; - case EVENT_FIXATE: - DoCast(SPELL_FIXATE); - StartChannel = false; - break; - default: - break; - } + summoned->SetWalk(true); + summoned->GetMotionMaster()->MovePoint(0, BrokenWP[i]); + if (i == 9) //On Sniffs, npc that Yell "Special" is the tenth to be created + _chosen = summoned->GetGUID(); } } + } - if (!UpdateVictim()) - return; - - events.Update(diff); + void UpdateAI(uint32 diff) override + { + _events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { + case EVENT_SHADE_START: + _instance->SetBossState(DATA_SHADE_OF_AKAMA, IN_PROGRESS); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->RemoveAurasDueToSpell(SPELL_STEALTH); + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(AKAMA_CHANNEL_WAYPOINT, AkamaWP[0], false); + break; + case EVENT_SHADE_CHANNEL: + me->SetFacingTo(3.118662f); + DoCastSelf(SPELL_AKAMA_SOUL_CHANNEL); + me->setFaction(FACTION_COMBAT); + _events.ScheduleEvent(EVENT_FIXATE, Seconds(5)); + break; + case EVENT_FIXATE: + DoCast(SPELL_FIXATE); + break; case EVENT_CHAIN_LIGHTNING: DoCastVictim(SPELL_CHAIN_LIGHTNING); - events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(10000, 15000)); + _events.Repeat(randtime(Seconds(8), Seconds(15))); break; case EVENT_DESTRUCTIVE_POISON: - DoCast(me, SPELL_DESTRUCTIVE_POISON); - events.ScheduleEvent(EVENT_DESTRUCTIVE_POISON, urand(4000, 5000)); + DoCastSelf(SPELL_DESTRUCTIVE_POISON); + _events.Repeat(randtime(Seconds(3), Seconds(7))); + break; + case EVENT_START_SOUL_EXPEL: + DoCast(SPELL_AKAMA_SOUL_EXPEL); + _events.ScheduleEvent(EVENT_START_BROKEN_FREE, Seconds(15)); + break; + case EVENT_START_BROKEN_FREE: + me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + Talk(SAY_BROKEN_FREE_0); + SummonBrokens(); + _events.ScheduleEvent(EVENT_BROKEN_FREE_1, Seconds(10)); + break; + case EVENT_BROKEN_FREE_1: + Talk(SAY_BROKEN_FREE_1); + _events.ScheduleEvent(EVENT_BROKEN_FREE_2, Seconds(12)); + break; + case EVENT_BROKEN_FREE_2: + Talk(SAY_BROKEN_FREE_2); + _events.ScheduleEvent(EVENT_BROKEN_FREE_3, Seconds(15)); + break; + case EVENT_BROKEN_FREE_3: + if (Creature* special = ObjectAccessor::GetCreature(*me, _chosen)) + special->AI()->Talk(SAY_BROKEN_SPECIAL); + + _summons.DoAction(ACTION_BROKEN_EMOTE, _pred); + _events.ScheduleEvent(EVENT_BROKEN_FREE_4, Seconds(5)); + break; + case EVENT_BROKEN_FREE_4: + _summons.DoAction(ACTION_BROKEN_HAIL, _pred); break; default: break; } } - DoMeleeAttackIfReady(); + if (me->getFaction() == FACTION_COMBAT) + { + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + } + + void JustDied(Unit* /*killer*/) override + { + _summons.DespawnAll(); + Talk(SAY_DEAD); + if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA))) + if (shade->IsAlive()) + shade->AI()->EnterEvadeMode(EVADE_REASON_OTHER); } void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override @@ -524,19 +551,18 @@ public: if (gossipListId == 0) { player->CLOSE_GOSSIP_MENU(); - StartChannel = true; - events.ScheduleEvent(EVENT_SHADE_START, 500); + _events.ScheduleEvent(EVENT_SHADE_START, Milliseconds(500)); } } private: - InstanceScript* instance; - EventMap events; - bool StartChannel; - bool ShadeHasDied; - bool StartCombat; - bool HasYelledOnce; - + InstanceScript* _instance; + EventMap _events; + SummonList _summons; + DummyEntryCheckPredicate _pred; + ObjectGuid _chosen; //Creature that should yell the speech special. + bool _isInCombat; + bool _hasYelledOnce; }; CreatureAI* GetAI(Creature* creature) const override @@ -545,70 +571,44 @@ public: } }; -// ######################################################## -// Ashtongue Channeler -// ######################################################## - class npc_ashtongue_channeler : public CreatureScript { public: npc_ashtongue_channeler() : CreatureScript("npc_ashtongue_channeler") { } - struct npc_ashtongue_channelerAI : public ScriptedAI + struct npc_ashtongue_channelerAI : public PassiveAI { - npc_ashtongue_channelerAI(Creature* creature) : ScriptedAI(creature) + npc_ashtongue_channelerAI(Creature* creature) : PassiveAI(creature) { - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } void Reset() override { - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + _scheduler.Schedule(Seconds(2), [this](TaskContext channel) + { + if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA))) + { + if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + DoCastSelf(SPELL_SHADE_SOUL_CHANNEL); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - events.ScheduleEvent(EVENT_CHANNEL, 2000); - } + else + me->DespawnOrUnsummon(Seconds(3)); + } - void JustDied(Unit* /*killer*/) override - { - if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA))) - Shade->AI()->DoAction(ACTION_CHANNELER_DIED); + channel.Repeat(Seconds(2)); + }); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } - void EnterCombat(Unit* /*who*/) override { } - void AttackStart(Unit* /*who*/) override { } - void UpdateAI(uint32 diff) override { - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_CHANNEL: - if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA))) - { - if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - DoCast(me, SPELL_SHADE_SOUL_CHANNEL); - else - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - Shade->AI()->DoAction(ACTION_CHANNELER_DIED); - } - } - events.ScheduleEvent(EVENT_CHANNEL, 2000); - break; - default: - break; - } - } + _scheduler.Update(diff); } private: - InstanceScript* instance; - EventMap events; + InstanceScript* _instance; + TaskScheduler _scheduler; }; CreatureAI* GetAI(Creature* creature) const override @@ -617,10 +617,6 @@ public: } }; -// ######################################################## -// Creature Generator Akama -// ######################################################## - class npc_creature_generator_akama : public CreatureScript { public: @@ -628,57 +624,53 @@ public: struct npc_creature_generator_akamaAI : public ScriptedAI { - npc_creature_generator_akamaAI(Creature* creature) : ScriptedAI(creature), Summons(me) + npc_creature_generator_akamaAI(Creature* creature) : ScriptedAI(creature), _summons(me) { Initialize(); - instance = creature->GetInstanceScript(); } void Initialize() { - doSpawning = false; - leftSide = false; + _leftSide = false; + _events.Reset(); + _summons.DespawnAll(); } void Reset() override { - Summons.DespawnAll(); - Initialize(); - if (me->GetPositionY() < 400.0f) - leftSide = true; + if (me->GetPositionY() < MIDDLE_OF_ROOM) + _leftSide = true; } void JustSummoned(Creature* summon) override { - Summons.Summon(summon); + _summons.Summon(summon); } void DoAction(int32 actionId) override { - doSpawning = true; - switch (actionId) { case ACTION_START_SPAWNING: - if (leftSide) + if (_leftSide) { - events.ScheduleEvent(EVENT_SPAWN_WAVE_B, 100); - events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, urand(2000, 5000)); + _events.ScheduleEvent(EVENT_SPAWN_WAVE_B, Milliseconds(100)); + _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, randtime(Seconds(2), Seconds(5))); } else { - events.ScheduleEvent(EVENT_SPAWN_WAVE_B, 10000); - events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, urand(2000, 5000)); + _events.ScheduleEvent(EVENT_SPAWN_WAVE_B, Seconds(10)); + _events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, randtime(Seconds(2), Seconds(5))); } break; case ACTION_STOP_SPAWNING: - doSpawning = false; + _events.Reset(); break; case ACTION_DESPAWN_ALL_SPAWNS: - doSpawning = false; - Summons.DespawnAll(); + _events.Reset(); + _summons.DespawnAll(); break; default: break; @@ -687,39 +679,34 @@ public: void UpdateAI(uint32 diff) override { - if (doSpawning) - { - events.Update(diff); + _events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) { - switch (eventId) - { - case EVENT_SPAWN_WAVE_B: - DoCast(me, SPELL_ASHTONGUE_WAVE_B); - events.ScheduleEvent(EVENT_SPAWN_WAVE_B, urand(45000, 50000)); - break; - case EVENT_SUMMON_ASHTONGUE_SORCERER: // left - DoCast(me, SPELL_SUMMON_ASHTONGUE_SORCERER); - events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, urand(30000, 35000)); - break; - case EVENT_SUMMON_ASHTONGUE_DEFENDER: // right - DoCast(me, SPELL_SUMMON_ASHTONGUE_DEFENDER); - events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, urand(30000, 35000)); - break; - default: - break; - } + case EVENT_SPAWN_WAVE_B: + DoCastSelf(SPELL_ASHTONGUE_WAVE_B); + _events.Repeat(randtime(Seconds(50), Seconds(60))); + break; + case EVENT_SUMMON_ASHTONGUE_SORCERER: // left + DoCastSelf(SPELL_SUMMON_ASHTONGUE_SORCERER); + _events.Repeat(randtime(Seconds(30), Seconds(35))); + break; + case EVENT_SUMMON_ASHTONGUE_DEFENDER: // right + DoCastSelf(SPELL_SUMMON_ASHTONGUE_DEFENDER); + _events.Repeat(randtime(Seconds(30), Seconds(40))); + break; + default: + break; } } } private: - InstanceScript* instance; - EventMap events; - SummonList Summons; - bool leftSide; - bool doSpawning; + EventMap _events; + SummonList _summons; + bool _leftSide; }; CreatureAI* GetAI(Creature* creature) const override @@ -728,10 +715,6 @@ public: } }; -// ######################################################## -// Ashtongue Sorcerer -// ######################################################## - class npc_ashtongue_sorcerer : public CreatureScript { public: @@ -742,103 +725,96 @@ public: npc_ashtongue_sorcererAI(Creature* creature) : ScriptedAI(creature) { Initialize(); - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } void Initialize() { - startedBanishing = false; - switchToCombat = false; + _switchToCombat = false; + _inBanish = false; } void Reset() override { - if (!startedBanishing) + if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA))) { - if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA))) + if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + me->GetMotionMaster()->MovePoint(0, shade->GetPosition()); + + else { - if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - me->GetMotionMaster()->MovePoint(0, Shade->GetPositionX(), Shade->GetPositionY(), Shade->GetPositionZ(), false); - else - { - if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - AttackStart(target); - } + if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE))) + AttackStart(akama); } } - Initialize(); } void JustDied(Unit* /*killer*/) override { - if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA))) - Shade->AI()->DoAction(ACTION_CHANNELER_DIED); - me->DespawnOrUnsummon(5000); + me->DespawnOrUnsummon(Seconds(5)); } + void EnterEvadeMode(EvadeReason /*why*/) override { } void EnterCombat(Unit* /*who*/) override { } void AttackStart(Unit* who) override { - if (!switchToCombat) + if (!_switchToCombat) return; + ScriptedAI::AttackStart(who); } - void UpdateAI(uint32 diff) override + void MoveInLineOfSight(Unit* who) override { - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) + if (!_inBanish && who->GetGUID() == _instance->GetGuidData(DATA_SHADE_OF_AKAMA) && me->IsWithinDist(who, 20.0f, false)) { - switch (eventId) + _inBanish = true; + me->StopMoving(); + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + frand(-8.0f, 8.0f), me->GetPositionY() + frand(-8.0f, 8.0f), me->GetPositionZ()); + + _scheduler.Schedule(Seconds(1) + Milliseconds(500), [this](TaskContext sorcer_channel) { - case EVENT_SORCERER_CHANNEL: - if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA))) + if (Creature* shade = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_SHADE_OF_AKAMA))) + { + if (shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) { - if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - { - me->SetFacingToObject(Shade); - DoCast(me, SPELL_SHADE_SOUL_CHANNEL); - events.ScheduleEvent(EVENT_SORCERER_CHANNEL, 2000); - } - else - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - Shade->AI()->DoAction(ACTION_CHANNELER_DIED); - switchToCombat = true; - if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - AttackStart(target); - } + me->SetFacingToObject(shade); + DoCastSelf(SPELL_SHADE_SOUL_CHANNEL); + sorcer_channel.Repeat(Seconds(2)); } - break; - default: - break; - } + else + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + _switchToCombat = true; + if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE))) + AttackStart(akama); + } + } + }); } + } - if (!startedBanishing) - { - Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA)); - if (me->IsWithinDist(Shade, 20.0f, false)) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MovePoint(1, me->GetPositionX() + frand (-8.0f, 8.0f), me->GetPositionY() + frand (-8.0f, 8.0f), me->GetPositionZ(), false); - events.ScheduleEvent(EVENT_SORCERER_CHANNEL, 1500); - startedBanishing = true; - } - } + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + if (!UpdateVictim()) + return; DoMeleeAttackIfReady(); } private: - InstanceScript* instance; - EventMap events; - bool startedBanishing; - bool switchToCombat; + InstanceScript* _instance; + TaskScheduler _scheduler; + bool _switchToCombat; + bool _inBanish; }; CreatureAI* GetAI(Creature* creature) const override @@ -847,10 +823,6 @@ public: } }; -// ######################################################## -// Ashtongue Defender -// ######################################################## - class npc_ashtongue_defender : public CreatureScript { public: @@ -860,54 +832,55 @@ public: { npc_ashtongue_defenderAI(Creature* creature) : ScriptedAI(creature) { - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } void Reset() override { - if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - AttackStart(target); + if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE))) + AttackStart(akama); } void JustDied(Unit* /*killer*/) override { - me->DespawnOrUnsummon(5000); + me->DespawnOrUnsummon(Seconds(5)); } void EnterCombat(Unit* /*who*/) override { - events.ScheduleEvent(EVENT_HEROIC_STRIKE, 5000); - events.ScheduleEvent(EVENT_SHIELD_BASH, urand(10000, 16000)); - events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, urand(10000, 16000)); - events.ScheduleEvent(EVENT_WINDFURY, urand(8000, 12000)); + _events.ScheduleEvent(EVENT_HEROIC_STRIKE, Seconds(5)); + _events.ScheduleEvent(EVENT_SHIELD_BASH, randtime(Seconds(10), Seconds(16))); + _events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, randtime(Seconds(10), Seconds(16))); + _events.ScheduleEvent(EVENT_WINDFURY, randtime(Seconds(8), Seconds(12))); } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; - events.Update(diff); + _events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_DEBILITATING_STRIKE: DoCastVictim(SPELL_DEBILITATING_STRIKE); - events.ScheduleEvent(EVENT_DEBILITATING_STRIKE, urand(8000, 16000)); + _events.Repeat(randtime(Seconds(20), Seconds(25))); break; case EVENT_HEROIC_STRIKE: - DoCast(me, SPELL_HEROIC_STRIKE); - events.ScheduleEvent(EVENT_HEROIC_STRIKE, urand(50000, 60000)); + DoCastSelf(SPELL_HEROIC_STRIKE); + _events.Repeat(randtime(Seconds(5), Seconds(15))); break; case EVENT_SHIELD_BASH: DoCastVictim(SPELL_SHIELD_BASH); - events.ScheduleEvent(EVENT_SHIELD_BASH, urand(8000, 16000)); + _events.Repeat(randtime(Seconds(10), Seconds(20))); break; case EVENT_WINDFURY: DoCastVictim(SPELL_WINDFURY); - events.ScheduleEvent(EVENT_WINDFURY, urand(6000 , 8000)); + _events.Repeat(randtime(Seconds(6), Seconds(8))); break; default: break; @@ -918,8 +891,8 @@ public: } private: - InstanceScript* instance; - EventMap events; + InstanceScript* _instance; + EventMap _events; }; CreatureAI* GetAI(Creature* creature) const override @@ -928,10 +901,6 @@ public: } }; -// ######################################################## -// Ashtongue Rogue -// ######################################################## - class npc_ashtongue_rogue : public CreatureScript { public: @@ -941,44 +910,46 @@ public: { npc_ashtongue_rogueAI(Creature* creature) : ScriptedAI(creature) { - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } void Reset() override { - if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - AttackStart(target); + if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE))) + AttackStart(akama); } void JustDied(Unit* /*killer*/) override { - me->DespawnOrUnsummon(5000); + me->DespawnOrUnsummon(Seconds(5)); } void EnterCombat(Unit* /*who*/) override { - events.ScheduleEvent(EVENT_DEBILITATING_POISON, urand(500, 2000)); - events.ScheduleEvent(EVENT_EVISCERATE, urand(2000, 5000)); + _events.ScheduleEvent(EVENT_DEBILITATING_POISON, randtime(Milliseconds(500), Seconds(2))); + _events.ScheduleEvent(EVENT_EVISCERATE, randtime(Seconds(2), Seconds(5))); } + void EnterEvadeMode(EvadeReason /*why*/) override { } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; - events.Update(diff); + _events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_DEBILITATING_POISON: DoCastVictim(SPELL_DEBILITATING_POISON); - events.ScheduleEvent(EVENT_DEBILITATING_POISON, urand(14000, 18000)); + _events.Repeat(randtime(Seconds(15), Seconds(20))); break; case EVENT_EVISCERATE: DoCastVictim(SPELL_EVISCERATE); - events.ScheduleEvent(EVENT_EVISCERATE, urand(12000, 16000)); + _events.Repeat(randtime(Seconds(12), Seconds(20))); break; default: break; @@ -989,8 +960,8 @@ public: } private: - InstanceScript* instance; - EventMap events; + InstanceScript* _instance; + EventMap _events; }; CreatureAI* GetAI(Creature* creature) const override @@ -999,10 +970,6 @@ public: } }; -// ######################################################## -// Ashtongue Elementalist -// ######################################################## - class npc_ashtongue_elementalist : public CreatureScript { public: @@ -1012,44 +979,46 @@ public: { npc_ashtongue_elementalistAI(Creature* creature) : ScriptedAI(creature) { - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } void Reset() override { - if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - AttackStart(target); + if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE))) + AttackStart(akama); } void JustDied(Unit* /*killer*/) override { - me->DespawnOrUnsummon(5000); + me->DespawnOrUnsummon(Seconds(5)); } void EnterCombat(Unit* /*who*/) override { - events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 18000); - events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 6000); + _events.ScheduleEvent(EVENT_RAIN_OF_FIRE, Seconds(18)); + _events.ScheduleEvent(EVENT_LIGHTNING_BOLT, Seconds(6)); } + void EnterEvadeMode(EvadeReason /*why*/) override { } + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; - events.Update(diff); + _events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_RAIN_OF_FIRE: DoCastVictim(SPELL_RAIN_OF_FIRE); - events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 20000); + _events.Repeat(randtime(Seconds(15), Seconds(20))); break; case EVENT_LIGHTNING_BOLT: DoCastVictim(SPELL_LIGHTNING_BOLT); - events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 15000); + _events.Repeat(randtime(Seconds(8), Seconds(15))); break; default: break; @@ -1060,8 +1029,8 @@ public: } private: - InstanceScript* instance; - EventMap events; + InstanceScript* _instance; + EventMap _events; }; CreatureAI* GetAI(Creature* creature) const override @@ -1070,10 +1039,6 @@ public: } }; -// ######################################################## -// Ashtongue Spiritbinder -// ######################################################## - class npc_ashtongue_spiritbinder : public CreatureScript { public: @@ -1084,44 +1049,72 @@ public: npc_ashtongue_spiritbinderAI(Creature* creature) : ScriptedAI(creature) { Initialize(); - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } void Initialize() { - spiritMend = false; - chainHeal = false; + _spiritMend = false; + _chainHeal = false; } void Reset() override { Initialize(); - if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE))) - AttackStart(target); + if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE))) + AttackStart(akama); } void JustDied(Unit* /*killer*/) override { - me->DespawnOrUnsummon(5000); + me->DespawnOrUnsummon(Seconds(5)); } void EnterCombat(Unit* /*who*/) override { - events.ScheduleEvent(EVENT_SPIRIT_HEAL, urand (5000, 6000)); + _events.ScheduleEvent(EVENT_SPIRIT_HEAL, randtime(Seconds(5), Seconds(6))); } + void DamageTaken(Unit* /*who*/, uint32& /*damage*/) override + { + if (!_spiritMend) + if (HealthBelowPct(30)) + { + DoCastSelf(SPELL_SPIRIT_MEND); + _spiritMend = true; + _events.ScheduleEvent(EVENT_SPIRIT_MEND_RESET, randtime(Seconds(10),Seconds(15))); + } + + if (!_chainHeal) + if (HealthBelowPct(50)) + { + DoCastSelf(SPELL_CHAIN_HEAL); + _chainHeal = true; + _events.ScheduleEvent(EVENT_CHAIN_HEAL_RESET, randtime(Seconds(10), Seconds(15))); + } + + } + + void EnterEvadeMode(EvadeReason /*why*/) override { } + void UpdateAI(uint32 diff) override { - events.Update(diff); + _events.Update(diff); - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = _events.ExecuteEvent()) { switch (eventId) { case EVENT_SPIRIT_HEAL: - DoCast(me, SPELL_SPIRITBINDER_SPIRIT_HEAL); - events.ScheduleEvent(EVENT_SPIRIT_HEAL, urand (13000, 16000)); + DoCastSelf(SPELL_SPIRITBINDER_SPIRIT_HEAL); + _events.Repeat(randtime(Seconds(13), Seconds(16))); + break; + case EVENT_SPIRIT_MEND_RESET: + _spiritMend = false; + break; + case EVENT_CHAIN_HEAL_RESET: + _chainHeal = false; break; default: break; @@ -1131,32 +1124,14 @@ public: if (!UpdateVictim()) return; - if (!spiritMend) - { - if (HealthBelowPct(25)) - { - DoCast(me, SPELL_SPIRIT_MEND); - spiritMend = true; - } - } - - if (!chainHeal) - { - if (HealthBelowPct(40)) - { - DoCast(me, SPELL_CHAIN_HEAL); - chainHeal = true; - } - } - DoMeleeAttackIfReady(); } private: - InstanceScript* instance; - EventMap events; - bool spiritMend; - bool chainHeal; + InstanceScript* _instance; + EventMap _events; + bool _spiritMend; + bool _chainHeal; }; CreatureAI* GetAI(Creature* creature) const override @@ -1165,6 +1140,119 @@ public: } }; +class npc_ashtongue_broken : public CreatureScript +{ +public: + npc_ashtongue_broken() : CreatureScript("npc_ashtongue_broken") { } + + struct npc_ashtongue_brokenAI : public ScriptedAI + { + npc_ashtongue_brokenAI(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + } + + void MovementInform(uint32 motionType, uint32 /*pointId*/) override + { + if (motionType != POINT_MOTION_TYPE) + return; + + if (Creature* akama = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AKAMA_SHADE))) + me->SetFacingToObject(akama); + } + + void DoAction(int32 actionId) override + { + switch (actionId) + { + case ACTION_BROKEN_SPECIAL: + Talk(SAY_BROKEN_SPECIAL); + break; + case ACTION_BROKEN_HAIL: + me->setFaction(FACTION_FRIENDLY); + Talk(SAY_BROKEN_HAIL); + break; + case ACTION_BROKEN_EMOTE: + me->SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_STAND_STATE, UNIT_STAND_STATE_KNEEL); + break; + default: + break; + } + } + + private: + InstanceScript* _instance; + }; + + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_ashtongue_brokenAI>(creature); + } +}; + +class spell_shade_soul_channel_serverside : public SpellScriptLoader +{ +public: + spell_shade_soul_channel_serverside() : SpellScriptLoader("spell_shade_soul_channel_serverside") { } + + class spell_shade_soul_channel_serverside_AuraScript : public AuraScript + { + PrepareAuraScript(spell_shade_soul_channel_serverside_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHADE_SOUL_CHANNEL_2)) + return false; + return true; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_shade_soul_channel_serverside_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_shade_soul_channel_serverside_AuraScript(); + } +}; + +class spell_shade_soul_channel : public SpellScriptLoader +{ +public: + spell_shade_soul_channel() : SpellScriptLoader("spell_shade_soul_channel") { } + + class spell_shade_soul_channel_AuraScript : public AuraScript + { + PrepareAuraScript(spell_shade_soul_channel_AuraScript); + + void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + int32 const maxSlowEff = -99; + if (aurEff->GetAmount() < maxSlowEff) + if (AuraEffect* slowEff = GetEffect(EFFECT_0)) + slowEff->ChangeAmount(maxSlowEff); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_shade_soul_channel_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DECREASE_SPEED, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_shade_soul_channel_AuraScript(); + } +}; + void AddSC_boss_shade_of_akama() { new boss_shade_of_akama(); @@ -1176,4 +1264,7 @@ void AddSC_boss_shade_of_akama() new npc_ashtongue_rogue(); new npc_ashtongue_elementalist(); new npc_ashtongue_spiritbinder(); + new npc_ashtongue_broken(); + new spell_shade_soul_channel_serverside(); + new spell_shade_soul_channel(); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp index ae4d17bdad4..0999f1fcd6b 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp @@ -117,7 +117,7 @@ public: DummyEntryCheckPredicate pred; summons.DoAction(EVENT_VOLCANO, pred); events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); - me->SetSpeed(MOVE_RUN, 1.2f); + me->SetSpeedRate(MOVE_RUN, 1.2f); me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); } @@ -126,7 +126,7 @@ public: phase = PHASE_CHASE; events.ScheduleEvent(EVENT_VOLCANO, 5000, GCD_CAST, PHASE_CHASE); events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); - me->SetSpeed(MOVE_RUN, 0.9f); + me->SetSpeedRate(MOVE_RUN, 0.9f); me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp index 72eb99bd7dc..56d333b2dda 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp @@ -91,7 +91,7 @@ public: void Despawn() { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); me->RemoveCorpse(); } @@ -218,7 +218,7 @@ public: { Creature* Teron = (ObjectAccessor::GetCreature((*me), TeronGUID)); if (!Teron || !Teron->IsAlive() || Teron->IsInEvadeMode()) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); CheckTeronTimer = 5000; } else CheckTeronTimer -= diff; @@ -236,9 +236,9 @@ public: return GetInstanceAI<boss_teron_gorefiendAI>(creature); } - struct boss_teron_gorefiendAI : public ScriptedAI + struct boss_teron_gorefiendAI : public BossAI { - boss_teron_gorefiendAI(Creature* creature) : ScriptedAI(creature) + boss_teron_gorefiendAI(Creature* creature) : BossAI(creature, DATA_TERON_GOREFIEND) { Initialize(); instance = creature->GetInstanceScript(); @@ -277,8 +277,7 @@ public: void Reset() override { - instance->SetBossState(DATA_TERON_GOREFIEND, NOT_STARTED); - + _Reset(); Initialize(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); @@ -316,9 +315,8 @@ public: void JustDied(Unit* /*killer*/) override { - instance->SetBossState(DATA_TERON_GOREFIEND, DONE); - Talk(SAY_DEATH); + _JustDied(); } float CalculateRandomLocation(float Loc, uint32 radius) @@ -363,7 +361,7 @@ public: /** WHAT IS FULLY NECESSARY FOR GOREFIEND TO BE 100% COMPLETE *****/ /************************************************************************/ - Unit* ghost = NULL; + Unit* ghost = nullptr; if (GhostGUID) ghost = ObjectAccessor::GetUnit(*me, GhostGUID); if (ghost && ghost->IsAlive() && ghost->HasAura(SPELL_SHADOW_OF_DEATH)) @@ -379,7 +377,7 @@ public: }*/ for (uint8 i = 0; i < 4; ++i) { - Creature* Construct = NULL; + Creature* Construct = nullptr; float X = CalculateRandomLocation(ghost->GetPositionX(), 10); float Y = CalculateRandomLocation(ghost->GetPositionY(), 10); Construct = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, Y, ghost->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000); @@ -435,17 +433,13 @@ public: for (uint8 i = 0; i < 2; ++i) { - Creature* Shadow = NULL; float X = CalculateRandomLocation(me->GetPositionX(), 10); - Shadow = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 0); - if (Shadow) + if (Creature* shadow = me->SummonCreature(CREATURE_SHADOWY_CONSTRUCT, X, me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 0)) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); - if (!target) - target = me->GetVictim(); - - if (target) - Shadow->AI()->AttackStart(target); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) + shadow->AI()->AttackStart(target); + else if (Unit* victim = me->GetVictim()) + shadow->AI()->AttackStart(victim); } } SummonShadowsTimer = 60000; diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp index 9b33ea88ca7..b9627856ae6 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp @@ -150,7 +150,7 @@ public: DoCast(target, SPELL_IMPALING_SPINE, true); SpineTargetGUID = target->GetGUID(); //must let target summon, otherwise you cannot click the spine - target->SummonGameObject(GO_NAJENTUS_SPINE, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 30); + target->SummonGameObject(GO_NAJENTUS_SPINE, *target, G3D::Quat(), 30); Talk(SAY_NEEDLE); events.DelayEvents(1500, GCD_CAST); events.DelayEvents(15000, GCD_YELL); diff --git a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp index d883a48b630..06b492e32d7 100644 --- a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp +++ b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp @@ -90,8 +90,6 @@ enum IllidariCouncil SPELL_BERSERK = 45078 }; -#define ERROR_INST_DATA "SD2 ERROR: Instance Data for Black Temple not set properly; Illidari Council event will not function properly." - struct CouncilYells { int32 entry; @@ -165,7 +163,7 @@ public: Council[1] = instance->GetGuidData(DATA_VERAS_DARKSHADOW); Council[2] = instance->GetGuidData(DATA_LADY_MALANDE); Council[3] = instance->GetGuidData(DATA_HIGH_NETHERMANCER_ZEREVOR); - } else TC_LOG_ERROR("scripts", ERROR_INST_DATA); + } } void EnterCombat(Unit* /*who*/) override { } @@ -231,6 +229,7 @@ public: { Initialize(); instance = creature->GetInstanceScript(); + SetBoundary(instance->GetBossBoundary(DATA_ILLIDARI_COUNCIL)); } void Initialize() @@ -257,7 +256,7 @@ public: { Initialize(); - Creature* pMember = NULL; + Creature* pMember = nullptr; for (uint8 i = 0; i < 4; ++i) { pMember = ObjectAccessor::GetCreature((*me), Council[i]); @@ -330,16 +329,16 @@ public: if (DeathCount > 3) { if (Creature* VoiceTrigger = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BLOOD_ELF_COUNCIL_VOICE))) - VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); instance->SetBossState(DATA_ILLIDARI_COUNCIL, DONE); //me->SummonCreature(AKAMAID, 746.466980f, 304.394989f, 311.90208f, 6.272870f, TEMPSUMMON_DEAD_DESPAWN, 0); - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); return; } Creature* pMember = (ObjectAccessor::GetCreature(*me, Council[DeathCount])); if (pMember && pMember->IsAlive()) - pMember->DealDamage(pMember, pMember->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + pMember->DealDamage(pMember, pMember->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); ++DeathCount; EndEventTimer = 1500; } else EndEventTimer -= diff; @@ -922,7 +921,7 @@ public: if (dmgInfo.GetAttacker() == target) return; int32 bp = absorbAmount / 2; - target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_REFLECTIVE_SHIELD_T, &bp, NULL, NULL, true, NULL, aurEff); + target->CastCustomSpell(dmgInfo.GetAttacker(), SPELL_REFLECTIVE_SHIELD_T, &bp, nullptr, nullptr, true, nullptr, aurEff); } void Register() override diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp index 86ad7958957..bac996918ac 100644 --- a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp +++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp @@ -35,6 +35,20 @@ DoorData const doorData[] = { 0, 0, DOOR_TYPE_ROOM } // END }; +BossBoundaryData const boundaries = +{ + { DATA_HIGH_WARLORD_NAJENTUS, new RectangleBoundary(394.0f, 479.4f, 707.8f, 859.1f) }, + { DATA_SUPREMUS, new RectangleBoundary(556.1f, 850.2f, 542.0f, 1001.0f) }, + { DATA_SHADE_OF_AKAMA, new RectangleBoundary(406.8f, 564.0f, 327.9f, 473.5f) }, + { DATA_TERON_GOREFIEND, new RectangleBoundary(512.5f, 613.3f, 373.2f, 432.0f) }, + { DATA_TERON_GOREFIEND, new ZRangeBoundary(179.5f, 223.6f) }, + { DATA_GURTOGG_BLOODBOIL, new RectangleBoundary(720.5f, 864.5f, 159.3f, 316.0f) }, + { DATA_RELIQUARY_OF_SOULS, new RectangleBoundary(435.9f, 558.8f, 113.3f, 229.6f) }, + { DATA_MOTHER_SHAHRAZ, new RectangleBoundary(903.4f, 982.1f, 92.4f, 476.7f) }, + { DATA_ILLIDARI_COUNCIL, new EllipseBoundary(Position(696.6f, 305.0f), 70.0 , 85.0) }, + { DATA_ILLIDAN_STORMRAGE, new EllipseBoundary(Position(694.8f, 309.0f), 70.0 , 85.0) } +}; + class instance_black_temple : public InstanceMapScript { public: @@ -47,6 +61,7 @@ class instance_black_temple : public InstanceMapScript SetHeaders(DataHeader); SetBossNumber(EncounterCount); LoadDoorData(doorData); + LoadBossBoundaries(boundaries); } void OnCreatureCreate(Creature* creature) override diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt deleted file mode 100644 index 55b0452fb0b..00000000000 --- a/src/server/scripts/Outland/CMakeLists.txt +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - Outland/zone_nagrand.cpp - Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h - Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp - Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp - Outland/HellfireCitadel/HellfireRamparts/instance_hellfire_ramparts.cpp - Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp - Outland/HellfireCitadel/HellfireRamparts/boss_watchkeeper_gargolmar.cpp - Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp - Outland/HellfireCitadel/HellfireRamparts/hellfire_ramparts.h - Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp - Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp - Outland/HellfireCitadel/BloodFurnace/blood_furnace.h - Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp - Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp - Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h - Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp - Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp - Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp - Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp - Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp - Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp - Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp - Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp - Outland/CoilfangReservoir/SteamVault/boss_warlord_kalithresh.cpp - Outland/CoilfangReservoir/SteamVault/steam_vault.h - Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp - Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp - Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp - Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h - Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp - Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp - Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp - Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp - Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp - Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h - Outland/CoilfangReservoir/TheSlavePens/boss_mennu_the_betrayer.cpp - Outland/CoilfangReservoir/TheSlavePens/boss_rokmar_the_crackler.cpp - Outland/CoilfangReservoir/TheSlavePens/boss_quagmirran.cpp - Outland/CoilfangReservoir/TheUnderbog/instance_the_underbog.cpp - Outland/CoilfangReservoir/TheUnderbog/boss_hungarfen.cpp - Outland/CoilfangReservoir/TheUnderbog/boss_the_black_stalker.cpp - Outland/zone_shattrath_city.cpp - Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp - Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp - Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp - Outland/TempestKeep/Mechanar/mechanar.h - Outland/TempestKeep/Mechanar/boss_gatewatcher_gyrokill.cpp - Outland/TempestKeep/Mechanar/instance_mechanar.cpp - Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp - Outland/TempestKeep/Eye/the_eye.h - Outland/TempestKeep/Eye/instance_the_eye.cpp - Outland/TempestKeep/Eye/boss_void_reaver.cpp - Outland/TempestKeep/Eye/boss_astromancer.cpp - Outland/TempestKeep/Eye/boss_alar.cpp - Outland/TempestKeep/Eye/boss_kaelthas.cpp - Outland/TempestKeep/Eye/the_eye.cpp - Outland/TempestKeep/botanica/the_botanica.h - Outland/TempestKeep/botanica/instance_the_botanica.cpp - Outland/TempestKeep/botanica/boss_commander_sarannis.cpp - Outland/TempestKeep/botanica/boss_thorngrin_the_tender.cpp - Outland/TempestKeep/botanica/boss_high_botanist_freywinn.cpp - Outland/TempestKeep/botanica/boss_warp_splinter.cpp - Outland/TempestKeep/botanica/boss_laj.cpp - Outland/TempestKeep/arcatraz/boss_zereketh_the_unbound.cpp - Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp - Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp - Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp - Outland/TempestKeep/arcatraz/instance_arcatraz.cpp - Outland/TempestKeep/arcatraz/arcatraz.h - Outland/TempestKeep/arcatraz/arcatraz.cpp - Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp - Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp - Outland/Auchindoun/AuchenaiCrypts/instance_auchenai_crypts.cpp - Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h - Outland/Auchindoun/ManaTombs/boss_pandemonius.cpp - Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp - Outland/Auchindoun/ManaTombs/instance_mana_tombs.cpp - Outland/Auchindoun/ManaTombs/mana_tombs.h - Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp - Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp - Outland/Auchindoun/SethekkHalls/boss_anzu.cpp - Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp - Outland/Auchindoun/SethekkHalls/sethekk_halls.h - Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp - Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp - Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp - Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp - Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp - Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h - Outland/boss_doomwalker.cpp - Outland/zone_terokkar_forest.cpp - Outland/zone_hellfire_peninsula.cpp - Outland/boss_doomlord_kazzak.cpp - Outland/BlackTemple/boss_teron_gorefiend.cpp - Outland/BlackTemple/black_temple.h - Outland/BlackTemple/illidari_council.cpp - Outland/BlackTemple/boss_shade_of_akama.cpp - Outland/BlackTemple/boss_supremus.cpp - Outland/BlackTemple/black_temple.cpp - Outland/BlackTemple/boss_mother_shahraz.cpp - Outland/BlackTemple/instance_black_temple.cpp - Outland/BlackTemple/boss_reliquary_of_souls.cpp - Outland/BlackTemple/boss_warlord_najentus.cpp - Outland/BlackTemple/boss_gurtogg_bloodboil.cpp - Outland/BlackTemple/boss_illidan.cpp - Outland/zone_shadowmoon_valley.cpp - Outland/zone_blades_edge_mountains.cpp - Outland/GruulsLair/boss_high_king_maulgar.cpp - Outland/GruulsLair/boss_gruul.cpp - Outland/GruulsLair/gruuls_lair.h - Outland/GruulsLair/instance_gruuls_lair.cpp - Outland/zone_netherstorm.cpp - Outland/zone_zangarmarsh.cpp -) - -message(" -> Prepared: Outland") diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp index e24499c3aee..3ddf0fec416 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -585,8 +585,8 @@ public: void Reset() override { - me->SetSpeed(MOVE_WALK, 0.6f); // walk - me->SetSpeed(MOVE_RUN, 0.6f); // run + me->SetSpeedRate(MOVE_WALK, 0.6f); // walk + me->SetSpeedRate(MOVE_RUN, 0.6f); // run Initialize(); //search for nearest waypoint (up on stairs) diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp index 8d117f7c3ef..f72b9a8d2ca 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -244,7 +244,7 @@ public: CheckChannelers(); Initialize(); me->SetCanDualWield(true); - me->SetSpeed(MOVE_RUN, 2.0f, true); + me->SetSpeedRate(MOVE_RUN, 2.0f); me->SetDisplayId(MODEL_NIGHTELF); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp new file mode 100644 index 00000000000..62552a3bf61 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp @@ -0,0 +1,1046 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CreatureTextMgr.h" +#include "LFGMgr.h" +#include "ScriptedGossip.h" +#include "ScriptedCreature.h" +#include "ScriptMgr.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" +#include "the_slave_pens.h" + +enum Spells +{ + // Ahune + SPELL_SYNCH_HEALTH = 46430, + SPELL_AHUNES_SHIELD = 45954, + SPELL_STAY_SUBMERGED = 46981, + SPELL_AHUNE_SELF_STUN = 46416, + SPELL_AHUNE_ACHIEVEMENT = 62043, + SPELL_AHUNE_SPANKY_HANDS = 46146, + SPELL_COLD_SLAP = 46145, + SPELL_RESURFACE = 46402, + SPELL_SUBMERGED = 37751, + SPELL_STAND = 37752, + + //Earther Ring Flamecaller + SPELL_FIND_OPENING_VISUAL = 45964, + SPELL_FIND_OPENING_BEAM_END = 46333, + SPELL_FIND_OPENING_TRIGGER = 46341, + SPELL_FIND_OPENING_CHANNEL = 46345, + SPELL_BONFIRE_VISUAL = 46339, + SPELL_FOUND_OPENING = 46421, + + //Ahune Bunny + SPELL_SUMMON_COLDWEAVE = 46143, + SPELL_SUMMON_FROSTWIND = 46382, + SPELL_SUMMON_HAILSTONE = 46176, + SPELL_SUMMONING_VISUAL_1 = 45937, + SPELL_SUMMONING_RHYME_AURA = 45926, + SPELL_SUMMONING_RHYME_BONFIRE = 45930, + SPELL_FORCE_WHISP_FLIGHT = 46603, + SPELL_SHAMANS_LOOK_FOR_OPENING = 46422, + SPELL_CLOSE_OPENING_VISUAL = 46236, + SPELL_ICE_BOMBARD = 46397, + SPELL_ICE_BOMBARDMENT_DEST_PICKER = 46398, + SPELL_ICE_BOMBARDMENT = 46396, + + // Ice Spear + SPELL_SUMMON_ICE_SPEAR_BUNNY = 46359, + SPELL_ICE_SPEAR_KNOCKBACK = 46360, + SPELL_SUMMON_ICE_SPEAR_GO = 46369, + SPELL_ICE_SPEAR_AURA = 46371, + SPELL_ICE_SPEAR_TARGET_PICKER = 46372, + SPELL_ICE_SPEAR_DELAY = 46878, + SPELL_ICE_SPEAR_VISUAL = 75498, + + // Slippery Floor + SPELL_SLIPPERY_FLOOR_AMBIENT = 46314, + SPELL_SLIPPERY_FLOOR_PERIODIC = 46320, + SPELL_SLIPPERY_FLOOR_SLIP = 45947, + SPELL_SLIPPERY_FLOOR_YOU_SLIPPED = 45946, + + // Frozen Core + SPELL_SUICIDE = 45254, + SPELL_SUMMON_LOOT_MISSILE = 45941, + SPELL_FROZEN_CORE_GETS_HIT = 46810, + SPELL_MINION_DESPAWNER = 46843, + SPELL_GHOST_DISGUISE = 46786 +}; + +enum Emotes +{ + EMOTE_EARTHEN_ASSAULT = 0, + EMOTE_RETREAT = 0, + EMOTE_RESURFACE = 1 +}; + +enum Says +{ + SAY_PLAYER_TEXT_1 = 0, + SAY_PLAYER_TEXT_2 = 1, + SAY_PLAYER_TEXT_3 = 2 +}; + +enum Events +{ + EVENT_EMERGE = 1, + EVENT_INITIAL_EMERGE = 2, + EVENT_SYNCH_HEALTH = 3, + EVENT_LOOKFOROPENING_0 = 4, + EVENT_LOOKFOROPENING_1 = 5, + EVENT_LOOKFOROPENING_2 = 6, + EVENT_SUMMON_HAILSTONE = 7, + EVENT_SUMMON_COLDWEAVE = 8, + EVENT_SUMMON_FROSTWIND = 9, + EVENT_SUMMON_AHUNE = 10, + EVENT_CLOSE_OPENING = 11, + EVENT_AHUNE_PHASE_ONE = 12, + EVENT_AHUNE_PHASE_TWO = 13, + EVENT_START_LOOKING_FOR_OPENING = 14, + EVENT_STOP_LOOKING_FOR_OPENING = 15 +}; + +enum Actions +{ + ACTION_START_EVENT = -2574500, + ACTION_AHUNE_RETREAT = -2586500, + ACTION_AHUNE_RESURFACE = -2586501, + ACTION_EMOTE_RESURFACE = -2575400 +}; + +enum Phases +{ + PHASE_ONE = 0, + PHASE_TWO = 1 +}; + +enum Points +{ + POINT_FLAMECALLER_000, + POINT_FLAMECALLER_001, + POINT_FLAMECALLER_002 +}; + +enum Misc +{ + MAX_FLAMECALLERS = 3 +}; + +Position const SummonPositions[] = +{ + { -99.1021f, -233.7526f, -1.22307f, 1.588250f }, // Ahune + { -98.0151f, -230.4555f, -1.21089f, 1.797689f }, // Frozen Core + { -143.172f, -147.6801f, -3.16113f, 4.852015f }, // Bonfire Bunny 000 + { -134.304f, -145.7803f, -1.70332f, 4.677482f }, // Bonfire Bunny 001 + { -125.036f, -144.2065f, -1.91660f, 4.991642f }, // Bonfire Bunny 002 + { -69.8121f, -162.4954f, -2.30451f, 1.710423f }, // Wisp Source Bunny + { -98.1029f, -230.7864f, -10.8085f, 1.448623f } // Wisp Dest Bunny +}; + +Position const FlameCallerSpots[] = +{ + { -145.2233f, -137.5543f, -1.59056f, 5.427049f }, + { -137.4383f, -136.4050f, -1.72384f, 5.336747f }, + { -129.0413f, -132.1494f, -2.09285f, 5.460842f } +}; + +class boss_ahune : public CreatureScript +{ +public: + boss_ahune() : CreatureScript("boss_ahune") { } + + struct boss_ahuneAI : public BossAI + { + boss_ahuneAI(Creature* creature) : BossAI(creature, DATA_AHUNE) + { + me->SetControlled(true, UNIT_STATE_ROOT); + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + events.ScheduleEvent(EVENT_INITIAL_EMERGE, Milliseconds(4)); + events.ScheduleEvent(EVENT_SYNCH_HEALTH, Seconds(3)); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AHUNE_BUNNY))) + ahuneBunny->AI()->EnterEvadeMode(); + summons.DespawnAll(); + me->DespawnOrUnsummon(); + } + + void JustDied(Unit* /*killer*/) override + { + instance->DoCastSpellOnPlayers(SPELL_AHUNE_ACHIEVEMENT); + + if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AHUNE_BUNNY))) + me->Kill(ahuneBunny); + if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) + me->Kill(frozenCore); + + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (!players.isEmpty()) + { + if (Group* group = players.begin()->GetSource()->GetGroup()) + if (group->isLFGGroup()) + sLFGMgr->FinishDungeon(group->GetGUID(), 286); + } + + _JustDied(); + } + + void DoAction(int32 action) override + { + if (action == ACTION_AHUNE_RETREAT) + { + Submerge(); + events.ScheduleEvent(EVENT_EMERGE, Seconds(35)); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_INITIAL_EMERGE: + DoCast(me, SPELL_STAND); + DoCast(me, SPELL_AHUNE_SPANKY_HANDS); + DoCast(me, SPELL_AHUNES_SHIELD); + break; + case EVENT_EMERGE: + Emerge(); + break; + case EVENT_SYNCH_HEALTH: + if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) + DoCast(frozenCore, SPELL_SYNCH_HEALTH, true); + else + DoCast(me, SPELL_SUICIDE); + events.Repeat(Seconds(3)); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + void Emerge() + { + if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) + frozenCore->AI()->DoAction(ACTION_AHUNE_RESURFACE); + + DoCast(me, SPELL_AHUNES_SHIELD); + me->RemoveAurasDueToSpell(SPELL_AHUNE_SELF_STUN); + me->RemoveAurasDueToSpell(SPELL_STAY_SUBMERGED); + DoCast(me, SPELL_STAND); + DoCast(me, SPELL_RESURFACE, true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + events.ScheduleEvent(EVENT_SYNCH_HEALTH, Seconds(3)); + } + + void Submerge() + { + if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) + frozenCore->AI()->DoAction(ACTION_AHUNE_RETREAT); + me->RemoveAurasDueToSpell(SPELL_AHUNES_SHIELD); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_31); + DoCast(me, SPELL_SUBMERGED, true); + DoCast(me, SPELL_AHUNE_SELF_STUN, true); + DoCast(me, SPELL_STAY_SUBMERGED, true); + me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + events.Reset(); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_ahuneAI>(creature); + } +}; + +class npc_frozen_core : public CreatureScript +{ +public: + npc_frozen_core() : CreatureScript("npc_frozen_core") { } + + struct npc_frozen_coreAI : public ScriptedAI + { + npc_frozen_coreAI(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + Initialize(); + } + + void Initialize() + { + me->SetReactState(REACT_PASSIVE); + me->setRegeneratingHealth(false); + DoCast(me, SPELL_FROZEN_CORE_GETS_HIT); + DoCast(me, SPELL_ICE_SPEAR_AURA); + } + + void JustDied(Unit* /*killer*/) override + { + if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE))) + me->Kill(ahune); + + DoCast(SPELL_SUMMON_LOOT_MISSILE); + DoCast(SPELL_MINION_DESPAWNER); + } + + void DoAction(int32 action) override + { + if (action == ACTION_AHUNE_RETREAT) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); + me->RemoveAurasDueToSpell(SPELL_ICE_SPEAR_AURA); + _events.ScheduleEvent(EVENT_SYNCH_HEALTH, Seconds(3), 0, PHASE_TWO); + } + else if (action == ACTION_AHUNE_RESURFACE) + { + _events.Reset(); + DoCast(me, SPELL_ICE_SPEAR_AURA); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SYNCH_HEALTH: + if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE))) + DoCast(ahune, SPELL_SYNCH_HEALTH, true); + else + DoCast(me, SPELL_SUICIDE); + _events.Repeat(Seconds(3)); + break; + default: + break; + } + } + } + + private: + InstanceScript* _instance; + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_frozen_coreAI>(creature); + } +}; + +class npc_ahune_bunny : public CreatureScript +{ +public: + npc_ahune_bunny() : CreatureScript("npc_ahune_bunny") { } + + struct npc_ahune_bunnyAI : public ScriptedAI + { + npc_ahune_bunnyAI(Creature* creature) : ScriptedAI(creature), _summons(me) + { + _instance = me->GetInstanceScript(); + _submerged = false; + } + + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_AHUNE) + return; + + summon->SetInCombatWithZone(); + _summons.Summon(summon); + } + + void JustDied(Unit* /*killer*/) override + { + _summons.DespawnAll(); + ResetFlameCallers(); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + _summons.DespawnAll(); + ResetFlameCallers(); + + me->SummonGameObject(GO_ICE_STONE, -69.90455f, -162.2449f, -2.366563f, 2.426008f, G3D::Quat(0.0f, 0.0f, 0.9366722f, 0.3502074f), 0); + } + + void DoAction(int32 action) override + { + if (action == ACTION_START_EVENT) + { + DoCast(me, SPELL_SUMMONING_VISUAL_1); + me->SummonCreature(NPC_WHISP_SOURCE_BUNNY, SummonPositions[5], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_WHISP_DEST_BUNNY, SummonPositions[6], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_000, SummonPositions[2], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_001, SummonPositions[3], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_002, SummonPositions[4], TEMPSUMMON_MANUAL_DESPAWN); + + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flameCaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + flameCaller->GetMotionMaster()->MovePoint(counter, FlameCallerSpots[counter].GetPosition()); + + _submerged = false; + _events.Reset(); + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_AHUNE, Seconds(10)); + _events.ScheduleEvent(EVENT_START_LOOKING_FOR_OPENING, Seconds(14), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, Seconds(22), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_HAILSTONE, Seconds(14), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_TWO, Seconds(108), 0, PHASE_ONE); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_START_LOOKING_FOR_OPENING: + Talk(EMOTE_EARTHEN_ASSAULT); + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + DoCast(flamecaller, SPELL_SHAMANS_LOOK_FOR_OPENING, true); + break; + case EVENT_SUMMON_HAILSTONE: + DoCast(SPELL_SUMMON_HAILSTONE); + break; + case EVENT_SUMMON_COLDWEAVE: + DoCast(SPELL_SUMMON_COLDWEAVE); + DoCast(SPELL_SUMMON_COLDWEAVE); + _events.Repeat(Seconds(8)); + if (_submerged) + _events.ScheduleEvent(EVENT_SUMMON_FROSTWIND, Seconds(4), 0, PHASE_ONE); + break; + case EVENT_SUMMON_FROSTWIND: + DoCast(SPELL_SUMMON_FROSTWIND); + break; + case EVENT_SUMMON_AHUNE: + if (TempSummon* ahune = me->SummonCreature(NPC_AHUNE, SummonPositions[0], TEMPSUMMON_DEAD_DESPAWN)) + { + ahune->SummonCreature(NPC_FROZEN_CORE, SummonPositions[1], TEMPSUMMON_CORPSE_DESPAWN); + ahune->SetInCombatWithZone(); + DoCast(ahune, SPELL_RESURFACE); + } + break; + case EVENT_CLOSE_OPENING: + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000))) + flamecaller->AI()->DoAction(ACTION_EMOTE_RESURFACE); + DoCast(SPELL_CLOSE_OPENING_VISUAL); + DoCast(me, SPELL_ICE_BOMBARD); + break; + case EVENT_AHUNE_PHASE_TWO: + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000))) + DoCast(flamecaller, SPELL_FOUND_OPENING); + if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE))) + ahune->AI()->DoAction(ACTION_AHUNE_RETREAT); + _events.Reset(); + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_CLOSE_OPENING, Seconds(25), 0, PHASE_TWO); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_ONE, Seconds(35), 0, PHASE_TWO); + break; + case EVENT_AHUNE_PHASE_ONE: + _submerged = true; + _events.Reset(); + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, Seconds(8), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_HAILSTONE, Seconds(5), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_START_LOOKING_FOR_OPENING, Seconds(5), 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_TWO, Seconds(100), 0, PHASE_ONE); + break; + default: + break; + } + } + } + + void ResetFlameCallers() + { + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + flamecaller->AI()->EnterEvadeMode(); + } + + private: + InstanceScript* _instance; + EventMap _events; + SummonList _summons; + bool _submerged; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_ahune_bunnyAI>(creature); + } +}; + +class npc_earthen_ring_flamecaller : public CreatureScript +{ +public: + npc_earthen_ring_flamecaller() : CreatureScript("npc_earthen_ring_flamecaller") { } + + struct npc_earthen_ring_flamecallerAI : public ScriptedAI + { + npc_earthen_ring_flamecallerAI(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + _mySpot = 0; + } + + void Reset() override + { + _events.Reset(); + } + + void MovementInform(uint32 motionType, uint32 pointId) override + { + if (motionType != POINT_MOTION_TYPE) + return; + + switch (pointId) + { + case POINT_FLAMECALLER_000: + _mySpot = POINT_FLAMECALLER_000; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + case POINT_FLAMECALLER_001: + _mySpot = POINT_FLAMECALLER_001; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + case POINT_FLAMECALLER_002: + _mySpot = POINT_FLAMECALLER_002; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + default: + break; + } + + DoCast(me, SPELL_FIND_OPENING_CHANNEL); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override + { + switch (spellInfo->Id) + { + case SPELL_SHAMANS_LOOK_FOR_OPENING: + _events.ScheduleEvent(EVENT_LOOKFOROPENING_0, Seconds(17)); + break; + case SPELL_FOUND_OPENING: + Talk(EMOTE_RETREAT); + break; + default: + break; + } + } + + void DoAction(int action) override + { + if (action == ACTION_EMOTE_RESURFACE) + Talk(EMOTE_RESURFACE); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_LOOKFOROPENING_0: + LookOpening(true, 0); + _events.ScheduleEvent(EVENT_LOOKFOROPENING_1, Seconds(26)); + break; + case EVENT_LOOKFOROPENING_1: + LookOpening(true, 1); + _events.ScheduleEvent(EVENT_LOOKFOROPENING_2, Seconds(25)); + break; + case EVENT_LOOKFOROPENING_2: + LookOpening(true, 2); + _events.ScheduleEvent(EVENT_STOP_LOOKING_FOR_OPENING, Seconds(27)); + break; + case EVENT_STOP_LOOKING_FOR_OPENING: + LookOpening(false, _mySpot); + break; + default: + break; + } + } + } + + void LookOpening(bool activate, uint8 spot) + { + if (_mySpot != spot) + return; + + if (Creature* bonfireBunny = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BONFIRE_BUNNY_000 + spot))) + if (Creature* beamBunny = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BEAM_BUNNY_000 + spot))) + { + if (activate) + { + DoCast(bonfireBunny, SPELL_FIND_OPENING_TRIGGER); + bonfireBunny->CastSpell(beamBunny, SPELL_FIND_OPENING_VISUAL, true); + } + else + { + DoCast(me, SPELL_FIND_OPENING_CHANNEL); + bonfireBunny->CastStop(); + beamBunny->RemoveAurasDueToSpell(SPELL_FIND_OPENING_BEAM_END); + } + } + } + + private: + EventMap _events; + InstanceScript* _instance; + uint8 _mySpot; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_earthen_ring_flamecallerAI>(creature); + } +}; + +class go_ahune_ice_stone : public GameObjectScript +{ +public: + go_ahune_ice_stone() : GameObjectScript("go_ahune_ice_stone") { } + + bool OnGossipSelect(Player* player, GameObject* go, uint32 /*sender*/, uint32 /*action*/) + { + InstanceScript* instance = go->GetInstanceScript(); + if (!instance) + return false; + + player->PlayerTalkClass->ClearMenus(); + + if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_AHUNE_BUNNY))) + { + ahuneBunny->AI()->DoAction(ACTION_START_EVENT); + ahuneBunny->SetInCombatWithZone(); + } + if (Creature* luma = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_LUMA_SKYMOTHER))) + luma->CastSpell(player, SPELL_SUMMONING_RHYME_AURA, true); + player->CLOSE_GOSSIP_MENU(); + go->Delete(); + + return true; + } +}; + +// 46430 - Synch Health +class spell_ahune_synch_health : public SpellScriptLoader +{ +public: + spell_ahune_synch_health() : SpellScriptLoader("spell_ahune_synch_health") { } + + class spell_ahune_synch_health_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ahune_synch_health_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SYNCH_HEALTH)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (Unit* caster = GetCaster()) + target->SetHealth(caster->GetHealth()); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ahune_synch_health_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ahune_synch_health_SpellScript(); + } +}; + +// 45926 - Summoning Rhyme Aura +class spell_summoning_rhyme_aura : public SpellScriptLoader +{ +public: + spell_summoning_rhyme_aura() : SpellScriptLoader("spell_summoning_rhyme_aura") { } + + class spell_summoning_rhyme_aura_AuraScript : public AuraScript + { + PrepareAuraScript(spell_summoning_rhyme_aura_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_FORCE_WHISP_FLIGHT) || !sSpellMgr->GetSpellInfo(SPELL_SUMMONING_RHYME_BONFIRE)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* aurEff) + { + Creature* caster = GetCaster()->ToCreature(); + Player* player = GetTarget()->ToPlayer(); + + if (!caster || !player) + return; + + player->CastSpell(player, SPELL_FORCE_WHISP_FLIGHT); + + switch (aurEff->GetTickNumber()) + { + case 1: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_1, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); + player->CastSpell(player, SPELL_SUMMONING_RHYME_BONFIRE, true); + break; + case 2: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_2, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); + break; + case 3: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_3, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); + Remove(); + break; + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summoning_rhyme_aura_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_summoning_rhyme_aura_AuraScript(); + } +}; + +// 46878 - Summon Ice Spear Delayer +class spell_summon_ice_spear_delayer : public SpellScriptLoader +{ +public: + spell_summon_ice_spear_delayer() : SpellScriptLoader("spell_summon_ice_spear_delayer") { } + + class spell_summon_ice_spear_delayer_AuraScript : public AuraScript + { + PrepareAuraScript(spell_summon_ice_spear_delayer_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ICE_SPEAR_GO) || !sSpellMgr->GetSpellInfo(SPELL_ICE_SPEAR_KNOCKBACK)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* aurEff) + { + if (Unit* tmpCaster = GetCaster()) + if (Creature* caster = tmpCaster->ToCreature()) + switch (aurEff->GetTickNumber()) + { + case 1: + caster->CastSpell(caster, SPELL_SUMMON_ICE_SPEAR_GO); + break; + case 3: + if (GameObject* spike = caster->FindNearestGameObject(GO_ICE_SPEAR, 3.0f)) + spike->UseDoorOrButton(); + caster->AI()->DoCastAOE(SPELL_ICE_SPEAR_KNOCKBACK, true); + break; + case 5: + if (GameObject* spike = caster->FindNearestGameObject(GO_ICE_SPEAR, 3.0f)) + spike->Delete(); + caster->DespawnOrUnsummon(); + break; + default: + break; + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_ice_spear_delayer_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_summon_ice_spear_delayer_AuraScript(); + } +}; + +// 46371 - Ice Spear Control Aura +class spell_ice_spear_control_aura : public SpellScriptLoader +{ +public: + spell_ice_spear_control_aura() : SpellScriptLoader("spell_ice_spear_control_aura") { } + + class spell_ice_spear_control_aura_AuraScript : public AuraScript + { + PrepareAuraScript(spell_ice_spear_control_aura_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_ICE_SPEAR_TARGET_PICKER)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, SPELL_ICE_SPEAR_TARGET_PICKER); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ice_spear_control_aura_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_ice_spear_control_aura_AuraScript(); + } +}; + +// 46372 - Ice Spear Target Picker +class spell_ice_spear_target_picker : public SpellScriptLoader +{ +public: + spell_ice_spear_target_picker() : SpellScriptLoader("spell_ice_spear_target_picker") { } + + class spell_ice_spear_target_picker_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ice_spear_target_picker_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ICE_SPEAR_BUNNY)) + return false; + return true; + } + + void FilterTargets(std::list<WorldObject*>& targets) + { + if (targets.empty()) + return; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ICE_SPEAR_BUNNY, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ice_spear_target_picker_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_ice_spear_target_picker_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ice_spear_target_picker_SpellScript(); + } +}; + +// 46320 - Spell Slippery Floor Periodic +class spell_slippery_floor_periodic : public SpellScriptLoader +{ +public: + spell_slippery_floor_periodic() : SpellScriptLoader("spell_slippery_floor_periodic") { } + + class spell_slippery_floor_periodic_SpellScript : public SpellScript + { + PrepareSpellScript(spell_slippery_floor_periodic_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SLIPPERY_FLOOR_SLIP)) + return false; + return true; + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (target->isMoving()) + { + target->CastSpell(target, SPELL_SLIPPERY_FLOOR_SLIP, true); + target->CastSpell(target, SPELL_SLIPPERY_FLOOR_YOU_SLIPPED, true); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_slippery_floor_periodic_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_slippery_floor_periodic_SpellScript(); + } +}; + +// 46146 - Ahune Spanky Hands +class spell_ahune_spanky_hands : public SpellScriptLoader +{ +public: + spell_ahune_spanky_hands() : SpellScriptLoader("spell_ahune_spanky_hands") { } + + class spell_ahune_spanky_hands_AuraScript : public AuraScript + { + PrepareAuraScript(spell_ahune_spanky_hands_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_COLD_SLAP)) + return false; + return true; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_COLD_SLAP, true); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_ahune_spanky_hands_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_ahune_spanky_hands_AuraScript(); + } +}; + +class spell_ahune_minion_despawner : public SpellScriptLoader +{ +public: + spell_ahune_minion_despawner() : SpellScriptLoader("spell_ahune_minion_despawner") { } + + class spell_ahune_minion_despawner_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ahune_minion_despawner_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (GetHitCreature()) + GetHitCreature()->DespawnOrUnsummon(); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ahune_minion_despawner_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ahune_minion_despawner_SpellScript(); + } +}; + +// 46398 - Spell Ice Bombardment Dest Picker +class spell_ice_bombardment_dest_picker : public SpellScriptLoader +{ +public: + spell_ice_bombardment_dest_picker() : SpellScriptLoader("spell_ice_bombardment_dest_picker") { } + + class spell_ice_bombardment_dest_picker_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ice_bombardment_dest_picker_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_ICE_BOMBARDMENT)) + return false; + return true; + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitDest()->GetPositionX(), GetHitDest()->GetPositionY(), GetHitDest()->GetPositionZ(), SPELL_ICE_BOMBARDMENT, true); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_ice_bombardment_dest_picker_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ice_bombardment_dest_picker_SpellScript(); + } +}; + +void AddSC_boss_ahune() +{ + new boss_ahune(); + new npc_frozen_core(); + new npc_earthen_ring_flamecaller(); + new npc_ahune_bunny(); + new go_ahune_ice_stone(); + new spell_ahune_synch_health(); + new spell_summoning_rhyme_aura(); + new spell_summon_ice_spear_delayer(); + new spell_ice_spear_control_aura(); + new spell_slippery_floor_periodic(); + new spell_ahune_spanky_hands(); + new spell_ahune_minion_despawner(); + new spell_ice_spear_target_picker(); + new spell_ice_bombardment_dest_picker(); +} diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp index 87a07cd1e5e..0fac7b5a39d 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp @@ -31,15 +31,125 @@ class instance_the_slave_pens : public InstanceMapScript public: instance_the_slave_pens() : InstanceMapScript(SPScriptName, 547) { } + struct instance_the_slave_pens_InstanceMapScript : public InstanceScript + { + instance_the_slave_pens_InstanceMapScript(Map* map) : InstanceScript(map) + { + counter = DATA_FLAMECALLER_000; + } + + void OnCreatureCreate(Creature* creature) override + { + switch (creature->GetEntry()) + { + case NPC_AHUNE: + AhuneGUID = creature->GetGUID(); + break; + case NPC_FROZEN_CORE: + FrozenCoreGUID = creature->GetGUID(); + break; + case NPC_AHUNE_LOC_BUNNY: + AhuneBunnyGUID = creature->GetGUID(); + break; + case NPC_SHAMAN_BONFIRE_BUNNY_000: + BonfireBunnyGUIDs[0] = creature->GetGUID(); + break; + case NPC_SHAMAN_BONFIRE_BUNNY_001: + BonfireBunnyGUIDs[1] = creature->GetGUID(); + break; + case NPC_SHAMAN_BONFIRE_BUNNY_002: + BonfireBunnyGUIDs[2] = creature->GetGUID(); + break; + case NPC_SHAMAN_BEAM_BUNNY_000: + BeamBunnyGUIDs[0] = creature->GetGUID(); + break; + case NPC_SHAMAN_BEAM_BUNNY_001: + BeamBunnyGUIDs[1] = creature->GetGUID(); + break; + case NPC_SHAMAN_BEAM_BUNNY_002: + BeamBunnyGUIDs[2] = creature->GetGUID(); + break; + case NPC_LUMA_SKYMOTHER: + LumaGUID = creature->GetGUID(); + break; + case NPC_EARTHEN_RING_FLAMECALLER: + SetGuidData(counter, creature->GetGUID()); + ++counter; + break; + default: + break; + } + } + + void SetGuidData(uint32 data, ObjectGuid guid) override + { + switch (data) + { + case DATA_FLAMECALLER_000: + FlameCallerGUIDs[0] = guid; + break; + case DATA_FLAMECALLER_001: + FlameCallerGUIDs[1] = guid; + break; + case DATA_FLAMECALLER_002: + FlameCallerGUIDs[2] = guid; + break; + default: + break; + } + } + + ObjectGuid GetGuidData(uint32 type) const override + { + switch (type) + { + case DATA_AHUNE: + return AhuneGUID; + case DATA_AHUNE_BUNNY: + return AhuneBunnyGUID; + case DATA_FROZEN_CORE: + return FrozenCoreGUID; + case DATA_FLAMECALLER_000: + return FlameCallerGUIDs[0]; + case DATA_FLAMECALLER_001: + return FlameCallerGUIDs[1]; + case DATA_FLAMECALLER_002: + return FlameCallerGUIDs[2]; + case DATA_BONFIRE_BUNNY_000: + return BonfireBunnyGUIDs[0]; + case DATA_BONFIRE_BUNNY_001: + return BonfireBunnyGUIDs[1]; + case DATA_BONFIRE_BUNNY_002: + return BonfireBunnyGUIDs[2]; + case DATA_BEAM_BUNNY_000: + return BeamBunnyGUIDs[0]; + case DATA_BEAM_BUNNY_001: + return BeamBunnyGUIDs[1]; + case DATA_BEAM_BUNNY_002: + return BeamBunnyGUIDs[2]; + case DATA_LUMA_SKYMOTHER: + return LumaGUID; + default: + break; + } + return ObjectGuid::Empty; + } + + protected: + ObjectGuid AhuneGUID; + ObjectGuid AhuneBunnyGUID; + ObjectGuid FrozenCoreGUID; + ObjectGuid LumaGUID; + ObjectGuid FlameCallerGUIDs[3]; + ObjectGuid BonfireBunnyGUIDs[3]; + ObjectGuid BeamBunnyGUIDs[3]; + uint8 counter; + }; + InstanceScript* GetInstanceScript(InstanceMap* map) const override { return new instance_the_slave_pens_InstanceMapScript(map); } - - struct instance_the_slave_pens_InstanceMapScript : public InstanceScript - { - instance_the_slave_pens_InstanceMapScript(Map* map) : InstanceScript(map) { } - }; }; void AddSC_instance_the_slave_pens() diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h index 95e6e44121e..544e98fd206 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h @@ -27,7 +27,43 @@ enum DataTypes { DATA_MENNU_THE_BETRAYER = 1, DATA_ROKMAR_THE_CRACKLER = 2, - DATA_QUAGMIRRAN = 3 + DATA_QUAGMIRRAN = 3, + DATA_AHUNE = 4, + DATA_AHUNE_BUNNY = 5, + DATA_FROZEN_CORE = 6, + DATA_FLAMECALLER_000 = 7, + DATA_FLAMECALLER_001 = 8, + DATA_FLAMECALLER_002 = 9, + DATA_BONFIRE_BUNNY_000 = 10, + DATA_BONFIRE_BUNNY_001 = 11, + DATA_BONFIRE_BUNNY_002 = 12, + DATA_BEAM_BUNNY_000 = 13, + DATA_BEAM_BUNNY_001 = 14, + DATA_BEAM_BUNNY_002 = 15, + DATA_LUMA_SKYMOTHER = 16 +}; + +enum CreaturesIds +{ + NPC_AHUNE = 25740, + NPC_FROZEN_CORE = 25865, + NPC_LUMA_SKYMOTHER = 25697, + NPC_AHUNE_LOC_BUNNY = 25745, + NPC_EARTHEN_RING_FLAMECALLER = 25754, + NPC_SHAMAN_BONFIRE_BUNNY_000 = 25971, + NPC_SHAMAN_BONFIRE_BUNNY_001 = 25972, + NPC_SHAMAN_BONFIRE_BUNNY_002 = 25973, + NPC_SHAMAN_BEAM_BUNNY_000 = 25964, + NPC_SHAMAN_BEAM_BUNNY_001 = 25965, + NPC_SHAMAN_BEAM_BUNNY_002 = 25966, + NPC_WHISP_DEST_BUNNY = 26120, + NPC_WHISP_SOURCE_BUNNY = 26121 +}; + +enum GameObjectIds +{ + GO_ICE_SPEAR = 188077, + GO_ICE_STONE = 187882 }; #endif // SLAVE_PENS_H diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp index 4e20e6b0953..9b8220596c9 100644 --- a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp @@ -372,7 +372,7 @@ class boss_vazruden_the_herald : public CreatureScript if (summon->GetEntry() == NPC_NAZAN) { summon->SetDisableGravity(true); - summon->SetSpeed(MOVE_FLIGHT, 2.5f); + summon->SetSpeedRate(MOVE_FLIGHT, 2.5f); if (victim) AttackStartNoMove(victim); } diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp index 499550945c6..2592ed3b262 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp @@ -180,24 +180,23 @@ class boss_grand_warlock_nethekurse : public CreatureScript } void MoveInLineOfSight(Unit* who) override - { if (!IntroOnce && me->IsWithinDistInMap(who, 30.0f)) - { + { if (who->GetTypeId() != TYPEID_PLAYER) return; - Talk(SAY_INTRO); - IntroOnce = true; - IsIntroEvent = true; + Talk(SAY_INTRO); + IntroOnce = true; + IsIntroEvent = true; - instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS); - } + instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS); + } - if (IsIntroEvent || !IsMainEvent) - return; + if (IsIntroEvent || !IsMainEvent) + return; - ScriptedAI::MoveInLineOfSight(who); + ScriptedAI::MoveInLineOfSight(who); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp index 4faab709e16..c29d560529d 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp @@ -109,7 +109,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript { removeAdds(); _Reset(); - me->SetSpeed(MOVE_RUN, 2); + me->SetSpeedRate(MOVE_RUN, 2); me->SetWalk(false); Initialize(); @@ -231,7 +231,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript { // stop bladedance InBlade = false; - me->SetSpeed(MOVE_RUN, 2); + me->SetSpeedRate(MOVE_RUN, 2); me->GetMotionMaster()->MoveChase(me->GetVictim()); Blade_Dance_Timer = 30000; Wait_Timer = 0; @@ -264,7 +264,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript Wait_Timer = 1; InBlade = true; Blade_Dance_Timer = 0; - me->SetSpeed(MOVE_RUN, 4); + me->SetSpeedRate(MOVE_RUN, 4); return; } else diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index 102d567e810..20d96ecd29c 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -130,7 +130,7 @@ class boss_alar : public CreatureScript _Reset(); me->SetDisplayId(me->GetNativeDisplayId()); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + me->SetSpeedRate(MOVE_RUN, DefaultMoveSpeedRate); //me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); //me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); @@ -178,7 +178,7 @@ class boss_alar : public CreatureScript me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->AttackStop(); me->SetTarget(ObjectGuid::Empty); - me->SetSpeed(MOVE_RUN, 5.0f); + me->SetSpeedRate(MOVE_RUN, 5.0f); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]); } @@ -261,7 +261,7 @@ class boss_alar : public CreatureScript case WE_REVIVE: me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); me->SetFullHealth(); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + me->SetSpeedRate(MOVE_RUN, DefaultMoveSpeedRate); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); DoZoneInCombat(); DoCast(me, SPELL_REBIRTH, true); @@ -289,6 +289,7 @@ class boss_alar : public CreatureScript me->SetPosition(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0.0f); me->StopMoving(); WaitEvent = WE_LAND; + return; } else { diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index 9fd1c5c7388..30b3fd67687 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -325,86 +325,85 @@ class boss_high_astromancer_solarian : public CreatureScript else Phase1_Timer-=diff; } - else - if (Phase == 2) + else if (Phase == 2) + { + //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. + me->AttackStop(); + me->StopMoving(); + if (Phase2_Timer <= diff) { - //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. - me->AttackStop(); - me->StopMoving(); - if (Phase2_Timer <= diff) - { - Phase = 3; - for (int i=0; i <= 2; ++i) - for (int j=1; j <= 4; j++) - SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); + Phase = 3; + for (int i=0; i <= 2; ++i) + for (int j=1; j <= 4; j++) + SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); - Talk(SAY_SUMMON1); - Phase2_Timer = 10000; - } - else - Phase2_Timer -= diff; + Talk(SAY_SUMMON1); + Phase2_Timer = 10000; } else - if (Phase == 3) - { - me->AttackStop(); - me->StopMoving(); - //Check Phase3_Timer - if (Phase3_Timer <= diff) - { - Phase = 1; - //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. - int i = rand32() % 3; - me->GetMotionMaster()->Clear(); - me->SetPosition(Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); - - for (int j=0; j <= 2; j++) - if (j != i) - SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisible(true); - - Talk(SAY_SUMMON2); - AppearDelay = true; - Phase3_Timer = 15000; - } - else - Phase3_Timer -= diff; - } - else - if (Phase == 4) - { - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 20000; - } - else - Fear_Timer -= diff; - //VoidBolt_Timer - if (VoidBolt_Timer <= diff) - { - DoCastVictim(SPELL_VOID_BOLT); - VoidBolt_Timer = 10000; - } - else - VoidBolt_Timer -= diff; - } - //When Solarian reaches 20% she will transform into a huge void walker. - if (Phase != 4 && me->HealthBelowPct(20)) - { - Phase = 4; - //To make sure she wont be invisible or not selecatble - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisible(true); - Talk(SAY_VOIDA); - Talk(SAY_VOIDB); - me->SetArmor(WV_ARMOR); - me->SetDisplayId(MODEL_VOIDWALKER); - me->SetObjectScale(defaultsize*2.5f); - } + Phase2_Timer -= diff; + } + else if (Phase == 3) + { + me->AttackStop(); + me->StopMoving(); + //Check Phase3_Timer + if (Phase3_Timer <= diff) + { + Phase = 1; + //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. + int i = rand32() % 3; + me->GetMotionMaster()->Clear(); + me->SetPosition(Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); + + for (int j=0; j <= 2; j++) + if (j != i) + SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisible(true); + + Talk(SAY_SUMMON2); + AppearDelay = true; + Phase3_Timer = 15000; + } + else + Phase3_Timer -= diff; + } + else if (Phase == 4) + { + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 20000; + } + else + Fear_Timer -= diff; + //VoidBolt_Timer + if (VoidBolt_Timer <= diff) + { + DoCastVictim(SPELL_VOID_BOLT); + VoidBolt_Timer = 10000; + } + else + VoidBolt_Timer -= diff; + } + + //When Solarian reaches 20% she will transform into a huge void walker. + if (Phase != 4 && me->HealthBelowPct(20)) + { + Phase = 4; + //To make sure she wont be invisible or not selecatble + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisible(true); + Talk(SAY_VOIDA); + Talk(SAY_VOIDB); + me->SetArmor(WV_ARMOR); + me->SetDisplayId(MODEL_VOIDWALKER); + me->SetObjectScale(defaultsize*2.5f); + } + DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index e5812390bd2..be27932e6b4 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -144,6 +144,7 @@ enum Spells // Thaladred the Darkener spells SPELL_PSYCHIC_BLOW = 10689, SPELL_SILENCE = 30225, + SPELL_REND = 36965, // Lord Sanguinar spells SPELL_BELLOWING_ROAR = 40636, // Grand Astromancer Capernian spells @@ -881,11 +882,13 @@ class boss_thaladred_the_darkener : public CreatureScript { Gaze_Timer = 100; Silence_Timer = 20000; + Rend_Timer = 4000; PsychicBlow_Timer = 10000; } uint32 Gaze_Timer; uint32 Silence_Timer; + uint32 Rend_Timer; uint32 PsychicBlow_Timer; void Reset() override @@ -939,6 +942,15 @@ class boss_thaladred_the_darkener : public CreatureScript else Silence_Timer -= diff; + //Rend_Timer + if (Rend_Timer <= diff) + { + DoCastVictim(SPELL_REND); + Rend_Timer = 4000; + } + else + Rend_Timer -= diff; + //PsychicBlow_Timer if (PsychicBlow_Timer <= diff) { diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp index 46388c3a185..edfa2aedf92 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,13 +15,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Void_Reaver -SD%Complete: 90 -SDComment: Should reset if raid are out of room. -SDCategory: Tempest Keep, The Eye -EndScriptData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "the_eye.h" @@ -43,10 +35,17 @@ enum Spells SPELL_BERSERK = 27680 }; +enum Events +{ + EVENT_POUNDING = 1, + EVENT_ARCANE_ORB, + EVENT_KNOCK_AWAY, + EVENT_BERSERK +}; + class boss_void_reaver : public CreatureScript { public: - boss_void_reaver() : CreatureScript("boss_void_reaver") { } struct boss_void_reaverAI : public BossAI @@ -58,21 +57,9 @@ class boss_void_reaver : public CreatureScript void Initialize() { - Pounding_Timer = 15000; - ArcaneOrb_Timer = 3000; - KnockAway_Timer = 30000; - Berserk_Timer = 600000; - Enraged = false; } - uint32 Pounding_Timer; - uint32 ArcaneOrb_Timer; - uint32 KnockAway_Timer; - uint32 Berserk_Timer; - - bool Enraged; - void Reset() override { Initialize(); @@ -95,71 +82,84 @@ class boss_void_reaver : public CreatureScript { Talk(SAY_AGGRO); _EnterCombat(); + + events.ScheduleEvent(EVENT_POUNDING, 15000); + events.ScheduleEvent(EVENT_ARCANE_ORB, 3000); + events.ScheduleEvent(EVENT_KNOCK_AWAY, 30000); + events.ScheduleEvent(EVENT_BERSERK, 600000); } void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; - // Pounding - if (Pounding_Timer <= diff) - { - DoCastVictim(SPELL_POUNDING); - Talk(SAY_POUNDING); - Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000) - } - else - Pounding_Timer -= diff; - // Arcane Orb - if (ArcaneOrb_Timer <= diff) - { - Unit* target = NULL; - std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); - std::vector<Unit*> target_list; - for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (!target) - continue; - // exclude pets & totems, 18 yard radius minimum - if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive() && !target->IsWithinDist(me, 18, false)) - target_list.push_back(target); - target = NULL; - } - if (!target_list.empty()) - target = *(target_list.begin() + rand32() % target_list.size()); - else - target = me->GetVictim(); + events.Update(diff); - if (target) - me->CastSpell(target, SPELL_ARCANE_ORB, false, NULL, NULL); - ArcaneOrb_Timer = 3000; - } - else - ArcaneOrb_Timer -= diff; - // Single Target knock back, reduces aggro - if (KnockAway_Timer <= diff) - { - DoCastVictim(SPELL_KNOCK_AWAY); - //Drop 25% aggro - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -25); - KnockAway_Timer = 30000; - } - else - KnockAway_Timer -= diff; - //Berserk - if (Berserk_Timer < diff && !Enraged) + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - DoCast(me, SPELL_BERSERK); - Enraged = true; + switch (eventId) + { + case EVENT_POUNDING: + DoCastVictim(SPELL_POUNDING); + Talk(SAY_POUNDING); + events.ScheduleEvent(EVENT_POUNDING, 15000); + break; + case EVENT_ARCANE_ORB: + { + Unit* target = NULL; + std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); + std::vector<Unit*> target_list; + for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr) + { + target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); + if (!target) + continue; + // exclude pets & totems, 18 yard radius minimum + if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive() && !target->IsWithinDist(me, 18, false)) + target_list.push_back(target); + target = NULL; + } + + if (!target_list.empty()) + target = *(target_list.begin() + rand32() % target_list.size()); + else + target = me->GetVictim(); + + if (target) + me->CastSpell(target, SPELL_ARCANE_ORB, false, NULL, NULL); + + events.ScheduleEvent(EVENT_ARCANE_ORB, 3000); + break; + } + case EVENT_KNOCK_AWAY: + DoCastVictim(SPELL_KNOCK_AWAY); + // Drop 25% aggro + if (DoGetThreat(me->GetVictim())) + DoModifyThreatPercent(me->GetVictim(), -25); + + events.ScheduleEvent(EVENT_KNOCK_AWAY, 30000); + break; + case EVENT_BERSERK: + if (!Enraged) + { + DoCast(me, SPELL_BERSERK); + Enraged = true; + } + break; + default: + break; + } } - else - Berserk_Timer -= diff; DoMeleeAttackIfReady(); } + + private: + bool Enraged; }; CreatureAI* GetAI(Creature* creature) const override diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp index 3aa2674aec6..d45e17bd28d 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp @@ -176,7 +176,7 @@ class npc_ragin_flames : public CreatureScript Initialize(); me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); + me->SetSpeedRate(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp index cab5b9efbc3..f4ff9f7084c 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp @@ -537,7 +537,7 @@ class npc_zerekethvoidzone : public CreatureScript void Reset() override { - me->SetUInt32Value(UNIT_NPC_FLAGS, 0); + me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); me->setFaction(16); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp index 856649c6c5e..b9e7fb0034d 100644 --- a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp @@ -103,7 +103,7 @@ class npc_warp_splinter_treant : public CreatureScript { if (Unit* Warp = ObjectAccessor::GetUnit(*me, WarpGuid)) { - if (me->IsWithinMeleeRange(Warp, 2.5f)) + if (me->IsWithinMeleeRange(Warp)) { int32 CurrentHP_Treant = (int32)me->GetHealth(); Warp->CastCustomSpell(Warp, SPELL_HEAL_FATHER, &CurrentHP_Treant, 0, 0, true, 0, 0, me->GetGUID()); @@ -167,7 +167,7 @@ class boss_warp_splinter : public CreatureScript { Initialize(); - me->SetSpeed(MOVE_RUN, 0.7f, true); + me->SetSpeedRate(MOVE_RUN, 0.7f); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Outland/outland_script_loader.cpp b/src/server/scripts/Outland/outland_script_loader.cpp new file mode 100644 index 00000000000..ed2c21da6c3 --- /dev/null +++ b/src/server/scripts/Outland/outland_script_loader.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +// Auchindoun - Auchenai Crypts +void AddSC_boss_shirrak_the_dead_watcher(); +void AddSC_boss_exarch_maladaar(); +void AddSC_instance_auchenai_crypts(); + +// Auchindoun - Mana Tombs +void AddSC_boss_pandemonius(); +void AddSC_boss_nexusprince_shaffar(); +void AddSC_instance_mana_tombs(); + +// Auchindoun - Sekketh Halls +void AddSC_boss_darkweaver_syth(); +void AddSC_boss_talon_king_ikiss(); +void AddSC_boss_anzu(); +void AddSC_instance_sethekk_halls(); + +// Auchindoun - Shadow Labyrinth +void AddSC_boss_ambassador_hellmaw(); +void AddSC_boss_blackheart_the_inciter(); +void AddSC_boss_grandmaster_vorpil(); +void AddSC_boss_murmur(); +void AddSC_instance_shadow_labyrinth(); + +// Black Temple +void AddSC_black_temple(); +void AddSC_boss_illidan(); +void AddSC_boss_shade_of_akama(); +void AddSC_boss_supremus(); +void AddSC_boss_gurtogg_bloodboil(); +void AddSC_boss_mother_shahraz(); +void AddSC_boss_reliquary_of_souls(); +void AddSC_boss_teron_gorefiend(); +void AddSC_boss_najentus(); +void AddSC_boss_illidari_council(); +void AddSC_instance_black_temple(); + +// Coilfang Reservoir - Serpent Shrine Cavern +void AddSC_boss_fathomlord_karathress(); +void AddSC_boss_hydross_the_unstable(); +void AddSC_boss_lady_vashj(); +void AddSC_boss_leotheras_the_blind(); +void AddSC_boss_morogrim_tidewalker(); +void AddSC_instance_serpentshrine_cavern(); +void AddSC_boss_the_lurker_below(); + +// Coilfang Reservoir - The Steam Vault +void AddSC_boss_hydromancer_thespia(); +void AddSC_boss_mekgineer_steamrigger(); +void AddSC_boss_warlord_kalithresh(); +void AddSC_instance_steam_vault(); + +// Coilfang Reservoir - The Slave Pens +void AddSC_instance_the_slave_pens(); +void AddSC_boss_mennu_the_betrayer(); +void AddSC_boss_rokmar_the_crackler(); +void AddSC_boss_quagmirran(); +void AddSC_boss_ahune(); + +// Coilfang Reservoir - The Underbog +void AddSC_instance_the_underbog(); +void AddSC_boss_hungarfen(); +void AddSC_boss_the_black_stalker(); + +// Gruul's Lair +void AddSC_boss_gruul(); +void AddSC_boss_high_king_maulgar(); +void AddSC_instance_gruuls_lair(); +void AddSC_boss_broggok(); //HC Blood Furnace +void AddSC_boss_kelidan_the_breaker(); +void AddSC_boss_the_maker(); +void AddSC_instance_blood_furnace(); +void AddSC_boss_magtheridon(); //HC Magtheridon's Lair +void AddSC_instance_magtheridons_lair(); +void AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls +void AddSC_boss_warbringer_omrogg(); +void AddSC_boss_warchief_kargath_bladefist(); +void AddSC_shattered_halls(); +void AddSC_instance_shattered_halls(); +void AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts +void AddSC_boss_omor_the_unscarred(); +void AddSC_boss_vazruden_the_herald(); +void AddSC_instance_ramparts(); +void AddSC_arcatraz(); //TK Arcatraz +void AddSC_boss_zereketh_the_unbound(); +void AddSC_boss_dalliah_the_doomsayer(); +void AddSC_boss_wrath_scryer_soccothrates(); +void AddSC_boss_harbinger_skyriss(); +void AddSC_instance_arcatraz(); +void AddSC_boss_high_botanist_freywinn(); //TK Botanica +void AddSC_boss_laj(); +void AddSC_boss_warp_splinter(); +void AddSC_boss_thorngrin_the_tender(); +void AddSC_boss_commander_sarannis(); +void AddSC_instance_the_botanica(); +void AddSC_boss_alar(); //TK The Eye +void AddSC_boss_kaelthas(); +void AddSC_boss_void_reaver(); +void AddSC_boss_high_astromancer_solarian(); +void AddSC_instance_the_eye(); +void AddSC_the_eye(); +void AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar +void AddSC_boss_gatewatcher_gyrokill(); +void AddSC_boss_nethermancer_sepethrea(); +void AddSC_boss_pathaleon_the_calculator(); +void AddSC_boss_mechano_lord_capacitus(); +void AddSC_instance_mechanar(); + +void AddSC_blades_edge_mountains(); +void AddSC_boss_doomlordkazzak(); +void AddSC_boss_doomwalker(); +void AddSC_hellfire_peninsula(); +void AddSC_nagrand(); +void AddSC_netherstorm(); +void AddSC_shadowmoon_valley(); +void AddSC_shattrath_city(); +void AddSC_terokkar_forest(); +void AddSC_zangarmarsh(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddOutlandScripts() +{ + // Auchindoun - Auchenai Crypts + AddSC_boss_shirrak_the_dead_watcher(); + AddSC_boss_exarch_maladaar(); + AddSC_instance_auchenai_crypts(); + + // Auchindoun - Mana Tombs + AddSC_boss_pandemonius(); + AddSC_boss_nexusprince_shaffar(); + AddSC_instance_mana_tombs(); + + // Auchindoun - Sekketh Halls + AddSC_boss_darkweaver_syth(); + AddSC_boss_talon_king_ikiss(); + AddSC_boss_anzu(); + AddSC_instance_sethekk_halls(); + + // Auchindoun - Shadow Labyrinth + AddSC_boss_ambassador_hellmaw(); + AddSC_boss_blackheart_the_inciter(); + AddSC_boss_grandmaster_vorpil(); + AddSC_boss_murmur(); + AddSC_instance_shadow_labyrinth(); + + // Black Temple + AddSC_black_temple(); + AddSC_boss_illidan(); + AddSC_boss_shade_of_akama(); + AddSC_boss_supremus(); + AddSC_boss_gurtogg_bloodboil(); + AddSC_boss_mother_shahraz(); + AddSC_boss_reliquary_of_souls(); + AddSC_boss_teron_gorefiend(); + AddSC_boss_najentus(); + AddSC_boss_illidari_council(); + AddSC_instance_black_temple(); + + // Coilfang Reservoir - Serpent Shrine Cavern + AddSC_boss_fathomlord_karathress(); + AddSC_boss_hydross_the_unstable(); + AddSC_boss_lady_vashj(); + AddSC_boss_leotheras_the_blind(); + AddSC_boss_morogrim_tidewalker(); + AddSC_instance_serpentshrine_cavern(); + AddSC_boss_the_lurker_below(); + + // Coilfang Reservoir - The Steam Vault + AddSC_instance_steam_vault(); + AddSC_boss_hydromancer_thespia(); + AddSC_boss_mekgineer_steamrigger(); + AddSC_boss_warlord_kalithresh(); + + // Coilfang Reservoir - The Slave Pens + AddSC_instance_the_slave_pens(); + AddSC_boss_mennu_the_betrayer(); + AddSC_boss_rokmar_the_crackler(); + AddSC_boss_quagmirran(); + AddSC_boss_ahune(); + + // Coilfang Reservoir - The Underbog + AddSC_instance_the_underbog(); + AddSC_boss_hungarfen(); + AddSC_boss_the_black_stalker(); + + // Gruul's Lair + AddSC_boss_gruul(); + AddSC_boss_high_king_maulgar(); + AddSC_instance_gruuls_lair(); + AddSC_boss_broggok(); //HC Blood Furnace + AddSC_boss_kelidan_the_breaker(); + AddSC_boss_the_maker(); + AddSC_instance_blood_furnace(); + AddSC_boss_magtheridon(); //HC Magtheridon's Lair + AddSC_instance_magtheridons_lair(); + AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls + AddSC_boss_warbringer_omrogg(); + AddSC_boss_warchief_kargath_bladefist(); + AddSC_shattered_halls(); + AddSC_instance_shattered_halls(); + AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts + AddSC_boss_omor_the_unscarred(); + AddSC_boss_vazruden_the_herald(); + AddSC_instance_ramparts(); + AddSC_arcatraz(); //TK Arcatraz + AddSC_boss_zereketh_the_unbound(); + AddSC_boss_dalliah_the_doomsayer(); + AddSC_boss_wrath_scryer_soccothrates(); + AddSC_boss_harbinger_skyriss(); + AddSC_instance_arcatraz(); + AddSC_boss_high_botanist_freywinn(); //TK Botanica + AddSC_boss_laj(); + AddSC_boss_warp_splinter(); + AddSC_boss_thorngrin_the_tender(); + AddSC_boss_commander_sarannis(); + AddSC_instance_the_botanica(); + AddSC_boss_alar(); //TK The Eye + AddSC_boss_kaelthas(); + AddSC_boss_void_reaver(); + AddSC_boss_high_astromancer_solarian(); + AddSC_instance_the_eye(); + AddSC_the_eye(); + AddSC_boss_gatewatcher_iron_hand(); //TK The Mechanar + AddSC_boss_gatewatcher_gyrokill(); + AddSC_boss_nethermancer_sepethrea(); + AddSC_boss_pathaleon_the_calculator(); + AddSC_boss_mechano_lord_capacitus(); + AddSC_instance_mechanar(); + + AddSC_blades_edge_mountains(); + AddSC_boss_doomlordkazzak(); + AddSC_boss_doomwalker(); + AddSC_hellfire_peninsula(); + AddSC_nagrand(); + AddSC_netherstorm(); + AddSC_shadowmoon_valley(); + AddSC_shattrath_city(); + AddSC_terokkar_forest(); + AddSC_zangarmarsh(); +} diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp index 30bf085be43..9074f1ea373 100644 --- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp @@ -959,7 +959,7 @@ public: { // Spell 37392 does not exist in dbc, manually spawning me->SummonCreature(NPC_OSCILLATING_FREQUENCY_SCANNER_TOP_BUNNY, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 0.5f, me->GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 50000); - me->SummonGameObject(GO_OSCILLATING_FREQUENCY_SCANNER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 50); + me->SummonGameObject(GO_OSCILLATING_FREQUENCY_SCANNER, *me, G3D::Quat(), 50); me->DespawnOrUnsummon(50000); } diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index 404cdc7ceb2..668c484dd63 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -159,7 +159,7 @@ public: else TC_LOG_ERROR("scripts", "TRINITY: npc_ancestral_wolf can not obtain owner or owner is not a player."); - creature->SetSpeed(MOVE_WALK, 1.5f); + creature->SetSpeedRate(MOVE_WALK, 1.5f); Reset(); } @@ -192,7 +192,7 @@ public: if (ryga->IsAlive() && !ryga->IsInCombat()) { ryga->SetWalk(true); - ryga->SetSpeed(MOVE_WALK, 1.5f); + ryga->SetSpeedRate(MOVE_WALK, 1.5f); ryga->GetMotionMaster()->MovePoint(0, 517.340698f, 3885.03975f, 190.455978f, true); Reset(); } @@ -778,7 +778,7 @@ public: me->AddAura(SPELL_JULES_THREATENS_AURA, me); me->SetCanFly(true); - me->SetSpeed(MOVE_RUN, 0.2f); + me->SetSpeedRate(MOVE_RUN, 0.2f); me->SetFacingTo(3.207566f); me->GetMotionMaster()->MoveJump(exorcismPos[2], 2.0f, 2.0f); @@ -798,7 +798,7 @@ public: break; case ACTION_JULES_MOVE_HOME: wpreached = false; - me->SetSpeed(MOVE_RUN, 1.0f); + me->SetSpeedRate(MOVE_RUN, 1.0f); me->GetMotionMaster()->MovePoint(11, exorcismPos[2]); events.CancelEvent(EVENT_SUMMON_SKULL); diff --git a/src/server/scripts/Outland/zone_netherstorm.cpp b/src/server/scripts/Outland/zone_netherstorm.cpp index d35dedb5d27..8803ce9d9ed 100644 --- a/src/server/scripts/Outland/zone_netherstorm.cpp +++ b/src/server/scripts/Outland/zone_netherstorm.cpp @@ -19,7 +19,7 @@ /* ScriptData SDName: Netherstorm SD%Complete: 80 -SDComment: Quest support: 10337, 10438, 10652 (special flight paths), 10198, 10191 +SDComment: Quest support: 10337, 10652 (special flight paths), 10198, 10191 SDCategory: Netherstorm EndScriptData */ @@ -335,56 +335,6 @@ public: }; /*###### -## npc_professor_dabiri -######*/ -enum ProfessorDabiriData -{ - SPELL_PHASE_DISTRUPTOR = 35780, - - //WHISPER_DABIRI = 0, not existing in database - - QUEST_DIMENSIUS = 10439, - QUEST_ON_NETHERY_WINGS = 10438, -}; - -#define GOSSIP_ITEM "I need a new phase distruptor, Professor" - -class npc_professor_dabiri : public CreatureScript -{ -public: - npc_professor_dabiri() : CreatureScript("npc_professor_dabiri") { } - - //OnQuestAccept: - //if (quest->GetQuestId() == QUEST_DIMENSIUS) - //creature->AI()->Talk(WHISPER_DABIRI, player); - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - creature->CastSpell(player, SPELL_PHASE_DISTRUPTOR, false); - player->CLOSE_GOSSIP_MENU(); - } - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(QUEST_ON_NETHERY_WINGS) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(29778)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - -/*###### ## npc_phase_hunter ######*/ @@ -752,7 +702,6 @@ void AddSC_netherstorm() { new npc_commander_dawnforge(); new at_commander_dawnforge(); - new npc_professor_dabiri(); new npc_phase_hunter(); new npc_bessy(); new npc_maxx_a_million_escort(); diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 7ea87a3c0c4..c91e5c94ca0 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -19,7 +19,7 @@ /* ScriptData SDName: Shadowmoon_Valley SD%Complete: 100 -SDComment: Quest support: 10583, 10601, 10804, 10854, 10458, 10481, 10480, 10781, 10451. Vendor Drake Dealer Hurlunk. +SDComment: Quest support: 10804, 10854, 10458, 10481, 10480, 10781, 10451. SDCategory: Shadowmoon Valley EndScriptData */ @@ -28,9 +28,6 @@ npc_invis_infernal_caster npc_infernal_attacker npc_mature_netherwing_drake npc_enslaved_netherwing_drake -npc_drake_dealer_hurlunk -npcs_flanis_swiftwing_and_kagrosh -npc_karynaku npc_earthmender_wilda npc_torloth_the_magnificent npc_illidari_spawn @@ -90,8 +87,10 @@ public: void SummonInfernal() { - Creature* infernal = me->SummonCreature(NPC_INFERNAL_ATTACKER, me->GetPositionX(), me->GetPositionY(), ground + 0.05f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000); - infernalGUID = infernal->GetGUID(); + if (Creature* infernal = me->SummonCreature(NPC_INFERNAL_ATTACKER, me->GetPositionX(), me->GetPositionY(), ground + 0.05f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000)) + infernalGUID = infernal->GetGUID(); + else + infernalGUID = ObjectGuid::Empty; } void UpdateAI(uint32 diff) override @@ -568,117 +567,6 @@ public: }; }; -/*###### -## npc_drake_dealer_hurlunk -######*/ - -class npc_drake_dealer_hurlunk : public CreatureScript -{ -public: - npc_drake_dealer_hurlunk() : CreatureScript("npc_drake_dealer_hurlunk") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_TRADE) - player->GetSession()->SendListInventory(creature->GetGUID()); - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsVendor() && player->GetReputationRank(1015) == REP_EXALTED) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - -/*###### -## npc_flanis_swiftwing_and_kagrosh -######*/ - -#define GOSSIP_HSK1 "Take Flanis's Pack" -#define GOSSIP_HSK2 "Take Kagrosh's Pack" - -class npcs_flanis_swiftwing_and_kagrosh : public CreatureScript -{ -public: - npcs_flanis_swiftwing_and_kagrosh() : CreatureScript("npcs_flanis_swiftwing_and_kagrosh") { } - - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - ItemPosCountVec dest; - uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30658, 1, NULL); - if (msg == EQUIP_ERR_OK) - { - player->StoreNewItem(dest, 30658, true); - player->PlayerTalkClass->ClearMenus(); - } - } - if (action == GOSSIP_ACTION_INFO_DEF+2) - { - ItemPosCountVec dest; - uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30659, 1, NULL); - if (msg == EQUIP_ERR_OK) - { - player->StoreNewItem(dest, 30659, true); - player->PlayerTalkClass->ClearMenus(); - } - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(10583) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(30658, 1, true)) - player->ADD_GOSSIP_ITEM(0, GOSSIP_HSK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - if (player->GetQuestStatus(10601) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(30659, 1, true)) - player->ADD_GOSSIP_ITEM(0, GOSSIP_HSK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - -/*###### -# npc_karynaku -####*/ - -enum Karynaku -{ - QUEST_ALLY_OF_NETHER = 10870, - QUEST_ZUHULED_THE_WACK = 10866, - - NPC_ZUHULED_THE_WACKED = 11980, - - TAXI_PATH_ID = 649, -}; - -class npc_karynaku : public CreatureScript -{ - public: - npc_karynaku() : CreatureScript("npc_karynaku") { } - - bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override - { - if (quest->GetQuestId() == QUEST_ALLY_OF_NETHER) - player->ActivateTaxiPathTo(TAXI_PATH_ID); - - if (quest->GetQuestId() == QUEST_ZUHULED_THE_WACK) - creature->SummonCreature(NPC_ZUHULED_THE_WACKED, -4204.94f, 316.397f, 122.508f, 1.309f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000); - - return true; - } -}; - /*#### # npc_earthmender_wilda ####*/ @@ -1701,9 +1589,6 @@ void AddSC_shadowmoon_valley() new npc_mature_netherwing_drake(); new npc_enslaved_netherwing_drake(); new npc_dragonmaw_peon(); - new npc_drake_dealer_hurlunk(); - new npcs_flanis_swiftwing_and_kagrosh(); - new npc_karynaku(); new npc_earthmender_wilda(); new npc_lord_illidan_stormrage(); new go_crystal_prison(); diff --git a/src/server/scripts/Outland/zone_shattrath_city.cpp b/src/server/scripts/Outland/zone_shattrath_city.cpp index c734d000077..e4e51a98348 100644 --- a/src/server/scripts/Outland/zone_shattrath_city.cpp +++ b/src/server/scripts/Outland/zone_shattrath_city.cpp @@ -29,7 +29,6 @@ npc_salsalabim npc_shattrathflaskvendors npc_zephyr npc_kservant -npc_ishanah EndContentData */ #include "ScriptMgr.h" @@ -43,13 +42,15 @@ EndContentData */ ## npc_raliq_the_drunk ######*/ -#define GOSSIP_RALIQ "You owe Sim'salabim money. Hand them over or die!" - -enum Raliq +enum RaliqTheDrunk { - SPELL_UPPERCUT = 10966, - QUEST_CRACK_SKULLS = 10009, - FACTION_HOSTILE_RD = 45 + SAY_RALIQ_ATTACK = 0, + OPTION_ID_COLLECT_A_DEBT = 0, + FACTION_OGRE_HOSTILE = 45, + MENU_ID_COLLECT_A_DEBT = 7729, + NPC_TEXT_WUT_YOU_WANT = 9440, + CRACKIN_SOME_SKULLS = 10009, + SPELL_UPPERCUT = 10966 }; class npc_raliq_the_drunk : public CreatureScript @@ -63,7 +64,8 @@ public: if (action == GOSSIP_ACTION_INFO_DEF+1) { player->CLOSE_GOSSIP_MENU(); - creature->setFaction(FACTION_HOSTILE_RD); + creature->setFaction(FACTION_OGRE_HOSTILE); + creature->AI()->Talk(SAY_RALIQ_ATTACK, player); creature->AI()->AttackStart(player); } return true; @@ -71,10 +73,16 @@ public: bool OnGossipHello(Player* player, Creature* creature) override { - if (player->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_RALIQ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(9440, creature->GetGUID()); + if (player->GetQuestStatus(CRACKIN_SOME_SKULLS) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM_DB(MENU_ID_COLLECT_A_DEBT, OPTION_ID_COLLECT_A_DEBT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(NPC_TEXT_WUT_YOU_WANT, creature->GetGUID()); + } + else + { + player->PlayerTalkClass->ClearMenus(); + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + } return true; } @@ -125,16 +133,14 @@ public: enum Salsalabim { - // Factions - FACTION_HOSTILE_SA = 90, - FACTION_FRIENDLY_SA = 35, - - // Quests - QUEST_10004 = 10004, - - // Spells - SPELL_MAGNETIC_PULL = 31705 - + SAY_DEMONIC_AGGRO = 0, + OPTION_ID_ALTRUIS_SENT_ME = 0, + FACTION_FRIENDLY = 35, + FACTION_DEMON_HOSTILE = 90, + MENU_ID_ALTRUIS_SENT_ME = 7725, + NPC_TEXT_SAL_GROWLS_AT_YOU = 9435, + PATIENCE_AND_UNDERSTANDING = 10004, + SPELL_MAGNETIC_PULL = 31705 }; class npc_salsalabim : public CreatureScript @@ -142,13 +148,26 @@ class npc_salsalabim : public CreatureScript public: npc_salsalabim() : CreatureScript("npc_salsalabim") { } - bool OnGossipHello(Player* player, Creature* creature) override + bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override { - if (player->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE) + player->PlayerTalkClass->ClearMenus(); + if (action == GOSSIP_ACTION_INFO_DEF+1) { - creature->setFaction(FACTION_HOSTILE_SA); + player->CLOSE_GOSSIP_MENU(); + creature->setFaction(FACTION_DEMON_HOSTILE); + creature->AI()->Talk(SAY_DEMONIC_AGGRO, player); creature->AI()->AttackStart(player); } + return true; + } + + bool OnGossipHello(Player* player, Creature* creature) override + { + if (player->GetQuestStatus(PATIENCE_AND_UNDERSTANDING) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM_DB(MENU_ID_ALTRUIS_SENT_ME, OPTION_ID_ALTRUIS_SENT_ME, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(NPC_TEXT_SAL_GROWLS_AT_YOU, creature->GetGUID()); + } else { if (creature->IsQuestGiver()) @@ -187,7 +206,7 @@ public: { if (done_by->GetTypeId() == TYPEID_PLAYER && me->HealthBelowPctDamaged(20, damage)) { - done_by->ToPlayer()->GroupEventHappens(QUEST_10004, me); + done_by->ToPlayer()->GroupEventHappens(PATIENCE_AND_UNDERSTANDING, me); damage = 0; EnterEvadeMode(); } @@ -220,6 +239,19 @@ Purchase requires exalted reputation with Scryers/Aldor, Cenarion Expedition and ################################################## */ +enum FlaskVendors +{ + ALDOR_REPUTATION = 932, + SCRYERS_REPUTATION = 934, + THE_SHA_TAR_REPUTATION = 935, + CENARION_EXPEDITION_REP = 942, + NPC_TEXT_EXALTED_ALDOR = 11083, // (need to be exalted with Sha'tar, Cenarion Expedition and the Aldor) + NPC_TEXT_EXALTED_SCRYERS = 11084, // (need to be exalted with Sha'tar, Cenarion Expedition and the Scryers) + NPC_TEXT_WELCOME_NAME = 11085, // Access granted + ARCANIST_XORITH = 23483, // Scryer Apothecary + HALDOR_THE_COMPULSIVE = 23484 // Aldor Apothecary +}; + class npc_shattrathflaskvendors : public CreatureScript { public: @@ -236,31 +268,31 @@ public: bool OnGossipHello(Player* player, Creature* creature) override { - if (creature->GetEntry() == 23484) + if (creature->GetEntry() == HALDOR_THE_COMPULSIVE) { // Aldor vendor - if (creature->IsVendor() && (player->GetReputationRank(932) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED)) + if (creature->IsVendor() && (player->GetReputationRank(ALDOR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(THE_SHA_TAR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(CENARION_EXPEDITION_REP) == REP_EXALTED)) { player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - player->SEND_GOSSIP_MENU(11085, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_WELCOME_NAME, creature->GetGUID()); } else { - player->SEND_GOSSIP_MENU(11083, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_EXALTED_ALDOR, creature->GetGUID()); } } - if (creature->GetEntry() == 23483) + if (creature->GetEntry() == ARCANIST_XORITH) { // Scryers vendor - if (creature->IsVendor() && (player->GetReputationRank(934) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED)) + if (creature->IsVendor() && (player->GetReputationRank(SCRYERS_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(THE_SHA_TAR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(CENARION_EXPEDITION_REP) == REP_EXALTED)) { player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - player->SEND_GOSSIP_MENU(11085, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_WELCOME_NAME, creature->GetGUID()); } else { - player->SEND_GOSSIP_MENU(11084, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_EXALTED_SCRYERS, creature->GetGUID()); } } @@ -272,7 +304,13 @@ public: # npc_zephyr ######*/ -#define GOSSIP_HZ "Take me to the Caverns of Time." +enum Zephyr +{ + OPTION_ID_TAKE_ME_TO_C_O_T = 0, + KEEPERS_OF_TIME_REPUTATION = 989, + MENU_ID_TAKE_ME_TO_C_O_T = 9205, + TELEPORT_CAVERNS_OF_TIME = 37778 +}; class npc_zephyr : public CreatureScript { @@ -283,15 +321,15 @@ public: { player->PlayerTalkClass->ClearMenus(); if (action == GOSSIP_ACTION_INFO_DEF+1) - player->CastSpell(player, 37778, false); + player->CastSpell(player, TELEPORT_CAVERNS_OF_TIME, false); return true; } bool OnGossipHello(Player* player, Creature* creature) override { - if (player->GetReputationRank(989) >= REP_REVERED) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HZ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if (player->GetReputationRank(KEEPERS_OF_TIME_REPUTATION) >= REP_REVERED) + player->ADD_GOSSIP_ITEM_DB(MENU_ID_TAKE_ME_TO_C_O_T, OPTION_ID_TAKE_ME_TO_C_O_T, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -305,28 +343,29 @@ public: enum KServant { - SAY1 = 0, - WHISP1 = 1, - WHISP2 = 2, - WHISP3 = 3, - WHISP4 = 4, - WHISP5 = 5, - WHISP6 = 6, - WHISP7 = 7, - WHISP8 = 8, - WHISP9 = 9, - WHISP10 = 10, - WHISP11 = 11, - WHISP12 = 12, - WHISP13 = 13, - WHISP14 = 14, - WHISP15 = 15, - WHISP16 = 16, - WHISP17 = 17, - WHISP18 = 18, - WHISP19 = 19, - WHISP20 = 20, - WHISP21 = 21 + SAY1 = 0, + WHISP1 = 1, + WHISP2 = 2, + WHISP3 = 3, + WHISP4 = 4, + WHISP5 = 5, + WHISP6 = 6, + WHISP7 = 7, + WHISP8 = 8, + WHISP9 = 9, + WHISP10 = 10, + WHISP11 = 11, + WHISP12 = 12, + WHISP13 = 13, + WHISP14 = 14, + WHISP15 = 15, + WHISP16 = 16, + WHISP17 = 17, + WHISP18 = 18, + WHISP19 = 19, + WHISP20 = 20, + WHISP21 = 21, + CITY_OF_LIGHT = 10211 }; class npc_kservant : public CreatureScript @@ -417,7 +456,7 @@ public: break; case 56: Talk(WHISP21, player); - player->GroupEventHappens(10211, me); + player->GroupEventHappens(CITY_OF_LIGHT, me); break; } } @@ -429,7 +468,7 @@ public: return; Player* player = who->ToPlayer(); - if (player && player->GetQuestStatus(10211) == QUEST_STATUS_INCOMPLETE) + if (player && player->GetQuestStatus(CITY_OF_LIGHT) == QUEST_STATUS_INCOMPLETE) { float Radius = 10.0f; if (me->IsWithinDistInMap(who, Radius)) @@ -443,43 +482,6 @@ public: }; }; -/*###### -# npc_ishanah -######*/ - -#define ISANAH_GOSSIP_1 "Who are the Sha'tar?" -#define ISANAH_GOSSIP_2 "Isn't Shattrath a draenei city? Why do you allow others here?" - -class npc_ishanah : public CreatureScript -{ -public: - npc_ishanah() : CreatureScript("npc_ishanah") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - player->SEND_GOSSIP_MENU(9458, creature->GetGUID()); - else if (action == GOSSIP_ACTION_INFO_DEF+2) - player->SEND_GOSSIP_MENU(9459, creature->GetGUID()); - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - void AddSC_shattrath_city() { new npc_raliq_the_drunk(); @@ -487,5 +489,4 @@ void AddSC_shattrath_city() new npc_shattrathflaskvendors(); new npc_zephyr(); new npc_kservant(); - new npc_ishanah(); } diff --git a/src/server/scripts/Outland/zone_terokkar_forest.cpp b/src/server/scripts/Outland/zone_terokkar_forest.cpp index 06a8af947b7..4b757544d65 100644 --- a/src/server/scripts/Outland/zone_terokkar_forest.cpp +++ b/src/server/scripts/Outland/zone_terokkar_forest.cpp @@ -27,7 +27,6 @@ EndScriptData */ npc_unkor_the_ruthless npc_infested_root_walker npc_rotting_forest_rager -npc_netherweb_victim npc_floon npc_isla_starmane npc_slim @@ -47,13 +46,13 @@ EndContentData */ enum UnkorTheRuthless { - SAY_SUBMIT = 0, - - FACTION_HOSTILE = 45, - FACTION_FRIENDLY = 35, - QUEST_DONTKILLTHEFATONE = 9889, - - SPELL_PULVERIZE = 2676 + SAY_SUBMIT = 0, + REQUIRED_KILL_COUNT = 10, + FACTION_FRIENDLY = 35, + FACTION_HOSTILE = 45, + SPELL_PULVERIZE = 2676, + QUEST_DONTKILLTHEFATONE = 9889, + NPC_BOULDERFIST_INVADER = 18260 }; class npc_unkor_the_ruthless : public CreatureScript @@ -117,7 +116,7 @@ public: Player* groupie = itr->GetSource(); if (groupie && groupie->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && - groupie->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, 18260) == 10) + groupie->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, NPC_BOULDERFIST_INVADER) == REQUIRED_KILL_COUNT) { groupie->AreaExploredOrEventHappens(QUEST_DONTKILLTHEFATONE); if (!CanDoQuest) @@ -126,7 +125,7 @@ public: } } else if (player->GetQuestStatus(QUEST_DONTKILLTHEFATONE) == QUEST_STATUS_INCOMPLETE && - player->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, 18260) == 10) + player->GetReqKillOrCastCurrentCount(QUEST_DONTKILLTHEFATONE, NPC_BOULDERFIST_INVADER) == REQUIRED_KILL_COUNT) { player->AreaExploredOrEventHappens(QUEST_DONTKILLTHEFATONE); CanDoQuest = true; @@ -171,6 +170,11 @@ public: ## npc_infested_root_walker ######*/ +enum InfestedRootWalker +{ + SPELL_SUMMON_WOOD_MITES = 39130 +}; + class npc_infested_root_walker : public CreatureScript { public: @@ -194,7 +198,7 @@ public: if (me->GetHealth() <= damage) if (rand32() % 100 < 75) //Summon Wood Mites - DoCast(me, 39130, true); + DoCast(me, SPELL_SUMMON_WOOD_MITES, true); } }; }; @@ -202,6 +206,12 @@ public: /*###### ## npc_skywing ######*/ + +enum Skywing +{ + QUEST_SKYWING = 10898 +}; + class npc_skywing : public CreatureScript { public: @@ -226,7 +236,7 @@ public: switch (waypointId) { case 8: - player->AreaExploredOrEventHappens(10898); + player->AreaExploredOrEventHappens(QUEST_SKYWING); break; } } @@ -240,7 +250,7 @@ public: return; Player* player = who->ToPlayer(); - if (player && player->GetQuestStatus(10898) == QUEST_STATUS_INCOMPLETE) + if (player && player->GetQuestStatus(QUEST_SKYWING) == QUEST_STATUS_INCOMPLETE) if (me->IsWithinDistInMap(who, 10.0f)) Start(false, false, who->GetGUID()); } @@ -258,6 +268,11 @@ public: ## npc_rotting_forest_rager ######*/ +enum RottingForestRager +{ + SPELL_SUMMON_LOTS_OF_WOOD_MITES = 39134 +}; + class npc_rotting_forest_rager : public CreatureScript { public: @@ -280,67 +295,8 @@ public: if (done_by->GetTypeId() == TYPEID_PLAYER) if (me->GetHealth() <= damage) if (rand32() % 100 < 75) - //Summon Lots of Wood Mights - DoCast(me, 39134, true); - } - }; -}; - -/*###### -## npc_netherweb_victim -######*/ - -enum NetherwebVictim -{ - QUEST_TARGET = 22459 - //SPELL_FREE_WEBBED = 38950 -}; - -const uint32 netherwebVictims[6] = -{ - 18470, 16805, 21242, 18452, 22482, 21285 -}; - -class npc_netherweb_victim : public CreatureScript -{ -public: - npc_netherweb_victim() : CreatureScript("npc_netherweb_victim") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_netherweb_victimAI(creature); - } - - struct npc_netherweb_victimAI : public ScriptedAI - { - npc_netherweb_victimAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override { } - void EnterCombat(Unit* /*who*/) override { } - void MoveInLineOfSight(Unit* /*who*/) override { } - - - void JustDied(Unit* killer) override - { - Player* player = killer->ToPlayer(); - if (!player) - return; - - if (player->GetQuestStatus(10873) == QUEST_STATUS_INCOMPLETE) - { - if (rand32() % 100 < 25) - { - me->SummonCreature(QUEST_TARGET, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - player->KilledMonsterCredit(QUEST_TARGET); - } - else - me->SummonCreature(netherwebVictims[rand32() % 6], 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - - if (rand32() % 100 < 75) - me->SummonCreature(netherwebVictims[rand32() % 6], 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - - me->SummonCreature(netherwebVictims[rand32() % 6], 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000); - } + //Summon Lots of Wood Mites + DoCast(me, SPELL_SUMMON_LOTS_OF_WOOD_MITES, true); } }; }; @@ -349,19 +305,22 @@ public: ## npc_floon ######*/ -#define GOSSIP_FLOON1 "You owe Sim'salabim money. Hand them over or die!" -#define GOSSIP_FLOON2 "Hand over the money or die...again!" - enum Floon { - SAY_FLOON_ATTACK = 0, - - SPELL_SILENCE = 6726, - SPELL_FROSTBOLT = 9672, - SPELL_FROST_NOVA = 11831, - - FACTION_HOSTILE_FL = 1738, - QUEST_CRACK_SKULLS = 10009 + SAY_FLOON_ATTACK = 0, + OPTION_ID_PAY_UP_OR_DIE = 0, + OPTION_ID_COLLECT_A_DEBT = 0, + FACTION_HOSTILE_FLOON = 1738, + MENU_ID_PAY_UP_OR_DIE = 7731, + MENU_ID_COLLECT_A_DEBT = 7732, + GOSSIP_FLOON_STRANGE_SOUNDS = 9442, + GOSSIP_HE_ALREADY_KILLED_ME = 9443, + + SPELL_SILENCE = 6726, + SPELL_FROSTBOLT = 9672, + SPELL_FROST_NOVA = 11831, + + QUEST_CRACKIN_SOME_SKULLS = 10009 }; class npc_floon : public CreatureScript @@ -374,13 +333,13 @@ public: player->PlayerTalkClass->ClearMenus(); if (action == GOSSIP_ACTION_INFO_DEF) { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FLOON2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(9443, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(MENU_ID_PAY_UP_OR_DIE, OPTION_ID_PAY_UP_OR_DIE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(GOSSIP_HE_ALREADY_KILLED_ME, creature->GetGUID()); } if (action == GOSSIP_ACTION_INFO_DEF+1) { player->CLOSE_GOSSIP_MENU(); - creature->setFaction(FACTION_HOSTILE_FL); + creature->setFaction(FACTION_HOSTILE_FLOON); creature->AI()->Talk(SAY_FLOON_ATTACK, player); creature->AI()->AttackStart(player); } @@ -389,10 +348,10 @@ public: bool OnGossipHello(Player* player, Creature* creature) override { - if (player->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FLOON1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + if (player->GetQuestStatus(QUEST_CRACKIN_SOME_SKULLS) == QUEST_STATUS_INCOMPLETE) + player->ADD_GOSSIP_ITEM_DB(MENU_ID_COLLECT_A_DEBT, OPTION_ID_COLLECT_A_DEBT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - player->SEND_GOSSIP_MENU(9442, creature->GetGUID()); + player->SEND_GOSSIP_MENU(GOSSIP_FLOON_STRANGE_SOUNDS, creature->GetGUID()); return true; } @@ -463,15 +422,16 @@ public: ######*/ enum IslaStarmaneData { - SAY_PROGRESS_1 = 0, - SAY_PROGRESS_2 = 1, - SAY_PROGRESS_3 = 2, - SAY_PROGRESS_4 = 3, - - QUEST_EFTW_H = 10052, - QUEST_EFTW_A = 10051, - GO_CAGE = 182794, - SPELL_CAT = 32447, + SAY_PROGRESS_1 = 0, + SAY_PROGRESS_2 = 1, + SAY_PROGRESS_3 = 2, + SAY_PROGRESS_4 = 3, + GO_DISTANCE = 10, + FACTION_ESCORTEE = 113, + ESCAPE_FROM_FIREWING_POINT_A = 10051, + ESCAPE_FROM_FIREWING_POINT_H = 10052, + SPELL_TRAVEL_FORM_CAT = 32447, + GO_CAGE = 182794 }; class npc_isla_starmane : public CreatureScript @@ -492,7 +452,7 @@ public: switch (waypointId) { case 0: - if (GameObject* Cage = me->FindNearestGameObject(GO_CAGE, 10)) + if (GameObject* Cage = me->FindNearestGameObject(GO_CAGE, GO_DISTANCE)) Cage->SetGoState(GO_STATE_ACTIVE); break; case 2: @@ -507,16 +467,16 @@ public: case 29: Talk(SAY_PROGRESS_4, player); if (player->GetTeam() == ALLIANCE) - player->GroupEventHappens(QUEST_EFTW_A, me); + player->GroupEventHappens(ESCAPE_FROM_FIREWING_POINT_A, me); else if (player->GetTeam() == HORDE) - player->GroupEventHappens(QUEST_EFTW_H, me); + player->GroupEventHappens(ESCAPE_FROM_FIREWING_POINT_H, me); me->SetInFront(player); break; case 30: me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE); break; case 31: - DoCast(me, SPELL_CAT); + DoCast(me, SPELL_TRAVEL_FORM_CAT); me->SetWalk(false); break; } @@ -532,19 +492,19 @@ public: if (Player* player = GetPlayerForEscort()) { if (player->GetTeam() == ALLIANCE) - player->FailQuest(QUEST_EFTW_A); + player->FailQuest(ESCAPE_FROM_FIREWING_POINT_A); else if (player->GetTeam() == HORDE) - player->FailQuest(QUEST_EFTW_H); + player->FailQuest(ESCAPE_FROM_FIREWING_POINT_H); } } }; bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override { - if (quest->GetQuestId() == QUEST_EFTW_H || quest->GetQuestId() == QUEST_EFTW_A) + if (quest->GetQuestId() == ESCAPE_FROM_FIREWING_POINT_H || quest->GetQuestId() == ESCAPE_FROM_FIREWING_POINT_A) { ENSURE_AI(npc_escortAI, (creature->AI()))->Start(true, false, player->GetGUID()); - creature->setFaction(113); + creature->setFaction(FACTION_ESCORTEE); } return true; } @@ -558,10 +518,20 @@ public: /*###### ## go_skull_pile ######*/ -#define GOSSIP_S_DARKSCREECHER_AKKARAI "Summon Darkscreecher Akkarai" -#define GOSSIP_S_KARROG "Summon Karrog" -#define GOSSIP_S_GEZZARAK_THE_HUNTRESS "Summon Gezzarak the Huntress" -#define GOSSIP_S_VAKKIZ_THE_WINDRAGER "Summon Vakkiz the Windrager" + +enum SkullPile +{ + OPTION_ID_GEZZARAK_THE_HUNTRESS = 0, + OPTION_ID_DARKSCREECHER_AKKARAI = 1, + OPTION_ID_KARROG = 2, + OPTION_ID_VAKKIZ_THE_WINDRAGER = 3, + GOSSIP_MENU_ID_SKULL_PILE = 8660, + ADVERSARIAL_BLOOD = 11885, + SUMMON_GEZZARAK_THE_HUNTRESS = 40632, + SUMMON_KARROG = 40640, + SUMMON_DARKSCREECHER_AKKARAI = 40642, + SUMMON_VAKKIZ_THE_WINDRAGER = 40644 +}; class go_skull_pile : public GameObjectScript { @@ -580,12 +550,12 @@ public: bool OnGossipHello(Player* player, GameObject* go) override { - if ((player->GetQuestStatus(11885) == QUEST_STATUS_INCOMPLETE) || player->GetQuestRewardStatus(11885)) + if ((player->GetQuestStatus(ADVERSARIAL_BLOOD) == QUEST_STATUS_INCOMPLETE) || player->GetQuestRewardStatus(ADVERSARIAL_BLOOD)) { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_DARKSCREECHER_AKKARAI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_KARROG, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_GEZZARAK_THE_HUNTRESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_S_VAKKIZ_THE_WINDRAGER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_ID_SKULL_PILE, OPTION_ID_GEZZARAK_THE_HUNTRESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_ID_SKULL_PILE, OPTION_ID_DARKSCREECHER_AKKARAI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_ID_SKULL_PILE, OPTION_ID_KARROG, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_ID_SKULL_PILE, OPTION_ID_VAKKIZ_THE_WINDRAGER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); } player->SEND_GOSSIP_MENU(go->GetGOInfo()->questgiver.gossipID, go->GetGUID()); @@ -597,16 +567,16 @@ public: switch (action) { case GOSSIP_ACTION_INFO_DEF + 1: - player->CastSpell(player, 40642, false); + player->CastSpell(player, SUMMON_GEZZARAK_THE_HUNTRESS, false); break; case GOSSIP_ACTION_INFO_DEF + 2: - player->CastSpell(player, 40640, false); + player->CastSpell(player, SUMMON_DARKSCREECHER_AKKARAI, false); break; case GOSSIP_ACTION_INFO_DEF + 3: - player->CastSpell(player, 40632, false); + player->CastSpell(player, SUMMON_KARROG, false); break; case GOSSIP_ACTION_INFO_DEF + 4: - player->CastSpell(player, 40644, false); + player->CastSpell(player, SUMMON_VAKKIZ_THE_WINDRAGER, false); break; } } @@ -618,7 +588,9 @@ public: enum Slim { - FACTION_CONSORTIUM = 933 + FACTION_CONSORTIUM = 933, + NPC_TEXT_NEITHER_SLIM_NOR_SHADY = 9895, + NPC_TEXT_I_SEE_YOU_ARE_A_FRIEND = 9896 }; class npc_slim : public CreatureScript @@ -640,10 +612,10 @@ public: if (creature->IsVendor() && player->GetReputationRank(FACTION_CONSORTIUM) >= REP_FRIENDLY) { player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - player->SEND_GOSSIP_MENU(9896, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_I_SEE_YOU_ARE_A_FRIEND, creature->GetGUID()); } else - player->SEND_GOSSIP_MENU(9895, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_NEITHER_SLIM_NOR_SHADY, creature->GetGUID()); return true; } @@ -719,7 +691,6 @@ void AddSC_terokkar_forest() new npc_unkor_the_ruthless(); new npc_infested_root_walker(); new npc_rotting_forest_rager(); - new npc_netherweb_victim(); new npc_floon(); new npc_isla_starmane(); new go_skull_pile(); diff --git a/src/server/scripts/Pet/CMakeLists.txt b/src/server/scripts/Pet/CMakeLists.txt deleted file mode 100644 index 9ca268a9a3f..00000000000 --- a/src/server/scripts/Pet/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - Pet/pet_dk.cpp - Pet/pet_generic.cpp - Pet/pet_hunter.cpp - Pet/pet_mage.cpp - Pet/pet_priest.cpp - Pet/pet_shaman.cpp -) - -message(" -> Prepared: Pet") diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp index 80b3a00774b..113b14a0d54 100644 --- a/src/server/scripts/Pet/pet_dk.cpp +++ b/src/server/scripts/Pet/pet_dk.cpp @@ -103,8 +103,8 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript //! HACK: Creature's can't have MOVEMENTFLAG_FLYING // Fly Away me->SetCanFly(true); - me->SetSpeed(MOVE_FLIGHT, 0.75f, true); - me->SetSpeed(MOVE_RUN, 0.75f, true); + me->SetSpeedRate(MOVE_FLIGHT, 0.75f); + me->SetSpeedRate(MOVE_RUN, 0.75f); float x = me->GetPositionX() + 20 * std::cos(me->GetOrientation()); float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation()); float z = me->GetPositionZ() + 40; diff --git a/src/server/scripts/Pet/pet_generic.cpp b/src/server/scripts/Pet/pet_generic.cpp index 35455bc474b..ff57bc0415c 100644 --- a/src/server/scripts/Pet/pet_generic.cpp +++ b/src/server/scripts/Pet/pet_generic.cpp @@ -20,10 +20,239 @@ * Scriptnames of files in this file should be prefixed with "npc_pet_gen_". */ + /* ContentData + npc_pet_gen_baby_blizzard_bear 100% Baby Blizzard Bear sits down occasionally + npc_pet_gen_egbert 100% Egbert run's around + npc_pet_gen_pandaren_monk 100% Pandaren Monk drinks and bows with you + npc_pet_gen_mojo 100% Mojo follows you when you kiss it + EndContentData */ + #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "PassiveAI.h" #include "Player.h" +enum BabyBlizzardBearMisc +{ + SPELL_BBB_PET_SIT = 61853, + EVENT_BBB_PET_SIT = 1, + EVENT_BBB_PET_SIT_INTER = 2 +}; + +class npc_pet_gen_baby_blizzard_bear : public CreatureScript +{ +public: + npc_pet_gen_baby_blizzard_bear() : CreatureScript("npc_pet_gen_baby_blizzard_bear") {} + + struct npc_pet_gen_baby_blizzard_bearAI : public NullCreatureAI + { + npc_pet_gen_baby_blizzard_bearAI(Creature* creature) : NullCreatureAI(creature) + { + if (Unit* owner = me->GetCharmerOrOwner()) + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); + _events.ScheduleEvent(EVENT_BBB_PET_SIT, urandms(10, 30)); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + if (Unit* owner = me->GetCharmerOrOwner()) + if (!me->IsWithinDist(owner, 25.f)) + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BBB_PET_SIT: + me->CastSpell(me, SPELL_BBB_PET_SIT, false); + _events.ScheduleEvent(EVENT_BBB_PET_SIT_INTER, urandms(15, 30)); + break; + case EVENT_BBB_PET_SIT_INTER: + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + _events.ScheduleEvent(EVENT_BBB_PET_SIT, urandms(10, 30)); + break; + default: + break; + } + } + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_pet_gen_baby_blizzard_bearAI(creature); + } +}; + +enum EgbertMisc +{ + SPELL_EGBERT = 40669, + EVENT_RETURN = 3 +}; + +class npc_pet_gen_egbert : public CreatureScript +{ +public: + npc_pet_gen_egbert() : CreatureScript("npc_pet_gen_egbert") {} + + struct npc_pet_gen_egbertAI : public NullCreatureAI + { + npc_pet_gen_egbertAI(Creature* creature) : NullCreatureAI(creature) + { + if (Unit* owner = me->GetCharmerOrOwner()) + if (owner->GetMap()->GetEntry()->addon > 1) + me->SetCanFly(true); + } + + void Reset() override + { + _events.Reset(); + if (Unit* owner = me->GetCharmerOrOwner()) + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); + } + + void EnterEvadeMode(EvadeReason why) override + { + if (!_EnterEvadeMode(why)) + return; + + Reset(); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + if (Unit* owner = me->GetCharmerOrOwner()) + { + if (!me->IsWithinDist(owner, 40.f)) + { + me->RemoveAura(SPELL_EGBERT); + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); + } + } + + if (me->HasAura(SPELL_EGBERT)) + _events.ScheduleEvent(EVENT_RETURN, urandms(5, 20)); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_RETURN: + me->RemoveAura(SPELL_EGBERT); + break; + default: + break; + } + } + } + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_pet_gen_egbertAI(creature); + } +}; + +enum PandarenMonkMisc +{ + SPELL_PANDAREN_MONK = 69800, + EVENT_FOCUS = 1, + EVENT_EMOTE = 2, + EVENT_FOLLOW = 3, + EVENT_DRINK = 4 +}; + +class npc_pet_gen_pandaren_monk : public CreatureScript +{ +public: + npc_pet_gen_pandaren_monk() : CreatureScript("npc_pet_gen_pandaren_monk") {} + + struct npc_pet_gen_pandaren_monkAI : public NullCreatureAI + { + npc_pet_gen_pandaren_monkAI(Creature* creature) : NullCreatureAI(creature) { } + + void Reset() override + { + _events.Reset(); + _events.ScheduleEvent(EVENT_FOCUS, 1000); + } + + void EnterEvadeMode(EvadeReason why) override + { + if (!_EnterEvadeMode(why)) + return; + + Reset(); + } + + void ReceiveEmote(Player* /*player*/, uint32 emote) override + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + me->StopMoving(); + + switch (emote) + { + case TEXT_EMOTE_BOW: + _events.ScheduleEvent(EVENT_FOCUS, 1000); + break; + case TEXT_EMOTE_DRINK: + _events.ScheduleEvent(EVENT_DRINK, 1000); + break; + } + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + if (Unit* owner = me->GetCharmerOrOwner()) + if (!me->IsWithinDist(owner, 30.f)) + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FOCUS: + if (Unit* owner = me->GetCharmerOrOwner()) + me->SetFacingToObject(owner); + _events.ScheduleEvent(EVENT_EMOTE, 1000); + break; + case EVENT_EMOTE: + me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); + _events.ScheduleEvent(EVENT_FOLLOW, 1000); + break; + case EVENT_FOLLOW: + if (Unit* owner = me->GetCharmerOrOwner()) + me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + break; + case EVENT_DRINK: + me->CastSpell(me, SPELL_PANDAREN_MONK, false); + break; + default: + break; + } + } + } + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_pet_gen_pandaren_monkAI(creature); + } +}; + enum Mojo { SAY_MOJO = 0, @@ -89,5 +318,8 @@ class npc_pet_gen_mojo : public CreatureScript void AddSC_generic_pet_scripts() { + new npc_pet_gen_baby_blizzard_bear(); + new npc_pet_gen_egbert(); + new npc_pet_gen_pandaren_monk(); new npc_pet_gen_mojo(); } diff --git a/src/server/scripts/Pet/pet_script_loader.cpp b/src/server/scripts/Pet/pet_script_loader.cpp new file mode 100644 index 00000000000..c3c0079fd46 --- /dev/null +++ b/src/server/scripts/Pet/pet_script_loader.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +void AddSC_deathknight_pet_scripts(); +void AddSC_generic_pet_scripts(); +void AddSC_hunter_pet_scripts(); +void AddSC_mage_pet_scripts(); +void AddSC_priest_pet_scripts(); +void AddSC_shaman_pet_scripts(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddPetScripts() +{ + AddSC_deathknight_pet_scripts(); + AddSC_generic_pet_scripts(); + AddSC_hunter_pet_scripts(); + AddSC_mage_pet_scripts(); + AddSC_priest_pet_scripts(); + AddSC_shaman_pet_scripts(); +} diff --git a/src/server/scripts/ScriptLoader.cpp.in.cmake b/src/server/scripts/ScriptLoader.cpp.in.cmake new file mode 100644 index 00000000000..33c336a9a93 --- /dev/null +++ b/src/server/scripts/ScriptLoader.cpp.in.cmake @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This file was created automatically from your script configuration! +// Use CMake to reconfigure this file, never change it on your own! + +#cmakedefine TRINITY_IS_DYNAMIC_SCRIPTLOADER + +#include "Define.h" +#include <vector> +#include <string> + +@TRINITY_SCRIPTS_FORWARD_DECL@ +#ifdef TRINITY_IS_DYNAMIC_SCRIPTLOADER +# include "revision_data.h" +# define TC_SCRIPT_API TC_API_EXPORT +extern "C" { + +/// Exposed in script modules to return the script module revision hash. +TC_SCRIPT_API char const* GetScriptModuleRevisionHash() +{ + return _HASH; +} + +/// Exposed in script module to return the name of the script module +/// contained in this shared library. +TC_SCRIPT_API char const* GetScriptModule() +{ + return "@TRINITY_CURRENT_SCRIPT_PROJECT@"; +} + +#else +# include "ScriptLoader.h" +# define TC_SCRIPT_API +#endif + +/// Exposed in script modules to register all scripts to the ScriptMgr. +TC_SCRIPT_API void AddScripts() +{ +@TRINITY_SCRIPTS_INVOKE@} + +/// Exposed in script modules to get the build directive of the module. +TC_SCRIPT_API char const* GetBuildDirective() +{ + return _BUILD_DIRECTIVE; +} + +#ifdef TRINITY_IS_DYNAMIC_SCRIPTLOADER +} // extern "C" +#endif diff --git a/src/server/scripts/ScriptLoader.h b/src/server/scripts/ScriptLoader.h new file mode 100644 index 00000000000..57b62df22d1 --- /dev/null +++ b/src/server/scripts/ScriptLoader.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SC_SCRIPTLOADER_H +#define SC_SCRIPTLOADER_H + +void AddScripts(); + +#endif diff --git a/src/server/scripts/PrecompiledHeaders/ScriptPCH.cpp b/src/server/scripts/ScriptPCH.cpp index 41fecf3c60d..41fecf3c60d 100644 --- a/src/server/scripts/PrecompiledHeaders/ScriptPCH.cpp +++ b/src/server/scripts/ScriptPCH.cpp diff --git a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h b/src/server/scripts/ScriptPCH.h index 1cd25309055..1cd25309055 100644 --- a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h +++ b/src/server/scripts/ScriptPCH.h diff --git a/src/server/scripts/Spells/CMakeLists.txt b/src/server/scripts/Spells/CMakeLists.txt deleted file mode 100644 index 7434d98cf49..00000000000 --- a/src/server/scripts/Spells/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - Spells/spell_shaman.cpp - Spells/spell_hunter.cpp - Spells/spell_rogue.cpp - Spells/spell_druid.cpp - Spells/spell_dk.cpp - Spells/spell_quest.cpp - Spells/spell_warrior.cpp - Spells/spell_generic.cpp - Spells/spell_warlock.cpp - Spells/spell_priest.cpp - Spells/spell_mage.cpp - Spells/spell_paladin.cpp - Spells/spell_item.cpp - Spells/spell_holiday.cpp - Spells/spell_pet.cpp -) - -message(" -> Prepared: Spells") diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 3cea620559a..980c0db19cc 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -22,7 +22,7 @@ */ #include "Player.h" -#include "UnitAI.h" +#include "PlayerAI.h" #include "ScriptMgr.h" #include "SpellScript.h" #include "SpellAuraEffects.h" @@ -30,6 +30,13 @@ enum DeathKnightSpells { + SPELL_DK_ACCLIMATION_HOLY = 50490, + SPELL_DK_ACCLIMATION_FIRE = 50362, + SPELL_DK_ACCLIMATION_FROST = 50485, + SPELL_DK_ACCLIMATION_ARCANE = 50486, + SPELL_DK_ACCLIMATION_SHADOW = 50489, + SPELL_DK_ACCLIMATION_NATURE = 50488, + SPELL_DK_ADVANTAGE_T10_4P_MELEE = 70657, SPELL_DK_ANTI_MAGIC_SHELL_TALENT = 51052, SPELL_DK_BLACK_ICE_R1 = 49140, SPELL_DK_BLOOD_BOIL_TRIGGERED = 65658, @@ -51,6 +58,7 @@ enum DeathKnightSpells SPELL_DK_IMPROVED_BLOOD_PRESENCE_R1 = 50365, SPELL_DK_IMPROVED_FROST_PRESENCE_R1 = 50384, SPELL_DK_IMPROVED_UNHOLY_PRESENCE_R1 = 50391, + SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL = 50475, SPELL_DK_IMPROVED_BLOOD_PRESENCE_TRIGGERED = 63611, SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622, SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART = 64962, @@ -65,8 +73,6 @@ enum DeathKnightSpells SPELL_DK_UNHOLY_PRESENCE_TRIGGERED = 49772, SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1 = 49189, SPELL_DK_WILL_OF_THE_NECROPOLIS_AURA_R1 = 52284, - SPELL_DK_RAISE_ALLY_INITIAL = 61999, - SPELL_DK_RAISE_ALLY = 46619, SPELL_DK_GHOUL_THRASH = 47480 }; @@ -80,6 +86,141 @@ enum Misc NPC_DK_GHOUL = 26125 }; +// -49200 - Acclimation +class spell_dk_acclimation : public SpellScriptLoader +{ +public: + spell_dk_acclimation() : SpellScriptLoader("spell_dk_acclimation") { } + + class spell_dk_acclimation_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_acclimation_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_HOLY) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_FIRE) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_FROST) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_NATURE) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_SHADOW) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_ARCANE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetDamageInfo()) + { + switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + case SPELL_SCHOOL_FIRE: + case SPELL_SCHOOL_NATURE: + case SPELL_SCHOOL_FROST: + case SPELL_SCHOOL_SHADOW: + case SPELL_SCHOOL_ARCANE: + return true; + default: + break; + } + } + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + uint32 triggerspell = 0; + + switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + triggerspell = SPELL_DK_ACCLIMATION_HOLY; + break; + case SPELL_SCHOOL_FIRE: + triggerspell = SPELL_DK_ACCLIMATION_FIRE; + break; + case SPELL_SCHOOL_NATURE: + triggerspell = SPELL_DK_ACCLIMATION_NATURE; + break; + case SPELL_SCHOOL_FROST: + triggerspell = SPELL_DK_ACCLIMATION_FROST; + break; + case SPELL_SCHOOL_SHADOW: + triggerspell = SPELL_DK_ACCLIMATION_SHADOW; + break; + case SPELL_SCHOOL_ARCANE: + triggerspell = SPELL_DK_ACCLIMATION_ARCANE; + break; + default: + return; + } + + if (Unit* target = eventInfo.GetActionTarget()) + target->CastSpell(target, triggerspell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dk_acclimation_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dk_acclimation_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dk_acclimation_AuraScript(); + } +}; + +// 70656 - Advantage (T10 4P Melee Bonus) +class spell_dk_advantage_t10_4p : public SpellScriptLoader +{ +public: + spell_dk_advantage_t10_4p() : SpellScriptLoader("spell_dk_advantage_t10_4p") { } + + class spell_dk_advantage_t10_4p_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_advantage_t10_4p_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_ADVANTAGE_T10_4P_MELEE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (Unit* caster = eventInfo.GetActor()) + { + if (caster->GetTypeId() != TYPEID_PLAYER || caster->getClass() != CLASS_DEATH_KNIGHT) + return false; + + for (uint8 i = 0; i < MAX_RUNES; ++i) + if (caster->ToPlayer()->GetRuneCooldown(i) == 0) + return false; + + return true; + } + + return false; + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dk_advantage_t10_4p_AuraScript::CheckProc); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dk_advantage_t10_4p_AuraScript(); + } +}; + // 50462 - Anti-Magic Shell (on raid member) class spell_dk_anti_magic_shell_raid : public SpellScriptLoader { @@ -228,7 +369,7 @@ class spell_dk_anti_magic_zone : public SpellScriptLoader void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/) { - SpellInfo const* talentSpell = sSpellMgr->EnsureSpellInfo(SPELL_DK_ANTI_MAGIC_SHELL_TALENT); + SpellInfo const* talentSpell = sSpellMgr->AssertSpellInfo(SPELL_DK_ANTI_MAGIC_SHELL_TALENT); amount = talentSpell->Effects[EFFECT_0].CalcValue(GetCaster()); if (Player* player = GetCaster()->ToPlayer()) amount += int32(2 * player->GetTotalAttackPowerValue(BASE_ATTACK)); @@ -921,6 +1062,52 @@ class spell_dk_improved_blood_presence : public SpellScriptLoader } }; +// 63611 - Improved Blood Presence Triggered +class spell_dk_improved_blood_presence_triggered : public SpellScriptLoader +{ +public: + spell_dk_improved_blood_presence_triggered() : SpellScriptLoader("spell_dk_improved_blood_presence_triggered") { } + + class spell_dk_improved_blood_presence_triggered_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_improved_blood_presence_triggered_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetActor()->GetTypeId() == TYPEID_PLAYER) + return true; + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) + eventInfo.GetActor()->CastCustomSpell(SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL, SPELLVALUE_BASE_POINT0, CalculatePct(int32(dmgInfo->GetDamage()), aurEff->GetAmount()), + eventInfo.GetActor(), true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dk_improved_blood_presence_triggered_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dk_improved_blood_presence_triggered_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dk_improved_blood_presence_triggered_AuraScript(); + } +}; + // -50384 - Improved Frost Presence class spell_dk_improved_frost_presence : public SpellScriptLoader { @@ -1636,7 +1823,7 @@ class spell_dk_will_of_the_necropolis : public SpellScriptLoader { // min pct of hp is stored in effect 0 of talent spell uint8 rank = GetSpellInfo()->GetRank(); - SpellInfo const* talentProto = sSpellMgr->EnsureSpellInfo(sSpellMgr->GetSpellWithRank(SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1, rank)); + SpellInfo const* talentProto = sSpellMgr->AssertSpellInfo(sSpellMgr->GetSpellWithRank(SPELL_DK_WILL_OF_THE_NECROPOLIS_TALENT_R1, rank)); int32 remainingHp = int32(GetTarget()->GetHealth() - dmgInfo.GetDamage()); int32 minHp = int32(GetTarget()->CountPctFromMaxHealth(talentProto->Effects[EFFECT_0].CalcValue(GetCaster()))); @@ -1733,36 +1920,39 @@ public: { PrepareSpellScript(spell_dk_raise_ally_initial_SpellScript); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Validate(SpellInfo const* spellInfo) override { - if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY_INITIAL)) + if (!sSpellMgr->GetSpellInfo(uint32(spellInfo->Effects[EFFECT_0].CalcValue()))) return false; return true; } + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + SpellCastResult CheckCast() { - // Raise Ally cannot be casted on alive players Unit* target = GetExplTargetUnit(); if (!target) return SPELL_FAILED_NO_VALID_TARGETS; if (target->IsAlive()) return SPELL_FAILED_TARGET_NOT_DEAD; - if (Player* playerCaster = GetCaster()->ToPlayer()) - if (playerCaster->InArena()) - return SPELL_FAILED_NOT_IN_ARENA; if (target->IsGhouled()) return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW; - return SPELL_CAST_OK; } void HandleDummy(SpellEffIndex /*effIndex*/) { - Player* caster = GetCaster()->ToPlayer(); - Player* target = GetHitPlayer(); - if (caster && target) - caster->SendGhoulResurrectRequest(target); + if (Player* target = GetHitPlayer()) + { + if (target->IsResurrectRequested()) // already have one active request + return; + target->SetResurrectRequestData(GetCaster(), 0, 0, uint32(GetEffectValue())); + GetSpell()->SendResurrectRequest(target); + } } void Register() override @@ -1785,12 +1975,8 @@ class player_ghoulAI : public PlayerAI void UpdateAI(uint32 /*diff*/) override { - if (Creature* ghoul = ObjectAccessor::GetCreature(*me, _ghoulGUID)) - { - if (!ghoul->IsAlive()) - me->RemoveAura(SPELL_DK_RAISE_ALLY); - } - else + Creature* ghoul = ObjectAccessor::GetCreature(*me, _ghoulGUID); + if (!ghoul || !ghoul->IsAlive()) me->RemoveAura(SPELL_DK_RAISE_ALLY); } @@ -1799,28 +1985,25 @@ class player_ghoulAI : public PlayerAI }; // 46619 - Raise Ally +#define DkRaiseAllyScriptName "spell_dk_raise_ally" class spell_dk_raise_ally : public SpellScriptLoader { public: - spell_dk_raise_ally() : SpellScriptLoader("spell_dk_raise_ally") { } + spell_dk_raise_ally() : SpellScriptLoader(DkRaiseAllyScriptName) { } class spell_dk_raise_ally_SpellScript : public SpellScript { PrepareSpellScript(spell_dk_raise_ally_SpellScript); - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Load() override { - if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY)) - return false; - return true; + return GetCaster()->GetTypeId() == TYPEID_PLAYER; } void SendText() { - Player* caster = GetCaster()->ToPlayer(); - Unit* original = GetOriginalCaster(); - if (caster && original) - original->Whisper(TEXT_RISE_ALLY, caster, true); + if (Unit* original = GetOriginalCaster()) + original->Whisper(TEXT_RISE_ALLY, GetCaster()->ToPlayer(), true); } void HandleSummon(SpellEffIndex effIndex) @@ -1839,9 +2022,8 @@ public: SummonPropertiesEntry const* properties = sSummonPropertiesStore.LookupEntry(829); uint32 duration = uint32(GetSpellInfo()->GetDuration()); - Position pos = caster->GetPosition(); - TempSummon* summon = originalCaster->GetMap()->SummonCreature(entry, pos, properties, duration, originalCaster, GetSpellInfo()->Id); + TempSummon* summon = originalCaster->GetMap()->SummonCreature(entry, *GetHitDest(), properties, duration, originalCaster, GetSpellInfo()->Id); if (!summon) return; @@ -1868,15 +2050,25 @@ public: // SMSG_POWER_UPDATE is sent summon->SetMaxPower(POWER_ENERGY, 100); - if (Player* player = GetCaster()->ToPlayer()) - player->SetGhoulResurrectGhoulGUID(summon->GetGUID()); + _ghoulGuid = summon->GetGUID(); + } + + void SetGhoul(SpellEffIndex /*effIndex*/) + { + if (Aura* aura = GetHitAura()) + if (spell_dk_raise_ally_AuraScript* script = dynamic_cast<spell_dk_raise_ally_AuraScript*>(aura->GetScriptByName(DkRaiseAllyScriptName))) + script->SetGhoulGuid(_ghoulGuid); } void Register() override { AfterHit += SpellHitFn(spell_dk_raise_ally_SpellScript::SendText); OnEffectHit += SpellEffectFn(spell_dk_raise_ally_SpellScript::HandleSummon, EFFECT_0, SPELL_EFFECT_SUMMON); + OnEffectHitTarget += SpellEffectFn(spell_dk_raise_ally_SpellScript::SetGhoul, EFFECT_1, SPELL_EFFECT_APPLY_AURA); } + + private: + ObjectGuid _ghoulGuid; }; SpellScript* GetSpellScript() const override @@ -1895,45 +2087,45 @@ public: oldAIState = false; } + void SetGhoulGuid(ObjectGuid guid) + { + ghoulGuid = guid; + } + private: - bool Validate(SpellInfo const* /*spellInfo*/) override + bool Load() override { - if (!sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_ALLY)) - return false; - return true; + return GetUnitOwner()->GetTypeId() == TYPEID_PLAYER; } void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { Player* player = GetTarget()->ToPlayer(); - if (!player || player->GetGhoulResurrectGhoulGUID().IsEmpty()) + if (ghoulGuid.IsEmpty()) return; - oldAI = player->GetAI(); + oldAI = player->AI(); oldAIState = player->IsAIEnabled; - player->SetAI(new player_ghoulAI(player, player->GetGhoulResurrectGhoulGUID())); + player->SetAI(new player_ghoulAI(player, ghoulGuid)); player->IsAIEnabled = true; } void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { Player* player = GetTarget()->ToPlayer(); - if (!player) - return; player->IsAIEnabled = oldAIState; - UnitAI* thisAI = player->GetAI(); + PlayerAI* thisAI = player->AI(); player->SetAI(oldAI); delete thisAI; // Dismiss ghoul if necessary - if (Creature* ghoul = ObjectAccessor::GetCreature(*player, player->GetGhoulResurrectGhoulGUID())) + if (Creature* ghoul = ObjectAccessor::GetCreature(*player, ghoulGuid)) { - ghoul->RemoveCharmedBy(nullptr); + ghoul->RemoveCharmedBy(player); ghoul->DespawnOrUnsummon(1000); } - player->SetGhoulResurrectGhoulGUID(ObjectGuid::Empty); player->RemoveAura(SPELL_GHOUL_FRENZY); } @@ -1943,7 +2135,8 @@ public: AfterEffectRemove += AuraEffectRemoveFn(spell_dk_raise_ally_AuraScript::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } - UnitAI* oldAI; + ObjectGuid ghoulGuid; + PlayerAI* oldAI; bool oldAIState; }; @@ -1965,7 +2158,7 @@ public: bool Validate(SpellInfo const* /*spellInfo*/) override { - if (!sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_THRASH)) + if (!sSpellMgr->GetSpellInfo(SPELL_GHOUL_FRENZY)) return false; return true; } @@ -2002,6 +2195,8 @@ public: void AddSC_deathknight_spell_scripts() { + new spell_dk_acclimation(); + new spell_dk_advantage_t10_4p(); new spell_dk_anti_magic_shell_raid(); new spell_dk_anti_magic_shell_self(); new spell_dk_anti_magic_zone(); @@ -2018,6 +2213,7 @@ void AddSC_deathknight_spell_scripts() new spell_dk_ghoul_explode(); new spell_dk_icebound_fortitude(); new spell_dk_improved_blood_presence(); + new spell_dk_improved_blood_presence_triggered(); new spell_dk_improved_frost_presence(); new spell_dk_improved_unholy_presence(); new spell_dk_pestilence(); diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 7b853c36075..0bf5ab01f45 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -31,6 +31,13 @@ enum DruidSpells { SPELL_DRUID_BEAR_FORM_PASSIVE = 1178, SPELL_DRUID_DIRE_BEAR_FORM_PASSIVE = 9635, + SPELL_DRUID_ECLIPSE_LUNAR_PROC = 48518, + SPELL_DRUID_ECLIPSE_SOLAR_PROC = 48517, + SPELL_DRUID_FORMS_TRINKET_BEAR = 37340, + SPELL_DRUID_FORMS_TRINKET_CAT = 37341, + SPELL_DRUID_FORMS_TRINKET_MOONKIN = 37343, + SPELL_DRUID_FORMS_TRINKET_NONE = 37344, + SPELL_DRUID_FORMS_TRINKET_TREE = 37342, SPELL_DRUID_ENRAGE = 5229, SPELL_DRUID_ENRAGE_MOD_DAMAGE = 51185, SPELL_DRUID_ENRAGED_DEFENSE = 70725, @@ -48,6 +55,8 @@ enum DruidSpells SPELL_DRUID_NATURES_SPLENDOR = 57865, SPELL_DRUID_SURVIVAL_INSTINCTS = 50322, SPELL_DRUID_SAVAGE_ROAR = 62071, + SPELL_DRUID_T9_FERAL_RELIC_BEAR = 67354, + SPELL_DRUID_T9_FERAL_RELIC_CAT = 67355, SPELL_DRUID_TIGER_S_FURY_ENERGIZE = 51178 }; @@ -131,6 +140,69 @@ class spell_dru_dash : public SpellScriptLoader } }; +class spell_dru_eclipse : public SpellScriptLoader +{ +public: + spell_dru_eclipse() : SpellScriptLoader("spell_dru_eclipse") { } + + class spell_dru_eclipse_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_eclipse_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_ECLIPSE_LUNAR_PROC)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_ECLIPSE_SOLAR_PROC)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (!eventInfo.GetSpellInfo()) + return false; + + if (eventInfo.GetActor()->HasAura(SPELL_DRUID_ECLIPSE_LUNAR_PROC) || eventInfo.GetActor()->HasAura(SPELL_DRUID_ECLIPSE_SOLAR_PROC)) + return false; + + // Triggered by Wrath? + if (eventInfo.GetSpellInfo()->SpellFamilyFlags[0] & 1) + return roll_chance_f(GetSpellInfo()->ProcChance * 0.6f) && _lunarProcCooldownEnd <= std::chrono::steady_clock::now(); + + return _solarProcCooldownEnd <= std::chrono::steady_clock::now(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + if (eventInfo.GetSpellInfo()->SpellFamilyFlags[0] & 1) + { + _lunarProcCooldownEnd = std::chrono::steady_clock::now() + Seconds(aurEff->GetAmount()); + eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_DRUID_ECLIPSE_LUNAR_PROC, TRIGGERED_FULL_MASK, nullptr, aurEff); + } + else + { + _solarProcCooldownEnd = std::chrono::steady_clock::now() + Seconds(aurEff->GetAmount()); + eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_DRUID_ECLIPSE_SOLAR_PROC, TRIGGERED_FULL_MASK, nullptr, aurEff); + } + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dru_eclipse_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dru_eclipse_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + std::chrono::steady_clock::time_point _lunarProcCooldownEnd = std::chrono::steady_clock::time_point::min(); + std::chrono::steady_clock::time_point _solarProcCooldownEnd = std::chrono::steady_clock::time_point::min(); + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dru_eclipse_AuraScript(); + } +}; + // 5229 - Enrage class spell_dru_enrage : public SpellScriptLoader { @@ -197,6 +269,91 @@ class spell_dru_enrage : public SpellScriptLoader } }; +// 37336 - Druid Forms Trinket +class spell_dru_forms_trinket : public SpellScriptLoader +{ +public: + spell_dru_forms_trinket() : SpellScriptLoader("spell_dru_forms_trinket") { } + + class spell_dru_forms_trinket_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_forms_trinket_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_BEAR) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_CAT) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_MOONKIN) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_NONE) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_TREE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + Unit* target = eventInfo.GetActor(); + + switch (target->GetShapeshiftForm()) + { + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_CAT: + case FORM_MOONKIN: + case FORM_NONE: + case FORM_TREE: + return true; + default: + break; + } + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + Unit* target = eventInfo.GetActor(); + uint32 triggerspell = 0; + + switch (target->GetShapeshiftForm()) + { + case FORM_BEAR: + case FORM_DIREBEAR: + triggerspell = SPELL_DRUID_FORMS_TRINKET_BEAR; + break; + case FORM_CAT: + triggerspell = SPELL_DRUID_FORMS_TRINKET_CAT; + break; + case FORM_MOONKIN: + triggerspell = SPELL_DRUID_FORMS_TRINKET_MOONKIN; + break; + case FORM_NONE: + triggerspell = SPELL_DRUID_FORMS_TRINKET_NONE; + break; + case FORM_TREE: + triggerspell = SPELL_DRUID_FORMS_TRINKET_TREE; + break; + default: + return; + } + + target->CastSpell(target, triggerspell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dru_forms_trinket_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dru_forms_trinket_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dru_forms_trinket_AuraScript(); + } +}; + // 54846 - Glyph of Starfire class spell_dru_glyph_of_starfire : public SpellScriptLoader { @@ -991,6 +1148,37 @@ class spell_dru_swift_flight_passive : public SpellScriptLoader } }; +// -33943 - Flight Form +class spell_dru_flight_form : public SpellScriptLoader +{ + public: + spell_dru_flight_form() : SpellScriptLoader("spell_dru_flight_form") { } + + class spell_dru_flight_form_SpellScript : public SpellScript + { + PrepareSpellScript(spell_dru_flight_form_SpellScript); + + SpellCastResult CheckCast() + { + Unit* caster = GetCaster(); + if (caster->IsInDisallowedMountForm()) + return SPELL_FAILED_NOT_SHAPESHIFT; + + return SPELL_CAST_OK; + } + + void Register() override + { + OnCheckCast += SpellCheckCastFn(spell_dru_flight_form_SpellScript::CheckCast); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_dru_flight_form_SpellScript(); + } +}; + // -5217 - Tiger's Fury class spell_dru_tiger_s_fury : public SpellScriptLoader { @@ -1048,6 +1236,77 @@ class spell_dru_typhoon : public SpellScriptLoader } }; +// 67353 - T9 Feral Relic (Idol of Mutilation) +class spell_dru_t9_feral_relic : public SpellScriptLoader +{ +public: + spell_dru_t9_feral_relic() : SpellScriptLoader("spell_dru_t9_feral_relic") { } + + class spell_dru_t9_feral_relic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_t9_feral_relic_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_T9_FERAL_RELIC_BEAR) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_T9_FERAL_RELIC_CAT)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + Unit* target = eventInfo.GetActor(); + + switch (target->GetShapeshiftForm()) + { + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_CAT: + return true; + default: + break; + } + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + uint32 triggerspell = 0; + + Unit* target = eventInfo.GetActor(); + + switch (target->GetShapeshiftForm()) + { + case FORM_BEAR: + case FORM_DIREBEAR: + triggerspell = SPELL_DRUID_T9_FERAL_RELIC_BEAR; + break; + case FORM_CAT: + triggerspell = SPELL_DRUID_T9_FERAL_RELIC_CAT; + break; + default: + return; + } + + target->CastSpell(target, triggerspell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dru_t9_feral_relic_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dru_t9_feral_relic_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dru_t9_feral_relic_AuraScript(); + } +}; + // 70691 - Item T10 Restoration 4P Bonus class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader { @@ -1177,7 +1436,9 @@ void AddSC_druid_spell_scripts() { new spell_dru_bear_form_passive(); new spell_dru_dash(); + new spell_dru_eclipse(); new spell_dru_enrage(); + new spell_dru_forms_trinket(); new spell_dru_glyph_of_starfire(); new spell_dru_idol_lifebloom(); new spell_dru_innervate(); @@ -1196,8 +1457,10 @@ void AddSC_druid_spell_scripts() new spell_dru_starfall_dummy(); new spell_dru_survival_instincts(); new spell_dru_swift_flight_passive(); + new spell_dru_flight_form(); new spell_dru_tiger_s_fury(); new spell_dru_typhoon(); + new spell_dru_t9_feral_relic(); new spell_dru_t10_restoration_4p_bonus(); new spell_dru_wild_growth(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index abde43ef952..e8ad73ceadb 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -430,6 +430,61 @@ class spell_gen_bandage : public SpellScriptLoader } }; +// Blood Reserve - 64568 +enum BloodReserve +{ + SPELL_GEN_BLOOD_RESERVE_AURA = 64568, + SPELL_GEN_BLOOD_RESERVE_HEAL = 64569 +}; + +class spell_gen_blood_reserve : public SpellScriptLoader +{ + public: + spell_gen_blood_reserve() : SpellScriptLoader("spell_gen_blood_reserve") { } + + class spell_gen_blood_reserve_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_blood_reserve_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_GEN_BLOOD_RESERVE_HEAL)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) + if (Unit* caster = eventInfo.GetActionTarget()) + if (caster->HealthBelowPctDamaged(35, dmgInfo->GetDamage())) + return true; + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActionTarget(); + caster->CastCustomSpell(SPELL_GEN_BLOOD_RESERVE_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), caster, TRIGGERED_FULL_MASK, nullptr, aurEff); + caster->RemoveAura(SPELL_GEN_BLOOD_RESERVE_AURA); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_gen_blood_reserve_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_gen_blood_reserve_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gen_blood_reserve_AuraScript(); + } +}; + enum Bonked { SPELL_BONKED = 62991, @@ -1245,7 +1300,7 @@ class spell_gen_defend : public SpellScriptLoader void Register() override { - SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(m_scriptSpellId); + SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId); // Defend spells cast by NPCs (add visuals) if (spell->Effects[EFFECT_0].ApplyAuraName == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) @@ -2085,7 +2140,7 @@ class spell_gen_mounted_charge: public SpellScriptLoader } // If target isn't a training dummy there's a chance of failing the charge - if (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE) && roll_chance_f(12.5f)) + if (!target->IsCharmedOwnedByPlayerOrPlayer() && roll_chance_f(12.5f)) spellId = SPELL_CHARGE_MISS_EFFECT; if (Unit* vehicle = GetCaster()->GetVehicleBase()) @@ -2148,7 +2203,7 @@ class spell_gen_mounted_charge: public SpellScriptLoader void Register() override { - SpellInfo const* spell = sSpellMgr->EnsureSpellInfo(m_scriptSpellId); + SpellInfo const* spell = sSpellMgr->AssertSpellInfo(m_scriptSpellId); if (spell->HasEffect(SPELL_EFFECT_SCRIPT_EFFECT)) OnEffectHitTarget += SpellEffectFn(spell_gen_mounted_charge_SpellScript::HandleScriptEffect, EFFECT_FIRST_FOUND, SPELL_EFFECT_SCRIPT_EFFECT); @@ -4155,6 +4210,40 @@ public: } }; +// 34098 - ClearAllDebuffs +class spell_gen_clear_debuffs : public SpellScriptLoader +{ + public: + spell_gen_clear_debuffs() : SpellScriptLoader("spell_gen_clear_debuffs") { } + + class spell_gen_clear_debuffs_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gen_clear_debuffs_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->RemoveOwnedAuras([](Aura const* aura) + { + SpellInfo const* spellInfo = aura->GetSpellInfo(); + return !spellInfo->IsPositive() && !spellInfo->IsPassive(); + }); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gen_clear_debuffs_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gen_clear_debuffs_SpellScript(); + } +}; + void AddSC_generic_spell_scripts() { new spell_gen_absorb0_hitlimit1(); @@ -4165,6 +4254,7 @@ void AddSC_generic_spell_scripts() new spell_gen_aura_service_uniform(); new spell_gen_av_drekthar_presence(); new spell_gen_bandage(); + new spell_gen_blood_reserve(); new spell_gen_bonked(); new spell_gen_break_shield("spell_gen_break_shield"); new spell_gen_break_shield("spell_gen_tournament_counterattack"); @@ -4241,4 +4331,5 @@ void AddSC_generic_spell_scripts() new spell_gen_stand(); new spell_gen_mixology_bonus(); new spell_gen_landmine_knockback_achievement(); + new spell_gen_clear_debuffs(); } diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index 7fe1f54a594..bd36e3cb765 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -29,6 +29,7 @@ #include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" +#include "Vehicle.h" // 45102 Romantic Picnic enum SpellsPicnic @@ -64,7 +65,7 @@ class spell_love_is_in_the_air_romantic_picnic : public SpellScriptLoader Unit* caster = GetCaster(); // If our player is no longer sit, remove all auras - if (target->getStandState() != UNIT_STAND_STATE_SIT) + if (target->GetStandState() != UNIT_STAND_STATE_SIT) { target->RemoveAura(SPELL_ROMANTIC_PICNIC_ACHIEV); target->RemoveAura(GetAura()); @@ -83,7 +84,7 @@ class spell_love_is_in_the_air_romantic_picnic : public SpellScriptLoader target->VisitNearbyWorldObject(INTERACTION_DISTANCE*2, searcher); for (std::list<Player*>::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr) { - if ((*itr) != target && (*itr)->HasAura(GetId())) // && (*itr)->getStandState() == UNIT_STAND_STATE_SIT) + if ((*itr) != target && (*itr)->HasAura(GetId())) // && (*itr)->GetStandState() == UNIT_STAND_STATE_SIT) { if (caster) { @@ -112,6 +113,105 @@ class spell_love_is_in_the_air_romantic_picnic : public SpellScriptLoader } }; +enum HallowEndCandysSpells +{ + SPELL_HALLOWS_END_CANDY_ORANGE_GIANT = 24924, // Effect 1: Apply Aura: Mod Size, Value: 30% + SPELL_HALLOWS_END_CANDY_SKELETON = 24925, // Effect 1: Apply Aura: Change Model (Skeleton). Effect 2: Apply Aura: Underwater Breathing + SPELL_HALLOWS_END_CANDY_PIRATE = 24926, // Effect 1: Apply Aura: Increase Swim Speed, Value: 50% + SPELL_HALLOWS_END_CANDY_GHOST = 24927, // Effect 1: Apply Aura: Levitate / Hover. Effect 2: Apply Aura: Slow Fall, Effect 3: Apply Aura: Water Walking + SPELL_HALLOWS_END_CANDY_FEMALE_DEFIAS_PIRATE = 44742, // Effect 1: Apply Aura: Change Model (Defias Pirate, Female). Effect 2: Increase Swim Speed, Value: 50% + SPELL_HALLOWS_END_CANDY_MALE_DEFIAS_PIRATE = 44743 // Effect 1: Apply Aura: Change Model (Defias Pirate, Male). Effect 2: Increase Swim Speed, Value: 50% +}; + +// 24930 - Hallow's End Candy +class spell_hallow_end_candy : public SpellScriptLoader +{ + public: + spell_hallow_end_candy() : SpellScriptLoader("spell_hallow_end_candy") { } + + class spell_hallow_end_candy_SpellScript : public SpellScript + { + PrepareSpellScript(spell_hallow_end_candy_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + for (uint32 spellId : spells) + if (!sSpellMgr->GetSpellInfo(spellId)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetCaster(), spells[urand(0, 3)], true); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_hallow_end_candy_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + + private: + static uint32 const spells[4]; + }; + + SpellScript* GetSpellScript() const override + { + return new spell_hallow_end_candy_SpellScript(); + } +}; + +uint32 const spell_hallow_end_candy::spell_hallow_end_candy_SpellScript::spells[4] = +{ + SPELL_HALLOWS_END_CANDY_ORANGE_GIANT, + SPELL_HALLOWS_END_CANDY_SKELETON, + SPELL_HALLOWS_END_CANDY_PIRATE, + SPELL_HALLOWS_END_CANDY_GHOST +}; + +// 24926 - Hallow's End Candy +class spell_hallow_end_candy_pirate : public SpellScriptLoader +{ + public: + spell_hallow_end_candy_pirate() : SpellScriptLoader("spell_hallow_end_candy_pirate") { } + + class spell_hallow_end_candy_pirate_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hallow_end_candy_pirate_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_HALLOWS_END_CANDY_FEMALE_DEFIAS_PIRATE) + || !sSpellMgr->GetSpellInfo(SPELL_HALLOWS_END_CANDY_MALE_DEFIAS_PIRATE)) + return false; + return true; + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + uint32 spell = GetTarget()->getGender() == GENDER_FEMALE ? SPELL_HALLOWS_END_CANDY_FEMALE_DEFIAS_PIRATE : SPELL_HALLOWS_END_CANDY_MALE_DEFIAS_PIRATE; + GetTarget()->CastSpell(GetTarget(), spell, true); + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + uint32 spell = GetTarget()->getGender() == GENDER_FEMALE ? SPELL_HALLOWS_END_CANDY_FEMALE_DEFIAS_PIRATE : SPELL_HALLOWS_END_CANDY_MALE_DEFIAS_PIRATE; + GetTarget()->RemoveAurasDueToSpell(spell); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_hallow_end_candy_pirate_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_MOD_INCREASE_SWIM_SPEED, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_hallow_end_candy_pirate_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_MOD_INCREASE_SWIM_SPEED, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_hallow_end_candy_pirate_AuraScript(); + } +}; + // 24750 Trick enum TrickSpells { @@ -410,6 +510,84 @@ class spell_pilgrims_bounty_buff_food : public SpellScriptLoader } }; +enum FeastOnSpells +{ + FEAST_ON_TURKEY = 61784, + FEAST_ON_CRANBERRIES = 61785, + FEAST_ON_SWEET_POTATOES = 61786, + FEAST_ON_PIE = 61787, + FEAST_ON_STUFFING = 61788, + SPELL_CRANBERRY_HELPINS = 61841, + SPELL_TURKEY_HELPINS = 61842, + SPELL_STUFFING_HELPINS = 61843, + SPELL_SWEET_POTATO_HELPINS = 61844, + SPELL_PIE_HELPINS = 61845, + SPELL_ON_PLATE_EAT_VISUAL = 61826 +}; + +class spell_pilgrims_bounty_feast_on : public SpellScriptLoader +{ + public: + spell_pilgrims_bounty_feast_on() : SpellScriptLoader("spell_pilgrims_bounty_feast_on") { } + + class spell_pilgrims_bounty_feast_on_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pilgrims_bounty_feast_on_SpellScript); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + + uint32 _spellId = 0; + switch (GetSpellInfo()->Id) + { + case FEAST_ON_TURKEY: + _spellId = SPELL_TURKEY_HELPINS; + break; + case FEAST_ON_CRANBERRIES: + _spellId = SPELL_CRANBERRY_HELPINS; + break; + case FEAST_ON_SWEET_POTATOES: + _spellId = SPELL_SWEET_POTATO_HELPINS; + break; + case FEAST_ON_PIE: + _spellId = SPELL_PIE_HELPINS; + break; + case FEAST_ON_STUFFING: + _spellId = SPELL_STUFFING_HELPINS; + break; + default: + return; + } + + if (Vehicle* vehicle = caster->GetVehicleKit()) + if (Unit* target = vehicle->GetPassenger(0)) + if (Player* player = target->ToPlayer()) + { + player->CastSpell(player, SPELL_ON_PLATE_EAT_VISUAL, true); + caster->CastSpell(player, _spellId, true, NULL, NULL, player->GetGUID()); + } + + if (Aura* aura = caster->GetAura(GetEffectValue())) + { + if (aura->GetStackAmount() == 1) + caster->RemoveAurasDueToSpell(aura->GetSpellInfo()->Effects[EFFECT_0].CalcValue()); + aura->ModStackAmount(-1); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_pilgrims_bounty_feast_on_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_pilgrims_bounty_feast_on_SpellScript(); + } +}; + enum TheTurkinator { SPELL_KILL_COUNTER_VISUAL = 62015, @@ -429,7 +607,7 @@ class spell_pilgrims_bounty_turkey_tracker : public SpellScriptLoader { PrepareSpellScript(spell_pilgrims_bounty_turkey_tracker_SpellScript); - bool Validate(SpellInfo const* /*spell*/) + bool Validate(SpellInfo const* /*spell*/) override { if (!sSpellMgr->GetSpellInfo(SPELL_KILL_COUNTER_VISUAL) || !sSpellMgr->GetSpellInfo(SPELL_KILL_COUNTER_VISUAL_MAX)) return false; @@ -472,18 +650,90 @@ class spell_pilgrims_bounty_turkey_tracker : public SpellScriptLoader } } - void Register() + void Register() override { OnEffectHitTarget += SpellEffectFn(spell_pilgrims_bounty_turkey_tracker_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); } }; - SpellScript* GetSpellScript() const + SpellScript* GetSpellScript() const override { return new spell_pilgrims_bounty_turkey_tracker_SpellScript(); } }; +enum SpiritOfSharing +{ + SPELL_THE_SPIRIT_OF_SHARING = 61849 +}; + +class spell_pilgrims_bounty_well_fed : public SpellScriptLoader +{ + private: + uint32 _triggeredSpellId; + + public: + spell_pilgrims_bounty_well_fed(const char* name, uint32 triggeredSpellId) : SpellScriptLoader(name), _triggeredSpellId(triggeredSpellId) { } + + class spell_pilgrims_bounty_well_fed_SpellScript : public SpellScript + { + PrepareSpellScript(spell_pilgrims_bounty_well_fed_SpellScript); + private: + uint32 _triggeredSpellId; + + public: + spell_pilgrims_bounty_well_fed_SpellScript(uint32 triggeredSpellId) : SpellScript(), _triggeredSpellId(triggeredSpellId) { } + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(_triggeredSpellId)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + Player* target = GetHitPlayer(); + if (!target) + return; + + if (Aura const* aura = target->GetAura(GetSpellInfo()->Id)) + { + if (aura->GetStackAmount() == 5) + target->CastSpell(target, _triggeredSpellId, true); + } + + Aura const* turkey = target->GetAura(SPELL_TURKEY_HELPINS); + Aura const* cranberies = target->GetAura(SPELL_CRANBERRY_HELPINS); + Aura const* stuffing = target->GetAura(SPELL_STUFFING_HELPINS); + Aura const* sweetPotatoes = target->GetAura(SPELL_SWEET_POTATO_HELPINS); + Aura const* pie = target->GetAura(SPELL_PIE_HELPINS); + + if ((turkey && turkey->GetStackAmount() == 5) && (cranberies && cranberies->GetStackAmount() == 5) && (stuffing && stuffing->GetStackAmount() == 5) + && (sweetPotatoes && sweetPotatoes->GetStackAmount() == 5) && (pie && pie->GetStackAmount() == 5)) + { + target->CastSpell(target, SPELL_THE_SPIRIT_OF_SHARING, true); + target->RemoveAurasDueToSpell(SPELL_TURKEY_HELPINS); + target->RemoveAurasDueToSpell(SPELL_CRANBERRY_HELPINS); + target->RemoveAurasDueToSpell(SPELL_STUFFING_HELPINS); + target->RemoveAurasDueToSpell(SPELL_SWEET_POTATO_HELPINS); + target->RemoveAurasDueToSpell(SPELL_PIE_HELPINS); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_pilgrims_bounty_well_fed_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_pilgrims_bounty_well_fed_SpellScript(_triggeredSpellId); + } +}; + enum Mistletoe { SPELL_CREATE_MISTLETOE = 26206, @@ -1032,11 +1282,79 @@ class spell_midsummer_braziers_hit : public SpellScriptLoader } }; +enum RibbonPoleData +{ + SPELL_HAS_FULL_MIDSUMMER_SET = 58933, + SPELL_BURNING_HOT_POLE_DANCE = 58934, + SPELL_RIBBON_DANCE_COSMETIC = 29726, + SPELL_RIBBON_DANCE = 29175, + GO_RIBBON_POLE = 181605, +}; + +class spell_gen_ribbon_pole_dancer_check : public SpellScriptLoader +{ + public: + spell_gen_ribbon_pole_dancer_check() : SpellScriptLoader("spell_gen_ribbon_pole_dancer_check") { } + + class spell_gen_ribbon_pole_dancer_check_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_ribbon_pole_dancer_check_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_HAS_FULL_MIDSUMMER_SET) + || !sSpellMgr->GetSpellInfo(SPELL_RIBBON_DANCE) + || !sSpellMgr->GetSpellInfo(SPELL_BURNING_HOT_POLE_DANCE)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + Unit* target = GetTarget(); + + // check if aura needs to be removed + if (!target->FindNearestGameObject(GO_RIBBON_POLE, 8.0f) || !target->HasUnitState(UNIT_STATE_CASTING)) + { + target->InterruptNonMeleeSpells(false); + target->RemoveAurasDueToSpell(GetId()); + target->RemoveAura(SPELL_RIBBON_DANCE_COSMETIC); + return; + } + + // set xp buff duration + if (Aura* aur = target->GetAura(SPELL_RIBBON_DANCE)) + { + aur->SetMaxDuration(std::min(3600000, aur->GetMaxDuration() + 180000)); + aur->RefreshDuration(); + + // reward achievement criteria + if (aur->GetMaxDuration() == 3600000 && target->HasAura(SPELL_HAS_FULL_MIDSUMMER_SET)) + target->CastSpell(target, SPELL_BURNING_HOT_POLE_DANCE, true); + } + else + target->AddAura(SPELL_RIBBON_DANCE, target); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_ribbon_pole_dancer_check_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gen_ribbon_pole_dancer_check_AuraScript(); + } +}; + void AddSC_holiday_spell_scripts() { // Love is in the Air new spell_love_is_in_the_air_romantic_picnic(); // Hallow's End + new spell_hallow_end_candy(); + new spell_hallow_end_candy_pirate(); new spell_hallow_end_trick(); new spell_hallow_end_trick_or_treat(); new spell_hallow_end_tricky_treat(); @@ -1047,6 +1365,12 @@ void AddSC_holiday_spell_scripts() new spell_pilgrims_bounty_buff_food("spell_gen_spice_bread_stuffing", SPELL_WELL_FED_HIT_TRIGGER); new spell_pilgrims_bounty_buff_food("spell_gen_pumpkin_pie", SPELL_WELL_FED_SPIRIT_TRIGGER); new spell_pilgrims_bounty_buff_food("spell_gen_candied_sweet_potato", SPELL_WELL_FED_HASTE_TRIGGER); + new spell_pilgrims_bounty_feast_on(); + new spell_pilgrims_bounty_well_fed("spell_pilgrims_bounty_well_fed_turkey", SPELL_WELL_FED_AP_TRIGGER); + new spell_pilgrims_bounty_well_fed("spell_pilgrims_bounty_well_fed_cranberry", SPELL_WELL_FED_ZM_TRIGGER); + new spell_pilgrims_bounty_well_fed("spell_pilgrims_bounty_well_fed_stuffing", SPELL_WELL_FED_HIT_TRIGGER); + new spell_pilgrims_bounty_well_fed("spell_pilgrims_bounty_well_fed_sweet_potatoes", SPELL_WELL_FED_HASTE_TRIGGER); + new spell_pilgrims_bounty_well_fed("spell_pilgrims_bounty_well_fed_pie", SPELL_WELL_FED_SPIRIT_TRIGGER); new spell_pilgrims_bounty_turkey_tracker(); // Winter Veil new spell_winter_veil_mistletoe(); @@ -1062,4 +1386,5 @@ void AddSC_holiday_spell_scripts() new spell_brewfest_barker_bunny(); // Midsummer Fire Festival new spell_midsummer_braziers_hit(); + new spell_gen_ribbon_pole_dancer_check(); } diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index abf4c6c1ad8..a75294ad6e0 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -40,6 +40,7 @@ enum HunterSpells SPELL_HUNTER_CHIMERA_SHOT_SERPENT = 53353, SPELL_HUNTER_CHIMERA_SHOT_VIPER = 53358, SPELL_HUNTER_CHIMERA_SHOT_SCORPID = 53359, + SPELL_HUNTER_GLYPH_OF_ARCANE_SHOT = 61389, SPELL_HUNTER_GLYPH_OF_ASPECT_OF_THE_VIPER = 56851, SPELL_HUNTER_IMPROVED_MEND_PET = 24406, SPELL_HUNTER_INVIGORATION_TRIGGERED = 53398, @@ -50,12 +51,15 @@ enum HunterSpells SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED = 54114, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_DEBUFF = 55711, SPELL_HUNTER_PET_CARRION_FEEDER_TRIGGERED = 54045, + SPELL_HUNTER_PIERCING_SHOTS = 63468, SPELL_HUNTER_READINESS = 23989, SPELL_HUNTER_SNIPER_TRAINING_R1 = 53302, SPELL_HUNTER_SNIPER_TRAINING_BUFF_R1 = 64418, + SPELL_HUNTER_T9_4P_GREATNESS = 68130, SPELL_HUNTER_VICIOUS_VIPER = 61609, SPELL_HUNTER_VIPER_ATTACK_SPEED = 60144, - SPELL_DRAENEI_GIFT_OF_THE_NAARU = 59543 + SPELL_DRAENEI_GIFT_OF_THE_NAARU = 59543, + SPELL_ROAR_OF_SACRIFICE_TRIGGERED = 67481 }; // 13161 - Aspect of the Beast @@ -192,8 +196,8 @@ class spell_hun_chimera_shot : public SpellScriptLoader { uint32 spellId = 0; int32 basePoint = 0; - Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras(); - for (Unit::AuraApplicationMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + Unit::AuraApplicationMap const& auras = unitTarget->GetAppliedAuras(); + for (Unit::AuraApplicationMap::const_iterator i = auras.begin(); i != auras.end(); ++i) { Aura* aura = i->second->GetBase(); if (aura->GetCasterGUID() != caster->GetGUID()) @@ -296,6 +300,68 @@ class spell_hun_disengage : public SpellScriptLoader } }; +// 56841 - Glyph of Arcane Shot +class spell_hun_glyph_of_arcane_shot : public SpellScriptLoader +{ + public: + spell_hun_glyph_of_arcane_shot() : SpellScriptLoader("spell_hun_glyph_of_arcane_shot") { } + + class spell_hun_glyph_of_arcane_shot_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_glyph_of_arcane_shot_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_GLYPH_OF_ARCANE_SHOT)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (Unit* procTarget = eventInfo.GetProcTarget()) + { + Unit::AuraApplicationMap const& auras = procTarget->GetAppliedAuras(); + for (Unit::AuraApplicationMap::const_iterator i = auras.begin(); i != auras.end(); ++i) + { + Aura const* aura = i->second->GetBase(); + if (aura->GetCasterGUID() != GetTarget()->GetGUID()) + continue; + // Search only Serpent Sting, Viper Sting, Scorpid Sting, Wyvern Sting + if (aura->GetSpellInfo()->SpellFamilyName == SPELLFAMILY_HUNTER + && aura->GetSpellInfo()->SpellFamilyFlags.HasFlag(0xC000, 0x1080)) + return true; + } + } + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + SpellInfo const* procSpell = eventInfo.GetSpellInfo(); + if (!procSpell) + return; + + int32 mana = procSpell->CalcPowerCost(GetTarget(), procSpell->GetSchoolMask()); + ApplyPct(mana, aurEff->GetAmount()); + + GetTarget()->CastCustomSpell(SPELL_HUNTER_GLYPH_OF_ARCANE_SHOT, SPELLVALUE_BASE_POINT0, mana, GetTarget()); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_hun_glyph_of_arcane_shot_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_hun_glyph_of_arcane_shot_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_hun_glyph_of_arcane_shot_AuraScript(); + } +}; + // -19572 - Improved Mend Pet class spell_hun_improved_mend_pet : public SpellScriptLoader { @@ -336,6 +402,7 @@ class spell_hun_improved_mend_pet : public SpellScriptLoader return new spell_hun_improved_mend_pet_AuraScript(); } }; + // 53412 - Invigoration class spell_hun_invigoration : public SpellScriptLoader { @@ -640,6 +707,63 @@ class spell_hun_pet_heart_of_the_phoenix : public SpellScriptLoader } }; +// -53234 - Piercing Shots +class spell_hun_piercing_shots : public SpellScriptLoader +{ +public: + spell_hun_piercing_shots() : SpellScriptLoader("spell_hun_piercing_shots") { } + + class spell_hun_piercing_shots_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_piercing_shots_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_PIERCING_SHOTS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetActionTarget()) + return true; + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + Unit* caster = eventInfo.GetActor(); + Unit* target = eventInfo.GetActionTarget(); + + if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) + { + SpellInfo const* piercingShots = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_PIERCING_SHOTS); + int32 duration = piercingShots->GetMaxDuration(); + uint32 amplitude = piercingShots->Effects[EFFECT_0].Amplitude; + uint32 dmg = dmgInfo->GetDamage(); + + uint32 bp = CalculatePct(int32(dmg), aurEff->GetAmount()) / (duration / int32(amplitude)); + bp += target->GetRemainingPeriodicAmount(target->GetGUID(), SPELL_HUNTER_PIERCING_SHOTS, SPELL_AURA_PERIODIC_DAMAGE); + + caster->CastCustomSpell(SPELL_HUNTER_PIERCING_SHOTS, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + } + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_hun_piercing_shots_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_hun_piercing_shots_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_hun_piercing_shots_AuraScript(); + } +}; + // 56654, 58882 - Rapid Recuperation class spell_hun_rapid_recuperation : public SpellScriptLoader { @@ -699,7 +823,7 @@ class spell_hun_readiness : public SpellScriptLoader // immediately finishes the cooldown on your other Hunter abilities except Bestial Wrath GetCaster()->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); ///! If spellId in cooldown map isn't valid, the above will return a null pointer. if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && @@ -724,6 +848,49 @@ class spell_hun_readiness : public SpellScriptLoader } }; +// 53480 - Roar of Sacrifice +class spell_hun_roar_of_sacrifice : public SpellScriptLoader +{ + public: + spell_hun_roar_of_sacrifice() : SpellScriptLoader("spell_hun_roar_of_sacrifice") { } + + class spell_hun_roar_of_sacrifice_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_roar_of_sacrifice_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROAR_OF_SACRIFICE_TRIGGERED)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return GetCaster() && (eventInfo.GetDamageInfo()->GetSchoolMask() & GetEffect(EFFECT_1)->GetMiscValue()) != 0; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + uint32 damage = CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), aurEff->GetAmount()); + eventInfo.GetActor()->CastCustomSpell(SPELL_ROAR_OF_SACRIFICE_TRIGGERED, SPELLVALUE_BASE_POINT0, damage, GetCaster(), TRIGGERED_FULL_MASK, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_hun_roar_of_sacrifice_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_hun_roar_of_sacrifice_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_hun_roar_of_sacrifice_AuraScript(); + } +}; + // 37506 - Scatter Shot class spell_hun_scatter_shot : public SpellScriptLoader { @@ -903,6 +1070,51 @@ class spell_hun_target_only_pet_and_owner : public SpellScriptLoader } }; +// 67151 - T9 4P Bonus +class spell_hun_t9_4p_bonus : public SpellScriptLoader +{ +public: + spell_hun_t9_4p_bonus() : SpellScriptLoader("spell_hun_t9_4p_bonus") { } + + class spell_hun_t9_4p_bonus_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_t9_4p_bonus_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_T9_4P_GREATNESS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetActor()->GetTypeId() == TYPEID_PLAYER && eventInfo.GetActor()->ToPlayer()->GetPet()) + return true; + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + Unit* caster = eventInfo.GetActor(); + + caster->CastSpell(caster->ToPlayer()->GetPet(), SPELL_HUNTER_T9_4P_GREATNESS, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_hun_t9_4p_bonus_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_hun_t9_4p_bonus_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_hun_t9_4p_bonus_AuraScript(); + } +}; + // 60144 - Viper Attack Speed class spell_hun_viper_attack_speed : public SpellScriptLoader { @@ -952,6 +1164,7 @@ void AddSC_hunter_spell_scripts() new spell_hun_ascpect_of_the_viper(); new spell_hun_chimera_shot(); new spell_hun_disengage(); + new spell_hun_glyph_of_arcane_shot(); new spell_hun_improved_mend_pet(); new spell_hun_invigoration(); new spell_hun_last_stand_pet(); @@ -960,11 +1173,14 @@ void AddSC_hunter_spell_scripts() new spell_hun_misdirection_proc(); new spell_hun_pet_carrion_feeder(); new spell_hun_pet_heart_of_the_phoenix(); + new spell_hun_piercing_shots(); new spell_hun_rapid_recuperation(); new spell_hun_readiness(); + new spell_hun_roar_of_sacrifice(); new spell_hun_scatter_shot(); new spell_hun_sniper_training(); new spell_hun_tame_beast(); new spell_hun_target_only_pet_and_owner(); + new spell_hun_t9_4p_bonus(); new spell_hun_viper_attack_speed(); } diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 0abff255e4b..5a6bb78eb10 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -201,6 +201,55 @@ class spell_item_blessing_of_ancient_kings : public SpellScriptLoader } }; +// 47770 - Roll Dice +class spell_item_decahedral_dwarven_dice : public SpellScriptLoader +{ + public: + spell_item_decahedral_dwarven_dice() : SpellScriptLoader("spell_item_decahedral_dwarven_dice") { } + + class spell_item_decahedral_dwarven_dice_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_decahedral_dwarven_dice_SpellScript); + + enum + { + TEXT_DECAHEDRAL_DWARVEN_DICE = 26147 + }; + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sObjectMgr->GetBroadcastText(TEXT_DECAHEDRAL_DWARVEN_DICE)) + return false; + return true; + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->TextEmote(TEXT_DECAHEDRAL_DWARVEN_DICE, GetHitUnit()); + + static uint32 const minimum = 1; + static uint32 const maximum = 100; + + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_decahedral_dwarven_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_item_decahedral_dwarven_dice_SpellScript(); + } +}; + // 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success // 22999 - Defibrillate (Goblin Jumper Cables XL) have 50% chance on success // 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success @@ -1319,6 +1368,57 @@ class spell_item_underbelly_elixir : public SpellScriptLoader } }; +// 47776 - Roll 'dem Bones +class spell_item_worn_troll_dice : public SpellScriptLoader +{ + public: + spell_item_worn_troll_dice() : SpellScriptLoader("spell_item_worn_troll_dice") { } + + class spell_item_worn_troll_dice_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_worn_troll_dice_SpellScript); + + enum + { + TEXT_WORN_TROLL_DICE = 26152 + }; + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sObjectMgr->GetBroadcastText(TEXT_WORN_TROLL_DICE)) + return false; + return true; + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->TextEmote(TEXT_WORN_TROLL_DICE, GetHitUnit()); + + static uint32 const minimum = 1; + static uint32 const maximum = 6; + + // roll twice + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_worn_troll_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_item_worn_troll_dice_SpellScript(); + } +}; + enum AirRifleSpells { SPELL_AIR_RIFLE_HOLD_VISUAL = 65582, @@ -1803,7 +1903,7 @@ class spell_item_crystal_prison_dummy_dnd : public SpellScriptLoader if (Creature* target = GetHitCreature()) if (target->isDead() && !target->IsPet()) { - GetCaster()->SummonGameObject(OBJECT_IMPRISONED_DOOMGUARD, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0, 0, 0, 0, uint32(target->GetRespawnTime()-time(NULL))); + GetCaster()->SummonGameObject(OBJECT_IMPRISONED_DOOMGUARD, *target, G3D::Quat(), uint32(target->GetRespawnTime()-time(NULL))); target->DespawnOrUnsummon(); } } @@ -2631,6 +2731,70 @@ public: } }; +enum SoulPreserver +{ + SPELL_SOUL_PRESERVER_DRUID = 60512, + SPELL_SOUL_PRESERVER_PALADIN = 60513, + SPELL_SOUL_PRESERVER_PRIEST = 60514, + SPELL_SOUL_PRESERVER_SHAMAN = 60515, +}; + +class spell_item_soul_preserver : public SpellScriptLoader +{ +public: + spell_item_soul_preserver() : SpellScriptLoader("spell_item_soul_preserver") { } + + class spell_item_soul_preserver_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_soul_preserver_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_DRUID) || + !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_PALADIN) || + !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_PRIEST) || + !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_SHAMAN)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + + switch (caster->getClass()) + { + case CLASS_DRUID: + caster->CastSpell(caster, SPELL_SOUL_PRESERVER_DRUID, true, nullptr, aurEff); + break; + case CLASS_PALADIN: + caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PALADIN, true, nullptr, aurEff); + break; + case CLASS_PRIEST: + caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PRIEST, true, nullptr, aurEff); + break; + case CLASS_SHAMAN: + caster->CastSpell(caster, SPELL_SOUL_PRESERVER_SHAMAN, true, nullptr, aurEff); + break; + default: + break; + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_soul_preserver_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_soul_preserver_AuraScript(); + } +}; + class spell_item_toy_train_set_pulse : public SpellScriptLoader { public: @@ -2668,6 +2832,336 @@ public: } }; +enum DeathChoiceSpells +{ + SPELL_DEATH_CHOICE_NORMAL_AURA = 67702, + SPELL_DEATH_CHOICE_NORMAL_AGILITY = 67703, + SPELL_DEATH_CHOICE_NORMAL_STRENGTH = 67708, + SPELL_DEATH_CHOICE_HEROIC_AURA = 67771, + SPELL_DEATH_CHOICE_HEROIC_AGILITY = 67772, + SPELL_DEATH_CHOICE_HEROIC_STRENGTH = 67773 +}; + +class spell_item_death_choice : public SpellScriptLoader +{ +public: + spell_item_death_choice() : SpellScriptLoader("spell_item_death_choice") { } + + class spell_item_death_choice_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_death_choice_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_NORMAL_STRENGTH) || + !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_NORMAL_AGILITY) || + !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_HEROIC_STRENGTH) || + !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_HEROIC_AGILITY)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + float str = caster->GetStat(STAT_STRENGTH); + float agi = caster->GetStat(STAT_AGILITY); + + switch (aurEff->GetId()) + { + case SPELL_DEATH_CHOICE_NORMAL_AURA: + { + if (str > agi) + caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_STRENGTH, true, nullptr, aurEff); + else + caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_AGILITY, true, nullptr, aurEff); + break; + } + case SPELL_DEATH_CHOICE_HEROIC_AURA: + { + if (str > agi) + caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_STRENGTH, true, nullptr, aurEff); + else + caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_AGILITY, true, nullptr, aurEff); + break; + } + default: + break; + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_death_choice_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_death_choice_AuraScript(); + } +}; + +enum TrinketStackSpells +{ + SPELL_LIGHTNING_CAPACITOR_AURA = 37657, // Lightning Capacitor + SPELL_LIGHTNING_CAPACITOR_STACK = 37658, + SPELL_LIGHTNING_CAPACITOR_TRIGGER = 37661, + SPELL_THUNDER_CAPACITOR_AURA = 54841, // Thunder Capacitor + SPELL_THUNDER_CAPACITOR_STACK = 54842, + SPELL_THUNDER_CAPACITOR_TRIGGER = 54843, + SPELL_TOC25_CASTER_TRINKET_NORMAL_AURA = 67712, // Item - Coliseum 25 Normal Caster Trinket + SPELL_TOC25_CASTER_TRINKET_NORMAL_STACK = 67713, + SPELL_TOC25_CASTER_TRINKET_NORMAL_TRIGGER = 67714, + SPELL_TOC25_CASTER_TRINKET_HEROIC_AURA = 67758, // Item - Coliseum 25 Heroic Caster Trinket + SPELL_TOC25_CASTER_TRINKET_HEROIC_STACK = 67759, + SPELL_TOC25_CASTER_TRINKET_HEROIC_TRIGGER = 67760, +}; + +class spell_item_trinket_stack : public SpellScriptLoader +{ +public: + spell_item_trinket_stack(char const* scriptName, uint32 stackSpell, uint32 triggerSpell) : SpellScriptLoader(scriptName), + _stackSpell(stackSpell), _triggerSpell(triggerSpell) + { + } + + class spell_item_trinket_stack_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_trinket_stack_AuraScript); + + public: + spell_item_trinket_stack_AuraScript(uint32 stackSpell, uint32 triggerSpell) : _stackSpell(stackSpell), _triggerSpell(triggerSpell) + { + } + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(_stackSpell) || !sSpellMgr->GetSpellInfo(_triggerSpell)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + + caster->CastSpell(caster, _stackSpell, true, nullptr, aurEff); // cast the stack + + Aura* dummy = caster->GetAura(_stackSpell); // retrieve aura + + //dont do anything if it's not the right amount of stacks; + if (!dummy || dummy->GetStackAmount() < aurEff->GetAmount()) + return; + + // if right amount, remove the aura and cast real trigger + caster->RemoveAurasDueToSpell(_stackSpell); + if (Unit* target = eventInfo.GetActionTarget()) + caster->CastSpell(target, _triggerSpell, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_trinket_stack_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + + private: + uint32 _stackSpell; + uint32 _triggerSpell; + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_trinket_stack_AuraScript(_stackSpell, _triggerSpell); + } + +private: + uint32 _stackSpell; + uint32 _triggerSpell; +}; + +// 57345 - Darkmoon Card: Greatness +enum DarkmoonCardSpells +{ + SPELL_DARKMOON_CARD_STRENGHT = 60229, + SPELL_DARKMOON_CARD_AGILITY = 60233, + SPELL_DARKMOON_CARD_INTELLECT = 60234, + SPELL_DARKMOON_CARD_SPIRIT = 60235, +}; + +class spell_item_darkmoon_card_greatness : public SpellScriptLoader +{ +public: + spell_item_darkmoon_card_greatness() : SpellScriptLoader("spell_item_darkmoon_card_greatness") { } + + class spell_item_darkmoon_card_greatness_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_darkmoon_card_greatness_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_STRENGHT) || + !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_AGILITY) || + !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_INTELLECT) || + !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_SPIRIT)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + float str = caster->GetStat(STAT_STRENGTH); + float agi = caster->GetStat(STAT_AGILITY); + float intl = caster->GetStat(STAT_INTELLECT); + float spi = caster->GetStat(STAT_SPIRIT); + float stat = 0.0f; + + uint32 spellTrigger = SPELL_DARKMOON_CARD_STRENGHT; + + if (str > stat) + { + spellTrigger = SPELL_DARKMOON_CARD_STRENGHT; + stat = str; + } + + if (agi > stat) + { + spellTrigger = SPELL_DARKMOON_CARD_AGILITY; + stat = agi; + } + + if (intl > stat) + { + spellTrigger = SPELL_DARKMOON_CARD_INTELLECT; + stat = intl; + } + + if (spi > stat) + { + spellTrigger = SPELL_DARKMOON_CARD_SPIRIT; + stat = spi; + } + + caster->CastSpell(caster, spellTrigger, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_darkmoon_card_greatness_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_darkmoon_card_greatness_AuraScript(); + } +}; + +// 43820 - Amani Charm of the Witch Doctor +enum CharmWitchDoctor +{ + SPELL_CHARM_WITCH_DOCTOR_PROC = 43821 +}; + +class spell_item_charm_witch_doctor : public SpellScriptLoader +{ +public: + spell_item_charm_witch_doctor() : SpellScriptLoader("spell_item_charm_witch_doctor") { } + + class spell_item_charm_witch_doctor_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_charm_witch_doctor_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_CHARM_WITCH_DOCTOR_PROC)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + Unit* target = eventInfo.GetActionTarget(); + + if (target) + { + int32 bp = CalculatePct(target->GetCreateHealth(),aurEff->GetSpellInfo()->Effects[1].CalcValue()); + caster->CastCustomSpell(target, SPELL_CHARM_WITCH_DOCTOR_PROC, &bp, nullptr, nullptr, true, nullptr, aurEff); + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_charm_witch_doctor_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_charm_witch_doctor_AuraScript(); + } +}; + +// 27522,40336 - Mana Drain +enum ManaDrainSpells +{ + SPELL_MANA_DRAIN_ENERGIZE = 29471, + SPELL_MANA_DRAIN_LEECH = 27526 +}; + +class spell_item_mana_drain : public SpellScriptLoader +{ +public: + spell_item_mana_drain() : SpellScriptLoader("spell_item_mana_drain") { } + + class spell_item_mana_drain_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_mana_drain_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MANA_DRAIN_ENERGIZE) + || !sSpellMgr->GetSpellInfo(SPELL_MANA_DRAIN_LEECH)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + Unit* target = eventInfo.GetActionTarget(); + + if (caster->IsAlive()) + caster->CastSpell(caster, SPELL_MANA_DRAIN_ENERGIZE, true, nullptr, aurEff); + + if (target && target->IsAlive()) + caster->CastSpell(target, SPELL_MANA_DRAIN_LEECH, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_mana_drain_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_mana_drain_AuraScript(); + } +}; + void AddSC_item_spell_scripts() { // 23074 Arcanite Dragonling @@ -2682,6 +3176,7 @@ void AddSC_item_spell_scripts() new spell_item_aegis_of_preservation(); new spell_item_arcane_shroud(); new spell_item_blessing_of_ancient_kings(); + new spell_item_decahedral_dwarven_dice(); new spell_item_defibrillate("spell_item_goblin_jumper_cables", 67, SPELL_GOBLIN_JUMPER_CABLES_FAIL); new spell_item_defibrillate("spell_item_goblin_jumper_cables_xl", 50, SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL); new spell_item_defibrillate("spell_item_gnomish_army_knife", 33); @@ -2706,6 +3201,7 @@ void AddSC_item_spell_scripts() new spell_item_six_demon_bag(); new spell_item_the_eye_of_diminution(); new spell_item_underbelly_elixir(); + new spell_item_worn_troll_dice(); new spell_item_red_rider_air_rifle(); new spell_item_create_heart_candy(); @@ -2736,5 +3232,14 @@ void AddSC_item_spell_scripts() new spell_item_chicken_cover(); new spell_item_muisek_vessel(); new spell_item_greatmothers_soulcatcher(); + new spell_item_soul_preserver(); new spell_item_toy_train_set_pulse(); + new spell_item_death_choice(); + new spell_item_trinket_stack("spell_item_lightning_capacitor", SPELL_LIGHTNING_CAPACITOR_STACK, SPELL_LIGHTNING_CAPACITOR_TRIGGER); + new spell_item_trinket_stack("spell_item_thunder_capacitor", SPELL_THUNDER_CAPACITOR_STACK, SPELL_THUNDER_CAPACITOR_TRIGGER); + new spell_item_trinket_stack("spell_item_toc25_normal_caster_trinket", SPELL_TOC25_CASTER_TRINKET_NORMAL_STACK, SPELL_TOC25_CASTER_TRINKET_NORMAL_TRIGGER); + new spell_item_trinket_stack("spell_item_toc25_heroic_caster_trinket", SPELL_TOC25_CASTER_TRINKET_HEROIC_STACK, SPELL_TOC25_CASTER_TRINKET_HEROIC_TRIGGER); + new spell_item_darkmoon_card_greatness(); + new spell_item_charm_witch_doctor(); + new spell_item_mana_drain(); } diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index d08968fbf55..bacbe31630c 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -29,6 +29,7 @@ enum MageSpells { + SPELL_MAGE_BLAZING_SPEED = 31643, SPELL_MAGE_BURNOUT = 29077, SPELL_MAGE_COLD_SNAP = 11958, SPELL_MAGE_FOCUS_MAGIC_PROC = 54648, @@ -116,6 +117,42 @@ class spell_mage_blast_wave : public SpellScriptLoader } }; +// -31641 - Blazing Speed +class spell_mage_blazing_speed : public SpellScriptLoader +{ +public: + spell_mage_blazing_speed() : SpellScriptLoader("spell_mage_blazing_speed") { } + + class spell_mage_blazing_speed_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_blazing_speed_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_BLAZING_SPEED)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + if (Unit* target = eventInfo.GetActionTarget()) + target->CastSpell(target, SPELL_MAGE_BLAZING_SPEED, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_mage_blazing_speed_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mage_blazing_speed_AuraScript(); + } +}; + // -44449 - Burnout class spell_mage_burnout : public SpellScriptLoader { @@ -180,7 +217,7 @@ class spell_mage_cold_snap : public SpellScriptLoader { GetCaster()->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); return spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && (spellInfo->GetSchoolMask() & SPELL_SCHOOL_MASK_FROST) && spellInfo->Id != SPELL_MAGE_COLD_SNAP && spellInfo->GetRecoveryTime() > 0; }, true); @@ -405,7 +442,7 @@ class spell_mage_ignite : public SpellScriptLoader { PreventDefaultAction(); - SpellInfo const* igniteDot = sSpellMgr->EnsureSpellInfo(SPELL_MAGE_IGNITE); + SpellInfo const* igniteDot = sSpellMgr->AssertSpellInfo(SPELL_MAGE_IGNITE); int32 pct = 8 * GetSpellInfo()->GetRank(); int32 amount = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), pct) / igniteDot->GetMaxTicks()); @@ -647,6 +684,7 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader void AddSC_mage_spell_scripts() { new spell_mage_blast_wave(); + new spell_mage_blazing_speed(); new spell_mage_burnout(); new spell_mage_cold_snap(); new spell_mage_fire_frost_ward(); diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index 8bd4b3eb070..6de95af8d8f 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -37,6 +37,7 @@ enum PaladinSpells SPELL_PALADIN_HOLY_SHOCK_R1 = 20473, SPELL_PALADIN_HOLY_SHOCK_R1_DAMAGE = 25912, SPELL_PALADIN_HOLY_SHOCK_R1_HEALING = 25914, + SPELL_PALADIN_ILLUMINATION_ENERGIZE = 20272, SPELL_PALADIN_BLESSING_OF_LOWER_CITY_DRUID = 37878, SPELL_PALADIN_BLESSING_OF_LOWER_CITY_PALADIN = 37879, @@ -871,6 +872,61 @@ class spell_pal_holy_shock : public SpellScriptLoader } }; +// -20210 - Illumination +class spell_pal_illumination : public SpellScriptLoader +{ +public: + spell_pal_illumination() : SpellScriptLoader("spell_pal_illumination") { } + + class spell_pal_illumination_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_illumination_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_HOLY_SHOCK_R1_HEALING) || + !sSpellMgr->GetSpellInfo(SPELL_PALADIN_ILLUMINATION_ENERGIZE) || + !sSpellMgr->GetSpellInfo(SPELL_PALADIN_HOLY_SHOCK_R1)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + // this script is valid only for the Holy Shock procs of illumination + if (eventInfo.GetHealInfo() && eventInfo.GetHealInfo()->GetSpellInfo()) + { + SpellInfo const* originalSpell = nullptr; + + // if proc comes from the Holy Shock heal, need to get mana cost of original spell - else it's the original heal itself + if (eventInfo.GetHealInfo()->GetSpellInfo()->SpellFamilyFlags[1] & 0x00010000) + originalSpell = sSpellMgr->GetSpellInfo(sSpellMgr->GetSpellWithRank(SPELL_PALADIN_HOLY_SHOCK_R1, eventInfo.GetHealInfo()->GetSpellInfo()->GetRank())); + else + originalSpell = eventInfo.GetHealInfo()->GetSpellInfo(); + + if (originalSpell && aurEff->GetSpellInfo()) + { + Unit* target = eventInfo.GetActor(); // Paladin is the target of the energize + uint32 bp = CalculatePct(originalSpell->CalcPowerCost(target, originalSpell->GetSchoolMask()), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()); + target->CastCustomSpell(SPELL_PALADIN_ILLUMINATION_ENERGIZE, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + } + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_pal_illumination_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_pal_illumination_AuraScript(); + } +}; + // Maybe this is incorrect // These spells should always be cast on login, regardless of whether the player has the talent or not @@ -1195,7 +1251,7 @@ class spell_pal_light_s_beacon : public SpellScriptLoader if (!procSpell) return; - uint32 healSpellId = procSpell->IsRankOf(sSpellMgr->EnsureSpellInfo(SPELL_PALADIN_HOLY_LIGHT)) ? SPELL_PALADIN_BEACON_OF_LIGHT_HEAL_1 : SPELL_PALADIN_BEACON_OF_LIGHT_HEAL_3; + uint32 healSpellId = procSpell->IsRankOf(sSpellMgr->AssertSpellInfo(SPELL_PALADIN_HOLY_LIGHT)) ? SPELL_PALADIN_BEACON_OF_LIGHT_HEAL_1 : SPELL_PALADIN_BEACON_OF_LIGHT_HEAL_3; uint32 heal = CalculatePct(eventInfo.GetHealInfo()->GetHeal(), aurEff->GetAmount()); Unit* beaconTarget = GetCaster(); @@ -1393,6 +1449,7 @@ void AddSC_paladin_spell_scripts() new spell_pal_hand_of_sacrifice(); new spell_pal_hand_of_salvation(); new spell_pal_holy_shock(); + new spell_pal_illumination(); new spell_pal_improved_aura("spell_pal_improved_concentraction_aura", SPELL_PALADIN_IMPROVED_CONCENTRACTION_AURA); new spell_pal_improved_aura("spell_pal_improved_devotion_aura", SPELL_PALADIN_IMPROVED_DEVOTION_AURA); new spell_pal_improved_aura("spell_pal_sanctified_retribution", SPELL_PALADIN_SANCTIFIED_RETRIBUTION_AURA); diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp index 7393a7d3bcb..cde291cd82b 100644 --- a/src/server/scripts/Spells/spell_pet.cpp +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -916,7 +916,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value AddPct(mod, spellInfo->Effects[EFFECT_0].CalcValue()); } @@ -959,7 +959,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value mod += CalculatePct(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); } @@ -989,7 +989,7 @@ public: if (itr != pet->ToPet()->m_spells.end()) // If pet has Wild Hunt { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); // Then get the SpellProto and add the dummy effect value mod += CalculatePct(1.0f, spellInfo->Effects[EFFECT_1].CalcValue()); } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index ecf5b7b5acf..9e2d265aa9c 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -29,6 +29,7 @@ enum PriestSpells { + SPELL_PRIEST_BLESSED_RECOVERY_R1 = 27813, SPELL_PRIEST_DIVINE_AEGIS = 47753, SPELL_PRIEST_EMPOWERED_RENEW = 63544, SPELL_PRIEST_GLYPH_OF_CIRCLE_OF_HEALING = 55675, @@ -88,6 +89,50 @@ class RaidCheck Unit const* _caster; }; +// -27811 - Blessed Recovery +class spell_pri_blessed_recovery : public SpellScriptLoader +{ +public: + spell_pri_blessed_recovery() : SpellScriptLoader("spell_pri_blessed_recovery") { } + + class spell_pri_blessed_recovery_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_blessed_recovery_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_BLESSED_RECOVERY_R1)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) + { + if (Unit* target = eventInfo.GetActionTarget()) + { + uint32 triggerSpell = sSpellMgr->GetSpellWithRank(SPELL_PRIEST_BLESSED_RECOVERY_R1, aurEff->GetSpellInfo()->GetRank()); + uint32 bp = CalculatePct(int32(dmgInfo->GetDamage()), aurEff->GetAmount()) / 3; + bp += target->GetRemainingPeriodicAmount(target->GetGUID(), triggerSpell, SPELL_AURA_PERIODIC_HEAL); + target->CastCustomSpell(triggerSpell, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + } + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_pri_blessed_recovery_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_pri_blessed_recovery_AuraScript(); + } +}; + // -34861 - Circle of Healing class spell_pri_circle_of_healing : public SpellScriptLoader { @@ -236,7 +281,7 @@ class spell_pri_glyph_of_prayer_of_healing : public SpellScriptLoader { PreventDefaultAction(); - SpellInfo const* triggeredSpellInfo = sSpellMgr->EnsureSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL); + SpellInfo const* triggeredSpellInfo = sSpellMgr->AssertSpellInfo(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL); int32 heal = int32(CalculatePct(int32(eventInfo.GetHealInfo()->GetHeal()), aurEff->GetAmount()) / triggeredSpellInfo->GetMaxTicks()); GetTarget()->CastCustomSpell(SPELL_PRIEST_GLYPH_OF_PRAYER_OF_HEALING_HEAL, SPELLVALUE_BASE_POINT0, heal, eventInfo.GetProcTarget(), true, NULL, aurEff); } @@ -869,6 +914,7 @@ class spell_pri_vampiric_touch : public SpellScriptLoader void AddSC_priest_spell_scripts() { + new spell_pri_blessed_recovery(); new spell_pri_circle_of_healing(); new spell_pri_divine_aegis(); new spell_pri_divine_hymn(); diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 3121a18734d..715e4d4ed2d 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -1080,9 +1080,7 @@ enum RedSnapperVeryTasty ITEM_RED_SNAPPER = 23614, SPELL_CAST_NET = 29866, - SPELL_NEW_SUMMON_TEST = 49214, - - GO_SCHOOL_OF_RED_SNAPPER = 181616 + SPELL_NEW_SUMMON_TEST = 49214 }; class spell_q9452_cast_net: public SpellScriptLoader @@ -1099,15 +1097,6 @@ class spell_q9452_cast_net: public SpellScriptLoader return GetCaster()->GetTypeId() == TYPEID_PLAYER; } - SpellCastResult CheckCast() - { - GameObject* go = GetCaster()->FindNearestGameObject(GO_SCHOOL_OF_RED_SNAPPER, 3.0f); - if (!go || go->GetRespawnTime()) - return SPELL_FAILED_REQUIRES_SPELL_FOCUS; - - return SPELL_CAST_OK; - } - void HandleDummy(SpellEffIndex /*effIndex*/) { Player* caster = GetCaster()->ToPlayer(); @@ -1127,7 +1116,6 @@ class spell_q9452_cast_net: public SpellScriptLoader void Register() override { - OnCheckCast += SpellCheckCastFn(spell_q9452_cast_net_SpellScript::CheckCast); OnEffectHit += SpellEffectFn(spell_q9452_cast_net_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); OnEffectHitTarget += SpellEffectFn(spell_q9452_cast_net_SpellScript::HandleActiveObject, EFFECT_1, SPELL_EFFECT_ACTIVATE_OBJECT); } @@ -1707,7 +1695,7 @@ enum Quest13291_13292_13239_13261Data NPC_SKYTALON = 31583, NPC_DECOY = 31578, // Spells - SPELL_RIDE = 56687 + SPELL_RIDE = 59319 }; class spell_q13291_q13292_q13239_q13261_frostbrood_skytalon_grab_decoy : public SpellScriptLoader @@ -2482,6 +2470,33 @@ class spell_q13665_q13790_bested_trigger : public SpellScriptLoader } }; +// herald of war and life without regret portal spells +class spell_59064_59439_portals : public SpellScriptLoader +{ +public: + spell_59064_59439_portals() : SpellScriptLoader("spell_59064_59439_portals") { } + + class spell_59064_59439_portals_SpellScript : public SpellScript + { + PrepareSpellScript(spell_59064_59439_portals_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetHitUnit()->CastSpell(GetHitUnit(), uint32(GetEffectValue())); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_59064_59439_portals_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_59064_59439_portals_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -2542,4 +2557,5 @@ void AddSC_quest_spell_scripts() new spell_q10929_fumping(); new spell_q12414_hand_over_reins(); new spell_q13665_q13790_bested_trigger(); + new spell_59064_59439_portals(); } diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index 9b577d4e140..1abb6741e0d 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -43,7 +43,8 @@ enum RogueSpells SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628, SPELL_ROGUE_HONOR_AMONG_THIEVES = 51698, SPELL_ROGUE_HONOR_AMONG_THIEVES_PROC = 52916, - SPELL_ROGUE_HONOR_AMONG_THIEVES_2 = 51699 + SPELL_ROGUE_HONOR_AMONG_THIEVES_2 = 51699, + SPELL_ROGUE_T10_2P_BONUS = 70804, }; // 13877, 33735, (check 51211, 65956) - Blade Flurry @@ -450,7 +451,7 @@ class spell_rog_preparation : public SpellScriptLoader Unit* caster = GetCaster(); caster->GetSpellHistory()->ResetCooldowns([caster](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); if (spellInfo->SpellFamilyName != SPELLFAMILY_ROGUE) return false; @@ -843,6 +844,40 @@ public: } }; +// 70805 - Rogue T10 2P Bonus -- THIS SHOULD BE REMOVED WITH NEW PROC SYSTEM. +class spell_rog_t10_2p_bonus : public SpellScriptLoader +{ +public: + spell_rog_t10_2p_bonus() : SpellScriptLoader("spell_rog_t10_2p_bonus") { } + + class spell_rog_t10_2p_bonus_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_t10_2p_bonus_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_T10_2P_BONUS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetActor() == eventInfo.GetActionTarget(); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_rog_t10_2p_bonus_AuraScript::CheckProc); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_rog_t10_2p_bonus_AuraScript(); + } +}; + void AddSC_rogue_spell_scripts() { new spell_rog_blade_flurry(); @@ -858,4 +893,5 @@ void AddSC_rogue_spell_scripts() new spell_rog_tricks_of_the_trade_proc(); new spell_rog_honor_among_thieves(); new spell_rog_honor_among_thieves_proc(); + new spell_rog_t10_2p_bonus(); } diff --git a/src/server/scripts/Spells/spell_script_loader.cpp b/src/server/scripts/Spells/spell_script_loader.cpp new file mode 100644 index 00000000000..b2c8d6663fa --- /dev/null +++ b/src/server/scripts/Spells/spell_script_loader.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// This is where scripts' loading functions should be declared: +void AddSC_deathknight_spell_scripts(); +void AddSC_druid_spell_scripts(); +void AddSC_generic_spell_scripts(); +void AddSC_hunter_spell_scripts(); +void AddSC_mage_spell_scripts(); +void AddSC_paladin_spell_scripts(); +void AddSC_priest_spell_scripts(); +void AddSC_rogue_spell_scripts(); +void AddSC_shaman_spell_scripts(); +void AddSC_warlock_spell_scripts(); +void AddSC_warrior_spell_scripts(); +void AddSC_quest_spell_scripts(); +void AddSC_item_spell_scripts(); +void AddSC_holiday_spell_scripts(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddSpellsScripts() +{ + AddSC_deathknight_spell_scripts(); + AddSC_druid_spell_scripts(); + AddSC_generic_spell_scripts(); + AddSC_hunter_spell_scripts(); + AddSC_mage_spell_scripts(); + AddSC_paladin_spell_scripts(); + AddSC_priest_spell_scripts(); + AddSC_rogue_spell_scripts(); + AddSC_shaman_spell_scripts(); + AddSC_warlock_spell_scripts(); + AddSC_warrior_spell_scripts(); + AddSC_quest_spell_scripts(); + AddSC_item_spell_scripts(); + AddSC_holiday_spell_scripts(); +} diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 41e72b1388b..ad65c7c6ec7 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -48,8 +48,10 @@ enum ShamanSpells SPELL_SHAMAN_ITEM_MANA_SURGE = 23571, SPELL_SHAMAN_LAVA_FLOWS_R1 = 51480, SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1 = 64694, + SPELL_SHAMAN_LIGHTNING_SHIELD_R1 = 26364, SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE = 52032, SPELL_SHAMAN_MANA_TIDE_TOTEM = 39609, + SPELL_SHAMAN_NATURE_GUARDIAN = 31616, SPELL_SHAMAN_SATED = 57724, SPELL_SHAMAN_STORM_EARTH_AND_FIRE = 51483, SPELL_SHAMAN_TOTEM_EARTHBIND_EARTHGRAB = 64695, @@ -671,7 +673,7 @@ class spell_sha_heroism : public SpellScriptLoader } }; -// 23551 - Lightning Shield +// 23551 - Lightning Shield T2 Bonus class spell_sha_item_lightning_shield : public SpellScriptLoader { public: @@ -706,7 +708,7 @@ class spell_sha_item_lightning_shield : public SpellScriptLoader } }; -// 23552 - Lightning Shield +// 23552 - Lightning Shield T2 Bonus class spell_sha_item_lightning_shield_trigger : public SpellScriptLoader { public: @@ -718,7 +720,7 @@ class spell_sha_item_lightning_shield_trigger : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) override { - if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_MANA_SURGE)) + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE)) return false; return true; } @@ -753,7 +755,7 @@ class spell_sha_item_mana_surge : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) override { - if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE)) + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_MANA_SURGE)) return false; return true; } @@ -865,6 +867,51 @@ class spell_sha_lava_lash : public SpellScriptLoader } }; +// -324 - Lightning Shield +class spell_sha_lightning_shield : public SpellScriptLoader +{ +public: + spell_sha_lightning_shield() : SpellScriptLoader("spell_sha_lightning_shield") { } + + class spell_sha_lightning_shield_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_lightning_shield_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_LIGHTNING_SHIELD_R1)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetActionTarget()) + return true; + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + uint32 triggerSpell = sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_LIGHTNING_SHIELD_R1, aurEff->GetSpellInfo()->GetRank()); + + eventInfo.GetActionTarget()->CastSpell(eventInfo.GetActor(), triggerSpell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_sha_lightning_shield_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_sha_lightning_shield_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_sha_lightning_shield_AuraScript(); + } +}; + // 52031, 52033, 52034, 52035, 52036, 58778, 58779, 58780 - Mana Spring Totem class spell_sha_mana_spring_totem : public SpellScriptLoader { @@ -924,6 +971,7 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader void HandleDummy(SpellEffIndex /*effIndex*/) { if (Unit* caster = GetCaster()) + { if (Unit* unitTarget = GetHitUnit()) { if (unitTarget->getPowerType() == POWER_MANA) @@ -938,6 +986,7 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader caster->CastCustomSpell(unitTarget, SPELL_SHAMAN_MANA_TIDE_TOTEM, &effBasePoints0, NULL, NULL, true, NULL, NULL, GetOriginalCaster()->GetGUID()); } } + } } void Register() override @@ -952,6 +1001,56 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader } }; +// -30881 - Nature's Guardian +class spell_sha_nature_guardian : public SpellScriptLoader +{ +public: + spell_sha_nature_guardian() : SpellScriptLoader("spell_sha_nature_guardian") { } + + class spell_sha_nature_guardian_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_nature_guardian_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_NATURE_GUARDIAN)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 healthpct = aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); // %s2 - the 30% threshold for health + + if (Unit* target = eventInfo.GetActionTarget()) + { + if (target->HealthBelowPctDamaged(healthpct, eventInfo.GetDamageInfo()->GetDamage())) + { + + uint32 bp = CalculatePct(target->GetMaxHealth(), aurEff->GetAmount()); + target->CastCustomSpell(SPELL_SHAMAN_NATURE_GUARDIAN, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + + // Threat reduction is around 10% confirmed in retail and from wiki + Unit* attacker = eventInfo.GetActor(); + if (attacker->IsAlive()) + attacker->getThreatManager().modifyThreatPercent(target, -10); + } + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_sha_nature_guardian_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_sha_nature_guardian_AuraScript(); + } +}; + // 6495 - Sentry Totem class spell_sha_sentry_totem : public SpellScriptLoader { @@ -1085,8 +1184,10 @@ void AddSC_shaman_spell_scripts() new spell_sha_item_mana_surge(); new spell_sha_item_t10_elemental_2p_bonus(); new spell_sha_lava_lash(); + new spell_sha_lightning_shield(); new spell_sha_mana_spring_totem(); new spell_sha_mana_tide_totem(); + new spell_sha_nature_guardian(); new spell_sha_sentry_totem(); new spell_sha_thunderstorm(); new spell_sha_totemic_mastery(); diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 7cc6fe888e9..5e0074bf9f7 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -50,6 +50,12 @@ enum WarlockSpells SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R2 = 60956, SPELL_WARLOCK_LIFE_TAP_ENERGIZE = 31818, SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2 = 32553, + SPELL_WARLOCK_NETHER_PROTECTION_HOLY = 54370, + SPELL_WARLOCK_NETHER_PROTECTION_FIRE = 54371, + SPELL_WARLOCK_NETHER_PROTECTION_FROST = 54372, + SPELL_WARLOCK_NETHER_PROTECTION_ARCANE = 54373, + SPELL_WARLOCK_NETHER_PROTECTION_SHADOW = 54374, + SPELL_WARLOCK_NETHER_PROTECTION_NATURE = 54375, SPELL_WARLOCK_SOULSHATTER = 32835, SPELL_WARLOCK_SIPHON_LIFE_HEAL = 63106, SPELL_WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117 @@ -271,7 +277,7 @@ class spell_warl_demonic_circle_summon : public SpellScriptLoader // WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST; allowing him to cast the WARLOCK_DEMONIC_CIRCLE_TELEPORT. // If not in range remove the WARLOCK_DEMONIC_CIRCLE_ALLOW_CAST. - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_CIRCLE_TELEPORT); if (GetTarget()->IsWithinDist(circle, spellInfo->GetMaxRange(true))) { @@ -362,7 +368,7 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader break; case CREATURE_FAMILY_VOIDWALKER: { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER); int32 hp = int32(targetCreature->CountPctFromMaxHealth(GetCaster()->CalculateSpellDamage(targetCreature, spellInfo, 0))); targetCreature->CastCustomSpell(targetCreature, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_VOIDWALKER, &hp, NULL, NULL, true); //unitTarget->CastSpell(unitTarget, 54441, true); @@ -377,6 +383,8 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader case CREATURE_FAMILY_IMP: targetCreature->CastSpell(targetCreature, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_IMP, true); break; + default: + break; } } } @@ -682,6 +690,95 @@ class spell_warl_life_tap : public SpellScriptLoader } }; +// -30299 - Nether Protection +class spell_warl_nether_protection : public SpellScriptLoader +{ +public: + spell_warl_nether_protection() : SpellScriptLoader("spell_warl_nether_protection") { } + + class spell_warl_nether_protection_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_nether_protection_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_HOLY) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_FIRE) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_FROST) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_ARCANE) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_SHADOW) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_NATURE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetDamageInfo()) + { + switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + case SPELL_SCHOOL_FIRE: + case SPELL_SCHOOL_NATURE: + case SPELL_SCHOOL_FROST: + case SPELL_SCHOOL_SHADOW: + case SPELL_SCHOOL_ARCANE: + return true; + default: + break; + } + } + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + uint32 triggerspell = 0; + + switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_HOLY; + break; + case SPELL_SCHOOL_FIRE: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_FIRE; + break; + case SPELL_SCHOOL_NATURE: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_NATURE; + break; + case SPELL_SCHOOL_FROST: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_FROST; + break; + case SPELL_SCHOOL_SHADOW: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_SHADOW; + break; + case SPELL_SCHOOL_ARCANE: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_ARCANE; + break; + default: + return; + } + + if (Unit* target = eventInfo.GetActionTarget()) + target->CastSpell(target, triggerspell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_warl_nether_protection_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warl_nether_protection_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_warl_nether_protection_AuraScript(); + } +}; + // 18541 - Ritual of Doom Effect class spell_warl_ritual_of_doom_effect : public SpellScriptLoader { @@ -917,6 +1014,7 @@ void AddSC_warlock_spell_scripts() new spell_warl_haunt(); new spell_warl_health_funnel(); new spell_warl_life_tap(); + new spell_warl_nether_protection(); new spell_warl_ritual_of_doom_effect(); new spell_warl_seed_of_corruption(); new spell_warl_shadow_ward(); diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index d224c234cb4..ea9ccc956e5 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -271,7 +271,7 @@ class spell_warr_deep_wounds : public SpellScriptLoader { ApplyPct(damage, 16 * GetSpellInfo()->GetRank()); - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC); + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC); uint32 ticks = uint32(spellInfo->GetDuration()) / spellInfo->Effects[EFFECT_0].Amplitude; // Add remaining ticks to damage done diff --git a/src/server/scripts/World/CMakeLists.txt b/src/server/scripts/World/CMakeLists.txt deleted file mode 100644 index 17b3f2d8492..00000000000 --- a/src/server/scripts/World/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -file(GLOB_RECURSE sources_World World/*.cpp World/*.h) - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} - ${sources_World} -) - -message(" -> Prepared: World") diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp index 1f89720803d..65dec74414b 100644 --- a/src/server/scripts/World/boss_emerald_dragons.cpp +++ b/src/server/scripts/World/boss_emerald_dragons.cpp @@ -205,7 +205,7 @@ class npc_dream_fog : public CreatureScript } // Seeping fog movement is slow enough for a player to be able to walk backwards and still outpace it me->SetWalk(true); - me->SetSpeed(MOVE_WALK, 0.75f); + me->SetSpeedRate(MOVE_WALK, 0.75f); } else _roamTimer -= diff; diff --git a/src/server/scripts/World/duel_reset.cpp b/src/server/scripts/World/duel_reset.cpp index 3c46255a1bf..b04f3ec0aa7 100644 --- a/src/server/scripts/World/duel_reset.cpp +++ b/src/server/scripts/World/duel_reset.cpp @@ -98,16 +98,16 @@ class DuelResetScript : public PlayerScript static void ResetSpellCooldowns(Player* player, bool onStartDuel) { - if (onStartDuel) + if (onStartDuel) { // remove cooldowns on spells that have < 10 min CD > 30 sec and has no onHold player->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool { SpellHistory::Clock::time_point now = SpellHistory::Clock::now(); uint32 cooldownDuration = itr->second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(itr->second.CooldownEnd - now).count() : 0; - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); - return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS - && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); + return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS + && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS && !itr->second.OnHold && cooldownDuration > 0 && ( spellInfo->RecoveryTime - cooldownDuration ) > (MINUTE / 2) * IN_MILLISECONDS @@ -119,11 +119,11 @@ class DuelResetScript : public PlayerScript // remove cooldowns on spells that have < 10 min CD and has no onHold player->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool { - SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first); - return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS - && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(itr->first); + return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS + && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS && !itr->second.OnHold; - }, true); + }, true); } // pet cooldowns diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index b90839f50c5..3db4f41706d 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -1171,7 +1171,7 @@ public: player->CastSpell(player, SPELL_CLEANSING_SOUL); player->SetStandState(UNIT_STAND_STATE_SIT); } - return true; + return true; } }; @@ -1197,6 +1197,29 @@ public: } }; +enum MidsummerPoleRibbon +{ + SPELL_POLE_DANCE = 29726, + SPELL_BLUE_FIRE_RING = 46842, + NPC_POLE_RIBBON_BUNNY = 17066, + ACTION_COSMETIC_FIRES = 0 +}; + +class go_midsummer_ribbon_pole : public GameObjectScript +{ +public: + go_midsummer_ribbon_pole() : GameObjectScript("go_midsummer_ribbon_pole") { } + + bool OnGossipHello(Player* player, GameObject* go) override + { + if (Creature* creature = go->FindNearestCreature(NPC_POLE_RIBBON_BUNNY, 10.0f)) + { + creature->GetAI()->DoAction(ACTION_COSMETIC_FIRES); + player->CastSpell(creature, SPELL_POLE_DANCE, true); + } + return true; + } +}; enum ToyTrainSpells { @@ -1211,7 +1234,7 @@ class go_toy_train_set : public GameObjectScript struct go_toy_train_setAI : public GameObjectAI { go_toy_train_setAI(GameObject* go) : GameObjectAI(go), _pulseTimer(3 * IN_MILLISECONDS) { } - + void UpdateAI(uint32 diff) override { if (diff < _pulseTimer) @@ -1274,5 +1297,6 @@ void AddSC_go_scripts() new go_veil_skith_cage(); new go_frostblade_shrine(); new go_midsummer_bonfire(); + new go_midsummer_ribbon_pole(); new go_toy_train_set(); } diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp index f4241ba0819..ff15698e579 100644 --- a/src/server/scripts/World/item_scripts.cpp +++ b/src/server/scripts/World/item_scripts.cpp @@ -57,18 +57,18 @@ public: //for special scripts switch (itemId) { - case 24538: + case 24538: if (player->GetAreaId() != 3628) disabled = true; - break; - case 34489: + break; + case 34489: if (player->GetZoneId() != 4080) disabled = true; - break; - case 34475: - if (const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(SPELL_ARCANE_CHARGES)) + break; + case 34475: + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_ARCANE_CHARGES)) Spell::SendCastResult(player, spellInfo, 1, SPELL_FAILED_NOT_ON_GROUND); - break; + break; } // allow use in flight only @@ -241,7 +241,7 @@ public: float x, y, z; go->GetClosePoint(x, y, z, go->GetObjectSize() / 3, 7.0f); - go->SummonGameObject(GO_HIGH_QUALITY_FUR, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ(), 0, 0, 0, 0, 0, 1); + go->SummonGameObject(GO_HIGH_QUALITY_FUR, *go, G3D::Quat(), 1); if (TempSummon* summon = player->SummonCreature(NPC_NESINGWARY_TRAPPER, x, y, z, go->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 1000)) { summon->SetVisible(false); diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 56d48949fac..277bc9ac804 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -36,7 +36,6 @@ npc_doctor 100% Gustaf Vanhowzen and Gregory Victor, quest 6622 npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given npc_snake_trap_serpents 80% AI for snakes that summoned by Snake Trap npc_shadowfiend 100% restore 5% of owner's mana when shadowfiend die from damage -npc_locksmith 75% list of keys needs to be confirmed npc_firework 100% NPC's summoned by rockets and rocket clusters, for making them cast visual npc_train_wrecker 100% Wind-Up Train Wrecker that kills train set EndContentData */ @@ -57,7 +56,6 @@ EndContentData */ #include "SpellHistory.h" #include "SpellAuras.h" #include "Pet.h" -#include "PetAI.h" #include "CreatureTextMgr.h" #include "SmartAI.h" @@ -582,6 +580,115 @@ public: }; /*###### +## npc_midsummer_bunny_pole +######*/ + +enum RibbonPoleData +{ + GO_RIBBON_POLE = 181605, + SPELL_RIBBON_DANCE_COSMETIC = 29726, + SPELL_RED_FIRE_RING = 46836, + SPELL_BLUE_FIRE_RING = 46842, + EVENT_CAST_RED_FIRE_RING = 1, + EVENT_CAST_BLUE_FIRE_RING = 2 +}; + +class npc_midsummer_bunny_pole : public CreatureScript +{ +public: + npc_midsummer_bunny_pole() : CreatureScript("npc_midsummer_bunny_pole") { } + + struct npc_midsummer_bunny_poleAI : public ScriptedAI + { + npc_midsummer_bunny_poleAI(Creature* creature) : ScriptedAI(creature) + { + Initialize(); + } + + void Initialize() + { + events.Reset(); + running = false; + } + + void Reset() override + { + Initialize(); + } + + void DoAction(int32 /*action*/) override + { + // Don't start event if it's already running. + if (running) + return; + + running = true; + events.ScheduleEvent(EVENT_CAST_RED_FIRE_RING, 1); + } + + bool checkNearbyPlayers() + { + // Returns true if no nearby player has aura "Test Ribbon Pole Channel". + std::list<Player*> players; + Trinity::UnitAuraCheck check(true, SPELL_RIBBON_DANCE_COSMETIC); + Trinity::PlayerListSearcher<Trinity::UnitAuraCheck> searcher(me, players, check); + me->VisitNearbyWorldObject(10.0f, searcher); + + return players.empty(); + } + + void UpdateAI(uint32 diff) override + { + if (!running) + return; + + events.Update(diff); + + switch (events.ExecuteEvent()) + { + case EVENT_CAST_RED_FIRE_RING: + { + if (checkNearbyPlayers()) + { + Reset(); + return; + } + + if (GameObject* go = me->FindNearestGameObject(GO_RIBBON_POLE, 10.0f)) + me->CastSpell(go, SPELL_RED_FIRE_RING, true); + + events.ScheduleEvent(EVENT_CAST_BLUE_FIRE_RING, Seconds(5)); + } + break; + case EVENT_CAST_BLUE_FIRE_RING: + { + if (checkNearbyPlayers()) + { + Reset(); + return; + } + + if (GameObject* go = me->FindNearestGameObject(GO_RIBBON_POLE, 10.0f)) + me->CastSpell(go, SPELL_BLUE_FIRE_RING, true); + + events.ScheduleEvent(EVENT_CAST_RED_FIRE_RING, Seconds(5)); + } + break; + } + } + + private: + EventMap events; + bool running; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_midsummer_bunny_poleAI(creature); + } +}; + +/*###### ## Triage quest ######*/ @@ -1189,36 +1296,49 @@ public: enum Sayge { - SPELL_DMG = 23768, // dmg - SPELL_RES = 23769, // res - SPELL_ARM = 23767, // arm - SPELL_SPI = 23738, // spi - SPELL_INT = 23766, // int - SPELL_STM = 23737, // stm - SPELL_STR = 23735, // str - SPELL_AGI = 23736, // agi - SPELL_FORTUNE = 23765 // faire fortune + GOSSIP_MENU_OPTION_ID_ANSWER_1 = 0, + GOSSIP_MENU_OPTION_ID_ANSWER_2 = 1, + GOSSIP_MENU_OPTION_ID_ANSWER_3 = 2, + GOSSIP_MENU_OPTION_ID_ANSWER_4 = 3, + GOSSIP_I_AM_READY_TO_DISCOVER = 6186, + GOSSIP_MENU_OPTION_SAYGE1 = 6185, + GOSSIP_MENU_OPTION_SAYGE2 = 6185, + GOSSIP_MENU_OPTION_SAYGE3 = 6185, + GOSSIP_MENU_OPTION_SAYGE4 = 6185, + GOSSIP_MENU_OPTION_SAYGE5 = 6187, + GOSSIP_MENU_OPTION_SAYGE6 = 6187, + GOSSIP_MENU_OPTION_SAYGE7 = 6187, + GOSSIP_MENU_OPTION_SAYGE8 = 6208, + GOSSIP_MENU_OPTION_SAYGE9 = 6208, + GOSSIP_MENU_OPTION_SAYGE10 = 6208, + GOSSIP_MENU_OPTION_SAYGE11 = 6209, + GOSSIP_MENU_OPTION_SAYGE12 = 6209, + GOSSIP_MENU_OPTION_SAYGE13 = 6209, + GOSSIP_MENU_OPTION_SAYGE14 = 6210, + GOSSIP_MENU_OPTION_SAYGE15 = 6210, + GOSSIP_MENU_OPTION_SAYGE16 = 6210, + GOSSIP_MENU_OPTION_SAYGE17 = 6211, + GOSSIP_MENU_I_HAVE_LONG_KNOWN = 7339, + GOSSIP_MENU_YOU_HAVE_BEEN_TASKED = 7340, + GOSSIP_MENU_SWORN_EXECUTIONER = 7341, + GOSSIP_MENU_DIPLOMATIC_MISSION = 7361, + GOSSIP_MENU_YOUR_BROTHER_SEEKS = 7362, + GOSSIP_MENU_A_TERRIBLE_BEAST = 7363, + GOSSIP_MENU_YOUR_FORTUNE_IS_CAST = 7364, + GOSSIP_MENU_HERE_IS_YOUR_FORTUNE = 7365, + GOSSIP_MENU_CANT_GIVE_YOU_YOUR = 7393, + + SPELL_STRENGTH = 23735, // +10% Strength + SPELL_AGILITY = 23736, // +10% Agility + SPELL_STAMINA = 23737, // +10% Stamina + SPELL_SPIRIT = 23738, // +10% Spirit + SPELL_INTELLECT = 23766, // +10% Intellect + SPELL_ARMOR = 23767, // +10% Armor + SPELL_DAMAGE = 23768, // +10% Damage + SPELL_RESISTANCE = 23769, // +25 Magic Resistance (All) + SPELL_FORTUNE = 23765 // Darkmoon Faire Fortune }; -#define GOSSIP_HELLO_SAYGE "Yes" -#define GOSSIP_SENDACTION_SAYGE1 "Slay the Man" -#define GOSSIP_SENDACTION_SAYGE2 "Turn him over to liege" -#define GOSSIP_SENDACTION_SAYGE3 "Confiscate the corn" -#define GOSSIP_SENDACTION_SAYGE4 "Let him go and have the corn" -#define GOSSIP_SENDACTION_SAYGE5 "Execute your friend painfully" -#define GOSSIP_SENDACTION_SAYGE6 "Execute your friend painlessly" -#define GOSSIP_SENDACTION_SAYGE7 "Let your friend go" -#define GOSSIP_SENDACTION_SAYGE8 "Confront the diplomat" -#define GOSSIP_SENDACTION_SAYGE9 "Show not so quiet defiance" -#define GOSSIP_SENDACTION_SAYGE10 "Remain quiet" -#define GOSSIP_SENDACTION_SAYGE11 "Speak against your brother openly" -#define GOSSIP_SENDACTION_SAYGE12 "Help your brother in" -#define GOSSIP_SENDACTION_SAYGE13 "Keep your brother out without letting him know" -#define GOSSIP_SENDACTION_SAYGE14 "Take credit, keep gold" -#define GOSSIP_SENDACTION_SAYGE15 "Take credit, share the gold" -#define GOSSIP_SENDACTION_SAYGE16 "Let the knight take credit" -#define GOSSIP_SENDACTION_SAYGE17 "Thanks" - class npc_sayge : public CreatureScript { public: @@ -1229,19 +1349,19 @@ public: if (creature->IsQuestGiver()) player->PrepareQuestMenu(creature->GetGUID()); - if (player->GetSpellHistory()->HasCooldown(SPELL_INT) || - player->GetSpellHistory()->HasCooldown(SPELL_ARM) || - player->GetSpellHistory()->HasCooldown(SPELL_DMG) || - player->GetSpellHistory()->HasCooldown(SPELL_RES) || - player->GetSpellHistory()->HasCooldown(SPELL_STR) || - player->GetSpellHistory()->HasCooldown(SPELL_AGI) || - player->GetSpellHistory()->HasCooldown(SPELL_STM) || - player->GetSpellHistory()->HasCooldown(SPELL_SPI)) - player->SEND_GOSSIP_MENU(7393, creature->GetGUID()); + if (player->GetSpellHistory()->HasCooldown(SPELL_STRENGTH) || + player->GetSpellHistory()->HasCooldown(SPELL_AGILITY) || + player->GetSpellHistory()->HasCooldown(SPELL_STAMINA) || + player->GetSpellHistory()->HasCooldown(SPELL_SPIRIT) || + player->GetSpellHistory()->HasCooldown(SPELL_INTELLECT) || + player->GetSpellHistory()->HasCooldown(SPELL_ARMOR) || + player->GetSpellHistory()->HasCooldown(SPELL_DAMAGE) || + player->GetSpellHistory()->HasCooldown(SPELL_RESISTANCE)) + player->SEND_GOSSIP_MENU(GOSSIP_MENU_CANT_GIVE_YOU_YOUR, creature->GetGUID()); else { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_SAYGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(7339, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_I_AM_READY_TO_DISCOVER, GOSSIP_MENU_OPTION_ID_ANSWER_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + player->SEND_GOSSIP_MENU(GOSSIP_MENU_I_HAVE_LONG_KNOWN, creature->GetGUID()); } return true; @@ -1252,43 +1372,43 @@ public: switch (action) { case GOSSIP_ACTION_INFO_DEF + 1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(7340, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE1, GOSSIP_MENU_OPTION_ID_ANSWER_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE2, GOSSIP_MENU_OPTION_ID_ANSWER_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE3, GOSSIP_MENU_OPTION_ID_ANSWER_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE4, GOSSIP_MENU_OPTION_ID_ANSWER_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); + player->SEND_GOSSIP_MENU(GOSSIP_MENU_YOU_HAVE_BEEN_TASKED, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF + 2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE5, GOSSIP_SENDER_MAIN + 1, GOSSIP_ACTION_INFO_DEF); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE6, GOSSIP_SENDER_MAIN + 2, GOSSIP_ACTION_INFO_DEF); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE7, GOSSIP_SENDER_MAIN + 3, GOSSIP_ACTION_INFO_DEF); - player->SEND_GOSSIP_MENU(7341, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE5, GOSSIP_MENU_OPTION_ID_ANSWER_1, GOSSIP_SENDER_MAIN + 1, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE6, GOSSIP_MENU_OPTION_ID_ANSWER_2, GOSSIP_SENDER_MAIN + 2, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE7, GOSSIP_MENU_OPTION_ID_ANSWER_3, GOSSIP_SENDER_MAIN + 3, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(GOSSIP_MENU_SWORN_EXECUTIONER, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF + 3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE8, GOSSIP_SENDER_MAIN + 4, GOSSIP_ACTION_INFO_DEF); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE9, GOSSIP_SENDER_MAIN + 5, GOSSIP_ACTION_INFO_DEF); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE10, GOSSIP_SENDER_MAIN + 2, GOSSIP_ACTION_INFO_DEF); - player->SEND_GOSSIP_MENU(7361, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE8, GOSSIP_MENU_OPTION_ID_ANSWER_1, GOSSIP_SENDER_MAIN + 4, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE9, GOSSIP_MENU_OPTION_ID_ANSWER_2, GOSSIP_SENDER_MAIN + 5, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE10,GOSSIP_MENU_OPTION_ID_ANSWER_3, GOSSIP_SENDER_MAIN + 2, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(GOSSIP_MENU_DIPLOMATIC_MISSION, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF + 4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE11, GOSSIP_SENDER_MAIN + 6, GOSSIP_ACTION_INFO_DEF); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE12, GOSSIP_SENDER_MAIN + 7, GOSSIP_ACTION_INFO_DEF); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE13, GOSSIP_SENDER_MAIN + 8, GOSSIP_ACTION_INFO_DEF); - player->SEND_GOSSIP_MENU(7362, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE11, GOSSIP_MENU_OPTION_ID_ANSWER_1, GOSSIP_SENDER_MAIN + 6, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE12, GOSSIP_MENU_OPTION_ID_ANSWER_2, GOSSIP_SENDER_MAIN + 7, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE13, GOSSIP_MENU_OPTION_ID_ANSWER_3, GOSSIP_SENDER_MAIN + 8, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(GOSSIP_MENU_YOUR_BROTHER_SEEKS, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF + 5: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE14, GOSSIP_SENDER_MAIN + 5, GOSSIP_ACTION_INFO_DEF); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE15, GOSSIP_SENDER_MAIN + 4, GOSSIP_ACTION_INFO_DEF); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE16, GOSSIP_SENDER_MAIN + 3, GOSSIP_ACTION_INFO_DEF); - player->SEND_GOSSIP_MENU(7363, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE14, GOSSIP_MENU_OPTION_ID_ANSWER_1, GOSSIP_SENDER_MAIN + 5, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE15, GOSSIP_MENU_OPTION_ID_ANSWER_2, GOSSIP_SENDER_MAIN + 4, GOSSIP_ACTION_INFO_DEF); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE16, GOSSIP_MENU_OPTION_ID_ANSWER_3, GOSSIP_SENDER_MAIN + 3, GOSSIP_ACTION_INFO_DEF); + player->SEND_GOSSIP_MENU(GOSSIP_MENU_A_TERRIBLE_BEAST, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SENDACTION_SAYGE17, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - player->SEND_GOSSIP_MENU(7364, creature->GetGUID()); + player->ADD_GOSSIP_ITEM_DB(GOSSIP_MENU_OPTION_SAYGE17, GOSSIP_MENU_OPTION_ID_ANSWER_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); + player->SEND_GOSSIP_MENU(GOSSIP_MENU_YOUR_FORTUNE_IS_CAST, creature->GetGUID()); break; case GOSSIP_ACTION_INFO_DEF + 6: creature->CastSpell(player, SPELL_FORTUNE, false); - player->SEND_GOSSIP_MENU(7365, creature->GetGUID()); + player->SEND_GOSSIP_MENU(GOSSIP_MENU_HERE_IS_YOUR_FORTUNE, creature->GetGUID()); break; } } @@ -1303,28 +1423,28 @@ public: SendAction(player, creature, action); break; case GOSSIP_SENDER_MAIN + 1: - spellId = SPELL_DMG; + spellId = SPELL_DAMAGE; break; case GOSSIP_SENDER_MAIN + 2: - spellId = SPELL_RES; + spellId = SPELL_RESISTANCE; break; case GOSSIP_SENDER_MAIN + 3: - spellId = SPELL_ARM; + spellId = SPELL_ARMOR; break; case GOSSIP_SENDER_MAIN + 4: - spellId = SPELL_SPI; + spellId = SPELL_SPIRIT; break; case GOSSIP_SENDER_MAIN + 5: - spellId = SPELL_INT; + spellId = SPELL_INTELLECT; break; case GOSSIP_SENDER_MAIN + 6: - spellId = SPELL_STM; + spellId = SPELL_STAMINA; break; case GOSSIP_SENDER_MAIN + 7: - spellId = SPELL_STR; + spellId = SPELL_STRENGTH; break; case GOSSIP_SENDER_MAIN + 8: - spellId = SPELL_AGI; + spellId = SPELL_AGILITY; break; } @@ -1744,149 +1864,6 @@ public: }; /*###### -## npc_locksmith -######*/ - -enum LockSmith -{ - QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ = 10704, - QUEST_DARK_IRON_LEGACY = 3802, - QUEST_THE_KEY_TO_SCHOLOMANCE_A = 5505, - QUEST_THE_KEY_TO_SCHOLOMANCE_H = 5511, - QUEST_HOTTER_THAN_HELL_A = 10758, - QUEST_HOTTER_THAN_HELL_H = 10764, - QUEST_RETURN_TO_KHAGDAR = 9837, - QUEST_CONTAINMENT = 13159, - QUEST_ETERNAL_VIGILANCE = 11011, - QUEST_KEY_TO_THE_FOCUSING_IRIS = 13372, - QUEST_HC_KEY_TO_THE_FOCUSING_IRIS = 13375, - - ITEM_ARCATRAZ_KEY = 31084, - ITEM_SHADOWFORGE_KEY = 11000, - ITEM_SKELETON_KEY = 13704, - ITEM_SHATTERED_HALLS_KEY = 28395, - ITEM_THE_MASTERS_KEY = 24490, - ITEM_VIOLET_HOLD_KEY = 42482, - ITEM_ESSENCE_INFUSED_MOONSTONE = 32449, - ITEM_KEY_TO_THE_FOCUSING_IRIS = 44582, - ITEM_HC_KEY_TO_THE_FOCUSING_IRIS = 44581, - - SPELL_ARCATRAZ_KEY = 54881, - SPELL_SHADOWFORGE_KEY = 54882, - SPELL_SKELETON_KEY = 54883, - SPELL_SHATTERED_HALLS_KEY = 54884, - SPELL_THE_MASTERS_KEY = 54885, - SPELL_VIOLET_HOLD_KEY = 67253, - SPELL_ESSENCE_INFUSED_MOONSTONE = 40173, -}; - -#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz." -#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths." -#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance." -#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls." -#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan." -#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold." -#define GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE "I've lost my Essence-Infused Moonstone." -#define GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS "I've lost my Key to the Focusing Iris." -#define GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS "I've lost my Heroic Key to the Focusing Iris." - -class npc_locksmith : public CreatureScript -{ -public: - npc_locksmith() : CreatureScript("npc_locksmith") { } - - bool OnGossipHello(Player* player, Creature* creature) override - { - // Arcatraz Key - if (player->GetQuestRewardStatus(QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ) && !player->HasItemCount(ITEM_ARCATRAZ_KEY, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ARCATRAZ_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - - // Shadowforge Key - if (player->GetQuestRewardStatus(QUEST_DARK_IRON_LEGACY) && !player->HasItemCount(ITEM_SHADOWFORGE_KEY, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHADOWFORGE_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - - // Skeleton Key - if ((player->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_A) || player->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_H)) && - !player->HasItemCount(ITEM_SKELETON_KEY, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SKELETON_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - - // Shatered Halls Key - if ((player->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_A) || player->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_H)) && - !player->HasItemCount(ITEM_SHATTERED_HALLS_KEY, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_SHATTERED_HALLS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - - // Master's Key - if (player->GetQuestRewardStatus(QUEST_RETURN_TO_KHAGDAR) && !player->HasItemCount(ITEM_THE_MASTERS_KEY, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_THE_MASTERS_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - - // Violet Hold Key - if (player->GetQuestRewardStatus(QUEST_CONTAINMENT) && !player->HasItemCount(ITEM_VIOLET_HOLD_KEY, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_VIOLET_HOLD_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - - // Essence-Infused Moonstone - if (player->GetQuestRewardStatus(QUEST_ETERNAL_VIGILANCE) && !player->HasItemCount(ITEM_ESSENCE_INFUSED_MOONSTONE, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - - // Key to the Focusing Iris - if (player->GetQuestRewardStatus(QUEST_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_KEY_TO_THE_FOCUSING_IRIS, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8); - - // Heroic Key to the Focusing Iris - if (player->GetQuestRewardStatus(QUEST_HC_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS, 1, true)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } - - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF + 1: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, SPELL_ARCATRAZ_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, SPELL_SHADOWFORGE_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, SPELL_SKELETON_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF + 4: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, SPELL_SHATTERED_HALLS_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF + 5: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, SPELL_THE_MASTERS_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF + 6: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, SPELL_VIOLET_HOLD_KEY, false); - break; - case GOSSIP_ACTION_INFO_DEF + 7: - player->CLOSE_GOSSIP_MENU(); - player->CastSpell(player, SPELL_ESSENCE_INFUSED_MOONSTONE, false); - break; - case GOSSIP_ACTION_INFO_DEF + 8: - player->CLOSE_GOSSIP_MENU(); - player->AddItem(ITEM_KEY_TO_THE_FOCUSING_IRIS, 1); - break; - case GOSSIP_ACTION_INFO_DEF + 9: - player->CLOSE_GOSSIP_MENU(); - player->AddItem(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS, 1); - break; - } - return true; - } -}; - -/*###### ## npc_experience ######*/ @@ -2192,7 +2169,7 @@ public: // Check if we are near Elune'ara lake south, if so try to summon Omen or a minion if (me->GetZoneId() == ZONE_MOONGLADE) { - if (!me->FindNearestCreature(NPC_OMEN, 100.0f, false) && me->GetDistance2d(omenSummonPos.GetPositionX(), omenSummonPos.GetPositionY()) <= 100.0f) + if (!me->FindNearestCreature(NPC_OMEN, 100.0f) && me->GetDistance2d(omenSummonPos.GetPositionX(), omenSummonPos.GetPositionY()) <= 100.0f) { switch (urand(0, 9)) { @@ -2214,7 +2191,7 @@ public: float displacement = 0.7f; for (uint8 i = 0; i < 4; i++) - me->SummonGameObject(GetFireworkGameObjectId(), me->GetPositionX() + (i%2 == 0 ? displacement : -displacement), me->GetPositionY() + (i > 1 ? displacement : -displacement), me->GetPositionZ() + 4.0f, me->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 1); + me->SummonGameObject(GetFireworkGameObjectId(), me->GetPositionX() + (i % 2 == 0 ? displacement : -displacement), me->GetPositionY() + (i > 1 ? displacement : -displacement), me->GetPositionZ() + 4.0f, me->GetOrientation(), G3D::Quat(), 1); } else //me->CastSpell(me, GetFireworkSpell(me->GetEntry()), true); @@ -2572,159 +2549,6 @@ class npc_train_wrecker : public CreatureScript } }; -enum EgbertMisc -{ - EVENT_MOVE_POS = 1, - EVENT_RETURN = 2 -}; - -class npc_egbert : public CreatureScript -{ -public: - npc_egbert() : CreatureScript("npc_egbert") {} - - struct npc_egbertAI : public PetAI - { - npc_egbertAI(Creature* creature) : PetAI(creature) - { - if (Unit* owner = me->GetCharmerOrOwner()) - if (owner->GetMap()->GetEntry()->addon > 1) - me->SetCanFly(true); - } - - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_MOVE_POS, urandms(1, 20)); - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_MOVE_POS: - if (Unit* owner = me->GetCharmerOrOwner()) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, owner->GetPositionX() + frand(-30.0f, 30.0f), owner->GetPositionY() + frand(-30.0f, 30.0f), owner->GetPositionZ()); - } - _events.ScheduleEvent(EVENT_RETURN, urandms(3, 4)); - break; - case EVENT_RETURN: - if (Unit* owner = me->GetCharmerOrOwner()) - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle()); - _events.ScheduleEvent(EVENT_MOVE_POS, urandms(1, 20)); - break; - default: - break; - } - } - } - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_egbertAI(creature); - } -}; - -enum PandarenMonkMisc -{ - SPELL_PANDAREN_MONK = 69800, - EVENT_FOCUS = 1, - EVENT_EMOTE = 2, - EVENT_FOLLOW = 3, - EVENT_DRINK = 4 -}; - -class npc_pandaren_monk : public CreatureScript -{ -public: - npc_pandaren_monk() : CreatureScript("npc_pandaren_monk") {} - - struct npc_pandaren_monkAI : public NullCreatureAI - { - npc_pandaren_monkAI(Creature* creature) : NullCreatureAI(creature) { } - - void Reset() override - { - _events.Reset(); - _events.ScheduleEvent(EVENT_FOCUS, 1000); - } - - void EnterEvadeMode(EvadeReason why) override - { - if (!_EnterEvadeMode(why)) - return; - - Reset(); - } - - void ReceiveEmote(Player* /*player*/, uint32 emote) override - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - me->StopMoving(); - - switch (emote) - { - case TEXT_EMOTE_BOW: - _events.ScheduleEvent(EVENT_FOCUS, 1000); - break; - case TEXT_EMOTE_DRINK: - _events.ScheduleEvent(EVENT_DRINK, 1000); - break; - } - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - if (Unit* owner = me->GetCharmerOrOwner()) - if (!me->IsWithinDist(owner, 30.f)) - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_FOCUS: - if (Unit* owner = me->GetCharmerOrOwner()) - me->SetFacingToObject(owner); - _events.ScheduleEvent(EVENT_EMOTE, 1000); - break; - case EVENT_EMOTE: - me->HandleEmoteCommand(EMOTE_ONESHOT_BOW); - _events.ScheduleEvent(EVENT_FOLLOW, 1000); - break; - case EVENT_FOLLOW: - if (Unit* owner = me->GetCharmerOrOwner()) - me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - break; - case EVENT_DRINK: - me->CastSpell(me, SPELL_PANDAREN_MONK, false); - break; - default: - break; - } - } - } - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_pandaren_monkAI(creature); - } -}; - void AddSC_npcs_special() { new npc_air_force_bots(); @@ -2732,6 +2556,7 @@ void AddSC_npcs_special() new npc_chicken_cluck(); new npc_dancing_flames(); new npc_torch_tossing_target_bunny_controller(); + new npc_midsummer_bunny_pole(); new npc_doctor(); new npc_injured_patient(); new npc_garments_of_quests(); @@ -2743,13 +2568,10 @@ void AddSC_npcs_special() new npc_training_dummy(); new npc_wormhole(); new npc_pet_trainer(); - new npc_locksmith(); new npc_experience(); new npc_firework(); new npc_spring_rabbit(); new npc_imp_in_a_ball(); new npc_stable_master(); new npc_train_wrecker(); - new npc_egbert(); - new npc_pandaren_monk(); } diff --git a/src/server/scripts/World/world_script_loader.cpp b/src/server/scripts/World/world_script_loader.cpp new file mode 100644 index 00000000000..0167024799f --- /dev/null +++ b/src/server/scripts/World/world_script_loader.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "World.h" + +// This is where scripts' loading functions should be declared: +// world +void AddSC_areatrigger_scripts(); +void AddSC_emerald_dragons(); +void AddSC_generic_creature(); +void AddSC_go_scripts(); +void AddSC_guards(); +void AddSC_item_scripts(); +void AddSC_npc_professions(); +void AddSC_npc_innkeeper(); +void AddSC_npcs_special(); +void AddSC_achievement_scripts(); +void AddSC_action_ip_logger(); +void AddSC_duel_reset(); +// player +void AddSC_chat_log(); +void AddSC_action_ip_logger(); + +// The name of this function should match: +// void Add${NameOfDirectory}Scripts() +void AddWorldScripts() +{ + AddSC_areatrigger_scripts(); + AddSC_emerald_dragons(); + AddSC_generic_creature(); + AddSC_go_scripts(); + AddSC_guards(); + AddSC_item_scripts(); + AddSC_npc_professions(); + AddSC_npc_innkeeper(); + AddSC_npcs_special(); + AddSC_achievement_scripts(); + AddSC_chat_log(); // location: scripts\World\chat_log.cpp + + // FIXME: This should be moved in a script validation hook. + // To avoid duplicate code, we check once /*ONLY*/ if logging is permitted or not. + if (sWorld->getBoolConfig(CONFIG_IP_BASED_ACTION_LOGGING)) + AddSC_action_ip_logger(); // location: scripts\World\action_ip_logger.cpp + AddSC_duel_reset(); +} |
