diff options
Diffstat (limited to 'src')
90 files changed, 2479 insertions, 723 deletions
diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index ddaab7dee61..888aa6ecef3 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -25,11 +25,13 @@ using namespace boost::property_tree; -bool ConfigMgr::LoadInitial(std::string const& file, std::string& error) +bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> args, + std::string& error) { std::lock_guard<std::mutex> lock(_configLock); _filename = file; + _args = args; try { @@ -65,7 +67,7 @@ ConfigMgr* ConfigMgr::instance() bool ConfigMgr::Reload(std::string& error) { - return LoadInitial(_filename, error); + return LoadInitial(_filename, std::move(_args), error); } template<class T> diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h index 10113cd88d3..573bc7b4a15 100644 --- a/src/common/Configuration/Config.h +++ b/src/common/Configuration/Config.h @@ -23,6 +23,7 @@ #include <string> #include <list> +#include <vector> #include <mutex> #include <boost/property_tree/ptree.hpp> @@ -35,7 +36,8 @@ class TC_COMMON_API ConfigMgr public: /// Method used only for loading main configuration files (authserver.conf and worldserver.conf) - bool LoadInitial(std::string const& file, std::string& error); + bool LoadInitial(std::string const& file, std::vector<std::string> args, + std::string& error); static ConfigMgr* instance(); @@ -47,10 +49,12 @@ public: float GetFloatDefault(std::string const& name, float def) const; std::string const& GetFilename(); + std::vector<std::string> const& GetArguments() const { return _args; } std::list<std::string> GetKeysByString(std::string const& name); private: std::string _filename; + std::vector<std::string> _args; boost::property_tree::ptree _config; std::mutex _configLock; diff --git a/src/common/Cryptography/SHA1.cpp b/src/common/Cryptography/SHA1.cpp index a01bd7844ee..aed4a069827 100644 --- a/src/common/Cryptography/SHA1.cpp +++ b/src/common/Cryptography/SHA1.cpp @@ -18,6 +18,7 @@ #include "SHA1.h" #include "BigNumber.h" +#include "Util.h" #include <cstring> #include <stdarg.h> @@ -67,3 +68,10 @@ void SHA1Hash::Finalize(void) SHA1_Final(mDigest, &mC); } +std::string CalculateSHA1Hash(std::string const& content) +{ + unsigned char digest[SHA_DIGEST_LENGTH]; + SHA1((unsigned char*)content.c_str(), content.length(), (unsigned char*)&digest); + + return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH); +} diff --git a/src/common/Cryptography/SHA1.h b/src/common/Cryptography/SHA1.h index 970ab5c0cb9..37ac2cc0166 100644 --- a/src/common/Cryptography/SHA1.h +++ b/src/common/Cryptography/SHA1.h @@ -46,5 +46,8 @@ class TC_COMMON_API SHA1Hash SHA_CTX mC; uint8 mDigest[SHA_DIGEST_LENGTH]; }; -#endif +/// Returns the SHA1 hash of the given content as hex string. +TC_COMMON_API std::string CalculateSHA1Hash(std::string const& content); + +#endif diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index a53187ad737..1392900fb9a 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -36,12 +36,14 @@ #include "GitRevision.h" #include "Util.h" #include <iostream> +#include <boost/filesystem/path.hpp> #include <boost/program_options.hpp> #include <openssl/opensslv.h> #include <openssl/crypto.h> using boost::asio::ip::tcp; using namespace boost::program_options; +namespace fs = boost::filesystem; #ifndef _TRINITY_REALM_CONFIG # define _TRINITY_REALM_CONFIG "authserver.conf" @@ -69,7 +71,7 @@ void StopDB(); void SignalHandler(const boost::system::error_code& error, int signalNumber); void KeepDatabaseAliveHandler(const boost::system::error_code& error); void BanExpiryHandler(boost::system::error_code const& error); -variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService); +variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService); boost::asio::io_service* _ioService; boost::asio::deadline_timer* _dbPingTimer; @@ -81,7 +83,7 @@ int main(int argc, char** argv) { signal(SIGABRT, &Trinity::AbortHandler); - std::string configFile = _TRINITY_REALM_CONFIG; + auto configFile = fs::absolute(_TRINITY_REALM_CONFIG); std::string configService; auto vm = GetConsoleArguments(argc, argv, configFile, configService); // exit if help or version is enabled @@ -98,7 +100,9 @@ int main(int argc, char** argv) #endif std::string configError; - if (!sConfigMgr->LoadInitial(configFile, configError)) + if (!sConfigMgr->LoadInitial(configFile.generic_string(), + std::vector<std::string>(argv, argv + argc), + configError)) { printf("Error in config file: %s\n", configError.c_str()); return 1; @@ -109,7 +113,7 @@ int main(int argc, char** argv) TC_LOG_INFO("server.authserver", "%s (authserver)", GitRevision::GetFullVersion()); TC_LOG_INFO("server.authserver", "<Ctrl-C> to stop.\n"); - TC_LOG_INFO("server.authserver", "Using configuration file %s.", configFile.c_str()); + TC_LOG_INFO("server.authserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str()); TC_LOG_INFO("server.authserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); TC_LOG_INFO("server.authserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100); @@ -286,13 +290,14 @@ void ServiceStatusWatcher(boost::system::error_code const& error) } #endif -variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService) +variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService) { options_description all("Allowed options"); all.add_options() ("help,h", "print usage message") ("version,v", "print version build info") - ("config,c", value<std::string>(&configFile)->default_value(_TRINITY_REALM_CONFIG), "use <arg> as configuration file") + ("config,c", value<fs::path>(&configFile)->default_value(fs::absolute(_TRINITY_REALM_CONFIG)), + "use <arg> as configuration file") ; #if PLATFORM == PLATFORM_WINDOWS options_description win("Windows platform specific options"); diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index f044e0cea94..43c327ffda1 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -820,41 +820,6 @@ bool AuthSession::HandleReconnectProof() } } -tcp::endpoint const GetAddressForClient(Realm const& realm, ip::address const& clientAddr) -{ - ip::address realmIp; - - // Attempt to send best address for client - if (clientAddr.is_loopback()) - { - // Try guessing if realm is also connected locally - if (realm.LocalAddress.is_loopback() || realm.ExternalAddress.is_loopback()) - realmIp = clientAddr; - else - { - // Assume that user connecting from the machine that authserver is located on - // has all realms available in his local network - realmIp = realm.LocalAddress; - } - } - else - { - if (clientAddr.is_v4() && - (clientAddr.to_v4().to_ulong() & realm.LocalSubnetMask.to_v4().to_ulong()) == - (realm.LocalAddress.to_v4().to_ulong() & realm.LocalSubnetMask.to_v4().to_ulong())) - { - realmIp = realm.LocalAddress; - } - else - realmIp = realm.ExternalAddress; - } - - tcp::endpoint endpoint(realmIp, realm.Port); - - // Return external IP - return endpoint; -} - bool AuthSession::HandleRealmList() { TC_LOG_DEBUG("server.authserver", "Entering _HandleRealmList"); diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index 6f67867c52b..7dc0a307ca2 100644 --- a/src/server/database/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp @@ -18,6 +18,7 @@ #include "UpdateFetcher.h" #include "Log.h" #include "Util.h" +#include "SHA1.h" #include <fstream> #include <chrono> @@ -25,7 +26,6 @@ #include <sstream> #include <exception> #include <unordered_map> -#include <openssl/sha.h> using namespace boost::filesystem; @@ -209,9 +209,8 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, } } - // Calculate hash - std::string const hash = - CalculateHash(ReadSQLUpdate(availableQuery.first)); + // Calculate a Sha1 hash based on query content. + std::string const hash = CalculateSHA1Hash(ReadSQLUpdate(availableQuery.first)); UpdateMode mode = MODE_APPLY; @@ -334,15 +333,6 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, return UpdateResult(importedUpdates, countRecentUpdates, countArchivedUpdates); } -std::string UpdateFetcher::CalculateHash(std::string const& query) const -{ - // Calculate a Sha1 hash based on query content. - unsigned char digest[SHA_DIGEST_LENGTH]; - SHA1((unsigned char*)query.c_str(), query.length(), (unsigned char*)&digest); - - return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH); -} - uint32 UpdateFetcher::Apply(Path const& path) const { using Time = std::chrono::high_resolution_clock; diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h index a17658818ce..cabc3c2fce3 100644 --- a/src/server/database/Updater/UpdateFetcher.h +++ b/src/server/database/Updater/UpdateFetcher.h @@ -112,7 +112,6 @@ private: AppliedFileStorage ReceiveAppliedFiles() const; std::string ReadSQLUpdate(Path const& file) const; - std::string CalculateHash(std::string const& query) const; uint32 Apply(Path const& path) const; diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index bbf4f4e02ce..68554722db6 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -245,9 +245,9 @@ void PetAI::UpdateAI(uint32 diff) } // Update speed as needed to prevent dropping too far behind and despawning - me->UpdateSpeed(MOVE_RUN, true); - me->UpdateSpeed(MOVE_WALK, true); - me->UpdateSpeed(MOVE_FLIGHT, true); + me->UpdateSpeed(MOVE_RUN); + me->UpdateSpeed(MOVE_WALK); + me->UpdateSpeed(MOVE_FLIGHT); } diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp index 5acb56b5173..17b104eb388 100644 --- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp +++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp @@ -582,13 +582,13 @@ void AuctionBotSeller::LoadSellerValues(SellerConfiguration& config) break; } - config.SetPriceRatioPerQuality(AUCTION_QUALITY_GRAY, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_WHITE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREEN, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_BLUE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_PURPLE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_ORANGE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO) / 100); - config.SetPriceRatioPerQuality(AUCTION_QUALITY_YELLOW, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO) / 100); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_GRAY, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_WHITE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREEN, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_BLUE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_PURPLE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_ORANGE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO)); + config.SetPriceRatioPerQuality(AUCTION_QUALITY_YELLOW, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO)); config.SetPriceRatioPerClass(ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_PRICE_RATIO)); config.SetPriceRatioPerClass(ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_PRICE_RATIO)); @@ -701,10 +701,10 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf { uint32 classRatio = config.GetPriceRatioPerClass(ItemClass(itemProto->Class)); uint32 qualityRatio = config.GetPriceRatioPerQuality(AuctionQuality(itemProto->Quality)); - uint32 priceRatio = (classRatio * qualityRatio) / 100; + float priceRatio = (classRatio * qualityRatio) / 10000.0f; - uint32 buyPrice = itemProto->BuyPrice; - uint32 sellPrice = itemProto->SellPrice; + float buyPrice = itemProto->BuyPrice; + float sellPrice = itemProto->SellPrice; if (buyPrice == 0) { @@ -712,11 +712,11 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf buyPrice = sellPrice * GetSellModifier(itemProto); else { - uint32 divisor = ((itemProto->Class == 2 || itemProto->Class == 4) ? 284 : 80); - uint32 tempLevel = (itemProto->ItemLevel == 0 ? 1 : itemProto->ItemLevel); - uint32 tempQuality = (itemProto->Quality == 0 ? 1 : itemProto->Quality); + float divisor = ((itemProto->Class == ITEM_CLASS_WEAPON || itemProto->Class == ITEM_CLASS_ARMOR) ? 284.0f : 80.0f); + float tempLevel = (itemProto->ItemLevel == 0 ? 1.0f : itemProto->ItemLevel); + float tempQuality = (itemProto->Quality == 0 ? 1.0f : itemProto->Quality); - buyPrice = tempLevel * tempQuality * GetBuyModifier(itemProto)* tempLevel / divisor; + buyPrice = tempLevel * tempQuality * static_cast<float>(GetBuyModifier(itemProto))* tempLevel / divisor; } } @@ -726,14 +726,15 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf if (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYPRICE_SELLER)) buyPrice = sellPrice; - uint32 basePrice = (buyPrice * stackCount * priceRatio) / (itemProto->Class == 6 ? 200 : itemProto->BuyCount) / 100; - uint32 range = basePrice * 0.04; + float basePriceFloat = (buyPrice * stackCount * priceRatio) / (itemProto->Class == 6 ? 200.0f : static_cast<float>(itemProto->BuyCount)) / 100.0f; + float range = basePriceFloat * 0.04f; - buyp = urand(basePrice - range, basePrice + range) + 1; - - basePrice = buyp * .5; + buyp = static_cast<uint32>(frand(basePriceFloat - range, basePriceFloat + range) + 0.5f); + if (buyp == 0) + buyp = 1; + uint32 basePrice = buyp * .5; range = buyp * .4; - bidp = urand(basePrice - range, basePrice + range) + 1; + bidp = urand(static_cast<uint32>(basePrice - range + 0.5f), static_cast<uint32>(basePrice + range + 0.5f)) + 1; } // Determines the stack size to use for the item diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index d5e1e0956b1..d3843c86aa4 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -379,10 +379,10 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); - SetSpeed(MOVE_WALK, cinfo->speed_walk); - SetSpeed(MOVE_RUN, cinfo->speed_run); - SetSpeed(MOVE_SWIM, 1.0f); // using 1.0 rate - SetSpeed(MOVE_FLIGHT, 1.0f); // using 1.0 rate + SetSpeedRate(MOVE_WALK, cinfo->speed_walk); + SetSpeedRate(MOVE_RUN, cinfo->speed_run); + SetSpeedRate(MOVE_SWIM, 1.0f); // using 1.0 rate + SetSpeedRate(MOVE_FLIGHT, 1.0f); // using 1.0 rate // Will set UNIT_FIELD_BOUNDINGRADIUS and UNIT_FIELD_COMBATREACH SetObjectScale(cinfo->scale); @@ -780,7 +780,7 @@ void Creature::DoFleeToGetAssistance() cell.Visit(p, grid_creature_searcher, *GetMap(), *this, radius); SetNoSearchAssistance(true); - UpdateSpeed(MOVE_RUN, false); + UpdateSpeed(MOVE_RUN); if (!creature) //SetFeared(true, EnsureVictim()->GetGUID(), 0, sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_FLEE_DELAY)); @@ -1636,7 +1636,7 @@ void Creature::setDeathState(DeathState s) if (HasSearchedAssistance()) { SetNoSearchAssistance(false); - UpdateSpeed(MOVE_RUN, false); + UpdateSpeed(MOVE_RUN); } //Dismiss group if is leader diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 773d5a05772..a8dad0b2fbc 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -519,41 +519,11 @@ Player* Item::GetOwner()const return ObjectAccessor::FindPlayer(GetOwnerGUID()); } +// Just a "legacy shortcut" for proto->GetSkill() uint32 Item::GetSkill() { - const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] = - { - SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES, - SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0, - SKILL_STAVES, 0, 0, SKILL_FIST_WEAPONS, 0, - SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS, - SKILL_FISHING - }; - - const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] = - { - 0, SKILL_CLOTH, SKILL_LEATHER, SKILL_MAIL, SKILL_PLATE_MAIL, 0, SKILL_SHIELD, 0, 0, 0, 0 - }; - ItemTemplate const* proto = GetTemplate(); - - switch (proto->Class) - { - case ITEM_CLASS_WEAPON: - if (proto->SubClass >= MAX_ITEM_SUBCLASS_WEAPON) - return 0; - else - return item_weapon_skills[proto->SubClass]; - - case ITEM_CLASS_ARMOR: - if (proto->SubClass >= MAX_ITEM_SUBCLASS_ARMOR) - return 0; - else - return item_armor_skills[proto->SubClass]; - - default: - return 0; - } + return proto->GetSkill(); } uint32 Item::GetSpell() diff --git a/src/server/game/Entities/Item/ItemPrototype.cpp b/src/server/game/Entities/Item/ItemPrototype.cpp new file mode 100644 index 00000000000..3bb7b128b08 --- /dev/null +++ b/src/server/game/Entities/Item/ItemPrototype.cpp @@ -0,0 +1,121 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "ItemPrototype.h" + +bool ItemTemplate::CanChangeEquipStateInCombat() const +{ + switch (InventoryType) + { + case INVTYPE_RELIC: + case INVTYPE_SHIELD: + case INVTYPE_HOLDABLE: + return true; + } + + switch (Class) + { + case ITEM_CLASS_WEAPON: + case ITEM_CLASS_PROJECTILE: + return true; + } + + return false; +} + + +float ItemTemplate::getDPS() const +{ + if (Delay == 0) + return 0; + float temp = 0; + for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i) + temp += Damage[i].DamageMin + Damage[i].DamageMax; + return temp * 500 / Delay; +} + + +int32 ItemTemplate::getFeralBonus(int32 extraDPS /*= 0*/) const +{ + // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc + if (Class == ITEM_CLASS_WEAPON && (1 << SubClass) & 0x02A5F3) + { + int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767; + if (bonus < 0) + return 0; + return bonus; + } + return 0; +} + +float ItemTemplate::GetItemLevelIncludingQuality() const +{ + float itemLevel = (float)ItemLevel; + switch (Quality) + { + case ITEM_QUALITY_POOR: + case ITEM_QUALITY_NORMAL: + case ITEM_QUALITY_UNCOMMON: + case ITEM_QUALITY_ARTIFACT: + case ITEM_QUALITY_HEIRLOOM: + itemLevel -= 13; // leaving this as a separate statement since we do not know the real behavior in this case + break; + case ITEM_QUALITY_RARE: + itemLevel -= 13; + break; + case ITEM_QUALITY_EPIC: + case ITEM_QUALITY_LEGENDARY: + default: + break; + } + return std::max<float>(0.f, itemLevel); +} + +uint32 ItemTemplate::GetSkill() const +{ + const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] = + { + SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES, + SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0, + SKILL_STAVES, 0, 0, SKILL_FIST_WEAPONS, 0, + SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS, + SKILL_FISHING + }; + + const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] = + { + 0, SKILL_CLOTH, SKILL_LEATHER, SKILL_MAIL, SKILL_PLATE_MAIL, 0, SKILL_SHIELD, 0, 0, 0, 0 + }; + + switch (Class) + { + case ITEM_CLASS_WEAPON: + if (SubClass >= MAX_ITEM_SUBCLASS_WEAPON) + return 0; + else + return item_weapon_skills[SubClass]; + + case ITEM_CLASS_ARMOR: + if (SubClass >= MAX_ITEM_SUBCLASS_ARMOR) + return 0; + else + return item_armor_skills[SubClass]; + + default: + return 0; + } +} diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h index 48ef9e81016..9b0f4628364 100644 --- a/src/server/game/Entities/Item/ItemPrototype.h +++ b/src/server/game/Entities/Item/ItemPrototype.h @@ -664,25 +664,7 @@ struct ItemTemplate uint32 FlagsCu; // helpers - bool CanChangeEquipStateInCombat() const - { - switch (InventoryType) - { - case INVTYPE_RELIC: - case INVTYPE_SHIELD: - case INVTYPE_HOLDABLE: - return true; - } - - switch (Class) - { - case ITEM_CLASS_WEAPON: - case ITEM_CLASS_PROJECTILE: - return true; - } - - return false; - } + bool CanChangeEquipStateInCombat() const; bool IsCurrencyToken() const { return (BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) != 0; } @@ -691,51 +673,13 @@ struct ItemTemplate return (Stackable == 2147483647 || Stackable <= 0) ? uint32(0x7FFFFFFF-1) : uint32(Stackable); } - float getDPS() const - { - if (Delay == 0) - return 0; - float temp = 0; - for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i) - temp+=Damage[i].DamageMin + Damage[i].DamageMax; - return temp*500/Delay; - } + float getDPS() const; - int32 getFeralBonus(int32 extraDPS = 0) const - { - // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc - if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3) - { - int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767; - if (bonus < 0) - return 0; - return bonus; - } - return 0; - } + int32 getFeralBonus(int32 extraDPS = 0) const; - float GetItemLevelIncludingQuality() const - { - float itemLevel = (float)ItemLevel; - switch (Quality) - { - case ITEM_QUALITY_POOR: - case ITEM_QUALITY_NORMAL: - case ITEM_QUALITY_UNCOMMON: - case ITEM_QUALITY_ARTIFACT: - case ITEM_QUALITY_HEIRLOOM: - itemLevel -= 13; // leaving this as a separate statement since we do not know the real behavior in this case - break; - case ITEM_QUALITY_RARE: - itemLevel -= 13; - break; - case ITEM_QUALITY_EPIC: - case ITEM_QUALITY_LEGENDARY: - default: - break; - } - return std::max<float>(0.f, itemLevel); - } + float GetItemLevelIncludingQuality() const; + + uint32 GetSkill() const; bool IsPotion() const { return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION; } bool IsWeaponVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_WEAPON_ENCHANTMENT; } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c58f2c940fc..503b6277963 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -20328,6 +20328,11 @@ void Player::Say(std::string const& text, Language language, WorldObject const* SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true); } +void Player::Say(uint32 textId, WorldObject const* target /*= nullptr*/) +{ + Talk(textId, CHAT_MSG_SAY, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), target); +} + void Player::Yell(std::string const& text, Language language, WorldObject const* /*= nullptr*/) { std::string _text(text); @@ -20338,6 +20343,11 @@ void Player::Yell(std::string const& text, Language language, WorldObject const* SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true); } +void Player::Yell(uint32 textId, WorldObject const* target /*= nullptr*/) +{ + Talk(textId, CHAT_MSG_YELL, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), target); +} + void Player::TextEmote(std::string const& text, WorldObject const* /*= nullptr*/, bool /*= false*/) { std::string _text(text); @@ -20348,6 +20358,11 @@ void Player::TextEmote(std::string const& text, WorldObject const* /*= nullptr*/ SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT)); } +void Player::TextEmote(uint32 textId, WorldObject const* target /*= nullptr*/, bool /*isBossEmote = false*/) +{ + Talk(textId, CHAT_MSG_EMOTE, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), target); +} + void Player::Whisper(std::string const& text, Language language, Player* target, bool /*= false*/) { ASSERT(target); @@ -20384,6 +20399,24 @@ void Player::Whisper(std::string const& text, Language language, Player* target, ChatHandler(GetSession()).PSendSysMessage(LANG_PLAYER_DND, target->GetName().c_str(), target->autoReplyMsg.c_str()); } +void Player::Whisper(uint32 textId, Player* target, bool /*isBossWhisper = false*/) +{ + if (!target) + return; + + BroadcastText const* bct = sObjectMgr->GetBroadcastText(textId); + if (!bct) + { + TC_LOG_ERROR("entities.unit", "WorldObject::MonsterWhisper: `broadcast_text` was not %u found", textId); + return; + } + + LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex(); + WorldPacket data; + ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, LANG_UNIVERSAL, this, target, bct->GetText(locale, getGender()), 0, "", locale); + target->SendDirectMessage(&data); +} + Item* Player::GetMItem(uint32 id) { ItemMap::const_iterator itr = mMitems.find(id); @@ -26561,3 +26594,22 @@ void Player::RemoveRestFlag(RestFlag restFlag) RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); } } + +uint32 Player::DoRandomRoll(uint32 minimum, uint32 maximum) +{ + ASSERT(maximum <= 10000); + + uint32 roll = urand(minimum, maximum); + + WorldPacket data(MSG_RANDOM_ROLL, 4 + 4 + 4 + 8); + data << uint32(minimum); + data << uint32(maximum); + data << uint32(roll); + data << GetGUID(); + if (Group* group = GetGroup()) + group->BroadcastPacket(&data, false); + else + SendDirectMessage(&data); + + return roll; +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index fd0fac69674..51443ce8939 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1148,12 +1148,16 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> /// Handles said message in regular chat based on declared language and in config pre-defined Range. void Say(std::string const& text, Language language, WorldObject const* = nullptr) override; + void Say(uint32 textId, WorldObject const* target = nullptr) override; /// Handles yelled message in regular chat based on declared language and in config pre-defined Range. void Yell(std::string const& text, Language language, WorldObject const* = nullptr) override; + void Yell(uint32 textId, WorldObject const* target = nullptr) override; /// Outputs an universal text which is supposed to be an action. void TextEmote(std::string const& text, WorldObject const* = nullptr, bool = false) override; + void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false) override; /// Handles whispers from Addons and players based on sender, receiver's guid and language. void Whisper(std::string const& text, Language language, Player* receiver, bool = false) override; + void Whisper(uint32 textId, Player* target, bool isBossWhisper = false) override; /*********************************************************/ /*** STORAGE SYSTEM ***/ @@ -2132,6 +2136,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void SendCinematicStart(uint32 CinematicSequenceId); void SendMovieStart(uint32 MovieId) const; + uint32 DoRandomRoll(uint32 minimum, uint32 maximum); + /*********************************************************/ /*** INSTANCE SYSTEM ***/ /*********************************************************/ diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 28a5a1b2587..ee8a0b093e7 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9106,7 +9106,7 @@ bool Unit::AttackStop() if (creature->HasSearchedAssistance()) { creature->SetNoSearchAssistance(false); - UpdateSpeed(MOVE_RUN, false); + UpdateSpeed(MOVE_RUN); } } @@ -9440,7 +9440,7 @@ void Unit::SetMinion(Minion *minion, bool apply) // FIXME: hack, speed must be set only at follow if (GetTypeId() == TYPEID_PLAYER && minion->IsPet()) for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) - minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true); + minion->SetSpeedRate(UnitMoveType(i), m_speed_rate[i]); // Ghoul pets have energy instead of mana (is anywhere better place for this code?) if (minion->IsPetGhoul() || minion->IsRisenAlly()) @@ -11870,9 +11870,9 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy) if (IsPet()) { - UpdateSpeed(MOVE_RUN, true); - UpdateSpeed(MOVE_SWIM, true); - UpdateSpeed(MOVE_FLIGHT, true); + UpdateSpeed(MOVE_RUN); + UpdateSpeed(MOVE_SWIM); + UpdateSpeed(MOVE_FLIGHT); } if (!(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_MOUNTED_COMBAT)) @@ -11916,7 +11916,7 @@ void Unit::ClearInCombat() if (Unit* owner = GetOwner()) for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) if (owner->GetSpeedRate(UnitMoveType(i)) > GetSpeedRate(UnitMoveType(i))) - SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true); + SetSpeedRate(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i))); } else if (!IsCharmed()) return; @@ -12003,25 +12003,26 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo || target->GetReactionTo(this) > REP_NEUTRAL) return false; + Player const* playerAffectingAttacker = HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? GetAffectingPlayer() : nullptr; + Player const* playerAffectingTarget = target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? target->GetAffectingPlayer() : nullptr; + // Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar) - if (GetReactionTo(target) == REP_NEUTRAL && - target->GetReactionTo(this) <= REP_NEUTRAL) + if ( + (playerAffectingAttacker && !playerAffectingTarget) || + (!playerAffectingAttacker && playerAffectingTarget) + ) { - if (!(target->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER) && - !(target->GetTypeId() == TYPEID_UNIT && GetTypeId() == TYPEID_UNIT)) - { - Player const* player = target->GetTypeId() == TYPEID_PLAYER ? target->ToPlayer() : ToPlayer(); - Unit const* creature = target->GetTypeId() == TYPEID_UNIT ? target : this; + Player const* player = playerAffectingAttacker ? playerAffectingAttacker : playerAffectingTarget; + Unit const* creature = playerAffectingAttacker ? target : this; - if (FactionTemplateEntry const* factionTemplate = creature->GetFactionTemplateEntry()) - { - if (!(player->GetReputationMgr().GetForcedRankIfAny(factionTemplate))) - if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction)) - if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry)) - if (!(repState->Flags & FACTION_FLAG_AT_WAR)) - return false; + if (FactionTemplateEntry const* factionTemplate = creature->GetFactionTemplateEntry()) + { + if (!(player->GetReputationMgr().GetForcedRankIfAny(factionTemplate))) + if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction)) + if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry)) + if (!(repState->Flags & FACTION_FLAG_AT_WAR)) + return false; - } } } @@ -12029,9 +12030,6 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo if (creatureAttacker && creatureAttacker->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER) return false; - Player const* playerAffectingAttacker = HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? GetAffectingPlayer() : NULL; - Player const* playerAffectingTarget = target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? target->GetAffectingPlayer() : NULL; - // check duel - before sanctuary checks if (playerAffectingAttacker && playerAffectingTarget) if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->opponent == playerAffectingTarget && playerAffectingAttacker->duel->startTime != 0) @@ -12302,7 +12300,7 @@ void Unit::SetVisible(bool x) UpdateObjectVisibility(); } -void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) +void Unit::UpdateSpeed(UnitMoveType mtype) { int32 main_speed_mod = 0; float stack_bonus = 1.0f; @@ -12365,7 +12363,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) // Update speed for vehicle if available if (GetTypeId() == TYPEID_PLAYER && GetVehicle()) - GetVehicleBase()->UpdateSpeed(MOVE_FLIGHT, true); + GetVehicleBase()->UpdateSpeed(MOVE_FLIGHT); break; } default: @@ -12447,7 +12445,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) speed = min_speed; } - SetSpeed(mtype, speed, forced); + SetSpeedRate(mtype, speed); } float Unit::GetSpeed(UnitMoveType mtype) const @@ -12455,7 +12453,12 @@ float Unit::GetSpeed(UnitMoveType mtype) const return m_speed_rate[mtype]*(IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype]); } -void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) +void Unit::SetSpeed(UnitMoveType mtype, float newValue) +{ + SetSpeedRate(mtype, newValue / (IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype])); +} + +void Unit::SetSpeedRate(UnitMoveType mtype, float rate) { if (rate < 0) rate = 0.0f; @@ -12468,100 +12471,59 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) propagateSpeedChange(); - WorldPacket data; - if (!forced) + // Spline packets are for units controlled by AI. "Force speed change" (wrongly named opcodes) and "move set speed" packets are for units controlled by a player. + static Opcodes const moveTypeToOpcode[MAX_MOVE_TYPE][3] = + { + {SMSG_SPLINE_SET_WALK_SPEED, SMSG_FORCE_WALK_SPEED_CHANGE, MSG_MOVE_SET_WALK_SPEED }, + {SMSG_SPLINE_SET_RUN_SPEED, SMSG_FORCE_RUN_SPEED_CHANGE, MSG_MOVE_SET_RUN_SPEED }, + {SMSG_SPLINE_SET_RUN_BACK_SPEED, SMSG_FORCE_RUN_BACK_SPEED_CHANGE, MSG_MOVE_SET_RUN_BACK_SPEED }, + {SMSG_SPLINE_SET_SWIM_SPEED, SMSG_FORCE_SWIM_SPEED_CHANGE, MSG_MOVE_SET_SWIM_SPEED }, + {SMSG_SPLINE_SET_SWIM_BACK_SPEED, SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, MSG_MOVE_SET_SWIM_BACK_SPEED }, + {SMSG_SPLINE_SET_TURN_RATE, SMSG_FORCE_TURN_RATE_CHANGE, MSG_MOVE_SET_TURN_RATE }, + {SMSG_SPLINE_SET_FLIGHT_SPEED, SMSG_FORCE_FLIGHT_SPEED_CHANGE, MSG_MOVE_SET_FLIGHT_SPEED }, + {SMSG_SPLINE_SET_FLIGHT_BACK_SPEED, SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, MSG_MOVE_SET_FLIGHT_BACK_SPEED }, + {SMSG_SPLINE_SET_PITCH_RATE, SMSG_FORCE_PITCH_RATE_CHANGE, MSG_MOVE_SET_PITCH_RATE }, + }; + + if (GetTypeId() == TYPEID_PLAYER) { - switch (mtype) - { - case MOVE_WALK: - data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4); - break; - case MOVE_RUN: - data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4); - break; - case MOVE_RUN_BACK: - data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); - break; - case MOVE_SWIM: - data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4); - break; - case MOVE_SWIM_BACK: - data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); - break; - case MOVE_TURN_RATE: - data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4); - break; - case MOVE_FLIGHT: - data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4); - break; - case MOVE_FLIGHT_BACK: - data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); - break; - case MOVE_PITCH_RATE: - data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4); - break; - default: - TC_LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype); - return; - } + // register forced speed changes for WorldSession::HandleForceSpeedChangeAck + // and do it only for real sent packets and use run for run/mounted as client expected + ++ToPlayer()->m_forced_speed_changes[mtype]; + + if (!IsInCombat()) + if (Pet* pet = ToPlayer()->GetPet()) + pet->SetSpeedRate(mtype, m_speed_rate[mtype]); + } + if (m_movedPlayer) // unit controlled by a player. + { + // Send notification to self. this packet is only sent to one client (the client of the player concerned by the change). + WorldPacket self; + self.Initialize(moveTypeToOpcode[mtype][1], mtype != MOVE_RUN ? 8 + 4 + 4 : 8 + 4 + 1 + 4); + self << GetPackGUID(); + self << (uint32)0; // Movement counter. Unimplemented at the moment! NUM_PMOVE_EVTS = 0x39Z. + if (mtype == MOVE_RUN) + self << uint8(1); // unknown byte added in 2.1.0 + self << float(GetSpeed(mtype)); + m_movedPlayer->GetSession()->SendPacket(&self); + + // Send notification to other players. sent to every clients (if in range) except one: the client of the player concerned by the change. + WorldPacket data; + data.Initialize(moveTypeToOpcode[mtype][2], 8 + 30 + 4); data << GetPackGUID(); BuildMovementPacket(&data); data << float(GetSpeed(mtype)); - SendMessageToSet(&data, true); + SendMessageToSet(&data, false); } - else + else // unit controlled by AI. { - if (GetTypeId() == TYPEID_PLAYER) - { - // register forced speed changes for WorldSession::HandleForceSpeedChangeAck - // and do it only for real sent packets and use run for run/mounted as client expected - ++ToPlayer()->m_forced_speed_changes[mtype]; - - if (!IsInCombat()) - if (Pet* pet = ToPlayer()->GetPet()) - pet->SetSpeed(mtype, m_speed_rate[mtype], forced); - } - - switch (mtype) - { - case MOVE_WALK: - data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16); - break; - case MOVE_RUN: - data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17); - break; - case MOVE_RUN_BACK: - data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16); - break; - case MOVE_SWIM: - data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16); - break; - case MOVE_SWIM_BACK: - data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16); - break; - case MOVE_TURN_RATE: - data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16); - break; - case MOVE_FLIGHT: - data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16); - break; - case MOVE_FLIGHT_BACK: - data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16); - break; - case MOVE_PITCH_RATE: - data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16); - break; - default: - TC_LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype); - return; - } + // send notification to every clients. + WorldPacket data; + data.Initialize(moveTypeToOpcode[mtype][0], 8 + 4); data << GetPackGUID(); - data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39 - if (mtype == MOVE_RUN) - data << uint8(0); // new 2.1.0 data << float(GetSpeed(mtype)); - SendMessageToSet(&data, true); + SendMessageToSet(&data, false); } } @@ -12827,7 +12789,7 @@ Unit* Creature::SelectVictim() if (target && _IsTargetAcceptable(target) && CanCreatureAttack(target)) { - if(!IsFocusing()) + if (!IsFocusing()) SetInFront(target); return target; } @@ -15625,12 +15587,19 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) Player* creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself(); /// @todo do instance binding anyway if the charmer/owner is offline - if (instanceMap->IsDungeon() && creditedPlayer) + if (instanceMap->IsDungeon() && (creditedPlayer || this == victim)) { if (instanceMap->IsRaidOrHeroicDungeon()) { if (creature->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) - ((InstanceMap*)instanceMap)->PermBindAllPlayers(creditedPlayer); + { + // if the boss killed itself we still need to bind players to the instance + if (!creditedPlayer && instanceMap->HavePlayers()) + creditedPlayer = instanceMap->GetPlayers().getFirst()->GetSource(); + + if (creditedPlayer) + ((InstanceMap*)instanceMap)->PermBindAllPlayers(creditedPlayer); + } } else { @@ -15638,7 +15607,8 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) // until the players leave the instance time_t resettime = creature->GetRespawnTimeEx() + 2 * HOUR; if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(creature->GetInstanceId())) - if (save->GetResetTime() < resettime) save->SetResetTime(resettime); + if (save->GetResetTime() < resettime) + save->SetResetTime(resettime); } } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 9255ce039f3..59d3bd2b25f 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -2018,10 +2018,11 @@ class TC_GAME_API Unit : public WorldObject void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL); void CalcHealAbsorb(Unit* victim, SpellInfo const* spellInfo, uint32& healAmount, uint32& absorb); - void UpdateSpeed(UnitMoveType mtype, bool forced); + void UpdateSpeed(UnitMoveType mtype); float GetSpeed(UnitMoveType mtype) const; float GetSpeedRate(UnitMoveType mtype) const { return m_speed_rate[mtype]; } - void SetSpeed(UnitMoveType mtype, float rate, bool forced = false); + void SetSpeed(UnitMoveType mtype, float newValue); + void SetSpeedRate(UnitMoveType mtype, float rate); float ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index, float value) const; int32 CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints = NULL) const; @@ -2165,11 +2166,11 @@ class TC_GAME_API Unit : public WorldObject virtual void Yell(std::string const& text, Language language, WorldObject const* target = nullptr); virtual void TextEmote(std::string const& text, WorldObject const* target = nullptr, bool isBossEmote = false); virtual void Whisper(std::string const& text, Language language, Player* target, bool isBossWhisper = false); - void Talk(uint32 textId, ChatMsg msgType, float textRange, WorldObject const* target); - void Say(uint32 textId, WorldObject const* target = nullptr); - void Yell(uint32 textId, WorldObject const* target = nullptr); - void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false); - void Whisper(uint32 textId, Player* target, bool isBossWhisper = false); + virtual void Talk(uint32 textId, ChatMsg msgType, float textRange, WorldObject const* target); + virtual void Say(uint32 textId, WorldObject const* target = nullptr); + virtual void Yell(uint32 textId, WorldObject const* target = nullptr); + virtual void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false); + virtual void Whisper(uint32 textId, Player* target, bool isBossWhisper = false); protected: explicit Unit (bool isWorldObject); diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index 84cbb86345d..1c1982600ca 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -488,9 +488,7 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData) void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received MSG_RANDOM_ROLL"); - - uint32 minimum, maximum, roll; + uint32 minimum, maximum; recvData >> minimum; recvData >> maximum; @@ -499,20 +497,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData) return; /********************/ - // everything's fine, do it - roll = urand(minimum, maximum); - - //TC_LOG_DEBUG("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll); - - WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8); - data << uint32(minimum); - data << uint32(maximum); - data << uint32(roll); - data << uint64(GetPlayer()->GetGUID()); - if (GetPlayer()->GetGroup()) - GetPlayer()->GetGroup()->BroadcastPacket(&data, false); - else - SendPacket(&data); + GetPlayer()->DoRandomRoll(minimum, maximum); } void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 02702fc5622..64f927a987f 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -473,7 +473,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData) { TC_LOG_ERROR("network", "%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value", move_type_name[move_type], _player->GetName().c_str(), _player->GetSpeed(move_type), newspeed); - _player->SetSpeed(move_type, _player->GetSpeedRate(move_type), true); + _player->SetSpeedRate(move_type, _player->GetSpeedRate(move_type)); } else // must be lesser - cheating { diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 664ed3dc8ec..794be12ee7c 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2345,9 +2345,9 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float { // we have mapheight and vmapheight and must select more appropriate - // we are already under the surface or vmap height above map heigt + // vmap height above map height // or if the distance of the vmap height is less the land height distance - if (z < mapHeight || vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z)) + if (vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z)) return vmapHeight; else return mapHeight; // better use .map surface height diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index aa45c5024e6..f9a98cffd0e 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -828,7 +828,7 @@ enum SpellEffects SPELL_EFFECT_CREATE_ITEM_2 = 157, SPELL_EFFECT_MILLING = 158, SPELL_EFFECT_ALLOW_RENAME_PET = 159, - SPELL_EFFECT_160 = 160, + SPELL_EFFECT_FORCE_CAST_2 = 160, SPELL_EFFECT_TALENT_SPEC_COUNT = 161, SPELL_EFFECT_TALENT_SPEC_SELECT = 162, SPELL_EFFECT_163 = 163, diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index b01ddcb060d..f27e47fba21 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -312,7 +312,7 @@ void MotionMaster::MoveCloserAndStop(uint32 id, Unit* target, float distance) float desty = _owner->GetPositionY() + distanceToTravel * std::sin(angle); MovePoint(id, destx, desty, target->GetPositionZ()); } - else + else { // we are already close enough. We just need to turn toward the target without changing position. Movement::MoveSplineInit init(_owner); diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 7d6d512e88d..005f10b44af 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -173,7 +173,7 @@ class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *> { MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath); } void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true); - /* Makes the unit move toward the target until it is at a certain distance from it. The unit then stops. + /* Makes the unit move toward the target until it is at a certain distance from it. The unit then stops. Only works in 2D. This method doesn't account for any movement done by the target. in other words, it only works if the target is stationary. */ diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index a57bdae7f52..94c37a8d6a3 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -268,9 +268,9 @@ void FollowMovementGenerator<Creature>::_updateSpeed(Creature* owner) if (!owner->IsPet() || !owner->IsInWorld() || !i_target.isValid() || i_target->GetGUID() != owner->GetOwnerGUID()) return; - owner->UpdateSpeed(MOVE_RUN, true); - owner->UpdateSpeed(MOVE_WALK, true); - owner->UpdateSpeed(MOVE_SWIM, true); + owner->UpdateSpeed(MOVE_RUN); + owner->UpdateSpeed(MOVE_WALK); + owner->UpdateSpeed(MOVE_SWIM); } template<> diff --git a/src/server/game/Scripting/ScriptReloadMgr.cpp b/src/server/game/Scripting/ScriptReloadMgr.cpp index aac0e26f02b..d13fa9c30f0 100644 --- a/src/server/game/Scripting/ScriptReloadMgr.cpp +++ b/src/server/game/Scripting/ScriptReloadMgr.cpp @@ -56,6 +56,7 @@ ScriptReloadMgr* ScriptReloadMgr::instance() #include "Config.h" #include "BuiltInConfig.h" #include "ScriptMgr.h" +#include "SHA1.h" #include "StartProcess.h" #include "MPSCQueue.h" #include "GitRevision.h" @@ -64,8 +65,10 @@ namespace fs = boost::filesystem; #ifdef _WIN32 #include <windows.h> + #define HOTSWAP_PLATFORM_REQUIRES_CACHING #else // Posix #include <dlfcn.h> + // #define HOTSWAP_PLATFORM_REQUIRES_CACHING #endif // Promote the sScriptReloadMgr to a HotSwapScriptReloadMgr @@ -99,13 +102,25 @@ typedef HMODULE HandleType; typedef void* HandleType; #endif +static fs::path GetDirectoryOfExecutable() +{ + ASSERT((!sConfigMgr->GetArguments().empty()), + "Expected the arguments to contain at least 1 element!"); + + fs::path path(sConfigMgr->GetArguments()[0]); + if (path.is_absolute()) + return path.parent_path(); + else + return fs::absolute(path).parent_path(); +} + class SharedLibraryUnloader { public: - SharedLibraryUnloader() - : _path() { } - explicit SharedLibraryUnloader(fs::path const& path) - : _path(path) { } + explicit SharedLibraryUnloader(fs::path path) + : path_(std::move(path)) { } + SharedLibraryUnloader(fs::path path, Optional<fs::path> cache_path) + : path_(std::move(path)), cache_path_(std::move(cache_path)) { } void operator() (HandleType handle) const { @@ -119,26 +134,37 @@ public: if (!success) { TC_LOG_ERROR("scripts.hotswap", "Failed to unload (syscall) the shared library \"%s\".", - _path.generic_string().c_str()); + path_.generic_string().c_str()); return; } - boost::system::error_code error; - if (fs::remove(_path, error)) + /// When the shared library was cached delete it's shared version + if (cache_path_) { - TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded and deleted the shared library \"%s\".", - _path.generic_string().c_str()); + boost::system::error_code error; + if (!fs::remove(*cache_path_, error)) + { + TC_LOG_ERROR("scripts.hotswap", "Failed to delete the cached shared library \"%s\" (%s).", + cache_path_->generic_string().c_str(), error.message().c_str()); + + return; + } + + TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded the shared library \"%s\" " + "and deleted it's cached version at \"%s\"", + path_.generic_string().c_str(), cache_path_->generic_string().c_str()); } else { - TC_LOG_ERROR("scripts.hotswap", "Failed to delete the shared library \"%s\" (%s).", - _path.generic_string().c_str(), error.message().c_str()); + TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded the shared library \"%s\".", + path_.generic_string().c_str()); } } private: - fs::path _path; + fs::path const path_; + Optional<fs::path> const cache_path_; }; typedef std::unique_ptr<typename std::remove_pointer<HandleType>::type, SharedLibraryUnloader> HandleHolder; @@ -165,7 +191,8 @@ public: ScriptModule& operator= (ScriptModule const&) = delete; ScriptModule& operator= (ScriptModule&& right) = delete; - static Optional<std::shared_ptr<ScriptModule>> CreateFromPath(fs::path const& path); + static Optional<std::shared_ptr<ScriptModule>> + CreateFromPath(fs::path const& path, Optional<fs::path> cache_path); char const* GetScriptModuleRevisionHash() const override { @@ -215,23 +242,41 @@ static bool GetFunctionFromSharedLibrary(HandleType handle, std::string const& n } // Load a shared library from the given path. -Optional<std::shared_ptr<ScriptModule>> ScriptModule::CreateFromPath(fs::path const& path) +Optional<std::shared_ptr<ScriptModule>> + ScriptModule::CreateFromPath(fs::path const& path, Optional<fs::path> cache_path) { + auto const load_path = [&] () -> fs::path { + if (cache_path) + return *cache_path; + else + return path; + }(); + #ifdef _WIN32 - HandleType handle = LoadLibrary(path.generic_string().c_str()); + HandleType handle = LoadLibrary(load_path.generic_string().c_str()); #else // Posix - HandleType handle = dlopen(path.c_str(), RTLD_LAZY); + HandleType handle = dlopen(load_path.generic_string().c_str(), RTLD_LAZY); #endif if (!handle) { - TC_LOG_ERROR("scripts.hotswap", "Could not load the shared library \"%s\" for reading.", - path.generic_string().c_str()); + if (cache_path) + { + TC_LOG_ERROR("scripts.hotswap", "Could not dynamic load the shared library \"%s\" " + "(the library is cached at %s)", + path.generic_string().c_str(), cache_path->generic_string().c_str()); + } + else + { + TC_LOG_ERROR("scripts.hotswap", "Could not dynamic load the shared library \"%s\".", + path.generic_string().c_str()); + } + return boost::none; } // Use RAII to release the library on failure. - HandleHolder holder(handle, SharedLibraryUnloader(path)); + HandleHolder holder(handle, SharedLibraryUnloader(path, std::move(cache_path))); GetScriptModuleRevisionHashType getScriptModuleRevisionHash; AddScriptsType addScripts; @@ -357,7 +402,7 @@ static bool IsDebuggerBlockingRebuild() /// /// This class manages shared library loading/unloading through watching /// the script module directory. Loaded shared libraries are mirrored -/// into a .cache subdirectory to allow lazy unloading as long as +/// into a cache subdirectory to allow lazy unloading as long as /// the shared library is still used which is useful for scripts /// which can't be instantly replaced like spells or instances. /// Several modules which reference different versions can be kept loaded @@ -400,6 +445,8 @@ class HotSwapScriptReloadMgr final // like "Release" or "Debug". The build directive from the // previous same module is used if there was any. std::string script_module_build_directive_; + // The time where the build job started + uint32 start_time_; // Type of the current running job BuildJobType type_; @@ -412,7 +459,7 @@ class HotSwapScriptReloadMgr final : script_module_name_(std::move(script_module_name)), script_module_project_name_(std::move(script_module_project_name)), script_module_build_directive_(std::move(script_module_build_directive)), - type_(BuildJobType::BUILD_JOB_NONE) { } + start_time_(getMSTime()), type_(BuildJobType::BUILD_JOB_NONE) { } bool IsValid() const { @@ -425,6 +472,8 @@ class HotSwapScriptReloadMgr final std::string const& GetBuildDirective() const { return script_module_build_directive_; } + uint32 GetTimeFromStart() const { return GetMSTimeDiffToNow(start_time_); } + BuildJobType GetType() const { return type_; } std::shared_ptr<Trinity::AsyncProcessResult> const& GetProcess() const @@ -500,7 +549,13 @@ public: /// Returns the absolute path to the script module directory static fs::path GetLibraryDirectory() { - return fs::absolute(sConfigMgr->GetStringDefault("HotSwap.ScriptDir", "scripts")); + // When an absolute path is given in the config use it, + // otherwise interpret paths relative to the executable. + fs::path path(sConfigMgr->GetStringDefault("HotSwap.ScriptDir", "scripts")); + if (path.is_absolute()) + return path; + else + return fs::absolute(path, GetDirectoryOfExecutable()); } /// Returns the absolute path to the scripts directory in the source tree. @@ -541,28 +596,28 @@ public: } } - // Get the cache directory path - fs::path const cache_path = [] - { - auto path = fs::absolute(sScriptReloadMgr->GetLibraryDirectory()); - path /= ".cache"; - return path; - }(); + #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING + + temporary_cache_path_ = CalculateTemporaryCachePath(); // We use the boost filesystem function versions which accept // an error code to prevent it from throwing exceptions. boost::system::error_code code; - if ((!fs::exists(cache_path, code) || (fs::remove_all(cache_path, code) > 0)) && - !fs::create_directory(cache_path, code)) + if ((!fs::exists(temporary_cache_path_, code) + || (fs::remove_all(temporary_cache_path_, code) > 0)) && + !fs::create_directory(temporary_cache_path_, code)) { - TC_LOG_ERROR("scripts.hotswap", "Couldn't create the cache directory \"%s\".", - cache_path.generic_string().c_str()); + TC_LOG_ERROR("scripts.hotswap", "Couldn't create the cache directory at \"%s\".", + temporary_cache_path_.generic_string().c_str()); + return; } // Used to silent compiler warnings (void)code; + #endif // #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING + // Correct the CMake prefix when needed if (sWorld->getBoolConfig(CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED)) DoCMakePrefixCorrectionIfNeeded(); @@ -694,6 +749,31 @@ private: _fileWatcher.watch(); } + static fs::path CalculateTemporaryCachePath() + { + auto path = fs::temp_directory_path(); + path /= Trinity::StringFormat("tc_script_cache_%s_%s", + GitRevision::GetBranch(), + CalculateSHA1Hash(sConfigMgr->GetFilename()).c_str()); + + return path; + } + + fs::path GenerateUniquePathForLibraryInCache(fs::path path) + { + ASSERT(!temporary_cache_path_.empty(), + "The temporary cache path wasn't set!"); + + // Create the cache path and increment the library counter to use an unique name for each library + auto cache_path = temporary_cache_path_; + cache_path /= Trinity::StringFormat("%s.%u%s", + path.stem().generic_string().c_str(), + _unique_library_name_counter++, + path.extension().generic_string().c_str()); + + return cache_path; + } + /// Updates the current state of the given source path void UpdateSourceChangeRequest(std::string const& module_name, fs::path const& path, @@ -774,32 +854,37 @@ private: ASSERT(_running_script_module_names.find(path) == _running_script_module_names.end(), "Can't load a module which is running already!"); - // Create the cache path and increment the library counter to use an unique name for each library - fs::path cache_path = fs::absolute(sScriptReloadMgr->GetLibraryDirectory()); - cache_path /= ".cache"; - cache_path /= Trinity::StringFormat("%s.%u%s", - path.stem().generic_string().c_str(), - _unique_library_name_counter++, - path.extension().generic_string().c_str()); + Optional<fs::path> cache_path; + + #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING + + // Copy the shared library into a cache on platforms which lock files on use (windows). + cache_path = GenerateUniquePathForLibraryInCache(path); - if ([&] - { - boost::system::error_code code; - fs::copy_file(path, cache_path, fs::copy_option::fail_if_exists, code); - return code; - }()) { - TC_LOG_FATAL("scripts.hotswap", ">> Failed to create cache entry for module \"%s\"!", - path.filename().generic_string().c_str()); + boost::system::error_code code; + fs::copy_file(path, *cache_path, fs::copy_option::fail_if_exists, code); + if (code) + { + TC_LOG_FATAL("scripts.hotswap", ">> Failed to create cache entry for module " + "\"%s\" at \"%s\" with reason (\"%s\")!", + path.filename().generic_string().c_str(), cache_path->generic_string().c_str(), + code.message().c_str()); + + // Find a better solution for this but it's much better + // to start the core without scripts + std::this_thread::sleep_for(std::chrono::seconds(5)); + ABORT(); + return; + } - // Find a better solution for this but it's much better - // to start the core without scripts - std::this_thread::sleep_for(std::chrono::seconds(5)); - ABORT(); - return; + TC_LOG_TRACE("scripts.hotswap", ">> Copied the shared library \"%s\" to \"%s\" for caching.", + path.filename().generic_string().c_str(), cache_path->generic_string().c_str()); } - auto module = ScriptModule::CreateFromPath(cache_path); + #endif // #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING + + auto module = ScriptModule::CreateFromPath(path, cache_path); if (!module) { TC_LOG_FATAL("scripts.hotswap", ">> Failed to load script module \"%s\"!", @@ -984,7 +1069,7 @@ private: return; } - + // Find all source files of a changed script module and removes // it from the changed source list, invoke the build afterwards. bool rebuild_buildfiles; @@ -1056,7 +1141,7 @@ private: ASSERT(_build_job->IsValid(), "Invalid build job!"); // Retrieve the result - auto const error = _build_job->GetProcess()->GetFutureResult().get(); + auto const error = _build_job->GetProcess()->GetFutureResult().get(); if (terminate_early) { @@ -1117,8 +1202,9 @@ private: if (!error) { // Installation was successful - TC_LOG_INFO("scripts.hotswap", ">> Successfully installed module %s.", - _build_job->GetModuleName().c_str()); + TC_LOG_INFO("scripts.hotswap", ">> Successfully installed module %s in %us", + _build_job->GetModuleName().c_str(), + _build_job->GetTimeFromStart() / IN_MILLISECONDS); } else { @@ -1144,7 +1230,7 @@ private: TC_LOG_INFO("scripts.hotswap", "Rerunning CMake because there were sources added or removed..."); - _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_RERUN_CMAKE, + _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_RERUN_CMAKE, InvokeAsyncCMakeCommand(BuiltInConfig::GetBuildDirectory())); } @@ -1247,7 +1333,7 @@ private: #ifndef _WIN32 // The worldserver location is ${CMAKE_INSTALL_PREFIX}/bin // on all other platforms then windows - current_path = current_path.remove_leaf(); + current_path = current_path.parent_path(); #endif if (value != current_path) @@ -1263,7 +1349,7 @@ private: if (base == branch) return true; - branch = branch.remove_leaf(); + branch = branch.parent_path(); } return false; @@ -1344,6 +1430,9 @@ private: // Is true when the build job dispatcher should stop after // the current job has finished bool terminate_early; + + // The path to the tc_scripts temporary cache + fs::path temporary_cache_path_; }; /// Maps efsw actions to strings diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index e3c6179a34a..1c77283d812 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -344,11 +344,12 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler() default: { sessionGuard.lock(); + LogOpcodeText(opcode, sessionGuard); + if (!_worldSession) { TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); - CloseSocket(); return ReadDataHandlerResult::Error; } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 5585dc8762b..a8adda3ad58 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2915,7 +2915,7 @@ void AuraEffect::HandleAuraModIncreaseSpeed(AuraApplication const* aurApp, uint8 Unit* target = aurApp->GetTarget(); - target->UpdateSpeed(MOVE_RUN, true); + target->UpdateSpeed(MOVE_RUN); } void AuraEffect::HandleAuraModIncreaseMountedSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -2930,7 +2930,7 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp, Unit* target = aurApp->GetTarget(); if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK) - target->UpdateSpeed(MOVE_FLIGHT, true); + target->UpdateSpeed(MOVE_FLIGHT); //! Update ability to fly if (GetAuraType() == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) @@ -2965,7 +2965,7 @@ void AuraEffect::HandleAuraModIncreaseSwimSpeed(AuraApplication const* aurApp, u Unit* target = aurApp->GetTarget(); - target->UpdateSpeed(MOVE_SWIM, true); + target->UpdateSpeed(MOVE_SWIM); } void AuraEffect::HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const @@ -2975,12 +2975,12 @@ void AuraEffect::HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8 Unit* target = aurApp->GetTarget(); - target->UpdateSpeed(MOVE_RUN, true); - target->UpdateSpeed(MOVE_SWIM, true); - target->UpdateSpeed(MOVE_FLIGHT, true); - target->UpdateSpeed(MOVE_RUN_BACK, true); - target->UpdateSpeed(MOVE_SWIM_BACK, true); - target->UpdateSpeed(MOVE_FLIGHT_BACK, true); + target->UpdateSpeed(MOVE_RUN); + target->UpdateSpeed(MOVE_SWIM); + target->UpdateSpeed(MOVE_FLIGHT); + target->UpdateSpeed(MOVE_RUN_BACK); + target->UpdateSpeed(MOVE_SWIM_BACK); + target->UpdateSpeed(MOVE_FLIGHT_BACK); } void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const @@ -2990,9 +2990,9 @@ void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint Unit* target = aurApp->GetTarget(); - target->UpdateSpeed(MOVE_RUN, true); - target->UpdateSpeed(MOVE_SWIM, true); - target->UpdateSpeed(MOVE_FLIGHT, true); + target->UpdateSpeed(MOVE_RUN); + target->UpdateSpeed(MOVE_SWIM); + target->UpdateSpeed(MOVE_FLIGHT); } /*********************************************************/ diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 3f0ff9a0f19..1c2b2743a6d 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -217,7 +217,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again - &Spell::EffectNULL, //160 SPELL_EFFECT_160 1 spell - 45534 + &Spell::EffectForceCast, //160 SPELL_EFFECT_FORCE_CAST_2 &Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert) &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec &Spell::EffectNULL, //163 unused @@ -3661,16 +3661,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) m_caster->CastSpell(unitTarget, 22682, true); return; } - // Decimate - case 28374: - case 54426: - if (unitTarget) - { - int32 decimateDamage = int32(unitTarget->GetHealth()) - int32(unitTarget->CountPctFromMaxHealth(5)); - if (decimateDamage > 0) - m_caster->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, decimateDamage, unitTarget); - } - return; // Mirren's Drinking Hat case 29830: { @@ -3781,28 +3771,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) break; } - // Roll Dice - Decahedral Dwarven Dice - case 47770: - { - char buf[128]; - const char *gender = "his"; - if (m_caster->getGender() > 0) - gender = "her"; - sprintf(buf, "%s rubs %s [Decahedral Dwarven Dice] between %s hands and rolls. One %u and one %u.", m_caster->GetName().c_str(), gender, gender, urand(1, 10), urand(1, 10)); - m_caster->TextEmote(buf); - break; - } - // Roll 'dem Bones - Worn Troll Dice - case 47776: - { - char buf[128]; - const char *gender = "his"; - if (m_caster->getGender() > 0) - gender = "her"; - sprintf(buf, "%s causually tosses %s [Worn Troll Dice]. One %u and one %u.", m_caster->GetName().c_str(), gender, urand(1, 6), urand(1, 6)); - m_caster->TextEmote(buf); - break; - } // Death Knight Initiate Visual case 51519: { diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 069c794ca8b..ccb1d78b8bc 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -754,7 +754,7 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 157 SPELL_EFFECT_CREATE_ITEM_2 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 158 SPELL_EFFECT_MILLING {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 159 SPELL_EFFECT_ALLOW_RENAME_PET - {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 160 SPELL_EFFECT_160 + {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 160 SPELL_EFFECT_FORCE_CAST_2 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 161 SPELL_EFFECT_TALENT_SPEC_COUNT {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 162 SPELL_EFFECT_TALENT_SPEC_SELECT {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 163 SPELL_EFFECT_163 diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index 861b45efa95..f1ddb448b35 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -477,11 +477,11 @@ public: if (handler->needReportToTarget(target)) ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, handler->GetNameLink().c_str(), ASpeed); - target->SetSpeed(MOVE_WALK, ASpeed, true); - target->SetSpeed(MOVE_RUN, ASpeed, true); - target->SetSpeed(MOVE_SWIM, ASpeed, true); - //target->SetSpeed(MOVE_TURN, ASpeed, true); - target->SetSpeed(MOVE_FLIGHT, ASpeed, true); + target->SetSpeedRate(MOVE_WALK, ASpeed); + target->SetSpeedRate(MOVE_RUN, ASpeed); + target->SetSpeedRate(MOVE_SWIM, ASpeed); + //target->SetSpeedRate(MOVE_TURN, ASpeed); + target->SetSpeedRate(MOVE_FLIGHT, ASpeed); return true; } @@ -525,7 +525,7 @@ public: if (handler->needReportToTarget(target)) ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, handler->GetNameLink().c_str(), Speed); - target->SetSpeed(MOVE_RUN, Speed, true); + target->SetSpeedRate(MOVE_RUN, Speed); return true; } @@ -570,7 +570,7 @@ public: if (handler->needReportToTarget(target)) ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, handler->GetNameLink().c_str(), Swim); - target->SetSpeed(MOVE_SWIM, Swim, true); + target->SetSpeedRate(MOVE_SWIM, Swim); return true; } @@ -615,7 +615,7 @@ public: if (handler->needReportToTarget(target)) ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, handler->GetNameLink().c_str(), BSpeed); - target->SetSpeed(MOVE_RUN_BACK, BSpeed, true); + target->SetSpeedRate(MOVE_RUN_BACK, BSpeed); return true; } @@ -651,7 +651,7 @@ public: if (handler->needReportToTarget(target)) ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, handler->GetNameLink().c_str(), FSpeed); - target->SetSpeed(MOVE_FLIGHT, FSpeed, true); + target->SetSpeedRate(MOVE_FLIGHT, FSpeed); return true; } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp index 51bb314968d..ffec32c0619 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp @@ -27,6 +27,8 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "molten_core.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" enum Emotes { @@ -36,9 +38,10 @@ enum Emotes enum Spells { SPELL_INFERNO = 19695, + SPELL_INFERNO_DMG = 19698, SPELL_IGNITE_MANA = 19659, SPELL_LIVING_BOMB = 20475, - SPELL_ARMAGEDDON = 20479, + SPELL_ARMAGEDDON = 20478, }; enum Events @@ -119,7 +122,36 @@ class boss_baron_geddon : public CreatureScript } }; +class spell_baron_geddon_inferno : public SpellScriptLoader +{ + public: + spell_baron_geddon_inferno() : SpellScriptLoader("spell_baron_geddon_inferno") { } + + class spell_baron_geddon_inferno_AuraScript : public AuraScript + { + PrepareAuraScript(spell_baron_geddon_inferno_AuraScript); + + void OnPeriodic(AuraEffect const* aurEff) + { + PreventDefaultAction(); + int32 damageForTick[8] = { 500, 500, 1000, 1000, 2000, 2000, 3000, 5000 }; + GetTarget()->CastCustomSpell(SPELL_INFERNO_DMG, SPELLVALUE_BASE_POINT0, damageForTick[aurEff->GetTickNumber() - 1], (Unit*)nullptr, TRIGGERED_FULL_MASK, nullptr, aurEff); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_baron_geddon_inferno_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_baron_geddon_inferno_AuraScript(); + } +}; + void AddSC_boss_baron_geddon() { new boss_baron_geddon(); + new spell_baron_geddon_inferno(); } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp index 7d7c60ac419..6ff20e66f7f 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp @@ -138,7 +138,7 @@ public: { Initialize(); - me->SetSpeed(MOVE_RUN, 2.0f); + me->SetSpeedRate(MOVE_RUN, 2.0f); me->SetDisableGravity(true); me->SetWalk(false); me->setActive(true); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp index 4aef3c8d4a3..ace15cc2a7e 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp @@ -562,7 +562,7 @@ public: arca->GetMotionMaster()->MovePoint(0, -11010.82f, -1761.18f, 156.47f); arca->setActive(true); arca->InterruptNonMeleeSpells(true); - arca->SetSpeed(MOVE_FLIGHT, 2.0f); + arca->SetSpeedRate(MOVE_FLIGHT, 2.0f); } return 10000; case 13: diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index b809128e731..ebe406c8909 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -405,7 +405,7 @@ public: Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); if (Orb && target) { - Orb->SetSpeed(MOVE_RUN, 0.5f); + Orb->SetSpeedRate(MOVE_RUN, 0.5f); Orb->AddThreat(target, 1000000.0f); Orb->AI()->AttackStart(target); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index 81044a0dbb1..3cf78b79f67 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -396,7 +396,7 @@ class npc_eye_of_acherus : public CreatureScript if (Player* owner = me->GetCharmerOrOwner()->ToPlayer()) { for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) - me->SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true); + me->SetSpeedRate(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i))); Talk(TALK_MOVE_START, owner); } me->GetMotionMaster()->MovePath(me->GetEntry() * 100, false); @@ -419,7 +419,7 @@ class npc_eye_of_acherus : public CreatureScript { owner->RemoveAura(SPELL_EYE_FLIGHT_BOOST); for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) - me->SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true); + me->SetSpeedRate(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i))); Talk(TALK_CONTROL, owner); } @@ -703,7 +703,7 @@ class npc_dark_rider_of_acherus : public CreatureScript TargetGUID = who->GetGUID(); me->SetWalk(true); - me->SetSpeed(MOVE_RUN, 0.4f); + me->SetSpeedRate(MOVE_RUN, 0.4f); me->GetMotionMaster()->MoveChase(who); me->SetTarget(TargetGUID); Intro = true; @@ -1050,7 +1050,7 @@ class npc_scarlet_miner_cart : public CreatureScript // Not 100% correct, but movement is smooth. Sometimes miner walks faster // than normal, this speed is fast enough to keep up at those times. - me->SetSpeed(MOVE_RUN, 1.25f); + me->SetSpeedRate(MOVE_RUN, 1.25f); me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index e336ff24382..d25a225717a 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -923,7 +923,7 @@ public: if (ObjectAccessor::GetCreature(*me, uiLichKingGUID)) DoCast(me, SPELL_MOGRAINE_CHARGE); // jumping charge // doesn't make it looks well, so workarounds, Darion charges, looks better - me->SetSpeed(MOVE_RUN, 3.0f); + me->SetSpeedRate(MOVE_RUN, 3.0f); me->SetWalk(false); SetHoldState(false); JumpToNextStep(0); @@ -935,7 +935,7 @@ public: temp->HandleEmoteCommand(EMOTE_ONESHOT_KICK); temp->AI()->Talk(SAY_LIGHT_OF_DAWN46); } - me->SetSpeed(MOVE_RUN, 6.0f); + me->SetSpeedRate(MOVE_RUN, 6.0f); me->SetStandState(UNIT_STAND_STATE_DEAD); SetHoldState(false); // Darion got kicked by lich king JumpToNextStep(0); @@ -997,7 +997,7 @@ public: Unit* temp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->setFaction(me->getFaction()); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); uiDefenderGUID[0] = temp->GetGUID(); @@ -1005,7 +1005,7 @@ public: temp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000); temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->setFaction(me->getFaction()); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); uiEarthshatterGUID[0] = temp->GetGUID(); @@ -1014,7 +1014,7 @@ public: { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); temp->AI()->Talk(SAY_LIGHT_OF_DAWN50); } @@ -1022,7 +1022,7 @@ public: { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->HandleEmoteCommand(EMOTE_STATE_ATTACK_UNARMED); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); } @@ -1030,7 +1030,7 @@ public: { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED); temp->SetWalk(false); - temp->SetSpeed(MOVE_RUN, 2.0f); + temp->SetSpeedRate(MOVE_RUN, 2.0f); temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ); } } @@ -1044,33 +1044,33 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiMaxwellGUID)) { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[14]); } if (Creature* temp = ObjectAccessor::GetCreature(*me, uiKorfaxGUID)) { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[11]); } if (Creature* temp = ObjectAccessor::GetCreature(*me, uiEligorGUID)) { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[17]); } if (Creature* temp = ObjectAccessor::GetCreature(*me, uiDefenderGUID[0])) { - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f })); } if (Creature* temp = ObjectAccessor::GetCreature(*me, uiEarthshatterGUID[0])) { - temp->SetSpeed(MOVE_RUN, 6.0f); + temp->SetSpeedRate(MOVE_RUN, 6.0f); temp->SetStandState(UNIT_STAND_STATE_DEAD); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f })); } @@ -1093,7 +1093,7 @@ public: break; case 46: // Darion stand up, "not today" - me->SetSpeed(MOVE_RUN, 1.0f); + me->SetSpeedRate(MOVE_RUN, 1.0f); me->SetWalk(true); me->SetStandState(UNIT_STAND_STATE_STAND); Talk(SAY_LIGHT_OF_DAWN53); @@ -1153,7 +1153,7 @@ public: temp->AI()->Talk(EMOTE_LIGHT_OF_DAWN16); temp->CastSpell(temp, SPELL_TIRION_CHARGE, false); // jumping charge temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - temp->SetSpeed(MOVE_RUN, 3.0f); // workarounds, make Tirion still running + temp->SetSpeedRate(MOVE_RUN, 3.0f); // workarounds, make Tirion still running temp->SetWalk(false); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2]); if (Creature* lktemp = ObjectAccessor::GetCreature(*me, uiLichKingGUID)) @@ -1171,7 +1171,7 @@ public: case 54: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiLichKingGUID)) { - temp->SetSpeed(MOVE_RUN, 1.0f); + temp->SetSpeedRate(MOVE_RUN, 1.0f); me->SetWalk(true); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29]); // 26 } @@ -1208,7 +1208,7 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiTirionGUID)) // Tirion runs to Darion { temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - temp->SetSpeed(MOVE_RUN, 1.0f); + temp->SetSpeedRate(MOVE_RUN, 1.0f); temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[6]); } JumpToNextStep(2500); diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp index 74b300919d8..f7a1c18c234 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp @@ -450,7 +450,7 @@ public: me->SetVisible(false); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->SetDisableGravity(true); - me->SetSpeed(MOVE_WALK, 5.0f, true); + me->SetSpeedRate(MOVE_WALK, 5.0f); wp_reached = false; count = 0; say_timer = 3000; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp index d9b481d7b6d..fded249f9ca 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp @@ -249,7 +249,7 @@ public: me->CastStop(SPELL_FOG_BREATH); me->RemoveAurasDueToSpell(SPELL_FOG_BREATH); me->StopMoving(); - me->SetSpeed(MOVE_RUN, 2.0f); + me->SetSpeedRate(MOVE_RUN, 2.0f); events.ScheduleEvent(EVENT_CLEAVE, urand(5000, 10000)); events.ScheduleEvent(EVENT_CORROSION, urand(10000, 20000)); @@ -530,7 +530,7 @@ public: npc_felmyst_vaporAI(Creature* creature) : ScriptedAI(creature) { me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetSpeed(MOVE_RUN, 0.8f); + me->SetSpeedRate(MOVE_RUN, 0.8f); } void Reset() override { } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp index 791f68bae31..72e76ba52bf 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp @@ -425,7 +425,7 @@ class npc_akilzon_eagle : public CreatureScript if (Unit* target = ObjectAccessor::GetUnit(*me, TargetGUID)) DoCast(target, SPELL_EAGLE_SWOOP, true); TargetGUID.Clear(); - me->SetSpeed(MOVE_RUN, 1.2f); + me->SetSpeedRate(MOVE_RUN, 1.2f); EagleSwoop_Timer = urand(5000, 10000); } } @@ -454,7 +454,7 @@ class npc_akilzon_eagle : public CreatureScript { target->GetContactPoint(me, x, y, z); z += 2; - me->SetSpeed(MOVE_RUN, 5.0f); + me->SetSpeedRate(MOVE_RUN, 5.0f); TargetGUID = target->GetGUID(); } me->GetMotionMaster()->MovePoint(0, x, y, z); diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index 0407cb6cd7c..188f9d0cc03 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -142,7 +142,7 @@ class boss_nalorakk : public CreatureScript me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); inMove = false; waitTimer = 0; - me->SetSpeed(MOVE_RUN, 2); + me->SetSpeedRate(MOVE_RUN, 2); me->SetWalk(false); }else { diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp index 96c0798ae05..a1c2369cf66 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp @@ -347,7 +347,7 @@ class boss_zuljin : public CreatureScript Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true); Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true); Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Vortex->SetSpeed(MOVE_RUN, 1.0f); + Vortex->SetSpeedRate(MOVE_RUN, 1.0f); Vortex->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0)); DoZoneInCombat(Vortex); } @@ -438,7 +438,7 @@ class boss_zuljin : public CreatureScript { if (me->GetVictim()) TankGUID = me->EnsureVictim()->GetGUID(); - me->SetSpeed(MOVE_RUN, 5.0f); + me->SetSpeedRate(MOVE_RUN, 5.0f); AttackStart(target); // change victim Claw_Rage_Timer = 0; Claw_Loop_Timer = 500; @@ -462,7 +462,7 @@ class boss_zuljin : public CreatureScript if (Claw_Counter == 12) { Claw_Rage_Timer = urand(15000, 20000); - me->SetSpeed(MOVE_RUN, 1.2f); + me->SetSpeedRate(MOVE_RUN, 1.2f); AttackStart(ObjectAccessor::GetUnit(*me, TankGUID)); TankGUID.Clear(); return; @@ -487,7 +487,7 @@ class boss_zuljin : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { TankGUID = me->EnsureVictim()->GetGUID(); - me->SetSpeed(MOVE_RUN, 5.0f); + me->SetSpeedRate(MOVE_RUN, 5.0f); AttackStart(target); // change victim Lynx_Rush_Timer = 0; Claw_Counter = 0; @@ -510,7 +510,7 @@ class boss_zuljin : public CreatureScript if (Claw_Counter == 9) { Lynx_Rush_Timer = urand(15000, 20000); - me->SetSpeed(MOVE_RUN, 1.2f); + me->SetSpeedRate(MOVE_RUN, 1.2f); AttackStart(ObjectAccessor::GetUnit(*me, TankGUID)); TankGUID.Clear(); } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp index 44cbdec2cb5..0526dcfa630 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp @@ -479,12 +479,12 @@ public: void DoMount() { me->Mount(SKARLOC_MOUNT_MODEL); - me->SetSpeed(MOVE_RUN, SPEED_MOUNT); + me->SetSpeedRate(MOVE_RUN, SPEED_MOUNT); } void DoUnmount() { me->Dismount(); - me->SetSpeed(MOVE_RUN, SPEED_RUN); + me->SetSpeedRate(MOVE_RUN, SPEED_RUN); } void EnterCombat(Unit* /*who*/) override { diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index 7da15b1fdce..71ebe870e3d 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -205,7 +205,7 @@ public: PointData = GetMoveData(); MovePoint = PointData->LocIdEnd; - me->SetSpeed(MOVE_FLIGHT, 1.5f); + me->SetSpeedRate(MOVE_FLIGHT, 1.5f); me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation); } } @@ -220,7 +220,7 @@ public: PointData = GetMoveData(); if (PointData) { - me->SetSpeed(MOVE_FLIGHT, 1.0f); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); me->GetMotionMaster()->MovePoint(PointData->LocId, PointData->fX, PointData->fY, PointData->fZ); } break; @@ -250,7 +250,7 @@ public: if (Creature * trigger = me->SummonCreature(NPC_TRIGGER, MiddleRoomLocation, TEMPSUMMON_CORPSE_DESPAWN)) triggerGUID = trigger->GetGUID(); me->GetMotionMaster()->MoveTakeoff(11, Phase2Floating); - me->SetSpeed(MOVE_FLIGHT, 1.0f); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); Talk(SAY_PHASE_2_TRANS); instance->SetData(DATA_ONYXIA_PHASE, Phase); events.ScheduleEvent(EVENT_WHELP_SPAWN, 5000); diff --git a/src/server/scripts/Kalimdor/zone_azshara.cpp b/src/server/scripts/Kalimdor/zone_azshara.cpp index 1ed95c16a0d..4847ac46542 100644 --- a/src/server/scripts/Kalimdor/zone_azshara.cpp +++ b/src/server/scripts/Kalimdor/zone_azshara.cpp @@ -404,7 +404,7 @@ public: DoCast(me, SPELL_PERIODIC_DEPTH_CHARGE); me->SetHover(true); me->SetSwim(true); - me->SetSpeed(MOVE_RUN, 0.85f, true); + me->SetSpeedRate(MOVE_RUN, 0.85f); me->GetMotionMaster()->MovementExpired(); me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP]); Escape = true; diff --git a/src/server/scripts/Kalimdor/zone_desolace.cpp b/src/server/scripts/Kalimdor/zone_desolace.cpp index 6880d8ee38f..3f4a905147f 100644 --- a/src/server/scripts/Kalimdor/zone_desolace.cpp +++ b/src/server/scripts/Kalimdor/zone_desolace.cpp @@ -89,7 +89,7 @@ public: me->UpdateEntry(NPC_TAMED_KODO); me->CombatStop(); me->DeleteThreatList(); - me->SetSpeed(MOVE_RUN, 0.6f, true); + me->SetSpeedRate(MOVE_RUN, 0.6f); me->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, me->GetFollowAngle()); me->setActive(true); } diff --git a/src/server/scripts/Kalimdor/zone_durotar.cpp b/src/server/scripts/Kalimdor/zone_durotar.cpp index 05caf9cca3a..62a041e7798 100644 --- a/src/server/scripts/Kalimdor/zone_durotar.cpp +++ b/src/server/scripts/Kalimdor/zone_durotar.cpp @@ -483,8 +483,8 @@ class spell_mount_check : public SpellScriptLoader else if (!owner->IsMounted() && target->IsMounted()) target->Dismount(); - target->SetSpeed(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN)); - target->SetSpeed(MOVE_WALK, owner->GetSpeedRate(MOVE_WALK)); + target->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN)); + target->SetSpeedRate(MOVE_WALK, owner->GetSpeedRate(MOVE_WALK)); } void Register() override diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp index ab09dd45710..3c11fd5d9a6 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp @@ -454,11 +454,11 @@ public: float distance = me->GetDistance(JedogaPosition[1]); if (distance < 9.0f) - me->SetSpeed(MOVE_WALK, 0.5f, true); + me->SetSpeedRate(MOVE_WALK, 0.5f); else if (distance < 15.0f) - me->SetSpeed(MOVE_WALK, 0.75f, true); + me->SetSpeedRate(MOVE_WALK, 0.75f); else if (distance < 20.0f) - me->SetSpeed(MOVE_WALK, 1.0f, true); + me->SetSpeedRate(MOVE_WALK, 1.0f); me->GetMotionMaster()->Clear(false); me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index e25f64f61aa..04b62f77e9a 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -178,7 +178,7 @@ class boss_prince_taldaram : public CreatureScript if (Unit* embraceTarget = GetEmbraceTarget()) { me->GetMotionMaster()->Clear(); - me->SetSpeed(MOVE_WALK, 2.0f, true); + me->SetSpeedRate(MOVE_WALK, 2.0f); me->GetMotionMaster()->MoveChase(embraceTarget); } events.ScheduleEvent(EVENT_VANISHED, 1300); @@ -188,7 +188,7 @@ class boss_prince_taldaram : public CreatureScript DoCast(embraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR); Talk(SAY_FEED); me->GetMotionMaster()->Clear(); - me->SetSpeed(MOVE_WALK, 1.0f, true); + me->SetSpeedRate(MOVE_WALK, 1.0f); me->GetMotionMaster()->MoveChase(me->GetVictim()); events.ScheduleEvent(EVENT_FEEDING, 20000); break; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index c89510211b9..7440984d7c5 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -804,7 +804,7 @@ class npc_anubarak_spike : public CreatureScript void StartChase(Unit* who) { DoCast(who, SPELL_MARK); - me->SetSpeed(MOVE_RUN, 0.5f); + me->SetSpeedRate(MOVE_RUN, 0.5f); // make sure the Spine will really follow the one he should me->getThreatManager().clearReferences(); me->SetInCombatWithZone(); diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 4c2b92da0ea..3ac85809fa2 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -2580,7 +2580,7 @@ class npc_quel_delar_sword : public CreatureScript void Reset() override { _events.Reset(); - me->SetSpeed(MOVE_FLIGHT, 4.5f, true); + me->SetSpeedRate(MOVE_FLIGHT, 4.5f); DoCast(SPELL_WHIRLWIND_VISUAL); if (_intro) _events.ScheduleEvent(EVENT_QUEL_DELAR_INIT, 0); diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index 03f12e46bc3..b24a36da3fb 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -418,7 +418,7 @@ class boss_krick : public CreatureScript case EVENT_OUTRO_6: if (Creature* tyrannus = ObjectAccessor::GetCreature(*me, _instanceScript->GetGuidData(DATA_TYRANNUS_EVENT))) { - tyrannus->SetSpeed(MOVE_FLIGHT, 3.5f, true); + tyrannus->SetSpeedRate(MOVE_FLIGHT, 3.5f); tyrannus->GetMotionMaster()->MovePoint(1, outroPos[4]); _tyrannusGUID = tyrannus->GetGUID(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index 166e9739a95..51711f9ded5 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -1069,7 +1069,7 @@ class npc_blood_queen_lana_thel : public CreatureScript if (Creature* summon = DoSummon(NPC_FLOATING_TRIGGER, triggerPos, 15000, TEMPSUMMON_TIMED_DESPAWN)) { summon->CastSpell(summon, SPELL_OOC_INVOCATION_VISUAL, true); - summon->SetSpeed(MOVE_FLIGHT, 0.15f, true); // todo: creature is swimming, check if this is blizzlike or not. + summon->SetSpeedRate(MOVE_FLIGHT, 0.15f); // todo: creature is swimming, check if this is blizzlike or not. summon->GetMotionMaster()->MovePoint(0, triggerEndPos); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index 056231285e2..9f20799df82 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -142,7 +142,7 @@ class boss_lord_marrowgar : public CreatureScript void Reset() override { _Reset(); - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); me->RemoveAurasDueToSpell(SPELL_BONE_STORM); me->RemoveAurasDueToSpell(SPELL_BERSERK); events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000); @@ -224,7 +224,7 @@ class boss_lord_marrowgar : public CreatureScript case EVENT_BONE_STORM_BEGIN: if (Aura* pStorm = me->GetAura(SPELL_BONE_STORM)) pStorm->SetDuration(int32(_boneStormDuration)); - me->SetSpeed(MOVE_RUN, _baseSpeed*3.0f, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed*3.0f); Talk(SAY_BONE_STORM); events.ScheduleEvent(EVENT_BONE_STORM_END, _boneStormDuration+1); // no break here @@ -242,7 +242,7 @@ class boss_lord_marrowgar : public CreatureScript if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) me->GetMotionMaster()->MovementExpired(); me->GetMotionMaster()->MoveChase(me->GetVictim()); - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); events.CancelEvent(EVENT_BONE_STORM_MOVE); events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000); if (!IsHeroic()) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 280a0aaa13a..fe6e4081326 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -369,21 +369,21 @@ class boss_professor_putricide : public CreatureScript { case POINT_FESTERGUT: instance->SetBossState(DATA_FESTERGUT, IN_PROGRESS); // needed here for delayed gate close - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); DoAction(ACTION_FESTERGUT_GAS); if (Creature* festergut = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FESTERGUT))) festergut->CastSpell(festergut, SPELL_GASEOUS_BLIGHT_LARGE, false, NULL, NULL, festergut->GetGUID()); break; case POINT_ROTFACE: instance->SetBossState(DATA_ROTFACE, IN_PROGRESS); // needed here for delayed gate close - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); DoAction(ACTION_ROTFACE_OOZE); events.ScheduleEvent(EVENT_ROTFACE_OOZE_FLOOD, 25000, 0, PHASE_ROTFACE); break; case POINT_TABLE: // stop attack me->GetMotionMaster()->MoveIdle(); - me->SetSpeed(MOVE_RUN, _baseSpeed, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed); if (GameObject* table = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_PUTRICIDE_TABLE))) me->SetFacingToObject(table); // operating on new phase already @@ -418,7 +418,7 @@ class boss_professor_putricide : public CreatureScript { case ACTION_FESTERGUT_COMBAT: SetPhase(PHASE_FESTERGUT); - me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f); me->GetMotionMaster()->MovePoint(POINT_FESTERGUT, festergutWatchPos); me->SetReactState(REACT_PASSIVE); DoZoneInCombat(me); @@ -435,7 +435,7 @@ class boss_professor_putricide : public CreatureScript case ACTION_ROTFACE_COMBAT: { SetPhase(PHASE_ROTFACE); - me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f); me->GetMotionMaster()->MovePoint(POINT_ROTFACE, rotfaceWatchPos); me->SetReactState(REACT_PASSIVE); _oozeFloodStage = 0; @@ -477,7 +477,7 @@ class boss_professor_putricide : public CreatureScript events.ScheduleEvent(EVENT_ROTFACE_DIES, 4500, 0, PHASE_ROTFACE); break; case ACTION_CHANGE_PHASE: - me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true); + me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f); events.DelayEvents(30000); me->AttackStop(); if (!IsHeroic()) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 0b129f3aa89..caa37465165 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -315,7 +315,7 @@ class boss_sindragosa : public CreatureScript me->SetCanFly(true); me->SetDisableGravity(true); me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); - me->SetSpeed(MOVE_FLIGHT, 4.0f); + me->SetSpeedRate(MOVE_FLIGHT, 4.0f); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); float moveTime = me->GetExactDist(&SindragosaFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); @@ -351,7 +351,7 @@ class boss_sindragosa : public CreatureScript me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); me->SetHomePosition(SindragosaLandPos); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetSpeed(MOVE_FLIGHT, 2.5f); + me->SetSpeedRate(MOVE_FLIGHT, 2.5f); // Sindragosa enters combat as soon as she lands DoZoneInCombat(); @@ -697,7 +697,7 @@ class npc_spinestalker : public CreatureScript return; me->setActive(true); - me->SetSpeed(MOVE_FLIGHT, 2.0f); + me->SetSpeedRate(MOVE_FLIGHT, 2.0f); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); float moveTime = me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); @@ -834,7 +834,7 @@ class npc_rimefang : public CreatureScript return; me->setActive(true); - me->SetSpeed(MOVE_FLIGHT, 2.0f); + me->SetSpeedRate(MOVE_FLIGHT, 2.0f); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); float moveTime = me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); 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 4675989228a..4a0a8217af8 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -763,7 +763,7 @@ class boss_the_lich_king : public CreatureScript { summons.Summon(summon); summon->SetReactState(REACT_PASSIVE); - summon->SetSpeed(MOVE_FLIGHT, 0.5f); + summon->SetSpeedRate(MOVE_FLIGHT, 0.5f); summon->GetMotionMaster()->MoveRandom(10.0f); if (!events.IsInPhase(PHASE_FROSTMOURNE)) summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15000)); @@ -1448,7 +1448,7 @@ class npc_valkyr_shadowguard : public CreatureScript _events.Reset(); me->SetReactState(REACT_PASSIVE); DoCast(me, SPELL_WINGS_OF_THE_DAMNED, false); - me->SetSpeed(MOVE_FLIGHT, 0.642857f, true); + me->SetSpeedRate(MOVE_FLIGHT, 0.642857f); } void IsSummonedBy(Unit* /*summoner*/) override diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index ec47b0db101..32054b67915 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -18,38 +18,74 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "naxxramas.h" +#include "SpellScript.h" +#include <math.h> -enum Spells +enum Texts { - SPELL_MORTAL_WOUND = 25646, - SPELL_ENRAGE = 28371, - SPELL_DECIMATE = 28374, - SPELL_BERSERK = 26662, - SPELL_INFECTED_WOUND = 29306 + EMOTE_SPOTS_ONE = 0, + EMOTE_DECIMATE = 1, + EMOTE_ENRAGE = 2, + EMOTE_DEVOURS_ALL = 3, + EMOTE_BERSERKER = 4 }; -enum Creatures +enum Spells { - NPC_ZOMBIE = 16360 + // Gluth + SPELL_MORTAL_WOUND = 54378, // spell effect dummy unused. what its supposed to do is unkown. + SPELL_ENRAGE = 28371, // 54427 in 25 man. + SPELL_DECIMATE = 28374, // 54426 in 25 man. Effect0 is handled by SpellScript (see below) and 2 rows in conditions table. Effect2 is handled by SpellScript (see below). + SPELL_DECIMATE_DMG = 28375, + SPELL_BERSERK = 26662, + SPELL_ZOMBIE_CHOW_SEARCH_SINGLE = 28239, // Insta kill spell. Single target. See spell script below. + SPELL_ZOMBIE_CHOW_SEARCH_MULTI = 28404, // Insta kill spell. Affect all zombies 10 yards around Gluth's center. See one row conditions table + spell script below. + + // Zombies + SPELL_INFECTED_WOUND = 29307 // Used by the zombies on self. }; Position const PosSummon[3] = { - {3267.9f, -3172.1f, 297.42f, 0.94f}, - {3253.2f, -3132.3f, 297.42f, 0}, - {3308.3f, -3185.8f, 297.42f, 1.58f}, + { 3270.132f, -3169.948f, 297.5891f, 5.88176f }, + { 3307.298f, -3183.449f, 297.5891f, 5.742133f }, + { 3255.708f, -3135.677f, 297.5891f, 1.867502f } }; enum Events { - EVENT_WOUND = 1, + EVENT_WOUND = 1, EVENT_ENRAGE, EVENT_DECIMATE, EVENT_BERSERK, EVENT_SUMMON, + EVENT_SEARCH_ZOMBIE_SINGLE, + EVENT_KILL_ZOMBIE_SINGLE, + EVENT_SEARCH_ZOMBIE_MULTI }; -#define EMOTE_NEARBY " spots a nearby zombie to devour!" +enum States +{ + STATE_GLUTH_NORMAL = 1, + STATE_GLUTH_EATING = 2, + + STATE_ZOMBIE_NORMAL = 1, + STATE_ZOMBIE_DECIMATED = 2, + STATE_ZOMBIE_TOBE_EATEN = 3 +}; + +enum SummonGroups +{ + SUMMON_GROUP_CHOW_10MAN = 1, + SUMMON_GROUP_CHOW_25MAN = 2 +}; + +enum Misc +{ + EVENT_GLUTH_ZOMBIE_BEHAVIOR = 10495, // unused. event handled by spell_gluth_decimate_SpellScript::HandleEvent + DATA_ZOMBIE_STATE = 1, + ACTION_DECIMATE_EVENT = 2, +}; class boss_gluth : public CreatureScript { @@ -58,99 +94,387 @@ public: CreatureAI* GetAI(Creature* creature) const override { - return new boss_gluthAI(creature); + return GetInstanceAI<boss_gluthAI>(creature); } struct boss_gluthAI : public BossAI { - boss_gluthAI(Creature* creature) : BossAI(creature, BOSS_GLUTH) - { - // Do not let Gluth be affected by zombies' debuff - me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true); - } - void MoveInLineOfSight(Unit* who) override + boss_gluthAI(Creature* creature) : BossAI(creature, BOSS_GLUTH), state(STATE_GLUTH_NORMAL) {} + + void Reset() override { - if (who->GetEntry() == NPC_ZOMBIE && me->IsWithinDistInMap(who, 7)) - { - SetGazeOn(who); - /// @todo use a script text - me->TextEmote(EMOTE_NEARBY, nullptr, true); - } - else - BossAI::MoveInLineOfSight(who); + _Reset(); + zombieToBeEatenGUID.Clear(); + state = STATE_GLUTH_NORMAL; + me->SetReactState(REACT_AGGRESSIVE); + me->SetSpeed(UnitMoveType::MOVE_RUN, 12.0f); } void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.ScheduleEvent(EVENT_WOUND, 10000); - events.ScheduleEvent(EVENT_ENRAGE, 15000); - events.ScheduleEvent(EVENT_DECIMATE, 105000); - events.ScheduleEvent(EVENT_BERSERK, 8*60000); - events.ScheduleEvent(EVENT_SUMMON, 15000); + events.ScheduleEvent(EVENT_WOUND, Seconds(10)); + events.ScheduleEvent(EVENT_ENRAGE, randtime(Seconds(16), Seconds(22))); + events.ScheduleEvent(EVENT_DECIMATE, randtime(Minutes(1)+Seconds(50), Minutes(2))); + events.ScheduleEvent(EVENT_BERSERK, Minutes(8)); + events.ScheduleEvent(EVENT_SUMMON, Seconds(15)); + events.ScheduleEvent(EVENT_SEARCH_ZOMBIE_SINGLE, Seconds(12)); } - void JustSummoned(Creature* summon) override + void SummonedCreatureDies(Creature* summoned, Unit* /* who */) override { - if (summon->GetEntry() == NPC_ZOMBIE) - summon->AI()->AttackStart(me); - summons.Summon(summon); + summons.Despawn(summoned); // needed or else dead zombies not despawned yet will still be in the list } void UpdateAI(uint32 diff) override { - if (!UpdateVictimWithGaze()) + if (!UpdateVictim() || !CheckInRoom()) return; events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + while (uint32 eventId = events.ExecuteEvent()) { switch (eventId) { case EVENT_WOUND: + if (state == STATE_GLUTH_EATING) + { + events.Repeat(Seconds(3)); + break; + } + DoCastVictim(SPELL_MORTAL_WOUND); - events.ScheduleEvent(EVENT_WOUND, 10000); + events.Repeat(Seconds(10)); break; case EVENT_ENRAGE: - /// @todo Add missing text + if (state == STATE_GLUTH_EATING) + { + events.Repeat(Seconds(5)); + break; + } + + Talk(EMOTE_ENRAGE); DoCast(me, SPELL_ENRAGE); - events.ScheduleEvent(EVENT_ENRAGE, 15000); + events.Repeat(randtime(Seconds(16), Seconds(22))); break; case EVENT_DECIMATE: - /// @todo Add missing text + if (state == STATE_GLUTH_EATING) + { + events.Repeat(Seconds(4)); + break; + } + + Talk(EMOTE_DECIMATE); DoCastAOE(SPELL_DECIMATE); - events.ScheduleEvent(EVENT_DECIMATE, 105000); + for (int i = 1; i <= 20; i++) + events.ScheduleEvent(EVENT_SEARCH_ZOMBIE_MULTI, Seconds(3*i)); + events.ScheduleEvent(EVENT_DECIMATE, randtime(Minutes(1)+Seconds(50), Minutes(2))); break; case EVENT_BERSERK: + Talk(EMOTE_BERSERKER); DoCast(me, SPELL_BERSERK); - events.ScheduleEvent(EVENT_BERSERK, 5*60000); + events.Repeat(Minutes(5)); //refresh the hard enrage buff break; case EVENT_SUMMON: - for (int32 i = 0; i < RAID_MODE(1, 2); ++i) - DoSummon(NPC_ZOMBIE, PosSummon[rand32() % RAID_MODE(1, 3)]); - events.ScheduleEvent(EVENT_SUMMON, 10000); + if (Is25ManRaid()) // one wave each 10s. one wave=1 zombie in 10man and 2 zombies in 25man. + me->SummonCreatureGroup(SUMMON_GROUP_CHOW_25MAN); + else + me->SummonCreatureGroup(SUMMON_GROUP_CHOW_10MAN); + events.Repeat(Seconds(10)); + break; + case EVENT_SEARCH_ZOMBIE_SINGLE: + { + Creature* zombie = nullptr; + for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr) + { + zombie=ObjectAccessor::GetCreature(*me, *itr); + if (!zombie || !zombie->IsAlive() || !zombie->IsWithinDistInMap(me, 10.0)) + zombie = nullptr; + } + + if (zombie) + { + zombieToBeEatenGUID = zombie->GetGUID(); // save for later use + + // the soon-to-be-eaten zombie should stop moving and stop attacking + zombie->AI()->SetData(DATA_ZOMBIE_STATE, STATE_ZOMBIE_TOBE_EATEN); + + // gluth should stop AAs on his primary target and turn toward the zombie (2 yards away). He then pauses for a few seconds. + me->SetSpeed(MOVE_RUN, 36.0f); + + me->SetReactState(ReactStates::REACT_PASSIVE); + me->AttackStop(); + + Talk(EMOTE_SPOTS_ONE); + + //me->SetTarget(ObjectGuid::Empty); + + me->GetMotionMaster()->MoveCloserAndStop(1, zombie, 2.0f); + + state = STATE_GLUTH_EATING; + } + + events.Repeat(RAID_MODE(Seconds(7), Seconds(5))); + break; + } + case EVENT_KILL_ZOMBIE_SINGLE: + { + Creature* zombieToBeEaten = ObjectAccessor::GetCreature(*me, zombieToBeEatenGUID); + if (zombieToBeEaten && zombieToBeEaten->IsAlive() && zombieToBeEaten->IsWithinDistInMap(me, 10.0)) + DoCast(zombieToBeEaten, SPELL_ZOMBIE_CHOW_SEARCH_SINGLE); // do the killing + healing in done inside by spell script see below. + + zombieToBeEatenGUID = ObjectGuid::Empty; + state = STATE_GLUTH_NORMAL; + me->SetSpeed(UnitMoveType::MOVE_RUN, 12.0f); + + // and then return on primary target + me->SetReactState(REACT_AGGRESSIVE); + + break; + } + case EVENT_SEARCH_ZOMBIE_MULTI: + { + if (state == STATE_GLUTH_EATING) // skip and simply wait for the next occurence + break; + + Creature* zombie = nullptr; + for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr) + { + zombie = ObjectAccessor::GetCreature(*me, *itr); + if (zombie && zombie->IsAlive() && zombie->GetExactDist2d(me) > 18.0) + zombie = nullptr; + } + + if (zombie) // cast the aoe spell only if at least one zombie is found nearby + { + Talk(EMOTE_DEVOURS_ALL); + DoCastAOE(SPELL_ZOMBIE_CHOW_SEARCH_MULTI); + } break; + } } } - if (me->GetVictim() && me->EnsureVictim()->GetEntry() == NPC_ZOMBIE) + DoMeleeAttackIfReady(); + } + + void MovementInform(uint32 /*type*/, uint32 id) override + { + if (id == 1){ + me->GetMotionMaster()->MoveIdle(); + events.ScheduleEvent(EVENT_KILL_ZOMBIE_SINGLE, Seconds(1)); + } + + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_DECIMATE_EVENT: + for (ObjectGuid zombieGuid : summons) + { + Creature* zombie = ObjectAccessor::GetCreature(*me, zombieGuid); + if (zombie && zombie->IsAlive()) + zombie->AI()->SetData(DATA_ZOMBIE_STATE, STATE_ZOMBIE_DECIMATED); + } + break; + } + } + + private: + ObjectGuid zombieToBeEatenGUID; + uint8 state; + }; + +}; + +// spell 28374 (10man) / 54426 (25man) - Decimate +class spell_gluth_decimate : public SpellScriptLoader +{ +public: + spell_gluth_decimate() : SpellScriptLoader("spell_gluth_decimate") { } + + class spell_gluth_decimate_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gluth_decimate_SpellScript); + + // handles the damaging effect of the decimate spell. + void HandleScriptEffect(SpellEffIndex /* index */) + { + if (Unit *unit = GetHitUnit()) { - if (me->IsWithinMeleeRange(me->GetVictim())) + int32 damage = int32(unit->GetHealth()) - int32(unit->CountPctFromMaxHealth(5)); + if (damage > 0) + GetCaster()->CastCustomSpell(SPELL_DECIMATE_DMG, SPELLVALUE_BASE_POINT0, damage, unit); + } + } + + // handles the change of zombies behavior after the decimate spell + void HandleEvent(SpellEffIndex /* index */) + { + GetCaster()->GetAI()->DoAction(ACTION_DECIMATE_EVENT); + } + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return (sSpellMgr->GetSpellInfo(SPELL_DECIMATE_DMG) != nullptr); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gluth_decimate_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + OnEffectHit += SpellEffectFn(spell_gluth_decimate_SpellScript::HandleEvent, EFFECT_2, SPELL_EFFECT_SEND_EVENT); + } + + bool Load() override + { + return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH; + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gluth_decimate_SpellScript(); + } + +}; + +// used by both 28239 & 28404 (single target and aoe zombie-kill spell) to heal Gluth on each target hit. + +class spell_gluth_zombiechow_search : public SpellScriptLoader +{ +public: + spell_gluth_zombiechow_search() : SpellScriptLoader("spell_gluth_zombiechow_search") { } + + class spell_gluth_zombiechow_search_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gluth_zombiechow_search_SpellScript); + + void HealForEachTargetHit() + { + GetCaster()->ModifyHealth(int32(GetCaster()->CountPctFromMaxHealth(5))); + } + + void Register() override + { + AfterHit += SpellHitFn(spell_gluth_zombiechow_search_SpellScript::HealForEachTargetHit); + } + + bool Load() override + { + return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH; + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_gluth_zombiechow_search_SpellScript(); + } + +}; + +// creature 16360 (10man) / 30303 (25man) +class npc_zombie_chow : public CreatureScript +{ +public: + + npc_zombie_chow() : CreatureScript("npc_zombie_chow") { } + + struct npc_zombie_chowAI : public ScriptedAI + { + npc_zombie_chowAI(Creature* creature) : ScriptedAI(creature) + { + GluthGUID = creature->GetInstanceScript()->GetGuidData(DATA_GLUTH); + + DoCast(me, SPELL_INFECTED_WOUND); + state = STATE_ZOMBIE_NORMAL; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (state == STATE_ZOMBIE_DECIMATED) + { + timer += diff; + Creature* gluth = ObjectAccessor::GetCreature(*me, GluthGUID); + // Putting this in the UpdateAI loop fixes an issue where death gripping a decimated zombie would make the zombie stand still until the rest of the fight. + // Also fix the issue where if one or more zombie is rooted when decimates hits (and MovePoint() is called), the zombie teleport to the boss. pretty weird behavior. + if (gluth && timer>1600 && me->GetExactDist2d(gluth) > 10.0 && me->CanFreeMove()) // it takes about 1600 ms for the animation to cycle. This way, the animation looks relatively smooth. { - me->Kill(me->GetVictim()); - me->ModifyHealth(int32(me->CountPctFromMaxHealth(5))); + me->GetMotionMaster()->MovePoint(0, gluth->GetPosition()); // isn't dynamic. So, to take into account Gluth's movement, it must be called periodicly. + timer = 0; } + + if (me->GetExactDist2d(gluth) <= 10.0) + me->StopMoving(); } - else + else if (state == STATE_ZOMBIE_NORMAL) DoMeleeAttackIfReady(); } + + void SetData(uint32 id, uint32 value) override + { + if (id == DATA_ZOMBIE_STATE) // change of state + { + state = value; + if (value == STATE_ZOMBIE_DECIMATED) + { + me->SetReactState(ReactStates::REACT_PASSIVE); + me->AttackStop(); + me->SetTarget(ObjectGuid::Empty); + // at this point, the zombie should be non attacking and non moving. + + me->SetWalk(true); // it doesnt seem to work with MoveFollow() (but it does work with MovePoint()). + + timer = 1000; + } + else if (value == STATE_ZOMBIE_TOBE_EATEN) + { + // forced to stand still + me->GetMotionMaster()->Clear(); + me->StopMoving(); + + // and loose aggro behavior + me->SetReactState(ReactStates::REACT_PASSIVE); + me->AttackStop(); + me->SetTarget(ObjectGuid::Empty); + + me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_GRIP, true); // not sure if this is blizz-like but this is very convenient + } + } + } + + uint32 GetData(uint32 index) const override + { + if (index == DATA_ZOMBIE_STATE) + return state; + return 0; + } + + private: + uint32 timer; + uint8 state; + ObjectGuid GluthGUID; }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_zombie_chowAI>(creature); + } }; void AddSC_boss_gluth() { new boss_gluth(); + new spell_gluth_decimate(); + new spell_gluth_zombiechow_search(); + new npc_zombie_chow(); } diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp index 02b82d255cd..e3971248513 100644 --- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp +++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp @@ -153,6 +153,9 @@ class instance_naxxramas : public InstanceMapScript case NPC_SIR: SirGUID = creature->GetGUID(); break; + case NPC_GLUTH: + GluthGUID = creature->GetGUID(); + break; case NPC_HEIGAN: HeiganGUID = creature->GetGUID(); break; @@ -327,6 +330,8 @@ class instance_naxxramas : public InstanceMapScript return SirGUID; case DATA_HEIGAN: return HeiganGUID; + case DATA_GLUTH: + return GluthGUID; case DATA_FEUGEN: return FeugenGUID; case DATA_STALAGG: @@ -582,6 +587,8 @@ class instance_naxxramas : public InstanceMapScript ObjectGuid HorsemenChestGUID; /* The Construct Quarter */ + // Gluth + ObjectGuid GluthGUID; // Thaddius ObjectGuid ThaddiusGUID; ObjectGuid FeugenGUID; diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h index bece5a60bee..a3fedf5aa40 100644 --- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h +++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h @@ -68,6 +68,7 @@ enum Data64 DATA_LADY, DATA_BARON, DATA_SIR, + DATA_GLUTH, DATA_THADDIUS, DATA_HEIGAN, DATA_FEUGEN, @@ -92,6 +93,7 @@ enum CreaturesIds NPC_LADY = 16065, NPC_BARON = 30549, NPC_SIR = 16063, + NPC_GLUTH = 15932, NPC_HEIGAN = 15936, NPC_THADDIUS = 15928, NPC_FEUGEN = 15930, diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 277ca793a8f..f000d7a3ef7 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -377,7 +377,7 @@ public: me->SetDisableGravity(true); me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); // TO DO: find what in core is making boss slower than in retail (when correct speed data) or find missing movement flag update or forced spline change - me->SetSpeed(MOVE_FLIGHT, _flySpeed * 0.25f); + me->SetSpeedRate(MOVE_FLIGHT, _flySpeed * 0.25f); if (_despawned) DoAction(ACTION_HANDLE_RESPAWN); @@ -603,7 +603,7 @@ public: me->SetRespawnDelay(respawnDelay); // Set speed to normal value - me->SetSpeed(MOVE_FLIGHT, _flySpeed); + me->SetSpeedRate(MOVE_FLIGHT, _flySpeed); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->RemoveAllAuras(); @@ -1165,7 +1165,7 @@ public: _instance = creature->GetInstanceScript(); me->SetReactState(REACT_PASSIVE); // TO DO: These were a bit faster than what they should be. Not sure what is the reason. - me->SetSpeed(MOVE_FLIGHT, 1.25f); + me->SetSpeedRate(MOVE_FLIGHT, 1.25f); } void Initialize() @@ -1274,7 +1274,7 @@ public: me->SetReactState(REACT_PASSIVE); // TO DO: Something is wrong with calculations for flying creatures that are on WP/Cyclic path. // They should get the same difference as to when at ground from run creature switch to walk. - me->SetSpeed(MOVE_FLIGHT, 0.45f); + me->SetSpeedRate(MOVE_FLIGHT, 0.45f); } void Reset() override @@ -1566,7 +1566,7 @@ public: { me->DespawnOrUnsummon(2050); me->SetOrientation(2.5f); - me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); Position pos = me->GetPosition(); pos.m_positionX += 10.0f; pos.m_positionY += 10.0f; diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp index e1a4a6ed7b8..3d9ea97b136 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -375,7 +375,7 @@ class npc_ruby_emerald_amber_drake : public CreatureScript { me->DespawnOrUnsummon(2050); me->SetOrientation(2.5f); - me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); Talk(SAY_DRAKES_TAKEOFF); Position pos = me->GetPosition(); Position offset = { 10.0f, 10.0f, 12.0f, 0.0f }; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index a98da2c6e3d..8f7687d0fca 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -174,7 +174,7 @@ public: { if (pSpark->IsAlive()) { - pSpark->SetSpeed(MOVE_RUN, 2.0f); + pSpark->SetSpeedRate(MOVE_RUN, 2.0f); pSpark->GetMotionMaster()->Clear(); pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); } @@ -355,7 +355,7 @@ public: { Position pos = ionar->GetPosition(); - me->SetSpeed(MOVE_RUN, 2.0f); + me->SetSpeedRate(MOVE_RUN, 2.0f); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 0714f2426bc..8aa443cba3f 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -703,7 +703,7 @@ class boss_leviathan_mk_ii : public CreatureScript if (Unit* turret = me->GetVehicleKit()->GetPassenger(3)) turret->KillSelf(); - me->SetSpeed(MOVE_RUN, 1.5f, true); + me->SetSpeedRate(MOVE_RUN, 1.5f); me->GetMotionMaster()->MovePoint(WP_MKII_P1_IDLE, VehicleRelocation[WP_MKII_P1_IDLE]); } else if (events.IsInPhase(PHASE_VOL7RON)) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp index f5337b2dca5..363f5907048 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp @@ -366,7 +366,7 @@ class boss_razorscale : public CreatureScript _EnterCombat(); if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL))) controller->AI()->DoAction(ACTION_HARPOON_BUILD); - me->SetSpeed(MOVE_FLIGHT, 3.0f, true); + me->SetSpeedRate(MOVE_FLIGHT, 3.0f); me->SetReactState(REACT_PASSIVE); phase = PHASE_GROUND; events.SetPhase(PHASE_GROUND); @@ -550,7 +550,7 @@ class boss_razorscale : public CreatureScript me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); me->SetReactState(REACT_AGGRESSIVE); me->RemoveAurasDueToSpell(SPELL_HARPOON_TRIGGER); - me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + me->SetSpeedRate(MOVE_FLIGHT, 1.0f); PermaGround = true; DoCastAOE(SPELL_FLAMEBREATH); events.ScheduleEvent(EVENT_FLAME, 15000, 0, PHASE_PERMAGROUND); @@ -677,7 +677,7 @@ class npc_expedition_commander : public CreatureScript if (Creature* summonedEngineer = me->SummonCreature(NPC_ENGINEER, PosEngSpawn, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000)) { summonedEngineer->SetWalk(false); - summonedEngineer->SetSpeed(MOVE_RUN, 0.5f); + summonedEngineer->SetSpeedRate(MOVE_RUN, 0.5f); summonedEngineer->SetHomePosition(PosEngRepair[n]); summonedEngineer->GetMotionMaster()->MoveTargetedHome(); Engineer[n] = summonedEngineer->GetGUID(); diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp index 1af45f3031a..ee71c696d7c 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp @@ -746,7 +746,7 @@ public: //! HACK: Creature's can't have MOVEMENTFLAG_FLYING me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL); - me->SetSpeed(MOVE_FLIGHT, 0.5f); + me->SetSpeedRate(MOVE_FLIGHT, 0.5f); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index d7b65093898..7615217a794 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -209,7 +209,7 @@ public: Initialize(); Summons.DespawnAll(); - me->SetSpeed(MOVE_FLIGHT, 3.0f); + me->SetSpeedRate(MOVE_FLIGHT, 3.0f); if ((ObjectAccessor::GetCreature(*me, m_uiGraufGUID) == NULL) && !me->IsMounted()) me->SummonCreature(NPC_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f); instance->SetBossState(DATA_SKADI_THE_RUTHLESS, NOT_STARTED); diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index 1e020edd10a..3d801cc2fbb 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -712,7 +712,7 @@ enum BorrowedTechnologyAndVolatility SPELL_PING_BUNNY = 59375, SPELL_IMMOLATION = 54690, SPELL_EXPLOSION = 59335, - SPELL_RIDE = 56687, + SPELL_RIDE = 59319, // Points POINT_GRAB_DECOY = 1, diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 7902c585509..3c651e10a1e 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -745,7 +745,7 @@ public: if (!Trigger) return; - Trigger->SetSpeed(MOVE_WALK, 3); + Trigger->SetSpeedRate(MOVE_WALK, 3); Trigger->SetWalk(true); Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z); @@ -1524,7 +1524,7 @@ public: void BeginWalk() { me->SetWalk(false); - me->SetSpeed(MOVE_RUN, 1.0f); + me->SetSpeedRate(MOVE_RUN, 1.0f); me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index 7e1215488e1..1a9074c2464 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -238,8 +238,8 @@ public: if (me->GetAuraCount(SPELL_SHADE_SOUL_CHANNEL_2) <= 3) { moveSpeed = (2.0f - (0.6f * me->GetAuraCount(SPELL_SHADE_SOUL_CHANNEL_2))); - me->SetSpeed(MOVE_WALK, moveSpeed / 2.5f); - me->SetSpeed(MOVE_RUN, (moveSpeed * 2) / 7); + me->SetSpeedRate(MOVE_WALK, moveSpeed / 2.5f); + me->SetSpeedRate(MOVE_RUN, (moveSpeed * 2) / 7); me->ClearUnitState(UNIT_STATE_ROOT); } else diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp index ae4d17bdad4..0999f1fcd6b 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp @@ -117,7 +117,7 @@ public: DummyEntryCheckPredicate pred; summons.DoAction(EVENT_VOLCANO, pred); events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE); - me->SetSpeed(MOVE_RUN, 1.2f); + me->SetSpeedRate(MOVE_RUN, 1.2f); me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); } @@ -126,7 +126,7 @@ public: phase = PHASE_CHASE; events.ScheduleEvent(EVENT_VOLCANO, 5000, GCD_CAST, PHASE_CHASE); events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE); - me->SetSpeed(MOVE_RUN, 0.9f); + me->SetSpeedRate(MOVE_RUN, 0.9f); me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp index e24499c3aee..3ddf0fec416 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -585,8 +585,8 @@ public: void Reset() override { - me->SetSpeed(MOVE_WALK, 0.6f); // walk - me->SetSpeed(MOVE_RUN, 0.6f); // run + me->SetSpeedRate(MOVE_WALK, 0.6f); // walk + me->SetSpeedRate(MOVE_RUN, 0.6f); // run Initialize(); //search for nearest waypoint (up on stairs) diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp index 8d117f7c3ef..f72b9a8d2ca 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -244,7 +244,7 @@ public: CheckChannelers(); Initialize(); me->SetCanDualWield(true); - me->SetSpeed(MOVE_RUN, 2.0f, true); + me->SetSpeedRate(MOVE_RUN, 2.0f); me->SetDisplayId(MODEL_NIGHTELF); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp new file mode 100644 index 00000000000..c5969c7b15a --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp @@ -0,0 +1,1051 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "CreatureTextMgr.h" +#include "LFGMgr.h" +#include "ScriptedGossip.h" +#include "ScriptedCreature.h" +#include "ScriptMgr.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" +#include "the_slave_pens.h" + +enum Spells +{ + // Ahune + SPELL_SYNCH_HEALTH = 46430, + SPELL_AHUNES_SHIELD = 45954, + SPELL_STAY_SUBMERGED = 46981, + SPELL_AHUNE_SELF_STUN = 46416, + SPELL_AHUNE_ACHIEVEMENT = 62043, + SPELL_AHUNE_SPANKY_HANDS = 46146, + SPELL_COLD_SLAP = 46145, + SPELL_RESURFACE = 46402, + SPELL_SUBMERGED = 37751, + SPELL_STAND = 37752, + + //Earther Ring Flamecaller + SPELL_FIND_OPENING_VISUAL = 45964, + SPELL_FIND_OPENING_BEAM_END = 46333, + SPELL_FIND_OPENING_TRIGGER = 46341, + SPELL_FIND_OPENING_CHANNEL = 46345, + SPELL_BONFIRE_VISUAL = 46339, + SPELL_FOUND_OPENING = 46421, + + //Ahune Bunny + SPELL_SUMMON_COLDWEAVE = 46143, + SPELL_SUMMON_FROSTWIND = 46382, + SPELL_SUMMON_HAILSTONE = 46176, + SPELL_SUMMONING_VISUAL_1 = 45937, + SPELL_SUMMONING_RHYME_AURA = 45926, + SPELL_SUMMONING_RHYME_BONFIRE = 45930, + SPELL_FORCE_WHISP_FLIGHT = 46603, + SPELL_SHAMANS_LOOK_FOR_OPENING = 46422, + SPELL_CLOSE_OPENING_VISUAL = 46236, + SPELL_ICE_BOMBARD = 46397, + SPELL_ICE_BOMBARDMENT_DEST_PICKER = 46398, + SPELL_ICE_BOMBARDMENT = 46396, + + // Ice Spear + SPELL_SUMMON_ICE_SPEAR_BUNNY = 46359, + SPELL_ICE_SPEAR_KNOCKBACK = 46360, + SPELL_SUMMON_ICE_SPEAR_GO = 46369, + SPELL_ICE_SPEAR_AURA = 46371, + SPELL_ICE_SPEAR_TARGET_PICKER = 46372, + SPELL_ICE_SPEAR_DELAY = 46878, + SPELL_ICE_SPEAR_VISUAL = 75498, + + // Slippery Floor + SPELL_SLIPPERY_FLOOR_AMBIENT = 46314, + SPELL_SLIPPERY_FLOOR_PERIODIC = 46320, + SPELL_SLIPPERY_FLOOR_SLIP = 45947, + + // Frozen Core + SPELL_SUICIDE = 45254, + SPELL_SUMMON_LOOT_MISSILE = 45941, + SPELL_FROZEN_CORE_GETS_HIT = 46810, + SPELL_MINION_DESPAWNER = 46843, + SPELL_GHOST_DISGUISE = 46786 +}; + +enum Emotes +{ + EMOTE_EARTHEN_ASSAULT = 0, + EMOTE_RETREAT = 0, + EMOTE_RESURFACE = 1 +}; + +enum Says +{ + SAY_PLAYER_TEXT_1 = 0, + SAY_PLAYER_TEXT_2 = 1, + SAY_PLAYER_TEXT_3 = 2 +}; + +enum Events +{ + EVENT_EMERGE = 1, + EVENT_INITIAL_EMERGE = 2, + EVENT_SYNCH_HEALTH = 3, + EVENT_FOUND_OPENING = 4, + EVENT_LOOKFOROPENING_0 = 5, + EVENT_LOOKFOROPENING_1 = 6, + EVENT_LOOKFOROPENING_2 = 7, + EVENT_SUMMON_HAILSTONE = 8, + EVENT_SUMMON_COLDWEAVE = 9, + EVENT_SUMMON_FROSTWIND = 10, + EVENT_SUMMON_AHUNE = 11, + EVENT_CLOSE_OPENING = 12, + EVENT_AHUNE_PHASE_ONE = 13, + EVENT_AHUNE_PHASE_TWO = 14, + EVENT_START_LOOKING_FOR_OPENING = 15, + EVENT_STOP_LOOKING_FOR_OPENING = 16 +}; + +enum Actions +{ + ACTION_START_EVENT = -2574500, + ACTION_AHUNE_RETREAT = -2586500, + ACTION_AHUNE_RESURFACE = -2586501, + ACTION_EMOTE_RESURFACE = -2575400 +}; + +enum Phases +{ + PHASE_ONE = 0, + PHASE_TWO = 1 +}; + +enum Points +{ + POINT_FLAMECALLER_000, + POINT_FLAMECALLER_001, + POINT_FLAMECALLER_002 +}; + +enum Misc +{ + MAX_FLAMECALLERS = 3 +}; + +Position const SummonPositions[] = +{ + { -99.1021f, -233.7526f, -1.22307f, 1.588250f }, // Ahune + { -98.0151f, -230.4555f, -1.21089f, 1.797689f }, // Frozen Core + { -143.172f, -147.6801f, -3.16113f, 4.852015f }, // Bonfire Bunny 000 + { -134.304f, -145.7803f, -1.70332f, 4.677482f }, // Bonfire Bunny 001 + { -125.036f, -144.2065f, -1.91660f, 4.991642f }, // Bonfire Bunny 002 + { -69.8121f, -162.4954f, -2.30451f, 1.710423f }, // Wisp Source Bunny + { -98.1029f, -230.7864f, -10.8085f, 1.448623f } // Wisp Dest Bunny +}; + +Position const FlameCallerSpots[] = +{ + { -145.2233f, -137.5543f, -1.59056f, 5.427049f }, + { -137.4383f, -136.4050f, -1.72384f, 5.336747f }, + { -129.0413f, -132.1494f, -2.09285f, 5.460842f } +}; + +class boss_ahune : public CreatureScript +{ +public: + boss_ahune() : CreatureScript("boss_ahune") { } + + struct boss_ahuneAI : public BossAI + { + boss_ahuneAI(Creature* creature) : BossAI(creature, DATA_AHUNE) + { + Initialize(); + } + + void Initialize() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + } + + void EnterCombat(Unit* /*who*/) override + { + _EnterCombat(); + events.ScheduleEvent(EVENT_INITIAL_EMERGE, 4); + events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AHUNE_BUNNY))) + ahuneBunny->AI()->EnterEvadeMode(); + summons.DespawnAll(); + me->DespawnOrUnsummon(); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + instance->DoCastSpellOnPlayers(SPELL_AHUNE_ACHIEVEMENT); + + if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AHUNE_BUNNY))) + me->Kill(ahuneBunny); + if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) + me->Kill(frozenCore); + + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (!players.isEmpty()) + { + if (Group* group = players.begin()->GetSource()->GetGroup()) + if (group->isLFGGroup()) + sLFGMgr->FinishDungeon(group->GetGUID(), 286); + } + } + + void JustSummoned(Creature* summon) override + { + BossAI::JustSummoned(summon); + } + + void DoAction(int32 action) override + { + if (action == ACTION_AHUNE_RETREAT) + { + Submerge(); + events.ScheduleEvent(EVENT_EMERGE, 35000); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_INITIAL_EMERGE: + DoCast(me, SPELL_STAND); + DoCast(me, SPELL_AHUNE_SPANKY_HANDS); + DoCast(me, SPELL_AHUNES_SHIELD); + break; + case EVENT_EMERGE: + Emerge(); + break; + case EVENT_SYNCH_HEALTH: + if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) + DoCast(frozenCore, SPELL_SYNCH_HEALTH); + else + DoCast(me, SPELL_SUICIDE); + events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000); + break; + default: + break; + } + } + DoMeleeAttackIfReady(); + } + + void Emerge() + { + if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) + frozenCore->AI()->DoAction(ACTION_AHUNE_RESURFACE); + + DoCast(me, SPELL_AHUNES_SHIELD); + me->RemoveAurasDueToSpell(SPELL_AHUNE_SELF_STUN); + me->RemoveAurasDueToSpell(SPELL_STAY_SUBMERGED); + DoCast(me, SPELL_STAND); + DoCast(me, SPELL_RESURFACE, true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000); + } + + void Submerge() + { + if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE))) + frozenCore->AI()->DoAction(ACTION_AHUNE_RETREAT); + me->RemoveAurasDueToSpell(SPELL_AHUNES_SHIELD); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_SUBMERGED, true); + DoCast(me, SPELL_AHUNE_SELF_STUN, true); + DoCast(me, SPELL_STAY_SUBMERGED, true); + me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); + events.Reset(); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_ahuneAI>(creature); + } +}; + +class npc_frozen_core : public CreatureScript +{ +public: + npc_frozen_core() : CreatureScript("npc_frozen_core") { } + + struct npc_frozen_coreAI : public ScriptedAI + { + npc_frozen_coreAI(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + Initialize(); + } + + void Initialize() + { + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + DoCast(me, SPELL_FROZEN_CORE_GETS_HIT); + DoCast(me, SPELL_ICE_SPEAR_AURA); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + DoCast(SPELL_MINION_DESPAWNER); + if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE))) + ahune->AI()->EnterEvadeMode(); + } + + void JustDied(Unit* /*killer*/) override + { + if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE))) + me->Kill(ahune); + + DoCast(SPELL_SUMMON_LOOT_MISSILE); + DoCast(SPELL_MINION_DESPAWNER); + } + + void DoAction(int32 action) override + { + if (action == ACTION_AHUNE_RETREAT) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); + me->RemoveAurasDueToSpell(SPELL_ICE_SPEAR_AURA); + _events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000, 0, PHASE_TWO); + } + else if (action == ACTION_AHUNE_RESURFACE) + { + _events.Reset(); + DoCast(me, SPELL_ICE_SPEAR_AURA); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SYNCH_HEALTH: + if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE))) + DoCast(ahune, SPELL_SYNCH_HEALTH); + else + DoCast(me, SPELL_SUICIDE); + _events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000); + break; + default: + break; + } + } + } + + private: + InstanceScript* _instance; + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_frozen_coreAI>(creature); + } +}; + +class npc_ahune_bunny : public CreatureScript +{ +public: + npc_ahune_bunny() : CreatureScript("npc_ahune_bunny") { } + + struct npc_ahune_bunnyAI : public ScriptedAI + { + npc_ahune_bunnyAI(Creature* creature) : ScriptedAI(creature), _summons(me) + { + _instance = me->GetInstanceScript(); + _submerged = false; + } + + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() == NPC_AHUNE) + return; + + summon->SetInCombatWithZone(); + _summons.Summon(summon); + } + + void JustDied(Unit* /*killer*/) override + { + _summons.DespawnAll(); + ResetFlameCallers(); + } + + void EnterEvadeMode(EvadeReason /*why*/) override + { + _EnterEvadeMode(); + _summons.DespawnAll(); + ResetFlameCallers(); + + me->SummonGameObject(GO_ICE_STONE, -69.90455f, -162.2449f, -2.366563f, 2.426008f, 0.0f, 0.0f, 0.9366722f, 0.3502074f, 0); + } + + void DoAction(int32 action) override + { + if (action == ACTION_START_EVENT) + { + DoCast(me, SPELL_SUMMONING_VISUAL_1); + me->SummonCreature(NPC_WHISP_SOURCE_BUNNY, SummonPositions[5], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_WHISP_DEST_BUNNY, SummonPositions[6], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_000, SummonPositions[2], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_001, SummonPositions[3], TEMPSUMMON_MANUAL_DESPAWN); + me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_002, SummonPositions[4], TEMPSUMMON_MANUAL_DESPAWN); + + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flameCaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + flameCaller->GetMotionMaster()->MovePoint(counter, FlameCallerSpots[counter].GetPosition()); + + _submerged = false; + _events.Reset(); + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_AHUNE, 10000); + _events.ScheduleEvent(EVENT_START_LOOKING_FOR_OPENING, 14000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, 22000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_HAILSTONE, 14000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_TWO, 108000, 0, PHASE_ONE); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_START_LOOKING_FOR_OPENING: + Talk(EMOTE_EARTHEN_ASSAULT); + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + DoCast(flamecaller, SPELL_SHAMANS_LOOK_FOR_OPENING, true); + break; + case EVENT_SUMMON_HAILSTONE: + DoCast(SPELL_SUMMON_HAILSTONE); + break; + case EVENT_SUMMON_COLDWEAVE: + DoCast(SPELL_SUMMON_COLDWEAVE); + DoCast(SPELL_SUMMON_COLDWEAVE); + _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, 8000, 0, PHASE_ONE); + if (_submerged) + _events.ScheduleEvent(EVENT_SUMMON_FROSTWIND, 4000, 0, PHASE_ONE); + break; + case EVENT_SUMMON_FROSTWIND: + DoCast(SPELL_SUMMON_FROSTWIND); + break; + case EVENT_SUMMON_AHUNE: + if (TempSummon* ahune = me->SummonCreature(NPC_AHUNE, SummonPositions[0], TEMPSUMMON_DEAD_DESPAWN)) + { + ahune->SummonCreature(NPC_FROZEN_CORE, SummonPositions[1], TEMPSUMMON_CORPSE_DESPAWN); + ahune->SetInCombatWithZone(); + DoCast(ahune, SPELL_RESURFACE); + } + break; + case EVENT_CLOSE_OPENING: + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000))) + flamecaller->AI()->DoAction(ACTION_EMOTE_RESURFACE); + DoCast(SPELL_CLOSE_OPENING_VISUAL); + DoCast(me, SPELL_ICE_BOMBARD); + break; + case EVENT_AHUNE_PHASE_TWO: + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000))) + DoCast(flamecaller, SPELL_FOUND_OPENING); + if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE))) + ahune->AI()->DoAction(ACTION_AHUNE_RETREAT); + _events.Reset(); + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_CLOSE_OPENING, 25000, 0, PHASE_TWO); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_ONE, 35000, 0, PHASE_TWO); + break; + case EVENT_AHUNE_PHASE_ONE: + _submerged = true; + _events.Reset(); + _events.SetPhase(PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, 8000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_SUMMON_HAILSTONE, 5000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_START_LOOKING_FOR_OPENING, 5000, 0, PHASE_ONE); + _events.ScheduleEvent(EVENT_AHUNE_PHASE_TWO, 100000, 0, PHASE_ONE); + break; + default: + break; + } + } + } + + void ResetFlameCallers() + { + for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter) + if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter))) + flamecaller->AI()->EnterEvadeMode(); + } + + private: + InstanceScript* _instance; + EventMap _events; + SummonList _summons; + bool _submerged; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_ahune_bunnyAI>(creature); + } +}; + +class npc_earthen_ring_flamecaller : public CreatureScript +{ +public: + npc_earthen_ring_flamecaller() : CreatureScript("npc_earthen_ring_flamecaller") { } + + struct npc_earthen_ring_flamecallerAI : public ScriptedAI + { + npc_earthen_ring_flamecallerAI(Creature* creature) : ScriptedAI(creature) + { + _instance = me->GetInstanceScript(); + } + + void Reset() override + { + _events.Reset(); + } + + void MovementInform(uint32 motionType, uint32 pointId) override + { + if (motionType != POINT_MOTION_TYPE) + return; + + switch (pointId) + { + case POINT_FLAMECALLER_000: + _mySpot = POINT_FLAMECALLER_000; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + case POINT_FLAMECALLER_001: + _mySpot = POINT_FLAMECALLER_001; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + case POINT_FLAMECALLER_002: + _mySpot = POINT_FLAMECALLER_002; + me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation()); + break; + default: + break; + } + + DoCast(me, SPELL_FIND_OPENING_CHANNEL); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override + { + switch (spellInfo->Id) + { + case SPELL_SHAMANS_LOOK_FOR_OPENING: + _events.ScheduleEvent(EVENT_LOOKFOROPENING_0, 17000); + break; + case SPELL_FOUND_OPENING: + _events.ScheduleEvent(EVENT_FOUND_OPENING, 0); + break; + default: + break; + } + } + + void DoAction(int action) override + { + if (action == ACTION_EMOTE_RESURFACE) + Talk(EMOTE_RESURFACE); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_LOOKFOROPENING_0: + LookOpening(true, 0); + _events.ScheduleEvent(EVENT_LOOKFOROPENING_1, 26000); + break; + case EVENT_LOOKFOROPENING_1: + LookOpening(true, 1); + _events.ScheduleEvent(EVENT_LOOKFOROPENING_2, 25000); + break; + case EVENT_LOOKFOROPENING_2: + LookOpening(true, 2); + _events.ScheduleEvent(EVENT_STOP_LOOKING_FOR_OPENING, 27000); + break; + case EVENT_STOP_LOOKING_FOR_OPENING: + LookOpening(false, _mySpot); + break; + case EVENT_FOUND_OPENING: + Talk(EMOTE_RETREAT); + default: + break; + } + } + } + + void LookOpening(bool activate, uint8 spot) + { + if (_mySpot != spot) + return; + + if (Creature* bonfireBunny = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BONFIRE_BUNNY_000 + spot))) + if (Creature* beamBunny = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BEAM_BUNNY_000 + spot))) + { + if (activate) + { + DoCast(bonfireBunny, SPELL_FIND_OPENING_TRIGGER); + bonfireBunny->CastSpell(beamBunny, SPELL_FIND_OPENING_VISUAL, true); + } + else + { + DoCast(me, SPELL_FIND_OPENING_CHANNEL); + bonfireBunny->CastStop(); + beamBunny->RemoveAurasDueToSpell(SPELL_FIND_OPENING_BEAM_END); + } + } + } + + private: + EventMap _events; + InstanceScript* _instance; + uint8 _mySpot; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_earthen_ring_flamecallerAI>(creature); + } +}; + +class go_ahune_ice_stone : public GameObjectScript +{ +public: + go_ahune_ice_stone() : GameObjectScript("go_ahune_ice_stone") { } + + bool OnGossipSelect(Player* player, GameObject* go, uint32 /*sender*/, uint32 /*action*/) + { + InstanceScript* instance = go->GetInstanceScript(); + if (!instance) + return false; + + player->PlayerTalkClass->ClearMenus(); + + if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_AHUNE_BUNNY))) + { + ahuneBunny->AI()->DoAction(ACTION_START_EVENT); + ahuneBunny->SetInCombatWithZone(); + } + if (Creature* luma = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_LUMA_SKYMOTHER))) + luma->CastSpell(player, SPELL_SUMMONING_RHYME_AURA, true); + player->CLOSE_GOSSIP_MENU(); + go->Delete(); + + return true; + } +}; + +// 46430 - Synch Health +class spell_ahune_synch_health : public SpellScriptLoader +{ +public: + spell_ahune_synch_health() : SpellScriptLoader("spell_ahune_synch_health") { } + + class spell_ahune_synch_health_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ahune_synch_health_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SYNCH_HEALTH)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (Unit* caster = GetCaster()) + target->SetHealth(caster->GetHealth()); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ahune_synch_health_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ahune_synch_health_SpellScript(); + } +}; + +// 45926 - Summoning Rhyme Aura +class spell_summoning_rhyme_aura : public SpellScriptLoader +{ +public: + spell_summoning_rhyme_aura() : SpellScriptLoader("spell_summoning_rhyme_aura") { } + + class spell_summoning_rhyme_aura_AuraScript : public AuraScript + { + PrepareAuraScript(spell_summoning_rhyme_aura_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_FORCE_WHISP_FLIGHT) || !sSpellMgr->GetSpellInfo(SPELL_SUMMONING_RHYME_BONFIRE)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* aurEff) + { + Creature* caster = GetCaster()->ToCreature(); + Player* player = GetTarget()->ToPlayer(); + + if (!caster || !player) + return; + + player->CastSpell(player, SPELL_FORCE_WHISP_FLIGHT); + + switch (aurEff->GetTickNumber()) + { + case 1: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_1, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); + player->CastSpell(player, SPELL_SUMMONING_RHYME_BONFIRE, true); + break; + case 2: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_2, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); + break; + case 3: + sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_3, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player); + Remove(); + break; + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summoning_rhyme_aura_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_summoning_rhyme_aura_AuraScript(); + } +}; + +// 46878 - Summon Ice Spear Delayer +class spell_summon_ice_spear_delayer : public SpellScriptLoader +{ +public: + spell_summon_ice_spear_delayer() : SpellScriptLoader("spell_summon_ice_spear_delayer") { } + + class spell_summon_ice_spear_delayer_AuraScript : public AuraScript + { + PrepareAuraScript(spell_summon_ice_spear_delayer_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ICE_SPEAR_GO) || !sSpellMgr->GetSpellInfo(SPELL_ICE_SPEAR_KNOCKBACK)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* aurEff) + { + if (Creature* caster = GetCaster()->ToCreature()) + switch (aurEff->GetTickNumber()) + { + case 1: + caster->CastSpell(caster, SPELL_SUMMON_ICE_SPEAR_GO); + break; + case 3: + if (GameObject* spike = caster->FindNearestGameObject(GO_ICE_SPEAR, 3.0f)) + spike->UseDoorOrButton(); + caster->AI()->DoCastAOE(SPELL_ICE_SPEAR_KNOCKBACK, true); + break; + case 5: + if (GameObject* spike = caster->FindNearestGameObject(GO_ICE_SPEAR, 3.0f)) + spike->Delete(); + caster->DespawnOrUnsummon(); + break; + default: + break; + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_ice_spear_delayer_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_summon_ice_spear_delayer_AuraScript(); + } +}; + +// 46371 - Ice Spear Control Aura +class spell_ice_spear_control_aura : public SpellScriptLoader +{ +public: + spell_ice_spear_control_aura() : SpellScriptLoader("spell_ice_spear_control_aura") { } + + class spell_ice_spear_control_aura_AuraScript : public AuraScript + { + PrepareAuraScript(spell_ice_spear_control_aura_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_ICE_SPEAR_TARGET_PICKER)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, SPELL_ICE_SPEAR_TARGET_PICKER); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ice_spear_control_aura_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_ice_spear_control_aura_AuraScript(); + } +}; + +// 46372 - Ice Spear Target Picker +class spell_ice_spear_target_picker : public SpellScriptLoader +{ +public: + spell_ice_spear_target_picker() : SpellScriptLoader("spell_ice_spear_target_picker") { } + + class spell_ice_spear_target_picker_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ice_spear_target_picker_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ICE_SPEAR_BUNNY)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ICE_SPEAR_BUNNY, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ice_spear_target_picker_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ice_spear_target_picker_SpellScript(); + } +}; + +// 46320 - Spell Slippery Floor Periodic +class spell_slippery_floor_periodic : public SpellScriptLoader +{ +public: + spell_slippery_floor_periodic() : SpellScriptLoader("spell_slippery_floor_periodic") { } + + class spell_slippery_floor_periodic_SpellScript : public SpellScript + { + PrepareSpellScript(spell_slippery_floor_periodic_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SLIPPERY_FLOOR_SLIP)) + return false; + return true; + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + if (target->isMoving()) + target->CastSpell(target, SPELL_SLIPPERY_FLOOR_SLIP, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_slippery_floor_periodic_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_slippery_floor_periodic_SpellScript(); + } +}; + +// 46146 - Ahune Spanky Hands +class spell_ahune_spanky_hands : public SpellScriptLoader +{ +public: + spell_ahune_spanky_hands() : SpellScriptLoader("spell_ahune_spanky_hands") { } + + class spell_ahune_spanky_hands_AuraScript : public AuraScript + { + PrepareAuraScript(spell_ahune_spanky_hands_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_COLD_SLAP)) + return false; + return true; + } + + void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_COLD_SLAP, true); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_ahune_spanky_hands_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_ahune_spanky_hands_AuraScript(); + } +}; + +class spell_ahune_minion_despawner : public SpellScriptLoader +{ +public: + spell_ahune_minion_despawner() : SpellScriptLoader("spell_ahune_minion_despawner") { } + + class spell_ahune_minion_despawner_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ahune_minion_despawner_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (GetHitCreature()) + GetHitCreature()->DespawnOrUnsummon(); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ahune_minion_despawner_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ahune_minion_despawner_SpellScript(); + } +}; + +// 46398 - Spell Ice Bombardment Dest Picker +class spell_ice_bombardment_dest_picker : public SpellScriptLoader +{ +public: + spell_ice_bombardment_dest_picker() : SpellScriptLoader("spell_ice_bombardment_dest_picker") { } + + class spell_ice_bombardment_dest_picker_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ice_bombardment_dest_picker_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_ICE_BOMBARDMENT)) + return false; + return true; + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitDest()->GetPositionX(), GetHitDest()->GetPositionY(), GetHitDest()->GetPositionZ(), SPELL_ICE_BOMBARDMENT, true); + } + + void Register() override + { + OnEffectHit += SpellEffectFn(spell_ice_bombardment_dest_picker_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ice_bombardment_dest_picker_SpellScript(); + } +}; + +void AddSC_boss_ahune() +{ + new boss_ahune(); + new npc_frozen_core(); + new npc_earthen_ring_flamecaller(); + new npc_ahune_bunny(); + new go_ahune_ice_stone(); + new spell_ahune_synch_health(); + new spell_summoning_rhyme_aura(); + new spell_summon_ice_spear_delayer(); + new spell_ice_spear_control_aura(); + new spell_slippery_floor_periodic(); + new spell_ahune_spanky_hands(); + new spell_ahune_minion_despawner(); + new spell_ice_spear_target_picker(); + new spell_ice_bombardment_dest_picker(); +} diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp index 87a07cd1e5e..0fac7b5a39d 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp @@ -31,15 +31,125 @@ class instance_the_slave_pens : public InstanceMapScript public: instance_the_slave_pens() : InstanceMapScript(SPScriptName, 547) { } + struct instance_the_slave_pens_InstanceMapScript : public InstanceScript + { + instance_the_slave_pens_InstanceMapScript(Map* map) : InstanceScript(map) + { + counter = DATA_FLAMECALLER_000; + } + + void OnCreatureCreate(Creature* creature) override + { + switch (creature->GetEntry()) + { + case NPC_AHUNE: + AhuneGUID = creature->GetGUID(); + break; + case NPC_FROZEN_CORE: + FrozenCoreGUID = creature->GetGUID(); + break; + case NPC_AHUNE_LOC_BUNNY: + AhuneBunnyGUID = creature->GetGUID(); + break; + case NPC_SHAMAN_BONFIRE_BUNNY_000: + BonfireBunnyGUIDs[0] = creature->GetGUID(); + break; + case NPC_SHAMAN_BONFIRE_BUNNY_001: + BonfireBunnyGUIDs[1] = creature->GetGUID(); + break; + case NPC_SHAMAN_BONFIRE_BUNNY_002: + BonfireBunnyGUIDs[2] = creature->GetGUID(); + break; + case NPC_SHAMAN_BEAM_BUNNY_000: + BeamBunnyGUIDs[0] = creature->GetGUID(); + break; + case NPC_SHAMAN_BEAM_BUNNY_001: + BeamBunnyGUIDs[1] = creature->GetGUID(); + break; + case NPC_SHAMAN_BEAM_BUNNY_002: + BeamBunnyGUIDs[2] = creature->GetGUID(); + break; + case NPC_LUMA_SKYMOTHER: + LumaGUID = creature->GetGUID(); + break; + case NPC_EARTHEN_RING_FLAMECALLER: + SetGuidData(counter, creature->GetGUID()); + ++counter; + break; + default: + break; + } + } + + void SetGuidData(uint32 data, ObjectGuid guid) override + { + switch (data) + { + case DATA_FLAMECALLER_000: + FlameCallerGUIDs[0] = guid; + break; + case DATA_FLAMECALLER_001: + FlameCallerGUIDs[1] = guid; + break; + case DATA_FLAMECALLER_002: + FlameCallerGUIDs[2] = guid; + break; + default: + break; + } + } + + ObjectGuid GetGuidData(uint32 type) const override + { + switch (type) + { + case DATA_AHUNE: + return AhuneGUID; + case DATA_AHUNE_BUNNY: + return AhuneBunnyGUID; + case DATA_FROZEN_CORE: + return FrozenCoreGUID; + case DATA_FLAMECALLER_000: + return FlameCallerGUIDs[0]; + case DATA_FLAMECALLER_001: + return FlameCallerGUIDs[1]; + case DATA_FLAMECALLER_002: + return FlameCallerGUIDs[2]; + case DATA_BONFIRE_BUNNY_000: + return BonfireBunnyGUIDs[0]; + case DATA_BONFIRE_BUNNY_001: + return BonfireBunnyGUIDs[1]; + case DATA_BONFIRE_BUNNY_002: + return BonfireBunnyGUIDs[2]; + case DATA_BEAM_BUNNY_000: + return BeamBunnyGUIDs[0]; + case DATA_BEAM_BUNNY_001: + return BeamBunnyGUIDs[1]; + case DATA_BEAM_BUNNY_002: + return BeamBunnyGUIDs[2]; + case DATA_LUMA_SKYMOTHER: + return LumaGUID; + default: + break; + } + return ObjectGuid::Empty; + } + + protected: + ObjectGuid AhuneGUID; + ObjectGuid AhuneBunnyGUID; + ObjectGuid FrozenCoreGUID; + ObjectGuid LumaGUID; + ObjectGuid FlameCallerGUIDs[3]; + ObjectGuid BonfireBunnyGUIDs[3]; + ObjectGuid BeamBunnyGUIDs[3]; + uint8 counter; + }; + InstanceScript* GetInstanceScript(InstanceMap* map) const override { return new instance_the_slave_pens_InstanceMapScript(map); } - - struct instance_the_slave_pens_InstanceMapScript : public InstanceScript - { - instance_the_slave_pens_InstanceMapScript(Map* map) : InstanceScript(map) { } - }; }; void AddSC_instance_the_slave_pens() diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h index 95e6e44121e..544e98fd206 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h @@ -27,7 +27,43 @@ enum DataTypes { DATA_MENNU_THE_BETRAYER = 1, DATA_ROKMAR_THE_CRACKLER = 2, - DATA_QUAGMIRRAN = 3 + DATA_QUAGMIRRAN = 3, + DATA_AHUNE = 4, + DATA_AHUNE_BUNNY = 5, + DATA_FROZEN_CORE = 6, + DATA_FLAMECALLER_000 = 7, + DATA_FLAMECALLER_001 = 8, + DATA_FLAMECALLER_002 = 9, + DATA_BONFIRE_BUNNY_000 = 10, + DATA_BONFIRE_BUNNY_001 = 11, + DATA_BONFIRE_BUNNY_002 = 12, + DATA_BEAM_BUNNY_000 = 13, + DATA_BEAM_BUNNY_001 = 14, + DATA_BEAM_BUNNY_002 = 15, + DATA_LUMA_SKYMOTHER = 16 +}; + +enum CreaturesIds +{ + NPC_AHUNE = 25740, + NPC_FROZEN_CORE = 25865, + NPC_LUMA_SKYMOTHER = 25697, + NPC_AHUNE_LOC_BUNNY = 25745, + NPC_EARTHEN_RING_FLAMECALLER = 25754, + NPC_SHAMAN_BONFIRE_BUNNY_000 = 25971, + NPC_SHAMAN_BONFIRE_BUNNY_001 = 25972, + NPC_SHAMAN_BONFIRE_BUNNY_002 = 25973, + NPC_SHAMAN_BEAM_BUNNY_000 = 25964, + NPC_SHAMAN_BEAM_BUNNY_001 = 25965, + NPC_SHAMAN_BEAM_BUNNY_002 = 25966, + NPC_WHISP_DEST_BUNNY = 26120, + NPC_WHISP_SOURCE_BUNNY = 26121 +}; + +enum GameObjectIds +{ + GO_ICE_SPEAR = 188077, + GO_ICE_STONE = 187882 }; #endif // SLAVE_PENS_H diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp index 4e20e6b0953..9b8220596c9 100644 --- a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp @@ -372,7 +372,7 @@ class boss_vazruden_the_herald : public CreatureScript if (summon->GetEntry() == NPC_NAZAN) { summon->SetDisableGravity(true); - summon->SetSpeed(MOVE_FLIGHT, 2.5f); + summon->SetSpeedRate(MOVE_FLIGHT, 2.5f); if (victim) AttackStartNoMove(victim); } diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp index 4faab709e16..c29d560529d 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp @@ -109,7 +109,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript { removeAdds(); _Reset(); - me->SetSpeed(MOVE_RUN, 2); + me->SetSpeedRate(MOVE_RUN, 2); me->SetWalk(false); Initialize(); @@ -231,7 +231,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript { // stop bladedance InBlade = false; - me->SetSpeed(MOVE_RUN, 2); + me->SetSpeedRate(MOVE_RUN, 2); me->GetMotionMaster()->MoveChase(me->GetVictim()); Blade_Dance_Timer = 30000; Wait_Timer = 0; @@ -264,7 +264,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript Wait_Timer = 1; InBlade = true; Blade_Dance_Timer = 0; - me->SetSpeed(MOVE_RUN, 4); + me->SetSpeedRate(MOVE_RUN, 4); return; } else diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index 56010c09897..20d96ecd29c 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -130,7 +130,7 @@ class boss_alar : public CreatureScript _Reset(); me->SetDisplayId(me->GetNativeDisplayId()); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + me->SetSpeedRate(MOVE_RUN, DefaultMoveSpeedRate); //me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); //me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); @@ -178,7 +178,7 @@ class boss_alar : public CreatureScript me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->AttackStop(); me->SetTarget(ObjectGuid::Empty); - me->SetSpeed(MOVE_RUN, 5.0f); + me->SetSpeedRate(MOVE_RUN, 5.0f); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]); } @@ -261,7 +261,7 @@ class boss_alar : public CreatureScript case WE_REVIVE: me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); me->SetFullHealth(); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + me->SetSpeedRate(MOVE_RUN, DefaultMoveSpeedRate); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); DoZoneInCombat(); DoCast(me, SPELL_REBIRTH, true); diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp index 3aa2674aec6..d45e17bd28d 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp @@ -176,7 +176,7 @@ class npc_ragin_flames : public CreatureScript Initialize(); me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); + me->SetSpeedRate(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp index 856649c6c5e..e64c0fe9f5e 100644 --- a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp +++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp @@ -167,7 +167,7 @@ class boss_warp_splinter : public CreatureScript { Initialize(); - me->SetSpeed(MOVE_RUN, 0.7f, true); + me->SetSpeedRate(MOVE_RUN, 0.7f); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Outland/outland_script_loader.cpp b/src/server/scripts/Outland/outland_script_loader.cpp index 91ba4e5689f..ed2c21da6c3 100644 --- a/src/server/scripts/Outland/outland_script_loader.cpp +++ b/src/server/scripts/Outland/outland_script_loader.cpp @@ -72,6 +72,7 @@ void AddSC_instance_the_slave_pens(); void AddSC_boss_mennu_the_betrayer(); void AddSC_boss_rokmar_the_crackler(); void AddSC_boss_quagmirran(); +void AddSC_boss_ahune(); // Coilfang Reservoir - The Underbog void AddSC_instance_the_underbog(); @@ -193,6 +194,7 @@ void AddOutlandScripts() AddSC_boss_mennu_the_betrayer(); AddSC_boss_rokmar_the_crackler(); AddSC_boss_quagmirran(); + AddSC_boss_ahune(); // Coilfang Reservoir - The Underbog AddSC_instance_the_underbog(); diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index 404cdc7ceb2..668c484dd63 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -159,7 +159,7 @@ public: else TC_LOG_ERROR("scripts", "TRINITY: npc_ancestral_wolf can not obtain owner or owner is not a player."); - creature->SetSpeed(MOVE_WALK, 1.5f); + creature->SetSpeedRate(MOVE_WALK, 1.5f); Reset(); } @@ -192,7 +192,7 @@ public: if (ryga->IsAlive() && !ryga->IsInCombat()) { ryga->SetWalk(true); - ryga->SetSpeed(MOVE_WALK, 1.5f); + ryga->SetSpeedRate(MOVE_WALK, 1.5f); ryga->GetMotionMaster()->MovePoint(0, 517.340698f, 3885.03975f, 190.455978f, true); Reset(); } @@ -778,7 +778,7 @@ public: me->AddAura(SPELL_JULES_THREATENS_AURA, me); me->SetCanFly(true); - me->SetSpeed(MOVE_RUN, 0.2f); + me->SetSpeedRate(MOVE_RUN, 0.2f); me->SetFacingTo(3.207566f); me->GetMotionMaster()->MoveJump(exorcismPos[2], 2.0f, 2.0f); @@ -798,7 +798,7 @@ public: break; case ACTION_JULES_MOVE_HOME: wpreached = false; - me->SetSpeed(MOVE_RUN, 1.0f); + me->SetSpeedRate(MOVE_RUN, 1.0f); me->GetMotionMaster()->MovePoint(11, exorcismPos[2]); events.CancelEvent(EVENT_SUMMON_SKULL); diff --git a/src/server/scripts/Outland/zone_shattrath_city.cpp b/src/server/scripts/Outland/zone_shattrath_city.cpp index c734d000077..e4e51a98348 100644 --- a/src/server/scripts/Outland/zone_shattrath_city.cpp +++ b/src/server/scripts/Outland/zone_shattrath_city.cpp @@ -29,7 +29,6 @@ npc_salsalabim npc_shattrathflaskvendors npc_zephyr npc_kservant -npc_ishanah EndContentData */ #include "ScriptMgr.h" @@ -43,13 +42,15 @@ EndContentData */ ## npc_raliq_the_drunk ######*/ -#define GOSSIP_RALIQ "You owe Sim'salabim money. Hand them over or die!" - -enum Raliq +enum RaliqTheDrunk { - SPELL_UPPERCUT = 10966, - QUEST_CRACK_SKULLS = 10009, - FACTION_HOSTILE_RD = 45 + SAY_RALIQ_ATTACK = 0, + OPTION_ID_COLLECT_A_DEBT = 0, + FACTION_OGRE_HOSTILE = 45, + MENU_ID_COLLECT_A_DEBT = 7729, + NPC_TEXT_WUT_YOU_WANT = 9440, + CRACKIN_SOME_SKULLS = 10009, + SPELL_UPPERCUT = 10966 }; class npc_raliq_the_drunk : public CreatureScript @@ -63,7 +64,8 @@ public: if (action == GOSSIP_ACTION_INFO_DEF+1) { player->CLOSE_GOSSIP_MENU(); - creature->setFaction(FACTION_HOSTILE_RD); + creature->setFaction(FACTION_OGRE_HOSTILE); + creature->AI()->Talk(SAY_RALIQ_ATTACK, player); creature->AI()->AttackStart(player); } return true; @@ -71,10 +73,16 @@ public: bool OnGossipHello(Player* player, Creature* creature) override { - if (player->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_RALIQ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(9440, creature->GetGUID()); + if (player->GetQuestStatus(CRACKIN_SOME_SKULLS) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM_DB(MENU_ID_COLLECT_A_DEBT, OPTION_ID_COLLECT_A_DEBT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(NPC_TEXT_WUT_YOU_WANT, creature->GetGUID()); + } + else + { + player->PlayerTalkClass->ClearMenus(); + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); + } return true; } @@ -125,16 +133,14 @@ public: enum Salsalabim { - // Factions - FACTION_HOSTILE_SA = 90, - FACTION_FRIENDLY_SA = 35, - - // Quests - QUEST_10004 = 10004, - - // Spells - SPELL_MAGNETIC_PULL = 31705 - + SAY_DEMONIC_AGGRO = 0, + OPTION_ID_ALTRUIS_SENT_ME = 0, + FACTION_FRIENDLY = 35, + FACTION_DEMON_HOSTILE = 90, + MENU_ID_ALTRUIS_SENT_ME = 7725, + NPC_TEXT_SAL_GROWLS_AT_YOU = 9435, + PATIENCE_AND_UNDERSTANDING = 10004, + SPELL_MAGNETIC_PULL = 31705 }; class npc_salsalabim : public CreatureScript @@ -142,13 +148,26 @@ class npc_salsalabim : public CreatureScript public: npc_salsalabim() : CreatureScript("npc_salsalabim") { } - bool OnGossipHello(Player* player, Creature* creature) override + bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override { - if (player->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE) + player->PlayerTalkClass->ClearMenus(); + if (action == GOSSIP_ACTION_INFO_DEF+1) { - creature->setFaction(FACTION_HOSTILE_SA); + player->CLOSE_GOSSIP_MENU(); + creature->setFaction(FACTION_DEMON_HOSTILE); + creature->AI()->Talk(SAY_DEMONIC_AGGRO, player); creature->AI()->AttackStart(player); } + return true; + } + + bool OnGossipHello(Player* player, Creature* creature) override + { + if (player->GetQuestStatus(PATIENCE_AND_UNDERSTANDING) == QUEST_STATUS_INCOMPLETE) + { + player->ADD_GOSSIP_ITEM_DB(MENU_ID_ALTRUIS_SENT_ME, OPTION_ID_ALTRUIS_SENT_ME, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + player->SEND_GOSSIP_MENU(NPC_TEXT_SAL_GROWLS_AT_YOU, creature->GetGUID()); + } else { if (creature->IsQuestGiver()) @@ -187,7 +206,7 @@ public: { if (done_by->GetTypeId() == TYPEID_PLAYER && me->HealthBelowPctDamaged(20, damage)) { - done_by->ToPlayer()->GroupEventHappens(QUEST_10004, me); + done_by->ToPlayer()->GroupEventHappens(PATIENCE_AND_UNDERSTANDING, me); damage = 0; EnterEvadeMode(); } @@ -220,6 +239,19 @@ Purchase requires exalted reputation with Scryers/Aldor, Cenarion Expedition and ################################################## */ +enum FlaskVendors +{ + ALDOR_REPUTATION = 932, + SCRYERS_REPUTATION = 934, + THE_SHA_TAR_REPUTATION = 935, + CENARION_EXPEDITION_REP = 942, + NPC_TEXT_EXALTED_ALDOR = 11083, // (need to be exalted with Sha'tar, Cenarion Expedition and the Aldor) + NPC_TEXT_EXALTED_SCRYERS = 11084, // (need to be exalted with Sha'tar, Cenarion Expedition and the Scryers) + NPC_TEXT_WELCOME_NAME = 11085, // Access granted + ARCANIST_XORITH = 23483, // Scryer Apothecary + HALDOR_THE_COMPULSIVE = 23484 // Aldor Apothecary +}; + class npc_shattrathflaskvendors : public CreatureScript { public: @@ -236,31 +268,31 @@ public: bool OnGossipHello(Player* player, Creature* creature) override { - if (creature->GetEntry() == 23484) + if (creature->GetEntry() == HALDOR_THE_COMPULSIVE) { // Aldor vendor - if (creature->IsVendor() && (player->GetReputationRank(932) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED)) + if (creature->IsVendor() && (player->GetReputationRank(ALDOR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(THE_SHA_TAR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(CENARION_EXPEDITION_REP) == REP_EXALTED)) { player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - player->SEND_GOSSIP_MENU(11085, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_WELCOME_NAME, creature->GetGUID()); } else { - player->SEND_GOSSIP_MENU(11083, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_EXALTED_ALDOR, creature->GetGUID()); } } - if (creature->GetEntry() == 23483) + if (creature->GetEntry() == ARCANIST_XORITH) { // Scryers vendor - if (creature->IsVendor() && (player->GetReputationRank(934) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED)) + if (creature->IsVendor() && (player->GetReputationRank(SCRYERS_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(THE_SHA_TAR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(CENARION_EXPEDITION_REP) == REP_EXALTED)) { player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE); - player->SEND_GOSSIP_MENU(11085, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_WELCOME_NAME, creature->GetGUID()); } else { - player->SEND_GOSSIP_MENU(11084, creature->GetGUID()); + player->SEND_GOSSIP_MENU(NPC_TEXT_EXALTED_SCRYERS, creature->GetGUID()); } } @@ -272,7 +304,13 @@ public: # npc_zephyr ######*/ -#define GOSSIP_HZ "Take me to the Caverns of Time." +enum Zephyr +{ + OPTION_ID_TAKE_ME_TO_C_O_T = 0, + KEEPERS_OF_TIME_REPUTATION = 989, + MENU_ID_TAKE_ME_TO_C_O_T = 9205, + TELEPORT_CAVERNS_OF_TIME = 37778 +}; class npc_zephyr : public CreatureScript { @@ -283,15 +321,15 @@ public: { player->PlayerTalkClass->ClearMenus(); if (action == GOSSIP_ACTION_INFO_DEF+1) - player->CastSpell(player, 37778, false); + player->CastSpell(player, TELEPORT_CAVERNS_OF_TIME, false); return true; } bool OnGossipHello(Player* player, Creature* creature) override { - if (player->GetReputationRank(989) >= REP_REVERED) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HZ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + if (player->GetReputationRank(KEEPERS_OF_TIME_REPUTATION) >= REP_REVERED) + player->ADD_GOSSIP_ITEM_DB(MENU_ID_TAKE_ME_TO_C_O_T, OPTION_ID_TAKE_ME_TO_C_O_T, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); @@ -305,28 +343,29 @@ public: enum KServant { - SAY1 = 0, - WHISP1 = 1, - WHISP2 = 2, - WHISP3 = 3, - WHISP4 = 4, - WHISP5 = 5, - WHISP6 = 6, - WHISP7 = 7, - WHISP8 = 8, - WHISP9 = 9, - WHISP10 = 10, - WHISP11 = 11, - WHISP12 = 12, - WHISP13 = 13, - WHISP14 = 14, - WHISP15 = 15, - WHISP16 = 16, - WHISP17 = 17, - WHISP18 = 18, - WHISP19 = 19, - WHISP20 = 20, - WHISP21 = 21 + SAY1 = 0, + WHISP1 = 1, + WHISP2 = 2, + WHISP3 = 3, + WHISP4 = 4, + WHISP5 = 5, + WHISP6 = 6, + WHISP7 = 7, + WHISP8 = 8, + WHISP9 = 9, + WHISP10 = 10, + WHISP11 = 11, + WHISP12 = 12, + WHISP13 = 13, + WHISP14 = 14, + WHISP15 = 15, + WHISP16 = 16, + WHISP17 = 17, + WHISP18 = 18, + WHISP19 = 19, + WHISP20 = 20, + WHISP21 = 21, + CITY_OF_LIGHT = 10211 }; class npc_kservant : public CreatureScript @@ -417,7 +456,7 @@ public: break; case 56: Talk(WHISP21, player); - player->GroupEventHappens(10211, me); + player->GroupEventHappens(CITY_OF_LIGHT, me); break; } } @@ -429,7 +468,7 @@ public: return; Player* player = who->ToPlayer(); - if (player && player->GetQuestStatus(10211) == QUEST_STATUS_INCOMPLETE) + if (player && player->GetQuestStatus(CITY_OF_LIGHT) == QUEST_STATUS_INCOMPLETE) { float Radius = 10.0f; if (me->IsWithinDistInMap(who, Radius)) @@ -443,43 +482,6 @@ public: }; }; -/*###### -# npc_ishanah -######*/ - -#define ISANAH_GOSSIP_1 "Who are the Sha'tar?" -#define ISANAH_GOSSIP_2 "Isn't Shattrath a draenei city? Why do you allow others here?" - -class npc_ishanah : public CreatureScript -{ -public: - npc_ishanah() : CreatureScript("npc_ishanah") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - player->SEND_GOSSIP_MENU(9458, creature->GetGUID()); - else if (action == GOSSIP_ACTION_INFO_DEF+2) - player->SEND_GOSSIP_MENU(9459, creature->GetGUID()); - - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - - return true; - } -}; - void AddSC_shattrath_city() { new npc_raliq_the_drunk(); @@ -487,5 +489,4 @@ void AddSC_shattrath_city() new npc_shattrathflaskvendors(); new npc_zephyr(); new npc_kservant(); - new npc_ishanah(); } diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp index 80b3a00774b..113b14a0d54 100644 --- a/src/server/scripts/Pet/pet_dk.cpp +++ b/src/server/scripts/Pet/pet_dk.cpp @@ -103,8 +103,8 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript //! HACK: Creature's can't have MOVEMENTFLAG_FLYING // Fly Away me->SetCanFly(true); - me->SetSpeed(MOVE_FLIGHT, 0.75f, true); - me->SetSpeed(MOVE_RUN, 0.75f, true); + me->SetSpeedRate(MOVE_FLIGHT, 0.75f); + me->SetSpeedRate(MOVE_RUN, 0.75f); float x = me->GetPositionX() + 20 * std::cos(me->GetOrientation()); float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation()); float z = me->GetPositionZ() + 40; diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 0abff255e4b..84c67bad63b 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -201,6 +201,55 @@ class spell_item_blessing_of_ancient_kings : public SpellScriptLoader } }; +// 47770 - Roll Dice +class spell_item_decahedral_dwarven_dice : public SpellScriptLoader +{ + public: + spell_item_decahedral_dwarven_dice() : SpellScriptLoader("spell_item_decahedral_dwarven_dice") { } + + class spell_item_decahedral_dwarven_dice_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_decahedral_dwarven_dice_SpellScript); + + enum + { + TEXT_DECAHEDRAL_DWARVEN_DICE = 26147 + }; + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sObjectMgr->GetBroadcastText(TEXT_DECAHEDRAL_DWARVEN_DICE)) + return false; + return true; + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->TextEmote(TEXT_DECAHEDRAL_DWARVEN_DICE, GetHitUnit()); + + static uint32 const minimum = 1; + static uint32 const maximum = 100; + + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_decahedral_dwarven_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_item_decahedral_dwarven_dice_SpellScript(); + } +}; + // 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success // 22999 - Defibrillate (Goblin Jumper Cables XL) have 50% chance on success // 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success @@ -1319,6 +1368,57 @@ class spell_item_underbelly_elixir : public SpellScriptLoader } }; +// 47776 - Roll 'dem Bones +class spell_item_worn_troll_dice : public SpellScriptLoader +{ + public: + spell_item_worn_troll_dice() : SpellScriptLoader("spell_item_worn_troll_dice") { } + + class spell_item_worn_troll_dice_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_worn_troll_dice_SpellScript); + + enum + { + TEXT_WORN_TROLL_DICE = 26152 + }; + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sObjectMgr->GetBroadcastText(TEXT_WORN_TROLL_DICE)) + return false; + return true; + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->TextEmote(TEXT_WORN_TROLL_DICE, GetHitUnit()); + + static uint32 const minimum = 1; + static uint32 const maximum = 6; + + // roll twice + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_worn_troll_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_item_worn_troll_dice_SpellScript(); + } +}; + enum AirRifleSpells { SPELL_AIR_RIFLE_HOLD_VISUAL = 65582, @@ -2682,6 +2782,7 @@ void AddSC_item_spell_scripts() new spell_item_aegis_of_preservation(); new spell_item_arcane_shroud(); new spell_item_blessing_of_ancient_kings(); + new spell_item_decahedral_dwarven_dice(); new spell_item_defibrillate("spell_item_goblin_jumper_cables", 67, SPELL_GOBLIN_JUMPER_CABLES_FAIL); new spell_item_defibrillate("spell_item_goblin_jumper_cables_xl", 50, SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL); new spell_item_defibrillate("spell_item_gnomish_army_knife", 33); @@ -2706,6 +2807,7 @@ void AddSC_item_spell_scripts() new spell_item_six_demon_bag(); new spell_item_the_eye_of_diminution(); new spell_item_underbelly_elixir(); + new spell_item_worn_troll_dice(); new spell_item_red_rider_air_rifle(); new spell_item_create_heart_candy(); diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 3121a18734d..ae761413ca5 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -1707,7 +1707,7 @@ enum Quest13291_13292_13239_13261Data NPC_SKYTALON = 31583, NPC_DECOY = 31578, // Spells - SPELL_RIDE = 56687 + SPELL_RIDE = 59319 }; class spell_q13291_q13292_q13239_q13261_frostbrood_skytalon_grab_decoy : public SpellScriptLoader diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp index 1f89720803d..65dec74414b 100644 --- a/src/server/scripts/World/boss_emerald_dragons.cpp +++ b/src/server/scripts/World/boss_emerald_dragons.cpp @@ -205,7 +205,7 @@ class npc_dream_fog : public CreatureScript } // Seeping fog movement is slow enough for a player to be able to walk backwards and still outpace it me->SetWalk(true); - me->SetSpeed(MOVE_WALK, 0.75f); + me->SetSpeedRate(MOVE_WALK, 0.75f); } else _roamTimer -= diff; diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 2b5553b4bb0..f4d736ac675 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -24,6 +24,7 @@ #include <openssl/crypto.h> #include <boost/asio/io_service.hpp> #include <boost/asio/deadline_timer.hpp> +#include <boost/filesystem/path.hpp> #include <boost/program_options.hpp> #include "Common.h" @@ -53,6 +54,7 @@ #include "AppenderDB.h" using namespace boost::program_options; +namespace fs = boost::filesystem; #ifndef _TRINITY_CORE_CONFIG #define _TRINITY_CORE_CONFIG "worldserver.conf" @@ -90,14 +92,14 @@ void ClearOnlineAccounts(); void ShutdownCLIThread(std::thread* cliThread); void ShutdownThreadPool(std::vector<std::thread>& threadPool); bool LoadRealmInfo(); -variables_map GetConsoleArguments(int argc, char** argv, std::string& cfg_file, std::string& cfg_service); +variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& cfg_service); /// Launch the Trinity server extern int main(int argc, char** argv) { signal(SIGABRT, &Trinity::AbortHandler); - std::string configFile = _TRINITY_CORE_CONFIG; + auto configFile = fs::absolute(_TRINITY_CORE_CONFIG); std::string configService; auto vm = GetConsoleArguments(argc, argv, configFile, configService); @@ -115,7 +117,9 @@ extern int main(int argc, char** argv) #endif std::string configError; - if (!sConfigMgr->LoadInitial(configFile, configError)) + if (!sConfigMgr->LoadInitial(configFile.generic_string(), + std::vector<std::string>(argv, argv + argc), + configError)) { printf("Error in config file: %s\n", configError.c_str()); return 1; @@ -136,7 +140,7 @@ extern int main(int argc, char** argv) TC_LOG_INFO("server.worldserver", " \\/_/\\/_/ \\/_/\\/_/\\/_/\\/_/\\/__/ `/___/> \\"); TC_LOG_INFO("server.worldserver", " C O R E /\\___/"); TC_LOG_INFO("server.worldserver", "http://TrinityCore.org \\/__/\n"); - TC_LOG_INFO("server.worldserver", "Using configuration file %s.", configFile.c_str()); + TC_LOG_INFO("server.worldserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str()); TC_LOG_INFO("server.worldserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); TC_LOG_INFO("server.worldserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100); @@ -571,7 +575,7 @@ void ClearOnlineAccounts() /// @} -variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService) +variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService) { // Silences warning about configService not be used if the OS is not Windows (void)configService; @@ -580,7 +584,8 @@ variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile all.add_options() ("help,h", "print usage message") ("version,v", "print version build info") - ("config,c", value<std::string>(&configFile)->default_value(_TRINITY_CORE_CONFIG), "use <arg> as configuration file") + ("config,c", value<fs::path>(&configFile)->default_value(fs::absolute(_TRINITY_CORE_CONFIG)), + "use <arg> as configuration file") ; #ifdef _WIN32 options_description win("Windows platform specific options"); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index c2694c640c5..1d425e68246 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -3581,6 +3581,7 @@ Appender.DBErrors=2,2,0,DBErrors.log Logger.root=5,Console Server Logger.server=3,Console Server Logger.commands.gm=3,Console GM +Logger.scripts.hotswap=3,Console Server Logger.sql.sql=5,Console DBErrors Logger.sql.updates=3,Console Server Logger.mmaps=3,Server @@ -3623,7 +3624,6 @@ Logger.mmaps=3,Server #Logger.rbac=3,Console Server #Logger.scripts=3,Console Server #Logger.scripts.ai=3,Console Server -#Logger.scripts.hotswap=3,Console Server #Logger.server.authserver=3,Console Server #Logger.spells=3,Console Server #Logger.spells.periodic=3,Console Server |