diff options
Diffstat (limited to 'src/server/scripts')
218 files changed, 8898 insertions, 8826 deletions
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 20b970b6ac1..3668a2b0dac 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -43,33 +43,20 @@ message(STATUS "SCRIPT PREPARATION COMPLETE") message("") include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Models - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Database + ${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 @@ -83,20 +70,18 @@ include_directories( ${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/Calendar ${CMAKE_SOURCE_DIR}/src/server/game/Chat ${CMAKE_SOURCE_DIR}/src/server/game/Chat/Channels - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${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/GameObject ${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 @@ -113,19 +98,16 @@ include_directories( ${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/LookingForGroup ${CMAKE_SOURCE_DIR}/src/server/game/Loot ${CMAKE_SOURCE_DIR}/src/server/game/Mails - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous ${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/Opcodes ${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP ${CMAKE_SOURCE_DIR}/src/server/game/Pools - ${CMAKE_SOURCE_DIR}/src/server/game/PrecompiledHeaders ${CMAKE_SOURCE_DIR}/src/server/game/Quests ${CMAKE_SOURCE_DIR}/src/server/game/Reputation ${CMAKE_SOURCE_DIR}/src/server/game/Scripting @@ -138,10 +120,13 @@ include_directories( ${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/Warden/Modules ${CMAKE_SOURCE_DIR}/src/server/game/Weather ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders + ${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} ) @@ -153,8 +138,6 @@ add_library(scripts STATIC ${scripts_STAT_PCH_SRC} ) -add_dependencies(scripts revision.h) - # Generate precompiled header if (USE_SCRIPTPCH) add_cxx_pch(scripts ${scripts_STAT_PCH_HDR} ${scripts_STAT_PCH_SRC}) diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 5668c20d6b0..8d9a40d9d1f 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -33,45 +33,40 @@ class account_commandscript : public CommandScript public: account_commandscript() : CommandScript("account_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand accountSetSecTable[] = + static std::vector<ChatCommand> accountSetSecTable = { - { "regmail", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_REGMAIL, true, &HandleAccountSetRegEmailCommand, "", NULL }, - { "email", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_EMAIL, true, &HandleAccountSetEmailCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "regmail", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_REGMAIL, true, &HandleAccountSetRegEmailCommand, "" }, + { "email", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_EMAIL, true, &HandleAccountSetEmailCommand, "" }, }; - static ChatCommand accountSetCommandTable[] = + static std::vector<ChatCommand> accountSetCommandTable = { - { "addon", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON, true, &HandleAccountSetAddonCommand, "", NULL }, + { "addon", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON, true, &HandleAccountSetAddonCommand, "" }, { "sec", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_SEC, true, NULL, "", accountSetSecTable }, - { "gmlevel", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_GMLEVEL, true, &HandleAccountSetGmLevelCommand, "", NULL }, - { "password", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_PASSWORD, true, &HandleAccountSetPasswordCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "gmlevel", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_GMLEVEL, true, &HandleAccountSetGmLevelCommand, "" }, + { "password", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_PASSWORD, true, &HandleAccountSetPasswordCommand, "" }, }; - static ChatCommand accountLockCommandTable[] = + static std::vector<ChatCommand> accountLockCommandTable = { - { "country", rbac::RBAC_PERM_COMMAND_ACCOUNT_LOCK_COUNTRY, false, &HandleAccountLockCountryCommand, "", NULL }, - { "ip", rbac::RBAC_PERM_COMMAND_ACCOUNT_LOCK_IP, false, &HandleAccountLockIpCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "country", rbac::RBAC_PERM_COMMAND_ACCOUNT_LOCK_COUNTRY, false, &HandleAccountLockCountryCommand, "" }, + { "ip", rbac::RBAC_PERM_COMMAND_ACCOUNT_LOCK_IP, false, &HandleAccountLockIpCommand, "" }, }; - static ChatCommand accountCommandTable[] = + static std::vector<ChatCommand> accountCommandTable = { - { "addon", rbac::RBAC_PERM_COMMAND_ACCOUNT_ADDON, false, &HandleAccountAddonCommand, "", NULL }, - { "create", rbac::RBAC_PERM_COMMAND_ACCOUNT_CREATE, true, &HandleAccountCreateCommand, "", NULL }, - { "delete", rbac::RBAC_PERM_COMMAND_ACCOUNT_DELETE, true, &HandleAccountDeleteCommand, "", NULL }, - { "email", rbac::RBAC_PERM_COMMAND_ACCOUNT_EMAIL, false, &HandleAccountEmailCommand, "", NULL }, - { "onlinelist", rbac::RBAC_PERM_COMMAND_ACCOUNT_ONLINE_LIST, true, &HandleAccountOnlineListCommand, "", NULL }, + { "addon", rbac::RBAC_PERM_COMMAND_ACCOUNT_ADDON, false, &HandleAccountAddonCommand, "" }, + { "create", rbac::RBAC_PERM_COMMAND_ACCOUNT_CREATE, true, &HandleAccountCreateCommand, "" }, + { "delete", rbac::RBAC_PERM_COMMAND_ACCOUNT_DELETE, true, &HandleAccountDeleteCommand, "" }, + { "email", rbac::RBAC_PERM_COMMAND_ACCOUNT_EMAIL, false, &HandleAccountEmailCommand, "" }, + { "onlinelist", rbac::RBAC_PERM_COMMAND_ACCOUNT_ONLINE_LIST, true, &HandleAccountOnlineListCommand, "" }, { "lock", rbac::RBAC_PERM_COMMAND_ACCOUNT_LOCK, false, NULL, "", accountLockCommandTable }, { "set", rbac::RBAC_PERM_COMMAND_ACCOUNT_SET, true, NULL, "", accountSetCommandTable }, - { "password", rbac::RBAC_PERM_COMMAND_ACCOUNT_PASSWORD, false, &HandleAccountPasswordCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_ACCOUNT, false, &HandleAccountCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "password", rbac::RBAC_PERM_COMMAND_ACCOUNT_PASSWORD, false, &HandleAccountPasswordCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_ACCOUNT, false, &HandleAccountCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "account", rbac::RBAC_PERM_COMMAND_ACCOUNT, true, NULL, "", accountCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -135,7 +130,7 @@ public: { TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Character:[%s] (GUID: %u) created Account %s (Email: '%s')", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), accountName, email.c_str()); } break; @@ -381,7 +376,7 @@ public: handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided email [%s] is not equal to registration email [%s].", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), email, oldEmail); return false; } @@ -393,7 +388,7 @@ public: handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided password is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter()); return false; } @@ -412,7 +407,7 @@ public: handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided password is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter()); return false; } @@ -425,7 +420,7 @@ public: 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].", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), oldEmail, email); break; case AOR_EMAIL_TOO_LONG: @@ -479,7 +474,7 @@ public: handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change password, but the provided old password is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter()); return false; } @@ -492,7 +487,7 @@ public: handler->SetSentErrorMessage(true); TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change password, but the entered email [%s] is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), emailConfirmation); return false; } @@ -515,7 +510,7 @@ public: 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()->GetGUIDLow()); + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter()); break; case AOR_PASS_TOO_LONG: handler->SendSysMessage(LANG_PASSWORD_TOO_LONG); diff --git a/src/server/scripts/Commands/cs_achievement.cpp b/src/server/scripts/Commands/cs_achievement.cpp index 8a038844ec1..ea77bc1f189 100644 --- a/src/server/scripts/Commands/cs_achievement.cpp +++ b/src/server/scripts/Commands/cs_achievement.cpp @@ -33,17 +33,15 @@ class achievement_commandscript : public CommandScript public: achievement_commandscript() : CommandScript("achievement_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand achievementCommandTable[] = + static std::vector<ChatCommand> achievementCommandTable = { - { "add", rbac::RBAC_PERM_COMMAND_ACHIEVEMENT_ADD, false, &HandleAchievementAddCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", rbac::RBAC_PERM_COMMAND_ACHIEVEMENT_ADD, false, &HandleAchievementAddCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "achievement", rbac::RBAC_PERM_COMMAND_ACHIEVEMENT, false, NULL, "", achievementCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_ahbot.cpp b/src/server/scripts/Commands/cs_ahbot.cpp index 559a775da31..44889fccd37 100644 --- a/src/server/scripts/Commands/cs_ahbot.cpp +++ b/src/server/scripts/Commands/cs_ahbot.cpp @@ -33,44 +33,40 @@ class ahbot_commandscript : public CommandScript public: ahbot_commandscript(): CommandScript("ahbot_commandscript") {} - ChatCommand* GetCommands() const + std::vector<ChatCommand> GetCommands() const { - static ChatCommand ahbotItemsAmountCommandTable[] = + static std::vector<ChatCommand> ahbotItemsAmountCommandTable = { - { "gray", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_GRAY, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_GRAY>, "", NULL }, - { "white", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_WHITE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_WHITE>, "", NULL }, - { "green", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_GREEN, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_GREEN>, "", NULL }, - { "blue", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_BLUE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_BLUE>, "", NULL }, - { "purple", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_PURPLE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_PURPLE>, "", NULL }, - { "orange", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_ORANGE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_ORANGE>, "", NULL }, - { "yellow", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_YELLOW, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_YELLOW>, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS, true, &HandleAHBotItemsAmountCommand, "", NULL }, - { NULL, 0, true, NULL, "", NULL } + { "gray", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_GRAY, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_GRAY>, "" }, + { "white", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_WHITE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_WHITE>, "" }, + { "green", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_GREEN, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_GREEN>, "" }, + { "blue", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_BLUE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_BLUE>, "" }, + { "purple", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_PURPLE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_PURPLE>, "" }, + { "orange", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_ORANGE, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_ORANGE>, "" }, + { "yellow", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS_YELLOW, true, &HandleAHBotItemsAmountQualityCommand<AUCTION_QUALITY_YELLOW>, "" }, + { "", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS, true, &HandleAHBotItemsAmountCommand, "" }, }; - static ChatCommand ahbotItemsRatioCommandTable[] = + static std::vector<ChatCommand> ahbotItemsRatioCommandTable = { - { "alliance", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_ALLIANCE, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_ALLIANCE>, "", NULL }, - { "horde", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_HORDE, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_HORDE>, "", NULL }, - { "neutral", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_NEUTRAL, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_NEUTRAL>, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO, true, &HandleAHBotItemsRatioCommand, "", NULL }, - { NULL, 0, true, NULL, "", NULL } + { "alliance", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_ALLIANCE, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_ALLIANCE>, "" }, + { "horde", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_HORDE, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_HORDE>, "" }, + { "neutral", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO_NEUTRAL, true, &HandleAHBotItemsRatioHouseCommand<AUCTION_HOUSE_NEUTRAL>, "" }, + { "", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO, true, &HandleAHBotItemsRatioCommand, "" }, }; - static ChatCommand ahbotCommandTable[] = + static std::vector<ChatCommand> ahbotCommandTable = { { "items", rbac::RBAC_PERM_COMMAND_AHBOT_ITEMS, true, NULL, "", ahbotItemsAmountCommandTable }, { "ratio", rbac::RBAC_PERM_COMMAND_AHBOT_RATIO, true, NULL, "", ahbotItemsRatioCommandTable }, - { "rebuild", rbac::RBAC_PERM_COMMAND_AHBOT_REBUILD, true, &HandleAHBotRebuildCommand, "", NULL }, - { "reload", rbac::RBAC_PERM_COMMAND_AHBOT_RELOAD, true, &HandleAHBotReloadCommand, "", NULL }, - { "status", rbac::RBAC_PERM_COMMAND_AHBOT_STATUS, true, &HandleAHBotStatusCommand, "", NULL }, - { NULL, 0, true, NULL, "", NULL } + { "rebuild", rbac::RBAC_PERM_COMMAND_AHBOT_REBUILD, true, &HandleAHBotRebuildCommand, "" }, + { "reload", rbac::RBAC_PERM_COMMAND_AHBOT_RELOAD, true, &HandleAHBotReloadCommand, "" }, + { "status", rbac::RBAC_PERM_COMMAND_AHBOT_STATUS, true, &HandleAHBotStatusCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "ahbot", rbac::RBAC_PERM_COMMAND_AHBOT, false, NULL, "", ahbotCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; diff --git a/src/server/scripts/Commands/cs_arena.cpp b/src/server/scripts/Commands/cs_arena.cpp index 4993a7484dd..71657d51e7b 100644 --- a/src/server/scripts/Commands/cs_arena.cpp +++ b/src/server/scripts/Commands/cs_arena.cpp @@ -34,22 +34,20 @@ class arena_commandscript : public CommandScript public: arena_commandscript() : CommandScript("arena_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand arenaCommandTable[] = + static std::vector<ChatCommand> arenaCommandTable = { - { "create", rbac::RBAC_PERM_COMMAND_ARENA_CREATE, true, &HandleArenaCreateCommand, "", NULL }, - { "disband", rbac::RBAC_PERM_COMMAND_ARENA_DISBAND, true, &HandleArenaDisbandCommand, "", NULL }, - { "rename", rbac::RBAC_PERM_COMMAND_ARENA_RENAME, true, &HandleArenaRenameCommand, "", NULL }, - { "captain", rbac::RBAC_PERM_COMMAND_ARENA_CAPTAIN, false, &HandleArenaCaptainCommand, "", NULL }, - { "info", rbac::RBAC_PERM_COMMAND_ARENA_INFO, true, &HandleArenaInfoCommand, "", NULL }, - { "lookup", rbac::RBAC_PERM_COMMAND_ARENA_LOOKUP, false, &HandleArenaLookupCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "create", rbac::RBAC_PERM_COMMAND_ARENA_CREATE, true, &HandleArenaCreateCommand, "" }, + { "disband", rbac::RBAC_PERM_COMMAND_ARENA_DISBAND, true, &HandleArenaDisbandCommand, "" }, + { "rename", rbac::RBAC_PERM_COMMAND_ARENA_RENAME, true, &HandleArenaRenameCommand, "" }, + { "captain", rbac::RBAC_PERM_COMMAND_ARENA_CAPTAIN, false, &HandleArenaCaptainCommand, "" }, + { "info", rbac::RBAC_PERM_COMMAND_ARENA_INFO, true, &HandleArenaInfoCommand, "" }, + { "lookup", rbac::RBAC_PERM_COMMAND_ARENA_LOOKUP, false, &HandleArenaLookupCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "arena", rbac::RBAC_PERM_COMMAND_ARENA, false, NULL, "", arenaCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -144,7 +142,7 @@ public: arena->Disband(); if (handler->GetSession()) TC_LOG_DEBUG("bg.arena", "GameMaster: %s [GUID: %u] disbanded arena team type: %u [Id: %u].", - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), arena->GetType(), teamId); + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), arena->GetType(), teamId); else TC_LOG_DEBUG("bg.arena", "Console: disbanded arena team type: %u [Id: %u].", arena->GetType(), teamId); @@ -209,7 +207,7 @@ public: handler->PSendSysMessage(LANG_ARENA_RENAME, arena->GetId(), oldArenaStr, newArenaStr); if (handler->GetSession()) TC_LOG_DEBUG("bg.arena", "GameMaster: %s [GUID: %u] rename arena team \"%s\"[Id: %u] to \"%s\"", - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), oldArenaStr, arena->GetId(), newArenaStr); + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), oldArenaStr, arena->GetId(), newArenaStr); else TC_LOG_DEBUG("bg.arena", "Console: rename arena team \"%s\"[Id: %u] to \"%s\"", oldArenaStr, arena->GetId(), newArenaStr); @@ -275,20 +273,20 @@ public: arena->SetCaptain(targetGuid); - CharacterNameData const* oldCaptainNameData = sWorld->GetCharacterNameData(arena->GetCaptain()); + CharacterInfo const* oldCaptainNameData = sWorld->GetCharacterInfo(arena->GetCaptain()); if (!oldCaptainNameData) { handler->SetSentErrorMessage(true); return false; } - handler->PSendSysMessage(LANG_ARENA_CAPTAIN, arena->GetName().c_str(), arena->GetId(), oldCaptainNameData->m_name.c_str(), target->GetName().c_str()); + handler->PSendSysMessage(LANG_ARENA_CAPTAIN, arena->GetName().c_str(), arena->GetId(), oldCaptainNameData->Name.c_str(), target->GetName().c_str()); if (handler->GetSession()) TC_LOG_DEBUG("bg.arena", "GameMaster: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team \"%s\"[Id: %u]", - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), target->GetName().c_str(), target->GetGUIDLow(), arena->GetName().c_str(), arena->GetId()); + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), target->GetName().c_str(), target->GetGUID().GetCounter(), arena->GetName().c_str(), arena->GetId()); else TC_LOG_DEBUG("bg.arena", "Console: promoted player: %s [GUID: %u] to leader of arena team \"%s\"[Id: %u]", - target->GetName().c_str(), target->GetGUIDLow(), arena->GetName().c_str(), arena->GetId()); + target->GetName().c_str(), target->GetGUID().GetCounter(), arena->GetName().c_str(), arena->GetId()); return true; } diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp index 4b90a672c82..67015cd7d9c 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -35,45 +35,40 @@ class ban_commandscript : public CommandScript public: ban_commandscript() : CommandScript("ban_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand unbanCommandTable[] = + static std::vector<ChatCommand> unbanCommandTable = { - { "account", rbac::RBAC_PERM_COMMAND_UNBAN_ACCOUNT, true, &HandleUnBanAccountCommand, "", NULL }, - { "character", rbac::RBAC_PERM_COMMAND_UNBAN_CHARACTER, true, &HandleUnBanCharacterCommand, "", NULL }, - { "playeraccount", rbac::RBAC_PERM_COMMAND_UNBAN_PLAYERACCOUNT, true, &HandleUnBanAccountByCharCommand, "", NULL }, - { "ip", rbac::RBAC_PERM_COMMAND_UNBAN_IP, true, &HandleUnBanIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", rbac::RBAC_PERM_COMMAND_UNBAN_ACCOUNT, true, &HandleUnBanAccountCommand, "" }, + { "character", rbac::RBAC_PERM_COMMAND_UNBAN_CHARACTER, true, &HandleUnBanCharacterCommand, "" }, + { "playeraccount", rbac::RBAC_PERM_COMMAND_UNBAN_PLAYERACCOUNT, true, &HandleUnBanAccountByCharCommand, "" }, + { "ip", rbac::RBAC_PERM_COMMAND_UNBAN_IP, true, &HandleUnBanIPCommand, "" }, }; - static ChatCommand banlistCommandTable[] = + static std::vector<ChatCommand> banlistCommandTable = { - { "account", rbac::RBAC_PERM_COMMAND_BANLIST_ACCOUNT, true, &HandleBanListAccountCommand, "", NULL }, - { "character", rbac::RBAC_PERM_COMMAND_BANLIST_CHARACTER, true, &HandleBanListCharacterCommand, "", NULL }, - { "ip", rbac::RBAC_PERM_COMMAND_BANLIST_IP, true, &HandleBanListIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", rbac::RBAC_PERM_COMMAND_BANLIST_ACCOUNT, true, &HandleBanListAccountCommand, "" }, + { "character", rbac::RBAC_PERM_COMMAND_BANLIST_CHARACTER, true, &HandleBanListCharacterCommand, "" }, + { "ip", rbac::RBAC_PERM_COMMAND_BANLIST_IP, true, &HandleBanListIPCommand, "" }, }; - static ChatCommand baninfoCommandTable[] = + static std::vector<ChatCommand> baninfoCommandTable = { - { "account", rbac::RBAC_PERM_COMMAND_BANINFO_ACCOUNT, true, &HandleBanInfoAccountCommand, "", NULL }, - { "character", rbac::RBAC_PERM_COMMAND_BANINFO_CHARACTER, true, &HandleBanInfoCharacterCommand, "", NULL }, - { "ip", rbac::RBAC_PERM_COMMAND_BANINFO_IP, true, &HandleBanInfoIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", rbac::RBAC_PERM_COMMAND_BANINFO_ACCOUNT, true, &HandleBanInfoAccountCommand, "" }, + { "character", rbac::RBAC_PERM_COMMAND_BANINFO_CHARACTER, true, &HandleBanInfoCharacterCommand, "" }, + { "ip", rbac::RBAC_PERM_COMMAND_BANINFO_IP, true, &HandleBanInfoIPCommand, "" }, }; - static ChatCommand banCommandTable[] = + static std::vector<ChatCommand> banCommandTable = { - { "account", rbac::RBAC_PERM_COMMAND_BAN_ACCOUNT, true, &HandleBanAccountCommand, "", NULL }, - { "character", rbac::RBAC_PERM_COMMAND_BAN_CHARACTER, true, &HandleBanCharacterCommand, "", NULL }, - { "playeraccount", rbac::RBAC_PERM_COMMAND_BAN_PLAYERACCOUNT, true, &HandleBanAccountByCharCommand, "", NULL }, - { "ip", rbac::RBAC_PERM_COMMAND_BAN_IP, true, &HandleBanIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", rbac::RBAC_PERM_COMMAND_BAN_ACCOUNT, true, &HandleBanAccountCommand, "" }, + { "character", rbac::RBAC_PERM_COMMAND_BAN_CHARACTER, true, &HandleBanCharacterCommand, "" }, + { "playeraccount", rbac::RBAC_PERM_COMMAND_BAN_PLAYERACCOUNT, true, &HandleBanAccountByCharCommand, "" }, + { "ip", rbac::RBAC_PERM_COMMAND_BAN_IP, true, &HandleBanIPCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "ban", rbac::RBAC_PERM_COMMAND_BAN, true, NULL, "", banCommandTable }, { "baninfo", rbac::RBAC_PERM_COMMAND_BANINFO, true, NULL, "", baninfoCommandTable }, { "banlist", rbac::RBAC_PERM_COMMAND_BANLIST, true, NULL, "", banlistCommandTable }, { "unban", rbac::RBAC_PERM_COMMAND_UNBAN, true, NULL, "", unbanCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -300,7 +295,7 @@ public: return false; Player* target = ObjectAccessor::FindPlayerByName(args); - uint32 targetGuid = 0; + ObjectGuid::LowType targetGuid = 0; std::string name(args); if (!target) @@ -318,7 +313,7 @@ public: targetGuid = (*resultCharacter)[0].GetUInt32(); } else - targetGuid = target->GetGUIDLow(); + targetGuid = target->GetGUID().GetCounter(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_BANINFO); stmt->setUInt32(0, targetGuid); diff --git a/src/server/scripts/Commands/cs_bf.cpp b/src/server/scripts/Commands/cs_bf.cpp index 830e801bcef..7101b89b5fa 100644 --- a/src/server/scripts/Commands/cs_bf.cpp +++ b/src/server/scripts/Commands/cs_bf.cpp @@ -31,21 +31,19 @@ class bf_commandscript : public CommandScript public: bf_commandscript() : CommandScript("bf_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand battlefieldcommandTable[] = + static std::vector<ChatCommand> battlefieldcommandTable = { - { "start", rbac::RBAC_PERM_COMMAND_BF_START, false, &HandleBattlefieldStart, "", NULL }, - { "stop", rbac::RBAC_PERM_COMMAND_BF_STOP, false, &HandleBattlefieldEnd, "", NULL }, - { "switch", rbac::RBAC_PERM_COMMAND_BF_SWITCH, false, &HandleBattlefieldSwitch, "", NULL }, - { "timer", rbac::RBAC_PERM_COMMAND_BF_TIMER, false, &HandleBattlefieldTimer, "", NULL }, - { "enable", rbac::RBAC_PERM_COMMAND_BF_ENABLE, false, &HandleBattlefieldEnable, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "start", rbac::RBAC_PERM_COMMAND_BF_START, false, &HandleBattlefieldStart, "" }, + { "stop", rbac::RBAC_PERM_COMMAND_BF_STOP, false, &HandleBattlefieldEnd, "" }, + { "switch", rbac::RBAC_PERM_COMMAND_BF_SWITCH, false, &HandleBattlefieldSwitch, "" }, + { "timer", rbac::RBAC_PERM_COMMAND_BF_TIMER, false, &HandleBattlefieldTimer, "" }, + { "enable", rbac::RBAC_PERM_COMMAND_BF_ENABLE, false, &HandleBattlefieldEnable, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "bf", rbac::RBAC_PERM_COMMAND_BF, false, NULL, "", battlefieldcommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_cast.cpp b/src/server/scripts/Commands/cs_cast.cpp index dfd0bb36755..5252d5e368a 100644 --- a/src/server/scripts/Commands/cs_cast.cpp +++ b/src/server/scripts/Commands/cs_cast.cpp @@ -33,26 +33,43 @@ class cast_commandscript : public CommandScript public: cast_commandscript() : CommandScript("cast_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand castCommandTable[] = + static std::vector<ChatCommand> castCommandTable = { - { "back", rbac::RBAC_PERM_COMMAND_CAST_BACK, false, &HandleCastBackCommand, "", NULL }, - { "dist", rbac::RBAC_PERM_COMMAND_CAST_DIST, false, &HandleCastDistCommand, "", NULL }, - { "self", rbac::RBAC_PERM_COMMAND_CAST_SELF, false, &HandleCastSelfCommand, "", NULL }, - { "target", rbac::RBAC_PERM_COMMAND_CAST_TARGET, false, &HandleCastTargetCommad, "", NULL }, - { "dest", rbac::RBAC_PERM_COMMAND_CAST_DEST, false, &HandleCastDestCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_CAST, false, &HandleCastCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "back", rbac::RBAC_PERM_COMMAND_CAST_BACK, false, &HandleCastBackCommand, "" }, + { "dist", rbac::RBAC_PERM_COMMAND_CAST_DIST, false, &HandleCastDistCommand, "" }, + { "self", rbac::RBAC_PERM_COMMAND_CAST_SELF, false, &HandleCastSelfCommand, "" }, + { "target", rbac::RBAC_PERM_COMMAND_CAST_TARGET, false, &HandleCastTargetCommad, "" }, + { "dest", rbac::RBAC_PERM_COMMAND_CAST_DEST, false, &HandleCastDestCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_CAST, false, &HandleCastCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "cast", rbac::RBAC_PERM_COMMAND_CAST, false, NULL, "", castCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } + static bool CheckSpellExistsAndIsValid(ChatHandler* handler, uint32 spellId) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo) + { + handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); + handler->SetSentErrorMessage(true); + return false; + } + + if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer())) + { + handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); + handler->SetSentErrorMessage(true); + return false; + } + return true; + } + static bool HandleCastCommand(ChatHandler* handler, char const* args) { if (!*args) @@ -71,20 +88,8 @@ public: if (!spellId) return false; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - { - handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - handler->SetSentErrorMessage(true); - return false; - } - - if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer())) - { - handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); - handler->SetSentErrorMessage(true); + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; - } char* triggeredStr = strtok(NULL, " "); if (triggeredStr) @@ -111,15 +116,13 @@ public: return false; } - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellId = handler->extractSpellIdFromLink((char*)args); - if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) - { - handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - handler->SetSentErrorMessage(true); + if (!spellId) + return false; + + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; - } char* triggeredStr = strtok(NULL, " "); if (triggeredStr) @@ -146,20 +149,8 @@ public: if (!spellId) return false; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - { - handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - handler->SetSentErrorMessage(true); - return false; - } - - if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer())) - { - handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); - handler->SetSentErrorMessage(true); + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; - } char* distStr = strtok(NULL, " "); @@ -192,28 +183,14 @@ public: return false; Unit* target = handler->getSelectedUnit(); - if (!target) - { - handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - handler->SetSentErrorMessage(true); - return false; - } // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellId = handler->extractSpellIdFromLink((char*)args); if (!spellId) return false; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo) - return false; - - if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer())) - { - handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); - handler->SetSentErrorMessage(true); + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; - } target->CastSpell(target, spellId, false); @@ -239,12 +216,11 @@ public: // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellId = handler->extractSpellIdFromLink((char*)args); - if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) - { - handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - handler->SetSentErrorMessage(true); + if (!spellId) + return false; + + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; - } char* triggeredStr = strtok(NULL, " "); if (triggeredStr) @@ -273,12 +249,11 @@ public: // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellId = handler->extractSpellIdFromLink((char*)args); - if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) - { - handler->PSendSysMessage(LANG_COMMAND_NOSPELLFOUND); - handler->SetSentErrorMessage(true); + if (!spellId) + return false; + + if (!CheckSpellExistsAndIsValid(handler, spellId)) return false; - } char* posX = strtok(NULL, " "); char* posY = strtok(NULL, " "); diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 4ef4454be99..65dd44f8563 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -35,43 +35,39 @@ class character_commandscript : public CommandScript public: character_commandscript() : CommandScript("character_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand pdumpCommandTable[] = + static std::vector<ChatCommand> pdumpCommandTable = { - { "load", rbac::RBAC_PERM_COMMAND_PDUMP_LOAD, true, &HandlePDumpLoadCommand, "", NULL }, - { "write", rbac::RBAC_PERM_COMMAND_PDUMP_WRITE, true, &HandlePDumpWriteCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "load", rbac::RBAC_PERM_COMMAND_PDUMP_LOAD, true, &HandlePDumpLoadCommand, "" }, + { "write", rbac::RBAC_PERM_COMMAND_PDUMP_WRITE, true, &HandlePDumpWriteCommand, "" }, }; - static ChatCommand characterDeletedCommandTable[] = + static std::vector<ChatCommand> characterDeletedCommandTable = { - { "delete", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE, true, &HandleCharacterDeletedDeleteCommand, "", NULL }, - { "list", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST, true, &HandleCharacterDeletedListCommand, "", NULL }, - { "restore", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE, true, &HandleCharacterDeletedRestoreCommand, "", NULL }, - { "old", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD, true, &HandleCharacterDeletedOldCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "delete", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE, true, &HandleCharacterDeletedDeleteCommand, "" }, + { "list", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST, true, &HandleCharacterDeletedListCommand, "" }, + { "restore", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE, true, &HandleCharacterDeletedRestoreCommand, "" }, + { "old", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD, true, &HandleCharacterDeletedOldCommand, "" }, }; - static ChatCommand characterCommandTable[] = + static std::vector<ChatCommand> characterCommandTable = { - { "customize", rbac::RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE, true, &HandleCharacterCustomizeCommand, "", NULL }, - { "changefaction", rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION, true, &HandleCharacterChangeFactionCommand, "", NULL }, - { "changerace", rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGERACE, true, &HandleCharacterChangeRaceCommand, "", NULL }, + { "customize", rbac::RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE, true, &HandleCharacterCustomizeCommand, "", }, + { "changefaction", rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION, true, &HandleCharacterChangeFactionCommand, "", }, + { "changerace", rbac::RBAC_PERM_COMMAND_CHARACTER_CHANGERACE, true, &HandleCharacterChangeRaceCommand, "", }, { "deleted", rbac::RBAC_PERM_COMMAND_CHARACTER_DELETED, true, NULL, "", characterDeletedCommandTable }, - { "erase", rbac::RBAC_PERM_COMMAND_CHARACTER_ERASE, true, &HandleCharacterEraseCommand, "", NULL }, - { "level", rbac::RBAC_PERM_COMMAND_CHARACTER_LEVEL, true, &HandleCharacterLevelCommand, "", NULL }, - { "rename", rbac::RBAC_PERM_COMMAND_CHARACTER_RENAME, true, &HandleCharacterRenameCommand, "", NULL }, - { "reputation", rbac::RBAC_PERM_COMMAND_CHARACTER_REPUTATION, true, &HandleCharacterReputationCommand, "", NULL }, - { "titles", rbac::RBAC_PERM_COMMAND_CHARACTER_TITLES, true, &HandleCharacterTitlesCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "erase", rbac::RBAC_PERM_COMMAND_CHARACTER_ERASE, true, &HandleCharacterEraseCommand, "", }, + { "level", rbac::RBAC_PERM_COMMAND_CHARACTER_LEVEL, true, &HandleCharacterLevelCommand, "", }, + { "rename", rbac::RBAC_PERM_COMMAND_CHARACTER_RENAME, true, &HandleCharacterRenameCommand, "", }, + { "reputation", rbac::RBAC_PERM_COMMAND_CHARACTER_REPUTATION, true, &HandleCharacterReputationCommand, "", }, + { "titles", rbac::RBAC_PERM_COMMAND_CHARACTER_TITLES, true, &HandleCharacterTitlesCommand, "", }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "character", rbac::RBAC_PERM_COMMAND_CHARACTER, true, NULL, "", characterCommandTable }, - { "levelup", rbac::RBAC_PERM_COMMAND_LEVELUP, false, &HandleLevelUpCommand, "", NULL }, + { "levelup", rbac::RBAC_PERM_COMMAND_LEVELUP, false, &HandleLevelUpCommand, "" }, { "pdump", rbac::RBAC_PERM_COMMAND_PDUMP, true, NULL, "", pdumpCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -133,7 +129,7 @@ public: DeletedInfo info; - info.guid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); + info.guid = ObjectGuid(HighGuid::Player, fields[0].GetUInt32()); info.name = fields[1].GetString(); info.accountId = fields[2].GetUInt32(); @@ -226,7 +222,7 @@ public: stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA); stmt->setUInt32(0, delInfo.guid.GetCounter()); if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) - sWorld->AddCharacterNameData(delInfo.guid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8(), (*result)[3].GetUInt8()); + sWorld->AddCharacterInfo(delInfo.guid, delInfo.accountId, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8(), (*result)[3].GetUInt8()); } static void HandleCharacterLevel(Player* player, ObjectGuid playerGuid, uint32 oldLevel, uint32 newLevel, ChatHandler* handler) @@ -339,7 +335,7 @@ public: return false; } - if (ObjectMgr::CheckPlayerName(newName, true) != CHAR_NAME_SUCCESS) + if (ObjectMgr::CheckPlayerName(newName, target ? target->GetSession()->GetSessionDbcLocale() : sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); @@ -386,7 +382,7 @@ public: CharacterDatabase.Execute(stmt); } - sWorld->UpdateCharacterNameData(targetGuid, newName); + sWorld->UpdateCharacterInfo(targetGuid, newName); handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, playerOldName.c_str(), newName.c_str()); @@ -483,7 +479,7 @@ public: { handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str()); target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); - stmt->setUInt32(1, target->GetGUIDLow()); + stmt->setUInt32(1, target->GetGUID().GetCounter()); } else { @@ -511,7 +507,7 @@ public: { handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str()); target->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION); - stmt->setUInt32(1, target->GetGUIDLow()); + stmt->setUInt32(1, target->GetGUID().GetCounter()); } else { @@ -539,7 +535,7 @@ public: /// @todo add text into database handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str()); target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE); - stmt->setUInt32(1, target->GetGUIDLow()); + stmt->setUInt32(1, target->GetGUID().GetCounter()); } else { @@ -899,7 +895,7 @@ public: return false; } - if (ObjectMgr::CheckPlayerName(name, true) != CHAR_NAME_SUCCESS) + if (ObjectMgr::CheckPlayerName(name, sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS) { handler->PSendSysMessage(LANG_INVALID_CHARACTER_NAME); handler->SetSentErrorMessage(true); @@ -909,7 +905,7 @@ public: guidStr = strtok(NULL, " "); } - uint32 guid = 0; + ObjectGuid::LowType guid = 0; if (guidStr) { @@ -921,7 +917,7 @@ public: return false; } - if (sObjectMgr->GetPlayerAccountIdByGUID(ObjectGuid(HIGHGUID_PLAYER, guid))) + if (sObjectMgr->GetPlayerAccountIdByGUID(ObjectGuid(HighGuid::Player, guid))) { handler->PSendSysMessage(LANG_CHARACTER_GUID_IN_USE, guid); handler->SetSentErrorMessage(true); @@ -969,7 +965,7 @@ public: ObjectGuid guid; // character name can't start from number if (isNumeric(playerStr)) - guid = ObjectGuid(HIGHGUID_PLAYER, uint32(atoi(playerStr))); + guid = ObjectGuid(HighGuid::Player, uint32(atoi(playerStr))); else { std::string name = handler->extractPlayerNameFromLink(playerStr); diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp index 54ae72c3d8a..2dc2c17bdc2 100644 --- a/src/server/scripts/Commands/cs_cheat.cpp +++ b/src/server/scripts/Commands/cs_cheat.cpp @@ -24,7 +24,6 @@ EndScriptData */ #include "Chat.h" #include "Language.h" -#include "ObjectMgr.h" #include "Player.h" #include "ScriptMgr.h" @@ -33,27 +32,24 @@ class cheat_commandscript : public CommandScript public: cheat_commandscript() : CommandScript("cheat_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - - static ChatCommand cheatCommandTable[] = + static std::vector<ChatCommand> cheatCommandTable = { - { "god", rbac::RBAC_PERM_COMMAND_CHEAT_GOD, false, &HandleGodModeCheatCommand, "", NULL }, - { "casttime", rbac::RBAC_PERM_COMMAND_CHEAT_CASTTIME, false, &HandleCasttimeCheatCommand, "", NULL }, - { "cooldown", rbac::RBAC_PERM_COMMAND_CHEAT_COOLDOWN, false, &HandleCoolDownCheatCommand, "", NULL }, - { "power", rbac::RBAC_PERM_COMMAND_CHEAT_POWER, false, &HandlePowerCheatCommand, "", NULL }, - { "waterwalk", rbac::RBAC_PERM_COMMAND_CHEAT_WATERWALK, false, &HandleWaterWalkCheatCommand, "", NULL }, - { "status", rbac::RBAC_PERM_COMMAND_CHEAT_STATUS, false, &HandleCheatStatusCommand, "", NULL }, - { "taxi", rbac::RBAC_PERM_COMMAND_CHEAT_TAXI, false, &HandleTaxiCheatCommand, "", NULL }, - { "explore", rbac::RBAC_PERM_COMMAND_CHEAT_EXPLORE, false, &HandleExploreCheatCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "god", rbac::RBAC_PERM_COMMAND_CHEAT_GOD, false, &HandleGodModeCheatCommand, "" }, + { "casttime", rbac::RBAC_PERM_COMMAND_CHEAT_CASTTIME, false, &HandleCasttimeCheatCommand, "" }, + { "cooldown", rbac::RBAC_PERM_COMMAND_CHEAT_COOLDOWN, false, &HandleCoolDownCheatCommand, "" }, + { "power", rbac::RBAC_PERM_COMMAND_CHEAT_POWER, false, &HandlePowerCheatCommand, "" }, + { "waterwalk", rbac::RBAC_PERM_COMMAND_CHEAT_WATERWALK, false, &HandleWaterWalkCheatCommand, "" }, + { "status", rbac::RBAC_PERM_COMMAND_CHEAT_STATUS, false, &HandleCheatStatusCommand, "" }, + { "taxi", rbac::RBAC_PERM_COMMAND_CHEAT_TAXI, false, &HandleTaxiCheatCommand, "" }, + { "explore", rbac::RBAC_PERM_COMMAND_CHEAT_EXPLORE, false, &HandleExploreCheatCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "cheat", rbac::RBAC_PERM_COMMAND_CHEAT, false, NULL, "", cheatCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -166,8 +162,8 @@ public: { Player* player = handler->GetSession()->GetPlayer(); - const char* enabled = "enabled"; - const char* disabled = "disabled"; + const char* enabled = "ON"; + const char* disabled = "OFF"; handler->SendSysMessage(LANG_COMMAND_CHEAT_STATUS); handler->PSendSysMessage(LANG_COMMAND_CHEAT_GOD, player->GetCommandStatus(CHEAT_GOD) ? enabled : disabled); @@ -175,6 +171,8 @@ public: handler->PSendSysMessage(LANG_COMMAND_CHEAT_CT, player->GetCommandStatus(CHEAT_CASTTIME) ? enabled : disabled); handler->PSendSysMessage(LANG_COMMAND_CHEAT_POWER, player->GetCommandStatus(CHEAT_POWER) ? enabled : disabled); handler->PSendSysMessage(LANG_COMMAND_CHEAT_WW, player->GetCommandStatus(CHEAT_WATERWALK) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_TAXINODES, player->isTaxiCheater() ? enabled : disabled); + return true; } @@ -186,13 +184,7 @@ public: std::string argstr = (char*)args; if (!*args) - { argstr = (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_WATERWALK)) ? "off" : "on"; - if (handler->GetSession()->GetPlayer()->GetCommandStatus(CHEAT_WATERWALK)) - argstr = "off"; - else - argstr = "on"; - } if (argstr == "off") { @@ -214,15 +206,7 @@ public: static bool HandleTaxiCheatCommand(ChatHandler* handler, const char* args) { - if (!*args) - { - handler->SendSysMessage(LANG_USE_BOL); - handler->SetSentErrorMessage(true); - return false; - } - std::string argstr = (char*)args; - Player* chr = handler->getSelectedPlayer(); if (!chr) @@ -230,13 +214,9 @@ public: else if (handler->HasLowerSecurity(chr, ObjectGuid::Empty)) // check online security return false; - if (argstr == "on") + if (!*args) { - chr->SetTaxiCheater(true); - handler->PSendSysMessage(LANG_YOU_GIVE_TAXIS, handler->GetNameLink(chr).c_str()); - if (handler->needReportToTarget(chr)) - ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, handler->GetNameLink().c_str()); - return true; + argstr = (chr->isTaxiCheater()) ? "off" : "on"; } if (argstr == "off") @@ -245,7 +225,14 @@ public: handler->PSendSysMessage(LANG_YOU_REMOVE_TAXIS, handler->GetNameLink(chr).c_str()); if (handler->needReportToTarget(chr)) ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, handler->GetNameLink().c_str()); - + return true; + } + else if (argstr == "on") + { + chr->SetTaxiCheater(true); + handler->PSendSysMessage(LANG_YOU_GIVE_TAXIS, handler->GetNameLink(chr).c_str()); + if (handler->needReportToTarget(chr)) + ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, handler->GetNameLink().c_str()); return true; } @@ -259,10 +246,11 @@ public: if (!*args) return false; + // std::int flag = (char*)args; int flag = atoi((char*)args); Player* chr = handler->getSelectedPlayer(); - if (chr == NULL) + if (!chr) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index ccd82aa3ef9..7f517d09e90 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -33,6 +33,7 @@ EndScriptData */ #include "GossipDef.h" #include "Transport.h" #include "Language.h" +#include "MapManager.h" #include <fstream> @@ -41,65 +42,62 @@ class debug_commandscript : public CommandScript public: debug_commandscript() : CommandScript("debug_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand debugPlayCommandTable[] = + static std::vector<ChatCommand> debugPlayCommandTable = { - { "cinematic", rbac::RBAC_PERM_COMMAND_DEBUG_PLAY_CINEMATIC, false, &HandleDebugPlayCinematicCommand, "", NULL }, - { "movie", rbac::RBAC_PERM_COMMAND_DEBUG_PLAY_MOVIE, false, &HandleDebugPlayMovieCommand, "", NULL }, - { "sound", rbac::RBAC_PERM_COMMAND_DEBUG_PLAY_SOUND, false, &HandleDebugPlaySoundCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cinematic", rbac::RBAC_PERM_COMMAND_DEBUG_PLAY_CINEMATIC, false, &HandleDebugPlayCinematicCommand, "" }, + { "movie", rbac::RBAC_PERM_COMMAND_DEBUG_PLAY_MOVIE, false, &HandleDebugPlayMovieCommand, "" }, + { "sound", rbac::RBAC_PERM_COMMAND_DEBUG_PLAY_SOUND, false, &HandleDebugPlaySoundCommand, "" }, }; - static ChatCommand debugSendCommandTable[] = + static std::vector<ChatCommand> debugSendCommandTable = { - { "buyerror", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_BUYERROR, false, &HandleDebugSendBuyErrorCommand, "", NULL }, - { "channelnotify", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_CHANNELNOTIFY, false, &HandleDebugSendChannelNotifyCommand, "", NULL }, - { "chatmessage", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_CHATMESSAGE, false, &HandleDebugSendChatMsgCommand, "", NULL }, - { "equiperror", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_EQUIPERROR, false, &HandleDebugSendEquipErrorCommand, "", NULL }, - { "largepacket", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_LARGEPACKET, false, &HandleDebugSendLargePacketCommand, "", NULL }, - { "opcode", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_OPCODE, false, &HandleDebugSendOpcodeCommand, "", NULL }, - { "qpartymsg", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_QPARTYMSG, false, &HandleDebugSendQuestPartyMsgCommand, "", NULL }, - { "qinvalidmsg", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_QINVALIDMSG, false, &HandleDebugSendQuestInvalidMsgCommand, "", NULL }, - { "sellerror", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SELLERROR, false, &HandleDebugSendSellErrorCommand, "", NULL }, - { "setphaseshift", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SETPHASESHIFT, false, &HandleDebugSendSetPhaseShiftCommand, "", NULL }, - { "spellfail", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SPELLFAIL, false, &HandleDebugSendSpellFailCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "buyerror", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_BUYERROR, false, &HandleDebugSendBuyErrorCommand, "" }, + { "channelnotify", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_CHANNELNOTIFY, false, &HandleDebugSendChannelNotifyCommand, "" }, + { "chatmessage", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_CHATMESSAGE, false, &HandleDebugSendChatMsgCommand, "" }, + { "equiperror", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_EQUIPERROR, false, &HandleDebugSendEquipErrorCommand, "" }, + { "largepacket", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_LARGEPACKET, false, &HandleDebugSendLargePacketCommand, "" }, + { "opcode", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_OPCODE, false, &HandleDebugSendOpcodeCommand, "" }, + { "qpartymsg", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_QPARTYMSG, false, &HandleDebugSendQuestPartyMsgCommand, "" }, + { "qinvalidmsg", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_QINVALIDMSG, false, &HandleDebugSendQuestInvalidMsgCommand, "" }, + { "sellerror", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SELLERROR, false, &HandleDebugSendSellErrorCommand, "" }, + { "setphaseshift", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SETPHASESHIFT, false, &HandleDebugSendSetPhaseShiftCommand, "" }, + { "spellfail", rbac::RBAC_PERM_COMMAND_DEBUG_SEND_SPELLFAIL, false, &HandleDebugSendSpellFailCommand, "" }, }; - static ChatCommand debugCommandTable[] = + static std::vector<ChatCommand> debugCommandTable = { - { "setbit", rbac::RBAC_PERM_COMMAND_DEBUG_SETBIT, false, &HandleDebugSet32BitCommand, "", NULL }, - { "threat", rbac::RBAC_PERM_COMMAND_DEBUG_THREAT, false, &HandleDebugThreatListCommand, "", NULL }, - { "hostil", rbac::RBAC_PERM_COMMAND_DEBUG_HOSTIL, false, &HandleDebugHostileRefListCommand, "", NULL }, - { "anim", rbac::RBAC_PERM_COMMAND_DEBUG_ANIM, false, &HandleDebugAnimCommand, "", NULL }, - { "arena", rbac::RBAC_PERM_COMMAND_DEBUG_ARENA, false, &HandleDebugArenaCommand, "", NULL }, - { "bg", rbac::RBAC_PERM_COMMAND_DEBUG_BG, false, &HandleDebugBattlegroundCommand, "", NULL }, - { "getitemstate", rbac::RBAC_PERM_COMMAND_DEBUG_GETITEMSTATE, false, &HandleDebugGetItemStateCommand, "", NULL }, - { "lootrecipient", rbac::RBAC_PERM_COMMAND_DEBUG_LOOTRECIPIENT, false, &HandleDebugGetLootRecipientCommand, "", NULL }, - { "getvalue", rbac::RBAC_PERM_COMMAND_DEBUG_GETVALUE, false, &HandleDebugGetValueCommand, "", NULL }, - { "getitemvalue", rbac::RBAC_PERM_COMMAND_DEBUG_GETITEMVALUE, false, &HandleDebugGetItemValueCommand, "", NULL }, - { "Mod32Value", rbac::RBAC_PERM_COMMAND_DEBUG_MOD32VALUE, false, &HandleDebugMod32ValueCommand, "", NULL }, + { "setbit", rbac::RBAC_PERM_COMMAND_DEBUG_SETBIT, false, &HandleDebugSet32BitCommand, "" }, + { "threat", rbac::RBAC_PERM_COMMAND_DEBUG_THREAT, false, &HandleDebugThreatListCommand, "" }, + { "hostil", rbac::RBAC_PERM_COMMAND_DEBUG_HOSTIL, false, &HandleDebugHostileRefListCommand, "" }, + { "anim", rbac::RBAC_PERM_COMMAND_DEBUG_ANIM, false, &HandleDebugAnimCommand, "" }, + { "arena", rbac::RBAC_PERM_COMMAND_DEBUG_ARENA, false, &HandleDebugArenaCommand, "" }, + { "bg", rbac::RBAC_PERM_COMMAND_DEBUG_BG, false, &HandleDebugBattlegroundCommand, "" }, + { "getitemstate", rbac::RBAC_PERM_COMMAND_DEBUG_GETITEMSTATE, false, &HandleDebugGetItemStateCommand, "" }, + { "lootrecipient", rbac::RBAC_PERM_COMMAND_DEBUG_LOOTRECIPIENT, false, &HandleDebugGetLootRecipientCommand, "" }, + { "getvalue", rbac::RBAC_PERM_COMMAND_DEBUG_GETVALUE, false, &HandleDebugGetValueCommand, "" }, + { "getitemvalue", rbac::RBAC_PERM_COMMAND_DEBUG_GETITEMVALUE, false, &HandleDebugGetItemValueCommand, "" }, + { "Mod32Value", rbac::RBAC_PERM_COMMAND_DEBUG_MOD32VALUE, false, &HandleDebugMod32ValueCommand, "" }, { "play", rbac::RBAC_PERM_COMMAND_DEBUG_PLAY, false, NULL, "", debugPlayCommandTable }, { "send", rbac::RBAC_PERM_COMMAND_DEBUG_SEND, false, NULL, "", debugSendCommandTable }, - { "setaurastate", rbac::RBAC_PERM_COMMAND_DEBUG_SETAURASTATE, false, &HandleDebugSetAuraStateCommand, "", NULL }, - { "setitemvalue", rbac::RBAC_PERM_COMMAND_DEBUG_SETITEMVALUE, false, &HandleDebugSetItemValueCommand, "", NULL }, - { "setvalue", rbac::RBAC_PERM_COMMAND_DEBUG_SETVALUE, false, &HandleDebugSetValueCommand, "", NULL }, - { "spawnvehicle", rbac::RBAC_PERM_COMMAND_DEBUG_SPAWNVEHICLE, false, &HandleDebugSpawnVehicleCommand, "", NULL }, - { "setvid", rbac::RBAC_PERM_COMMAND_DEBUG_SETVID, false, &HandleDebugSetVehicleIdCommand, "", NULL }, - { "entervehicle", rbac::RBAC_PERM_COMMAND_DEBUG_ENTERVEHICLE, false, &HandleDebugEnterVehicleCommand, "", NULL }, - { "uws", rbac::RBAC_PERM_COMMAND_DEBUG_UWS, false, &HandleDebugUpdateWorldStateCommand, "", NULL }, - { "update", rbac::RBAC_PERM_COMMAND_DEBUG_UPDATE, false, &HandleDebugUpdateCommand, "", NULL }, - { "itemexpire", rbac::RBAC_PERM_COMMAND_DEBUG_ITEMEXPIRE, false, &HandleDebugItemExpireCommand, "", NULL }, - { "areatriggers", rbac::RBAC_PERM_COMMAND_DEBUG_AREATRIGGERS, false, &HandleDebugAreaTriggersCommand, "", NULL }, - { "los", rbac::RBAC_PERM_COMMAND_DEBUG_LOS, false, &HandleDebugLoSCommand, "", NULL }, - { "moveflags", rbac::RBAC_PERM_COMMAND_DEBUG_MOVEFLAGS, false, &HandleDebugMoveflagsCommand, "", NULL }, - { "transport", rbac::RBAC_PERM_COMMAND_DEBUG_TRANSPORT, false, &HandleDebugTransportCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "setaurastate", rbac::RBAC_PERM_COMMAND_DEBUG_SETAURASTATE, false, &HandleDebugSetAuraStateCommand, "" }, + { "setitemvalue", rbac::RBAC_PERM_COMMAND_DEBUG_SETITEMVALUE, false, &HandleDebugSetItemValueCommand, "" }, + { "setvalue", rbac::RBAC_PERM_COMMAND_DEBUG_SETVALUE, false, &HandleDebugSetValueCommand, "" }, + { "spawnvehicle", rbac::RBAC_PERM_COMMAND_DEBUG_SPAWNVEHICLE, false, &HandleDebugSpawnVehicleCommand, "" }, + { "setvid", rbac::RBAC_PERM_COMMAND_DEBUG_SETVID, false, &HandleDebugSetVehicleIdCommand, "" }, + { "entervehicle", rbac::RBAC_PERM_COMMAND_DEBUG_ENTERVEHICLE, false, &HandleDebugEnterVehicleCommand, "" }, + { "uws", rbac::RBAC_PERM_COMMAND_DEBUG_UWS, false, &HandleDebugUpdateWorldStateCommand, "" }, + { "update", rbac::RBAC_PERM_COMMAND_DEBUG_UPDATE, false, &HandleDebugUpdateCommand, "" }, + { "itemexpire", rbac::RBAC_PERM_COMMAND_DEBUG_ITEMEXPIRE, false, &HandleDebugItemExpireCommand, "" }, + { "areatriggers", rbac::RBAC_PERM_COMMAND_DEBUG_AREATRIGGERS, false, &HandleDebugAreaTriggersCommand, "" }, + { "los", rbac::RBAC_PERM_COMMAND_DEBUG_LOS, false, &HandleDebugLoSCommand, "" }, + { "moveflags", rbac::RBAC_PERM_COMMAND_DEBUG_MOVEFLAGS, false, &HandleDebugMoveflagsCommand, "" }, + { "transport", rbac::RBAC_PERM_COMMAND_DEBUG_TRANSPORT, false, &HandleDebugTransportCommand, "" }, + { "loadcells", rbac::RBAC_PERM_COMMAND_DEBUG_LOADCELLS, false, &HandleDebugLoadCellsCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "debug", rbac::RBAC_PERM_COMMAND_DEBUG, true, NULL, "", debugCommandTable }, - { "wpgps", rbac::RBAC_PERM_COMMAND_WPGPS, false, &HandleWPGPSCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "wpgps", rbac::RBAC_PERM_COMMAND_WPGPS, false, &HandleWPGPSCommand, "" }, }; return commandTable; } @@ -500,7 +498,7 @@ public: return false; handler->PSendSysMessage("Loot recipient for creature %s (GUID %u, DB GUID %u) is %s", - target->GetName().c_str(), target->GetGUIDLow(), target->GetDBTableGUIDLow(), + target->GetName().c_str(), target->GetGUID().GetCounter(), target->GetSpawnId(), target->hasLootRecipient() ? (target->GetLootRecipient() ? target->GetLootRecipient()->GetName().c_str() : "offline") : "no loot recipient"); return true; } @@ -595,7 +593,7 @@ public: break; } - handler->PSendSysMessage("bag: %d slot: %d guid: %d - state: %s", bagSlot, item->GetSlot(), item->GetGUIDLow(), st.c_str()); + handler->PSendSysMessage("bag: %d slot: %d guid: %d - state: %s", bagSlot, item->GetSlot(), item->GetGUID().GetCounter(), st.c_str()); } if (updateQueue.empty()) handler->PSendSysMessage("The player's updatequeue is empty"); @@ -616,7 +614,7 @@ public: if (item->GetSlot() != i) { - handler->PSendSysMessage("Item with slot %d and guid %d has an incorrect slot value: %d", i, item->GetGUIDLow(), item->GetSlot()); + handler->PSendSysMessage("Item with slot %d and guid %d has an incorrect slot value: %d", i, item->GetGUID().GetCounter(), item->GetSlot()); error = true; continue; } @@ -640,28 +638,28 @@ public: uint16 qp = item->GetQueuePos(); if (qp > updateQueue.size()) { - handler->PSendSysMessage("The item with slot %d and guid %d has its queuepos (%d) larger than the update queue size! ", item->GetSlot(), item->GetGUIDLow(), qp); + handler->PSendSysMessage("The item with slot %d and guid %d has its queuepos (%d) larger than the update queue size! ", item->GetSlot(), item->GetGUID().GetCounter(), qp); error = true; continue; } if (updateQueue[qp] == NULL) { - handler->PSendSysMessage("The item with slot %d and guid %d has its queuepos (%d) pointing to NULL in the queue!", item->GetSlot(), item->GetGUIDLow(), qp); + handler->PSendSysMessage("The item with slot %d and guid %d has its queuepos (%d) pointing to NULL in the queue!", item->GetSlot(), item->GetGUID().GetCounter(), qp); error = true; continue; } if (updateQueue[qp] != item) { - handler->PSendSysMessage("The item with slot %d and guid %d has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", item->GetSlot(), item->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); + handler->PSendSysMessage("The item with slot %d and guid %d has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", item->GetSlot(), item->GetGUID().GetCounter(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUID().GetCounter()); error = true; continue; } } else if (item->GetState() != ITEM_UNCHANGED) { - handler->PSendSysMessage("The item with slot %d and guid %d is not in queue but should be (state: %d)!", item->GetSlot(), item->GetGUIDLow(), item->GetState()); + handler->PSendSysMessage("The item with slot %d and guid %d is not in queue but should be (state: %d)!", item->GetSlot(), item->GetGUID().GetCounter(), item->GetState()); error = true; continue; } @@ -676,7 +674,7 @@ public: if (item2->GetSlot() != j) { - handler->PSendSysMessage("The item in bag %d and slot %d (guid: %d) has an incorrect slot value: %d", bag->GetSlot(), j, item2->GetGUIDLow(), item2->GetSlot()); + handler->PSendSysMessage("The item in bag %d and slot %d (guid: %d) has an incorrect slot value: %d", bag->GetSlot(), j, item2->GetGUID().GetCounter(), item2->GetSlot()); error = true; continue; } @@ -708,28 +706,28 @@ public: uint16 qp = item2->GetQueuePos(); if (qp > updateQueue.size()) { - handler->PSendSysMessage("The item in bag %d at slot %d having guid %d has a queuepos (%d) larger than the update queue size! ", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp); + handler->PSendSysMessage("The item in bag %d at slot %d having guid %d has a queuepos (%d) larger than the update queue size! ", bag->GetSlot(), item2->GetSlot(), item2->GetGUID().GetCounter(), qp); error = true; continue; } if (updateQueue[qp] == NULL) { - handler->PSendSysMessage("The item in bag %d at slot %d having guid %d has a queuepos (%d) that points to NULL in the queue!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp); + handler->PSendSysMessage("The item in bag %d at slot %d having guid %d has a queuepos (%d) that points to NULL in the queue!", bag->GetSlot(), item2->GetSlot(), item2->GetGUID().GetCounter(), qp); error = true; continue; } if (updateQueue[qp] != item2) { - handler->PSendSysMessage("The item in bag %d at slot %d having guid %d has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUIDLow()); + handler->PSendSysMessage("The item in bag %d at slot %d having guid %d has a queuepos (%d) that points to another item in the queue (bag: %d, slot: %d, guid: %d)", bag->GetSlot(), item2->GetSlot(), item2->GetGUID().GetCounter(), qp, updateQueue[qp]->GetBagSlot(), updateQueue[qp]->GetSlot(), updateQueue[qp]->GetGUID().GetCounter()); error = true; continue; } } else if (item2->GetState() != ITEM_UNCHANGED) { - handler->PSendSysMessage("The item in bag %d at slot %d having guid %d is not in queue but should be (state: %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUIDLow(), item2->GetState()); + handler->PSendSysMessage("The item in bag %d at slot %d having guid %d is not in queue but should be (state: %d)!", bag->GetSlot(), item2->GetSlot(), item2->GetGUID().GetCounter(), item2->GetState()); error = true; continue; } @@ -804,14 +802,14 @@ public: ThreatContainer::StorageType const &threatList = target->getThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator itr; uint32 count = 0; - handler->PSendSysMessage("Threat list of %s (guid %u)", target->GetName().c_str(), target->GetGUIDLow()); + handler->PSendSysMessage("Threat list of %s (guid %u)", target->GetName().c_str(), target->GetGUID().GetCounter()); for (itr = threatList.begin(); itr != threatList.end(); ++itr) { Unit* unit = (*itr)->getTarget(); if (!unit) continue; ++count; - handler->PSendSysMessage(" %u. %s (guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUIDLow(), (*itr)->getThreat()); + handler->PSendSysMessage(" %u. %s (guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), (*itr)->getThreat()); } handler->SendSysMessage("End of threat list."); return true; @@ -824,13 +822,13 @@ public: target = handler->GetSession()->GetPlayer(); HostileReference* ref = target->getHostileRefManager().getFirst(); uint32 count = 0; - handler->PSendSysMessage("Hostil reference list of %s (guid %u)", target->GetName().c_str(), target->GetGUIDLow()); + handler->PSendSysMessage("Hostil reference list of %s (guid %u)", target->GetName().c_str(), target->GetGUID().GetCounter()); while (ref) { if (Unit* unit = ref->GetSource()->GetOwner()) { ++count; - handler->PSendSysMessage(" %u. %s (guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUIDLow(), ref->getThreat()); + handler->PSendSysMessage(" %u. %s (guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), ref->getThreat()); } ref = ref->next(); } @@ -927,7 +925,7 @@ public: Map* map = handler->GetSession()->GetPlayer()->GetMap(); - if (!v->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_VEHICLE), map, handler->GetSession()->GetPlayer()->GetPhaseMask(), entry, x, y, z, o, nullptr, id)) + if (!v->Create(map->GenerateLowGuid<HighGuid::Vehicle>(), map, handler->GetSession()->GetPlayer()->GetPhaseMask(), entry, x, y, z, o, nullptr, id)) { delete v; return false; @@ -969,10 +967,10 @@ public: if (!e || !f) return false; - uint32 guid = (uint32)atoi(e); + ObjectGuid::LowType guid = (uint32)atoi(e); uint32 index = (uint32)atoi(f); - Item* i = handler->GetSession()->GetPlayer()->GetItemByGuid(ObjectGuid(HIGHGUID_ITEM, 0, guid)); + Item* i = handler->GetSession()->GetPlayer()->GetItemByGuid(ObjectGuid(HighGuid::Item, 0, guid)); if (!i) return false; @@ -999,11 +997,11 @@ public: if (!e || !f || !g) return false; - uint32 guid = (uint32)atoi(e); + ObjectGuid::LowType guid = (uint32)atoi(e); uint32 index = (uint32)atoi(f); uint32 value = (uint32)atoi(g); - Item* i = handler->GetSession()->GetPlayer()->GetItemByGuid(ObjectGuid(HIGHGUID_ITEM, 0, guid)); + Item* i = handler->GetSession()->GetPlayer()->GetItemByGuid(ObjectGuid(HighGuid::Item, 0, guid)); if (!i) return false; @@ -1025,9 +1023,9 @@ public: if (!e) return false; - uint32 guid = (uint32)atoi(e); + ObjectGuid::LowType guid = (uint32)atoi(e); - Item* i = handler->GetSession()->GetPlayer()->GetItemByGuid(ObjectGuid(HIGHGUID_ITEM, guid)); + Item* i = handler->GetSession()->GetPlayer()->GetItemByGuid(ObjectGuid(HighGuid::Item, guid)); if (!i) return false; @@ -1052,7 +1050,7 @@ public: static bool HandleDebugLoSCommand(ChatHandler* handler, char const* /*args*/) { if (Unit* unit = handler->getSelectedUnit()) - handler->PSendSysMessage("Unit %s (GuidLow: %u) is %sin LoS", unit->GetName().c_str(), unit->GetGUIDLow(), handler->GetSession()->GetPlayer()->IsWithinLOSInMap(unit) ? "" : "not "); + handler->PSendSysMessage("Unit %s (GuidLow: %u) is %sin LoS", unit->GetName().c_str(), unit->GetGUID().GetCounter(), handler->GetSession()->GetPlayer()->IsWithinLOSInMap(unit) ? "" : "not "); return true; } @@ -1197,7 +1195,7 @@ public: if (opcode >= handler->GetSession()->GetPlayer()->GetValuesCount()) { - handler->PSendSysMessage(LANG_TOO_BIG_INDEX, opcode, handler->GetSession()->GetPlayer()->GetGUIDLow(), handler->GetSession()->GetPlayer()->GetValuesCount()); + handler->PSendSysMessage(LANG_TOO_BIG_INDEX, opcode, handler->GetSession()->GetPlayer()->GetGUID().GetCounter(), handler->GetSession()->GetPlayer()->GetValuesCount()); return false; } @@ -1247,13 +1245,13 @@ public: { value = unit->GetUInt32Value(updateIndex); - handler->PSendSysMessage(LANG_UPDATE, unit->GetGUIDLow(), updateIndex, value); + handler->PSendSysMessage(LANG_UPDATE, unit->GetGUID().GetCounter(), updateIndex, value); return true; } value = atoi(val); - handler->PSendSysMessage(LANG_UPDATE_CHANGE, unit->GetGUIDLow(), updateIndex, value); + handler->PSendSysMessage(LANG_UPDATE_CHANGE, unit->GetGUID().GetCounter(), updateIndex, value); unit->SetUInt32Value(updateIndex, value); @@ -1391,6 +1389,31 @@ public: handler->PSendSysMessage("Transport %s %s", transport->GetName().c_str(), start ? "started" : "stopped"); return true; } + + static bool HandleDebugLoadCellsCommand(ChatHandler* handler, char const* args) + { + Player* player = handler->GetSession()->GetPlayer(); + if (!player) + return false; + + Map* map = nullptr; + + if (*args) + { + int32 mapId = atoi(args); + map = sMapMgr->FindBaseNonInstanceMap(mapId); + } + if (!map) + 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); + + 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; + } }; void AddSC_debug_commandscript() diff --git a/src/server/scripts/Commands/cs_deserter.cpp b/src/server/scripts/Commands/cs_deserter.cpp index 2887ac8c134..9f461207707 100644 --- a/src/server/scripts/Commands/cs_deserter.cpp +++ b/src/server/scripts/Commands/cs_deserter.cpp @@ -43,31 +43,27 @@ public: * @brief Returns the command structure for the system. */ - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand deserterInstanceCommandTable[] = + static std::vector<ChatCommand> deserterInstanceCommandTable = { - { "add", rbac::RBAC_PERM_COMMAND_DESERTER_INSTANCE_ADD, false, &HandleDeserterInstanceAdd, "", NULL }, - { "remove", rbac::RBAC_PERM_COMMAND_DESERTER_INSTANCE_REMOVE, false, &HandleDeserterInstanceRemove, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", rbac::RBAC_PERM_COMMAND_DESERTER_INSTANCE_ADD, false, &HandleDeserterInstanceAdd, "" }, + { "remove", rbac::RBAC_PERM_COMMAND_DESERTER_INSTANCE_REMOVE, false, &HandleDeserterInstanceRemove, "" }, }; - static ChatCommand deserterBGCommandTable[] = + static std::vector<ChatCommand> deserterBGCommandTable = { - { "add", rbac::RBAC_PERM_COMMAND_DESERTER_BG_ADD, false, &HandleDeserterBGAdd, "", NULL }, - { "remove", rbac::RBAC_PERM_COMMAND_DESERTER_BG_REMOVE, false, &HandleDeserterBGRemove, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", rbac::RBAC_PERM_COMMAND_DESERTER_BG_ADD, false, &HandleDeserterBGAdd, "" }, + { "remove", rbac::RBAC_PERM_COMMAND_DESERTER_BG_REMOVE, false, &HandleDeserterBGRemove, "" }, }; - static ChatCommand deserterCommandTable[] = + static std::vector<ChatCommand> deserterCommandTable = { { "instance", rbac::RBAC_PERM_COMMAND_DESERTER_INSTANCE, false, NULL, "", deserterInstanceCommandTable }, { "bg", rbac::RBAC_PERM_COMMAND_DESERTER_BG, false, NULL, "", deserterBGCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "deserter", rbac::RBAC_PERM_COMMAND_DESERTER, false, NULL, "", deserterCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_disable.cpp b/src/server/scripts/Commands/cs_disable.cpp index 14f76945a80..8c73f3f41de 100644 --- a/src/server/scripts/Commands/cs_disable.cpp +++ b/src/server/scripts/Commands/cs_disable.cpp @@ -37,42 +37,38 @@ class disable_commandscript : public CommandScript public: disable_commandscript() : CommandScript("disable_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand removeDisableCommandTable[] = + static std::vector<ChatCommand> removeDisableCommandTable = { - { "spell", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_SPELL, true, &HandleRemoveDisableSpellCommand, "", NULL }, - { "quest", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_QUEST, true, &HandleRemoveDisableQuestCommand, "", NULL }, - { "map", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP, true, &HandleRemoveDisableMapCommand, "", NULL }, - { "battleground", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND, true, &HandleRemoveDisableBattlegroundCommand, "", NULL }, - { "achievement_criteria", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_ACHIEVEMENT_CRITERIA, true, &HandleRemoveDisableAchievementCriteriaCommand, "", NULL }, - { "outdoorpvp", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_OUTDOORPVP, true, &HandleRemoveDisableOutdoorPvPCommand, "", NULL }, - { "vmap", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_VMAP, true, &HandleRemoveDisableVmapCommand, "", NULL }, - { "mmap", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MMAP, true, &HandleRemoveDisableMMapCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "spell", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_SPELL, true, &HandleRemoveDisableSpellCommand, "" }, + { "quest", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_QUEST, true, &HandleRemoveDisableQuestCommand, "" }, + { "map", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP, true, &HandleRemoveDisableMapCommand, "" }, + { "battleground", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND, true, &HandleRemoveDisableBattlegroundCommand, "" }, + { "achievement_criteria", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_ACHIEVEMENT_CRITERIA, true, &HandleRemoveDisableAchievementCriteriaCommand, "" }, + { "outdoorpvp", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_OUTDOORPVP, true, &HandleRemoveDisableOutdoorPvPCommand, "" }, + { "vmap", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_VMAP, true, &HandleRemoveDisableVmapCommand, "" }, + { "mmap", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MMAP, true, &HandleRemoveDisableMMapCommand, "" }, }; - static ChatCommand addDisableCommandTable[] = + static std::vector<ChatCommand> addDisableCommandTable = { - { "spell", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_SPELL, true, &HandleAddDisableSpellCommand, "", NULL }, - { "quest", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_QUEST, true, &HandleAddDisableQuestCommand, "", NULL }, - { "map", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MAP, true, &HandleAddDisableMapCommand, "", NULL }, - { "battleground", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND, true, &HandleAddDisableBattlegroundCommand, "", NULL }, - { "achievement_criteria", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_ACHIEVEMENT_CRITERIA, true, &HandleAddDisableAchievementCriteriaCommand, "", NULL }, - { "outdoorpvp", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_OUTDOORPVP, true, &HandleAddDisableOutdoorPvPCommand, "", NULL }, - { "vmap", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_VMAP, true, &HandleAddDisableVmapCommand, "", NULL }, - { "mmap", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MMAP, true, &HandleAddDisableMMapCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "spell", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_SPELL, true, &HandleAddDisableSpellCommand, "" }, + { "quest", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_QUEST, true, &HandleAddDisableQuestCommand, "" }, + { "map", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MAP, true, &HandleAddDisableMapCommand, "" }, + { "battleground", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND, true, &HandleAddDisableBattlegroundCommand, "" }, + { "achievement_criteria", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_ACHIEVEMENT_CRITERIA, true, &HandleAddDisableAchievementCriteriaCommand, "" }, + { "outdoorpvp", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_OUTDOORPVP, true, &HandleAddDisableOutdoorPvPCommand, "" }, + { "vmap", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_VMAP, true, &HandleAddDisableVmapCommand, "" }, + { "mmap", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MMAP, true, &HandleAddDisableMMapCommand, "" }, }; - static ChatCommand disableCommandTable[] = + static std::vector<ChatCommand> disableCommandTable = { { "add", rbac::RBAC_PERM_COMMAND_DISABLE_ADD, true, NULL, "", addDisableCommandTable }, { "remove", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE, true, NULL, "", removeDisableCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "disable", rbac::RBAC_PERM_COMMAND_DISABLE, false, NULL, "", disableCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_event.cpp b/src/server/scripts/Commands/cs_event.cpp index 37495289149..352bce4e7f0 100644 --- a/src/server/scripts/Commands/cs_event.cpp +++ b/src/server/scripts/Commands/cs_event.cpp @@ -33,20 +33,18 @@ class event_commandscript : public CommandScript public: event_commandscript() : CommandScript("event_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand eventCommandTable[] = + static std::vector<ChatCommand> eventCommandTable = { - { "activelist", rbac::RBAC_PERM_COMMAND_EVENT_ACTIVELIST, true, &HandleEventActiveListCommand, "", NULL }, - { "start", rbac::RBAC_PERM_COMMAND_EVENT_START, true, &HandleEventStartCommand, "", NULL }, - { "stop", rbac::RBAC_PERM_COMMAND_EVENT_STOP, true, &HandleEventStopCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_EVENT, true, &HandleEventInfoCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "activelist", rbac::RBAC_PERM_COMMAND_EVENT_ACTIVELIST, true, &HandleEventActiveListCommand, "" }, + { "start", rbac::RBAC_PERM_COMMAND_EVENT_START, true, &HandleEventStartCommand, "" }, + { "stop", rbac::RBAC_PERM_COMMAND_EVENT_STOP, true, &HandleEventStopCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_EVENT, true, &HandleEventInfoCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "event", rbac::RBAC_PERM_COMMAND_EVENT, false, NULL, "", eventCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index 94e974bea0b..81b70603680 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -36,22 +36,20 @@ class gm_commandscript : public CommandScript public: gm_commandscript() : CommandScript("gm_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand gmCommandTable[] = + static std::vector<ChatCommand> gmCommandTable = { - { "chat", rbac::RBAC_PERM_COMMAND_GM_CHAT, false, &HandleGMChatCommand, "", NULL }, - { "fly", rbac::RBAC_PERM_COMMAND_GM_FLY, false, &HandleGMFlyCommand, "", NULL }, - { "ingame", rbac::RBAC_PERM_COMMAND_GM_INGAME, true, &HandleGMListIngameCommand, "", NULL }, - { "list", rbac::RBAC_PERM_COMMAND_GM_LIST, true, &HandleGMListFullCommand, "", NULL }, - { "visible", rbac::RBAC_PERM_COMMAND_GM_VISIBLE, false, &HandleGMVisibleCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_GM, false, &HandleGMCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "chat", rbac::RBAC_PERM_COMMAND_GM_CHAT, false, &HandleGMChatCommand, "" }, + { "fly", rbac::RBAC_PERM_COMMAND_GM_FLY, false, &HandleGMFlyCommand, "" }, + { "ingame", rbac::RBAC_PERM_COMMAND_GM_INGAME, true, &HandleGMListIngameCommand, "" }, + { "list", rbac::RBAC_PERM_COMMAND_GM_LIST, true, &HandleGMListFullCommand, "" }, + { "visible", rbac::RBAC_PERM_COMMAND_GM_VISIBLE, false, &HandleGMVisibleCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_GM, false, &HandleGMCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "gm", rbac::RBAC_PERM_COMMAND_GM, false, NULL, "", gmCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 1ddfaa4bfd8..a810106269e 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -36,27 +36,25 @@ class go_commandscript : public CommandScript public: go_commandscript() : CommandScript("go_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand goCommandTable[] = - { - { "creature", rbac::RBAC_PERM_COMMAND_GO_CREATURE, false, &HandleGoCreatureCommand, "", NULL }, - { "graveyard", rbac::RBAC_PERM_COMMAND_GO_GRAVEYARD, false, &HandleGoGraveyardCommand, "", NULL }, - { "grid", rbac::RBAC_PERM_COMMAND_GO_GRID, false, &HandleGoGridCommand, "", NULL }, - { "object", rbac::RBAC_PERM_COMMAND_GO_OBJECT, false, &HandleGoObjectCommand, "", NULL }, - { "taxinode", rbac::RBAC_PERM_COMMAND_GO_TAXINODE, false, &HandleGoTaxinodeCommand, "", NULL }, - { "trigger", rbac::RBAC_PERM_COMMAND_GO_TRIGGER, false, &HandleGoTriggerCommand, "", NULL }, - { "zonexy", rbac::RBAC_PERM_COMMAND_GO_ZONEXY, false, &HandleGoZoneXYCommand, "", NULL }, - { "xyz", rbac::RBAC_PERM_COMMAND_GO_XYZ, false, &HandleGoXYZCommand, "", NULL }, - { "ticket", rbac::RBAC_PERM_COMMAND_GO_TICKET, false, &HandleGoTicketCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoXYZCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + static std::vector<ChatCommand> goCommandTable = + { + { "creature", rbac::RBAC_PERM_COMMAND_GO_CREATURE, false, &HandleGoCreatureCommand, "" }, + { "graveyard", rbac::RBAC_PERM_COMMAND_GO_GRAVEYARD, false, &HandleGoGraveyardCommand, "" }, + { "grid", rbac::RBAC_PERM_COMMAND_GO_GRID, false, &HandleGoGridCommand, "" }, + { "object", rbac::RBAC_PERM_COMMAND_GO_OBJECT, false, &HandleGoObjectCommand, "" }, + { "taxinode", rbac::RBAC_PERM_COMMAND_GO_TAXINODE, false, &HandleGoTaxinodeCommand, "" }, + { "trigger", rbac::RBAC_PERM_COMMAND_GO_TRIGGER, false, &HandleGoTriggerCommand, "" }, + { "zonexy", rbac::RBAC_PERM_COMMAND_GO_ZONEXY, false, &HandleGoZoneXYCommand, "" }, + { "xyz", rbac::RBAC_PERM_COMMAND_GO_XYZ, false, &HandleGoXYZCommand, "" }, + { "ticket", rbac::RBAC_PERM_COMMAND_GO_TICKET, false, &HandleGoTicketCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_GO, false, &HandleGoXYZCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "go", rbac::RBAC_PERM_COMMAND_GO, false, NULL, "", goCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -135,21 +133,9 @@ public: float z = fields[2].GetFloat(); float o = fields[3].GetFloat(); uint32 mapId = fields[4].GetUInt16(); - uint32 guid = fields[5].GetUInt32(); - uint32 id = fields[6].GetUInt32(); Transport* transport = NULL; - if (Creature* creature = ObjectAccessor::GetObjectInWorld(ObjectGuid(HIGHGUID_UNIT, id, guid), (Creature*)NULL)) - { - x = creature->GetPositionX(); - y = creature->GetPositionY(); - z = creature->GetPositionZ(); - o = creature->GetOrientation(); - mapId = creature->GetMapId(); - transport = creature->GetTransport(); - } - if (!MapManager::IsValidMapCoord(mapId, x, y, z, o) || sObjectMgr->IsTransportMap(mapId)) { handler->PSendSysMessage(LANG_INVALID_TARGET_COORD, x, y, mapId); diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 0142cfa0e52..fda9101fc3f 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -37,37 +37,33 @@ class gobject_commandscript : public CommandScript public: gobject_commandscript() : CommandScript("gobject_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand gobjectAddCommandTable[] = + static std::vector<ChatCommand> gobjectAddCommandTable = { - { "temp", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD_TEMP, false, &HandleGameObjectAddTempCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, false, &HandleGameObjectAddCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "temp", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD_TEMP, false, &HandleGameObjectAddTempCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, false, &HandleGameObjectAddCommand, "" }, }; - static ChatCommand gobjectSetCommandTable[] = + static std::vector<ChatCommand> gobjectSetCommandTable = { - { "phase", rbac::RBAC_PERM_COMMAND_GOBJECT_SET_PHASE, false, &HandleGameObjectSetPhaseCommand, "", NULL }, - { "state", rbac::RBAC_PERM_COMMAND_GOBJECT_SET_STATE, false, &HandleGameObjectSetStateCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "phase", rbac::RBAC_PERM_COMMAND_GOBJECT_SET_PHASE, false, &HandleGameObjectSetPhaseCommand, "" }, + { "state", rbac::RBAC_PERM_COMMAND_GOBJECT_SET_STATE, false, &HandleGameObjectSetStateCommand, "" }, }; - static ChatCommand gobjectCommandTable[] = - { - { "activate", rbac::RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, false, &HandleGameObjectActivateCommand, "", NULL }, - { "delete", rbac::RBAC_PERM_COMMAND_GOBJECT_DELETE, false, &HandleGameObjectDeleteCommand, "", NULL }, - { "info", rbac::RBAC_PERM_COMMAND_GOBJECT_INFO, false, &HandleGameObjectInfoCommand, "", NULL }, - { "move", rbac::RBAC_PERM_COMMAND_GOBJECT_MOVE, false, &HandleGameObjectMoveCommand, "", NULL }, - { "near", rbac::RBAC_PERM_COMMAND_GOBJECT_NEAR, false, &HandleGameObjectNearCommand, "", NULL }, - { "target", rbac::RBAC_PERM_COMMAND_GOBJECT_TARGET, false, &HandleGameObjectTargetCommand, "", NULL }, - { "turn", rbac::RBAC_PERM_COMMAND_GOBJECT_TURN, false, &HandleGameObjectTurnCommand, "", NULL }, + static std::vector<ChatCommand> gobjectCommandTable = + { + { "activate", rbac::RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, false, &HandleGameObjectActivateCommand, "" }, + { "delete", rbac::RBAC_PERM_COMMAND_GOBJECT_DELETE, false, &HandleGameObjectDeleteCommand, "" }, + { "info", rbac::RBAC_PERM_COMMAND_GOBJECT_INFO, false, &HandleGameObjectInfoCommand, "" }, + { "move", rbac::RBAC_PERM_COMMAND_GOBJECT_MOVE, false, &HandleGameObjectMoveCommand, "" }, + { "near", rbac::RBAC_PERM_COMMAND_GOBJECT_NEAR, false, &HandleGameObjectNearCommand, "" }, + { "target", rbac::RBAC_PERM_COMMAND_GOBJECT_TARGET, false, &HandleGameObjectTargetCommand, "" }, + { "turn", rbac::RBAC_PERM_COMMAND_GOBJECT_TURN, false, &HandleGameObjectTurnCommand, "" }, { "add", rbac::RBAC_PERM_COMMAND_GOBJECT_ADD, false, NULL, "", gobjectAddCommandTable }, { "set", rbac::RBAC_PERM_COMMAND_GOBJECT_SET, false, NULL, "", gobjectSetCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "gobject", rbac::RBAC_PERM_COMMAND_GOBJECT, false, NULL, "", gobjectCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -81,7 +77,7 @@ public: if (!id) return false; - uint32 guidLow = atoi(id); + ObjectGuid::LowType guidLow = atoi(id); if (!guidLow) return false; @@ -150,7 +146,7 @@ public: Map* map = player->GetMap(); GameObject* object = new GameObject; - uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_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)) { @@ -166,6 +162,8 @@ public: // fill the gameobject data and save to the db object->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), player->GetPhaseMaskForSpawn()); + guidLow = object->GetSpawnId(); + // delete the old object and do a clean load from DB with a fresh new GameObject instance. // this is required to avoid weird behavior and memory leaks delete object; @@ -290,7 +288,8 @@ public: bool found = false; float x, y, z, o; - uint32 guidLow, id, phase; + ObjectGuid::LowType guidLow; + uint32 id, phase; uint16 mapId; uint32 poolId; @@ -324,7 +323,7 @@ public: return false; } - GameObject* target = handler->GetSession()->GetPlayer()->GetMap()->GetGameObject(ObjectGuid(HIGHGUID_GAMEOBJECT, id, guidLow)); + GameObject* target = handler->GetSession()->GetPlayer()->GetMap()->GetGameObject(ObjectGuid(HighGuid::GameObject, id, guidLow)); handler->PSendSysMessage(LANG_GAMEOBJECT_DETAIL, guidLow, objectInfo->name.c_str(), guidLow, id, x, y, z, mapId, o, phase); @@ -350,7 +349,7 @@ public: if (!id) return false; - uint32 guidLow = atoi(id); + ObjectGuid::LowType guidLow = atoi(id); if (!guidLow) return false; @@ -373,7 +372,7 @@ public: Unit* owner = ObjectAccessor::GetUnit(*handler->GetSession()->GetPlayer(), ownerGuid); if (!owner || !ownerGuid.IsPlayer()) { - handler->PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, ownerGuid.GetCounter(), object->GetGUIDLow()); + handler->PSendSysMessage(LANG_COMMAND_DELOBJREFERCREATURE, ownerGuid.GetCounter(), object->GetGUID().GetCounter()); handler->SetSentErrorMessage(true); return false; } @@ -385,7 +384,7 @@ public: object->Delete(); object->DeleteFromDB(); - handler->PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, object->GetGUIDLow()); + handler->PSendSysMessage(LANG_COMMAND_DELOBJMESSAGE, object->GetGUID().GetCounter()); return true; } @@ -398,7 +397,7 @@ public: if (!id) return false; - uint32 guidLow = atoi(id); + ObjectGuid::LowType guidLow = atoi(id); if (!guidLow) return false; @@ -426,16 +425,26 @@ public: o = player->GetOrientation(); } + Map* map = object->GetMap(); + object->Relocate(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), o); object->UpdateRotationFields(); - object->DestroyForNearbyPlayers(); - object->UpdateObjectVisibility(); - object->SaveToDB(); - object->Refresh(); - handler->PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, object->GetGUIDLow(), object->GetGOInfo()->name.c_str(), object->GetGUIDLow(), o); + // Generate a completely new spawn with new guid + // 3.3.5a client caches recently deleted objects and brings them back to life + // when CreateObject block for this guid is received again + // however it entirely skips parsing that block and only uses already known location + object->Delete(); + + object = new GameObject(); + if (!object->LoadGameObjectFromDB(guidLow, map)) + { + delete object; + return false; + } + handler->PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetSpawnId()); return true; } @@ -447,7 +456,7 @@ public: if (!id) return false; - uint32 guidLow = atoi(id); + ObjectGuid::LowType guidLow = atoi(id); if (!guidLow) return false; @@ -468,21 +477,20 @@ public: char* toY = strtok(NULL, " "); char* toZ = strtok(NULL, " "); + float x, y, z; if (!toX) { Player* player = handler->GetSession()->GetPlayer(); - object->Relocate(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), object->GetOrientation()); - object->DestroyForNearbyPlayers(); - object->UpdateObjectVisibility(); + player->GetPosition(x, y, z); } else { if (!toY || !toZ) return false; - float x = (float)atof(toX); - float y = (float)atof(toY); - float z = (float)atof(toZ); + x = (float)atof(toX); + y = (float)atof(toY); + z = (float)atof(toZ); if (!MapManager::IsValidMapCoord(object->GetMapId(), x, y, z)) { @@ -490,17 +498,27 @@ public: handler->SetSentErrorMessage(true); return false; } - - object->Relocate(x, y, z, object->GetOrientation()); - object->DestroyForNearbyPlayers(); - object->UpdateObjectVisibility(); } + Map* map = object->GetMap(); + + object->Relocate(x, y, z, object->GetOrientation()); object->SaveToDB(); - object->Refresh(); - handler->PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, object->GetGUIDLow(), object->GetGOInfo()->name.c_str(), object->GetGUIDLow()); + // Generate a completely new spawn with new guid + // 3.3.5a client caches recently deleted objects and brings them back to life + // when CreateObject block for this guid is received again + // however it entirely skips parsing that block and only uses already known location + object->Delete(); + + object = new GameObject(); + if (!object->LoadGameObjectFromDB(guidLow, map)) + { + delete object; + return false; + } + handler->PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetSpawnId()); return true; } @@ -512,7 +530,7 @@ public: if (!id) return false; - uint32 guidLow = atoi(id); + ObjectGuid::LowType guidLow = atoi(id); if (!guidLow) return false; @@ -566,7 +584,7 @@ public: do { Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); + ObjectGuid::LowType guid = fields[0].GetUInt32(); uint32 entry = fields[1].GetUInt32(); float x = fields[2].GetFloat(); float y = fields[3].GetFloat(); @@ -635,7 +653,7 @@ public: if (!id) return false; - uint32 guidLow = atoi(id); + ObjectGuid::LowType guidLow = atoi(id); if (!guidLow) return false; diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index c0a4b2cfead..054cff996f9 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -28,23 +28,21 @@ class group_commandscript : public CommandScript public: group_commandscript() : CommandScript("group_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand groupCommandTable[] = + static std::vector<ChatCommand> groupCommandTable = { - { "leader", rbac::RBAC_PERM_COMMAND_GROUP_LEADER, false, &HandleGroupLeaderCommand, "", NULL }, - { "disband", rbac::RBAC_PERM_COMMAND_GROUP_DISBAND, false, &HandleGroupDisbandCommand, "", NULL }, - { "remove", rbac::RBAC_PERM_COMMAND_GROUP_REMOVE, false, &HandleGroupRemoveCommand, "", NULL }, - { "join", rbac::RBAC_PERM_COMMAND_GROUP_JOIN, false, &HandleGroupJoinCommand, "", NULL }, - { "list", rbac::RBAC_PERM_COMMAND_GROUP_LIST, false, &HandleGroupListCommand, "", NULL }, - { "summon", rbac::RBAC_PERM_COMMAND_GROUP_SUMMON, false, &HandleGroupSummonCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "leader", rbac::RBAC_PERM_COMMAND_GROUP_LEADER, false, &HandleGroupLeaderCommand, "" }, + { "disband", rbac::RBAC_PERM_COMMAND_GROUP_DISBAND, false, &HandleGroupDisbandCommand, "" }, + { "remove", rbac::RBAC_PERM_COMMAND_GROUP_REMOVE, false, &HandleGroupRemoveCommand, "" }, + { "join", rbac::RBAC_PERM_COMMAND_GROUP_JOIN, false, &HandleGroupJoinCommand, "" }, + { "list", rbac::RBAC_PERM_COMMAND_GROUP_LIST, false, &HandleGroupListCommand, "" }, + { "summon", rbac::RBAC_PERM_COMMAND_GROUP_SUMMON, false, &HandleGroupSummonCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "group", rbac::RBAC_PERM_COMMAND_GROUP, false, NULL, "", groupCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -269,7 +267,7 @@ public: const char* onlineState = ""; // Parse the guid to uint32... - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); + ObjectGuid parseGUID(HighGuid::Player, uint32(atoul(args))); // ... and try to extract a player out of it. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp index a735e296f59..04b633f6f40 100644 --- a/src/server/scripts/Commands/cs_guild.cpp +++ b/src/server/scripts/Commands/cs_guild.cpp @@ -34,23 +34,21 @@ class guild_commandscript : public CommandScript public: guild_commandscript() : CommandScript("guild_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand guildCommandTable[] = + static std::vector<ChatCommand> guildCommandTable = { - { "create", rbac::RBAC_PERM_COMMAND_GUILD_CREATE, true, &HandleGuildCreateCommand, "", NULL }, - { "delete", rbac::RBAC_PERM_COMMAND_GUILD_DELETE, true, &HandleGuildDeleteCommand, "", NULL }, - { "invite", rbac::RBAC_PERM_COMMAND_GUILD_INVITE, true, &HandleGuildInviteCommand, "", NULL }, - { "uninvite", rbac::RBAC_PERM_COMMAND_GUILD_UNINVITE, true, &HandleGuildUninviteCommand, "", NULL }, - { "rank", rbac::RBAC_PERM_COMMAND_GUILD_RANK, true, &HandleGuildRankCommand, "", NULL }, - { "rename", rbac::RBAC_PERM_COMMAND_GUILD_RENAME, true, &HandleGuildRenameCommand, "", NULL }, - { "info", rbac::RBAC_PERM_COMMAND_GUILD_INFO, true, &HandleGuildInfoCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "create", rbac::RBAC_PERM_COMMAND_GUILD_CREATE, true, &HandleGuildCreateCommand, "" }, + { "delete", rbac::RBAC_PERM_COMMAND_GUILD_DELETE, true, &HandleGuildDeleteCommand, "" }, + { "invite", rbac::RBAC_PERM_COMMAND_GUILD_INVITE, true, &HandleGuildInviteCommand, "" }, + { "uninvite", rbac::RBAC_PERM_COMMAND_GUILD_UNINVITE, true, &HandleGuildUninviteCommand, "" }, + { "rank", rbac::RBAC_PERM_COMMAND_GUILD_RANK, true, &HandleGuildRankCommand, "" }, + { "rename", rbac::RBAC_PERM_COMMAND_GUILD_RENAME, true, &HandleGuildRenameCommand, "" }, + { "info", rbac::RBAC_PERM_COMMAND_GUILD_INFO, true, &HandleGuildInfoCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "guild", rbac::RBAC_PERM_COMMAND_GUILD, true, NULL, "", guildCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -158,7 +156,7 @@ public: if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid)) return false; - uint32 guildId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(targetGuid); + ObjectGuid::LowType guildId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(targetGuid); if (!guildId) return false; @@ -184,7 +182,7 @@ public: if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid, &target_name)) return false; - uint32 guildId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(targetGuid); + ObjectGuid::LowType guildId = target ? target->GetGuildId() : Player::GetGuildIdFromDB(targetGuid); if (!guildId) return false; diff --git a/src/server/scripts/Commands/cs_honor.cpp b/src/server/scripts/Commands/cs_honor.cpp index ad2c53415bb..e8b41309d47 100644 --- a/src/server/scripts/Commands/cs_honor.cpp +++ b/src/server/scripts/Commands/cs_honor.cpp @@ -33,26 +33,23 @@ class honor_commandscript : public CommandScript public: honor_commandscript() : CommandScript("honor_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand honorAddCommandTable[] = + static std::vector<ChatCommand> honorAddCommandTable = { - { "kill", rbac::RBAC_PERM_COMMAND_HONOR_ADD_KILL, false, &HandleHonorAddKillCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_HONOR_ADD, false, &HandleHonorAddCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "kill", rbac::RBAC_PERM_COMMAND_HONOR_ADD_KILL, false, &HandleHonorAddKillCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_HONOR_ADD, false, &HandleHonorAddCommand, "" }, }; - static ChatCommand honorCommandTable[] = + static std::vector<ChatCommand> honorCommandTable = { { "add", rbac::RBAC_PERM_COMMAND_HONOR_ADD, false, NULL, "", honorAddCommandTable }, - { "update", rbac::RBAC_PERM_COMMAND_HONOR_UPDATE, false, &HandleHonorUpdateCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "update", rbac::RBAC_PERM_COMMAND_HONOR_UPDATE, false, &HandleHonorUpdateCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "honor", rbac::RBAC_PERM_COMMAND_HONOR, false, NULL, "", honorCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_instance.cpp b/src/server/scripts/Commands/cs_instance.cpp index 78c8f970f52..5651aaa12ee 100644 --- a/src/server/scripts/Commands/cs_instance.cpp +++ b/src/server/scripts/Commands/cs_instance.cpp @@ -36,23 +36,21 @@ class instance_commandscript : public CommandScript public: instance_commandscript() : CommandScript("instance_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand instanceCommandTable[] = + static std::vector<ChatCommand> instanceCommandTable = { - { "listbinds", rbac::RBAC_PERM_COMMAND_INSTANCE_LISTBINDS, false, &HandleInstanceListBindsCommand, "", NULL }, - { "unbind", rbac::RBAC_PERM_COMMAND_INSTANCE_UNBIND, false, &HandleInstanceUnbindCommand, "", NULL }, - { "stats", rbac::RBAC_PERM_COMMAND_INSTANCE_STATS, true, &HandleInstanceStatsCommand, "", NULL }, - { "savedata", rbac::RBAC_PERM_COMMAND_INSTANCE_SAVEDATA, false, &HandleInstanceSaveDataCommand, "", NULL }, - { "setbossstate", rbac::RBAC_PERM_COMMAND_INSTANCE_SET_BOSS_STATE, true, &HandleInstanceSetBossStateCommand, "", NULL }, - { "getbossstate", rbac::RBAC_PERM_COMMAND_INSTANCE_GET_BOSS_STATE, true, &HandleInstanceGetBossStateCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "listbinds", rbac::RBAC_PERM_COMMAND_INSTANCE_LISTBINDS, false, &HandleInstanceListBindsCommand, "" }, + { "unbind", rbac::RBAC_PERM_COMMAND_INSTANCE_UNBIND, false, &HandleInstanceUnbindCommand, "" }, + { "stats", rbac::RBAC_PERM_COMMAND_INSTANCE_STATS, true, &HandleInstanceStatsCommand, "" }, + { "savedata", rbac::RBAC_PERM_COMMAND_INSTANCE_SAVEDATA, false, &HandleInstanceSaveDataCommand, "" }, + { "setbossstate", rbac::RBAC_PERM_COMMAND_INSTANCE_SET_BOSS_STATE, true, &HandleInstanceSetBossStateCommand, "" }, + { "getbossstate", rbac::RBAC_PERM_COMMAND_INSTANCE_GET_BOSS_STATE, true, &HandleInstanceGetBossStateCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "instance", rbac::RBAC_PERM_COMMAND_INSTANCE, true, NULL, "", instanceCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; @@ -170,22 +168,22 @@ public: static bool HandleInstanceSaveDataCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); - Map* map = player->GetMap(); - if (!map->IsDungeon()) + InstanceMap* map = player->GetMap()->ToInstanceMap(); + if (!map) { handler->PSendSysMessage(LANG_NOT_DUNGEON); handler->SetSentErrorMessage(true); return false; } - if (!((InstanceMap*)map)->GetInstanceScript()) + if (!map->GetInstanceScript()) { handler->PSendSysMessage(LANG_NO_INSTANCE_DATA); handler->SetSentErrorMessage(true); return false; } - ((InstanceMap*)map)->GetInstanceScript()->SaveToDB(); + map->GetInstanceScript()->SaveToDB(); return true; } @@ -217,7 +215,7 @@ public: { playerName = param3; if (normalizePlayerName(playerName)) - player = sObjectAccessor->FindPlayerByName(playerName); + player = ObjectAccessor::FindPlayerByName(playerName); } if (!player) @@ -227,15 +225,15 @@ public: return false; } - Map* map = player->GetMap(); - if (!map->IsDungeon()) + InstanceMap* map = player->GetMap()->ToInstanceMap(); + if (!map) { handler->PSendSysMessage(LANG_NOT_DUNGEON); handler->SetSentErrorMessage(true); return false; } - if (!map->ToInstanceMap()->GetInstanceScript()) + if (!map->GetInstanceScript()) { handler->PSendSysMessage(LANG_NO_INSTANCE_DATA); handler->SetSentErrorMessage(true); @@ -246,15 +244,16 @@ public: state = atoi(param2); // Reject improper values. - if (state > TO_BE_DECIDED || encounterId > map->ToInstanceMap()->GetInstanceScript()->GetEncounterCount()) + if (state > TO_BE_DECIDED || encounterId > map->GetInstanceScript()->GetEncounterCount()) { handler->PSendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } - map->ToInstanceMap()->GetInstanceScript()->SetBossState(encounterId, (EncounterState)state); - handler->PSendSysMessage(LANG_COMMAND_INST_SET_BOSS_STATE, encounterId, state); + map->GetInstanceScript()->SetBossState(encounterId, EncounterState(state)); + std::string stateName = InstanceScript::GetBossStateName(state); + handler->PSendSysMessage(LANG_COMMAND_INST_SET_BOSS_STATE, encounterId, state, stateName); return true; } @@ -283,7 +282,7 @@ public: { playerName = param2; if (normalizePlayerName(playerName)) - player = sObjectAccessor->FindPlayerByName(playerName); + player = ObjectAccessor::FindPlayerByName(playerName); } if (!player) @@ -293,15 +292,15 @@ public: return false; } - Map* map = player->GetMap(); - if (!map->IsDungeon()) + InstanceMap* map = player->GetMap()->ToInstanceMap(); + if (!map) { handler->PSendSysMessage(LANG_NOT_DUNGEON); handler->SetSentErrorMessage(true); return false; } - if (!map->ToInstanceMap()->GetInstanceScript()) + if (!map->GetInstanceScript()) { handler->PSendSysMessage(LANG_NO_INSTANCE_DATA); handler->SetSentErrorMessage(true); @@ -310,15 +309,16 @@ public: encounterId = atoi(param1); - if (encounterId > map->ToInstanceMap()->GetInstanceScript()->GetEncounterCount()) + if (encounterId > map->GetInstanceScript()->GetEncounterCount()) { handler->PSendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } - uint8 state = map->ToInstanceMap()->GetInstanceScript()->GetBossState(encounterId); - handler->PSendSysMessage(LANG_COMMAND_INST_GET_BOSS_STATE, encounterId, state); + uint32 state = map->GetInstanceScript()->GetBossState(encounterId); + std::string stateName = InstanceScript::GetBossStateName(state); + handler->PSendSysMessage(LANG_COMMAND_INST_GET_BOSS_STATE, encounterId, state, stateName); return true; } }; diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp index 21211afad50..d7fd4e6664c 100644 --- a/src/server/scripts/Commands/cs_learn.cpp +++ b/src/server/scripts/Commands/cs_learn.cpp @@ -36,40 +36,36 @@ class learn_commandscript : public CommandScript public: learn_commandscript() : CommandScript("learn_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand learnAllMyCommandTable[] = + static std::vector<ChatCommand> learnAllMyCommandTable = { - { "class", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_CLASS, false, &HandleLearnAllMyClassCommand, "", NULL }, - { "pettalents", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_PETTALENTS, false, &HandleLearnAllMyPetTalentsCommand, "", NULL }, - { "spells", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_SPELLS, false, &HandleLearnAllMySpellsCommand, "", NULL }, - { "talents", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_TALENTS, false, &HandleLearnAllMyTalentsCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "class", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_CLASS, false, &HandleLearnAllMyClassCommand, "" }, + { "pettalents", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_PETTALENTS, false, &HandleLearnAllMyPetTalentsCommand, "" }, + { "spells", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_SPELLS, false, &HandleLearnAllMySpellsCommand, "" }, + { "talents", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY_TALENTS, false, &HandleLearnAllMyTalentsCommand, "" }, }; - static ChatCommand learnAllCommandTable[] = + static std::vector<ChatCommand> learnAllCommandTable = { { "my", rbac::RBAC_PERM_COMMAND_LEARN_ALL_MY, false, NULL, "", learnAllMyCommandTable }, - { "gm", rbac::RBAC_PERM_COMMAND_LEARN_ALL_GM, false, &HandleLearnAllGMCommand, "", NULL }, - { "crafts", rbac::RBAC_PERM_COMMAND_LEARN_ALL_CRAFTS, false, &HandleLearnAllCraftsCommand, "", NULL }, - { "default", rbac::RBAC_PERM_COMMAND_LEARN_ALL_DEFAULT, false, &HandleLearnAllDefaultCommand, "", NULL }, - { "lang", rbac::RBAC_PERM_COMMAND_LEARN_ALL_LANG, false, &HandleLearnAllLangCommand, "", NULL }, - { "recipes", rbac::RBAC_PERM_COMMAND_LEARN_ALL_RECIPES, false, &HandleLearnAllRecipesCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "gm", rbac::RBAC_PERM_COMMAND_LEARN_ALL_GM, false, &HandleLearnAllGMCommand, "" }, + { "crafts", rbac::RBAC_PERM_COMMAND_LEARN_ALL_CRAFTS, false, &HandleLearnAllCraftsCommand, "" }, + { "default", rbac::RBAC_PERM_COMMAND_LEARN_ALL_DEFAULT, false, &HandleLearnAllDefaultCommand, "" }, + { "lang", rbac::RBAC_PERM_COMMAND_LEARN_ALL_LANG, false, &HandleLearnAllLangCommand, "" }, + { "recipes", rbac::RBAC_PERM_COMMAND_LEARN_ALL_RECIPES, false, &HandleLearnAllRecipesCommand, "" }, }; - static ChatCommand learnCommandTable[] = + static std::vector<ChatCommand> learnCommandTable = { { "all", rbac::RBAC_PERM_COMMAND_LEARN_ALL, false, NULL, "", learnAllCommandTable }, - { "", rbac::RBAC_PERM_COMMAND_LEARN, false, &HandleLearnCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "", rbac::RBAC_PERM_COMMAND_LEARN, false, &HandleLearnCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "learn", rbac::RBAC_PERM_COMMAND_LEARN, false, NULL, "", learnCommandTable }, - { "unlearn", rbac::RBAC_PERM_COMMAND_UNLEARN, false, &HandleUnLearnCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "unlearn", rbac::RBAC_PERM_COMMAND_UNLEARN, false, &HandleUnLearnCommand, "" }, }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_lfg.cpp b/src/server/scripts/Commands/cs_lfg.cpp index d1662f3a97c..9287d5553e3 100644 --- a/src/server/scripts/Commands/cs_lfg.cpp +++ b/src/server/scripts/Commands/cs_lfg.cpp @@ -43,22 +43,20 @@ class lfg_commandscript : public CommandScript public: lfg_commandscript() : CommandScript("lfg_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand lfgCommandTable[] = + static std::vector<ChatCommand> lfgCommandTable = { - { "player", rbac::RBAC_PERM_COMMAND_LFG_PLAYER, false, &HandleLfgPlayerInfoCommand, "", NULL }, - { "group", rbac::RBAC_PERM_COMMAND_LFG_GROUP, false, &HandleLfgGroupInfoCommand, "", NULL }, - { "queue", rbac::RBAC_PERM_COMMAND_LFG_QUEUE, true, &HandleLfgQueueInfoCommand, "", NULL }, - { "clean", rbac::RBAC_PERM_COMMAND_LFG_CLEAN, true, &HandleLfgCleanCommand, "", NULL }, - { "options", rbac::RBAC_PERM_COMMAND_LFG_OPTIONS, true, &HandleLfgOptionsCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "player", rbac::RBAC_PERM_COMMAND_LFG_PLAYER, false, &HandleLfgPlayerInfoCommand, "" }, + { "group", rbac::RBAC_PERM_COMMAND_LFG_GROUP, false, &HandleLfgGroupInfoCommand, "" }, + { "queue", rbac::RBAC_PERM_COMMAND_LFG_QUEUE, true, &HandleLfgQueueInfoCommand, "" }, + { "clean", rbac::RBAC_PERM_COMMAND_LFG_CLEAN, true, &HandleLfgCleanCommand, "" }, + { "options", rbac::RBAC_PERM_COMMAND_LFG_OPTIONS, true, &HandleLfgOptionsCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "lfg", rbac::RBAC_PERM_COMMAND_LFG, true, NULL, "", lfgCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -80,7 +78,7 @@ public: ObjectGuid guidTarget; std::string nameTarget; - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); + ObjectGuid parseGUID(HighGuid::Player, uint32(atoul(args))); if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) { @@ -150,7 +148,7 @@ public: static bool HandleLfgQueueInfoCommand(ChatHandler* handler, char const* args) { - handler->SendSysMessage(sLFGMgr->DumpQueueInfo(*args != '\0').c_str()); + handler->SendSysMessage(sLFGMgr->DumpQueueInfo(*args != '\0').c_str(), true); return true; } diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index 39ad786cf83..a1b79a69605 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -36,21 +36,19 @@ class list_commandscript : public CommandScript public: list_commandscript() : CommandScript("list_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand listCommandTable[] = + static std::vector<ChatCommand> listCommandTable = { - { "creature", rbac::RBAC_PERM_COMMAND_LIST_CREATURE, true, &HandleListCreatureCommand, "", NULL }, - { "item", rbac::RBAC_PERM_COMMAND_LIST_ITEM, true, &HandleListItemCommand, "", NULL }, - { "object", rbac::RBAC_PERM_COMMAND_LIST_OBJECT, true, &HandleListObjectCommand, "", NULL }, - { "auras", rbac::RBAC_PERM_COMMAND_LIST_AURAS, false, &HandleListAurasCommand, "", NULL }, - { "mail", rbac::RBAC_PERM_COMMAND_LIST_MAIL, true, &HandleListMailCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "creature", rbac::RBAC_PERM_COMMAND_LIST_CREATURE, true, &HandleListCreatureCommand, "" }, + { "item", rbac::RBAC_PERM_COMMAND_LIST_ITEM, true, &HandleListItemCommand, "" }, + { "object", rbac::RBAC_PERM_COMMAND_LIST_OBJECT, true, &HandleListObjectCommand, "" }, + { "auras", rbac::RBAC_PERM_COMMAND_LIST_AURAS, false, &HandleListAurasCommand, "" }, + { "mail", rbac::RBAC_PERM_COMMAND_LIST_MAIL, true, &HandleListMailCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "list", rbac::RBAC_PERM_COMMAND_LIST,true, NULL, "", listCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -109,7 +107,7 @@ public: do { Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); + ObjectGuid::LowType guid = fields[0].GetUInt32(); float x = fields[1].GetFloat(); float y = fields[2].GetFloat(); float z = fields[3].GetFloat(); @@ -235,8 +233,8 @@ public: do { Field* fields = result->Fetch(); - uint32 itemGuid = fields[0].GetUInt32(); - uint32 itemSender = fields[1].GetUInt32(); + ObjectGuid::LowType itemGuid = fields[0].GetUInt32(); + ObjectGuid::LowType itemSender = fields[1].GetUInt32(); uint32 itemReceiver = fields[2].GetUInt32(); uint32 itemSenderAccountId = fields[3].GetUInt32(); std::string itemSenderName = fields[4].GetString(); @@ -398,7 +396,7 @@ public: do { Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); + ObjectGuid::LowType guid = fields[0].GetUInt32(); float x = fields[1].GetFloat(); float y = fields[2].GetFloat(); float z = fields[3].GetFloat(); @@ -476,7 +474,7 @@ public: if (!*args) return false; - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); + ObjectGuid parseGUID(HighGuid::Player, uint32(atoul(args))); if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) { @@ -500,7 +498,7 @@ public: stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_LIST_INFO); stmt->setUInt32(0, targetGuid.GetCounter()); - PreparedQueryResult queryResult = CharacterDatabase.Query(stmt); + queryResult = CharacterDatabase.Query(stmt); if (queryResult) { @@ -534,7 +532,7 @@ public: { do { - uint32 item_guid = (*result2)[0].GetUInt32(); + ObjectGuid::LowType item_guid = (*result2)[0].GetUInt32(); stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MAIL_LIST_ITEMS); stmt->setUInt32(0, item_guid); PreparedQueryResult result3 = CharacterDatabase.Query(stmt); diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index 56aa6d0bf92..ec35c5a7b62 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -37,47 +37,43 @@ class lookup_commandscript : public CommandScript public: lookup_commandscript() : CommandScript("lookup_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand lookupPlayerCommandTable[] = + static std::vector<ChatCommand> lookupPlayerCommandTable = { - { "ip", rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_IP, true, &HandleLookupPlayerIpCommand, "", NULL }, - { "account", rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_ACCOUNT, true, &HandleLookupPlayerAccountCommand, "", NULL }, - { "email", rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_EMAIL, true, &HandleLookupPlayerEmailCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "ip", rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_IP, true, &HandleLookupPlayerIpCommand, "" }, + { "account", rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_ACCOUNT, true, &HandleLookupPlayerAccountCommand, "" }, + { "email", rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER_EMAIL, true, &HandleLookupPlayerEmailCommand, "" }, }; - static ChatCommand lookupSpellCommandTable[] = + static std::vector<ChatCommand> lookupSpellCommandTable = { - { "id", rbac::RBAC_PERM_COMMAND_LOOKUP_SPELL_ID, true, &HandleLookupSpellIdCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_LOOKUP_SPELL, true, &HandleLookupSpellCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "id", rbac::RBAC_PERM_COMMAND_LOOKUP_SPELL_ID, true, &HandleLookupSpellIdCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_LOOKUP_SPELL, true, &HandleLookupSpellCommand, "" }, }; - static ChatCommand lookupCommandTable[] = + static std::vector<ChatCommand> lookupCommandTable = { - { "area", rbac::RBAC_PERM_COMMAND_LOOKUP_AREA, true, &HandleLookupAreaCommand, "", NULL }, - { "creature", rbac::RBAC_PERM_COMMAND_LOOKUP_CREATURE, true, &HandleLookupCreatureCommand, "", NULL }, - { "event", rbac::RBAC_PERM_COMMAND_LOOKUP_EVENT, true, &HandleLookupEventCommand, "", NULL }, - { "faction", rbac::RBAC_PERM_COMMAND_LOOKUP_FACTION, true, &HandleLookupFactionCommand, "", NULL }, - { "item", rbac::RBAC_PERM_COMMAND_LOOKUP_ITEM, true, &HandleLookupItemCommand, "", NULL }, - { "itemset", rbac::RBAC_PERM_COMMAND_LOOKUP_ITEMSET, true, &HandleLookupItemSetCommand, "", NULL }, - { "object", rbac::RBAC_PERM_COMMAND_LOOKUP_OBJECT, true, &HandleLookupObjectCommand, "", NULL }, - { "quest", rbac::RBAC_PERM_COMMAND_LOOKUP_QUEST, true, &HandleLookupQuestCommand, "", NULL }, + { "area", rbac::RBAC_PERM_COMMAND_LOOKUP_AREA, true, &HandleLookupAreaCommand, "" }, + { "creature", rbac::RBAC_PERM_COMMAND_LOOKUP_CREATURE, true, &HandleLookupCreatureCommand, "" }, + { "event", rbac::RBAC_PERM_COMMAND_LOOKUP_EVENT, true, &HandleLookupEventCommand, "" }, + { "faction", rbac::RBAC_PERM_COMMAND_LOOKUP_FACTION, true, &HandleLookupFactionCommand, "" }, + { "item", rbac::RBAC_PERM_COMMAND_LOOKUP_ITEM, true, &HandleLookupItemCommand, "" }, + { "itemset", rbac::RBAC_PERM_COMMAND_LOOKUP_ITEMSET, true, &HandleLookupItemSetCommand, "" }, + { "object", rbac::RBAC_PERM_COMMAND_LOOKUP_OBJECT, true, &HandleLookupObjectCommand, "" }, + { "quest", rbac::RBAC_PERM_COMMAND_LOOKUP_QUEST, true, &HandleLookupQuestCommand, "" }, { "player", rbac::RBAC_PERM_COMMAND_LOOKUP_PLAYER, true, NULL, "", lookupPlayerCommandTable }, - { "skill", rbac::RBAC_PERM_COMMAND_LOOKUP_SKILL, true, &HandleLookupSkillCommand, "", NULL }, + { "skill", rbac::RBAC_PERM_COMMAND_LOOKUP_SKILL, true, &HandleLookupSkillCommand, "" }, { "spell", rbac::RBAC_PERM_COMMAND_LOOKUP_SPELL, true, NULL, "", lookupSpellCommandTable }, - { "taxinode", rbac::RBAC_PERM_COMMAND_LOOKUP_TAXINODE, true, &HandleLookupTaxiNodeCommand, "", NULL }, - { "tele", rbac::RBAC_PERM_COMMAND_LOOKUP_TELE, true, &HandleLookupTeleCommand, "", NULL }, - { "title", rbac::RBAC_PERM_COMMAND_LOOKUP_TITLE, true, &HandleLookupTitleCommand, "", NULL }, - { "map", rbac::RBAC_PERM_COMMAND_LOOKUP_MAP, true, &HandleLookupMapCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "taxinode", rbac::RBAC_PERM_COMMAND_LOOKUP_TAXINODE, true, &HandleLookupTaxiNodeCommand, "" }, + { "tele", rbac::RBAC_PERM_COMMAND_LOOKUP_TELE, true, &HandleLookupTeleCommand, "" }, + { "title", rbac::RBAC_PERM_COMMAND_LOOKUP_TITLE, true, &HandleLookupTitleCommand, "" }, + { "map", rbac::RBAC_PERM_COMMAND_LOOKUP_MAP, true, &HandleLookupMapCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "lookup", rbac::RBAC_PERM_COMMAND_LOOKUP, true, NULL, "", lookupCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -1410,7 +1406,7 @@ public: do { Field* characterFields = result2->Fetch(); - uint32 guid = characterFields[0].GetUInt32(); + ObjectGuid::LowType guid = characterFields[0].GetUInt32(); std::string name = characterFields[1].GetString(); handler->PSendSysMessage(LANG_LOOKUP_PLAYER_CHARACTER, name.c_str(), guid); diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index 922958f7222..f3c1f4d7df8 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -34,29 +34,26 @@ class message_commandscript : public CommandScript public: message_commandscript() : CommandScript("message_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand channelSetCommandTable[] = + static std::vector<ChatCommand> channelSetCommandTable = { - { "ownership", rbac::RBAC_PERM_COMMAND_CHANNEL_SET_OWNERSHIP, false, &HandleChannelSetOwnership, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "ownership", rbac::RBAC_PERM_COMMAND_CHANNEL_SET_OWNERSHIP, false, &HandleChannelSetOwnership, "" }, }; - static ChatCommand channelCommandTable[] = + static std::vector<ChatCommand> channelCommandTable = { { "set", rbac::RBAC_PERM_COMMAND_CHANNEL_SET, true, NULL, "", channelSetCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "channel", rbac::RBAC_PERM_COMMAND_CHANNEL, true, NULL, "", channelCommandTable }, - { "nameannounce", rbac::RBAC_PERM_COMMAND_NAMEANNOUNCE, true, &HandleNameAnnounceCommand, "", NULL }, - { "gmnameannounce", rbac::RBAC_PERM_COMMAND_GMNAMEANNOUNCE, true, &HandleGMNameAnnounceCommand, "", NULL }, - { "announce", rbac::RBAC_PERM_COMMAND_ANNOUNCE, true, &HandleAnnounceCommand, "", NULL }, - { "gmannounce", rbac::RBAC_PERM_COMMAND_GMANNOUNCE, true, &HandleGMAnnounceCommand, "", NULL }, - { "notify", rbac::RBAC_PERM_COMMAND_NOTIFY, true, &HandleNotifyCommand, "", NULL }, - { "gmnotify", rbac::RBAC_PERM_COMMAND_GMNOTIFY, true, &HandleGMNotifyCommand, "", NULL }, - { "whispers", rbac::RBAC_PERM_COMMAND_WHISPERS, false, &HandleWhispersCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "nameannounce", rbac::RBAC_PERM_COMMAND_NAMEANNOUNCE, true, &HandleNameAnnounceCommand, "" }, + { "gmnameannounce", rbac::RBAC_PERM_COMMAND_GMNAMEANNOUNCE, true, &HandleGMNameAnnounceCommand, "" }, + { "announce", rbac::RBAC_PERM_COMMAND_ANNOUNCE, true, &HandleAnnounceCommand, "" }, + { "gmannounce", rbac::RBAC_PERM_COMMAND_GMANNOUNCE, true, &HandleGMAnnounceCommand, "" }, + { "notify", rbac::RBAC_PERM_COMMAND_NOTIFY, true, &HandleNotifyCommand, "" }, + { "gmnotify", rbac::RBAC_PERM_COMMAND_GMNOTIFY, true, &HandleGMNotifyCommand, "" }, + { "whispers", rbac::RBAC_PERM_COMMAND_WHISPERS, false, &HandleWhispersCommand, "" }, }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index c8a908f6930..b81d6152c03 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -42,62 +42,61 @@ class misc_commandscript : public CommandScript public: misc_commandscript() : CommandScript("misc_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand commandTable[] = - { - { "additem", rbac::RBAC_PERM_COMMAND_ADDITEM, false, &HandleAddItemCommand, "", NULL }, - { "additemset", rbac::RBAC_PERM_COMMAND_ADDITEMSET, false, &HandleAddItemSetCommand, "", NULL }, - { "appear", rbac::RBAC_PERM_COMMAND_APPEAR, false, &HandleAppearCommand, "", NULL }, - { "aura", rbac::RBAC_PERM_COMMAND_AURA, false, &HandleAuraCommand, "", NULL }, - { "bank", rbac::RBAC_PERM_COMMAND_BANK, false, &HandleBankCommand, "", NULL }, - { "bindsight", rbac::RBAC_PERM_COMMAND_BINDSIGHT, false, &HandleBindSightCommand, "", NULL }, - { "combatstop", rbac::RBAC_PERM_COMMAND_COMBATSTOP, true, &HandleCombatStopCommand, "", NULL }, - { "cometome", rbac::RBAC_PERM_COMMAND_COMETOME, false, &HandleComeToMeCommand, "", NULL }, - { "commands", rbac::RBAC_PERM_COMMAND_COMMANDS, true, &HandleCommandsCommand, "", NULL }, - { "cooldown", rbac::RBAC_PERM_COMMAND_COOLDOWN, false, &HandleCooldownCommand, "", NULL }, - { "damage", rbac::RBAC_PERM_COMMAND_DAMAGE, false, &HandleDamageCommand, "", NULL }, - { "dev", rbac::RBAC_PERM_COMMAND_DEV, false, &HandleDevCommand, "", NULL }, - { "die", rbac::RBAC_PERM_COMMAND_DIE, false, &HandleDieCommand, "", NULL }, - { "dismount", rbac::RBAC_PERM_COMMAND_DISMOUNT, false, &HandleDismountCommand, "", NULL }, - { "distance", rbac::RBAC_PERM_COMMAND_DISTANCE, false, &HandleGetDistanceCommand, "", NULL }, - { "flusharenapoints", rbac::RBAC_PERM_COMMAND_FLUSHARENAPOINTS, false, &HandleFlushArenaPointsCommand, "", NULL }, - { "freeze", rbac::RBAC_PERM_COMMAND_FREEZE, false, &HandleFreezeCommand, "", NULL }, - { "gps", rbac::RBAC_PERM_COMMAND_GPS, false, &HandleGPSCommand, "", NULL }, - { "guid", rbac::RBAC_PERM_COMMAND_GUID, false, &HandleGUIDCommand, "", NULL }, - { "help", rbac::RBAC_PERM_COMMAND_HELP, true, &HandleHelpCommand, "", NULL }, - { "hidearea", rbac::RBAC_PERM_COMMAND_HIDEAREA, false, &HandleHideAreaCommand, "", NULL }, - { "itemmove", rbac::RBAC_PERM_COMMAND_ITEMMOVE, false, &HandleItemMoveCommand, "", NULL }, - { "kick", rbac::RBAC_PERM_COMMAND_KICK, true, &HandleKickPlayerCommand, "", NULL }, - { "linkgrave", rbac::RBAC_PERM_COMMAND_LINKGRAVE, false, &HandleLinkGraveCommand, "", NULL }, - { "listfreeze", rbac::RBAC_PERM_COMMAND_LISTFREEZE, false, &HandleListFreezeCommand, "", NULL }, - { "maxskill", rbac::RBAC_PERM_COMMAND_MAXSKILL, false, &HandleMaxSkillCommand, "", NULL }, - { "movegens", rbac::RBAC_PERM_COMMAND_MOVEGENS, false, &HandleMovegensCommand, "", NULL }, - { "mute", rbac::RBAC_PERM_COMMAND_MUTE, true, &HandleMuteCommand, "", NULL }, - { "mutehistory", rbac::RBAC_PERM_COMMAND_MUTEHISTORY, true, &HandleMuteInfoCommand, "", NULL }, - { "neargrave", rbac::RBAC_PERM_COMMAND_NEARGRAVE, false, &HandleNearGraveCommand, "", NULL }, - { "pinfo", rbac::RBAC_PERM_COMMAND_PINFO, true, &HandlePInfoCommand, "", NULL }, - { "playall", rbac::RBAC_PERM_COMMAND_PLAYALL, false, &HandlePlayAllCommand, "", NULL }, - { "possess", rbac::RBAC_PERM_COMMAND_POSSESS, false, &HandlePossessCommand, "", NULL }, - { "pvpstats", rbac::RBAC_PERM_COMMAND_PVPSTATS, true, &HandlePvPstatsCommand, "", NULL }, - { "recall", rbac::RBAC_PERM_COMMAND_RECALL, false, &HandleRecallCommand, "", NULL }, - { "repairitems", rbac::RBAC_PERM_COMMAND_REPAIRITEMS, true, &HandleRepairitemsCommand, "", NULL }, - { "respawn", rbac::RBAC_PERM_COMMAND_RESPAWN, false, &HandleRespawnCommand, "", NULL }, - { "revive", rbac::RBAC_PERM_COMMAND_REVIVE, true, &HandleReviveCommand, "", NULL }, - { "saveall", rbac::RBAC_PERM_COMMAND_SAVEALL, true, &HandleSaveAllCommand, "", NULL }, - { "save", rbac::RBAC_PERM_COMMAND_SAVE, false, &HandleSaveCommand, "", NULL }, - { "setskill", rbac::RBAC_PERM_COMMAND_SETSKILL, false, &HandleSetSkillCommand, "", NULL }, - { "showarea", rbac::RBAC_PERM_COMMAND_SHOWAREA, false, &HandleShowAreaCommand, "", NULL }, - { "summon", rbac::RBAC_PERM_COMMAND_SUMMON, false, &HandleSummonCommand, "", NULL }, - { "unaura", rbac::RBAC_PERM_COMMAND_UNAURA, false, &HandleUnAuraCommand, "", NULL }, - { "unbindsight", rbac::RBAC_PERM_COMMAND_UNBINDSIGHT, false, HandleUnbindSightCommand, "", NULL }, - { "unfreeze", rbac::RBAC_PERM_COMMAND_UNFREEZE, false, &HandleUnFreezeCommand, "", NULL }, - { "unmute", rbac::RBAC_PERM_COMMAND_UNMUTE, true, &HandleUnmuteCommand, "", NULL }, - { "unpossess", rbac::RBAC_PERM_COMMAND_UNPOSSESS, false, &HandleUnPossessCommand, "", NULL }, - { "unstuck", rbac::RBAC_PERM_COMMAND_UNSTUCK, true, &HandleUnstuckCommand, "", NULL }, - { "wchange", rbac::RBAC_PERM_COMMAND_WCHANGE, false, &HandleChangeWeather, "", NULL }, - { "mailbox", rbac::RBAC_PERM_COMMAND_MAILBOX, false, &HandleMailBoxCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + static std::vector<ChatCommand> commandTable = + { + { "additem", rbac::RBAC_PERM_COMMAND_ADDITEM, false, &HandleAddItemCommand, "" }, + { "additemset", rbac::RBAC_PERM_COMMAND_ADDITEMSET, false, &HandleAddItemSetCommand, "" }, + { "appear", rbac::RBAC_PERM_COMMAND_APPEAR, false, &HandleAppearCommand, "" }, + { "aura", rbac::RBAC_PERM_COMMAND_AURA, false, &HandleAuraCommand, "" }, + { "bank", rbac::RBAC_PERM_COMMAND_BANK, false, &HandleBankCommand, "" }, + { "bindsight", rbac::RBAC_PERM_COMMAND_BINDSIGHT, false, &HandleBindSightCommand, "" }, + { "combatstop", rbac::RBAC_PERM_COMMAND_COMBATSTOP, true, &HandleCombatStopCommand, "" }, + { "cometome", rbac::RBAC_PERM_COMMAND_COMETOME, false, &HandleComeToMeCommand, "" }, + { "commands", rbac::RBAC_PERM_COMMAND_COMMANDS, true, &HandleCommandsCommand, "" }, + { "cooldown", rbac::RBAC_PERM_COMMAND_COOLDOWN, false, &HandleCooldownCommand, "" }, + { "damage", rbac::RBAC_PERM_COMMAND_DAMAGE, false, &HandleDamageCommand, "" }, + { "dev", rbac::RBAC_PERM_COMMAND_DEV, false, &HandleDevCommand, "" }, + { "die", rbac::RBAC_PERM_COMMAND_DIE, false, &HandleDieCommand, "" }, + { "dismount", rbac::RBAC_PERM_COMMAND_DISMOUNT, false, &HandleDismountCommand, "" }, + { "distance", rbac::RBAC_PERM_COMMAND_DISTANCE, false, &HandleGetDistanceCommand, "" }, + { "flusharenapoints", rbac::RBAC_PERM_COMMAND_FLUSHARENAPOINTS, false, &HandleFlushArenaPointsCommand, "" }, + { "freeze", rbac::RBAC_PERM_COMMAND_FREEZE, false, &HandleFreezeCommand, "" }, + { "gps", rbac::RBAC_PERM_COMMAND_GPS, false, &HandleGPSCommand, "" }, + { "guid", rbac::RBAC_PERM_COMMAND_GUID, false, &HandleGUIDCommand, "" }, + { "help", rbac::RBAC_PERM_COMMAND_HELP, true, &HandleHelpCommand, "" }, + { "hidearea", rbac::RBAC_PERM_COMMAND_HIDEAREA, false, &HandleHideAreaCommand, "" }, + { "itemmove", rbac::RBAC_PERM_COMMAND_ITEMMOVE, false, &HandleItemMoveCommand, "" }, + { "kick", rbac::RBAC_PERM_COMMAND_KICK, true, &HandleKickPlayerCommand, "" }, + { "linkgrave", rbac::RBAC_PERM_COMMAND_LINKGRAVE, false, &HandleLinkGraveCommand, "" }, + { "listfreeze", rbac::RBAC_PERM_COMMAND_LISTFREEZE, false, &HandleListFreezeCommand, "" }, + { "maxskill", rbac::RBAC_PERM_COMMAND_MAXSKILL, false, &HandleMaxSkillCommand, "" }, + { "movegens", rbac::RBAC_PERM_COMMAND_MOVEGENS, false, &HandleMovegensCommand, "" }, + { "mute", rbac::RBAC_PERM_COMMAND_MUTE, true, &HandleMuteCommand, "" }, + { "mutehistory", rbac::RBAC_PERM_COMMAND_MUTEHISTORY, true, &HandleMuteInfoCommand, "" }, + { "neargrave", rbac::RBAC_PERM_COMMAND_NEARGRAVE, false, &HandleNearGraveCommand, "" }, + { "pinfo", rbac::RBAC_PERM_COMMAND_PINFO, true, &HandlePInfoCommand, "" }, + { "playall", rbac::RBAC_PERM_COMMAND_PLAYALL, false, &HandlePlayAllCommand, "" }, + { "possess", rbac::RBAC_PERM_COMMAND_POSSESS, false, &HandlePossessCommand, "" }, + { "pvpstats", rbac::RBAC_PERM_COMMAND_PVPSTATS, true, &HandlePvPstatsCommand, "" }, + { "recall", rbac::RBAC_PERM_COMMAND_RECALL, false, &HandleRecallCommand, "" }, + { "repairitems", rbac::RBAC_PERM_COMMAND_REPAIRITEMS, true, &HandleRepairitemsCommand, "" }, + { "respawn", rbac::RBAC_PERM_COMMAND_RESPAWN, false, &HandleRespawnCommand, "" }, + { "revive", rbac::RBAC_PERM_COMMAND_REVIVE, true, &HandleReviveCommand, "" }, + { "saveall", rbac::RBAC_PERM_COMMAND_SAVEALL, true, &HandleSaveAllCommand, "" }, + { "save", rbac::RBAC_PERM_COMMAND_SAVE, false, &HandleSaveCommand, "" }, + { "setskill", rbac::RBAC_PERM_COMMAND_SETSKILL, false, &HandleSetSkillCommand, "" }, + { "showarea", rbac::RBAC_PERM_COMMAND_SHOWAREA, false, &HandleShowAreaCommand, "" }, + { "summon", rbac::RBAC_PERM_COMMAND_SUMMON, false, &HandleSummonCommand, "" }, + { "unaura", rbac::RBAC_PERM_COMMAND_UNAURA, false, &HandleUnAuraCommand, "" }, + { "unbindsight", rbac::RBAC_PERM_COMMAND_UNBINDSIGHT, false, HandleUnbindSightCommand, "" }, + { "unfreeze", rbac::RBAC_PERM_COMMAND_UNFREEZE, false, &HandleUnFreezeCommand, "" }, + { "unmute", rbac::RBAC_PERM_COMMAND_UNMUTE, true, &HandleUnmuteCommand, "" }, + { "unpossess", rbac::RBAC_PERM_COMMAND_UNPOSSESS, false, &HandleUnPossessCommand, "" }, + { "unstuck", rbac::RBAC_PERM_COMMAND_UNSTUCK, true, &HandleUnstuckCommand, "" }, + { "wchange", rbac::RBAC_PERM_COMMAND_WCHANGE, false, &HandleChangeWeather, "" }, + { "mailbox", rbac::RBAC_PERM_COMMAND_MAILBOX, false, &HandleMailBoxCommand, "" }, }; return commandTable; } @@ -600,8 +599,10 @@ public: target->SaveToDB(); } else - // will resurrected at login without corpse - sObjectAccessor->ConvertCorpseForPlayer(targetGuid); + { + SQLTransaction trans(nullptr); + Player::OfflineResurrect(targetGuid, trans); + } return true; } @@ -641,7 +642,7 @@ public: return false; } - handler->PSendSysMessage(LANG_OBJECT_GUID, guid.GetCounter(), guid.GetHigh()); + handler->PSendSysMessage(LANG_OBJECT_GUID, guid.ToString().c_str()); return true; } @@ -820,7 +821,7 @@ public: // Save all players in the world static bool HandleSaveAllCommand(ChatHandler* handler, char const* /*args*/) { - sObjectAccessor->SaveAllPlayers(); + ObjectAccessor::SaveAllPlayers(); handler->SendSysMessage(LANG_PLAYERS_SAVED); return true; } @@ -1325,8 +1326,8 @@ public: static bool HandleMaxSkillCommand(ChatHandler* handler, char const* /*args*/) { - Player* SelectedPlayer = handler->getSelectedPlayer(); - if (!SelectedPlayer) + Player* player = handler->getSelectedPlayerOrSelf(); + if (!player) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); handler->SetSentErrorMessage(true); @@ -1334,7 +1335,7 @@ public: } // each skills that have max skill value dependent from level seted to current level max skill value - SelectedPlayer->UpdateSkillsToMaxSkillsForLevel(); + player->UpdateSkillsToMaxSkillsForLevel(); return true; } @@ -1421,7 +1422,7 @@ public: PreparedStatement* stmt = NULL; // To make sure we get a target, we convert our guid to an omniversal... - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); + ObjectGuid parseGUID(HighGuid::Player, uint32(atoul(args))); // ... and make sure we get a target, somehow. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) @@ -1468,7 +1469,7 @@ public: // Account data print variables std::string userName = handler->GetTrinityString(LANG_ERROR); uint32 accId = 0; - uint32 lowguid = targetGuid.GetCounter(); + ObjectGuid::LowType lowguid = targetGuid.GetCounter(); std::string eMail = handler->GetTrinityString(LANG_ERROR); std::string regMail = handler->GetTrinityString(LANG_ERROR); uint32 security = 0; @@ -1657,7 +1658,7 @@ public: { Field* fields = result4->Fetch(); xp = fields[0].GetUInt32(); // Used for "current xp" output and "%u XP Left" calculation - uint32 gguid = fields[1].GetUInt32(); // We check if have a guild for the person, so we might not require to query it at all + ObjectGuid::LowType gguid = fields[1].GetUInt32(); // We check if have a guild for the person, so we might not require to query it at all xptotal = sObjectMgr->GetXPForLevel(level); if (gguid != 0) @@ -1772,21 +1773,13 @@ public: PreparedQueryResult result6 = CharacterDatabase.Query(stmt4); if (result6) { - // Define the variables, so the compiler knows they exist - uint32 rmailint = 0; - - // Fetch the fields - readmail is a SUM(x) and given out as char! Thus... - // ... while totalmail is a COUNT(x), which is given out as INt64, which we just convert on fetch... Field* fields = result6->Fetch(); - std::string readmail = fields[0].GetString(); + uint32 readmail = uint32(fields[0].GetDouble()); uint32 totalmail = uint32(fields[1].GetUInt64()); - // ... we have to convert it from Char to int. We can use totalmail as it is - rmailint = atoul(readmail.c_str()); - // Output XXI. LANG_INFO_CHR_MAILS if at least one mail is given if (totalmail >= 1) - handler->PSendSysMessage(LANG_PINFO_CHR_MAILS, rmailint, totalmail); + handler->PSendSysMessage(LANG_PINFO_CHR_MAILS, readmail, totalmail); } return true; @@ -2018,7 +2011,7 @@ public: return false; } - handler->PSendSysMessage(LANG_MOVEGENS_LIST, (unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), unit->GetGUIDLow()); + handler->PSendSysMessage(LANG_MOVEGENS_LIST, (unit->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), unit->GetGUID().GetCounter()); MotionMaster* motionMaster = unit->GetMotionMaster(); float x, y, z; @@ -2061,9 +2054,9 @@ public: if (!target) handler->SendSysMessage(LANG_MOVEGENS_CHASE_NULL); else if (target->GetTypeId() == TYPEID_PLAYER) - handler->PSendSysMessage(LANG_MOVEGENS_CHASE_PLAYER, target->GetName().c_str(), target->GetGUIDLow()); + handler->PSendSysMessage(LANG_MOVEGENS_CHASE_PLAYER, target->GetName().c_str(), target->GetGUID().GetCounter()); else - handler->PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, target->GetName().c_str(), target->GetGUIDLow()); + handler->PSendSysMessage(LANG_MOVEGENS_CHASE_CREATURE, target->GetName().c_str(), target->GetGUID().GetCounter()); break; } case FOLLOW_MOTION_TYPE: @@ -2077,9 +2070,9 @@ public: if (!target) handler->SendSysMessage(LANG_MOVEGENS_FOLLOW_NULL); else if (target->GetTypeId() == TYPEID_PLAYER) - handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_PLAYER, target->GetName().c_str(), target->GetGUIDLow()); + handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_PLAYER, target->GetName().c_str(), target->GetGUID().GetCounter()); else - handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, target->GetName().c_str(), target->GetGUIDLow()); + handler->PSendSysMessage(LANG_MOVEGENS_FOLLOW_CREATURE, target->GetName().c_str(), target->GetGUID().GetCounter()); break; } case HOME_MOTION_TYPE: @@ -2485,7 +2478,7 @@ public: // If player found: delete his freeze aura Field* fields = result->Fetch(); - uint32 lowGuid = fields[0].GetUInt32(); + ObjectGuid::LowType lowGuid = fields[0].GetUInt32(); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA_FROZEN); stmt->setUInt32(0, lowGuid); diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 14623e591c1..479c34dd90c 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -42,22 +42,20 @@ class mmaps_commandscript : public CommandScript public: mmaps_commandscript() : CommandScript("mmaps_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand mmapCommandTable[] = + static std::vector<ChatCommand> mmapCommandTable = { - { "loadedtiles", rbac::RBAC_PERM_COMMAND_MMAP_LOADEDTILES, false, &HandleMmapLoadedTilesCommand, "", NULL }, - { "loc", rbac::RBAC_PERM_COMMAND_MMAP_LOC, false, &HandleMmapLocCommand, "", NULL }, - { "path", rbac::RBAC_PERM_COMMAND_MMAP_PATH, false, &HandleMmapPathCommand, "", NULL }, - { "stats", rbac::RBAC_PERM_COMMAND_MMAP_STATS, false, &HandleMmapStatsCommand, "", NULL }, - { "testarea", rbac::RBAC_PERM_COMMAND_MMAP_TESTAREA, false, &HandleMmapTestArea, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "loadedtiles", rbac::RBAC_PERM_COMMAND_MMAP_LOADEDTILES, false, &HandleMmapLoadedTilesCommand, "" }, + { "loc", rbac::RBAC_PERM_COMMAND_MMAP_LOC, false, &HandleMmapLocCommand, "" }, + { "path", rbac::RBAC_PERM_COMMAND_MMAP_PATH, false, &HandleMmapPathCommand, "" }, + { "stats", rbac::RBAC_PERM_COMMAND_MMAP_STATS, false, &HandleMmapStatsCommand, "" }, + { "testarea", rbac::RBAC_PERM_COMMAND_MMAP_TESTAREA, false, &HandleMmapTestArea, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { - { "mmap", rbac::RBAC_PERM_COMMAND_MMAP, true, NULL, "", mmapCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "mmap", rbac::RBAC_PERM_COMMAND_MMAP, true, NULL, "", mmapCommandTable }, }; return commandTable; } @@ -87,6 +85,10 @@ public: if (para && strcmp(para, "true") == 0) useStraightPath = true; + bool useStraightLine = false; + if (para && strcmp(para, "line") == 0) + useStraightLine = true; + // unit locations float x, y, z; player->GetPosition(x, y, z); @@ -94,11 +96,11 @@ public: // path PathGenerator path(target); path.SetUseStraightPath(useStraightPath); - bool result = path.CalculatePath(x, y, z); + bool result = path.CalculatePath(x, y, z, false, useStraightLine); Movement::PointsArray const& pointPath = path.GetPath(); handler->PSendSysMessage("%s's path to %s:", target->GetName().c_str(), player->GetName().c_str()); - handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); + handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : useStraightLine ? "Raycast" : "SmoothPath"); handler->PSendSysMessage("Result: %s - Length: %zu - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); G3D::Vector3 const &start = path.GetStartPosition(); diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index 54d1f314140..a3eed4dfd5d 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -36,49 +36,46 @@ class modify_commandscript : public CommandScript public: modify_commandscript() : CommandScript("modify_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand modifyspeedCommandTable[] = + static std::vector<ChatCommand> modifyspeedCommandTable = { - { "all", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_ALL, false, &HandleModifyASpeedCommand, "", NULL }, - { "backwalk", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_BACKWALK, false, &HandleModifyBWalkCommand, "", NULL }, - { "fly", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_FLY, false, &HandleModifyFlyCommand, "", NULL }, - { "walk", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_WALK, false, &HandleModifySpeedCommand, "", NULL }, - { "swim", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_SWIM, false, &HandleModifySwimCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED, false, &HandleModifyASpeedCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "all", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_ALL, false, &HandleModifyASpeedCommand, "" }, + { "backwalk", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_BACKWALK, false, &HandleModifyBWalkCommand, "" }, + { "fly", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_FLY, false, &HandleModifyFlyCommand, "" }, + { "walk", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_WALK, false, &HandleModifySpeedCommand, "" }, + { "swim", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED_SWIM, false, &HandleModifySwimCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED, false, &HandleModifyASpeedCommand, "" }, }; - static ChatCommand modifyCommandTable[] = + static std::vector<ChatCommand> modifyCommandTable = { - { "arenapoints", rbac::RBAC_PERM_COMMAND_MODIFY_ARENAPOINTS, false, &HandleModifyArenaCommand, "", NULL }, - { "bit", rbac::RBAC_PERM_COMMAND_MODIFY_BIT, false, &HandleModifyBitCommand, "", NULL }, - { "drunk", rbac::RBAC_PERM_COMMAND_MODIFY_DRUNK, false, &HandleModifyDrunkCommand, "", NULL }, - { "energy", rbac::RBAC_PERM_COMMAND_MODIFY_ENERGY, false, &HandleModifyEnergyCommand, "", NULL }, - { "faction", rbac::RBAC_PERM_COMMAND_MODIFY_FACTION, false, &HandleModifyFactionCommand, "", NULL }, - { "gender", rbac::RBAC_PERM_COMMAND_MODIFY_GENDER, false, &HandleModifyGenderCommand, "", NULL }, - { "honor", rbac::RBAC_PERM_COMMAND_MODIFY_HONOR, false, &HandleModifyHonorCommand, "", NULL }, - { "hp", rbac::RBAC_PERM_COMMAND_MODIFY_HP, false, &HandleModifyHPCommand, "", NULL }, - { "mana", rbac::RBAC_PERM_COMMAND_MODIFY_MANA, false, &HandleModifyManaCommand, "", NULL }, - { "money", rbac::RBAC_PERM_COMMAND_MODIFY_MONEY, false, &HandleModifyMoneyCommand, "", NULL }, - { "mount", rbac::RBAC_PERM_COMMAND_MODIFY_MOUNT, false, &HandleModifyMountCommand, "", NULL }, - { "phase", rbac::RBAC_PERM_COMMAND_MODIFY_PHASE, false, &HandleModifyPhaseCommand, "", NULL }, - { "rage", rbac::RBAC_PERM_COMMAND_MODIFY_RAGE, false, &HandleModifyRageCommand, "", NULL }, - { "reputation", rbac::RBAC_PERM_COMMAND_MODIFY_REPUTATION, false, &HandleModifyRepCommand, "", NULL }, - { "runicpower", rbac::RBAC_PERM_COMMAND_MODIFY_RUNICPOWER, false, &HandleModifyRunicPowerCommand, "", NULL }, - { "scale", rbac::RBAC_PERM_COMMAND_MODIFY_SCALE, false, &HandleModifyScaleCommand, "", NULL }, + { "arenapoints", rbac::RBAC_PERM_COMMAND_MODIFY_ARENAPOINTS, false, &HandleModifyArenaCommand, "" }, + { "bit", rbac::RBAC_PERM_COMMAND_MODIFY_BIT, false, &HandleModifyBitCommand, "" }, + { "drunk", rbac::RBAC_PERM_COMMAND_MODIFY_DRUNK, false, &HandleModifyDrunkCommand, "" }, + { "energy", rbac::RBAC_PERM_COMMAND_MODIFY_ENERGY, false, &HandleModifyEnergyCommand, "" }, + { "faction", rbac::RBAC_PERM_COMMAND_MODIFY_FACTION, false, &HandleModifyFactionCommand, "" }, + { "gender", rbac::RBAC_PERM_COMMAND_MODIFY_GENDER, false, &HandleModifyGenderCommand, "" }, + { "honor", rbac::RBAC_PERM_COMMAND_MODIFY_HONOR, false, &HandleModifyHonorCommand, "" }, + { "hp", rbac::RBAC_PERM_COMMAND_MODIFY_HP, false, &HandleModifyHPCommand, "" }, + { "mana", rbac::RBAC_PERM_COMMAND_MODIFY_MANA, false, &HandleModifyManaCommand, "" }, + { "money", rbac::RBAC_PERM_COMMAND_MODIFY_MONEY, false, &HandleModifyMoneyCommand, "" }, + { "mount", rbac::RBAC_PERM_COMMAND_MODIFY_MOUNT, false, &HandleModifyMountCommand, "" }, + { "phase", rbac::RBAC_PERM_COMMAND_MODIFY_PHASE, false, &HandleModifyPhaseCommand, "" }, + { "rage", rbac::RBAC_PERM_COMMAND_MODIFY_RAGE, false, &HandleModifyRageCommand, "" }, + { "reputation", rbac::RBAC_PERM_COMMAND_MODIFY_REPUTATION, false, &HandleModifyRepCommand, "" }, + { "runicpower", rbac::RBAC_PERM_COMMAND_MODIFY_RUNICPOWER, false, &HandleModifyRunicPowerCommand, "" }, + { "scale", rbac::RBAC_PERM_COMMAND_MODIFY_SCALE, false, &HandleModifyScaleCommand, "" }, { "speed", rbac::RBAC_PERM_COMMAND_MODIFY_SPEED, false, NULL, "", modifyspeedCommandTable }, - { "spell", rbac::RBAC_PERM_COMMAND_MODIFY_SPELL, false, &HandleModifySpellCommand, "", NULL }, - { "standstate", rbac::RBAC_PERM_COMMAND_MODIFY_STANDSTATE, false, &HandleModifyStandStateCommand, "", NULL }, - { "talentpoints", rbac::RBAC_PERM_COMMAND_MODIFY_TALENTPOINTS, false, &HandleModifyTalentCommand, "", NULL }, - { "xp", rbac::RBAC_PERM_COMMAND_MODIFY_XP, false, &HandleModifyXPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "spell", rbac::RBAC_PERM_COMMAND_MODIFY_SPELL, false, &HandleModifySpellCommand, "" }, + { "standstate", rbac::RBAC_PERM_COMMAND_MODIFY_STANDSTATE, false, &HandleModifyStandStateCommand, "" }, + { "talentpoints", rbac::RBAC_PERM_COMMAND_MODIFY_TALENTPOINTS, false, &HandleModifyTalentCommand, "" }, + { "xp", rbac::RBAC_PERM_COMMAND_MODIFY_XP, false, &HandleModifyXPCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { - { "morph", rbac::RBAC_PERM_COMMAND_MORPH, false, &HandleModifyMorphCommand, "", NULL }, - { "demorph", rbac::RBAC_PERM_COMMAND_DEMORPH, false, &HandleDeMorphCommand, "", NULL }, + { "morph", rbac::RBAC_PERM_COMMAND_MORPH, false, &HandleModifyMorphCommand, "" }, + { "demorph", rbac::RBAC_PERM_COMMAND_DEMORPH, false, &HandleDeMorphCommand, "" }, { "modify", rbac::RBAC_PERM_COMMAND_MODIFY, false, NULL, "", modifyCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -292,7 +289,7 @@ public: uint32 flag = target->GetUInt32Value(UNIT_FIELD_FLAGS); uint32 npcflag = target->GetUInt32Value(UNIT_NPC_FLAGS); uint32 dyflag = target->GetUInt32Value(UNIT_DYNAMIC_FLAGS); - handler->PSendSysMessage(LANG_CURRENT_FACTION, target->GetGUIDLow(), factionid, flag, npcflag, dyflag); + handler->PSendSysMessage(LANG_CURRENT_FACTION, target->GetGUID().GetCounter(), factionid, flag, npcflag, dyflag); return true; } @@ -328,7 +325,7 @@ public: return false; } - handler->PSendSysMessage(LANG_YOU_CHANGE_FACTION, target->GetGUIDLow(), factionid, flag, npcflag, dyflag); + handler->PSendSysMessage(LANG_YOU_CHANGE_FACTION, target->GetGUID().GetCounter(), factionid, flag, npcflag, dyflag); target->setFaction(factionid); target->SetUInt32Value(UNIT_FIELD_FLAGS, flag); @@ -421,7 +418,7 @@ public: target->ToPlayer()->SendTalentsInfoData(false); return true; } - else if (target->ToCreature()->IsPet()) + else if (target->IsPet()) { Unit* owner = target->GetOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER && ((Pet*)target)->IsPermanentPetFor(owner->ToPlayer())) diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 09a41fd82b5..99c10b074a0 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -170,69 +170,61 @@ class npc_commandscript : public CommandScript public: npc_commandscript() : CommandScript("npc_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand npcAddCommandTable[] = - { - { "formation", rbac::RBAC_PERM_COMMAND_NPC_ADD_FORMATION, false, &HandleNpcAddFormationCommand, "", NULL }, - { "item", rbac::RBAC_PERM_COMMAND_NPC_ADD_ITEM, false, &HandleNpcAddVendorItemCommand, "", NULL }, - { "move", rbac::RBAC_PERM_COMMAND_NPC_ADD_MOVE, false, &HandleNpcAddMoveCommand, "", NULL }, - { "temp", rbac::RBAC_PERM_COMMAND_NPC_ADD_TEMP, false, &HandleNpcAddTempSpawnCommand, "", NULL }, - //{ "weapon", rbac::RBAC_PERM_COMMAND_NPC_ADD_WEAPON, false, &HandleNpcAddWeaponCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, &HandleNpcAddCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + static std::vector<ChatCommand> npcAddCommandTable = + { + { "formation", rbac::RBAC_PERM_COMMAND_NPC_ADD_FORMATION, false, &HandleNpcAddFormationCommand, "" }, + { "item", rbac::RBAC_PERM_COMMAND_NPC_ADD_ITEM, false, &HandleNpcAddVendorItemCommand, "" }, + { "move", rbac::RBAC_PERM_COMMAND_NPC_ADD_MOVE, false, &HandleNpcAddMoveCommand, "" }, + { "temp", rbac::RBAC_PERM_COMMAND_NPC_ADD_TEMP, false, &HandleNpcAddTempSpawnCommand, "" }, + //{ "weapon", rbac::RBAC_PERM_COMMAND_NPC_ADD_WEAPON, false, &HandleNpcAddWeaponCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, &HandleNpcAddCommand, "" }, }; - static ChatCommand npcDeleteCommandTable[] = + static std::vector<ChatCommand> npcDeleteCommandTable = { - { "item", rbac::RBAC_PERM_COMMAND_NPC_DELETE_ITEM, false, &HandleNpcDeleteVendorItemCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, &HandleNpcDeleteCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "item", rbac::RBAC_PERM_COMMAND_NPC_DELETE_ITEM, false, &HandleNpcDeleteVendorItemCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, &HandleNpcDeleteCommand, "" }, }; - static ChatCommand npcFollowCommandTable[] = + static std::vector<ChatCommand> npcFollowCommandTable = { - { "stop", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW_STOP, false, &HandleNpcUnFollowCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, &HandleNpcFollowCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "stop", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW_STOP, false, &HandleNpcUnFollowCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, &HandleNpcFollowCommand, "" }, }; - static ChatCommand npcSetCommandTable[] = - { - { "allowmove", rbac::RBAC_PERM_COMMAND_NPC_SET_ALLOWMOVE, false, &HandleNpcSetAllowMovementCommand, "", NULL }, - { "entry", rbac::RBAC_PERM_COMMAND_NPC_SET_ENTRY, false, &HandleNpcSetEntryCommand, "", NULL }, - { "factionid", rbac::RBAC_PERM_COMMAND_NPC_SET_FACTIONID, false, &HandleNpcSetFactionIdCommand, "", NULL }, - { "flag", rbac::RBAC_PERM_COMMAND_NPC_SET_FLAG, false, &HandleNpcSetFlagCommand, "", NULL }, - { "level", rbac::RBAC_PERM_COMMAND_NPC_SET_LEVEL, false, &HandleNpcSetLevelCommand, "", NULL }, - { "link", rbac::RBAC_PERM_COMMAND_NPC_SET_LINK, false, &HandleNpcSetLinkCommand, "", NULL }, - { "model", rbac::RBAC_PERM_COMMAND_NPC_SET_MODEL, false, &HandleNpcSetModelCommand, "", NULL }, - { "movetype", rbac::RBAC_PERM_COMMAND_NPC_SET_MOVETYPE, false, &HandleNpcSetMoveTypeCommand, "", NULL }, - { "phase", rbac::RBAC_PERM_COMMAND_NPC_SET_PHASE, false, &HandleNpcSetPhaseCommand, "", NULL }, - { "spawndist", rbac::RBAC_PERM_COMMAND_NPC_SET_SPAWNDIST, false, &HandleNpcSetSpawnDistCommand, "", NULL }, - { "spawntime", rbac::RBAC_PERM_COMMAND_NPC_SET_SPAWNTIME, false, &HandleNpcSetSpawnTimeCommand, "", NULL }, - { "data", rbac::RBAC_PERM_COMMAND_NPC_SET_DATA, false, &HandleNpcSetDataCommand, "", NULL }, - //{ "name", rbac::RBAC_PERM_COMMAND_NPC_SET_NAME, false, &HandleNpcSetNameCommand, "", NULL }, - //{ "subname", rbac::RBAC_PERM_COMMAND_NPC_SET_SUBNAME, false, &HandleNpcSetSubNameCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + static std::vector<ChatCommand> npcSetCommandTable = + { + { "allowmove", rbac::RBAC_PERM_COMMAND_NPC_SET_ALLOWMOVE, false, &HandleNpcSetAllowMovementCommand, "" }, + { "entry", rbac::RBAC_PERM_COMMAND_NPC_SET_ENTRY, false, &HandleNpcSetEntryCommand, "" }, + { "factionid", rbac::RBAC_PERM_COMMAND_NPC_SET_FACTIONID, false, &HandleNpcSetFactionIdCommand, "" }, + { "flag", rbac::RBAC_PERM_COMMAND_NPC_SET_FLAG, false, &HandleNpcSetFlagCommand, "" }, + { "level", rbac::RBAC_PERM_COMMAND_NPC_SET_LEVEL, false, &HandleNpcSetLevelCommand, "" }, + { "link", rbac::RBAC_PERM_COMMAND_NPC_SET_LINK, false, &HandleNpcSetLinkCommand, "" }, + { "model", rbac::RBAC_PERM_COMMAND_NPC_SET_MODEL, false, &HandleNpcSetModelCommand, "" }, + { "movetype", rbac::RBAC_PERM_COMMAND_NPC_SET_MOVETYPE, false, &HandleNpcSetMoveTypeCommand, "" }, + { "phase", rbac::RBAC_PERM_COMMAND_NPC_SET_PHASE, false, &HandleNpcSetPhaseCommand, "" }, + { "spawndist", rbac::RBAC_PERM_COMMAND_NPC_SET_SPAWNDIST, false, &HandleNpcSetSpawnDistCommand, "" }, + { "spawntime", rbac::RBAC_PERM_COMMAND_NPC_SET_SPAWNTIME, false, &HandleNpcSetSpawnTimeCommand, "" }, + { "data", rbac::RBAC_PERM_COMMAND_NPC_SET_DATA, false, &HandleNpcSetDataCommand, "" }, }; - static ChatCommand npcCommandTable[] = - { - { "info", rbac::RBAC_PERM_COMMAND_NPC_INFO, false, &HandleNpcInfoCommand, "", NULL }, - { "near", rbac::RBAC_PERM_COMMAND_NPC_NEAR, false, &HandleNpcNearCommand, "", NULL }, - { "move", rbac::RBAC_PERM_COMMAND_NPC_MOVE, false, &HandleNpcMoveCommand, "", NULL }, - { "playemote", rbac::RBAC_PERM_COMMAND_NPC_PLAYEMOTE, false, &HandleNpcPlayEmoteCommand, "", NULL }, - { "say", rbac::RBAC_PERM_COMMAND_NPC_SAY, false, &HandleNpcSayCommand, "", NULL }, - { "textemote", rbac::RBAC_PERM_COMMAND_NPC_TEXTEMOTE, false, &HandleNpcTextEmoteCommand, "", NULL }, - { "whisper", rbac::RBAC_PERM_COMMAND_NPC_WHISPER, false, &HandleNpcWhisperCommand, "", NULL }, - { "yell", rbac::RBAC_PERM_COMMAND_NPC_YELL, false, &HandleNpcYellCommand, "", NULL }, - { "tame", rbac::RBAC_PERM_COMMAND_NPC_TAME, false, &HandleNpcTameCommand, "", NULL }, + static std::vector<ChatCommand> npcCommandTable = + { + { "info", rbac::RBAC_PERM_COMMAND_NPC_INFO, false, &HandleNpcInfoCommand, "" }, + { "near", rbac::RBAC_PERM_COMMAND_NPC_NEAR, false, &HandleNpcNearCommand, "" }, + { "move", rbac::RBAC_PERM_COMMAND_NPC_MOVE, false, &HandleNpcMoveCommand, "" }, + { "playemote", rbac::RBAC_PERM_COMMAND_NPC_PLAYEMOTE, false, &HandleNpcPlayEmoteCommand, "" }, + { "say", rbac::RBAC_PERM_COMMAND_NPC_SAY, false, &HandleNpcSayCommand, "" }, + { "textemote", rbac::RBAC_PERM_COMMAND_NPC_TEXTEMOTE, false, &HandleNpcTextEmoteCommand, "" }, + { "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 }, - { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "npc", rbac::RBAC_PERM_COMMAND_NPC, false, NULL, "", npcCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -260,7 +252,7 @@ public: if (Transport* trans = chr->GetTransport()) { - uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT); + ObjectGuid::LowType guid = map->GenerateLowGuid<HighGuid::Unit>(); CreatureData& data = sObjectMgr->NewOrExistCreatureData(guid); data.id = id; data.phaseMask = chr->GetPhaseMaskForSpawn(); @@ -278,7 +270,7 @@ public: } Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) + if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) { delete creature; return false; @@ -286,7 +278,7 @@ public: creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - uint32 db_guid = creature->GetDBTableGUIDLow(); + ObjectGuid::LowType db_guid = creature->GetSpawnId(); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells() // current "creature" variable is deleted and created fresh new, otherwise old values might trigger asserts or cause undefined behavior @@ -368,7 +360,7 @@ public: char* guidStr = strtok((char*)args, " "); char* waitStr = strtok((char*)NULL, " "); - uint32 lowGuid = atoi((char*)guidStr); + ObjectGuid::LowType lowGuid = atoi((char*)guidStr); // attempt check creature existence by DB data CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid); @@ -489,12 +481,12 @@ public: if (!cId) return false; - uint32 lowguid = atoi(cId); + ObjectGuid::LowType lowguid = atoi(cId); if (!lowguid) return false; if (CreatureData const* cr_data = sObjectMgr->GetCreatureData(lowguid)) - unit = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, cr_data->id, lowguid)); + unit = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HighGuid::Unit, cr_data->id, lowguid)); } else unit = handler->getSelectedCreature(); @@ -705,7 +697,7 @@ public: std::string curRespawnDelayStr = secsToTimeString(uint64(curRespawnDelay), true); std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(), true); - handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), target->GetGUIDLow(), faction, npcflags, Entry, displayid, nativeid); + handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetSpawnId(), target->GetGUID().GetCounter(), faction, npcflags, Entry, displayid, nativeid); handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); handler->PSendSysMessage(LANG_NPCINFO_EQUIPMENT, target->GetCurrentEquipmentId(), target->GetOriginalEquipmentId()); handler->PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); @@ -764,7 +756,7 @@ public: do { Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); + ObjectGuid::LowType guid = fields[0].GetUInt32(); uint32 entry = fields[1].GetUInt32(); float x = fields[2].GetFloat(); float y = fields[3].GetFloat(); @@ -790,7 +782,7 @@ public: //move selected creature static bool HandleNpcMoveCommand(ChatHandler* handler, char const* args) { - uint32 lowguid = 0; + ObjectGuid::LowType lowguid = 0; Creature* creature = handler->getSelectedCreature(); @@ -823,7 +815,7 @@ public: } else { - lowguid = creature->GetDBTableGUIDLow(); + lowguid = creature->GetSpawnId(); } float x = handler->GetSession()->GetPlayer()->GetPositionX(); @@ -833,7 +825,7 @@ public: if (creature) { - if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(creature->GetSpawnId())) { const_cast<CreatureData*>(data)->posX = x; const_cast<CreatureData*>(data)->posY = y; @@ -939,7 +931,7 @@ public: if (!guid_str) return false; - uint32 lowguid = 0; + ObjectGuid::LowType lowguid = 0; Creature* creature = NULL; if (dontdel_str) @@ -977,7 +969,7 @@ public: creature = handler->getSelectedCreature(); if (!creature || creature->IsPet()) return false; - lowguid = creature->GetDBTableGUIDLow(); + lowguid = creature->GetSpawnId(); } else // case .setmovetype #creature_guid $move_type (with selected creature) { @@ -985,7 +977,7 @@ public: /* impossible without entry if (lowguid) - creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT)); + creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HighGuid::Unit)); */ // attempt check creature existence by DB data @@ -1001,7 +993,7 @@ public: } else { - lowguid = creature->GetDBTableGUIDLow(); + lowguid = creature->GetSpawnId(); } } @@ -1101,10 +1093,10 @@ public: mtype = RANDOM_MOTION_TYPE; Creature* creature = handler->getSelectedCreature(); - uint32 guidLow = 0; + ObjectGuid::LowType guidLow = 0; if (creature) - guidLow = creature->GetDBTableGUIDLow(); + guidLow = creature->GetSpawnId(); else return false; @@ -1150,10 +1142,10 @@ public: } Creature* creature = handler->getSelectedCreature(); - uint32 guidLow = 0; + ObjectGuid::LowType guidLow = 0; if (creature) - guidLow = creature->GetDBTableGUIDLow(); + guidLow = creature->GetSpawnId(); else return false; @@ -1282,7 +1274,7 @@ public: return false; } - ObjectGuid receiver_guid(HIGHGUID_PLAYER, uint32(atoul(receiver_str))); + ObjectGuid receiver_guid(HighGuid::Player, uint32(atoul(receiver_str))); // check online security Player* receiver = ObjectAccessor::FindPlayer(receiver_guid); @@ -1414,17 +1406,17 @@ public: if (!*args) return false; - uint32 leaderGUID = (uint32) atoi((char*)args); + ObjectGuid::LowType leaderGUID = (uint32) atoi((char*)args); Creature* creature = handler->getSelectedCreature(); - if (!creature || !creature->GetDBTableGUIDLow()) + if (!creature || !creature->GetSpawnId()) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } - uint32 lowguid = creature->GetDBTableGUIDLow(); + ObjectGuid::LowType lowguid = creature->GetSpawnId(); if (creature->GetFormation()) { handler->PSendSysMessage("Selected creature is already member of group %u", creature->GetFormation()->GetId()); @@ -1466,7 +1458,7 @@ public: if (!*args) return false; - uint32 linkguid = (uint32) atoi((char*)args); + ObjectGuid::LowType linkguid = (uint32) atoi((char*)args); Creature* creature = handler->getSelectedCreature(); @@ -1477,21 +1469,21 @@ public: return false; } - if (!creature->GetDBTableGUIDLow()) + if (!creature->GetSpawnId()) { - handler->PSendSysMessage("Selected creature %u isn't in creature table", creature->GetGUIDLow()); + handler->PSendSysMessage("Selected creature %u isn't in creature table", creature->GetGUID().GetCounter()); handler->SetSentErrorMessage(true); return false; } - if (!sObjectMgr->SetCreatureLinkedRespawn(creature->GetDBTableGUIDLow(), linkguid)) + if (!sObjectMgr->SetCreatureLinkedRespawn(creature->GetSpawnId(), linkguid)) { handler->PSendSysMessage("Selected creature can't link with guid '%u'", linkguid); handler->SetSentErrorMessage(true); return false; } - handler->PSendSysMessage("LinkGUID '%u' added to creature with DBTableGUID: '%u'", linkguid, creature->GetDBTableGUIDLow()); + handler->PSendSysMessage("LinkGUID '%u' added to creature with DBTableGUID: '%u'", linkguid, creature->GetSpawnId()); return true; } @@ -1563,98 +1555,6 @@ public: */ return true; } - - static bool HandleNpcSetNameCommand(ChatHandler* /*handler*/, char const* /*args*/) - { - /* Temp. disabled - if (!*args) - return false; - - if (strlen((char*)args)>75) - { - handler->PSendSysMessage(LANG_TOO_LONG_NAME, strlen((char*)args)-75); - return true; - } - - for (uint8 i = 0; i < strlen(args); ++i) - { - if (!isalpha(args[i]) && args[i] != ' ') - { - handler->SendSysMessage(LANG_CHARS_ONLY); - return false; - } - } - - uint64 guid; - guid = handler->GetSession()->GetPlayer()->GetSelection(); - if (guid == 0) - { - handler->SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), guid); - - if (!creature) - { - handler->SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - creature->SetName(args); - uint32 idname = sObjectMgr->AddCreatureTemplate(creature->GetName()); - creature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - creature->SaveToDB(); - */ - - return true; - } - - static bool HandleNpcSetSubNameCommand(ChatHandler* /*handler*/, char const* /*args*/) - { - /* Temp. disabled - - if (!*args) - args = ""; - - if (strlen((char*)args)>75) - { - handler->PSendSysMessage(LANG_TOO_LONG_SUBNAME, strlen((char*)args)-75); - return true; - } - - for (uint8 i = 0; i < strlen(args); i++) - { - if (!isalpha(args[i]) && args[i] != ' ') - { - handler->SendSysMessage(LANG_CHARS_ONLY); - return false; - } - } - uint64 guid; - guid = handler->GetSession()->GetPlayer()->GetSelection(); - if (guid == 0) - { - handler->SendSysMessage(LANG_NO_SELECTION); - return true; - } - - Creature* creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), guid); - - if (!creature) - { - handler->SendSysMessage(LANG_SELECT_CREATURE); - return true; - } - - uint32 idname = sObjectMgr->AddCreatureSubName(creature->GetName(), args, creature->GetUInt32Value(UNIT_FIELD_DISPLAYID)); - creature->SetUInt32Value(OBJECT_FIELD_ENTRY, idname); - - creature->SaveToDB(); - */ - return true; - } }; void AddSC_npc_commandscript() diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp index fdac9d1a35f..e3046817821 100644 --- a/src/server/scripts/Commands/cs_pet.cpp +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -27,20 +27,18 @@ class pet_commandscript : public CommandScript public: pet_commandscript() : CommandScript("pet_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand petCommandTable[] = + static std::vector<ChatCommand> petCommandTable = { - { "create", rbac::RBAC_PERM_COMMAND_PET_CREATE, false, &HandlePetCreateCommand, "", NULL }, - { "learn", rbac::RBAC_PERM_COMMAND_PET_LEARN, false, &HandlePetLearnCommand, "", NULL }, - { "unlearn", rbac::RBAC_PERM_COMMAND_PET_UNLEARN, false, &HandlePetUnlearnCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "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, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "pet", rbac::RBAC_PERM_COMMAND_PET, false, NULL, "", petCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index 9ad12bd0943..442950bca96 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -33,20 +33,18 @@ class quest_commandscript : public CommandScript public: quest_commandscript() : CommandScript("quest_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand questCommandTable[] = + static std::vector<ChatCommand> questCommandTable = { - { "add", rbac::RBAC_PERM_COMMAND_QUEST_ADD, false, &HandleQuestAdd, "", NULL }, - { "complete", rbac::RBAC_PERM_COMMAND_QUEST_COMPLETE, false, &HandleQuestComplete, "", NULL }, - { "remove", rbac::RBAC_PERM_COMMAND_QUEST_REMOVE, false, &HandleQuestRemove, "", NULL }, - { "reward", rbac::RBAC_PERM_COMMAND_QUEST_REWARD, false, &HandleQuestReward, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", rbac::RBAC_PERM_COMMAND_QUEST_ADD, false, &HandleQuestAdd, "" }, + { "complete", rbac::RBAC_PERM_COMMAND_QUEST_COMPLETE, false, &HandleQuestComplete, "" }, + { "remove", rbac::RBAC_PERM_COMMAND_QUEST_REMOVE, false, &HandleQuestRemove, "" }, + { "reward", rbac::RBAC_PERM_COMMAND_QUEST_REWARD, false, &HandleQuestReward, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "quest", rbac::RBAC_PERM_COMMAND_QUEST, false, NULL, "", questCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -243,7 +241,7 @@ public: // prepare Quest Tracker datas PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_QUEST_TRACK_GM_COMPLETE); stmt->setUInt32(0, quest->GetQuestId()); - stmt->setUInt32(1, player->GetGUIDLow()); + stmt->setUInt32(1, player->GetGUID().GetCounter()); // add to Quest Tracker CharacterDatabase.Execute(stmt); diff --git a/src/server/scripts/Commands/cs_rbac.cpp b/src/server/scripts/Commands/cs_rbac.cpp index 497bd45ec5c..c28aa04175f 100644 --- a/src/server/scripts/Commands/cs_rbac.cpp +++ b/src/server/scripts/Commands/cs_rbac.cpp @@ -1,383 +1,380 @@ -/*
- * Copyright (C) 2008-2015 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/>.
- */
-
-/* ScriptData
-Name: rbac_commandscript
-%Complete: 100
-Comment: All role based access control related commands (including account related)
-Category: commandscripts
-EndScriptData */
-
-#include "AccountMgr.h"
-#include "Config.h"
-#include "Chat.h"
-#include "Language.h"
-#include "Player.h"
-#include "ScriptMgr.h"
-
-struct RBACCommandData
-{
- RBACCommandData(): id(0), realmId(0), rbac(NULL), needDelete(false) { }
- ~RBACCommandData()
- {
- if (needDelete)
- delete rbac;
- }
-
- uint32 id;
- int32 realmId;
- rbac::RBACData* rbac;
- bool needDelete;
-};
-
-class rbac_commandscript : public CommandScript
-{
-public:
- rbac_commandscript() : CommandScript("rbac_commandscript") { }
-
- ChatCommand* GetCommands() const
- {
- static ChatCommand rbacAccountCommandTable[] =
- {
- { "list", rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_LIST, true, &HandleRBACPermListCommand, "", NULL },
- { "grant", rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_GRANT, true, &HandleRBACPermGrantCommand, "", NULL },
- { "deny", rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_DENY, true, &HandleRBACPermDenyCommand, "", NULL },
- { "revoke", rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_REVOKE, true, &HandleRBACPermRevokeCommand, "", NULL },
- { NULL, 0, false, NULL, "", NULL }
- };
-
- static ChatCommand rbacCommandTable[] =
- {
- { "account", rbac::RBAC_PERM_COMMAND_RBAC_ACC, true, NULL, "", rbacAccountCommandTable },
- { "list", rbac::RBAC_PERM_COMMAND_RBAC_LIST, true, &HandleRBACListPermissionsCommand, "", NULL },
- { NULL, 0, false, NULL, "", NULL }
- };
-
- static ChatCommand commandTable[] =
- {
- { "rbac", rbac::RBAC_PERM_COMMAND_RBAC, true, NULL, "", rbacCommandTable },
- { NULL, 0, false, NULL, "", NULL }
- };
-
- return commandTable;
- }
-
- static RBACCommandData* ReadParams(ChatHandler* handler, char const* args, bool checkParams = true)
- {
- if (!args)
- return NULL;
-
- char* param1 = strtok((char*)args, " ");
- char* param2 = strtok(NULL, " ");
- char* param3 = strtok(NULL, " ");
-
- int32 realmId = -1;
- uint32 accountId = 0;
- std::string accountName;
- uint32 id = 0;
- RBACCommandData* data = NULL;
- rbac::RBACData* rdata = NULL;
- bool useSelectedPlayer = false;
-
- if (checkParams)
- {
- if (!param3)
- {
- if (param2)
- realmId = atoi(param2);
-
- if (param1)
- id = atoi(param1);
-
- useSelectedPlayer = true;
- }
- else
- {
- id = atoi(param2);
- realmId = atoi(param3);
- }
-
- if (!id)
- {
- handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, id);
- handler->SetSentErrorMessage(true);
- return NULL;
- }
-
- if (realmId < -1 || !realmId)
- {
- handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_REALM, realmId);
- handler->SetSentErrorMessage(true);
- return NULL;
- }
- }
- else if (!param1)
- useSelectedPlayer = true;
-
- if (useSelectedPlayer)
- {
- Player* player = handler->getSelectedPlayer();
- if (!player)
- return NULL;
-
- rdata = player->GetSession()->GetRBACData();
- accountId = rdata->GetId();
- AccountMgr::GetName(accountId, accountName);
- }
- else
- {
- accountName = param1;
-
- if (AccountMgr::normalizeString(accountName))
- accountId = AccountMgr::GetId(accountName);
-
- if (!accountId)
- {
- handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str());
- handler->SetSentErrorMessage(true);
- return NULL;
- }
- }
-
- if (checkParams && handler->HasLowerSecurityAccount(NULL, accountId, true))
- return NULL;
-
- data = new RBACCommandData();
-
- if (!rdata)
- {
- data->rbac = new rbac::RBACData(accountId, accountName, realmID, AccountMgr::GetSecurity(accountId, realmID));
- data->rbac->LoadFromDB();
- data->needDelete = true;
- }
- else
- data->rbac = rdata;
-
- data->id = id;
- data->realmId = realmId;
- return data;
- }
-
- static bool HandleRBACPermGrantCommand(ChatHandler* handler, char const* args)
- {
- RBACCommandData* command = ReadParams(handler, args);
-
- if (!command)
- {
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- rbac::RBACCommandResult result = command->rbac->GrantPermission(command->id, command->realmId);
- rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(command->id);
-
- switch (result)
- {
- case rbac::RBAC_CANT_ADD_ALREADY_ADDED:
- handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED_IN_LIST, command->id, permission->GetName().c_str(),
- command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str());
- break;
- case rbac::RBAC_IN_DENIED_LIST:
- handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED_IN_DENIED_LIST, command->id, permission->GetName().c_str(),
- command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str());
- break;
- case rbac::RBAC_OK:
- handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED, command->id, permission->GetName().c_str(),
- command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str());
- break;
- case rbac::RBAC_ID_DOES_NOT_EXISTS:
- handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, command->id);
- break;
- default:
- break;
- }
-
- delete command;
-
- return true;
- }
-
- static bool HandleRBACPermDenyCommand(ChatHandler* handler, char const* args)
- {
- RBACCommandData* command = ReadParams(handler, args);
-
- if (!command)
- {
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- rbac::RBACCommandResult result = command->rbac->DenyPermission(command->id, command->realmId);
- rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(command->id);
-
- switch (result)
- {
- case rbac::RBAC_CANT_ADD_ALREADY_ADDED:
- handler->PSendSysMessage(LANG_RBAC_PERM_DENIED_IN_LIST, command->id, permission->GetName().c_str(),
- command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str());
- break;
- case rbac::RBAC_IN_GRANTED_LIST:
- handler->PSendSysMessage(LANG_RBAC_PERM_DENIED_IN_GRANTED_LIST, command->id, permission->GetName().c_str(),
- command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str());
- break;
- case rbac::RBAC_OK:
- handler->PSendSysMessage(LANG_RBAC_PERM_DENIED, command->id, permission->GetName().c_str(),
- command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str());
- break;
- case rbac::RBAC_ID_DOES_NOT_EXISTS:
- handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, command->id);
- break;
- default:
- break;
- }
-
- delete command;
-
- return true;
- }
-
- static bool HandleRBACPermRevokeCommand(ChatHandler* handler, char const* args)
- {
- RBACCommandData* command = ReadParams(handler, args);
-
- if (!command)
- {
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- rbac::RBACCommandResult result = command->rbac->RevokePermission(command->id, command->realmId);
- rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(command->id);
-
- switch (result)
- {
- case rbac::RBAC_CANT_REVOKE_NOT_IN_LIST:
- handler->PSendSysMessage(LANG_RBAC_PERM_REVOKED_NOT_IN_LIST, command->id, permission->GetName().c_str(),
- command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str());
- break;
- case rbac::RBAC_OK:
- handler->PSendSysMessage(LANG_RBAC_PERM_REVOKED, command->id, permission->GetName().c_str(),
- command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str());
- break;
- case rbac::RBAC_ID_DOES_NOT_EXISTS:
- handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, command->id);
- break;
- default:
- break;
- }
-
- delete command;
-
- return true;
- }
-
- static bool HandleRBACPermListCommand(ChatHandler* handler, char const* args)
- {
- RBACCommandData* command = ReadParams(handler, args, false);
-
- if (!command)
- {
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_GRANTED, command->rbac->GetId(), command->rbac->GetName().c_str());
- rbac::RBACPermissionContainer const& granted = command->rbac->GetGrantedPermissions();
- if (granted.empty())
- handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_EMPTY));
- else
- {
- for (rbac::RBACPermissionContainer::const_iterator itr = granted.begin(); itr != granted.end(); ++itr)
- {
- rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(*itr);
- handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str());
- }
- }
-
- handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_DENIED, command->rbac->GetId(), command->rbac->GetName().c_str());
- rbac::RBACPermissionContainer const& denied = command->rbac->GetDeniedPermissions();
- if (denied.empty())
- handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_EMPTY));
- else
- {
- for (rbac::RBACPermissionContainer::const_iterator itr = denied.begin(); itr != denied.end(); ++itr)
- {
- rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(*itr);
- handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str());
- }
- }
- handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_BY_SEC_LEVEL, command->rbac->GetId(), command->rbac->GetName().c_str(), command->rbac->GetSecurityLevel());
- rbac::RBACPermissionContainer const& defaultPermissions = sAccountMgr->GetRBACDefaultPermissions(command->rbac->GetSecurityLevel());
- if (defaultPermissions.empty())
- handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_EMPTY));
- else
- {
- for (rbac::RBACPermissionContainer::const_iterator itr = defaultPermissions.begin(); itr != defaultPermissions.end(); ++itr)
- {
- rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(*itr);
- handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str());
- }
- }
-
- delete command;
-
- return true;
- }
-
- static bool HandleRBACListPermissionsCommand(ChatHandler* handler, char const* args)
- {
- uint32 id = 0;
- if (char* param1 = strtok((char*)args, " "))
- id = atoi(param1);
-
- if (!id)
- {
- rbac::RBACPermissionsContainer const& permissions = sAccountMgr->GetRBACPermissionList();
- handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_PERMISSIONS_HEADER));
- for (rbac::RBACPermissionsContainer::const_iterator it = permissions.begin(); it != permissions.end(); ++it)
- {
- rbac::RBACPermission const* permission = it->second;
- handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str());
- }
- }
- else
- {
- rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(id);
- if (!permission)
- {
- handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, id);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_PERMISSIONS_HEADER));
- handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str());
- handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_PERMS_LINKED_HEADER));
- rbac::RBACPermissionContainer const& permissions = permission->GetLinkedPermissions();
- for (rbac::RBACPermissionContainer::const_iterator it = permissions.begin(); it != permissions.end(); ++it)
- if (rbac::RBACPermission const* rbacPermission = sAccountMgr->GetRBACPermission(*it))
- handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, rbacPermission->GetId(), rbacPermission->GetName().c_str());
- }
-
- return true;
- }
-};
-
-void AddSC_rbac_commandscript()
-{
- new rbac_commandscript();
-}
+/* + * Copyright (C) 2008-2015 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/>. + */ + +/* ScriptData +Name: rbac_commandscript +%Complete: 100 +Comment: All role based access control related commands (including account related) +Category: commandscripts +EndScriptData */ + +#include "AccountMgr.h" +#include "Config.h" +#include "Chat.h" +#include "Language.h" +#include "Player.h" +#include "ScriptMgr.h" + +struct RBACCommandData +{ + RBACCommandData(): id(0), realmId(0), rbac(NULL), needDelete(false) { } + ~RBACCommandData() + { + if (needDelete) + delete rbac; + } + + uint32 id; + int32 realmId; + rbac::RBACData* rbac; + bool needDelete; +}; + +class rbac_commandscript : public CommandScript +{ +public: + rbac_commandscript() : CommandScript("rbac_commandscript") { } + + std::vector<ChatCommand> GetCommands() const + { + static std::vector<ChatCommand> rbacAccountCommandTable = + { + { "list", rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_LIST, true, &HandleRBACPermListCommand, "" }, + { "grant", rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_GRANT, true, &HandleRBACPermGrantCommand, "" }, + { "deny", rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_DENY, true, &HandleRBACPermDenyCommand, "" }, + { "revoke", rbac::RBAC_PERM_COMMAND_RBAC_ACC_PERM_REVOKE, true, &HandleRBACPermRevokeCommand, "" }, + }; + + static std::vector<ChatCommand> rbacCommandTable = + { + { "account", rbac::RBAC_PERM_COMMAND_RBAC_ACC, true, NULL, "", rbacAccountCommandTable }, + { "list", rbac::RBAC_PERM_COMMAND_RBAC_LIST, true, &HandleRBACListPermissionsCommand, "" }, + }; + + static std::vector<ChatCommand> commandTable = + { + { "rbac", rbac::RBAC_PERM_COMMAND_RBAC, true, NULL, "", rbacCommandTable }, + }; + + return commandTable; + } + + static RBACCommandData* ReadParams(ChatHandler* handler, char const* args, bool checkParams = true) + { + if (!args) + return NULL; + + char* param1 = strtok((char*)args, " "); + char* param2 = strtok(NULL, " "); + char* param3 = strtok(NULL, " "); + + int32 realmId = -1; + uint32 accountId = 0; + std::string accountName; + uint32 id = 0; + RBACCommandData* data = NULL; + rbac::RBACData* rdata = NULL; + bool useSelectedPlayer = false; + + if (checkParams) + { + if (!param3) + { + if (param2) + realmId = atoi(param2); + + if (param1) + id = atoi(param1); + + useSelectedPlayer = true; + } + else + { + id = atoi(param2); + realmId = atoi(param3); + } + + if (!id) + { + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, id); + handler->SetSentErrorMessage(true); + return NULL; + } + + if (realmId < -1 || !realmId) + { + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_REALM, realmId); + handler->SetSentErrorMessage(true); + return NULL; + } + } + else if (!param1) + useSelectedPlayer = true; + + if (useSelectedPlayer) + { + Player* player = handler->getSelectedPlayer(); + if (!player) + return NULL; + + rdata = player->GetSession()->GetRBACData(); + accountId = rdata->GetId(); + AccountMgr::GetName(accountId, accountName); + } + else + { + accountName = param1; + + if (AccountMgr::normalizeString(accountName)) + accountId = AccountMgr::GetId(accountName); + + if (!accountId) + { + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); + handler->SetSentErrorMessage(true); + return NULL; + } + } + + if (checkParams && handler->HasLowerSecurityAccount(NULL, accountId, true)) + return NULL; + + data = new RBACCommandData(); + + if (!rdata) + { + data->rbac = new rbac::RBACData(accountId, accountName, realmID, AccountMgr::GetSecurity(accountId, realmID)); + data->rbac->LoadFromDB(); + data->needDelete = true; + } + else + data->rbac = rdata; + + data->id = id; + data->realmId = realmId; + return data; + } + + static bool HandleRBACPermGrantCommand(ChatHandler* handler, char const* args) + { + RBACCommandData* command = ReadParams(handler, args); + + if (!command) + { + handler->SetSentErrorMessage(true); + return false; + } + + rbac::RBACCommandResult result = command->rbac->GrantPermission(command->id, command->realmId); + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(command->id); + + switch (result) + { + case rbac::RBAC_CANT_ADD_ALREADY_ADDED: + handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED_IN_LIST, command->id, permission->GetName().c_str(), + command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str()); + break; + case rbac::RBAC_IN_DENIED_LIST: + handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED_IN_DENIED_LIST, command->id, permission->GetName().c_str(), + command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str()); + break; + case rbac::RBAC_OK: + handler->PSendSysMessage(LANG_RBAC_PERM_GRANTED, command->id, permission->GetName().c_str(), + command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str()); + break; + case rbac::RBAC_ID_DOES_NOT_EXISTS: + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, command->id); + break; + default: + break; + } + + delete command; + + return true; + } + + static bool HandleRBACPermDenyCommand(ChatHandler* handler, char const* args) + { + RBACCommandData* command = ReadParams(handler, args); + + if (!command) + { + handler->SetSentErrorMessage(true); + return false; + } + + rbac::RBACCommandResult result = command->rbac->DenyPermission(command->id, command->realmId); + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(command->id); + + switch (result) + { + case rbac::RBAC_CANT_ADD_ALREADY_ADDED: + handler->PSendSysMessage(LANG_RBAC_PERM_DENIED_IN_LIST, command->id, permission->GetName().c_str(), + command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str()); + break; + case rbac::RBAC_IN_GRANTED_LIST: + handler->PSendSysMessage(LANG_RBAC_PERM_DENIED_IN_GRANTED_LIST, command->id, permission->GetName().c_str(), + command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str()); + break; + case rbac::RBAC_OK: + handler->PSendSysMessage(LANG_RBAC_PERM_DENIED, command->id, permission->GetName().c_str(), + command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str()); + break; + case rbac::RBAC_ID_DOES_NOT_EXISTS: + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, command->id); + break; + default: + break; + } + + delete command; + + return true; + } + + static bool HandleRBACPermRevokeCommand(ChatHandler* handler, char const* args) + { + RBACCommandData* command = ReadParams(handler, args); + + if (!command) + { + handler->SetSentErrorMessage(true); + return false; + } + + rbac::RBACCommandResult result = command->rbac->RevokePermission(command->id, command->realmId); + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(command->id); + + switch (result) + { + case rbac::RBAC_CANT_REVOKE_NOT_IN_LIST: + handler->PSendSysMessage(LANG_RBAC_PERM_REVOKED_NOT_IN_LIST, command->id, permission->GetName().c_str(), + command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str()); + break; + case rbac::RBAC_OK: + handler->PSendSysMessage(LANG_RBAC_PERM_REVOKED, command->id, permission->GetName().c_str(), + command->realmId, command->rbac->GetId(), command->rbac->GetName().c_str()); + break; + case rbac::RBAC_ID_DOES_NOT_EXISTS: + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, command->id); + break; + default: + break; + } + + delete command; + + return true; + } + + static bool HandleRBACPermListCommand(ChatHandler* handler, char const* args) + { + RBACCommandData* command = ReadParams(handler, args, false); + + if (!command) + { + handler->SetSentErrorMessage(true); + return false; + } + + handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_GRANTED, command->rbac->GetId(), command->rbac->GetName().c_str()); + rbac::RBACPermissionContainer const& granted = command->rbac->GetGrantedPermissions(); + if (granted.empty()) + handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_EMPTY)); + else + { + for (rbac::RBACPermissionContainer::const_iterator itr = granted.begin(); itr != granted.end(); ++itr) + { + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(*itr); + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + } + } + + handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_DENIED, command->rbac->GetId(), command->rbac->GetName().c_str()); + rbac::RBACPermissionContainer const& denied = command->rbac->GetDeniedPermissions(); + if (denied.empty()) + handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_EMPTY)); + else + { + for (rbac::RBACPermissionContainer::const_iterator itr = denied.begin(); itr != denied.end(); ++itr) + { + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(*itr); + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + } + } + handler->PSendSysMessage(LANG_RBAC_LIST_HEADER_BY_SEC_LEVEL, command->rbac->GetId(), command->rbac->GetName().c_str(), command->rbac->GetSecurityLevel()); + rbac::RBACPermissionContainer const& defaultPermissions = sAccountMgr->GetRBACDefaultPermissions(command->rbac->GetSecurityLevel()); + if (defaultPermissions.empty()) + handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_EMPTY)); + else + { + for (rbac::RBACPermissionContainer::const_iterator itr = defaultPermissions.begin(); itr != defaultPermissions.end(); ++itr) + { + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(*itr); + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + } + } + + delete command; + + return true; + } + + static bool HandleRBACListPermissionsCommand(ChatHandler* handler, char const* args) + { + uint32 id = 0; + if (char* param1 = strtok((char*)args, " ")) + id = atoi(param1); + + if (!id) + { + rbac::RBACPermissionsContainer const& permissions = sAccountMgr->GetRBACPermissionList(); + handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_PERMISSIONS_HEADER)); + for (rbac::RBACPermissionsContainer::const_iterator it = permissions.begin(); it != permissions.end(); ++it) + { + rbac::RBACPermission const* permission = it->second; + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + } + } + else + { + rbac::RBACPermission const* permission = sAccountMgr->GetRBACPermission(id); + if (!permission) + { + handler->PSendSysMessage(LANG_RBAC_WRONG_PARAMETER_ID, id); + handler->SetSentErrorMessage(true); + return false; + } + + handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_PERMISSIONS_HEADER)); + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, permission->GetId(), permission->GetName().c_str()); + handler->PSendSysMessage("%s", handler->GetTrinityString(LANG_RBAC_LIST_PERMS_LINKED_HEADER)); + rbac::RBACPermissionContainer const& permissions = permission->GetLinkedPermissions(); + for (rbac::RBACPermissionContainer::const_iterator it = permissions.begin(); it != permissions.end(); ++it) + if (rbac::RBACPermission const* rbacPermission = sAccountMgr->GetRBACPermission(*it)) + handler->PSendSysMessage(LANG_RBAC_LIST_ELEMENT, rbacPermission->GetId(), rbacPermission->GetName().c_str()); + } + + return true; + } +}; + +void AddSC_rbac_commandscript() +{ + new rbac_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index f4b442de92a..44e34b8e2a9 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -47,122 +47,119 @@ class reload_commandscript : public CommandScript public: reload_commandscript() : CommandScript("reload_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand reloadAllCommandTable[] = + static std::vector<ChatCommand> reloadAllCommandTable = { - { "achievement", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_ACHIEVEMENT, true, &HandleReloadAllAchievementCommand, "", NULL }, - { "area", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_AREA, true, &HandleReloadAllAreaCommand, "", NULL }, - { "gossips", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_GOSSIP, true, &HandleReloadAllGossipsCommand, "", NULL }, - { "item", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_ITEM, true, &HandleReloadAllItemCommand, "", NULL }, - { "locales", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_LOCALES, true, &HandleReloadAllLocalesCommand, "", NULL }, - { "loot", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_LOOT, true, &HandleReloadAllLootCommand, "", NULL }, - { "npc", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_NPC, true, &HandleReloadAllNpcCommand, "", NULL }, - { "quest", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_QUEST, true, &HandleReloadAllQuestCommand, "", NULL }, - { "scripts", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_SCRIPTS, true, &HandleReloadAllScriptsCommand, "", NULL }, - { "spell", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_SPELL, true, &HandleReloadAllSpellCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_RELOAD_ALL, true, &HandleReloadAllCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "achievement", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_ACHIEVEMENT, true, &HandleReloadAllAchievementCommand, "" }, + { "area", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_AREA, true, &HandleReloadAllAreaCommand, "" }, + { "gossips", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_GOSSIP, true, &HandleReloadAllGossipsCommand, "" }, + { "item", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_ITEM, true, &HandleReloadAllItemCommand, "" }, + { "locales", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_LOCALES, true, &HandleReloadAllLocalesCommand, "" }, + { "loot", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_LOOT, true, &HandleReloadAllLootCommand, "" }, + { "npc", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_NPC, true, &HandleReloadAllNpcCommand, "" }, + { "quest", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_QUEST, true, &HandleReloadAllQuestCommand, "" }, + { "scripts", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_SCRIPTS, true, &HandleReloadAllScriptsCommand, "" }, + { "spell", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_SPELL, true, &HandleReloadAllSpellCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_RELOAD_ALL, true, &HandleReloadAllCommand, "" }, }; - static ChatCommand reloadCommandTable[] = + static std::vector<ChatCommand> reloadCommandTable = { - { "auctions", rbac::RBAC_PERM_COMMAND_RELOAD_AUCTIONS, true, &HandleReloadAuctionsCommand, "", NULL }, - { "access_requirement", rbac::RBAC_PERM_COMMAND_RELOAD_ACCESS_REQUIREMENT, true, &HandleReloadAccessRequirementCommand, "", NULL }, - { "achievement_criteria_data", rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_CRITERIA_DATA, true, &HandleReloadAchievementCriteriaDataCommand, "", NULL }, - { "achievement_reward", rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD, true, &HandleReloadAchievementRewardCommand, "", NULL }, + { "auctions", rbac::RBAC_PERM_COMMAND_RELOAD_AUCTIONS, true, &HandleReloadAuctionsCommand, "" }, + { "access_requirement", rbac::RBAC_PERM_COMMAND_RELOAD_ACCESS_REQUIREMENT, true, &HandleReloadAccessRequirementCommand, "" }, + { "achievement_criteria_data", rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_CRITERIA_DATA, true, &HandleReloadAchievementCriteriaDataCommand, "" }, + { "achievement_reward", rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD, true, &HandleReloadAchievementRewardCommand, "" }, { "all", rbac::RBAC_PERM_COMMAND_RELOAD_ALL, true, NULL, "", reloadAllCommandTable }, - { "areatrigger_involvedrelation", rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_INVOLVEDRELATION, true, &HandleReloadQuestAreaTriggersCommand, "", NULL }, - { "areatrigger_tavern", rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TAVERN, true, &HandleReloadAreaTriggerTavernCommand, "", NULL }, - { "areatrigger_teleport", rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TELEPORT, true, &HandleReloadAreaTriggerTeleportCommand, "", NULL }, - { "autobroadcast", rbac::RBAC_PERM_COMMAND_RELOAD_AUTOBROADCAST, true, &HandleReloadAutobroadcastCommand, "", NULL }, - { "battleground_template", rbac::RBAC_PERM_COMMAND_RELOAD_BATTLEGROUND_TEMPLATE, true, &HandleReloadBattlegroundTemplate, "", NULL }, - { "broadcast_text", rbac::RBAC_PERM_COMMAND_RELOAD_BROADCAST_TEXT, true, &HandleReloadBroadcastTextCommand, "", NULL }, - { "command", rbac::RBAC_PERM_COMMAND_RELOAD_COMMAND, true, &HandleReloadCommandCommand, "", NULL }, - { "conditions", rbac::RBAC_PERM_COMMAND_RELOAD_CONDITIONS, true, &HandleReloadConditions, "", NULL }, - { "config", rbac::RBAC_PERM_COMMAND_RELOAD_CONFIG, true, &HandleReloadConfigCommand, "", NULL }, - { "creature_text", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEXT, true, &HandleReloadCreatureText, "", NULL }, - { "creature_questender", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTENDER, true, &HandleReloadCreatureQuestEnderCommand, "", NULL }, - { "creature_linked_respawn", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LINKED_RESPAWN, true, &HandleReloadLinkedRespawnCommand, "", NULL }, - { "creature_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesCreatureCommand, "", NULL }, - { "creature_onkill_reputation", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REPUTATION, true, &HandleReloadOnKillReputationCommand, "", NULL }, - { "creature_queststarter", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTSTARTER, true, &HandleReloadCreatureQuestStarterCommand, "", NULL }, - { "creature_summon_groups", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_SUMMON_GROUPS, true, &HandleReloadCreatureSummonGroupsCommand, "", NULL }, - { "creature_template", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEMPLATE, true, &HandleReloadCreatureTemplateCommand, "", NULL }, - { "disables", rbac::RBAC_PERM_COMMAND_RELOAD_DISABLES, true, &HandleReloadDisablesCommand, "", NULL }, - { "disenchant_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesDisenchantCommand, "", NULL }, - { "event_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS, true, &HandleReloadEventScriptsCommand, "", NULL }, - { "fishing_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_FISHING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesFishingCommand, "", NULL }, - { "game_graveyard_zone", rbac::RBAC_PERM_COMMAND_RELOAD_GAME_GRAVEYARD_ZONE, true, &HandleReloadGameGraveyardZoneCommand, "", NULL }, - { "game_tele", rbac::RBAC_PERM_COMMAND_RELOAD_GAME_TELE, true, &HandleReloadGameTeleCommand, "", NULL }, - { "gameobject_questender", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTENDER, true, &HandleReloadGOQuestEnderCommand, "", NULL }, - { "gameobject_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesGameobjectCommand, "", NULL }, - { "gameobject_queststarter", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTSTARTER, true, &HandleReloadGOQuestStarterCommand, "", NULL }, - { "gm_tickets", rbac::RBAC_PERM_COMMAND_RELOAD_GM_TICKETS, true, &HandleReloadGMTicketsCommand, "", NULL }, - { "gossip_menu", rbac::RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU, true, &HandleReloadGossipMenuCommand, "", NULL }, - { "gossip_menu_option", rbac::RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION, true, &HandleReloadGossipMenuOptionCommand, "", NULL }, - { "item_enchantment_template", rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_ENCHANTMENT_TEMPLATE, true, &HandleReloadItemEnchantementsCommand, "", NULL }, - { "item_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesItemCommand, "", NULL }, - { "item_set_names", rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAMES, true, &HandleReloadItemSetNamesCommand, "", NULL }, - { "lfg_dungeon_rewards", rbac::RBAC_PERM_COMMAND_RELOAD_LFG_DUNGEON_REWARDS, true, &HandleReloadLfgRewardsCommand, "", NULL }, - { "locales_achievement_reward", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_ACHIEVEMENT_REWARD, true, &HandleReloadLocalesAchievementRewardCommand, "", NULL }, - { "locales_creature", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_CRETURE, true, &HandleReloadLocalesCreatureCommand, "", NULL }, - { "locales_creature_text", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_CRETURE_TEXT, true, &HandleReloadLocalesCreatureTextCommand, "", NULL }, - { "locales_gameobject", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_GAMEOBJECT, true, &HandleReloadLocalesGameobjectCommand, "", NULL }, - { "locales_gossip_menu_option", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_GOSSIP_MENU_OPTION, true, &HandleReloadLocalesGossipMenuOptionCommand, "", NULL }, - { "locales_item", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_ITEM, true, &HandleReloadLocalesItemCommand, "", NULL }, - { "locales_item_set_name", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_ITEM_SET_NAME, true, &HandleReloadLocalesItemSetNameCommand, "", NULL }, - { "locales_npc_text", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_NPC_TEXT, true, &HandleReloadLocalesNpcTextCommand, "", NULL }, - { "locales_page_text", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_PAGE_TEXT, true, &HandleReloadLocalesPageTextCommand, "", NULL }, - { "locales_points_of_interest", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_POINTS_OF_INTEREST, true, &HandleReloadLocalesPointsOfInterestCommand, "", NULL }, - { "locales_quest", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_QUEST, true, &HandleReloadLocalesQuestCommand, "", NULL }, - { "mail_level_reward", rbac::RBAC_PERM_COMMAND_RELOAD_MAIL_LEVEL_REWARD, true, &HandleReloadMailLevelRewardCommand, "", NULL }, - { "mail_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_MAIL_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesMailCommand, "", NULL }, - { "milling_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_MILLING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesMillingCommand, "", NULL }, - { "npc_spellclick_spells", rbac::RBAC_PERM_COMMAND_RELOAD_NPC_SPELLCLICK_SPELLS, true, &HandleReloadSpellClickSpellsCommand, "", NULL }, - { "npc_trainer", rbac::RBAC_PERM_COMMAND_RELOAD_NPC_TRAINER, true, &HandleReloadNpcTrainerCommand, "", NULL }, - { "npc_vendor", rbac::RBAC_PERM_COMMAND_RELOAD_NPC_VENDOR, true, &HandleReloadNpcVendorCommand, "", NULL }, - { "page_text", rbac::RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT, true, &HandleReloadPageTextsCommand, "", NULL }, - { "pickpocketing_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_PICKPOCKETING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesPickpocketingCommand, "", NULL }, - { "points_of_interest", rbac::RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST, true, &HandleReloadPointsOfInterestCommand, "", NULL }, - { "prospecting_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_PROSPECTING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesProspectingCommand, "", NULL }, - { "quest_poi", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_POI, true, &HandleReloadQuestPOICommand, "", NULL }, - { "quest_template", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE, true, &HandleReloadQuestTemplateCommand, "", NULL }, - { "rbac", rbac::RBAC_PERM_COMMAND_RELOAD_RBAC, true, &HandleReloadRBACCommand, "", NULL }, - { "reference_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_REFERENCE_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesReferenceCommand, "", NULL }, - { "reserved_name", rbac::RBAC_PERM_COMMAND_RELOAD_RESERVED_NAME, true, &HandleReloadReservedNameCommand, "", NULL }, - { "reputation_reward_rate", rbac::RBAC_PERM_COMMAND_RELOAD_REPUTATION_REWARD_RATE, true, &HandleReloadReputationRewardRateCommand, "", NULL }, - { "reputation_spillover_template", rbac::RBAC_PERM_COMMAND_RELOAD_SPILLOVER_TEMPLATE, true, &HandleReloadReputationRewardRateCommand, "", NULL }, - { "skill_discovery_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_DISCOVERY_TEMPLATE, true, &HandleReloadSkillDiscoveryTemplateCommand, "", NULL }, - { "skill_extra_item_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_EXTRA_ITEM_TEMPLATE, true, &HandleReloadSkillExtraItemTemplateCommand, "", NULL }, - { "skill_fishing_base_level", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_FISHING_BASE_LEVEL, true, &HandleReloadSkillFishingBaseLevelCommand, "", NULL }, - { "skinning_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKINNING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesSkinningCommand, "", NULL }, - { "smart_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_SMART_SCRIPTS, true, &HandleReloadSmartScripts, "", NULL }, - { "spell_required", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_REQUIRED, true, &HandleReloadSpellRequiredCommand, "", NULL }, - { "spell_area", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_AREA, true, &HandleReloadSpellAreaCommand, "", NULL }, - { "spell_bonus_data", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_BONUS_DATA, true, &HandleReloadSpellBonusesCommand, "", NULL }, - { "spell_group", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP, true, &HandleReloadSpellGroupsCommand, "", NULL }, - { "spell_learn_spell", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LEARN_SPELL, true, &HandleReloadSpellLearnSpellCommand, "", NULL }, - { "spell_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesSpellCommand, "", NULL }, - { "spell_linked_spell", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LINKED_SPELL, true, &HandleReloadSpellLinkedSpellCommand, "", NULL }, - { "spell_pet_auras", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PET_AURAS, true, &HandleReloadSpellPetAurasCommand, "", NULL }, - { "spell_proc_event", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PROC_EVENT, true, &HandleReloadSpellProcEventCommand, "", NULL }, - { "spell_proc", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PROC, true, &HandleReloadSpellProcsCommand, "", NULL }, - { "spell_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_SCRIPTS, true, &HandleReloadSpellScriptsCommand, "", NULL }, - { "spell_target_position", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_TARGET_POSITION, true, &HandleReloadSpellTargetPositionCommand, "", NULL }, - { "spell_threats", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_THREATS, true, &HandleReloadSpellThreatsCommand, "", NULL }, - { "spell_group_stack_rules", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP_STACK_RULES, true, &HandleReloadSpellGroupStackRulesCommand, "", NULL }, - { "trinity_string", rbac::RBAC_PERM_COMMAND_RELOAD_TRINITY_STRING, true, &HandleReloadTrinityStringCommand, "", NULL }, - { "warden_action", rbac::RBAC_PERM_COMMAND_RELOAD_WARDEN_ACTION, true, &HandleReloadWardenactionCommand, "", NULL }, - { "waypoint_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_WAYPOINT_SCRIPTS, true, &HandleReloadWpScriptsCommand, "", NULL }, - { "waypoint_data", rbac::RBAC_PERM_COMMAND_RELOAD_WAYPOINT_DATA, true, &HandleReloadWpCommand, "", NULL }, - { "vehicle_accessory", rbac::RBAC_PERM_COMMAND_RELOAD_VEHICLE_ACCESORY, true, &HandleReloadVehicleAccessoryCommand, "", NULL }, - { "vehicle_template_accessory", rbac::RBAC_PERM_COMMAND_RELOAD_VEHICLE_TEMPLATE_ACCESSORY, true, &HandleReloadVehicleTemplateAccessoryCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "areatrigger_involvedrelation", rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_INVOLVEDRELATION, true, &HandleReloadQuestAreaTriggersCommand, "" }, + { "areatrigger_tavern", rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TAVERN, true, &HandleReloadAreaTriggerTavernCommand, "" }, + { "areatrigger_teleport", rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_TELEPORT, true, &HandleReloadAreaTriggerTeleportCommand, "" }, + { "autobroadcast", rbac::RBAC_PERM_COMMAND_RELOAD_AUTOBROADCAST, true, &HandleReloadAutobroadcastCommand, "" }, + { "battleground_template", rbac::RBAC_PERM_COMMAND_RELOAD_BATTLEGROUND_TEMPLATE, true, &HandleReloadBattlegroundTemplate, "" }, + { "broadcast_text", rbac::RBAC_PERM_COMMAND_RELOAD_BROADCAST_TEXT, true, &HandleReloadBroadcastTextCommand, "" }, + { "command", rbac::RBAC_PERM_COMMAND_RELOAD_COMMAND, true, &HandleReloadCommandCommand, "" }, + { "conditions", rbac::RBAC_PERM_COMMAND_RELOAD_CONDITIONS, true, &HandleReloadConditions, "" }, + { "config", rbac::RBAC_PERM_COMMAND_RELOAD_CONFIG, true, &HandleReloadConfigCommand, "" }, + { "creature_text", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEXT, true, &HandleReloadCreatureText, "" }, + { "creature_questender", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTENDER, true, &HandleReloadCreatureQuestEnderCommand, "" }, + { "creature_linked_respawn", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LINKED_RESPAWN, true, &HandleReloadLinkedRespawnCommand, "" }, + { "creature_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesCreatureCommand, "" }, + { "creature_onkill_reputation", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REPUTATION, true, &HandleReloadOnKillReputationCommand, "" }, + { "creature_queststarter", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTSTARTER, true, &HandleReloadCreatureQuestStarterCommand, "" }, + { "creature_summon_groups", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_SUMMON_GROUPS, true, &HandleReloadCreatureSummonGroupsCommand, "" }, + { "creature_template", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEMPLATE, true, &HandleReloadCreatureTemplateCommand, "" }, + { "disables", rbac::RBAC_PERM_COMMAND_RELOAD_DISABLES, true, &HandleReloadDisablesCommand, "" }, + { "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, "" }, + { "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, "" }, + { "gameobject_queststarter", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTSTARTER, true, &HandleReloadGOQuestStarterCommand, "" }, + { "gm_tickets", rbac::RBAC_PERM_COMMAND_RELOAD_GM_TICKETS, true, &HandleReloadGMTicketsCommand, "" }, + { "gossip_menu", rbac::RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU, true, &HandleReloadGossipMenuCommand, "" }, + { "gossip_menu_option", rbac::RBAC_PERM_COMMAND_RELOAD_GOSSIP_MENU_OPTION, true, &HandleReloadGossipMenuOptionCommand, "" }, + { "item_enchantment_template", rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_ENCHANTMENT_TEMPLATE, true, &HandleReloadItemEnchantementsCommand, "" }, + { "item_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesItemCommand, "" }, + { "item_set_names", rbac::RBAC_PERM_COMMAND_RELOAD_ITEM_SET_NAMES, true, &HandleReloadItemSetNamesCommand, "" }, + { "lfg_dungeon_rewards", rbac::RBAC_PERM_COMMAND_RELOAD_LFG_DUNGEON_REWARDS, true, &HandleReloadLfgRewardsCommand, "" }, + { "locales_achievement_reward", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_ACHIEVEMENT_REWARD, true, &HandleReloadLocalesAchievementRewardCommand, "" }, + { "locales_creature", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_CRETURE, true, &HandleReloadLocalesCreatureCommand, "" }, + { "locales_creature_text", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_CRETURE_TEXT, true, &HandleReloadLocalesCreatureTextCommand, "" }, + { "locales_gameobject", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_GAMEOBJECT, true, &HandleReloadLocalesGameobjectCommand, "" }, + { "locales_gossip_menu_option", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_GOSSIP_MENU_OPTION, true, &HandleReloadLocalesGossipMenuOptionCommand, "" }, + { "locales_item", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_ITEM, true, &HandleReloadLocalesItemCommand, "" }, + { "locales_item_set_name", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_ITEM_SET_NAME, true, &HandleReloadLocalesItemSetNameCommand, "" }, + { "locales_npc_text", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_NPC_TEXT, true, &HandleReloadLocalesNpcTextCommand, "" }, + { "locales_page_text", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_PAGE_TEXT, true, &HandleReloadLocalesPageTextCommand, "" }, + { "locales_points_of_interest", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_POINTS_OF_INTEREST, true, &HandleReloadLocalesPointsOfInterestCommand, "" }, + { "locales_quest", rbac::RBAC_PERM_COMMAND_RELOAD_LOCALES_QUEST, true, &HandleReloadLocalesQuestCommand, "" }, + { "mail_level_reward", rbac::RBAC_PERM_COMMAND_RELOAD_MAIL_LEVEL_REWARD, true, &HandleReloadMailLevelRewardCommand, "" }, + { "mail_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_MAIL_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesMailCommand, "" }, + { "milling_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_MILLING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesMillingCommand, "" }, + { "npc_spellclick_spells", rbac::RBAC_PERM_COMMAND_RELOAD_NPC_SPELLCLICK_SPELLS, true, &HandleReloadSpellClickSpellsCommand, "" }, + { "npc_trainer", rbac::RBAC_PERM_COMMAND_RELOAD_NPC_TRAINER, true, &HandleReloadNpcTrainerCommand, "" }, + { "npc_vendor", rbac::RBAC_PERM_COMMAND_RELOAD_NPC_VENDOR, true, &HandleReloadNpcVendorCommand, "" }, + { "page_text", rbac::RBAC_PERM_COMMAND_RELOAD_PAGE_TEXT, true, &HandleReloadPageTextsCommand, "" }, + { "pickpocketing_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_PICKPOCKETING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesPickpocketingCommand, "" }, + { "points_of_interest", rbac::RBAC_PERM_COMMAND_RELOAD_POINTS_OF_INTEREST, true, &HandleReloadPointsOfInterestCommand, "" }, + { "prospecting_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_PROSPECTING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesProspectingCommand, "" }, + { "quest_poi", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_POI, true, &HandleReloadQuestPOICommand, "" }, + { "quest_template", rbac::RBAC_PERM_COMMAND_RELOAD_QUEST_TEMPLATE, true, &HandleReloadQuestTemplateCommand, "" }, + { "rbac", rbac::RBAC_PERM_COMMAND_RELOAD_RBAC, true, &HandleReloadRBACCommand, "" }, + { "reference_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_REFERENCE_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesReferenceCommand, "" }, + { "reserved_name", rbac::RBAC_PERM_COMMAND_RELOAD_RESERVED_NAME, true, &HandleReloadReservedNameCommand, "" }, + { "reputation_reward_rate", rbac::RBAC_PERM_COMMAND_RELOAD_REPUTATION_REWARD_RATE, true, &HandleReloadReputationRewardRateCommand, "" }, + { "reputation_spillover_template", rbac::RBAC_PERM_COMMAND_RELOAD_SPILLOVER_TEMPLATE, true, &HandleReloadReputationRewardRateCommand, "" }, + { "skill_discovery_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_DISCOVERY_TEMPLATE, true, &HandleReloadSkillDiscoveryTemplateCommand, "" }, + { "skill_extra_item_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_EXTRA_ITEM_TEMPLATE, true, &HandleReloadSkillExtraItemTemplateCommand, "" }, + { "skill_fishing_base_level", rbac::RBAC_PERM_COMMAND_RELOAD_SKILL_FISHING_BASE_LEVEL, true, &HandleReloadSkillFishingBaseLevelCommand, "" }, + { "skinning_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_SKINNING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesSkinningCommand, "" }, + { "smart_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_SMART_SCRIPTS, true, &HandleReloadSmartScripts, "" }, + { "spell_required", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_REQUIRED, true, &HandleReloadSpellRequiredCommand, "" }, + { "spell_area", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_AREA, true, &HandleReloadSpellAreaCommand, "" }, + { "spell_bonus_data", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_BONUS_DATA, true, &HandleReloadSpellBonusesCommand, "" }, + { "spell_group", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP, true, &HandleReloadSpellGroupsCommand, "" }, + { "spell_learn_spell", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LEARN_SPELL, true, &HandleReloadSpellLearnSpellCommand, "" }, + { "spell_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesSpellCommand, "" }, + { "spell_linked_spell", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LINKED_SPELL, true, &HandleReloadSpellLinkedSpellCommand, "" }, + { "spell_pet_auras", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PET_AURAS, true, &HandleReloadSpellPetAurasCommand, "" }, + { "spell_proc_event", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PROC_EVENT, true, &HandleReloadSpellProcEventCommand, "" }, + { "spell_proc", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_PROC, true, &HandleReloadSpellProcsCommand, "" }, + { "spell_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_SCRIPTS, true, &HandleReloadSpellScriptsCommand, "" }, + { "spell_target_position", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_TARGET_POSITION, true, &HandleReloadSpellTargetPositionCommand, "" }, + { "spell_threats", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_THREATS, true, &HandleReloadSpellThreatsCommand, "" }, + { "spell_group_stack_rules", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP_STACK_RULES, true, &HandleReloadSpellGroupStackRulesCommand, "" }, + { "trinity_string", rbac::RBAC_PERM_COMMAND_RELOAD_TRINITY_STRING, true, &HandleReloadTrinityStringCommand, "" }, + { "warden_action", rbac::RBAC_PERM_COMMAND_RELOAD_WARDEN_ACTION, true, &HandleReloadWardenactionCommand, "" }, + { "waypoint_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_WAYPOINT_SCRIPTS, true, &HandleReloadWpScriptsCommand, "" }, + { "waypoint_data", rbac::RBAC_PERM_COMMAND_RELOAD_WAYPOINT_DATA, true, &HandleReloadWpCommand, "" }, + { "vehicle_accessory", rbac::RBAC_PERM_COMMAND_RELOAD_VEHICLE_ACCESORY, true, &HandleReloadVehicleAccessoryCommand, "" }, + { "vehicle_template_accessory", rbac::RBAC_PERM_COMMAND_RELOAD_VEHICLE_TEMPLATE_ACCESSORY, true, &HandleReloadVehicleTemplateAccessoryCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "reload", rbac::RBAC_PERM_COMMAND_RELOAD, true, NULL, "", reloadCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -749,12 +746,21 @@ public: return true; } - static bool HandleReloadSkillExtraItemTemplateCommand(ChatHandler* handler, const char* /*args*/) + static bool HandleReloadSkillPerfectItemTemplateCommand(ChatHandler* handler, const char* /*args*/) + { // latched onto HandleReloadSkillExtraItemTemplateCommand as it's part of that table group (and i don't want to chance all the command IDs) + TC_LOG_INFO("misc", "Re-Loading Skill Perfection Data Table..."); + LoadSkillPerfectItemTable(); + handler->SendGlobalGMSysMessage("DB table `skill_perfect_item_template` (perfect item procs when crafting) reloaded."); + return true; + } + + static bool HandleReloadSkillExtraItemTemplateCommand(ChatHandler* handler, const char* args) { TC_LOG_INFO("misc", "Re-Loading Skill Extra Item Table..."); LoadSkillExtraItemTable(); handler->SendGlobalGMSysMessage("DB table `skill_extra_item_template` (extra item creation when crafting) reloaded."); - return true; + + return HandleReloadSkillPerfectItemTemplateCommand(handler, args); } static bool HandleReloadSkillFishingBaseLevelCommand(ChatHandler* handler, const char* /*args*/) diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index b2bccfd884a..d1c7421b761 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -35,23 +35,21 @@ class reset_commandscript : public CommandScript public: reset_commandscript() : CommandScript("reset_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand resetCommandTable[] = + static std::vector<ChatCommand> resetCommandTable = { - { "achievements", rbac::RBAC_PERM_COMMAND_RESET_ACHIEVEMENTS, true, &HandleResetAchievementsCommand, "", NULL }, - { "honor", rbac::RBAC_PERM_COMMAND_RESET_HONOR, true, &HandleResetHonorCommand, "", NULL }, - { "level", rbac::RBAC_PERM_COMMAND_RESET_LEVEL, true, &HandleResetLevelCommand, "", NULL }, - { "spells", rbac::RBAC_PERM_COMMAND_RESET_SPELLS, true, &HandleResetSpellsCommand, "", NULL }, - { "stats", rbac::RBAC_PERM_COMMAND_RESET_STATS, true, &HandleResetStatsCommand, "", NULL }, - { "talents", rbac::RBAC_PERM_COMMAND_RESET_TALENTS, true, &HandleResetTalentsCommand, "", NULL }, - { "all", rbac::RBAC_PERM_COMMAND_RESET_ALL, true, &HandleResetAllCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "achievements", rbac::RBAC_PERM_COMMAND_RESET_ACHIEVEMENTS, true, &HandleResetAchievementsCommand, "" }, + { "honor", rbac::RBAC_PERM_COMMAND_RESET_HONOR, true, &HandleResetHonorCommand, "" }, + { "level", rbac::RBAC_PERM_COMMAND_RESET_LEVEL, true, &HandleResetLevelCommand, "" }, + { "spells", rbac::RBAC_PERM_COMMAND_RESET_SPELLS, true, &HandleResetSpellsCommand, "" }, + { "stats", rbac::RBAC_PERM_COMMAND_RESET_STATS, true, &HandleResetStatsCommand, "" }, + { "talents", rbac::RBAC_PERM_COMMAND_RESET_TALENTS, true, &HandleResetTalentsCommand, "" }, + { "all", rbac::RBAC_PERM_COMMAND_RESET_ALL, true, &HandleResetAllCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "reset", rbac::RBAC_PERM_COMMAND_RESET, true, NULL, "", resetCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_send.cpp b/src/server/scripts/Commands/cs_send.cpp index e7ea4bc99d7..b7165ed339c 100644 --- a/src/server/scripts/Commands/cs_send.cpp +++ b/src/server/scripts/Commands/cs_send.cpp @@ -27,21 +27,19 @@ class send_commandscript : public CommandScript public: send_commandscript() : CommandScript("send_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand sendCommandTable[] = + static std::vector<ChatCommand> sendCommandTable = { - { "items", rbac::RBAC_PERM_COMMAND_SEND_ITEMS, true, &HandleSendItemsCommand, "", NULL }, - { "mail", rbac::RBAC_PERM_COMMAND_SEND_MAIL, true, &HandleSendMailCommand, "", NULL }, - { "message", rbac::RBAC_PERM_COMMAND_SEND_MESSAGE, true, &HandleSendMessageCommand, "", NULL }, - { "money", rbac::RBAC_PERM_COMMAND_SEND_MONEY, true, &HandleSendMoneyCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "items", rbac::RBAC_PERM_COMMAND_SEND_ITEMS, true, &HandleSendItemsCommand, "" }, + { "mail", rbac::RBAC_PERM_COMMAND_SEND_MAIL, true, &HandleSendMailCommand, "" }, + { "message", rbac::RBAC_PERM_COMMAND_SEND_MESSAGE, true, &HandleSendMessageCommand, "" }, + { "money", rbac::RBAC_PERM_COMMAND_SEND_MONEY, true, &HandleSendMoneyCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "send", rbac::RBAC_PERM_COMMAND_SEND, false, NULL, "", sendCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -77,7 +75,7 @@ public: std::string text = msgText; // from console show not existed sender - MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUID().GetCounter() : 0, MAIL_STATIONERY_GM); /// @todo Fix poor design SQLTransaction trans = CharacterDatabase.BeginTransaction(); @@ -176,7 +174,7 @@ public: } // from console show not existed sender - MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUID().GetCounter() : 0, MAIL_STATIONERY_GM); // fill mail MailDraft draft(subject, text); @@ -236,7 +234,7 @@ public: std::string text = msgText; // from console show not existed sender - MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUID().GetCounter() : 0, MAIL_STATIONERY_GM); SQLTransaction trans = CharacterDatabase.BeginTransaction(); diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 0fecdea5ced..e41a7d161d2 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -28,71 +28,64 @@ EndScriptData */ #include "ObjectAccessor.h" #include "Player.h" #include "ScriptMgr.h" -#include "SystemConfig.h" +#include "GitRevision.h" class server_commandscript : public CommandScript { public: server_commandscript() : CommandScript("server_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand serverIdleRestartCommandTable[] = + static std::vector<ChatCommand> serverIdleRestartCommandTable = { - { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART_CANCEL, true, &HandleServerShutDownCancelCommand, "", NULL }, - { "" , rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, &HandleServerIdleRestartCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART_CANCEL, true, &HandleServerShutDownCancelCommand, "" }, + { "" , rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, &HandleServerIdleRestartCommand, "" }, }; - static ChatCommand serverIdleShutdownCommandTable[] = + static std::vector<ChatCommand> serverIdleShutdownCommandTable = { - { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN_CANCEL, true, &HandleServerShutDownCancelCommand, "", NULL }, - { "" , rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, &HandleServerIdleShutDownCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN_CANCEL, true, &HandleServerShutDownCancelCommand, "" }, + { "" , rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, &HandleServerIdleShutDownCommand, "" }, }; - static ChatCommand serverRestartCommandTable[] = + static std::vector<ChatCommand> serverRestartCommandTable = { - { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_RESTART_CANCEL, true, &HandleServerShutDownCancelCommand, "", NULL }, - { "" , rbac::RBAC_PERM_COMMAND_SERVER_RESTART, true, &HandleServerRestartCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_RESTART_CANCEL, true, &HandleServerShutDownCancelCommand, "" }, + { "" , rbac::RBAC_PERM_COMMAND_SERVER_RESTART, true, &HandleServerRestartCommand, "" }, }; - static ChatCommand serverShutdownCommandTable[] = + static std::vector<ChatCommand> serverShutdownCommandTable = { - { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN_CANCEL, true, &HandleServerShutDownCancelCommand, "", NULL }, - { "" , rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, &HandleServerShutDownCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN_CANCEL, true, &HandleServerShutDownCancelCommand, "" }, + { "" , rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, &HandleServerShutDownCommand, "" }, }; - static ChatCommand serverSetCommandTable[] = + static std::vector<ChatCommand> serverSetCommandTable = { - { "difftime", rbac::RBAC_PERM_COMMAND_SERVER_SET_DIFFTIME, true, &HandleServerSetDiffTimeCommand, "", NULL }, - { "loglevel", rbac::RBAC_PERM_COMMAND_SERVER_SET_LOGLEVEL, true, &HandleServerSetLogLevelCommand, "", NULL }, - { "motd", rbac::RBAC_PERM_COMMAND_SERVER_SET_MOTD, true, &HandleServerSetMotdCommand, "", NULL }, - { "closed", rbac::RBAC_PERM_COMMAND_SERVER_SET_CLOSED, true, &HandleServerSetClosedCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "difftime", rbac::RBAC_PERM_COMMAND_SERVER_SET_DIFFTIME, true, &HandleServerSetDiffTimeCommand, "" }, + { "loglevel", rbac::RBAC_PERM_COMMAND_SERVER_SET_LOGLEVEL, true, &HandleServerSetLogLevelCommand, "" }, + { "motd", rbac::RBAC_PERM_COMMAND_SERVER_SET_MOTD, true, &HandleServerSetMotdCommand, "" }, + { "closed", rbac::RBAC_PERM_COMMAND_SERVER_SET_CLOSED, true, &HandleServerSetClosedCommand, "" }, }; - static ChatCommand serverCommandTable[] = + static std::vector<ChatCommand> serverCommandTable = { - { "corpses", rbac::RBAC_PERM_COMMAND_SERVER_CORPSES, true, &HandleServerCorpsesCommand, "", NULL }, - { "exit", rbac::RBAC_PERM_COMMAND_SERVER_EXIT, true, &HandleServerExitCommand, "", NULL }, + { "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 }, - { "info", rbac::RBAC_PERM_COMMAND_SERVER_INFO, true, &HandleServerInfoCommand, "", NULL }, - { "motd", rbac::RBAC_PERM_COMMAND_SERVER_MOTD, true, &HandleServerMotdCommand, "", NULL }, - { "plimit", rbac::RBAC_PERM_COMMAND_SERVER_PLIMIT, true, &HandleServerPLimitCommand, "", NULL }, + { "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 }, - { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "server", rbac::RBAC_PERM_COMMAND_SERVER, true, NULL, "", serverCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -100,7 +93,7 @@ public: // Triggering corpses expire check in world static bool HandleServerCorpsesCommand(ChatHandler* /*handler*/, char const* /*args*/) { - sObjectAccessor->RemoveOldCorpses(); + sWorld->RemoveOldCorpses(); return true; } @@ -115,7 +108,7 @@ public: std::string uptime = secsToTimeString(sWorld->GetUptime()); uint32 updateTime = sWorld->GetUpdateTime(); - handler->SendSysMessage(_FULLVERSION); + handler->SendSysMessage(GitRevision::GetFullVersion()); handler->PSendSysMessage(LANG_CONNECTED_PLAYERS, playersNum, maxPlayersNum); handler->PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); handler->PSendSysMessage(LANG_UPTIME, uptime.c_str()); diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index e488aa0e607..9ea516f0972 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -35,21 +35,19 @@ class tele_commandscript : public CommandScript public: tele_commandscript() : CommandScript("tele_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand teleCommandTable[] = + static std::vector<ChatCommand> teleCommandTable = { - { "add", rbac::RBAC_PERM_COMMAND_TELE_ADD, false, &HandleTeleAddCommand, "", NULL }, - { "del", rbac::RBAC_PERM_COMMAND_TELE_DEL, true, &HandleTeleDelCommand, "", NULL }, - { "name", rbac::RBAC_PERM_COMMAND_TELE_NAME, true, &HandleTeleNameCommand, "", NULL }, - { "group", rbac::RBAC_PERM_COMMAND_TELE_GROUP, false, &HandleTeleGroupCommand, "", NULL }, - { "", rbac::RBAC_PERM_COMMAND_TELE, false, &HandleTeleCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", rbac::RBAC_PERM_COMMAND_TELE_ADD, false, &HandleTeleAddCommand, "" }, + { "del", rbac::RBAC_PERM_COMMAND_TELE_DEL, true, &HandleTeleDelCommand, "" }, + { "name", rbac::RBAC_PERM_COMMAND_TELE_NAME, true, &HandleTeleNameCommand, "" }, + { "group", rbac::RBAC_PERM_COMMAND_TELE_GROUP, false, &HandleTeleGroupCommand, "" }, + { "", rbac::RBAC_PERM_COMMAND_TELE, false, &HandleTeleCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "tele", rbac::RBAC_PERM_COMMAND_TELE, false, NULL, "", teleCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -319,7 +317,7 @@ public: } MapEntry const* map = sMapStore.LookupEntry(tele->mapId); - if (!map || map->IsBattlegroundOrArena()) + if (!map || (map->IsBattlegroundOrArena() && (me->GetMapId() != tele->mapId || !me->IsGameMaster()))) { handler->SendSysMessage(LANG_CANNOT_TELE_TO_BG); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index 5fc3cc618e5..a9baa45f344 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -36,38 +36,35 @@ class ticket_commandscript : public CommandScript public: ticket_commandscript() : CommandScript("ticket_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand ticketResponseCommandTable[] = + static std::vector<ChatCommand> ticketResponseCommandTable = { - { "append", rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE_APPEND, true, &HandleGMTicketResponseAppendCommand, "", NULL }, - { "appendln", rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE_APPENDLN, true, &HandleGMTicketResponseAppendLnCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "append", rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE_APPEND, true, &HandleGMTicketResponseAppendCommand, "" }, + { "appendln", rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE_APPENDLN, true, &HandleGMTicketResponseAppendLnCommand, "" }, }; - static ChatCommand ticketCommandTable[] = + static std::vector<ChatCommand> ticketCommandTable = { - { "assign", rbac::RBAC_PERM_COMMAND_TICKET_ASSIGN, true, &HandleGMTicketAssignToCommand, "", NULL }, - { "close", rbac::RBAC_PERM_COMMAND_TICKET_CLOSE, true, &HandleGMTicketCloseByIdCommand, "", NULL }, - { "closedlist", rbac::RBAC_PERM_COMMAND_TICKET_CLOSEDLIST, true, &HandleGMTicketListClosedCommand, "", NULL }, - { "comment", rbac::RBAC_PERM_COMMAND_TICKET_COMMENT, true, &HandleGMTicketCommentCommand, "", NULL }, - { "complete", rbac::RBAC_PERM_COMMAND_TICKET_COMPLETE, true, &HandleGMTicketCompleteCommand, "", NULL }, - { "delete", rbac::RBAC_PERM_COMMAND_TICKET_DELETE, true, &HandleGMTicketDeleteByIdCommand, "", NULL }, - { "escalate", rbac::RBAC_PERM_COMMAND_TICKET_ESCALATE, true, &HandleGMTicketEscalateCommand, "", NULL }, - { "escalatedlist", rbac::RBAC_PERM_COMMAND_TICKET_ESCALATEDLIST, true, &HandleGMTicketListEscalatedCommand, "", NULL }, - { "list", rbac::RBAC_PERM_COMMAND_TICKET_LIST, true, &HandleGMTicketListCommand, "", NULL }, - { "onlinelist", rbac::RBAC_PERM_COMMAND_TICKET_ONLINELIST, true, &HandleGMTicketListOnlineCommand, "", NULL }, - { "reset", rbac::RBAC_PERM_COMMAND_TICKET_RESET, true, &HandleGMTicketResetCommand, "", NULL }, + { "assign", rbac::RBAC_PERM_COMMAND_TICKET_ASSIGN, true, &HandleGMTicketAssignToCommand, "" }, + { "close", rbac::RBAC_PERM_COMMAND_TICKET_CLOSE, true, &HandleGMTicketCloseByIdCommand, "" }, + { "closedlist", rbac::RBAC_PERM_COMMAND_TICKET_CLOSEDLIST, true, &HandleGMTicketListClosedCommand, "" }, + { "comment", rbac::RBAC_PERM_COMMAND_TICKET_COMMENT, true, &HandleGMTicketCommentCommand, "" }, + { "complete", rbac::RBAC_PERM_COMMAND_TICKET_COMPLETE, true, &HandleGMTicketCompleteCommand, "" }, + { "delete", rbac::RBAC_PERM_COMMAND_TICKET_DELETE, true, &HandleGMTicketDeleteByIdCommand, "" }, + { "escalate", rbac::RBAC_PERM_COMMAND_TICKET_ESCALATE, true, &HandleGMTicketEscalateCommand, "" }, + { "escalatedlist", rbac::RBAC_PERM_COMMAND_TICKET_ESCALATEDLIST, true, &HandleGMTicketListEscalatedCommand, "" }, + { "list", rbac::RBAC_PERM_COMMAND_TICKET_LIST, true, &HandleGMTicketListCommand, "" }, + { "onlinelist", rbac::RBAC_PERM_COMMAND_TICKET_ONLINELIST, true, &HandleGMTicketListOnlineCommand, "" }, + { "reset", rbac::RBAC_PERM_COMMAND_TICKET_RESET, true, &HandleGMTicketResetCommand, "" }, { "response", rbac::RBAC_PERM_COMMAND_TICKET_RESPONSE, true, NULL, "", ticketResponseCommandTable }, - { "togglesystem", rbac::RBAC_PERM_COMMAND_TICKET_TOGGLESYSTEM, true, &HandleToggleGMTicketSystem, "", NULL }, - { "unassign", rbac::RBAC_PERM_COMMAND_TICKET_UNASSIGN, true, &HandleGMTicketUnAssignCommand, "", NULL }, - { "viewid", rbac::RBAC_PERM_COMMAND_TICKET_VIEWID, true, &HandleGMTicketGetByIdCommand, "", NULL }, - { "viewname", rbac::RBAC_PERM_COMMAND_TICKET_VIEWNAME, true, &HandleGMTicketGetByNameCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "togglesystem", rbac::RBAC_PERM_COMMAND_TICKET_TOGGLESYSTEM, true, &HandleToggleGMTicketSystem, "" }, + { "unassign", rbac::RBAC_PERM_COMMAND_TICKET_UNASSIGN, true, &HandleGMTicketUnAssignCommand, "" }, + { "viewid", rbac::RBAC_PERM_COMMAND_TICKET_VIEWID, true, &HandleGMTicketGetByIdCommand, "" }, + { "viewname", rbac::RBAC_PERM_COMMAND_TICKET_VIEWNAME, true, &HandleGMTicketGetByNameCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "ticket", rbac::RBAC_PERM_COMMAND_TICKET, false, NULL, "", ticketCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -113,7 +110,7 @@ public: // If assigned to different player other than current, leave //! Console can override though - Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : NULL; + Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr; if (player && ticket->IsAssignedNotTo(player->GetGUID())) { handler->PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId(), target.c_str()); @@ -146,14 +143,14 @@ public: // Ticket should be assigned to the player who tries to close it. // Console can override though - Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : NULL; + Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr; if (player && ticket->IsAssignedNotTo(player->GetGUID())) { handler->PSendSysMessage(LANG_COMMAND_TICKETCANNOTCLOSE, ticket->GetId()); return true; } - sTicketMgr->CloseTicket(ticket->GetId(), player ? player->GetGUID() : ObjectGuid(uint64(-1))); + sTicketMgr->ResolveAndCloseTicket(ticket->GetId(), player ? player->GetGUID() : ObjectGuid(uint64(0))); sTicketMgr->UpdateLastChange(); std::string msg = ticket->FormatMessageString(*handler, player ? player->GetName().c_str() : "Console", NULL, NULL, NULL, NULL); @@ -190,7 +187,7 @@ public: // Cannot comment ticket assigned to someone else //! Console excluded - Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : NULL; + Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr; if (player && ticket->IsAssignedNotTo(player->GetGUID())) { handler->PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId()); @@ -220,7 +217,9 @@ public: if (!*args) return false; - uint32 ticketId = atoi(args); + char* ticketIdStr = strtok((char*)args, " "); + uint32 ticketId = atoi(ticketIdStr); + GmTicket* ticket = sTicketMgr->GetTicket(ticketId); if (!ticket || ticket->IsClosed() || ticket->IsCompleted()) { @@ -228,10 +227,28 @@ public: return true; } + char* response = strtok(NULL, "\n"); + if (response) + { + // Cannot add response to ticket, assigned to someone else + //! Console excluded + Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr; + if (player && ticket->IsAssignedNotTo(player->GetGUID())) + { + handler->PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId()); + return true; + } + + ticket->AppendResponse(response); + } + if (Player* player = ticket->GetPlayer()) ticket->SendResponse(player->GetSession()); + Player* gm = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr; + SQLTransaction trans = SQLTransaction(NULL); + ticket->SetResolvedBy(gm ? gm->GetGUID() : ObjectGuid(uint64(0))); ticket->SetCompleted(); ticket->SaveToDB(trans); @@ -476,7 +493,7 @@ public: // Cannot add response to ticket, assigned to someone else //! Console excluded - Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : NULL; + Player* player = handler->GetSession() ? handler->GetSession()->GetPlayer() : nullptr; if (player && ticket->IsAssignedNotTo(player->GetGUID())) { handler->PSendSysMessage(LANG_COMMAND_TICKETALREADYASSIGNED, ticket->GetId()); diff --git a/src/server/scripts/Commands/cs_titles.cpp b/src/server/scripts/Commands/cs_titles.cpp index 74a2f9f5aaf..bc6027ce3c3 100644 --- a/src/server/scripts/Commands/cs_titles.cpp +++ b/src/server/scripts/Commands/cs_titles.cpp @@ -33,25 +33,22 @@ class titles_commandscript : public CommandScript public: titles_commandscript() : CommandScript("titles_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand titlesSetCommandTable[] = + static std::vector<ChatCommand> titlesSetCommandTable = { - { "mask", rbac::RBAC_PERM_COMMAND_TITLES_SET_MASK, false, &HandleTitlesSetMaskCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "mask", rbac::RBAC_PERM_COMMAND_TITLES_SET_MASK, false, &HandleTitlesSetMaskCommand, "" }, }; - static ChatCommand titlesCommandTable[] = + static std::vector<ChatCommand> titlesCommandTable = { - { "add", rbac::RBAC_PERM_COMMAND_TITLES_ADD, false, &HandleTitlesAddCommand, "", NULL }, - { "current", rbac::RBAC_PERM_COMMAND_TITLES_CURRENT, false, &HandleTitlesCurrentCommand, "", NULL }, - { "remove", rbac::RBAC_PERM_COMMAND_TITLES_REMOVE, false, &HandleTitlesRemoveCommand, "", NULL }, + { "add", rbac::RBAC_PERM_COMMAND_TITLES_ADD, false, &HandleTitlesAddCommand, "" }, + { "current", rbac::RBAC_PERM_COMMAND_TITLES_CURRENT, false, &HandleTitlesCurrentCommand, "" }, + { "remove", rbac::RBAC_PERM_COMMAND_TITLES_REMOVE, false, &HandleTitlesRemoveCommand, "" }, { "set", rbac::RBAC_PERM_COMMAND_TITLES_SET, false, NULL, "", titlesSetCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "titles", rbac::RBAC_PERM_COMMAND_TITLES, false, NULL, "", titlesCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index c9da1ed9635..30ee8254f72 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -34,23 +34,21 @@ class wp_commandscript : public CommandScript public: wp_commandscript() : CommandScript("wp_commandscript") { } - ChatCommand* GetCommands() const override + std::vector<ChatCommand> GetCommands() const override { - static ChatCommand wpCommandTable[] = + static std::vector<ChatCommand> wpCommandTable = { - { "add", rbac::RBAC_PERM_COMMAND_WP_ADD, false, &HandleWpAddCommand, "", NULL }, - { "event", rbac::RBAC_PERM_COMMAND_WP_EVENT, false, &HandleWpEventCommand, "", NULL }, - { "load", rbac::RBAC_PERM_COMMAND_WP_LOAD, false, &HandleWpLoadCommand, "", NULL }, - { "modify", rbac::RBAC_PERM_COMMAND_WP_MODIFY, false, &HandleWpModifyCommand, "", NULL }, - { "unload", rbac::RBAC_PERM_COMMAND_WP_UNLOAD, false, &HandleWpUnLoadCommand, "", NULL }, - { "reload", rbac::RBAC_PERM_COMMAND_WP_RELOAD, false, &HandleWpReloadCommand, "", NULL }, - { "show", rbac::RBAC_PERM_COMMAND_WP_SHOW, false, &HandleWpShowCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", rbac::RBAC_PERM_COMMAND_WP_ADD, false, &HandleWpAddCommand, "" }, + { "event", rbac::RBAC_PERM_COMMAND_WP_EVENT, false, &HandleWpEventCommand, "" }, + { "load", rbac::RBAC_PERM_COMMAND_WP_LOAD, false, &HandleWpLoadCommand, "" }, + { "modify", rbac::RBAC_PERM_COMMAND_WP_MODIFY, false, &HandleWpModifyCommand, "" }, + { "unload", rbac::RBAC_PERM_COMMAND_WP_UNLOAD, false, &HandleWpUnLoadCommand, "" }, + { "reload", rbac::RBAC_PERM_COMMAND_WP_RELOAD, false, &HandleWpReloadCommand, "" }, + { "show", rbac::RBAC_PERM_COMMAND_WP_SHOW, false, &HandleWpShowCommand, "" }, }; - static ChatCommand commandTable[] = + static std::vector<ChatCommand> commandTable = { { "wp", rbac::RBAC_PERM_COMMAND_WP, false, NULL, "", wpCommandTable }, - { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -150,7 +148,7 @@ public: path_number = strtok((char*)args, " "); uint32 pathid = 0; - uint32 guidLow = 0; + ObjectGuid::LowType guidLow = 0; Creature* target = handler->getSelectedCreature(); // Did player provide a path_id? @@ -179,7 +177,7 @@ public: return true; } - guidLow = target->GetDBTableGUIDLow(); + guidLow = target->GetSpawnId(); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_ADDON_BY_GUID); @@ -246,7 +244,7 @@ public: return true; } - uint32 guildLow = target->GetDBTableGUIDLow(); + uint32 guildLow = target->GetSpawnId(); if (target->GetCreatureAddon()) { @@ -376,6 +374,12 @@ public: if (show == "del") { + if (!arg_id) + { + handler->SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r"); + return true; + } + id = atoi(arg_id); stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID); @@ -568,7 +572,7 @@ public: } // The visual waypoint - wpGuid = target->GetGUIDLow(); + wpGuid = target->GetGUID().GetCounter(); // User did select a visual waypoint? @@ -579,7 +583,7 @@ public: if (!result) { - handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow()); + handler->PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID().GetCounter()); // Select waypoint number from database // Since we compare float values, we have to deal with // some difficulties. @@ -628,7 +632,7 @@ 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))) + if (Creature* wpCreature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HighGuid::Unit, VISUAL_WAYPOINT, wpGuid))) { wpCreature->CombatStop(); wpCreature->DeleteFromDB(); @@ -661,7 +665,7 @@ public: // Respawn the owner of the waypoints if (wpGuid != 0) { - if (Creature* wpCreature = map->GetCreature(ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpGuid))) + if (Creature* wpCreature = map->GetCreature(ObjectGuid(HighGuid::Unit, VISUAL_WAYPOINT, wpGuid))) { wpCreature->CombatStop(); wpCreature->DeleteFromDB(); @@ -669,7 +673,7 @@ public: } // re-create Creature* wpCreature2 = new Creature(); - if (!wpCreature2->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation())) + 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; @@ -680,7 +684,7 @@ public: 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->GetDBTableGUIDLow(), map)) + if (!wpCreature2->LoadCreatureFromDB(wpCreature2->GetSpawnId(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; @@ -782,7 +786,7 @@ public: } stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_WAYPOINT_DATA_ALL_BY_WPGUID); - stmt->setUInt32(0, target->GetGUIDLow()); + stmt->setUInt32(0, target->GetGUID().GetCounter()); PreparedQueryResult result = WorldDatabase.Query(stmt); if (!result) @@ -842,7 +846,7 @@ public: { Field* fields = result2->Fetch(); uint32 wpguid = fields[0].GetUInt32(); - Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpguid)); + Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HighGuid::Unit, VISUAL_WAYPOINT, wpguid)); if (!creature) { @@ -886,7 +890,7 @@ public: float o = chr->GetOrientation(); Creature* wpCreature = new Creature(); - if (!wpCreature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) + if (!wpCreature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; @@ -895,14 +899,14 @@ public: // Set "wpguid" column to the visual waypoint stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID); - stmt->setInt32(0, int32(wpCreature->GetGUIDLow())); + stmt->setInt32(0, int32(wpCreature->GetGUID().GetCounter())); 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->GetDBTableGUIDLow(), map)) + if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; @@ -948,7 +952,7 @@ public: Map* map = chr->GetMap(); Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) + if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; @@ -956,7 +960,7 @@ public: } creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) + if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete creature; @@ -997,7 +1001,7 @@ public: Map* map = chr->GetMap(); Creature* creature = new Creature(); - if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) + if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, chr->GetPhaseMaskForSpawn(), id, x, y, z, o)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; @@ -1005,7 +1009,7 @@ public: } creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); - if (!creature->LoadCreatureFromDB(creature->GetDBTableGUIDLow(), map)) + if (!creature->LoadCreatureFromDB(creature->GetSpawnId(), map)) { handler->PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete creature; @@ -1037,8 +1041,8 @@ public: do { Field* fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, guid)); + ObjectGuid::LowType guid = fields[0].GetUInt32(); + Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HighGuid::Unit, VISUAL_WAYPOINT, guid)); if (!creature) { handler->PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp index dd49f01624b..9c9dfe38349 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp @@ -579,105 +579,6 @@ enum DughalQuests #define SAY_DUGHAL_FREE "Thank you, $N! I'm free!!!" #define GOSSIP_DUGHAL "You're free, Dughal! Get out of here!" -/* -class npc_dughal_stormwing : public CreatureScript -{ -public: - npc_dughal_stormwing() : CreatureScript("npc_dughal_stormwing") { } - - CreatureAI* GetAI(Creature* creature) const override - { - npc_dughal_stormwingAI* dughal_stormwingAI = new npc_dughal_stormwingAI(creature); - - dughal_stormwingAI->AddWaypoint(0, 280.42f, -82.86f, -77.12f, 0); - dughal_stormwingAI->AddWaypoint(1, 287.64f, -87.01f, -76.79f, 0); - dughal_stormwingAI->AddWaypoint(2, 354.63f, -64.95f, -67.53f, 0); - - return dughal_stormwingAI; - } - - 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(); - CAST_AI(npc_escort::npc_escortAI, (creature->AI()))->Start(false, true, player->GetGUID()); - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - instance->SetData(DATA_QUEST_JAIL_BREAK, ENCOUNTER_STATE_IN_PROGRESS); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUGHAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(2846, creature->GetGUID()); - } - return true; - } - - struct npc_dughal_stormwingAI : public npc_escortAI - { - npc_dughal_stormwingAI(Creature* creature) : npc_escortAI(creature) { } - - void WaypointReached(uint32 waypointId) override - { - switch (waypointId) - { - case 0: - me->Say(SAY_DUGHAL_FREE, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_OBJECTIVE_COMPLETED); - break; - case 2: - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); - break; - } - } - - void EnterCombat(Unit* who) override { } - void Reset() override { } - - void JustDied(Unit* killer) override - { - if (IsBeingEscorted && killer == me) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); - } - } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if ((instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& instance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_ENDED) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisible(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } - }; -}; - - */ - // 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 !?!!" @@ -694,168 +595,6 @@ enum MarshalWindsor NPC_REGINALD_WINDSOR = 9682 }; -/* -Player* playerStart; -class npc_marshal_windsor : public CreatureScript -{ -public: - npc_marshal_windsor() : CreatureScript("npc_marshal_windsor") { } - - CreatureAI* GetAI(Creature* creature) const override - { - npc_marshal_windsorAI* marshal_windsorAI = new npc_marshal_windsorAI(creature); - - marshal_windsorAI->AddWaypoint(0, 316.336f, -225.528f, -77.7258f, 7000); - marshal_windsorAI->AddWaypoint(1, 316.336f, -225.528f, -77.7258f, 2000); - marshal_windsorAI->AddWaypoint(2, 322.96f, -207.13f, -77.87f, 0); - marshal_windsorAI->AddWaypoint(3, 281.05f, -172.16f, -75.12f, 0); - marshal_windsorAI->AddWaypoint(4, 272.19f, -139.14f, -70.61f, 0); - marshal_windsorAI->AddWaypoint(5, 283.62f, -116.09f, -70.21f, 0); - marshal_windsorAI->AddWaypoint(6, 296.18f, -94.30f, -74.08f, 0); - marshal_windsorAI->AddWaypoint(7, 294.57f, -93.11f, -74.08f, 0); - marshal_windsorAI->AddWaypoint(8, 314.31f, -74.31f, -76.09f, 0); - marshal_windsorAI->AddWaypoint(9, 360.22f, -62.93f, -66.77f, 0); - marshal_windsorAI->AddWaypoint(10, 383.38f, -69.40f, -63.25f, 0); - marshal_windsorAI->AddWaypoint(11, 389.99f, -67.86f, -62.57f, 0); - marshal_windsorAI->AddWaypoint(12, 400.98f, -72.01f, -62.31f, 0); - marshal_windsorAI->AddWaypoint(13, 404.22f, -62.30f, -63.50f, 2300); - marshal_windsorAI->AddWaypoint(14, 404.22f, -62.30f, -63.50f, 1500); - marshal_windsorAI->AddWaypoint(15, 407.65f, -51.86f, -63.96f, 0); - marshal_windsorAI->AddWaypoint(16, 403.61f, -51.71f, -63.92f, 1000); - marshal_windsorAI->AddWaypoint(17, 403.61f, -51.71f, -63.92f, 2000); - marshal_windsorAI->AddWaypoint(18, 403.61f, -51.71f, -63.92f, 1000); - marshal_windsorAI->AddWaypoint(19, 403.61f, -51.71f, -63.92f, 0); - - return marshal_windsorAI; - } - - bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override - { - if (quest->GetQuestId() == 4322) - { - PlayerStart = player; - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - { - CAST_AI(npc_escort::npc_escortAI, (creature->AI()))->Start(true, false, player->GetGUID()); - instance->SetData(DATA_QUEST_JAIL_BREAK, ENCOUNTER_STATE_IN_PROGRESS); - creature->setFaction(11); - } - } - return false; - } - - struct npc_marshal_windsorAI : public npc_escortAI - { - npc_marshal_windsorAI(Creature* creature) : npc_escortAI(creature) - { - instance = creature->GetInstanceScript(); - } - - void WaypointReached(uint32 waypointId) override - { - switch (waypointId) - { - case 1: - me->Say(SAY_WINDSOR_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 7: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_WINDSOR_4_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold = true; - break; - case 10: - me->setFaction(534); - break; - case 12: - me->Say(SAY_WINDSOR_6, LANG_UNIVERSAL, PlayerGUID); - instance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_IN_PROGRESS); - break; - case 13: - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK - break; - case 14: - instance->SetData(DATA_GATE_SR, 0); - me->setFaction(11); - break; - case 16: - me->Say(SAY_WINDSOR_9, LANG_UNIVERSAL, PlayerGUID); - break; - case 17: - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK - break; - case 18: - instance->SetData(DATA_GATE_SC, 0); - break; - case 19: - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SummonCreature(NPC_REGINALD_WINDSOR, 403.61f, -51.71f, -63.92f, 3.600434f, TEMPSUMMON_DEAD_DESPAWN, 0); - instance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_ENDED); - break; - } - } - - void EnterCombat(Unit* who) override - { - switch (urand(0, 2)) - { - case 0: - me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); - break; - case 2: - me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); - break; - } - } - - void Reset() override { } - - void JustDied(Unit* slayer) override - { - instance->SetData(DATA_QUEST_JAIL_BREAK, ENCOUNTER_STATE_FAILED); - } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - return; - - if (instance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) - SetEscortPaused(false); - - if (!instance->GetData(DATA_GATE_D) && instance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_NOT_STARTED) - { - me->Say(SAY_WINDSOR_4_2, LANG_UNIVERSAL, PlayerGUID); - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_BEFORE_START); - } - if (instance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) - { - me->Say(SAY_WINDSOR_4_3, LANG_UNIVERSAL, PlayerGUID); - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); - } - if ((instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& instance->GetData(DATA_SUPPLY_ROOM) == ENCOUNTER_STATE_ENDED) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisible(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } - }; -}; - - */ - // 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!" @@ -878,320 +617,6 @@ enum MarshalReginaldWindor NPC_CREST_KILLER = 9680 }; -/* -int wp = 0; -class npc_marshal_reginald_windsor : public CreatureScript -{ -public: - npc_marshal_reginald_windsor() : CreatureScript("npc_marshal_reginald_windsor") { } - - CreatureAI* GetAI(Creature* creature) const override - { - npc_marshal_reginald_windsorAI* marshal_reginald_windsorAI = new npc_marshal_reginald_windsorAI(creature); - - marshal_reginald_windsorAI->AddWaypoint(0, 403.61f, -52.71f, -63.92f, 4000); - marshal_reginald_windsorAI->AddWaypoint(1, 403.61f, -52.71f, -63.92f, 4000); - marshal_reginald_windsorAI->AddWaypoint(2, 406.33f, -54.87f, -63.95f, 0); - marshal_reginald_windsorAI->AddWaypoint(3, 407.99f, -73.91f, -62.26f, 0); - marshal_reginald_windsorAI->AddWaypoint(4, 557.03f, -119.71f, -61.83f, 0); - marshal_reginald_windsorAI->AddWaypoint(5, 573.40f, -124.39f, -65.07f, 0); - marshal_reginald_windsorAI->AddWaypoint(6, 593.91f, -130.29f, -69.25f, 0); - marshal_reginald_windsorAI->AddWaypoint(7, 593.21f, -132.16f, -69.25f, 0); - marshal_reginald_windsorAI->AddWaypoint(8, 593.21f, -132.16f, -69.25f, 3000); - marshal_reginald_windsorAI->AddWaypoint(9, 622.81f, -135.55f, -71.92f, 0); - marshal_reginald_windsorAI->AddWaypoint(10, 634.68f, -151.29f, -70.32f, 0); - marshal_reginald_windsorAI->AddWaypoint(11, 635.06f, -153.25f, -70.32f, 0); - marshal_reginald_windsorAI->AddWaypoint(12, 635.06f, -153.25f, -70.32f, 3000); - marshal_reginald_windsorAI->AddWaypoint(13, 635.06f, -153.25f, -70.32f, 1500); - marshal_reginald_windsorAI->AddWaypoint(14, 655.25f, -172.39f, -73.72f, 0); - marshal_reginald_windsorAI->AddWaypoint(15, 654.79f, -226.30f, -83.06f, 0); - marshal_reginald_windsorAI->AddWaypoint(16, 622.85f, -268.85f, -83.96f, 0); - marshal_reginald_windsorAI->AddWaypoint(17, 579.45f, -275.56f, -80.44f, 0); - marshal_reginald_windsorAI->AddWaypoint(18, 561.19f, -266.85f, -75.59f, 0); - marshal_reginald_windsorAI->AddWaypoint(19, 547.91f, -253.92f, -70.34f, 0); - marshal_reginald_windsorAI->AddWaypoint(20, 549.20f, -252.40f, -70.34f, 0); - marshal_reginald_windsorAI->AddWaypoint(21, 549.20f, -252.40f, -70.34f, 4000); - marshal_reginald_windsorAI->AddWaypoint(22, 555.33f, -269.16f, -74.40f, 0); - marshal_reginald_windsorAI->AddWaypoint(23, 554.31f, -270.88f, -74.40f, 0); - marshal_reginald_windsorAI->AddWaypoint(24, 554.31f, -270.88f, -74.40f, 4000); - marshal_reginald_windsorAI->AddWaypoint(25, 536.10f, -249.60f, -67.47f, 0); - marshal_reginald_windsorAI->AddWaypoint(26, 520.94f, -216.65f, -59.28f, 0); - marshal_reginald_windsorAI->AddWaypoint(27, 505.99f, -148.74f, -62.17f, 0); - marshal_reginald_windsorAI->AddWaypoint(28, 484.21f, -56.24f, -62.43f, 0); - marshal_reginald_windsorAI->AddWaypoint(29, 470.39f, -6.01f, -70.10f, 0); - marshal_reginald_windsorAI->AddWaypoint(30, 451.27f, 30.85f, -70.07f, 0); - marshal_reginald_windsorAI->AddWaypoint(31, 452.45f, 29.85f, -70.37f, 1500); - marshal_reginald_windsorAI->AddWaypoint(32, 452.45f, 29.85f, -70.37f, 7000); - marshal_reginald_windsorAI->AddWaypoint(33, 452.45f, 29.85f, -70.37f, 10000); - marshal_reginald_windsorAI->AddWaypoint(34, 451.27f, 31.85f, -70.07f, 0); - - return marshal_reginald_windsorAI; - } - - struct npc_marshal_reginald_windsorAI : public npc_escortAI - { - npc_marshal_reginald_windsorAI(Creature* creature) : npc_escortAI(creature) - { - } - - void WaypointReached(uint32 waypointId) override - { - wp = waypointId; - switch (waypointId) - { - case 0: - me->setFaction(11); - me->Say(SAY_REGINALD_WINDSOR_0_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - me->Say(SAY_REGINALD_WINDSOR_0_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 7: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_5_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 8: - me->Say(SAY_REGINALD_WINDSOR_5_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 11: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_7_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 12: - me->Say(SAY_REGINALD_WINDSOR_7_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 13: - me->Say(SAY_REGINALD_WINDSOR_7_3, LANG_UNIVERSAL, PlayerGUID); - break; - case 20: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_13_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 21: - me->Say(SAY_REGINALD_WINDSOR_13_3, LANG_UNIVERSAL, PlayerGUID); - break; - case 23: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_14_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 24: - me->Say(SAY_REGINALD_WINDSOR_14_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 31: - me->Say(SAY_REGINALD_WINDSOR_20_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 32: - me->Say(SAY_REGINALD_WINDSOR_20_2, LANG_UNIVERSAL, PlayerGUID); - PlayerStart->GroupEventHappens(QUEST_JAIL_BREAK, me); - instance->SetData(DATA_SHILL, ENCOUNTER_STATE_ENDED); - break; - } - } - - void MoveInLineOfSight(Unit* who) override - - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - if (Player* player = who->ToPlayer()) - { - if (player->GetQuestStatus(4322) == QUEST_STATUS_INCOMPLETE) - { - float Radius = 10.0f; - if (me->IsWithinDistInMap(who, Radius)) - { - SetEscortPaused(false); - Start(true, false, who->GetGUID()); - } - } - } - } - - void EnterCombat(Unit* who) override - { - switch (urand(0, 2)) - { - case 0: - me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); - break; - case 2: - me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); - break; - } - } - void Reset() override { } - - void JustDied(Unit* slayer) override - { - instance->SetData(DATA_QUEST_JAIL_BREAK, ENCOUNTER_STATE_FAILED); - } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - return; - - if (wp == 7) - { - if (!instance->GetData(DATA_GATE_J) && instance->GetData(DATA_JAZ) == ENCOUNTER_STATE_NOT_STARTED) - { - instance->SetData(DATA_NPC_JAZ, 1); - instance->SetData(DATA_JAZ, ENCOUNTER_STATE_IN_PROGRESS); - } - if (instance->GetData(DATA_NPC_JAZ) && instance->GetData(DATA_NPC_OGRABISI) && instance->GetData(DATA_JAZ) == ENCOUNTER_STATE_IN_PROGRESS) - { - SetEscortPaused(false); - instance->SetData(DATA_JAZ, ENCOUNTER_STATE_ENDED); - } - } - else if (wp == 11) - { - if (!instance->GetData(DATA_GATE_S) && instance->GetData(DATA_SHILL) == ENCOUNTER_STATE_NOT_STARTED) - { - instance->SetData(DATA_NPC_SHILL, 1); - instance->SetData(DATA_SHILL, ENCOUNTER_STATE_IN_PROGRESS); - } - if (instance->GetData(DATA_NPC_SHILL) && instance->GetData(DATA_SHILL) == ENCOUNTER_STATE_IN_PROGRESS) - { - instance->SetData(DATA_SHILL, ENCOUNTER_STATE_ENDED); - SetEscortPaused(false); - } - } - else if (wp == 20) - { - if (!instance->GetData(DATA_GATE_C) && instance->GetData(DATA_CREST) == ENCOUNTER_STATE_NOT_STARTED) - { - instance->SetData(DATA_NPC_CREST, 1); - me->Say(SAY_REGINALD_WINDSOR_13_2, LANG_UNIVERSAL, PlayerGUID); - instance->SetData(DATA_CREST, ENCOUNTER_STATE_IN_PROGRESS); - } - if (instance->GetData(DATA_NPC_CREST) && instance->GetData(DATA_CREST) == ENCOUNTER_STATE_IN_PROGRESS) - { - SetEscortPaused(false); - instance->SetData(DATA_CREST, ENCOUNTER_STATE_ENDED); - } - } - if (instance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) SetEscortPaused(false); - npc_escortAI::UpdateAI(diff); - } - }; -}; -*/ - -// npc_tobias_seecher -#define SAY_TOBIAS_FREE "Thank you! I will run for safety immediately!" - -/* -class npc_tobias_seecher : public CreatureScript -{ -public: - npc_tobias_seecher() : CreatureScript("npc_tobias_seecher") { } - - CreatureAI* GetAI(Creature* creature) const override - { - npc_tobias_seecherAI* tobias_seecherAI = new npc_tobias_seecherAI(creature); - - tobias_seecherAI->AddWaypoint(0, 549.21f, -281.07f, -75.27f); - tobias_seecherAI->AddWaypoint(1, 554.39f, -267.39f, -73.68f); - tobias_seecherAI->AddWaypoint(2, 533.59f, -249.38f, -67.04f); - tobias_seecherAI->AddWaypoint(3, 519.44f, -217.02f, -59.34f); - tobias_seecherAI->AddWaypoint(4, 506.55f, -153.49f, -62.34f); - - return tobias_seecherAI; - } - - 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(); - CAST_AI(npc_escort::npc_escortAI, (creature->AI()))->Start(false, true, player->GetGUID()); - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - instance->SetData(DATA_TOBIAS, ENCOUNTER_STATE_IN_PROGRESS); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Get out of here, Tobias, you're free!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(2847, creature->GetGUID()); - } - return true; - } - - struct npc_tobias_seecherAI : public npc_escortAI - { - npc_tobias_seecherAI(Creature* creature) : npc_escortAI(creature) { } - - void EnterCombat(Unit* who) override { } - void Reset() override { } - - void JustDied(Unit* killer) override - { - if (IsBeingEscorted && killer == me) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_TOBIAS, ENCOUNTER_STATE_ENDED); - } - } - - void WaypointReached(uint32 waypointId) override - { - switch (waypointId) - { - case 0: - me->Say(SAY_TOBIAS_FREE, LANG_UNIVERSAL, PlayerGUID); - break; - case 2: - instance->SetData(DATA_TOBIAS, ENCOUNTER_STATE_OBJECTIVE_COMPLETED); - break; - case 4: - me->SetVisible(false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_TOBIAS, ENCOUNTER_STATE_ENDED); - break; - } - } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - return; - - if ((instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& instance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_ENDED) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisible(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } - }; -}; - -*/ - // npc_rocknot enum RocknotSays { @@ -1349,10 +774,4 @@ void AddSC_blackrock_depths() new npc_kharan_mighthammer(); new npc_lokhtos_darkbargainer(); new npc_rocknot(); - // Fix us - /*new npc_dughal_stormwing(); - new npc_tobias_seecher(); - new npc_marshal_windsor(); - new npc_marshal_reginald_windsor(); - */ } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp deleted file mode 100644 index c2261785782..00000000000 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2008-2015 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" - -enum Spells -{ - SPELL_SHADOWBOLT = 17228, - SPELL_CURSEOFTONGUES = 15470, - SPELL_CURSEOFWEAKNESS = 17227, - SPELL_DEMONARMOR = 11735, - SPELL_ENVELOPINGWEB = 15471 -}; - -enum Events -{ - EVENT_SHADOWBOLT = 1, - EVENT_CURSE_OF_TONGUES = 2, - EVENT_CURSE_OF_WEAKNESS = 3, - EVENT_DEMON_ARMOR = 4, - EVENT_ENVELOPING_WEB = 5 -}; - -class boss_anubshiah : public CreatureScript -{ - public: - boss_anubshiah() : CreatureScript("boss_anubshiah") { } - - struct boss_anubshiahAI : public ScriptedAI - { - boss_anubshiahAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - _events.Reset(); - } - - void EnterCombat(Unit* /*who*/) override - { - _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000); - _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 24000); - _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 12000); - _events.ScheduleEvent(EVENT_DEMON_ARMOR, 3000); - _events.ScheduleEvent(EVENT_ENVELOPING_WEB, 16000); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_SHADOWBOLT: - DoCast(me, SPELL_SHADOWBOLT); - _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000); - break; - case EVENT_CURSE_OF_TONGUES: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_CURSEOFTONGUES); - _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 18000); - break; - case EVENT_CURSE_OF_WEAKNESS: - DoCastVictim(SPELL_CURSEOFWEAKNESS); - _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 45000); - break; - case EVENT_DEMON_ARMOR: - DoCast(me, SPELL_DEMONARMOR); - _events.ScheduleEvent(EVENT_DEMON_ARMOR, 300000); - break; - case EVENT_ENVELOPING_WEB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_ENVELOPINGWEB); - _events.ScheduleEvent(EVENT_ENVELOPING_WEB, 12000); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_anubshiahAI(creature); - } -}; - -void AddSC_boss_anubshiah() -{ - new boss_anubshiah(); -} diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp deleted file mode 100644 index 83702ffb16d..00000000000 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2008-2015 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" - -enum Spells -{ - SPELL_WHIRLWIND = 15589, - SPELL_MORTALSTRIKE = 24573 -}; - -enum Events -{ - EVENT_WHIRLWIND = 1, - EVENT_MORTALSTRIKE = 2 -}; - -class boss_gorosh_the_dervish : public CreatureScript -{ - public: - boss_gorosh_the_dervish() : CreatureScript("boss_gorosh_the_dervish") { } - - struct boss_gorosh_the_dervishAI : public ScriptedAI - { - boss_gorosh_the_dervishAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - _events.Reset(); - } - - void EnterCombat(Unit* /*who*/) override - { - _events.ScheduleEvent(EVENT_WHIRLWIND, 12000); - _events.ScheduleEvent(EVENT_MORTALSTRIKE, 22000); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_WHIRLWIND: - DoCast(me, SPELL_WHIRLWIND); - _events.ScheduleEvent(EVENT_WHIRLWIND, 15000); - break; - case EVENT_MORTALSTRIKE: - DoCastVictim(SPELL_MORTALSTRIKE); - _events.ScheduleEvent(EVENT_MORTALSTRIKE, 15000); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_gorosh_the_dervishAI(creature); - } -}; - -void AddSC_boss_gorosh_the_dervish() -{ - new boss_gorosh_the_dervish(); -} diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp deleted file mode 100644 index 44dbbe3f4c2..00000000000 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008-2015 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" - -enum Grizzle -{ - SPELL_GROUNDTREMOR = 6524, - SPELL_FRENZY = 28371, - EMOTE_FRENZY_KILL = 0 -}; - -enum Events -{ - EVENT_GROUNDTREMOR = 1, - EVENT_FRENZY = 2 -}; - -enum Phases -{ - PHASE_ONE = 1, - PHASE_TWO = 2 -}; - -class boss_grizzle : public CreatureScript -{ - public: - boss_grizzle() : CreatureScript("boss_grizzle") { } - - struct boss_grizzleAI : public ScriptedAI - { - boss_grizzleAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - _events.Reset(); - } - - void EnterCombat(Unit* /*who*/) override - { - _events.SetPhase(PHASE_ONE); - _events.ScheduleEvent(EVENT_GROUNDTREMOR, 12000); - } - - void DamageTaken(Unit* /*attacker*/, uint32& damage) override - { - if (me->HealthBelowPctDamaged(50, damage) && _events.IsInPhase(PHASE_ONE)) - { - _events.SetPhase(PHASE_TWO); - _events.ScheduleEvent(EVENT_FRENZY, 0, 0, PHASE_TWO); - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_GROUNDTREMOR: - DoCastVictim(SPELL_GROUNDTREMOR); - _events.ScheduleEvent(EVENT_GROUNDTREMOR, 8000); - break; - case EVENT_FRENZY: - DoCast(me, SPELL_FRENZY); - Talk(EMOTE_FRENZY_KILL); - _events.ScheduleEvent(EVENT_FRENZY, 15000, 0, PHASE_TWO); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new boss_grizzleAI(creature); - } -}; - -void AddSC_boss_grizzle() -{ - new boss_grizzle(); -} diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h index c79a57d0746..12798833a3f 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h @@ -25,14 +25,18 @@ uint32 const EncounterCount = 8; enum BWLEncounter { - BOSS_RAZORGORE = 0, - BOSS_VAELASTRAZ = 1, - BOSS_BROODLORD = 2, - BOSS_FIREMAW = 3, - BOSS_EBONROC = 4, - BOSS_FLAMEGOR = 5, - BOSS_CHROMAGGUS = 6, - BOSS_NEFARIAN = 7 + // Encounter States/Boss GUIDs + DATA_RAZORGORE_THE_UNTAMED = 0, + DATA_VAELASTRAZ_THE_CORRUPT = 1, + DATA_BROODLORD_LASHLAYER = 2, + DATA_FIREMAW = 3, + DATA_EBONROC = 4, + DATA_FLAMEGOR = 5, + DATA_CHROMAGGUS = 6, + DATA_NEFARIAN = 7, + + // Additional Data + DATA_LORD_VICTOR_NEFARIUS = 8 }; enum CreatureIds @@ -44,7 +48,7 @@ enum CreatureIds NPC_BLACKWING_WARLOCK = 12459, NPC_VAELASTRAZ = 13020, NPC_BROODLORD = 12017, - NPC_FIRENAW = 11983, + NPC_FIREMAW = 11983, NPC_EBONROC = 14601, NPC_FLAMEGOR = 11981, NPC_CHROMAGGUS = 14020, @@ -52,17 +56,14 @@ enum CreatureIds NPC_NEFARIAN = 11583 }; -enum BWLData64 +enum GameObjectIds { - DATA_RAZORGORE_THE_UNTAMED = 1, - DATA_VAELASTRAZ_THE_CORRUPT, - DATA_BROODLORD_LASHLAYER, - DATA_FIRENAW, - DATA_EBONROC, - DATA_FLAMEGOR, - DATA_CHROMAGGUS, - DATA_LORD_VICTOR_NEFARIUS, - DATA_NEFARIAN + GO_BLACK_DRAGON_EGG = 177807, + GO_BOSSGATE01 = 175946, + GO_DRAKE_RIDER_PORTCULLIS = 175185, + GO_ALTERAC_VALLEY_GATE = 180424, + GO_GATE = 185483, + GO_VACCUUM_EXIT_GATE = 181125 }; enum BWLEvents @@ -79,4 +80,4 @@ enum BWLMisc DATA_EGG_EVENT }; -#endif
\ No newline at end of file +#endif diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp index 2609cf5fdf8..5ba933005ec 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -50,16 +50,10 @@ public: struct boss_broodlordAI : public BossAI { - boss_broodlordAI(Creature* creature) : BossAI(creature, BOSS_BROODLORD) { } + boss_broodlordAI(Creature* creature) : BossAI(creature, DATA_BROODLORD_LASHLAYER) { } void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_VAELASTRAZ) != DONE) - { - EnterEvadeMode(); - return; - } - _EnterCombat(); Talk(SAY_AGGRO); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp index 61d6c052cdf..9a49b96e68e 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp @@ -71,7 +71,7 @@ public: struct boss_chromaggusAI : public BossAI { - boss_chromaggusAI(Creature* creature) : BossAI(creature, BOSS_CHROMAGGUS) + boss_chromaggusAI(Creature* creature) : BossAI(creature, DATA_CHROMAGGUS) { Initialize(); @@ -193,11 +193,6 @@ public: void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_FLAMEGOR) != DONE) - { - EnterEvadeMode(); - return; - } _EnterCombat(); events.ScheduleEvent(EVENT_SHIMMER, 0); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp index 8bd3ae0ebce..7a7e30f7913 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp @@ -41,15 +41,10 @@ public: struct boss_ebonrocAI : public BossAI { - boss_ebonrocAI(Creature* creature) : BossAI(creature, BOSS_EBONROC) { } + boss_ebonrocAI(Creature* creature) : BossAI(creature, DATA_EBONROC) { } void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_BROODLORD) != DONE) - { - EnterEvadeMode(); - return; - } _EnterCombat(); events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp index e41153796e5..3dcdbfe01df 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp @@ -41,15 +41,10 @@ public: struct boss_firemawAI : public BossAI { - boss_firemawAI(Creature* creature) : BossAI(creature, BOSS_FIREMAW) { } + boss_firemawAI(Creature* creature) : BossAI(creature, DATA_FIREMAW) { } void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_BROODLORD) != DONE) - { - EnterEvadeMode(); - return; - } _EnterCombat(); events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp index 011c695b61f..20e69211da2 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp @@ -46,15 +46,10 @@ public: struct boss_flamegorAI : public BossAI { - boss_flamegorAI(Creature* creature) : BossAI(creature, BOSS_FLAMEGOR) { } + boss_flamegorAI(Creature* creature) : BossAI(creature, DATA_FLAMEGOR) { } void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_BROODLORD) != DONE) - { - EnterEvadeMode(); - return; - } _EnterCombat(); events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp index 1ff18b845a1..a89571e8197 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp @@ -166,7 +166,7 @@ public: struct boss_victor_nefariusAI : public BossAI { - boss_victor_nefariusAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) + boss_victor_nefariusAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN) { Initialize(); } @@ -367,9 +367,9 @@ public: } } - void sGossipSelect(Player* player, uint32 sender, uint32 action) override + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override { - if (sender == GOSSIP_ID && action == GOSSIP_OPTION_ID) + if (menuId == GOSSIP_ID && gossipListId == GOSSIP_OPTION_ID) { player->CLOSE_GOSSIP_MENU(); Talk(SAY_GAMESBEGIN_1); @@ -394,7 +394,7 @@ public: struct boss_nefarianAI : public BossAI { - boss_nefarianAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) + boss_nefarianAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN) { Initialize(); } @@ -458,7 +458,7 @@ public: { if (canDespawn && DespawnTimer <= diff) { - instance->SetBossState(BOSS_NEFARIAN, FAIL); + instance->SetBossState(DATA_NEFARIAN, FAIL); std::list<Creature*> constructList; me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp index 8d660fc17d1..1d66964ce6b 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp @@ -68,7 +68,7 @@ public: struct boss_razorgoreAI : public BossAI { - boss_razorgoreAI(Creature* creature) : BossAI(creature, BOSS_RAZORGORE) + boss_razorgoreAI(Creature* creature) : BossAI(creature, DATA_RAZORGORE_THE_UNTAMED) { Initialize(); } @@ -175,7 +175,7 @@ public: { if (InstanceScript* instance = go->GetInstanceScript()) if (instance->GetData(DATA_EGG_EVENT) != DONE) - if (Creature* razor = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_RAZORGORE_THE_UNTAMED))) + if (Creature* razor = instance->GetCreature(DATA_RAZORGORE_THE_UNTAMED)) { razor->Attack(player, true); player->CastSpell(razor, SPELL_MINDCONTROL); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp index 0a2a245ece6..76ab4736275 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp @@ -68,7 +68,7 @@ public: struct boss_vaelAI : public BossAI { - boss_vaelAI(Creature* creature) : BossAI(creature, BOSS_VAELASTRAZ) + boss_vaelAI(Creature* creature) : BossAI(creature, DATA_VAELASTRAZ_THE_CORRUPT) { Initialize(); creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); @@ -221,9 +221,9 @@ public: DoMeleeAttackIfReady(); } - void sGossipSelect(Player* player, uint32 sender, uint32 action) override + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override { - if (sender == GOSSIP_ID && action == 0) + if (menuId == GOSSIP_ID && gossipListId == 0) { player->CLOSE_GOSSIP_MENU(); BeginSpeech(player); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp index 7e38a9265f7..97646b774eb 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp @@ -15,23 +15,36 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ScriptMgr.h" +#include "Player.h" #include "ScriptedCreature.h" -#include "PassiveAI.h" +#include "ScriptMgr.h" #include "blackwing_lair.h" -#include "Player.h" -/* -Blackwing Lair Encounter: -1 - boss_razorgore.cpp -2 - boss_vaelastrasz.cpp -3 - boss_broodlord_lashlayer.cpp -4 - boss_firemaw.cpp -5 - boss_ebonroc.cpp -6 - boss_flamegor.cpp -7 - boss_chromaggus.cpp -8 - boss_nefarian.cpp -*/ +DoorData const doorData[] = +{ + { GO_BOSSGATE01, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_DRAKE_RIDER_PORTCULLIS, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_ALTERAC_VALLEY_GATE, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GATE, DATA_FIREMAW, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GATE, DATA_EBONROC, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GATE, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_VACCUUM_EXIT_GATE, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; + +ObjectData const creatureData[] = +{ + { NPC_RAZORGORE, DATA_RAZORGORE_THE_UNTAMED }, + { NPC_VAELASTRAZ, DATA_VAELASTRAZ_THE_CORRUPT }, + { NPC_BROODLORD, DATA_BROODLORD_LASHLAYER }, + { NPC_FIREMAW, DATA_FIREMAW }, + { NPC_EBONROC, DATA_EBONROC }, + { NPC_FLAMEGOR, DATA_FLAMEGOR }, + { NPC_CHROMAGGUS, DATA_CHROMAGGUS }, + { NPC_NEFARIAN, DATA_NEFARIAN }, + { NPC_VICTOR_NEFARIUS, DATA_LORD_VICTOR_NEFARIUS }, + { 0, 0 } // END +}; Position const SummonPosition[8] = { @@ -57,92 +70,84 @@ public: instance_blackwing_lair_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadDoorData(doorData); + LoadObjectData(creatureData, nullptr); + // Razorgore EggCount = 0; EggEvent = 0; - SetBossNumber(EncounterCount); } void OnCreatureCreate(Creature* creature) override { + InstanceScript::OnCreatureCreate(creature); + switch (creature->GetEntry()) { - case NPC_RAZORGORE: - RazorgoreTheUntamedGUID = creature->GetGUID(); - break; case NPC_BLACKWING_DRAGON: case NPC_BLACKWING_TASKMASTER: case NPC_BLACKWING_LEGIONAIRE: case NPC_BLACKWING_WARLOCK: - if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + if (Creature* razor = GetCreature(DATA_RAZORGORE_THE_UNTAMED)) razor->AI()->JustSummoned(creature); break; - case NPC_VAELASTRAZ: - VaelastraszTheCorruptGUID = creature->GetGUID(); - break; - case NPC_BROODLORD: - BroodlordLashlayerGUID = creature->GetGUID(); - break; - case NPC_FIRENAW: - FiremawGUID = creature->GetGUID(); - break; - case NPC_EBONROC: - EbonrocGUID = creature->GetGUID(); - break; - case NPC_FLAMEGOR: - FlamegorGUID = creature->GetGUID(); - break; - case NPC_CHROMAGGUS: - ChromaggusGUID = creature->GetGUID(); - break; - case NPC_VICTOR_NEFARIUS: - LordVictorNefariusGUID = creature->GetGUID(); - break; - case NPC_NEFARIAN: - NefarianGUID = creature->GetGUID(); + default: break; } } void OnGameObjectCreate(GameObject* go) override { - switch (go->GetEntry()) + InstanceScript::OnGameObjectCreate(go); + + if (go->GetEntry() == GO_BLACK_DRAGON_EGG) { - case 177807: // Egg - if (GetBossState(BOSS_FIREMAW) == DONE) - go->SetPhaseMask(2, true); - else - EggList.push_back(go->GetGUID()); - break; - case 175946: // Door - RazorgoreDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_RAZORGORE) == DONE, go); - break; - case 175185: // Door - VaelastraszDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_VAELASTRAZ) == DONE, go); - break; - case 180424: // Door - BroodlordDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_BROODLORD) == DONE, go); - break; - case 185483: // Door - ChrommagusDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_FIREMAW) == DONE && GetBossState(BOSS_EBONROC) == DONE && GetBossState(BOSS_FLAMEGOR) == DONE, go); - break; - case 181125: // Door - NefarianDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_CHROMAGGUS) == DONE, go); - break; + if (GetBossState(DATA_FIREMAW) == DONE) + go->SetPhaseMask(2, true); + else + EggList.push_back(go->GetGUID()); } } void OnGameObjectRemove(GameObject* go) override { - if (go->GetEntry() == 177807) // Egg + InstanceScript::OnGameObjectRemove(go); + + if (go->GetEntry() == GO_BLACK_DRAGON_EGG) EggList.remove(go->GetGUID()); } + bool CheckRequiredBosses(uint32 bossId, Player const* player /*= nullptr*/) const override + { + if (_SkipCheckRequiredBosses(player)) + return true; + + switch (bossId) + { + case DATA_BROODLORD_LASHLAYER: + if (GetBossState(DATA_VAELASTRAZ_THE_CORRUPT) != DONE) + return false; + break; + case DATA_FIREMAW: + case DATA_EBONROC: + case DATA_FLAMEGOR: + if (GetBossState(DATA_BROODLORD_LASHLAYER) != DONE) + return false; + break; + case DATA_CHROMAGGUS: + if (GetBossState(DATA_FIREMAW) != DONE + || GetBossState(DATA_EBONROC) != DONE + || GetBossState(DATA_FLAMEGOR) != DONE) + return false; + break; + default: + break; + } + + return true; + } + bool SetBossState(uint32 type, EncounterState state) override { if (!InstanceScript::SetBossState(type, state)) @@ -150,40 +155,25 @@ public: switch (type) { - case BOSS_RAZORGORE: - HandleGameObject(RazorgoreDoorGUID, state == DONE); + case DATA_RAZORGORE_THE_UNTAMED: if (state == DONE) { for (GuidList::const_iterator itr = EggList.begin(); itr != EggList.end(); ++itr) - if (GameObject* egg = instance->GetGameObject((*itr))) + if (GameObject* egg = instance->GetGameObject(*itr)) egg->SetPhaseMask(2, true); } SetData(DATA_EGG_EVENT, NOT_STARTED); break; - case BOSS_VAELASTRAZ: - HandleGameObject(VaelastraszDoorGUID, state == DONE); - break; - case BOSS_BROODLORD: - HandleGameObject(BroodlordDoorGUID, state == DONE); - break; - case BOSS_FIREMAW: - case BOSS_EBONROC: - case BOSS_FLAMEGOR: - HandleGameObject(ChrommagusDoorGUID, GetBossState(BOSS_FIREMAW) == DONE && GetBossState(BOSS_EBONROC) == DONE && GetBossState(BOSS_FLAMEGOR) == DONE); - break; - case BOSS_CHROMAGGUS: - HandleGameObject(NefarianDoorGUID, state == DONE); - break; - case BOSS_NEFARIAN: + case DATA_NEFARIAN: switch (state) { case NOT_STARTED: - if (Creature* nefarian = instance->GetCreature(NefarianGUID)) + if (Creature* nefarian = GetCreature(DATA_NEFARIAN)) nefarian->DespawnOrUnsummon(); break; case FAIL: - _events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15*IN_MILLISECONDS*MINUTE); - SetBossState(BOSS_NEFARIAN, NOT_STARTED); + _events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15 * IN_MILLISECONDS * MINUTE); + SetBossState(DATA_NEFARIAN, NOT_STARTED); break; default: break; @@ -193,24 +183,6 @@ public: return true; } - ObjectGuid GetGuidData(uint32 id) const override - { - switch (id) - { - case DATA_RAZORGORE_THE_UNTAMED: return RazorgoreTheUntamedGUID; - case DATA_VAELASTRAZ_THE_CORRUPT: return VaelastraszTheCorruptGUID; - case DATA_BROODLORD_LASHLAYER: return BroodlordLashlayerGUID; - case DATA_FIRENAW: return FiremawGUID; - case DATA_EBONROC: return EbonrocGUID; - case DATA_FLAMEGOR: return FlamegorGUID; - case DATA_CHROMAGGUS: return ChromaggusGUID; - case DATA_LORD_VICTOR_NEFARIUS: return LordVictorNefariusGUID; - case DATA_NEFARIAN: return NefarianGUID; - } - - return ObjectGuid::Empty; - } - void SetData(uint32 type, uint32 data) override { if (type == DATA_EGG_EVENT) @@ -218,7 +190,7 @@ public: switch (data) { case IN_PROGRESS: - _events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45*IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45 * IN_MILLISECONDS); EggEvent = data; EggCount = 0; break; @@ -230,13 +202,13 @@ public: case SPECIAL: if (++EggCount == 15) { - if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + if (Creature* razor = GetCreature(DATA_RAZORGORE_THE_UNTAMED)) { SetData(DATA_EGG_EVENT, DONE); razor->RemoveAurasDueToSpell(42013); // MindControl DoRemoveAurasDueToSpellOnPlayers(42013); } - _events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, 1 * IN_MILLISECONDS); _events.CancelEvent(EVENT_RAZOR_SPAWN); } if (EggEvent == NOT_STARTED) @@ -249,8 +221,8 @@ public: void OnUnitDeath(Unit* unit) override { //! HACK, needed because of buggy CreatureAI after charm - if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(BOSS_RAZORGORE) != DONE) - SetBossState(BOSS_RAZORGORE, DONE); + if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(DATA_RAZORGORE_THE_UNTAMED) != DONE) + SetBossState(DATA_RAZORGORE_THE_UNTAMED, DONE); } void Update(uint32 diff) override @@ -268,15 +240,15 @@ public: for (uint8 i = urand(2, 5); i > 0 ; --i) if (Creature* summon = instance->SummonCreature(Entry[urand(0, 4)], SummonPosition[urand(0, 7)])) summon->SetInCombatWithZone(); - _events.ScheduleEvent(EVENT_RAZOR_SPAWN, urand(12, 17)*IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_RAZOR_SPAWN, urand(12, 17) * IN_MILLISECONDS); break; case EVENT_RAZOR_PHASE_TWO: _events.CancelEvent(EVENT_RAZOR_SPAWN); - if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + if (Creature* razor = GetCreature(DATA_RAZORGORE_THE_UNTAMED)) razor->AI()->DoAction(ACTION_PHASE_TWO); break; case EVENT_RESPAWN_NEFARIUS: - if (Creature* nefarius = instance->GetCreature(LordVictorNefariusGUID)) + if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS)) { nefarius->SetPhaseMask(1, true); nefarius->setActive(true); @@ -291,34 +263,11 @@ public: protected: // Misc EventMap _events; + // Razorgore uint8 EggCount; uint32 EggEvent; - ObjectGuid RazorgoreTheUntamedGUID; - ObjectGuid RazorgoreDoorGUID; GuidList EggList; - - // Vaelastrasz the Corrupt - ObjectGuid VaelastraszTheCorruptGUID; - ObjectGuid VaelastraszDoorGUID; - - // Broodlord Lashlayer - ObjectGuid BroodlordLashlayerGUID; - ObjectGuid BroodlordDoorGUID; - - // 3 Dragons - ObjectGuid FiremawGUID; - ObjectGuid EbonrocGUID; - ObjectGuid FlamegorGUID; - ObjectGuid ChrommagusDoorGUID; - - // Chormaggus - ObjectGuid ChromaggusGUID; - ObjectGuid NefarianDoorGUID; - - // Nefarian - ObjectGuid LordVictorNefariusGUID; - ObjectGuid NefarianGUID; }; InstanceScript* GetInstanceScript(InstanceMap* map) 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 9fd81b6a0f6..e2202a7e526 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -86,6 +86,7 @@ class boss_ragnaros : public CreatureScript _introState = 0; me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); } void Initialize() diff --git a/src/server/scripts/EasternKingdoms/CMakeLists.txt b/src/server/scripts/EasternKingdoms/CMakeLists.txt index fdebfca7979..76e4d36e0a9 100644 --- a/src/server/scripts/EasternKingdoms/CMakeLists.txt +++ b/src/server/scripts/EasternKingdoms/CMakeLists.txt @@ -17,12 +17,9 @@ set(scripts_STAT_SRCS EasternKingdoms/AlteracValley/boss_vanndar.cpp EasternKingdoms/AlteracValley/alterac_valley.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp - EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index 5ad5a3782ae..c1470d3bc47 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -203,10 +203,6 @@ public: void AggroAllPlayers(Creature* temp) { Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) { if (Player* player = i->GetSource()) @@ -365,7 +361,7 @@ public: } } - void UpdateEscortAI(const uint32 uiDiff) override + void UpdateEscortAI(uint32 uiDiff) override { if (uiPhase) { diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp index 0b5c3302890..96c7c5d8102 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp @@ -108,7 +108,7 @@ public: { Talk(SAY_DEATH); if (Unit* midnight = ObjectAccessor::GetUnit(*me, Midnight)) - midnight->Kill(midnight); + midnight->KillSelf(); } void UpdateAI(uint32 diff) override; @@ -264,7 +264,7 @@ void boss_attumen::boss_attumenAI::UpdateAI(uint32 diff) } Midnight.Clear(); me->SetVisible(false); - me->Kill(me); + me->KillSelf(); } else ResetTimer -= diff; } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp index 8965b64767a..0a287173ada 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp @@ -181,23 +181,21 @@ public: // temporary store for the best suitable beam reciever Unit* target = me; - if (Map* map = me->GetMap()) - { - Map::PlayerList const& players = map->GetPlayers(); + Map::PlayerList const& players = me->GetMap()->GetPlayers(); - // get the best suitable target - for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) - { - Player* p = i->GetSource(); - if (p && p->IsAlive() // alive - && (!target || target->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best - && !p->HasAura(PlayerDebuff[j]) // not exhausted - && !p->HasAura(PlayerBuff[(j + 1) % 3]) // not on another beam - && !p->HasAura(PlayerBuff[(j + 2) % 3]) - && IsBetween(me, p, portal)) // on the beam - target = p; - } + // get the best suitable target + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + Player* p = i->GetSource(); + if (p && p->IsAlive() // alive + && (!target || target->GetDistance2d(portal)>p->GetDistance2d(portal)) // closer than current best + && !p->HasAura(PlayerDebuff[j]) // not exhausted + && !p->HasAura(PlayerBuff[(j + 1) % 3]) // not on another beam + && !p->HasAura(PlayerBuff[(j + 2) % 3]) + && IsBetween(me, p, portal)) // on the beam + target = p; } + // buff the target if (target->GetTypeId() == TYPEID_PLAYER) target->AddAura(PlayerBuff[j], target); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp index 0abba3dfff4..d11c4a6e584 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp @@ -295,7 +295,7 @@ public: { Unit* axe = ObjectAccessor::GetUnit(*me, axes[i]); if (axe && axe->IsAlive()) - axe->Kill(axe); + axe->KillSelf(); axes[i].Clear(); } } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp index 92c3f83034d..8aba0a15462 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp @@ -25,7 +25,6 @@ EndScriptData */ /* ContentData npc_barnes -npc_berthold npc_image_of_medivh EndContentData */ @@ -310,11 +309,7 @@ public: { if (WipeTimer <= diff) { - Map* map = me->GetMap(); - if (!map->IsDungeon()) - return; - - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); if (PlayerList.isEmpty()) return; @@ -416,41 +411,6 @@ public: }; /*### -# npc_berthold -####*/ - -#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library" - -class npc_berthold : public CreatureScript -{ -public: - npc_berthold() : CreatureScript("npc_berthold") { } - - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF + 1) - player->CastSpell(player, SPELL_TELEPORT, true); - - player->CLOSE_GOSSIP_MENU(); - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (InstanceScript* instance = creature->GetInstanceScript()) - { - // Check if Shade of Aran event is done - if (instance->GetData(TYPE_ARAN) == DONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - } - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } -}; - -/*### # npc_image_of_medivh ####*/ @@ -552,32 +512,30 @@ public: YellTimer = 10000; } - uint32 NextStep(uint32 Step) + uint32 NextStep(uint32 step) { - Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID); - Map* map = me->GetMap(); - switch (Step) + switch (step) { case 0: return 9999999; case 1: me->Yell(SAY_DIALOG_MEDIVH_1, LANG_UNIVERSAL); return 10000; case 2: - if (arca) + if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID)) arca->Yell(SAY_DIALOG_ARCANAGOS_2, LANG_UNIVERSAL); return 20000; case 3: me->Yell(SAY_DIALOG_MEDIVH_3, LANG_UNIVERSAL); return 10000; case 4: - if (arca) + if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID)) arca->Yell(SAY_DIALOG_ARCANAGOS_4, LANG_UNIVERSAL); return 20000; case 5: me->Yell(SAY_DIALOG_MEDIVH_5, LANG_UNIVERSAL); return 20000; case 6: - if (arca) + if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID)) arca->Yell(SAY_DIALOG_ARCANAGOS_6, LANG_UNIVERSAL); return 10000; case 7: @@ -591,15 +549,15 @@ public: me->TextEmote(EMOTE_DIALOG_MEDIVH_7); return 10000; case 10: - if (arca) + if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID)) DoCast(arca, SPELL_CONFLAGRATION_BLAST, false); return 1000; case 11: - if (arca) + if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID)) arca->Yell(SAY_DIALOG_ARCANAGOS_8, LANG_UNIVERSAL); return 5000; case 12: - if (arca) + if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID)) { arca->GetMotionMaster()->MovePoint(0, -11010.82f, -1761.18f, 156.47f); arca->setActive(true); @@ -611,27 +569,27 @@ public: me->Yell(SAY_DIALOG_MEDIVH_9, LANG_UNIVERSAL); return 10000; case 14: + { me->SetVisible(false); me->ClearInCombat(); - if (map->IsDungeon()) + InstanceMap::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); + for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - InstanceMap::PlayerList const &PlayerList = map->GetPlayers(); - for (InstanceMap::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->GetSource()->IsAlive()) { - if (i->GetSource()->IsAlive()) - { - if (i->GetSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE) - i->GetSource()->CompleteQuest(9645); - } + if (i->GetSource()->GetQuestStatus(9645) == QUEST_STATUS_INCOMPLETE) + i->GetSource()->CompleteQuest(9645); } } return 50000; + } case 15: - if (arca) + if (Creature* arca = ObjectAccessor::GetCreature(*me, ArcanagosGUID)) arca->DealDamage(arca, arca->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return 5000; - default : return 9999999; + default: + return 9999999; } } @@ -668,6 +626,5 @@ public: void AddSC_karazhan() { new npc_barnes(); - new npc_berthold(); new npc_image_of_medivh(); } diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index a95ac9aaa20..e4cc7c0e84a 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -473,7 +473,7 @@ public: if (FlameStrikeTimer <= diff) { DoCast(me, SPELL_FLAMESTRIKE1_NORMAL, true); - me->Kill(me); + me->KillSelf(); } else FlameStrikeTimer -= diff; } }; @@ -636,7 +636,7 @@ public: if (HatchTimer <= diff) { me->SummonCreature(CREATURE_PHOENIX, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000); - me->Kill(me); + me->KillSelf(); } else HatchTimer -= diff; } }; @@ -675,7 +675,7 @@ public: void UpdateAI(uint32 diff) override { if (DespawnTimer <= diff) - me->Kill(me); + me->KillSelf(); else DespawnTimer -= diff; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp index f57de5316ab..480fd8848f5 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_selin_fireheart.cpp @@ -139,7 +139,7 @@ class boss_selin_fireheart : public CreatureScript for (Creature* crystal : Crystals) { if (crystal && crystal->IsAlive()) - crystal->Kill(crystal); + crystal->KillSelf(); } } @@ -218,7 +218,7 @@ class boss_selin_fireheart : public CreatureScript Creature* CrystalChosen = ObjectAccessor::GetCreature(*me, CrystalGUID); if (CrystalChosen && CrystalChosen->IsAlive()) - CrystalChosen->Kill(CrystalChosen); + CrystalChosen->KillSelf(); CrystalGUID.Clear(); diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp index 9b303fce89d..9c904dcada9 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/magisters_terrace.cpp @@ -145,39 +145,13 @@ public: m_uiTransformTimer = MINUTE*IN_MILLISECONDS; } - // some targeting issues with the spell, so use this workaround as temporary solution - void DoWorkaroundForQuestCredit() - { - Map* map = me->GetMap(); - - if (!map || map->IsHeroic()) - return; - - Map::PlayerList const &lList = map->GetPlayers(); - - if (lList.isEmpty()) - return; - - SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_ORB_KILL_CREDIT); - - for (Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i) - { - if (Player* player = i->GetSource()) - { - if (spell && spell->Effects[0].MiscValue) - player->KilledMonsterCredit(spell->Effects[0].MiscValue); - } - } - } - void UpdateAI(uint32 uiDiff) override { if (m_uiTransformTimer) { if (m_uiTransformTimer <= uiDiff) { - DoCast(me, SPELL_ORB_KILL_CREDIT, false); - DoWorkaroundForQuestCredit(); + DoCast(me, SPELL_ORB_KILL_CREDIT, true); // Transform and update entry, now ready for quest/read gossip DoCast(me, SPELL_TRANSFORM_TO_KAEL, false); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index 326360428d2..f2d7f23bdc7 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -93,11 +93,6 @@ class npc_unworthy_initiate : public CreatureScript public: npc_unworthy_initiate() : CreatureScript("npc_unworthy_initiate") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_unworthy_initiateAI(creature); - } - struct npc_unworthy_initiateAI : public ScriptedAI { npc_unworthy_initiateAI(Creature* creature) : ScriptedAI(creature) @@ -152,10 +147,11 @@ public: if (id == 1) { wait_timer = 5000; + me->LoadEquipment(1); me->CastSpell(me, SPELL_DK_INITIATE_VISUAL, true); if (Player* starter = ObjectAccessor::GetPlayer(*me, playerGUID)) - sCreatureTextMgr->SendChat(me, SAY_EVENT_ATTACK, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, starter); + Talk(SAY_EVENT_ATTACK, starter); phase = PHASE_TO_ATTACK; } @@ -285,6 +281,11 @@ public: } } }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_unworthy_initiateAI(creature); + } }; class npc_unworthy_initiate_anchor : public CreatureScript @@ -456,6 +457,7 @@ enum Spells_DKI //SPELL_DUEL_TRIGGERED = 52990, SPELL_DUEL_VICTORY = 52994, SPELL_DUEL_FLAG = 52991, + SPELL_GROVEL = 7267, }; enum Says_VBM @@ -493,8 +495,6 @@ public: creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15); - sCreatureTextMgr->SendChat(creature, SAY_DUEL, NULL, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); - player->CastSpell(creature, SPELL_DUEL, false); player->CastSpell(player, SPELL_DUEL_FLAG, true); } @@ -517,11 +517,6 @@ public: return true; } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_death_knight_initiateAI(creature); - } - struct npc_death_knight_initiateAI : public CombatAI { npc_death_knight_initiateAI(Creature* creature) : CombatAI(creature) @@ -556,6 +551,7 @@ public: if (!m_bIsDuelInProgress && pSpell->Id == SPELL_DUEL) { m_uiDuelerGUID = pCaster->GetGUID(); + Talk(SAY_DUEL, pCaster); m_bIsDuelInProgress = true; } } @@ -576,7 +572,7 @@ public: pDoneBy->AttackStop(); me->CastSpell(pDoneBy, SPELL_DUEL_VICTORY, true); lose = true; - me->CastSpell(me, 7267, true); + me->CastSpell(me, SPELL_GROVEL, true); me->RestoreFaction(); } } @@ -606,13 +602,13 @@ public: { if (lose) { - if (!me->HasAura(7267)) + if (!me->HasAura(SPELL_GROVEL)) EnterEvadeMode(); return; } else if (me->GetVictim() && me->EnsureVictim()->GetTypeId() == TYPEID_PLAYER && me->EnsureVictim()->HealthBelowPct(10)) { - me->EnsureVictim()->CastSpell(me->GetVictim(), 7267, true); // beg + me->EnsureVictim()->CastSpell(me->GetVictim(), SPELL_GROVEL, true); // beg me->EnsureVictim()->RemoveGameObject(SPELL_DUEL_FLAG, true); EnterEvadeMode(); return; @@ -625,6 +621,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_death_knight_initiateAI(creature); + } }; /*###### @@ -728,13 +728,19 @@ class npc_dark_rider_of_acherus : public CreatureScript ## npc_salanar_the_horseman ######*/ -enum Spells_Salanar +enum SalanarTheHorseman { - SPELL_REALM_OF_SHADOWS = 52693, + GOSSIP_SALANAR_MENU = 9739, + GOSSIP_SALANAR_OPTION = 0, + SALANAR_SAY = 0, + QUEST_INTO_REALM_OF_SHADOWS = 12687, + NPC_DARK_RIDER_OF_ACHERUS = 28654, + NPC_SALANAR_IN_REALM_OF_SHADOWS = 28788, SPELL_EFFECT_STOLEN_HORSE = 52263, SPELL_DELIVER_STOLEN_HORSE = 52264, SPELL_CALL_DARK_RIDER = 52266, - SPELL_EFFECT_OVERTAKE = 52349 + SPELL_EFFECT_OVERTAKE = 52349, + SPELL_REALM_OF_SHADOWS = 52693 }; class npc_salanar_the_horseman : public CreatureScript @@ -742,15 +748,19 @@ class npc_salanar_the_horseman : public CreatureScript public: npc_salanar_the_horseman() : CreatureScript("npc_salanar_the_horseman") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_salanar_the_horsemanAI(creature); - } - struct npc_salanar_the_horsemanAI : public ScriptedAI { npc_salanar_the_horsemanAI(Creature* creature) : ScriptedAI(creature) { } + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + if (menuId == GOSSIP_SALANAR_MENU && gossipListId == GOSSIP_SALANAR_OPTION) + { + player->CastSpell(player, SPELL_REALM_OF_SHADOWS, true); + player->PlayerTalkClass->SendCloseGossip(); + } + } + void SpellHit(Unit* caster, const SpellInfo* spell) override { if (spell->Id == SPELL_DELIVER_STOLEN_HORSE) @@ -765,7 +775,7 @@ public: caster->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); caster->setFaction(35); DoCast(caster, SPELL_CALL_DARK_RIDER, true); - if (Creature* Dark_Rider = me->FindNearestCreature(28654, 15)) + if (Creature* Dark_Rider = me->FindNearestCreature(NPC_DARK_RIDER_OF_ACHERUS, 15)) ENSURE_AI(npc_dark_rider_of_acherus::npc_dark_rider_of_acherusAI, Dark_Rider->AI())->InitDespawnHorse(caster); } } @@ -783,10 +793,11 @@ public: { if (Player* player = charmer->ToPlayer()) { - // for quest Into the Realm of Shadows(12687) - if (me->GetEntry() == 28788 && player->GetQuestStatus(12687) == QUEST_STATUS_INCOMPLETE) + // for quest Into the Realm of Shadows(QUEST_INTO_REALM_OF_SHADOWS) + if (me->GetEntry() == NPC_SALANAR_IN_REALM_OF_SHADOWS && player->GetQuestStatus(QUEST_INTO_REALM_OF_SHADOWS) == QUEST_STATUS_INCOMPLETE) { - player->GroupEventHappens(12687, me); + player->GroupEventHappens(QUEST_INTO_REALM_OF_SHADOWS, me); + Talk(SALANAR_SAY); charmer->RemoveAurasDueToSpell(SPELL_EFFECT_OVERTAKE); if (Creature* creature = who->ToCreature()) { @@ -795,14 +806,17 @@ public: } } - if (player->HasAura(SPELL_REALM_OF_SHADOWS)) - player->RemoveAurasDueToSpell(SPELL_REALM_OF_SHADOWS); + player->RemoveAurasDueToSpell(SPELL_REALM_OF_SHADOWS); } } } } }; + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_salanar_the_horsemanAI(creature); + } }; /*###### diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index 3df07562d50..ce8b094bb83 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -1218,7 +1218,7 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiLichKingGUID)) // Lich king disappears here { temp->AI()->Talk(EMOTE_LIGHT_OF_DAWN17); - temp->Kill(temp); + temp->KillSelf(); } JumpToNextStep(10000); break; @@ -1293,8 +1293,8 @@ public: //if (GameObject* go = me->GetMap()->GetGameObject(uiDawnofLightGUID)) // Turn off dawn of light // go->SetPhaseMask(0, true); { - Map* map = me->GetMap(); // search players with in 50 yards for quest credit - Map::PlayerList const &PlayerList = map->GetPlayers(); + // search players with in 50 yards for quest credit + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); if (!PlayerList.isEmpty()) { for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) @@ -1633,7 +1633,7 @@ public: if (temp->IsAlive()) { temp->SetVisible(false); - temp->Kill(temp); + temp->KillSelf(); } } }; diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp index 14be8c51bc2..bac4e450a03 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp @@ -359,8 +359,8 @@ public: { die = false; if (Unit* body = ObjectAccessor::GetUnit(*me, bodyGUID)) - body->Kill(body); - me->Kill(me); + body->KillSelf(); + me->KillSelf(); } else wait -= diff; } @@ -538,11 +538,7 @@ public: Player* SelectRandomPlayer(float range = 0.0f, bool checkLoS = true) { - Map* map = me->GetMap(); - if (!map->IsDungeon()) - return NULL; - - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); if (PlayerList.isEmpty()) return NULL; diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp index ed9f7ccb6dd..c41b1d87d61 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/instance_scarlet_monastery.cpp @@ -121,7 +121,7 @@ class instance_scarlet_monastery : public InstanceMapScript { Creature* add = instance->GetCreature(guid); if (add && add->IsAlive()) - add->Kill(add); + add->KillSelf(); } HorsemanAdds.clear(); HandleGameObject(PumpkinShrineGUID, false); diff --git a/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp b/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp index 8d7d43048b4..f6f6dab866d 100644 --- a/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp +++ b/src/server/scripts/EasternKingdoms/Stratholme/boss_baron_rivendare.cpp @@ -106,7 +106,8 @@ public: void AttackStart(Unit* who) override { //can't use entercombat(), boss' dmg aura sets near players in combat, before entering the room's door - instance->SetData(TYPE_BARON, IN_PROGRESS); + if (instance->GetData(TYPE_BARON) == NOT_STARTED) + instance->SetData(TYPE_BARON, IN_PROGRESS); ScriptedAI::AttackStart(who); } diff --git a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp index ba99df8cdd5..60dd27eed90 100644 --- a/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp +++ b/src/server/scripts/EasternKingdoms/Stratholme/stratholme.cpp @@ -170,7 +170,7 @@ public: { if (Player* player = temp->ToPlayer()) player->KilledMonsterCredit(NPC_RESTLESS, me->GetGUID()); - me->Kill(me); + me->KillSelf(); } } else @@ -248,7 +248,7 @@ public: if (Tagged) { if (Die_Timer <= diff) - me->Kill(me); + me->KillSelf(); else Die_Timer -= diff; } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp index 31ca716e0fb..77e0e680f4a 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp @@ -698,7 +698,7 @@ public: if (KillTimer <= diff) { - me->Kill(me); + me->KillSelf(); KillTimer = 9999999; } else KillTimer -= diff; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index ae327dbb874..c8964b2ff31 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -551,13 +551,9 @@ public: bool OnGossipHello(Player* player, GameObject* go) override { - Map* map = go->GetMap(); - if (!map->IsDungeon()) - return true; - #if MAX_PLAYERS_IN_SPECTRAL_REALM > 0 uint8 SpectralPlayers = 0; - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = go->GetMap()->GetPlayers(); for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { if (i->GetSource() && i->GetSource()->GetPositionZ() < DEMON_REALM_Z + 5) @@ -569,6 +565,8 @@ public: player->GetSession()->SendNotification(GO_FAILED); return true; } +#else + (void)go; #endif player->CastSpell(player, SPELL_TELEPORT_SPECTRAL, true); @@ -688,12 +686,8 @@ public: void TeleportAllPlayersBack() { - Map* map = me->GetMap(); - if (!map->IsDungeon()) - return; - - Map::PlayerList const &playerList = map->GetPlayers(); - Position homePos = me->GetHomePosition(); + Map::PlayerList const &playerList = me->GetMap()->GetPlayers(); + Position const& homePos = me->GetHomePosition(); for (Map::PlayerList::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr) { Player* player = itr->GetSource(); diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index 4d544ccdeab..e3deac506b0 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -1112,7 +1112,7 @@ public: else if (me->IsWithinDistInMap(me->GetVictim(), 3)) // Explode if it's close enough to it's target { DoCastVictim(SPELL_FELFIRE_FISSION); - me->Kill(me); + me->KillSelf(); } } }; @@ -1172,7 +1172,7 @@ public: uiTimer = 5000; break; case 3: - me->Kill(me); + me->KillSelf(); me->RemoveCorpse(); break; } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp index b3ad89b08f8..f6622ffe1f4 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp @@ -113,7 +113,7 @@ class instance_zulaman : public InstanceMapScript return false; } - void OnPlayerEnter(Player* /*player*/) + void OnPlayerEnter(Player* /*player*/) override { if (!HarrisonJonesGUID) instance->SummonCreature(NPC_HARRISON_JONES, HarrisonJonesLoc); @@ -197,7 +197,7 @@ class instance_zulaman : public InstanceMapScript return ss.str(); } - void Load(const char* load) + void Load(const char* load) override { if (!load) return; diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp index 3b52e6775b2..1927b0f9829 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp @@ -268,9 +268,9 @@ class npc_harrison_jones : public CreatureScript void EnterCombat(Unit* /*who*/) override { } - void sGossipSelect(Player* player, uint32 sender, uint32 action) override + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override { - if (me->GetCreatureTemplate()->GossipMenuId == sender && !action) + if (me->GetCreatureTemplate()->GossipMenuId == menuId && !gossipListId) { player->CLOSE_GOSSIP_MENU(); me->SetFacingToObject(player); diff --git a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp index 5b63c509eaa..e0612a5ec78 100644 --- a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp @@ -235,7 +235,7 @@ public: summoned->GetMotionMaster()->MovePoint(0, AmbushMoveTo[spawnId]); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_RINJI_TRAPPED) { @@ -272,7 +272,7 @@ public: } } - void UpdateEscortAI(const uint32 diff) override + void UpdateEscortAI(uint32 diff) override { //Check if we have a current target if (!UpdateVictim()) diff --git a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp index ecfd705cf4d..607b449552f 100644 --- a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp +++ b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp @@ -63,11 +63,12 @@ public: Initialize(); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_MISSING_IN_ACTION) { Talk(SAY_CORPORAL_1, player); + me->setFaction(250); npc_escortAI::Start(true, false, player->GetGUID(), quest); } } diff --git a/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp b/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp index 5707ebbf734..b162b4f4d75 100644 --- a/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp +++ b/src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp @@ -61,7 +61,7 @@ public: Talk(SAY_ATTACKED, who); } - void sQuestAccept(Player* player, Quest const* quest) + void sQuestAccept(Player* player, Quest const* quest) override { if (quest->GetQuestId() == QUEST_GALENS_ESCAPE) { diff --git a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp index 9cecbc31665..9af23f17dca 100644 --- a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp @@ -277,145 +277,6 @@ public: }; /*###### -## npc_anchorite_truuen -######*/ - -enum Truuen -{ - NPC_GHOST_UTHER = 17233, - NPC_THEL_DANIS = 1854, - NPC_GHOUL = 1791, //ambush - - QUEST_TOMB_LIGHTBRINGER = 9446, - - SAY_WP_0 = 0, //Beware! We are attacked! - SAY_WP_1 = 1, //It must be the purity of the Mark of the Lightbringer that is drawing forth the Scourge to attack us. We must proceed with caution lest we be overwhelmed! - SAY_WP_2 = 2, //This land truly needs to be cleansed by the Light! Let us continue on to the tomb. It isn't far now... - SAY_WP_3 = 0, //Be welcome, friends! - SAY_WP_4 = 0, //Thank you for coming here in remembrance of me. Your efforts in recovering that symbol, while unnecessary, are certainly touching to an old man's heart. - SAY_WP_5 = 1, //Please, rise my friend. Keep the Blessing as a symbol of the strength of the Light and how heroes long gone might once again rise in each of us to inspire. - SAY_WP_6 = 2 //Thank you my friend for making this possible. This is a day that I shall never forget! I think I will stay a while. Please return to High Priestess MacDonnell at the camp. I know that she'll be keenly interested to know of what has transpired here. -}; - -class npc_anchorite_truuen : public CreatureScript -{ -public: - npc_anchorite_truuen() : CreatureScript("npc_anchorite_truuen") { } - - bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override - { - if (quest->GetQuestId() == QUEST_TOMB_LIGHTBRINGER) - { - npc_escortAI* pEscortAI = ENSURE_AI(npc_anchorite_truuen::npc_anchorite_truuenAI, creature->AI()); - pEscortAI->Start(true, true, player->GetGUID()); - } - return false; - } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_anchorite_truuenAI(creature); - } - - struct npc_anchorite_truuenAI : public npc_escortAI - { - npc_anchorite_truuenAI(Creature* creature) : npc_escortAI(creature) - { - Initialize(); - } - - void Initialize() - { - m_uiChatTimer = 7000; - } - - uint32 m_uiChatTimer; - - ObjectGuid UghostGUID; - - void Reset() override - { - Initialize(); - } - - void JustSummoned(Creature* summoned) override - { - if (summoned->GetEntry() == NPC_GHOUL) - summoned->AI()->AttackStart(me); - } - - void WaypointReached(uint32 waypointId) override - { - Player* player = GetPlayerForEscort(); - - switch (waypointId) - { - case 8: - Talk(SAY_WP_0); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+7.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+5.0f, me->GetPositionY()+5.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - break; - case 9: - Talk(SAY_WP_1); - break; - case 14: - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+7.0f, me->GetPositionY()+7.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+5.0f, me->GetPositionY()+5.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+10.0f, me->GetPositionY()+10.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - me->SummonCreature(NPC_GHOUL, me->GetPositionX()+8.0f, me->GetPositionY()+8.0f, me->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 90000); - break; - case 15: - Talk(SAY_WP_2); - break; - case 21: - if (Creature* Theldanis = GetClosestCreatureWithEntry(me, NPC_THEL_DANIS, 150)) - Theldanis->AI()->Talk(SAY_WP_3); - break; - case 23: - if (Creature* Ughost = me->SummonCreature(NPC_GHOST_UTHER, 971.86f, -1825.42f, 81.99f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - UghostGUID = Ughost->GetGUID(); - Ughost->SetDisableGravity(true); - Ughost->AI()->Talk(SAY_WP_4, me); - } - m_uiChatTimer = 4000; - break; - case 24: - if (Creature* Ughost = ObjectAccessor::GetCreature(*me, UghostGUID)) - Ughost->AI()->Talk(SAY_WP_5, me); - m_uiChatTimer = 4000; - break; - case 25: - if (Creature* Ughost = ObjectAccessor::GetCreature(*me, UghostGUID)) - Ughost->AI()->Talk(SAY_WP_6, me); - m_uiChatTimer = 4000; - break; - case 26: - if (player) - player->GroupEventHappens(QUEST_TOMB_LIGHTBRINGER, me); - break; - } - } - - void EnterCombat(Unit* /*who*/) override { } - - void JustDied(Unit* /*killer*/) override - { - if (Player* player = GetPlayerForEscort()) - player->FailQuest(QUEST_TOMB_LIGHTBRINGER); - } - - void UpdateAI(uint32 uiDiff) override - { - npc_escortAI::UpdateAI(uiDiff); - DoMeleeAttackIfReady(); - if (HasEscortState(STATE_ESCORT_ESCORTING)) - m_uiChatTimer = 6000; - } - }; -}; - -/*###### ## ######*/ @@ -425,5 +286,4 @@ void AddSC_western_plaguelands() new npc_myranda_the_hag(); new npc_the_scourge_cauldron(); new npc_andorhal_tower(); - new npc_anchorite_truuen(); } diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp index 8d9406adee1..ab7509c7a2b 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp @@ -226,7 +226,7 @@ public: } } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { DoCast(player, SPELL_TELEPORT_DARNASSUS); } diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt index ce8d0cfbcfd..f74b809c814 100644 --- a/src/server/scripts/Kalimdor/CMakeLists.txt +++ b/src/server/scripts/Kalimdor/CMakeLists.txt @@ -111,7 +111,6 @@ set(scripts_STAT_SRCS Kalimdor/zone_winterspring.cpp Kalimdor/zone_thousand_needles.cpp Kalimdor/zone_ashenvale.cpp - Kalimdor/zone_teldrassil.cpp Kalimdor/OnyxiasLair/boss_onyxia.cpp Kalimdor/OnyxiasLair/onyxias_lair.h Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp index 254e3a41d6b..d0a9b233454 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp @@ -235,7 +235,7 @@ public: if (AnetheronGUID) { Creature* boss = ObjectAccessor::GetCreature(*me, AnetheronGUID); - if (!boss || (boss && boss->isDead())) + if (!boss || boss->isDead()) { me->setDeathState(JUST_DIED); me->RemoveCorpse(); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp index 08942e3393f..8bfdee067b2 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp @@ -200,7 +200,6 @@ public: CrippleTimer = 50000; WarstompTimer = 10000; CheckTimer = 5000; - instance = creature->GetInstanceScript(); AzgalorGUID = instance->GetGuidData(DATA_AZGALOR); } @@ -208,7 +207,6 @@ public: uint32 WarstompTimer; uint32 CheckTimer; ObjectGuid AzgalorGUID; - InstanceScript* instance; void Reset() override { @@ -248,7 +246,7 @@ public: if (AzgalorGUID) { Creature* boss = ObjectAccessor::GetCreature(*me, AzgalorGUID); - if (!boss || (boss && boss->isDead())) + if (!boss || boss->isDead()) { me->setDeathState(JUST_DIED); me->RemoveCorpse(); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp index b897eb4464a..12e0ae8d194 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp @@ -229,7 +229,7 @@ class spell_mark_of_kazrogal : public SpellScriptLoader } }; - SpellScript* GetSpellScript() const + SpellScript* GetSpellScript() const override { return new spell_mark_of_kazrogal_SpellScript(); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp index 70ecaad3d8d..c39fbc90795 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp @@ -218,7 +218,7 @@ public: break; case 5: me->SetVisible(false); - me->Kill(me); + me->KillSelf(); break; } 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 b5d2931377f..a73a6b8d998 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp @@ -817,7 +817,7 @@ public: cityman1->AI()->Talk(SAY_PHASE204); cityman1->SetTarget(me->GetGUID()); if (Creature* cityman0 = ObjectAccessor::GetCreature(*me, citymenGUID[0])) - cityman0->Kill(cityman0); + cityman0->KillSelf(); me->SetTarget(citymenGUID[1]); } JumpToNextStep(0); @@ -829,7 +829,7 @@ public: break; case 33: if (Creature* cityman1 = ObjectAccessor::GetCreature(*me, citymenGUID[1])) - cityman1->Kill(cityman1); + cityman1->KillSelf(); JumpToNextStep(1000); break; case 34: diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp index 780cf6646a3..33b8516657a 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp @@ -433,15 +433,11 @@ public: } //kill credit Creature for quest - Map* map = me->GetMap(); - Map::PlayerList const& players = map->GetPlayers(); - if (!players.isEmpty() && map->IsDungeon()) + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* player = itr->GetSource()) - player->KilledMonsterCredit(20156); - } + if (Player* player = itr->GetSource()) + player->KilledMonsterCredit(20156); } //alot will happen here, thrall and taretha talk, erozion appear at spot to explain diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index 76fe8819716..65d6565ad9a 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -316,9 +316,20 @@ public: MovePoint = iTemp; } + bool CheckInRoom() override + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 95.0f) + { + EnterEvadeMode(); + return false; + } + + return true; + } + void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) + if (!UpdateVictim() || !CheckInRoom()) return; //Common to PHASE_START && PHASE_END diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp index d8966ec76c1..b57d1b78de0 100644 --- a/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp +++ b/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp @@ -54,14 +54,10 @@ public: Player* GetPlayerInMap() { Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* player = itr->GetSource()) - return player; - } + if (Player* player = itr->GetSource()) + return player; } TC_LOG_DEBUG("scripts", "Instance Razorfen Kraul: GetPlayerInMap, but PlayerList is empty!"); return NULL; diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp index 463d1ee7e0b..8ccc5f0b4ce 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ossirian.cpp @@ -143,8 +143,6 @@ class boss_ossirian : public CreatureScript Talk(SAY_AGGRO); Map* map = me->GetMap(); - if (!map->IsDungeon()) - return; WorldPacket data(SMSG_WEATHER, (4+4+4)); data << uint32(WEATHER_STATE_HEAVY_SANDSTORM) << float(1) << uint8(0); @@ -153,7 +151,7 @@ class boss_ossirian : public CreatureScript for (uint8 i = 0; i < NUM_TORNADOS; ++i) { Position Point = me->GetRandomPoint(RoomCenter, RoomRadius); - if (Creature* Tornado = me->GetMap()->SummonCreature(NPC_SAND_VORTEX, Point)) + if (Creature* Tornado = map->SummonCreature(NPC_SAND_VORTEX, Point)) Tornado->CastSpell(Tornado, SPELL_SAND_STORM, true); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp index 5b338dd8860..6016893a785 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp @@ -536,8 +536,7 @@ public: void SpawnEyeTentacle(float x, float y) { - Creature* Spawned; - Spawned = DoSpawnCreature(NPC_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500); + Creature* Spawned = DoSpawnCreature(NPC_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500); if (Spawned && Spawned->AI()) if (Unit* target = SelectRandomNotStomach()) Spawned->AI()->AttackStart(target); @@ -587,21 +586,10 @@ public: //WisperTimer if (WisperTimer <= diff) { - Map* map = me->GetMap(); - if (!map->IsDungeon()) - return; - //Play random sound to the zone - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) - { - if (Player* pPlr = itr->GetSource()) - pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER, pPlr); - } - } + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) + me->PlayDirectSound(RANDOM_SOUND_WHISPER, itr->GetSource()); //One random wisper every 90 - 300 seconds WisperTimer = urand(90000, 300000); @@ -929,7 +917,7 @@ public: void JustDied(Unit* /*killer*/) override { if (Unit* p = ObjectAccessor::GetUnit(*me, Portal)) - p->Kill(p); + p->KillSelf(); } void Reset() override @@ -955,7 +943,7 @@ public: //KillSelfTimer if (KillSelfTimer <= diff) { - me->Kill(me); + me->KillSelf(); return; } else KillSelfTimer -= diff; @@ -1009,7 +997,7 @@ public: void JustDied(Unit* /*killer*/) override { if (Unit* p = ObjectAccessor::GetUnit(*me, Portal)) - p->Kill(p); + p->KillSelf(); } void Reset() override @@ -1037,7 +1025,7 @@ public: if (EvadeTimer <= diff) { if (Unit* p = ObjectAccessor::GetUnit(*me, Portal)) - p->Kill(p); + p->KillSelf(); //Dissapear and reappear at new position me->SetVisible(false); @@ -1045,7 +1033,7 @@ public: Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); if (!target) { - me->Kill(me); + me->KillSelf(); return; } @@ -1125,7 +1113,7 @@ public: void JustDied(Unit* /*killer*/) override { if (Unit* p = ObjectAccessor::GetUnit(*me, Portal)) - p->Kill(p); + p->KillSelf(); } void Reset() override @@ -1154,7 +1142,7 @@ public: if (EvadeTimer <= diff) { if (Unit* p = ObjectAccessor::GetUnit(*me, Portal)) - p->Kill(p); + p->KillSelf(); //Dissapear and reappear at new position me->SetVisible(false); @@ -1162,7 +1150,7 @@ public: Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); if (!target) { - me->Kill(me); + me->KillSelf(); return; } @@ -1243,7 +1231,7 @@ public: void JustDied(Unit* /*killer*/) override { if (Unit* p = ObjectAccessor::GetUnit(*me, Portal)) - p->Kill(p); + p->KillSelf(); } void Reset() override diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp index 7238760822b..05ec05873f5 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -208,11 +208,13 @@ class PlayerOrPetCheck public: bool operator()(WorldObject* object) const { - if (object->GetTypeId() != TYPEID_PLAYER) - if (!object->ToCreature()->IsPet()) - return true; + if (object->GetTypeId() == TYPEID_PLAYER) + return false; - return false; + if (Creature* creature = object->ToCreature()) + return !creature->IsPet(); + + return true; } }; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index 65ffb7fd696..b39ce0307a5 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -559,8 +559,7 @@ public: if (ArcaneBurst_Timer <= diff) { - Unit* mvic; - if ((mvic=SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) != NULL) + if (Unit* mvic = SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) { DoCast(mvic, SPELL_ARCANEBURST); ArcaneBurst_Timer = 5000; diff --git a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp index 46e831b0f83..7bd197774bc 100644 --- a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp +++ b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp @@ -111,6 +111,7 @@ public: instance_zulfarrak_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); + GahzRillaEncounter = NOT_STARTED; PyramidPhase = 0; major_wave_Timer = 0; minor_wave_Timer = 0; diff --git a/src/server/scripts/Kalimdor/zone_azshara.cpp b/src/server/scripts/Kalimdor/zone_azshara.cpp index 6727aa69552..d6aa943123b 100644 --- a/src/server/scripts/Kalimdor/zone_azshara.cpp +++ b/src/server/scripts/Kalimdor/zone_azshara.cpp @@ -345,7 +345,7 @@ public: } } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { player->CLOSE_GOSSIP_MENU(); me->CastSpell(player, SPELL_GIVE_SOUTHFURY_MOONSTONE, true); diff --git a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp index 5c9a57acec7..52e32d3d37c 100644 --- a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp +++ b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp @@ -230,7 +230,7 @@ public: Talk(ATTACK_YELL, who); } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { player->CLOSE_GOSSIP_MENU(); me->setFaction(FACTION_HOSTILE); @@ -465,13 +465,13 @@ public: SayTimer = 8000; } - uint32 NextStep(uint8 Step) + uint32 NextStep(uint8 step) { Creature* Spark = ObjectAccessor::GetCreature(*me, SparkGUID); if (!Spark) return 99999999; - switch (Step) + switch (step) { case 0: Spark->GetMotionMaster()->MovePoint(0, -5080.70f, -11253.61f, 0.56f); diff --git a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp index ab2e82171f1..0ae870b27ee 100644 --- a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp +++ b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp @@ -272,7 +272,7 @@ public: if (killer->GetGUID() == legoso->GetGUID() || (group && group->IsMember(killer->GetGUID())) || - killer->GetGUIDLow() == legoso->AI()->GetData(DATA_EVENT_STARTER_GUID)) + killer->GetGUID().GetCounter() == legoso->AI()->GetData(DATA_EVENT_STARTER_GUID)) legoso->AI()->DoAction(ACTION_LEGOSO_SIRONAS_KILLED); } } @@ -370,7 +370,7 @@ public: { if (quest->GetQuestId() == QUEST_ENDING_THEIR_WORLD) { - SetData(DATA_EVENT_STARTER_GUID, player->GetGUIDLow()); + SetData(DATA_EVENT_STARTER_GUID, player->GetGUID().GetCounter()); Start(true, true, player->GetGUID(), quest); } } @@ -541,7 +541,7 @@ public: case PHASE_PLANT_FIRST_DETONATE: // first explosives detonate finish for (GuidList::iterator itr = _explosivesGuids.begin(); itr != _explosivesGuids.end(); ++itr) { - if (GameObject* explosive = sObjectAccessor->GetGameObject(*me, *itr)) + if (GameObject* explosive = ObjectAccessor::GetGameObject(*me, *itr)) me->RemoveGameObject(explosive, true); } _explosivesGuids.clear(); @@ -638,7 +638,7 @@ public: case PHASE_PLANT_SECOND_DETONATE: // second explosives detonate finish for (GuidList::iterator itr = _explosivesGuids.begin(); itr != _explosivesGuids.end(); ++itr) { - if (GameObject* explosive = sObjectAccessor->GetGameObject(*me, *itr)) + if (GameObject* explosive = ObjectAccessor::GetGameObject(*me, *itr)) me->RemoveGameObject(explosive, true); } _explosivesGuids.clear(); @@ -808,7 +808,7 @@ public: private: int8 _phase; uint32 _moveTimer; - uint32 _eventStarterGuidLow; + ObjectGuid::LowType _eventStarterGuidLow; GuidList _explosivesGuids; EventMap _events; }; diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp index b0800918765..fba0956ccfc 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -352,7 +352,7 @@ class spell_ooze_zap_channel_end : public SpellScriptLoader PreventHitDefaultEffect(effIndex); if (Player* player = GetCaster()->ToPlayer()) player->CastSpell(player, SPELL_OOZE_CHANNEL_CREDIT, true); - GetHitUnit()->Kill(GetHitUnit()); + GetHitUnit()->KillSelf(); } void Register() override diff --git a/src/server/scripts/Kalimdor/zone_moonglade.cpp b/src/server/scripts/Kalimdor/zone_moonglade.cpp index 163620230ef..c7decd3e286 100644 --- a/src/server/scripts/Kalimdor/zone_moonglade.cpp +++ b/src/server/scripts/Kalimdor/zone_moonglade.cpp @@ -108,64 +108,6 @@ public: }; /*###### -## npc_great_bear_spirit -######*/ - -#define GOSSIP_BEAR1 "What do you represent, spirit?" -#define GOSSIP_BEAR2 "I seek to understand the importance of strength of the body." -#define GOSSIP_BEAR3 "I seek to understand the importance of strength of the heart." -#define GOSSIP_BEAR4 "I have heard your words, Great Bear Spirit, and I understand. I now seek your blessings to fully learn the way of the Claw." - -class npc_great_bear_spirit : public CreatureScript -{ -public: - npc_great_bear_spirit() : CreatureScript("npc_great_bear_spirit") { } - - 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_BEAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(4721, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(4733, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(4734, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - player->SEND_GOSSIP_MENU(4735, creature->GetGUID()); - if (player->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE) - player->AreaExploredOrEventHappens(5929); - if (player->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE) - player->AreaExploredOrEventHappens(5930); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - //ally or horde quest - if (player->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - player->SEND_GOSSIP_MENU(4719, creature->GetGUID()); - } - else - player->SEND_GOSSIP_MENU(4718, creature->GetGUID()); - - return true; - } - -}; - -/*###### ## npc_silva_filnaveth ######*/ @@ -712,7 +654,6 @@ public: void AddSC_moonglade() { new npc_bunthen_plainswind(); - new npc_great_bear_spirit(); new npc_silva_filnaveth(); new npc_clintar_spirit(); new npc_omen(); diff --git a/src/server/scripts/Kalimdor/zone_teldrassil.cpp b/src/server/scripts/Kalimdor/zone_teldrassil.cpp deleted file mode 100644 index 2173cd6de06..00000000000 --- a/src/server/scripts/Kalimdor/zone_teldrassil.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2008-2015 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: Teldrassil -SD%Complete: 100 -SDComment: Quest support: 938 -SDCategory: Teldrassil -EndScriptData */ - -/* ContentData -npc_mist -EndContentData */ - -#include "ScriptMgr.h" -#include "ScriptedCreature.h" -#include "ScriptedFollowerAI.h" -#include "Player.h" - -/*#### -# npc_mist -####*/ - -enum Mist -{ - SAY_AT_HOME = 0, - EMOTE_AT_HOME = 1, - QUEST_MIST = 938, - NPC_ARYNIA = 3519, - FACTION_DARNASSUS = 79 -}; - -class npc_mist : public CreatureScript -{ -public: - npc_mist() : CreatureScript("npc_mist") { } - - bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override - { - if (quest->GetQuestId() == QUEST_MIST) - if (npc_mistAI* pMistAI = CAST_AI(npc_mist::npc_mistAI, creature->AI())) - pMistAI->StartFollow(player, FACTION_DARNASSUS, quest); - - return true; - } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_mistAI(creature); - } - - struct npc_mistAI : public FollowerAI - { - npc_mistAI(Creature* creature) : FollowerAI(creature) { } - - void Reset() override { } - - void MoveInLineOfSight(Unit* who) override - - { - FollowerAI::MoveInLineOfSight(who); - - if (!me->GetVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && who->GetEntry() == NPC_ARYNIA) - { - if (me->IsWithinDistInMap(who, 10.0f)) - { - Talk(SAY_AT_HOME, who); - DoComplete(); - } - } - } - - void DoComplete() - { - Talk(EMOTE_AT_HOME); - - Player* player = GetLeaderForFollower(); - if (player && player->GetQuestStatus(QUEST_MIST) == QUEST_STATUS_INCOMPLETE) - player->GroupEventHappens(QUEST_MIST, me); - - //The follow is over (and for later development, run off to the woods before really end) - SetFollowComplete(); - } - - //call not needed here, no known abilities - /*void UpdateFollowerAI(const uint32 Diff) override - { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - }*/ - }; - -}; - -void AddSC_teldrassil() -{ - new npc_mist(); -} diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp index eab104d8df2..bb54ae08d77 100644 --- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp +++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp @@ -612,7 +612,7 @@ public: summoned->AI()->AttackStart(me); } - void UpdateEscortAI(const uint32 Diff) override + void UpdateEscortAI(uint32 Diff) override { if (!UpdateVictim()) { diff --git a/src/server/scripts/Kalimdor/zone_winterspring.cpp b/src/server/scripts/Kalimdor/zone_winterspring.cpp index 5cb6e78b399..53eadd4a38b 100644 --- a/src/server/scripts/Kalimdor/zone_winterspring.cpp +++ b/src/server/scripts/Kalimdor/zone_winterspring.cpp @@ -568,7 +568,7 @@ public: } - void UpdateEscortAI(const uint32 diff) override + void UpdateEscortAI(uint32 diff) override { DialogueUpdate(diff); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp index cfed13a8f38..d8ebfbbd743 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp @@ -230,11 +230,7 @@ public: // Roll Insanity uint32 spell = GetSpellForPhaseMask(phase); uint32 spell2 = GetSpellForPhaseMask(nextPhase); - Map* map = me->GetMap(); - if (!map) - return; - - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); if (!PlayerList.isEmpty()) { for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) 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 7cb2c0e5178..240e8a7b957 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp @@ -185,7 +185,7 @@ public: who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); AttackStart(who); } - else if (me->GetMap()->IsDungeon()) + else { who->SetInCombatWith(me); me->AddThreat(who, 0.0f); @@ -433,7 +433,7 @@ public: { ENSURE_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerok = true; ENSURE_AI(boss_jedoga_shadowseeker::boss_jedoga_shadowseekerAI, boss->AI())->bOpFerokFail = false; - me->Kill(me); + me->KillSelf(); } } break; diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp index b4627d7f941..3b12104a90b 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp @@ -338,14 +338,14 @@ struct dummy_dragonAI : public ScriptedAI if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) instance->SetBossState(DATA_SHADRON, DONE); if (Creature* acolyte = me->FindNearestCreature(NPC_ACOLYTE_OF_SHADRON, 100.0f)) - acolyte->Kill(acolyte); + acolyte->KillSelf(); break; case NPC_VESPERON: spellId = SPELL_POWER_OF_VESPERON; if (instance->GetBossState(DATA_SARTHARION) != IN_PROGRESS) instance->SetBossState(DATA_VESPERON, DONE); if (Creature* acolyte = me->FindNearestCreature(NPC_ACOLYTE_OF_VESPERON, 100.0f)) - acolyte->Kill(acolyte); + acolyte->KillSelf(); break; } @@ -652,23 +652,19 @@ class npc_acolyte_of_shadron : public CreatureScript if (ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADRON))) instance->SetBossState(DATA_PORTAL_OPEN, NOT_STARTED); - Map* map = me->GetMap(); - if (map->IsDungeon()) - { - Map::PlayerList const& PlayerList = map->GetPlayers(); + Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); - if (PlayerList.isEmpty()) - return; + if (PlayerList.isEmpty()) + return; - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_SHIFT) && !i->GetSource()->GetVictim()) { - if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_SHIFT) && !i->GetSource()->GetVictim()) - { - i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_SHIFT_REMOVAL_ALL, true); - i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_RESIDUE, true); - i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); - i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); - } + i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_SHIFT_REMOVAL_ALL, true); + i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_RESIDUE, true); + i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); + i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); } } @@ -740,26 +736,22 @@ class npc_acolyte_of_vesperon : public CreatureScript vesperon->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); } - Map* map = me->GetMap(); - if (map->IsDungeon()) - { - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); - if (PlayerList.isEmpty()) - return; + if (PlayerList.isEmpty()) + return; - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_SHIFT) && !i->GetSource()->GetVictim()) { - if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_SHIFT) && !i->GetSource()->GetVictim()) - { - i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_SHIFT_REMOVAL_ALL, true); - i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_RESIDUE, true); - i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); - i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); - } - if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_TORMENT_VESP) && !i->GetSource()->GetVictim()) - i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); + i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_SHIFT_REMOVAL_ALL, true); + i->GetSource()->CastSpell(i->GetSource(), SPELL_TWILIGHT_RESIDUE, true); + i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT); + i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_ENTER); } + if (i->GetSource()->IsAlive() && i->GetSource()->HasAura(SPELL_TWILIGHT_TORMENT_VESP) && !i->GetSource()->GetVictim()) + i->GetSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); } instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_TWILIGHT_TORMENT_VESP_ACO); @@ -956,7 +948,7 @@ public: //DoCastVictim(57620, true); //DoCastVictim(57874, true); me->RemoveAllAuras(); - me->Kill(me); + me->KillSelf(); } } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp index eb6230fabfc..eb004505bab 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp @@ -263,7 +263,7 @@ class npc_onyx_flamecaller : public CreatureScript } } - void UpdateEscortAI(uint32 const diff) override + void UpdateEscortAI(uint32 diff) override { if (!UpdateVictim()) return; diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index ad510682e15..6bc49de5319 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -26,14 +26,6 @@ #include "ruby_sanctum.h" #include "Player.h" -/* ScriptData -SDName: ruby_sanctum -SDAuthors: Kaelima, Warpten -SD%Complete: 90% -SDComment: Based on Kaelima's initial work (half of it). Corporeality handling is a pure guess, we lack info. -SDCategory: Chamber of Aspects -EndScriptData */ - enum Texts { // Shared @@ -87,6 +79,8 @@ enum Spells // Living Inferno SPELL_BLAZING_AURA = 75885, + SPELL_SPAWN_LIVING_EMBERS = 75880, + SPELL_SUMMON_LIVING_EMBER = 75881, // Halion Controller SPELL_COSMETIC_FIRE_PILLAR = 76006, @@ -111,7 +105,7 @@ enum Spells SPELL_LEAVE_TWILIGHT_REALM = 74812, SPELL_TWILIGHT_PHASING = 74808, // Phase spell from phase 1 to phase 2 SPELL_SUMMON_TWILIGHT_PORTAL = 74809, // Summons go 202794 - SPELL_SUMMON_EXIT_PORTALS = 74805, // Custom spell created in spell_dbc. + SPELL_SUMMON_EXIT_PORTALS = 74805, // Custom spell created in spell_dbc. // Used in Cataclysm, need a sniff of cata and up SPELL_TWILIGHT_MENDING = 75509, SPELL_TWILIGHT_REALM = 74807, SPELL_DUSK_SHROUD = 75476, @@ -130,20 +124,20 @@ enum Events EVENT_TAIL_LASH = 6, // Twilight Halion - EVENT_SOUL_CONSUMPTION = 8, + EVENT_SOUL_CONSUMPTION = 7, // Meteor Strike - EVENT_SPAWN_METEOR_FLAME = 9, + EVENT_SPAWN_METEOR_FLAME = 8, // Halion Controller - EVENT_START_INTRO = 10, - EVENT_INTRO_PROGRESS_1 = 11, - EVENT_INTRO_PROGRESS_2 = 12, - EVENT_INTRO_PROGRESS_3 = 13, - EVENT_CHECK_CORPOREALITY = 14, - EVENT_SHADOW_PULSARS_SHOOT = 15, - EVENT_TRIGGER_BERSERK = 16, - EVENT_TWILIGHT_MENDING = 17 + EVENT_START_INTRO = 9, + EVENT_INTRO_PROGRESS_1 = 10, + EVENT_INTRO_PROGRESS_2 = 11, + EVENT_INTRO_PROGRESS_3 = 12, + EVENT_CHECK_CORPOREALITY = 13, + EVENT_SHADOW_PULSARS_SHOOT = 14, + EVENT_TRIGGER_BERSERK = 15, + EVENT_TWILIGHT_MENDING = 16 }; enum Actions @@ -174,7 +168,8 @@ enum Misc DATA_MATERIAL_DAMAGE_TAKEN = 2, DATA_STACKS_DISPELLED = 3, DATA_FIGHT_PHASE = 4, - DATA_EVADE_METHOD = 5 + DATA_EVADE_METHOD = 5, + DATA_SPAWNED_FLAMES = 6, }; enum OrbCarrierSeats @@ -365,11 +360,11 @@ class boss_halion : public CreatureScript if (Creature* twilightHalion = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_TWILIGHT_HALION))) if (twilightHalion->IsAlive()) - twilightHalion->Kill(twilightHalion); + twilightHalion->KillSelf(); if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) if (controller->IsAlive()) - controller->Kill(controller); + controller->KillSelf(); } Position const* GetMeteorStrikePosition() const { return &_meteorStrikePos; } @@ -528,7 +523,7 @@ class boss_twilight_halion : public CreatureScript if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) if (controller->IsAlive()) - controller->Kill(controller); + controller->KillSelf(); instance->SendEncounterUnit(ENCOUNTER_FRAME_DISENGAGE, me); } @@ -703,7 +698,7 @@ class npc_halion_controller : public CreatureScript // The IsInCombat() check is needed because that check should be false when Halion is // not engaged, while it would return true without as UpdateVictim() checks for // combat state. - if (!(_events.IsInPhase(PHASE_INTRO)) && me->IsInCombat() && !UpdateVictim()) + if (!_events.IsInPhase(PHASE_INTRO) && me->IsInCombat() && !UpdateVictim()) { EnterEvadeMode(); return; @@ -894,8 +889,6 @@ class npc_halion_controller : public CreatureScript } }; -typedef npc_halion_controller::npc_halion_controllerAI controllerAI; - class npc_orb_carrier : public CreatureScript { public: @@ -997,7 +990,7 @@ class npc_meteor_strike_initial : public CreatureScript if (!owner) return; - // Let Halion Controller count as summoner + // Let Controller count as summoner if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER))) controller->AI()->JustSummoned(me); @@ -1007,11 +1000,12 @@ class npc_meteor_strike_initial : public CreatureScript 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 angle[4]; angle[0] = me->GetAngle(ownerPos); - angle[1] = me->GetAngle(ownerPos) - static_cast<float>(M_PI/2); - angle[2] = me->GetAngle(ownerPos) - static_cast<float>(-M_PI/2); - angle[3] = me->GetAngle(ownerPos) - static_cast<float>(M_PI); + angle[1] = angle[0] + randomAdjustment; + angle[2] = angle[0] + static_cast<float>(M_PI); + angle[3] = angle[2] + randomAdjustment; _meteorList.clear(); for (uint8 i = 0; i < 4; i++) @@ -1020,7 +1014,10 @@ 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,11 +1043,8 @@ class npc_meteor_strike : public CreatureScript struct npc_meteor_strikeAI : public ScriptedAI { npc_meteor_strikeAI(Creature* creature) : ScriptedAI(creature), - _instance(creature->GetInstanceScript()) + _instance(creature->GetInstanceScript()), _spawnCount(0) { - _range = 5.0f; - _spawnCount = 0; - SetCombatMovement(false); } @@ -1071,34 +1065,34 @@ class npc_meteor_strike : public CreatureScript controller->AI()->JustSummoned(me); } - void UpdateAI(uint32 diff) override + void SetData(uint32 dataType, uint32 dataCount) override { - if (_spawnCount > 5) - return; + if (dataType == DATA_SPAWNED_FLAMES) + _spawnCount += dataCount; + } + + uint32 GetData(uint32 dataType) const override + { + if (dataType == DATA_SPAWNED_FLAMES) + return _spawnCount; + return 0; + } + void UpdateAI(uint32 diff) override + { _events.Update(diff); if (_events.ExecuteEvent() == EVENT_SPAWN_METEOR_FLAME) { - Position pos = me->GetNearPosition( _range, 0.0f); - + Position pos = me->GetNearPosition(5.0f, frand(-static_cast<float>(M_PI / 6.0f), static_cast<float>(M_PI / 6.0f))); if (Creature* flame = me->SummonCreature(NPC_METEOR_STRIKE_FLAME, pos, TEMPSUMMON_TIMED_DESPAWN, 25000)) - { - if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER))) - controller->AI()->JustSummoned(flame); - - flame->CastSpell(flame, SPELL_METEOR_STRIKE_FIRE_AURA_2, true); - ++_spawnCount; - } - _range += 5.0f; - _events.ScheduleEvent(EVENT_SPAWN_METEOR_FLAME, 800); + flame->AI()->SetGUID(me->GetGUID()); } } private: InstanceScript* _instance; EventMap _events; - float _range; uint8 _spawnCount; }; @@ -1108,6 +1102,67 @@ class npc_meteor_strike : public CreatureScript } }; +class npc_meteor_strike_flame : public CreatureScript +{ + public: + npc_meteor_strike_flame() : CreatureScript("npc_meteor_strike_flame") { } + + struct npc_meteor_strike_flameAI : public ScriptedAI + { + npc_meteor_strike_flameAI(Creature* creature) : ScriptedAI(creature), + _instance(creature->GetInstanceScript()) + { + SetCombatMovement(false); + } + + void SetGUID(ObjectGuid guid, int32 /*id = 0 */) override + { + _rootOwnerGuid = guid; + _events.ScheduleEvent(EVENT_SPAWN_METEOR_FLAME, 800); + } + + void IsSummonedBy(Unit* /*summoner*/) override + { + // Let Halion Controller count as summoner. + if (Creature* controller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HALION_CONTROLLER))) + controller->AI()->JustSummoned(me); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + if (_events.ExecuteEvent() != EVENT_SPAWN_METEOR_FLAME) + return; + + me->CastSpell(me, SPELL_METEOR_STRIKE_FIRE_AURA_2, true); + + Creature* meteorStrike = ObjectAccessor::GetCreature(*me, _rootOwnerGuid); + if (!meteorStrike) + return; + + meteorStrike->AI()->SetData(DATA_SPAWNED_FLAMES, 1); + if (meteorStrike->AI()->GetData(DATA_SPAWNED_FLAMES) > 5) + return; + + Position pos = me->GetNearPosition(5.0f, frand(-static_cast<float>(M_PI / 6.0f), static_cast<float>(M_PI / 6.0f))); + if (Creature* flame = me->SummonCreature(NPC_METEOR_STRIKE_FLAME, pos, TEMPSUMMON_TIMED_DESPAWN, 25000)) + flame->AI()->SetGUID(_rootOwnerGuid); + } + + void EnterEvadeMode() override { } + + private: + InstanceScript* _instance; + EventMap _events; + ObjectGuid _rootOwnerGuid; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetRubySanctumAI<npc_meteor_strike_flameAI>(creature); + } +}; + class npc_combustion_consumption : public CreatureScript { public: @@ -1120,26 +1175,23 @@ class npc_combustion_consumption : public CreatureScript { SetCombatMovement(false); - switch (me->GetEntry()) + switch (creature->GetEntry()) { case NPC_COMBUSTION: _explosionSpell = SPELL_FIERY_COMBUSTION_EXPLOSION; _damageSpell = SPELL_COMBUSTION_DAMAGE_AURA; - me->SetPhaseMask(0x01, true); + creature->SetPhaseMask(IsHeroic() ? 0x21 : 0x01, true); break; case NPC_CONSUMPTION: _explosionSpell = SPELL_SOUL_CONSUMPTION_EXPLOSION; _damageSpell = SPELL_CONSUMPTION_DAMAGE_AURA; - me->SetPhaseMask(0x20, true); + creature->SetPhaseMask(IsHeroic() ? 0x21 : 0x20, true); break; default: // Should never happen _explosionSpell = 0; _damageSpell = 0; break; } - - if (IsHeroic()) - me->SetPhaseMask(0x01 | 0x20, true); } void IsSummonedBy(Unit* summoner) override @@ -1161,7 +1213,7 @@ class npc_combustion_consumption : public CreatureScript me->CastCustomSpell(SPELL_SCALE_AURA, SPELLVALUE_AURA_STACK, stackAmount, me); DoCast(me, _damageSpell); - int32 damage = 1200 + (stackAmount * 1290); // Needs more researches. + int32 damage = 1200 + (stackAmount * 1290); // Needs more research. summoner->CastCustomSpell(_explosionSpell, SPELLVALUE_BASE_POINT0, damage, summoner); } @@ -1194,6 +1246,10 @@ class npc_living_inferno : public CreatureScript me->SetInCombatWithZone(); me->CastSpell(me, SPELL_BLAZING_AURA, true); + // 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); + if (InstanceScript* instance = me->GetInstanceScript()) if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HALION_CONTROLLER))) controller->AI()->JustSummoned(me); @@ -1211,7 +1267,6 @@ class npc_living_inferno : public CreatureScript } }; -//! Need sniff data class npc_living_ember : public CreatureScript { public: @@ -1296,7 +1351,7 @@ class go_twilight_portal : public GameObjectScript _spellId = gameobject->GetGOInfo()->goober.spellId; break; case GO_HALION_PORTAL_1: - case GO_HALION_PORTAL_2: // Not used, not seen in sniffs. Just in case. + case GO_HALION_PORTAL_2: gameobject->SetPhaseMask(0x1, true); /// Because WDB template has non-existent spell ID, not seen in sniffs either, meh _spellId = SPELL_TWILIGHT_REALM; @@ -1739,12 +1794,46 @@ class spell_halion_summon_exit_portals : public SpellScriptLoader } }; +class spell_halion_spawn_living_embers : public SpellScriptLoader +{ + public: + spell_halion_spawn_living_embers() : SpellScriptLoader("spell_halion_spawn_living_embers") { } + + class spell_halion_spawn_living_embers_SpellScript : public SpellScript + { + PrepareSpellScript(spell_halion_spawn_living_embers_SpellScript); + + void SelectMeteorFlames(std::list<WorldObject*>& unitList) + { + if (!unitList.empty()) + Trinity::Containers::RandomResizeList(unitList, 10); + } + + void HandleScript(SpellEffIndex /* effIndex */) + { + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_SUMMON_LIVING_EMBER, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_halion_spawn_living_embers_SpellScript::SelectMeteorFlames, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_halion_spawn_living_embers_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_halion_spawn_living_embers_SpellScript(); + } +}; + void AddSC_boss_halion() { new boss_halion(); new boss_twilight_halion(); new npc_halion_controller(); + new npc_meteor_strike_flame(); new npc_meteor_strike_initial(); new npc_meteor_strike(); new npc_combustion_consumption(); @@ -1766,4 +1855,5 @@ void AddSC_boss_halion() new spell_halion_twilight_phasing(); new spell_halion_twilight_cutter(); new spell_halion_clear_debuffs(); + new spell_halion_spawn_living_embers(); } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp index c375e5c1b95..512016c6eeb 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp @@ -254,7 +254,7 @@ public: if (uiChargeTimer <= uiDiff) { Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) + if (!players.isEmpty()) { for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { @@ -281,7 +281,7 @@ public: if (Unit* pPassenger = pVehicle->GetPassenger(SEAT_ID_0)) { Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) + if (!players.isEmpty()) { for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { @@ -400,7 +400,7 @@ public: if (uiInterceptTimer <= uiDiff) { Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) + if (!players.isEmpty()) { for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { @@ -867,7 +867,7 @@ public: else { Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) + if (!players.isEmpty()) { for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { 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 758b4d25c43..f50a26eae23 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -664,10 +664,9 @@ struct boss_faction_championsAI : public BossAI { std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList(); std::list<HostileReference*>::const_iterator iter; - Unit* target; for (iter = tList.begin(); iter!=tList.end(); ++iter) { - target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); + Unit* target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); if (target && target->getPowerType() == POWER_MANA) return target; } @@ -679,10 +678,9 @@ struct boss_faction_championsAI : public BossAI std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList(); std::list<HostileReference*>::const_iterator iter; uint32 count = 0; - Unit* target; for (iter = tList.begin(); iter != tList.end(); ++iter) { - target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); + Unit* target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); if (target && me->GetDistance2d(target) < distance) ++count; } diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp index 0b829c2c6dd..620eb54ffa9 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp @@ -123,11 +123,13 @@ class boss_bronjahm : public CreatureScript void JustSummoned(Creature* summon) override { - summons.Summon(summon); - summon->SetReactState(REACT_PASSIVE); - summon->GetMotionMaster()->Clear(); - summon->GetMotionMaster()->MoveFollow(me, me->GetObjectSize(), 0.0f); - summon->CastSpell(summon, SPELL_PURPLE_BANISH_VISUAL, true); + if (summon->GetEntry() == NPC_CORRUPTED_SOUL_FRAGMENT) + { + summons.Summon(summon); + summon->SetReactState(REACT_PASSIVE); + summon->GetMotionMaster()->MoveFollow(me, me->GetObjectSize(), 0.0f); + summon->CastSpell(summon, SPELL_PURPLE_BANISH_VISUAL, true); + } } uint32 GetData(uint32 type) const override @@ -223,9 +225,15 @@ class npc_corrupted_soul_fragment : public CreatureScript instance = me->GetInstanceScript(); } + void IsSummonedBy(Unit* /*summoner*/) override + { + if (Creature* bronjahm = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_BRONJAHM))) + bronjahm->AI()->JustSummoned(me); + } + void MovementInform(uint32 type, uint32 id) override { - if (type != CHASE_MOTION_TYPE) + if (type != FOLLOW_MOTION_TYPE) return; if (instance->GetGuidData(DATA_BRONJAHM).GetCounter() != id) diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index fd0fff44f66..c19af1cf79d 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -137,9 +137,8 @@ class boss_ick : public CreatureScript struct boss_ickAI : public BossAI { - boss_ickAI(Creature* creature) : BossAI(creature, DATA_ICK), _vehicle(creature->GetVehicleKit()) + boss_ickAI(Creature* creature) : BossAI(creature, DATA_ICK) { - ASSERT(_vehicle); _tempThreat = 0; } @@ -177,7 +176,8 @@ class boss_ick : public CreatureScript { if (Creature* krick = GetKrick()) { - _vehicle->RemoveAllPassengers(); + if (Vehicle* _vehicle = me->GetVehicleKit()) + _vehicle->RemoveAllPassengers(); if (krick->AI()) krick->AI()->DoAction(ACTION_OUTRO); } @@ -268,7 +268,6 @@ class boss_ick : public CreatureScript } private: - Vehicle* _vehicle; float _tempThreat; }; 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 3384b562860..3e56f9a1753 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -290,9 +290,8 @@ class boss_rimefang : public CreatureScript struct boss_rimefangAI : public ScriptedAI { - boss_rimefangAI(Creature* creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit()) + boss_rimefangAI(Creature* creature) : ScriptedAI(creature) { - ASSERT(_vehicle); Initialize(); } @@ -314,7 +313,8 @@ class boss_rimefang : public CreatureScript void JustReachedHome() override { - _vehicle->InstallAllAccessories(false); + if (Vehicle* _vehicle = me->GetVehicleKit()) + _vehicle->InstallAllAccessories(false); } void DoAction(int32 actionId) override @@ -376,7 +376,6 @@ class boss_rimefang : public CreatureScript } private: - Vehicle* _vehicle; ObjectGuid _hoarfrostTargetGUID; EventMap _events; uint8 _currentWaypoint; diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp index 79f9a6e7c61..f3b70f069c4 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp @@ -110,9 +110,8 @@ class npc_iceborn_protodrake : public CreatureScript struct npc_iceborn_protodrakeAI: public ScriptedAI { - npc_iceborn_protodrakeAI(Creature* creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit()) + npc_iceborn_protodrakeAI(Creature* creature) : ScriptedAI(creature) { - ASSERT(_vehicle); Initialize(); } @@ -128,7 +127,8 @@ class npc_iceborn_protodrake : public CreatureScript void EnterCombat(Unit* /*who*/) override { - _vehicle->RemoveAllPassengers(); + if (Vehicle* _vehicle = me->GetVehicleKit()) + _vehicle->RemoveAllPassengers(); } void UpdateAI(uint32 diff) override @@ -148,7 +148,6 @@ class npc_iceborn_protodrake : public CreatureScript } private: - Vehicle* _vehicle; uint32 _frostBreathCooldown; }; diff --git a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp index f10c108c00c..4438c4ab199 100644 --- a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp +++ b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp @@ -18,8 +18,8 @@ #include "InstanceScript.h" #include "Player.h" #include "ScriptMgr.h" -#include "WorldSession.h" #include "gundrak.h" +#include "EventMap.h" DoorData const doorData[] = { @@ -190,7 +190,7 @@ class instance_gundrak : public InstanceMapScript bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override { - if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES)) + if (_SkipCheckRequiredBosses(player)) return true; switch (bossId) 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 abeaff421cf..aeaf8a70ba5 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -376,7 +376,7 @@ class boss_prince_keleseth_icc : public CreatureScript void InitializeAI() override { - if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetSpawnId())) if (data->curhealth) _spawnHealth = data->curhealth; @@ -591,7 +591,7 @@ class boss_prince_taldaram_icc : public CreatureScript void InitializeAI() override { - if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetSpawnId())) if (data->curhealth) _spawnHealth = data->curhealth; @@ -815,7 +815,7 @@ class boss_prince_valanar_icc : public CreatureScript void InitializeAI() override { - if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetSpawnId())) if (data->curhealth) _spawnHealth = data->curhealth; 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 efc24b94cdb..a7ac5d1227e 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 @@ -203,7 +203,7 @@ class boss_blood_queen_lana_thel : public CreatureScript { instance->SetData(DATA_BLOOD_QUICKENING_STATE, DONE); if (Player* player = killer->ToPlayer()) - player->RewardPlayerAndGroupAtEvent(NPC_INFILTRATOR_MINCHAR_BQ, player); + player->RewardPlayerAndGroupAtEvent(Is25ManRaid() ? NPC_INFILTRATOR_MINCHAR_BQ_25 : NPC_INFILTRATOR_MINCHAR_BQ, player); if (Creature* minchar = me->FindNearestCreature(NPC_INFILTRATOR_MINCHAR_BQ, 200.0f)) { minchar->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 943be27943d..365e0a1588d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -203,6 +203,9 @@ enum Misc { DATA_MADE_A_MESS = 45374613, // 4537, 4613 are achievement IDs FACTION_SCOURGE = 974, + + GOSSIP_MENU_MURADIN_BRONZEBEARD = 10934, + GOSSIP_MENU_HIGH_OVERLORD_SAURFANG = 10952 }; enum MovePoints @@ -634,6 +637,15 @@ class npc_high_overlord_saurfang_icc : public CreatureScript _events.Reset(); } + void sGossipSelect(Player* player, uint32 menuId, uint32 /*gossipListId*/) override + { + if (menuId == GOSSIP_MENU_HIGH_OVERLORD_SAURFANG) + { + player->PlayerTalkClass->SendCloseGossip(); + DoAction(ACTION_START_EVENT); + } + } + void DoAction(int32 action) override { switch (action) @@ -798,28 +810,6 @@ class npc_high_overlord_saurfang_icc : public CreatureScript std::list<Creature*> _guardList; }; - bool OnGossipHello(Player* player, Creature* creature) override - { - InstanceScript* instance = creature->GetInstanceScript(); - if (instance && instance->GetBossState(DATA_DEATHBRINGER_SAURFANG) != DONE) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "We are ready to go, High Overlord. The Lich King must fall!", 631, -ACTION_START_EVENT); - player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); - } - - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - player->CLOSE_GOSSIP_MENU(); - if (action == -ACTION_START_EVENT) - creature->AI()->DoAction(ACTION_START_EVENT); - - return true; - } - CreatureAI* GetAI(Creature* creature) const override { return GetIcecrownCitadelAI<npc_high_overlord_saurfangAI>(creature); @@ -843,6 +833,15 @@ class npc_muradin_bronzebeard_icc : public CreatureScript _events.Reset(); } + void sGossipSelect(Player* player, uint32 menuId, uint32 /*gossipListId*/) override + { + if (menuId == GOSSIP_MENU_MURADIN_BRONZEBEARD) + { + player->PlayerTalkClass->SendCloseGossip(); + DoAction(ACTION_START_EVENT); + } + } + void DoAction(int32 action) override { switch (action) @@ -946,28 +945,6 @@ class npc_muradin_bronzebeard_icc : public CreatureScript std::list<Creature*> _guardList; }; - bool OnGossipHello(Player* player, Creature* creature) override - { - InstanceScript* instance = creature->GetInstanceScript(); - if (instance && instance->GetBossState(DATA_DEATHBRINGER_SAURFANG) != DONE) - { - player->ADD_GOSSIP_ITEM(0, "Let it begin...", 631, -ACTION_START_EVENT + 1); - player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); - } - - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - player->CLOSE_GOSSIP_MENU(); - if (action == -ACTION_START_EVENT + 1) - creature->AI()->DoAction(ACTION_START_EVENT); - - return true; - } - CreatureAI* GetAI(Creature* creature) const override { return GetIcecrownCitadelAI<npc_muradin_bronzebeard_iccAI>(creature); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp index db0fcee22fa..e3e89d865ff 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp @@ -470,21 +470,11 @@ class spell_festergut_blighted_spores : public SpellScriptLoader if (target->HasAura(SPELL_ORANGE_BLIGHT_RESIDUE)) return; - if (target->GetMap() && !target->GetMap()->Is25ManRaid()) - { - if (target->GetQuestStatus(QUEST_RESIDUE_RENDEZVOUS_10) != QUEST_STATUS_INCOMPLETE) - return; - - target->CastSpell(target, SPELL_ORANGE_BLIGHT_RESIDUE, TRIGGERED_FULL_MASK); - } - - if (target->GetMap() && target->GetMap()->Is25ManRaid()) - { - if (target->GetQuestStatus(QUEST_RESIDUE_RENDEZVOUS_25) != QUEST_STATUS_INCOMPLETE) - return; + uint32 questId = target->GetMap()->Is25ManRaid() ? QUEST_RESIDUE_RENDEZVOUS_25 : QUEST_RESIDUE_RENDEZVOUS_10; + if (target->GetQuestStatus(questId) != QUEST_STATUS_INCOMPLETE) + return; - target->CastSpell(target, SPELL_ORANGE_BLIGHT_RESIDUE, TRIGGERED_FULL_MASK); - } + target->CastSpell(target, SPELL_ORANGE_BLIGHT_RESIDUE, TRIGGERED_FULL_MASK); } void Register() override 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 68430f6f0f7..babd444288f 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -492,7 +492,7 @@ public: _caster->CastSpell(_caster, _spellId, true); _caster->GetTransport()->AddObjectToRemoveList(); - if (GameObject* go = HashMapHolder<GameObject>::Find(_otherTransport)) + if (Transport* go = HashMapHolder<Transport>::Find(_otherTransport)) go->AddObjectToRemoveList(); return true; @@ -770,9 +770,8 @@ class npc_gunship : public CreatureScript if (isVictory) { - if (GameObject* go = HashMapHolder<GameObject>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - if (Transport* otherTransport = go->ToTransport()) - otherTransport->EnableMovement(true); + if (Transport* otherTransport = HashMapHolder<Transport>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + otherTransport->EnableMovement(true); me->GetTransport()->EnableMovement(true); @@ -962,7 +961,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript } } - void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override { me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); me->GetTransport()->EnableMovement(true); @@ -1035,9 +1034,8 @@ class npc_high_overlord_saurfang_igb : public CreatureScript if (Transport* orgrimsHammer = me->GetTransport()) orgrimsHammer->SummonPassenger(NPC_TELEPORT_PORTAL, OrgrimsHammerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, NULL, 21000); - if (GameObject* go = HashMapHolder<GameObject>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - if (Transport* skybreaker = go->ToTransport()) - skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); + if (Transport* skybreaker = HashMapHolder<Transport>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + skybreaker->SummonPassenger(NPC_TELEPORT_EXIT, SkybreakerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000); _events.ScheduleEvent(EVENT_ADDS, 60000); @@ -1231,7 +1229,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript } } - void sGossipSelect(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* /*player*/, uint32 /*menuId*/, uint32 /*gossipListId*/) override { me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); me->GetTransport()->EnableMovement(true); @@ -1308,9 +1306,8 @@ class npc_muradin_bronzebeard_igb : public CreatureScript if (Transport* skybreaker = me->GetTransport()) skybreaker->SummonPassenger(NPC_TELEPORT_PORTAL, SkybreakerTeleportPortal, TEMPSUMMON_TIMED_DESPAWN, NULL, 21000); - if (GameObject* go = HashMapHolder<GameObject>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - if (Transport* orgrimsHammer = go->ToTransport()) - orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); + if (Transport* orgrimsHammer = HashMapHolder<Transport>::Find(_instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + orgrimsHammer->SummonPassenger(NPC_TELEPORT_EXIT, OrgrimsHammerTeleportExit, TEMPSUMMON_TIMED_DESPAWN, NULL, 23000); _events.ScheduleEvent(EVENT_ADDS_BOARD_YELL, 6000); _events.ScheduleEvent(EVENT_ADDS, 60000); @@ -1397,7 +1394,7 @@ class npc_zafod_boombox : public CreatureScript me->SetReactState(REACT_PASSIVE); } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { player->AddItem(ITEM_GOBLIN_ROCKET_PACK, 1); player->PlayerTalkClass->SendCloseGossip(); @@ -1454,9 +1451,8 @@ struct npc_gunship_boarding_addAI : public gunship_npc_AI if (!myTransport) return; - if (GameObject* go = HashMapHolder<GameObject>::Find(Instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) - if (Transport* destTransport = go->ToTransport()) - destTransport->CalculatePassengerPosition(x, y, z, &o); + if (Transport* destTransport = HashMapHolder<Transport>::Find(Instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE))) + destTransport->CalculatePassengerPosition(x, y, z, &o); float angle = frand(0, float(M_PI) * 2.0f); x += 2.0f * std::cos(angle); @@ -2352,7 +2348,7 @@ class spell_igb_gunship_fall_teleport : public SpellScriptLoader void SelectTransport(WorldObject*& target) { if (InstanceScript* instance = target->GetInstanceScript()) - target = HashMapHolder<GameObject>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)); + target = HashMapHolder<Transport>::Find(instance->GetGuidData(DATA_ICECROWN_GUNSHIP_BATTLE)); } void RelocateDest(SpellEffIndex /*effIndex*/) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index f5843cbfd30..3a745e2c98c 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -820,7 +820,7 @@ class npc_vengeful_shade : public CreatureScript case SPELL_VENGEFUL_BLAST_25N: case SPELL_VENGEFUL_BLAST_10H: case SPELL_VENGEFUL_BLAST_25H: - me->Kill(me); + me->KillSelf(); break; default: break; @@ -1008,7 +1008,7 @@ class spell_cultist_dark_martyrdom : public SpellScriptLoader if (Unit* owner = GetCaster()->ToTempSummon()->GetSummoner()) owner->GetAI()->SetGUID(GetCaster()->GetGUID(), GUID_CULTIST); - GetCaster()->Kill(GetCaster()); + GetCaster()->KillSelf(); GetCaster()->SetDisplayId(uint32(GetCaster()->GetEntry() == NPC_CULT_FANATIC ? 38009 : 38010)); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index d7a580800bc..be134a06173 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -205,7 +205,7 @@ struct RotfaceHeightCheck bool operator()(Creature* stalker) const { - return stalker->GetPositionZ() < _rotface->GetPositionZ() + 5.0f; + return stalker->GetPositionZ() > _rotface->GetPositionZ() + 5.0f; } private: diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index d56a3f80f75..1a2ebd179fe 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -480,8 +480,8 @@ class spell_rotface_ooze_flood : public SpellScriptLoader targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); // .resize() runs pop_back(); - if (targets.size() > 4) - targets.resize(4); + if (targets.size() > 5) + targets.resize(5); while (targets.size() > 2) targets.pop_front(); @@ -892,21 +892,11 @@ class spell_rotface_slime_spray : public SpellScriptLoader if (target->HasAura(SPELL_GREEN_BLIGHT_RESIDUE)) return; - if (target->GetMap() && !target->GetMap()->Is25ManRaid()) - { - if (target->GetQuestStatus(QUEST_RESIDUE_RENDEZVOUS_10) != QUEST_STATUS_INCOMPLETE) - return; - - target->CastSpell(target, SPELL_GREEN_BLIGHT_RESIDUE, TRIGGERED_FULL_MASK); - } - - if (target->GetMap() && target->GetMap()->Is25ManRaid()) - { - if (target->GetQuestStatus(QUEST_RESIDUE_RENDEZVOUS_25) != QUEST_STATUS_INCOMPLETE) - return; + uint32 questId = target->GetMap()->Is25ManRaid() ? QUEST_RESIDUE_RENDEZVOUS_25 : QUEST_RESIDUE_RENDEZVOUS_10; + if (target->GetQuestStatus(questId) != QUEST_STATUS_INCOMPLETE) + return; - target->CastSpell(target, SPELL_GREEN_BLIGHT_RESIDUE, TRIGGERED_FULL_MASK); - } + target->CastSpell(target, SPELL_GREEN_BLIGHT_RESIDUE, TRIGGERED_FULL_MASK); } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index e908d088554..65d99b022dc 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -648,7 +648,7 @@ class npc_spinestalker : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetSpawnId()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -671,7 +671,7 @@ class npc_spinestalker : public CreatureScript void JustRespawned() override { ScriptedAI::JustRespawned(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetSpawnId()); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) override @@ -784,7 +784,7 @@ class npc_rimefang : public CreatureScript // Increase add count if (!me->isDead()) { - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetSpawnId()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -807,7 +807,7 @@ class npc_rimefang : public CreatureScript void JustRespawned() override { ScriptedAI::JustRespawned(); - _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade + _instance->SetData(DATA_SINDRAGOSA_FROSTWYRMS, me->GetSpawnId()); // this cannot be in Reset because reset also happens on evade } void JustDied(Unit* /*killer*/) override @@ -951,7 +951,7 @@ class npc_sindragosa_trash : public CreatureScript if (!me->isDead()) { if (me->GetEntry() == NPC_FROSTWING_WHELP) - _instance->SetData(_frostwyrmId, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade + _instance->SetData(_frostwyrmId, me->GetSpawnId()); // this cannot be in Reset because reset also happens on evade Reset(); } } @@ -974,7 +974,7 @@ class npc_sindragosa_trash : public CreatureScript // Increase add count if (me->GetEntry() == NPC_FROSTWING_WHELP) - _instance->SetData(_frostwyrmId, me->GetDBTableGUIDLow()); // this cannot be in Reset because reset also happens on evade + _instance->SetData(_frostwyrmId, me->GetSpawnId()); // this cannot be in Reset because reset also happens on evade } void SetData(uint32 type, uint32 data) override 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 07816ebbe39..4fadc0bf8fa 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -432,20 +432,21 @@ class StartMovementEvent : public BasicEvent { public: StartMovementEvent(Creature* summoner, Creature* owner) - : _summoner(summoner), _owner(owner) + : _summonerGuid(summoner->GetGUID()), _owner(owner) { } bool Execute(uint64 /*time*/, uint32 /*diff*/) { _owner->SetReactState(REACT_AGGRESSIVE); - if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(_summoner))) - _owner->AI()->AttackStart(target); + if (Creature* _summoner = ObjectAccessor::GetCreature(*_owner, _summonerGuid)) + if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(_summoner))) + _owner->AI()->AttackStart(target); return true; } private: - Creature* _summoner; + ObjectGuid _summonerGuid; Creature* _owner; }; @@ -1198,9 +1199,9 @@ class npc_tirion_fordring_tft : public CreatureScript SetEquipmentSlots(true); // remove glow on ashbringer } - void sGossipSelect(Player* /*player*/, uint32 sender, uint32 action) override + void sGossipSelect(Player* /*player*/, uint32 menuId, uint32 gossipListId) override { - if (me->GetCreatureTemplate()->GossipMenuId == sender && !action) + if (me->GetCreatureTemplate()->GossipMenuId == menuId && !gossipListId) { _events.SetPhase(PHASE_INTRO); me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index 7af550582a0..4a76dc667e8 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -156,7 +156,7 @@ class RisenArchmageCheck bool operator()(Creature* creature) { return creature->IsAlive() && creature->GetEntry() == NPC_RISEN_ARCHMAGE && - creature->GetDBTableGUIDLow() && !creature->IsInCombat(); + creature->GetSpawnId() && !creature->IsInCombat(); } }; @@ -244,7 +244,7 @@ class ValithriaDespawner : public BasicEvent creature->DespawnOrUnsummon(); return; case NPC_RISEN_ARCHMAGE: - if (!creature->GetDBTableGUIDLow()) + if (!creature->GetSpawnId()) { creature->DespawnOrUnsummon(); return; @@ -297,7 +297,7 @@ class boss_valithria_dreamwalker : public CreatureScript void InitializeAI() override { - if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetDBTableGUIDLow())) + if (CreatureData const* data = sObjectMgr->GetCreatureData(me->GetSpawnId())) if (data->curhealth) _spawnHealth = data->curhealth; @@ -309,7 +309,7 @@ class boss_valithria_dreamwalker : public CreatureScript { me->SetHealth(_spawnHealth); me->SetReactState(REACT_PASSIVE); - me->LoadCreaturesAddon(true); + me->LoadCreaturesAddon(); // immune to percent heals me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_OBS_MOD_HEALTH, true); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_HEAL_PCT, true); @@ -712,7 +712,7 @@ class npc_risen_archmage : public CreatureScript void EnterCombat(Unit* /*target*/) override { me->FinishSpell(CURRENT_CHANNELED_SPELL, false); - if (me->GetDBTableGUIDLow() && _canCallEnterCombat) + if (me->GetSpawnId() && _canCallEnterCombat) { std::list<Creature*> archmages; RisenArchmageCheck check; @@ -750,7 +750,7 @@ class npc_risen_archmage : public CreatureScript void UpdateAI(uint32 diff) override { if (!me->IsInCombat()) - if (me->GetDBTableGUIDLow()) + if (me->GetSpawnId()) if (!me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) DoCast(me, SPELL_CORRUPTION); @@ -1072,7 +1072,7 @@ class npc_dream_cloud : public CreatureScript _events.Reset(); _events.ScheduleEvent(EVENT_CHECK_PLAYER, 1000); me->SetCorpseDelay(0); // remove corpse immediately - me->LoadCreaturesAddon(true); + me->LoadCreaturesAddon(); } void UpdateAI(uint32 diff) override @@ -1336,7 +1336,7 @@ class spell_dreamwalker_summon_dream_portal : public SpellScriptLoader if (!GetHitUnit()) return; - uint32 spellId = RAND<uint32>(71301, 72220, 72223, 72225); + uint32 spellId = RAND(71301, 72220, 72223, 72225); GetHitUnit()->CastSpell(GetHitUnit(), spellId, true); } @@ -1367,7 +1367,7 @@ class spell_dreamwalker_summon_nightmare_portal : public SpellScriptLoader if (!GetHitUnit()) return; - uint32 spellId = RAND<uint32>(71977, 72481, 72482, 72483); + uint32 spellId = RAND(71977, 72481, 72482, 72483); GetHitUnit()->CastSpell(GetHitUnit(), spellId, true); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 8c1befe72ff..f05fc48c074 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -545,7 +545,7 @@ class npc_highlord_tirion_fordring_lh : public CreatureScript case EVENT_MURADIN_RUN: case EVENT_SAURFANG_RUN: if (Creature* factionNPC = ObjectAccessor::GetCreature(*me, _factionNPC)) - factionNPC->GetMotionMaster()->MovePath(factionNPC->GetDBTableGUIDLow()*10, false); + factionNPC->GetMotionMaster()->MovePath(factionNPC->GetSpawnId() * 10, false); me->setActive(false); _damnedKills = 3; break; @@ -1140,7 +1140,7 @@ class npc_crok_scourgebane : public CreatureScript } } - void UpdateEscortAI(uint32 const diff) override + void UpdateEscortAI(uint32 diff) override { if (_wipeCheckTimer <= diff) _wipeCheckTimer = 0; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index 091190b6b4e..e739f5a5036 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -155,6 +155,7 @@ enum CreaturesIds NPC_ALCHEMIST_ADRIANNA = 38501, NPC_ALRIN_THE_AGILE = 38551, NPC_INFILTRATOR_MINCHAR_BQ = 38558, + NPC_INFILTRATOR_MINCHAR_BQ_25 = 39123, NPC_MINCHAR_BEAM_STALKER = 38557, NPC_VALITHRIA_DREAMWALKER_QUEST = 38589, diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 1b823b4a452..5354d1772b6 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -17,7 +17,6 @@ #include "AccountMgr.h" #include "InstanceScript.h" -#include "Map.h" #include "ObjectMgr.h" #include "Player.h" #include "PoolMgr.h" @@ -26,7 +25,6 @@ #include "Transport.h" #include "TransportMgr.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "icecrown_citadel.h" enum EventIds @@ -419,14 +417,14 @@ class instance_icecrown_citadel : public InstanceMapScript if (creature->AI()->GetData(1/*DATA_FROSTWYRM_OWNER*/) == DATA_SPINESTALKER) { - SpinestalkerTrash.erase(creature->GetDBTableGUIDLow()); + SpinestalkerTrash.erase(creature->GetSpawnId()); if (SpinestalkerTrash.empty()) if (Creature* spinestalk = instance->GetCreature(SpinestalkerGUID)) spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); } else { - RimefangTrash.erase(creature->GetDBTableGUIDLow()); + RimefangTrash.erase(creature->GetSpawnId()); if (RimefangTrash.empty()) if (Creature* spinestalk = instance->GetCreature(RimefangGUID)) spinestalk->AI()->DoAction(ACTION_START_FROSTWYRM); @@ -441,7 +439,7 @@ class instance_icecrown_citadel : public InstanceMapScript if (GetBossState(DATA_SINDRAGOSA) == DONE) return; - FrostwyrmGUIDs.erase(creature->GetDBTableGUIDLow()); + FrostwyrmGUIDs.erase(creature->GetSpawnId()); if (FrostwyrmGUIDs.empty()) { instance->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY()); @@ -1121,7 +1119,7 @@ class instance_icecrown_citadel : public InstanceMapScript bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override { - if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES)) + if (_SkipCheckRequiredBosses(player)) return true; switch (bossId) diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp index 733647fdb66..11fe5f41455 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp @@ -17,39 +17,61 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "Player.h" #include "naxxramas.h" -enum Says +enum AnubSays { SAY_AGGRO = 0, SAY_GREET = 1, - SAY_SLAY = 2 + SAY_SLAY = 2, + + EMOTE_LOCUST = 3 }; -Position const GuardSummonPos = {3333.72f, -3476.30f, 287.1f, 6.2801f}; +enum GuardSays +{ + EMOTE_FRENZY = 0, + EMOTE_SPAWN = 1, + EMOTE_SCARAB = 2 +}; enum Events { - EVENT_IMPALE = 1, - EVENT_LOCUST, - EVENT_SPAWN_GUARDIAN_NORMAL, - EVENT_BERSERK + EVENT_IMPALE = 1, // Cast Impale on a random target + EVENT_LOCUST, // Begin channeling Locust Swarm + EVENT_LOCUST_ENDS, // Locust swarm dissipates + EVENT_SPAWN_GUARD, // 10-man only - crypt guard has delayed spawn; also used for the locust swarm crypt guard in both modes + EVENT_SCARABS, // spawn corpse scarabs + EVENT_BERSERK // Berserk }; enum Spells { - SPELL_IMPALE = 28783, - SPELL_LOCUST_SWARM = 28785, + SPELL_IMPALE = 28783, // 25-man: 56090 + SPELL_LOCUST_SWARM = 28785, // 25-man: 54021 SPELL_SUMMON_CORPSE_SCARABS_PLR = 29105, // This spawns 5 corpse scarabs on top of player SPELL_SUMMON_CORPSE_SCARABS_MOB = 28864, // This spawns 10 corpse scarabs on top of dead guards SPELL_BERSERK = 27680 }; +enum SpawnGroups +{ + GROUP_INITIAL_25M = 1, + GROUP_SINGLE_SPAWN = 2 +}; + enum Misc { ACHIEV_TIMED_START_EVENT = 9891 }; +enum Phases +{ + PHASE_NORMAL = 1, + PHASE_SWARM +}; + class boss_anubrekhan : public CreatureScript { public: @@ -62,46 +84,64 @@ public: struct boss_anubrekhanAI : public BossAI { - boss_anubrekhanAI(Creature* creature) : BossAI(creature, BOSS_ANUBREKHAN) + boss_anubrekhanAI(Creature* creature) : BossAI(creature, BOSS_ANUBREKHAN) { } + + void SummonGuards() { - Initialize(); + if (Is25ManRaid()) + me->SummonCreatureGroup(GROUP_INITIAL_25M); } - void Initialize() + void InitializeAI() override { - hasTaunted = false; + if (!me->isDead()) + { + Reset(); + SummonGuards(); + } } - bool hasTaunted; - void Reset() override { _Reset(); + guardCorpses.clear(); + } - Initialize(); + void JustReachedHome() override + { + _JustReachedHome(); + SummonGuards(); + } - if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - { - Position pos; + void JustSummoned(Creature* summon) override + { + BossAI::JustSummoned(summon); - // respawn guard using home position, - // otherwise, after a wipe, they respawn where boss was at wipe moment. - pos = me->GetHomePosition(); - pos.m_positionY -= 10.0f; - me->SummonCreature(NPC_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); + if (me->IsInCombat()) + if (summon->GetEntry() == NPC_CRYPT_GUARD) + summon->AI()->Talk(EMOTE_SPAWN, me); + } - pos = me->GetHomePosition(); - pos.m_positionY += 10.0f; - me->SummonCreature(NPC_CRYPT_GUARD, pos, TEMPSUMMON_CORPSE_DESPAWN); - } + void SummonedCreatureDies(Creature* summon, Unit* killer) override + { + BossAI::SummonedCreatureDies(summon, killer); + + if (summon->GetEntry() == NPC_CRYPT_GUARD) + guardCorpses.insert(summon->GetGUID()); + } + + void SummonedCreatureDespawn(Creature* summon) override + { + BossAI::SummonedCreatureDespawn(summon); + + if (summon->GetEntry() == NPC_CRYPT_GUARD) + guardCorpses.erase(summon->GetGUID()); } void KilledUnit(Unit* victim) override { - /// Force the player to spawn corpse scarabs via spell, @todo Check percent chance for scarabs, 20% at the moment - if (!(rand32() % 5)) - if (victim->GetTypeId() == TYPEID_PLAYER) - victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, NULL, NULL, me->GetGUID()); + if (victim->GetTypeId() == TYPEID_PLAYER) + victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_PLR, true, nullptr, nullptr, me->GetGUID()); Talk(SAY_SLAY); } @@ -113,37 +153,22 @@ public: // start achievement timer (kill Maexna within 20 min) instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); } + void EnterCombat(Unit* /*who*/) override { _EnterCombat(); Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_IMPALE, urand(10000, 20000)); - events.ScheduleEvent(EVENT_LOCUST, 90000); - events.ScheduleEvent(EVENT_BERSERK, 600000); - - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - events.ScheduleEvent(EVENT_SPAWN_GUARDIAN_NORMAL, urand(15000, 20000)); - } - - void MoveInLineOfSight(Unit* who) override - { - if (!hasTaunted && me->IsWithinDistInMap(who, 60.0f) && who->GetTypeId() == TYPEID_PLAYER) - { - Talk(SAY_GREET); - hasTaunted = true; - } - ScriptedAI::MoveInLineOfSight(who); - } - void SummonedCreatureDespawn(Creature* summon) override - { - BossAI::SummonedCreatureDespawn(summon); + summons.DoZoneInCombat(); - // check if it is an actual killed guard - if (!me->IsAlive() || summon->IsAlive() || summon->GetEntry() != NPC_CRYPT_GUARD) - return; + 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); - summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, NULL, NULL, me->GetGUID()); + if (!Is25ManRaid()) + events.ScheduleEvent(EVENT_SPAWN_GUARD, urand(15, 20) * IN_MILLISECONDS); } void UpdateAI(uint32 diff) override @@ -158,22 +183,44 @@ public: switch (eventId) { case EVENT_IMPALE: - //Cast Impale on a random target - //Do NOT cast it when we are afflicted by locust swarm - if (!me->HasAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_LOCUST_SWARM, me))) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_IMPALE); - events.ScheduleEvent(EVENT_IMPALE, urand(10000, 20000)); + if (events.GetTimeUntilEvent(EVENT_LOCUST) < 5 * IN_MILLISECONDS) break; // don't chain impale tank -> locust swarm + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_IMPALE); + else + EnterEvadeMode(); + + events.ScheduleEvent(EVENT_IMPALE, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_NORMAL); + 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)) + if (Creature* creatureTarget = ObjectAccessor::GetCreature(*me, target)) + { + creatureTarget->CastSpell(creatureTarget, SPELL_SUMMON_CORPSE_SCARABS_MOB, true, nullptr, nullptr, me->GetGUID()); + creatureTarget->AI()->Talk(EMOTE_SCARAB); + creatureTarget->DespawnOrUnsummon(); + } + } break; case EVENT_LOCUST: - /// @todo Add Text + Talk(EMOTE_LOCUST); DoCast(me, SPELL_LOCUST_SWARM); - DoSummon(NPC_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); + 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); + 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); break; - case EVENT_SPAWN_GUARDIAN_NORMAL: - /// @todo Add Text - DoSummon(NPC_CRYPT_GUARD, GuardSummonPos, 0, TEMPSUMMON_CORPSE_DESPAWN); + case EVENT_SPAWN_GUARD: + me->SummonCreatureGroup(GROUP_SINGLE_SPAWN); break; case EVENT_BERSERK: DoCast(me, SPELL_BERSERK, true); @@ -182,13 +229,37 @@ public: } } - DoMeleeAttackIfReady(); + if (events.IsInPhase(PHASE_NORMAL)) + DoMeleeAttackIfReady(); } + private: + GuidSet guardCorpses; }; }; +class at_anubrekhan_entrance : public AreaTriggerScript +{ + public: + at_anubrekhan_entrance() : AreaTriggerScript("at_anubrekhan_entrance") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override + { + InstanceScript* instance = player->GetInstanceScript(); + if (!instance || instance->GetData(DATA_HAD_ANUBREKHAN_GREET) || instance->GetBossState(BOSS_ANUBREKHAN) != NOT_STARTED) + return true; + + if (Creature* anub = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_ANUBREKHAN))) + anub->AI()->Talk(SAY_GREET); + instance->SetData(DATA_HAD_ANUBREKHAN_GREET, 1u); + + return true; + } +}; + void AddSC_boss_anubrekhan() { new boss_anubrekhan(); + + new at_anubrekhan_entrance(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp index a87501e885a..dd9061603c8 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_faerlina.cpp @@ -18,14 +18,20 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "naxxramas.h" +#include "Player.h" +#include "SpellAuras.h" #include "SpellInfo.h" enum Yells { - SAY_GREET = 0, - SAY_AGGRO = 1, - SAY_SLAY = 2, - SAY_DEATH = 3 + SAY_GREET = 0, + SAY_AGGRO = 1, + SAY_SLAY = 2, + SAY_DEATH = 3, + + EMOTE_WIDOW_EMBRACE = 4, + EMOTE_FRENZY = 5 + }; enum Spells @@ -33,7 +39,9 @@ enum Spells SPELL_POISON_BOLT_VOLLEY = 28796, SPELL_RAIN_OF_FIRE = 28794, SPELL_FRENZY = 28798, - SPELL_WIDOWS_EMBRACE = 28732 + SPELL_WIDOWS_EMBRACE = 28732, + + SPELL_ADD_FIREBALL = 54095 // 25-man: 54096 }; #define SPELL_WIDOWS_EMBRACE_HELPER RAID_MODE<uint32>(28732, 54097) @@ -45,6 +53,12 @@ enum Events EVENT_FRENZY = 3 }; +enum SummonGroups +{ + SUMMON_GROUP_WORSHIPPERS = 1, + SUMMON_GROUP_FOLLOWERS = 2 +}; + enum Misc { DATA_FRENZY_DISPELS = 1 @@ -57,39 +71,46 @@ class boss_faerlina : public CreatureScript struct boss_faerlinaAI : public BossAI { - boss_faerlinaAI(Creature* creature) : BossAI(creature, BOSS_FAERLINA), - _frenzyDispels(0), _introDone(false), _delayFrenzy(false) + boss_faerlinaAI(Creature* creature) : BossAI(creature, BOSS_FAERLINA), _frenzyDispels(0) { } + + void SummonAdds() { + me->SummonCreatureGroup(SUMMON_GROUP_WORSHIPPERS); + if (Is25ManRaid()) + me->SummonCreatureGroup(SUMMON_GROUP_FOLLOWERS); } + void InitializeAI() override + { + if (!me->isDead()) + { + Reset(); + SummonAdds(); + } + } + + void JustReachedHome() override + { + _JustReachedHome(); + SummonAdds(); + } void EnterCombat(Unit* /*who*/) override { _EnterCombat(); Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_POISON, urand(10000, 15000)); - events.ScheduleEvent(EVENT_FIRE, urand(6000, 18000)); - events.ScheduleEvent(EVENT_FRENZY, urand(60000, 80000)); + 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)); } void Reset() override { _Reset(); - _delayFrenzy = false; _frenzyDispels = 0; } - void MoveInLineOfSight(Unit* who) override - { - if (!_introDone && who->GetTypeId() == TYPEID_PLAYER) - { - Talk(SAY_GREET); - _introDone = true; - } - - BossAI::MoveInLineOfSight(who); - } - void KilledUnit(Unit* /*victim*/) override { if (!urand(0, 2)) @@ -106,9 +127,8 @@ class boss_faerlina : public CreatureScript { if (spell->Id == SPELL_WIDOWS_EMBRACE_HELPER) { - /// @todo Add Text ++_frenzyDispels; - _delayFrenzy = true; + Talk(EMOTE_WIDOW_EMBRACE, caster); me->Kill(caster); } } @@ -126,12 +146,6 @@ class boss_faerlina : public CreatureScript if (!UpdateVictim()) return; - if (_delayFrenzy && !me->HasAura(SPELL_WIDOWS_EMBRACE_HELPER)) - { - _delayFrenzy = false; - DoCast(me, SPELL_FRENZY, true); - } - events.Update(diff); if (me->HasUnitState(UNIT_STATE_CASTING)) @@ -152,13 +166,14 @@ class boss_faerlina : public CreatureScript events.ScheduleEvent(EVENT_FIRE, urand(6000, 18000)); break; case EVENT_FRENZY: - /// @todo Add Text - if (!me->HasAura(SPELL_WIDOWS_EMBRACE_HELPER)) - DoCast(me, SPELL_FRENZY); + if (Aura* widowsEmbrace = me->GetAura(SPELL_WIDOWS_EMBRACE_HELPER)) + events.ScheduleEvent(EVENT_FRENZY, widowsEmbrace->GetDuration()+1 * IN_MILLISECONDS); else - _delayFrenzy = true; - - events.ScheduleEvent(EVENT_FRENZY, urand(60000, 80000)); + { + DoCast(SPELL_FRENZY); + Talk(EMOTE_FRENZY); + events.ScheduleEvent(EVENT_FRENZY, urand(60 * IN_MILLISECONDS, 80 * IN_MILLISECONDS)); + } break; } } @@ -168,8 +183,6 @@ class boss_faerlina : public CreatureScript private: uint32 _frenzyDispels; - bool _introDone; - bool _delayFrenzy; }; CreatureAI* GetAI(Creature* creature) const override @@ -192,19 +205,36 @@ class npc_faerlina_add : public CreatureScript void Reset() override { - if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) { + if (!Is25ManRaid()) { me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_BIND, true); me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_CHARM, true); } } + void EnterCombat(Unit* /*who*/) override + { + if (Creature* faerlina = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FAERLINA))) + faerlina->AI()->DoZoneInCombat(nullptr, 250.0f); + } + void JustDied(Unit* /*killer*/) override { - if (_instance && GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + if (!Is25ManRaid()) if (Creature* faerlina = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FAERLINA))) DoCast(faerlina, SPELL_WIDOWS_EMBRACE); } + void UpdateAI(uint32 /*diff*/) override + { + if (!UpdateVictim()) + return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + DoCastVictim(SPELL_ADD_FIREBALL); + DoMeleeAttackIfReady(); // this will only happen if the fireball cast fails for some reason + } + private: InstanceScript* const _instance; }; @@ -226,9 +256,29 @@ class achievement_momma_said_knock_you_out : public AchievementCriteriaScript } }; +class at_faerlina_entrance : public AreaTriggerScript +{ + public: + at_faerlina_entrance() : AreaTriggerScript("at_faerlina_entrance") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override + { + InstanceScript* instance = player->GetInstanceScript(); + if (!instance || instance->GetData(DATA_HAD_FAERLINA_GREET) || instance->GetBossState(BOSS_FAERLINA) != NOT_STARTED) + return true; + + if (Creature* faerlina = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_FAERLINA))) + faerlina->AI()->Talk(SAY_GREET); + instance->SetData(DATA_HAD_FAERLINA_GREET, 1u); + + return true; + } +}; + void AddSC_boss_faerlina() { new boss_faerlina(); new npc_faerlina_add(); + new at_faerlina_entrance(); new achievement_momma_said_knock_you_out(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp index 705d15081c1..3ef6a7c15e3 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -221,12 +221,12 @@ public: } } - void MovementInform(uint32 type, uint32 id) override + void MovementInform(uint32 type, uint32 point) override { if (type != POINT_MOTION_TYPE) return; - if (id == 2 || id == 5 || id == 8 || id == 11) + if (point == 2 || point == 5 || point == 8 || point == 11) { movementCompleted = true; me->SetReactState(REACT_AGGRESSIVE); @@ -251,7 +251,7 @@ public: } nextMovementStarted = false; - nextWP = id + 1; + nextWP = point + 1; } // switch to "who" if nearer than current target. diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index 7a76e8b8217..3778d8d25a0 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -176,8 +176,6 @@ class boss_gothik : public CreatureScript } uint32 waveCount; - typedef std::vector<Creature*> TriggerVct; - TriggerVct liveTrigger, deadTrigger; bool mergedSides; bool phaseTwo; bool thirtyPercentReached; @@ -319,37 +317,30 @@ class boss_gothik : public CreatureScript bool CheckGroupSplitted() { - Map* map = me->GetMap(); - if (map && map->IsDungeon()) + bool checklife = false; + bool checkdead = false; + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - Map::PlayerList const &PlayerList = map->GetPlayers(); - if (!PlayerList.isEmpty()) + if (i->GetSource() && i->GetSource()->IsAlive() && + i->GetSource()->GetPositionX() <= POS_X_NORTH && + i->GetSource()->GetPositionX() >= POS_X_SOUTH && + i->GetSource()->GetPositionY() <= POS_Y_GATE && + i->GetSource()->GetPositionY() >= POS_Y_EAST) { - bool checklife = false; - bool checkdead = false; - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->GetSource() && i->GetSource()->IsAlive() && - i->GetSource()->GetPositionX() <= POS_X_NORTH && - i->GetSource()->GetPositionX() >= POS_X_SOUTH && - i->GetSource()->GetPositionY() <= POS_Y_GATE && - i->GetSource()->GetPositionY() >= POS_Y_EAST) - { - checklife = true; - } - else if (i->GetSource() && i->GetSource()->IsAlive() && - i->GetSource()->GetPositionX() <= POS_X_NORTH && - i->GetSource()->GetPositionX() >= POS_X_SOUTH && - i->GetSource()->GetPositionY() >= POS_Y_GATE && - i->GetSource()->GetPositionY() <= POS_Y_WEST) - { - checkdead = true; - } - - if (checklife && checkdead) - return true; - } + checklife = true; } + else if (i->GetSource() && i->GetSource()->IsAlive() && + i->GetSource()->GetPositionX() <= POS_X_NORTH && + i->GetSource()->GetPositionX() >= POS_X_SOUTH && + i->GetSource()->GetPositionY() >= POS_Y_GATE && + i->GetSource()->GetPositionY() <= POS_Y_WEST) + { + checkdead = true; + } + + if (checklife && checkdead) + return true; } return false; @@ -557,20 +548,13 @@ class npc_gothik_minion : public CreatureScript if (!_EnterEvadeMode()) return; - Map* map = me->GetMap(); - if (map->IsDungeon()) + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - Map::PlayerList const &PlayerList = map->GetPlayers(); - if (!PlayerList.isEmpty()) + if (i->GetSource() && i->GetSource()->IsAlive() && isOnSameSide(i->GetSource())) { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->GetSource() && i->GetSource()->IsAlive() && isOnSameSide(i->GetSource())) - { - AttackStart(i->GetSource()); - return; - } - } + AttackStart(i->GetSource()); + return; } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp index 3d7c128c8dd..36e48d068b5 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_heigan.cpp @@ -21,36 +21,42 @@ #include "naxxramas.h" #include "Player.h" -enum Heigan +enum Spells { - SPELL_DECREPIT_FEVER = 29998, // 25-man: 55011 - SPELL_SPELL_DISRUPTION = 29310, - SPELL_PLAGUE_CLOUD = 29350, - - SAY_AGGRO = 0, - SAY_SLAY = 1, - SAY_TAUNT = 2, - SAY_DEATH = 3 + SPELL_DECREPIT_FEVER = 29998, // 25-man: 55011 + SPELL_SPELL_DISRUPTION = 29310, + SPELL_PLAGUE_CLOUD = 29350, + SPELL_TELEPORT_SELF = 30211, +}; + +enum Yells +{ + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_TAUNT = 2, + SAY_DEATH = 3, + + EMOTE_DANCE = 4, + EMOTE_DANCE_END = 5, }; enum Events { - EVENT_NONE, - EVENT_DISRUPT, + EVENT_DISRUPT = 1, EVENT_FEVER, EVENT_ERUPT, - EVENT_PHASE, + EVENT_DANCE, + EVENT_DANCE_END }; enum Phases { PHASE_FIGHT = 1, - PHASE_DANCE, + PHASE_DANCE }; enum Misc { - ACTION_SAFETY_DANCE_FAIL = 1, DATA_SAFETY_DANCE = 19962139 }; @@ -66,39 +72,25 @@ public: struct boss_heiganAI : public BossAI { - boss_heiganAI(Creature* creature) : BossAI(creature, BOSS_HEIGAN) + boss_heiganAI(Creature* creature) : BossAI(creature, BOSS_HEIGAN), eruptSection(0), eruptDirection(false), safetyDance(false) { } + + void Reset() override { - eruptSection = 0; - eruptDirection = false; - safetyDance = false; - phase = PHASE_FIGHT; + me->SetReactState(REACT_AGGRESSIVE); + _Reset(); } - uint32 eruptSection; - bool eruptDirection; - bool safetyDance; - Phases phase; - void KilledUnit(Unit* who) override { - if (!(rand32() % 5)) - Talk(SAY_SLAY); + Talk(SAY_SLAY); + if (who->GetTypeId() == TYPEID_PLAYER) safetyDance = false; } - void SetData(uint32 id, uint32 data) override - { - if (id == DATA_SAFETY_DANCE) - safetyDance = data ? true : false; - } - uint32 GetData(uint32 type) const override { - if (type == DATA_SAFETY_DANCE) - return safetyDance ? 1 : 0; - - return 0; + return (type == DATA_SAFETY_DANCE && safetyDance) ? 1u : 0u; } void JustDied(Unit* /*killer*/) override @@ -111,35 +103,14 @@ public: { _EnterCombat(); Talk(SAY_AGGRO); - EnterPhase(PHASE_FIGHT); - safetyDance = true; - } - void EnterPhase(Phases newPhase) - { - phase = newPhase; - events.Reset(); eruptSection = 3; - if (phase == PHASE_FIGHT) - { - events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000)); - events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000)); - events.ScheduleEvent(EVENT_PHASE, 90000); - events.ScheduleEvent(EVENT_ERUPT, 15000); - me->GetMotionMaster()->MoveChase(me->GetVictim()); - } - else - { - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o - (float(M_PI) / 2)); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetTarget(ObjectGuid::Empty); - DoCastAOE(SPELL_PLAGUE_CLOUD); - events.ScheduleEvent(EVENT_PHASE, 45000); - events.ScheduleEvent(EVENT_ERUPT, 8000); - } + 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); + + safetyDance = true; } void UpdateAI(uint32 diff) override @@ -155,15 +126,36 @@ public: { case EVENT_DISRUPT: DoCastAOE(SPELL_SPELL_DISRUPTION); - events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000)); + events.ScheduleEvent(EVENT_DISRUPT, 11 * IN_MILLISECONDS); break; case EVENT_FEVER: DoCastAOE(SPELL_DECREPIT_FEVER); - events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000)); + events.ScheduleEvent(EVENT_FEVER, urand(20 * IN_MILLISECONDS, 25 * IN_MILLISECONDS)); + break; + case EVENT_DANCE: + events.SetPhase(PHASE_DANCE); + Talk(SAY_TAUNT); + Talk(EMOTE_DANCE); + eruptSection = 3; + 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); break; - case EVENT_PHASE: - /// @todo Add missing texts for both phase switches - EnterPhase(phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT); + 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); + me->CastStop(); + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(); break; case EVENT_ERUPT: instance->SetData(DATA_HEIGAN_ERUPT, eruptSection); @@ -176,13 +168,22 @@ public: eruptDirection ? ++eruptSection : --eruptSection; - events.ScheduleEvent(EVENT_ERUPT, phase == PHASE_FIGHT ? 10000 : 3000); + 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); break; } } DoMeleeAttackIfReady(); } + + private: + uint32 eruptSection; + bool eruptDirection; + + bool safetyDance; // is achievement still possible? (= no player deaths yet) }; }; @@ -205,7 +206,7 @@ class spell_heigan_eruption : public SpellScriptLoader if (GetHitDamage() >= int32(GetHitPlayer()->GetHealth())) if (InstanceScript* instance = caster->GetInstanceScript()) if (Creature* Heigan = ObjectAccessor::GetCreature(*caster, instance->GetGuidData(DATA_HEIGAN))) - Heigan->AI()->SetData(DATA_SAFETY_DANCE, 0); + Heigan->AI()->KilledUnit(GetHitPlayer()); } void Register() override @@ -223,9 +224,7 @@ class spell_heigan_eruption : public SpellScriptLoader class achievement_safety_dance : public AchievementCriteriaScript { public: - achievement_safety_dance() : AchievementCriteriaScript("achievement_safety_dance") - { - } + achievement_safety_dance() : AchievementCriteriaScript("achievement_safety_dance") { } bool OnCheck(Player* /*player*/, Unit* target) override { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp index 33fb43b6bbc..494c173f5fc 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_loatheb.cpp @@ -27,7 +27,10 @@ enum Spells SPELL_WARN_NECROTIC_AURA = 59481, SPELL_SUMMON_SPORE = 29234, SPELL_DEATHBLOOM = 29865, - SPELL_INEVITABLE_DOOM = 29204 + SPELL_INEVITABLE_DOOM = 29204, + SPELL_FUNGAL_CREEP = 29232, + + SPELL_DEATHBLOOM_FINAL_DAMAGE = 55594, }; enum Texts @@ -72,29 +75,35 @@ class boss_loatheb : public CreatureScript void Reset() override { _Reset(); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FUNGAL_CREEP); Initialize(); } void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.ScheduleEvent(EVENT_NECROTIC_AURA, 17000); - events.ScheduleEvent(EVENT_DEATHBLOOM, 5000); - events.ScheduleEvent(EVENT_SPORE, IsHeroic() ? 18000 : 36000); - events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 120000); + 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); } - void SummonedCreatureDies(Creature* /*summon*/, Unit* /*killer*/) override + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override { _sporeLoserData = false; + summon->CastSpell(summon,SPELL_FUNGAL_CREEP,true); } - uint32 GetData(uint32 id) const override + void SummonedCreatureDespawn(Creature* summon) override { - if (id != DATA_ACHIEVEMENT_SPORE_LOSER) - return 0; + summons.Despawn(summon); + if (summon->IsAlive()) + summon->CastSpell(summon,SPELL_FUNGAL_CREEP,true); + } - return uint32(_sporeLoserData); + uint32 GetData(uint32 id) const override + { + return (_sporeLoserData && id == DATA_ACHIEVEMENT_SPORE_LOSER) ? 1u : 0u; } void UpdateAI(uint32 diff) override @@ -111,21 +120,29 @@ class boss_loatheb : public CreatureScript case EVENT_NECROTIC_AURA: DoCastAOE(SPELL_NECROTIC_AURA); DoCast(me, SPELL_WARN_NECROTIC_AURA); - events.ScheduleEvent(EVENT_NECROTIC_AURA, 20000); - events.ScheduleEvent(EVENT_NECROTIC_AURA_FADING, 14000); + events.ScheduleEvent(EVENT_NECROTIC_AURA, 20 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_NECROTIC_AURA_FADING, 14 * IN_MILLISECONDS); break; case EVENT_DEATHBLOOM: DoCastAOE(SPELL_DEATHBLOOM); - events.ScheduleEvent(EVENT_DEATHBLOOM, 30000); + events.ScheduleEvent(EVENT_DEATHBLOOM, 30 * IN_MILLISECONDS); break; case EVENT_INEVITABLE_DOOM: _doomCounter++; DoCastAOE(SPELL_INEVITABLE_DOOM); - events.ScheduleEvent(EVENT_INEVITABLE_DOOM, std::max(120000 - _doomCounter * 15000, 15000)); // needs to be confirmed + if (_doomCounter > 6) + { + if (_doomCounter & 1) // odd + events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 14 * IN_MILLISECONDS); + else + events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 17 * IN_MILLISECONDS); + } + else + events.ScheduleEvent(EVENT_INEVITABLE_DOOM, 30 * IN_MILLISECONDS); break; case EVENT_SPORE: DoCast(me, SPELL_SUMMON_SPORE, false); - events.ScheduleEvent(EVENT_SPORE, IsHeroic() ? 18000 : 36000); + events.ScheduleEvent(EVENT_SPORE, RAID_MODE(36,18) * IN_MILLISECONDS); break; case EVENT_NECROTIC_AURA_FADING: Talk(SAY_NECROTIC_AURA_FADING); @@ -203,9 +220,46 @@ class spell_loatheb_necrotic_aura_warning : public SpellScriptLoader } }; +class spell_loatheb_deathbloom : public SpellScriptLoader +{ + public: + spell_loatheb_deathbloom() : SpellScriptLoader("spell_loatheb_deathbloom") { } + + class spell_loatheb_deathbloom_AuraScript : public AuraScript + { + PrepareAuraScript(spell_loatheb_deathbloom_AuraScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DEATHBLOOM_FINAL_DAMAGE)) + return false; + return true; + } + + void AfterRemove(AuraEffect const* eff, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) + return; + + GetTarget()->CastSpell(nullptr, SPELL_DEATHBLOOM_FINAL_DAMAGE, true, nullptr, eff, GetCasterGUID()); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_loatheb_deathbloom_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_loatheb_deathbloom_AuraScript(); + } +}; + 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 e52731d003e..0d938122f28 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -18,6 +18,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "PassiveAI.h" +#include "SpellScript.h" #include "naxxramas.h" enum Spells @@ -28,6 +29,14 @@ enum Spells SPELL_NECROTIC_POISON = 28776, SPELL_FRENZY = 54123 }; +#define SPELL_FRENZY_HELPER RAID_MODE(54123,54124) + +enum Emotes +{ + EMOTE_SPIDERS = 0, + EMOTE_WEB_WRAP = 1, + EMOTE_WEB_SPRAY = 2 +}; enum Creatures { @@ -35,12 +44,16 @@ enum Creatures NPC_SPIDERLING = 17055, }; -#define MAX_POS_WRAP 3 -const Position PosWrap[MAX_POS_WRAP] = +#define MAX_WRAP_POSITION 7 +const Position WrapPositions[MAX_WRAP_POSITION] = { - {3546.796f, -3869.082f, 296.450f, 0.0f}, - {3531.271f, -3847.424f, 299.450f, 0.0f}, - {3497.067f, -3843.384f, 302.384f, 0.0f}, + {3453.818f, -3854.651f, 308.7581f, 4.362833f}, + {3535.042f, -3842.383f, 300.795f, 3.179324f}, + {3538.399f, -3846.088f, 299.964f, 4.310297f}, + {3548.464f, -3854.676f, 298.6075f, 4.546609f}, + {3557.663f, -3870.123f, 297.5027f, 3.756433f}, + {3560.546f, -3879.353f, 297.4843f, 2.508937f}, + {3562.535f, -3892.507f, 298.532f, 6.022466f}, }; enum Events @@ -51,7 +64,24 @@ enum Events EVENT_POISON, EVENT_WRAP, EVENT_SUMMON, - EVENT_FRENZY, +}; + +const float WEB_WRAP_MOVE_SPEED = 20.0f; + +struct WebTargetSelector : public std::unary_function<Unit*, bool> +{ + WebTargetSelector(Unit* maexxna) : _maexxna(maexxna) {} + bool operator()(Unit const* target) const + { + if (_maexxna->GetVictim() == target) // never target tank + return false; + if (target->HasAura(SPELL_WEB_WRAP)) // never target targets that are already webbed + return false; + return true; + } + + private: + const Unit* _maexxna; }; class boss_maexxna : public CreatureScript @@ -66,27 +96,22 @@ public: struct boss_maexxnaAI : public BossAI { - boss_maexxnaAI(Creature* creature) : BossAI(creature, BOSS_MAEXXNA) - { - Initialize(); - } + boss_maexxnaAI(Creature* creature) : BossAI(creature, BOSS_MAEXXNA) { } - void Initialize() + void EnterCombat(Unit* /*who*/) override { - enraged = false; + _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); } - bool enraged; - - void EnterCombat(Unit* /*who*/) override + void Reset() override { - _EnterCombat(); - Initialize(); - events.ScheduleEvent(EVENT_WRAP, 20000); - events.ScheduleEvent(EVENT_SPRAY, 40000); - events.ScheduleEvent(EVENT_SHOCK, urand(5000, 10000)); - events.ScheduleEvent(EVENT_POISON, urand(10000, 15000)); - events.ScheduleEvent(EVENT_SUMMON, 30000); + _Reset(); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_WEB_WRAP); } void UpdateAI(uint32 diff) override @@ -94,10 +119,9 @@ public: if (!UpdateVictim() || !CheckInRoom()) return; - if (!enraged && HealthBelowPct(30)) + if (HealthBelowPct(30) && !me->HasAura(SPELL_FRENZY_HELPER)) { - enraged = true; - events.ScheduleEvent(EVENT_FRENZY, 0); // will be cast immediately + DoCast(SPELL_FRENZY); } events.Update(diff); @@ -107,41 +131,49 @@ public: switch (eventId) { case EVENT_WRAP: - /// @todo Add missing text - for (uint8 i = 0; i < RAID_MODE(1, 2); ++i) + { + std::list<Unit*> targets; + SelectTargetList(targets, WebTargetSelector(me), RAID_MODE(1, 2), SELECT_TARGET_RANDOM); + if (!targets.empty()) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0, true, -SPELL_WEB_WRAP)) + Talk(EMOTE_WEB_WRAP); + int8 wrapPos = -1; + for (Unit* target : targets) { + if (wrapPos == -1) // allow all positions on the first target + wrapPos = urand(0, MAX_WRAP_POSITION - 1); + else // on subsequent iterations, only allow positions that are not equal to the previous one (this is sufficient since we should only have two targets at most, ever) + wrapPos = (wrapPos + urand(1, MAX_WRAP_POSITION - 1)) % MAX_WRAP_POSITION; + target->RemoveAura(sSpellMgr->GetSpellIdForDifficulty(SPELL_WEB_SPRAY, me)); - uint8 pos = rand32() % MAX_POS_WRAP; - target->GetMotionMaster()->MoveJump(PosWrap[pos].GetPositionX(), PosWrap[pos].GetPositionY(), PosWrap[pos].GetPositionZ(), 20, 20); - if (Creature* wrap = DoSummon(NPC_WEB_WRAP, PosWrap[pos], 0, TEMPSUMMON_CORPSE_DESPAWN)) - wrap->AI()->SetGUID(target->GetGUID()); + if (Creature* wrap = DoSummon(NPC_WEB_WRAP, WrapPositions[wrapPos], 70 * IN_MILLISECONDS, TEMPSUMMON_TIMED_DESPAWN)) + { + wrap->AI()->SetGUID(target->GetGUID()); // handles application of debuff + target->GetMotionMaster()->MoveJump(WrapPositions[wrapPos], WEB_WRAP_MOVE_SPEED, WEB_WRAP_MOVE_SPEED); // move after stun to avoid stun cancelling move + } } } events.ScheduleEvent(EVENT_WRAP, 40000); break; + } case EVENT_SPRAY: + Talk(EMOTE_WEB_SPRAY); DoCastAOE(SPELL_WEB_SPRAY); events.ScheduleEvent(EVENT_SPRAY, 40000); break; case EVENT_SHOCK: DoCastAOE(SPELL_POISON_SHOCK); - events.ScheduleEvent(EVENT_SHOCK, urand(10000, 20000)); + events.ScheduleEvent(EVENT_SHOCK, urandms(10, 20)); break; case EVENT_POISON: DoCastVictim(SPELL_NECROTIC_POISON); - events.ScheduleEvent(EVENT_POISON, urand(10000, 20000)); - break; - case EVENT_FRENZY: - DoCast(me, SPELL_FRENZY, true); - events.ScheduleEvent(EVENT_FRENZY, 600000); + events.ScheduleEvent(EVENT_POISON, urandms(10, 20)); break; case EVENT_SUMMON: - /// @todo Add missing text + Talk(EMOTE_SPIDERS); uint8 amount = urand(8, 10); for (uint8 i = 0; i < amount; ++i) - DoSummon(NPC_SPIDERLING, me, 0, TEMPSUMMON_CORPSE_DESPAWN); + DoSummon(NPC_SPIDERLING, me, 4.0f, 5 * IN_MILLISECONDS, TEMPSUMMON_CORPSE_TIMED_DESPAWN); events.ScheduleEvent(EVENT_SUMMON, 40000); break; } @@ -165,23 +197,49 @@ public: struct npc_webwrapAI : public NullCreatureAI { - npc_webwrapAI(Creature* creature) : NullCreatureAI(creature) { } + npc_webwrapAI(Creature* creature) : NullCreatureAI(creature), visibleTimer(0) { } ObjectGuid victimGUID; + uint32 visibleTimer; + + void InitializeAI() override + { + me->SetVisible(false); + } void SetGUID(ObjectGuid guid, int32 /*param*/) override { + if (!guid) + return; victimGUID = guid; - if (me->m_spells[0] && victimGUID) - if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID)) - victim->CastSpell(victim, me->m_spells[0], true, NULL, NULL, me->GetGUID()); + if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID)) + { + visibleTimer = (me->GetDistance2d(victim)/WEB_WRAP_MOVE_SPEED + 0.5f) * IN_MILLISECONDS; + victim->CastSpell(victim, SPELL_WEB_WRAP, true, NULL, NULL, me->GetGUID()); + } + } + + void UpdateAI(uint32 diff) override + { + if (!visibleTimer) + return; + + if (diff >= visibleTimer) + { + visibleTimer = 0; + me->SetVisible(true); + } + else + visibleTimer -= diff; } void JustDied(Unit* /*killer*/) override { - if (me->m_spells[0] && victimGUID) + if (victimGUID) if (Unit* victim = ObjectAccessor::GetUnit(*me, victimGUID)) - victim->RemoveAurasDueToSpell(me->m_spells[0], me->GetGUID()); + victim->RemoveAurasDueToSpell(SPELL_WEB_WRAP, me->GetGUID()); + + me->DespawnOrUnsummon(5 * IN_MILLISECONDS); } }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index f5e5b287571..7b3a9f8ac74 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -19,51 +19,58 @@ #include "ScriptedCreature.h" #include "naxxramas.h" -enum Noth +enum Phases { - SAY_AGGRO = 0, - SAY_SUMMON = 1, - SAY_SLAY = 2, - SAY_DEATH = 3, - - SOUND_DEATH = 8848, - - SPELL_CURSE_PLAGUEBRINGER = 29213, // 25-man: 54835 - SPELL_CRIPPLE = 29212, // 25-man: 54814 - SPELL_TELEPORT = 29216, - - NPC_WARRIOR = 16984, - NPC_CHAMPION = 16983, - NPC_GUARDIAN = 16981 + PHASE_NONE, + PHASE_GROUND, + PHASE_BALCONY }; -#define SPELL_BLINK RAND(29208, 29209, 29210, 29211) +enum Events +{ + EVENT_CURSE = 1, // curse of the plaguebringer + EVENT_BLINK, // blink (25m only) + EVENT_WARRIOR, // summon warriors during ground phase + EVENT_BALCONY, // become untargetable and begin balcony phase + EVENT_BALCONY_TELEPORT, // actually teleport to balcony, this is slightly delayed + EVENT_WAVE, // spawn wave during balcony phase + EVENT_GROUND, // end balcony phase and teleport to ground + EVENT_GROUND_ATTACKABLE // become attackable and aggressive again at start of ground phase, once again slightly delayed to prevent motionmaster weirdness +}; -// Teleport position of Noth on his balcony -Position const Teleport = { 2631.370f, -3529.680f, 274.040f, 6.277f }; +enum Talk +{ + SAY_AGGRO = 0, + SAY_SUMMON = 1, + SAY_SLAY = 2, + SAY_DEATH = 3, -#define MAX_SUMMON_POS 5 + EMOTE_SUMMON = 4, // ground phase + EMOTE_SUMMON_WAVE = 5, // balcony phase + EMOTE_TELEPORT_1 = 6, // ground to balcony + EMOTE_TELEPORT_2 = 7 // balcony to ground +}; -Position const SummonPos[MAX_SUMMON_POS] = +enum Spells { - { 2728.12f, -3544.43f, 261.91f, 6.04f }, - { 2729.05f, -3544.47f, 261.91f, 5.58f }, - { 2728.24f, -3465.08f, 264.20f, 3.56f }, - { 2704.11f, -3456.81f, 265.53f, 4.51f }, - { 2663.56f, -3464.43f, 262.66f, 5.20f } + SPELL_CURSE = 29213, // 25-man: 54835 + SPELL_CRIPPLE = 29212, // 25-man: 54814 + + SPELL_TELEPORT = 29216, // ground to balcony + SPELL_TELEPORT_BACK = 29231 // balcony to ground }; -enum Events +enum Adds { - EVENT_NONE, - EVENT_BERSERK, - EVENT_CURSE, - EVENT_BLINK, - EVENT_WARRIOR, - EVENT_BALCONY, - EVENT_WAVE, - EVENT_GROUND + N_WARRIOR_SPELLS = 3, + N_CHAMPION_SPELLS = 6, + N_GUARDIAN_SPELLS = 3 }; +const uint32 SummonWarriorSpells[N_WARRIOR_SPELLS] = { 29247, 29248, 29249 }; +const uint32 SummonChampionSpells[N_CHAMPION_SPELLS] = { 29238, 29255, 29257, 29258, 29262, 29267 }; +const uint32 SummonGuardianSpells[N_GUARDIAN_SPELLS] = { 29239, 29256, 29268 }; + +#define SPELL_BLINK RAND(29208, 29209, 29210, 29211) class boss_noth : public CreatureScript { @@ -72,16 +79,38 @@ public: struct boss_nothAI : public BossAI { - boss_nothAI(Creature* creature) : BossAI(creature, BOSS_NOTH) + boss_nothAI(Creature* creature) : BossAI(creature, BOSS_NOTH), balconyCount(0), justBlinked(false) { - balconyCount = 0; - waveCount = 0; + std::copy(SummonWarriorSpells, SummonWarriorSpells + N_WARRIOR_SPELLS, _SummonWarriorSpells); + std::copy(SummonChampionSpells, SummonChampionSpells + N_CHAMPION_SPELLS, _SummonChampionSpells); + std::copy(SummonGuardianSpells, SummonGuardianSpells + N_GUARDIAN_SPELLS, _SummonGuardianSpells); + + events.SetPhase(PHASE_NONE); + } + + void EnterEvadeMode() override + { + Reset(); // teleport back first + _EnterEvadeMode(); } void Reset() override { - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (!me->IsAlive()) + return; + + // in case we reset during balcony phase + if (events.IsInPhase(PHASE_BALCONY)) + { + DoCastAOE(SPELL_TELEPORT_BACK); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); + } + + balconyCount = 0; + events.SetPhase(PHASE_NONE); + justBlinked = false; + _Reset(); } @@ -89,31 +118,44 @@ public: { _EnterCombat(); Talk(SAY_AGGRO); - balconyCount = 0; EnterPhaseGround(); } void EnterPhaseGround() { - me->SetReactState(REACT_AGGRESSIVE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + events.SetPhase(PHASE_GROUND); + DoZoneInCombat(); if (me->getThreatManager().isThreatListEmpty()) - EnterEvadeMode(); + Reset(); else { - events.ScheduleEvent(EVENT_BALCONY, 110000); - events.ScheduleEvent(EVENT_CURSE, 10000 + rand32() % 15000); - events.ScheduleEvent(EVENT_WARRIOR, 30000); + uint8 secondsGround; + switch (balconyCount) + { + case 0: + secondsGround = 90; + break; + case 1: + secondsGround = 110; + break; + case 2: + default: + secondsGround = 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); if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - events.ScheduleEvent(EVENT_BLINK, urand(20000, 40000)); + events.ScheduleEvent(EVENT_BLINK, urand(20,30) * IN_MILLISECONDS, 0, PHASE_GROUND); } } - void KilledUnit(Unit* /*victim*/) override + void KilledUnit(Unit* victim) override { - if (!(rand32() % 5)) + if (victim->GetTypeId() == TYPEID_PLAYER) Talk(SAY_SLAY); } @@ -121,7 +163,7 @@ public: { summons.Summon(summon); summon->setActive(true); - summon->AI()->DoZoneInCombat(); + summon->AI()->DoZoneInCombat(nullptr, 250.0f); // specify range to cover entire room - default 50yd is not enough } void JustDied(Unit* /*killer*/) override @@ -130,10 +172,35 @@ public: Talk(SAY_DEATH); } - void SummonUndead(uint32 entry, uint32 num) + void DamageTaken(Unit* /*who*/, uint32& damage) override // prevent noth from somehow dying in the balcony phase { - for (uint32 i = 0; i < num; ++i) - me->SummonCreature(entry, SummonPos[rand32() % MAX_SUMMON_POS], TEMPSUMMON_CORPSE_DESPAWN, 60000); + if (!events.IsInPhase(PHASE_BALCONY)) + return; + if (damage < me->GetHealth()) + return; + + me->SetHealth(1u); + damage = 0u; + } + + void HandleSummon(uint32* spellsList, const uint8 nSpells, uint8 num) + { // this ensures we do not spawn two mobs using the same spell (<=> in the same position) if we can help it + while (num) + for (uint8 it = 0; it < nSpells && num; ++it) + { + num--; + uint8 selected = urand(it, nSpells - 1); + DoCastAOE(spellsList[selected]); + if (selected != it) // shuffle the selected into the part of the array that is no longer being searched + std::swap(spellsList[selected], spellsList[it]); + } + } + + void CastSummon(uint8 nWarrior, uint8 nChampion, uint8 nGuardian) + { + HandleSummon(_SummonWarriorSpells, N_WARRIOR_SPELLS, nWarrior); + HandleSummon(_SummonChampionSpells, N_CHAMPION_SPELLS, nChampion); + HandleSummon(_SummonGuardianSpells, N_GUARDIAN_SPELLS, nGuardian); } void UpdateAI(uint32 diff) override @@ -151,72 +218,115 @@ public: switch (eventId) { case EVENT_CURSE: - DoCastAOE(SPELL_CURSE_PLAGUEBRINGER); - events.ScheduleEvent(EVENT_CURSE, urand(50000, 60000)); - return; + { + DoCastAOE(SPELL_CURSE); + events.ScheduleEvent(EVENT_CURSE, urand(50, 70) * IN_MILLISECONDS, 0, PHASE_GROUND); + break; + } case EVENT_WARRIOR: Talk(SAY_SUMMON); - SummonUndead(NPC_WARRIOR, RAID_MODE(2, 3)); - events.ScheduleEvent(EVENT_WARRIOR, 30000); - return; + Talk(EMOTE_SUMMON); + + CastSummon(RAID_MODE(2, 3), 0, 0); + + events.ScheduleEvent(EVENT_WARRIOR, 40 * IN_MILLISECONDS, 0, PHASE_GROUND); + break; case EVENT_BLINK: DoCastAOE(SPELL_CRIPPLE, true); DoCastAOE(SPELL_BLINK); DoResetThreat(); - events.ScheduleEvent(EVENT_BLINK, 40000); - return; + justBlinked = true; + + events.ScheduleEvent(EVENT_BLINK, 40000, 0, PHASE_GROUND); + break; case EVENT_BALCONY: + events.SetPhase(PHASE_BALCONY); me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); me->AttackStop(); + me->StopMoving(); me->RemoveAllAuras(); - me->NearTeleportTo(Teleport.GetPositionX(), Teleport.GetPositionY(), Teleport.GetPositionZ(), Teleport.GetOrientation()); - events.Reset(); - events.ScheduleEvent(EVENT_WAVE, urand(2000, 5000)); - waveCount = 0; - return; + + 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); + + uint8 secondsBalcony; + switch (balconyCount) + { + case 0: + secondsBalcony = 70; + break; + case 1: + secondsBalcony = 97; + break; + case 2: + default: + secondsBalcony = 120; + break; + } + events.ScheduleEvent(EVENT_GROUND, secondsBalcony * IN_MILLISECONDS, 0, PHASE_BALCONY); + break; + case EVENT_BALCONY_TELEPORT: + Talk(EMOTE_TELEPORT_1); + DoCastAOE(SPELL_TELEPORT); + break; case EVENT_WAVE: - Talk(SAY_SUMMON); + Talk(EMOTE_SUMMON_WAVE); switch (balconyCount) { case 0: - SummonUndead(NPC_CHAMPION, RAID_MODE(2, 4)); + CastSummon(0, RAID_MODE(2, 4), 0); break; case 1: - SummonUndead(NPC_CHAMPION, RAID_MODE(1, 2)); - SummonUndead(NPC_GUARDIAN, RAID_MODE(1, 2)); + CastSummon(0, RAID_MODE(1, 2), RAID_MODE(1, 2)); break; case 2: - SummonUndead(NPC_GUARDIAN, RAID_MODE(2, 4)); + CastSummon(0, 0, RAID_MODE(2, 4)); break; default: - SummonUndead(NPC_CHAMPION, RAID_MODE(5, 10)); - SummonUndead(NPC_GUARDIAN, RAID_MODE(5, 10)); + CastSummon(0, RAID_MODE(5, 10), RAID_MODE(5, 10)); break; } - ++waveCount; - events.ScheduleEvent(waveCount < 2 ? EVENT_WAVE : EVENT_GROUND, urand(30000, 45000)); - return; + events.ScheduleEvent(EVENT_WAVE, urand(30, 45) * IN_MILLISECONDS, 0, PHASE_BALCONY); + break; case EVENT_GROUND: - { ++balconyCount; - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o); - events.ScheduleEvent(EVENT_BALCONY, 110000); + + DoCastAOE(SPELL_TELEPORT_BACK); + Talk(EMOTE_TELEPORT_2); + EnterPhaseGround(); - return; - } + break; + case EVENT_GROUND_ATTACKABLE: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + break; } } - if (me->HasReactState(REACT_AGGRESSIVE)) - DoMeleeAttackIfReady(); + if (events.IsInPhase(PHASE_GROUND)) + { + /* workaround for movechase breaking after blinking + without this noth would just stand there unless his current target moves */ + if (justBlinked && me->GetVictim() && !me->IsWithinMeleeRange(me->EnsureVictim())) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->EnsureVictim()); + justBlinked = false; + } + else + DoMeleeAttackIfReady(); + } } private: - uint32 waveCount; uint32 balconyCount; + + bool justBlinked; + + uint32 _SummonWarriorSpells[N_WARRIOR_SPELLS]; + uint32 _SummonChampionSpells[N_CHAMPION_SPELLS]; + uint32 _SummonGuardianSpells[N_GUARDIAN_SPELLS]; }; CreatureAI* GetAI(Creature* creature) const override diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp index f5842181358..7c85c5f73b9 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp @@ -21,7 +21,7 @@ enum Spells { - SPELL_HATEFUL_STRIKE = 41926, + SPELL_HATEFUL_STRIKE = 28308, SPELL_FRENZY = 28131, SPELL_BERSERK = 26662, SPELL_SLIME_BOLT = 32309 @@ -33,7 +33,7 @@ enum Yells SAY_SLAY = 1, SAY_DEATH = 2, EMOTE_BERSERK = 3, - EMOTE_ENRAGE = 4 + EMOTE_FRENZY = 4 }; enum Events @@ -49,6 +49,11 @@ enum Misc ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT = 10286 }; +enum HatefulThreatAmounts +{ + HATEFUL_THREAT_AMT = 1000, +}; + class boss_patchwerk : public CreatureScript { public: @@ -92,8 +97,8 @@ public: _EnterCombat(); Enraged = false; Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_HATEFUL, 1000); - events.ScheduleEvent(EVENT_BERSERK, 360000); + events.ScheduleEvent(EVENT_HATEFUL, 1 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_BERSERK, 6 * MINUTE * IN_MILLISECONDS); instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT); } @@ -111,37 +116,68 @@ public: { case EVENT_HATEFUL: { - //Cast Hateful strike on the player with the highest - //amount of HP within melee distance - uint32 MostHP = 0; - Unit* pMostHPTarget = NULL; + // Hateful Strike targets the highest non-MT threat in melee range on 10man + // and the higher HP target out of the two highest non-MT threats in melee range on 25man + float MostThreat = 0.0f; + Unit* secondThreatTarget = NULL; + Unit* thirdThreatTarget = NULL; + std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); for (; i != me->getThreatManager().getThreatList().end(); ++i) - { + { // find second highest Unit* target = (*i)->getTarget(); - if (target->IsAlive() && target != me->GetVictim() && target->GetHealth() > MostHP && me->IsWithinMeleeRange(target)) + if (target->IsAlive() && target != me->GetVictim() && (*i)->getThreat() >= MostThreat && me->IsWithinMeleeRange(target)) + { + MostThreat = (*i)->getThreat(); + secondThreatTarget = target; + } + } + + if (secondThreatTarget && Is25ManRaid()) + { // find third highest + MostThreat = 0.0f; + i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) { - MostHP = target->GetHealth(); - pMostHPTarget = target; + Unit* target = (*i)->getTarget(); + if (target->IsAlive() && target != me->GetVictim() && target != secondThreatTarget && (*i)->getThreat() >= MostThreat && me->IsWithinMeleeRange(target)) + { + MostThreat = (*i)->getThreat(); + thirdThreatTarget = target; + } } } - if (!pMostHPTarget) - pMostHPTarget = me->GetVictim(); + Unit* pHatefulTarget = NULL; + if (!thirdThreatTarget) + pHatefulTarget = secondThreatTarget; + else if (secondThreatTarget) + pHatefulTarget = (secondThreatTarget->GetHealth() < thirdThreatTarget->GetHealth()) ? thirdThreatTarget : secondThreatTarget; + + if (!pHatefulTarget) + pHatefulTarget = me->GetVictim(); + + DoCast(pHatefulTarget, SPELL_HATEFUL_STRIKE, true); - DoCast(pMostHPTarget, SPELL_HATEFUL_STRIKE, true); + // add threat to highest threat targets + if (me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim())) + me->getThreatManager().addThreat(me->GetVictim(), HATEFUL_THREAT_AMT); + if (secondThreatTarget) + me->getThreatManager().addThreat(secondThreatTarget, HATEFUL_THREAT_AMT); + if (thirdThreatTarget) + me->getThreatManager().addThreat(thirdThreatTarget, HATEFUL_THREAT_AMT); // this will only ever be used in 25m - events.ScheduleEvent(EVENT_HATEFUL, 1000); + events.ScheduleEvent(EVENT_HATEFUL, 1 * IN_MILLISECONDS); break; } case EVENT_BERSERK: DoCast(me, SPELL_BERSERK, true); Talk(EMOTE_BERSERK); - events.ScheduleEvent(EVENT_SLIME, 2000); + events.ScheduleEvent(EVENT_SLIME, 2 * IN_MILLISECONDS); break; case EVENT_SLIME: DoCastVictim(SPELL_SLIME_BOLT, true); - events.ScheduleEvent(EVENT_SLIME, 2000); + events.ScheduleEvent(EVENT_SLIME, 2 * IN_MILLISECONDS); break; } } @@ -149,7 +185,7 @@ public: if (!Enraged && HealthBelowPct(5)) { DoCast(me, SPELL_FRENZY, true); - Talk(EMOTE_ENRAGE); + Talk(EMOTE_FRENZY); Enraged = true; } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp index ee482c23d1b..02a7aa570e5 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -43,6 +43,7 @@ enum Spells SPELL_BERSERK = 26662, SPELL_DIES = 29357, SPELL_CHILL = 28547, + SPELL_CHECK_RESISTS = 60539, }; enum Phases @@ -67,7 +68,8 @@ enum Events EVENT_EXPLOSION, EVENT_LAND, EVENT_GROUND, - EVENT_BIRTH + EVENT_BIRTH, + EVENT_CHECK_RESISTS }; enum Misc @@ -90,10 +92,9 @@ class boss_sapphiron : public CreatureScript struct boss_sapphironAI : public BossAI { boss_sapphironAI(Creature* creature) : - BossAI(creature, BOSS_SAPPHIRON), _map(me->GetMap()) + BossAI(creature, BOSS_SAPPHIRON), _iceboltCount(0), _map(me->GetMap()) { Initialize(); - _iceboltCount = 0; } void Initialize() @@ -101,7 +102,6 @@ class boss_sapphiron : public CreatureScript _phase = PHASE_NULL; _canTheHundredClub = true; - _checkFrostResistTimer = 5 * IN_MILLISECONDS; } void InitializeAI() override @@ -123,7 +123,16 @@ class boss_sapphiron : public CreatureScript _Reset(); if (_phase == PHASE_FLIGHT) + { ClearIceBlock(); + me->SetReactState(REACT_AGGRESSIVE); + if (me->IsHovering()) + { + me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); + me->SetHover(false); + } + me->SetDisableGravity(false); + } Initialize(); } @@ -134,22 +143,30 @@ class boss_sapphiron : public CreatureScript 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(); - - CheckPlayersFrostResist(); } void SpellHitTarget(Unit* target, SpellInfo const* spell) override { - if (spell->Id == SPELL_ICEBOLT) + switch(spell->Id) { - IceBlockMap::iterator itr = _iceblocks.find(target->GetGUID()); - if (itr != _iceblocks.end() && !itr->second) + case SPELL_ICEBOLT: { - if (GameObject* iceblock = me->SummonGameObject(GO_ICEBLOCK, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, 0, 0, 0, 0, 25)) - itr->second = iceblock->GetGUID(); + 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; + break; } } @@ -157,8 +174,6 @@ class boss_sapphiron : public CreatureScript { _JustDied(); me->CastSpell(me, SPELL_DIES, true); - - CheckPlayersFrostResist(); } void MovementInform(uint32 /*type*/, uint32 id) override @@ -176,22 +191,6 @@ class boss_sapphiron : public CreatureScript } } - void CheckPlayersFrostResist() - { - if (_canTheHundredClub && _map && _map->IsRaid()) - { - Map::PlayerList const &players = _map->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (itr->GetSource()->GetResistance(SPELL_SCHOOL_FROST) > MAX_FROST_RESISTANCE) - { - _canTheHundredClub = false; - break; - } - } - } - } - void EnterPhaseGround() { _phase = PHASE_GROUND; @@ -235,23 +234,16 @@ class boss_sapphiron : public CreatureScript if ((_phase != PHASE_BIRTH && !UpdateVictim()) || !CheckInRoom()) return; - if (_canTheHundredClub) - { - if (_checkFrostResistTimer <= diff) - { - CheckPlayersFrostResist(); - _checkFrostResistTimer = 5 * IN_MILLISECONDS; - } - else - _checkFrostResistTimer -= diff; - } - if (_phase == PHASE_GROUND) { while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { + case EVENT_CHECK_RESISTS: + DoCast(me, SPELL_CHECK_RESISTS); + events.ScheduleEvent(EVENT_CHECK_RESISTS, 30 * IN_MILLISECONDS); + return; case EVENT_BERSERK: Talk(EMOTE_ENRAGE); DoCast(me, SPELL_BERSERK); @@ -270,7 +262,6 @@ class boss_sapphiron : public CreatureScript return; case EVENT_BLIZZARD: { - //DoCastAOE(SPELL_SUMMON_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); @@ -300,9 +291,14 @@ class boss_sapphiron : public CreatureScript { switch (eventId) { + case EVENT_CHECK_RESISTS: + DoCast(me, SPELL_CHECK_RESISTS); + events.ScheduleEvent(EVENT_CHECK_RESISTS, 30 * IN_MILLISECONDS); + return; case EVENT_LIFTOFF: Talk(EMOTE_AIR_PHASE); me->SetDisableGravity(true); + me->SetHover(true); events.ScheduleEvent(EVENT_ICEBOLT, 1500); _iceboltCount = RAID_MODE(2, 3); return; @@ -346,6 +342,7 @@ class boss_sapphiron : public CreatureScript case EVENT_LAND: me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); Talk(EMOTE_GROUND_PHASE); + me->SetHover(false); me->SetDisableGravity(false); events.ScheduleEvent(EVENT_GROUND, 1500); return; @@ -406,7 +403,6 @@ class boss_sapphiron : public CreatureScript uint32 _iceboltCount; IceBlockMap _iceblocks; bool _canTheHundredClub; - uint32 _checkFrostResistTimer; Map* _map; }; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index d74fd5a03f8..5d3b038d41d 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -19,48 +19,104 @@ #include "ScriptedCreature.h" #include "SpellScript.h" #include "Player.h" +#include "ObjectGuid.h" #include "naxxramas.h" -//Stalagg -enum StalaggYells + +enum Phases +{ + PHASE_NOT_ENGAGED = 1, + PHASE_PETS, + PHASE_TRANSITION, + PHASE_THADDIUS, + PHASE_RESETTING +}; + +enum AIActions { - SAY_STAL_AGGRO = 0, - SAY_STAL_SLAY = 1, - SAY_STAL_DEATH = 2 + ACTION_RESET_ENCOUNTER_TIMER = -1, // sent from instance AI + ACTION_BEGIN_RESET_ENCOUNTER = 0, // sent from thaddius to pets to trigger despawn and encounter reset + ACTION_RESET_ENCOUNTER, // sent from thaddius to pets to trigger respawn and full reset + ACTION_FEUGEN_DIED, // sent from respective pet to thaddius to indicate death + ACTION_STALAGG_DIED, // ^ + ACTION_FEUGEN_RESET, // pet to thaddius + ACTION_STALAGG_RESET, // ^ + ACTION_FEUGEN_AGGRO, // pet to thaddius on combat start + ACTION_STALAGG_AGGRO, // ^ + ACTION_FEUGEN_REVIVING_FX, // thaddius to pet when pet reports its death + ACTION_STALAGG_REVIVING_FX, // ^ + ACTION_FEUGEN_REVIVED, // thaddius to pet when pet should revive + ACTION_STALAGG_REVIVED, // ^ + ACTION_TRANSITION, // thaddius to pets when transition starts (coil overload anim) + ACTION_TRANSITION_2, // thaddius to pets to make the coils shock him + ACTION_TRANSITION_3, // thaddius to pets to disable coil GO after spawn + + ACTION_POLARITY_CROSSED // triggers achievement failure, sent from spellscript }; -enum StalagSpells +enum Events { - SPELL_POWERSURGE = 28134, - SPELL_MAGNETIC_PULL = 28338, - SPELL_STALAGG_TESLA = 28097 + EVENT_SHIFT = 1, // polarity shift + EVENT_SHIFT_TALK, // polarity shift yell (hack? couldn't find any event for cast finish) + EVENT_CHAIN, // chain lightning + EVENT_BERSERK, // enrage timer + EVENT_REVIVE_FEUGEN, // timer until feugen is revived (if stalagg still lives) + EVENT_REVIVE_STALAGG, // timer until stalagg is revived (if feugen still lives) + EVENT_TRANSITION_1, // timer until overload emote + EVENT_TRANSITION_2, // timer until thaddius gets zapped by the coils + EVENT_TRANSITION_3, // timer until thaddius engages + EVENT_ENABLE_BALL_LIGHTNING // grace period after thaddius aggro after which he starts being a baller (e.g. tossing ball lightning at out of range targets) }; -//Feugen -enum FeugenYells +enum Misc { - SAY_FEUG_AGGRO = 0, - SAY_FEUG_SLAY = 1, - SAY_FEUG_DEATH = 2 + MAX_POLARITY_10M = 5, + MAX_POLARITY_25M = 13, + + DATA_POLARITY_CROSSED = 1, +}; + +// Feugen & Stalagg +enum PetYells +{ + SAY_STALAGG_AGGRO = 0, + SAY_STALAGG_SLAY = 1, + SAY_STALAGG_DEATH = 2, + + SAY_FEUGEN_AGGRO = 0, + SAY_FEUGEN_SLAY = 1, + SAY_FEUGEN_DEATH = 2, + + EMOTE_FEIGN_DEATH = 3, + EMOTE_FEIGN_REVIVE = 4, + + EMOTE_TESLA_LINK_BREAKS = 0, + EMOTE_TESLA_OVERLOAD = 1 }; -enum FeugenSpells +enum PetSpells { - SPELL_STATICFIELD = 28135, - SPELL_FEUGEN_TESLA = 28109 + SPELL_STALAGG_POWERSURGE = 28134, + //SPELL_STALAGG_TESLA = 28097, + SPELL_STALAGG_TESLA_PERIODIC = 28098, + SPELL_STALAGG_CHAIN_VISUAL = 28096, + + SPELL_FEUGEN_STATICFIELD = 28135, + //SPELL_FEUGEN_TESLA = 28109, + SPELL_FEUGEN_TESLA_PERIODIC = 28110, + SPELL_FEUGEN_CHAIN_VISUAL = 28111, + + SPELL_MAGNETIC_PULL = 54517, + SPELL_MAGNETIC_PULL_EFFECT = 28337, + + SPELL_TESLA_SHOCK = 28099 }; -// Thaddius DoAction -enum ThaddiusActions +enum PetMisc { - ACTION_FEUGEN_RESET, - ACTION_FEUGEN_DIED, - ACTION_STALAGG_RESET, - ACTION_STALAGG_DIED + OVERLOAD_DISTANCE = 28 }; -//generic -#define C_TESLA_COIL 16218 //the coils (emotes "Tesla Coil overloads!") //Thaddius enum ThaddiusYells @@ -70,34 +126,31 @@ enum ThaddiusYells SAY_SLAY = 2, SAY_ELECT = 3, SAY_DEATH = 4, - SAY_SCREAM = 5 + SAY_SCREAM = 5, + + EMOTE_POLARITY_SHIFTED = 6 }; enum ThaddiusSpells { - SPELL_POLARITY_SHIFT = 28089, - SPELL_BALL_LIGHTNING = 28299, - SPELL_CHAIN_LIGHTNING = 28167, - SPELL_BERSERK = 27680, - SPELL_POSITIVE_CHARGE = 28062, - SPELL_POSITIVE_CHARGE_STACK = 29659, - SPELL_NEGATIVE_CHARGE = 28085, - SPELL_NEGATIVE_CHARGE_STACK = 29660, - SPELL_POSITIVE_POLARITY = 28059, - SPELL_NEGATIVE_POLARITY = 28084, -}; + SPELL_THADDIUS_INACTIVE_VISUAL = 28160, + SPELL_THADDIUS_SPARK_VISUAL = 28136, + SPELL_SHOCK_VISUAL = 28159, -enum Events -{ - EVENT_NONE, - EVENT_SHIFT, - EVENT_CHAIN, - EVENT_BERSERK, -}; + SPELL_BALL_LIGHTNING = 28299, + SPELL_CHAIN_LIGHTNING = 28167, + SPELL_BERSERK = 27680, -enum Achievement -{ - DATA_POLARITY_SWITCH = 76047605, + // polarity handling + SPELL_POLARITY_SHIFT = 28089, + + SPELL_POSITIVE_CHARGE_APPLY = 28059, + SPELL_POSITIVE_CHARGE_TICK = 28062, + SPELL_POSITIVE_CHARGE_AMP = 29659, + + SPELL_NEGATIVE_CHARGE_APPLY = 28084, + SPELL_NEGATIVE_CHARGE_TICK = 28085, + SPELL_NEGATIVE_CHARGE_AMP = 29660, }; class boss_thaddius : public CreatureScript @@ -112,166 +165,276 @@ public: struct boss_thaddiusAI : public BossAI { - boss_thaddiusAI(Creature* creature) : BossAI(creature, BOSS_THADDIUS) - { - // init is a bit tricky because thaddius shall track the life of both adds, but not if there was a wipe - // and, in particular, if there was a crash after both adds were killed (should not respawn) - - // Moreover, the adds may not yet be spawn. So just track down the status if mob is spawn - // and each mob will send its status at reset (meaning that it is alive) - checkFeugenAlive = false; - if (Creature* pFeugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - checkFeugenAlive = pFeugen->IsAlive(); + public: + boss_thaddiusAI(Creature* creature) : BossAI(creature, BOSS_THADDIUS), stalaggAlive(true), feugenAlive(true), ballLightningEnabled(false), shockingEligibility(true) + { + if (instance->GetBossState(BOSS_THADDIUS) != DONE) + { + events.SetPhase(PHASE_NOT_ENGAGED); + SetCombatMovement(false); - checkStalaggAlive = false; - if (Creature* pStalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - checkStalaggAlive = pStalagg->IsAlive(); + // initialize everything properly, and ensure that the coils are loaded by the time we initialize + BeginResetEncounter(true); + } + } - if (!checkFeugenAlive && !checkStalaggAlive) + void KilledUnit(Unit* victim) override { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_AGGRESSIVE); + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } - else + + void Reset() override { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_PASSIVE); + if (events.IsInPhase(PHASE_TRANSITION) || (events.IsInPhase(PHASE_THADDIUS) && me->IsAlive())) + BeginResetEncounter(); } - polaritySwitch = false; - uiAddsTimer = 0; - } - - bool checkStalaggAlive; - bool checkFeugenAlive; - bool polaritySwitch; - uint32 uiAddsTimer; - - void KilledUnit(Unit* /*victim*/) override - { - if (!(rand32() % 5)) - Talk(SAY_SLAY); - } - - void JustDied(Unit* /*killer*/) override - { - _JustDied(); - Talk(SAY_DEATH); - } + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + me->setActive(false); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->setActive(false); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->setActive(false); + Talk(SAY_DEATH); + } - void DoAction(int32 action) override - { - switch (action) + void DoAction(int32 action) override { - case ACTION_FEUGEN_RESET: - checkFeugenAlive = true; - break; - case ACTION_FEUGEN_DIED: - checkFeugenAlive = false; - break; - case ACTION_STALAGG_RESET: - checkStalaggAlive = true; - break; - case ACTION_STALAGG_DIED: - checkStalaggAlive = false; - break; + switch (action) + { + case ACTION_RESET_ENCOUNTER_TIMER: + if (events.IsInPhase(PHASE_RESETTING)) + ResetEncounter(); + break; + case ACTION_FEUGEN_RESET: + case ACTION_STALAGG_RESET: + if (!events.IsInPhase(PHASE_NOT_ENGAGED) && !events.IsInPhase(PHASE_RESETTING)) + BeginResetEncounter(); + break; + case ACTION_FEUGEN_AGGRO: + case ACTION_STALAGG_AGGRO: + if (events.IsInPhase(PHASE_RESETTING)) + return BeginResetEncounter(); + if (!events.IsInPhase(PHASE_NOT_ENGAGED)) + return; + events.SetPhase(PHASE_PETS); + + shockingEligibility = true; + + if (!instance->CheckRequiredBosses(BOSS_THADDIUS)) + return BeginResetEncounter(); + instance->SetBossState(BOSS_THADDIUS, IN_PROGRESS); + + me->setActive(true); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->setActive(true); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->setActive(true); + break; + case ACTION_FEUGEN_DIED: + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_FEUGEN_REVIVING_FX); + feugenAlive = false; + if (stalaggAlive) + events.ScheduleEvent(EVENT_REVIVE_FEUGEN, 5 * IN_MILLISECONDS, 0, PHASE_PETS); + else + Transition(); + + break; + case ACTION_STALAGG_DIED: + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_STALAGG_REVIVING_FX); + stalaggAlive = false; + if (feugenAlive) + events.ScheduleEvent(EVENT_REVIVE_STALAGG, 5 * IN_MILLISECONDS, 0, PHASE_PETS); + else + Transition(); + + break; + + case ACTION_POLARITY_CROSSED: + shockingEligibility = false; + break; + default: + break; + } } - if (!checkFeugenAlive && !checkStalaggAlive) + uint32 GetData(uint32 id) const override { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - // REACT_AGGRESSIVE only reset when he takes damage. - DoZoneInCombat(); + return (id == DATA_POLARITY_CROSSED && shockingEligibility) ? 1u : 0u; } - else + + void Transition() // initiate transition between pet phase and thaddius phase { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); - me->SetReactState(REACT_PASSIVE); + events.SetPhase(PHASE_TRANSITION); + + 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); } - } - void EnterCombat(Unit* /*who*/) override - { - _EnterCombat(); - Talk(SAY_AGGRO); - events.ScheduleEvent(EVENT_SHIFT, 30000); - events.ScheduleEvent(EVENT_CHAIN, urand(10000, 20000)); - events.ScheduleEvent(EVENT_BERSERK, 360000); - } + void BeginResetEncounter(bool initial = false) + { + if (instance->GetBossState(BOSS_THADDIUS) == DONE) + return; + if (events.IsInPhase(PHASE_RESETTING)) + return; - void DamageTaken(Unit* /*pDoneBy*/, uint32 & /*uiDamage*/) override - { - me->SetReactState(REACT_AGGRESSIVE); - } + 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); - void SetData(uint32 id, uint32 data) override - { - if (id == DATA_POLARITY_SWITCH) - polaritySwitch = data ? true : false; - } + // remove polarity shift debuffs on reset + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_POSITIVE_CHARGE_APPLY); + instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_NEGATIVE_CHARGE_APPLY); - uint32 GetData(uint32 id) const override - { - if (id != DATA_POLARITY_SWITCH) - return 0; + me->DespawnOrUnsummon(); - return uint32(polaritySwitch); - } + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + events.SetPhase(PHASE_RESETTING); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_BEGIN_RESET_ENCOUNTER); - void UpdateAI(uint32 diff) override - { - if (checkFeugenAlive && checkStalaggAlive) - uiAddsTimer = 0; + me->setActive(false); + } - if (checkStalaggAlive != checkFeugenAlive) + void ResetEncounter() { - uiAddsTimer += diff; - if (uiAddsTimer > 5000) - { - if (!checkStalaggAlive) - { - if (Creature* pStalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) - pStalagg->Respawn(); - } - else - { - if (Creature* pFeugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - pFeugen->Respawn(); - } - } - } + feugenAlive = true; + stalaggAlive = true; - if (!UpdateVictim()) - return; + me->Respawn(true); + _Reset(); + events.SetPhase(PHASE_NOT_ENGAGED); - events.Update(diff); + me->CastSpell(me, SPELL_THADDIUS_INACTIVE_VISUAL, true); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_RESET_ENCOUNTER); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_RESET_ENCOUNTER); + } - while (uint32 eventId = events.ExecuteEvent()) + void UpdateAI(uint32 diff) override { - switch (eventId) + if (events.IsInPhase(PHASE_NOT_ENGAGED)) + return; + if (events.IsInPhase(PHASE_THADDIUS) && !UpdateVictim()) + return; + + events.Update(diff); + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_SHIFT: - DoCastAOE(SPELL_POLARITY_SHIFT); - events.ScheduleEvent(EVENT_SHIFT, 30000); - return; - case EVENT_CHAIN: - DoCastVictim(SPELL_CHAIN_LIGHTNING); - events.ScheduleEvent(EVENT_CHAIN, urand(10000, 20000)); - return; - case EVENT_BERSERK: - DoCast(me, SPELL_BERSERK); - return; + switch (eventId) + { + case EVENT_REVIVE_FEUGEN: + feugenAlive = true; + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_FEUGEN_REVIVED); + break; + case EVENT_REVIVE_STALAGG: + stalaggAlive = true; + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_STALAGG_REVIVED); + break; + case EVENT_TRANSITION_1: // tesla coils overload + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_TRANSITION); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_TRANSITION); + break; + case EVENT_TRANSITION_2: // tesla coils shock thaddius + me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true); + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_TRANSITION_2); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_TRANSITION_2); + break; + case EVENT_TRANSITION_3: // thaddius becomes active + me->CastSpell(me, SPELL_THADDIUS_SPARK_VISUAL, true); + ballLightningEnabled = 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); + + 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(); + + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + feugen->AI()->DoAction(ACTION_TRANSITION_3); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + stalagg->AI()->DoAction(ACTION_TRANSITION_3); + + events.SetPhase(PHASE_THADDIUS); + + 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); + + break; + case EVENT_ENABLE_BALL_LIGHTNING: + ballLightningEnabled = 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); + break; + case EVENT_SHIFT_TALK: + Talk(SAY_ELECT); + Talk(EMOTE_POLARITY_SHIFTED); + 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); + else + { + me->CastStop(); + DoCastVictim(SPELL_CHAIN_LIGHTNING); + events.ScheduleEvent(EVENT_CHAIN, urand(10, 20) * IN_MILLISECONDS, PHASE_THADDIUS); + } + break; + case EVENT_BERSERK: + me->CastStop(); + DoCast(me, SPELL_BERSERK); + break; + default: + break; + } + } + + if (events.IsInPhase(PHASE_THADDIUS)) + { + if (me->IsWithinMeleeRange(me->GetVictim())) + DoMeleeAttackIfReady(); + else + if (ballLightningEnabled) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_BALL_LIGHTNING); } } - if (events.GetTimer() > 15000 && !me->IsWithinMeleeRange(me->GetVictim())) - DoCastVictim(SPELL_BALL_LIGHTNING); - else - DoMeleeAttackIfReady(); - } + private: + bool stalaggAlive; + bool feugenAlive; + bool ballLightningEnabled; + bool shockingEligibility; }; }; @@ -288,88 +451,257 @@ public: struct npc_stalaggAI : public ScriptedAI { - npc_stalaggAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + public: + npc_stalaggAI(Creature* creature) : ScriptedAI(creature), _myCoil(ObjectGuid::Empty), _myCoilGO(ObjectGuid::Empty), isOverloading(false), refreshBeam(false), isFeignDeath(false) + { + Initialize(); + instance = creature->GetInstanceScript(); + } - void Initialize() - { - powerSurgeTimer = urand(20000, 25000); - magneticPullTimer = 20000; - } + void Initialize() + { + if (GameObject* coil = myCoilGO()) + coil->SetGoState(GO_STATE_ACTIVE); - InstanceScript* instance; + // if the encounter reset while feigning death + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + isOverloading = false; + isFeignDeath = false; - uint32 powerSurgeTimer; - uint32 magneticPullTimer; + // force tesla coil state refresh + refreshBeam = true; - void Reset() override - { - if (Creature* pThaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_STALAGG_RESET); - Initialize(); - } + powerSurgeTimer = 10 * IN_MILLISECONDS; + } - void KilledUnit(Unit* /*victim*/) override - { - if (!(rand32() % 5)) - Talk(SAY_STAL_SLAY); - } + void Reset() override + { + if (isFeignDeath || !me->IsAlive()) + return; + if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) + thaddius->AI()->DoAction(ACTION_STALAGG_RESET); + } - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_STAL_AGGRO); - DoCast(SPELL_STALAGG_TESLA); - } + void BeginResetEncounter() + { + if (GameObject* coil = myCoilGO()) + coil->SetGoState(GO_STATE_READY); + me->DespawnOrUnsummon(); + me->setActive(false); + } - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_STAL_DEATH); - if (Creature* pThaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_STALAGG_DIED); - } + void ResetEncounter() + { + me->Respawn(true); + Initialize(); + } - void UpdateAI(uint32 uiDiff) override - { - if (!UpdateVictim()) - return; + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_BEGIN_RESET_ENCOUNTER: + BeginResetEncounter(); + break; + case ACTION_RESET_ENCOUNTER: + ResetEncounter(); + break; + case ACTION_STALAGG_REVIVING_FX: + break; + case ACTION_STALAGG_REVIVED: + if (!isFeignDeath) + break; + + me->SetFullHealth(); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetReactState(REACT_AGGRESSIVE); + 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))) + if (feugen->GetVictim()) + { + me->AddThreat(feugen->EnsureVictim(), 0.0f); + me->SetInCombatWith(feugen->EnsureVictim()); + } + break; + case ACTION_TRANSITION: + me->KillSelf(); // true death + me->DespawnOrUnsummon(); + + if (Creature* coil = myCoil()) + { + coil->CastStop(); + coil->AI()->Talk(EMOTE_TESLA_OVERLOAD); + } + break; + case ACTION_TRANSITION_2: + if (Creature* coil = myCoil()) + if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) + coil->CastSpell(thaddius, SPELL_SHOCK_VISUAL); + break; + case ACTION_TRANSITION_3: + if (GameObject* coil = myCoilGO()) + coil->SetGoState(GO_STATE_READY); + break; + default: + break; + } + } - if (magneticPullTimer <= uiDiff) + void KilledUnit(Unit* victim) override { - if (Creature* pFeugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_STALAGG_SLAY); + } + + void EnterCombat(Unit* who) override + { + Talk(SAY_STALAGG_AGGRO); + + if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) + thaddius->AI()->DoAction(ACTION_STALAGG_AGGRO); + + if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) + if (!feugen->IsInCombat()) + { + feugen->AddThreat(who, 0.0f); + feugen->SetInCombatWith(who); + } + } + + void DamageTaken(Unit* /*who*/, uint32& damage) override + { + if (damage < me->GetHealth()) + return; + + if (isFeignDeath) // don't take damage while feigning death { - Unit* pStalaggVictim = me->GetVictim(); - Unit* pFeugenVictim = pFeugen->GetVictim(); + damage = 0; + return; + } + + isFeignDeath = true; + isOverloading = false; + + Talk(EMOTE_FEIGN_DEATH); + if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) + thaddius->AI()->DoAction(ACTION_STALAGG_DIED); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAllAuras(); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->StopMoving(); + me->SetStandState(UNIT_STAND_STATE_DEAD); - if (pFeugenVictim && pStalaggVictim) + damage = 0; + + // force beam refresh as we just removed auras + refreshBeam = true; + } + + void SpellHit(Unit* caster, SpellInfo const* spell) override + { + if (!caster) + return; + if (spell->Id != SPELL_STALAGG_TESLA_PERIODIC) + return; + if (!isFeignDeath && me->IsInCombat() && !me->GetHomePosition().IsInDist(me, OVERLOAD_DISTANCE)) + { + if (!isOverloading) { - // magnetic pull is not working. So just jump. + isOverloading = true; + caster->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + if (Creature* creatureCaster = caster->ToCreature()) + creatureCaster->AI()->Talk(EMOTE_TESLA_LINK_BREAKS); + me->RemoveAura(SPELL_STALAGG_CHAIN_VISUAL); + } + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + { + caster->CastStop(SPELL_TESLA_SHOCK); + caster->CastSpell(target, SPELL_TESLA_SHOCK,true); + } + } + else if (isOverloading || refreshBeam) + { + isOverloading = false; + refreshBeam = false; + caster->CastStop(); + caster->CastSpell(me, SPELL_STALAGG_CHAIN_VISUAL, true); + caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + } + } - // reset aggro to be sure that feugen will not follow the jump - pFeugen->getThreatManager().modifyThreatPercent(pFeugenVictim, -100); - pFeugenVictim->JumpTo(me, 0.3f); + void UpdateAI(uint32 uiDiff) override + { + if (!isFeignDeath) + if (!UpdateVictim()) + return; - me->getThreatManager().modifyThreatPercent(pStalaggVictim, -100); - pStalaggVictim->JumpTo(pFeugen, 0.3f); + if (powerSurgeTimer <= uiDiff) + { + if (isFeignDeath) // delay until potential revive + powerSurgeTimer = 0u; + else + { + DoCast(me, SPELL_STALAGG_POWERSURGE); + powerSurgeTimer = urand(25, 30) * IN_MILLISECONDS; } } + else + powerSurgeTimer -= uiDiff; - magneticPullTimer = 20000; + if (!isFeignDeath) + DoMeleeAttackIfReady(); } - else magneticPullTimer -= uiDiff; - if (powerSurgeTimer <= uiDiff) + private: + Creature* myCoil() { - DoCast(me, SPELL_POWERSURGE); - powerSurgeTimer = urand(15000, 20000); - } else powerSurgeTimer -= uiDiff; + Creature* coil = nullptr; + if (_myCoil) + coil = ObjectAccessor::GetCreature(*me, _myCoil); + if (!coil) + { + coil = me->FindNearestCreature(NPC_TESLA, 1000.0f, true); + if (coil) + { + _myCoil = coil->GetGUID(); + coil->SetReactState(REACT_PASSIVE); + } + } + return coil; + } - DoMeleeAttackIfReady(); - } + GameObject* myCoilGO() + { + GameObject* coil = nullptr; + if (_myCoilGO) + coil = ObjectAccessor::GetGameObject(*me, _myCoilGO); + if (!coil) + { + coil = me->FindNearestGameObject(GO_CONS_NOX_TESLA_STALAGG, 1000.0f); + if (coil) + _myCoilGO = coil->GetGUID(); + } + return coil; + } + + InstanceScript* instance; + + uint32 powerSurgeTimer; + + ObjectGuid _myCoil; + ObjectGuid _myCoilGO; + bool isOverloading; + bool refreshBeam; + bool isFeignDeath; }; }; @@ -386,142 +718,381 @@ public: struct npc_feugenAI : public ScriptedAI { - npc_feugenAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - staticFieldTimer = 5000; - } + public: + npc_feugenAI(Creature* creature) : ScriptedAI(creature), _myCoil(ObjectGuid::Empty), _myCoilGO(ObjectGuid::Empty), isOverloading(false), refreshBeam(false), isFeignDeath(false) + { + Initialize(); + instance = creature->GetInstanceScript(); + } - InstanceScript* instance; + void Initialize() + { + if (GameObject* coil = myCoilGO()) + coil->SetGoState(GO_STATE_ACTIVE); - uint32 staticFieldTimer; + // if the encounter reset while feigning death + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + isOverloading = false; + isFeignDeath = false; - void Reset() override - { - if (Creature* pThaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_FEUGEN_RESET); - Initialize(); - } + // force coil state to refresh + refreshBeam = true; - void KilledUnit(Unit* /*victim*/) override - { - if (!(rand32() % 5)) - Talk(SAY_FEUG_SLAY); - } + staticFieldTimer = 6 * IN_MILLISECONDS; + magneticPullTimer = 20 * IN_MILLISECONDS; + } - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_FEUG_AGGRO); - DoCast(SPELL_FEUGEN_TESLA); - } + void Reset() override + { + if (isFeignDeath || !me->IsAlive()) + return; + if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) + thaddius->AI()->DoAction(ACTION_FEUGEN_RESET); + } - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_FEUG_DEATH); - if (Creature* pThaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) - if (pThaddius->AI()) - pThaddius->AI()->DoAction(ACTION_FEUGEN_DIED); - } + void BeginResetEncounter() + { + if (GameObject* coil = myCoilGO()) + coil->SetGoState(GO_STATE_READY); + me->DespawnOrUnsummon(); + me->setActive(false); + } - void UpdateAI(uint32 uiDiff) override - { - if (!UpdateVictim()) - return; + void ResetEncounter() + { + me->Respawn(true); + Initialize(); + } - if (staticFieldTimer <= uiDiff) + void DoAction(int32 action) override { - DoCast(me, SPELL_STATICFIELD); - staticFieldTimer = 5000; - } else staticFieldTimer -= uiDiff; + switch (action) + { + case ACTION_BEGIN_RESET_ENCOUNTER: + BeginResetEncounter(); + break; + case ACTION_RESET_ENCOUNTER: + ResetEncounter(); + break; + case ACTION_FEUGEN_REVIVING_FX: + break; + case ACTION_FEUGEN_REVIVED: + if (!isFeignDeath) + break; + + me->SetFullHealth(); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetReactState(REACT_AGGRESSIVE); + 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))) + if (stalagg->GetVictim()) + { + me->AddThreat(stalagg->EnsureVictim(), 0.0f); + me->SetInCombatWith(stalagg->EnsureVictim()); + } + staticFieldTimer = 6 * IN_MILLISECONDS; + magneticPullTimer = 30 * IN_MILLISECONDS; + break; + case ACTION_TRANSITION: + me->KillSelf(); // true death this time around + me->DespawnOrUnsummon(); + + if (Creature* coil = myCoil()) + { + coil->CastStop(); + coil->AI()->Talk(EMOTE_TESLA_OVERLOAD); + } + break; + case ACTION_TRANSITION_2: + if (Creature* coil = myCoil()) + if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) + coil->CastSpell(thaddius, SPELL_SHOCK_VISUAL); + break; + case ACTION_TRANSITION_3: + if (GameObject* coil = myCoilGO()) + coil->SetGoState(GO_STATE_READY); + default: + break; + } + } - DoMeleeAttackIfReady(); - } - }; + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_FEUGEN_SLAY); + } -}; + void EnterCombat(Unit* who) override + { + Talk(SAY_FEUGEN_AGGRO); -class spell_thaddius_pos_neg_charge : public SpellScriptLoader -{ - public: - spell_thaddius_pos_neg_charge() : SpellScriptLoader("spell_thaddius_pos_neg_charge") { } + if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) + thaddius->AI()->DoAction(ACTION_STALAGG_AGGRO); - class spell_thaddius_pos_neg_charge_SpellScript : public SpellScript - { - PrepareSpellScript(spell_thaddius_pos_neg_charge_SpellScript); + if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) + if (!stalagg->IsInCombat()) + { + stalagg->AddThreat(who, 0.0f); + stalagg->SetInCombatWith(who); + } + } - bool Validate(SpellInfo const* /*spell*/) override + void DamageTaken(Unit* /*who*/, uint32& damage) override { - if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE)) - return false; - if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_STACK)) - return false; - if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE)) - return false; - if (!sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_STACK)) - return false; - return true; + if (damage < me->GetHealth()) + return; + + if (isFeignDeath) // don't take damage while feigning death + { + damage = 0; + return; + } + + isFeignDeath = true; + isOverloading = false; + + Talk(EMOTE_FEIGN_DEATH); + if (Creature* thaddius = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THADDIUS))) + thaddius->AI()->DoAction(ACTION_FEUGEN_DIED); + + me->RemoveAllAuras(); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->StopMoving(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + damage = 0; + + // force beam refresh as we just removed auras + refreshBeam = true; } - bool Load() override + void SpellHit(Unit* caster, SpellInfo const* spell) override { - return GetCaster()->GetTypeId() == TYPEID_UNIT; + if (!caster) + return; + if (spell->Id != SPELL_FEUGEN_TESLA_PERIODIC) + return; + if (!isFeignDeath && me->IsInCombat() && !me->GetHomePosition().IsInDist(me, OVERLOAD_DISTANCE)) + { + if (!isOverloading) + { + isOverloading = true; + caster->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + if (Creature* creatureCaster = caster->ToCreature()) + creatureCaster->AI()->Talk(EMOTE_TESLA_LINK_BREAKS); + me->RemoveAura(SPELL_STALAGG_CHAIN_VISUAL); + } + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + { + caster->CastStop(SPELL_TESLA_SHOCK); + caster->CastSpell(target, SPELL_TESLA_SHOCK,true); + } + } + else if (isOverloading || refreshBeam) + { + isOverloading = false; + refreshBeam = false; + caster->CastStop(); + caster->CastSpell(me, SPELL_FEUGEN_CHAIN_VISUAL, true); + caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + } } - void HandleTargets(std::list<WorldObject*>& targets) + void UpdateAI(uint32 uiDiff) override { - uint8 count = 0; - for (std::list<WorldObject*>::iterator ihit = targets.begin(); ihit != targets.end(); ++ihit) - if ((*ihit)->GetGUID() != GetCaster()->GetGUID()) - if (Player* target = (*ihit)->ToPlayer()) - if (target->HasAura(GetTriggeringSpell()->Id)) - ++count; + if (isFeignDeath) + return; + if (!UpdateVictim()) + return; - if (count) + if (magneticPullTimer <= uiDiff) + { + DoCast(me, SPELL_MAGNETIC_PULL); + magneticPullTimer = 20 * IN_MILLISECONDS; + } + else magneticPullTimer -= uiDiff; + + if (staticFieldTimer <= uiDiff) { - uint32 spellId = 0; + DoCast(me, SPELL_FEUGEN_STATICFIELD); + staticFieldTimer = 6 * IN_MILLISECONDS; + } + else staticFieldTimer -= uiDiff; - if (GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE) - spellId = SPELL_POSITIVE_CHARGE_STACK; - else // if (GetSpellInfo()->Id == SPELL_NEGATIVE_CHARGE) - spellId = SPELL_NEGATIVE_CHARGE_STACK; + DoMeleeAttackIfReady(); + } - GetCaster()->SetAuraStack(spellId, GetCaster(), count); + private: + Creature* myCoil() + { + Creature* coil = nullptr; + if (_myCoil) + coil = ObjectAccessor::GetCreature(*me, _myCoil); + if (!coil) + { + coil = me->FindNearestCreature(NPC_TESLA, 1000.0f, true); + if (coil) + { + _myCoil = coil->GetGUID(); + coil->SetReactState(REACT_PASSIVE); + } } + return coil; + } + + GameObject* myCoilGO() + { + GameObject* coil = nullptr; + if (_myCoilGO) + coil = ObjectAccessor::GetGameObject(*me, _myCoilGO); + if (!coil) + { + coil = me->FindNearestGameObject(GO_CONS_NOX_TESLA_FEUGEN, 1000.0f); + if (coil) + _myCoilGO = coil->GetGUID(); + } + return coil; + } + InstanceScript* instance; + + uint32 magneticPullTimer; + uint32 staticFieldTimer; + + ObjectGuid _myCoil; + ObjectGuid _myCoilGO; + + bool isOverloading; + bool refreshBeam; + bool isFeignDeath; + }; +}; + +class npc_tesla : public CreatureScript +{ +public: + npc_tesla() : CreatureScript("npc_tesla") { } + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_teslaAI>(creature); + } + + struct npc_teslaAI : public ScriptedAI + { + npc_teslaAI(Creature* creature) : ScriptedAI(creature) { } + + void EnterEvadeMode() override { } // never stop casting due to evade + void UpdateAI(uint32 /*diff*/) override { } // never do anything unless told + void EnterCombat(Unit* /*who*/) override { } + void DamageTaken(Unit* /*who*/, uint32& damage) override { damage = 0; } // no, you can't kill it + }; +}; + +class spell_thaddius_polarity_charge : public SpellScriptLoader +{ + public: + spell_thaddius_polarity_charge() : SpellScriptLoader("spell_thaddius_polarity_charge") { } + + class spell_thaddius_polarity_charge_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thaddius_polarity_charge_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + return ( + sSpellMgr->GetSpellInfo(SPELL_POLARITY_SHIFT) && + sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_APPLY) && + sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_TICK) && + sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_AMP) && + sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_APPLY) && + sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_TICK) && + sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_AMP) + ); } - void HandleDamage(SpellEffIndex /*effIndex*/) + void HandleTargets(std::list<WorldObject*>& targetList) { if (!GetTriggeringSpell()) return; - Unit* target = GetHitUnit(); - Unit* caster = GetCaster(); + uint32 triggeringId = GetTriggeringSpell()->Id; + uint32 ampId; + switch (triggeringId) + { + case SPELL_POSITIVE_CHARGE_APPLY: + ampId = SPELL_POSITIVE_CHARGE_AMP; + break; + case SPELL_NEGATIVE_CHARGE_APPLY: + ampId = SPELL_NEGATIVE_CHARGE_AMP; + break; + default: + return; + } - if (target->HasAura(GetTriggeringSpell()->Id)) - SetHitDamage(0); - else + uint8 maxStacks = 0; + if (GetCaster()) + switch (GetCaster()->GetMap()->GetDifficulty()) + { + case RAID_DIFFICULTY_10MAN_NORMAL: + maxStacks = MAX_POLARITY_10M; + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + maxStacks = MAX_POLARITY_25M; + break; + default: + break; + } + + uint8 stacksCount = 1; // do we get a stack for our own debuff? + std::list<WorldObject*>::iterator it = targetList.begin(); + while(it != targetList.end()) + { + if ((*it)->GetTypeId() != TYPEID_PLAYER) + { + it = targetList.erase(it); + continue; + } + if ((*it)->ToPlayer()->HasAura(triggeringId)) + { + it = targetList.erase(it); + if (stacksCount < maxStacks) + stacksCount++; + continue; + } + + // this guy will get hit - achievement failure trigger + if (Creature* thaddius = (*it)->FindNearestCreature(NPC_THADDIUS,200.0f)) + thaddius->AI()->DoAction(ACTION_POLARITY_CROSSED); + + ++it; + } + + if (GetCaster() && GetCaster()->ToPlayer()) { - if (target->GetTypeId() == TYPEID_PLAYER && caster->IsAIEnabled) - caster->ToCreature()->AI()->SetData(DATA_POLARITY_SWITCH, 1); + if (!GetCaster()->ToPlayer()->HasAura(ampId)) + GetCaster()->ToPlayer()->AddAura(ampId, GetCaster()); + GetCaster()->ToPlayer()->SetAuraStack(ampId, GetCaster(), stacksCount); } } void Register() override { - OnEffectHitTarget += SpellEffectFn(spell_thaddius_pos_neg_charge_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thaddius_pos_neg_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thaddius_polarity_charge_SpellScript::HandleTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ALLY); } }; SpellScript* GetSpellScript() const override { - return new spell_thaddius_pos_neg_charge_SpellScript(); + return new spell_thaddius_polarity_charge_SpellScript; } }; @@ -536,16 +1107,33 @@ class spell_thaddius_polarity_shift : public SpellScriptLoader bool Validate(SpellInfo const* /*spell*/) override { - if (!sSpellMgr->GetSpellInfo(SPELL_POSITIVE_POLARITY) || !sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_POLARITY)) - return false; - return true; + return ( + sSpellMgr->GetSpellInfo(SPELL_POLARITY_SHIFT) && + sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_APPLY) && + sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_TICK) && + sSpellMgr->GetSpellInfo(SPELL_POSITIVE_CHARGE_AMP) && + sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_APPLY) && + sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_TICK) && + sSpellMgr->GetSpellInfo(SPELL_NEGATIVE_CHARGE_AMP) + ); } - void HandleDummy(SpellEffIndex /* effIndex */) + void HandleDummy(SpellEffIndex /*effIndex*/) { - Unit* caster = GetCaster(); if (Unit* target = GetHitUnit()) - target->CastSpell(target, roll_chance_i(50) ? SPELL_POSITIVE_POLARITY : SPELL_NEGATIVE_POLARITY, true, NULL, NULL, caster->GetGUID()); + if (target->GetTypeId() == TYPEID_PLAYER) + { + if (roll_chance_i(50)) + { // positive + target->CastSpell(target, SPELL_POSITIVE_CHARGE_APPLY, true); + target->RemoveAura(SPELL_POSITIVE_CHARGE_AMP); + } + else + { // negative + target->CastSpell(target, SPELL_NEGATIVE_CHARGE_APPLY, true); + target->RemoveAura(SPELL_NEGATIVE_CHARGE_AMP); + } + } } void Register() override @@ -560,23 +1148,131 @@ class spell_thaddius_polarity_shift : public SpellScriptLoader } }; -class achievement_polarity_switch : public AchievementCriteriaScript +class spell_thaddius_magnetic_pull : public SpellScriptLoader { public: - achievement_polarity_switch() : AchievementCriteriaScript("achievement_polarity_switch") { } + spell_thaddius_magnetic_pull() : SpellScriptLoader("spell_thaddius_magnetic_pull") { }; + + class spell_thaddius_magnetic_pull_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thaddius_magnetic_pull_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + return sSpellMgr->GetSpellInfo(SPELL_MAGNETIC_PULL) ? true : false; + } + + void HandleCast() // only feugen ever casts this according to wowhead data + { + Unit* feugen = GetCaster(); + if (!feugen || feugen->GetEntry() != NPC_FEUGEN) + return; + + Unit* stalagg = ObjectAccessor::GetCreature(*feugen, feugen->GetInstanceScript()->GetGuidData(DATA_STALAGG)); + if (!stalagg) + return; + + Unit* feugenTank = feugen->GetVictim(); + Unit* stalaggTank = stalagg->GetVictim(); + + if (!feugenTank || !stalaggTank) + return; + + ThreatManager& feugenThreat = feugen->getThreatManager(); + ThreatManager& stalaggThreat = stalagg->getThreatManager(); + + if (feugenTank == stalaggTank) // special behavior if the tanks are the same (taken from retail) + { + float feugenTankThreat = feugenThreat.getThreat(feugenTank); + float stalaggTankThreat = stalaggThreat.getThreat(stalaggTank); + + feugenThreat.addThreat(feugenTank, stalaggTankThreat - feugenTankThreat); + stalaggThreat.addThreat(stalaggTank, feugenTankThreat - stalaggTankThreat); + + feugen->CastSpell(stalaggTank, SPELL_MAGNETIC_PULL_EFFECT, true); + } + else // normal case, two tanks + { + float feugenTankThreat = feugenThreat.getThreat(feugenTank); + float feugenOtherThreat = feugenThreat.getThreat(stalaggTank); + float stalaggTankThreat = stalaggThreat.getThreat(stalaggTank); + float stalaggOtherThreat = stalaggThreat.getThreat(feugenTank); + + // set the two entries in feugen's threat table to be equal to the ones in stalagg's + feugenThreat.addThreat(stalaggTank, stalaggTankThreat - feugenOtherThreat); + feugenThreat.addThreat(feugenTank, stalaggOtherThreat - feugenTankThreat); + + // set the two entries in stalagg's threat table to be equal to the ones in feugen's + stalaggThreat.addThreat(feugenTank, feugenTankThreat - stalaggOtherThreat); + stalaggThreat.addThreat(stalaggTank, feugenOtherThreat - stalaggTankThreat); + + // pull the two tanks across + feugenTank->CastSpell(stalaggTank, SPELL_MAGNETIC_PULL_EFFECT, true); + stalaggTank->CastSpell(feugenTank, SPELL_MAGNETIC_PULL_EFFECT, true); + + // and make both attack their respective new tanks + if (feugen->GetAI()) + feugen->GetAI()->AttackStart(stalaggTank); + if (stalagg->GetAI()) + stalagg->GetAI()->AttackStart(feugenTank); + } + } + + void Register() override + { + OnCast += SpellCastFn(spell_thaddius_magnetic_pull_SpellScript::HandleCast); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thaddius_magnetic_pull_SpellScript(); + } +}; + +class at_thaddius_entrance : public AreaTriggerScript +{ + public: + at_thaddius_entrance() : AreaTriggerScript("at_thaddius_entrance") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override + { + InstanceScript* instance = player->GetInstanceScript(); + if (!instance || instance->GetData(DATA_HAD_THADDIUS_GREET) || instance->GetBossState(BOSS_THADDIUS) == DONE) + return true; + + if (Creature* thaddius = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_THADDIUS))) + thaddius->AI()->Talk(SAY_GREET); + instance->SetData(DATA_HAD_THADDIUS_GREET, 1u); + + return true; + } +}; + +class achievement_thaddius_shocking : public AchievementCriteriaScript +{ + public: + achievement_thaddius_shocking() : AchievementCriteriaScript("achievement_thaddius_shocking") { } bool OnCheck(Player* /*source*/, Unit* target) override { - return target && target->GetAI()->GetData(DATA_POLARITY_SWITCH); + return target && target->GetAI() && target->GetAI()->GetData(DATA_POLARITY_CROSSED); } }; + void AddSC_boss_thaddius() { new boss_thaddius(); new npc_stalagg(); new npc_feugen(); - new spell_thaddius_pos_neg_charge(); + new npc_tesla(); + + new spell_thaddius_polarity_charge(); new spell_thaddius_polarity_shift(); - new achievement_polarity_switch(); + new spell_thaddius_magnetic_pull(); + + new at_thaddius_entrance(); + + new achievement_thaddius_shocking(); } diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 3a431ab3ac0..53ce68d3efc 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -60,7 +60,6 @@ DoorData const doorData[] = MinionData const minionData[] = { - { NPC_FOLLOWER_WORSHIPPER, BOSS_FAERLINA }, { NPC_DK_UNDERSTUDY, BOSS_RAZUVIOUS }, { NPC_SIR, BOSS_HORSEMEN }, { NPC_THANE, BOSS_HORSEMEN }, @@ -78,12 +77,13 @@ ObjectData const objectData[] = { 0, 0, } }; -float const HeiganPos[2] = { 2796.0f, -3707.0f }; +// from P2 teleport spell stored target +float const HeiganPos[2] = { 2793.86f, -3707.38f }; float const HeiganEruptionSlope[3] = { - (-3685.0f - HeiganPos[1]) / (2724.0f - HeiganPos[0]), - (-3647.0f - HeiganPos[1]) / (2749.0f - HeiganPos[0]), - (-3637.0f - HeiganPos[1]) / (2771.0f - HeiganPos[0]) + (-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 @@ -125,6 +125,9 @@ class instance_naxxramas : public InstanceMapScript minHorsemenDiedTime = 0; maxHorsemenDiedTime = 0; AbominationCount = 0; + hadAnubRekhanGreet = false; + hadFaerlinaGreet = false; + hadThaddiusGreet = false; CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT; playerDied = 0; @@ -134,6 +137,9 @@ class instance_naxxramas : public InstanceMapScript { switch (creature->GetEntry()) { + case NPC_ANUBREKHAN: + AnubRekhanGUID = creature->GetGUID(); + break; case NPC_FAERLINA: FaerlinaGUID = creature->GetGUID(); break; @@ -149,12 +155,12 @@ class instance_naxxramas : public InstanceMapScript case NPC_SIR: SirGUID = creature->GetGUID(); break; - case NPC_THADDIUS: - ThaddiusGUID = creature->GetGUID(); - break; case NPC_HEIGAN: HeiganGUID = creature->GetGUID(); break; + case NPC_THADDIUS: + ThaddiusGUID = creature->GetGUID(); + break; case NPC_FEUGEN: FeugenGUID = creature->GetGUID(); break; @@ -182,6 +188,19 @@ class instance_naxxramas : public InstanceMapScript AddMinion(creature, false); } + 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) @@ -246,7 +265,6 @@ class instance_naxxramas : public InstanceMapScript if (go->GetGOInfo()->displayId == 6785 || go->GetGOInfo()->displayId == 1287) { uint32 section = GetEruptionSection(go->GetPositionX(), go->GetPositionY()); - HeiganEruptionGUID[section].erase(go->GetGUID()); return; } @@ -319,6 +337,17 @@ class instance_naxxramas : public InstanceMapScript case DATA_ABOMINATION_KILLED: AbominationCount = value; break; + case DATA_HAD_ANUBREKHAN_GREET: + hadAnubRekhanGreet = (value == 1u); + break; + case DATA_HAD_FAERLINA_GREET: + hadFaerlinaGreet = (value == 1u); + break; + case DATA_HAD_THADDIUS_GREET: + hadThaddiusGreet = (value == 1u); + break; + default: + break; } } @@ -328,6 +357,12 @@ class instance_naxxramas : public InstanceMapScript { case DATA_ABOMINATION_KILLED: return AbominationCount; + case DATA_HAD_ANUBREKHAN_GREET: + return hadAnubRekhanGreet ? 1u : 0u; + case DATA_HAD_FAERLINA_GREET: + return hadFaerlinaGreet ? 1u : 0u; + case DATA_HAD_THADDIUS_GREET: + return hadThaddiusGreet ? 1u : 0u; default: break; } @@ -339,6 +374,8 @@ class instance_naxxramas : public InstanceMapScript { switch (id) { + case DATA_ANUBREKHAN: + return AnubRekhanGUID; case DATA_FAERLINA: return FaerlinaGUID; case DATA_THANE: @@ -349,14 +386,14 @@ class instance_naxxramas : public InstanceMapScript return BaronGUID; case DATA_SIR: return SirGUID; - case DATA_THADDIUS: - return ThaddiusGUID; case DATA_HEIGAN: return HeiganGUID; case DATA_FEUGEN: return FeugenGUID; case DATA_STALAGG: return StalaggGUID; + case DATA_THADDIUS: + return ThaddiusGUID; case DATA_KELTHUZAD: return KelthuzadGUID; case DATA_KELTHUZAD_PORTAL01: @@ -525,6 +562,11 @@ class instance_naxxramas : public InstanceMapScript 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; } @@ -552,7 +594,7 @@ class instance_naxxramas : public InstanceMapScript // 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. - bool AreAllEncoutersDone() + bool AreAllEncountersDone() { uint32 numBossAlive = 0; for (uint32 i = 0; i < EncounterCount; ++i) @@ -589,7 +631,7 @@ class instance_naxxramas : public InstanceMapScript case 13239: // Loatheb case 13240: // Thaddius case 7617: // Kel'Thuzad - if (AreAllEncoutersDone() && !playerDied) + if (AreAllEncountersDone() && !playerDied) return true; return false; } @@ -599,6 +641,8 @@ class instance_naxxramas : public InstanceMapScript protected: /* The Arachnid Quarter */ + // Anub'rekhan + ObjectGuid AnubRekhanGUID; // Grand Widow Faerlina ObjectGuid FaerlinaGUID; @@ -635,6 +679,9 @@ class instance_naxxramas : public InstanceMapScript ObjectGuid KelthuzadDoorGUID; ObjectGuid LichKingGUID; uint8 AbominationCount; + bool hadAnubRekhanGreet; + bool hadFaerlinaGreet; + bool hadThaddiusGreet; uint8 CurrentWingTaunt; /* The Immortal / The Undying */ diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index 459903c4c86..d2b99784953 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -46,6 +46,9 @@ enum Data DATA_HEIGAN_ERUPT, DATA_GOTHIK_GATE, DATA_SAPPHIRON_BIRTH, + DATA_HAD_ANUBREKHAN_GREET, + DATA_HAD_FAERLINA_GREET, + DATA_HAD_THADDIUS_GREET, DATA_HORSEMEN0, DATA_HORSEMEN1, @@ -61,6 +64,7 @@ enum Data enum Data64 { + DATA_ANUBREKHAN, DATA_FAERLINA, DATA_THANE, DATA_LADY, @@ -81,15 +85,17 @@ enum Data64 enum CreaturesIds { + NPC_ANUBREKHAN = 15956, NPC_FAERLINA = 15953, NPC_THANE = 16064, NPC_LADY = 16065, NPC_BARON = 30549, NPC_SIR = 16063, - NPC_THADDIUS = 15928, NPC_HEIGAN = 15936, + NPC_THADDIUS = 15928, NPC_FEUGEN = 15930, NPC_STALAGG = 15929, + NPC_TESLA = 16218, NPC_SAPPHIRON = 15989, NPC_KEL_THUZAD = 15990, NPC_CRYPT_GUARD = 16573, @@ -169,6 +175,10 @@ 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, diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 9c339e596a4..33ffea4993b 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -1244,8 +1244,9 @@ public: ++_wpCount; } else if (Vehicle* hoverDisk = me->GetVehicleKit()) - if (Unit* lordPassenger = hoverDisk->GetPassenger(0)) - lordPassenger->ToCreature()->AI()->DoAction(ACTION_SET_DISK_VICTIM_CHASE); + if (Unit* passenger = hoverDisk->GetPassenger(0)) + if (Creature* lordPassenger = passenger->ToCreature()) + lordPassenger->AI()->DoAction(ACTION_SET_DISK_VICTIM_CHASE); } private: @@ -1485,7 +1486,7 @@ public: creature->AI()->SetGUID(me->GetGUID(), DATA_LAST_OVERLOAD_GUID); } - void UpdateAI(uint32 /*diff*/) + void UpdateAI(uint32 /*diff*/) override { } @@ -1530,15 +1531,14 @@ public: { npc_wyrmrest_skytalonAI(Creature* creature) : VehicleAI(creature) { - _summoner = NULL; } void IsSummonedBy(Unit* summoner) override { - _summoner = NULL; + _summoner.Clear(); if (Player* player = summoner->ToPlayer()) { - _summoner = player; + _summoner = player->GetGUID(); _events.ScheduleEvent(EVENT_CAST_RIDE_SPELL, 2*IN_MILLISECONDS); } } @@ -1553,7 +1553,8 @@ public: switch (eventId) { case EVENT_CAST_RIDE_SPELL: - me->CastSpell(_summoner, SPELL_RIDE_RED_DRAGON_TRIGGERED, true); + if (Player* player = ObjectAccessor::GetPlayer(*me, _summoner)) + me->CastSpell(player, SPELL_RIDE_RED_DRAGON_TRIGGERED, true); break; } } @@ -1575,7 +1576,7 @@ public: } private: - Player* _summoner; + ObjectGuid _summoner; EventMap _events; }; 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 7b884f39a41..d1f2be5525d 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 @@ -77,10 +77,10 @@ public: /// @todo this should be handled in map, maybe add a summon function in map // There is no other way afaik... - void SpawnGameObject(uint32 entry, Position& pos) + void SpawnGameObject(uint32 entry, Position const& pos) { - GameObject* go = new GameObject; - if (!go->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, instance, + 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)) { @@ -99,30 +99,19 @@ public: platformGUID = go->GetGUID(); break; case GO_FOCUSING_IRIS_10: - if (instance->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - { - irisGUID = go->GetGUID(); - focusingIrisPosition = go->GetPosition(); - } - break; case GO_FOCUSING_IRIS_25: - if (instance->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - { - irisGUID = go->GetGUID(); - focusingIrisPosition = go->GetPosition(); - } + irisGUID = go->GetGUID(); + focusingIrisPosition = go->GetPosition(); break; case GO_EXIT_PORTAL: exitPortalGUID = go->GetGUID(); exitPortalPosition = go->GetPosition(); break; case GO_HEART_OF_MAGIC_10: - if (instance->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) - heartOfMagicGUID = go->GetGUID(); - break; case GO_HEART_OF_MAGIC_25: - if (instance->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) - heartOfMagicGUID = go->GetGUID(); + heartOfMagicGUID = go->GetGUID(); + break; + default: break; } } @@ -167,10 +156,10 @@ public: if (eventId == EVENT_FOCUSING_IRIS) { if (Creature* alexstraszaBunny = instance->GetCreature(alexstraszaBunnyGUID)) - { alexstraszaBunny->CastSpell(alexstraszaBunny, SPELL_IRIS_OPENED); - instance->GetGameObject(irisGUID)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); - } + + if (GameObject* iris = instance->GetGameObject(irisGUID)) + iris->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); if (Creature* malygos = instance->GetCreature(malygosGUID)) malygos->AI()->DoAction(0); // ACTION_LAND_ENCOUNTER_START @@ -184,17 +173,17 @@ public: { if (Creature* malygos = instance->GetCreature(malygosGUID)) { - std::list<HostileReference*> m_threatlist = malygos->getThreatManager().getThreatList(); + ThreatContainer::StorageType const& threatList = malygos->getThreatManager().getThreatList(); for (GuidList::const_iterator itr_vortex = vortexTriggers.begin(); itr_vortex != vortexTriggers.end(); ++itr_vortex) { - if (m_threatlist.empty()) + if (threatList.empty()) return; uint8 counter = 0; if (Creature* trigger = instance->GetCreature(*itr_vortex)) { // each trigger have to cast the spell to 5 players. - for (std::list<HostileReference*>::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) + for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) { if (counter >= 5) break; diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp index 2c9d88eac8a..495cf85b759 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp @@ -117,14 +117,12 @@ class boss_keristrasza : public CreatureScript ContainmentSphereGUIDs[1] = instance->GetGuidData(ORMOROKS_CONTAINMET_SPHERE); ContainmentSphereGUIDs[2] = instance->GetGuidData(TELESTRAS_CONTAINMET_SPHERE); - GameObject* ContainmentSpheres[DATA_CONTAINMENT_SPHERES]; - for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i) { - ContainmentSpheres[i] = ObjectAccessor::GetGameObject(*me, ContainmentSphereGUIDs[i]); - if (!ContainmentSpheres[i]) + GameObject* ContainmentSphere = ObjectAccessor::GetGameObject(*me, ContainmentSphereGUIDs[i]); + if (!ContainmentSphere) return false; - if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE) + if (ContainmentSphere->GetGoState() != GO_STATE_ACTIVE) return false; } if (remove_prison) diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp index c3f5c75e059..737a5d5c982 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -229,6 +229,21 @@ class instance_oculus : public InstanceMapScript return true; } + uint32 GetData(uint32 type) const override + { + if (type == DATA_CONSTRUCTS) + { + if (CentrifugueConstructCounter == 0) + return KILL_NO_CONSTRUCT; + else if (CentrifugueConstructCounter == 1) + return KILL_ONE_CONSTRUCT; + else if (CentrifugueConstructCounter > 1) + return KILL_MORE_CONSTRUCT; + } + + return KILL_NO_CONSTRUCT; + } + ObjectGuid GetGuidData(uint32 type) const override { switch (type) diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index 450f97cb9b7..3ab9814b5b5 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -20,6 +20,7 @@ #include "ScriptedGossip.h" #include "SpellScript.h" #include "SpellAuraEffects.h" +#include "SpellInfo.h" #include "CombatAI.h" #include "Player.h" #include "Vehicle.h" @@ -76,6 +77,11 @@ enum Drakes SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, // (60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25, 000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec. // you do not have access to until you kill the Mage-Lord Urom SPELL_EMERALD_DREAM_FUNNEL = 50344, // (60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels. +/* + * All Drakes + * GPS System + */ + SPELL_GPS = 53389, // Misc POINT_LAND = 2, @@ -101,7 +107,13 @@ enum Says WHISPER_DRAKES_WELCOME = 1, WHISPER_DRAKES_ABILITIES = 2, WHISPER_DRAKES_SPECIAL = 3, - WHISPER_DRAKES_LOWHEALTH = 4 + WHISPER_DRAKES_LOWHEALTH = 4, + WHISPER_GPS_10_CONSTRUCTS = 5, + WHISPER_GPS_1_CONSTRUCT = 6, + WHISPER_GPS_VAROS = 7, + WHISPER_GPS_UROM = 8, + WHISPER_GPS_EREGOS = 9, + WHISPER_GPS_END = 10 }; class npc_verdisa_beglaristrasz_eternos : public CreatureScript @@ -250,6 +262,26 @@ class npc_ruby_emerald_amber_drake : public CreatureScript Initialize(); } + void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override + { + if (Unit* creator = ObjectAccessor::GetUnit(*me, me->GetCreatorGUID())) + if (spell->Id == SPELL_GPS) + { + if (_instance->GetBossState(DATA_EREGOS) == DONE) + Talk(WHISPER_GPS_END, creator); + else if (_instance->GetBossState(DATA_UROM) == DONE) + Talk(WHISPER_GPS_EREGOS, creator); + else if (_instance->GetBossState(DATA_VAROS) == DONE) + Talk(WHISPER_GPS_UROM, creator); + else if (_instance->GetData(DATA_CONSTRUCTS) == KILL_NO_CONSTRUCT) + Talk(WHISPER_GPS_VAROS, creator); + else if (_instance->GetData(DATA_CONSTRUCTS) == KILL_ONE_CONSTRUCT) + Talk(WHISPER_GPS_1_CONSTRUCT, creator); + else if (_instance->GetData(DATA_CONSTRUCTS) == KILL_MORE_CONSTRUCT) + Talk(WHISPER_GPS_10_CONSTRUCTS, creator); + } + } + void IsSummonedBy(Unit* summoner) override { if (_instance->GetBossState(DATA_EREGOS) == IN_PROGRESS) diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.h b/src/server/scripts/Northrend/Nexus/Oculus/oculus.h index fd46f0a6bcc..08fc15c5752 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.h +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.h @@ -29,7 +29,9 @@ enum DataTypes DATA_DRAKOS = 0, DATA_VAROS = 1, DATA_UROM = 2, - DATA_EREGOS = 3 + DATA_EREGOS = 3, + // GPS System + DATA_CONSTRUCTS = 4 }; enum CreatureIds @@ -91,6 +93,13 @@ enum InstanceEvents EVENT_EREGOS_INTRO }; +enum ConstructKillState +{ + KILL_NO_CONSTRUCT = 0, + KILL_ONE_CONSTRUCT = 1, + KILL_MORE_CONSTRUCT = 2 +}; + enum Misc { POINT_MOVE_OUT = 1 diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp index 6233c7e8953..86dbe6c16fb 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp @@ -437,7 +437,7 @@ public: return 0; } - void UpdateEscortAI(const uint32 uiDiff) override + void UpdateEscortAI(uint32 uiDiff) override { if (uiPhaseTimer <= uiDiff) { diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp index c67e31c4cc0..227b9c208cc 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp @@ -18,7 +18,6 @@ #include "InstanceScript.h" #include "Player.h" #include "ScriptMgr.h" -#include "WorldSession.h" #include "halls_of_stone.h" DoorData const doorData[] = @@ -172,7 +171,7 @@ class instance_halls_of_stone : public InstanceMapScript bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override { - if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES)) + if (_SkipCheckRequiredBosses(player)) return true; switch (bossId) 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 25d1e214260..7618a0b9156 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 @@ -242,7 +242,7 @@ class ActivateLivingConstellation : public BasicEvent { } - bool Execute(uint64 execTime, uint32 /*diff*/) + bool Execute(uint64 execTime, uint32 /*diff*/) override { if (!_instance || _instance->GetBossState(BOSS_ALGALON) != IN_PROGRESS) return true; // delete event @@ -264,7 +264,7 @@ class CosmicSmashDamageEvent : public BasicEvent { } - bool Execute(uint64 /*execTime*/, uint32 /*diff*/) + bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override { _caster->CastSpell((Unit*)NULL, SPELL_COSMIC_SMASH_TRIGGERED, TRIGGERED_FULL_MASK); return true; @@ -281,7 +281,7 @@ class SummonUnleashedDarkMatter : public BasicEvent { } - bool Execute(uint64 execTime, uint32 /*diff*/) + bool Execute(uint64 execTime, uint32 /*diff*/) override { _caster->CastSpell((Unit*)NULL, SPELL_SUMMON_UNLEASHED_DARK_MATTER, TRIGGERED_FULL_MASK); _caster->m_Events.AddEvent(this, execTime + 30000); @@ -322,7 +322,7 @@ class boss_algalon_the_observer : public CreatureScript void KilledUnit(Unit* victim) override { - if (victim->GetTypeId() == TYPEID_UNIT) + if (victim->GetTypeId() == TYPEID_PLAYER) { _fedOnTears = true; if (!_hasYelled) 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 a04c809f893..b31436f656a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -97,9 +97,6 @@ enum Creatures NPC_MIMIRON_TARGET_BEACON = 33369, NPC_HODIR_TARGET_BEACON = 33108, NPC_FREYA_TARGET_BEACON = 33366, - NPC_LOREKEEPER = 33686, // Hard mode starter - NPC_BRANZ_BRONZBEARD = 33579, - NPC_DELORAH = 33701, NPC_ULDUAR_GAUNTLET_GENERATOR = 33571, // Trigger tied to towers }; @@ -224,7 +221,7 @@ class boss_flame_leviathan : public CreatureScript struct boss_flame_leviathanAI : public BossAI { - boss_flame_leviathanAI(Creature* creature) : BossAI(creature, BOSS_LEVIATHAN), vehicle(creature->GetVehicleKit()) + boss_flame_leviathanAI(Creature* creature) : BossAI(creature, BOSS_LEVIATHAN) { Initialize(); } @@ -244,7 +241,6 @@ class boss_flame_leviathan : public CreatureScript void InitializeAI() override { - ASSERT(vehicle); if (!me->isDead()) Reset(); @@ -256,7 +252,6 @@ class boss_flame_leviathan : public CreatureScript me->SetReactState(REACT_PASSIVE); } - Vehicle* vehicle; uint8 ActiveTowersCount; uint8 Shutdown; bool ActiveTowers; @@ -339,7 +334,7 @@ class boss_flame_leviathan : public CreatureScript void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { if (spell->Id == SPELL_START_THE_ENGINE) - vehicle->InstallAllAccessories(false); + ASSERT_NOTNULL(me->GetVehicleKit())->InstallAllAccessories(false); if (spell->Id == SPELL_ELECTROSHOCK) me->InterruptSpell(CURRENT_CHANNELED_SPELL); @@ -584,16 +579,14 @@ class boss_flame_leviathan_seat : public CreatureScript struct boss_flame_leviathan_seatAI : public ScriptedAI { - boss_flame_leviathan_seatAI(Creature* creature) : ScriptedAI(creature), vehicle(creature->GetVehicleKit()) + boss_flame_leviathan_seatAI(Creature* creature) : ScriptedAI(creature) { - ASSERT(vehicle); me->SetReactState(REACT_PASSIVE); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); instance = creature->GetInstanceScript(); } InstanceScript* instance; - Vehicle* vehicle; void PassengerBoarded(Unit* who, int8 seatId, bool apply) override { @@ -628,7 +621,7 @@ class boss_flame_leviathan_seat : public CreatureScript if (apply) return; - if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) + if (Unit* device = ASSERT_NOTNULL(me->GetVehicleKit())->GetPassenger(SEAT_DEVICE)) { device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); device->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable @@ -1171,9 +1164,49 @@ class npc_freya_ward_summon : public CreatureScript } }; -//npc lore keeper -#define GOSSIP_ITEM_1 "Activate secondary defensive systems" -#define GOSSIP_ITEM_2 "Confirmed" +enum BrannBronzebeardGossips +{ + GOSSIP_MENU_BRANN_BRONZEBEARD = 10355, + GOSSIP_OPTION_BRANN_BRONZEBEARD = 0 +}; + +class npc_brann_bronzebeard_ulduar_intro : public CreatureScript +{ + public: + npc_brann_bronzebeard_ulduar_intro() : CreatureScript("npc_brann_bronzebeard_ulduar_intro") { } + + struct npc_brann_bronzebeard_ulduar_introAI : public ScriptedAI + { + npc_brann_bronzebeard_ulduar_introAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } + + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + if (menuId == GOSSIP_MENU_BRANN_BRONZEBEARD && gossipListId == GOSSIP_OPTION_BRANN_BRONZEBEARD) + { + player->PlayerTalkClass->SendCloseGossip(); + if (Creature* loreKeeper = _instance->GetCreature(DATA_LORE_KEEPER_OF_NORGANNON)) + loreKeeper->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + } + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI<npc_brann_bronzebeard_ulduar_introAI>(creature); + } +}; + +enum LoreKeeperGossips +{ + GOSSIP_MENU_LORE_KEEPER = 10477, + GOSSIP_OPTION_LORE_KEEPER = 0 +}; class npc_lorekeeper : public CreatureScript { @@ -1184,6 +1217,7 @@ class npc_lorekeeper : public CreatureScript { npc_lorekeeperAI(Creature* creature) : ScriptedAI(creature) { + _instance = creature->GetInstanceScript(); } void DoAction(int32 action) override @@ -1191,66 +1225,42 @@ class npc_lorekeeper : public CreatureScript // Start encounter if (action == ACTION_SPAWN_VEHICLES) { - for (int32 i = 0; i < RAID_MODE(2, 5); ++i) + for (uint8 i = 0; i < RAID_MODE(2, 5); ++i) DoSummon(VEHICLE_SIEGE, PosSiege[i], 3000, TEMPSUMMON_CORPSE_TIMED_DESPAWN); - for (int32 i = 0; i < RAID_MODE(2, 5); ++i) + for (uint8 i = 0; i < RAID_MODE(2, 5); ++i) DoSummon(VEHICLE_CHOPPER, PosChopper[i], 3000, TEMPSUMMON_CORPSE_TIMED_DESPAWN); - for (int32 i = 0; i < RAID_MODE(2, 5); ++i) + for (uint8 i = 0; i < RAID_MODE(2, 5); ++i) DoSummon(VEHICLE_DEMOLISHER, PosDemolisher[i], 3000, TEMPSUMMON_CORPSE_TIMED_DESPAWN); - return; } } - }; - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->CLOSE_GOSSIP_MENU(); - InstanceScript* instance = creature->GetInstanceScript(); - if (!instance) - return true; - switch (action) + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override { - case GOSSIP_ACTION_INFO_DEF+1: - player->PrepareGossipMenu(creature); - instance->instance->LoadGrid(364, -16); //make sure leviathan is loaded + if (menuId == GOSSIP_MENU_LORE_KEEPER && gossipListId == GOSSIP_OPTION_LORE_KEEPER) + { + player->PlayerTalkClass->SendCloseGossip(); + _instance->instance->LoadGrid(364, -16); // make sure leviathan is loaded - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - if (Creature* leviathan = instance->instance->GetCreature(instance->GetGuidData(BOSS_LEVIATHAN))) + if (Creature* leviathan = _instance->instance->GetCreature(_instance->GetGuidData(BOSS_LEVIATHAN))) { leviathan->AI()->DoAction(ACTION_START_HARD_MODE); - creature->SetVisible(false); - creature->AI()->DoAction(ACTION_SPAWN_VEHICLES); // spawn the vehicles - if (Creature* Delorah = creature->FindNearestCreature(NPC_DELORAH, 1000, true)) + me->SetVisible(false); + DoAction(ACTION_SPAWN_VEHICLES); // spawn the vehicles + if (Creature* delorah = _instance->GetCreature(DATA_DELLORAH)) { - if (Creature* Branz = creature->FindNearestCreature(NPC_BRANZ_BRONZBEARD, 1000, true)) + if (Creature* brann = _instance->GetCreature(DATA_BRANN_BRONZEBEARD_INTRO)) { - Delorah->GetMotionMaster()->MovePoint(0, Branz->GetPositionX()-4, Branz->GetPositionY(), Branz->GetPositionZ()); - /// @todo Delorah->AI()->Talk(xxxx, Branz->GetGUID()); when reached at branz + delorah->GetMotionMaster()->MovePoint(0, brann->GetPositionX() - 4, brann->GetPositionY(), brann->GetPositionZ()); + /// @todo delorah->AI()->Talk(xxxx, brann->GetGUID()); when reached at branz } } } - break; + } } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - InstanceScript* instance = creature->GetInstanceScript(); - if (instance && instance->GetData(BOSS_LEVIATHAN) != DONE && player) - { - player->PrepareGossipMenu(creature); - - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - } - return true; - } + private: + InstanceScript* _instance; + }; CreatureAI* GetAI(Creature* creature) const override { @@ -1258,56 +1268,6 @@ class npc_lorekeeper : public CreatureScript } }; -//enable hardmode -////npc_brann_bronzebeard this requires more work involving area triggers. if reached this guy speaks through his radio.. -//#define GOSSIP_ITEM_1 "xxxxx" -//#define GOSSIP_ITEM_2 "xxxxx" -// -/* -class npc_brann_bronzebeard : public CreatureScript -{ -public: - npc_brann_bronzebeard() : CreatureScript("npc_brann_bronzebeard") { } - - //bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) override - //{ - // player->PlayerTalkClass->ClearMenus(); - // switch (action) - // { - // case GOSSIP_ACTION_INFO_DEF+1: - // if (player) - // { - // player->PrepareGossipMenu(creature); - // - // player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - // player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - // } - // break; - // case GOSSIP_ACTION_INFO_DEF+2: - // if (player) - // player->CLOSE_GOSSIP_MENU(); - // if (Creature* Lorekeeper = creature->FindNearestCreature(NPC_LOREKEEPER, 1000, true)) //lore keeper of lorgannon - // Lorekeeper->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - // break; - // } - // return true; - //} - //bool OnGossipHello(Player* player, Creature* creature) override - //{ - // InstanceScript* instance = creature->GetInstanceScript(); - // if (instance && instance->GetData(BOSS_LEVIATHAN) !=DONE) - // { - // player->PrepareGossipMenu(creature); - // - // player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - // player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - // } - // return true; - //} - // -} -*/ - class go_ulduar_tower : public GameObjectScript { public: @@ -1840,8 +1800,8 @@ void AddSC_boss_flame_leviathan() new npc_hodirs_fury(); new npc_freyas_ward(); new npc_freya_ward_summon(); + new npc_brann_bronzebeard_ulduar_intro(); new npc_lorekeeper(); - // new npc_brann_bronzebeard(); new go_ulduar_tower(); new achievement_three_car_garage_demolisher(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 2228a860e0d..6958b5d78a5 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -594,8 +594,8 @@ class boss_freya : public CreatureScript const uint32 summonSpell[2][4] = { /* 0Elder, 1Elder, 2Elder, 3Elder */ - /* 10N */ {62950, 62953, 62955, 62957}, - /* 25N */ {62952, 62954, 62956, 62958} + /* 10N */ {62950, 62952, 62953, 62954}, + /* 25N */ {62955, 62956, 62957, 62958} }; me->CastSpell((Unit*)NULL, summonSpell[me->GetMap()->GetDifficulty()][elderCount], true); @@ -611,17 +611,16 @@ class boss_freya : public CreatureScript me->DespawnOrUnsummon(7500); me->CastSpell(me, SPELL_KNOCK_ON_WOOD_CREDIT, true); - Creature* Elder[3]; for (uint8 n = 0; n < 3; ++n) { - Elder[n] = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF + n)); - if (Elder[n] && Elder[n]->IsAlive()) + Creature* Elder = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF + n)); + if (Elder && Elder->IsAlive()) { - Elder[n]->RemoveAllAuras(); - Elder[n]->AttackStop(); - Elder[n]->CombatStop(true); - Elder[n]->DeleteThreatList(); - Elder[n]->GetAI()->DoAction(ACTION_ELDER_FREYA_KILLED); + Elder->RemoveAllAuras(); + Elder->AttackStop(); + Elder->CombatStop(true); + Elder->DeleteThreatList(); + Elder->GetAI()->DoAction(ACTION_ELDER_FREYA_KILLED); } } } @@ -750,8 +749,8 @@ class boss_elder_brightleaf : public CreatureScript case EVENT_SOLAR_FLARE: { uint8 stackAmount = 0; - if (me->GetAura(SPELL_FLUX_AURA)) - stackAmount = me->GetAura(SPELL_FLUX_AURA)->GetStackAmount(); + if (Aura* aura = me->GetAura(SPELL_FLUX_AURA)) + stackAmount = aura->GetStackAmount(); me->CastCustomSpell(SPELL_SOLAR_FLARE, SPELLVALUE_MAX_TARGETS, stackAmount, me, false); events.ScheduleEvent(EVENT_SOLAR_FLARE, urand(5000, 10000)); break; 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 64403ad40ca..7e005eff303 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -234,16 +234,12 @@ class boss_general_vezax : public CreatureScript void CheckShamanisticRage() { - Map* map = me->GetMap(); - if (map && map->IsDungeon()) - { - // If Shaman has Shamanistic Rage and use it during the fight, it will cast Corrupted Rage on him - Map::PlayerList const& Players = map->GetPlayers(); - for (Map::PlayerList::const_iterator itr = Players.begin(); itr != Players.end(); ++itr) - if (Player* player = itr->GetSource()) - if (player->HasSpell(SPELL_SHAMANTIC_RAGE)) - player->CastSpell(player, SPELL_CORRUPTED_RAGE, false); - } + // If Shaman has Shamanistic Rage and use it during the fight, it will cast Corrupted Rage on him + Map::PlayerList const& Players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = Players.begin(); itr != Players.end(); ++itr) + if (Player* player = itr->GetSource()) + if (player->HasSpell(SPELL_SHAMANTIC_RAGE)) + player->CastSpell(player, SPELL_CORRUPTED_RAGE, false); } uint32 GetData(uint32 type) const override @@ -280,34 +276,28 @@ class boss_general_vezax : public CreatureScript */ Unit* CheckPlayersInRange(uint8 playersMin, float rangeMin, float rangeMax) { - Map* map = me->GetMap(); - if (map && map->IsDungeon()) + std::list<Player*> PlayerList; + Map::PlayerList const& Players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = Players.begin(); itr != Players.end(); ++itr) { - std::list<Player*> PlayerList; - Map::PlayerList const& Players = map->GetPlayers(); - for (Map::PlayerList::const_iterator itr = Players.begin(); itr != Players.end(); ++itr) + if (Player* player = itr->GetSource()) { - if (Player* player = itr->GetSource()) - { - float distance = player->GetDistance(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); - if (rangeMin > distance || distance > rangeMax) - continue; + float distance = player->GetDistance(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + if (rangeMin > distance || distance > rangeMax) + continue; - PlayerList.push_back(player); - } + PlayerList.push_back(player); } + } - if (PlayerList.empty()) - return NULL; - - size_t size = PlayerList.size(); - if (size < playersMin) - return NULL; + if (PlayerList.empty()) + return NULL; - return Trinity::Containers::SelectRandomContainerElement(PlayerList); - } + size_t size = PlayerList.size(); + if (size < playersMin) + return NULL; - return NULL; + return Trinity::Containers::SelectRandomContainerElement(PlayerList); } }; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index 098e7aa34be..4b60107a182 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -396,11 +396,11 @@ class boss_hodir : public CreatureScript me->SetControlled(true, UNIT_STATE_STUNNED); me->CombatStop(true); + DoCastAOE(SPELL_KILL_CREDIT, true); /// need to be cast before changing boss faction + /// spell will target enemies only me->setFaction(35); me->DespawnOrUnsummon(10000); - DoCastAOE(SPELL_KILL_CREDIT); - _JustDied(); } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp index d0b87f728c5..a04b53ac495 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp @@ -117,10 +117,9 @@ class boss_ignis : public CreatureScript struct boss_ignis_AI : public BossAI { - boss_ignis_AI(Creature* creature) : BossAI(creature, BOSS_IGNIS), _vehicle(me->GetVehicleKit()) + boss_ignis_AI(Creature* creature) : BossAI(creature, BOSS_IGNIS) { Initialize(); - ASSERT(_vehicle); } void Initialize() @@ -133,7 +132,7 @@ class boss_ignis : public CreatureScript void Reset() override { _Reset(); - if (_vehicle) + if (Vehicle* _vehicle = me->GetVehicleKit()) _vehicle->RemoveAllPassengers(); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_IGNIS_START_EVENT); @@ -284,7 +283,6 @@ class boss_ignis : public CreatureScript private: ObjectGuid _slagPotGUID; - Vehicle* _vehicle; time_t _firstConstructKill; bool _shattered; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index eb9e310b840..92c7d18a065 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -100,11 +100,9 @@ class boss_kologarn : public CreatureScript struct boss_kologarnAI : public BossAI { - boss_kologarnAI(Creature* creature) : BossAI(creature, BOSS_KOLOGARN), vehicle(creature->GetVehicleKit()), + boss_kologarnAI(Creature* creature) : BossAI(creature, BOSS_KOLOGARN), left(false), right(false) { - ASSERT(vehicle); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); @@ -113,7 +111,6 @@ class boss_kologarn : public CreatureScript Reset(); } - Vehicle* vehicle; bool left, right; ObjectGuid eyebeamTarget; @@ -128,9 +125,10 @@ class boss_kologarn : public CreatureScript events.ScheduleEvent(EVENT_FOCUSED_EYEBEAM, 21000); events.ScheduleEvent(EVENT_ENRAGE, 600000); - for (uint8 i = 0; i < 2; ++i) - if (Unit* arm = vehicle->GetPassenger(i)) - arm->ToCreature()->SetInCombatWithZone(); + if (Vehicle* vehicle = me->GetVehicleKit()) + for (uint8 i = 0; i < 2; ++i) + if (Unit* arm = vehicle->GetPassenger(i)) + arm->ToCreature()->SetInCombatWithZone(); _EnterCombat(); } @@ -283,7 +281,7 @@ class boss_kologarn : public CreatureScript case EVENT_RESPAWN_LEFT_ARM: case EVENT_RESPAWN_RIGHT_ARM: { - if (vehicle) + if (Vehicle* vehicle = me->GetVehicleKit()) { int8 seat = eventId == EVENT_RESPAWN_LEFT_ARM ? 0 : 1; uint32 entry = eventId == EVENT_RESPAWN_LEFT_ARM ? NPC_LEFT_ARM : NPC_RIGHT_ARM; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 3c068915585..5c852cd7f26 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -120,7 +120,7 @@ enum Spells SPELL_SUMMON_ROCKET_STRIKE = 63036, SPELL_SCRIPT_EFFECT_ROCKET_STRIKE = 63681, // Cast by Rocket (Mimiron Visual) SPELL_ROCKET_STRIKE = 64064, // Added in creature_template_addon - SPELL_ROCKET_STRIKE_LEFT = 64402, // Cast by VX-001 + SPELL_ROCKET_STRIKE_SINGLE = 64402, // Cast by VX-001 SPELL_ROCKET_STRIKE_BOTH = 65034, // Cast by VX-001 // Flames @@ -320,6 +320,12 @@ enum Waypoints WP_AERIAL_P4_POS }; +enum SeatIds : int8 +{ + ROCKET_SEAT_LEFT = 5, + ROCKET_SEAT_RIGHT = 6 +}; + uint32 const RepairSpells[4] = { SPELL_SEAT_1, @@ -695,7 +701,7 @@ class boss_leviathan_mk_ii : public CreatureScript { me->CastStop(); if (Unit* turret = me->GetVehicleKit()->GetPassenger(3)) - turret->Kill(turret); + turret->KillSelf(); me->SetSpeed(MOVE_RUN, 1.5f, true); me->GetMotionMaster()->MovePoint(WP_MKII_P1_IDLE, VehicleRelocation[WP_MKII_P1_IDLE]); @@ -1043,18 +1049,18 @@ class boss_vx_001 : public CreatureScript events.RescheduleEvent(EVENT_RAPID_BURST, 3000, 0, PHASE_VX_001); break; case EVENT_ROCKET_STRIKE: - DoCastAOE(events.IsInPhase(PHASE_VX_001) ? SPELL_ROCKET_STRIKE_LEFT : SPELL_ROCKET_STRIKE_BOTH); + DoCastAOE(events.IsInPhase(PHASE_VX_001) ? SPELL_ROCKET_STRIKE_SINGLE : SPELL_ROCKET_STRIKE_BOTH); events.ScheduleEvent(EVENT_RELOAD, 10000); events.RescheduleEvent(EVENT_ROCKET_STRIKE, urand(20000, 25000)); break; case EVENT_RELOAD: - for (uint8 seat = 6; seat <= 7; seat++) + for (int8 seat = ROCKET_SEAT_LEFT; seat <= ROCKET_SEAT_RIGHT; ++seat) if (Unit* rocket = me->GetVehicleKit()->GetPassenger(seat)) rocket->SetDisplayId(rocket->GetNativeDisplayId()); break; case EVENT_HAND_PULSE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 120, true)) - DoCast(target, urand(0, 1) == 0 ? SPELL_HAND_PULSE_LEFT : SPELL_HAND_PULSE_RIGHT); + DoCast(target, RAND(SPELL_HAND_PULSE_LEFT, SPELL_HAND_PULSE_RIGHT)); events.RescheduleEvent(EVENT_HAND_PULSE, urand(1500, 3000), 0, PHASE_VOL7RON); break; case EVENT_FROST_BOMB: @@ -2187,8 +2193,8 @@ class spell_mimiron_rocket_strike : public SpellScriptLoader if (targets.empty()) return; - if (m_scriptSpellId == SPELL_ROCKET_STRIKE_LEFT && GetCaster()->IsVehicle()) - if (WorldObject* target = GetCaster()->GetVehicleKit()->GetPassenger(6)) + if (m_scriptSpellId == SPELL_ROCKET_STRIKE_SINGLE && GetCaster()->IsVehicle()) + if (WorldObject* target = GetCaster()->GetVehicleKit()->GetPassenger(RAND(ROCKET_SEAT_LEFT, ROCKET_SEAT_RIGHT))) { targets.clear(); targets.push_back(target); 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 d0e4b7be63b..8545d5b21eb 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -401,20 +401,21 @@ class StartAttackEvent : public BasicEvent { public: StartAttackEvent(Creature* summoner, Creature* owner) - : _summoner(summoner), _owner(owner) + : _summonerGuid(summoner->GetGUID()), _owner(owner) { } bool Execute(uint64 /*time*/, uint32 /*diff*/) { _owner->SetReactState(REACT_AGGRESSIVE); - if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f)) - _owner->AI()->AttackStart(target); + if (Creature* _summoner = ObjectAccessor::GetCreature(*_owner, _summonerGuid)) + if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f)) + _owner->AI()->AttackStart(target); return true; } private: - Creature* _summoner; + ObjectGuid _summonerGuid; Creature* _owner; }; @@ -695,19 +696,22 @@ class boss_sara : public CreatureScript void DamageTaken(Unit* /*attacker*/, uint32& damage) override { - if (_events.IsInPhase(PHASE_ONE) && damage >= me->GetHealth()) + if (damage >= me->GetHealth()) { - damage = 0; + damage = me->GetHealth() - 1; - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) - voice->AI()->DoAction(ACTION_PHASE_TRANSFORM); - - Talk(SAY_SARA_TRANSFORM_1); - _events.SetPhase(PHASE_TRANSFORM); - _events.ScheduleEvent(EVENT_TRANSFORM_1, 4700, 0, PHASE_TRANSFORM); - _events.ScheduleEvent(EVENT_TRANSFORM_2, 9500, 0, PHASE_TRANSFORM); - _events.ScheduleEvent(EVENT_TRANSFORM_3, 14300, 0, PHASE_TRANSFORM); - _events.ScheduleEvent(EVENT_TRANSFORM_4, 14500, 0, PHASE_TRANSFORM); + if (_events.IsInPhase(PHASE_ONE)) + { + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->DoAction(ACTION_PHASE_TRANSFORM); + + Talk(SAY_SARA_TRANSFORM_1); + _events.SetPhase(PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_1, 4700, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_2, 9500, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_3, 14300, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_4, 14500, 0, PHASE_TRANSFORM); + } } } @@ -1504,9 +1508,9 @@ class npc_observation_ring_keeper : public CreatureScript DoCast(SPELL_KEEPER_ACTIVE); } - void sGossipSelect(Player* player, uint32 sender, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 menuId, uint32 /*gossipListId*/) override { - if (sender != 10333) + if (menuId != 10333) return; me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); @@ -2419,7 +2423,7 @@ class spell_yogg_saron_squeeze : public SpellScriptLoader // 64125 { if (Unit* vehicle = GetTarget()->GetVehicleBase()) if (vehicle->IsAlive()) - vehicle->Kill(vehicle); // should tentacle die or just release its target? + vehicle->KillSelf(); // should tentacle die or just release its target? } void Register() override @@ -2901,7 +2905,7 @@ class spell_yogg_saron_insane : public SpellScriptLoader // 63120 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { if (GetTarget()->IsAlive()) - GetTarget()->Kill(GetTarget()); + GetTarget()->KillSelf(); } void Register() override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index ca3ea3a60ed..f2edfa816a0 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -54,6 +54,15 @@ MinionData const minionData[] = { 0, 0, } }; +ObjectData const creatureData[] = +{ + { NPC_BRANN_BRONZEBEARD_INTRO, DATA_BRANN_BRONZEBEARD_INTRO }, + { NPC_LORE_KEEPER_OF_NORGANNON, DATA_LORE_KEEPER_OF_NORGANNON }, + { NPC_HIGH_EXPLORER_DELLORAH, DATA_DELLORAH }, + { NPC_BRONZEBEARD_RADIO, DATA_BRONZEBEARD_RADIO }, + { 0, 0, } +}; + class instance_ulduar : public InstanceMapScript { public: @@ -68,6 +77,7 @@ class instance_ulduar : public InstanceMapScript LoadDoorData(doorData); LoadMinionData(minionData); + LoadObjectData(creatureData, nullptr); _algalonTimer = 61; _maxArmorItemLevel = 0; @@ -420,6 +430,8 @@ class instance_ulduar : public InstanceMapScript algalon->AI()->JustSummoned(creature); break; } + + InstanceScript::OnCreatureCreate(creature); } void OnCreatureRemove(Creature* creature) override @@ -446,6 +458,8 @@ class instance_ulduar : public InstanceMapScript default: break; } + + InstanceScript::OnCreatureRemove(creature); } void OnGameObjectCreate(GameObject* gameObject) override @@ -690,22 +704,7 @@ class instance_ulduar : public InstanceMapScript { case BOSS_LEVIATHAN: if (state == DONE) - { - // Eject all players from vehicles and make them untargetable. - // They will be despawned after a while - for (auto const& vehicleGuid : LeviathanVehicleGUIDs) - { - if (Creature* vehicleCreature = instance->GetCreature(vehicleGuid)) - { - if (Vehicle* vehicle = vehicleCreature->GetVehicleKit()) - { - vehicle->RemoveAllPassengers(); - vehicleCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - vehicleCreature->DespawnOrUnsummon(5 * MINUTE * IN_MILLISECONDS); - } - } - } - } + _events.ScheduleEvent(EVENT_DESPAWN_LEVIATHAN_VEHICLES, 5 * IN_MILLISECONDS); break; case BOSS_IGNIS: case BOSS_RAZORSCALE: @@ -1164,6 +1163,22 @@ class instance_ulduar : public InstanceMapScript algalon->AI()->DoAction(EVENT_DESPAWN_ALGALON); } break; + case EVENT_DESPAWN_LEVIATHAN_VEHICLES: + // Eject all players from vehicles and make them untargetable. + // They will be despawned after a while + for (auto const& vehicleGuid : LeviathanVehicleGUIDs) + { + if (Creature* vehicleCreature = instance->GetCreature(vehicleGuid)) + { + if (Vehicle* vehicle = vehicleCreature->GetVehicleKit()) + { + vehicle->RemoveAllPassengers(); + vehicleCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + vehicleCreature->DespawnOrUnsummon(5 * MINUTE * IN_MILLISECONDS); + } + } + } + break; } } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index d40fb698658..834ab32864f 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -80,6 +80,23 @@ enum UlduarNPCs NPC_YOGG_SARON = 33288, NPC_ALGALON = 32871, + // Flame Leviathan + NPC_ULDUAR_COLOSSUS = 33237, + NPC_BRANN_BRONZEBEARD_INTRO = 33579, + NPC_BRANN_BRONZEBEARD_FLYING_MACHINE = 34119, + NPC_BRANN_S_FLYING_MACHINE = 34120, + NPC_ARCHMAGE_PENTARUS = 33624, + NPC_ARCHMAGE_RHYDIAN = 33696, + NPC_LORE_KEEPER_OF_NORGANNON = 33686, + NPC_HIGH_EXPLORER_DELLORAH = 33701, + NPC_BRONZEBEARD_RADIO = 34054, + NPC_FLAME_LEVIATHAN = 33113, + NPC_FLAME_LEVIATHAN_SEAT = 33114, + NPC_FLAME_LEVIATHAN_TURRET = 33139, + NPC_LEVIATHAN_DEFENSE_TURRET = 33142, + NPC_OVERLOAD_CONTROL_DEVICE = 33143, + NPC_ORBITAL_SUPPORT = 34286, + // Mimiron NPC_LEVIATHAN_MKII = 33432, NPC_VX_001 = 33651, @@ -382,6 +399,12 @@ enum UlduarData DATA_UNIVERSE_GLOBE, DATA_ALGALON_TRAPDOOR, DATA_BRANN_BRONZEBEARD_ALG, + + // Misc + DATA_BRANN_BRONZEBEARD_INTRO, + DATA_LORE_KEEPER_OF_NORGANNON, + DATA_DELLORAH, + DATA_BRONZEBEARD_RADIO }; enum UlduarWorldStates @@ -404,6 +427,7 @@ enum UlduarEvents EVENT_DESPAWN_ALGALON = 1, EVENT_UPDATE_ALGALON_TIMER = 2, ACTION_INIT_ALGALON = 6, + EVENT_DESPAWN_LEVIATHAN_VEHICLES = 7 }; enum YoggSaronIllusions @@ -424,11 +448,13 @@ class PlayerOrPetCheck public: bool operator()(WorldObject* object) const { - if (object->GetTypeId() != TYPEID_PLAYER) - if (!object->ToCreature()->IsPet()) - return true; + if (object->GetTypeId() == TYPEID_PLAYER) + return false; + + if (Creature* creature = object->ToCreature()) + return !creature->IsPet(); - return false; + return true; } }; diff --git a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp index 36d2c5f8ed3..d3868b8df9c 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp @@ -16,19 +16,18 @@ */ #include "ScriptMgr.h" +#include "SpellScript.h" #include "ScriptedCreature.h" #include "violet_hold.h" enum Spells { + SPELL_SUMMON_PLAYER = 21150, SPELL_ARCANE_VACUUM = 58694, SPELL_BLIZZARD = 58693, - H_SPELL_BLIZZARD = 59369, SPELL_MANA_DESTRUCTION = 59374, SPELL_TAIL_SWEEP = 58690, - H_SPELL_TAIL_SWEEP = 59283, SPELL_UNCONTROLLABLE_ENERGY = 58688, - H_SPELL_UNCONTROLLABLE_ENERGY = 59281, SPELL_TRANSFORM = 58668 }; @@ -45,129 +44,91 @@ enum Yells class boss_cyanigosa : public CreatureScript { -public: - boss_cyanigosa() : CreatureScript("boss_cyanigosa") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_cyanigosaAI>(creature); - } - - struct boss_cyanigosaAI : public ScriptedAI - { - boss_cyanigosaAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - uiArcaneVacuumTimer = 10000; - uiBlizzardTimer = 15000; - uiManaDestructionTimer = 30000; - uiTailSweepTimer = 20000; - uiUncontrollableEnergyTimer = 25000; - } - - uint32 uiArcaneVacuumTimer; - uint32 uiBlizzardTimer; - uint32 uiManaDestructionTimer; - uint32 uiTailSweepTimer; - uint32 uiUncontrollableEnergyTimer; - - InstanceScript* instance; - - void Reset() override - { - Initialize(); - instance->SetData(DATA_CYANIGOSA_EVENT, NOT_STARTED); - } + public: + boss_cyanigosa() : CreatureScript("boss_cyanigosa") { } - void EnterCombat(Unit* /*who*/) override + struct boss_cyanigosaAI : public BossAI { - Talk(SAY_AGGRO); - - instance->SetData(DATA_CYANIGOSA_EVENT, IN_PROGRESS); - } - - void MoveInLineOfSight(Unit* /*who*/) override { } + boss_cyanigosaAI(Creature* creature) : BossAI(creature, DATA_CYANIGOSA) { } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_REMOVE_NPC) == 1) + void EnterCombat(Unit* who) override { - me->DespawnOrUnsummon(); - instance->SetData(DATA_REMOVE_NPC, 0); + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); } - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiArcaneVacuumTimer <= diff) + void KilledUnit(Unit* victim) override { - DoCast(SPELL_ARCANE_VACUUM); - uiArcaneVacuumTimer = 10000; - } else uiArcaneVacuumTimer -= diff; + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - if (uiBlizzardTimer <= diff) + void JustDied(Unit* killer) override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_BLIZZARD); - uiBlizzardTimer = 15000; - } else uiBlizzardTimer -= diff; + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } - if (uiTailSweepTimer <= diff) - { - DoCast(SPELL_TAIL_SWEEP); - uiTailSweepTimer = 20000; - } else uiTailSweepTimer -= diff; + void MoveInLineOfSight(Unit* /*who*/) override { } - if (uiUncontrollableEnergyTimer <= diff) + void UpdateAI(uint32 diff) override { - DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY); - uiUncontrollableEnergyTimer = 25000; - } else uiUncontrollableEnergyTimer -= diff; + if (!UpdateVictim()) + return; + + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } - if (IsHeroic()) + void ScheduleTasks() override { - if (uiManaDestructionTimer <= diff) + scheduler.Schedule(Seconds(10), [this](TaskContext task) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_MANA_DESTRUCTION); - uiManaDestructionTimer = 30000; - } else uiManaDestructionTimer -= diff; - } + DoCastAOE(SPELL_ARCANE_VACUUM); + task.Repeat(); + }); - DoMeleeAttackIfReady(); - } + scheduler.Schedule(Seconds(15), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true)) + DoCast(target, SPELL_BLIZZARD); + task.Repeat(); + }); - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); + scheduler.Schedule(Seconds(20), [this](TaskContext task) + { + DoCastVictim(SPELL_TAIL_SWEEP); + task.Repeat(); + }); - instance->SetData(DATA_CYANIGOSA_EVENT, DONE); - } + scheduler.Schedule(Seconds(25), [this](TaskContext task) + { + DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY); + task.Repeat(); + }); - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; + if (IsHeroic()) + { + scheduler.Schedule(Seconds(30), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true)) + DoCast(target, SPELL_MANA_DESTRUCTION); + task.Repeat(); + }); + } + } + }; - Talk(SAY_SLAY); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<boss_cyanigosaAI>(creature); } - }; - }; class achievement_defenseless : public AchievementCriteriaScript { public: - achievement_defenseless() : AchievementCriteriaScript("achievement_defenseless") - { - } + achievement_defenseless() : AchievementCriteriaScript("achievement_defenseless") { } bool OnCheck(Player* /*player*/, Unit* target) override { @@ -178,10 +139,40 @@ class achievement_defenseless : public AchievementCriteriaScript if (!instance) return false; - if (!instance->GetData(DATA_DEFENSELESS)) - return false; + return instance->GetData(DATA_DEFENSELESS) != 0; + } +}; + +class spell_cyanigosa_arcane_vacuum : public SpellScriptLoader +{ + public: + spell_cyanigosa_arcane_vacuum() : SpellScriptLoader("spell_cyanigosa_arcane_vacuum") { } + + class spell_cyanigosa_arcane_vacuum_SpellScript : public SpellScript + { + PrepareSpellScript(spell_cyanigosa_arcane_vacuum_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_PLAYER)) + return false; + return true; + } - return true; + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_PLAYER, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_cyanigosa_arcane_vacuum_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_cyanigosa_arcane_vacuum_SpellScript(); } }; @@ -189,4 +180,5 @@ void AddSC_boss_cyanigosa() { new boss_cyanigosa(); new achievement_defenseless(); + new spell_cyanigosa_arcane_vacuum(); } diff --git a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp index e990b8796de..cc27bf52118 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp @@ -24,12 +24,11 @@ enum Spells SPELL_BLOODLUST = 54516, SPELL_BREAK_BONDS = 59463, SPELL_CHAIN_HEAL = 54481, - H_SPELL_CHAIN_HEAL = 59473, SPELL_EARTH_SHIELD = 54479, - H_SPELL_EARTH_SHIELD = 59471, SPELL_EARTH_SHOCK = 54511, SPELL_LIGHTNING_BOLT = 53044, - SPELL_STORMSTRIKE = 51876 + SPELL_STORMSTRIKE = 51876, + SPELL_WINDFURY = 54493 }; enum Yells @@ -44,209 +43,208 @@ enum Yells class boss_erekem : public CreatureScript { -public: - boss_erekem() : CreatureScript("boss_erekem") { } + public: + boss_erekem() : CreatureScript("boss_erekem") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_erekemAI>(creature); - } - - struct boss_erekemAI : public ScriptedAI - { - boss_erekemAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() + struct boss_erekemAI : public BossAI { - uiBloodlustTimer = 15000; - uiChainHealTimer = 0; - uiEarthShockTimer = urand(2000, 8000); - uiLightningBoltTimer = urand(5000, 10000); - uiEarthShieldTimer = 20000; - } - - uint32 uiBloodlustTimer; - uint32 uiChainHealTimer; - uint32 uiEarthShockTimer; - uint32 uiLightningBoltTimer; - uint32 uiEarthShieldTimer; - - InstanceScript* instance; + boss_erekemAI(Creature* creature) : BossAI(creature, DATA_EREKEM) + { + Initialize(); + } - void Reset() override - { - Initialize(); - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + void Initialize() + { + _phase = 0; + } - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) + void Reset() override { - if (!pGuard1->IsAlive()) - pGuard1->Respawn(); + Initialize(); + BossAI::Reset(); + me->SetCanDualWield(false); } - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) + + void EnterCombat(Unit* who) override { - if (!pGuard2->IsAlive()) - pGuard2->Respawn(); + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); + DoCast(me, SPELL_EARTH_SHIELD); } - } - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; + void MovementInform(uint32 type, uint32 pointId) override + { + if (type == EFFECT_MOTION_TYPE && pointId == POINT_INTRO) + me->SetFacingTo(4.921828f); + } - if (me->Attack(who, true)) + void JustReachedHome() override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_EREKEM); + } - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) - { - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); - if (!pGuard1->GetVictim() && pGuard1->AI()) - pGuard1->AI()->AttackStart(who); - } - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) - { - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); - if (!pGuard2->GetVictim() && pGuard2->AI()) - pGuard2->AI()->AttackStart(who); - } + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } - } - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); - DoCast(me, SPELL_EARTH_SHIELD); + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_EREKEM_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) + bool CheckGuardAuras(Creature* guard) const + { + static uint32 const MechanicImmunityList = + (1 << MECHANIC_SNARE) + | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) + | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) + | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) + | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) + | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) + | (1 << MECHANIC_TURN); + + static std::list<AuraType> const AuraImmunityList = { - EnterEvadeMode(); - return; - } + SPELL_AURA_MOD_STUN, + SPELL_AURA_MOD_DECREASE_SPEED, + SPELL_AURA_MOD_ROOT, + SPELL_AURA_MOD_CONFUSE, + SPELL_AURA_MOD_FEAR + }; - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } + if (guard->HasAuraWithMechanic(MechanicImmunityList)) + return true; - void MoveInLineOfSight(Unit* /*who*/) override { } + for (AuraType type : AuraImmunityList) + if (guard->HasAuraType(type)) + return true; + return false; + } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //spam stormstrike in hc mode if spawns are dead - if (IsHeroic()) + bool CheckGuardAlive() const { - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) { - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) - { - if (!pGuard1->IsAlive() && !pGuard2->IsAlive()) - DoCastVictim(SPELL_STORMSTRIKE); - } + if (Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i))) + if (guard->IsAlive()) + return true; } + + return false; } - if (uiEarthShieldTimer <= diff) + Unit* GetChainHealTarget() const { - DoCast(me, SPELL_EARTH_SHIELD); - uiEarthShieldTimer = 20000; - } else uiEarthShieldTimer -= diff; + if (HealthBelowPct(85)) + return me; - if (uiChainHealTimer <= diff) - { - if (ObjectGuid TargetGUID = GetChainHealTargetGUID()) + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) { - if (Creature* target = ObjectAccessor::GetCreature(*me, TargetGUID)) - DoCast(target, SPELL_CHAIN_HEAL); - - //If one of the adds is dead spawn heals faster - Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)); - Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)); - uiChainHealTimer = ((pGuard1 && !pGuard1->IsAlive()) || (pGuard2 && !pGuard2->IsAlive()) ? 3000 : 8000) + rand32() % 3000; + if (Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i))) + if (guard->IsAlive() && !guard->HealthAbovePct(75)) + return guard; } - } else uiChainHealTimer -= diff; - if (uiBloodlustTimer <= diff) - { - DoCast(me, SPELL_BLOODLUST); - uiBloodlustTimer = urand(35000, 45000); - } else uiBloodlustTimer -= diff; + return nullptr; + } - if (uiEarthShockTimer <= diff) + void UpdateAI(uint32 diff) override { - DoCastVictim(SPELL_EARTH_SHOCK); - uiEarthShockTimer = urand(8000, 13000); - } else uiEarthShockTimer -= diff; + if (!UpdateVictim()) + return; + + if (_phase == 0 && !CheckGuardAlive()) + { + _phase = 1; + me->SetCanDualWield(true); + DoCast(me, SPELL_WINDFURY, true); + } + + scheduler.Update(diff, [this] + { + if (_phase == 1) + DoSpellAttackIfReady(SPELL_STORMSTRIKE); + else + DoMeleeAttackIfReady(); + }); + } - if (uiLightningBoltTimer <= diff) + void ScheduleTasks() override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_LIGHTNING_BOLT); - uiLightningBoltTimer = urand(18000, 24000); - } else uiLightningBoltTimer -= diff; + scheduler.Schedule(Seconds(20), [this](TaskContext task) + { + if (Unit* ally = DoSelectLowestHpFriendly(30.0f)) + DoCast(ally, SPELL_EARTH_SHIELD); - DoMeleeAttackIfReady(); - } + task.Repeat(Seconds(20)); + }); - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); + scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + DoCast(SPELL_BLOODLUST); + task.Repeat(Seconds(35), Seconds(45)); + }); - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); - } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); - } - } + scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f)) + DoCast(target, SPELL_LIGHTNING_BOLT); - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; + task.Repeat(Milliseconds(2500)); + }); - Talk(SAY_SLAY); - } + scheduler.Schedule(Seconds(10), [this](TaskContext task) + { + if (Unit* ally = DoSelectLowestHpFriendly(40.0f)) + DoCast(ally, SPELL_CHAIN_HEAL); - ObjectGuid GetChainHealTargetGUID() - { - if (HealthBelowPct(85)) - return me->GetGUID(); + if (!CheckGuardAlive()) + task.Repeat(Seconds(3)); + else + task.Repeat(Seconds(8), Seconds(11)); + }); + + scheduler.Schedule(Seconds(2), Seconds(8), [this](TaskContext task) + { + DoCastVictim(SPELL_EARTH_SHOCK); + task.Repeat(Seconds(8), Seconds(13)); + }); - Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)); - if (pGuard1 && pGuard1->IsAlive() && !pGuard1->HealthAbovePct(75)) - return pGuard1->GetGUID(); + scheduler.Schedule(Seconds(0), [this](TaskContext task) + { + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) + { + Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i)); + + if (guard && guard->IsAlive() && CheckGuardAuras(guard)) + { + DoCastAOE(SPELL_BREAK_BONDS); + task.Repeat(Seconds(10)); + return; + } + } + task.Repeat(Milliseconds(500)); + }); + } - Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)); - if (pGuard2 && pGuard2->IsAlive() && !pGuard2->HealthAbovePct(75)) - return pGuard2->GetGUID(); + private: + uint8 _phase; + }; - return ObjectGuid::Empty; + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<boss_erekemAI>(creature); } - }; - }; enum GuardSpells @@ -258,84 +256,61 @@ enum GuardSpells class npc_erekem_guard : public CreatureScript { -public: - npc_erekem_guard() : CreatureScript("npc_erekem_guard") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_erekem_guardAI>(creature); - } - - struct npc_erekem_guardAI : public ScriptedAI - { - npc_erekem_guardAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + public: + npc_erekem_guard() : CreatureScript("npc_erekem_guard") { } - void Initialize() + struct npc_erekem_guardAI : public ScriptedAI { - uiStrikeTimer = urand(4000, 8000); - uiHowlingScreechTimer = urand(8000, 13000); - uiGushingWoundTimer = urand(1000, 3000); - } - - uint32 uiGushingWoundTimer; - uint32 uiHowlingScreechTimer; - uint32 uiStrikeTimer; - - InstanceScript* instance; - - void Reset() override - { - Initialize(); - } + npc_erekem_guardAI(Creature* creature) : ScriptedAI(creature) { } - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; + void Reset() override + { + scheduler.CancelAll(); + } - if (me->Attack(who, true)) + void EnterCombat(Unit* /*who*/) override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + DoZoneInCombat(); } - } - void MoveInLineOfSight(Unit* /*who*/) override { } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + scheduler.Update(diff, + std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); + } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; + void ScheduledTasks() + { + scheduler.Schedule(Seconds(4), Seconds(8), [this](TaskContext task) + { + DoCastVictim(SPELL_STRIKE); + task.Repeat(Seconds(4), Seconds(8)); + }); - DoMeleeAttackIfReady(); + scheduler.Schedule(Seconds(8), Seconds(13), [this](TaskContext task) + { + DoCastAOE(SPELL_HOWLING_SCREECH); + task.Repeat(Seconds(8), Seconds(13)); + }); - if (uiStrikeTimer <= diff) - { - DoCastVictim(SPELL_STRIKE); - uiStrikeTimer = urand(4000, 8000); - } else uiStrikeTimer -= diff; + scheduler.Schedule(Seconds(1), Seconds(3), [this](TaskContext task) + { + DoCastVictim(SPELL_GUSHING_WOUND); + task.Repeat(Seconds(7), Seconds(12)); + }); + } - if (uiHowlingScreechTimer <= diff) - { - DoCastVictim(SPELL_HOWLING_SCREECH); - uiHowlingScreechTimer = urand(8000, 13000); - } else uiHowlingScreechTimer -= diff; + private: + TaskScheduler scheduler; + }; - if (uiGushingWoundTimer <= diff) - { - DoCastVictim(SPELL_GUSHING_WOUND); - uiGushingWoundTimer = urand(7000, 12000); - } else uiGushingWoundTimer -= diff; + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_erekem_guardAI>(creature); } - }; - }; void AddSC_boss_erekem() diff --git a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp index 48fe8049d19..3c29cc1123c 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp @@ -17,25 +17,32 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" #include "violet_hold.h" enum Spells { - SPELL_DRAINED = 59820, - SPELL_FRENZY = 54312, - SPELL_FRENZY_H = 59522, - SPELL_PROTECTIVE_BUBBLE = 54306, SPELL_WATER_BLAST = 54237, - SPELL_WATER_BLAST_H = 59520, SPELL_WATER_BOLT_VOLLEY = 54241, - SPELL_WATER_BOLT_VOLLEY_H = 59521, - SPELL_SPLASH = 59516, - SPELL_WATER_GLOBULE = 54268 -}; - -enum IchoronCreatures -{ - NPC_ICHOR_GLOBULE = 29321, + SPELL_SPLATTER = 54259, + SPELL_PROTECTIVE_BUBBLE = 54306, + SPELL_FRENZY = 54312, + SPELL_BURST = 54379, + SPELL_DRAINED = 59820, + SPELL_THREAT_PROC = 61732, + SPELL_SHRINK = 54297, + + SPELL_WATER_GLOBULE_SUMMON_1 = 54258, + SPELL_WATER_GLOBULE_SUMMON_2 = 54264, + SPELL_WATER_GLOBULE_SUMMON_3 = 54265, + SPELL_WATER_GLOBULE_SUMMON_4 = 54266, + SPELL_WATER_GLOBULE_SUMMON_5 = 54267, + SPELL_WATER_GLOBULE_TRANSFORM = 54268, + SPELL_WATER_GLOBULE_VISUAL = 54260, + + SPELL_MERGE = 54269, + SPELL_SPLASH = 59516 }; enum Yells @@ -46,24 +53,15 @@ enum Yells SAY_SPAWN = 3, SAY_ENRAGE = 4, SAY_SHATTER = 5, - SAY_BUBBLE = 6 + SAY_BUBBLE = 6, + EMOTE_SHATTER = 7 }; enum Actions { - ACTION_WATER_ELEMENT_HIT = 1, - ACTION_WATER_ELEMENT_KILLED = 2, -}; - -/// @todo get those positions from spawn of creature 29326 -#define MAX_SPAWN_LOC 5 -static Position SpawnLoc[MAX_SPAWN_LOC]= -{ - {1840.64f, 795.407f, 44.079f, 1.676f}, - {1886.24f, 757.733f, 47.750f, 5.201f}, - {1877.91f, 845.915f, 43.417f, 3.560f}, - {1918.97f, 850.645f, 47.225f, 4.136f}, - {1935.50f, 796.224f, 52.492f, 4.224f}, + ACTION_WATER_GLOBULE_HIT = 1, + ACTION_PROTECTIVE_BUBBLE_SHATTERED = 2, + ACTION_DRAINED = 3 }; enum Misc @@ -73,338 +71,394 @@ enum Misc class boss_ichoron : public CreatureScript { -public: - boss_ichoron() : CreatureScript("boss_ichoron") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_ichoronAI>(creature); - } - - struct boss_ichoronAI : public ScriptedAI - { - boss_ichoronAI(Creature* creature) : ScriptedAI(creature), m_waterElements(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + public: + boss_ichoron() : CreatureScript("boss_ichoron") { } - void Initialize() + struct boss_ichoronAI : public BossAI { - bIsExploded = false; - bIsFrenzy = false; - dehydration = true; - uiBubbleCheckerTimer = 1000; - uiWaterBoltVolleyTimer = urand(10000, 15000); - } + boss_ichoronAI(Creature* creature) : BossAI(creature, DATA_ICHORON) + { + Initialize(); - bool bIsExploded; - bool bIsFrenzy; - bool dehydration; + /// for some reason ichoron can't walk back to it's water basin on evade + me->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING); + } - uint32 uiBubbleCheckerTimer; - uint32 uiWaterBoltVolleyTimer; + void Initialize() + { + _isFrenzy = false; + _dehydration = true; + } - InstanceScript* instance; + void Reset() override + { + Initialize(); + BossAI::Reset(); - SummonList m_waterElements; + DoCast(me, SPELL_THREAT_PROC, true); + } - void Reset() override - { - Initialize(); + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); + } - me->SetVisible(true); - DespawnWaterElements(); + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_ICHORON); + } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } + void DoAction(int32 actionId) override + { + switch (actionId) + { + case ACTION_WATER_GLOBULE_HIT: + if (!me->IsAlive()) + break; + + me->ModifyHealth(int32(me->CountPctFromMaxHealth(3))); + _dehydration = false; + break; + case ACTION_PROTECTIVE_BUBBLE_SHATTERED: + { + Talk(SAY_SHATTER); + Talk(EMOTE_SHATTER); - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); + DoCastAOE(SPELL_SPLATTER, true); + DoCastAOE(SPELL_BURST, true); + DoCast(me, SPELL_DRAINED, true); - DoCast(me, SPELL_PROTECTIVE_BUBBLE); + uint32 damage = me->CountPctFromMaxHealth(30); + me->LowerPlayerDamageReq(damage); + me->ModifyHealth(-std::min<int32>(damage, me->GetHealth() - 1)); - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_ICHORON_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; + scheduler.DelayAll(Seconds(15)); + break; + } + case ACTION_DRAINED: + if (HealthAbovePct(30)) + { + Talk(SAY_BUBBLE); + DoCast(me, SPELL_PROTECTIVE_BUBBLE, true); + } + break; + default: + break; } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; + } - if (me->Attack(who, true)) + uint32 GetData(uint32 type) const override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + if (type == DATA_DEHYDRATION) + return _dehydration ? 1 : 0; + return 0; } - } - void DoAction(int32 param) override - { - if (!me->IsAlive()) - return; + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - switch (param) + void JustDied(Unit* killer) override { - case ACTION_WATER_ELEMENT_HIT: - me->ModifyHealth(int32(me->CountPctFromMaxHealth(1))); - - if (bIsExploded) - DoExplodeCompleted(); - - dehydration = false; - break; - case ACTION_WATER_ELEMENT_KILLED: - uint32 damage = me->CountPctFromMaxHealth(3); - me->ModifyHealth(-int32(damage)); - me->LowerPlayerDamageReq(damage); - break; + BossAI::JustDied(killer); + Talk(SAY_DEATH); } - } - void DespawnWaterElements() - { - m_waterElements.DespawnAll(); - } + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); - // call when explode shall stop. - // either when "hit" by a bubble, or when there is no bubble left. - void DoExplodeCompleted() - { - bIsExploded = false; + if (summon->GetEntry() == NPC_ICHOR_GLOBULE) + DoCast(summon, SPELL_WATER_GLOBULE_VISUAL); + } - if (!HealthBelowPct(25)) + void SummonedCreatureDespawn(Creature* summon) override { - Talk(SAY_BUBBLE); - DoCast(me, SPELL_PROTECTIVE_BUBBLE, true); + BossAI::SummonedCreatureDespawn(summon); + + if (summons.empty()) + me->RemoveAurasDueToSpell(SPELL_DRAINED, ObjectGuid::Empty, 0, AURA_REMOVE_BY_EXPIRE); } - me->SetVisible(true); - me->GetMotionMaster()->MoveChase(me->GetVictim()); - } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; - uint32 GetData(uint32 type) const override - { - if (type == DATA_DEHYDRATION) - return dehydration ? 1 : 0; + if (!_isFrenzy && HealthBelowPct(25) && !me->HasAura(SPELL_DRAINED)) + { + Talk(SAY_ENRAGE); + DoCast(me, SPELL_FRENZY, true); + _isFrenzy = true; + } - return 0; - } + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } + + void ScheduleTasks() override + { + scheduler.Async([this] + { + DoCast(me, SPELL_SHRINK); + DoCast(me, SPELL_PROTECTIVE_BUBBLE); + }); - void MoveInLineOfSight(Unit* /*who*/) override { } + scheduler.Schedule(Seconds(10), Seconds(15), [this](TaskContext task) + { + DoCastAOE(SPELL_WATER_BOLT_VOLLEY); + task.Repeat(Seconds(10), Seconds(15)); + }); + scheduler.Schedule(Seconds(6), Seconds(9), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f)) + DoCast(target, SPELL_WATER_BLAST); + task.Repeat(Seconds(6), Seconds(9)); + }); + } - void UpdateAI(uint32 uiDiff) override + private: + bool _isFrenzy; + bool _dehydration; + }; + + CreatureAI* GetAI(Creature* creature) const override { - if (!UpdateVictim()) - return; + return GetVioletHoldAI<boss_ichoronAI>(creature); + } +}; + +class npc_ichor_globule : public CreatureScript +{ + public: + npc_ichor_globule() : CreatureScript("npc_ichor_globule") { } - if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded) + struct npc_ichor_globuleAI : public ScriptedAI + { + npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature) { - Talk(SAY_ENRAGE); - DoCast(me, SPELL_FRENZY, true); - bIsFrenzy = true; + _instance = creature->GetInstanceScript(); + creature->SetReactState(REACT_PASSIVE); } - if (!bIsFrenzy) + void SpellHit(Unit* caster, SpellInfo const* spellInfo) override { - if (uiBubbleCheckerTimer <= uiDiff) + if (spellInfo->Id == SPELL_WATER_GLOBULE_VISUAL) { - if (!bIsExploded) - { - if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE)) - { - Talk(SAY_SHATTER); - DoCast(me, SPELL_WATER_BLAST); - DoCast(me, SPELL_DRAINED); - bIsExploded = true; - me->AttackStop(); - me->SetVisible(false); - for (uint8 i = 0; i < 10; i++) - { - int tmp = urand(0, MAX_SPAWN_LOC-1); - me->SummonCreature(NPC_ICHOR_GLOBULE, SpawnLoc[tmp], TEMPSUMMON_CORPSE_DESPAWN); - } - } - } - else - { - bool bIsWaterElementsAlive = false; - if (!m_waterElements.empty()) - { - for (SummonList::const_iterator itr = m_waterElements.begin(); itr != m_waterElements.end(); ++itr) - if (Creature* temp = ObjectAccessor::GetCreature(*me, *itr)) - if (temp->IsAlive()) - { - bIsWaterElementsAlive = true; - break; - } - } - - if (!bIsWaterElementsAlive) - DoExplodeCompleted(); - } - uiBubbleCheckerTimer = 1000; + DoCast(me, SPELL_WATER_GLOBULE_TRANSFORM); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->MoveFollow(caster, 0.0f, 0.0f); } - else uiBubbleCheckerTimer -= uiDiff; } - if (!bIsExploded) + void MovementInform(uint32 type, uint32 id) override { - if (uiWaterBoltVolleyTimer <= uiDiff) - { - DoCast(me, SPELL_WATER_BOLT_VOLLEY); - uiWaterBoltVolleyTimer = urand(10000, 15000); - } - else uiWaterBoltVolleyTimer -= uiDiff; + if (type != FOLLOW_MOTION_TYPE) + return; + + if (_instance->GetObjectGuid(DATA_ICHORON).GetCounter() != id) + return; - DoMeleeAttackIfReady(); + me->CastSpell(me, SPELL_MERGE); + me->DespawnOrUnsummon(1); } + + // on retail spell casted on a creature's death are not casted after death but keeping mob at 1 health, casting it and then letting the mob die. + // this feature should be still implemented + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (damage >= me->GetHealth()) + DoCastAOE(SPELL_SPLASH); + } + + void UpdateAI(uint32 /*diff*/) override { } + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_ichor_globuleAI>(creature); } +}; + +// 59820 - Drained +class spell_ichoron_drained : public SpellScriptLoader +{ + public: + spell_ichoron_drained() : SpellScriptLoader("spell_ichoron_drained") { } - void JustDied(Unit* /*killer*/) override + class spell_ichoron_drained_AuraScript : public AuraScript { - Talk(SAY_DEATH); + PrepareAuraScript(spell_ichoron_drained_AuraScript); - if (bIsExploded) + bool Load() override { - bIsExploded = false; - me->SetVisible(true); + return GetOwner()->GetEntry() == NPC_ICHORON || GetOwner()->GetEntry() == NPC_DUMMY_ICHORON; } - DespawnWaterElements(); + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_31); + GetTarget()->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + } - if (instance->GetData(DATA_WAVE_COUNT) == 6) + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); + GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_31); + GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + if (GetTarget()->IsAIEnabled) + GetTarget()->GetAI()->DoAction(ACTION_DRAINED); } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) + + void Register() override { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); + AfterEffectApply += AuraEffectApplyFn(spell_ichoron_drained_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_drained_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_ichoron_drained_AuraScript(); } +}; + +// 54269 - Merge +class spell_ichoron_merge : public SpellScriptLoader +{ + public: + spell_ichoron_merge() : SpellScriptLoader("spell_ichoron_merge") { } - void JustSummoned(Creature* summoned) override + class spell_ichoron_merge_SpellScript : public SpellScript { - if (summoned) + PrepareSpellScript(spell_ichoron_merge_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - summoned->SetSpeed(MOVE_RUN, 0.3f); - summoned->GetMotionMaster()->MoveFollow(me, 0, 0); - m_waterElements.Summon(summoned); - instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID()); + if (!sSpellMgr->GetSpellInfo(SPELL_SHRINK)) + return false; + return true; } - } - void SummonedCreatureDespawn(Creature* summoned) override - { - if (summoned) + void HandleScript(SpellEffIndex /*effIndex*/) { - m_waterElements.Despawn(summoned); - instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID()); + if (Creature* target = GetHitCreature()) + { + if (Aura* aura = target->GetAura(SPELL_SHRINK)) + aura->ModStackAmount(-1); + + target->AI()->DoAction(ACTION_WATER_GLOBULE_HIT); + } } - } - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ichoron_merge_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; - Talk(SAY_SLAY); + SpellScript* GetSpellScript() const override + { + return new spell_ichoron_merge_SpellScript(); } - }; - }; -class npc_ichor_globule : public CreatureScript +// 54306 - Protective Bubble +class spell_ichoron_protective_bubble : public SpellScriptLoader { -public: - npc_ichor_globule() : CreatureScript("npc_ichor_globule") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_ichor_globuleAI>(creature); - } + public: + spell_ichoron_protective_bubble() : SpellScriptLoader("spell_ichoron_protective_bubble") { } - struct npc_ichor_globuleAI : public ScriptedAI - { - npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature) + class spell_ichoron_protective_bubble_AuraScript : public AuraScript { - Initialize(); - instance = creature->GetInstanceScript(); - } + PrepareAuraScript(spell_ichoron_protective_bubble_AuraScript); - void Initialize() - { - uiRangeCheck_Timer = 1000; - } + bool Load() override + { + return GetOwner()->GetEntry() == NPC_ICHORON || GetOwner()->GetEntry() == NPC_DUMMY_ICHORON; + } - InstanceScript* instance; + void HandleShatter(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + //if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL) + if (GetAura()->GetCharges() <= 1) + if (GetTarget()->IsAIEnabled) + GetTarget()->GetAI()->DoAction(ACTION_PROTECTIVE_BUBBLE_SHATTERED); + } - uint32 uiRangeCheck_Timer; + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_protective_bubble_AuraScript::HandleShatter, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + } + }; - void Reset() override + AuraScript* GetAuraScript() const override { - Initialize(); - DoCast(me, SPELL_WATER_GLOBULE); + return new spell_ichoron_protective_bubble_AuraScript(); } +}; - void AttackStart(Unit* /*who*/) override - { - return; - } +// 54259 - Splatter +class spell_ichoron_splatter : public SpellScriptLoader +{ + public: + spell_ichoron_splatter() : SpellScriptLoader("spell_ichoron_splatter") { } - void UpdateAI(uint32 uiDiff) override + class spell_ichoron_splatter_AuraScript : public AuraScript { - if (uiRangeCheck_Timer < uiDiff) + PrepareAuraScript(spell_ichoron_splatter_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override { - if (Creature* pIchoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON))) - { - if (me->IsWithinDist(pIchoron, 2.0f, false)) - { - if (pIchoron->AI()) - pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT); - me->DespawnOrUnsummon(); - } - } - uiRangeCheck_Timer = 1000; + if (!sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_1) + || !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_2) + || !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_3) + || !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_4) + || !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_5) + || !sSpellMgr->GetSpellInfo(SPELL_SHRINK)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), RAND(SPELL_WATER_GLOBULE_SUMMON_1, SPELL_WATER_GLOBULE_SUMMON_2, SPELL_WATER_GLOBULE_SUMMON_3, SPELL_WATER_GLOBULE_SUMMON_4, SPELL_WATER_GLOBULE_SUMMON_5), true); } - else uiRangeCheck_Timer -= uiDiff; - } - void JustDied(Unit* /*killer*/) override + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + if (Aura* aura = GetTarget()->GetAura(SPELL_SHRINK)) + aura->ModStackAmount(10); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ichoron_splatter_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_splatter_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override { - DoCast(me, SPELL_SPLASH); - if (Creature* pIchoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON))) - if (pIchoron->AI()) - pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED); + return new spell_ichoron_splatter_AuraScript(); } - }; - }; class achievement_dehydration : public AchievementCriteriaScript { public: - achievement_dehydration() : AchievementCriteriaScript("achievement_dehydration") - { - } + achievement_dehydration() : AchievementCriteriaScript("achievement_dehydration") { } bool OnCheck(Player* /*player*/, Unit* target) override { @@ -423,5 +477,9 @@ void AddSC_boss_ichoron() { new boss_ichoron(); new npc_ichor_globule(); + new spell_ichoron_drained(); + new spell_ichoron_merge(); + new spell_ichoron_protective_bubble(); + new spell_ichoron_splatter(); new achievement_dehydration(); } diff --git a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp index c3df7b71b83..c3b617f8199 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp @@ -21,139 +21,88 @@ enum Spells { - SPELL_CAUTERIZING_FLAMES = 59466, //Only in heroic - SPELL_FIREBOLT = 54235, - H_SPELL_FIREBOLT = 59468, - SPELL_FLAME_BREATH = 54282, - H_SPELL_FLAME_BREATH = 59469, - SPELL_LAVA_BURN = 54249, - H_SPELL_LAVA_BURN = 59594 + SPELL_CAUTERIZING_FLAMES = 59466, // Only in heroic + SPELL_FIREBOLT = 54235, + SPELL_FLAME_BREATH = 54282, + SPELL_LAVA_BURN = 54249 }; class boss_lavanthor : public CreatureScript { -public: - boss_lavanthor() : CreatureScript("boss_lavanthor") { } + public: + boss_lavanthor() : CreatureScript("boss_lavanthor") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_lavanthorAI>(creature); - } - - struct boss_lavanthorAI : public ScriptedAI - { - boss_lavanthorAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - uiFireboltTimer = 1000; - uiFlameBreathTimer = 5000; - uiLavaBurnTimer = 10000; - uiCauterizingFlamesTimer = 3000; - } - - uint32 uiFireboltTimer; - uint32 uiFlameBreathTimer; - uint32 uiLavaBurnTimer; - uint32 uiCauterizingFlamesTimer; - - InstanceScript* instance; - - void Reset() override - { - Initialize(); - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) override - { - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_LAVANTHOR_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* who) override + struct boss_lavanthorAI : public BossAI { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; + boss_lavanthorAI(Creature* creature) : BossAI(creature, DATA_LAVANTHOR) { } - if (me->Attack(who, true)) + void Reset() override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + BossAI::Reset(); } - } - - void MoveInLineOfSight(Unit* /*who*/) override { } + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiFireboltTimer <= diff) + void JustReachedHome() override { - DoCastVictim(SPELL_FIREBOLT); - uiFireboltTimer = urand(5000, 13000); - } else uiFireboltTimer -= diff; + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_LAVANTHOR); + } - if (uiFlameBreathTimer <= diff) + void JustDied(Unit* killer) override { - DoCastVictim(SPELL_FLAME_BREATH); - uiFlameBreathTimer = urand(10000, 15000); - } else uiFlameBreathTimer -= diff; + BossAI::JustDied(killer); + } - if (uiLavaBurnTimer <= diff) + void UpdateAI(uint32 diff) override { - DoCastVictim(SPELL_LAVA_BURN); - uiLavaBurnTimer = urand(15000, 23000); + if (!UpdateVictim()) + return; + + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); } - if (IsHeroic()) + void ScheduleTasks() override { - if (uiCauterizingFlamesTimer <= diff) + scheduler.Schedule(Seconds(1), [this](TaskContext task) { - DoCastVictim(SPELL_CAUTERIZING_FLAMES); - uiCauterizingFlamesTimer = urand(10000, 16000); - } else uiCauterizingFlamesTimer -= diff; - } + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true)) + DoCast(target, SPELL_FIREBOLT); + task.Repeat(Seconds(5), Seconds(13)); + }); - DoMeleeAttackIfReady(); - } + scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_FLAME_BREATH); + task.Repeat(Seconds(10), Seconds(15)); + }); - void JustDied(Unit* /*killer*/) override - { - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); - } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); + scheduler.Schedule(Seconds(10), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f)) + DoCast(target, SPELL_LAVA_BURN); + task.Repeat(Seconds(15), Seconds(23)); + }); + + if (IsHeroic()) + { + scheduler.Schedule(Seconds(3), [this](TaskContext task) + { + DoCastAOE(SPELL_CAUTERIZING_FLAMES); + task.Repeat(Seconds(10), Seconds(16)); + }); + } } - } - }; + }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<boss_lavanthorAI>(creature); + } }; void AddSC_boss_lavanthor() diff --git a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp index 9a6422dec32..41542416468 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp @@ -17,124 +17,183 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "violet_hold.h" -//Spells enum Spells { SPELL_CORROSIVE_SALIVA = 54527, - SPELL_OPTIC_LINK = 54396 + SPELL_OPTIC_LINK = 54396, + SPELL_RAY_OF_PAIN = 54438, + SPELL_RAY_OF_SUFFERING = 54442, + + // Visual + SPELL_OPTIC_LINK_LEVEL_1 = 54393, + SPELL_OPTIC_LINK_LEVEL_2 = 54394, + SPELL_OPTIC_LINK_LEVEL_3 = 54395 }; class boss_moragg : public CreatureScript { -public: - boss_moragg() : CreatureScript("boss_moragg") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_moraggAI>(creature); - } - - struct boss_moraggAI : public ScriptedAI - { - boss_moraggAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + public: + boss_moragg() : CreatureScript("boss_moragg") { } - void Initialize() + struct boss_moraggAI : public BossAI { - uiOpticLinkTimer = 10000; - uiCorrosiveSalivaTimer = 5000; - } + boss_moraggAI(Creature* creature) : BossAI(creature, DATA_MORAGG) { } - uint32 uiOpticLinkTimer; - uint32 uiCorrosiveSalivaTimer; + void Reset() override + { + BossAI::Reset(); + } - InstanceScript* instance; + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + } - void Reset() override - { - Initialize(); + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_MORAGG); + } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + } - void EnterCombat(Unit* /*who*/) override - { - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_MORAGG_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) return; - } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } - if (me->Attack(who, true)) + void ScheduleTasks() override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + scheduler.Async([this] + { + DoCast(me, SPELL_RAY_OF_PAIN); + DoCast(me, SPELL_RAY_OF_SUFFERING); + }); + + scheduler.Schedule(Seconds(15), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true)) + DoCast(target, SPELL_OPTIC_LINK); + task.Repeat(Seconds(25)); + }); + + scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_CORROSIVE_SALIVA); + task.Repeat(Seconds(10)); + }); } - } + }; - void MoveInLineOfSight(Unit* /*who*/) override { } + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<boss_moraggAI>(creature); + } +}; +class spell_moragg_ray : public SpellScriptLoader +{ + public: + spell_moragg_ray() : SpellScriptLoader("spell_moragg_ray") { } - void UpdateAI(uint32 diff) override + class spell_moragg_ray_AuraScript : public AuraScript { - //Return since we have no target - if (!UpdateVictim()) - return; + PrepareAuraScript(spell_moragg_ray_AuraScript); - if (uiOpticLinkTimer <= diff) + void OnPeriodic(AuraEffect const* aurEff) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_OPTIC_LINK); - uiOpticLinkTimer = 15000; - } else uiOpticLinkTimer -= diff; + PreventDefaultAction(); + + if (!GetTarget()->IsAIEnabled) + return; - if (uiCorrosiveSalivaTimer <= diff) + if (Unit* target = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true)) + { + uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; + GetTarget()->CastSpell(target, triggerSpell, TRIGGERED_FULL_MASK, nullptr, aurEff); + } + } + + void Register() override { - DoCastVictim(SPELL_CORROSIVE_SALIVA); - uiCorrosiveSalivaTimer = 10000; - } else uiCorrosiveSalivaTimer -= diff; + OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; - DoMeleeAttackIfReady(); + AuraScript* GetAuraScript() const override + { + return new spell_moragg_ray_AuraScript(); } - void JustDied(Unit* /*killer*/) override +}; + +class spell_moragg_optic_link : public SpellScriptLoader +{ +public: + spell_moragg_optic_link() : SpellScriptLoader("spell_moragg_optic_link") { } + + class spell_moragg_optic_link_AuraScript : public AuraScript + { + PrepareAuraScript(spell_moragg_optic_link_AuraScript); + + void OnPeriodic(AuraEffect const* aurEff) { - if (instance->GetData(DATA_WAVE_COUNT) == 6) + if (Unit* caster = GetCaster()) { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); + if (aurEff->GetTickNumber() >= 8) + caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_3, TRIGGERED_FULL_MASK, nullptr, aurEff); + + if (aurEff->GetTickNumber() >= 4) + caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_2, TRIGGERED_FULL_MASK, nullptr, aurEff); + + caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_1, TRIGGERED_FULL_MASK, nullptr, aurEff); } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) + } + + void OnUpdate(AuraEffect* aurEff) + { + switch (aurEff->GetTickNumber()) { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); + case 1: + aurEff->SetAmount(aurEff->GetAmount() + 250); // base amount is 500 + break; + case 4: + aurEff->SetAmount(aurEff->GetAmount() * 2); // goes to 1500 + break; + case 8: + aurEff->SetAmount(aurEff->GetAmount() * 2); // goes to 3000 + break; + default: + break; } } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_optic_link_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_moragg_optic_link_AuraScript::OnUpdate, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } }; + AuraScript* GetAuraScript() const override + { + return new spell_moragg_optic_link_AuraScript(); + } }; void AddSC_boss_moragg() { new boss_moragg(); + new spell_moragg_ray(); + new spell_moragg_optic_link(); } diff --git a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp index 833b06cfbff..93e74aaca71 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp @@ -17,292 +17,275 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" -#include "violet_hold.h" +#include "SpellInfo.h" +#include "SpellScript.h" #include "Player.h" +#include "violet_hold.h" + +/* + * TODO: + * - Implement Ethereal Summon Target + */ enum Spells { SPELL_ARCANE_BARRAGE_VOLLEY = 54202, - SPELL_ARCANE_BARRAGE_VOLLEY_H = 59483, SPELL_ARCANE_BUFFET = 54226, - SPELL_ARCANE_BUFFET_H = 59485, - SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102, - SPELL_SUMMON_ETHEREAL_SPHERE_2 = 54137, - SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138 + SPELL_SUMMON_TARGET_VISUAL = 54111 }; +static uint32 const EtherealSphereCount = 3; +static uint32 const EtherealSphereSummonSpells[EtherealSphereCount] = { 54102, 54137, 54138 }; +static uint32 const EtherealSphereHeroicSummonSpells[EtherealSphereCount] = { 54102, 54137, 54138 }; + enum NPCs { NPC_ETHEREAL_SPHERE = 29271, - //NPC_ETHEREAL_SPHERE2 = 32582, // heroic only? + NPC_ETHEREAL_SPHERE2 = 32582, + NPC_ETHEREAL_SUMMON_TARGET = 29276 }; enum CreatureSpells { SPELL_ARCANE_POWER = 54160, H_SPELL_ARCANE_POWER = 59474, + SPELL_MAGIC_PULL = 50770, SPELL_SUMMON_PLAYERS = 54164, - SPELL_POWER_BALL_VISUAL = 54141 + SPELL_POWER_BALL_VISUAL = 54141, + SPELL_POWER_BALL_DAMAGE_TRIGGER = 54207 }; enum Yells { + // Xevozz SAY_AGGRO = 0, SAY_SLAY = 1, SAY_DEATH = 2, SAY_SPAWN = 3, SAY_CHARGED = 4, SAY_REPEAT_SUMMON = 5, - SAY_SUMMON_ENERGY = 6 + SAY_SUMMON_ENERGY = 6, + + // Ethereal Sphere + SAY_ETHEREAL_SPHERE_SUMMON = 0 }; -class boss_xevozz : public CreatureScript +enum SphereActions { -public: - boss_xevozz() : CreatureScript("boss_xevozz") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_xevozzAI>(creature); - } + ACTION_SUMMON = 1, +}; - struct boss_xevozzAI : public ScriptedAI - { - boss_xevozzAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } +class boss_xevozz : public CreatureScript +{ + public: + boss_xevozz() : CreatureScript("boss_xevozz") { } - void Initialize() + struct boss_xevozzAI : public BossAI { - uiSummonEtherealSphere_Timer = urand(10000, 12000); - uiArcaneBarrageVolley_Timer = urand(20000, 22000); - uiArcaneBuffet_Timer = uiSummonEtherealSphere_Timer + urand(5000, 6000); - } + boss_xevozzAI(Creature* creature) : BossAI(creature, DATA_XEVOZZ) { } - InstanceScript* instance; - - uint32 uiSummonEtherealSphere_Timer; - uint32 uiArcaneBarrageVolley_Timer; - uint32 uiArcaneBuffet_Timer; + void Reset() override + { + BossAI::Reset(); + } - void Reset() override - { - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); + } - Initialize(); - DespawnSphere(); - } + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_XEVOZZ); + } - void DespawnSphere() - { - std::list<Creature*> assistList; - GetCreatureListWithEntryInGrid(assistList, me, NPC_ETHEREAL_SPHERE, 150.0f); + void JustSummoned(Creature* summon) override + { + BossAI::JustSummoned(summon); + summon->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f); + } - if (assistList.empty()) - return; + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - for (std::list<Creature*>::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + void JustDied(Unit* killer) override { - if (Creature* pSphere = *iter) - pSphere->Kill(pSphere, false); + BossAI::JustDied(killer); + Talk(SAY_DEATH); } - } - void JustSummoned(Creature* summoned) override - { - summoned->SetSpeed(MOVE_RUN, 0.5f); - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + void SpellHit(Unit* /*who*/, SpellInfo const* spell) override { - summoned->AddThreat(target, 0.00f); - summoned->AI()->AttackStart(target); + if (spell->Id == SPELL_ARCANE_POWER || spell->Id == H_SPELL_ARCANE_POWER) + Talk(SAY_SUMMON_ENERGY); } - } - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } - if (me->Attack(who, true)) + void ScheduleTasks() override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + scheduler.Schedule(Seconds(8), Seconds(10), [this](TaskContext task) + { + DoCastAOE(SPELL_ARCANE_BARRAGE_VOLLEY); + task.Repeat(Seconds(8), Seconds(10)); + }); + + scheduler.Schedule(Seconds(10), Seconds(11), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true)) + DoCast(target, SPELL_ARCANE_BUFFET); + task.Repeat(Seconds(15), Seconds(20)); + }); + + scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + Talk(SAY_REPEAT_SUMMON); + + std::list<uint8> summonSpells = { 0, 1, 2 }; + + uint8 spell = Trinity::Containers::SelectRandomContainerElement(summonSpells); + DoCast(me, EtherealSphereSummonSpells[spell]); + summonSpells.remove(spell); + + if (IsHeroic()) + { + spell = Trinity::Containers::SelectRandomContainerElement(summonSpells); + task.Schedule(Milliseconds(2500), [this, spell](TaskContext /*task*/) + { + DoCast(me, EtherealSphereHeroicSummonSpells[spell]); + }); + } + + task.Schedule(Seconds(33), Seconds(35), [this](TaskContext /*task*/) + { + DummyEntryCheckPredicate pred; + summons.DoAction(ACTION_SUMMON, pred); + }); + + task.Repeat(Seconds(45), Seconds(47)); + }); } - } + }; - void EnterCombat(Unit* /*who*/) override + CreatureAI* GetAI(Creature* creature) const override { - Talk(SAY_AGGRO); - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_XEVOZZ_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + return GetVioletHoldAI<boss_xevozzAI>(creature); } +}; - void MoveInLineOfSight(Unit* /*who*/) override { } - +class npc_ethereal_sphere : public CreatureScript +{ + public: + npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { } - void UpdateAI(uint32 uiDiff) override + struct npc_ethereal_sphereAI : public ScriptedAI { - //Return since we have no target - if (!UpdateVictim()) - return; + npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature) + { + instance = creature->GetInstanceScript(); + } - if (uiArcaneBarrageVolley_Timer < uiDiff) + void Reset() override { - DoCast(me, SPELL_ARCANE_BARRAGE_VOLLEY); - uiArcaneBarrageVolley_Timer = urand(20000, 22000); + scheduler.CancelAll(); + ScheduledTasks(); + + DoCast(me, SPELL_POWER_BALL_VISUAL); + DoCast(me, SPELL_POWER_BALL_DAMAGE_TRIGGER); + + me->DespawnOrUnsummon(40000); } - else uiArcaneBarrageVolley_Timer -= uiDiff; - if (uiArcaneBuffet_Timer) + void DoAction(int32 action) override { - if (uiArcaneBuffet_Timer < uiDiff) + if (action == ACTION_SUMMON) { - DoCastVictim(SPELL_ARCANE_BUFFET); - uiArcaneBuffet_Timer = 0; + Talk(SAY_ETHEREAL_SPHERE_SUMMON); + DoCastAOE(SPELL_SUMMON_PLAYERS); } - else uiArcaneBuffet_Timer -= uiDiff; } - if (uiSummonEtherealSphere_Timer < uiDiff) + void UpdateAI(uint32 diff) override { - Talk(SAY_SPAWN); - DoCast(me, SPELL_SUMMON_ETHEREAL_SPHERE_1); - if (IsHeroic()) // extra one for heroic - me->SummonCreature(NPC_ETHEREAL_SPHERE, me->GetPositionX() - 5 + rand32() % 10, me->GetPositionY() - 5 + rand32() % 10, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 40000); - - uiSummonEtherealSphere_Timer = urand(45000, 47000); - uiArcaneBuffet_Timer = urand(5000, 6000); + scheduler.Update(diff); } - else uiSummonEtherealSphere_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - DespawnSphere(); - - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); - } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) + void ScheduledTasks() { - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - instance->SetData(DATA_WAVE_COUNT, 13); + scheduler.Schedule(Seconds(1), [this](TaskContext task) + { + if (Creature* xevozz = instance->GetCreature(DATA_XEVOZZ)) + { + if (me->IsWithinDist(xevozz, 3.0f)) + { + DoCastAOE(SPELL_ARCANE_POWER); + me->DespawnOrUnsummon(8000); + return; + } + } + task.Repeat(); + }); } - } - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - Talk(SAY_SLAY); - } - }; - -}; - -class npc_ethereal_sphere : public CreatureScript -{ -public: - npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { } + private: + InstanceScript* instance; + TaskScheduler scheduler; + }; - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_ethereal_sphereAI>(creature); - } - - struct npc_ethereal_sphereAI : public ScriptedAI - { - npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() + CreatureAI* GetAI(Creature* creature) const override { - uiSummonPlayers_Timer = urand(33000, 35000); - uiRangeCheck_Timer = 1000; + return GetVioletHoldAI<npc_ethereal_sphereAI>(creature); } +}; - InstanceScript* instance; - - uint32 uiSummonPlayers_Timer; - uint32 uiRangeCheck_Timer; - - void Reset() override - { - Initialize(); - } +class spell_xevozz_summon_players : public SpellScriptLoader +{ + public: + spell_xevozz_summon_players() : SpellScriptLoader("spell_xevozz_summon_players") { } - void UpdateAI(uint32 uiDiff) override + class spell_xevozz_summon_players_SpellScript : public SpellScript { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!me->HasAura(SPELL_POWER_BALL_VISUAL)) - DoCast(me, SPELL_POWER_BALL_VISUAL); + PrepareSpellScript(spell_xevozz_summon_players_SpellScript); - if (uiRangeCheck_Timer < uiDiff) + bool Validate(SpellInfo const* /*spellInfo*/) override { - if (Creature* pXevozz = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_XEVOZZ))) - { - float fDistance = me->GetDistance2d(pXevozz); - if (fDistance <= 3) - DoCast(pXevozz, SPELL_ARCANE_POWER); - else - DoCast(me, 35845); //Is it blizzlike? - } - uiRangeCheck_Timer = 1000; + if (!sSpellMgr->GetSpellInfo(SPELL_MAGIC_PULL)) + return false; + return true; } - else uiRangeCheck_Timer -= uiDiff; - if (uiSummonPlayers_Timer < uiDiff) + void HandleScript(SpellEffIndex /*effIndex*/) { - DoCast(me, SPELL_SUMMON_PLAYERS); // not working right - - Map* map = me->GetMap(); - if (map && map->IsDungeon()) - { - Map::PlayerList const &PlayerList = map->GetPlayers(); - - if (!PlayerList.isEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->GetSource()->IsAlive()) - DoTeleportPlayer(i->GetSource(), me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), i->GetSource()->GetOrientation()); - } + GetCaster()->CastSpell(GetHitUnit(), SPELL_MAGIC_PULL, true); + } - uiSummonPlayers_Timer = urand(33000, 35000); + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_xevozz_summon_players_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); } - else uiSummonPlayers_Timer -= uiDiff; - } - }; + }; + SpellScript* GetSpellScript() const override + { + return new spell_xevozz_summon_players_SpellScript(); + } }; void AddSC_boss_xevozz() { new boss_xevozz(); new npc_ethereal_sphere(); + new spell_xevozz_summon_players(); } diff --git a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp index 90fd936e853..14d7b5fcd95 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp @@ -22,15 +22,13 @@ enum Spells { SPELL_SHROUD_OF_DARKNESS = 54524, - H_SPELL_SHROUD_OF_DARKNESS = 59745, SPELL_SUMMON_VOID_SENTRY = 54369, SPELL_VOID_SHIFT = 54361, - H_SPELL_VOID_SHIFT = 59743, -}; - -enum Creatures -{ - NPC_VOID_SENTRY = 29364 + SPELL_VOID_SHIFTED = 54343, + SPELL_ZURAMAT_ADD = 54341, + SPELL_ZURAMAT_ADD_2 = 54342, + SPELL_ZURAMAT_ADD_DUMMY = 54351, + SPELL_SUMMON_VOID_SENTRY_BALL = 58650 }; enum Yells @@ -45,160 +43,172 @@ enum Yells enum Misc { + ACTION_DESPAWN_VOID_SENTRY_BALL = 1, DATA_VOID_DANCE = 2153 }; class boss_zuramat : public CreatureScript { -public: - boss_zuramat() : CreatureScript("boss_zuramat") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_zuramatAI>(creature); - } - - struct boss_zuramatAI : public ScriptedAI - { - boss_zuramatAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + public: + boss_zuramat() : CreatureScript("boss_zuramat") { } - void Initialize() + struct boss_zuramatAI : public BossAI { - SpellShroudOfDarknessTimer = 22000; - SpellVoidShiftTimer = 15000; - SpellSummonVoidTimer = 12000; - voidDance = true; - } - - InstanceScript* instance; + boss_zuramatAI(Creature* creature) : BossAI(creature, DATA_ZURAMAT) + { + Initialize(); + } - uint32 SpellVoidShiftTimer; - uint32 SpellSummonVoidTimer; - uint32 SpellShroudOfDarknessTimer; - bool voidDance; + void Initialize() + { + _voidDance = true; + } - void Reset() override - { - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + void Reset() override + { + BossAI::Reset(); + Initialize(); + } - Initialize(); - } + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); + } - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_ZURAMAT); + } - if (me->Attack(who, true)) + void SummonedCreatureDies(Creature* summon, Unit* /*who*/) override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + if (summon->GetEntry() == NPC_VOID_SENTRY) + _voidDance = false; } - } - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_ZURAMAT_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - } + void SummonedCreatureDespawn(Creature* summon) override + { + if (summon->GetEntry() == NPC_VOID_SENTRY) + summon->AI()->DoAction(ACTION_DESPAWN_VOID_SENTRY_BALL); + BossAI::SummonedCreatureDespawn(summon); + } - void MoveInLineOfSight(Unit* /*who*/) override { } + uint32 GetData(uint32 type) const override + { + if (type == DATA_VOID_DANCE) + return _voidDance ? 1 : 0; + return 0; + } - void UpdateAI(uint32 diff) override - { - //Return since we have no target - if (!UpdateVictim()) - return; + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } - if (SpellSummonVoidTimer <= diff) + void KilledUnit(Unit* victim) override { - DoCastVictim(SPELL_SUMMON_VOID_SENTRY, false); - SpellSummonVoidTimer = 20000; - } else SpellSummonVoidTimer -=diff; + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - if (SpellVoidShiftTimer <= diff) + void UpdateAI(uint32 diff) override { - if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(unit, SPELL_VOID_SHIFT); - SpellVoidShiftTimer = 20000; - } else SpellVoidShiftTimer -=diff; + if (!UpdateVictim()) + return; - if (SpellShroudOfDarknessTimer <= diff) + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } + + void ScheduleTasks() override { - DoCastVictim(SPELL_SHROUD_OF_DARKNESS); - SpellShroudOfDarknessTimer = 20000; - } else SpellShroudOfDarknessTimer -=diff; + scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCast(me, SPELL_SUMMON_VOID_SENTRY); + task.Repeat(Seconds(7), Seconds(10)); + }); - DoMeleeAttackIfReady(); - } + scheduler.Schedule(Seconds(9), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, true)) + DoCast(target, SPELL_VOID_SHIFT); + task.Repeat(Seconds(15)); + }); - void SummonedCreatureDies(Creature* summoned, Unit* /*who*/) override - { - if (summoned->GetEntry() == NPC_VOID_SENTRY) - voidDance = false; - } + scheduler.Schedule(Seconds(18), Seconds(20), [this](TaskContext task) + { + DoCast(me, SPELL_SHROUD_OF_DARKNESS); + task.Repeat(Seconds(18), Seconds(20)); + }); + } - uint32 GetData(uint32 type) const override - { - if (type == DATA_VOID_DANCE) - return voidDance ? 1 : 0; + private: + bool _voidDance; + }; - return 0; + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<boss_zuramatAI>(creature); } +}; + +class npc_void_sentry : public CreatureScript +{ + public: + npc_void_sentry() : CreatureScript("npc_void_sentry") { } - void JustDied(Unit* /*killer*/) override + struct npc_void_sentryAI : public ScriptedAI { - Talk(SAY_DEATH); + npc_void_sentryAI(Creature* creature) : ScriptedAI(creature), _summons(creature) + { + me->SetReactState(REACT_PASSIVE); + } - if (instance->GetData(DATA_WAVE_COUNT) == 6) + void IsSummonedBy(Unit* /*summoner*/) override { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); + me->CastSpell(me, SPELL_SUMMON_VOID_SENTRY_BALL, true); } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) + + void JustSummoned(Creature* summon) override { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); + _summons.Summon(summon); + summon->SetReactState(REACT_PASSIVE); } - } - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; + void SummonedCreatureDespawn(Creature* summon) override + { + _summons.Despawn(summon); + } - Talk(SAY_SLAY); - } + void DoAction(int32 actionId) override + { + if (actionId == ACTION_DESPAWN_VOID_SENTRY_BALL) + _summons.DespawnAll(); + } + + void JustDied(Unit* /*killer*/) override + { + DoAction(ACTION_DESPAWN_VOID_SENTRY_BALL); + } - }; + private: + SummonList _summons; + }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_void_sentryAI>(creature); + } }; class achievement_void_dance : public AchievementCriteriaScript { public: - achievement_void_dance() : AchievementCriteriaScript("achievement_void_dance") - { - } + achievement_void_dance() : AchievementCriteriaScript("achievement_void_dance") { } bool OnCheck(Player* /*player*/, Unit* target) override { @@ -216,5 +226,6 @@ class achievement_void_dance : public AchievementCriteriaScript void AddSC_boss_zuramat() { new boss_zuramat(); + new npc_void_sentry(); new achievement_void_dance(); } diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp index ef9ad806c89..14c3ac58b1f 100644 --- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp @@ -18,803 +18,930 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "InstanceScript.h" +#include "WorldPacket.h" #include "violet_hold.h" #include "Player.h" -#include "TemporarySummon.h" -#define MAX_ENCOUNTER 3 +/* + * TODO: + * - replace bosses by dummy npcs also after grid unload + */ -/* Violet Hold encounters: -0 - First boss -1 - Second boss -2 - Cyanigosa*/ +Position const DefenseSystemLocation = { 1888.146f, 803.382f, 58.60389f, 3.071779f }; // sniff -/* Violet hold bosses: -1 - Moragg -2 - Erekem -3 - Ichoron -4 - Lavanthor -5 - Xevozz -6 - Zuramat -7 - Cyanigosa */ +Position const CyanigosaSpawnLocation = { 1922.109f, 804.4493f, 52.49254f, 3.176499f }; // sniff +Position const CyanigosaJumpLocation = { 1888.32f, 804.473f, 38.3578f, 0.0f }; // sniff -enum GameObjects +Position const SaboteurSpawnLocation = { 1886.251f, 803.0743f, 38.42326f, 3.211406f }; // sniff + +uint32 const PortalPositionsSize = 5; +Position const PortalPositions[PortalPositionsSize] = // sniff { - GO_MAIN_DOOR = 191723, - GO_XEVOZZ_DOOR = 191556, - GO_LAVANTHOR_DOOR = 191566, - GO_ICHORON_DOOR = 191722, - GO_ZURAMAT_DOOR = 191565, - GO_EREKEM_DOOR = 191564, - GO_EREKEM_GUARD_1_DOOR = 191563, - GO_EREKEM_GUARD_2_DOOR = 191562, - GO_MORAGG_DOOR = 191606, - GO_INTRO_ACTIVATION_CRYSTAL = 193615, - GO_ACTIVATION_CRYSTAL = 193611 + { 1877.523f, 850.1788f, 45.36822f, 4.34587f }, // 0 + { 1890.679f, 753.4202f, 48.771f, 1.675516f }, // 1 + { 1936.09f, 803.1875f, 54.09715f, 3.054326f }, // 2 + { 1858.243f, 770.2379f, 40.42146f, 0.9075712f }, // 3 + { 1907.288f, 831.1111f, 40.22015f, 3.560472f } // 4 }; -enum AzureSaboteurSpells +uint32 const PortalElitePositionsSize = 3; +Position const PortalElitePositions[PortalElitePositionsSize] = // sniff { - SABOTEUR_SHIELD_DISRUPTION = 58291, - SABOTEUR_SHIELD_EFFECT = 45775 + { 1911.281f, 800.9722f, 39.91673f, 3.01942f }, // 5 + { 1926.516f, 763.6616f, 52.35725f, 2.251475f }, // 6 + { 1922.464f, 847.0699f, 48.50161f, 3.961897f } // 7 }; -enum CrystalSpells +uint32 const PortalIntroPositionsSize = 5; +Position const PortalIntroPositions[PortalIntroPositionsSize] = // sniff { - SPELL_ARCANE_LIGHTNING = 57930 + { 1877.51f, 850.1042f, 44.65989f, 4.782202f }, // 0 - Intro + { 1890.637f, 753.4705f, 48.72239f, 1.710423f }, // 1 - Intro + { 1936.073f, 803.1979f, 53.37491f, 3.124139f }, // 2 - Intro + { 1886.545f, 803.2014f, 40.40931f, 3.159046f }, // 3 - Boss 1/2 + { 1924.096f, 804.3707f, 54.29256f, 3.228859f } // 4 - Boss 3 }; -const Position PortalLocation[] = +uint32 const EncouterPortalsCount = PortalPositionsSize + PortalElitePositionsSize; + +uint32 const MoraggPathSize = 3; +G3D::Vector3 const MoraggPath[MoraggPathSize] = // sniff { - {1877.51f, 850.104f, 44.6599f, 4.7822f }, // WP 1 - {1918.37f, 853.437f, 47.1624f, 4.12294f}, // WP 2 - {1936.07f, 803.198f, 53.3749f, 3.12414f}, // WP 3 - {1927.61f, 758.436f, 51.4533f, 2.20891f}, // WP 4 - {1890.64f, 753.471f, 48.7224f, 1.71042f}, // WP 5 - {1908.31f, 809.657f, 38.7037f, 3.08701f} // WP 6 + { 1893.895f, 728.1261f, 47.75016f }, + { 1892.997f, 738.4987f, 47.66684f }, + { 1889.76f, 758.1089f, 47.66684f } }; -const Position ArcaneSphere = {1887.060059f, 806.151001f, 61.321602f, 0.0f}; -const Position BossStartMove1 = {1894.684448f, 739.390503f, 47.668003f, 0.0f}; -const Position BossStartMove2 = {1875.173950f, 860.832703f, 43.333565f, 0.0f}; -const Position BossStartMove21 = {1858.854614f, 855.071411f, 43.333565f, 0.0f}; -const Position BossStartMove22 = {1891.926636f, 863.388977f, 43.333565f, 0.0f}; -const Position BossStartMove3 = {1916.138062f, 778.152222f, 35.772308f, 0.0f}; -const Position BossStartMove4 = {1853.618286f, 758.557617f, 38.657505f, 0.0f}; -const Position BossStartMove5 = {1906.683960f, 842.348022f, 38.637459f, 0.0f}; -const Position BossStartMove6 = {1928.207031f, 852.864441f, 47.200813f, 0.0f}; - -const Position CyanigosasSpawnLocation = {1930.281250f, 804.407715f, 52.410946f, 3.139621f}; -const Position MiddleRoomLocation = {1892.291260f, 805.696838f, 38.438862f, 3.139621f}; -const Position MiddleRoomPortalSaboLocation = {1896.622925f, 804.854126f, 38.504772f, 3.139621f}; - -//Cyanigosa's prefight event data -enum Yells +uint32 const ErekemPathSize = 3; +G3D::Vector3 const ErekemPath[ErekemPathSize] = // sniff { - CYANIGOSA_SAY_SPAWN = 0 + { 1871.456f, 871.0361f, 43.41524f }, + { 1874.948f, 859.5452f, 43.33349f }, + { 1877.245f, 851.967f, 43.3335f } }; -enum Spells +uint32 const ErekemGuardLeftPathSize = 3; +G3D::Vector3 const ErekemGuardLeftPath[ErekemGuardLeftPathSize] = // sniff { - CYANIGOSA_SPELL_TRANSFORM = 58668, - CYANIGOSA_BLUE_AURA = 47759, + { 1853.752f, 862.4528f, 43.41614f }, + { 1866.931f, 854.577f, 43.3335f }, + { 1872.973f, 850.7875f, 43.3335f } }; -class instance_violet_hold : public InstanceMapScript +uint32 const ErekemGuardRightPathSize = 3; +G3D::Vector3 const ErekemGuardRightPath[ErekemGuardRightPathSize] = // sniff { -public: - instance_violet_hold() : InstanceMapScript("instance_violet_hold", 608) { } + { 1892.418f, 872.2831f, 43.41563f }, + { 1885.639f, 859.0245f, 43.3335f }, + { 1882.432f, 852.2423f, 43.3335f } +}; - InstanceScript* GetInstanceScript(InstanceMap* map) const override - { - return new instance_violet_hold_InstanceMapScript(map); - } +uint32 const IchoronPathSize = 5; +G3D::Vector3 const IchoronPath[IchoronPathSize] = // sniff +{ + { 1942.041f, 749.5228f, 30.95229f }, + { 1930.571f, 762.9065f, 31.98814f }, + { 1923.657f, 770.6718f, 34.07256f }, + { 1910.631f, 784.4096f, 37.09015f }, + { 1906.595f, 788.3828f, 37.99429f } +}; - struct instance_violet_hold_InstanceMapScript : public InstanceScript - { - instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map) - { - SetHeaders(DataHeader); +uint32 const LavanthorPathSize = 3; +G3D::Vector3 const LavanthorPath[LavanthorPathSize] = // sniff +{ + { 1844.557f, 748.7083f, 38.74205f }, + { 1854.618f, 761.5295f, 38.65631f }, + { 1862.17f, 773.2255f, 38.74879f } +}; - uiRemoveNpc = 0; +uint32 const XevozzPathSize = 3; +G3D::Vector3 const XevozzPath[XevozzPathSize] = // sniff +{ + { 1908.417f, 845.8502f, 38.71947f }, + { 1905.557f, 841.3157f, 38.65529f }, + { 1899.453f, 832.533f, 38.70752f } +}; - uiDoorIntegrity = 100; +uint32 const ZuramatPathSize = 3; +G3D::Vector3 const ZuramatPath[ZuramatPathSize] = // sniff +{ + { 1934.151f, 860.9463f, 47.29499f }, + { 1927.085f, 852.1342f, 47.19214f }, + { 1923.226f, 847.3297f, 47.15541f } +}; - uiWaveCount = 0; - uiLocation = urand(0, 5); - uiFirstBoss = 0; - uiSecondBoss = 0; - uiCountErekemGuards = 0; - uiCountActivationCrystals = 0; - uiCyanigosaEventPhase = 1; +enum Yells +{ + SAY_CYANIGOSA_SPAWN = 3, + SAY_XEVOZZ_SPAWN = 3, + SAY_EREKEM_SPAWN = 3, + SAY_ICHORON_SPAWN = 3, + SAY_ZURAMAT_SPAWN = 3, - uiActivationTimer = 5000; - uiDoorSpellTimer = 2000; - uiCyanigosaEventTimer = 3 * IN_MILLISECONDS; + SOUND_MORAGG_SPAWN = 10112 +}; - bActive = false; - bWiped = false; - bIsDoorSpellCast = false; - bCrystalActivated = false; - defenseless = true; - uiMainEventPhase = NOT_STARTED; +enum Spells +{ + SPELL_CYANIGOSA_TRANSFORM = 58668, + SPELL_CYANIGOSA_ARCANE_POWER_STATE = 49411, + SPELL_MORAGG_EMOTE_ROAR = 48350, + SPELL_LAVANTHOR_SPECIAL_UNARMED = 33334, + SPELL_ZURAMAT_COSMETIC_CHANNEL_OMNI = 57552 +}; - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } +ObjectData const creatureData[] = +{ + { NPC_XEVOZZ, DATA_XEVOZZ }, + { NPC_LAVANTHOR, DATA_LAVANTHOR }, + { NPC_ICHORON, DATA_ICHORON }, + { NPC_ZURAMAT, DATA_ZURAMAT }, + { NPC_EREKEM, DATA_EREKEM }, + { NPC_MORAGG, DATA_MORAGG }, + { NPC_CYANIGOSA, DATA_CYANIGOSA }, + { NPC_SINCLARI, DATA_SINCLARI }, + { NPC_SINCLARI_TRIGGER, DATA_SINCLARI_TRIGGER }, + { 0, 0 } // END +}; - ObjectGuid uiMoragg; - ObjectGuid uiErekem; - ObjectGuid uiErekemGuard[2]; - ObjectGuid uiIchoron; - ObjectGuid uiLavanthor; - ObjectGuid uiXevozz; - ObjectGuid uiZuramat; - ObjectGuid uiCyanigosa; - ObjectGuid uiSinclari; - - ObjectGuid uiMoraggCell; - ObjectGuid uiErekemCell; - ObjectGuid uiErekemLeftGuardCell; - ObjectGuid uiErekemRightGuardCell; - ObjectGuid uiIchoronCell; - ObjectGuid uiLavanthorCell; - ObjectGuid uiXevozzCell; - ObjectGuid uiZuramatCell; - ObjectGuid uiMainDoor; - ObjectGuid uiTeleportationPortal; - ObjectGuid uiSaboteurPortal; - - ObjectGuid uiActivationCrystal[4]; - - uint32 uiActivationTimer; - uint32 uiCyanigosaEventTimer; - uint32 uiDoorSpellTimer; - - GuidSet trashMobs; // to kill with crystal - - uint8 uiWaveCount; - uint8 uiLocation; - uint8 uiFirstBoss; - uint8 uiSecondBoss; - uint8 uiRemoveNpc; - - uint8 uiDoorIntegrity; - - uint16 m_auiEncounter[MAX_ENCOUNTER]; - uint8 uiCountErekemGuards; - uint8 uiCountActivationCrystals; - uint8 uiCyanigosaEventPhase; - uint8 uiMainEventPhase; // SPECIAL: pre event animations, IN_PROGRESS: event itself - - bool bActive; - bool bWiped; - bool bIsDoorSpellCast; - bool bCrystalActivated; - bool defenseless; - - std::list<uint8> NpcAtDoorCastingList; - - std::string str_data; - - bool IsEncounterInProgress() const override - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; +ObjectData const gameObjectData[] = +{ + { GO_EREKEM_GUARD_1_DOOR, DATA_EREKEM_LEFT_GUARD_CELL }, + { GO_EREKEM_GUARD_2_DOOR, DATA_EREKEM_RIGHT_GUARD_CELL }, + { GO_EREKEM_DOOR, DATA_EREKEM_CELL }, + { GO_ZURAMAT_DOOR, DATA_ZURAMAT_CELL }, + { GO_LAVANTHOR_DOOR, DATA_LAVANTHOR_CELL }, + { GO_MORAGG_DOOR, DATA_MORAGG_CELL }, + { GO_ICHORON_DOOR, DATA_ICHORON_CELL }, + { GO_XEVOZZ_DOOR, DATA_XEVOZZ_CELL }, + { GO_MAIN_DOOR, DATA_MAIN_DOOR }, + { 0, 0 } // END +}; - return false; - } +MinionData const minionData[] = +{ + { NPC_EREKEM_GUARD, DATA_EREKEM }, + { 0, 0, } // END +}; + +class instance_violet_hold : public InstanceMapScript +{ + public: + instance_violet_hold() : InstanceMapScript(VioletHoldScriptName, 608) { } - void OnCreatureCreate(Creature* creature) override + struct instance_violet_hold_InstanceMapScript : public InstanceScript { - switch (creature->GetEntry()) + instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map) { - case CREATURE_XEVOZZ: - uiXevozz = creature->GetGUID(); - break; - case CREATURE_LAVANTHOR: - uiLavanthor = creature->GetGUID(); - break; - case CREATURE_ICHORON: - uiIchoron = creature->GetGUID(); - break; - case CREATURE_ZURAMAT: - uiZuramat = creature->GetGUID(); - break; - case CREATURE_EREKEM: - uiErekem = creature->GetGUID(); - break; - case CREATURE_EREKEM_GUARD: - if (uiCountErekemGuards < 2) - { - uiErekemGuard[uiCountErekemGuards++] = creature->GetGUID(); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - } - break; - case CREATURE_MORAGG: - uiMoragg = creature->GetGUID(); - break; - case CREATURE_CYANIGOSA: - uiCyanigosa = creature->GetGUID(); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - break; - case CREATURE_SINCLARI: - uiSinclari = creature->GetGUID(); - break; + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadObjectData(creatureData, gameObjectData); + LoadMinionData(minionData); + + FirstBossId = 0; + SecondBossId = 0; + + DoorIntegrity = 100; + WaveCount = 0; + EventState = NOT_STARTED; + + LastPortalLocation = urand(0, EncouterPortalsCount - 1); + + Defenseless = true; } - /* - BEWARE - SHIT. - if (creature->GetGUID() == uiFirstBoss || creature->GetGUID() == uiSecondBoss) + void OnCreatureCreate(Creature* creature) override { - creature->AllLootRemovedFromCorpse(); - creature->RemoveLootMode(1); + InstanceScript::OnCreatureCreate(creature); + + switch (creature->GetEntry()) + { + case NPC_EREKEM_GUARD: + for (uint8 i = 0; i < ErekemGuardCount; ++i) + if (ErekemGuardGUIDs[i].IsEmpty()) + { + ErekemGuardGUIDs[i] = creature->GetGUID(); + break; + } + break; + default: + break; + } } - */ - } - void OnGameObjectCreate(GameObject* go) override - { - switch (go->GetEntry()) + void OnCreatureRemove(Creature* creature) override { - case GO_EREKEM_GUARD_1_DOOR: - uiErekemLeftGuardCell = go->GetGUID(); - break; - case GO_EREKEM_GUARD_2_DOOR: - uiErekemRightGuardCell = go->GetGUID(); - break; - case GO_EREKEM_DOOR: - uiErekemCell = go->GetGUID(); - break; - case GO_ZURAMAT_DOOR: - uiZuramatCell = go->GetGUID(); - break; - case GO_LAVANTHOR_DOOR: - uiLavanthorCell = go->GetGUID(); - break; - case GO_MORAGG_DOOR: - uiMoraggCell = go->GetGUID(); - break; - case GO_ICHORON_DOOR: - uiIchoronCell = go->GetGUID(); - break; - case GO_XEVOZZ_DOOR: - uiXevozzCell = go->GetGUID(); - break; - case GO_MAIN_DOOR: - uiMainDoor = go->GetGUID(); - break; - case GO_ACTIVATION_CRYSTAL: - if (uiCountActivationCrystals < 4) - uiActivationCrystal[uiCountActivationCrystals++] = go->GetGUID(); - break; + InstanceScript::OnCreatureRemove(creature); + + switch (creature->GetEntry()) + { + case NPC_EREKEM_GUARD: + for (uint8 i = 0; i < ErekemGuardCount; ++i) + if (ErekemGuardGUIDs[i] == creature->GetGUID()) + { + ErekemGuardGUIDs[i].Clear(); + break; + } + break; + default: + break; + } } - } - void SetData(uint32 type, uint32 data) override - { - switch (type) + void OnGameObjectCreate(GameObject* go) override { - case DATA_1ST_BOSS_EVENT: - UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, CREATURE_EREKEM, NULL); - m_auiEncounter[0] = data; - if (data == DONE) - SaveToDB(); - break; - case DATA_2ND_BOSS_EVENT: - UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, CREATURE_MORAGG, NULL); - m_auiEncounter[1] = data; - if (data == DONE) - SaveToDB(); - break; - case DATA_CYANIGOSA_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) - { - SaveToDB(); - uiMainEventPhase = DONE; - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_ACTIVE); - } - break; - case DATA_WAVE_COUNT: - uiWaveCount = data; - bActive = true; - break; - case DATA_REMOVE_NPC: - uiRemoveNpc = data; - break; - case DATA_PORTAL_LOCATION: - uiLocation = (uint8)data; - break; - case DATA_DOOR_INTEGRITY: - uiDoorIntegrity = data; - defenseless = false; - DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, uiDoorIntegrity); - break; - case DATA_NPC_PRESENCE_AT_DOOR_ADD: - NpcAtDoorCastingList.push_back(data); - break; - case DATA_NPC_PRESENCE_AT_DOOR_REMOVE: - if (!NpcAtDoorCastingList.empty()) - NpcAtDoorCastingList.pop_back(); - break; - case DATA_MAIN_DOOR: - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - { - switch (data) - { - case GO_STATE_ACTIVE: - pMainDoor->SetGoState(GO_STATE_ACTIVE); - break; - case GO_STATE_READY: - pMainDoor->SetGoState(GO_STATE_READY); - break; - case GO_STATE_ACTIVE_ALTERNATIVE: - pMainDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + InstanceScript::OnGameObjectCreate(go); + + switch (go->GetEntry()) + { + case GO_ACTIVATION_CRYSTAL: + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (ActivationCrystalGUIDs[i].IsEmpty()) + { + ActivationCrystalGUIDs[i] = go->GetGUID(); break; - } - } - break; - case DATA_START_BOSS_ENCOUNTER: - switch (uiWaveCount) - { - case 6: - StartBossEncounter(uiFirstBoss); - break; - case 12: - StartBossEncounter(uiSecondBoss); - break; - } - break; - case DATA_ACTIVATE_CRYSTAL: - ActivateCrystal(); - break; - case DATA_MAIN_EVENT_PHASE: - uiMainEventPhase = data; - if (data == IN_PROGRESS) // Start event - { - if (GameObject* mainDoor = instance->GetGameObject(uiMainDoor)) - mainDoor->SetGoState(GO_STATE_READY); - uiWaveCount = 1; - bActive = true; - for (int i = 0; i < 4; ++i) - if (GameObject* crystal = instance->GetGameObject(uiActivationCrystal[i])) - crystal->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - uiRemoveNpc = 0; // might not have been reset after a wipe on a boss. - } - break; + } + break; + default: + break; + } } - } - void SetGuidData(uint32 type, ObjectGuid data) override - { - switch (type) + void OnGameObjectRemove(GameObject* go) override { - case DATA_ADD_TRASH_MOB: - trashMobs.insert(data); - break; - case DATA_DEL_TRASH_MOB: - trashMobs.erase(data); - break; + InstanceScript::OnGameObjectRemove(go); + + switch (go->GetEntry()) + { + case GO_ACTIVATION_CRYSTAL: + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (ActivationCrystalGUIDs[i] == go->GetGUID()) + { + ActivationCrystalGUIDs[i].Clear(); + break; + } + break; + default: + break; + } } - } - uint32 GetData(uint32 type) const override - { - switch (type) + void FillInitialWorldStates(WorldPacket& data) override { - case DATA_1ST_BOSS_EVENT: return m_auiEncounter[0]; - case DATA_2ND_BOSS_EVENT: return m_auiEncounter[1]; - case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2]; - case DATA_WAVE_COUNT: return uiWaveCount; - case DATA_REMOVE_NPC: return uiRemoveNpc; - case DATA_PORTAL_LOCATION: return uiLocation; - case DATA_DOOR_INTEGRITY: return uiDoorIntegrity; - case DATA_NPC_PRESENCE_AT_DOOR: return NpcAtDoorCastingList.size(); - case DATA_FIRST_BOSS: return uiFirstBoss; - case DATA_SECOND_BOSS: return uiSecondBoss; - case DATA_MAIN_EVENT_PHASE: return uiMainEventPhase; - case DATA_DEFENSELESS: return defenseless ? 1 : 0; + data << uint32(WORLD_STATE_VH_SHOW) << uint32(EventState == IN_PROGRESS ? 1 : 0); + data << uint32(WORLD_STATE_VH_PRISON_STATE) << uint32(DoorIntegrity); + data << uint32(WORLD_STATE_VH_WAVE_COUNT) << uint32(WaveCount); } - return 0; - } - - ObjectGuid GetGuidData(uint32 identifier) const override - { - switch (identifier) + bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override { - case DATA_MORAGG: return uiMoragg; - case DATA_EREKEM: return uiErekem; - case DATA_EREKEM_GUARD_1: return uiErekemGuard[0]; - case DATA_EREKEM_GUARD_2: return uiErekemGuard[1]; - case DATA_ICHORON: return uiIchoron; - case DATA_LAVANTHOR: return uiLavanthor; - case DATA_XEVOZZ: return uiXevozz; - case DATA_ZURAMAT: return uiZuramat; - case DATA_CYANIGOSA: return uiCyanigosa; - case DATA_MORAGG_CELL: return uiMoraggCell; - case DATA_EREKEM_CELL: return uiErekemCell; - case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell; - case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell; - case DATA_ICHORON_CELL: return uiIchoronCell; - case DATA_LAVANTHOR_CELL: return uiLavanthorCell; - case DATA_XEVOZZ_CELL: return uiXevozzCell; - case DATA_ZURAMAT_CELL: return uiZuramatCell; - case DATA_MAIN_DOOR: return uiMainDoor; - case DATA_SINCLARI: return uiSinclari; - case DATA_TELEPORTATION_PORTAL: return uiTeleportationPortal; - case DATA_SABOTEUR_PORTAL: return uiSaboteurPortal; + if (_SkipCheckRequiredBosses(player)) + return true; + + switch (bossId) + { + case DATA_MORAGG: + case DATA_EREKEM: + case DATA_ICHORON: + case DATA_LAVANTHOR: + case DATA_XEVOZZ: + case DATA_ZURAMAT: + /// old code used cell door state to check this + if (!(WaveCount == 6 && FirstBossId == bossId) && !(WaveCount == 12 && SecondBossId == bossId)) + return false; + break; + case DATA_CYANIGOSA: + if (WaveCount < 18) + return false; + break; + default: + break; + } + + return true; } - return ObjectGuid::Empty; - } + bool SetBossState(uint32 type, EncounterState state) override + { + if (!InstanceScript::SetBossState(type, state)) + return false; - void SpawnPortal() - { - SetData(DATA_PORTAL_LOCATION, (GetData(DATA_PORTAL_LOCATION) + urand(1, 5))%6); - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) - if (Creature* portal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, PortalLocation[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN)) - uiTeleportationPortal = portal->GetGUID(); - } + switch (type) + { + case DATA_1ST_BOSS: + if (state == DONE) + UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_EREKEM, nullptr); + break; + case DATA_2ND_BOSS: + if (state == DONE) + UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_MORAGG, nullptr); + break; + case DATA_CYANIGOSA: + if (state == DONE) + SetData(DATA_MAIN_EVENT_STATE, DONE); + break; + case DATA_MORAGG: + case DATA_EREKEM: + case DATA_ICHORON: + case DATA_LAVANTHOR: + case DATA_XEVOZZ: + case DATA_ZURAMAT: + // this won't work correctly because bossstate was initializd with TO_BE_DECIDED + if (WaveCount == 6) + SetBossState(DATA_1ST_BOSS, state); + else if (WaveCount == 12) + SetBossState(DATA_2ND_BOSS, state); + + if (state == DONE) + SetData(DATA_WAVE_COUNT, WaveCount + 1); + break; + default: + break; + } - void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true) - { - Creature* pBoss = NULL; + return true; + } - switch (uiBoss) + void SetData(uint32 type, uint32 data) override { - case BOSS_MORAGG: - HandleGameObject(uiMoraggCell, bForceRespawn); - pBoss = instance->GetCreature(uiMoragg); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove1); - break; - case BOSS_EREKEM: - HandleGameObject(uiErekemCell, bForceRespawn); - HandleGameObject(uiErekemRightGuardCell, bForceRespawn); - HandleGameObject(uiErekemLeftGuardCell, bForceRespawn); - - pBoss = instance->GetCreature(uiErekem); - - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove2); - - if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0])) - { - if (bForceRespawn) - pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - else - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - pGuard1->GetMotionMaster()->MovePoint(0, BossStartMove21); - } + switch (type) + { + case DATA_WAVE_COUNT: + WaveCount = data; + if (WaveCount) + { + Scheduler.Schedule(Seconds(IsBossWave(WaveCount - 1) ? 45 : 5), [this](TaskContext /*task*/) + { + AddWave(); + }); + } + break; + case DATA_DOOR_INTEGRITY: + DoorIntegrity = data; + Defenseless = false; + DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, DoorIntegrity); + break; + case DATA_START_BOSS_ENCOUNTER: + switch (WaveCount) + { + case 6: + StartBossEncounter(FirstBossId); + break; + case 12: + StartBossEncounter(SecondBossId); + break; + } + break; + case DATA_MAIN_EVENT_STATE: + EventState = data; + if (data == IN_PROGRESS) // Start event + { + DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, WaveCount); + DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, DoorIntegrity); + DoUpdateWorldState(WORLD_STATE_VH_SHOW, 1); - if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1])) - { - if (bForceRespawn) - pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - else - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - pGuard2->GetMotionMaster()->MovePoint(0, BossStartMove22); - } - break; - case BOSS_ICHORON: - HandleGameObject(uiIchoronCell, bForceRespawn); - pBoss = instance->GetCreature(uiIchoron); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove3); - break; - case BOSS_LAVANTHOR: - HandleGameObject(uiLavanthorCell, bForceRespawn); - pBoss = instance->GetCreature(uiLavanthor); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove4); - break; - case BOSS_XEVOZZ: - HandleGameObject(uiXevozzCell, bForceRespawn); - pBoss = instance->GetCreature(uiXevozz); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove5); - break; - case BOSS_ZURAMAT: - HandleGameObject(uiZuramatCell, bForceRespawn); - pBoss = instance->GetCreature(uiZuramat); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove6); - break; + WaveCount = 1; + Scheduler.Async(std::bind(&instance_violet_hold_InstanceMapScript::AddWave, this)); + + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (GameObject* crystal = instance->GetGameObject(ActivationCrystalGUIDs[i])) + crystal->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + else if (data == NOT_STARTED) + { + if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) + { + mainDoor->SetGoState(GO_STATE_ACTIVE); + mainDoor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + + DoUpdateWorldState(WORLD_STATE_VH_SHOW, 0); + DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, WaveCount); + DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, DoorIntegrity); + + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (GameObject* crystal = instance->GetGameObject(ActivationCrystalGUIDs[i])) + crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + else if (data == DONE) + { + if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) + { + mainDoor->SetGoState(GO_STATE_ACTIVE); + mainDoor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + + DoUpdateWorldState(WORLD_STATE_VH_SHOW, 0); + + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (GameObject* crystal = instance->GetGameObject(ActivationCrystalGUIDs[i])) + crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + sinclari->AI()->DoAction(ACTION_SINCLARI_OUTRO); + } + break; + case DATA_HANDLE_CELLS: + HandleCells(data, false); + break; + } } - // generic boss state changes - if (pBoss) + uint32 GetData(uint32 type) const override { - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - pBoss->SetReactState(REACT_AGGRESSIVE); - - if (!bForceRespawn) + switch (type) { - if (pBoss->isDead()) - { - // respawn but avoid to be looted again - pBoss->Respawn(); - pBoss->RemoveLootMode(1); - } - pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - uiWaveCount = 0; + case DATA_1ST_BOSS: + return FirstBossId; + case DATA_2ND_BOSS: + return SecondBossId; + case DATA_MAIN_EVENT_STATE: + return EventState; + case DATA_WAVE_COUNT: + return WaveCount; + case DATA_DOOR_INTEGRITY: + return DoorIntegrity; + case DATA_DEFENSELESS: + return Defenseless ? 1 : 0; + default: + break; } + + return 0; } - } - void AddWave() - { - DoUpdateWorldState(WORLD_STATE_VH, 1); - DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, uiWaveCount); + ObjectGuid GetGuidData(uint32 type) const override + { + switch (type) + { + case DATA_EREKEM_GUARD_1: + case DATA_EREKEM_GUARD_2: + return ErekemGuardGUIDs[type - DATA_EREKEM_GUARD_1]; + default: + break; + } - switch (uiWaveCount) + return InstanceScript::GetGuidData(type); + } + + void SpawnPortal() { - case 6: - if (uiFirstBoss == 0) - uiFirstBoss = urand(1, 6); - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) + LastPortalLocation = (LastPortalLocation + urand(1, EncouterPortalsCount - 1)) % (EncouterPortalsCount); + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + { + if (LastPortalLocation < PortalPositionsSize) { - if (Creature* pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN)) - uiSaboteurPortal = pPortal->GetGUID(); - if (Creature* pAzureSaboteur = pSinclari->SummonCreature(CREATURE_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN)) - pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false); + if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalPositions[LastPortalLocation], TEMPSUMMON_CORPSE_DESPAWN)) + portal->AI()->SetData(DATA_PORTAL_LOCATION, LastPortalLocation); } - break; - case 12: - if (uiSecondBoss == 0) - do - { - uiSecondBoss = urand(1, 6); - } while (uiSecondBoss == uiFirstBoss); - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) + else { - if (Creature* pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN)) - uiSaboteurPortal = pPortal->GetGUID(); - if (Creature* pAzureSaboteur = pSinclari->SummonCreature(CREATURE_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN)) - pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false); + if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL_ELITE, PortalElitePositions[LastPortalLocation - PortalPositionsSize], TEMPSUMMON_CORPSE_DESPAWN)) + portal->AI()->SetData(DATA_PORTAL_LOCATION, LastPortalLocation); } - break; - case 18: - { - Creature* pSinclari = instance->GetCreature(uiSinclari); - if (pSinclari) - pSinclari->SummonCreature(CREATURE_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN); - break; } - case 1: + } + + void HandleCells(uint8 bossId, bool open = true) + { + switch (bossId) { - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_READY); - DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); - // no break + case DATA_MORAGG: + HandleGameObject(GetObjectGuid(DATA_MORAGG_CELL), open); + break; + case DATA_EREKEM: + HandleGameObject(GetObjectGuid(DATA_EREKEM_CELL), open); + HandleGameObject(GetObjectGuid(DATA_EREKEM_LEFT_GUARD_CELL), open); + HandleGameObject(GetObjectGuid(DATA_EREKEM_RIGHT_GUARD_CELL), open); + break; + case DATA_ICHORON: + HandleGameObject(GetObjectGuid(DATA_ICHORON_CELL), open); + break; + case DATA_LAVANTHOR: + HandleGameObject(GetObjectGuid(DATA_LAVANTHOR_CELL), open); + break; + case DATA_XEVOZZ: + HandleGameObject(GetObjectGuid(DATA_XEVOZZ_CELL), open); + break; + case DATA_ZURAMAT: + HandleGameObject(GetObjectGuid(DATA_ZURAMAT_CELL), open); + break; + default: + break; } - default: - SpawnPortal(); - break; } - } - std::string GetSaveData() override - { - OUT_SAVE_INST_DATA; + void StartBossEncounter(uint8 bossId) + { + switch (bossId) + { + case DATA_MORAGG: + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* moragg = GetCreature(DATA_MORAGG)) + { + moragg->PlayDirectSound(SOUND_MORAGG_SPAWN); + moragg->CastSpell(moragg, SPELL_MORAGG_EMOTE_ROAR); + } - std::ostringstream saveStream; - saveStream << "V H " << (uint16)m_auiEncounter[0] - << ' ' << (uint16)m_auiEncounter[1] - << ' ' << (uint16)m_auiEncounter[2] - << ' ' << (uint16)uiFirstBoss - << ' ' << (uint16)uiSecondBoss; + task.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* moragg = GetCreature(DATA_MORAGG)) + moragg->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, MoraggPath, MoraggPathSize, true); + + task.Schedule(Seconds(8), [this](TaskContext /*task*/) + { + if (Creature* moragg = GetCreature(DATA_MORAGG)) + { + moragg->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + moragg->AI()->DoZoneInCombat(moragg, 200.0f); + } + }); + }); + }); + break; + case DATA_EREKEM: + Scheduler.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* erekem = GetCreature(DATA_EREKEM)) + erekem->AI()->Talk(SAY_EREKEM_SPAWN); - str_data = saveStream.str(); + task.Schedule(Seconds(5), [this](TaskContext task) + { + if (Creature* erekem = GetCreature(DATA_EREKEM)) + erekem->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, ErekemPath, ErekemPathSize, true); + + if (Creature* guard = instance->GetCreature(GetGuidData(DATA_EREKEM_GUARD_1))) + guard->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, ErekemGuardLeftPath, ErekemGuardLeftPathSize, true); + if (Creature* guard = instance->GetCreature(GetGuidData(DATA_EREKEM_GUARD_2))) + guard->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, ErekemGuardRightPath, ErekemGuardRightPathSize, true); + + task.Schedule(Seconds(6), [this](TaskContext task) + { + if (Creature* erekem = GetCreature(DATA_EREKEM)) + erekem->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + + task.Schedule(Seconds(1), [this](TaskContext /*task*/) + { + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) + { + if (Creature* guard = instance->GetCreature(GetGuidData(i))) + guard->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + } + + if (Creature* erekem = GetCreature(DATA_EREKEM)) + { + erekem->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + erekem->AI()->DoZoneInCombat(erekem, 200.0f); + } + }); + }); + }); + }); + break; + case DATA_ICHORON: + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* ichoron = GetCreature(DATA_ICHORON)) + ichoron->AI()->Talk(SAY_ICHORON_SPAWN); - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } + task.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* ichoron = GetCreature(DATA_ICHORON)) + ichoron->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, IchoronPath, IchoronPathSize, true); + + task.Schedule(Seconds(14), [this](TaskContext /*task*/) + { + if (Creature* ichoron = GetCreature(DATA_ICHORON)) + { + ichoron->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + ichoron->AI()->DoZoneInCombat(ichoron, 200.0f); + } + }); + }); + }); + break; + case DATA_LAVANTHOR: + Scheduler.Schedule(Seconds(1), [this](TaskContext task) + { + if (Creature* lavanthor = GetCreature(DATA_LAVANTHOR)) + lavanthor->CastSpell(lavanthor, SPELL_LAVANTHOR_SPECIAL_UNARMED); - void Load(const char* in) override - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } + task.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* lavanthor = GetCreature(DATA_LAVANTHOR)) + lavanthor->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, LavanthorPath, LavanthorPathSize, true); + + task.Schedule(Seconds(8), [this](TaskContext /*task*/) + { + if (Creature* lavanthor = GetCreature(DATA_LAVANTHOR)) + { + lavanthor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + lavanthor->AI()->DoZoneInCombat(lavanthor, 200.0f); + } + }); + }); + }); + break; + case DATA_XEVOZZ: + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* xevozz = GetCreature(DATA_XEVOZZ)) + xevozz->AI()->Talk(SAY_XEVOZZ_SPAWN); - OUT_LOAD_INST_DATA(in); + task.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* xevozz = GetCreature(DATA_XEVOZZ)) + xevozz->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE); + + task.Schedule(Seconds(4), [this](TaskContext task) + { + if (Creature* xevozz = GetCreature(DATA_XEVOZZ)) + xevozz->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, XevozzPath, XevozzPathSize, true); + + task.Schedule(Seconds(4), [this](TaskContext /*task*/) + { + if (Creature* xevozz = GetCreature(DATA_XEVOZZ)) + { + xevozz->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + xevozz->AI()->DoZoneInCombat(xevozz, 200.0f); + } + }); + }); + }); + }); + break; + case DATA_ZURAMAT: + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* zuramat = GetCreature(DATA_ZURAMAT)) + { + zuramat->CastSpell(zuramat, SPELL_ZURAMAT_COSMETIC_CHANNEL_OMNI); + zuramat->AI()->Talk(SAY_ZURAMAT_SPAWN); + } - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4; + task.Schedule(Seconds(6), [this](TaskContext task) + { + if (Creature* zuramat = GetCreature(DATA_ZURAMAT)) + zuramat->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, ZuramatPath, ZuramatPathSize, true); + + task.Schedule(Seconds(4), [this](TaskContext /*task*/) + { + if (Creature* zuramat = GetCreature(DATA_ZURAMAT)) + { + zuramat->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + zuramat->AI()->DoZoneInCombat(zuramat, 200.0f); + } + }); + }); + }); + break; + default: + return; + } - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; + HandleCells(bossId); + } - if (dataHead1 == 'V' && dataHead2 == 'H') + void ResetBossEncounter(uint8 bossId) { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; + if (bossId < DATA_CYANIGOSA || bossId > DATA_ZURAMAT) + return; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + Creature* boss = GetCreature(bossId); + if (!boss) + return; - uiFirstBoss = uint8(data3); - uiSecondBoss = uint8(data4); - } else OUT_LOAD_INST_DATA_FAIL; + switch (bossId) + { + case DATA_CYANIGOSA: + boss->DespawnOrUnsummon(); + break; + case DATA_EREKEM: + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) + { + if (Creature* guard = instance->GetCreature(GetGuidData(i))) + { + if (guard->isDead()) + guard->Respawn(); - OUT_LOAD_INST_DATA_COMPLETE; - } + if (GetBossState(bossId) == DONE) + UpdateKilledBoss(guard); - bool CheckWipe() - { - Map::PlayerList const &players = instance->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + guard->GetMotionMaster()->MoveTargetedHome(); + guard->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + } + } + // no break + default: + if (boss->isDead()) + { + // respawn and update to a placeholder npc to avoid be looted again + boss->Respawn(); + UpdateKilledBoss(boss); + } + + boss->GetMotionMaster()->MoveTargetedHome(); + boss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + break; + } + } + + void AddWave() { - Player* player = itr->GetSource(); - if (player->IsGameMaster()) - continue; + DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, WaveCount); - if (player->IsAlive()) - return false; + switch (WaveCount) + { + case 6: + if (FirstBossId == 0) + FirstBossId = urand(DATA_MORAGG, DATA_ZURAMAT); + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + { + sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL_INTRO, PortalIntroPositions[3], TEMPSUMMON_TIMED_DESPAWN, 3000); + sinclari->SummonCreature(NPC_SABOTEOUR, SaboteurSpawnLocation, TEMPSUMMON_DEAD_DESPAWN); + } + break; + case 12: + if (SecondBossId == 0) + do + { + SecondBossId = urand(DATA_MORAGG, DATA_ZURAMAT); + } while (SecondBossId == FirstBossId); + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + { + sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL_INTRO, PortalIntroPositions[3], TEMPSUMMON_TIMED_DESPAWN, 3000); + sinclari->SummonCreature(NPC_SABOTEOUR, SaboteurSpawnLocation, TEMPSUMMON_DEAD_DESPAWN); + } + break; + case 18: + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + { + sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL_INTRO, PortalIntroPositions[4], TEMPSUMMON_TIMED_DESPAWN, 6000); + if (Creature* cyanigosa = sinclari->SummonCreature(NPC_CYANIGOSA, CyanigosaSpawnLocation, TEMPSUMMON_DEAD_DESPAWN)) + cyanigosa->CastSpell(cyanigosa, SPELL_CYANIGOSA_ARCANE_POWER_STATE, true); + ScheduleCyanigosaIntro(); + } + break; + default: + SpawnPortal(); + break; + } } - return true; - } + void WriteSaveDataMore(std::ostringstream& data) override + { + data << FirstBossId << ' ' << SecondBossId; + } - void Update(uint32 diff) override - { - if (!instance->HavePlayers()) - return; + void ReadSaveDataMore(std::istringstream& data) override + { + data >> FirstBossId; + data >> SecondBossId; + } - // portals should spawn if other portal is dead and doors are closed - if (bActive && uiMainEventPhase == IN_PROGRESS) + bool CheckWipe() const { - if (uiActivationTimer < diff) + Map::PlayerList const& players = instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { - AddWave(); - bActive = false; - // 1 minute waiting time after each boss fight - uiActivationTimer = (uiWaveCount == 6 || uiWaveCount == 12) ? 60000 : 5000; - } else uiActivationTimer -= diff; + Player* player = itr->GetSource(); + if (player->IsGameMaster()) + continue; + + if (player->IsAlive()) + return false; + } + + return true; + } + + void UpdateKilledBoss(Creature* boss) + { + switch (boss->GetEntry()) + { + case NPC_XEVOZZ: + boss->UpdateEntry(NPC_DUMMY_XEVOZZ); + break; + case NPC_LAVANTHOR: + boss->UpdateEntry(NPC_DUMMY_LAVANTHOR); + break; + case NPC_ICHORON: + boss->UpdateEntry(NPC_DUMMY_ICHORON); + break; + case NPC_ZURAMAT: + boss->UpdateEntry(NPC_DUMMY_ZURAMAT); + break; + case NPC_EREKEM: + boss->UpdateEntry(NPC_DUMMY_EREKEM); + break; + case NPC_MORAGG: + boss->UpdateEntry(NPC_DUMMY_MORAGG); + break; + case NPC_EREKEM_GUARD: + boss->UpdateEntry(NPC_DUMMY_EREKEM_GUARD); + break; + default: + break; + } } - // if main event is in progress and players have wiped then reset instance - if (uiMainEventPhase == IN_PROGRESS && CheckWipe()) + void Update(uint32 diff) override { - SetData(DATA_REMOVE_NPC, 1); - StartBossEncounter(uiFirstBoss, false); - StartBossEncounter(uiSecondBoss, false); + if (!instance->HavePlayers()) + return; - SetData(DATA_MAIN_DOOR, GO_STATE_ACTIVE); - SetData(DATA_WAVE_COUNT, 0); - uiMainEventPhase = NOT_STARTED; + // if main event is in progress and players have wiped then reset instance + if ((EventState == IN_PROGRESS && CheckWipe()) || EventState == FAIL) + { + ResetBossEncounter(FirstBossId); + ResetBossEncounter(SecondBossId); + ResetBossEncounter(DATA_CYANIGOSA); + + WaveCount = 0; + DoorIntegrity = 100; + Defenseless = true; + SetData(DATA_MAIN_EVENT_STATE, NOT_STARTED); + + Scheduler.CancelAll(); + + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + sinclari->AI()->EnterEvadeMode(); + } - for (int i = 0; i < 4; ++i) - if (GameObject* crystal = instance->GetGameObject(uiActivationCrystal[i])) - crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + Scheduler.Update(diff); - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) + if (EventState == IN_PROGRESS) { - pSinclari->SetVisible(true); + // if door is destroyed, event is failed + if (!GetData(DATA_DOOR_INTEGRITY)) + EventState = FAIL; + } + } - std::list<Creature*> GuardList; - pSinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) + void ScheduleCyanigosaIntro() + { + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA)) + cyanigosa->AI()->Talk(SAY_CYANIGOSA_SPAWN); + + task.Schedule(Seconds(6), [this](TaskContext task) { - for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA)) + cyanigosa->GetMotionMaster()->MoveJump(CyanigosaJumpLocation, 10.0f, 27.44744f); + + task.Schedule(Seconds(7), [this](TaskContext /*task*/) { - if (Creature* pGuard = *itr) + if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA)) { - pGuard->SetVisible(true); - pGuard->SetReactState(REACT_AGGRESSIVE); - pGuard->GetMotionMaster()->MovePoint(1, pGuard->GetHomePosition()); + cyanigosa->RemoveAurasDueToSpell(SPELL_CYANIGOSA_ARCANE_POWER_STATE); + cyanigosa->CastSpell(cyanigosa, SPELL_CYANIGOSA_TRANSFORM, true); + cyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); } - } - } - pSinclari->GetMotionMaster()->MovePoint(1, pSinclari->GetHomePosition()); - pSinclari->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } + }); + }); + }); } - // Cyanigosa is spawned but not tranformed, prefight event - Creature* pCyanigosa = instance->GetCreature(uiCyanigosa); - if (pCyanigosa && !pCyanigosa->HasAura(CYANIGOSA_SPELL_TRANSFORM)) + void ProcessEvent(WorldObject* /*go*/, uint32 eventId) override { - if (uiCyanigosaEventTimer <= diff) + if (eventId == EVENT_ACTIVATE_CRYSTAL) { - switch (uiCyanigosaEventPhase) - { - case 1: - pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_BLUE_AURA, false); - pCyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN); - uiCyanigosaEventTimer = 7*IN_MILLISECONDS; - ++uiCyanigosaEventPhase; - break; - case 2: - pCyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f); - pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_BLUE_AURA, false); - uiCyanigosaEventTimer = 7*IN_MILLISECONDS; - ++uiCyanigosaEventPhase; - break; - case 3: - pCyanigosa->RemoveAurasDueToSpell(CYANIGOSA_BLUE_AURA); - pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_SPELL_TRANSFORM, 0); - pCyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - pCyanigosa->SetReactState(REACT_AGGRESSIVE); - uiCyanigosaEventTimer = 2*IN_MILLISECONDS; - ++uiCyanigosaEventPhase; - break; - case 4: - uiCyanigosaEventPhase = 0; - break; - } - } else uiCyanigosaEventTimer -= diff; + instance->SummonCreature(NPC_DEFENSE_SYSTEM, DefenseSystemLocation); + Defenseless = false; + } } - // if there are NPCs in front of the prison door, which are casting the door seal spell and doors are active - if (GetData(DATA_NPC_PRESENCE_AT_DOOR) && uiMainEventPhase == IN_PROGRESS) + static bool IsBossWave(uint8 wave) { - // if door integrity is > 0 then decrase it's integrity state - if (GetData(DATA_DOOR_INTEGRITY)) - { - if (uiDoorSpellTimer < diff) - { - SetData(DATA_DOOR_INTEGRITY, GetData(DATA_DOOR_INTEGRITY)-1); - uiDoorSpellTimer =2000; - } else uiDoorSpellTimer -= diff; - } - // else set door state to active (means door will open and group have failed to sustain mob invasion on the door) - else - { - SetData(DATA_MAIN_DOOR, GO_STATE_ACTIVE); - uiMainEventPhase = FAIL; - } + return wave && ((wave % 6) == 0); } - } - void ActivateCrystal() - { - // just to make things easier we'll get the gameobject from the map - GameObject* invoker = instance->GetGameObject(uiActivationCrystal[0]); - if (!invoker) - return; + protected: + TaskScheduler Scheduler; - SpellInfo const* spellInfoLightning = sSpellMgr->GetSpellInfo(SPELL_ARCANE_LIGHTNING); - if (!spellInfoLightning) - return; + static uint8 const ErekemGuardCount = 2; + ObjectGuid ErekemGuardGUIDs[ErekemGuardCount]; - // the orb - TempSummon* trigger = invoker->SummonCreature(NPC_DEFENSE_SYSTEM, ArcaneSphere, TEMPSUMMON_MANUAL_DESPAWN, 0); - if (!trigger) - return; + static uint8 const ActivationCrystalCount = 5; + ObjectGuid ActivationCrystalGUIDs[ActivationCrystalCount]; - // visuals - trigger->CastSpell(trigger, spellInfoLightning, true, 0, 0, trigger->GetGUID()); + uint32 FirstBossId; + uint32 SecondBossId; - // Kill all mobs registered with SetGuidData(ADD_TRASH_MOB) - for (GuidSet::const_iterator itr = trashMobs.begin(); itr != trashMobs.end();) - { - Creature* creature = instance->GetCreature(*itr); - // Increment the iterator before killing the creature because the kill will remove itr from trashMobs - ++itr; - if (creature && creature->IsAlive()) - trigger->Kill(creature); - } - } + uint8 DoorIntegrity; + uint8 WaveCount; + uint8 EventState; + uint8 LastPortalLocation; - void ProcessEvent(WorldObject* /*go*/, uint32 uiEventId) override + bool Defenseless; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override { - switch (uiEventId) - { - case EVENT_ACTIVATE_CRYSTAL: - bCrystalActivated = true; // Activation by player's will throw event signal - ActivateCrystal(); - break; - } + return new instance_violet_hold_InstanceMapScript(map); } - }; }; void AddSC_instance_violet_hold() diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp index 645a9da4764..fdb4c4dc3fc 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -15,35 +15,41 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "Player.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" #include "ScriptedEscortAI.h" -#include "violet_hold.h" -#include "Player.h" -#include "SpellAuras.h" #include "SpellAuraEffects.h" #include "SpellScript.h" +#include "violet_hold.h" -#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay." -#define GOSSIP_ITEM_1 "Activate the crystals when we get in trouble, right" -#define GOSSIP_I_WANT_IN "I'm not fighting, so send me in now!" -#define SPAWN_TIME 20000 +/* + * TODO: + * - add missing trash emotes + */ -enum PortalCreatures +enum PortalCreatureIds { - CREATURE_AZURE_INVADER_1 = 30661, - CREATURE_AZURE_INVADER_2 = 30961, - CREATURE_AZURE_SPELLBREAKER_1 = 30662, - CREATURE_AZURE_SPELLBREAKER_2 = 30962, - CREATURE_AZURE_BINDER_1 = 30663, - CREATURE_AZURE_BINDER_2 = 30918, - CREATURE_AZURE_MAGE_SLAYER_1 = 30664, - CREATURE_AZURE_MAGE_SLAYER_2 = 30963, - CREATURE_AZURE_CAPTAIN = 30666, - CREATURE_AZURE_SORCEROR = 30667, - CREATURE_AZURE_RAIDER = 30668, - CREATURE_AZURE_STALKER = 32191 + NPC_AZURE_INVADER_1 = 30661, + NPC_AZURE_SPELLBREAKER_1 = 30662, + NPC_AZURE_BINDER_1 = 30663, + NPC_AZURE_MAGE_SLAYER_1 = 30664, + NPC_VETERAN_MAGE_HUNTER = 30665, + NPC_AZURE_CAPTAIN_1 = 30666, + NPC_AZURE_SORCEROR_1 = 30667, + NPC_AZURE_RAIDER_1 = 30668, + + NPC_AZURE_BINDER_2 = 30918, + NPC_AZURE_INVADER_2 = 30961, + NPC_AZURE_SPELLBREAKER_2 = 30962, + NPC_AZURE_MAGE_SLAYER_2 = 30963, + NPC_AZURE_BINDER_3 = 31007, + NPC_AZURE_INVADER_3 = 31008, + NPC_AZURE_SPELLBREAKER_3 = 31009, + NPC_AZURE_MAGE_SLAYER_3 = 31010, + NPC_AZURE_RAIDER_2 = 31118, + NPC_AZURE_STALKER_1 = 32191 }; enum AzureInvaderSpells @@ -59,7 +65,7 @@ enum AzureSellbreakerSpells SPELL_ARCANE_BLAST = 58462, SPELL_SLOW = 25603, SPELL_CHAINS_OF_ICE = 58464, - SPELL_CONE_OF_COLD = 58463 + SPELL_CONE_OF_COLD = 58463, }; enum AzureBinderSpells @@ -67,7 +73,7 @@ enum AzureBinderSpells SPELL_ARCANE_BARRAGE = 58456, SPELL_ARCANE_EXPLOSION = 58455, SPELL_FROST_NOVA = 58458, - SPELL_FROSTBOLT = 58457 + SPELL_FROSTBOLT = 58457, }; enum AzureMageSlayerSpells @@ -85,7 +91,7 @@ enum AzureCaptainSpells enum AzureSorcerorSpells { SPELL_ARCANE_STREAM = 60181, - SPELL_MANA_DETONATION = 60182 + SPELL_MANA_DETONATION = 60182, }; enum AzureRaiderSpells @@ -102,8 +108,8 @@ enum AzureStalkerSpells enum AzureSaboteurSpells { - SABOTEUR_SHIELD_DISRUPTION = 58291, - SABOTEUR_SHIELD_EFFECT = 45775 + SPELL_SHIELD_DISRUPTION = 58291, + SPELL_TELEPORT_VISUAL = 51347 }; enum TrashDoorSpell @@ -111,19 +117,45 @@ enum TrashDoorSpell SPELL_DESTROY_DOOR_SEAL = 58040 }; -enum Spells +enum DefenseSystemSpells +{ + SPELL_ARCANE_LIGHTNING_DAMAGE = 57912, + SPELL_ARCANE_LIGHTNING_INSTAKILL = 58152, + SPELL_ARCANE_LIGHTNING_DUMMY = 57930 +}; + +enum MiscSpells +{ + SPELL_PORTAL_PERIODIC = 58008, + SPELL_PORTAL_CHANNEL = 58012, + SPELL_CRYSTAL_ACTIVATION = 57804, + + SPELL_TELEPORT_PLAYER = 62138, + SPELL_TELEPORT_PLAYER_EFFECT = 62139 +}; + +enum MiscData { - SPELL_PORTAL_CHANNEL = 58012, - SPELL_CRYSTAL_ACTIVATION = 57804, - SPELL_ARCANE_SPHERE_PASSIVE = 44263 + DATA_PORTAL_PERIODIC_TICK = 1 }; enum Sinclari { - SAY_SINCLARI_1 = 0 + // Sinclari + SAY_SINCLARI_INTRO_1 = 0, + SAY_SINCLARI_INTRO_2 = 1, + SAY_SINCLARI_OUTRO = 2, + + GOSSIP_MENU_START_ENCOUNTER = 9998, + GOSSIP_MENU_SEND_ME_IN = 10275, + + // Sinclari Trigger + SAY_SINCLARI_ELITE_SQUAD = 0, + SAY_SINCLARI_PORTAL_GUARDIAN = 1, + SAY_SINCLARI_PORTAL_KEEPER = 2 }; -float FirstPortalWPs [6][3] = +G3D::Vector3 const FirstPortalWPs[6] = { {1877.670288f, 842.280273f, 43.333591f}, {1877.338867f, 834.615356f, 38.762287f}, @@ -134,7 +166,7 @@ float FirstPortalWPs [6][3] = //{1825.736084f, 807.305847f, 44.363785f} }; -float SecondPortalFirstWPs [9][3] = +G3D::Vector3 const SecondPortalFirstWPs[9] = { {1902.561401f, 853.334656f, 47.106117f}, {1895.486084f, 855.376404f, 44.334591f}, @@ -148,7 +180,7 @@ float SecondPortalFirstWPs [9][3] = //{1825.736084f, 807.305847f, 44.363785f} }; -float SecondPortalSecondWPs [8][3] = +G3D::Vector3 const SecondPortalSecondWPs[8] = { {1929.392212f, 837.614990f, 47.136166f}, {1928.290649f, 824.750427f, 45.474411f}, @@ -161,7 +193,7 @@ float SecondPortalSecondWPs [8][3] = //{1825.736084f, 807.305847f, 44.363785f} }; -float ThirdPortalWPs [8][3] = +G3D::Vector3 const ThirdPortalWPs[8] = { {1934.049438f, 815.778503f, 52.408699f}, {1928.290649f, 824.750427f, 45.474411f}, @@ -174,7 +206,7 @@ float ThirdPortalWPs [8][3] = //{1825.736084f, 807.305847f, 44.363785f} }; -float FourthPortalWPs [9][3] = +G3D::Vector3 const FourthPortalWPs[9] = { {1921.658447f, 761.657043f, 50.866741f}, {1910.559814f, 755.780457f, 47.701447f}, @@ -188,7 +220,7 @@ float FourthPortalWPs [9][3] = //{1827.100342f, 801.605957f, 44.363358f} }; -float FifthPortalWPs [6][3] = +G3D::Vector3 const FifthPortalWPs[6] = { {1887.398804f, 763.633240f, 47.666851f}, {1879.020386f, 775.396973f, 38.705990f}, @@ -199,7 +231,7 @@ float FifthPortalWPs [6][3] = //{1827.100342f, 801.605957f, 44.363358f} }; -float SixthPoralWPs [4][3] = +G3D::Vector3 const SixthPoralWPs[4] = { {1888.861084f, 805.074768f, 38.375790f}, {1869.793823f, 804.135804f, 38.647018f}, @@ -208,1221 +240,1188 @@ float SixthPoralWPs [4][3] = //{1826.889648f, 803.929993f, 44.363239f} }; -const float SaboteurFinalPos1[3][3] = +G3D::Vector3 const DefaultPortalWPs[1] = +{ + { 1843.567017f, 804.288208f, 44.139091f } +}; + +uint32 const SaboteurMoraggPathSize = 5; +G3D::Vector3 const SaboteurMoraggPath[SaboteurMoraggPathSize] = // sniff { - {1892.502319f, 777.410767f, 38.630402f}, - {1891.165161f, 762.969421f, 47.666920f}, - {1893.168091f, 740.919189f, 47.666920f} + { 1886.251f, 803.0743f, 38.42326f }, + { 1885.71f, 799.8929f, 38.37241f }, + { 1889.505f, 762.3288f, 47.66684f }, + { 1894.542f, 742.1829f, 47.66684f }, + { 1894.603f, 739.9231f, 47.66684f }, }; -const float SaboteurFinalPos2[3][3] = + +uint32 const SaboteurErekemPathSize = 5; +G3D::Vector3 const SaboteurErekemPath[SaboteurErekemPathSize] = // sniff +{ + { 1886.251f, 803.0743f, 38.42326f }, + { 1881.047f, 829.6866f, 38.64856f }, + { 1877.585f, 844.6685f, 38.49014f }, + { 1876.085f, 851.6685f, 42.99014f }, + { 1873.747f, 864.1373f, 43.33349f } +}; + +uint32 const SaboteurIchoronPathSize = 3; +G3D::Vector3 const SaboteurIchoronPath[SaboteurIchoronPathSize] = // sniff { - {1882.242676f, 834.818726f, 38.646786f}, - {1879.220825f, 842.224854f, 43.333641f}, - {1873.842896f, 863.892456f, 43.333641f} + { 1886.251f, 803.0743f, 38.42326f }, + { 1888.672f, 801.2348f, 38.42305f }, + { 1901.987f, 793.3254f, 38.65126f } }; -const float SaboteurFinalPos3[2][3] = + +uint32 const SaboteurLavanthorPathSize = 3; +G3D::Vector3 const SaboteurLavanthorPath[SaboteurLavanthorPathSize] = // sniff { - {1904.298340f, 792.400391f, 38.646782f}, - {1935.716919f, 758.437073f, 30.627895f} + { 1886.251f, 803.0743f, 38.42326f }, + { 1867.925f, 778.8035f, 38.64702f }, + { 1853.304f, 759.0161f, 38.65761f } }; -const float SaboteurFinalPos4[3] = + +uint32 const SaboteurXevozzPathSize = 4; +G3D::Vector3 const SaboteurXevozzPath[SaboteurXevozzPathSize] = // sniff { - 1855.006104f, 760.641724f, 38.655266f + { 1886.251f, 803.0743f, 38.42326f }, + { 1889.096f, 810.0487f, 38.43871f }, + { 1896.547f, 823.5473f, 38.72863f }, + { 1906.666f, 842.3111f, 38.63351f } }; -const float SaboteurFinalPos5[3] = + +uint32 const SaboteurZuramatPathSize = 7; +G3D::Vector3 const SaboteurZuramatPath[SaboteurZuramatPathSize] = // sniff { - 1906.667358f, 841.705566f, 38.637894f + { 1886.251f, 803.0743f, 38.42326f }, + { 1889.69f, 807.0032f, 38.39914f }, + { 1906.91f, 818.2574f, 38.86596f }, + { 1929.03f, 824.2713f, 46.09165f }, + { 1928.441f, 842.8891f, 47.15078f }, + { 1927.454f, 851.6091f, 47.19094f }, + { 1927.947f, 852.2986f, 47.19637f } }; -const float SaboteurFinalPos6[5][3] = + +Position const SinclariPositions[] = // sniff { - {1911.437012f, 821.289246f, 38.684128f}, - {1920.734009f, 822.978027f, 41.525414f}, - {1928.262939f, 830.836609f, 44.668266f}, - {1929.338989f, 837.593933f, 47.137596f}, - {1931.063354f, 848.468445f, 47.190434f} - }; + { 1829.142f, 798.219f, 44.36212f, 0.122173f }, // 0 - Crystal + { 1820.12f, 803.916f, 44.36466f, 0.0f }, // 1 - Outside + { 1816.185f, 804.0629f, 44.44799f, 3.176499f }, // 2 - Second Spawn Point + { 1827.886f, 804.0555f, 44.36467f, 0.0f } // 3 - Outro +}; -const Position MovePosition = {1806.955566f, 803.851807f, 44.363323f, 0.0f}; -const Position playerTeleportPosition = {1830.531006f, 803.939758f, 44.340508f, 6.281611f}; -const Position sinclariOutsidePosition = {1817.315674f, 804.060608f, 44.363998f, 0.0f}; +Position const GuardsMovePosition = { 1802.099f, 803.7724f, 44.36466f, 0.0f }; // sniff class npc_sinclari_vh : public CreatureScript { -public: - npc_sinclari_vh() : CreatureScript("npc_sinclari_vh") { } - - 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(); - ENSURE_AI(npc_sinclari_vh::npc_sinclariAI, (creature->AI()))->uiPhase = 1; - if (InstanceScript* instance = creature->GetInstanceScript()) - instance->SetData(DATA_MAIN_EVENT_PHASE, SPECIAL); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->SEND_GOSSIP_MENU(13854, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->NearTeleportTo(playerTeleportPosition.GetPositionX(), playerTeleportPosition.GetPositionY(), playerTeleportPosition.GetPositionZ(), playerTeleportPosition.GetOrientation(), true); - player->CLOSE_GOSSIP_MENU(); - break; - } - return true; - } + public: + npc_sinclari_vh() : CreatureScript("npc_sinclari_vh") { } - bool OnGossipHello(Player* player, Creature* creature) override - { - if (InstanceScript* instance = creature->GetInstanceScript()) + bool OnGossipHello(Player* player, Creature* creature) override { - switch (instance->GetData(DATA_MAIN_EVENT_PHASE)) + // override default gossip + if (InstanceScript* instance = creature->GetInstanceScript()) { - case NOT_STARTED: - case FAIL: // Allow to start event if not started or wiped - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(13853, creature->GetGUID()); - break; - case IN_PROGRESS: // Allow to teleport inside if event is in progress - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_I_WANT_IN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->SEND_GOSSIP_MENU(13853, creature->GetGUID()); - break; - default: - player->SEND_GOSSIP_MENU(13910, creature->GetGUID()); + switch (instance->GetData(DATA_MAIN_EVENT_STATE)) + { + case IN_PROGRESS: + player->PrepareGossipMenu(creature, GOSSIP_MENU_SEND_ME_IN, true); + player->SendPreparedGossip(creature); + return true; + case DONE: + return true; // NYI + case NOT_STARTED: + case FAIL: + default: + break; + } } - } - return true; - } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_sinclariAI>(creature); - } - - struct npc_sinclariAI : public ScriptedAI - { - npc_sinclariAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); + // load default gossip + return false; } - void Initialize() + struct npc_sinclariAI : public ScriptedAI { - uiPhase = 0; - uiTimer = 0; - } + npc_sinclariAI(Creature* creature) : ScriptedAI(creature), _summons(creature) + { + _instance = creature->GetInstanceScript(); + } - InstanceScript* instance; + void Reset() override + { + _summons.DespawnAll(); + for (uint8 i = 0; i < PortalIntroCount; ++i) + if (Creature* summon = me->SummonCreature(NPC_TELEPORTATION_PORTAL_INTRO, PortalIntroPositions[i], TEMPSUMMON_MANUAL_DESPAWN)) + summon->AI()->SetData(DATA_PORTAL_LOCATION, i); - uint8 uiPhase; - uint32 uiTimer; + me->SetVisible(true); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - void Reset() override - { - Initialize(); + std::list<Creature*> guardList; + me->GetCreatureListWithEntryInGrid(guardList, NPC_VIOLET_HOLD_GUARD, 100.0f); + for (Creature* guard : guardList) + { + guard->Respawn(true); + guard->SetVisible(true); + guard->SetReactState(REACT_AGGRESSIVE); + guard->AI()->EnterEvadeMode(); + } + } - me->SetReactState(REACT_AGGRESSIVE); + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + if (menuId == GOSSIP_MENU_START_ENCOUNTER && gossipListId == 0) + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + _instance->SetData(DATA_MAIN_EVENT_STATE, SPECIAL); + ScheduleIntro(); + player->PlayerTalkClass->SendCloseGossip(); + } + else if (menuId == GOSSIP_MENU_SEND_ME_IN && gossipListId == 0) + { + me->CastSpell(player, SPELL_TELEPORT_PLAYER, true); + player->PlayerTalkClass->SendCloseGossip(); + } + } - std::list<Creature*> GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) + void DoAction(int32 actionId) override { - for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + if (actionId == ACTION_SINCLARI_OUTRO) { - if (Creature* pGuard = *itr) - { - pGuard->DisappearAndDie(); - pGuard->Respawn(); - pGuard->SetVisible(true); - pGuard->SetReactState(REACT_AGGRESSIVE); - } + me->SetVisible(true); + ScheduleOutro(); } } - } - void UpdateAI(uint32 uiDiff) override - { - ScriptedAI::UpdateAI(uiDiff); + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } - if (uiPhase) + void ScheduleIntro() { - if (uiTimer <= uiDiff) + _scheduler.Schedule(Seconds(1), [this](TaskContext task) { - switch (uiPhase) + switch (task.GetRepeatCounter()) { + case 0: + me->SetWalk(true); + me->GetMotionMaster()->MovePoint(0, SinclariPositions[0]); + task.Repeat(Seconds(1)); + break; case 1: - Talk(SAY_SINCLARI_1); - uiTimer = 4000; - uiPhase = 2; + me->HandleEmoteCommand(EMOTE_ONESHOT_USE_STANDING); + me->GetMap()->SummonCreature(NPC_DEFENSE_SYSTEM, DefenseSystemLocation); + task.Repeat(Seconds(3)); break; case 2: - { - std::list<Creature*> GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + me->SetFacingTo(SinclariPositions[0].GetOrientation()); + Talk(SAY_SINCLARI_INTRO_1); + + task.Schedule(Seconds(1), [this](TaskContext /*task*/) + { + std::list<Creature*> guardList; + me->GetCreatureListWithEntryInGrid(guardList, NPC_VIOLET_HOLD_GUARD, 100.0f); + for (Creature* guard : guardList) { - if (Creature* pGuard = *itr) - { - pGuard->SetWalk(false); - pGuard->GetMotionMaster()->MovePoint(0, MovePosition); - } + guard->SetReactState(REACT_PASSIVE); + guard->SetWalk(false); + guard->GetMotionMaster()->MovePoint(0, GuardsMovePosition); } - uiTimer = 6000; - uiPhase = 3; + }); + + task.Repeat(Seconds(2)); break; - } case 3: - { - std::list<Creature*> GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - { - pGuard->SetVisible(false); - pGuard->SetReactState(REACT_PASSIVE); - } - } - uiTimer = 2000; - uiPhase = 4; + me->GetMotionMaster()->MovePoint(0, SinclariPositions[1]); + _summons.DespawnAll(); + task.Repeat(Seconds(5)); break; - } case 4: - me->GetMotionMaster()->MovePoint(0, sinclariOutsidePosition); - uiTimer = 4000; - uiPhase = 5; + me->SetFacingTo(SinclariPositions[1].GetOrientation()); + + task.Schedule(Seconds(1), [this](TaskContext /*task*/) + { + std::list<Creature*> guardList; + me->GetCreatureListWithEntryInGrid(guardList, NPC_VIOLET_HOLD_GUARD, 100.0f); + for (Creature* guard : guardList) + guard->SetVisible(false); + }); + + task.Repeat(Seconds(6)); break; case 5: - instance->SetData(DATA_MAIN_EVENT_PHASE, IN_PROGRESS); - me->SetReactState(REACT_PASSIVE); - uiTimer = 0; - uiPhase = 0; + Talk(SAY_SINCLARI_INTRO_2); + task.Repeat(Seconds(4)); + break; + case 6: + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE); + task.Repeat(Seconds(1)); + break; + case 7: + if (GameObject* mainDoor = _instance->GetGameObject(DATA_MAIN_DOOR)) + { + mainDoor->SetGoState(GO_STATE_READY); + mainDoor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + task.Repeat(Seconds(5)); + break; + case 8: + me->SetVisible(false); + task.Repeat(Seconds(1)); + break; + case 9: + _instance->SetData(DATA_MAIN_EVENT_STATE, IN_PROGRESS); + // [1] GUID: Full: 0xF1300077C202E6DD Type: Creature Entry: 30658 Low: 190173 + break; + default: break; } - } - else uiTimer -= uiDiff; + }); } - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - }; + void ScheduleOutro() + { + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + Talk(SAY_SINCLARI_OUTRO); + me->GetMotionMaster()->MovePoint(0, SinclariPositions[3]); -}; + task.Schedule(Seconds(10), [this](TaskContext /*task*/) + { + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + }); + }); + } -class npc_azure_saboteur : public CreatureScript -{ -public: - npc_azure_saboteur() : CreatureScript("npc_azure_saboteur") { } + void JustSummoned(Creature* summon) override + { + ScriptedAI::JustSummoned(summon); + _summons.Summon(summon); + } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_saboteurAI>(creature); - } + void SummonedCreatureDespawn(Creature* summon) override + { + _summons.Despawn(summon); + ScriptedAI::SummonedCreatureDespawn(summon); + } - struct npc_azure_saboteurAI : public npc_escortAI - { - npc_azure_saboteurAI(Creature* creature):npc_escortAI(creature) - { - instance = creature->GetInstanceScript(); - bHasGotMovingPoints = false; - uiBoss = 0; - Reset(); - } + private: + InstanceScript* _instance; + TaskScheduler _scheduler; - InstanceScript* instance; - bool bHasGotMovingPoints; - uint32 uiBoss; + SummonList _summons; + }; - void Reset() override + CreatureAI* GetAI(Creature* creature) const override { - if (!uiBoss) - uiBoss = instance->GetData(DATA_WAVE_COUNT) == 6 ? instance->GetData(DATA_FIRST_BOSS) : instance->GetData(DATA_SECOND_BOSS); - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + return GetVioletHoldAI<npc_sinclariAI>(creature); } +}; - void WaypointReached(uint32 waypointId) override - { - switch (uiBoss) - { - case 1: - if (waypointId == 2) - FinishPointReached(); - break; - case 2: - if (waypointId == 2) - FinishPointReached(); - break; - case 3: - if (waypointId == 1) - FinishPointReached(); - break; - case 4: - if (waypointId == 0) - FinishPointReached(); - break; - case 5: - if (waypointId == 0) - FinishPointReached(); - break; - case 6: - if (waypointId == 4) - FinishPointReached(); - break; - } - } +class npc_azure_saboteur : public CreatureScript +{ + public: + npc_azure_saboteur() : CreatureScript("npc_azure_saboteur") { } - void UpdateAI(uint32 diff) override + struct npc_azure_saboteurAI : public ScriptedAI { - if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) - me->CastStop(); + npc_azure_saboteurAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); - npc_escortAI::UpdateAI(diff); + if (_instance->GetData(DATA_WAVE_COUNT) == 6) + _bossId = _instance->GetData(DATA_1ST_BOSS); + else + _bossId = _instance->GetData(DATA_2ND_BOSS); + } - if (!bHasGotMovingPoints) + void StartMovement() { - bHasGotMovingPoints = true; - switch (uiBoss) + uint32 pathSize = 0; + G3D::Vector3 const* path = nullptr; + + switch (_bossId) { - case 1: - for (int i=0;i<3;i++) - AddWaypoint(i, SaboteurFinalPos1[i][0], SaboteurFinalPos1[i][1], SaboteurFinalPos1[i][2], 0); - me->SetHomePosition(SaboteurFinalPos1[2][0], SaboteurFinalPos1[2][1], SaboteurFinalPos1[2][2], 4.762346f); + case DATA_MORAGG: + pathSize = SaboteurMoraggPathSize; + path = SaboteurMoraggPath; break; - case 2: - for (int i=0;i<3;i++) - AddWaypoint(i, SaboteurFinalPos2[i][0], SaboteurFinalPos2[i][1], SaboteurFinalPos2[i][2], 0); - me->SetHomePosition(SaboteurFinalPos2[2][0], SaboteurFinalPos2[2][1], SaboteurFinalPos2[2][2], 1.862674f); + case DATA_EREKEM: + pathSize = SaboteurErekemPathSize; + path = SaboteurErekemPath; break; - case 3: - for (int i=0;i<2;i++) - AddWaypoint(i, SaboteurFinalPos3[i][0], SaboteurFinalPos3[i][1], SaboteurFinalPos3[i][2], 0); - me->SetHomePosition(SaboteurFinalPos3[1][0], SaboteurFinalPos3[1][1], SaboteurFinalPos3[1][2], 5.500638f); + case DATA_ICHORON: + pathSize = SaboteurIchoronPathSize; + path = SaboteurIchoronPath; break; - case 4: - AddWaypoint(0, SaboteurFinalPos4[0], SaboteurFinalPos4[1], SaboteurFinalPos4[2], 0); - me->SetHomePosition(SaboteurFinalPos4[0], SaboteurFinalPos4[1], SaboteurFinalPos4[2], 3.991108f); + case DATA_LAVANTHOR: + pathSize = SaboteurLavanthorPathSize; + path = SaboteurLavanthorPath; break; - case 5: - AddWaypoint(0, SaboteurFinalPos5[0], SaboteurFinalPos5[1], SaboteurFinalPos5[2], 0); - me->SetHomePosition(SaboteurFinalPos5[0], SaboteurFinalPos5[1], SaboteurFinalPos5[2], 1.100841f); + case DATA_XEVOZZ: + pathSize = SaboteurXevozzPathSize; + path = SaboteurXevozzPath; break; - case 6: - for (int i=0;i<5;i++) - AddWaypoint(i, SaboteurFinalPos6[i][0], SaboteurFinalPos6[i][1], SaboteurFinalPos6[i][2], 0); - me->SetHomePosition(SaboteurFinalPos6[4][0], SaboteurFinalPos6[4][1], SaboteurFinalPos6[4][2], 0.983031f); + case DATA_ZURAMAT: + pathSize = SaboteurZuramatPathSize; + path = SaboteurZuramatPath; break; } - SetDespawnAtEnd(false); - Start(true, true); + if (path) + me->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, path, pathSize, false); } - } - void FinishPointReached() + void Reset() override + { + _scheduler.CancelAll(); + _scheduler.Schedule(Seconds(2), [this](TaskContext /*task*/) + { + StartMovement(); + }); + } + + void MovementInform(uint32 type, uint32 pointId) override + { + if (type == EFFECT_MOTION_TYPE && pointId == POINT_INTRO) + { + _scheduler.Schedule(Seconds(0), [this](TaskContext task) + { + me->CastSpell(me, SPELL_SHIELD_DISRUPTION, false); + + if (task.GetRepeatCounter() < 2) + task.Repeat(Seconds(1)); + else + { + task.Schedule(Seconds(2), [this](TaskContext /*task*/) + { + _instance->SetData(DATA_START_BOSS_ENCOUNTER, 1); + me->CastSpell(me, SPELL_TELEPORT_VISUAL, false); + me->DespawnOrUnsummon(1000); + }); + } + }); + } + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + + private: + InstanceScript* _instance; + TaskScheduler _scheduler; + + uint32 _bossId; + }; + + CreatureAI* GetAI(Creature* creature) const override { - me->CastSpell(me, SABOTEUR_SHIELD_DISRUPTION, false); - me->DisappearAndDie(); - Creature* pSaboPort = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_SABOTEUR_PORTAL)); - if (pSaboPort) - pSaboPort->DisappearAndDie(); - instance->SetData(DATA_START_BOSS_ENCOUNTER, 1); + return GetVioletHoldAI<npc_azure_saboteurAI>(creature); } - }; - }; -class npc_teleportation_portal_vh : public CreatureScript +struct npc_violet_hold_teleportation_portal_commonAI : public ScriptedAI { -public: - npc_teleportation_portal_vh() : CreatureScript("npc_teleportation_portal_vh") { } + npc_violet_hold_teleportation_portal_commonAI(Creature* creature) : ScriptedAI(creature), _summons(me) + { + _instance = creature->GetInstanceScript(); + _portalLocation = 0; + } - CreatureAI* GetAI(Creature* creature) const override + void InitializeAI() override { - return GetInstanceAI<npc_teleportation_portalAI>(creature); + ScriptedAI::InitializeAI(); + ScheduleTasks(); } - struct npc_teleportation_portalAI : public ScriptedAI + void SetData(uint32 type, uint32 data) override { - npc_teleportation_portalAI(Creature* creature) : ScriptedAI(creature), listOfMobs(me) - { - Initialize(); - instance = creature->GetInstanceScript(); - uiTypeOfMobsPortal = urand(0, 1); // 0 - elite mobs 1 - portal guardian or portal keeper with regular mobs - } + if (type == DATA_PORTAL_LOCATION) + _portalLocation = uint8(data); + } - void Initialize() - { - uiSpawnTimer = 10000; - bPortalGuardianOrKeeperOrEliteSpawn = false; - } + void MoveInLineOfSight(Unit* /*who*/) override { } - uint32 uiSpawnTimer; - bool bPortalGuardianOrKeeperOrEliteSpawn; - uint8 uiTypeOfMobsPortal; + void EnterCombat(Unit* /*who*/) override { } - SummonList listOfMobs; + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + summon->AI()->SetData(DATA_PORTAL_LOCATION, _portalLocation); + } - InstanceScript* instance; + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + _summons.Despawn(summon); + } - void Reset() override - { - Initialize(); - } + virtual void ScheduleTasks() { } - void EnterCombat(Unit* /*who*/) override { } + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } - void MoveInLineOfSight(Unit* /*who*/) override { } +protected: + InstanceScript* _instance; + SummonList _summons; + TaskScheduler _scheduler; + uint8 _portalLocation; +}; +class npc_violet_hold_teleportation_portal : public CreatureScript +{ + public: + npc_violet_hold_teleportation_portal() : CreatureScript("npc_violet_hold_teleportation_portal") { } - void UpdateAI(uint32 diff) override + struct npc_violet_hold_teleportation_portalAI : public npc_violet_hold_teleportation_portal_commonAI { - if (instance->GetData(DATA_REMOVE_NPC) == 1) + npc_violet_hold_teleportation_portalAI(Creature* creature) : npc_violet_hold_teleportation_portal_commonAI(creature) { - me->DespawnOrUnsummon(); - instance->SetData(DATA_REMOVE_NPC, 0); } - uint8 uiWaveCount = instance->GetData(DATA_WAVE_COUNT); - if ((uiWaveCount == 6) || (uiWaveCount == 12)) //Don't spawn mobs on boss encounters - return; + void InitializeAI() override + { + npc_violet_hold_teleportation_portal_commonAI::InitializeAI(); + me->CastSpell(me, SPELL_PORTAL_PERIODIC, true); + } - switch (uiTypeOfMobsPortal) + void SetData(uint32 type, uint32 data) override { - // spawn elite mobs and then set portals visibility to make it look like it dissapeard - case 0: - if (!bPortalGuardianOrKeeperOrEliteSpawn) + npc_violet_hold_teleportation_portal_commonAI::SetData(type, data); + + if (type == DATA_PORTAL_PERIODIC_TICK) + { + if (data == 1) { - if (uiSpawnTimer <= diff) + uint32 entry = RAND(NPC_PORTAL_GUARDIAN, NPC_PORTAL_KEEPER); + if (Creature* portalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) + me->CastSpell(portalKeeper, SPELL_PORTAL_CHANNEL, false); + + if (Creature* sinclariTrigger = _instance->GetCreature(DATA_SINCLARI_TRIGGER)) { - bPortalGuardianOrKeeperOrEliteSpawn = true; - uint8 k = uiWaveCount < 12 ? 2 : 3; - for (uint8 i = 0; i < k; ++i) - { - uint32 entry = RAND(CREATURE_AZURE_CAPTAIN, CREATURE_AZURE_RAIDER, CREATURE_AZURE_STALKER, CREATURE_AZURE_SORCEROR); - DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); - } - me->SetVisible(false); - } else uiSpawnTimer -= diff; + if (entry == NPC_PORTAL_GUARDIAN) + sinclariTrigger->AI()->Talk(SAY_SINCLARI_PORTAL_GUARDIAN); + else if (entry == NPC_PORTAL_KEEPER) + sinclariTrigger->AI()->Talk(SAY_SINCLARI_PORTAL_KEEPER); + } } else { - // if all spawned elites have died kill portal - if (listOfMobs.empty()) + uint8 k = _instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4; + while (k--) { - me->Kill(me, false); - me->RemoveCorpse(); + uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_INVADER_2, NPC_AZURE_SPELLBREAKER_1, NPC_AZURE_SPELLBREAKER_2, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_MAGE_SLAYER_2, NPC_AZURE_BINDER_1, NPC_AZURE_BINDER_2); + DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); } } - break; - // spawn portal guardian or portal keeper with regular mobs - case 1: - if (uiSpawnTimer <= diff) - { - if (bPortalGuardianOrKeeperOrEliteSpawn) - { - uint8 k = instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4; - for (uint8 i = 0; i < k; ++i) - { - uint32 entry = RAND(CREATURE_AZURE_INVADER_1, CREATURE_AZURE_INVADER_2, CREATURE_AZURE_SPELLBREAKER_1, CREATURE_AZURE_SPELLBREAKER_2, CREATURE_AZURE_MAGE_SLAYER_1, CREATURE_AZURE_MAGE_SLAYER_2, CREATURE_AZURE_BINDER_1, CREATURE_AZURE_BINDER_2); - DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); - } - } - else - { - bPortalGuardianOrKeeperOrEliteSpawn = true; - uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER); - if (Creature* pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) - me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false); - } - uiSpawnTimer = SPAWN_TIME; - } else uiSpawnTimer -= diff; + } + } + + void SummonedCreatureDies(Creature* summon, Unit* killer) override + { + npc_violet_hold_teleportation_portal_commonAI::SummonedCreatureDies(summon, killer); + + if (summon->GetEntry() == NPC_PORTAL_GUARDIAN || summon->GetEntry() == NPC_PORTAL_KEEPER) + { + _instance->SetData(DATA_WAVE_COUNT, _instance->GetData(DATA_WAVE_COUNT) + 1); + me->DespawnOrUnsummon(); + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_violet_hold_teleportation_portalAI>(creature); + } +}; + +class npc_violet_hold_teleportation_portal_elite : public CreatureScript +{ + public: + npc_violet_hold_teleportation_portal_elite() : CreatureScript("npc_violet_hold_teleportation_portal_elite") { } - if (bPortalGuardianOrKeeperOrEliteSpawn && !me->IsNonMeleeSpellCast(false)) + struct npc_violet_hold_teleportation_portal_eliteAI : public npc_violet_hold_teleportation_portal_commonAI + { + npc_violet_hold_teleportation_portal_eliteAI(Creature* creature) : npc_violet_hold_teleportation_portal_commonAI(creature) + { + } + + void ScheduleTasks() override + { + _scheduler.Schedule(Seconds(15), [this](TaskContext task) + { + uint8 k = _instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4; + while (k--) { - me->Kill(me, false); - me->RemoveCorpse(); + uint32 entry = RAND(NPC_AZURE_CAPTAIN_1, NPC_AZURE_RAIDER_1, NPC_AZURE_STALKER_1, NPC_AZURE_SORCEROR_1); + DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); } - break; + + if (Creature* sinclariTrigger = _instance->GetCreature(DATA_SINCLARI_TRIGGER)) + sinclariTrigger->AI()->Talk(SAY_SINCLARI_ELITE_SQUAD); + + task.Schedule(Seconds(1), [this](TaskContext /*task*/) + { + me->SetVisible(false); + }); + }); } - } - void JustDied(Unit* /*killer*/) override + void SummonedCreatureDies(Creature* summon, Unit* killer) override + { + npc_violet_hold_teleportation_portal_commonAI::SummonedCreatureDies(summon, killer); + + if (_summons.empty()) + { + _instance->SetData(DATA_WAVE_COUNT, _instance->GetData(DATA_WAVE_COUNT) + 1); + me->DespawnOrUnsummon(); + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override { - instance->SetData(DATA_WAVE_COUNT, instance->GetData(DATA_WAVE_COUNT)+1); + return GetVioletHoldAI<npc_violet_hold_teleportation_portal_eliteAI>(creature); } +}; + +class npc_violet_hold_teleportation_portal_intro : public CreatureScript +{ + public: + npc_violet_hold_teleportation_portal_intro() : CreatureScript("npc_violet_hold_teleportation_portal_intro") { } - void JustSummoned(Creature* summoned) override + struct npc_violet_hold_teleportation_portal_introAI : public npc_violet_hold_teleportation_portal_commonAI { - listOfMobs.Summon(summoned); - instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID()); - } + npc_violet_hold_teleportation_portal_introAI(Creature* creature) : npc_violet_hold_teleportation_portal_commonAI(creature) + { + } - void SummonedCreatureDies(Creature* summoned, Unit* /*killer*/) override + void ScheduleTasks() override + { + if (_instance->GetData(DATA_MAIN_EVENT_STATE) != NOT_STARTED) + return; + + _scheduler.Schedule(Seconds(15), [this](TaskContext task) + { + uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_BINDER_1); + DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); + + task.Repeat(); + }); + } + }; + + CreatureAI* GetAI(Creature* creature) const override { - listOfMobs.Despawn(summoned); - instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID()); + return GetVioletHoldAI<npc_violet_hold_teleportation_portal_introAI>(creature); } - }; - }; struct violet_hold_trashAI : public npc_escortAI { - violet_hold_trashAI(Creature* creature):npc_escortAI(creature) + violet_hold_trashAI(Creature* creature) : npc_escortAI(creature) { - instance = creature->GetInstanceScript(); - bHasGotMovingPoints = false; - portalLocationID = instance->GetData(DATA_PORTAL_LOCATION); - secondPortalRouteID = 0; - } + _instance = creature->GetInstanceScript(); - public: - InstanceScript* instance; - bool bHasGotMovingPoints; - uint32 portalLocationID; - uint32 secondPortalRouteID; + _lastWaypointId = 0; - void WaypointReached(uint32 waypointId) override - { - switch (portalLocationID) + SetDespawnAtEnd(false); + + _scheduler.SetValidator([this] { - case 0: - if (waypointId == 5) - CreatureStartAttackDoor(); - break; - case 1: - if ((waypointId == 8 && secondPortalRouteID == 0) || (waypointId == 7 && secondPortalRouteID == 1)) - CreatureStartAttackDoor(); - break; - case 2: - if (waypointId == 7) - CreatureStartAttackDoor(); - break; - case 3: - if (waypointId == 8) - CreatureStartAttackDoor(); - break; - case 4: - if (waypointId == 5) - CreatureStartAttackDoor(); - break; - case 5: - if (waypointId == 3) - CreatureStartAttackDoor(); - break; - } + return !me->HasUnitState(UNIT_STATE_CASTING); + }); } - void UpdateAI(uint32) override + void Reset() override { - if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) - me->CastStop(); + _scheduler.CancelAll(); + } - if (!bHasGotMovingPoints) + void SetData(uint32 type, uint32 data) override + { + if (type == DATA_PORTAL_LOCATION) { - bHasGotMovingPoints = true; - switch (portalLocationID) + G3D::Vector3 const* path = nullptr; + + switch (data) { case 0: - for (int i=0;i<6;i++) - AddWaypoint(i, FirstPortalWPs[i][0]+irand(-1, 1), FirstPortalWPs[i][1]+irand(-1, 1), FirstPortalWPs[i][2]+irand(-1, 1), 0); - me->SetHomePosition(FirstPortalWPs[5][0], FirstPortalWPs[5][1], FirstPortalWPs[5][2], 3.149439f); + _lastWaypointId = 5; + path = FirstPortalWPs; break; - case 1: - secondPortalRouteID = urand(0, 1); - switch (secondPortalRouteID) + case 7: + switch (urand(0, 1)) { case 0: - for (int i=0;i<9;i++) - AddWaypoint(i, SecondPortalFirstWPs[i][0]+irand(-1, 1), SecondPortalFirstWPs[i][1]+irand(-1, 1), SecondPortalFirstWPs[i][2], 0); - me->SetHomePosition(SecondPortalFirstWPs[8][0]+irand(-1, 1), SecondPortalFirstWPs[8][1]+irand(-1, 1), SecondPortalFirstWPs[8][2]+irand(-1, 1), 3.149439f); + _lastWaypointId = 8; + path = SecondPortalFirstWPs; break; case 1: - for (int i=0;i<8;i++) - AddWaypoint(i, SecondPortalSecondWPs[i][0]+irand(-1, 1), SecondPortalSecondWPs[i][1]+irand(-1, 1), SecondPortalSecondWPs[i][2], 0); - me->SetHomePosition(SecondPortalSecondWPs[7][0], SecondPortalSecondWPs[7][1], SecondPortalSecondWPs[7][2], 3.149439f); + _lastWaypointId = 7; + path = SecondPortalSecondWPs; break; } break; case 2: - for (int i=0;i<8;i++) - AddWaypoint(i, ThirdPortalWPs[i][0]+irand(-1, 1), ThirdPortalWPs[i][1]+irand(-1, 1), ThirdPortalWPs[i][2], 0); - me->SetHomePosition(ThirdPortalWPs[7][0], ThirdPortalWPs[7][1], ThirdPortalWPs[7][2], 3.149439f); + _lastWaypointId = 7; + path = ThirdPortalWPs; break; - case 3: - for (int i=0;i<9;i++) - AddWaypoint(i, FourthPortalWPs[i][0]+irand(-1, 1), FourthPortalWPs[i][1]+irand(-1, 1), FourthPortalWPs[i][2], 0); - me->SetHomePosition(FourthPortalWPs[8][0], FourthPortalWPs[8][1], FourthPortalWPs[8][2], 3.149439f); + case 6: + _lastWaypointId = 8; + path = FourthPortalWPs; break; - case 4: - for (int i=0;i<6;i++) - AddWaypoint(i, FifthPortalWPs[i][0]+irand(-1, 1), FifthPortalWPs[i][1]+irand(-1, 1), FifthPortalWPs[i][2], 0); - me->SetHomePosition(FifthPortalWPs[5][0], FifthPortalWPs[5][1], FifthPortalWPs[5][2], 3.149439f); + case 1: + _lastWaypointId = 5; + path = FifthPortalWPs; break; case 5: - for (int i=0;i<4;i++) - AddWaypoint(i, SixthPoralWPs[i][0]+irand(-1, 1), SixthPoralWPs[i][1]+irand(-1, 1), SixthPoralWPs[i][2], 0); - me->SetHomePosition(SixthPoralWPs[3][0], SixthPoralWPs[3][1], SixthPoralWPs[3][2], 3.149439f); + _lastWaypointId = 3; + path = SixthPoralWPs; + break; + default: + _lastWaypointId = 0; + path = DefaultPortalWPs; break; } - SetDespawnAtEnd(false); + + if (path) + { + for (uint32 i = 0; i <= _lastWaypointId; i++) + AddWaypoint(i, path[i].x + irand(-1, 1), path[i].y + irand(-1, 1), path[i].z, 0); + me->SetHomePosition(path[_lastWaypointId].x, path[_lastWaypointId].y, path[_lastWaypointId].z, float(M_PI)); + } + Start(true, true); } } - void JustDied(Unit* /*killer*/) override + void WaypointReached(uint32 waypointId) override { - instance->SetData(DATA_NPC_PRESENCE_AT_DOOR_REMOVE, 1); + if (waypointId == _lastWaypointId) + CreatureStartAttackDoor(); } - void CreatureStartAttackDoor() + void EnterCombat(Unit* who) override { - me->SetReactState(REACT_PASSIVE); - DoCast(SPELL_DESTROY_DOOR_SEAL); - instance->SetData(DATA_NPC_PRESENCE_AT_DOOR_ADD, 1); + npc_escortAI::EnterCombat(who); + ScheduledTasks(); } -}; + void UpdateEscortAI(uint32 diff) override + { + if (_instance->GetData(DATA_MAIN_EVENT_STATE) != IN_PROGRESS) + me->CastStop(); -class npc_azure_invader : public CreatureScript -{ -public: - npc_azure_invader() : CreatureScript("npc_azure_invader") { } + if (!UpdateVictim()) + return; - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_invaderAI>(creature); + _scheduler.Update(diff, + std::bind(&npc_escortAI::DoMeleeAttackIfReady, this)); } - struct npc_azure_invaderAI : public violet_hold_trashAI + virtual void ScheduledTasks() { } + + void CreatureStartAttackDoor() { - npc_azure_invaderAI(Creature* creature) : violet_hold_trashAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + me->SetReactState(REACT_DEFENSIVE); + DoCastAOE(SPELL_DESTROY_DOOR_SEAL); + } - void Initialize() - { - uiCleaveTimer = 5000; - uiImpaleTimer = 4000; - uiBrutalStrikeTimer = 5000; - uiSunderArmorTimer = 4000; - } +protected: + InstanceScript* _instance; + TaskScheduler _scheduler; - uint32 uiCleaveTimer; - uint32 uiImpaleTimer; - uint32 uiBrutalStrikeTimer; - uint32 uiSunderArmorTimer; + uint32 _lastWaypointId; +}; - void Reset() override - { - Initialize(); - } +class npc_azure_invader : public CreatureScript +{ + public: + npc_azure_invader() : CreatureScript("npc_azure_invader") { } - void UpdateAI(uint32 diff) override + struct npc_azure_invaderAI : public violet_hold_trashAI { - violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); + npc_azure_invaderAI(Creature* creature) : violet_hold_trashAI(creature) { } - if (!UpdateVictim()) - return; - - if (me->GetEntry() == CREATURE_AZURE_INVADER_1) - { - if (uiCleaveTimer <= diff) - { - DoCastVictim(SPELL_CLEAVE); - uiCleaveTimer = 5000; - } else uiCleaveTimer -= diff; - - if (uiImpaleTimer <= diff) - { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) - DoCast(target, SPELL_IMPALE); - uiImpaleTimer = 4000; - } else uiImpaleTimer -= diff; - } - - if (me->GetEntry() == CREATURE_AZURE_INVADER_2) + void ScheduledTasks() override { - if (uiBrutalStrikeTimer <= diff) + if (me->GetEntry() == NPC_AZURE_INVADER_1) { - DoCastVictim(SPELL_BRUTAL_STRIKE); - uiBrutalStrikeTimer = 5000; - } else uiBrutalStrikeTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_CLEAVE); + task.Repeat(); + }); - if (uiSunderArmorTimer <= diff) + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCastVictim(SPELL_IMPALE); + task.Repeat(); + }); + } + else if (me->GetEntry() == NPC_AZURE_INVADER_2) { - DoCastVictim(SPELL_SUNDER_ARMOR); - uiSunderArmorTimer = urand(8000, 10000); - } else uiSunderArmorTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_BRUTAL_STRIKE); + task.Repeat(); + }); - DoMeleeAttackIfReady(); + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCastVictim(SPELL_SUNDER_ARMOR); + task.Repeat(Seconds(8), Seconds(10)); + }); + } } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_azure_invaderAI>(creature); } - }; - }; class npc_azure_binder : public CreatureScript { -public: - npc_azure_binder() : CreatureScript("npc_azure_binder") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_binderAI>(creature); - } - - struct npc_azure_binderAI : public violet_hold_trashAI - { - npc_azure_binderAI(Creature* creature) : violet_hold_trashAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - uiArcaneExplosionTimer = 5000; - uiArcainBarrageTimer = 4000; - uiFrostNovaTimer = 5000; - uiFrostboltTimer = 4000; - } - - uint32 uiArcaneExplosionTimer; - uint32 uiArcainBarrageTimer; - uint32 uiFrostNovaTimer; - uint32 uiFrostboltTimer; - - void Reset() override - { - Initialize(); - } + public: + npc_azure_binder() : CreatureScript("npc_azure_binder") { } - void UpdateAI(uint32 diff) override + struct npc_azure_binderAI : public violet_hold_trashAI { - violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; + npc_azure_binderAI(Creature* creature) : violet_hold_trashAI(creature) { } - if (me->GetEntry() == CREATURE_AZURE_BINDER_1) + void ScheduledTasks() override { - if (uiArcaneExplosionTimer <= diff) + if (me->GetEntry() == NPC_AZURE_BINDER_1) { - DoCast(SPELL_ARCANE_EXPLOSION); - uiArcaneExplosionTimer = 5000; - } else uiArcaneExplosionTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastAOE(SPELL_ARCANE_EXPLOSION); + task.Repeat(); + }); - if (uiArcainBarrageTimer <= diff) - { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) DoCast(target, SPELL_ARCANE_BARRAGE); - uiArcainBarrageTimer = 6000; - } else uiArcainBarrageTimer -= diff; - } - - if (me->GetEntry() == CREATURE_AZURE_BINDER_2) - { - if (uiFrostNovaTimer <= diff) + task.Repeat(Seconds(6)); + }); + } + else if (me->GetEntry() == NPC_AZURE_BINDER_2) { - DoCast(SPELL_FROST_NOVA); - uiFrostNovaTimer = 5000; - } else uiFrostNovaTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastAOE(SPELL_FROST_NOVA); + task.Repeat(); + }); - if (uiFrostboltTimer <= diff) - { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) - DoCast(target, SPELL_FROSTBOLT); - uiFrostboltTimer = 6000; - } else uiFrostboltTimer -= diff; + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f)) + DoCast(target, SPELL_FROSTBOLT); + task.Repeat(Seconds(6)); + }); + } } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_azure_binderAI>(creature); } - }; - }; class npc_azure_mage_slayer : public CreatureScript { -public: - npc_azure_mage_slayer() : CreatureScript("npc_azure_mage_slayer") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_mage_slayerAI>(creature); - } - - struct npc_azure_mage_slayerAI : public violet_hold_trashAI - { - npc_azure_mage_slayerAI(Creature* creature) : violet_hold_trashAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - uiArcaneEmpowermentTimer = 5000; - uiSpellLockTimer = 5000; - } - - uint32 uiArcaneEmpowermentTimer; - uint32 uiSpellLockTimer; - - void Reset() override - { - Initialize(); - } + public: + npc_azure_mage_slayer() : CreatureScript("npc_azure_mage_slayer") { } - void UpdateAI(uint32 diff) override + struct npc_azure_mage_slayerAI : public violet_hold_trashAI { - violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; + npc_azure_mage_slayerAI(Creature* creature) : violet_hold_trashAI(creature) { } - if (me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_1) + void ScheduledTasks() override { - if (uiArcaneEmpowermentTimer <= diff) + if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_1) { - DoCast(me, SPELL_ARCANE_EMPOWERMENT); - uiArcaneEmpowermentTimer = 14000; - } else uiArcaneEmpowermentTimer -= diff; - } - - if (me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_2) - { - if (uiSpellLockTimer <= diff) + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCast(me, SPELL_ARCANE_EMPOWERMENT); + task.Repeat(Seconds(14)); + }); + } + else if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_2) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) - DoCast(target, SPELL_SPELL_LOCK); - uiSpellLockTimer = 9000; - } else uiSpellLockTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + // wrong spellid? + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_SPELL_LOCK); + task.Repeat(Seconds(9)); + }); + } } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_azure_mage_slayerAI>(creature); } - }; - }; class npc_azure_raider : public CreatureScript { -public: - npc_azure_raider() : CreatureScript("npc_azure_raider") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_raiderAI>(creature); - } - - struct npc_azure_raiderAI : public violet_hold_trashAI - { - npc_azure_raiderAI(Creature* creature) : violet_hold_trashAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - uiConcussionBlowTimer = 5000; - uiMagicReflectionTimer = 8000; - } - - uint32 uiConcussionBlowTimer; - uint32 uiMagicReflectionTimer; - - void Reset() override - { - Initialize(); - } + public: + npc_azure_raider() : CreatureScript("npc_azure_raider") { } - void UpdateAI(uint32 diff) override + struct npc_azure_raiderAI : public violet_hold_trashAI { - violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); + npc_azure_raiderAI(Creature* creature) : violet_hold_trashAI(creature) { } - if (!UpdateVictim()) - return; - - if (uiConcussionBlowTimer <= diff) + void ScheduledTasks() override { - DoCastVictim(SPELL_CONCUSSION_BLOW); - uiConcussionBlowTimer = 5000; - } else uiConcussionBlowTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_CONCUSSION_BLOW); + task.Repeat(); + }); - if (uiMagicReflectionTimer <= diff) - { - DoCast(SPELL_MAGIC_REFLECTION); - uiMagicReflectionTimer = urand(10000, 15000); - } else uiMagicReflectionTimer -= diff; + _scheduler.Schedule(Seconds(8), [this](TaskContext task) + { + DoCast(me, SPELL_MAGIC_REFLECTION); + task.Repeat(Seconds(10), Seconds(15)); + }); + } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_azure_raiderAI>(creature); } - }; - }; class npc_azure_stalker : public CreatureScript { -public: - npc_azure_stalker() : CreatureScript("npc_azure_stalker") { } - - struct npc_azure_stalkerAI : public violet_hold_trashAI - { - npc_azure_stalkerAI(Creature* creature) : violet_hold_trashAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - _backstabTimer = 1300; - _tacticalBlinkTimer = 8000; - _tacticalBlinkCast = false; - } - - void Reset() override - { - Initialize(); - } + public: + npc_azure_stalker() : CreatureScript("npc_azure_stalker") { } - void UpdateAI(uint32 diff) override + struct npc_azure_stalkerAI : public violet_hold_trashAI { - violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; + npc_azure_stalkerAI(Creature* creature) : violet_hold_trashAI(creature) { } - if (!_tacticalBlinkCast) + void ScheduledTasks() override { - if (_tacticalBlinkTimer <= diff) + _scheduler.Schedule(Seconds(8), [this](TaskContext task) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f)) DoCast(target, SPELL_TACTICAL_BLINK); - _tacticalBlinkTimer = 6000; - _tacticalBlinkCast = true; - } else _tacticalBlinkTimer -= diff; - } - else - { - if (_backstabTimer <= diff) - { - Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true); - DoCast(target, SPELL_BACKSTAB); - _tacticalBlinkCast = false; - _backstabTimer =1300; - } else _backstabTimer -= diff; + task.Schedule(Milliseconds(1300), [this](TaskContext /*task*/) + { + if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 5.0f)) + DoCast(target, SPELL_BACKSTAB); + }); + + task.Repeat(); + }); } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_azure_stalkerAI>(creature); } - - private: - uint32 _backstabTimer; - uint32 _tacticalBlinkTimer; - bool _tacticalBlinkCast; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_stalkerAI>(creature); - } }; class npc_azure_spellbreaker : public CreatureScript { -public: - npc_azure_spellbreaker() : CreatureScript("npc_azure_spellbreaker") { } + public: + npc_azure_spellbreaker() : CreatureScript("npc_azure_spellbreaker") { } - struct npc_azure_spellbreakerAI : public violet_hold_trashAI - { - npc_azure_spellbreakerAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_spellbreakerAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_spellbreakerAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiArcaneBlastTimer = 5000; - uiSlowTimer = 4000; - uiChainsOfIceTimer = 5000; - uiConeOfColdTimer = 4000; - } + void ScheduledTasks() override + { + if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_1) + { + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_ARCANE_BLAST); + task.Repeat(Seconds(6)); + }); + + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_SLOW); + task.Repeat(Seconds(5)); + }); + } + else if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_2) + { + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_CHAINS_OF_ICE); + task.Repeat(Seconds(7)); + }); - uint32 uiArcaneBlastTimer; - uint32 uiSlowTimer; - uint32 uiChainsOfIceTimer; - uint32 uiConeOfColdTimer; + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCast(me, SPELL_CONE_OF_COLD); + task.Repeat(Seconds(5)); + }); + } + } + }; - void Reset() override + CreatureAI* GetAI(Creature* creature) const override { - Initialize(); + return GetVioletHoldAI<npc_azure_spellbreakerAI>(creature); } +}; - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_1) - { - if (uiArcaneBlastTimer <= diff) - { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) - DoCast(target, SPELL_ARCANE_BLAST); - uiArcaneBlastTimer = 6000; - } else uiArcaneBlastTimer -= diff; +class npc_azure_captain : public CreatureScript +{ + public: + npc_azure_captain() : CreatureScript("npc_azure_captain") { } - if (uiSlowTimer <= diff) - { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) - DoCast(target, SPELL_SLOW); - uiSlowTimer = 5000; - } else uiSlowTimer -= diff; - } + struct npc_azure_captainAI : public violet_hold_trashAI + { + npc_azure_captainAI(Creature* creature) : violet_hold_trashAI(creature) { } - if (me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_2) + void ScheduledTasks() override { - if (uiChainsOfIceTimer <= diff) + _scheduler.Schedule(Seconds(5), [this](TaskContext task) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) - DoCast(target, SPELL_CHAINS_OF_ICE); - uiChainsOfIceTimer = 7000; - } else uiChainsOfIceTimer -= diff; + DoCastVictim(SPELL_MORTAL_STRIKE); + task.Repeat(); + }); - if (uiConeOfColdTimer <= diff) + _scheduler.Schedule(Seconds(8), [this](TaskContext task) { - DoCast(SPELL_CONE_OF_COLD); - uiConeOfColdTimer = 5000; - } else uiConeOfColdTimer -= diff; + DoCast(me, SPELL_WHIRLWIND_OF_STEEL); + task.Repeat(); + }); } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI<npc_azure_captainAI>(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_spellbreakerAI>(creature); - } }; -class npc_azure_captain : public CreatureScript +class npc_azure_sorceror : public CreatureScript { -public: - npc_azure_captain() : CreatureScript("npc_azure_captain") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_captainAI>(creature); - } + public: + npc_azure_sorceror() : CreatureScript("npc_azure_sorceror") { } - struct npc_azure_captainAI : public violet_hold_trashAI - { - npc_azure_captainAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_sorcerorAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_sorcerorAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiMortalStrikeTimer = 5000; - uiWhirlwindTimer = 8000; - } + void ScheduledTasks() override + { + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 35.0f)) + DoCast(target, SPELL_ARCANE_STREAM); + task.Repeat(Seconds(5), Seconds(10)); + }); - uint32 uiMortalStrikeTimer; - uint32 uiWhirlwindTimer; + _scheduler.Schedule(Seconds(), Seconds(), [this](TaskContext task) + { + DoCastAOE(SPELL_MANA_DETONATION); + task.Repeat(Seconds(2), Seconds(6)); + }); + } + }; - void Reset() override + CreatureAI* GetAI(Creature* creature) const override { - Initialize(); + return GetVioletHoldAI<npc_azure_sorcerorAI>(creature); } +}; - void UpdateAI(uint32 diff) override +class npc_violet_hold_defense_system : public CreatureScript +{ + public: + npc_violet_hold_defense_system() : CreatureScript("npc_violet_hold_defense_system") { } + + struct npc_violet_hold_defense_systemAI : public ScriptedAI { - violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); + npc_violet_hold_defense_systemAI(Creature* creature) : ScriptedAI(creature) { } - if (!UpdateVictim()) - return; + void Reset() override + { + ScheduledTasks(); + me->DespawnOrUnsummon(7000); + } - if (uiMortalStrikeTimer <= diff) + void ScheduledTasks() { - DoCastVictim(SPELL_MORTAL_STRIKE); - uiMortalStrikeTimer = 5000; - } else uiMortalStrikeTimer -= diff; + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCastAOE(SPELL_ARCANE_LIGHTNING_DAMAGE); + DoCastAOE(SPELL_ARCANE_LIGHTNING_DUMMY); + if (task.GetRepeatCounter() == 2) + DoCastAOE(SPELL_ARCANE_LIGHTNING_INSTAKILL); + else + task.Repeat(Seconds(1)); + }); + } - if (uiWhirlwindTimer <= diff) + void UpdateAI(uint32 diff) override { - DoCast(me, SPELL_WHIRLWIND_OF_STEEL); - uiWhirlwindTimer = 8000; - } else uiWhirlwindTimer -= diff; + _scheduler.Update(diff); + } - DoMeleeAttackIfReady(); - } - }; + private: + TaskScheduler _scheduler; + }; + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_violet_hold_defense_systemAI(creature); + } }; -class npc_azure_sorceror : public CreatureScript +class go_activation_crystal : public GameObjectScript { -public: - npc_azure_sorceror() : CreatureScript("npc_azure_sorceror") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_sorcerorAI>(creature); - } - - struct npc_azure_sorcerorAI : public violet_hold_trashAI - { - npc_azure_sorcerorAI(Creature* creature) : violet_hold_trashAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } + public: + go_activation_crystal() : GameObjectScript("go_activation_crystal") { } - void Initialize() + bool OnGossipHello(Player* player, GameObject* /*go*/) override { - uiArcaneStreamTimer = 4000; - uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer; - uiManaDetonationTimer = 5000; + player->CastSpell(player, SPELL_CRYSTAL_ACTIVATION, true); + return false; } +}; - uint32 uiArcaneStreamTimer; - uint32 uiArcaneStreamTimerStartingValueHolder; - uint32 uiManaDetonationTimer; - - void Reset() override - { - Initialize(); - } +// 58040 - Destroy Door Seal +class spell_violet_hold_destroy_door_seal : public SpellScriptLoader +{ + public: + spell_violet_hold_destroy_door_seal() : SpellScriptLoader("spell_violet_hold_destroy_door_seal") { } - void UpdateAI(uint32 diff) override + class spell_violet_hold_destroy_door_seal_AuraScript : public AuraScript { - violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); + PrepareAuraScript(spell_violet_hold_destroy_door_seal_AuraScript); - if (!UpdateVictim()) - return; + bool Load() override + { + _instance = GetUnitOwner()->GetInstanceScript(); + return _instance != nullptr; + } - if (uiArcaneStreamTimer <= diff) + void PeriodicTick(AuraEffect const* /*aurEff*/) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) - DoCast(target, SPELL_ARCANE_STREAM); - uiArcaneStreamTimer = urand(0, 5000)+5000; - uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer; - } else uiArcaneStreamTimer -= diff; - - if (uiManaDetonationTimer <= diff && uiArcaneStreamTimer >=1500 && uiArcaneStreamTimer <= uiArcaneStreamTimerStartingValueHolder/2) + PreventDefaultAction(); + if (uint32 integrity = _instance->GetData(DATA_DOOR_INTEGRITY)) + _instance->SetData(DATA_DOOR_INTEGRITY, integrity - 1); + } + + void Register() override { - DoCast(SPELL_MANA_DETONATION); - uiManaDetonationTimer = urand(2000, 6000); - } else uiManaDetonationTimer -= diff; + OnEffectPeriodic += AuraEffectPeriodicFn(spell_violet_hold_destroy_door_seal_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + + private: + InstanceScript* _instance = nullptr; + }; - DoMeleeAttackIfReady(); + AuraScript* GetAuraScript() const override + { + return new spell_violet_hold_destroy_door_seal_AuraScript(); } - }; }; - -class npc_violet_hold_arcane_sphere : public CreatureScript +// 58008 - Portal Periodic +class spell_violet_hold_portal_periodic : public SpellScriptLoader { -public: - npc_violet_hold_arcane_sphere() : CreatureScript("npc_violet_hold_arcane_sphere") { } + public: + spell_violet_hold_portal_periodic() : SpellScriptLoader("spell_violet_hold_portal_periodic") { } - struct npc_violet_hold_arcane_sphereAI : public ScriptedAI - { - npc_violet_hold_arcane_sphereAI(Creature* creature) : ScriptedAI(creature) + class spell_violet_hold_portal_periodic_AuraScript : public AuraScript { - Initialize(); - } + PrepareAuraScript(spell_violet_hold_portal_periodic_AuraScript); - void Initialize() - { - DespawnTimer = 3000; - } + void PeriodicTick(AuraEffect const* aurEff) + { + PreventDefaultAction(); + if (GetTarget()->IsAIEnabled) + GetTarget()->GetAI()->SetData(DATA_PORTAL_PERIODIC_TICK, aurEff->GetTickNumber()); + } - uint32 DespawnTimer; + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_violet_hold_portal_periodic_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; - void Reset() override + AuraScript* GetAuraScript() const override { - Initialize(); - - me->SetDisableGravity(true); - DoCast(me, SPELL_ARCANE_SPHERE_PASSIVE, true); + return new spell_violet_hold_portal_periodic_AuraScript(); } +}; - void EnterCombat(Unit * /*who*/) override { } +// 62138 - Teleport to Inside Violet Hold +class spell_violet_hold_teleport_player : public SpellScriptLoader +{ + public: + spell_violet_hold_teleport_player() : SpellScriptLoader("spell_violet_hold_teleport_player") { } - void UpdateAI(uint32 diff) override + class spell_violet_hold_teleport_player_SpellScript : public SpellScript { - if (DespawnTimer <= diff) - me->Kill(me); - else - DespawnTimer -= diff; - } - }; + PrepareSpellScript(spell_violet_hold_teleport_player_SpellScript); - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_violet_hold_arcane_sphereAI(creature); - } -}; + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_TELEPORT_PLAYER_EFFECT)) + return false; + return true; + } -class go_activation_crystal : public GameObjectScript -{ -public: - go_activation_crystal() : GameObjectScript("go_activation_crystal") { } + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->CastSpell(target, SPELL_TELEPORT_PLAYER_EFFECT, true); + } - bool OnGossipHello(Player * /*player*/, GameObject* go) override - { - go->EventInform(EVENT_ACTIVATE_CRYSTAL); - return false; - } + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_violet_hold_teleport_player_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_violet_hold_teleport_player_SpellScript(); + } }; void AddSC_violet_hold() { new npc_sinclari_vh(); - new npc_teleportation_portal_vh(); + new npc_violet_hold_teleportation_portal(); + new npc_violet_hold_teleportation_portal_elite(); + new npc_violet_hold_teleportation_portal_intro(); new npc_azure_invader(); new npc_azure_spellbreaker(); new npc_azure_binder(); @@ -1432,6 +1431,9 @@ void AddSC_violet_hold() new npc_azure_raider(); new npc_azure_stalker(); new npc_azure_saboteur(); - new npc_violet_hold_arcane_sphere(); + new npc_violet_hold_defense_system(); new go_activation_crystal(); + new spell_violet_hold_destroy_door_seal(); + new spell_violet_hold_portal_periodic(); + new spell_violet_hold_teleport_player(); } diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.h b/src/server/scripts/Northrend/VioletHold/violet_hold.h index 404d1f493e6..113a3c46ea0 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.h +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.h @@ -15,42 +15,58 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_VIOLET_HOLD_H -#define DEF_VIOLET_HOLD_H +#ifndef VIOLET_HOLD_H_ +#define VIOLET_HOLD_H_ -#define DataHeader "VIO" +#define VioletHoldScriptName "instance_violet_hold" +#define DataHeader "VH" + +uint32 const EncounterCount = 3 + 6; + +// Defined in instance_violet_hold.cpp +extern Position const DefenseSystemLocation; +uint8 const PortalIntroCount = 3; +extern Position const PortalIntroPositions[]; + +/* + * Violet hold bosses: + * + * 1 - Moragg + * 2 - Erekem + * 3 - Ichoron + * 4 - Lavanthor + * 5 - Xevozz + * 6 - Zuramat + * 7 - Cyanigosa + */ enum Data { - DATA_1ST_BOSS_EVENT, - DATA_2ND_BOSS_EVENT, - DATA_CYANIGOSA_EVENT, + // Main encounters + DATA_1ST_BOSS = 0, + DATA_2ND_BOSS = 1, + DATA_CYANIGOSA = 2, + // Bosses + DATA_MORAGG = 3, + DATA_EREKEM = 4, + DATA_ICHORON = 5, + DATA_LAVANTHOR = 6, + DATA_XEVOZZ = 7, + DATA_ZURAMAT = 8, + + // Misc + DATA_MAIN_EVENT_STATE, DATA_WAVE_COUNT, - DATA_REMOVE_NPC, - DATA_PORTAL_LOCATION, DATA_DOOR_INTEGRITY, - DATA_NPC_PRESENCE_AT_DOOR, - DATA_NPC_PRESENCE_AT_DOOR_ADD, - DATA_NPC_PRESENCE_AT_DOOR_REMOVE, + DATA_PORTAL_LOCATION, DATA_START_BOSS_ENCOUNTER, - DATA_FIRST_BOSS, - DATA_SECOND_BOSS, - DATA_ACTIVATE_CRYSTAL, - DATA_MAIN_EVENT_PHASE, DATA_DEFENSELESS, -}; -enum Data64 -{ - DATA_MORAGG, - DATA_EREKEM, + // Bosses DATA_EREKEM_GUARD_1, DATA_EREKEM_GUARD_2, - DATA_ICHORON, - DATA_LAVANTHOR, - DATA_XEVOZZ, - DATA_ZURAMAT, - DATA_CYANIGOSA, + + // Cells DATA_MORAGG_CELL, DATA_EREKEM_CELL, DATA_EREKEM_LEFT_GUARD_CELL, @@ -59,55 +75,86 @@ enum Data64 DATA_LAVANTHOR_CELL, DATA_XEVOZZ_CELL, DATA_ZURAMAT_CELL, + + // Misc DATA_MAIN_DOOR, DATA_SINCLARI, - DATA_TELEPORTATION_PORTAL, - DATA_SABOTEUR_PORTAL, - DATA_ADD_TRASH_MOB, - DATA_DEL_TRASH_MOB + DATA_SINCLARI_TRIGGER, + DATA_HANDLE_CELLS }; -enum Bosses +enum CreaturesIds { - BOSS_NONE, // 0 used as marker for not yet randomized - BOSS_MORAGG, - BOSS_EREKEM, - BOSS_ICHORON, - BOSS_LAVANTHOR, - BOSS_XEVOZZ, - BOSS_ZURAMAT, - BOSS_CYANIGOSA + NPC_TELEPORTATION_PORTAL = 30679, + NPC_TELEPORTATION_PORTAL_ELITE = 32174, + NPC_TELEPORTATION_PORTAL_INTRO = 31011, + NPC_PORTAL_GUARDIAN = 30660, + NPC_PORTAL_KEEPER = 30695, + NPC_XEVOZZ = 29266, + NPC_LAVANTHOR = 29312, + NPC_ICHORON = 29313, + NPC_ICHOR_GLOBULE = 29321, + NPC_ICHORON_SUMMON_TARGET = 29326, + NPC_ZURAMAT = 29314, + NPC_VOID_SENTRY = 29364, + NPC_VOID_SENTRY_BALL = 29365, + NPC_EREKEM = 29315, + NPC_EREKEM_GUARD = 29395, + NPC_MORAGG = 29316, + + NPC_DUMMY_XEVOZZ = 32231, + NPC_DUMMY_LAVANTHOR = 32237, + NPC_DUMMY_ICHORON = 32234, + NPC_DUMMY_ZURAMAT = 32230, + NPC_DUMMY_EREKEM = 32226, + NPC_DUMMY_EREKEM_GUARD = 32228, + NPC_DUMMY_MORAGG = 32235, + + NPC_CYANIGOSA = 31134, + NPC_SINCLARI = 30658, + NPC_SINCLARI_TRIGGER = 32204, + NPC_SABOTEOUR = 31079, + NPC_VIOLET_HOLD_GUARD = 30659, + NPC_DEFENSE_SYSTEM = 30837 }; -enum CreaturesIds +enum GameObjectIds { - CREATURE_TELEPORTATION_PORTAL = 31011, - CREATURE_PORTAL_GUARDIAN = 30660, - CREATURE_PORTAL_KEEPER = 30695, - CREATURE_XEVOZZ = 29266, - CREATURE_LAVANTHOR = 29312, - CREATURE_ICHORON = 29313, - CREATURE_ZURAMAT = 29314, - CREATURE_EREKEM = 29315, - CREATURE_EREKEM_GUARD = 29395, - CREATURE_MORAGG = 29316, - CREATURE_CYANIGOSA = 31134, - CREATURE_SINCLARI = 30658, - CREATURE_SABOTEOUR = 31079, - NPC_VIOLET_HOLD_GUARD = 30659, - NPC_DEFENSE_SYSTEM = 30837 + GO_MAIN_DOOR = 191723, + GO_XEVOZZ_DOOR = 191556, + GO_LAVANTHOR_DOOR = 191566, + GO_ICHORON_DOOR = 191722, + GO_ZURAMAT_DOOR = 191565, + GO_EREKEM_DOOR = 191564, + GO_EREKEM_GUARD_1_DOOR = 191563, + GO_EREKEM_GUARD_2_DOOR = 191562, + GO_MORAGG_DOOR = 191606, + GO_ACTIVATION_CRYSTAL = 193611, + GO_INTRO_ACTIVATION_CRYSTAL = 193615 }; enum WorldStateIds { - WORLD_STATE_VH = 3816, - WORLD_STATE_VH_PRISON_STATE = 3815, - WORLD_STATE_VH_WAVE_COUNT = 3810, + WORLD_STATE_VH_SHOW = 3816, + WORLD_STATE_VH_PRISON_STATE = 3815, + WORLD_STATE_VH_WAVE_COUNT = 3810, }; enum Events { - EVENT_ACTIVATE_CRYSTAL = 20001 + EVENT_ACTIVATE_CRYSTAL = 20001 }; -#endif +enum InstanceMisc +{ + ACTION_SINCLARI_OUTRO = 1, + POINT_INTRO = 1 +}; + +template<class AI> +inline AI* GetVioletHoldAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, VioletHoldScriptName); +} + +#endif // VIOLET_HOLD_H_ diff --git a/src/server/scripts/Northrend/isle_of_conquest.cpp b/src/server/scripts/Northrend/isle_of_conquest.cpp index ba21b60f11d..fccdc8098b6 100644 --- a/src/server/scripts/Northrend/isle_of_conquest.cpp +++ b/src/server/scripts/Northrend/isle_of_conquest.cpp @@ -161,19 +161,6 @@ class spell_ioc_gunship_portal : public SpellScriptLoader * Position: X: 7.305609 Y: -0.095246 Z: 34.51022 O: 0 */ caster->TeleportTo(GetHitCreature()->GetWorldLocation(), TELE_TO_NOT_LEAVE_TRANSPORT); - /* - * HACK: This aura should be added by 20212 and 20213 but can't find any SMSG_SPELL_GO. Could't find their position. - * ServerToClient: SMSG_AURA_UPDATE (0x0072) - * [0] CasterGUID: Full: xxxxx Type: Unit Entry: 20212 Low: xxx - * [0] Flags: None (0) - * [0] Caster Level: 60 - * [0] Spell ID: 66656 - * [0] Charges: 0 - * [0] Effect Mask: 1 - * [0] Slot: 37 - * Guid: Full: xxxxx Type: Player2 Low: xxxxx - */ - caster->AddAura(SPELL_PARACHUTE, caster); } void Register() override @@ -219,7 +206,7 @@ class spell_ioc_parachute_ic : public SpellScriptLoader class StartLaunchEvent : public BasicEvent { public: - StartLaunchEvent(float x, float y, float z, uint32 lowGuid) : _x(x), _y(y), _z(z), _lowGuid(lowGuid) + StartLaunchEvent(float x, float y, float z, ObjectGuid::LowType lowGuid) : _x(x), _y(y), _z(z), _lowGuid(lowGuid) { } @@ -240,7 +227,7 @@ class StartLaunchEvent : public BasicEvent private: float _x, _y, _z; - uint32 _lowGuid; + ObjectGuid::LowType _lowGuid; }; class spell_ioc_launch : public SpellScriptLoader @@ -261,7 +248,7 @@ class spell_ioc_launch : public SpellScriptLoader x = GetExplTargetDest()->GetPositionX(); y = GetExplTargetDest()->GetPositionY(); z = GetExplTargetDest()->GetPositionZ(); - GetCaster()->ToCreature()->m_Events.AddEvent(new StartLaunchEvent(x, y, z, GetHitPlayer()->GetGUIDLow()), GetCaster()->ToCreature()->m_Events.CalculateTime(2500)); + GetCaster()->ToCreature()->m_Events.AddEvent(new StartLaunchEvent(x, y, z, GetHitPlayer()->GetGUID().GetCounter()), GetCaster()->ToCreature()->m_Events.CalculateTime(2500)); } void Register() override diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 280a94aa21f..6ef9abe2267 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -596,12 +596,13 @@ public: switch (IntroPhase) { case 1: - Talk(SAY_START_1); + if (Player* player = GetPlayerForEscort()) + Talk(SAY_START_1, player); IntroPhase = 2; IntroTimer = 7500; break; case 2: - Talk(SAY_END_1); + Talk(SAY_START_2); IntroPhase = 3; IntroTimer = 7500; break; @@ -611,12 +612,13 @@ public: IntroTimer = 0; break; case 4: - Talk(SAY_START_2); + Talk(SAY_END_1); IntroPhase = 5; IntroTimer = 8000; break; case 5: - Talk(SAY_END_2); + if (Player* player = GetPlayerForEscort()) + Talk(SAY_END_2, player); IntroPhase = 6; IntroTimer = 2500; break; @@ -1324,7 +1326,7 @@ public: arlos->AI()->Talk(SAY_ARLOS_1); arlos->AI()->Talk(SAY_ARLOS_2); leryssa->AI()->Talk(SAY_LERYSSA_1); - arlos->Kill(arlos, false); + arlos->KillSelf(false); leryssa->RemoveAura(SPELL_STUN); leryssa->ClearUnitState(UNIT_STATE_STUNNED); leryssa->SetWalk(false); @@ -1819,7 +1821,7 @@ public: player->FailQuest(QUEST_GET_ME_OUTA_HERE); } - void UpdateEscortAI(const uint32 /*diff*/) override + void UpdateEscortAI(uint32 /*diff*/) override { if (GetAttack() && UpdateVictim()) { diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 83fd3859716..54b06260e78 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -762,7 +762,7 @@ public: } } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { DoCast(player, SPELL_SUMMON_ASHWOOD_BRAND); } diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp index fe72a2cedf7..ba69a1385d5 100644 --- a/src/server/scripts/Northrend/zone_howling_fjord.cpp +++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp @@ -98,7 +98,7 @@ public: player->FailQuest(QUEST_TRAIL_OF_FIRE); } - void UpdateEscortAI(const uint32 diff) override + void UpdateEscortAI(uint32 diff) override { if (HealthBelowPct(75)) { diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index d5d2eebda38..5d47e7fa4ec 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -622,17 +622,17 @@ public: enum MiscLifewarden { - NPC_PRESENCE = 28563, // Freya's Presence - NPC_SABOTEUR = 28538, // Cultist Saboteur - NPC_SERVANT = 28320, // Servant of Freya + NPC_PRESENCE = 28563, // Freya's Presence + NPC_SABOTEUR = 28538, // Cultist Saboteur + NPC_SERVANT = 28320, // Servant of Freya - WHISPER_ACTIVATE = 0, + WHISPER_ACTIVATE = 0, - SPELL_FREYA_DUMMY = 51318, - SPELL_LIFEFORCE = 51395, - SPELL_FREYA_DUMMY_TRIGGER = 51335, - SPELL_LASHER_EMERGE = 48195, - SPELL_WILD_GROWTH = 52948, + SPELL_FREYA_DUMMY = 51318, + SPELL_LIFEFORCE = 51395, + SPELL_FREYA_DUMMY_TRIGGER = 51335, + SPELL_LASHER_EMERGE = 48195, + SPELL_WILD_GROWTH = 52948, }; class spell_q12620_the_lifewarden_wrath : public SpellScriptLoader @@ -702,25 +702,25 @@ public: enum KickWhatKick { - NPC_LUCKY_WILHELM = 28054, - NPC_APPLE = 28053, - NPC_DROSTAN = 28328, - NPC_CRUNCHY = 28346, - NPC_THICKBIRD = 28093, - - SPELL_HIT_APPLE = 51331, - SPELL_MISS_APPLE = 51332, - SPELL_MISS_BIRD_APPLE = 51366, - SPELL_APPLE_FALL = 51371, - SPELL_BIRD_FALL = 51369, - - EVENT_MISS = 0, - EVENT_HIT = 1, - EVENT_MISS_BIRD = 2, - - SAY_WILHELM_MISS = 0, - SAY_WILHELM_HIT = 1, - SAY_DROSTAN_REPLY_MISS = 0, + NPC_LUCKY_WILHELM = 28054, + NPC_APPLE = 28053, + NPC_DROSTAN = 28328, + NPC_CRUNCHY = 28346, + NPC_THICKBIRD = 28093, + + SPELL_HIT_APPLE = 51331, + SPELL_MISS_APPLE = 51332, + SPELL_MISS_BIRD_APPLE = 51366, + SPELL_APPLE_FALL = 51371, + SPELL_BIRD_FALL = 51369, + + EVENT_MISS = 0, + EVENT_HIT = 1, + EVENT_MISS_BIRD = 2, + + SAY_WILHELM_MISS = 0, + SAY_WILHELM_HIT = 1, + SAY_DROSTAN_REPLY_MISS = 0, }; class spell_q12589_shoot_rjr : public SpellScriptLoader @@ -778,7 +778,7 @@ public: wilhelm->AI()->Talk(SAY_WILHELM_MISS); drostan->AI()->Talk(SAY_DROSTAN_REPLY_MISS); - bird->Kill(bird); + bird->KillSelf(); crunchy->GetMotionMaster()->MovePoint(0, bird->GetPositionX(), bird->GetPositionY(), bird->GetMap()->GetWaterOrGroundLevel(bird->GetPositionX(), bird->GetPositionY(), bird->GetPositionZ())); /// @todo Make crunchy perform emote eat when he reaches the bird @@ -800,8 +800,6 @@ public: wilhelm->AI()->Talk(SAY_WILHELM_HIT); if (Player* player = shooter->ToPlayer()) player->KilledMonsterCredit(NPC_APPLE); - apple->DespawnOrUnsummon(); - break; } } @@ -828,11 +826,11 @@ may be easily converted to SAI when they get.*/ enum SongOfWindAndWater { // Spells - SPELL_DEVOUR_WIND = 52862, - SPELL_DEVOUR_WATER = 52864, + SPELL_DEVOUR_WIND = 52862, + SPELL_DEVOUR_WATER = 52864, // NPCs - NPC_HAIPHOON_WATER = 28999, - NPC_HAIPHOON_AIR = 28985 + NPC_HAIPHOON_WATER = 28999, + NPC_HAIPHOON_AIR = 28985 }; class npc_haiphoon : public CreatureScript @@ -883,7 +881,7 @@ enum ReconnaissanceFlight VIC_SAY_6 = 6, PLANE_EMOTE = 0, - SPELL_ENGINE = 52255, // Engine on Fire + SPELL_ENGINE = 52255, // Engine on Fire SPELL_LAND = 52226, // Land Flying Machine SPELL_CREDIT = 53328 // Land Flying Machine Credit diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index d5d9f8ae77e..e86e907b550 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -85,13 +85,13 @@ public: DoMeleeAttackIfReady(); } - void sGossipSelect(Player* player, uint32 sender, uint32 action) override + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override { - if (sender == GOSSIP_ID && action == GOSSIP_OPTION_ID) + if (menuId == GOSSIP_ID && gossipListId == GOSSIP_OPTION_ID) { player->CLOSE_GOSSIP_MENU(); me->setFaction(113); - npc_escortAI::Start(true, true, player->GetGUID()); + Start(true, true, player->GetGUID()); } } }; @@ -381,7 +381,7 @@ class npc_hyldsmeet_protodrake : public CreatureScript class npc_hyldsmeet_protodrakeAI : public CreatureAI { public: - npc_hyldsmeet_protodrakeAI(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0), _vehicleKit(creature->GetVehicleKit()) { } + npc_hyldsmeet_protodrakeAI(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0) { } void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override { @@ -396,6 +396,7 @@ class npc_hyldsmeet_protodrake : public CreatureScript { //! We need to manually reinstall accessories because the vehicle itself is friendly to players, //! so EnterEvadeMode is never triggered. The accessory on the other hand is hostile and killable. + Vehicle* _vehicleKit = me->GetVehicleKit(); if (_accessoryRespawnTimer && _accessoryRespawnTimer <= diff && _vehicleKit) { _vehicleKit->InstallAllAccessories(true); @@ -407,7 +408,6 @@ class npc_hyldsmeet_protodrake : public CreatureScript private: uint32 _accessoryRespawnTimer; - Vehicle* _vehicleKit; }; CreatureAI* GetAI(Creature* creature) const override @@ -476,7 +476,7 @@ public: objectCounter = 0; } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { player->CLOSE_GOSSIP_MENU(); playerGUID = player->GetGUID(); diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp index 91c796a6e69..e36930f5745 100644 --- a/src/server/scripts/Northrend/zone_zuldrak.cpp +++ b/src/server/scripts/Northrend/zone_zuldrak.cpp @@ -267,7 +267,7 @@ public: return; } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { _events.ScheduleEvent(EVENT_RECRUIT_1, 100); player->CLOSE_GOSSIP_MENU(); @@ -552,7 +552,7 @@ public: } } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { player->CLOSE_GOSSIP_MENU(); DoCast(player, SPELL_ALCHEMIST_APPRENTICE_INVISBUFF); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp index dec236e5f33..89f35457a44 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPEP.h" #include "WorldPacket.h" @@ -70,16 +71,14 @@ void OPvPCapturePointEP_EWT::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[EP_EWT_FLAGS]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit); - } + Map* map = sMapMgr->FindMap(0, 0); + auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); + + bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_Objects[EP_EWT_FLAGS]); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); UpdateTowerState(); @@ -180,16 +179,14 @@ void OPvPCapturePointEP_NPT::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[EP_NPT_FLAGS]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit); - } + Map* map = sMapMgr->FindMap(0, 0); + auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); + + bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_Objects[EP_NPT_FLAGS]); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); UpdateTowerState(); @@ -223,9 +220,12 @@ void OPvPCapturePointEP_NPT::SummonGO(uint32 team) m_SummonedGOSide = team; DelObject(EP_NPT_BUFF); AddObject(EP_NPT_BUFF, EP_NPT_LordaeronShrine.entry, EP_NPT_LordaeronShrine.map, EP_NPT_LordaeronShrine.x, EP_NPT_LordaeronShrine.y, EP_NPT_LordaeronShrine.z, EP_NPT_LordaeronShrine.o, EP_NPT_LordaeronShrine.rot0, EP_NPT_LordaeronShrine.rot1, EP_NPT_LordaeronShrine.rot2, EP_NPT_LordaeronShrine.rot3); - GameObject* go = HashMapHolder<GameObject>::Find(m_Objects[EP_NPT_BUFF]); - if (go) - go->SetUInt32Value(GAMEOBJECT_FACTION, (team == ALLIANCE ? 84 : 83)); + + Map* map = sMapMgr->FindMap(0, 0); + auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_Objects[EP_NPT_BUFF]); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + if (GameObject* go = itr->second) + go->SetUInt32Value(GAMEOBJECT_FACTION, (team == ALLIANCE ? 84 : 83)); } } @@ -274,16 +274,14 @@ void OPvPCapturePointEP_CGT::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[EP_CGT_FLAGS]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit); - } + Map* map = sMapMgr->FindMap(0, 0); + auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); + + bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_Objects[EP_CGT_FLAGS]); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); UpdateTowerState(); @@ -375,16 +373,14 @@ void OPvPCapturePointEP_PWT::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[EP_PWT_FLAGS]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit); - } + Map* map = sMapMgr->FindMap(0, 0); + auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); + + bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_Objects[EP_PWT_FLAGS]); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); UpdateTowerState(); @@ -479,6 +475,7 @@ bool OutdoorPvPEP::SetupOutdoorPvP() AddCapturePoint(new OPvPCapturePointEP_PWT(this)); AddCapturePoint(new OPvPCapturePointEP_CGT(this)); AddCapturePoint(new OPvPCapturePointEP_NPT(this)); + SetMapFromZone(EPBuffZones[0]); return true; } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp index f8a7647a1d5..a639962efde 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPHP.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPHP.h" #include "OutdoorPvP.h" @@ -58,6 +59,7 @@ OutdoorPvPHP::OutdoorPvPHP() m_TypeId = OUTDOOR_PVP_HP; m_AllianceTowersControlled = 0; m_HordeTowersControlled = 0; + SetMapFromZone(OutdoorPvPHPBuffZones[0]); } bool OutdoorPvPHP::SetupOutdoorPvP() @@ -238,16 +240,14 @@ void OPvPCapturePointHP::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - GameObject* flag2 = HashMapHolder<GameObject>::Find(m_Objects[m_TowerType]); - if (flag) - { - flag->SetGoArtKit(artkit); - } - if (flag2) - { - flag2->SetGoArtKit(artkit2); - } + Map* map = sMapMgr->FindMap(530, 0); + auto bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); + + bounds = map->GetGameObjectBySpawnIdStore().equal_range(m_Objects[m_TowerType]); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit2); // send world state update if (field) diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp index 761e12b226c..8664acdfc57 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPNA.h" #include "Player.h" @@ -43,7 +44,7 @@ void OutdoorPvPNA::HandleKillImpl(Player* player, Unit* killed) uint32 OPvPCapturePointNA::GetAliveGuardsCount() { uint32 cnt = 0; - for (std::map<uint32, ObjectGuid>::iterator itr = m_Creatures.begin(); itr != m_Creatures.end(); ++itr) + for (std::map<uint32, uint32>::iterator itr = m_Creatures.begin(); itr != m_Creatures.end(); ++itr) { switch (itr->first) { @@ -62,10 +63,13 @@ uint32 OPvPCapturePointNA::GetAliveGuardsCount() case NA_NPC_GUARD_13: case NA_NPC_GUARD_14: case NA_NPC_GUARD_15: - if (Creature const* const cr = HashMapHolder<Creature>::Find(itr->second)) - if (cr->IsAlive()) + { + auto bounds = m_PvP->GetMap()->GetCreatureBySpawnIdStore().equal_range(itr->second); + for (auto itr2 = bounds.first; itr2 != bounds.second; ++itr2) + if (itr2->second->IsAlive()) ++cnt; break; + } default: break; } @@ -186,6 +190,7 @@ bool OutdoorPvPNA::SetupOutdoorPvP() { // m_TypeId = OUTDOOR_PVP_NA; _MUST_ be set in ctor, because of spawns cleanup // add the zones affected by the pvp buff + SetMapFromZone(NA_BUFF_ZONE); RegisterZone(NA_BUFF_ZONE); // halaa @@ -372,9 +377,9 @@ bool OPvPCapturePointNA::HandleCustomSpell(Player* player, uint32 spellId, GameO return false; } -int32 OPvPCapturePointNA::HandleOpenGo(Player* player, ObjectGuid guid) +int32 OPvPCapturePointNA::HandleOpenGo(Player* player, GameObject* go) { - int32 retval = OPvPCapturePoint::HandleOpenGo(player, guid); + int32 retval = OPvPCapturePoint::HandleOpenGo(player, go); if (retval >= 0) { const go_type * gos = NULL; @@ -567,11 +572,9 @@ void OPvPCapturePointNA::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - if (flag) - { - flag->SetGoArtKit(artkit); - } + auto bounds = sMapMgr->FindMap(530, 0)->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); UpdateHalaaWorldState(); } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h index fac9d8fa357..07bf6919b7a 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h @@ -269,7 +269,7 @@ class OPvPCapturePointNA : public OPvPCapturePoint bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go) override; - int32 HandleOpenGo(Player* player, ObjectGuid guid) override; + int32 HandleOpenGo(Player* player, GameObject* go) override; uint32 GetAliveGuardsCount(); uint32 GetControllingFaction() const; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp index f052824538e..d2892541373 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPSI.cpp @@ -58,6 +58,8 @@ void OutdoorPvPSI::UpdateWorldState() bool OutdoorPvPSI::SetupOutdoorPvP() { + SetMapFromZone(OutdoorPvPSIBuffZones[0]); + for (uint8 i = 0; i < OutdoorPvPSIBuffZonesNum; ++i) RegisterZone(OutdoorPvPSIBuffZones[i]); return true; @@ -160,13 +162,8 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId) // he dropped it further, summon mound GameObject* go = new GameObject; Map* map = player->GetMap(); - if (!map) - { - delete go; - return true; - } - if (!go->Create(sObjectMgr->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->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) { delete go; return true; @@ -194,13 +191,8 @@ bool OutdoorPvPSI::HandleDropFlag(Player* player, uint32 spellId) // he dropped it further, summon mound GameObject* go = new GameObject; Map* map = player->GetMap(); - if (!map) - { - delete go; - return true; - } - if (!go->Create(sObjectMgr->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->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) { delete go; return true; diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp index 17736c7747b..0b68a45f8a5 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPTF.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPTF.h" #include "OutdoorPvPMgr.h" @@ -227,6 +228,8 @@ bool OutdoorPvPTF::SetupOutdoorPvP() second_digit = 0; first_digit = 0; + SetMapFromZone(OutdoorPvPTFBuffZones[0]); + // add the zones affected by the pvp buff for (uint8 i = 0; i < OutdoorPvPTFBuffZonesNum; ++i) RegisterZone(OutdoorPvPTFBuffZones[i]); @@ -310,9 +313,9 @@ void OPvPCapturePointTF::ChangeState() break; } - GameObject* flag = HashMapHolder<GameObject>::Find(m_capturePointGUID); - if (flag) - flag->SetGoArtKit(artkit); + auto bounds = sMapMgr->FindMap(530, 0)->GetGameObjectBySpawnIdStore().equal_range(m_capturePointSpawnId); + for (auto itr = bounds.first; itr != bounds.second; ++itr) + itr->second->SetGoArtKit(artkit); UpdateTowerState(); } diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp index ee86d8efc90..54aa815617e 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.cpp @@ -15,6 +15,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "MapManager.h" #include "ScriptMgr.h" #include "OutdoorPvPZM.h" #include "ObjectMgr.h" @@ -151,6 +152,8 @@ bool OutdoorPvPZM::SetupOutdoorPvP() m_AllianceTowersControlled = 0; m_HordeTowersControlled = 0; + SetMapFromZone(OutdoorPvPZMBuffZones[0]); + // add the zones affected by the pvp buff for (uint8 i = 0; i < OutdoorPvPZMBuffZonesNum; ++i) RegisterZone(OutdoorPvPZMBuffZones[i]); @@ -181,9 +184,9 @@ bool OPvPCapturePointZM_GraveYard::Update(uint32 /*diff*/) return retval; } -int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, ObjectGuid guid) +int32 OPvPCapturePointZM_GraveYard::HandleOpenGo(Player* player, GameObject* go) { - int32 retval = OPvPCapturePoint::HandleOpenGo(player, guid); + int32 retval = OPvPCapturePoint::HandleOpenGo(player, go); if (retval >= 0) { if (player->HasAura(ZM_BATTLE_STANDARD_A) && m_GraveYardState != ZM_GRAVEYARD_A) @@ -297,8 +300,8 @@ void OPvPCapturePointZM_GraveYard::SetBeaconState(uint32 controlling_faction) bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player* player, Creature* c, GossipMenuItems const& /*gso*/) { - ObjectGuid guid = c->GetGUID(); - std::map<ObjectGuid, uint32>::iterator itr = m_CreatureTypes.find(guid); + std::map<uint32, uint32>::iterator itr = m_CreatureTypes.find(c->GetSpawnId()); + if (itr != m_CreatureTypes.end()) { if (itr->second == ZM_ALLIANCE_FIELD_SCOUT && player->GetTeam() == ALLIANCE && m_BothControllingFaction == ALLIANCE && !m_FlagCarrierGUID && m_GraveYardState != ZM_GRAVEYARD_A) @@ -309,25 +312,23 @@ bool OPvPCapturePointZM_GraveYard::CanTalkTo(Player* player, Creature* c, Gossip return false; } -bool OPvPCapturePointZM_GraveYard::HandleGossipOption(Player* player, ObjectGuid guid, uint32 /*gossipid*/) +bool OPvPCapturePointZM_GraveYard::HandleGossipOption(Player* player, Creature* creature, uint32 /*gossipid*/) { - std::map<ObjectGuid, uint32>::iterator itr = m_CreatureTypes.find(guid); + std::map<uint32, uint32>::iterator itr = m_CreatureTypes.find(creature->GetSpawnId()); + if (itr != m_CreatureTypes.end()) { - Creature* cr = HashMapHolder<Creature>::Find(guid); - if (!cr) - return true; // if the flag is already taken, then return if (m_FlagCarrierGUID) return true; if (itr->second == ZM_ALLIANCE_FIELD_SCOUT) { - cr->CastSpell(player, ZM_BATTLE_STANDARD_A, true); + creature->CastSpell(player, ZM_BATTLE_STANDARD_A, true); m_FlagCarrierGUID = player->GetGUID(); } else if (itr->second == ZM_HORDE_FIELD_SCOUT) { - cr->CastSpell(player, ZM_BATTLE_STANDARD_H, true); + creature->CastSpell(player, ZM_BATTLE_STANDARD_H, true); m_FlagCarrierGUID = player->GetGUID(); } UpdateTowerState(); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h index 9c76b35937e..4be0d0eedb7 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPZM.h @@ -188,15 +188,15 @@ class OPvPCapturePointZM_GraveYard : public OPvPCapturePoint void ChangeState() override { } - void FillInitialWorldStates(WorldPacket & data); + void FillInitialWorldStates(WorldPacket & data) override; void UpdateTowerState(); - int32 HandleOpenGo(Player* player, ObjectGuid guid) override; + int32 HandleOpenGo(Player* player, GameObject* go) override; void SetBeaconState(uint32 controlling_team); // not good atm - bool HandleGossipOption(Player* player, ObjectGuid guid, uint32 gossipid) override; + bool HandleGossipOption(Player* player, Creature* creature, uint32 gossipid) override; bool HandleDropFlag(Player* player, uint32 spellId) override; diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp index 263fd8340b9..6e43cfa2d0f 100644 --- a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp +++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp @@ -109,8 +109,7 @@ public: if (Inhibitmagic_Timer <= diff) { float dist; - Map* map = me->GetMap(); - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) if (Player* i_pl = i->GetSource()) if (i_pl->IsAlive() && (dist = i_pl->GetDistance(me)) < 45) diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp index 9667b4e3bb0..80cc2028cb3 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp @@ -136,7 +136,7 @@ class boss_ambassador_hellmaw : public CreatureScript Talk(SAY_DEATH); } - void UpdateEscortAI(uint32 const diff) override + void UpdateEscortAI(uint32 diff) override { if (!UpdateVictim()) return; diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp index d0e12c87a55..04d3a20d945 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp @@ -182,8 +182,7 @@ class boss_grandmaster_vorpil : public CreatureScript break; case EVENT_DRAW_SHADOWS: { - Map* map = me->GetMap(); - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) if (Player* i_pl = i->GetSource()) if (i_pl->IsAlive() && !i_pl->HasAura(SPELL_BANISH)) @@ -258,7 +257,7 @@ class npc_voidtraveler : public CreatureScript { DoCastAOE(SPELL_EMPOWERING_SHADOWS, true); DoCast(me, SPELL_SHADOW_NOVA, true); - me->Kill(me); + me->KillSelf(); return; } me->GetMotionMaster()->MoveFollow(Vorpil, 0, 0); diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.cpp b/src/server/scripts/Outland/BlackTemple/black_temple.cpp index 764cd9594ea..f044fcef5c7 100644 --- a/src/server/scripts/Outland/BlackTemple/black_temple.cpp +++ b/src/server/scripts/Outland/BlackTemple/black_temple.cpp @@ -15,22 +15,12 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* -Name: Black_Temple -Complete: 100% -Comment: Spirit of Olum: Player Teleporter to Seer Kanai Teleport after defeating Naj'entus and Supremus. -*/ - #include "ScriptMgr.h" #include "ScriptedCreature.h" -#include "ScriptedGossip.h" #include "black_temple.h" -#include "Player.h" enum Spells { - // Spirit of Olum - SPELL_TELEPORT = 41566, // Wrathbone Flayer SPELL_CLEAVE = 15496, SPELL_IGNORED = 39544, @@ -53,36 +43,6 @@ enum Events }; // ######################################################## -// Spirit of Olum -// ######################################################## - -class npc_spirit_of_olum : public CreatureScript -{ -public: - npc_spirit_of_olum() : CreatureScript("npc_spirit_of_olum") { } - - struct npc_spirit_of_olumAI : public ScriptedAI - { - npc_spirit_of_olumAI(Creature* creature) : ScriptedAI(creature) { } - - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override - { - if (action == 1) - { - player->CLOSE_GOSSIP_MENU(); - player->InterruptNonMeleeSpells(false); - player->CastSpell(player, SPELL_TELEPORT, false); - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_spirit_of_olumAI(creature); - } -}; - -// ######################################################## // Wrathbone Flayer // ######################################################## @@ -123,7 +83,6 @@ public: void UpdateAI(uint32 diff) override { - if (!_enteredCombat) { _events.Update(diff); @@ -215,12 +174,11 @@ public: CreatureAI* GetAI(Creature* creature) const override { - return GetInstanceAI<npc_wrathbone_flayerAI>(creature); + return GetBlackTempleAI<npc_wrathbone_flayerAI>(creature); } }; void AddSC_black_temple() { - new npc_spirit_of_olum(); new npc_wrathbone_flayer(); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 7cc460d4548..f8c031f69e7 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -1779,7 +1779,7 @@ public: DoMeleeAttackIfReady(); } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { player->CLOSE_GOSSIP_MENU(); EnterPhase(PHASE_CHANNEL); 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 e4369f0348d..25ff1bf9536 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -519,9 +519,9 @@ public: DoMeleeAttackIfReady(); } - void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) override + void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override { - if (action == 0) + if (gossipListId == 0) { player->CLOSE_GOSSIP_MENU(); StartChannel = true; diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp index 61b202fcfeb..0bc6a4f49a4 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp @@ -1,215 +1,215 @@ -/*
- * Copyright (C) 2008-2015 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 "black_temple.h"
-#include "Player.h"
-#include "SpellInfo.h"
-
-enum Texts
-{
- SAY_AGGRO = 0,
- SAY_NEEDLE = 1,
- SAY_SLAY = 2,
- SAY_SPECIAL = 3,
- SAY_ENRAGE = 4,
- SAY_DEATH = 5
-};
-
-enum Spells
-{
- SPELL_NEEDLE_SPINE = 39992,
- SPELL_TIDAL_BURST = 39878,
- SPELL_TIDAL_SHIELD = 39872,
- SPELL_IMPALING_SPINE = 39837,
- SPELL_CREATE_NAJENTUS_SPINE = 39956,
- SPELL_HURL_SPINE = 39948,
- SPELL_BERSERK = 26662
-
-};
-
-enum Events
-{
- EVENT_BERSERK = 1,
- EVENT_YELL = 2,
- EVENT_NEEDLE = 3,
- EVENT_SPINE = 4,
- EVENT_SHIELD = 5
-};
-
-enum EventGroups
-{
- GCD_CAST = 1,
- GCD_YELL = 2
-};
-
-class boss_najentus : public CreatureScript
-{
-public:
- boss_najentus() : CreatureScript("boss_najentus") { }
-
- struct boss_najentusAI : public BossAI
- {
- boss_najentusAI(Creature* creature) : BossAI(creature, DATA_HIGH_WARLORD_NAJENTUS)
- {
- }
-
- void Reset() override
- {
- _Reset();
- SpineTargetGUID.Clear();
- }
-
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_SLAY);
- events.DelayEvents(5000, GCD_YELL);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- _JustDied();
- Talk(SAY_DEATH);
- }
-
- void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override
- {
- if (spell->Id == SPELL_HURL_SPINE && me->HasAura(SPELL_TIDAL_SHIELD))
- {
- me->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD);
- DoCast(me, SPELL_TIDAL_BURST, true);
- ResetTimer();
- }
- }
-
- void EnterCombat(Unit* /*who*/) override
- {
- _EnterCombat();
- Talk(SAY_AGGRO);
- events.ScheduleEvent(EVENT_BERSERK, 480000, GCD_CAST);
- events.ScheduleEvent(EVENT_YELL, 45000 + (rand32() % 76) * 1000, GCD_YELL);
- ResetTimer();
- }
-
- bool RemoveImpalingSpine()
- {
- if (!SpineTargetGUID)
- return false;
-
- Unit* target = ObjectAccessor::GetUnit(*me, SpineTargetGUID);
- if (target && target->HasAura(SPELL_IMPALING_SPINE))
- target->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE);
- SpineTargetGUID.Clear();
- return true;
- }
-
- void ResetTimer(uint32 inc = 0)
- {
- events.RescheduleEvent(EVENT_NEEDLE, 10000 + inc, GCD_CAST);
- events.RescheduleEvent(EVENT_SPINE, 20000 + inc, GCD_CAST);
- events.RescheduleEvent(EVENT_SHIELD, 60000 + inc);
- }
-
- void ExecuteEvent(uint32 eventId) override
- {
- switch (eventId)
- {
- case EVENT_SHIELD:
- DoCast(me, SPELL_TIDAL_SHIELD, true);
- ResetTimer(45000);
- break;
- case EVENT_BERSERK:
- Talk(SAY_ENRAGE);
- DoCast(me, SPELL_BERSERK, true);
- events.DelayEvents(15000, GCD_YELL);
- break;
- case EVENT_SPINE:
- {
- Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
-
- if (!target)
- target = me->GetVictim();
-
- if (target)
- {
- 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);
- Talk(SAY_NEEDLE);
- events.DelayEvents(1500, GCD_CAST);
- events.DelayEvents(15000, GCD_YELL);
- }
- events.ScheduleEvent(EVENT_SPINE, 21000, GCD_CAST);
- return;
- }
- case EVENT_NEEDLE:
- {
- //DoCast(me, SPELL_NEEDLE_SPINE, true);
- std::list<Unit*> targets;
- SelectTargetList(targets, 3, SELECT_TARGET_RANDOM, 80, true);
- for (std::list<Unit*>::const_iterator i = targets.begin(); i != targets.end(); ++i)
- DoCast(*i, 39835, true);
- events.ScheduleEvent(EVENT_NEEDLE, urand(15000, 25000), GCD_CAST);
- events.DelayEvents(1500, GCD_CAST);
- return;
- }
- case EVENT_YELL:
- Talk(SAY_SPECIAL);
- events.ScheduleEvent(EVENT_YELL, urand(25000, 100000), GCD_YELL);
- events.DelayEvents(15000, GCD_YELL);
- break;
- default:
- break;
- }
- }
-
- private:
- ObjectGuid SpineTargetGUID;
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetBlackTempleAI<boss_najentusAI>(creature);
- }
-};
-
-class go_najentus_spine : public GameObjectScript
-{
-public:
- go_najentus_spine() : GameObjectScript("go_najentus_spine") { }
-
- bool OnGossipHello(Player* player, GameObject* go) override
- {
- if (InstanceScript* instance = go->GetInstanceScript())
- if (Creature* Najentus = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_HIGH_WARLORD_NAJENTUS)))
- if (ENSURE_AI(boss_najentus::boss_najentusAI, Najentus->AI())->RemoveImpalingSpine())
- {
- player->CastSpell(player, SPELL_CREATE_NAJENTUS_SPINE, true);
- go->Delete();
- }
- return true;
- }
-
-};
-
-void AddSC_boss_najentus()
-{
- new boss_najentus();
- new go_najentus_spine();
-}
+/* + * Copyright (C) 2008-2015 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 "black_temple.h" +#include "Player.h" +#include "SpellInfo.h" + +enum Texts +{ + SAY_AGGRO = 0, + SAY_NEEDLE = 1, + SAY_SLAY = 2, + SAY_SPECIAL = 3, + SAY_ENRAGE = 4, + SAY_DEATH = 5 +}; + +enum Spells +{ + SPELL_NEEDLE_SPINE = 39992, + SPELL_TIDAL_BURST = 39878, + SPELL_TIDAL_SHIELD = 39872, + SPELL_IMPALING_SPINE = 39837, + SPELL_CREATE_NAJENTUS_SPINE = 39956, + SPELL_HURL_SPINE = 39948, + SPELL_BERSERK = 26662 + +}; + +enum Events +{ + EVENT_BERSERK = 1, + EVENT_YELL = 2, + EVENT_NEEDLE = 3, + EVENT_SPINE = 4, + EVENT_SHIELD = 5 +}; + +enum EventGroups +{ + GCD_CAST = 1, + GCD_YELL = 2 +}; + +class boss_najentus : public CreatureScript +{ +public: + boss_najentus() : CreatureScript("boss_najentus") { } + + struct boss_najentusAI : public BossAI + { + boss_najentusAI(Creature* creature) : BossAI(creature, DATA_HIGH_WARLORD_NAJENTUS) + { + } + + void Reset() override + { + _Reset(); + SpineTargetGUID.Clear(); + } + + void KilledUnit(Unit* /*victim*/) override + { + Talk(SAY_SLAY); + events.DelayEvents(5000, GCD_YELL); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + Talk(SAY_DEATH); + } + + void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override + { + if (spell->Id == SPELL_HURL_SPINE && me->HasAura(SPELL_TIDAL_SHIELD)) + { + me->RemoveAurasDueToSpell(SPELL_TIDAL_SHIELD); + DoCast(me, SPELL_TIDAL_BURST, true); + ResetTimer(); + } + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + Talk(SAY_AGGRO); + events.ScheduleEvent(EVENT_BERSERK, 480000, GCD_CAST); + events.ScheduleEvent(EVENT_YELL, 45000 + (rand32() % 76) * 1000, GCD_YELL); + ResetTimer(); + } + + bool RemoveImpalingSpine() + { + if (!SpineTargetGUID) + return false; + + Unit* target = ObjectAccessor::GetUnit(*me, SpineTargetGUID); + if (target && target->HasAura(SPELL_IMPALING_SPINE)) + target->RemoveAurasDueToSpell(SPELL_IMPALING_SPINE); + SpineTargetGUID.Clear(); + return true; + } + + void ResetTimer(uint32 inc = 0) + { + events.RescheduleEvent(EVENT_NEEDLE, 10000 + inc, GCD_CAST); + events.RescheduleEvent(EVENT_SPINE, 20000 + inc, GCD_CAST); + events.RescheduleEvent(EVENT_SHIELD, 60000 + inc); + } + + void ExecuteEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_SHIELD: + DoCast(me, SPELL_TIDAL_SHIELD, true); + ResetTimer(45000); + break; + case EVENT_BERSERK: + Talk(SAY_ENRAGE); + DoCast(me, SPELL_BERSERK, true); + events.DelayEvents(15000, GCD_YELL); + break; + case EVENT_SPINE: + { + Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1); + + if (!target) + target = me->GetVictim(); + + if (target) + { + 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); + Talk(SAY_NEEDLE); + events.DelayEvents(1500, GCD_CAST); + events.DelayEvents(15000, GCD_YELL); + } + events.ScheduleEvent(EVENT_SPINE, 21000, GCD_CAST); + return; + } + case EVENT_NEEDLE: + { + //DoCast(me, SPELL_NEEDLE_SPINE, true); + std::list<Unit*> targets; + SelectTargetList(targets, 3, SELECT_TARGET_RANDOM, 80, true); + for (std::list<Unit*>::const_iterator i = targets.begin(); i != targets.end(); ++i) + DoCast(*i, 39835, true); + events.ScheduleEvent(EVENT_NEEDLE, urand(15000, 25000), GCD_CAST); + events.DelayEvents(1500, GCD_CAST); + return; + } + case EVENT_YELL: + Talk(SAY_SPECIAL); + events.ScheduleEvent(EVENT_YELL, urand(25000, 100000), GCD_YELL); + events.DelayEvents(15000, GCD_YELL); + break; + default: + break; + } + } + + private: + ObjectGuid SpineTargetGUID; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetBlackTempleAI<boss_najentusAI>(creature); + } +}; + +class go_najentus_spine : public GameObjectScript +{ +public: + go_najentus_spine() : GameObjectScript("go_najentus_spine") { } + + bool OnGossipHello(Player* player, GameObject* go) override + { + if (InstanceScript* instance = go->GetInstanceScript()) + if (Creature* Najentus = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_HIGH_WARLORD_NAJENTUS))) + if (ENSURE_AI(boss_najentus::boss_najentusAI, Najentus->AI())->RemoveImpalingSpine()) + { + player->CastSpell(player, SPELL_CREATE_NAJENTUS_SPINE, true); + go->Delete(); + } + return true; + } + +}; + +void AddSC_boss_najentus() +{ + new boss_najentus(); + new go_najentus_spine(); +} 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 d817c08d7f2..0292ed65697 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -257,8 +257,7 @@ public: void EnterCombat(Unit* who) override { // remove old tainted cores to prevent cheating in phase 2 - Map* map = me->GetMap(); - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) if (Player* player = itr->GetSource()) player->DestroyItemCount(31088, 1, true); @@ -634,7 +633,7 @@ public: } if (Creature* vashj = ObjectAccessor::GetCreature(*me, VashjGUID)) if (!vashj->IsInCombat() || ENSURE_AI(boss_lady_vashj::boss_lady_vashjAI, vashj->AI())->Phase != 2 || vashj->isDead()) - me->Kill(me); + me->KillSelf(); Move = 1000; } else Move -= diff; } 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 5d967a3546f..253c601e228 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 @@ -788,8 +788,7 @@ public: if (Earthshock_Timer <= diff) { - Map* map = me->GetMap(); - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) { if (Player* i_pl = itr->GetSource()) diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp index 096777163a6..7c4dbdeaab1 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp @@ -259,8 +259,7 @@ public: if (CheckTimer <= diff)//check if there are players in melee range { InRange = false; - Map* map = me->GetMap(); - Map::PlayerList const &PlayerList = map->GetPlayers(); + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); if (!PlayerList.isEmpty()) { for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) @@ -274,15 +273,11 @@ public: if (RotTimer) { - Map* map = me->GetMap(); - if (map->IsDungeon()) + Map::PlayerList const &PlayerList = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { - Map::PlayerList const &PlayerList = map->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->GetSource() && i->GetSource()->IsAlive() && me->HasInArc(diff/20000.f*float(M_PI)*2.f, i->GetSource()) && me->IsWithinDist(i->GetSource(), SPOUT_DIST) && !i->GetSource()->IsInWater()) - DoCast(i->GetSource(), SPELL_SPOUT, true); // only knock back players in arc, in 100yards, not in water - } + if (i->GetSource() && i->GetSource()->IsAlive() && me->HasInArc(diff/20000.f*float(M_PI)*2.f, i->GetSource()) && me->IsWithinDist(i->GetSource(), SPOUT_DIST) && !i->GetSource()->IsInWater()) + DoCast(i->GetSource(), SPELL_SPOUT, true); // only knock back players in arc, in 100yards, not in water } if (SpoutAnimTimer <= diff) diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp index b76712fc541..a8d65cc096d 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp @@ -219,12 +219,12 @@ public: if (WateryGrave_Timer <= diff) { //Teleport 4 players under the waterfalls - Unit* target; GuidSet targets; GuidSet::const_iterator itr; for (uint8 i = 0; i < 4; ++i) { counter = 0; + Unit* target; do { target = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only @@ -257,12 +257,12 @@ public: //WateryGlobules_Timer if (WateryGlobules_Timer <= diff) { - Unit* pGlobuleTarget; GuidSet globules; GuidSet::const_iterator itr; for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD { counter = 0; + Unit* pGlobuleTarget; do { pGlobuleTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); 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 a6c00c05dce..749f5cbf88b 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 @@ -364,21 +364,21 @@ class boss_vazruden_the_herald : public CreatureScript } } - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - if (!summoned) + if (!summon) return; Unit* victim = me->GetVictim(); - if (summoned->GetEntry() == NPC_NAZAN) + if (summon->GetEntry() == NPC_NAZAN) { - summoned->SetDisableGravity(true); - summoned->SetSpeed(MOVE_FLIGHT, 2.5f); + summon->SetDisableGravity(true); + summon->SetSpeed(MOVE_FLIGHT, 2.5f); if (victim) AttackStartNoMove(victim); } else if (victim) - summoned->AI()->AttackStart(victim); + summon->AI()->AttackStart(victim); } void SentryDownBy(Unit* killer) 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 7f2e08b39ca..9f7592a9ee4 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 @@ -127,18 +127,18 @@ class boss_warchief_kargath_bladefist : public CreatureScript Talk(SAY_AGGRO); } - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - switch (summoned->GetEntry()) + switch (summon->GetEntry()) { case NPC_HEARTHEN_GUARD: case NPC_SHARPSHOOTER_GUARD: case NPC_REAVER_GUARD: - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0)); - adds.push_back(summoned->GetGUID()); + summon->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0)); + adds.push_back(summon->GetGUID()); break; case NPC_SHATTERED_ASSASSIN: - assassins.push_back(summoned->GetGUID()); + assassins.push_back(summon->GetGUID()); break; } } diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp index 500b0ae4bcb..f47e191c118 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp @@ -82,7 +82,7 @@ class boss_shattered_executioner : public CreatureScript void Reset() override { _Reset(); - + // _Reset() resets the loot mode, so we add them again, if any uint32 prisonersExecuted = instance->GetData(DATA_PRISONERS_EXECUTED); if (prisonersExecuted == 0) diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index f5583c0bc53..2d99fd9bacf 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -25,115 +25,236 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "Spell.h" +#include "SpellScript.h" #include "the_eye.h" -#include "WorldPacket.h" -#include "Opcodes.h" enum Yells { // Kael'thas Speech - SAY_INTRO = 0, - SAY_INTRO_CAPERNIAN = 1, - SAY_INTRO_TELONICUS = 2, - SAY_INTRO_THALADRED = 3, - SAY_INTRO_SANGUINAR = 4, - SAY_PHASE2_WEAPON = 5, - SAY_PHASE3_ADVANCE = 6, - SAY_PHASE4_INTRO2 = 7, - SAY_PHASE5_NUTS = 8, - SAY_SLAY = 9, - SAY_MINDCONTROL = 10, - SAY_GRAVITYLAPSE = 11, - SAY_SUMMON_PHOENIX = 12, - SAY_DEATH = 13, + SAY_INTRO = 0, + SAY_INTRO_CAPERNIAN = 1, + SAY_INTRO_TELONICUS = 2, + SAY_INTRO_THALADRED = 3, + SAY_INTRO_SANGUINAR = 4, + SAY_PHASE2_WEAPON = 5, + SAY_PHASE3_ADVANCE = 6, + SAY_PHASE4_INTRO2 = 7, + SAY_PHASE5_NUTS = 8, + SAY_SLAY = 9, + SAY_MIND_CONTROL = 10, + SAY_GRAVITY_LAPSE = 11, + SAY_SUMMON_PHOENIX = 12, + SAY_DEATH = 13, + EMOTE_PYROBLAST = 14, // Thaladred the Darkener speech - SAY_THALADRED_AGGRO = 0, - SAY_THALADRED_DEATH = 1, - EMOTE_THALADRED_GAZE = 2, + SAY_THALADRED_AGGRO = 0, + SAY_THALADRED_DEATH = 1, + EMOTE_THALADRED_GAZE = 2, //Lord Sanguinar speech - SAY_SANGUINAR_AGGRO = 0, - SAY_SANGUINAR_DEATH = 1, + SAY_SANGUINAR_AGGRO = 0, + SAY_SANGUINAR_DEATH = 1, // Grand Astromancer Capernian speech - SAY_CAPERNIAN_AGGRO = 0, - SAY_CAPERNIAN_DEATH = 1, + SAY_CAPERNIAN_AGGRO = 0, + SAY_CAPERNIAN_DEATH = 1, // Master Engineer Telonicus speech - SAY_TELONICUS_AGGRO = 0, - SAY_TELONICUS_DEATH = 1 + SAY_TELONICUS_AGGRO = 0, + SAY_TELONICUS_DEATH = 1 }; enum Spells { // Phase 2 spells - SPELL_SUMMON_WEAPONS = 36976, - SPELL_SUMMON_WEAPONA = 36958, - SPELL_SUMMON_WEAPONB = 36959, - SPELL_SUMMON_WEAPONC = 36960, - SPELL_SUMMON_WEAPOND = 36961, - SPELL_SUMMON_WEAPONE = 36962, - SPELL_SUMMON_WEAPONF = 36963, - SPELL_SUMMON_WEAPONG = 36964, - SPELL_RES_VISUAL = 24171, + SPELL_SUMMON_WEAPONS = 36976, + SPELL_SUMMON_WEAPONA = 36958, + SPELL_SUMMON_WEAPONB = 36959, + SPELL_SUMMON_WEAPONC = 36960, + SPELL_SUMMON_WEAPOND = 36961, + SPELL_SUMMON_WEAPONE = 36962, + SPELL_SUMMON_WEAPONF = 36963, + SPELL_SUMMON_WEAPONG = 36964, + SPELL_RESSURECTION = 36450, // Phase 4 spells - SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell - SPELL_PYROBLAST = 36819, - SPELL_FLAME_STRIKE = 36735, - SPELL_FLAME_STRIKE_VIS = 36730, - SPELL_FLAME_STRIKE_DMG = 36731, - SPELL_ARCANE_DISRUPTION = 36834, - SPELL_SHOCK_BARRIER = 36815, - SPELL_PHOENIX_ANIMATION = 36723, - SPELL_MIND_CONTROL = 32830, + SPELL_FIREBALL = 36805, + SPELL_PYROBLAST = 36819, + SPELL_FLAME_STRIKE = 36735, + SPELL_FLAME_STRIKE_VIS = 36730, + SPELL_FLAME_STRIKE_DMG = 36731, + SPELL_ARCANE_DISRUPTION = 36834, + SPELL_SHOCK_BARRIER = 36815, + SPELL_PHOENIX_ANIMATION = 36723, + //SPELL_MIND_CONTROL = 32830, + SPELL_MIND_CONTROL = 36797, + SPELL_BANISH = 40370, // Cast on Phoenix // Phase 5 spells - SPELL_EXPLODE = 36092, - SPELL_FULLPOWER = 36187, - SPELL_KNOCKBACK = 11027, - SPELL_GRAVITY_LAPSE = 34480, - SPELL_GRAVITY_LAPSE_AURA = 39432, - SPELL_NETHER_BEAM = 35873, + SPELL_KAEL_GAINING_POWER = 36091, + SPELL_KAEL_EXPLODES = 36373, + SPELL_KAEL_EXPLODES2 = 36375, + SPELL_KAEL_EXPLODES3 = 36092, + SPELL_KAEL_EXPLODES4 = 36354, + SPELL_KAEL_STUNNED = 36185, + SPELL_FULLPOWER = 36187, + SPELL_NETHER_BEAM = 35873, + SPELL_PURE_NETHER_BEAM = 36196, + SPELL_SUMMON_NETHER_VAPOR = 35865, + + // Visual, phase transition spells + SPELL_NETHER_BEAM_VISUAL = 36089, // Channeled by trigger on Kael'thas. + SPELL_NETHER_BEAM_VISUAL2 = 36090, // Channeled by trigger on Kael'thas. + SPELL_NETHER_BEAM_VISUAL3 = 36364, // Cast by Kael'thas on himself, purple glowing effect. + + // Gravity Lapse spells + SPELL_GRAVITY_LAPSE = 35941, + SPELL_GRAVITY_LAPSE_PERIODIC = 34480, + SPELL_GRAVITY_LAPSE_FLIGHT_AURA = 39432, // Cast by players on themselves, allows flight + + // 25 teleport spells, one for each raid member... + SPELL_GRAVITY_LAPSE_TELE_FRONT = 35966, + SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT = 35967, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT = 35968, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT = 35969, + SPELL_GRAVITY_LAPSE_TELE_BACK = 35970, + SPELL_GRAVITY_LAPSE_TELE_TO_CASTER = 35971, + SPELL_GRAVITY_LAPSE_TELE_BACK_LEFT = 35972, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT2 = 35973, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT = 35974, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT2 = 35975, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT3 = 35976, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT = 35977, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT = 35978, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK = 35979, + SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT2 = 35980, + SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT = 35981, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_RIGHT = 35982, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT2 = 35983, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_LEFT = 35984, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT3 = 35985, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT2 = 35986, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK2 = 35987, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT2 = 35988, + SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT2 = 35989, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT3 = 35990, // Thaladred the Darkener spells - SPELL_PSYCHIC_BLOW = 10689, - SPELL_SILENCE = 30225, + SPELL_PSYCHIC_BLOW = 10689, + SPELL_SILENCE = 30225, // Lord Sanguinar spells - SPELL_BELLOWING_ROAR = 40636, + SPELL_BELLOWING_ROAR = 40636, // Grand Astromancer Capernian spells - SPELL_CAPERNIAN_FIREBALL = 36971, - SPELL_CONFLAGRATION = 37018, - SPELL_ARCANE_EXPLOSION = 36970, + SPELL_CAPERNIAN_FIREBALL = 36971, + SPELL_CONFLAGRATION = 37018, + SPELL_ARCANE_EXPLOSION = 36970, //Master Engineer Telonicus spells - SPELL_BOMB = 37036, - SPELL_REMOTE_TOY = 37027, + SPELL_BOMB = 37036, + SPELL_REMOTE_TOY = 37027, //Nether Vapor spell - SPELL_NETHER_VAPOR = 35859, + SPELL_NETHER_VAPOR = 35859, //Phoenix spell - SPELL_BURN = 36720, - SPELL_EMBER_BLAST = 34341, - SPELL_REBIRTH = 41587 + SPELL_BURN = 36720, + SPELL_EMBER_BLAST = 34341, + SPELL_REBIRTH = 41587 }; enum Creatures { - NPC_PHOENIX = 21362, - NPC_PHOENIX_EGG = 21364 + NPC_PHOENIX = 21362, + NPC_PHOENIX_EGG = 21364 }; enum Models { //Phoenix egg and phoenix model - MODEL_ID_PHOENIX = 19682, - MODEL_ID_PHOENIX_EGG = 20245 + MODEL_ID_PHOENIX = 19682, + MODEL_ID_PHOENIX_EGG = 20245 }; -enum Misc +enum Actions { - MAX_ADVISORS = 4 + ACTION_START_ENCOUNTER, + ACTION_REVIVE_ADVISORS, + ACTION_PREPARE_ADVISORS, + ACTION_ACTIVE_ADVISOR, + ACTION_SCHEDULE_COMBAT_EVENTS +}; + +enum Advisors +{ + ADVISOR_THALADRED, + ADVISOR_SANGUINAR, + ADVISOR_CAPERNIAN, + ADVISOR_TELONICUS, + MAX_ADVISORS = 4, + + MAX_DEFEATED_ADVISORS = 4, + MAX_KILLED_ADVISORS = 8 +}; + +enum Events +{ + EVENT_START_ENCOUNTER = 1, + EVENT_ACTIVE_ADVISOR, + EVENT_SUMMON_WEAPONS, + EVENT_REVIVE_ADVISORS, + EVENT_ENGAGE_COMBAT, + EVENT_FULL_POWER, + EVENT_FIREBALL, + EVENT_ARCANE_DISRUPTION, + EVENT_FLAMESTRIKE, + EVENT_MIND_CONTROL, + EVENT_SUMMON_PHOENIX, + EVENT_SHOCK_BARRIER, + EVENT_PYROBLAST, + EVENT_PYROBLAST_CAST, + EVENT_GAINING_POWER, + EVENT_END_TRANSITION, + EVENT_GRAVITY_LAPSE, + EVENT_NETHER_BEAM, + + // Movement updates + EVENT_TRANSITION_1, + EVENT_TRANSITION_2, + EVENT_TRANSITION_3, + EVENT_TRANSITION_4, + EVENT_TRANSITION_5, + EVENT_TRANSITION_6, + + // Phase transition + EVENT_SIZE_INCREASE, + EVENT_EXPLODE, + EVENT_RESUME_COMBAT, + + // Advisors + EVENT_DELAYED_RESSURECTION, + + // Event groups + EVENT_GROUP_COMBAT = 1, // Default abilities + EVENT_GROUP_SPECIAL = 2 // Special abilities (Pyroblast, Nether Beam, Shock Barrier) +}; + +enum Phases +{ + PHASE_NONE, + PHASE_INTRO, + PHASE_REVIVED_ADVISORS, + PHASE_COMBAT, + PHASE_TRANSITION +}; + +enum MovementPoints +{ + POINT_START_TRANSITION = 1, + POINT_TRANSITION_CENTER_ASCENDING = 2, + POINT_TRANSITION_HALFWAY_ASCENDING = 3, + POINT_TRANSITION_TOP = 4, + POINT_TRANSITION_HALFWAY_DESCENDING = 5, + POINT_END_TRANSITION = 6 }; uint32 m_auiSpellSummonWeapon[]= @@ -142,61 +263,83 @@ uint32 m_auiSpellSummonWeapon[]= SPELL_SUMMON_WEAPONE, SPELL_SUMMON_WEAPONF, SPELL_SUMMON_WEAPONG }; +uint32 GravityLapseSpells[] = +{ + SPELL_GRAVITY_LAPSE_TELE_FRONT, + SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT, + SPELL_GRAVITY_LAPSE_TELE_BACK, + SPELL_GRAVITY_LAPSE_TELE_TO_CASTER, + SPELL_GRAVITY_LAPSE_TELE_BACK_LEFT, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT2, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT3, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK, + SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_RIGHT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_LEFT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT3, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT3 +}; + const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target //const float KAEL_VISIBLE_RANGE = 50.0f; -const float afGravityPos[3] = {795.0f, 0.0f, 70.0f}; +Position const afGravityPos = {795.0f, 0.0f, 70.0f}; -#define TIME_PHASE_2_3 120000 -#define TIME_PHASE_3_4 180000 +Position const TransitionPos[6] = +{ + // First two values are not static, they seem to differ on each sniff. + { 794.0522f, -0.96732f, 48.97848f, 0.0f }, + { 796.641f, -0.5888171f, 48.72847f, 3.176499f }, + { 795.007f, -0.471827f, 75.0f, 0.0f }, + { 795.007f, -0.471827f, 75.0f, 3.133458f }, + { 792.419f, -0.504778f, 50.0505f, 0.0f }, + { 792.419f, -0.504778f, 50.0505f, 3.130386f } +}; -//Base AI for Advisors struct advisorbase_ai : public ScriptedAI { advisorbase_ai(Creature* creature) : ScriptedAI(creature) { Initialize(); instance = creature->GetInstanceScript(); - m_bDoubled_Health = false; } void Initialize() { - FakeDeath = false; - DelayRes_Timer = 0; + _hasRessurrected = false; + _inFakeDeath = false; DelayRes_Target.Clear(); } - InstanceScript* instance; - bool FakeDeath; - bool m_bDoubled_Health; - uint32 DelayRes_Timer; - ObjectGuid DelayRes_Target; - void Reset() override { - if (m_bDoubled_Health) - { - me->SetMaxHealth(me->GetMaxHealth() / 2); - m_bDoubled_Health = false; - } - Initialize(); me->SetStandState(UNIT_STAND_STATE_STAND); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); //reset encounter - if (instance->GetData(DATA_KAELTHASEVENT) == 1 || instance->GetData(DATA_KAELTHASEVENT) == 3) + if (instance->GetBossState(DATA_KAELTHAS) == IN_PROGRESS) if (Creature* Kaelthas = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KAELTHAS))) Kaelthas->AI()->EnterEvadeMode(); } void MoveInLineOfSight(Unit* who) override - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + if (!who || _inFakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return; ScriptedAI::MoveInLineOfSight(who); @@ -204,69 +347,61 @@ struct advisorbase_ai : public ScriptedAI void AttackStart(Unit* who) override { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + if (!who || _inFakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return; ScriptedAI::AttackStart(who); } - void Revive(Unit* /*Target*/) + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // double health for phase 3 - me->SetMaxHealth(me->GetMaxHealth() * 2); - m_bDoubled_Health = true; - me->SetFullHealth(); - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoCast(me, SPELL_RES_VISUAL, false); - DelayRes_Timer = 2000; + if (spell->Id == SPELL_RESSURECTION) + { + _hasRessurrected = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + me->SetStandState(UNIT_STAND_STATE_STAND); + events.ScheduleEvent(EVENT_DELAYED_RESSURECTION, 2000); + } } void DamageTaken(Unit* killer, uint32 &damage) override { - if (damage < me->GetHealth()) - return; - - //Prevent glitch if in fake death - if (FakeDeath && instance->GetData(DATA_KAELTHASEVENT) != 0) - { - damage = 0; - return; - } - - //Don't really die in phase 1 & 3, only die after that - if (instance->GetData(DATA_KAELTHASEVENT) != 0) + if (damage >= me->GetHealth() && !_inFakeDeath && !_hasRessurrected) { //prevent death damage = 0; - FakeDeath = true; + _inFakeDeath = true; me->InterruptNonMeleeSpells(false); me->SetHealth(0); - me->StopMoving(); me->ClearComboPointHolders(); me->RemoveAllAurasOnDeath(); me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->ClearAllReactives(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); me->SetTarget(ObjectGuid::Empty); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); me->SetStandState(UNIT_STAND_STATE_DEAD); + me->GetMotionMaster()->Clear(); JustDied(killer); } } + void JustDied(Unit* /*killer*/) override + { + if (Creature* kael = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KAELTHAS))) + kael->AI()->DoAction(ACTION_ACTIVE_ADVISOR); + } + void UpdateAI(uint32 diff) override { - if (DelayRes_Timer) + if (_hasRessurrected) + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - if (DelayRes_Timer <= diff) + if (eventId == EVENT_DELAYED_RESSURECTION) { - DelayRes_Timer = 0; - FakeDeath = false; + _inFakeDeath = false; Unit* Target = ObjectAccessor::GetUnit(*me, DelayRes_Target); if (!Target) @@ -277,9 +412,15 @@ struct advisorbase_ai : public ScriptedAI me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveChase(Target); me->AddThreat(Target, 0.0f); - } else DelayRes_Timer -= diff; + } } } + public: + EventMap events; + InstanceScript* instance; + bool _hasRessurrected; + bool _inFakeDeath; + ObjectGuid DelayRes_Target; }; class boss_kaelthas : public CreatureScript @@ -293,150 +434,199 @@ class boss_kaelthas : public CreatureScript boss_kaelthasAI(Creature* creature) : BossAI(creature, DATA_KAELTHAS) { Initialize(); - PhaseSubphase = 0; - Phase_Timer = 0; } void Initialize() { - Fireball_Timer = 5000 + rand32() % 10000; - ArcaneDisruption_Timer = 45000; - MindControl_Timer = 40000; - Phoenix_Timer = 50000; - ShockBarrier_Timer = 60000; - FlameStrike_Timer = 30000; - GravityLapse_Timer = 20000; - GravityLapse_Phase = 0; - NetherBeam_Timer = 8000; - NetherVapor_Timer = 10000; - PyrosCast = 0; - Phase = 0; - InGravityLapse = false; - IsCastingFireball = false; - ChainPyros = false; + _advisorCounter = 0; + _pyrosCast = 0; + _netherbeamsCast = 0; + _phase = PHASE_NONE; + _scaleStage = 0; + _hasFullPower = false; } - uint32 Fireball_Timer; - uint32 ArcaneDisruption_Timer; - uint32 Phoenix_Timer; - uint32 ShockBarrier_Timer; - uint32 GravityLapse_Timer; - uint32 GravityLapse_Phase; - uint32 NetherBeam_Timer; - uint32 NetherVapor_Timer; - uint32 FlameStrike_Timer; - uint32 MindControl_Timer; - uint32 Phase; - uint32 PhaseSubphase; //generic - uint32 Phase_Timer; //generic timer - uint32 PyrosCast; - - bool InGravityLapse; - bool IsCastingFireball; - bool ChainPyros; - - ObjectGuid m_auiAdvisorGuid[MAX_ADVISORS]; - void Reset() override { Initialize(); - - if (me->IsInCombat()) - PrepareAdvisors(); - - _Reset(); - + DoAction(ACTION_PREPARE_ADVISORS); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - instance->SetData(DATA_KAELTHASEVENT, 0); - } - - void PrepareAdvisors() - { - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Creature* creature = ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[i])) - { - creature->Respawn(); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - creature->setFaction(me->getFaction()); - creature->AI()->EnterEvadeMode(); - } - } + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + me->SetDisableGravity(false); + me->SetTarget(ObjectGuid::Empty); + me->SetObjectScale(1.0f); + BossAI::Reset(); } - void StartEvent() + void JustReachedHome() override { - m_auiAdvisorGuid[0] = instance->GetGuidData(DATA_THALADREDTHEDARKENER); - m_auiAdvisorGuid[1] = instance->GetGuidData(DATA_LORDSANGUINAR); - m_auiAdvisorGuid[2] = instance->GetGuidData(DATA_GRANDASTROMANCERCAPERNIAN); - m_auiAdvisorGuid[3] = instance->GetGuidData(DATA_MASTERENGINEERTELONICUS); - - if (!m_auiAdvisorGuid[0] || !m_auiAdvisorGuid[1] || !m_auiAdvisorGuid[2] || !m_auiAdvisorGuid[3]) - { - TC_LOG_ERROR("scripts", "Kael'Thas One or more advisors missing, Skipping Phases 1-3"); - - Talk(SAY_PHASE4_INTRO2); + BossAI::JustReachedHome(); - Phase = 4; + // Rebuild the surrounding environment. + if (GameObject* statue = instance->GetGameObject(DATA_KAEL_STATUE_LEFT)) + statue->ResetDoorOrButton(); - instance->SetData(DATA_KAELTHASEVENT, 4); + if (GameObject* statue = instance->GetGameObject(DATA_KAEL_STATUE_RIGHT)) + statue->ResetDoorOrButton(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (GameObject* window = instance->GetGameObject(DATA_TEMPEST_BRIDGE_WINDOW)) + window->ResetDoorOrButton(); + } - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - AttackStart(target); - } - else + void DoAction(int32 action) override + { + switch (action) { - PrepareAdvisors(); - - Talk(SAY_INTRO); - - instance->SetData(DATA_KAELTHASEVENT, 1); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + case ACTION_START_ENCOUNTER: + Talk(SAY_INTRO); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + _advisorGuid[ADVISOR_THALADRED] = instance->GetGuidData(DATA_THALADREDTHEDARKENER); + _advisorGuid[ADVISOR_SANGUINAR] = instance->GetGuidData(DATA_LORDSANGUINAR); + _advisorGuid[ADVISOR_CAPERNIAN] = instance->GetGuidData(DATA_GRANDASTROMANCERCAPERNIAN); + _advisorGuid[ADVISOR_TELONICUS] = instance->GetGuidData(DATA_MASTERENGINEERTELONICUS); + + _phase = PHASE_INTRO; + instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS); + events.ScheduleEvent(EVENT_START_ENCOUNTER, 23000); + break; + case ACTION_PREPARE_ADVISORS: + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + if (Creature* creature = ObjectAccessor::GetCreature(*me, _advisorGuid[i])) + { + creature->Respawn(true); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + creature->AI()->EnterEvadeMode(); + } + } + break; + case ACTION_ACTIVE_ADVISOR: + // They have already been active, so we are not handling new ones, just counting their death. + if (_phase == PHASE_REVIVED_ADVISORS) + ++_advisorCounter; - PhaseSubphase = 0; - Phase_Timer = 23000; - Phase = 1; + switch (_advisorCounter) + { + case ADVISOR_THALADRED: + Talk(SAY_INTRO_THALADRED); + events.ScheduleEvent(EVENT_ACTIVE_ADVISOR, 7000); + break; + case ADVISOR_SANGUINAR: + Talk(SAY_INTRO_SANGUINAR); + events.ScheduleEvent(EVENT_ACTIVE_ADVISOR, 12500); + break; + case ADVISOR_CAPERNIAN: + Talk(SAY_INTRO_CAPERNIAN); + events.ScheduleEvent(EVENT_ACTIVE_ADVISOR, 7000); + break; + case ADVISOR_TELONICUS: + Talk(SAY_INTRO_TELONICUS); + events.ScheduleEvent(EVENT_ACTIVE_ADVISOR, 8400); + break; + case MAX_DEFEATED_ADVISORS: + // Every advisor defeated - Phase 2 starts. + Talk(SAY_PHASE2_WEAPON); + events.ScheduleEvent(EVENT_SUMMON_WEAPONS, 3500); + break; + case MAX_KILLED_ADVISORS: + // Every advisor killed - Phase 3 starts. + events.ScheduleEvent(EVENT_ENGAGE_COMBAT, 5000); + break; + default: + break; + } + break; + case ACTION_SCHEDULE_COMBAT_EVENTS: + _phase = PHASE_COMBAT; + events.SetPhase(PHASE_COMBAT); + events.ScheduleEvent(EVENT_FIREBALL, 1000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ARCANE_DISRUPTION, 45000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + events.ScheduleEvent(EVENT_FLAMESTRIKE, 30000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + events.ScheduleEvent(EVENT_MIND_CONTROL, 40000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + events.ScheduleEvent(EVENT_SUMMON_PHOENIX, 50000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + default: + break; } } void MoveInLineOfSight(Unit* who) override { - if (!me->HasUnitState(UNIT_STATE_STUNNED) && me->CanCreatureAttack(who)) + if (_phase == PHASE_NONE && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 30.0f)) { - if (!me->CanFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; + DoAction(ACTION_START_ENCOUNTER); + who->SetInCombatWith(me); + me->AddThreat(who, 0.0f); + me->SetTarget(who->GetGUID()); + } + } - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - if (!me->GetVictim() && Phase >= 4) - { - who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (me->GetMap()->IsDungeon()) - { - if (!instance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); + void DamageTaken(Unit* attacker, uint32& damage) override + { + if (_phase == PHASE_NONE) + { + DoAction(ACTION_START_ENCOUNTER); + me->SetTarget(attacker->GetGUID()); + } - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } - } + if (!_hasFullPower && me->HealthBelowPctDamaged(50, damage)) + { + _hasFullPower = true; + me->AttackStop(); + me->InterruptNonMeleeSpells(false); + events.CancelEventGroup(EVENT_GROUP_COMBAT); + events.CancelEventGroup(EVENT_GROUP_SPECIAL); + events.SetPhase(PHASE_TRANSITION); + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MovePoint(POINT_START_TRANSITION, TransitionPos[0]); } } - void EnterCombat(Unit* /*who*/) override + void MovementInform(uint32 type, uint32 point) override { - if (!instance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); + if (type != POINT_MOTION_TYPE) + return; + + switch (point) + { + case POINT_START_TRANSITION: + events.ScheduleEvent(EVENT_TRANSITION_1, 1000); + break; + case POINT_TRANSITION_CENTER_ASCENDING: + me->SetFacingTo(float(M_PI)); + Talk(SAY_PHASE5_NUTS); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisableGravity(true); + //me->SetHover(true); -- Set in sniffs, but breaks his visual. + events.ScheduleEvent(EVENT_TRANSITION_2, 2000); + events.ScheduleEvent(EVENT_SIZE_INCREASE, 5000); + break; + case POINT_TRANSITION_HALFWAY_ASCENDING: + DoCast(me, SPELL_NETHER_BEAM_VISUAL3, true); + events.ScheduleEvent(EVENT_TRANSITION_3, 1000); + break; + case POINT_TRANSITION_TOP: + events.ScheduleEvent(EVENT_EXPLODE, 10000); + break; + case POINT_TRANSITION_HALFWAY_DESCENDING: + events.ScheduleEvent(EVENT_TRANSITION_5, 2000); + break; + case POINT_END_TRANSITION: + me->SetReactState(REACT_AGGRESSIVE); + me->InterruptNonMeleeSpells(false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAurasDueToSpell(SPELL_FULLPOWER); + + if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0)) + AttackStart(target); - instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS); + DoAction(ACTION_SCHEDULE_COMBAT_EVENTS); + events.ScheduleEvent(EVENT_GRAVITY_LAPSE, 10000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + default: + break; + } } void KilledUnit(Unit* /*victim*/) override @@ -456,563 +646,230 @@ class boss_kaelthas : public CreatureScript } } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Talk(SAY_DEATH); - - instance->SetData(DATA_KAELTHASEVENT, 0); - - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Unit* pAdvisor = ObjectAccessor::GetUnit(*me, m_auiAdvisorGuid[i])) - pAdvisor->Kill(pAdvisor); - } - _JustDied(); + BossAI::JustDied(killer); } void UpdateAI(uint32 diff) override { - //Phase 1 - switch (Phase) - { - case 1: - { - Unit* target = NULL; - Creature* Advisor = NULL; - - //Subphase switch - switch (PhaseSubphase) - { - //Subphase 1 - Start - case 0: - if (Phase_Timer <= diff) - { - Talk(SAY_INTRO_THALADRED); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 1 - Unlock advisor - case 1: - if (Phase_Timer <= diff) - { - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[0])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - Advisor->AI()->AttackStart(target); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 2 - Start - case 2: - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[0])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Talk(SAY_INTRO_SANGUINAR); - - //start advisor within 12.5 seconds - Phase_Timer = 12500; - ++PhaseSubphase; - } - break; - - //Subphase 2 - Unlock advisor - case 3: - if (Phase_Timer <= diff) - { - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[1])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - Advisor->AI()->AttackStart(target); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 3 - Start - case 4: - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[1])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Talk(SAY_INTRO_CAPERNIAN); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } - break; - - //Subphase 3 - Unlock advisor - case 5: - if (Phase_Timer <= diff) - { - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[2])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - Advisor->AI()->AttackStart(target); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 4 - Start - case 6: - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[2])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Talk(SAY_INTRO_TELONICUS); - - //start advisor within 8.4 seconds - Phase_Timer = 8400; - ++PhaseSubphase; - } - break; - - //Subphase 4 - Unlock advisor - case 7: - if (Phase_Timer <= diff) - { - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[3])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - Advisor->AI()->AttackStart(target); - } - - Phase_Timer = 3000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //End of phase 1 - case 8: - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[3])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Phase = 2; - instance->SetData(DATA_KAELTHASEVENT, 2); + if (_phase == PHASE_COMBAT) + if (!UpdateVictim()) + return; - Talk(SAY_PHASE2_WEAPON); + events.Update(diff); - PhaseSubphase = 0; - Phase_Timer = 3500; - DoCast(me, SPELL_SUMMON_WEAPONS); - } - break; - } - } - break; + // SPELL_KAEL_GAINING_POWER and SPELL_KAEL_STUNNED are channeling spells that need to be interrupted during his transition. + if (me->HasUnitState(UNIT_STATE_CASTING) && !me->FindCurrentSpellBySpellId(SPELL_KAEL_GAINING_POWER) && !me->FindCurrentSpellBySpellId(SPELL_KAEL_STUNNED)) + return; - case 2: + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - if (PhaseSubphase == 0) - { - if (Phase_Timer <= diff) + case EVENT_START_ENCOUNTER: + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); + DoAction(ACTION_ACTIVE_ADVISOR); + break; + case EVENT_ACTIVE_ADVISOR: + if (Creature* advisor = ObjectAccessor::GetCreature(*me, _advisorGuid[_advisorCounter])) { - PhaseSubphase = 1; - } - else - Phase_Timer -= diff; - } + advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //Spawn weapons - if (PhaseSubphase == 1) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + advisor->AI()->AttackStart(target); + } + ++_advisorCounter; + break; + case EVENT_SUMMON_WEAPONS: { DoCast(me, SPELL_SUMMON_WEAPONS, false); - uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32); + uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon) / sizeof(uint32); for (uint32 i = 0; i < uiMaxWeapon; ++i) DoCast(me, m_auiSpellSummonWeapon[i], true); - PhaseSubphase = 2; - Phase_Timer = TIME_PHASE_2_3; - } - - if (PhaseSubphase == 2) - { - if (Phase_Timer <= diff) - { - Talk(SAY_PHASE3_ADVANCE); - instance->SetData(DATA_KAELTHASEVENT, 3); - Phase = 3; - PhaseSubphase = 0; - } - else - Phase_Timer -= diff; - } - } - break; - - case 3: - { - if (PhaseSubphase == 0) - { - //Respawn advisors - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); - - Creature* Advisor; - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - Advisor = ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[i]); - - if (!Advisor) - TC_LOG_ERROR("scripts", "SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); - else - ENSURE_AI(advisorbase_ai, Advisor->AI())->Revive(target); - } - - PhaseSubphase = 1; - Phase_Timer = TIME_PHASE_3_4; + events.ScheduleEvent(EVENT_REVIVE_ADVISORS, 120000); + break; } - - if (Phase_Timer <= diff) - { + case EVENT_REVIVE_ADVISORS: + _phase = PHASE_REVIVED_ADVISORS; + Talk(SAY_PHASE3_ADVANCE); + DoCast(me, SPELL_RESSURECTION); + break; + case EVENT_ENGAGE_COMBAT: Talk(SAY_PHASE4_INTRO2); - Phase = 4; - - instance->SetData(DATA_KAELTHASEVENT, 4); // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. DoResetThreat(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) AttackStart(target); - Phase_Timer = 30000; - } - else - Phase_Timer -= diff; - } - break; - - case 4: - case 5: - case 6: - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fireball_Timer - if (!InGravityLapse && !ChainPyros && Phase != 5) - { - if (Fireball_Timer <= diff) - { - if (!IsCastingFireball) - { - if (!me->IsNonMeleeSpellCast(false)) - { - //interruptable - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); - int32 dmg = 20000 + rand32() % 5000; - me->CastCustomSpell(me->GetVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); - IsCastingFireball = true; - Fireball_Timer = 2500; - } - } - else - { - //apply resistance - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); - IsCastingFireball = false; - Fireball_Timer = 5000 + rand32() % 10000; - } - } - else - Fireball_Timer -= diff; + DoAction(ACTION_SCHEDULE_COMBAT_EVENTS); + events.ScheduleEvent(EVENT_PYROBLAST, 60000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_FIREBALL: + DoCastVictim(SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 2500, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_ARCANE_DISRUPTION: + DoCastVictim(SPELL_ARCANE_DISRUPTION, true); + events.ScheduleEvent(EVENT_ARCANE_DISRUPTION, 60000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_FLAMESTRIKE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_FLAME_STRIKE); - //ArcaneDisruption_Timer - if (ArcaneDisruption_Timer <= diff) + events.ScheduleEvent(EVENT_FLAMESTRIKE, 30000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_MIND_CONTROL: + Talk(SAY_MIND_CONTROL); + DoCastAOE(SPELL_MIND_CONTROL, true); + events.ScheduleEvent(EVENT_MIND_CONTROL, 60000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_SUMMON_PHOENIX: + DoCast(me, SPELL_PHOENIX_ANIMATION); + Talk(SAY_SUMMON_PHOENIX); + events.ScheduleEvent(EVENT_SUMMON_PHOENIX, urand(45000, 60000), EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_END_TRANSITION: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + DoCast(SPELL_FULLPOWER); + events.ScheduleEvent(EVENT_TRANSITION_4, 2000); + break; + case EVENT_PYROBLAST: + _pyrosCast = 0; + Talk(EMOTE_PYROBLAST); + DoCast(me, SPELL_SHOCK_BARRIER); + events.DelayEvents(10000, EVENT_GROUP_COMBAT); + events.ScheduleEvent(EVENT_PYROBLAST_CAST, 1000, EVENT_GROUP_SPECIAL, PHASE_COMBAT); + break; + case EVENT_PYROBLAST_CAST: + if (_pyrosCast < 3) { - DoCastVictim(SPELL_ARCANE_DISRUPTION, true); - ArcaneDisruption_Timer = 60000; + DoCastVictim(SPELL_PYROBLAST); + events.ScheduleEvent(EVENT_PYROBLAST_CAST, 3000); + _pyrosCast++; } else - ArcaneDisruption_Timer -= diff; - - if (FlameStrike_Timer <= diff) + events.ScheduleEvent(EVENT_PYROBLAST, 60000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_GRAVITY_LAPSE: + Talk(SAY_GRAVITY_LAPSE); + DoCastAOE(SPELL_GRAVITY_LAPSE); + DoCast(me, SPELL_NETHER_VAPOR); + events.DelayEvents(24000, EVENT_GROUP_COMBAT); + events.ScheduleEvent(EVENT_NETHER_BEAM, 3000, EVENT_GROUP_SPECIAL, PHASE_COMBAT); + events.ScheduleEvent(EVENT_SHOCK_BARRIER, 1000, EVENT_GROUP_SPECIAL, PHASE_COMBAT); + events.ScheduleEvent(EVENT_GRAVITY_LAPSE, 30000, EVENT_GROUP_SPECIAL, PHASE_COMBAT); + break; + case EVENT_NETHER_BEAM: + if (_netherbeamsCast <= 8) { if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(unit, SPELL_FLAME_STRIKE); + DoCast(unit, SPELL_NETHER_BEAM); - FlameStrike_Timer = 30000; + _netherbeamsCast++; + events.ScheduleEvent(EVENT_NETHER_BEAM, 3000); } else - FlameStrike_Timer -= diff; - - if (MindControl_Timer <= diff) - { - if (me->getThreatManager().getThreatList().size() >= 2) - for (uint32 i = 0; i < 3; ++i) - { - TC_LOG_DEBUG("scripts", "Kael'Thas mind control not supported."); - //DoCast(unit, SPELL_MIND_CONTROL); - } - - MindControl_Timer = 60000; - } - else - MindControl_Timer -= diff; - } - - //Phoenix_Timer - if (Phoenix_Timer <= diff) - { - DoCast(me, SPELL_PHOENIX_ANIMATION); - Talk(SAY_SUMMON_PHOENIX); - - Phoenix_Timer = 60000; - } - else - Phoenix_Timer -= diff; - - //Phase 4 specific spells - if (Phase == 4) - { - if (HealthBelowPct(50)) - { - instance->SetData(DATA_KAELTHASEVENT, 4); - Phase = 5; - Phase_Timer = 10000; - - Talk(SAY_PHASE5_NUTS); - - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetPosition(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->MonsterMoveWithSpeed(afGravityPos[0], afGravityPos[1], afGravityPos[2], 1); - - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_FULLPOWER); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ChainPyros = true; - PyrosCast = 0; - ShockBarrier_Timer = 60000; - } - else - ShockBarrier_Timer -= diff; - - //Chain Pyros (3 of them max) - if (ChainPyros && !me->IsNonMeleeSpellCast(false)) - { - if (PyrosCast < 3) - { - DoCastVictim(SPELL_PYROBLAST); - ++PyrosCast; - } - else - { - ChainPyros = false; - Fireball_Timer = 2500; - ArcaneDisruption_Timer = 60000; - } - } - } - - if (Phase == 5) - { - if (Phase_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - me->RemoveAurasDueToSpell(SPELL_FULLPOWER); + _netherbeamsCast = 0; + break; + case EVENT_TRANSITION_1: + me->GetMotionMaster()->MovePoint(POINT_TRANSITION_CENTER_ASCENDING, TransitionPos[1]); + break; + case EVENT_TRANSITION_2: + DoCast(me, SPELL_KAEL_GAINING_POWER); + me->GetMotionMaster()->Clear(); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT); + me->GetMotionMaster()->MovePoint(POINT_TRANSITION_HALFWAY_ASCENDING, TransitionPos[2], false); + break; + case EVENT_TRANSITION_3: + me->GetMotionMaster()->MovePoint(POINT_TRANSITION_TOP, TransitionPos[3], false); + break; + case EVENT_TRANSITION_4: + me->GetMotionMaster()->MovePoint(POINT_TRANSITION_HALFWAY_DESCENDING, TransitionPos[4], false); + break; + case EVENT_TRANSITION_5: + me->GetMotionMaster()->MovePoint(POINT_END_TRANSITION, TransitionPos[5], false); + break; + case EVENT_EXPLODE: + me->InterruptNonMeleeSpells(false); + me->RemoveAurasDueToSpell(SPELL_NETHER_BEAM_VISUAL3); + DoCast(me, SPELL_KAEL_EXPLODES3, true); + DoCast(me, SPELL_KAEL_STUNNED); // Core doesn't handle the emote properly while flying. + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DROWNED); - DoCast(me, SPELL_EXPLODE); + // Destroy the surrounding environment. + if (GameObject* statue = instance->GetGameObject(DATA_KAEL_STATUE_LEFT)) + statue->UseDoorOrButton(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Phase = 6; - AttackStart(me->GetVictim()); - } - else - Phase_Timer -= diff; - } + if (GameObject* statue = instance->GetGameObject(DATA_KAEL_STATUE_RIGHT)) + statue->UseDoorOrButton(); - //Phase 5 - if (Phase == 6) - { - //GravityLapse_Timer - if (GravityLapse_Timer <= diff) - { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); - ThreatContainer::StorageType::const_iterator i = threatlist.begin(); - - switch (GravityLapse_Phase) - { - case 0: - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetPosition(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->MonsterMoveWithSpeed(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - - // 1) Kael'thas will portal the whole raid right into his body - for (i = threatlist.begin(); i != threatlist.end(); ++i) - { - Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); - if (unit && (unit->GetTypeId() == TYPEID_PLAYER)) - { - //Use work around packet to prevent player from being dropped from combat - DoTeleportPlayer(unit, afGravityPos[0], afGravityPos[1], afGravityPos[2], unit->GetOrientation()); - } - } - - GravityLapse_Timer = 500; - ++GravityLapse_Phase; - InGravityLapse = true; - ShockBarrier_Timer = 1000; - NetherBeam_Timer = 5000; - break; - - case 1: - Talk(SAY_GRAVITYLAPSE); - - // 2) At that point he will put a Gravity Lapse debuff on everyone - for (i = threatlist.begin(); i != threatlist.end(); ++i) - { - if (Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - { - DoCast(unit, SPELL_KNOCKBACK, true); - //Gravity lapse - needs an exception in Spell system to work - - unit->CastSpell(unit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); - unit->CastSpell(unit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); - - //Using packet workaround - WorldPacket data(SMSG_MOVE_SET_CAN_FLY, 12); - data << unit->GetPackGUID(); - data << uint32(0); - unit->SendMessageToSet(&data, true); - } - } - GravityLapse_Timer = 10000; - ++GravityLapse_Phase; - break; - - case 2: - //Cast nether vapor aura on self - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_NETHER_VAPOR); - - GravityLapse_Timer = 20000; - ++GravityLapse_Phase; - break; - - case 3: - //Remove flight - for (i = threatlist.begin(); i != threatlist.end(); ++i) - { - if (Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - { - //Using packet workaround - WorldPacket data(SMSG_MOVE_UNSET_CAN_FLY, 12); - data << unit->GetPackGUID(); - data << uint32(0); - unit->SendMessageToSet(&data, true); - } - } - - me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); - InGravityLapse = false; - GravityLapse_Timer = 60000; - GravityLapse_Phase = 0; - AttackStart(me->GetVictim()); - break; - } - } - else - GravityLapse_Timer -= diff; + if (GameObject* window = instance->GetGameObject(DATA_TEMPEST_BRIDGE_WINDOW)) + window->UseDoorOrButton(); - if (InGravityLapse) + events.ScheduleEvent(EVENT_END_TRANSITION, 10000); + break; + case EVENT_SIZE_INCREASE: + switch (_scaleStage) { - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ShockBarrier_Timer = 20000; - } - else - ShockBarrier_Timer -= diff; - - //NetherBeam_Timer - if (NetherBeam_Timer <= diff) - { - if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(unit, SPELL_NETHER_BEAM); - - NetherBeam_Timer = 4000; - } - else - NetherBeam_Timer -= diff; + case 0: + me->SetObjectScale(1.4f); + events.ScheduleEvent(EVENT_SIZE_INCREASE, 5000); + break; + case 1: + me->SetObjectScale(1.8f); + events.ScheduleEvent(EVENT_SIZE_INCREASE, 3000); + break; + case 2: + me->SetObjectScale(2.0f); + events.ScheduleEvent(EVENT_SIZE_INCREASE, 1000); + break; + case 3: + me->SetObjectScale(2.2f); + break; + default: + break; } - } - - if (!InGravityLapse) - DoMeleeAttackIfReady(); + ++_scaleStage; + break; + default: + break; } } + + if (events.IsInPhase(PHASE_COMBAT)) + DoMeleeAttackIfReady(); } + private: + uint8 _advisorCounter; + uint8 _phase; + uint8 _pyrosCast; + uint8 _scaleStage; + uint8 _netherbeamsCast; + bool _hasFullPower; + ObjectGuid _advisorGuid[MAX_ADVISORS]; }; + CreatureAI* GetAI(Creature* creature) const override { return GetInstanceAI<boss_kaelthasAI>(creature); } }; -//Thaladred the Darkener AI class boss_thaladred_the_darkener : public CreatureScript { public: boss_thaladred_the_darkener() : CreatureScript("boss_thaladred_the_darkener") { } - + struct boss_thaladred_the_darkenerAI : public advisorbase_ai { boss_thaladred_the_darkenerAI(Creature* creature) : advisorbase_ai(creature) @@ -1040,32 +897,23 @@ class boss_thaladred_the_darkener : public CreatureScript void EnterCombat(Unit* who) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - Talk(SAY_THALADRED_AGGRO); me->AddThreat(who, 5000000.0f); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - if (instance->GetData(DATA_KAELTHASEVENT) == 3) + if (_hasRessurrected) Talk(SAY_THALADRED_DEATH); + + advisorbase_ai::JustDied(killer); } void UpdateAI(uint32 diff) override { advisorbase_ai::UpdateAI(diff); - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || _inFakeDeath) return; //Gaze_Timer @@ -1110,13 +958,12 @@ class boss_thaladred_the_darkener : public CreatureScript } }; -//Lord Sanguinar AI class boss_lord_sanguinar : public CreatureScript { public: boss_lord_sanguinar() : CreatureScript("boss_lord_sanguinar") { } - + struct boss_lord_sanguinarAI : public advisorbase_ai { boss_lord_sanguinarAI(Creature* creature) : advisorbase_ai(creature) @@ -1137,33 +984,24 @@ class boss_lord_sanguinar : public CreatureScript advisorbase_ai::Reset(); } - void EnterCombat(Unit* who) override + void EnterCombat(Unit* /*who*/) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - Talk(SAY_SANGUINAR_AGGRO); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - if (instance->GetData(DATA_KAELTHASEVENT) == 3) + if (_hasRessurrected) Talk(SAY_SANGUINAR_DEATH); + + advisorbase_ai::JustDied(killer); } void UpdateAI(uint32 diff) override { advisorbase_ai::UpdateAI(diff); - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || _inFakeDeath) return; //Fear_Timer @@ -1183,13 +1021,13 @@ class boss_lord_sanguinar : public CreatureScript return GetInstanceAI<boss_lord_sanguinarAI>(creature); } }; -//Grand Astromancer Capernian AI + class boss_grand_astromancer_capernian : public CreatureScript { public: boss_grand_astromancer_capernian() : CreatureScript("boss_grand_astromancer_capernian") { } - + struct boss_grand_astromancer_capernianAI : public advisorbase_ai { boss_grand_astromancer_capernianAI(Creature* creature) : advisorbase_ai(creature) @@ -1219,15 +1057,17 @@ class boss_grand_astromancer_capernian : public CreatureScript advisorbase_ai::Reset(); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - if (instance->GetData(DATA_KAELTHASEVENT) == 3) + if (_hasRessurrected) Talk(SAY_CAPERNIAN_DEATH); + + advisorbase_ai::JustDied(killer); } void AttackStart(Unit* who) override { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + if (!who || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return; if (me->Attack(who, true)) @@ -1240,39 +1080,18 @@ class boss_grand_astromancer_capernian : public CreatureScript } } - void EnterCombat(Unit* who) override + void EnterCombat(Unit* /*who*/) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; + Talk(SAY_CAPERNIAN_AGGRO); } void UpdateAI(uint32 diff) override { advisorbase_ai::UpdateAI(diff); - //Faking Death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || _inFakeDeath) return; - //Yell_Timer - if (!Yell) - { - if (Yell_Timer <= diff) - { - Talk(SAY_CAPERNIAN_AGGRO); - Yell = true; - } - else - Yell_Timer -= diff; - } - //Fireball_Timer if (Fireball_Timer <= diff) { @@ -1334,7 +1153,6 @@ class boss_grand_astromancer_capernian : public CreatureScript } }; -//Master Engineer Telonicus AI class boss_master_engineer_telonicus : public CreatureScript { public: @@ -1364,20 +1182,16 @@ class boss_master_engineer_telonicus : public CreatureScript advisorbase_ai::Reset(); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - if (instance->GetData(DATA_KAELTHASEVENT) == 3) + if (_hasRessurrected) Talk(SAY_TELONICUS_DEATH); + + advisorbase_ai::JustDied(killer); } - void EnterCombat(Unit* who) override + void EnterCombat(Unit* /*who*/) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - Talk(SAY_TELONICUS_AGGRO); } @@ -1385,12 +1199,7 @@ class boss_master_engineer_telonicus : public CreatureScript { advisorbase_ai::UpdateAI(diff); - //Faking Death, do nothing - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || _inFakeDeath) return; //Bomb_Timer @@ -1423,7 +1232,6 @@ class boss_master_engineer_telonicus : public CreatureScript } }; -//Flame Strike AI class npc_kael_flamestrike : public CreatureScript { public: @@ -1478,7 +1286,7 @@ class npc_kael_flamestrike : public CreatureScript DoCast(me, SPELL_FLAME_STRIKE_DMG); } else - me->Kill(me); + me->KillSelf(); KillSelf = true; Timer = 1000; @@ -1494,13 +1302,12 @@ class npc_kael_flamestrike : public CreatureScript } }; -//Phoenix AI class npc_phoenix_tk : public CreatureScript { public: npc_phoenix_tk() : CreatureScript("npc_phoenix_tk") { } - + struct npc_phoenix_tkAI : public ScriptedAI { npc_phoenix_tkAI(Creature* creature) : ScriptedAI(creature) @@ -1554,13 +1361,12 @@ class npc_phoenix_tk : public CreatureScript } }; -//Phoenix Egg AI class npc_phoenix_egg_tk : public CreatureScript { public: npc_phoenix_egg_tk() : CreatureScript("npc_phoenix_egg_tk") { } - + struct npc_phoenix_egg_tkAI : public ScriptedAI { npc_phoenix_egg_tkAI(Creature* creature) : ScriptedAI(creature) @@ -1621,6 +1427,54 @@ class npc_phoenix_egg_tk : public CreatureScript } }; +// 35941 - Gravity Lapse +class spell_kael_gravity_lapse : public SpellScriptLoader +{ + public: + spell_kael_gravity_lapse() : SpellScriptLoader("spell_kael_gravity_lapse") { } + + class spell_kael_gravity_lapse_SpellScript : public SpellScript + { + PrepareSpellScript(spell_kael_gravity_lapse_SpellScript); + + public: + spell_kael_gravity_lapse_SpellScript() + { + _targetCount = 0; + } + + bool Validate(SpellInfo const* /*spell*/) override + { + for (uint8 i = 0; i < 25; ++i) + if (!sSpellMgr->GetSpellInfo(GravityLapseSpells[i])) + return false; + + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), GravityLapseSpells[_targetCount], true); + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_GRAVITY_LAPSE_PERIODIC, true); + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_GRAVITY_LAPSE_FLIGHT_AURA, true); + _targetCount++; + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_kael_gravity_lapse_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + + private: + uint8 _targetCount; + }; + + SpellScript* GetSpellScript() const override + { + return new spell_kael_gravity_lapse_SpellScript(); + } +}; + void AddSC_boss_kaelthas() { new boss_kaelthas(); @@ -1631,4 +1485,5 @@ void AddSC_boss_kaelthas() new npc_kael_flamestrike(); new npc_phoenix_tk(); new npc_phoenix_egg_tk(); + new spell_kael_gravity_lapse(); } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp index c421b9974ce..173e0596bea 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp @@ -34,6 +34,21 @@ EndScriptData */ 3 - Void Reaver event */ +DoorData const doorData[] = +{ + { GO_ARCANE_DOOR_LEFT, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_SW }, + { GO_ARCANE_DOOR_RIGHT, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_SE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; + +ObjectData const gameObjectData[] = +{ + { GO_KAEL_STATUE_RIGHT, DATA_KAEL_STATUE_RIGHT }, + { GO_KAEL_STATUE_LEFT, DATA_KAEL_STATUE_LEFT }, + { GO_TEMPEST_BRIDDGE_WINDOW, DATA_TEMPEST_BRIDGE_WINDOW }, + { 0, 0 } // END +}; + class instance_the_eye : public InstanceMapScript { public: @@ -45,8 +60,8 @@ class instance_the_eye : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); - - KaelthasEventPhase = 0; + LoadDoorData(doorData); + LoadObjectData(nullptr, gameObjectData); } ObjectGuid ThaladredTheDarkener; @@ -56,7 +71,6 @@ class instance_the_eye : public InstanceMapScript ObjectGuid Kaelthas; ObjectGuid Astromancer; ObjectGuid Alar; - uint8 KaelthasEventPhase; void OnCreatureCreate(Creature* creature) override { @@ -102,28 +116,6 @@ class instance_the_eye : public InstanceMapScript } return ObjectGuid::Empty; } - - void SetData(uint32 type, uint32 data) override - { - switch (type) - { - case DATA_KAELTHASEVENT: - KaelthasEventPhase = data; - break; - default: - break; - } - } - - uint32 GetData(uint32 type) const override - { - switch (type) - { - case DATA_KAELTHASEVENT: - return KaelthasEventPhase; - } - return 0; - } }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h index c46fe408274..ca60e14e923 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h +++ b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h @@ -33,10 +33,14 @@ enum DataTypes DATA_ASTROMANCER = 4, DATA_GRANDASTROMANCERCAPERNIAN = 5, - DATA_KAELTHASEVENT = 6, - DATA_LORDSANGUINAR = 7, - DATA_MASTERENGINEERTELONICUS = 8, - DATA_THALADREDTHEDARKENER = 9 + DATA_LORDSANGUINAR = 6, + DATA_MASTERENGINEERTELONICUS = 7, + DATA_THALADREDTHEDARKENER = 8, + + // Additional Data + DATA_KAEL_STATUE_LEFT = 9, + DATA_KAEL_STATUE_RIGHT = 10, + DATA_TEMPEST_BRIDGE_WINDOW = 11 }; enum CreatureIds @@ -50,4 +54,13 @@ enum CreatureIds NPC_ALAR = 19514 }; +enum GameObjectIds +{ + GO_TEMPEST_BRIDDGE_WINDOW = 184069, + GO_KAEL_STATUE_RIGHT = 184596, + GO_KAEL_STATUE_LEFT = 184597, + GO_ARCANE_DOOR_LEFT = 184324, + GO_ARCANE_DOOR_RIGHT = 184325 +}; + #endif diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index d1a31906d58..0a9f8640ad2 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -165,7 +165,6 @@ public: void Reset() override { - ryga = NULL; } // Override Evade Mode event, recast buff that was removed by standard handler @@ -175,15 +174,6 @@ public: DoCast(me, SPELL_ANCESTRAL_WOLF_BUFF, true); } - void MoveInLineOfSight(Unit* who) override - { - if (!ryga && who->GetEntry() == NPC_RYGA && me->IsWithinDistInMap(who, 15.0f)) - if (Creature* temp = who->ToCreature()) - ryga = temp; - - npc_escortAI::MoveInLineOfSight(who); - } - void WaypointReached(uint32 waypointId) override { switch (waypointId) @@ -238,9 +228,6 @@ public: break; } } - - private: - Creature* ryga; }; CreatureAI* GetAI(Creature* creature) const override @@ -496,7 +483,7 @@ class npc_barada : public CreatureScript { public: npc_barada() : CreatureScript("npc_barada") { } - + struct npc_baradaAI : public ScriptedAI { npc_baradaAI(Creature* creature) : ScriptedAI(creature) @@ -792,7 +779,7 @@ public: me->SetCanFly(true); me->SetSpeed(MOVE_RUN, 0.2f); - + me->SetFacingTo(3.207566f); me->GetMotionMaster()->MoveJump(exorcismPos[2], 2.0f, 2.0f); @@ -873,14 +860,14 @@ public: } } } - + private: EventMap events; SummonList summons; - + uint8 circleRounds; uint8 point; - + bool wpreached; }; diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp index 0fd5a82d7e8..7e64fbfd27d 100644 --- a/src/server/scripts/Pet/pet_mage.cpp +++ b/src/server/scripts/Pet/pet_mage.cpp @@ -59,9 +59,9 @@ class npc_pet_mage_mirror_image : public CreatureScript Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); me->VisitNearbyObject(40.0f, searcher); - Unit* highestThreatUnit = NULL; + Unit* highestThreatUnit = nullptr; float highestThreat = 0.0f; - Unit* nearestPlayer = NULL; + Unit* nearestPlayer = nullptr; for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) { // Consider only units without CC @@ -107,7 +107,6 @@ class npc_pet_mage_mirror_image : public CreatureScript // Prioritize units with threat referenced to owner if (highestThreat > 0.0f && highestThreatUnit) me->Attack(highestThreatUnit, false); - // If there is no such target, try to attack nearest hostile unit if such exists else if (nearestPlayer) me->Attack(nearestPlayer, false); @@ -193,9 +192,9 @@ class npc_pet_mage_mirror_image : public CreatureScript return; // assign target if image doesnt have any or the target is not actual - if (me->GetVictim() && me->GetVictim() != target || !me->GetVictim()) + if (!target || me->GetVictim() != target) { - Unit* ownerTarget = NULL; + Unit* ownerTarget = nullptr; if (Player* owner = me->GetCharmerOrOwner()->ToPlayer()) ownerTarget = owner->GetSelectedUnit(); diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index cd0052c24bc..88271dc7139 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -1343,6 +1343,15 @@ class spell_dk_raise_dead : public SpellScriptLoader GetCaster()->CastSpell(targets, spellInfo, NULL, TRIGGERED_FULL_MASK); } + void OverrideCooldown() + { + // Because the ghoul is summoned by one of triggered spells SendCooldownEvent is not sent for this spell + // but the client has locked it by itself so we need some link between this spell and the real spell summoning. + // Luckily such link already exists - spell category + // This starts infinite category cooldown which can later be used by SendCooldownEvent to send packet for this spell + GetCaster()->GetSpellHistory()->StartCooldown(GetSpellInfo(), 0, nullptr, true); + } + void Register() override { OnCheckCast += SpellCheckCastFn(spell_dk_raise_dead_SpellScript::CheckCast); @@ -1351,6 +1360,7 @@ class spell_dk_raise_dead : public SpellScriptLoader OnCast += SpellCastFn(spell_dk_raise_dead_SpellScript::ConsumeReagents); OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_2, SPELL_EFFECT_DUMMY); + AfterCast += SpellCastFn(spell_dk_raise_dead_SpellScript::OverrideCooldown); } private: diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 68c115f9faf..ca8c9a9ef93 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -614,6 +614,47 @@ class spell_gen_burn_brutallus : public SpellScriptLoader } }; +// 48750 - Burning Depths Necrolyte Image +class spell_gen_burning_depths_necrolyte_image : public SpellScriptLoader +{ + public: + spell_gen_burning_depths_necrolyte_image() : SpellScriptLoader("spell_gen_burning_depths_necrolyte_image") { } + + class spell_gen_burning_depths_necrolyte_image_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_burning_depths_necrolyte_image_AuraScript); + + bool Validate(SpellInfo const* spellInfo) override + { + if (!sSpellMgr->GetSpellInfo(uint32(spellInfo->Effects[EFFECT_2].CalcValue()))) + return false; + return true; + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(GetTarget(), uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue())); + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveAurasDueToSpell(uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue()), GetCasterGUID()); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_gen_burning_depths_necrolyte_image_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_gen_burning_depths_necrolyte_image_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_TRANSFORM, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gen_burning_depths_necrolyte_image_AuraScript(); + } +}; + enum CannibalizeSpells { SPELL_CANNIBALIZE_TRIGGERED = 20578 @@ -3383,7 +3424,7 @@ class spell_gen_turkey_marker : public SpellScriptLoader void Register() override { - AfterEffectApply += AuraEffectApplyFn(spell_gen_turkey_marker_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectApply += AuraEffectApplyFn(spell_gen_turkey_marker_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK); OnEffectPeriodic += AuraEffectPeriodicFn(spell_gen_turkey_marker_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } @@ -4093,6 +4134,7 @@ void AddSC_generic_spell_scripts() new spell_gen_break_shield("spell_gen_break_shield"); new spell_gen_break_shield("spell_gen_tournament_counterattack"); new spell_gen_burn_brutallus(); + new spell_gen_burning_depths_necrolyte_image(); new spell_gen_cannibalize(); new spell_gen_chaos_blast(); new spell_gen_clone(); diff --git a/src/server/scripts/Spells/spell_holiday.cpp b/src/server/scripts/Spells/spell_holiday.cpp index 93e13667cb0..e29f87a5ff9 100644 --- a/src/server/scripts/Spells/spell_holiday.cpp +++ b/src/server/scripts/Spells/spell_holiday.cpp @@ -277,6 +277,86 @@ class spell_hallow_end_tricky_treat : public SpellScriptLoader } }; +// Hallowed wands +enum HallowendData +{ + //wand spells + SPELL_HALLOWED_WAND_PIRATE = 24717, + SPELL_HALLOWED_WAND_NINJA = 24718, + SPELL_HALLOWED_WAND_LEPER_GNOME = 24719, + SPELL_HALLOWED_WAND_RANDOM = 24720, + SPELL_HALLOWED_WAND_SKELETON = 24724, + SPELL_HALLOWED_WAND_WISP = 24733, + SPELL_HALLOWED_WAND_GHOST = 24737, + SPELL_HALLOWED_WAND_BAT = 24741 +}; + +class spell_hallow_end_wand : public SpellScriptLoader +{ +public: + spell_hallow_end_wand() : SpellScriptLoader("spell_hallow_end_wand") {} + + class spell_hallow_end_wand_SpellScript : public SpellScript + { + PrepareSpellScript(spell_hallow_end_wand_SpellScript); + + bool Validate(SpellInfo const* /*spellEntry*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PIRATE_COSTUME_MALE) || + !sSpellMgr->GetSpellInfo(SPELL_PIRATE_COSTUME_FEMALE) || + !sSpellMgr->GetSpellInfo(SPELL_NINJA_COSTUME_MALE) || + !sSpellMgr->GetSpellInfo(SPELL_NINJA_COSTUME_FEMALE) || + !sSpellMgr->GetSpellInfo(SPELL_LEPER_GNOME_COSTUME_MALE) || + !sSpellMgr->GetSpellInfo(SPELL_LEPER_GNOME_COSTUME_FEMALE) || + !sSpellMgr->GetSpellInfo(SPELL_GHOST_COSTUME_MALE) || + !sSpellMgr->GetSpellInfo(SPELL_GHOST_COSTUME_FEMALE)) + return false; + return true; + } + + void HandleScriptEffect() + { + Unit* caster = GetCaster(); + Unit* target = GetHitUnit(); + + uint32 spellId = 0; + uint8 gender = target->getGender(); + + switch (GetSpellInfo()->Id) + { + case SPELL_HALLOWED_WAND_LEPER_GNOME: + spellId = gender ? SPELL_LEPER_GNOME_COSTUME_FEMALE : SPELL_LEPER_GNOME_COSTUME_MALE; + break; + case SPELL_HALLOWED_WAND_PIRATE: + spellId = gender ? SPELL_PIRATE_COSTUME_FEMALE : SPELL_PIRATE_COSTUME_MALE; + break; + case SPELL_HALLOWED_WAND_GHOST: + spellId = gender ? SPELL_GHOST_COSTUME_FEMALE : SPELL_GHOST_COSTUME_MALE; + break; + case SPELL_HALLOWED_WAND_NINJA: + spellId = gender ? SPELL_NINJA_COSTUME_FEMALE : SPELL_NINJA_COSTUME_MALE; + break; + case SPELL_HALLOWED_WAND_RANDOM: + spellId = RAND(SPELL_HALLOWED_WAND_PIRATE, SPELL_HALLOWED_WAND_NINJA, SPELL_HALLOWED_WAND_LEPER_GNOME, SPELL_HALLOWED_WAND_SKELETON, SPELL_HALLOWED_WAND_WISP, SPELL_HALLOWED_WAND_GHOST, SPELL_HALLOWED_WAND_BAT); + break; + default: + return; + } + caster->CastSpell(target, spellId, true); + } + + void Register() override + { + AfterHit += SpellHitFn(spell_hallow_end_wand_SpellScript::HandleScriptEffect); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_hallow_end_wand_SpellScript(); + } +}; + enum PilgrimsBountyBuffFood { // Pilgrims Bounty Buff Food @@ -824,6 +904,60 @@ class spell_brewfest_barker_bunny : public SpellScriptLoader } }; +enum TorchSpells +{ + SPELL_TORCH_TOSSING_TRAINING = 45716, + SPELL_TORCH_TOSSING_PRACTICE = 46630, + SPELL_TORCH_TOSSING_TRAINING_SUCCESS_ALLIANCE = 45719, + SPELL_TORCH_TOSSING_TRAINING_SUCCESS_HORDE = 46651, + SPELL_BRAZIERS_HIT = 45724 +}; + +// 45724 - Braziers Hit! +class spell_midsummer_braziers_hit : public SpellScriptLoader +{ + public: + spell_midsummer_braziers_hit() : SpellScriptLoader("spell_midsummer_braziers_hit") { } + + class spell_midsummer_braziers_hit_AuraScript : public AuraScript + { + PrepareAuraScript(spell_midsummer_braziers_hit_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_TORCH_TOSSING_TRAINING) || !sSpellMgr->GetSpellInfo(SPELL_TORCH_TOSSING_PRACTICE)) + return false; + return true; + } + + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + Player* player = GetTarget()->ToPlayer(); + if (!player) + return; + + if ((player->HasAura(SPELL_TORCH_TOSSING_TRAINING) && GetStackAmount() == 8) || (player->HasAura(SPELL_TORCH_TOSSING_PRACTICE) && GetStackAmount() == 20)) + { + if (player->GetTeam() == ALLIANCE) + player->CastSpell(player, SPELL_TORCH_TOSSING_TRAINING_SUCCESS_ALLIANCE, true); + else if (player->GetTeam() == HORDE) + player->CastSpell(player, SPELL_TORCH_TOSSING_TRAINING_SUCCESS_HORDE, true); + Remove(); + } + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_midsummer_braziers_hit_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AuraEffectHandleModes(AURA_EFFECT_HANDLE_REAPPLY)); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_midsummer_braziers_hit_AuraScript(); + } +}; + void AddSC_holiday_spell_scripts() { // Love is in the Air @@ -832,6 +966,7 @@ void AddSC_holiday_spell_scripts() new spell_hallow_end_trick(); new spell_hallow_end_trick_or_treat(); new spell_hallow_end_tricky_treat(); + new spell_hallow_end_wand(); // Pilgrims Bounty new spell_pilgrims_bounty_buff_food("spell_gen_slow_roasted_turkey", SPELL_WELL_FED_AP_TRIGGER); new spell_pilgrims_bounty_buff_food("spell_gen_cranberry_chutney", SPELL_WELL_FED_ZM_TRIGGER); @@ -850,4 +985,6 @@ void AddSC_holiday_spell_scripts() new spell_brewfest_relay_race_intro_force_player_to_throw(); new spell_brewfest_dismount_ram(); new spell_brewfest_barker_bunny(); + // Midsummer Fire Festival + new spell_midsummer_braziers_hit(); } diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 75df264360f..0ca4112b288 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -213,6 +213,8 @@ class spell_hun_chimera_shot : public SpellScriptLoader basePoint = (aurEff->GetAmount() + aurEff->GetBonusAmount()) * aurEff->GetDonePct(); ApplyPct(basePoint, TickCount * 40); basePoint = unitTarget->SpellDamageBonusTaken(caster, aura->GetSpellInfo(), basePoint, DOT, aura->GetStackAmount()); + if (Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(aura->GetSpellInfo()->Id, SPELLMOD_DOT, basePoint); aurEff->SetBonusAmount(caster->SpellDamageBonusDone(unitTarget, aurEff->GetSpellInfo(), 0, DOT)); } @@ -478,7 +480,7 @@ class spell_hun_misdirection : public SpellScriptLoader void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT) + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEFAULT || !GetTarget()->HasAura(SPELL_HUNTER_MISDIRECTION_PROC)) GetTarget()->ResetRedirectThreat(); } @@ -638,6 +640,45 @@ class spell_hun_pet_heart_of_the_phoenix : public SpellScriptLoader } }; +// 56654, 58882 - Rapid Recuperation +class spell_hun_rapid_recuperation : public SpellScriptLoader +{ + public: + spell_hun_rapid_recuperation() : SpellScriptLoader("spell_hun_rapid_recuperation") { } + + class spell_hun_rapid_recuperation_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_rapid_recuperation_AuraScript); + + bool Validate(SpellInfo const* spellInfo) override + { + if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_0].TriggerSpell)) + return false; + return true; + } + + void HandlePeriodic(AuraEffect const* aurEff) + { + PreventDefaultAction(); + + Unit* target = GetTarget(); + uint32 mana = CalculatePct(target->GetMaxPower(POWER_MANA), aurEff->GetAmount()); + + target->CastCustomSpell(GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, SPELLVALUE_BASE_POINT0, int32(mana), target, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_hun_rapid_recuperation_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_hun_rapid_recuperation_AuraScript(); + } +}; + // 23989 - Readiness class spell_hun_readiness : public SpellScriptLoader { @@ -919,6 +960,7 @@ 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_rapid_recuperation(); new spell_hun_readiness(); new spell_hun_scatter_shot(); new spell_hun_sniper_training(); diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 717382a0e36..f0b6c0945c2 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -2509,7 +2509,7 @@ class spell_item_chicken_cover : public SpellScriptLoader if (!target->HasAura(SPELL_CHICKEN_NET) && (caster->GetQuestStatus(QUEST_CHICKEN_PARTY) == QUEST_STATUS_INCOMPLETE || caster->GetQuestStatus(QUEST_FLOWN_THE_COOP) == QUEST_STATUS_INCOMPLETE)) { caster->CastSpell(caster, SPELL_CAPTURE_CHICKEN_ESCAPE, true); - target->Kill(target); + target->KillSelf(); } } } diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 4edbf8822f7..c45442e1f80 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -45,11 +45,17 @@ enum MageSpells SPELL_MAGE_WORGEN_FORM = 32819, SPELL_MAGE_SHEEP_FORM = 32820, SPELL_MAGE_GLYPH_OF_ETERNAL_WATER = 70937, + SPELL_MAGE_SHATTERED_BARRIER = 55080, SPELL_MAGE_SUMMON_WATER_ELEMENTAL_PERMANENT = 70908, SPELL_MAGE_SUMMON_WATER_ELEMENTAL_TEMPORARY = 70907, SPELL_MAGE_GLYPH_OF_BLAST_WAVE = 62126, }; +enum MageSpellIcons +{ + SPELL_ICON_MAGE_SHATTERED_BARRIER = 2945 +}; + // Incanter's Absorbtion class spell_mage_incanters_absorbtion_base_AuraScript : public AuraScript { @@ -321,6 +327,13 @@ class spell_mage_ice_barrier : public SpellScriptLoader { PrepareAuraScript(spell_mage_ice_barrier_AuraScript); + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_SHATTERED_BARRIER)) + return false; + return true; + } + void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) { canBeRecalculated = false; @@ -341,10 +354,22 @@ class spell_mage_ice_barrier : public SpellScriptLoader } } + void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/) + { + // Shattered Barrier + // Procs only if removed by damage. + if (aurEff->GetAmount() <= 0) + if (Unit* caster = GetCaster()) + if (AuraEffect* dummy = caster->GetDummyAuraEffect(SPELLFAMILY_MAGE, SPELL_ICON_MAGE_SHATTERED_BARRIER, EFFECT_0)) + if (roll_chance_i(dummy->GetSpellInfo()->ProcChance)) + caster->CastSpell(GetTarget(), SPELL_MAGE_SHATTERED_BARRIER, true, nullptr, aurEff); + } + void Register() override { DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_ice_barrier_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); AfterEffectAbsorb += AuraEffectAbsorbFn(spell_mage_ice_barrier_AuraScript::Trigger, EFFECT_0); + AfterEffectRemove += AuraEffectRemoveFn(spell_mage_ice_barrier_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); } }; diff --git a/src/server/scripts/Spells/spell_pet.cpp b/src/server/scripts/Spells/spell_pet.cpp index 764debc1a6b..a0664a2ea00 100644 --- a/src/server/scripts/Spells/spell_pet.cpp +++ b/src/server/scripts/Spells/spell_pet.cpp @@ -1367,7 +1367,7 @@ public: if (GetCaster()->GetOwner()->ToPlayer()) { // Pet's base damage changes depending on happiness - if (GetCaster()->IsPet() && GetCaster()->ToPet()->IsHunterPet()) + if (GetCaster()->IsPet() && GetCaster()->IsHunterPet()) { switch (GetCaster()->ToPet()->GetHappinessState()) { diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 60ff67d74c0..8af97e46dee 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -2453,6 +2453,35 @@ class spell_q12414_hand_over_reins : public SpellScriptLoader } }; +// 13790 13793 13811 13814 - Among the Champions +// 13665 13745 13750 13756 13761 13767 13772 13777 13782 13787 - The Grand Melee +class spell_q13665_q13790_bested_trigger : public SpellScriptLoader +{ + public: + spell_q13665_q13790_bested_trigger() : SpellScriptLoader("spell_q13665_q13790_bested_trigger") { } + + class spell_q13665_q13790_bested_trigger_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q13665_q13790_bested_trigger_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* target = GetHitUnit()->GetCharmerOrOwnerOrSelf(); + target->CastSpell(target, uint32(GetEffectValue())); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_q13665_q13790_bested_trigger_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_q13665_q13790_bested_trigger_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -2512,4 +2541,5 @@ void AddSC_quest_spell_scripts() new spell_q14100_q14111_make_player_destroy_totems(); new spell_q10929_fumping(); new spell_q12414_hand_over_reins(); + new spell_q13665_q13790_bested_trigger(); } diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index da50f471f1c..23a6cdee8a9 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -233,7 +233,7 @@ class spell_rog_deadly_poison : public SpellScriptLoader SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(enchant->spellid[s]); if (!spellInfo) { - TC_LOG_ERROR("spells", "Player::CastItemCombatSpell Enchant %i, player (Name: %s, GUID: %u) cast unknown spell %i", enchant->ID, player->GetName().c_str(), player->GetGUIDLow(), enchant->spellid[s]); + TC_LOG_ERROR("spells", "Player::CastItemCombatSpell Enchant %i, player (Name: %s, GUID: %u) cast unknown spell %i", enchant->ID, player->GetName().c_str(), player->GetGUID().GetCounter(), enchant->spellid[s]); continue; } diff --git a/src/server/scripts/World/action_ip_logger.cpp b/src/server/scripts/World/action_ip_logger.cpp index 50195887ec2..f0ffbe1c7f3 100644 --- a/src/server/scripts/World/action_ip_logger.cpp +++ b/src/server/scripts/World/action_ip_logger.cpp @@ -96,7 +96,7 @@ class AccountActionIpLogger : public AccountScript // We declare all the required variables uint32 playerGuid = accountId; - uint32 characterGuid = 0; + ObjectGuid::LowType characterGuid = 0; std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it later. // With this switch, we change systemNote so that we have a more accurate phrasing of what type it is. @@ -201,7 +201,7 @@ class CharacterActionIpLogger : public PlayerScript // We declare all the required variables uint32 playerGuid = player->GetSession()->GetAccountId(); - uint32 characterGuid = player->GetGUIDLow(); + ObjectGuid::LowType characterGuid = player->GetGUID().GetCounter(); const std::string currentIp = player->GetSession()->GetRemoteAddress(); std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it... @@ -269,7 +269,7 @@ public: // Else, this script isn't loaded in the first place: We require no config check. // We declare all the required variables - uint32 characterGuid = guid.GetCounter(); // We have no access to any member function of Player* or WorldSession*. So use old-fashioned way. + ObjectGuid::LowType characterGuid = guid.GetCounter(); // We have no access to any member function of Player* or WorldSession*. So use old-fashioned way. // Query playerGuid/accountId, as we only have characterGuid std::string systemNote = "ERROR"; // "ERROR" is a placeholder here. We change it later. diff --git a/src/server/scripts/World/duel_reset.cpp b/src/server/scripts/World/duel_reset.cpp new file mode 100644 index 00000000000..9e720455692 --- /dev/null +++ b/src/server/scripts/World/duel_reset.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2008-2015 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 "Player.h" +#include "Pet.h" +#include "SpellInfo.h" + +class DuelResetScript : public PlayerScript +{ + public: + DuelResetScript() : PlayerScript("DuelResetScript") { } + + // Called when a duel starts (after 3s countdown) + void OnDuelStart(Player* player1, Player* player2) override + { + // Cooldowns reset + if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_COOLDOWNS)) + { + player1->GetSpellHistory()->SaveCooldownStateBeforeDuel(); + player2->GetSpellHistory()->SaveCooldownStateBeforeDuel(); + + + ResetSpellCooldowns(player1); + ResetSpellCooldowns(player2); + } + + // Health and mana reset + if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_HEALTH_MANA)) + { + player1->SaveHealthBeforeDuel(); + player1->SetHealth(player1->GetMaxHealth()); + + player2->SaveHealthBeforeDuel(); + player2->SetHealth(player2->GetMaxHealth()); + + // check if player1 class uses mana + if (player1->getPowerType() == POWER_MANA || player1->getClass() == CLASS_DRUID) + { + player1->SaveManaBeforeDuel(); + player1->SetPower(POWER_MANA, player1->GetMaxPower(POWER_MANA)); + } + + // check if player2 class uses mana + if (player2->getPowerType() == POWER_MANA || player2->getClass() == CLASS_DRUID) + { + player2->SaveManaBeforeDuel(); + player2->SetPower(POWER_MANA, player2->GetMaxPower(POWER_MANA)); + } + } + } + + // Called when a duel ends + void OnDuelEnd(Player* winner, Player* loser, DuelCompleteType type) override + { + // do not reset anything if DUEL_INTERRUPTED or DUEL_FLED + if (type == DUEL_WON) + { + // Cooldown restore + if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_COOLDOWNS)) + { + + ResetSpellCooldowns(winner); + ResetSpellCooldowns(loser); + + winner->GetSpellHistory()->RestoreCooldownStateAfterDuel(); + loser->GetSpellHistory()->RestoreCooldownStateAfterDuel(); + } + + // Health and mana restore + if (sWorld->getBoolConfig(CONFIG_RESET_DUEL_HEALTH_MANA)) + { + winner->RestoreHealthAfterDuel(); + loser->RestoreHealthAfterDuel(); + + // check if player1 class uses mana + if (winner->getPowerType() == POWER_MANA || winner->getClass() == CLASS_DRUID) + winner->RestoreManaAfterDuel(); + + // check if player2 class uses mana + if (loser->getPowerType() == POWER_MANA || loser->getClass() == CLASS_DRUID) + loser->RestoreManaAfterDuel(); + } + } + } + + static void ResetSpellCooldowns(Player* player) + { + // 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 && !itr->second.OnHold; + }, true); + + // pet cooldowns + if (Pet* pet = player->GetPet()) + pet->GetSpellHistory()->ResetAllCooldowns(); + } +}; + +void AddSC_duel_reset() +{ + new DuelResetScript(); +} + diff --git a/src/server/scripts/World/npc_professions.cpp b/src/server/scripts/World/npc_professions.cpp index 44411b20aaf..9c05e4e2c08 100644 --- a/src/server/scripts/World/npc_professions.cpp +++ b/src/server/scripts/World/npc_professions.cpp @@ -179,6 +179,52 @@ enum ProfessionSpells }; /*### +# specialization trainers +###*/ +enum SpecializationTrainers +{ + /* Alchemy */ + N_TRAINER_TRANSMUTE = 22427, // Zarevhi + N_TRAINER_ELIXIR = 19052, // Lorokeem + N_TRAINER_POTION = 17909, // Lauranna Thar'well + + /* Blacksmithing */ + N_TRAINER_SMITHOMNI1 = 11145, // Myolor Sunderfury + N_TRAINER_SMITHOMNI2 = 11176, // Krathok Moltenfist + N_TRAINER_WEAPON1 = 11146, // Ironus Coldsteel + N_TRAINER_WEAPON2 = 11178, // Borgosh Corebender + N_TRAINER_ARMOR1 = 5164, // Grumnus Steelshaper + N_TRAINER_ARMOR2 = 11177, // Okothos Ironrager + N_TRAINER_HAMMER = 11191, // Lilith the Lithe + N_TRAINER_AXE = 11192, // Kilram + N_TRAINER_SWORD = 11193, // Seril Scourgebane + + /* Leatherworking */ + N_TRAINER_DRAGON1 = 7866, // Peter Galen + N_TRAINER_DRAGON2 = 7867, // Thorkaf Dragoneye + N_TRAINER_ELEMENTAL1 = 7868, // Sarah Tanner + N_TRAINER_ELEMENTAL2 = 7869, // Brumn Winterhoof + N_TRAINER_TRIBAL1 = 7870, // Caryssia Moonhunter + N_TRAINER_TRIBAL2 = 7871, // Se'Jib + + /* Tailoring */ + N_TRAINER_SPELLFIRE = 22213, // Gidge Spellweaver + N_TRAINER_MOONCLOTH = 22208, // Nasmara Moonsong + N_TRAINER_SHADOWEAVE = 22212, // Andrion Darkspinner +}; + +/*### +# specialization quests +###*/ +enum SpecializationQuests +{ + /* Alchemy */ + Q_MASTER_TRANSMUTE = 10899, + Q_MASTER_ELIXIR = 10902, + Q_MASTER_POTION = 10897, +}; + +/*### # formulas to calculate unlearning cost ###*/ @@ -395,23 +441,23 @@ public: if (player->HasSkill(SKILL_ALCHEMY) && player->GetBaseSkillValue(SKILL_ALCHEMY) >= 350 && player->getLevel() > 67) { - if (player->GetQuestRewardStatus(10899) || player->GetQuestRewardStatus(10902) || player->GetQuestRewardStatus(10897)) + if (player->GetQuestRewardStatus(Q_MASTER_TRANSMUTE) || player->GetQuestRewardStatus(Q_MASTER_ELIXIR) || player->GetQuestRewardStatus(Q_MASTER_POTION)) { switch (creature->GetEntry()) { - case 22427: //Zarevhi + case N_TRAINER_TRANSMUTE: //Zarevhi if (!HasAlchemySpell(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1); if (player->HasSpell(S_TRANSMUTE)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); break; - case 19052: //Lorokeem + case N_TRAINER_ELIXIR: //Lorokeem if (!HasAlchemySpell(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2); if (player->HasSpell(S_ELIXIR)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5); break; - case 17909: //Lauranna Thar'well + case N_TRAINER_POTION: //Lauranna Thar'well if (!HasAlchemySpell(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_POTION, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3); if (player->HasSpell(S_POTION)) @@ -464,17 +510,17 @@ public: { switch (creature->GetEntry()) { - case 22427: + case N_TRAINER_TRANSMUTE: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, action); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 19052: + case N_TRAINER_ELIXIR: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_ELIXIR, GOSSIP_SENDER_CHECK, action); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 17909: + case N_TRAINER_POTION: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_POTION, GOSSIP_SENDER_CHECK, action); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -489,17 +535,17 @@ public: { switch (creature->GetEntry()) { - case 22427: //Zarevhi + case N_TRAINER_TRANSMUTE: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_TRANSMUTE, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 19052: //Lorokeem + case N_TRAINER_ELIXIR: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_ELIXIR, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 17909: //Lauranna Thar'well + case N_TRAINER_POTION: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_POTION, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ALCHEMY_SPEC, DoHighUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -564,20 +610,20 @@ public: { switch (creatureId) { - case 11145: //Myolor Sunderfury - case 11176: //Krathok Moltenfist + case N_TRAINER_SMITHOMNI1: + case N_TRAINER_SMITHOMNI2: if (!player->HasSpell(S_ARMOR) && !player->HasSpell(S_WEAPON) && player->GetReputationRank(REP_ARMOR) >= REP_FRIENDLY) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARMOR_LEARN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); if (!player->HasSpell(S_WEAPON) && !player->HasSpell(S_ARMOR) && player->GetReputationRank(REP_WEAPON) >= REP_FRIENDLY) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEAPON_LEARN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); break; - case 11146: //Ironus Coldsteel - case 11178: //Borgosh Corebender + case N_TRAINER_WEAPON1: + case N_TRAINER_WEAPON2: if (player->HasSpell(S_WEAPON)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_WEAPON_UNLEARN, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 3); break; - case 5164: //Grumnus Steelshaper - case 11177: //Okothos Ironrager + case N_TRAINER_ARMOR1: + case N_TRAINER_ARMOR2: if (player->HasSpell(S_ARMOR)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARMOR_UNLEARN, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); break; @@ -588,19 +634,19 @@ public: { switch (creatureId) { - case 11191: //Lilith the Lithe + case N_TRAINER_HAMMER: if (!HasWeaponSub(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_HAMMER, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 5); if (player->HasSpell(S_HAMMER)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_HAMMER, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 8); break; - case 11192: //Kilram + case N_TRAINER_AXE: if (!HasWeaponSub(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_AXE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 6); if (player->HasSpell(S_AXE)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_AXE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 9); break; - case 11193: //Seril Scourgebane + case N_TRAINER_SWORD: if (!HasWeaponSub(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SWORD, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 7); if (player->HasSpell(S_SWORD)) @@ -685,17 +731,17 @@ public: { switch (creature->GetEntry()) { - case 11191: + case N_TRAINER_HAMMER: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_HAMMER, GOSSIP_SENDER_CHECK, action); //unknown textID (TALK_HAMMER_LEARN) player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 11192: + case N_TRAINER_AXE: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_AXE, GOSSIP_SENDER_CHECK, action); //unknown textID (TALK_AXE_LEARN) player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 11193: + case N_TRAINER_SWORD: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SWORD, GOSSIP_SENDER_CHECK, action); //unknown textID (TALK_SWORD_LEARN) player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -710,26 +756,26 @@ public: { switch (creature->GetEntry()) { - case 11146: //Ironus Coldsteel - case 11178: //Borgosh Corebender - case 5164: //Grumnus Steelshaper - case 11177: //Okothos Ironrager + case N_TRAINER_WEAPON1: + case N_TRAINER_WEAPON2: + case N_TRAINER_ARMOR1: + case N_TRAINER_ARMOR2: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SMITH_SPEC, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_ARMORORWEAPON, DoLowUnlearnCost(player), false); //unknown textID (TALK_UNLEARN_AXEORWEAPON) player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 11191: + case N_TRAINER_HAMMER: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_HAMMER, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(player), false); //unknown textID (TALK_HAMMER_UNLEARN) player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 11192: + case N_TRAINER_AXE: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_AXE, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(player), false); //unknown textID (TALK_AXE_UNLEARN) player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 11193: + case N_TRAINER_SWORD: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SWORD, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_WEAPON_SPEC, DoMedUnlearnCost(player), false); //unknown textID (TALK_SWORD_UNLEARN) player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -901,18 +947,18 @@ public: { switch (creature->GetEntry()) { - case 7866: //Peter Galen - case 7867: //Thorkaf Dragoneye + case N_TRAINER_DRAGON1: + case N_TRAINER_DRAGON2: if (player->HasSpell(S_DRAGON)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_DRAGON, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 1); break; - case 7868: //Sarah Tanner - case 7869: //Brumn Winterhoof + case N_TRAINER_ELEMENTAL1: + case N_TRAINER_ELEMENTAL2: if (player->HasSpell(S_ELEMENTAL)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_ELEMENTAL, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 2); break; - case 7870: //Caryssia Moonhunter - case 7871: //Se'Jib + case N_TRAINER_TRIBAL1: + case N_TRAINER_TRIBAL2: if (player->HasSpell(S_TRIBAL)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_TRIBAL, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 3); break; @@ -952,20 +998,20 @@ public: { switch (creature->GetEntry()) { - case 7866: //Peter Galen - case 7867: //Thorkaf Dragoneye + case N_TRAINER_DRAGON1: + case N_TRAINER_DRAGON2: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_DRAGON, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 7868: //Sarah Tanner - case 7869: //Brumn Winterhoof + case N_TRAINER_ELEMENTAL1: + case N_TRAINER_ELEMENTAL2: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_ELEMENTAL, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 7870: //Caryssia Moonhunter - case 7871: //Se'Jib + case N_TRAINER_TRIBAL1: + case N_TRAINER_TRIBAL2: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_TRIBAL, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_LEATHER_SPEC, DoMedUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -1027,19 +1073,19 @@ public: { switch (creature->GetEntry()) { - case 22213: //Gidge Spellweaver + case N_TRAINER_SPELLFIRE: if (!HasTailorSpell(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SPELLFIRE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 1); if (player->HasSpell(S_SPELLFIRE)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_SPELLFIRE, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 4); break; - case 22208: //Nasmara Moonsong + case N_TRAINER_MOONCLOTH: if (!HasTailorSpell(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_MOONCLOTH, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 2); if (player->HasSpell(S_MOONCLOTH)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_UNLEARN_MOONCLOTH, GOSSIP_SENDER_UNLEARN, GOSSIP_ACTION_INFO_DEF + 5); break; - case 22212: //Andrion Darkspinner + case N_TRAINER_SHADOWEAVE: if (!HasTailorSpell(player)) player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SHADOWEAVE, GOSSIP_SENDER_LEARN, GOSSIP_ACTION_INFO_DEF + 3); if (player->HasSpell(S_SHADOWEAVE)) @@ -1092,17 +1138,17 @@ public: { switch (creature->GetEntry()) { - case 22213: + case N_TRAINER_SPELLFIRE: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SPELLFIRE, GOSSIP_SENDER_CHECK, action); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 22208: + case N_TRAINER_MOONCLOTH: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_MOONCLOTH, GOSSIP_SENDER_CHECK, action); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 22212: + case N_TRAINER_SHADOWEAVE: player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_LEARN_SHADOWEAVE, GOSSIP_SENDER_CHECK, action); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -1117,17 +1163,17 @@ public: { switch (creature->GetEntry()) { - case 22213: //Gidge Spellweaver + case N_TRAINER_SPELLFIRE: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SPELLFIRE, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 22208: //Nasmara Moonsong + case N_TRAINER_MOONCLOTH: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_MOONCLOTH, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); break; - case 22212: //Andrion Darkspinner + case N_TRAINER_SHADOWEAVE: player->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_UNLEARN_SHADOWEAVE, GOSSIP_SENDER_CHECK, action, BOX_UNLEARN_TAILOR_SPEC, DoHighUnlearnCost(player), false); //unknown textID () player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index d1d2ddc8a80..22eabd3dd65 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -57,6 +57,7 @@ EndContentData */ #include "SpellAuras.h" #include "Pet.h" #include "CreatureTextMgr.h" +#include "SmartAI.h" /*######## # npc_air_force_bots @@ -942,6 +943,28 @@ public: { npc_garments_of_questsAI(Creature* creature) : npc_escortAI(creature) { + switch (me->GetEntry()) + { + case ENTRY_SHAYA: + quest = QUEST_MOON; + break; + case ENTRY_ROBERTS: + quest = QUEST_LIGHT_1; + break; + case ENTRY_DOLF: + quest = QUEST_LIGHT_2; + break; + case ENTRY_KORJA: + quest = QUEST_SPIRIT; + break; + case ENTRY_DG_KEL: + quest = QUEST_DARKNESS; + break; + default: + quest = 0; + break; + } + Reset(); } @@ -951,6 +974,7 @@ public: bool CanRun; uint32 RunAwayTimer; + uint32 quest; void Reset() override { @@ -982,93 +1006,20 @@ public: if (Player* player = caster->ToPlayer()) { - switch (me->GetEntry()) + if (quest && player->GetQuestStatus(quest) == QUEST_STATUS_INCOMPLETE) { - case ENTRY_SHAYA: - if (player->GetQuestStatus(QUEST_MOON) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; - case ENTRY_ROBERTS: - if (player->GetQuestStatus(QUEST_LIGHT_1) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; - case ENTRY_DOLF: - if (player->GetQuestStatus(QUEST_LIGHT_2) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; - case ENTRY_KORJA: - if (player->GetQuestStatus(QUEST_SPIRIT) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; - case ENTRY_DG_KEL: - if (player->GetQuestStatus(QUEST_DARKNESS) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; + if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) + { + Talk(SAY_THANKS, caster); + CanRun = true; + } + else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) + { + CasterGUID = caster->GetGUID(); + me->SetStandState(UNIT_STAND_STATE_STAND); + Talk(SAY_HEALED, caster); + IsHealed = true; + } } // give quest credit, not expect any special quest objectives @@ -2371,6 +2322,71 @@ public: } }; +enum StableMasters +{ + SPELL_MINIWING = 54573, + SPELL_JUBLING = 54611, + SPELL_DARTER = 54619, + SPELL_WORG = 54631, + SPELL_SMOLDERWEB = 54634, + SPELL_CHIKEN = 54677, + SPELL_WOLPERTINGER = 54688, + + STABLE_MASTER_GOSSIP_SUB_MENU = 9820 +}; + +class npc_stable_master : public CreatureScript +{ + public: + npc_stable_master() : CreatureScript("npc_stable_master") { } + + struct npc_stable_masterAI : public SmartAI + { + npc_stable_masterAI(Creature* creature) : SmartAI(creature) { } + + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + SmartAI::sGossipSelect(player, menuId, gossipListId); + if (menuId != STABLE_MASTER_GOSSIP_SUB_MENU) + return; + + switch (gossipListId) + { + case 0: + player->CastSpell(player, SPELL_MINIWING, false); + break; + case 1: + player->CastSpell(player, SPELL_JUBLING, false); + break; + case 2: + player->CastSpell(player, SPELL_DARTER, false); + break; + case 3: + player->CastSpell(player, SPELL_WORG, false); + break; + case 4: + player->CastSpell(player, SPELL_SMOLDERWEB, false); + break; + case 5: + player->CastSpell(player, SPELL_CHIKEN, false); + break; + case 6: + player->CastSpell(player, SPELL_WOLPERTINGER, false); + break; + default: + return; + } + + player->PlayerTalkClass->SendCloseGossip(); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_stable_masterAI(creature); + } +}; + void AddSC_npcs_special() { new npc_air_force_bots(); @@ -2393,4 +2409,5 @@ void AddSC_npcs_special() new npc_firework(); new npc_spring_rabbit(); new npc_imp_in_a_ball(); + new npc_stable_master(); } |