diff --git a/doc/ScriptCommands.md b/doc/ScriptCommands.md index 021ec577e..d287b5724 100644 --- a/doc/ScriptCommands.md +++ b/doc/ScriptCommands.md @@ -177,15 +177,15 @@ Commands and their parameters TemporaryFactionFlags --------------------- -* `TEMPFACTION_NONE`: 0x00, when no flag is used in temporary faction change, faction will be persistent. It will then require manual change back to default/another faction when changed once -* `TEMPFACTION_RESTORE_RESPAWN`: 0x01, default faction will be restored at respawn -* `TEMPFACTION_RESTORE_COMBAT_STOP`: 0x02, ... at CombatStop() (happens at creature death, at evade or custom script among others) -* `TEMPFACTION_RESTORE_REACH_HOME`: 0x04, ... at reaching home in home movement (evade), if not already done at CombatStop() +* `TEMPFACTION_NONE` = 0x00, // When no flag is used in temporary faction change, faction will be persistent. It will then require manual change back to default/another faction when changed once +* `TEMPFACTION_RESTORE_RESPAWN` = 0x01, // Default faction will be restored at respawn +* `TEMPFACTION_RESTORE_COMBAT_STOP` = 0x02, // ... at CombatStop() (happens at creature death, at evade or custom scripte among others) +* `TEMPFACTION_RESTORE_REACH_HOME` = 0x04, // ... at reaching home in home movement (evade), if not already done at CombatStop() -The next flags allow to remove unit_flags combined with a faction change (also these flags will be reapplied when the faction is changed back) +// The next flags allow to remove unit_flags combined with a faction change (also these flags will be reapplied when the faction is changed back) -* `TEMPFACTION_TOGGLE_NON_ATTACKABLE`: 0x08, remove UNIT_FLAG_NON_ATTACKABLE(0x02) when faction is changed (reapply when temp-faction is removed) -* `TEMPFACTION_TOGGLE_OOC_NOT_ATTACK`: 0x10, remove UNIT_FLAG_OOC_NOT_ATTACKABLE(0x100) when faction is changed (reapply when temp-faction is removed) -* `TEMPFACTION_TOGGLE_PASSIVE` : 0x20, remove UNIT_FLAG_PASSIVE(0x200) -* `TEMPFACTION_TOGGLE_PACIFIED` : 0x40, remove UNIT_FLAG_PACIFIED(0x20000) when faction is changed (reapply when temp-faction is removed) -* `TEMPFACTION_TOGGLE_NOT_SELECTABLE`: 0x80, remove UNIT_FLAG_NOT_SELECTABLE(0x2000000) when faction is changed (reapply when temp-faction is removed) +* `TEMPFACTION_TOGGLE_NON_ATTACKABLE` = 0x08, // Remove UNIT_FLAG_NON_ATTACKABLE(0x02) when faction is changed (reapply when temp-faction is removed) +* `TEMPFACTION_TOGGLE_OOC_NOT_ATTACK` = 0x10, // Remove UNIT_FLAG_OOC_NOT_ATTACKABLE(0x100) when faction is changed (reapply when temp-faction is removed) +* `TEMPFACTION_TOGGLE_PASSIVE` = 0x20, // Remove UNIT_FLAG_PASSIVE(0x200) when faction is changed (reapply when temp-faction is removed) +* `TEMPFACTION_TOGGLE_PACIFIED` = 0x40, // Remove UNIT_FLAG_PACIFIED(0x20000) when faction is changed (reapply when temp-faction is removed) +* `TEMPFACTION_TOGGLE_NOT_SELECTABLE` = 0x80, // Remove UNIT_FLAG_NOT_SELECTABLE(0x2000000) when faction is changed (reapply when temp-faction is removed) \ No newline at end of file diff --git a/src/game/AuctionHouseBot/AuctionHouseBot.cpp b/src/game/AuctionHouseBot/AuctionHouseBot.cpp index d5063714e..6a6b51882 100644 --- a/src/game/AuctionHouseBot/AuctionHouseBot.cpp +++ b/src/game/AuctionHouseBot/AuctionHouseBot.cpp @@ -694,7 +694,7 @@ uint32 AuctionBotBuyer::GetBuyableEntry(AHB_Buyer_Config& config) { config.SameItemInfo.clear(); uint32 count = 0; - time_t Now = time(NULL); + time_t Now = time(nullptr); AuctionHouseObject::AuctionEntryMapBounds bounds = sAuctionMgr.GetAuctionsMap(config.GetHouseType())->GetAuctionsBounds(); for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr) @@ -706,20 +706,21 @@ uint32 AuctionBotBuyer::GetBuyableEntry(AHB_Buyer_Config& config) ItemPrototype const* prototype = item->GetProto(); if (prototype) { - ++config.SameItemInfo[item->GetEntry()].ItemCount; // Structure constructor will make sure Element are correctly initialised if entry is created here. - config.SameItemInfo[item->GetEntry()].BuyPrice = config.SameItemInfo[item->GetEntry()].BuyPrice + (itr->second->buyout / item->GetCount()); - config.SameItemInfo[item->GetEntry()].BidPrice = config.SameItemInfo[item->GetEntry()].BidPrice + (itr->second->startbid / item->GetCount()); - if (itr->second->buyout != 0) + BuyerItemInfo& buyerItem = config.SameItemInfo[item->GetEntry()]; // Structure constructor will make sure Element are correctly initialised if entry is created here. + ++buyerItem.ItemCount; + buyerItem.BuyPrice = buyerItem.BuyPrice + (Aentry->buyout / item->GetCount()); + buyerItem.BidPrice = buyerItem.BidPrice + (Aentry->startbid / item->GetCount()); + if (Aentry->buyout != 0) { - if (itr->second->buyout / item->GetCount() < config.SameItemInfo[item->GetEntry()].MinBuyPrice) - config.SameItemInfo[item->GetEntry()].MinBuyPrice = itr->second->buyout / item->GetCount(); - else if (config.SameItemInfo[item->GetEntry()].MinBuyPrice == 0) - config.SameItemInfo[item->GetEntry()].MinBuyPrice = itr->second->buyout / item->GetCount(); + if (Aentry->buyout / item->GetCount() < buyerItem.MinBuyPrice) + buyerItem.MinBuyPrice = Aentry->buyout / item->GetCount(); + else if (buyerItem.MinBuyPrice == 0) + buyerItem.MinBuyPrice = Aentry->buyout / item->GetCount(); } - if (itr->second->startbid / item->GetCount() < config.SameItemInfo[item->GetEntry()].MinBidPrice) - config.SameItemInfo[item->GetEntry()].MinBidPrice = itr->second->startbid / item->GetCount(); - else if (config.SameItemInfo[item->GetEntry()].MinBidPrice == 0) - config.SameItemInfo[item->GetEntry()].MinBidPrice = itr->second->startbid / item->GetCount(); + if (Aentry->startbid / item->GetCount() < buyerItem.MinBidPrice) + buyerItem.MinBidPrice = Aentry->startbid / item->GetCount(); + else if (buyerItem.MinBidPrice == 0) + buyerItem.MinBidPrice = Aentry->startbid / item->GetCount(); if (!Aentry->owner) { @@ -898,7 +899,7 @@ void AuctionBotBuyer::addNewAuctionBuyerBotBid(AHB_Buyer_Config& config) PrepareListOfEntry(config); - time_t Now = time(NULL); + time_t Now = time(nullptr); uint32 BuyCycles; if (config.CheckedEntry.size() > sAuctionBotConfig.GetItemPerCycleBoost()) { @@ -906,21 +907,22 @@ void AuctionBotBuyer::addNewAuctionBuyerBotBid(AHB_Buyer_Config& config) BASIC_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Boost value used for Buyer! (if this happens often adjust both ItemsPerCycle in ahbot.conf)"); } else - { BuyCycles = sAuctionBotConfig.GetItemPerCycleNormal(); } + BuyCycles = sAuctionBotConfig.GetItemPerCycleNormal(); for (CheckEntryMap::iterator itr = config.CheckedEntry.begin(); itr != config.CheckedEntry.end();) { - AuctionEntry* auction = auctionHouse->GetAuction(itr->second.AuctionId); + BuyerAuctionEval& auctionEval = itr->second; + AuctionEntry* auction = auctionHouse->GetAuction(auctionEval.AuctionId); if (!auction || auction->moneyDeliveryTime) // is auction not active now { DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Entry %u on ah %u doesn't exists, perhaps bought already?", - itr->second.AuctionId, auction->GetHouseId()); + auctionEval.AuctionId, auction->GetHouseId()); config.CheckedEntry.erase(itr++); continue; } - if ((itr->second.LastChecked != 0) && ((Now - itr->second.LastChecked) <= m_CheckInterval)) + if ((auctionEval.LastChecked != 0) && ((Now - auctionEval.LastChecked) <= m_CheckInterval)) { DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: In time interval wait for entry %u!", auction->Id); ++itr; @@ -928,7 +930,7 @@ void AuctionBotBuyer::addNewAuctionBuyerBotBid(AHB_Buyer_Config& config) } if (BuyCycles == 0) - { break; } + break; uint32 MaxChance = 5000; @@ -945,11 +947,10 @@ void AuctionBotBuyer::addNewAuctionBuyerBotBid(AHB_Buyer_Config& config) BasePrice *= item->GetCount(); double MaxBuyablePrice = (BasePrice * config.BuyerPriceRatio) / 100; - BuyerItemInfoMap::iterator sameitem_itr = config.SameItemInfo.find(item->GetEntry()); - uint64 buyoutPrice = auction->buyout / item->GetCount(); + uint32 buyoutPrice = auction->buyout / item->GetCount(); + uint32 bidPrice; + uint32 bidPriceByItem; - uint64 bidPrice; - uint64 bidPriceByItem; if (auction->bid >= auction->startbid) { bidPrice = auction->GetAuctionOutBid(); @@ -963,26 +964,38 @@ void AuctionBotBuyer::addNewAuctionBuyerBotBid(AHB_Buyer_Config& config) double InGame_BuyPrice; double InGame_BidPrice; + uint32 minBidPrice; + uint32 minBuyPrice; + + BuyerItemInfoMap::iterator sameitem_itr = config.SameItemInfo.find(item->GetEntry()); if (sameitem_itr == config.SameItemInfo.end()) { InGame_BuyPrice = 0; InGame_BidPrice = 0; + minBidPrice = 0; + minBuyPrice = 0; } else { - if (sameitem_itr->second.ItemCount == 1) MaxBuyablePrice = MaxBuyablePrice * 5; // if only one item exist can be buyed if the price is high too. - InGame_BuyPrice = sameitem_itr->second.BuyPrice / sameitem_itr->second.ItemCount; - InGame_BidPrice = sameitem_itr->second.BidPrice / sameitem_itr->second.ItemCount; + const BuyerItemInfo& sameBuyerItem = sameitem_itr->second; + + if (sameBuyerItem.ItemCount == 1) + MaxBuyablePrice = MaxBuyablePrice * 5; // if only one item exist can be bought if the price is high too. + + InGame_BuyPrice = sameBuyerItem.BuyPrice / sameBuyerItem.ItemCount; + InGame_BidPrice = sameBuyerItem.BidPrice / sameBuyerItem.ItemCount; + minBidPrice = sameBuyerItem.MinBidPrice; + minBuyPrice = sameBuyerItem.MinBuyPrice; } double MaxBidablePrice = MaxBuyablePrice - (MaxBuyablePrice / 30); // Max Bidable price defined to 70% of max buyable price DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Auction added with data:"); - DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: MaxPrice of Entry %u is %.1fg.", itr->second.AuctionId, MaxBuyablePrice / 10000); + DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: MaxPrice of Entry %u is %.1fg.", auctionEval.AuctionId, MaxBuyablePrice / 10000); DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: GamePrice buy=%.1fg, bid=%.1fg.", InGame_BuyPrice / 10000, InGame_BidPrice / 10000); - DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Minimal price see in AH Buy=" UI64FMTD "g, Bid=" UI64FMTD "g.", - sameitem_itr->second.MinBuyPrice / 10000, sameitem_itr->second.MinBidPrice / 10000); - DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Actual Entry price, Buy=" UI64FMTD "g, Bid=" UI64FMTD "g.", buyoutPrice / 10000, bidPrice / 10000); + DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Minimal price see in AH Buy=%ug, Bid=%ug.", + minBuyPrice / 10000, minBidPrice / 10000); + DEBUG_FILTER_LOG(LOG_FILTER_AHBOT_BUYER, "AHBot: Actual Entry price, Buy=%ug, Bid=%ug.", buyoutPrice / 10000, bidPrice / 10000); if (!auction->owner) // Original auction owner { @@ -990,24 +1003,24 @@ void AuctionBotBuyer::addNewAuctionBuyerBotBid(AHB_Buyer_Config& config) } if (auction->buyout != 0) // Is the item directly buyable? { - if (IsBuyableEntry(buyoutPrice, InGame_BuyPrice, MaxBuyablePrice, sameitem_itr->second.MinBuyPrice, MaxChance, config.FactionChance)) + if (IsBuyableEntry(buyoutPrice, InGame_BuyPrice, MaxBuyablePrice, minBuyPrice, MaxChance, config.FactionChance)) { - if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, sameitem_itr->second.MinBidPrice, MaxChance / 2, config.FactionChance)) + if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, minBidPrice, MaxChance / 2, config.FactionChance)) if (urand(0, 5) == 0) PlaceBidToEntry(auction, bidPrice); else BuyEntry(auction); else - { BuyEntry(auction); } + BuyEntry(auction); } else { - if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, sameitem_itr->second.MinBidPrice, MaxChance / 2, config.FactionChance)) - { PlaceBidToEntry(auction, bidPrice); } + if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, minBidPrice, MaxChance / 2, config.FactionChance)) + PlaceBidToEntry(auction, bidPrice); } } else // buyout = 0 mean only bid are possible - if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, sameitem_itr->second.MinBidPrice, MaxChance, config.FactionChance)) - { PlaceBidToEntry(auction, bidPrice); } + if (IsBidableEntry(bidPriceByItem, InGame_BuyPrice, MaxBidablePrice, minBidPrice, MaxChance, config.FactionChance)) + PlaceBidToEntry(auction, bidPrice); - itr->second.LastChecked = Now; + auctionEval.LastChecked = Now; --BuyCycles; ++itr; @@ -1920,9 +1933,12 @@ void AuctionHouseBot::Rebuild(bool all) { AuctionHouseObject::AuctionEntryMapBounds bounds = sAuctionMgr.GetAuctionsMap(AuctionHouseType(i))->GetAuctionsBounds(); for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr) - if (!itr->second->owner) // ahbot auction - if (all || itr->second->bid == 0) // expire now auction if no bid or forced - itr->second->expireTime = sWorld.GetGameTime(); + { + AuctionEntry* entry = itr->second; + if (!entry->owner) // ahbot auction + if (all || entry->bid == 0) // expire now auction if no bid or forced + entry->expireTime = sWorld.GetGameTime(); + } } } diff --git a/src/game/BattleGround/BattleGround.cpp b/src/game/BattleGround/BattleGround.cpp index 020a3b87d..c5b25ea01 100644 --- a/src/game/BattleGround/BattleGround.cpp +++ b/src/game/BattleGround/BattleGround.cpp @@ -81,7 +81,7 @@ namespace MaNGOS class BattleGroundYellBuilder { public: - BattleGroundYellBuilder(Language language, int32 textId, Creature const* source, va_list* args = nullptr) + BattleGroundYellBuilder(Language language, int32 textId, Creature const* source, va_list* args = NULL) : i_language(language), i_textId(textId), i_source(source), i_args(args) {} void operator()(WorldPacket& data, int32 loc_idx) { @@ -125,13 +125,13 @@ namespace MaNGOS snprintf(str, 2048, text, arg1str, arg2str); ObjectGuid guid; - char const* pName = nullptr; + char const* pName = NULL; if (i_source) { guid = i_source->GetObjectGuid(); pName = i_source->GetName(); } - ChatHandler::BuildChatPacket(data, i_msgtype, str, LANG_UNIVERSAL, CHAT_TAG_NONE, ObjectGuid(), nullptr, guid, pName); + ChatHandler::BuildChatPacket(data, i_msgtype, str, LANG_UNIVERSAL, CHAT_TAG_NONE, ObjectGuid(), NULL, guid, pName); } private: ChatMsg i_msgtype; @@ -997,6 +997,7 @@ void BattleGround::RemovePlayerAtLeave(ObjectGuid guid, bool Transport, bool Sen plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); plr->RemoveAurasDueToSpell(isArena() ? SPELL_ARENA_DAMPENING : SPELL_BATTLEGROUND_DAMPENING); + plr->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); if (!plr->IsAlive()) // resurrect on exit { @@ -1313,11 +1314,12 @@ void BattleGround::RemoveFromBGFreeSlotQueue() { // set to be able to re-add if needed m_InBGFreeSlotQueue = false; - for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr) + BGFreeSlotQueueType& bgFreeSlot = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID]; + for (BGFreeSlotQueueType::iterator itr = bgFreeSlot.begin(); itr != bgFreeSlot.end(); ++itr) { if ((*itr)->GetInstanceID() == GetInstanceID()) { - sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].erase(itr); + bgFreeSlot.erase(itr); return; } } diff --git a/src/game/BattleGround/BattleGround.h b/src/game/BattleGround/BattleGround.h index 0c2baefcc..ecd48432e 100644 --- a/src/game/BattleGround/BattleGround.h +++ b/src/game/BattleGround/BattleGround.h @@ -491,6 +491,12 @@ class BattleGround // Process Capture event virtual bool HandleEvent(uint32 /*eventId*/, GameObject* /*go*/) { return false; } + // Called when a creature is created + virtual void HandleCreatureCreate(Creature* /*creature*/) {} + + // handle capture objective complete + virtual void HandleObjectiveComplete(uint32 /*eventId*/, const std::list& /*players*/, Team /*team*/) {} + // Called when a gameobject is created virtual void HandleGameObjectCreate(GameObject* /*go*/) {} diff --git a/src/game/BattleGround/BattleGroundBE.cpp b/src/game/BattleGround/BattleGroundBE.cpp index c5b00b35f..69d3a3c42 100644 --- a/src/game/BattleGround/BattleGroundBE.cpp +++ b/src/game/BattleGround/BattleGroundBE.cpp @@ -92,7 +92,7 @@ void BattleGroundBE::HandleKillPlayer(Player* player, Player* killer) bool BattleGroundBE::HandlePlayerUnderMap(Player* player) { - player->TeleportTo(GetMapId(), 6238.930176f, 262.963470f, 0.889519f, player->GetOrientation(), false); + player->TeleportTo(GetMapId(), 6238.930176f, 262.963470f, 0.889519f, player->GetOrientation()); return true; } diff --git a/src/game/BattleGround/BattleGroundMgr.cpp b/src/game/BattleGround/BattleGroundMgr.cpp index 23915cba8..d415f30d3 100644 --- a/src/game/BattleGround/BattleGroundMgr.cpp +++ b/src/game/BattleGround/BattleGroundMgr.cpp @@ -1437,7 +1437,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket* data, BattleGround* bg) if (bg->isArena()) { // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H - for (int8 i = 0; i < BG_TEAMS_COUNT; ++i) + for (int8 i = 0; i < PVP_TEAM_COUNT; ++i) { if (ArenaTeam* at = sObjectMgr.GetArenaTeamById(bg->m_ArenaTeamIds[i])) data->WriteBits(at->GetName().length(), 8); @@ -1451,6 +1451,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket* data, BattleGround* bg) { ObjectGuid memberGuid = itr->first; Player* player = sObjectMgr.GetPlayer(itr->first); + const BattleGroundScore* score = itr->second; data->WriteBit(0); // unk1 data->WriteBit(0); // unk2 @@ -1466,18 +1467,18 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket* data, BattleGround* bg) data->WriteBit(team == ALLIANCE); // unk7 data->WriteGuidMask<7>(memberGuid); - buffer << uint32(itr->second->HealingDone); // healing done - buffer << uint32(itr->second->DamageDone); // damage done + buffer << uint32(score->HealingDone); // healing done + buffer << uint32(score->DamageDone); // damage done if (!bg->isArena()) { - buffer << uint32(itr->second->BonusHonor); - buffer << uint32(itr->second->Deaths); - buffer << uint32(itr->second->HonorableKills); + buffer << uint32(score->BonusHonor); + buffer << uint32(score->Deaths); + buffer << uint32(score->HonorableKills); } buffer.WriteGuidBytes<4>(memberGuid); - buffer << uint32(itr->second->KillingBlows); + buffer << uint32(score->KillingBlows); // if (unk5) << uint32() unk buffer.WriteGuidBytes<5>(memberGuid); // if (unk6) << uint32() unk @@ -1493,25 +1494,25 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket* data, BattleGround* bg) { case BATTLEGROUND_AV: data->WriteBits(5, 24); // count of next fields - buffer << uint32(((BattleGroundAVScore*)itr->second)->GraveyardsAssaulted); // GraveyardsAssaulted - buffer << uint32(((BattleGroundAVScore*)itr->second)->GraveyardsDefended); // GraveyardsDefended - buffer << uint32(((BattleGroundAVScore*)itr->second)->TowersAssaulted); // TowersAssaulted - buffer << uint32(((BattleGroundAVScore*)itr->second)->TowersDefended); // TowersDefended - buffer << uint32(((BattleGroundAVScore*)itr->second)->SecondaryObjectives); // SecondaryObjectives - free some of the Lieutnants + buffer << uint32(((BattleGroundAVScore*)score)->GraveyardsAssaulted); // GraveyardsAssaulted + buffer << uint32(((BattleGroundAVScore*)score)->GraveyardsDefended); // GraveyardsDefended + buffer << uint32(((BattleGroundAVScore*)score)->TowersAssaulted); // TowersAssaulted + buffer << uint32(((BattleGroundAVScore*)score)->TowersDefended); // TowersDefended + buffer << uint32(((BattleGroundAVScore*)score)->SecondaryObjectives); // SecondaryObjectives - free some of the Lieutnants break; case BATTLEGROUND_WS: data->WriteBits(2, 24); // count of next fields - buffer << uint32(((BattleGroundWGScore*)itr->second)->FlagCaptures); // flag captures - buffer << uint32(((BattleGroundWGScore*)itr->second)->FlagReturns); // flag returns + buffer << uint32(((BattleGroundWGScore*)score)->FlagCaptures); // flag captures + buffer << uint32(((BattleGroundWGScore*)score)->FlagReturns); // flag returns break; case BATTLEGROUND_AB: data->WriteBits(2, 24); // count of next fields - buffer << uint32(((BattleGroundABScore*)itr->second)->BasesAssaulted); // bases asssulted - buffer << uint32(((BattleGroundABScore*)itr->second)->BasesDefended); // bases defended + buffer << uint32(((BattleGroundABScore*)score)->BasesAssaulted); // bases asssulted + buffer << uint32(((BattleGroundABScore*)score)->BasesDefended); // bases defended break; case BATTLEGROUND_EY: data->WriteBits(1, 24); // count of next fields - buffer << uint32(((BattleGroundEYScore*)itr->second)->FlagCaptures); // flag captures + buffer << uint32(((BattleGroundEYScore*)score)->FlagCaptures); // flag captures break; case BATTLEGROUND_NA: case BATTLEGROUND_BE: @@ -1541,7 +1542,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket* data, BattleGround* bg) if (bg->isRated()) // arena { - for (int8 i = 0; i < BG_TEAMS_COUNT; ++i) + for (int8 i = 0; i < PVP_TEAM_COUNT; ++i) { uint32 pointsLost = bg->m_ArenaTeamRatingChanges[i] < 0 ? abs(bg->m_ArenaTeamRatingChanges[i]) : 0; uint32 pointsGained = bg->m_ArenaTeamRatingChanges[i] > 0 ? bg->m_ArenaTeamRatingChanges[i] : 0; @@ -1558,7 +1559,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket* data, BattleGround* bg) if (bg->isArena()) { - for (int8 i = 0; i < BG_TEAMS_COUNT; ++i) + for (int8 i = 0; i < PVP_TEAM_COUNT; ++i) { if (ArenaTeam* at = sObjectMgr.GetArenaTeamById(bg->m_ArenaTeamIds[i])) data->append(at->GetName().data(), at->GetName().length()); @@ -1902,15 +1903,17 @@ void BattleGroundMgr::CreateInitialBattleGrounds() uint32 MinPlayersPerTeam = fields[1].GetUInt32(); uint32 MaxPlayersPerTeam = fields[2].GetUInt32(); - // check values from DB - if (MaxPlayersPerTeam == 0 || MinPlayersPerTeam == 0) + if (MaxPlayersPerTeam == 0) { - sLog.outErrorDb("Table `battleground_template` for id %u have wrong min/max players per team settings. BG not created.", bgTypeID); + sLog.outErrorDb("Table `battleground_template` for id %u doesn't allow any player per team settings. BG not created.", bgTypeID); continue; } if (MinPlayersPerTeam > MaxPlayersPerTeam) + { MinPlayersPerTeam = MaxPlayersPerTeam; + sLog.outErrorDb("Table `battleground_template` for id %u has min players > max players per team settings. Min players will use same value as max players.", bgTypeID); + } float AStartLoc[4]; float HStartLoc[4]; diff --git a/src/game/BattleGround/BattleGroundNA.cpp b/src/game/BattleGround/BattleGroundNA.cpp index 2665014e9..7162224d4 100644 --- a/src/game/BattleGround/BattleGroundNA.cpp +++ b/src/game/BattleGround/BattleGroundNA.cpp @@ -93,7 +93,7 @@ void BattleGroundNA::HandleKillPlayer(Player* player, Player* killer) bool BattleGroundNA::HandlePlayerUnderMap(Player* player) { - player->TeleportTo(GetMapId(), 4055.504395f, 2919.660645f, 13.611241f, player->GetOrientation(), false); + player->TeleportTo(GetMapId(), 4055.504395f, 2919.660645f, 13.611241f, player->GetOrientation()); return true; } diff --git a/src/game/BattleGround/BattleGroundRL.cpp b/src/game/BattleGround/BattleGroundRL.cpp index a501ffc02..57cf014ff 100644 --- a/src/game/BattleGround/BattleGroundRL.cpp +++ b/src/game/BattleGround/BattleGroundRL.cpp @@ -92,7 +92,7 @@ void BattleGroundRL::HandleKillPlayer(Player* player, Player* killer) bool BattleGroundRL::HandlePlayerUnderMap(Player* player) { - player->TeleportTo(GetMapId(), 1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation(), false); + player->TeleportTo(GetMapId(), 1285.810547f, 1667.896851f, 39.957642f, player->GetOrientation()); return true; } diff --git a/src/game/ChatCommands/Level0.cpp b/src/game/ChatCommands/Level0.cpp index dbd886f8e..ee11a66a9 100644 --- a/src/game/ChatCommands/Level0.cpp +++ b/src/game/ChatCommands/Level0.cpp @@ -125,7 +125,7 @@ bool ChatHandler::HandleServerInfoCommand(char* /*args*/) bool ChatHandler::HandleDismountCommand(char* /*args*/) { Player* player = m_session->GetPlayer(); - + // If player is not mounted, so go out :) if (!player->IsMounted()) { @@ -175,10 +175,11 @@ bool ChatHandler::HandleGMListIngameCommand(char* /*args*/) HashMapHolder::MapType& m = sObjectAccessor.GetPlayers(); for (HashMapHolder::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { - AccountTypes itr_sec = itr->second->GetSession()->GetSecurity(); - if ((itr->second->isGameMaster() || (itr_sec > SEC_PLAYER && itr_sec <= (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_GM_LIST))) && - (!m_session || itr->second->IsVisibleGloballyFor(m_session->GetPlayer()))) - { names.push_back(std::make_pair(GetNameLink(itr->second), itr->second->isAcceptWhispers())); } + Player* player = itr->second; + AccountTypes security = player->GetSession()->GetSecurity(); + if ((player->isGameMaster() || (security > SEC_PLAYER && security <= (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_GM_LIST))) && + (!m_session || player->IsVisibleGloballyFor(m_session->GetPlayer()))) + names.push_back(std::make_pair(GetNameLink(player), player->isAcceptWhispers())); } } @@ -189,10 +190,10 @@ bool ChatHandler::HandleGMListIngameCommand(char* /*args*/) char const* accepts = GetMangosString(LANG_GM_ACCEPTS_WHISPER); char const* not_accept = GetMangosString(LANG_GM_NO_WHISPER); for (std::list >::const_iterator iter = names.begin(); iter != names.end(); ++iter) - { PSendSysMessage("%s - %s", iter->first.c_str(), iter->second ? accepts : not_accept); } + PSendSysMessage("%s - %s", iter->first.c_str(), iter->second ? accepts : not_accept); } else - { SendSysMessage(LANG_GMS_NOT_LOGGED); } + SendSysMessage(LANG_GMS_NOT_LOGGED); return true; } diff --git a/src/game/ChatCommands/Level1.cpp b/src/game/ChatCommands/Level1.cpp index 916a8b9b9..c679c8b5e 100644 --- a/src/game/ChatCommands/Level1.cpp +++ b/src/game/ChatCommands/Level1.cpp @@ -383,8 +383,8 @@ bool ChatHandler::HandleSummonCommand(char* args) if (!ExtractPlayerTarget(&args, &target, &target_guid, &target_name)) return false; - Player* _player = m_session->GetPlayer(); - if (target == _player || target_guid == _player->GetObjectGuid()) + Player* player = m_session->GetPlayer(); + if (target == player || target_guid == player->GetObjectGuid()) { PSendSysMessage(LANG_CANT_TELEPORT_SELF); SetSentErrorMessage(true); @@ -405,7 +405,7 @@ bool ChatHandler::HandleSummonCommand(char* args) return false; } - Map* pMap = m_session->GetPlayer()->GetMap(); + Map* pMap = player->GetMap(); if (pMap->IsBattleGroundOrArena()) { @@ -442,9 +442,9 @@ bool ChatHandler::HandleSummonCommand(char* args) } // we are in instance, and can summon only player in our group with us as lead - if (!m_session->GetPlayer()->GetGroup() || !target->GetGroup() || - (target->GetGroup()->GetLeaderGuid() != m_session->GetPlayer()->GetObjectGuid()) || - (m_session->GetPlayer()->GetGroup()->GetLeaderGuid() != m_session->GetPlayer()->GetObjectGuid())) + if (!player->GetGroup() || !target->GetGroup() || + (target->GetGroup()->GetLeaderGuid() != player->GetObjectGuid()) || + (player->GetGroup()->GetLeaderGuid() != player->GetObjectGuid())) // the last check is a bit excessive, but let it be, just in case { PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, nameLink.c_str()); @@ -455,7 +455,7 @@ bool ChatHandler::HandleSummonCommand(char* args) PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), ""); if (needReportToTarget(target)) - ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(_player->GetName()).c_str()); + ChatHandler(target).PSendSysMessage(LANG_SUMMONED_BY, playerLink(player->GetName()).c_str()); // stop flight if need if (target->IsTaxiFlying()) @@ -483,12 +483,12 @@ bool ChatHandler::HandleSummonCommand(char* args) PSendSysMessage(LANG_SUMMONING, nameLink.c_str(), GetMangosString(LANG_OFFLINE)); // in point where GM stay - Player::SavePositionInDB(target_guid, m_session->GetPlayer()->GetMapId(), - m_session->GetPlayer()->GetPositionX(), - m_session->GetPlayer()->GetPositionY(), - m_session->GetPlayer()->GetPositionZ(), - m_session->GetPlayer()->GetOrientation(), - m_session->GetPlayer()->GetZoneId()); + Player::SavePositionInDB(target_guid, player->GetMapId(), + player->GetPositionX(), + player->GetPositionY(), + player->GetPositionZ(), + player->GetOrientation(), + player->GetZoneId()); } return true; @@ -1984,13 +1984,14 @@ bool ChatHandler::HandleGroupgoCommand(char* args) return false; } - Map* gmMap = m_session->GetPlayer()->GetMap(); + Player* player = m_session->GetPlayer(); + Map* gmMap = player->GetMap(); bool to_instance = gmMap->Instanceable(); // we are in instance, and can summon only player in our group with us as lead if (to_instance && ( - !m_session->GetPlayer()->GetGroup() || (grp->GetLeaderGuid() != m_session->GetPlayer()->GetObjectGuid()) || - (m_session->GetPlayer()->GetGroup()->GetLeaderGuid() != m_session->GetPlayer()->GetObjectGuid()))) + !player->GetGroup() || (grp->GetLeaderGuid() != player->GetObjectGuid()) || + (player->GetGroup()->GetLeaderGuid() != player->GetObjectGuid()))) // the last check is a bit excessive, but let it be, just in case { SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); @@ -1998,7 +1999,7 @@ bool ChatHandler::HandleGroupgoCommand(char* args) return false; } - for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + for (GroupReference* itr = grp->GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* pl = itr->getSource(); diff --git a/src/game/ChatCommands/Level2.cpp b/src/game/ChatCommands/Level2.cpp index 9f689ed88..f88be755b 100644 --- a/src/game/ChatCommands/Level2.cpp +++ b/src/game/ChatCommands/Level2.cpp @@ -48,7 +48,9 @@ #include "GMTicketMgr.h" #include "WaypointManager.h" #include "Util.h" -#include "PhaseMgr.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "WaypointMovementGenerator.h" #include #include #include @@ -834,7 +836,7 @@ bool ChatHandler::HandleGameObjectTargetCommand(char* args) result = WorldDatabase.PQuery("SELECT gameobject.guid, id, position_x, position_y, position_z, orientation, map, " "(POW(position_x - %f, 2) + POW(position_y - %f, 2) + POW(position_z - %f, 2)) AS order_ FROM gameobject " "LEFT OUTER JOIN game_event_gameobject on gameobject.guid=game_event_gameobject.guid WHERE map = '%i' %s ORDER BY order_ ASC LIMIT 10", - m_session->GetPlayer()->GetPositionX(), m_session->GetPlayer()->GetPositionY(), m_session->GetPlayer()->GetPositionZ(), m_session->GetPlayer()->GetMapId(), eventFilter.str().c_str()); + pl->GetPositionX(), pl->GetPositionY(), pl->GetPositionZ(), pl->GetMapId(), eventFilter.str().c_str()); } if (!result) @@ -1107,7 +1109,7 @@ bool ChatHandler::HandleGameObjectAddCommand(char* args) } GameObject* pGameObj = new GameObject; - if (!pGameObj->Create(db_lowGUID, gInfo->id, map, plr->GetPhaseMgr()->GetPhaseMaskForSpawn(), x, y, z, o)) + if (!pGameObj->Create(db_lowGUID, gInfo->id, map, plr->GetPhaseMaskForSpawn(), x, y, z, o)) { delete pGameObj; return false; @@ -1117,7 +1119,7 @@ bool ChatHandler::HandleGameObjectAddCommand(char* args) pGameObj->SetRespawnTime(spawntimeSecs); // fill the gameobject data and save to the db - pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), plr->GetPhaseMgr()->GetPhaseMaskForSpawn()); + pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), plr->GetPhaseMaskForSpawn()); // this will generate a new guid if the object is in an instance if (!pGameObj->LoadFromDB(db_lowGUID, map)) @@ -1596,8 +1598,8 @@ bool ChatHandler::HandleNpcAddCommand(char* args) delete pCreature; return false; } - - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); + + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); uint32 db_guid = pCreature->GetGUIDLow(); @@ -1790,57 +1792,6 @@ bool ChatHandler::HandleNpcAIInfoCommand(char* /*args*/) return true; } -// add move for creature -bool ChatHandler::HandleNpcAddMoveCommand(char* args) -{ - uint32 lowguid; - if (!ExtractUint32KeyFromLink(&args, "Hcreature", lowguid)) - return false; - - uint32 wait; - if (!ExtractOptUInt32(&args, wait, 0)) - return false; - - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - Player* player = m_session->GetPlayer(); - - if (player->GetMapId() != data->mapid) - { - PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); - SetSentErrorMessage(true); - return false; - } - - Creature* pCreature = player->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - - sWaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0); - - // update movement type - WorldDatabase.PExecuteLog("UPDATE creature SET MovementType=%u WHERE guid=%u", WAYPOINT_MOTION_TYPE, lowguid); - if (pCreature) - { - pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); - pCreature->GetMotionMaster()->Initialize(); - if (pCreature->IsAlive()) // dead creature will reset movement generator at respawn - { - pCreature->SetDeathState(JUST_DIED); - pCreature->Respawn(); - } - pCreature->SaveToDB(); - } - - SendSysMessage(LANG_WAYPOINT_ADDED); - - return true; -} - // change level of creature or pet bool ChatHandler::HandleNpcChangeLevelCommand(char* args) { @@ -1967,9 +1918,9 @@ bool ChatHandler::HandleNpcDeleteCommand(char* args) bool ChatHandler::HandleNpcMoveCommand(char* args) { uint32 lowguid = 0; + Player* player = m_session->GetPlayer(); Creature* pCreature = getSelectedCreature(); - if (!pCreature) { // number or [name] Shift-click form |color|Hcreature:creature_guid|h[name]|h|r @@ -1984,8 +1935,6 @@ bool ChatHandler::HandleNpcMoveCommand(char* args) return false; } - Player* player = m_session->GetPlayer(); - if (player->GetMapId() != data->mapid) { PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); @@ -1998,10 +1947,10 @@ bool ChatHandler::HandleNpcMoveCommand(char* args) else lowguid = pCreature->GetGUIDLow(); - float x = m_session->GetPlayer()->GetPositionX(); - float y = m_session->GetPlayer()->GetPositionY(); - float z = m_session->GetPlayer()->GetPositionZ(); - float o = m_session->GetPlayer()->GetOrientation(); + float x = player->GetPositionX(); + float y = player->GetPositionY(); + float z = player->GetPositionZ(); + float o = player->GetOrientation(); if (pCreature) { @@ -2269,6 +2218,7 @@ bool ChatHandler::HandleNpcFollowCommand(char* /*args*/) PSendSysMessage(LANG_CREATURE_FOLLOW_YOU_NOW, creature->GetName()); return true; } + // npc unfollow handling bool ChatHandler::HandleNpcUnFollowCommand(char* /*args*/) { @@ -2282,30 +2232,31 @@ bool ChatHandler::HandleNpcUnFollowCommand(char* /*args*/) return false; } - if (creature->GetMotionMaster()->empty() || - creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != FOLLOW_MOTION_TYPE) + MotionMaster* creatureMotion = creature->GetMotionMaster(); + if (creatureMotion->empty() || + creatureMotion->GetCurrentMovementGeneratorType() != FOLLOW_MOTION_TYPE) { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName()); SetSentErrorMessage(true); return false; } - FollowMovementGenerator const* mgen - = static_cast const*>((creature->GetMotionMaster()->top())); + FollowMovementGenerator const* mgen = static_cast const*>(creatureMotion->top()); if (mgen->GetTarget() != player) { - PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU); + PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU, creature->GetName()); SetSentErrorMessage(true); return false; } // reset movement - creature->GetMotionMaster()->MovementExpired(true); + creatureMotion->MovementExpired(true); PSendSysMessage(LANG_CREATURE_NOT_FOLLOW_YOU_NOW, creature->GetName()); return true; } + // npc tame handling bool ChatHandler::HandleNpcTameCommand(char* /*args*/) { @@ -2494,7 +2445,7 @@ bool ChatHandler::HandleItemMoveCommand(char* args) if (!pParam1) return false; - char* pParam2 = strtok(NULL, " "); + char* pParam2 = strtok(nullptr, " "); if (!pParam2) return false; @@ -2504,17 +2455,18 @@ bool ChatHandler::HandleItemMoveCommand(char* args) if (srcslot == dstslot) return true; - if (!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true)) + Player* player = m_session->GetPlayer(); + if (!player->IsValidPos(INVENTORY_SLOT_BAG_0, srcslot, true)) return false; // can be autostore pos - if (!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0, dstslot, false)) + if (!player->IsValidPos(INVENTORY_SLOT_BAG_0, dstslot, false)) return false; uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - m_session->GetPlayer()->SwapItem(src, dst); + player->SwapItem(src, dst); return true; } @@ -2605,10 +2557,7 @@ bool ChatHandler::HandleModifyPhaseCommand(char* args) else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target)) return false; - if (target->GetTypeId() == TYPEID_PLAYER) - ((Player*)target)->GetPhaseMgr()->SetCustomPhase(phasemask); - else - target->SetPhaseMask(phasemask,true); + target->SetPhaseMask(phasemask, true); return true; } @@ -2926,6 +2875,49 @@ bool ChatHandler::HandleDelTicketCommand(char* args) return true; } +/// Helper function +inline Creature* Helper_CreateWaypointFor(Creature* wpOwner, WaypointPathOrigin wpOrigin, int32 pathId, uint32 wpId, WaypointNode const* wpNode, CreatureInfo const* waypointInfo) +{ + TemporarySummonWaypoint* wpCreature = new TemporarySummonWaypoint(wpOwner->GetObjectGuid(), wpId, pathId, (uint32)wpOrigin); + + CreatureCreatePos pos(wpOwner->GetMap(), wpNode->x, wpNode->y, wpNode->z, wpNode->orientation, wpOwner->GetPhaseMask()); + + if (!wpCreature->Create(wpOwner->GetMap()->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, waypointInfo)) + { + delete wpCreature; + return NULL; + } + + wpCreature->SetVisibility(VISIBILITY_OFF); + wpCreature->SetRespawnCoord(pos); + + wpCreature->SetActiveObjectState(true); + + wpCreature->Summon(TEMPSUMMON_TIMED_DESPAWN, 5 * MINUTE * IN_MILLISECONDS); // Also initializes the AI and MMGen + return wpCreature; +} + +inline void UnsummonVisualWaypoints(Player const* player, ObjectGuid ownerGuid) +{ + std::list waypoints; + MaNGOS::AllCreaturesOfEntryInRangeCheck checkerForWaypoint(player, VISUAL_WAYPOINT, SIZE_OF_GRIDS); + MaNGOS::CreatureListSearcher searcher(waypoints, checkerForWaypoint); + Cell::VisitGridObjects(player, searcher, SIZE_OF_GRIDS); + + for (std::list::iterator itr = waypoints.begin(); itr != waypoints.end(); ++itr) + { + if ((*itr)->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) + continue; + + TemporarySummonWaypoint* wpTarget = dynamic_cast(*itr); + if (!wpTarget) + continue; + + if (wpTarget->GetSummonerGuid() == ownerGuid) + wpTarget->UnSummon(); + } +} + /** * Add a waypoint to a creature. * @@ -2951,143 +2943,139 @@ bool ChatHandler::HandleWpAddCommand(char* args) { DEBUG_LOG("DEBUG: HandleWpAddCommand"); - // optional - char* guid_str = NULL; + CreatureInfo const* waypointInfo = ObjectMgr::GetCreatureTemplate(VISUAL_WAYPOINT); + if (!waypointInfo || waypointInfo->GetHighGuid() != HIGHGUID_UNIT) + return false; // must exist as normal creature in mangos.sql 'creature_template' - if (*args) + Creature* targetCreature = getSelectedCreature(); + WaypointPathOrigin wpDestination = PATH_NO_PATH; ///< into which storage + int32 wpPathId = 0; ///< along which path + uint32 wpPointId = 0; ///< pointId if a waypoint was selected, in this case insert after + Creature* wpOwner = NULL; + + if (targetCreature) { - guid_str = strtok(args, " "); - } - - uint32 lowguid = 0; - uint32 point = 0; - Creature* target = getSelectedCreature(); - // Did player provide a GUID? - if (!guid_str) - { - DEBUG_LOG("DEBUG: HandleWpAddCommand - No GUID provided"); - - // No GUID provided - // -> Player must have selected a creature - - if (!target || !target->HasStaticDBSpawnData()) + // Check if the user did specify a visual waypoint + if (targetCreature->GetEntry() == VISUAL_WAYPOINT && targetCreature->GetSubtype() == CREATURE_SUBTYPE_TEMPORARY_SUMMON) { - SendSysMessage(LANG_SELECT_CREATURE); + TemporarySummonWaypoint* wpTarget = dynamic_cast(targetCreature); + if (!wpTarget) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + + // Who moves along this waypoint? + wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); + SetSentErrorMessage(true); + return false; + } + wpDestination = (WaypointPathOrigin)wpTarget->GetPathOrigin(); + wpPathId = wpTarget->GetPathId(); + wpPointId = wpTarget->GetWaypointId() + 1; // Insert as next waypoint + } + else // normal creature selected + wpOwner = targetCreature; + } + else //!targetCreature - first argument must be dbGuid + { + uint32 dbGuid; + if (!ExtractUInt32(&args, dbGuid)) + { + PSendSysMessage(LANG_WAYPOINT_NOGUID); SetSentErrorMessage(true); return false; } - if (target->GetEntry() == VISUAL_WAYPOINT) - { - DEBUG_LOG("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) "); - - QueryResult* result = - WorldDatabase.PQuery("SELECT id, point FROM creature_movement WHERE wpguid = %u", - target->GetGUIDLow()); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow()); - // User selected a visual spawnpoint -> get the NPC - // Select NPC GUID - // Since we compare float values, we have to deal with - // some difficulties. - // Here we search for all waypoints that only differ in one from 1 thousand - // (0.001) - There is no other way to compare C++ floats with mySQL floats - // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html - const char* maxDIFF = "0.01"; - result = WorldDatabase.PQuery("SELECT id, point FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )", - target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow()); - SetSentErrorMessage(true); - return false; - } - } - do - { - Field* fields = result->Fetch(); - lowguid = fields[0].GetUInt32(); - point = fields[1].GetUInt32(); - } - while (result->NextRow()); - delete result; - - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - target = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - if (!target) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid); - SetSentErrorMessage(true); - return false; - } - } - else - { - lowguid = target->GetGUIDLow(); - } - } - else - { - DEBUG_LOG("DEBUG: HandleWpAddCommand - GUID provided"); - - // GUID provided - // Warn if player also selected a creature - // -> Creature selection is ignored <- - if (target) - { - SendSysMessage(LANG_WAYPOINT_CREATSELECTED); - } - lowguid = atoi((char*)guid_str); - - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); + CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); if (!data) { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); SetSentErrorMessage(true); return false; } - target = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - if (!target || target->IsPet()) + if (m_session->GetPlayer()->GetMapId() != data->mapid) { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, dbGuid); + SetSentErrorMessage(true); + return false; + } + + wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid)); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); SetSentErrorMessage(true); return false; } } - // lowguid -> GUID of the NPC - // point -> number of the waypoint (if not 0) - DEBUG_LOG("DEBUG: HandleWpAddCommand - danach"); - DEBUG_LOG("DEBUG: HandleWpAddCommand - point == 0"); - - Player* player = m_session->GetPlayer(); - sWaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0); - - // update movement type - if (target) + if (wpDestination == PATH_NO_PATH) // No Waypoint selected, parse additional params { - target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); - target->GetMotionMaster()->Initialize(); - if (target->IsAlive()) // dead creature will reset movement generator at respawn + if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source { - target->SetDeathState(JUST_DIED); - target->Respawn(); + uint32 src = (uint32)PATH_NO_PATH; + if (ExtractOptUInt32(&args, src, src)) + wpDestination = (WaypointPathOrigin)src; + else // pathId provided but no destination + { + if (wpPathId != 0) + wpDestination = PATH_FROM_ENTRY; // Multiple Paths must only be assigned by entry + } } - target->SaveToDB(); - } - else - WorldDatabase.PExecuteLog("UPDATE creature SET MovementType=%u WHERE guid=%u", WAYPOINT_MOTION_TYPE, lowguid); - PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid); + if (wpDestination == PATH_NO_PATH) // No overwrite params. Do best estimate + { + if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) + wpMMGen->GetPathInformation(wpPathId, wpDestination); + + // Get information about default path if no current path. If no default path, prepare data dependendy on uniqueness + if (wpDestination == PATH_NO_PATH && !sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpDestination)) + { + wpDestination = PATH_FROM_ENTRY; // Default place to store paths + if (wpOwner->HasStaticDBSpawnData()) + { + QueryResult* result = WorldDatabase.PQuery("SELECT COUNT(id) FROM creature WHERE id = %u", wpOwner->GetEntry()); + if (result && result->Fetch()[0].GetUInt32() != 1) + wpDestination = PATH_FROM_GUID; + delete result; + } + } + } + } + + // All arguments parsed + // wpOwner will get a new waypoint inserted into wpPath = GetPathFromOrigin(wpOwner, wpDestination, wpPathId) at wpPointId + + float x, y, z; + m_session->GetPlayer()->GetPosition(x, y, z); + if (!sWaypointMgr.AddNode(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPointId, wpDestination, x, y, z)) + { + PSendSysMessage(LANG_WAYPOINT_NOTCREATED, wpPointId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpDestination).c_str()); + SetSentErrorMessage(true); + return false; + } + + // Unsummon old visuals, summon new ones + UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); + WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpDestination); + for (WaypointPath::const_iterator itr = wpPath->begin(); itr != wpPath->end(); ++itr) + { + if (!Helper_CreateWaypointFor(wpOwner, wpDestination, wpPathId, itr->first, &itr->second, waypointInfo)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + SetSentErrorMessage(true); + return false; + } + } + + PSendSysMessage(LANG_WAYPOINT_ADDED, wpPointId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpDestination).c_str()); return true; } // HandleWpAddCommand @@ -3124,365 +3112,192 @@ bool ChatHandler::HandleWpModifyCommand(char* args) return false; // must exist as normal creature in mangos.sql 'creature_template' // first arg: add del text emote spell waittime move - char* show_str = strtok(args, " "); - if (!show_str) - { + char* subCmd_str = ExtractLiteralArg(&args); + if (!subCmd_str) return false; - } - std::string show = show_str; + std::string subCmd = subCmd_str; // Check // Remember: "show" must also be the name of a column! - if ((show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2") - && (show != "textid3") && (show != "textid4") && (show != "textid5") - && (show != "waittime") && (show != "del") && (show != "move") && (show != "add") - && (show != "model1") && (show != "model2") && (show != "orientation")) - { + if ((subCmd != "waittime") && (subCmd != "scriptid") && (subCmd != "orientation") && (subCmd != "del") && (subCmd != "move")) return false; - } // Next arg is: - // Did user provide a GUID - // or did the user select a creature? - // -> variable lowguid is filled with the GUID of the NPC - uint32 lowguid = 0; - uint32 point = 0; - uint32 wpGuid = 0; - Creature* target = getSelectedCreature(); + // Did user provide a GUID or did the user select a creature? + Creature* targetCreature = getSelectedCreature(); // Expect a visual waypoint to be selected + Creature* wpOwner = nullptr; // Who moves along the waypoint + uint32 wpId = 0; + WaypointPathOrigin wpSource = PATH_NO_PATH; + int32 wpPathId = 0; - if (target) + if (targetCreature) { DEBUG_LOG("DEBUG: HandleWpModifyCommand - User did select an NPC"); - // Did the user select a visual spawnpoint? - if (target->GetEntry() != VISUAL_WAYPOINT) + // Check if the user did specify a visual waypoint + if (targetCreature->GetEntry() != VISUAL_WAYPOINT || targetCreature->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + TemporarySummonWaypoint* wpTarget = dynamic_cast(targetCreature); + if (!wpTarget) { PSendSysMessage(LANG_WAYPOINT_VP_SELECT); SetSentErrorMessage(true); return false; } - wpGuid = target->GetGUIDLow(); - - // The visual waypoint - QueryResult* result = - WorldDatabase.PQuery("SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1", - target->GetGUIDLow()); - if (!result) + // Who moves along this waypoint? + wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); + if (!wpOwner) { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid); + PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); SetSentErrorMessage(true); return false; } - DEBUG_LOG("DEBUG: HandleWpModifyCommand - After getting wpGuid"); + wpId = wpTarget->GetWaypointId(); - Field* fields = result->Fetch(); - lowguid = fields[0].GetUInt32(); - point = fields[1].GetUInt32(); - - // Cleanup memory - DEBUG_LOG("DEBUG: HandleWpModifyCommand - Cleanup memory"); - delete result; + wpPathId = wpTarget->GetPathId(); + wpSource = (WaypointPathOrigin)wpTarget->GetPathOrigin(); } else { + uint32 dbGuid = 0; // User did provide - - char* guid_str = strtok((char*)NULL, " "); - if (!guid_str) + if (!ExtractUInt32(&args, dbGuid)) { SendSysMessage(LANG_WAYPOINT_NOGUID); - return false; - } - lowguid = atoi((char*)guid_str); - - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); SetSentErrorMessage(true); return false; } - PSendSysMessage("DEBUG: GUID provided: %d", lowguid); - - char* point_str = strtok((char*)NULL, " "); - if (!point_str) + if (!ExtractUInt32(&args, wpId)) { SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN); - return false; - } - point = atoi((char*)point_str); - - PSendSysMessage("DEBUG: wpNumber provided: %d", point); - - // Now we need the GUID of the visual waypoint - // -> "del", "move", "add" command - - QueryResult* result = WorldDatabase.PQuery("SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point); SetSentErrorMessage(true); return false; } - Field* fields = result->Fetch(); - wpGuid = fields[0].GetUInt32(); - - // Free memory - delete result; - } - - char* arg_str = NULL; - // Check for argument - if ((show.find("text") == std::string::npos) && (show != "del") && (show != "move") && (show != "add")) - { - // Text is enclosed in "<>", all other arguments not - if (show.find("text") != std::string::npos) - arg_str = strtok((char*)NULL, "<>"); - else - arg_str = strtok((char*)NULL, " "); - - if (!arg_str) + CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); + if (!data) { - PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str); + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); + return false; + } + + wpOwner = m_session->GetPlayer()->GetMap()->GetAnyTypeCreature(data->GetObjectGuid(dbGuid)); + if (!wpOwner) + { + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); + SetSentErrorMessage(true); return false; } } - DEBUG_LOG("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command"); - - // wpGuid -> GUID of the waypoint creature - // lowguid -> GUID of the NPC - // point -> waypoint number - - // Special functions: - // add - move - del -> no args commands - // Add a waypoint after the selected visual - if (show == "add" && target) + if (wpSource == PATH_NO_PATH) // No waypoint selected { - PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid); + if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) + wpMMGen->GetPathInformation(wpPathId, wpSource); - // Get the creature for which we read the waypoint - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } + if (wpSource == PATH_NO_PATH) + sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpSource); + } - Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - - if (!npcCreature) - { - PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND); - SetSentErrorMessage(true); - return false; - } - - DEBUG_LOG("DEBUG: HandleWpModifyCommand - add -- npcCreature"); - - // What to do: - // Add the visual spawnpoint (DB only) - // Adjust the waypoints - // Respawn the owner of the waypoints - DEBUG_LOG("DEBUG: HandleWpModifyCommand - add"); - - Player* chr = m_session->GetPlayer(); - Map* map = chr->GetMap(); - - if (npcCreature) - { - npcCreature->GetMotionMaster()->Initialize(); - if (npcCreature->IsAlive()) // dead creature will reset movement generator at respawn - { - npcCreature->SetDeathState(JUST_DIED); - npcCreature->Respawn(); - } - } - - // create the waypoint creature - wpGuid = 0; - Creature* wpCreature = new Creature; - - CreatureCreatePos pos(chr, chr->GetOrientation()); - - if (!wpCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, waypointInfo)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - delete wpCreature; - return false; - } - - wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); - // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - wpCreature->LoadFromDB(wpCreature->GetGUIDLow(), map); - map->Add(wpCreature); - wpGuid = wpCreature->GetGUIDLow(); - - sWaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid); - - if (!wpGuid) - return false; - - PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point + 1); - return true; - } // add - - if (show == "del" && target) + WaypointPath const* wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpSource); + if (!wpPath) { - PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid); - - // Get the creature for which we read the waypoint - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - - // wpCreature - Creature* wpCreature = NULL; - if (wpGuid != 0) - { - wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpGuid)); - wpCreature->DeleteFromDB(); - wpCreature->AddObjectToRemoveList(); - } - - // What to do: - // Remove the visual spawnpoint - // Adjust the waypoints - // Respawn the owner of the waypoints - - sWaypointMgr.DeleteNode(lowguid, point); - - if (npcCreature) - { - // Any waypoints left? - QueryResult* result2 = WorldDatabase.PQuery("SELECT point FROM creature_movement WHERE id = '%u'", lowguid); - if (!result2) - { - npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE); - } - else - { - npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); - delete result2; - } - npcCreature->GetMotionMaster()->Initialize(); - if (npcCreature->IsAlive()) // dead creature will reset movement generator at respawn - { - npcCreature->SetDeathState(JUST_DIED); - npcCreature->Respawn(); - } - npcCreature->SaveToDB(); - } - - PSendSysMessage(LANG_WAYPOINT_REMOVED); - return true; - } // del - - if (show == "move" && target) - { - PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid); - - Player* chr = m_session->GetPlayer(); - Map* map = chr->GetMap(); - { - // Get the creature for which we read the waypoint - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - - // wpCreature - Creature* wpCreature = NULL; - // What to do: - // Move the visual spawnpoint - // Respawn the owner of the waypoints - if (wpGuid != 0) - { - wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpGuid)); - wpCreature->DeleteFromDB(); - wpCreature->AddObjectToRemoveList(); - // re-create - Creature* wpCreature2 = new Creature; - - CreatureCreatePos pos(chr, chr->GetOrientation()); - - if (!wpCreature2->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, waypointInfo)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - delete wpCreature2; - return false; - } - - wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); - // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - wpCreature2->LoadFromDB(wpCreature2->GetGUIDLow(), map); - map->Add(wpCreature2); - // npcCreature->GetMap()->Add(wpCreature2); - } - - sWaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ()); - - if (npcCreature) - { - npcCreature->GetMotionMaster()->Initialize(); - if (npcCreature->IsAlive()) // dead creature will reset movement generator at respawn - { - npcCreature->SetDeathState(JUST_DIED); - npcCreature->Respawn(); - } - } - PSendSysMessage(LANG_WAYPOINT_CHANGED); - } - return true; - } // move - - // Create creature - npc that has the waypoint - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); - if (!data) - { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDPATH, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpSource).c_str()); SetSentErrorMessage(true); return false; } - // set in game textids not supported - if (show == "textid1" || show == "textid2" || show == "textid3" || - show == "textid4" || show == "textid5") + WaypointPath::const_iterator point = wpPath->find(wpId); + if (point == wpPath->end()) { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND, wpId, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpSource).c_str()); + SetSentErrorMessage(true); return false; } - sWaypointMgr.SetNodeText(lowguid, point, show_str, arg_str); - - Creature* npcCreature = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - if (npcCreature) + // If no visual WP was selected, but we are not going to remove it + if (!targetCreature && subCmd != "del") { - npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); - npcCreature->GetMotionMaster()->Initialize(); - if (npcCreature->IsAlive()) // dead creature will reset movement generator at respawn + targetCreature = Helper_CreateWaypointFor(wpOwner, wpSource, wpPathId, wpId, &(point->second), waypointInfo); + if (!targetCreature) { - npcCreature->SetDeathState(JUST_DIED); - npcCreature->Respawn(); + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); + SetSentErrorMessage(true); + return false; } } - PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str); + if (subCmd == "del") // Remove WP, no additional command required + { + sWaypointMgr.DeleteNode(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource); + + if (TemporarySummonWaypoint* wpCreature = dynamic_cast(targetCreature)) + wpCreature->UnSummon(); + + if (wpPath->empty()) + { + wpOwner->SetDefaultMovementType(RANDOM_MOTION_TYPE); + wpOwner->GetMotionMaster()->Initialize(); + if (wpOwner->IsAlive()) // Dead creature will reset movement generator at respawn + { + wpOwner->SetDeathState(JUST_DIED); + wpOwner->Respawn(); + } + wpOwner->SaveToDB(); + } + + PSendSysMessage(LANG_WAYPOINT_REMOVED); + return true; + } + else if (subCmd == "move") // Move to player position, no additional command required + { + float x, y, z; + m_session->GetPlayer()->GetPosition(x, y, z); + + // Move visual waypoint + targetCreature->NearTeleportTo(x, y, z, targetCreature->GetOrientation()); + + sWaypointMgr.SetNodePosition(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, x, y, z); + + PSendSysMessage(LANG_WAYPOINT_CHANGED); + return true; + } + else if (subCmd == "waittime") + { + uint32 waittime; + if (!ExtractUInt32(&args, waittime)) + return false; + + sWaypointMgr.SetNodeWaittime(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, waittime); + } + else if (subCmd == "scriptid") + { + uint32 scriptId; + if (!ExtractUInt32(&args, scriptId)) + return false; + + if (!sWaypointMgr.SetNodeScriptId(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, scriptId)) + PSendSysMessage(LANG_WAYPOINT_INFO_UNK_SCRIPTID, scriptId); + } + else if (subCmd == "orientation") + { + float ori; + if (!ExtractFloat(&args, ori)) + return false; + + sWaypointMgr.SetNodeOrientation(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpId, wpPathId, wpSource, ori); + } + + PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, subCmd_str); return true; } @@ -3522,371 +3337,202 @@ bool ChatHandler::HandleWpShowCommand(char* args) if (!waypointInfo || waypointInfo->GetHighGuid() != HIGHGUID_UNIT) return false; // must exist as normal creature in mangos.sql 'creature_template' - // first arg: on, off, first, last - char* show_str = strtok(args, " "); - if (!show_str) - { + // first arg: info, on, off, first, last + + char* subCmd_str = ExtractLiteralArg(&args); + if (!subCmd_str) return false; - } - // second arg: GUID (optional, if a creature is selected) - char* guid_str = strtok((char*)NULL, " "); - DEBUG_LOG("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str); - // if (!guid_str) { - // return false; - //} + std::string subCmd = subCmd_str; ///< info, on, off, first, last - // Did user provide a GUID - // or did the user select a creature? - // -> variable lowguid is filled with the GUID - Creature* target = getSelectedCreature(); - // Did player provide a GUID? - if (!guid_str) + uint32 dbGuid = 0; + int32 wpPathId = 0; + WaypointPathOrigin wpOrigin = PATH_NO_PATH; + + // User selected an npc? + Creature* targetCreature = getSelectedCreature(); + if (targetCreature) { - DEBUG_LOG("DEBUG: HandleWpShowCommand: !guid_str"); - // No GUID provided - // -> Player must have selected a creature - - if (!target) + if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source { - SendSysMessage(LANG_SELECT_CREATURE); - SetSentErrorMessage(true); + uint32 src; + if (ExtractOptUInt32(&args, src, (uint32)PATH_NO_PATH)) + wpOrigin = (WaypointPathOrigin)src; + } + } + else // Guid must be provided + { + if (!ExtractUInt32(&args, dbGuid)) // No creature selected and no dbGuid provided return false; - } - } - else - { - DEBUG_LOG("DEBUG: HandleWpShowCommand: GUID provided"); - // GUID provided - // Warn if player also selected a creature - // -> Creature selection is ignored <- - if (target) + + if (ExtractOptInt32(&args, wpPathId, 0)) // Fill path-id and source { - SendSysMessage(LANG_WAYPOINT_CREATSELECTED); + uint32 src = (uint32)PATH_NO_PATH; + if (ExtractOptUInt32(&args, src, src)) + wpOrigin = (WaypointPathOrigin)src; } - uint32 lowguid = atoi((char*)guid_str); - - CreatureData const* data = sObjectMgr.GetCreatureData(lowguid); + // Params now parsed, check them + CreatureData const* data = sObjectMgr.GetCreatureData(dbGuid); if (!data) { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); SetSentErrorMessage(true); return false; } - target = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(lowguid)); - - if (!target) + targetCreature = m_session->GetPlayer()->GetMap()->GetCreature(data->GetObjectGuid(dbGuid)); + if (!targetCreature) { - PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid); + PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, dbGuid); SetSentErrorMessage(true); return false; } } - uint32 lowguid = target->GetGUIDLow(); + Creature* wpOwner = NULL; ///< Npc that is moving + TemporarySummonWaypoint* wpTarget = NULL; // Define here for wp-info command - std::string show = show_str; - uint32 Maxpoint; - - DEBUG_LOG("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str); - - // Show info for the selected waypoint - if (show == "info") + // Show info for the selected waypoint (Step one: get moving npc) + if (subCmd == "info") { - PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid); - // Check if the user did specify a visual waypoint - if (target->GetEntry() != VISUAL_WAYPOINT) + if (targetCreature->GetEntry() != VISUAL_WAYPOINT || targetCreature->GetSubtype() != CREATURE_SUBTYPE_TEMPORARY_SUMMON) + { + PSendSysMessage(LANG_WAYPOINT_VP_SELECT); + SetSentErrorMessage(true); + return false; + } + wpTarget = dynamic_cast(targetCreature); + if (!wpTarget) { PSendSysMessage(LANG_WAYPOINT_VP_SELECT); SetSentErrorMessage(true); return false; } - // PSendSysMessage("wp on, GUID: %u", lowguid); - - // pCreature->GetPositionX(); - - QueryResult* result = - WorldDatabase.PQuery("SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u", - target->GetGUIDLow()); - if (!result) + // Who moves along this waypoint? + wpOwner = targetCreature->GetMap()->GetAnyTypeCreature(wpTarget->GetSummonerGuid()); + if (!wpOwner) { - // Since we compare float values, we have to deal with - // some difficulties. - // Here we search for all waypoints that only differ in one from 1 thousand - // (0.001) - There is no other way to compare C++ floats with mySQL floats - // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html - const char* maxDIFF = "0.01"; - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetObjectGuid().GetRawValue()); + PSendSysMessage(LANG_WAYPOINT_NOTFOUND_NPC, wpTarget->GetSummonerGuid().GetString().c_str()); + SetSentErrorMessage(true); + return false; + } - result = WorldDatabase.PQuery("SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )", - target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF); - if (!result) + // Ignore params, use information of selected waypoint! + wpOrigin = (WaypointPathOrigin)wpTarget->GetPathOrigin(); + wpPathId = wpTarget->GetPathId(); + } + else + wpOwner = targetCreature; + + // Get the path + WaypointPath* wpPath = NULL; + if (wpOrigin != PATH_NO_PATH) // Might have been provided by param + wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); + else + { + if (wpOwner->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE) + if (WaypointMovementGenerator const* wpMMGen = dynamic_cast const*>(wpOwner->GetMotionMaster()->GetCurrent())) { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid); + wpMMGen->GetPathInformation(wpPathId, wpOrigin); + wpPath = sWaypointMgr.GetPathFromOrigin(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), wpPathId, wpOrigin); + } + + if (wpOrigin == PATH_NO_PATH) + wpPath = sWaypointMgr.GetDefaultPath(wpOwner->GetEntry(), wpOwner->GetGUIDLow(), &wpOrigin); + } + + if (!wpPath || wpPath->empty()) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUNDPATH, wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); + SetSentErrorMessage(true); + return false; + } + + // Show info for the selected waypoint (Step two: Show actual info) + if (subCmd == "info") + { + // Find the waypoint + WaypointPath::const_iterator point = wpPath->find(wpTarget->GetWaypointId()); + if (point == wpPath->end()) + { + PSendSysMessage(LANG_WAYPOINT_NOTFOUND, wpTarget->GetWaypointId(), wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, wpTarget->GetWaypointId(), wpOwner->GetGuidStr().c_str(), wpPathId, WaypointManager::GetOriginString(wpOrigin).c_str()); + PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, point->second.delay); + PSendSysMessage(LANG_WAYPOINT_INFO_ORI, point->second.orientation); + PSendSysMessage(LANG_WAYPOINT_INFO_SCRIPTID, point->second.script_id); + if (wpOrigin == PATH_FROM_EXTERNAL) + PSendSysMessage(LANG_WAYPOINT_INFO_AISCRIPT, wpOwner->GetScriptName().c_str()); + if (WaypointBehavior* behaviour = point->second.behavior) + { + PSendSysMessage(" ModelId1: %u", behaviour->model1); + PSendSysMessage(" ModelId2: %u", behaviour->model2); + PSendSysMessage(" Emote: %u", behaviour->emote); + PSendSysMessage(" Spell: %u", behaviour->spell); + for (int i = 0; i < MAX_WAYPOINT_TEXT; ++i) + PSendSysMessage(" TextId%i: %i \'%s\'", i + 1, behaviour->textid[i], (behaviour->textid[i] ? GetMangosString(behaviour->textid[i]) : "")); + } + + return true; + } + + if (subCmd == "on") + { + UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); + + for (WaypointPath::const_iterator pItr = wpPath->begin(); pItr != wpPath->end(); ++pItr) + { + if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, pItr->first, &(pItr->second), waypointInfo)) + { + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); SetSentErrorMessage(true); return false; } } - do - { - Field* fields = result->Fetch(); - uint32 wpGuid = fields[0].GetUInt32(); - uint32 point = fields[1].GetUInt32(); - int waittime = fields[2].GetUInt32(); - uint32 emote = fields[3].GetUInt32(); - uint32 spell = fields[4].GetUInt32(); - uint32 textid[MAX_WAYPOINT_TEXT]; - for (int i = 0; i < MAX_WAYPOINT_TEXT; ++i) - textid[i] = fields[5 + i].GetUInt32(); - uint32 model1 = fields[10].GetUInt32(); - uint32 model2 = fields[11].GetUInt32(); - // Get the creature for which we read the waypoint - CreatureData const* data = sObjectMgr.GetCreatureData(wpGuid); - Creature* wpCreature = m_session->GetPlayer()->GetMap()->GetCreature(data ? data->GetObjectGuid(wpGuid) : ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpGuid)); - - PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : ""), wpGuid); - PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime); - PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1); - PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2); - PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote); - PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell); - for (int i = 0; i < MAX_WAYPOINT_TEXT; ++i) - PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i + 1, textid[i], (textid[i] ? GetMangosString(textid[i]) : "")); - } - while (result->NextRow()); - // Cleanup memory - delete result; return true; } - if (show == "on") + if (subCmd == "first") { - PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid); - - QueryResult* result = WorldDatabase.PQuery("SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'", lowguid); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - // Delete all visuals for this NPC - QueryResult* result2 = WorldDatabase.PQuery("SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid); - if (result2) - { - bool hasError = false; - do - { - Field* fields = result2->Fetch(); - uint32 wpGuid = fields[0].GetUInt32(); - Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpGuid)); - - if (!pCreature) - { - PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpGuid); - hasError = true; - WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid=%u", wpGuid); - } - else - { - pCreature->DeleteFromDB(); - pCreature->AddObjectToRemoveList(); - } - } - while (result2->NextRow()); - delete result2; - if (hasError) - { - PSendSysMessage(LANG_WAYPOINT_TOOFAR1); - PSendSysMessage(LANG_WAYPOINT_TOOFAR2); - PSendSysMessage(LANG_WAYPOINT_TOOFAR3); - } - } - - do - { - Player* chr = m_session->GetPlayer(); - Map* map = chr->GetMap(); - - Field* fields = result->Fetch(); - uint32 point = fields[0].GetUInt32(); - CreatureCreatePos pos(map, fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), chr->GetOrientation(), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); - - Creature* wpCreature = new Creature; - - if (!wpCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, waypointInfo)) - { - PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - delete wpCreature; - delete result; - return false; - } - - wpCreature->SetVisibility(VISIBILITY_OFF); - DEBUG_LOG("DEBUG: UPDATE creature_movement SET wpguid = '%u", wpCreature->GetGUIDLow()); - // set "wpguid" column to the visual waypoint - WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid=%u WHERE id=%u and point=%u", wpCreature->GetGUIDLow(), lowguid, point); - - wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); - // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); - wpCreature->LoadFromDB(wpCreature->GetGUIDLow(), map); - map->Add(wpCreature); - // wpCreature->GetMap()->Add(wpCreature); - } - while (result->NextRow()); - - // Cleanup memory - delete result; - return true; - } - - if (show == "first") - { - PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid); - - QueryResult* result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'", lowguid); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid); - SetSentErrorMessage(true); - return false; - } - - Player* chr = m_session->GetPlayer(); - Map* map = chr->GetMap(); - - Field* fields = result->Fetch(); - CreatureCreatePos pos(map, fields[0].GetFloat(), fields[1].GetFloat(), fields[2].GetFloat(), chr->GetOrientation(), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); - - Creature* pCreature = new Creature; - - if (!pCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, waypointInfo)) + if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, wpPath->begin()->first, &(wpPath->begin()->second), waypointInfo)) { PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); - delete pCreature; - delete result; + SetSentErrorMessage(true); return false; } - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); - pCreature->LoadFromDB(pCreature->GetGUIDLow(), map); - map->Add(pCreature); // player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint"); - - // Cleanup memory - delete result; return true; } - if (show == "last") + if (subCmd == "last") { - PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid); - - QueryResult* result = WorldDatabase.PQuery("SELECT MAX(point) FROM creature_movement WHERE id = '%u'", lowguid); - if (result) + if (!Helper_CreateWaypointFor(wpOwner, wpOrigin, wpPathId, wpPath->rbegin()->first, &(wpPath->rbegin()->second), waypointInfo)) { - Maxpoint = (*result)[0].GetUInt32(); - - delete result; - } - else - Maxpoint = 0; - - result = WorldDatabase.PQuery("SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'", Maxpoint, lowguid); - if (!result) - { - PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid); + PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); SetSentErrorMessage(true); return false; } - Player* chr = m_session->GetPlayer(); - Map* map = chr->GetMap(); - - Field* fields = result->Fetch(); - CreatureCreatePos pos(map, fields[0].GetFloat(), fields[1].GetFloat(), fields[2].GetFloat(), chr->GetOrientation(), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); - - Creature* pCreature = new Creature; - - if (!pCreature->Create(map->GenerateLocalLowGuid(HIGHGUID_UNIT), pos, waypointInfo)) - { - PSendSysMessage(LANG_WAYPOINT_NOTCREATED, VISUAL_WAYPOINT); - delete pCreature; - delete result; - return false; - } - - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr()->GetPhaseMaskForSpawn()); - pCreature->LoadFromDB(pCreature->GetGUIDLow(), map); - map->Add(pCreature); // player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint"); - // Cleanup memory - delete result; return true; } - if (show == "off") + if (subCmd == "off") { - QueryResult* result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id=%u", VISUAL_WAYPOINT); - if (!result) - { - SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND); - SetSentErrorMessage(true); - return false; - } - bool hasError = false; - do - { - Field* fields = result->Fetch(); - uint32 wpGuid = fields[0].GetUInt32(); - Creature* pCreature = m_session->GetPlayer()->GetMap()->GetCreature(ObjectGuid(HIGHGUID_UNIT, VISUAL_WAYPOINT, wpGuid)); - if (!pCreature) - { - PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, wpGuid); - hasError = true; - WorldDatabase.PExecuteLog("DELETE FROM creature WHERE guid=%u", wpGuid); - } - else - { - pCreature->DeleteFromDB(); - pCreature->AddObjectToRemoveList(); - } - } - while (result->NextRow()); - // set "wpguid" column to "empty" - no visual waypoint spawned - WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid=0 WHERE wpguid <> 0"); - - if (hasError) - { - PSendSysMessage(LANG_WAYPOINT_TOOFAR1); - PSendSysMessage(LANG_WAYPOINT_TOOFAR2); - PSendSysMessage(LANG_WAYPOINT_TOOFAR3); - } - - SendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); - // Cleanup memory - delete result; - + UnsummonVisualWaypoints(m_session->GetPlayer(), wpOwner->GetObjectGuid()); + PSendSysMessage(LANG_WAYPOINT_VP_ALLREMOVED); return true; } - PSendSysMessage("DEBUG: wpshow - no valid command found"); - - return true; -} // HandleWpShowCommand - -bool ChatHandler::HandleReloadPhaseDefinitionsCommand(char* /*args*/) -{ - SendSysMessage("Reloading phase_definitions table..."); - sObjectMgr.LoadPhaseDefinitions(); - sWorld.UpdatePhaseDefinitions(); - SendSysMessage("Phase Definitions reloaded."); - return true; -} + return false; +} bool ChatHandler::HandleWpExportCommand(char* args) { diff --git a/src/game/ChatCommands/Level3.cpp b/src/game/ChatCommands/Level3.cpp index 712b1e580..c3c5112b3 100644 --- a/src/game/ChatCommands/Level3.cpp +++ b/src/game/ChatCommands/Level3.cpp @@ -2370,7 +2370,8 @@ bool ChatHandler::HandleLearnAllMyClassCommand(char* /*args*/) bool ChatHandler::HandleLearnAllMySpellsCommand(char* /*args*/) { - ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(m_session->GetPlayer()->getClass()); + Player* player = m_session->GetPlayer(); + ChrClassesEntry const* clsEntry = sChrClassesStore.LookupEntry(player->getClass()); if (!clsEntry) return true; uint32 family = clsEntry->spellfamily; @@ -2390,7 +2391,7 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(char* /*args*/) continue; // skip wrong class/race skills - if (!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id)) + if (!player->IsSpellFitByClassAndRace(spellInfo->Id)) continue; // skip other spell families @@ -2403,10 +2404,10 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(char* /*args*/) continue; // skip broken spells - if (!SpellMgr::IsSpellValid(spellInfo, m_session->GetPlayer(), false)) + if (!SpellMgr::IsSpellValid(spellInfo, player, false)) continue; - m_session->GetPlayer()->learnSpell(spellInfo->Id, false); + player->learnSpell(spellInfo->Id, false); } SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); @@ -2447,7 +2448,7 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(char* /*args*/) continue; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, m_session->GetPlayer(), false)) + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, player, false)) continue; // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) @@ -2540,9 +2541,11 @@ bool ChatHandler::HandleLearnAllMyPetTalentsCommand(char* /*args*/) bool ChatHandler::HandleLearnAllLangCommand(char* /*args*/) { + Player* player = m_session->GetPlayer(); + // skipping UNIVERSAL language (0) for (int i = 1; i < LANGUAGES_COUNT; ++i) - m_session->GetPlayer()->learnSpell(lang_description[i].spell_id, false); + player->learnSpell(lang_description[i].spell_id, false); SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); return true; @@ -2563,6 +2566,7 @@ bool ChatHandler::HandleLearnAllDefaultCommand(char* args) bool ChatHandler::HandleLearnCommand(char* args) { + Player* player = m_session->GetPlayer(); Player* targetPlayer = getSelectedPlayer(); if (!targetPlayer) @@ -2577,12 +2581,12 @@ bool ChatHandler::HandleLearnCommand(char* args) if (!spell || !sSpellStore.LookupEntry(spell)) return false; - bool allRanks = ExtractLiteralArg(&args, "all") != NULL; + bool allRanks = ExtractLiteralArg(&args, "all") != nullptr; if (!allRanks && *args) // can be fail also at syntax error return false; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, m_session->GetPlayer())) + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, player)) { PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spell); SetSentErrorMessage(true); @@ -2591,7 +2595,7 @@ bool ChatHandler::HandleLearnCommand(char* args) if (!allRanks && targetPlayer->HasSpell(spell)) { - if (targetPlayer == m_session->GetPlayer()) + if (targetPlayer == player) SendSysMessage(LANG_YOU_KNOWN_SPELL); else PSendSysMessage(LANG_TARGET_KNOWN_SPELL, GetNameLink(targetPlayer).c_str()); @@ -3956,9 +3960,10 @@ bool ChatHandler::HandleGetDistanceCommand(char* args) bool ChatHandler::HandleDieCommand(char* /*args*/) { + Player* player = m_session->GetPlayer(); Unit* target = getSelectedUnit(); - if (!target || !m_session->GetPlayer()->GetSelectionGuid()) + if (!target || !player->GetSelectionGuid()) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SetSentErrorMessage(true); @@ -3973,7 +3978,7 @@ bool ChatHandler::HandleDieCommand(char* /*args*/) if (target->IsAlive()) { - m_session->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + player->DealDamage(target, target->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } return true; @@ -3985,8 +3990,9 @@ bool ChatHandler::HandleDamageCommand(char* args) return false; Unit* target = getSelectedUnit(); + Player* player = m_session->GetPlayer(); - if (!target || !m_session->GetPlayer()->GetSelectionGuid()) + if (!target || !player->GetSelectionGuid()) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SetSentErrorMessage(true); @@ -4005,12 +4011,12 @@ bool ChatHandler::HandleDamageCommand(char* args) uint32 damage = damage_int; - // flat melee damage without resistence/etc reduction + // flat melee damage without resistance/etc reduction if (!*args) { - m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - if (target != m_session->GetPlayer()) - m_session->GetPlayer()->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); + player->DealDamage(target, damage, nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + if (target != player) + player->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); return true; } @@ -4024,7 +4030,7 @@ bool ChatHandler::HandleDamageCommand(char* args) SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); if (schoolmask & SPELL_SCHOOL_MASK_NORMAL) - damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage); + damage = player->CalcArmorReducedDamage(target, damage); // melee damage by specific school if (!*args) @@ -4032,16 +4038,16 @@ bool ChatHandler::HandleDamageCommand(char* args) uint32 absorb = 0; uint32 resist = 0; - target->CalculateDamageAbsorbAndResist(m_session->GetPlayer(), schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + target->CalculateDamageAbsorbAndResist(player, schoolmask, SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); if (damage <= absorb + resist) return true; damage -= absorb + resist; - m_session->GetPlayer()->DealDamageMods(target, damage, &absorb); - m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); - m_session->GetPlayer()->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); + player->DealDamageMods(target, damage, &absorb); + player->DealDamage(target, damage, nullptr, DIRECT_DAMAGE, schoolmask, nullptr, false); + player->SendAttackStateUpdate(HITINFO_NORMALSWING2, target, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); return true; } @@ -4052,7 +4058,7 @@ bool ChatHandler::HandleDamageCommand(char* args) if (!spellid || !sSpellStore.LookupEntry(spellid)) return false; - m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage); + player->SpellNonMeleeDamageLog(target, spellid, damage); return true; } @@ -6411,7 +6417,7 @@ bool ChatHandler::HandleCastCommand(char* args) return false; } - bool triggered = ExtractLiteralArg(&args, "triggered") != NULL; + bool triggered = ExtractLiteralArg(&args, "triggered") != nullptr; if (!triggered && *args) // can be fail also at syntax error return false; @@ -7132,8 +7138,10 @@ bool ChatHandler::HandleSendMessageCommand(char* args) if (!*args) return false; + WorldSession* rPlayerSession = rPlayer->GetSession(); + ///- Check that he is not logging out. - if (rPlayer->GetSession()->isLogingOut()) + if (rPlayerSession->isLogingOut()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -7142,8 +7150,8 @@ bool ChatHandler::HandleSendMessageCommand(char* args) ///- Send the message // Use SendAreaTriggerMessage for fastest delivery. - rPlayer->GetSession()->SendAreaTriggerMessage("%s", args); - rPlayer->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); + rPlayerSession->SendAreaTriggerMessage("%s", args); + rPlayerSession->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); // Confirmation message std::string nameLink = GetNameLink(rPlayer); @@ -7301,3 +7309,11 @@ bool ChatHandler::HandleMmapTestArea(char* args) return true; } + +bool ChatHandler::HandleServerResetAllRaidCommand(char* args) +{ + PSendSysMessage("Global raid instances reset, all players in raid instances will be teleported to homebind!"); + sMapPersistentStateMgr.GetScheduler().ResetAllRaid(); + return true; +} + diff --git a/src/game/ChatCommands/debugcmds.cpp b/src/game/ChatCommands/debugcmds.cpp index 39fd07e95..1aa615852 100644 --- a/src/game/ChatCommands/debugcmds.cpp +++ b/src/game/ChatCommands/debugcmds.cpp @@ -37,7 +37,6 @@ #include "ObjectMgr.h" #include "ObjectGuid.h" #include "SpellMgr.h" -#include "PhaseMgr.h" bool ChatHandler::HandleDebugSendSpellFailCommand(char* args) { @@ -129,58 +128,60 @@ bool ChatHandler::HandleDebugSendOpcodeCommand(char* /*args*/) if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) unit = m_session->GetPlayer(); - std::ifstream ifs("opcode.txt"); - if (ifs.bad()) + std::ifstream stream("opcode.txt"); + if (!stream.is_open()) return false; - uint32 opcode; - ifs >> opcode; + uint32 opcode = 0; + if (!(stream >> opcode)) + { + stream.close(); + return false; + } WorldPacket data(Opcodes(opcode), 0); - while (!ifs.eof()) + std::string type; + while (stream >> type) { - std::string type; - ifs >> type; - - if (type == "") + if (type.empty()) break; if (type == "uint8") { - uint16 val1; - ifs >> val1; - data << uint8(val1); + uint16 value; + stream >> value; + data << uint8(value); } else if (type == "uint16") { - uint16 val2; - ifs >> val2; - data << val2; + uint16 value; + stream >> value; + data << value; } else if (type == "uint32") { - uint32 val3; - ifs >> val3; - data << val3; + uint32 value; + stream >> value; + data << value; } else if (type == "uint64") { - uint64 val4; - ifs >> val4; - data << val4; + uint64 value; + stream >> value; + data << value; } else if (type == "float") { - float val5; - ifs >> val5; - data << val5; + float value; + stream >> value; + data << value; } else if (type == "string") { - std::string val6; - ifs >> val6; - data << val6; + std::string value; + stream >> value; + data << value; } else if (type == "pguid") { @@ -192,11 +193,15 @@ bool ChatHandler::HandleDebugSendOpcodeCommand(char* /*args*/) break; } } - ifs.close(); + stream.close(); + DEBUG_LOG("Sending opcode %u, %s", data.GetOpcode(), data.GetOpcodeName()); + data.hexlike(); ((Player*)unit)->GetSession()->SendPacket(&data); + PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName()); + return true; } @@ -673,32 +678,23 @@ bool ChatHandler::HandleDebugSendSetPhaseShiftCommand(char* args) if (!*args) return false; - char* t = strtok((char*)args, " "); + char* m = strtok((char*)args, " "); char* p = strtok(NULL, " "); - if (!t) - return false; - - std::set terrainswap; - std::set phaseId; - - terrainswap.insert((uint32)atoi(t)); - - if (p) - phaseId.insert((uint32)atoi(p)); - - m_session->SendSetPhaseShift(phaseId, terrainswap); + uint16 MapId = atoi(m); + uint32 PhaseShift = atoi(p); + m_session->SendSetPhaseShift(PhaseShift, MapId); return true; } bool ChatHandler::HandleDebugPhaseCommand(char* args) { - Player* player = getSelectedPlayer(); - if (!player) - player = m_session->GetPlayer(); + uint32 emote_id; + if (!ExtractUInt32(&args, emote_id)) + { return false; } - player->GetPhaseMgr()->SendDebugReportToPlayer(m_session->GetPlayer()); - return true; + m_session->GetPlayer()->HandleEmoteCommand(emote_id); + return true; } // show animation @@ -973,29 +969,30 @@ bool ChatHandler::HandlerDebugModValueHelper(Object* target, uint32 field, char* return false; uint32 value = target->GetUInt32Value(field); + const char* guidString = guid.GetString().c_str(); switch (type) { default: case 1: // int + value = uint32(int32(value) + int32(iValue)); - DEBUG_LOG(GetMangosString(LANG_CHANGE_INT32), guid.GetString().c_str(), field, iValue, value, value); - PSendSysMessage(LANG_CHANGE_INT32_FIELD, guid.GetString().c_str(), field, iValue, value, value); + DEBUG_LOG(GetMangosString(LANG_CHANGE_INT32), guidString, field, iValue, value, value); + PSendSysMessage(LANG_CHANGE_INT32_FIELD, guidString, field, iValue, value, value); break; case 2: // |= bit or value |= iValue; - DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guid.GetString().c_str(), field, typeStr, iValue, value); - PSendSysMessage(LANG_CHANGE_HEX_FIELD, guid.GetString().c_str(), field, typeStr, iValue, value); + DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guidString, field, typeStr, iValue, value); + PSendSysMessage(LANG_CHANGE_HEX_FIELD, guidString, field, typeStr, iValue, value); break; case 3: // &= bit and value &= iValue; - DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guid.GetString().c_str(), field, typeStr, iValue, value); - PSendSysMessage(LANG_CHANGE_HEX_FIELD, guid.GetString().c_str(), field, typeStr, iValue, value); + DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guidString, field, typeStr, iValue, value); + PSendSysMessage(LANG_CHANGE_HEX_FIELD, guidString, field, typeStr, iValue, value); break; case 4: // &=~ bit and not value &= ~iValue; - DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guid.GetString().c_str(), field, typeStr, iValue, value); - PSendSysMessage(LANG_CHANGE_HEX_FIELD, guid.GetString().c_str(), field, typeStr, iValue, value); + DEBUG_LOG(GetMangosString(LANG_CHANGE_HEX), guidString, field, typeStr, iValue, value); + PSendSysMessage(LANG_CHANGE_HEX_FIELD, guidString, field, typeStr, iValue, value); break; } diff --git a/src/game/MotionGenerators/HomeMovementGenerator.cpp b/src/game/MotionGenerators/HomeMovementGenerator.cpp index 9ba8664a7..f35324db9 100644 --- a/src/game/MotionGenerators/HomeMovementGenerator.cpp +++ b/src/game/MotionGenerators/HomeMovementGenerator.cpp @@ -47,7 +47,7 @@ void HomeMovementGenerator::_setTargetLocation(Creature& owner) Movement::MoveSplineInit init(owner); float x, y, z, o; // at apply we can select more nice return points base at current movegen - if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner, x, y, z)) + if (owner.GetMotionMaster()->empty() || !owner.GetMotionMaster()->top()->GetResetPosition(owner, x, y, z, o)) { owner.GetRespawnCoord(x, y, z, &o); init.SetFacing(o); diff --git a/src/game/MotionGenerators/MotionMaster.h b/src/game/MotionGenerators/MotionMaster.h index 50ebd57d7..62727098a 100644 --- a/src/game/MotionGenerators/MotionMaster.h +++ b/src/game/MotionGenerators/MotionMaster.h @@ -76,6 +76,8 @@ class MotionMaster : private std::stack void Initialize(); + MovementGenerator const* GetCurrent() const { return top(); } + MovementGenerator* operator->(void) { return top(); } using Impl::top; diff --git a/src/game/MotionGenerators/MovementGenerator.h b/src/game/MotionGenerators/MovementGenerator.h index e60f36340..7b88280ee 100644 --- a/src/game/MotionGenerators/MovementGenerator.h +++ b/src/game/MotionGenerators/MovementGenerator.h @@ -59,7 +59,7 @@ class MovementGenerator virtual void unitSpeedChanged() { } // used by Evade code for select point to evade with expected restart default movement - virtual bool GetResetPosition(Unit&, float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } + virtual bool GetResetPosition(Unit&, float& /*x*/, float& /*y*/, float& /*z*/, float& o) const { return false; } // given destination unreachable? due to pathfinsing or other virtual bool IsReachable() const { return true; } @@ -70,7 +70,7 @@ class MovementGenerator }; template -class MovementGeneratorMedium : public MovementGenerator +class MANGOS_DLL_SPEC MovementGeneratorMedium : public MovementGenerator { public: void Initialize(Unit& u) override @@ -98,10 +98,10 @@ class MovementGeneratorMedium : public MovementGenerator // u->AssertIsType(); return (static_cast(this))->Update(*((T*)&u), time_diff); } - bool GetResetPosition(Unit& u, float& x, float& y, float& z) const override + bool GetResetPosition(Unit& u, float& x, float& y, float& z, float& o) const override { // u->AssertIsType(); - return (static_cast(this))->GetResetPosition(*((T*)&u), x, y, z); + return (static_cast(this))->GetResetPosition(*((T*)&u), x, y, z, o); } public: // Will not link if not overridden in the generators @@ -112,7 +112,7 @@ class MovementGeneratorMedium : public MovementGenerator bool Update(T& u, const uint32& time_diff); // not need always overwrites - bool GetResetPosition(T& /*u*/, float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } + bool GetResetPosition(T& /*u*/, float& /*x*/, float& /*y*/, float& /*z*/, float& /*o*/) const { return false; } }; struct SelectableMovement : public FactoryHolder diff --git a/src/game/MotionGenerators/PathFinder.h b/src/game/MotionGenerators/PathFinder.h index c1139a844..7880d24aa 100644 --- a/src/game/MotionGenerators/PathFinder.h +++ b/src/game/MotionGenerators/PathFinder.h @@ -101,10 +101,11 @@ class PathFinder const dtNavMeshQuery* m_navMeshQuery; // the nav mesh query used to find the path dtQueryFilter m_filter; // use single filter for all movements, update it when needed + - void setStartPosition(const Vector3 &point) { m_startPosition = point; } - void setEndPosition(const Vector3 &point) { m_actualEndPosition = point; m_endPosition = point; } - void setActualEndPosition(const Vector3 &point) { m_actualEndPosition = point; } + void setStartPosition(const Vector3& point) { m_startPosition = point; } + void setEndPosition(const Vector3& point) { m_actualEndPosition = point; m_endPosition = point; } + void setActualEndPosition(const Vector3& point) { m_actualEndPosition = point; } void clear() { diff --git a/src/game/MotionGenerators/TargetedMovementGenerator.cpp b/src/game/MotionGenerators/TargetedMovementGenerator.cpp index e1736bf86..6e26a0974 100644 --- a/src/game/MotionGenerators/TargetedMovementGenerator.cpp +++ b/src/game/MotionGenerators/TargetedMovementGenerator.cpp @@ -317,11 +317,11 @@ void FollowMovementGenerator::Reset(T& owner) // This factor defines how much of the bounding-radius (as measurement of size) will be used for recalculating a new following position // The smaller, the more micro movement, the bigger, possibly no proper movement updates -#define FOLLOW_RECALCULATE_FACTOR 0.1f +#define FOLLOW_RECALCULATE_FACTOR 1.0f // This factor defines when the distance of a follower will have impact onto following-position updates #define FOLLOW_DIST_GAP_FOR_DIST_FACTOR 3.0f // This factor defines how much of the follow-distance will be used as sloppyness value (if the above distance is exceeded) -#define FOLLOW_DIST_RECALCULATE_FACTOR 0.1f +#define FOLLOW_DIST_RECALCULATE_FACTOR 1.0f template float FollowMovementGenerator::GetDynamicTargetDistance(T& owner, bool forRangeCheck) const diff --git a/src/game/MotionGenerators/WaypointMovementGenerator.cpp b/src/game/MotionGenerators/WaypointMovementGenerator.cpp index 30f883c90..e6f1ac76b 100644 --- a/src/game/MotionGenerators/WaypointMovementGenerator.cpp +++ b/src/game/MotionGenerators/WaypointMovementGenerator.cpp @@ -38,40 +38,35 @@ #include //-----------------------------------------------// -void WaypointMovementGenerator::LoadPath(Creature& creature) +void WaypointMovementGenerator::LoadPath(Creature& creature, int32 pathId, WaypointPathOrigin wpOrigin, uint32 overwriteEntry) { DETAIL_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "LoadPath: loading waypoint path for %s", creature.GetGuidStr().c_str()); - i_path = sWaypointMgr.GetPath(creature.GetGUIDLow()); + if (!overwriteEntry) + overwriteEntry = creature.GetEntry(); - // We may LoadPath() for several occasions: + if (wpOrigin == PATH_NO_PATH && pathId == 0) + i_path = sWaypointMgr.GetDefaultPath(overwriteEntry, creature.GetGUIDLow(), &m_PathOrigin); + else + { + m_PathOrigin = wpOrigin == PATH_NO_PATH ? PATH_FROM_ENTRY : wpOrigin; + i_path = sWaypointMgr.GetPathFromOrigin(overwriteEntry, creature.GetGUIDLow(), pathId, m_PathOrigin); + } + m_pathId = pathId; - // 1: When creature.MovementType=2 - // 1a) Path is selected by creature.guid == creature_movement.id - // 1b) Path for 1a) does not exist and then use path from creature.GetEntry() == creature_movement_template.entry - - // 2: When creature_template.MovementType=2 - // 2a) Creature is summoned and has creature_template.MovementType=2 - // Creators need to be sure that creature_movement_template is always valid for summons. - // Mob that can be summoned anywhere should not have creature_movement_template for example. - - // No movement found for guid + // No movement found for entry nor guid if (!i_path) { - i_path = sWaypointMgr.GetPathTemplate(creature.GetEntry()); - - // No movement found for entry - if (!i_path) - { - sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path", - creature.GetName(), creature.GetEntry(), creature.GetGUIDLow()); - return; - } + if (m_PathOrigin == PATH_FROM_EXTERNAL) + sLog.outErrorScriptLib("WaypointMovementGenerator::LoadPath: %s doesn't have waypoint path %i", creature.GetGuidStr().c_str(), pathId); + else + sLog.outErrorDb("WaypointMovementGenerator::LoadPath: %s doesn't have waypoint path %i", creature.GetGuidStr().c_str(), pathId); + return; } - // Initialize the i_currentNode to point to the first node if (i_path->empty()) return; + // Initialize the i_currentNode to point to the first node i_currentNode = i_path->begin()->first; m_lastReachedWaypoint = 0; } @@ -80,10 +75,6 @@ void WaypointMovementGenerator::Initialize(Creature& creature) { creature.addUnitState(UNIT_STAT_ROAMING); creature.clearUnitState(UNIT_STAT_WAYPOINT_PAUSED); - - LoadPath(creature); - - StartMoveNow(creature); } void WaypointMovementGenerator::Finalize(Creature& creature) @@ -158,23 +149,16 @@ void WaypointMovementGenerator::OnArrived(Creature& creature) } if (MangosStringLocale const* textData = sObjectMgr.GetMangosStringLocale(textId)) - creature.MonsterText(textData, nullptr); + creature.MonsterText(textData, NULL); else sLog.outErrorDb("%s reached waypoint %u, attempted to do text %i, but required text-data could not be found", creature.GetGuidStr().c_str(), i_currentNode, textId); } } // Inform script - MovementInform(creature); Stop(node.delay); } -void WaypointMovementGenerator::StartMoveNow(Creature& creature) -{ - i_nextMoveTime.Reset(0); - StartMove(creature); -} - void WaypointMovementGenerator::StartMove(Creature& creature) { if (!i_path || i_path->empty()) @@ -254,13 +238,7 @@ bool WaypointMovementGenerator::Update(Creature& creature, const uint3 return true; } -void WaypointMovementGenerator::MovementInform(Creature& creature) -{ - if (creature.AI()) - creature.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode); -} - -bool WaypointMovementGenerator::GetResetPosition(Creature&, float& x, float& y, float& z) const +bool WaypointMovementGenerator::GetResetPosition(Creature&, float& x, float& y, float& z, float& o) const { // prevent a crash at empty waypoint path. if (!i_path || i_path->empty()) @@ -271,9 +249,34 @@ bool WaypointMovementGenerator::GetResetPosition(Creature&, float& x, if (!m_lastReachedWaypoint && lastPoint == i_path->end()) return false; - MANGOS_ASSERT(lastPoint != i_path->end()); + MANGOS_ASSERT(lastPoint != i_path->end()); + + WaypointNode const* curWP = &(lastPoint->second); + + x = curWP->x; + y = curWP->y; + z = curWP->z; + + if (curWP->orientation != 100) + o = curWP->orientation; + else // Calculate the resulting angle based on positions between previous and current waypoint + { + WaypointNode const* prevWP; + if (lastPoint != i_path->begin()) // Not the first waypoint + { + --lastPoint; + prevWP = &(lastPoint->second); + } + else // Take the last waypoint (crbegin()) as previous + prevWP = &(i_path->rbegin()->second); + + float dx = x - prevWP->x; + float dy = y - prevWP->y; + o = atan2(dy, dx); // returns value between -Pi..Pi + + o = (o >= 0) ? o : 2 * M_PI_F + o; + } - x = lastPoint->second.x; y = lastPoint->second.y; z = lastPoint->second.z; return true; } @@ -418,9 +421,12 @@ void FlightPathMovementGenerator::DoEventIfAny(Player& player, TaxiPathNodeEntry } } -bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, float& z) const +bool FlightPathMovementGenerator::GetResetPosition(Player&, float& x, float& y, float& z, float& o) const { const TaxiPathNodeEntry& node = (*i_path)[i_currentNode]; - x = node.x; y = node.y; z = node.z; + x = node.x; + y = node.y; + z = node.z; + return true; } diff --git a/src/game/MotionGenerators/WaypointMovementGenerator.h b/src/game/MotionGenerators/WaypointMovementGenerator.h index 7e3faa942..9a0e35ab3 100644 --- a/src/game/MotionGenerators/WaypointMovementGenerator.h +++ b/src/game/MotionGenerators/WaypointMovementGenerator.h @@ -42,7 +42,7 @@ #define STOP_TIME_FOR_PLAYER (3 * MINUTE * IN_MILLISECONDS) // 3 Minutes template -class PathMovementBase +class MANGOS_DLL_SPEC PathMovementBase { public: PathMovementBase() : i_currentNode(0) {} @@ -66,9 +66,9 @@ template class WaypointMovementGenerator; template<> -class WaypointMovementGenerator +class MANGOS_DLL_SPEC WaypointMovementGenerator : public MovementGeneratorMedium< Creature, WaypointMovementGenerator >, - public PathMovementBase + public PathMovementBase { public: WaypointMovementGenerator(Creature&) : i_nextMoveTime(0), m_isArrivalDone(false), m_lastReachedWaypoint(0) {} @@ -78,21 +78,21 @@ class WaypointMovementGenerator void Finalize(Creature&); void Reset(Creature& u); bool Update(Creature& u, const uint32& diff); - - void MovementInform(Creature&); + void InitializeWaypointPath(Creature& u, int32 id, WaypointPathOrigin wpSource, uint32 initialDelay, uint32 overwriteEntry); MovementGeneratorType GetMovementGeneratorType() const { return WAYPOINT_MOTION_TYPE; } - // now path movement implmementation - void LoadPath(Creature& c); - - bool GetResetPosition(Creature&, float& x, float& y, float& z) const; + bool GetResetPosition(Creature&, float& /*x*/, float& /*y*/, float& /*z*/, float& /*o*/) const; + uint32 getLastReachedWaypoint() const { return m_lastReachedWaypoint; } + void GetPathInformation(int32& pathId, WaypointPathOrigin& wpOrigin) const { pathId = m_pathId; wpOrigin = m_PathOrigin; } + void GetPathInformation(std::ostringstream& oss) const; void AddToWaypointPauseTime(int32 waitTimeDiff); - - uint32 getLastReachedWaypoint() const { return m_lastReachedWaypoint; } + bool SetNextWaypoint(uint32 pointId); private: + void LoadPath(Creature& c, int32 id, WaypointPathOrigin wpOrigin, uint32 overwriteEntry); + void Stop(int32 time) { i_nextMoveTime.Reset(time); } bool Stopped(Creature& u); bool CanMove(int32 diff, Creature& u); @@ -100,11 +100,12 @@ class WaypointMovementGenerator void OnArrived(Creature&); void StartMove(Creature&); - void StartMoveNow(Creature& creature); - ShortTimeTracker i_nextMoveTime; bool m_isArrivalDone; - uint32 m_lastReachedWaypoint; + uint32 m_lastReachedWaypoint; + + int32 m_pathId; + WaypointPathOrigin m_PathOrigin; }; /** FlightPathMovementGenerator generates movement of the player for the paths @@ -133,7 +134,7 @@ class FlightPathMovementGenerator void SetCurrentNodeAfterTeleport(); void SkipCurrentNode() { ++i_currentNode; } void DoEventIfAny(Player& player, TaxiPathNodeEntry const& node, bool departure); - bool GetResetPosition(Player&, float& x, float& y, float& z) const; + bool GetResetPosition(Player&, float& x, float& y, float& z, float& o) const; }; #endif diff --git a/src/game/Object/AggressorAI.cpp b/src/game/Object/AggressorAI.cpp index 72ca24e1a..9cbfff38b 100644 --- a/src/game/Object/AggressorAI.cpp +++ b/src/game/Object/AggressorAI.cpp @@ -147,7 +147,7 @@ AggressorAI::IsVisible(Unit* pl) const void AggressorAI::AttackStart(Unit* u) { - if (!u) + if (!u || !m_creature->CanAttackByItself()) return; if (m_creature->Attack(u, true)) diff --git a/src/game/Object/ArenaTeam.cpp b/src/game/Object/ArenaTeam.cpp index bb310b62e..0a5e46b22 100644 --- a/src/game/Object/ArenaTeam.cpp +++ b/src/game/Object/ArenaTeam.cpp @@ -351,8 +351,6 @@ void ArenaTeam::Disband(WorldSession* session) void ArenaTeam::Roster(WorldSession* session) { - Player* pl = NULL; - uint8 unk308 = 0; WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100); @@ -363,7 +361,7 @@ void ArenaTeam::Roster(WorldSession* session) for (MemberList::const_iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { - pl = sObjectMgr.GetPlayer(itr->guid); + Player* pl = sObjectMgr.GetPlayer(itr->guid); data << itr->guid; // guid data << uint8((pl ? 1 : 0)); // online flag diff --git a/src/game/Object/Calendar.cpp b/src/game/Object/Calendar.cpp index 35282f193..0d44d1d46 100644 --- a/src/game/Object/Calendar.cpp +++ b/src/game/Object/Calendar.cpp @@ -353,7 +353,7 @@ void CalendarMgr::RemoveEvent(uint64 eventId, Player* remover) // Add invit to an event and inform client // some check done before so it may fail and raison is sent to client // return value is the CalendarInvite pointer on success -CalendarInvite* CalendarMgr::AddInvite(CalendarEvent* event, ObjectGuid const& senderGuid, ObjectGuid const& inviteeGuid, CalendarInviteStatus status, CalendarModerationRank rank, std::string text, time_t statusTime) +CalendarInvite* CalendarMgr::AddInvite(CalendarEvent* event, ObjectGuid const& senderGuid, ObjectGuid const& inviteeGuid, CalendarInviteStatus status, CalendarModerationRank rank, const std::string& text, time_t statusTime) { Player* sender = sObjectMgr.GetPlayer(senderGuid); if (!event || !sender) @@ -481,7 +481,7 @@ void CalendarMgr::CopyEvent(uint64 eventId, time_t newTime, ObjectGuid const& gu return; if (newEvent->IsGuildAnnouncement()) - AddInvite(newEvent, guid, guid, CALENDAR_STATUS_CONFIRMED, CALENDAR_RANK_OWNER, "", time(NULL)); + AddInvite(newEvent, guid, guid, CALENDAR_STATUS_CONFIRMED, CALENDAR_RANK_OWNER, "", time(nullptr)); else { // copy all invitees, set new owner as the one who make the copy, set invitees status to invited @@ -490,18 +490,19 @@ void CalendarMgr::CopyEvent(uint64 eventId, time_t newTime, ObjectGuid const& gu while (ci_itr != cInvMap->end()) { - if (ci_itr->second->InviteeGuid == guid) + const CalendarInvite* invite = ci_itr->second; + if (invite->InviteeGuid == guid) { - AddInvite(newEvent, guid, ci_itr->second->InviteeGuid, CALENDAR_STATUS_CONFIRMED, CALENDAR_RANK_OWNER, "", time(NULL)); + AddInvite(newEvent, guid, invite->InviteeGuid, CALENDAR_STATUS_CONFIRMED, CALENDAR_RANK_OWNER, "", time(nullptr)); } else { CalendarModerationRank rank = CALENDAR_RANK_PLAYER; // copy moderator rank - if (ci_itr->second->Rank == CALENDAR_RANK_MODERATOR) + if (invite->Rank == CALENDAR_RANK_MODERATOR) rank = CALENDAR_RANK_MODERATOR; - AddInvite(newEvent, guid, ci_itr->second->InviteeGuid, CALENDAR_STATUS_INVITED, rank, "", time(NULL)); + AddInvite(newEvent, guid, invite->InviteeGuid, CALENDAR_STATUS_INVITED, rank, "", time(nullptr)); } ++ci_itr; } diff --git a/src/game/Object/Calendar.h b/src/game/Object/Calendar.h index 324cb43af..6a1432257 100644 --- a/src/game/Object/Calendar.h +++ b/src/game/Object/Calendar.h @@ -234,8 +234,8 @@ class CalendarMgr CalendarEvent* AddEvent(ObjectGuid const& guid, std::string title, std::string description, uint32 type, uint32 repeatable, uint32 maxInvites, int32 dungeonId, time_t eventTime, time_t unkTime, uint32 flags); - - CalendarInvite* AddInvite(CalendarEvent* event, ObjectGuid const& senderGuid, ObjectGuid const& inviteeGuid, CalendarInviteStatus status, CalendarModerationRank rank, std::string text, time_t statusTime); + + CalendarInvite* AddInvite(CalendarEvent* event, ObjectGuid const& senderGuid, ObjectGuid const& inviteeGuid, CalendarInviteStatus status, CalendarModerationRank rank, const std::string& text, time_t statusTime); void RemoveEvent(uint64 eventId, Player* remover); bool RemoveInvite(uint64 eventId, uint64 inviteId, ObjectGuid const& removerGuid); diff --git a/src/game/Object/Creature.cpp b/src/game/Object/Creature.cpp index 796024cea..21bb0fddd 100644 --- a/src/game/Object/Creature.cpp +++ b/src/game/Object/Creature.cpp @@ -168,8 +168,7 @@ Creature::Creature(CreatureSubtype subtype) : Unit(), m_corpseDecayTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_aggroDelay(0), m_respawnradius(5.0f), m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), - m_regenHealth(true), m_AI_locked(false), m_IsDeadByDefault(false), - m_temporaryFactionFlags(TEMPFACTION_NONE), + m_AI_locked(false), m_IsDeadByDefault(false), m_temporaryFactionFlags(TEMPFACTION_NONE), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_creatureInfo(NULL) { @@ -252,6 +251,12 @@ void Creature::RemoveCorpse() if (AI()) { AI()->CorpseRemoved(respawnDelay); } + if (m_isCreatureLinkingTrigger) + GetMap()->GetCreatureLinkingHolder()->DoCreatureLinkingEvent(LINKING_EVENT_DESPAWN, this); + + if (InstanceData* mapInstance = GetInstanceData()) + mapInstance->OnCreatureDespawn(this); + // script can set time (in seconds) explicit, override the original if (respawnDelay) { m_respawnTime = time(NULL) + respawnDelay; } @@ -335,6 +340,24 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender); + // set PowerType based on unit class + switch (cinfo->UnitClass) + { + case CLASS_WARRIOR: + SetPowerType(POWER_RAGE); + break; + case CLASS_PALADIN: + case CLASS_MAGE: + SetPowerType(POWER_MANA); + break; + case CLASS_ROGUE: + SetPowerType(POWER_ENERGY); + break; + default: + sLog.outErrorDb("Creature (Entry: %u) has unhandled unit class. Power type will not be set!", Entry); + break; + } + // Load creature equipment if (eventData && eventData->equipment_id) { @@ -663,33 +686,68 @@ void Creature::RegenerateAll(uint32 update_diff) if (!IsInCombat() || IsPolymorphed()) RegenerateHealth(); - RegenerateMana(); + RegeneratePower(); m_regenTimer = REGEN_TIME_FULL; } -void Creature::RegenerateMana() +void Creature::RegeneratePower() { - uint32 curValue = GetPower(POWER_MANA); - uint32 maxValue = GetMaxPower(POWER_MANA); + if (!IsRegeneratingPower()) + return; + + Powers powerType = GetPowerType(); + uint32 curValue = GetPower(powerType); + uint32 maxValue = GetMaxPower(powerType); if (curValue >= maxValue) return; - uint32 addvalue = 0; + float addValue = 0.0f; - // Combat and any controlled creature - if (IsInCombat() || GetCharmerOrOwnerGuid()) + switch (powerType) { - float ManaIncreaseRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_MANA); - float Spirit = GetStat(STAT_SPIRIT); + case POWER_MANA: + // Combat and any controlled creature + if (IsInCombat() || GetCharmerOrOwnerGuid()) + { + float ManaIncreaseRate = sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_MANA); + float Spirit = GetStat(STAT_SPIRIT); - addvalue = uint32((Spirit / 5.0f + 17.0f) * ManaIncreaseRate); + addValue = uint32(Spirit / 5.0f + 17.0f) * ManaIncreaseRate; + } + else + addValue = maxValue / 3.0f; + break; + case POWER_ENERGY: + // ToDo: for vehicle this is different - NEEDS TO BE FIXED! + addValue = 20 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_ENERGY); + break; + case POWER_FOCUS: + addValue = 24 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_FOCUS); + break; + default: + return; } - else - addvalue = maxValue / 3; - ModifyPower(POWER_MANA, addvalue); + // Apply modifiers (if any) + AuraList const& ModPowerRegenAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); + for (AuraList::const_iterator i = ModPowerRegenAuras.begin(); i != ModPowerRegenAuras.end(); ++i) + { + Modifier const* modifier = (*i)->GetModifier(); + if (modifier->m_miscvalue == int32(powerType)) + addValue += modifier->m_amount; + } + + AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); + for (AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) + { + Modifier const* modifier = (*i)->GetModifier(); + if (modifier->m_miscvalue == int32(powerType)) + addValue *= (modifier->m_amount + 100) / 100.0f; + } + + ModifyPower(powerType, int32(addValue)); } void Creature::RegenerateHealth() @@ -1237,12 +1295,12 @@ void Creature::SelectLevel(const CreatureInfo* cinfo, float percentHealth /*= 10 switch (i) { - case POWER_MANA: maxValue = mana; break; - case POWER_RAGE: maxValue = 0; break; - case POWER_FOCUS: maxValue = POWER_FOCUS_DEFAULT; break; - case POWER_ENERGY: maxValue = POWER_ENERGY_DEFAULT * cinfo->PowerMultiplier; break; - case POWER_RUNE: maxValue = 0; break; - case POWER_RUNIC_POWER: maxValue = 0; break; + case POWER_MANA: maxValue = mana; break; + case POWER_RAGE: maxValue = 0; break; + case POWER_FOCUS: maxValue = POWER_FOCUS_DEFAULT; break; + case POWER_ENERGY: maxValue = POWER_ENERGY_DEFAULT * cinfo->PowerMultiplier; break; + case POWER_RUNE: maxValue = 0; break; + case POWER_RUNIC_POWER: maxValue = 0; break; } uint32 value = maxValue; @@ -1313,22 +1371,22 @@ float Creature::_GetDamageMod(int32 Rank) } } -float Creature::GetSpellDamageMod(int32 Rank) +float Creature::_GetSpellDamageMod(int32 Rank) { switch (Rank) // define rates for each elite rank { - case CREATURE_ELITE_NORMAL: - return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_NORMAL_SPELLDAMAGE); - case CREATURE_ELITE_ELITE: - return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE); - case CREATURE_ELITE_RAREELITE: - return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE); - case CREATURE_ELITE_WORLDBOSS: - return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE); - case CREATURE_ELITE_RARE: - return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_RARE_SPELLDAMAGE); - default: - return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE); + case CREATURE_ELITE_NORMAL: + return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_NORMAL_SPELLDAMAGE); + case CREATURE_ELITE_ELITE: + return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE); + case CREATURE_ELITE_RAREELITE: + return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE); + case CREATURE_ELITE_WORLDBOSS: + return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE); + case CREATURE_ELITE_RARE: + return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_RARE_SPELLDAMAGE); + default: + return sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE); } } @@ -1581,7 +1639,7 @@ void Creature::SetDeathState(DeathState s) if ((s == JUST_DIED && !m_IsDeadByDefault) || (s == JUST_ALIVED && m_IsDeadByDefault)) { m_corpseDecayTimer = m_corpseDelay * IN_MILLISECONDS; // the max/default time for corpse decay (before creature is looted/AllLootRemovedFromCorpse() is called) - m_respawnTime = time(NULL) + m_respawnDelay; // respawn delay (spawntimesecs) + m_respawnTime = time(nullptr) + m_respawnDelay; // respawn delay (spawntimesecs) // always save boss respawn time at death to prevent crash cheating if (sWorld.getConfig(CONFIG_BOOL_SAVE_RESPAWN_TIME_IMMEDIATELY) || IsWorldBoss()) @@ -1614,7 +1672,7 @@ void Creature::SetDeathState(DeathState s) Unit::SetDeathState(ALIVE); SetHealth(GetMaxHealth()); - SetLootRecipient(NULL); + SetLootRecipient(nullptr); if (GetTemporaryFactionFlags() & TEMPFACTION_RESTORE_RESPAWN) ClearTemporaryFaction(); @@ -2523,6 +2581,10 @@ void Creature::SetFactionTemporary(uint32 factionId, uint32 tempFactionFlags) RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_PASSIVE) RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_PACIFIED) + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); + if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_NOT_SELECTABLE) + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } void Creature::ClearTemporaryFaction() @@ -2535,13 +2597,17 @@ void Creature::ClearTemporaryFaction() // Reset to original faction setFaction(GetCreatureInfo()->FactionAlliance); - // Reset UNIT_FLAG_NON_ATTACKABLE, UNIT_FLAG_OOC_NOT_ATTACKABLE or UNIT_FLAG_PASSIVE flags + // Reset UNIT_FLAG_NON_ATTACKABLE, UNIT_FLAG_OOC_NOT_ATTACKABLE, UNIT_FLAG_PASSIVE, UNIT_FLAG_PACIFIED or UNIT_FLAG_NOT_SELECTABLE flags if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_NON_ATTACKABLE && GetCreatureInfo()->UnitFlags & UNIT_FLAG_NON_ATTACKABLE) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_OOC_NOT_ATTACK && GetCreatureInfo()->UnitFlags & UNIT_FLAG_OOC_NOT_ATTACKABLE && !IsInCombat()) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_PASSIVE && GetCreatureInfo()->UnitFlags & UNIT_FLAG_PASSIVE) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_PACIFIED && GetCreatureInfo()->UnitFlags & UNIT_FLAG_PACIFIED) + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); + if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_NOT_SELECTABLE && GetCreatureInfo()->UnitFlags & UNIT_FLAG_NOT_SELECTABLE) + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_temporaryFactionFlags = TEMPFACTION_NONE; } diff --git a/src/game/Object/Creature.h b/src/game/Object/Creature.h index a49fcd444..f40b3ef44 100644 --- a/src/game/Object/Creature.h +++ b/src/game/Object/Creature.h @@ -612,6 +612,8 @@ enum TemporaryFactionFlags // Used at real fact TEMPFACTION_TOGGLE_NON_ATTACKABLE = 0x08, // Remove UNIT_FLAG_NON_ATTACKABLE(0x02) when faction is changed (reapply when temp-faction is removed) TEMPFACTION_TOGGLE_OOC_NOT_ATTACK = 0x10, // Remove UNIT_FLAG_OOC_NOT_ATTACKABLE(0x100) when faction is changed (reapply when temp-faction is removed) TEMPFACTION_TOGGLE_PASSIVE = 0x20, // Remove UNIT_FLAG_PASSIVE(0x200) when faction is changed (reapply when temp-faction is removed) + TEMPFACTION_TOGGLE_PACIFIED = 0x40, // Remove UNIT_FLAG_PACIFIED(0x20000) when faction is changed (reapply when temp-faction is removed) + TEMPFACTION_TOGGLE_NOT_SELECTABLE = 0x80, // Remove UNIT_FLAG_NOT_SELECTABLE(0x2000000) when faction is changed (reapply when temp-faction is removed) TEMPFACTION_ALL, }; @@ -732,7 +734,10 @@ class Creature : public Unit void UpdateAttackPowerAndDamage(bool ranged = false) override; void UpdateDamagePhysical(WeaponAttackType attType) override; uint32 GetCurrentEquipmentId() { return m_equipmentId; } - float GetSpellDamageMod(int32 Rank); + + static float _GetHealthMod(int32 Rank); ///< Get custom factor to scale health (default 1, CONFIG_FLOAT_RATE_CREATURE_*_HP) + static float _GetDamageMod(int32 Rank); ///< Get custom factor to scale damage (default 1, CONFIG_FLOAT_RATE_*_DAMAGE) + static float _GetSpellDamageMod(int32 Rank); ///< Get custom factor to scale spell damage (default 1, CONFIG_FLOAT_RATE_*_SPELLDAMAGE) VendorItemData const* GetVendorItems() const; VendorItemData const* GetVendorTemplateItems() const; @@ -921,9 +926,6 @@ class Creature : public Unit void _RealtimeSetCreatureInfo(); - static float _GetHealthMod(int32 Rank); - static float _GetDamageMod(int32 Rank); - uint32 m_lootMoney; ObjectGuid m_lootRecipientGuid; // player who will have rights for looting if m_lootGroupRecipient==0 or group disbanded uint32 m_lootGroupRecipientId; // group who will have rights for looting if set and exist @@ -937,7 +939,7 @@ class Creature : public Unit float m_respawnradius; CreatureSubtype m_subtype; // set in Creatures subclasses for fast it detect without dynamic_cast use - void RegenerateMana(); + void RegeneratePower(); void RegenerateHealth(); MovementGeneratorType m_defaultMovementType; Cell m_currentCell; // store current cell where creature listed @@ -946,7 +948,6 @@ class Creature : public Unit // below fields has potential for optimization bool m_AlreadyCallAssistance; bool m_AlreadySearchedAssistance; - bool m_regenHealth; bool m_AI_locked; bool m_IsDeadByDefault; uint32 m_temporaryFactionFlags; // used for real faction changes (not auras etc) diff --git a/src/game/Object/CreatureAI.cpp b/src/game/Object/CreatureAI.cpp index 7dd4916c2..fadf1859b 100644 --- a/src/game/Object/CreatureAI.cpp +++ b/src/game/Object/CreatureAI.cpp @@ -154,12 +154,13 @@ void CreatureAI::SetCombatMovement(bool enable, bool stopOrStartMovement /*=fals void CreatureAI::HandleMovementOnAttackStart(Unit* victim) { + MotionMaster* creatureMotion = m_creature->GetMotionMaster(); if (m_isCombatMovement) - m_creature->GetMotionMaster()->MoveChase(victim, m_attackDistance, m_attackAngle); + creatureMotion->MoveChase(victim, m_attackDistance, m_attackAngle); // TODO - adapt this to only stop OOC-MMGens when MotionMaster rewrite is finished - else if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE || m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == RANDOM_MOTION_TYPE) + else if (creatureMotion->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE || creatureMotion->GetCurrentMovementGeneratorType() == RANDOM_MOTION_TYPE) { - m_creature->GetMotionMaster()->MoveIdle(); + creatureMotion->MoveIdle(); m_creature->StopMoving(); } } @@ -223,10 +224,20 @@ void CreatureAI::SendAIEventAround(AIEventType eventType, Unit* pInvoker, uint32 { std::list receiverList; - // Use this check here to collect only assitable creatures in case of CALL_ASSISTANCE, else be less strict - MaNGOS::AnyAssistCreatureInRangeCheck u_check(m_creature, eventType == AI_EVENT_CALL_ASSISTANCE ? pInvoker : NULL, fRadius); - MaNGOS::CreatureListSearcher searcher(receiverList, u_check); - Cell::VisitGridObjects(m_creature, searcher, fRadius); + // Allow sending custom AI events to all units in range + if (eventType >= AI_EVENT_CUSTOM_EVENTAI_A && eventType <= AI_EVENT_CUSTOM_EVENTAI_F && eventType != AI_EVENT_GOT_CCED) + { + MaNGOS::AnyUnitInObjectRangeCheck u_check(m_creature, fRadius); + MaNGOS::CreatureListSearcher searcher(receiverList, u_check); + Cell::VisitGridObjects(m_creature, searcher, fRadius); + } + else + { + // Use this check here to collect only assitable creatures in case of CALL_ASSISTANCE, else be less strict + MaNGOS::AnyAssistCreatureInRangeCheck u_check(m_creature, eventType == AI_EVENT_CALL_ASSISTANCE ? pInvoker : NULL, fRadius); + MaNGOS::CreatureListSearcher searcher(receiverList, u_check); + Cell::VisitGridObjects(m_creature, searcher, fRadius); + } if (!receiverList.empty()) { diff --git a/src/game/Object/CreatureAI.h b/src/game/Object/CreatureAI.h index bcb9d00ec..c701d96de 100644 --- a/src/game/Object/CreatureAI.h +++ b/src/game/Object/CreatureAI.h @@ -85,19 +85,23 @@ enum AIEventType AI_EVENT_CUSTOM_EVENTAI_A = 5, // Sender = Npc that throws custom event, Invoker = TARGET_T_ACTION_INVOKER (if exists) AI_EVENT_CUSTOM_EVENTAI_B = 6, // Sender = Npc that throws custom event, Invoker = TARGET_T_ACTION_INVOKER (if exists) AI_EVENT_GOT_CCED = 7, // Sender = CCed Npc, Invoker = Caster that CCed - MAXIMAL_AI_EVENT_EVENTAI = 8, + AI_EVENT_CUSTOM_EVENTAI_C = 8, // Sender = Npc that throws custom event, Invoker = TARGET_T_ACTION_INVOKER (if exists) + AI_EVENT_CUSTOM_EVENTAI_D = 9, // Sender = Npc that throws custom event, Invoker = TARGET_T_ACTION_INVOKER (if exists) + AI_EVENT_CUSTOM_EVENTAI_E = 10, // Sender = Npc that throws custom event, Invoker = TARGET_T_ACTION_INVOKER (if exists) + AI_EVENT_CUSTOM_EVENTAI_F = 11, // Sender = Npc that throws custom event, Invoker = TARGET_T_ACTION_INVOKER (if exists) + MAXIMAL_AI_EVENT_EVENTAI = 12, // Internal Use - AI_EVENT_CALL_ASSISTANCE = 10, // Sender = Attacked Npc, Invoker = Enemy + AI_EVENT_CALL_ASSISTANCE = 13, // Sender = Attacked Npc, Invoker = Enemy - // Predefined for SD3 + // Predefined for SD2 AI_EVENT_START_ESCORT = 100, // Invoker = Escorting Player AI_EVENT_START_ESCORT_B = 101, // Invoker = Escorting Player AI_EVENT_START_EVENT = 102, // Invoker = EventStarter AI_EVENT_START_EVENT_A = 103, // Invoker = EventStarter AI_EVENT_START_EVENT_B = 104, // Invoker = EventStarter - // Some IDs for special cases in SD3 + // Some IDs for special cases in SD2 AI_EVENT_CUSTOM_A = 1000, AI_EVENT_CUSTOM_B = 1001, AI_EVENT_CUSTOM_C = 1002, diff --git a/src/game/Object/CreatureEventAI.cpp b/src/game/Object/CreatureEventAI.cpp index 79b694a23..21bea214b 100644 --- a/src/game/Object/CreatureEventAI.cpp +++ b/src/game/Object/CreatureEventAI.cpp @@ -91,16 +91,21 @@ inline bool IsEventFlagsFitForNormalMap(uint8 eFlags) CreatureEventAI::CreatureEventAI(Creature* c) : CreatureAI(c), m_Phase(0), m_MeleeEnabled(true), + m_DynamicMovement(false), + m_HasOOCLoSEvent(false), m_InvinceabilityHpLevel(0), m_throwAIEventMask(0), - m_throwAIEventStep(0) + m_throwAIEventStep(0), + m_LastSpellMaxRange(0) { // Need make copy for filter unneeded steps and safe in case table reload CreatureEventAI_Event_Map::const_iterator creatureEventsItr = sEventAIMgr.GetCreatureEventAIMap().find(m_creature->GetEntry()); if (creatureEventsItr != sEventAIMgr.GetCreatureEventAIMap().end()) { uint32 events_count = 0; - for (CreatureEventAI_Event_Vec::const_iterator i = creatureEventsItr->second.begin(); i != creatureEventsItr->second.end(); ++i) + + const CreatureEventAI_Event_Vec& creatureEvent = creatureEventsItr->second; + for (CreatureEventAI_Event_Vec::const_iterator i = creatureEvent.begin(); i != creatureEvent.end(); ++i) { // Debug check #ifndef MANGOS_DEBUG @@ -119,27 +124,33 @@ CreatureEventAI::CreatureEventAI(Creature* c) : CreatureAI(c), } // EventMap had events but they were not added because they must be for instance if (events_count == 0) - sLog.outErrorEventAI("Creature %u has events but no events added to list because of instance flags.", m_creature->GetEntry()); + sLog.outErrorEventAI("Creature %u has events but no events added to list because of instance flags (spawned in map %u, difficulty %u).", m_creature->GetEntry(), m_creature->GetMapId(), m_creature->GetMap()->GetDifficulty()); else { m_CreatureEventAIList.reserve(events_count); - for (CreatureEventAI_Event_Vec::const_iterator i = creatureEventsItr->second.begin(); i != creatureEventsItr->second.end(); ++i) + for (CreatureEventAI_Event_Vec::const_iterator i = creatureEvent.begin(); i != creatureEvent.end(); ++i) { // Debug check #ifndef MANGOS_DEBUG if (i->event_flags & EFLAG_DEBUG_ONLY) continue; #endif + bool storeEvent = false; if (m_creature->GetMap()->IsDungeon()) { if ((1 << (m_creature->GetMap()->GetSpawnMode() + 1)) & i->event_flags) - { - // event flagged for instance mode - m_CreatureEventAIList.push_back(CreatureEventAIHolder(*i)); - } + storeEvent = true; } else if (IsEventFlagsFitForNormalMap(i->event_flags)) + storeEvent = true; + + if (storeEvent) + { m_CreatureEventAIList.push_back(CreatureEventAIHolder(*i)); + // Cache for fast use + if (i->event_type == EVENT_T_OOC_LOS) + m_HasOOCLoSEvent = true; + } } } } @@ -1191,7 +1202,7 @@ void CreatureEventAI::EnterCombat(Unit* enemy) void CreatureEventAI::AttackStart(Unit* who) { - if (!who) + if (!who || !m_creature->CanAttackByItself()) return; if (m_creature->Attack(who, m_MeleeEnabled)) diff --git a/src/game/Object/CreatureEventAI.h b/src/game/Object/CreatureEventAI.h index 2c304c027..d62304dea 100644 --- a/src/game/Object/CreatureEventAI.h +++ b/src/game/Object/CreatureEventAI.h @@ -689,6 +689,7 @@ class CreatureEventAI : public CreatureAI // Note that Step 100 means that AI_EVENT_GOT_FULL_HEALTH was sent // Steps 0..2 correspond to AI_EVENT_LOST_SOME_HEALTH(90%), AI_EVENT_LOST_HEALTH(50%), AI_EVENT_CRITICAL_HEALTH(10%) uint32 m_throwAIEventStep; // Used for damage taken/ received heal + float m_LastSpellMaxRange; // Maximum spell range that was cast during dynamic movement }; #endif diff --git a/src/game/Object/GameObject.cpp b/src/game/Object/GameObject.cpp index 58415db44..e7c31a891 100644 --- a/src/game/Object/GameObject.cpp +++ b/src/game/Object/GameObject.cpp @@ -140,7 +140,7 @@ void GameObject::RemoveFromWorld() Object::RemoveFromWorld(); } -bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, QuaternionData rotation, uint8 animprogress, GOState go_state) +bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, const QuaternionData& rotation, uint8 animprogress, GOState go_state) { MANGOS_ASSERT(map); Relocate(x, y, z, ang); @@ -1134,8 +1134,8 @@ void GameObject::Use(Unit* user) // Some may have have animation and/or are expected to despawn. // TODO: Improve this when more information is available, currently these traps are known that must send the anim (Onyxia/ Heigan Fissures/ Trap in DireMaul) - if (GetDisplayId() == 4392 || GetDisplayId() == 4472 || GetDisplayId() == 6785 || GetDisplayId() == 3073) - { SendGameObjectCustomAnim(GetObjectGuid()); } + if (GetDisplayId() == 4392 || GetDisplayId() == 4472 || GetDisplayId() == 4491 || GetDisplayId() == 6785 || GetDisplayId() == 3073 || GetDisplayId() == 7998) + SendGameObjectCustomAnim(GetObjectGuid()); // TODO: Despawning of traps? (Also related to code in ::Update) return; @@ -1733,7 +1733,7 @@ void GameObject::SetWorldRotation(float qx, float qy, float qz, float qw) m_worldRotation.w = rotation.w; } -void GameObject::SetTransportPathRotation(QuaternionData rotation) +void GameObject::SetTransportPathRotation(const QuaternionData& rotation) { SetFloatValue(GAMEOBJECT_PARENTROTATION + 0, rotation.x); SetFloatValue(GAMEOBJECT_PARENTROTATION + 1, rotation.y); diff --git a/src/game/Object/GameObject.h b/src/game/Object/GameObject.h index ee29180b5..c625405f2 100644 --- a/src/game/Object/GameObject.h +++ b/src/game/Object/GameObject.h @@ -647,9 +647,8 @@ class GameObject : public WorldObject void AddToWorld() override; void RemoveFromWorld() override; - bool Create(uint32 guidlow, uint32 name_id, Map* map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state); bool Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, - QuaternionData rotation = QuaternionData(), uint8 animprogress = GO_ANIMPROGRESS_DEFAULT, GOState go_state = GO_STATE_READY); + const QuaternionData& rotation = QuaternionData(), uint8 animprogress = GO_ANIMPROGRESS_DEFAULT, GOState go_state = GO_STATE_READY); void Update(uint32 update_diff, uint32 p_time) override; GameObjectInfo const* GetGOInfo() const; @@ -660,7 +659,7 @@ class GameObject : public WorldObject // z_rot, y_rot, x_rot - rotation angles around z, y and x axes void SetWorldRotationAngles(float z_rot, float y_rot, float x_rot); void SetWorldRotation(float qx, float qy, float qz, float qw); - void SetTransportPathRotation(QuaternionData rotation); // transforms(rotates) transport's path + void SetTransportPathRotation(const QuaternionData& rotation); // transforms(rotates) transport's path int64 GetPackedWorldRotation() const { return m_packedRotation; } // overwrite WorldObject function for proper name localization diff --git a/src/game/Object/Guild.cpp b/src/game/Object/Guild.cpp index 56e5ea633..0d8ad12ac 100644 --- a/src/game/Object/Guild.cpp +++ b/src/game/Object/Guild.cpp @@ -122,7 +122,7 @@ bool Guild::Create(Player* leader, std::string gname) m_LeaderGuid = leader->GetObjectGuid(); m_Name = gname; - GINFO = ""; + GINFO.clear(); MOTD = "No message set."; m_GuildBankMoney = 0; m_Id = sObjectMgr.GenerateGuildId(); @@ -319,8 +319,11 @@ bool Guild::CheckGuildStructure() // Allow only 1 guildmaster, set other to officer for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) - if (itr->second.RankId == GR_GUILDMASTER && m_LeaderGuid != itr->second.guid) - itr->second.ChangeRank(GR_OFFICER); + { + MemberSlot& member = itr->second; + if (member.RankId == GR_GUILDMASTER && m_LeaderGuid != member.guid) + member.ChangeRank(GR_OFFICER); + } return true; } @@ -580,18 +583,22 @@ bool Guild::ChangeMemberRank(ObjectGuid guid, uint8 newRank) void Guild::BroadcastToGuild(WorldSession* session, const std::string& msg, uint32 language) { - if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(), GR_RIGHT_GCHATSPEAK)) + if (!session) + return; + + Player* player = session->GetPlayer(); + if (!player || !HasRankRight(player->GetRank(), GR_RIGHT_GCHATSPEAK)) + return; + + WorldPacket data; + ChatHandler::BuildChatPacket(data, CHAT_MSG_GUILD, msg.c_str(), Language(language), player->GetChatTag(), player->GetObjectGuid(), player->GetName()); + + for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) { - WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_GUILD, msg.c_str(), Language(language), session->GetPlayer()->GetChatTag(), session->GetPlayer()->GetObjectGuid(), session->GetPlayer()->GetName()); + Player* pl = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first)); - for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) - { - Player* pl = ObjectAccessor::FindPlayer(ObjectGuid(HIGHGUID_PLAYER, itr->first)); - - if (pl && pl->GetSession() && HasRankRight(pl->GetRank(), GR_RIGHT_GCHATLISTEN) && !pl->GetSocial()->HasIgnore(session->GetPlayer()->GetObjectGuid())) - pl->GetSession()->SendPacket(&data); - } + if (pl && pl->GetSession() && HasRankRight(pl->GetRank(), GR_RIGHT_GCHATLISTEN) && !pl->GetSocial()->HasIgnore(player->GetObjectGuid())) + pl->GetSession()->SendPacket(&data); } } @@ -690,12 +697,12 @@ void Guild::MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 max return; } - MemberSlot const* member = &itr->second; - uint32 level = Player::GetLevelFromDB(member->guid); + MemberSlot const& member = itr->second; + uint32 level = Player::GetLevelFromDB(member.guid); - if (member->guid != session->GetPlayer()->GetObjectGuid() && level >= minLevel && level <= maxLevel && member->RankId <= minRank) + if (member.guid != session->GetPlayer()->GetObjectGuid() && level >= minLevel && level <= maxLevel && member.RankId <= minRank) { - data << member->guid.WriteAsPacked(); + data << member.guid.WriteAsPacked(); data << uint8(level); ++count; } @@ -1521,21 +1528,22 @@ uint32 Guild::GetMemberSlotWithdrawRem(uint32 LowGuid, uint8 TabId) if (itr == members.end()) return 0; - if (itr->second.RankId == GR_GUILDMASTER) + MemberSlot& member = itr->second; + if (member.RankId == GR_GUILDMASTER) return WITHDRAW_SLOT_UNLIMITED; - if ((GetBankRights(itr->second.RankId, TabId) & GUILD_BANK_RIGHT_VIEW_TAB) != GUILD_BANK_RIGHT_VIEW_TAB) + if ((GetBankRights(member.RankId, TabId) & GUILD_BANK_RIGHT_VIEW_TAB) != GUILD_BANK_RIGHT_VIEW_TAB) return 0; - uint32 curTime = uint32(time(NULL) / MINUTE); - if (curTime - itr->second.BankResetTimeTab[TabId] >= 24 * HOUR / MINUTE) + uint32 curTime = uint32(time(nullptr) / MINUTE); + if (curTime - member.BankResetTimeTab[TabId] >= 24 * HOUR / MINUTE) { - itr->second.BankResetTimeTab[TabId] = curTime; - itr->second.BankRemSlotsTab[TabId] = GetBankSlotPerDay(itr->second.RankId, TabId); + member.BankResetTimeTab[TabId] = curTime; + member.BankRemSlotsTab[TabId] = GetBankSlotPerDay(member.RankId, TabId); CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeTab%u='%u', BankRemSlotsTab%u='%u' WHERE guildid='%u' AND guid='%u'", - uint32(TabId), itr->second.BankResetTimeTab[TabId], uint32(TabId), itr->second.BankRemSlotsTab[TabId], m_Id, LowGuid); + uint32(TabId), member.BankResetTimeTab[TabId], uint32(TabId), member.BankRemSlotsTab[TabId], m_Id, LowGuid); } - return itr->second.BankRemSlotsTab[TabId]; + return member.BankRemSlotsTab[TabId]; } uint64 Guild::GetMemberMoneyWithdrawRem(uint32 LowGuid) @@ -1544,19 +1552,20 @@ uint64 Guild::GetMemberMoneyWithdrawRem(uint32 LowGuid) if (itr == members.end()) return 0; - if (itr->second.RankId == GR_GUILDMASTER) + MemberSlot& member = itr->second; + if (member.RankId == GR_GUILDMASTER) return WITHDRAW_MONEY_UNLIMITED; - uint32 curTime = uint32(time(NULL) / MINUTE); // minutes + uint32 curTime = uint32(time(nullptr) / MINUTE); // minutes // 24 hours - if (curTime > itr->second.BankResetTimeMoney + 24 * HOUR / MINUTE) + if (curTime > member.BankResetTimeMoney + 24 * HOUR / MINUTE) { - itr->second.BankResetTimeMoney = curTime; - itr->second.BankRemMoney = GetBankMoneyPerDay(itr->second.RankId); + member.BankResetTimeMoney = curTime; + member.BankRemMoney = GetBankMoneyPerDay(member.RankId); CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeMoney='%u', BankRemMoney='%u' WHERE guildid='%u' AND guid='%u'", - itr->second.BankResetTimeMoney, itr->second.BankRemMoney, m_Id, LowGuid); + member.BankResetTimeMoney, member.BankRemMoney, m_Id, LowGuid); } - return itr->second.BankRemMoney; + return member.BankRemMoney; } void Guild::SetBankMoneyPerDay(uint32 rankId, uint32 money) @@ -1570,8 +1579,11 @@ void Guild::SetBankMoneyPerDay(uint32 rankId, uint32 money) m_Ranks[rankId].BankMoneyPerDay = money; for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) - if (itr->second.RankId == rankId) - itr->second.BankResetTimeMoney = 0; + { + MemberSlot& member = itr->second; + if (member.RankId == rankId) + member.BankResetTimeMoney = 0; + } CharacterDatabase.PExecute("UPDATE guild_rank SET BankMoneyPerDay='%u' WHERE rid='%u' AND guildid='%u'", money, rankId, m_Id); CharacterDatabase.PExecute("UPDATE guild_member SET BankResetTimeMoney='0' WHERE guildid='%u' AND rank='%u'", m_Id, rankId); @@ -2401,10 +2413,9 @@ void Guild::MoveFromBankToChar(Player* pl, uint8 BankTab, uint8 BankTabSlot, uin { pl->MoveItemFromInventory(PlayerBag, PlayerSlot, true); pItemChar->DeleteFromInventoryDB(); + StoreItem(BankTab, gDest, pItemChar); } - if (pItemChar) - StoreItem(BankTab, gDest, pItemChar); pl->MoveItemToInventory(iDest, pItemBank, true); pl->SaveInventoryAndGoldToDB(); diff --git a/src/game/Object/ItemEnchantmentMgr.cpp b/src/game/Object/ItemEnchantmentMgr.cpp index cb6d5821d..00d8b1fa0 100644 --- a/src/game/Object/ItemEnchantmentMgr.cpp +++ b/src/game/Object/ItemEnchantmentMgr.cpp @@ -130,7 +130,8 @@ uint32 GetItemEnchantMod(int32 entry) double dRoll = rand_chance(); float fCount = 0; - for (EnchStoreList::const_iterator ench_iter = tab->second.begin(); ench_iter != tab->second.end(); ++ench_iter) + const EnchStoreList& enchantList = tab->second; + for (EnchStoreList::const_iterator ench_iter = enchantList.begin(); ench_iter != enchantList.end(); ++ench_iter) { fCount += ench_iter->chance; @@ -141,7 +142,7 @@ uint32 GetItemEnchantMod(int32 entry) dRoll = (irand(0, (int)floor(fCount * 100) + 1)) / 100; fCount = 0; - for (EnchStoreList::const_iterator ench_iter = tab->second.begin(); ench_iter != tab->second.end(); ++ench_iter) + for (EnchStoreList::const_iterator ench_iter = enchantList.begin(); ench_iter != enchantList.end(); ++ench_iter) { fCount += ench_iter->chance; diff --git a/src/game/Object/Object.cpp b/src/game/Object/Object.cpp index dc33c3577..4d7111678 100644 --- a/src/game/Object/Object.cpp +++ b/src/game/Object/Object.cpp @@ -1592,7 +1592,7 @@ namespace MaNGOS : i_object(obj), i_msgtype(msgtype), i_textData(textData), i_language(language), i_target(target) {} void operator()(WorldPacket& data, int32 loc_idx) { - char const* text = nullptr; + char const* text = NULL; if ((int32)i_textData->Content.size() > loc_idx + 1 && !i_textData->Content[loc_idx + 1].empty()) text = i_textData->Content[loc_idx + 1].c_str(); else diff --git a/src/game/Object/Object.h b/src/game/Object/Object.h index cae69f0c7..226c64efd 100644 --- a/src/game/Object/Object.h +++ b/src/game/Object/Object.h @@ -39,13 +39,15 @@ #define CONTACT_DISTANCE 0.5f #define INTERACTION_DISTANCE 5.0f #define ATTACK_DISTANCE 5.0f -#define MAX_VISIBILITY_DISTANCE 333.0f // max distance for visible object show, limited in 333 yards -#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents -#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards -#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards +#define INSPECT_DISTANCE 28.0f +#define TRADE_DISTANCE 11.11f +#define MAX_VISIBILITY_DISTANCE 333.0f // max distance for visible object show, limited in 333 yards +#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents +#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards +#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards #define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // currently used (correctly?) for any non Unit world objects. This is actually the bounding_radius, like player/creature from creature_model_data -#define DEFAULT_OBJECT_SCALE 1.0f // player/item Scale as default, npc/go from database, pets from dbc +#define DEFAULT_OBJECT_SCALE 1.0f // player/item scale as default, npc/go from database, pets from dbc #define MAX_STEALTH_DETECT_RANGE 45.0f @@ -601,8 +603,8 @@ class WorldObject : public Object virtual void SendMessageToSetInRange(WorldPacket* data, float dist, bool self) const; void SendMessageToSetExcept(WorldPacket* data, Player const* skipped_receiver) const; - void MonsterSay(const char* text, uint32 language, Unit const* target = nullptr) const; - void MonsterYell(const char* text, uint32 language, Unit const* target = nullptr) const; + void MonsterSay(const char* text, uint32 language, Unit const* target = NULL) const; + void MonsterYell(const char* text, uint32 language, Unit const* target = NULL) const; void MonsterTextEmote(const char* text, Unit const* target, bool IsBossEmote = false) const; void MonsterWhisper(const char* text, Unit const* target, bool IsBossWhisper = false) const; void MonsterText(MangosStringLocale const* textData, Unit const* target) const; diff --git a/src/game/Object/ObjectMgr.cpp b/src/game/Object/ObjectMgr.cpp index 2dfecf3aa..565f7a8e5 100644 --- a/src/game/Object/ObjectMgr.cpp +++ b/src/game/Object/ObjectMgr.cpp @@ -53,7 +53,9 @@ #include "InstanceData.h" #include "DB2Structure.h" #include "DB2Stores.h" -#include "PhaseMgr.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" #include @@ -192,15 +194,6 @@ ObjectMgr::~ObjectMgr() for (CacheTrainerSpellMap::iterator itr = m_mCacheTrainerSpellMap.begin(); itr != m_mCacheTrainerSpellMap.end(); ++itr) itr->second.Clear(); - - for (PhaseDefinitionStore::iterator itr = _PhaseDefinitionStore.begin(); itr != _PhaseDefinitionStore.end(); ++itr) - { - for (PhaseDefinitionContainer::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) - delete *itr2; - } - - for (SpellPhaseStore::iterator itr = _SpellPhaseStore.begin(); itr != _SpellPhaseStore.end(); ++itr) - delete itr->second; } Group* ObjectMgr::GetGroupById(uint32 id) const @@ -984,14 +977,14 @@ void ObjectMgr::LoadCreatureClassLvlStats() CreatureClassLvlStats const* ObjectMgr::GetCreatureClassLvlStats(uint32 level, uint32 unitClass, int32 expansion) const { if (expansion < 0) - return nullptr; + return NULL; CreatureClassLvlStats const* cCLS = &m_creatureClassLvlStats[level][classToIndex[unitClass]][expansion]; if (cCLS->BaseHealth != 0 && cCLS->BaseDamage > 0.1f) return cCLS; - return nullptr; + return NULL; } void ObjectMgr::LoadEquipmentTemplates() @@ -5091,19 +5084,17 @@ void ObjectMgr::LoadGossipText() BarGoLink bar(1); bar.step(); - sLog.outString(); sLog.outString(">> Loaded %u npc texts", count); + sLog.outString(); return; } - int cic; - BarGoLink bar(result->GetRowCount()); do { ++count; - cic = 0; + int cic = 0; Field* fields = result->Fetch(); @@ -5135,8 +5126,8 @@ void ObjectMgr::LoadGossipText() } while (result->NextRow()); - sLog.outString(); sLog.outString(">> Loaded %u npc texts", count); + sLog.outString(); delete result; } @@ -7354,11 +7345,15 @@ void ObjectMgr::LoadNPCSpellClickSpells() continue; } - SpellEntry const* spellinfo = sSpellStore.LookupEntry(info.spellId); - if (!spellinfo) + // spell can be 0 for special or custom cases + if (info.spellId) { - sLog.outErrorDb("Table npc_spellclick_spells references unknown spellid %u. Skipping entry.", info.spellId); - continue; + SpellEntry const* spellinfo = sSpellStore.LookupEntry(info.spellId); + if (!spellinfo) + { + sLog.outErrorDb("Table npc_spellclick_spells references unknown spellid %u. Skipping entry.", info.spellId); + continue; + } } if (info.conditionId && !sConditionStorage.LookupEntry(info.conditionId)) @@ -7704,7 +7699,7 @@ static LanguageType GetRealmLanguageType(bool create) } } -bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bool create = false) +bool isValidString(const std::wstring& wstr, uint32 strictMask, bool numericOrSpace, bool create = false) { if (strictMask == 0) // any language, ignore realm { @@ -8159,8 +8154,7 @@ bool ObjectMgr::IsPlayerMeetToCondition(uint16 conditionId, Player const* pPlaye return false; } - -bool ObjectMgr::CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names) +bool ObjectMgr::CheckDeclinedNames(const std::wstring& mainpart, DeclinedName const& names) { for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { @@ -8490,6 +8484,16 @@ bool PlayerCondition::Meets(Player const* player, Map const* map, WorldObject co case 3: // Creature source is dead return !source || source->GetTypeId() != TYPEID_UNIT || !((Unit*)source)->IsAlive(); } + case CONDITION_CREATURE_IN_RANGE: + { + Creature* creature = NULL; + + MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check(*player, m_value1, true, false, m_value2, true); + MaNGOS::CreatureLastSearcher searcher(creature, creature_check); + Cell::VisitGridObjects(player, searcher, m_value2); + + return creature; + } default: return false; } @@ -8945,6 +8949,19 @@ bool PlayerCondition::IsValid(uint16 entry, ConditionType condition, uint32 valu } break; } + case CONDITION_CREATURE_IN_RANGE: + { + if (!sCreatureStorage.LookupEntry (value1)) + { + sLog.outErrorDb("Creature in range condition (entry %u, type %u) has an invalid value in value1. (Creature %u does not exist in the database), skipping.", entry, condition, value1); + return false; + } + if (value2 <= 0) + { + sLog.outErrorDb("Creature in range condition (entry %u, type %u) has an invalid value in value2. (Range %u must be greater than 0), skipping.", entry, condition, value2); + return false; + } + } case CONDITION_NONE: break; default: @@ -10422,117 +10439,6 @@ bool DoDisplayText(WorldObject* source, int32 entry, Unit const* target /*=NULL* return true; } -void ObjectMgr::LoadPhaseDefinitions() -{ - for (PhaseDefinitionStore::iterator itr = _PhaseDefinitionStore.begin(); itr != _PhaseDefinitionStore.end(); ++itr) - { - for (PhaseDefinitionContainer::iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) - delete *itr2; - } - - _PhaseDefinitionStore.clear(); - - // 0 1 2 3 4 5 6 - QueryResult* result = WorldDatabase.Query("SELECT zoneId, entry, phasemask, phaseId, terrainswapmap, flags, condition_id FROM `phase_definitions` ORDER BY `entry` ASC"); - - if (!result) - { - sLog.outString(">> Loaded 0 phasing definitions. DB table `phase_definitions` is empty."); - return; - } - - uint32 count = 0; - do - { - Field* fields = result->Fetch(); - - PhaseDefinition* phaseDefinition = new PhaseDefinition(); - - phaseDefinition->zoneId = fields[0].GetUInt32(); - phaseDefinition->entry = fields[1].GetUInt32(); - phaseDefinition->phasemask = fields[2].GetUInt32(); - phaseDefinition->phaseId = fields[3].GetUInt32(); - phaseDefinition->terrainswapmap = fields[4].GetUInt32(); - phaseDefinition->flags = fields[5].GetUInt32(); - phaseDefinition->conditionId = fields[6].GetUInt16(); - - // Checks - if ((phaseDefinition->flags & PHASE_FLAG_OVERWRITE_EXISTING) && (phaseDefinition->flags & PHASE_FLAG_NEGATE_PHASE)) - { - sLog.outError("Flags defined in phase_definitions in zoneId %d and entry %u does contain PHASE_FLAG_OVERWRITE_EXISTING and PHASE_FLAG_NEGATE_PHASE. Setting flags to PHASE_FLAG_OVERWRITE_EXISTING", phaseDefinition->zoneId, phaseDefinition->entry); - phaseDefinition->flags &= ~PHASE_FLAG_NEGATE_PHASE; - } - - if (!sConditionStorage.LookupEntry(phaseDefinition->conditionId)) - { - sLog.outError("Condition id defined in phase_definitions in zoneId %d and entry %u does not exists. Skipping condition.", phaseDefinition->zoneId, phaseDefinition->entry); - phaseDefinition->conditionId = 0; - } - - _PhaseDefinitionStore[phaseDefinition->zoneId].push_back(phaseDefinition); - - ++count; - } - while (result->NextRow()); - - delete result; - - sLog.outString(">> Loaded %u phasing definitions.", count); -} - -void ObjectMgr::LoadSpellPhaseInfo() -{ - for (SpellPhaseStore::iterator itr = _SpellPhaseStore.begin(); itr != _SpellPhaseStore.end(); ++itr) - delete itr->second; - - _SpellPhaseStore.clear(); - - // 0 1 2 - QueryResult* result = WorldDatabase.Query("SELECT id, phasemask, terrainswapmap FROM `spell_phase`"); - - if (!result) - { - sLog.outString(">> Loaded 0 spell dbc infos. DB table `spell_phase` is empty."); - return; - } - - uint32 count = 0; - do - { - Field* fields = result->Fetch(); - - SpellPhaseInfo* spellPhaseInfo = new SpellPhaseInfo(); - spellPhaseInfo->spellId = fields[0].GetUInt32(); - - SpellEntry const* spell = sSpellStore.LookupEntry(spellPhaseInfo->spellId); - if (!spell) - { - sLog.outError("Spell %u defined in `spell_phase` does not exists, skipped.", spellPhaseInfo->spellId); - delete spellPhaseInfo; - continue; - } - - if (!IsSpellHaveAura(spell, SPELL_AURA_PHASE) && !IsSpellHaveAura(spell, SPELL_AURA_PHASE_2)) - { - sLog.outError("Spell %u defined in `spell_phase` does not have aura effect type SPELL_AURA_PHASE or SPELL_AURA_PHASE_2, useless value.", spellPhaseInfo->spellId); - delete spellPhaseInfo; - continue; - } - - spellPhaseInfo->phasemask = fields[1].GetUInt32(); - spellPhaseInfo->terrainswapmap = fields[2].GetUInt32(); - - _SpellPhaseStore[spellPhaseInfo->spellId] = spellPhaseInfo; - - ++count; - } - while (result->NextRow()); - - delete result; - - sLog.outString(">> Loaded %u spell phase dbc infos.", count); -} - CreatureDataPair const* FindCreatureData::GetResult() const { if (i_spawnedData) diff --git a/src/game/Object/ObjectMgr.h b/src/game/Object/ObjectMgr.h index 1c397adfc..257c3262d 100644 --- a/src/game/Object/ObjectMgr.h +++ b/src/game/Object/ObjectMgr.h @@ -448,6 +448,7 @@ enum ConditionType CONDITION_GENDER = 35, // 0=male, 1=female, 2=none (see enum Gender) CONDITION_DEAD_OR_AWAY = 36, // value1: 0=player dead, 1=player is dead (with group dead), 2=player in instance are dead, 3=creature is dead // value2: if != 0 only consider players in range of this value + CONDITION_CREATURE_IN_RANGE = 37, // value1: creature entry; value2: range; returns only alive creatures }; enum ConditionSource // From where was the condition called? @@ -462,7 +463,6 @@ enum ConditionSource // From where was th CONDITION_FROM_SPELL_AREA = 7, // Used to check a condition from spell_area table CONDITION_FROM_SPELLCLICK = 8, // Used to check a condition from npc_spellclick_spells table CONDITION_FROM_DBSCRIPTS = 9, // Used to check a condition from DB Scripts Engine - CONDITION_FROM_PHASEMGR = 10, // Used to check a condition from phase manager }; class PlayerCondition @@ -1041,7 +1041,7 @@ class ObjectMgr static PetNameInvalidReason CheckPetName(const std::string& name); static bool IsValidCharterName(const std::string& name); - static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names); + static bool CheckDeclinedNames(const std::wstring& mainpart, DeclinedName const& names); int GetIndexForLocale(LocaleConstant loc); LocaleConstant GetLocaleForIndex(int i); @@ -1192,11 +1192,11 @@ class ObjectMgr uint32 GetModelForRace(uint32 sourceModelId, uint32 racemask); /** - * \brief: Data returned is used to compute health, mana, armor, damage of creatures. May be nullptr. + * \brief: Data returned is used to compute health, mana, armor, damage of creatures. May be NULL. * \param uint32 level creature level * \param uint32 unitClass creature class, related to CLASSMASK_ALL_CREATURES * \param uint32 expansion creature expansion (we could have creature exp = 0 for wotlk as well as exp = 1 or exp = 2) - * \return: CreatureClassLvlStats const* or nullptr + * \return: CreatureClassLvlStats const* or NULL * * Description: GetCreatureClassLvlStats give fast access to creature stats data. * FullName: ObjectMgr::GetCreatureClassLvlStats diff --git a/src/game/Object/Pet.cpp b/src/game/Object/Pet.cpp index 5c805b2e2..da2853338 100644 --- a/src/game/Object/Pet.cpp +++ b/src/game/Object/Pet.cpp @@ -227,7 +227,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8())); uint32 savedhealth = fields[10].GetUInt32(); - uint32 savedmana = fields[11].GetUInt32(); + uint32 savedpower = fields[11].GetUInt32(); // set current pet as current // 0=current @@ -274,17 +274,20 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petentry, uint32 petnumber, bool c { LearnPetPassives(); CastPetAuras(current); + CastOwnerTalentAuras(); } + Powers powerType = GetPowerType(); + if (getPetType() == SUMMON_PET && !current) // all (?) summon pets come with full health when called, but not when they are current { SetHealth(GetMaxHealth()); - SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); + SetPower(powerType, GetMaxPower(powerType)); } else { SetHealth(savedhealth > GetMaxHealth() ? GetMaxHealth() : savedhealth); - SetPower(POWER_MANA, savedmana > GetMaxPower(POWER_MANA) ? GetMaxPower(POWER_MANA) : savedmana); + SetPower(powerType, savedpower > GetMaxPower(powerType) ? GetMaxPower(powerType) : savedpower); } AIM_Initialize(); @@ -369,7 +372,7 @@ void Pet::SavePetToDB(PetSaveMode mode) } uint32 curhealth = GetHealth(); - uint32 curmana = GetPower(POWER_MANA); + uint32 curpower = GetPower(GetPowerType()); // stable and not in slot saves if (mode != PET_SAVE_AS_CURRENT) @@ -423,7 +426,7 @@ void Pet::SavePetToDB(PetSaveMode mode) savePet.addString(m_name); savePet.addUInt32(uint32(HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) ? 0 : 1)); savePet.addUInt32((curhealth < 1 ? 1 : curhealth)); - savePet.addUInt32(curmana); + savePet.addUInt32(curpower); std::ostringstream ss; for (uint32 i = ACTION_BAR_INDEX_START; i < ACTION_BAR_INDEX_END; ++i) @@ -565,20 +568,10 @@ void Pet::RegenerateAll(uint32 update_diff) // regenerate focus for hunter pets or energy for deathknight's ghoul if (m_regenTimer <= update_diff) { - switch (GetPowerType()) - { - case POWER_FOCUS: - case POWER_ENERGY: - Regenerate(GetPowerType()); - break; - default: - break; - } - if (!IsInCombat() || IsPolymorphed()) RegenerateHealth(); - RegenerateMana(); + RegeneratePower(); m_regenTimer = 4000; } @@ -586,43 +579,6 @@ void Pet::RegenerateAll(uint32 update_diff) m_regenTimer -= update_diff; } -void Pet::Regenerate(Powers power) -{ - uint32 curValue = GetPower(power); - uint32 maxValue = GetMaxPower(power); - - if (curValue >= maxValue) - return; - - float addvalue = 0.0f; - - switch (power) - { - case POWER_FOCUS: - { - // For hunter pets. - addvalue = 24 * sWorld.getConfig(CONFIG_FLOAT_RATE_POWER_FOCUS); - break; - } - case POWER_ENERGY: - { - // For deathknight's ghoul. - addvalue = 20; - break; - } - default: - return; - } - - // Apply modifiers (if any). - AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); - for (AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) - if ((*i)->GetModifier()->m_miscvalue == int32(power)) - addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f; - - ModifyPower(power, (int32)addvalue); -} - bool Pet::CanTakeMoreActiveSpells(uint32 spellid) { uint8 activecount = 1; @@ -1060,7 +1016,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner) UpdateAllStats(); SetHealth(GetMaxHealth()); - SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); + SetPower(GetPowerType(), GetMaxPower(GetPowerType())); return true; } @@ -1912,6 +1868,7 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) return; PetSpellMap::iterator itr = m_spells.find(spellid); + PetSpell& petSpell = itr->second; uint32 i; @@ -1924,11 +1881,11 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) { m_autospells.push_back(spellid); - if (itr->second.active != ACT_ENABLED) + if (petSpell.active != ACT_ENABLED) { - itr->second.active = ACT_ENABLED; - if (itr->second.state != PETSPELL_NEW) - itr->second.state = PETSPELL_CHANGED; + petSpell.active = ACT_ENABLED; + if (petSpell.state != PETSPELL_NEW) + petSpell.state = PETSPELL_CHANGED; } } } @@ -1941,11 +1898,11 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) if (i < m_autospells.size()) { m_autospells.erase(itr2); - if (itr->second.active != ACT_DISABLED) + if (petSpell.active != ACT_DISABLED) { - itr->second.active = ACT_DISABLED; - if (itr->second.state != PETSPELL_NEW) - itr->second.state = PETSPELL_CHANGED; + petSpell.active = ACT_DISABLED; + if (petSpell.state != PETSPELL_NEW) + petSpell.state = PETSPELL_CHANGED; } } } @@ -2042,6 +1999,44 @@ void Pet::CastPetAuras(bool current) } } +void Pet::CastOwnerTalentAuras() +{ + if (!GetOwner() || GetOwner()->GetTypeId() != TYPEID_PLAYER) + return; + + Player* pOwner = static_cast(GetOwner()); + + // Handle Ferocious Inspiration Talent + if (pOwner && pOwner->getClass() == CLASS_HUNTER) + { + // clear any existing Ferocious Inspiration auras + RemoveAurasDueToSpell(75593); + RemoveAurasDueToSpell(75446); + RemoveAurasDueToSpell(75447); + + if (IsAlive()) + { + const SpellEntry* seTalent = pOwner->GetKnownTalentRankById(1800); // Ferocious Inspiration + + if (seTalent) + { + switch (seTalent->Id) + { + case 34455: // Ferocious Inspiration Rank 1 + CastSpell(this, 75593, true); // Ferocious Inspiration 1% + break; + case 34459: // Ferocious Inspiration Rank 2 + CastSpell(this, 75446, true); // Ferocious Inspiration 2% + break; + case 34460: // Ferocious Inspiration Rank 3 + CastSpell(this, 75447, true); // Ferocious Inspiration 3% + break; + } + } + } + } // End Ferocious Inspiration Talent +} + void Pet::CastPetAura(PetAura const* aura) { uint32 auraId = aura->GetAura(GetEntry()); diff --git a/src/game/Object/Pet.h b/src/game/Object/Pet.h index 2a5fa12bd..033b525ed 100644 --- a/src/game/Object/Pet.h +++ b/src/game/Object/Pet.h @@ -178,7 +178,6 @@ class Pet : public Creature } void RegenerateAll(uint32 update_diff) override; // overwrite Creature::RegenerateAll - void Regenerate(Powers power); void GivePetXP(uint32 xp); void GivePetLevel(uint32 level); void SynchronizeLevelWithOwner(); @@ -198,6 +197,11 @@ class Pet : public Creature void UpdateMaxPower(Powers power) override; void UpdateAttackPowerAndDamage(bool ranged = false) override; void UpdateDamagePhysical(WeaponAttackType attType) override; + uint32 GetCurrentEquipmentId() const { return m_equipmentId; } + + static float _GetHealthMod(int32 Rank); ///< Get custom factor to scale health (default 1, CONFIG_FLOAT_RATE_CREATURE_*_HP) + static float _GetDamageMod(int32 Rank); ///< Get custom factor to scale damage (default 1, CONFIG_FLOAT_RATE_*_DAMAGE) + static float _GetSpellDamageMod(int32 Rank); ///< Get custom factor to scale spell damage (default 1, CONFIG_FLOAT_RATE_*_SPELLDAMAGE) bool CanTakeMoreActiveSpells(uint32 SpellIconID); void ToggleAutocast(uint32 spellid, bool apply); @@ -209,6 +213,7 @@ class Pet : public Creature void LearnPetPassives(); void CastPetAuras(bool current); + void CastOwnerTalentAuras(); void CastPetAura(PetAura const* aura); void _LoadSpellCooldowns(); diff --git a/src/game/Object/Player.cpp b/src/game/Object/Player.cpp index ad82f52e3..4dea7d30f 100644 --- a/src/game/Object/Player.cpp +++ b/src/game/Object/Player.cpp @@ -73,7 +73,6 @@ #include "SQLStorages.h" #include "Vehicle.h" #include "Calendar.h" -#include "PhaseMgr.h" #ifdef ENABLE_ELUNA #include "LuaEngine.h" #endif /*ENABLE_ELUNA*/ @@ -568,8 +567,6 @@ Player::Player(WorldSession* session): Unit(), m_mover(this), m_camera(this), m_ m_cachedGS = 0; m_slot = 255; - - phaseMgr = new PhaseMgr(this); } Player::~Player() @@ -610,8 +607,6 @@ Player::~Player() delete m_declinedname; delete m_runes; - - delete phaseMgr; } void Player::CleanupsBeforeDelete() @@ -853,6 +848,9 @@ bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 c } // all item positions resolved + if (info->phaseMap != 0) + CharacterDatabase.PExecute("REPLACE INTO `character_phase_data` (`guid`, `map`) VALUES (%u, %u)", guidlow, info->phaseMap); + return true; } @@ -958,7 +956,11 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage) data << uint32(resist); SendMessageToSet(&data, true); - uint32 final_damage = DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + DamageEffectType damageType = SELF_DAMAGE; + if (type == DAMAGE_FALL && getClass() == CLASS_ROGUE) + damageType = SELF_DAMAGE_ROGUE_FALL; + + uint32 final_damage = DealDamage(this, damage, NULL, damageType, SPELL_SCHOOL_MASK_NORMAL, NULL, false); if (!IsAlive()) { @@ -1390,8 +1392,8 @@ void Player::Update(uint32 update_diff, uint32 p_time) HandleSobering(); } - // Not auto-free ghost from body in instances - if (m_deathTimer > 0 && !GetMap()->Instanceable()) + // Not auto-free ghost from body in instances; also check for resurrection prevention + if (m_deathTimer > 0 && !GetMap()->Instanceable() && !HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) { if (p_time >= m_deathTimer) { @@ -2448,7 +2450,15 @@ void Player::SetGameMaster(bool on) RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); // restore phase - SetPhaseMask(phaseMgr->GetCurrentPhasemask(), false); + AuraList const& phases = GetAurasByType(SPELL_AURA_PHASE); + AuraList const& phases2 = GetAurasByType(SPELL_AURA_PHASE_2); + + if (!phases.empty()) + SetPhaseMask(phases.front()->GetMiscValue(), false); + else if (!phases2.empty()) + SetPhaseMask(phases2.front()->GetMiscValue(), false); + else + SetPhaseMask(PHASEMASK_NORMAL, false); CallForAllControlledUnits(SetGameMasterOffHelper(getFaction()), CONTROLLED_PET | CONTROLLED_TOTEMS | CONTROLLED_GUARDIANS | CONTROLLED_CHARM); @@ -2460,9 +2470,6 @@ void Player::SetGameMaster(bool on) UpdateArea(m_areaUpdateId); getHostileRefManager().setOnlineOfflineState(true); - - phaseMgr->AddUpdateFlag(PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED); - phaseMgr->Update(); } m_camera.UpdateVisibilityForOwner(); @@ -2691,11 +2698,6 @@ void Player::GiveLevel(uint32 level) MailDraft(mailReward->mailTemplateId).SendMailTo(this, MailSender(MAIL_CREATURE, mailReward->senderEntry)); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); - - PhaseUpdateData phaseUdateData; - phaseUdateData.AddConditionType(CONDITION_LEVEL); - - phaseMgr->NotifyConditionChanged(phaseUdateData); } void Player::UpdateFreeTalentPoints(bool resetIfNeed) @@ -3080,7 +3082,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; - bool dependent_set = false; bool disabled_case = false; bool superceded_old = false; @@ -3088,6 +3089,8 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen if (itr != m_spells.end()) { uint32 next_active_spell_id = 0; + bool dependent_set = false; + // fix activate state for non-stackable low rank (and find next spell for !active case) if (sSpellMgr.IsRankedSpellNonStackableInSpellBook(spellInfo)) { @@ -4688,7 +4691,7 @@ void Player::KillPlayer() // SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_IN_PVP ); SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE); - ApplyModByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(GetMapId())->Instanceable()); + ApplyModByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(GetMapId())->Instanceable() && !HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)); // 6 minutes until repop at graveyard m_deathTimer = 6 * MINUTE * IN_MILLISECONDS; @@ -6884,11 +6887,7 @@ void Player::UpdateArea(uint32 newArea) SetFFAPvP(false); } - phaseMgr->AddUpdateFlag(PHASE_UPDATE_FLAG_AREA_UPDATE); - UpdateAreaDependentAuras(); - - phaseMgr->RemoveUpdateFlag(PHASE_UPDATE_FLAG_AREA_UPDATE); } bool Player::CanUseCapturePoint() @@ -8498,7 +8497,7 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) // 0 - Battle for Wintergrasp in progress, 1 - otherwise FillInitialWorldState(data, count, 0xED9, 1); // Time when next Battle for Wintergrasp starts - FillInitialWorldState(data, count, 0x1102, uint32(time(nullptr) + 9000)); + FillInitialWorldState(data, count, 0x1102, uint32(time(NULL) + 9000)); switch (zoneid) { @@ -8844,10 +8843,10 @@ InventoryResult Player::CanUnequipItems(uint32 item, uint32 count) const return EQUIP_ERR_OK; } } - Bag* pBag; + for (int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { - pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i); + Bag* pBag = (Bag*)GetItemByPos(INVENTORY_SLOT_BAG_0, i); if (pBag) { for (uint32 j = 0; j < pBag->GetBagSize(); ++j) @@ -13211,7 +13210,7 @@ void Player::SendPreparedQuest(ObjectGuid guid) { qe._Delay = 0; // TEXTEMOTE_MESSAGE; // zyg: player emote qe._Emote = 0; // TEXTEMOTE_HELLO; // zyg: NPC emote - title = ""; + title.clear(); } else { @@ -14423,11 +14422,6 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status) q_status.uState = QUEST_CHANGED; } - PhaseUpdateData phaseUdateData; - phaseUdateData.AddQuestUpdate(quest_id); - - phaseMgr->NotifyConditionChanged(phaseUdateData); - UpdateForQuestWorldObjects(); } @@ -18965,18 +18959,14 @@ void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) WorldPacket data(SMSG_SPELL_COOLDOWN, 8 + 1 + m_spells.size() * 8); data << GetObjectGuid(); data << uint8(0x0); // flags (0x1, 0x2) - time_t curTime = time(NULL); + time_t curTime = time(nullptr); for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) { if (itr->second.state == PLAYERSPELL_REMOVED) continue; uint32 unSpellId = itr->first; SpellEntry const* spellInfo = sSpellStore.LookupEntry(unSpellId); - if (!spellInfo) - { - MANGOS_ASSERT(spellInfo); - continue; - } + MANGOS_ASSERT(spellInfo); // Not send cooldown for this spells if (spellInfo->HasAttribute(SPELL_ATTR_DISABLED_WHILE_ACTIVE)) @@ -22103,6 +22093,25 @@ void Player::_LoadSkills(QueryResult* result) } } +uint32 Player::GetPhaseMaskForSpawn() const +{ + uint32 phase = PHASEMASK_NORMAL; + if (!isGameMaster()) + phase = GetPhaseMask(); + else + { + AuraList const& phases = GetAurasByType(SPELL_AURA_PHASE); + if (!phases.empty()) + phase = phases.front()->GetMiscValue(); + } + + // some aura phases include 1 normal map in addition to phase itself + if (uint32 n_phase = phase & ~PHASEMASK_NORMAL) + return n_phase; + + return PHASEMASK_NORMAL; +} + InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limit_count) const { ItemPrototype const* pProto = pItem->GetProto(); diff --git a/src/game/Object/Player.h b/src/game/Object/Player.h index ab41b6c3d..5004be09a 100644 --- a/src/game/Object/Player.h +++ b/src/game/Object/Player.h @@ -60,7 +60,6 @@ class PlayerSocial; class DungeonPersistentState; class Spell; class Item; -class PhaseMgr; struct AreaTrigger; @@ -1209,7 +1208,7 @@ class Player : public Unit void RemovePet(PetSaveMode mode); - PhaseMgr* GetPhaseMgr() { return phaseMgr; } + uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn void Say(const std::string& text, const uint32 language); void Yell(const std::string& text, const uint32 language); @@ -2854,8 +2853,6 @@ class Player : public Unit uint32 m_timeSyncServer; uint32 m_cachedGS; - - PhaseMgr* phaseMgr; }; void AddItemsSetItem(Player* player, Item* item); diff --git a/src/game/Object/ReactorAI.cpp b/src/game/Object/ReactorAI.cpp index 434e126a7..c6882acd3 100644 --- a/src/game/Object/ReactorAI.cpp +++ b/src/game/Object/ReactorAI.cpp @@ -48,7 +48,7 @@ ReactorAI::MoveInLineOfSight(Unit*) void ReactorAI::AttackStart(Unit* p) { - if (!p) + if (!p || !m_creature->CanAttackByItself()) return; if (m_creature->Attack(p, true)) diff --git a/src/game/Object/ReputationMgr.cpp b/src/game/Object/ReputationMgr.cpp index 62d75d438..19df108ad 100644 --- a/src/game/Object/ReputationMgr.cpp +++ b/src/game/Object/ReputationMgr.cpp @@ -142,13 +142,14 @@ void ReputationMgr::SendState(FactionState const* faction, bool anyRankIncreased for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) { - if (itr->second.needSend) + FactionState& subFaction = itr->second; + if (subFaction.needSend) { - itr->second.needSend = false; - if (itr->second.ReputationListID != faction->ReputationListID) + subFaction.needSend = false; + if (subFaction.ReputationListID != faction->ReputationListID) { - data << uint32(itr->second.ReputationListID); - data << uint32(itr->second.Standing); + data << uint32(subFaction.ReputationListID); + data << uint32(subFaction.Standing); ++count; } @@ -317,36 +318,39 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); if (itr != m_factions.end()) { + FactionState& faction = itr->second; int32 BaseRep = GetBaseReputation(factionEntry); if (incremental) - standing += itr->second.Standing + BaseRep; + standing += faction.Standing + BaseRep; if (standing > Reputation_Cap) standing = Reputation_Cap; else if (standing < Reputation_Bottom) standing = Reputation_Bottom; - ReputationRank old_rank = ReputationToRank(itr->second.Standing + BaseRep); + ReputationRank old_rank = ReputationToRank(faction.Standing + BaseRep); ReputationRank new_rank = ReputationToRank(standing); - itr->second.Standing = standing - BaseRep; - itr->second.needSend = true; - itr->second.needSave = true; + faction.Standing = standing - BaseRep; + faction.needSend = true; + faction.needSave = true; - SetVisible(&itr->second); + SetVisible(&faction); if (new_rank <= REP_HOSTILE) - SetAtWar(&itr->second, true); + SetAtWar(&faction, true); UpdateRankCounters(old_rank, new_rank); m_player->ReputationChanged(factionEntry); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID); - m_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID); + + AchievementMgr& achievementManager = m_player->GetAchievementMgr(); + achievementManager.UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID); + achievementManager.UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID); + achievementManager.UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID); + achievementManager.UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID); + achievementManager.UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID); if (new_rank > old_rank) return true; @@ -532,11 +536,12 @@ void ReputationMgr::SaveToDB() for (FactionStateList::iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) { - if (itr->second.needSave) + FactionState& faction = itr->second; + if (faction.needSave) { - stmtDel.PExecute(m_player->GetGUIDLow(), itr->second.ID); - stmtIns.PExecute(m_player->GetGUIDLow(), itr->second.ID, itr->second.Standing, itr->second.Flags); - itr->second.needSave = false; + stmtDel.PExecute(m_player->GetGUIDLow(), faction.ID); + stmtIns.PExecute(m_player->GetGUIDLow(), faction.ID, faction.Standing, faction.Flags); + faction.needSave = false; } } } diff --git a/src/game/Object/SocialMgr.cpp b/src/game/Object/SocialMgr.cpp index 970e31fba..18af3caa0 100644 --- a/src/game/Object/SocialMgr.cpp +++ b/src/game/Object/SocialMgr.cpp @@ -138,19 +138,20 @@ void PlayerSocial::SendSocialList() for (PlayerSocialMap::iterator itr = m_playerSocialMap.begin(); itr != m_playerSocialMap.end(); ++itr) { - sSocialMgr.GetFriendInfo(plr, itr->first, itr->second); + FriendInfo& friendInfo = itr->second; + sSocialMgr.GetFriendInfo(plr, itr->first, friendInfo); data << ObjectGuid(HIGHGUID_PLAYER, itr->first); // player guid - data << uint32(itr->second.Flags); // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?) - data << itr->second.Note; // string note - if (itr->second.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend() + data << uint32(friendInfo.Flags); // player flag (0x1-friend?, 0x2-ignored?, 0x4-muted?) + data << friendInfo.Note; // string note + if (friendInfo.Flags & SOCIAL_FLAG_FRIEND) // if IsFriend() { - data << uint8(itr->second.Status); // online/offline/etc? - if (itr->second.Status) // if online + data << uint8(friendInfo.Status); // online/offline/etc? + if (friendInfo.Status) // if online { - data << uint32(itr->second.Area); // player area - data << uint32(itr->second.Level); // player level - data << uint32(itr->second.Class); // player class + data << uint32(friendInfo.Area); // player area + data << uint32(friendInfo.Level); // player level + data << uint32(friendInfo.Class); // player class } } } diff --git a/src/game/Object/SpellMgr.cpp b/src/game/Object/SpellMgr.cpp index b59aefa7a..ee1a8fba2 100644 --- a/src/game/Object/SpellMgr.cpp +++ b/src/game/Object/SpellMgr.cpp @@ -776,6 +776,8 @@ bool IsPositiveEffect(SpellEntry const* spellproto, SpellEffectIndex effIndex) // some explicitly required script effect sets switch (spellproto->Id) { + case 42436: // Drink! + case 42492: // Cast Energized case 46650: // Open Brutallus Back Door case 62488: // Activate Construct case 64503: // Water @@ -903,6 +905,7 @@ bool IsPositiveEffect(SpellEntry const* spellproto, SpellEffectIndex effIndex) case SPELL_AURA_PERIODIC_LEECH: case SPELL_AURA_MOD_STALKED: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_PREVENT_RESURRECTION: return false; case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. // part of negative spell if casted at self (prevent cancel) @@ -2231,6 +2234,25 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons if ((spellInfo_1->Id == 62559 && spellInfo_2->Id == 62538) || (spellInfo_2->Id == 62559 && spellInfo_1->Id == 62538)) return false; + + // Phase 2 Transform and Shadowy Barrier + if ((spellInfo_1->Id == 65157 && spellInfo_2->Id == 64775) || + (spellInfo_2->Id == 65157 && spellInfo_1->Id == 64775)) + return false; + + // Empowered (dummy) and Empowered + if ((spellInfo_1->Id == 64161 && spellInfo_2->Id == 65294) || + (spellInfo_2->Id == 64161 && spellInfo_1->Id == 65294)) + return false; + + // Spectral Realm (reaction) and Spectral Realm (invisibility) + if ((spellInfo_1->Id == 44852 && spellInfo_2->Id == 46021) || + (spellInfo_2->Id == 44852 && spellInfo_1->Id == 46021)) + return false; + + // Halls of Reflection Clone + if (spellInfo_1->SpellIconID == 692 && spellInfo_2->SpellIconID == 692) + return false; break; } case SPELLFAMILY_MAGE: @@ -3489,7 +3511,11 @@ void SpellMgr::LoadSpellScriptTarget() spellEffect->EffectImplicitTargetA == TARGET_AREAEFFECT_GO_AROUND_SOURCE || spellEffect->EffectImplicitTargetB == TARGET_AREAEFFECT_GO_AROUND_SOURCE || spellEffect->EffectImplicitTargetA == TARGET_AREAEFFECT_GO_AROUND_DEST || - spellEffect->EffectImplicitTargetB == TARGET_AREAEFFECT_GO_AROUND_DEST) + spellEffect->EffectImplicitTargetB == TARGET_AREAEFFECT_GO_AROUND_DEST || + spellEffect->EffectImplicitTargetA == TARGET_NARROW_FRONTAL_CONE || + spellEffect->EffectImplicitTargetB == TARGET_NARROW_FRONTAL_CONE || + spellEffect->EffectImplicitTargetA == TARGET_NARROW_FRONTAL_CONE_2 || + spellEffect->EffectImplicitTargetB == TARGET_NARROW_FRONTAL_CONE_2) { targetfound = true; break; diff --git a/src/game/Object/SpellMgr.h b/src/game/Object/SpellMgr.h index 74fa6b867..f7aabcc95 100644 --- a/src/game/Object/SpellMgr.h +++ b/src/game/Object/SpellMgr.h @@ -1128,8 +1128,8 @@ class SpellMgr return 0; } - - uint8 IsHighRankOfSpell(uint32 spell1, uint32 spell2) const + + bool IsHighRankOfSpell(uint32 spell1, uint32 spell2) const { SpellChainMap::const_iterator itr = mSpellChains.find(spell1); diff --git a/src/game/Object/TemporarySummon.cpp b/src/game/Object/TemporarySummon.cpp index 459a76cce..4170c7f41 100644 --- a/src/game/Object/TemporarySummon.cpp +++ b/src/game/Object/TemporarySummon.cpp @@ -217,3 +217,11 @@ void TemporarySummon::UnSummon() void TemporarySummon::SaveToDB() { } + +TemporarySummonWaypoint::TemporarySummonWaypoint(ObjectGuid summoner, uint32 waypoint_id, int32 path_id, uint32 pathOrigin) : + TemporarySummon(summoner), + m_waypoint_id(waypoint_id), + m_path_id(path_id), + m_pathOrigin(pathOrigin) +{ +} diff --git a/src/game/Object/TemporarySummon.h b/src/game/Object/TemporarySummon.h index 58a320f0d..6799e7e50 100644 --- a/src/game/Object/TemporarySummon.h +++ b/src/game/Object/TemporarySummon.h @@ -55,4 +55,20 @@ class TemporarySummon : public Creature uint32 m_lifetime; ObjectGuid m_summoner; }; + +class TemporarySummonWaypoint : public TemporarySummon +{ + public: + explicit TemporarySummonWaypoint(ObjectGuid summoner, uint32 waypoint_id, int32 path_id, uint32 pathOrigin); + + uint32 GetWaypointId() const { return m_waypoint_id; } + int32 GetPathId() const { return m_path_id; } + uint32 GetPathOrigin() const { return m_pathOrigin; } + + private: + uint32 m_waypoint_id; + int32 m_path_id; + uint32 m_pathOrigin; +}; + #endif diff --git a/src/game/Object/Totem.cpp b/src/game/Object/Totem.cpp index 6562fed4f..a86b4f57a 100644 --- a/src/game/Object/Totem.cpp +++ b/src/game/Object/Totem.cpp @@ -189,8 +189,13 @@ void Totem::SetTypeBySummonSpell(SpellEntry const* spellProto) bool Totem::IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index, bool castOnSelf) const { + // Totem may affected by some specific spells + // Mana Spring, Healing stream, Mana tide + // Flags : 0x00000002000 | 0x00000004000 | 0x00004000000 -> 0x00004006000 + if (spellInfo->GetSpellFamilyName() == SPELLFAMILY_SHAMAN && spellInfo->IsFitToFamilyMask(UI64LIT(0x00004006000))) + return false; SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(index); - if(spellEffect) + if (spellEffect) { // TODO: possibly all negative auras immune? switch(spellEffect->Effect) diff --git a/src/game/Object/Unit.cpp b/src/game/Object/Unit.cpp index f0b2b2f15..d1591bb81 100644 --- a/src/game/Object/Unit.cpp +++ b/src/game/Object/Unit.cpp @@ -883,14 +883,12 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa // remove affects from attacker at any non-DoT damage (including 0 damage) if (damagetype != DOT) { - RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + if (damagetype != SELF_DAMAGE_ROGUE_FALL) + RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - if (pVictim != this) - RemoveSpellsCausingAura(SPELL_AURA_MOD_INVISIBILITY); - if (pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->IsStandState() && !pVictim->hasUnitState(UNIT_STAT_STUNNED)) - { pVictim->SetStandState(UNIT_STAND_STATE_STAND); } + pVictim->SetStandState(UNIT_STAND_STATE_STAND); } if (!damage) @@ -952,7 +950,7 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa ((Creature*)pVictim)->SetLootRecipient(this); - JustKilledCreature((Creature*)pVictim, nullptr); + JustKilledCreature((Creature*)pVictim, NULL); pVictim->SetHealth(0); return damage; @@ -978,7 +976,7 @@ uint32 Unit::DealDamage(Unit* pVictim, uint32 damage, CleanDamage const* cleanDa { SpellEntry const* shareSpell = (*itr)->GetSpellProto(); uint32 shareDamage = uint32(damage*(*itr)->GetModifier()->m_amount / 100.0f); - DealDamageMods(shareTarget, shareDamage, nullptr); + DealDamageMods(shareTarget, shareDamage, NULL); DealDamage(shareTarget, shareDamage, 0, damagetype, GetSpellSchoolMask(shareSpell), shareSpell, false); } } @@ -4335,7 +4333,7 @@ bool Unit::AddSpellAuraHolder(SpellAuraHolder* holder) switch (aurNameReal) { - // DoT/HoT/etc + // DoT/HoT/etc case SPELL_AURA_DUMMY: // allow stack case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: @@ -4346,7 +4344,7 @@ bool Unit::AddSpellAuraHolder(SpellAuraHolder* holder) case SPELL_AURA_OBS_MOD_MANA: case SPELL_AURA_POWER_BURN_MANA: case SPELL_AURA_CONTROL_VEHICLE: - case SPELL_AURA_284: // SPELL_AURA_LINKED_AURA, unknown how it is handled, but let it stack like vehicle control aura + case SPELL_AURA_TRIGGER_LINKED_AURA: case SPELL_AURA_PERIODIC_DUMMY: break; case SPELL_AURA_PERIODIC_ENERGIZE: // all or self or clear non-stackable @@ -4367,7 +4365,7 @@ bool Unit::AddSpellAuraHolder(SpellAuraHolder* holder) if (!IsPassiveSpell(aurSpellInfo) || !IsPassiveSpellStackableWithRanks(aurSpellInfo)) { // Hack exceptions for Vehicle/Linked auras - if (!IsSpellHaveAura(aurSpellInfo, SPELL_AURA_CONTROL_VEHICLE) && !IsSpellHaveAura(aurSpellInfo, SPELL_AURA_284) && + if (!IsSpellHaveAura(aurSpellInfo, SPELL_AURA_CONTROL_VEHICLE) && !IsSpellHaveAura(aurSpellInfo, SPELL_AURA_TRIGGER_LINKED_AURA) && !RemoveNoStackAurasDueToAuraHolder(holder)) { delete holder; @@ -5750,8 +5748,10 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, SpellSchoolMask d void Unit::SetPowerType(Powers new_powertype) { + // set power type SetByteValue(UNIT_FIELD_BYTES_0, 3, new_powertype); + // group updates if (GetTypeId() == TYPEID_PLAYER) { if (((Player*)this)->GetGroup()) @@ -5768,22 +5768,38 @@ void Unit::SetPowerType(Powers new_powertype) } } - switch (new_powertype) + // special cases for power type switching (druid and pets only) + if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->IsPet())) { - default: - case POWER_MANA: - break; - case POWER_RAGE: - SetMaxPower(POWER_RAGE, GetCreatePowers(POWER_RAGE)); - SetPower(POWER_RAGE, 0); - break; - case POWER_FOCUS: - SetMaxPower(POWER_FOCUS, GetCreatePowers(POWER_FOCUS)); - SetPower(POWER_FOCUS, GetCreatePowers(POWER_FOCUS)); - break; - case POWER_ENERGY: - SetMaxPower(POWER_ENERGY, GetCreatePowers(POWER_ENERGY)); - break; + uint32 maxValue = GetCreatePowers(new_powertype); + uint32 curValue = maxValue; + + // special cases with current power = 0 + switch (new_powertype) + { + case POWER_RAGE: + case POWER_RUNE: + case POWER_RUNIC_POWER: + curValue = 0; + break; + default: + break; + } + + // set power (except for mana) + if (new_powertype != POWER_MANA) + { + SetMaxPower(new_powertype, maxValue); + SetPower(new_powertype, curValue); + } + + // send power type update to client + WorldPacket data(SMSG_POWER_UPDATE); + data << GetPackGUID(); + data << uint32(1); // power count + data << uint8(new_powertype); + data << uint32(curValue); + SendMessageToSet(&data, true); } } @@ -6717,7 +6733,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* pVictim, SpellEntry const* spellProto, u // Creature damage if (GetTypeId() == TYPEID_UNIT && !((Creature*)this)->IsPet()) - DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->Rank); + DoneTotalMod *= ((Creature*)this)->_GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->Rank); AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for (AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) @@ -9269,6 +9285,10 @@ void Unit::SetDeathState(DeathState s) if (IsVehicle()) m_vehicleInfo->RemoveAccessoriesFromMap(); + // Unboard from transport + if (GetTransportInfo() && ((Unit*)GetTransportInfo()->GetTransport())->IsVehicle()) + ((Unit*)GetTransportInfo()->GetTransport())->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, GetObjectGuid()); + ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); // remove aurastates allowing special moves @@ -10417,14 +10437,14 @@ uint32 Unit::GetCreatePowers(Powers power) const { case POWER_HEALTH: return 0; // is it really should be here? case POWER_MANA: return GetCreateMana(); - case POWER_RAGE: return 1000; + case POWER_RAGE: return POWER_RAGE_DEFAULT; case POWER_FOCUS: if(GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_HUNTER) - return 100; - return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->IsPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : 100); - case POWER_ENERGY: return 100; - case POWER_RUNE: return GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_DEATH_KNIGHT ? 8 : 0; - case POWER_RUNIC_POWER: return GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_DEATH_KNIGHT ? 1000 : 0; + return POWER_FOCUS_DEFAULT; + return (GetTypeId() == TYPEID_PLAYER || !((Creature const*)this)->IsPet() || ((Pet const*)this)->getPetType() != HUNTER_PET ? 0 : POWER_FOCUS_DEFAULT); + case POWER_ENERGY: return POWER_ENERGY_DEFAULT; + case POWER_RUNE: return GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_DEATH_KNIGHT ? POWER_RUNE_DEFAULT : 0; + case POWER_RUNIC_POWER: return GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_DEATH_KNIGHT ? POWER_RUNIC_POWER_DEFAULT : 0; case POWER_SOUL_SHARDS: return 0; case POWER_ECLIPSE: return 0; // TODO: fix me case POWER_HOLY_POWER: return 0; @@ -10438,9 +10458,9 @@ uint32 Unit::GetCreateMaxPowers(Powers power) const switch (power) { case POWER_HOLY_POWER: - return GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_PALADIN ? 3 : 0; + return GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_PALADIN ? POWER_HOLY_POWER_DEFAULT : 0; case POWER_SOUL_SHARDS: - return GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_WARLOCK ? 3 : 0; + return GetTypeId() == TYPEID_PLAYER && ((Player const*)this)->getClass() == CLASS_WARLOCK ? POWER_SOUL_SHARDS_DEFAULT : 0; default: return GetCreatePowers(power); } @@ -10593,7 +10613,6 @@ void CharmInfo::InitCharmCreateSpells() bool onlyselfcast = true; SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo) onlyselfcast = false; for (uint32 i = 0; i < 3 && onlyselfcast; ++i) // nonexistent spell will not make any problems as onlyselfcast would be false -> break right away { SpellEffectEntry const* spellEffect = spellInfo->GetSpellEffect(SpellEffectIndex(i)); @@ -10843,7 +10862,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* pTarget, uint32 procFlag, if (itr->second->IsDeleted()) continue; - SpellProcEventEntry const* spellProcEvent = nullptr; + SpellProcEventEntry const* spellProcEvent = NULL; // check if that aura is triggered by proc event (then it will be managed by proc handler) if (!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, spellProcEvent)) { @@ -11031,8 +11050,7 @@ void Unit::StopMoving(bool forceSendStop /*=false*/) return; Movement::MoveSplineInit init(*this); - init.SetFacing(GetOrientation()); - init.Launch(); + init.Stop(); } void Unit::InterruptMoving(bool forceSendStop /*=false*/) @@ -11644,6 +11662,24 @@ void Unit::SetFFAPvP(bool state) CallForAllControlledUnits(SetFFAPvPHelper(state), CONTROLLED_PET | CONTROLLED_TOTEMS | CONTROLLED_GUARDIANS | CONTROLLED_CHARM); } +void Unit::RestoreOriginalFaction() +{ + if (GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->setFactionForRace(getRace()); + else + { + Creature* creature = (Creature*)this; + + if (creature->IsPet() || creature->IsTotem()) + { + if (Unit* owner = GetOwner()) + setFaction(owner->getFaction()); + } + else + setFaction(creature->GetCreatureInfo()->FactionAlliance); + } +} + void Unit::KnockBackFrom(Unit* target, float horizontalSpeed, float verticalSpeed) { float angle = this == target ? GetOrientation() + M_PI_F : target->GetAngle(this); diff --git a/src/game/Object/Unit.h b/src/game/Object/Unit.h index 7aad62d6e..fffdf6ac0 100644 --- a/src/game/Object/Unit.h +++ b/src/game/Object/Unit.h @@ -753,6 +753,7 @@ class MovementInfo MovementFlags GetMovementFlags() const { return MovementFlags(moveFlags); } void SetMovementFlags(MovementFlags f) { moveFlags = f; } MovementFlags2 GetMovementFlags2() const { return MovementFlags2(moveFlags2); } + void AddMovementFlags2(MovementFlags2 f) { moveFlags2 |= f; } // Position manipulations Position const* GetPos() const { return &pos; } @@ -1256,13 +1257,13 @@ enum IgnoreUnitState // Power type values defines enum PowerDefaults { - POWER_RAGE_DEFAULT = 1000, - POWER_FOCUS_DEFAULT = 100, - POWER_ENERGY_DEFAULT = 100, - POWER_RUNE_DEFAULT = 8, - POWER_RUNIC_POWER_DEFAULT = 1000, - POWER_HOLY_POWER_DEFAULT = 3, - POWER_SOUL_SHARDS_DEFAULT = 3, + POWER_RAGE_DEFAULT = 1000, + POWER_FOCUS_DEFAULT = 100, + POWER_ENERGY_DEFAULT = 100, + POWER_RUNE_DEFAULT = 8, + POWER_RUNIC_POWER_DEFAULT = 1000, + POWER_HOLY_POWER_DEFAULT = 3, + POWER_SOUL_SHARDS_DEFAULT = 3, }; struct SpellProcEventEntry; // used only privately @@ -1861,6 +1862,10 @@ class Unit : public WorldObject */ void setFaction(uint32 faction) { SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction); } FactionTemplateEntry const* getFactionTemplateEntry() const; + /** + * + */ + void RestoreOriginalFaction(); /** * Are we hostile towards the given Unit? * @param unit the unit we want to check against @@ -3384,6 +3389,7 @@ class Unit : public WorldObject SpellAuraProcResult HandleManaShieldAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleModResistanceAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleRemoveByDamageChanceProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); + SpellAuraProcResult HandleInvisibilityAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); SpellAuraProcResult HandleNULLProc(Unit* /*pVictim*/, uint32 /*damage*/, Aura* /*triggeredByAura*/, SpellEntry const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 /*cooldown*/) { // no proc handler for this aura type diff --git a/src/game/Object/Vehicle.cpp b/src/game/Object/Vehicle.cpp index 9937b1336..3954cb381 100644 --- a/src/game/Object/Vehicle.cpp +++ b/src/game/Object/Vehicle.cpp @@ -115,7 +115,7 @@ VehicleInfo::VehicleInfo(Unit* owner, VehicleEntry const* vehicleEntry, uint32 o if (IsUsableSeatForCreature(seatEntry->m_flags)) m_creatureSeats |= 1 << i; - if (IsUsableSeatForPlayer(seatEntry->m_flags)) + if (IsUsableSeatForPlayer(seatEntry->m_flags, seatEntry->m_flagsB)) m_playerSeats |= 1 << i; } } @@ -146,6 +146,32 @@ void VehicleInfo::Initialize() summoned->CastCustomSpell((Unit*)m_owner, SPELL_RIDE_VEHICLE_HARDCODED, &basepoint0, NULL, NULL, true); } } + + // Initialize movement limitations + uint32 vehicleFlags = GetVehicleEntry()->m_flags; + Unit* pVehicle = (Unit*)m_owner; + + if (vehicleFlags & VEHICLE_FLAG_NO_STRAFE) + pVehicle->m_movementInfo.AddMovementFlags2(MOVEFLAG2_NO_STRAFE); + if (vehicleFlags & VEHICLE_FLAG_NO_JUMPING) + pVehicle->m_movementInfo.AddMovementFlags2(MOVEFLAG2_NO_JUMPING); + if (vehicleFlags & VEHICLE_FLAG_FULLSPEEDTURNING) + pVehicle->m_movementInfo.AddMovementFlags2(MOVEFLAG2_FULLSPEEDTURNING); + if (vehicleFlags & VEHICLE_FLAG_ALLOW_PITCHING) + pVehicle->m_movementInfo.AddMovementFlags2(MOVEFLAG2_ALLOW_PITCHING); + if (vehicleFlags & VEHICLE_FLAG_FULLSPEEDPITCHING) + pVehicle->m_movementInfo.AddMovementFlags2(MOVEFLAG2_FULLSPEEDPITCHING); + + if (vehicleFlags & VEHICLE_FLAG_FIXED_POSITION) + pVehicle->SetRoot(true); + + // Initialize power type based on DBC values (creatures only) + if (pVehicle->GetTypeId() == TYPEID_UNIT) + { + if (PowerDisplayEntry const* powerEntry = sPowerDisplayStore.LookupEntry(GetVehicleEntry()->m_powerDisplayID)) + pVehicle->SetPowerType(Powers(powerEntry->power)); + } + m_isInitialized = true; } @@ -304,6 +330,7 @@ void VehicleInfo::UnBoard(Unit* passenger, bool changeVehicle) { Player* pPlayer = (Player*)passenger; pPlayer->ResummonPetTemporaryUnSummonedIfAny(); + pPlayer->SetFallInformation(0, pPlayer->GetPositionZ()); // SMSG_PET_DISMISS_SOUND (?) } @@ -473,9 +500,13 @@ uint8 VehicleInfo::GetTakenSeatsMask() const return takenSeatsMask; } -bool VehicleInfo:: IsUsableSeatForPlayer(uint32 seatFlags) const +bool VehicleInfo::IsUsableSeatForPlayer(uint32 seatFlags, uint32 seatFlagsB) const { - return seatFlags & SEAT_FLAG_USABLE; + return seatFlags & SEAT_FLAG_CAN_EXIT || + seatFlags & SEAT_FLAG_UNCONTROLLED || + seatFlagsB & + (SEAT_FLAG_B_USABLE_FORCED | SEAT_FLAG_B_USABLE_FORCED_2 | + SEAT_FLAG_B_USABLE_FORCED_3 | SEAT_FLAG_B_USABLE_FORCED_4); } /// Add control and such modifiers to a passenger if required @@ -483,10 +514,17 @@ void VehicleInfo::ApplySeatMods(Unit* passenger, uint32 seatFlags) { Unit* pVehicle = (Unit*)m_owner; // Vehicles are alawys Unit + if (seatFlags & SEAT_FLAG_NOT_SELECTABLE) + passenger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (passenger->GetTypeId() == TYPEID_PLAYER) { Player* pPlayer = (Player*)passenger; + // group update + if (pPlayer->GetGroup()) + pPlayer->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_VEHICLE_SEAT); + if (seatFlags & SEAT_FLAG_CAN_CONTROL) { pPlayer->GetCamera().SetView(pVehicle); @@ -511,10 +549,13 @@ void VehicleInfo::ApplySeatMods(Unit* passenger, uint32 seatFlags) { ((Creature*)pVehicle)->SetWalk(true, true); } + + // set vehicle faction as per the controller faction + ((Creature*)pVehicle)->SetFactionTemporary(pPlayer->getFaction(), TEMPFACTION_NONE); } } - if (seatFlags & (SEAT_FLAG_USABLE | SEAT_FLAG_CAN_CAST)) + if (seatFlags & SEAT_FLAG_CAN_CAST) { CharmInfo* charmInfo = pVehicle->InitCharmInfo(pVehicle); charmInfo->InitVehicleCreateSpells(); @@ -543,35 +584,47 @@ void VehicleInfo::RemoveSeatMods(Unit* passenger, uint32 seatFlags) { Unit* pVehicle = (Unit*)m_owner; + if (seatFlags & SEAT_FLAG_NOT_SELECTABLE) + passenger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (passenger->GetTypeId() == TYPEID_PLAYER) { Player* pPlayer = (Player*)passenger; + // group update + if (pPlayer->GetGroup()) + pPlayer->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_VEHICLE_SEAT); + if (seatFlags & SEAT_FLAG_CAN_CONTROL) { - pPlayer->SetCharm(NULL); + pPlayer->SetCharm(nullptr); pVehicle->SetCharmerGuid(ObjectGuid()); pPlayer->SetClientControl(pVehicle, 0); - pPlayer->SetMover(NULL); + pPlayer->SetMover(nullptr); pVehicle->clearUnitState(UNIT_STAT_CONTROLLED); pVehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); // must be called after movement control unapplying pPlayer->GetCamera().ResetView(); + + // reset vehicle faction + if (pVehicle->GetTypeId() == TYPEID_UNIT) + ((Creature*)pVehicle)->ClearTemporaryFaction(); } - if (seatFlags & (SEAT_FLAG_USABLE | SEAT_FLAG_CAN_CAST)) + if (seatFlags & SEAT_FLAG_CAN_CAST) pPlayer->RemovePetActionBar(); } else if (passenger->GetTypeId() == TYPEID_UNIT) { if (seatFlags & SEAT_FLAG_CAN_CONTROL) { - passenger->SetCharm(NULL); + passenger->SetCharm(nullptr); pVehicle->SetCharmerGuid(ObjectGuid()); } + // Reinitialize movement ((Creature*)passenger)->AI()->SetCombatMovement(true, true); if (!passenger->getVictim()) diff --git a/src/game/Object/Vehicle.h b/src/game/Object/Vehicle.h index ba38f860d..f18bebaff 100644 --- a/src/game/Object/Vehicle.h +++ b/src/game/Object/Vehicle.h @@ -74,6 +74,7 @@ class VehicleInfo : public TransportBase ~VehicleInfo(); VehicleEntry const* GetVehicleEntry() const { return m_vehicleEntry; } + VehicleSeatEntry const* GetSeatEntry(uint8 seat) const; void Board(Unit* passenger, uint8 seat); // Board a passenger to a vehicle void SwitchSeat(Unit* passenger, uint8 seat); // Used to switch seats of a passenger @@ -89,7 +90,6 @@ class VehicleInfo : public TransportBase void CalculateBoardingPositionOf(float gx, float gy, float gz, float go, float& lx, float& ly, float& lz, float& lo) const; // Seat information - VehicleSeatEntry const* GetSeatEntry(uint8 seat) const; bool GetUsableSeatFor(Unit* passenger, uint8& seat) const; bool IsSeatAvailableFor(Unit* passenger, uint8 seat) const; @@ -97,8 +97,8 @@ class VehicleInfo : public TransportBase uint8 GetEmptySeatsMask() const { return ~GetTakenSeatsMask(); } uint8 GetEmptySeats() const { return m_vehicleSeats.size() - m_passengers.size(); } - bool IsUsableSeatForPlayer(uint32 seatFlags) const; - bool IsUsableSeatForCreature(uint32 seatFlags) const { return true; } // special flag?, !IsUsableSeatForPlayer(seatFlags)? + bool IsUsableSeatForPlayer(uint32 seatFlags, uint32 seatFlagsB) const; + bool IsUsableSeatForCreature(uint32 /*seatFlags*/) const { return true; } // special flag?, !IsUsableSeatForPlayer(seatFlags)? // Apply/ Remove Controlling of the vehicle void ApplySeatMods(Unit* passenger, uint32 seatFlags); diff --git a/src/game/OutdoorPvP/OutdoorPvPEP.cpp b/src/game/OutdoorPvP/OutdoorPvPEP.cpp index 9536a3f57..466c5ae0b 100644 --- a/src/game/OutdoorPvP/OutdoorPvPEP.cpp +++ b/src/game/OutdoorPvP/OutdoorPvPEP.cpp @@ -154,24 +154,24 @@ void OutdoorPvPEP::HandleObjectiveComplete(uint32 eventId, const std::list::const_iterator itr = players.begin(); itr != players.end(); ++itr) diff --git a/src/game/OutdoorPvP/OutdoorPvPHP.cpp b/src/game/OutdoorPvP/OutdoorPvPHP.cpp index bd3ba39ec..d29dd0133 100644 --- a/src/game/OutdoorPvP/OutdoorPvPHP.cpp +++ b/src/game/OutdoorPvP/OutdoorPvPHP.cpp @@ -141,7 +141,7 @@ void OutdoorPvPHP::HandleObjectiveComplete(uint32 eventId, const std::listGetTeam() == team) { (*itr)->KilledMonsterCredit(credit); - (*itr)->RewardHonor(nullptr, 1, HONOR_REWARD_HELLFIRE); + (*itr)->RewardHonor(NULL, 1, HONOR_REWARD_HELLFIRE); } } } diff --git a/src/game/OutdoorPvP/OutdoorPvPNA.cpp b/src/game/OutdoorPvP/OutdoorPvPNA.cpp index ef737d184..cd04fe554 100644 --- a/src/game/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/game/OutdoorPvP/OutdoorPvPNA.cpp @@ -537,7 +537,8 @@ void OutdoorPvPNA::RespawnSoldier() if (Player* player = sObjectMgr.GetPlayer(itr->first)) { // summon a soldier replacement in the order they were set in the deque. delete the element after summon - player->SummonCreature(m_zoneOwner == ALLIANCE ? NPC_ALLIANCE_HANAANI_GUARD : NPC_HORDE_HALAANI_GUARD, m_deadSoldiers.front().x, m_deadSoldiers.front().y, m_deadSoldiers.front().z, m_deadSoldiers.front().o, TEMPSUMMON_DEAD_DESPAWN, 0, true); + const HalaaSoldiersSpawns& location = m_deadSoldiers.front(); + player->SummonCreature(m_zoneOwner == ALLIANCE ? NPC_ALLIANCE_HANAANI_GUARD : NPC_HORDE_HALAANI_GUARD, location.x, location.y, location.z, location.o, TEMPSUMMON_DEAD_DESPAWN, 0, true); m_deadSoldiers.pop(); break; } diff --git a/src/game/Server/DBCEnums.h b/src/game/Server/DBCEnums.h index d9fde5cca..75b257b68 100644 --- a/src/game/Server/DBCEnums.h +++ b/src/game/Server/DBCEnums.h @@ -593,6 +593,7 @@ enum VehicleFlags VEHICLE_FLAG_UNK12 = 0x00080000, VEHICLE_FLAG_UNK13 = 0x00100000, VEHICLE_FLAG_UNK14 = 0x00200000, + VEHICLE_FLAG_FIXED_POSITION = 0x00200000, // Used for vehicles that have a fixed position, such as cannons VEHICLE_FLAG_DISABLE_SWITCH = 0x00400000, // Can't change seats, VEHICLE_ID = 335 chopper VEHICLE_FLAG_UNK15 = 0x00800000, VEHICLE_FLAG_UNK16 = 0x01000000, @@ -620,19 +621,19 @@ enum VehicleSeatFlags SEAT_FLAG_UNK10 = 0x00000400, // "AllowsTurning" SEAT_FLAG_CAN_CONTROL = 0x00000800, // Lua_UnitInVehicleControlSeat SEAT_FLAG_UNK11 = 0x00001000, // "Can Cast Mount Spell" - SEAT_FLAG_UNK12 = 0x00002000, // "Uncontrolled" + SEAT_FLAG_UNCONTROLLED = 0x00002000, // "Uncontrolled" SEAT_FLAG_CAN_ATTACK = 0x00004000, // Can attack, cast spells and use items from vehicle? SEAT_FLAG_UNK13 = 0x00008000, // "ShouldUseVehicleSeatExitAnimationOnForcedExit" SEAT_FLAG_UNK14 = 0x00010000, SEAT_FLAG_UNK15 = 0x00020000, SEAT_FLAG_UNK16 = 0x00040000, // "HasVehicleExitAnimForVoluntaryExit" SEAT_FLAG_UNK17 = 0x00080000, // "HasVehicleExitAnimForForcedExit" - SEAT_FLAG_UNK18 = 0x00100000, + SEAT_FLAG_NOT_SELECTABLE = 0x00100000, SEAT_FLAG_UNK19 = 0x00200000, SEAT_FLAG_UNK20 = 0x00400000, // "RecHasVehicleEnterAnim" SEAT_FLAG_UNK21 = 0x00800000, // Lua_IsUsingVehicleControls SEAT_FLAG_UNK22 = 0x01000000, // "EnableVehicleZoom" - SEAT_FLAG_USABLE = 0x02000000, // Lua_CanExitVehicle + SEAT_FLAG_CAN_EXIT = 0x02000000, // Lua_CanExitVehicle SEAT_FLAG_CAN_SWITCH = 0x04000000, // Lua_CanSwitchVehicleSeats SEAT_FLAG_UNK23 = 0x08000000, // "HasStartWaitingForVehicleTransitionAnimEnter" SEAT_FLAG_UNK24 = 0x10000000, // "HasStartWaitingForVehicleTransitionAnimExit" @@ -641,4 +642,16 @@ enum VehicleSeatFlags SEAT_FLAG_UNK26 = 0x80000000, // "AllowsInteraction" }; +enum VehicleSeatFlagsB +{ + SEAT_FLAG_B_USABLE_FORCED = 0x00000002, + SEAT_FLAG_B_TARGETS_IN_RAIDUI = 0x00000008, // Lua_UnitTargetsVehicleInRaidUI + SEAT_FLAG_B_EJECTABLE = 0x00000020, // Ejectable + SEAT_FLAG_B_USABLE_FORCED_2 = 0x00000040, + SEAT_FLAG_B_USABLE_FORCED_3 = 0x00000100, + SEAT_FLAG_B_USABLE_FORCED_4 = 0x02000000, + SEAT_FLAG_B_CAN_SWITCH = 0x04000000, + SEAT_FLAG_B_PLAYERFRAME_UI = 0x80000000 // Lua_UnitHasVehiclePlayerFrameUI +}; + #endif diff --git a/src/game/Server/DBCStores.cpp b/src/game/Server/DBCStores.cpp index 8d5416a38..e188296ed 100644 --- a/src/game/Server/DBCStores.cpp +++ b/src/game/Server/DBCStores.cpp @@ -165,6 +165,7 @@ DBCStorage sQuestSortStore(QuestSortEntryfmt); DBCStorage sQuestXPLevelStore(QuestXPLevelfmt); DBCStorage sPhaseStore(Phasefmt); +DBCStorage sPowerDisplayStore(PowerDisplayfmt); DBCStorage sPvPDifficultyStore(PvPDifficultyfmt); DBCStorage sRandomPropertiesPointsStore(RandomPropertiesPointsfmt); @@ -599,6 +600,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bar, bad_dbc_files, sQuestSortStore, dbcPath, "QuestSort.dbc"); LoadDBC(availableDbcLocales, bar, bad_dbc_files, sQuestXPLevelStore, dbcPath, "QuestXP.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sPhaseStore, dbcPath,"Phase.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sPowerDisplayStore, dbcPath,"PowerDisplay.dbc"); LoadDBC(availableDbcLocales, bar, bad_dbc_files, sPvPDifficultyStore, dbcPath, "PvpDifficulty.dbc"); for (uint32 i = 0; i < sPvPDifficultyStore.GetNumRows(); ++i) if (PvPDifficultyEntry const* entry = sPvPDifficultyStore.LookupEntry(i)) diff --git a/src/game/Server/DBCStores.h b/src/game/Server/DBCStores.h index 0cd62a5bb..8027817b1 100644 --- a/src/game/Server/DBCStores.h +++ b/src/game/Server/DBCStores.h @@ -206,6 +206,7 @@ extern DBCStorage sQuestFactionRewardStore; extern DBCStorage sQuestSortStore; extern DBCStorage sQuestXPLevelStore; extern DBCStorage sPhaseStore; +extern DBCStorage sPowerDisplayStore; // extern DBCStorage sPvPDifficultyStore; -- use GetBattlegroundSlotByLevel for access extern DBCStorage sRandomPropertiesPointsStore; extern DBCStorage sScalingStatDistributionStore; diff --git a/src/game/Server/DBCStructure.h b/src/game/Server/DBCStructure.h index 5359ec371..f1b21ff87 100644 --- a/src/game/Server/DBCStructure.h +++ b/src/game/Server/DBCStructure.h @@ -1456,6 +1456,16 @@ struct PhaseEntry uint32 Flags; // 2 - 0x0, 0x4, 0x8 }; +struct PowerDisplayEntry +{ + uint32 id; // 0 m_ID + uint32 power; // 1 m_power + // uint32 unk1 // 2 + // float unk2 // 3 + // float unk3 // 4 + // float unk4 // 5 +}; + struct PvPDifficultyEntry { //uint32 id; // 0 m_ID @@ -1807,32 +1817,31 @@ struct SpellCooldownsEntry // SpellEffect.dbc struct SpellEffectEntry { - //uint32 Id; // 0 m_ID - uint32 Effect; // 73-75 m_effect - float EffectMultipleValue; // 106-108 m_effectAmplitude - uint32 EffectApplyAuraName; // 100-102 m_effectAura - uint32 EffectAmplitude; // 103-105 m_effectAuraPeriod - int32 EffectBasePoints; // 82-84 m_effectBasePoints (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints) - //float unk_320_4; // 169-171 3.2.0 - float DmgMultiplier; // 156-158 m_effectChainAmplitude - uint32 EffectChainTarget; // 109-111 m_effectChainTargets - int32 EffectDieSides; // 76-78 m_effectDieSides - uint32 EffectItemType; // 112-114 m_effectItemType - uint32 EffectMechanic; // 85-87 m_effectMechanic - int32 EffectMiscValue; // 115-117 m_effectMiscValue - int32 EffectMiscValueB; // 118-120 m_effectMiscValueB - float EffectPointsPerComboPoint; // 124-126 m_effectPointsPerCombo - uint32 EffectRadiusIndex; // 94-96 m_effectRadiusIndex - spellradius.dbc - uint32 EffectRadiusMaxIndex; // 97-99 4.0.0 - float EffectRealPointsPerLevel; // 79-81 m_effectRealPointsPerLevel - ClassFamilyMask EffectSpellClassMask; // 127-129 m_effectSpellClassMask - uint32 EffectTriggerSpell; // 121-123 m_effectTriggerSpell - uint32 EffectImplicitTargetA; // 88-90 m_implicitTargetA - uint32 EffectImplicitTargetB; // 91-93 m_implicitTargetB - uint32 EffectSpellId; // new 4.0.0 - uint32 EffectIndex; // new 4.0.0 - //uint32 unk; // 24 - 4.2.0 - + //uint32 Id; // 0 m_ID + uint32 Effect; // 1 m_effect + float EffectMultipleValue; // 2 m_effectAmplitude + uint32 EffectApplyAuraName; // 3 m_effectAura + uint32 EffectAmplitude; // 4 m_effectAuraPeriod + int32 EffectBasePoints; // 5 m_effectBasePoints (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints) + float EffectBonusMultiplier; // 6 m_effectBonus + float EffectDamageMultiplier; // 7 m_effectChainAmplitude + uint32 EffectChainTarget; // 8 m_effectChainTargets + int32 EffectDieSides; // 9 m_effectDieSides + uint32 EffectItemType; // 10 m_effectItemType + uint32 EffectMechanic; // 11 m_effectMechanic + int32 EffectMiscValue; // 12 m_effectMiscValue + int32 EffectMiscValueB; // 13 m_effectMiscValueB + float EffectPointsPerComboPoint; // 14 m_effectPointsPerCombo + uint32 EffectRadiusIndex; // 15 m_effectRadiusIndex - spellradius.dbc + uint32 EffectRadiusMaxIndex; // 16 4.0.0 + float EffectRealPointsPerLevel; // 17 m_effectRealPointsPerLevel + ClassFamilyMask EffectSpellClassMask; // 18 19 20 m_effectSpellClassMask + uint32 EffectTriggerSpell; // 21 m_effectTriggerSpell + uint32 EffectImplicitTargetA; // 22 m_implicitTargetA + uint32 EffectImplicitTargetB; // 23 m_implicitTargetB + uint32 EffectSpellId; // 24 m_spellId - spell.dbc + uint32 EffectIndex; // 25 m_spellEffectIdx + //uint32 unk; // 26 4.2.0 only 0 or 1 // helpers int32 CalculateSimpleValue() const { return EffectBasePoints; } @@ -2353,7 +2362,7 @@ struct VehicleEntry uint32 m_uiLocomotionType; // 34 float m_msslTrgtImpactTexRadius; // 35 uint32 m_uiSeatIndicatorType; // 36 m_vehicleUIIndicatorID - uint32 m_powerType; // 37 m_powerDisplayID + uint32 m_powerDisplayID; // 37 // 38 new in 3.1 // 39 new in 3.1 }; @@ -2421,9 +2430,6 @@ struct VehicleSeatEntry //uint32 unk[6]; // 58-63 //uint32 unk2; // 64 4.0.0 //uint32 unk3; // 65 4.0.1 - - bool IsUsable() const { return m_flags & SEAT_FLAG_USABLE; } - }; struct WMOAreaTableEntry diff --git a/src/game/Server/DBCfmt.h b/src/game/Server/DBCfmt.h index e208336ce..d1928bc82 100644 --- a/src/game/Server/DBCfmt.h +++ b/src/game/Server/DBCfmt.h @@ -104,7 +104,8 @@ const char OverrideSpellDatafmt[]="niiiiiiiiiixx"; const char QuestFactionRewardfmt[] = "niiiiiiiiii"; const char QuestSortEntryfmt[]="nx"; const char QuestXPLevelfmt[] = "niiiiiiiiii"; -const char Phasefmt[]="nii"; +const char Phasefmt[] = "nii"; +const char PowerDisplayfmt[] = "nixxxx"; const char PvPDifficultyfmt[] = "diiiii"; const char RandomPropertiesPointsfmt[] = "niiiiiiiiiiiiiii"; const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiixi"; diff --git a/src/game/Server/SharedDefines.h b/src/game/Server/SharedDefines.h index 2bb5f86c6..9bf7c830c 100644 --- a/src/game/Server/SharedDefines.h +++ b/src/game/Server/SharedDefines.h @@ -326,13 +326,13 @@ enum SpellAttributesEx SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE = 0x00010000,// 16 unaffected by school immunity SPELL_ATTR_EX_UNK17 = 0x00020000,// 17 for auras SPELL_AURA_TRACK_CREATURES, SPELL_AURA_TRACK_RESOURCES and SPELL_AURA_TRACK_STEALTHED select non-stacking tracking spells SPELL_ATTR_EX_UNK18 = 0x00040000,// 18 - SPELL_ATTR_EX_UNK19 = 0x00080000,// 19 + SPELL_ATTR_EX_CANT_TARGET_SELF = 0x00080000,// 19 spells with area effect or friendly targets that exclude the caster SPELL_ATTR_EX_REQ_TARGET_COMBO_POINTS = 0x00100000,// 20 Req combo points on target SPELL_ATTR_EX_UNK21 = 0x00200000,// 21 - SPELL_ATTR_EX_REQ_COMBO_POINTS = 0x00400000,// 22 Use combo points (in 4.x not required combo point target selected) + SPELL_ATTR_EX_REQ_COMBO_POINTS = 0x00400000,// 22 Use combo points SPELL_ATTR_EX_UNK23 = 0x00800000,// 23 SPELL_ATTR_EX_UNK24 = 0x01000000,// 24 Req fishing pole?? - SPELL_ATTR_EX_UNK25 = 0x02000000,// 25 not set in 2.4.2 + SPELL_ATTR_EX_UNK25 = 0x02000000,// 25 SPELL_ATTR_EX_UNK26 = 0x04000000,// 26 SPELL_ATTR_EX_UNK27 = 0x08000000,// 27 SPELL_ATTR_EX_UNK28 = 0x10000000,// 28 @@ -896,11 +896,11 @@ enum SpellEffects SPELL_EFFECT_LEAP_BACK = 138, SPELL_EFFECT_CLEAR_QUEST = 139, SPELL_EFFECT_FORCE_CAST = 140, - SPELL_EFFECT_141 = 141, + SPELL_EFFECT_FORCE_CAST_WITH_VALUE = 141, SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE = 142, SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143, SPELL_EFFECT_KNOCKBACK_FROM_POSITION = 144, - SPELL_EFFECT_145 = 145, + SPELL_EFFECT_GRAVITY_PULL = 145, SPELL_EFFECT_ACTIVATE_RUNE = 146, SPELL_EFFECT_QUEST_FAIL = 147, SPELL_EFFECT_148 = 148, @@ -1411,7 +1411,7 @@ enum Targets TARGET_SELF = 1, TARGET_RANDOM_ENEMY_CHAIN_IN_AREA = 2, // only one spell has that, but regardless, it's a target type after all TARGET_RANDOM_FRIEND_CHAIN_IN_AREA = 3, - TARGET_4 = 4, // some plague spells that are infectious - maybe targets not-infected friends inrange + TARGET_RANDOM_UNIT_CHAIN_IN_AREA = 4, // some plague spells that are infectious - maybe targets not-infected friends inrange TARGET_PET = 5, TARGET_CHAIN_DAMAGE = 6, TARGET_AREAEFFECT_INSTANT = 7, // targets around provided destination point @@ -1460,7 +1460,7 @@ enum Targets TARGET_ALL_RAID_AROUND_CASTER = 56, TARGET_SINGLE_FRIEND_2 = 57, TARGET_58 = 58, - TARGET_59 = 59, + TARGET_FRIENDLY_FRONTAL_CONE = 59, TARGET_NARROW_FRONTAL_CONE = 60, TARGET_AREAEFFECT_PARTY_AND_CLASS = 61, TARGET_DUELVSPLAYER_COORDINATES = 63, @@ -1503,12 +1503,12 @@ enum Targets TARGET_VEHICLE_PASSENGER_6 = 102, TARGET_VEHICLE_PASSENGER_7 = 103, TARGET_IN_FRONT_OF_CASTER_30 = 104, - TARGET_105 = 105, // 1 spell + TARGET_105 = 105, TARGET_106 = 106, TARGET_107 = 107, // possible TARGET_WMO(GO?)_IN_FRONT_OF_CASTER(_30 ?) TODO: Verify the angle! TARGET_GO_IN_FRONT_OF_CASTER_90 = 108, TARGET_109 = 109, // spell 89008 - TARGET_110 = 110, // front enemy aoe + TARGET_NARROW_FRONTAL_CONE_2 = 110, TARGET_111 = 111, // not used TARGET_112 = 112, // spell 89549 TARGET_113 = 113, // not used @@ -1597,8 +1597,10 @@ enum DamageEffectType DOT = 2, HEAL = 3, /// used also in case when damage applied to health but not applied to spell channelInterruptFlags/etc - NODAMAGE = 4, - SELF_DAMAGE = 5 + NODAMAGE = 4, + /// used to avoid rogue loosing stealth on falling damage + SELF_DAMAGE_ROGUE_FALL = 5, + SELF_DAMAGE = 6 }; enum GameobjectTypes diff --git a/src/game/Server/WorldSession.cpp b/src/game/Server/WorldSession.cpp index 769b5de5a..c311b5c73 100644 --- a/src/game/Server/WorldSession.cpp +++ b/src/game/Server/WorldSession.cpp @@ -671,6 +671,51 @@ void WorldSession::SendNotification(int32 string_id, ...) } } +void WorldSession::SendSetPhaseShift(uint32 phaseMask, uint16 mapId) +{ + ObjectGuid guid = _player->GetObjectGuid(); + + uint32 phaseFlags = 0; + + for (uint32 i = 0; i < sPhaseStore.GetNumRows(); i++) + { + if (PhaseEntry const* phase = sPhaseStore.LookupEntry(i)) + { + if (phase->PhaseShift == phaseMask) + { + phaseFlags = phase->Flags; + break; + } + } + } + + WorldPacket data(SMSG_SET_PHASE_SHIFT, 30); + data.WriteGuidMask<2, 3, 1, 6, 4, 5, 0, 7>(guid); + data.WriteGuidBytes<7, 4>(guid); + + data << uint32(0); // number of WorldMapArea.dbc entries to control world map shift * 2 + + data.WriteGuidBytes<1>(guid); + data << uint32(phaseMask ? phaseFlags : 8); + data.WriteGuidBytes<2, 6>(guid); + + data << uint32(0); // number of inactive terrain swaps * 2 + + data << uint32(phaseMask ? 2 : 0); // WRONG: number of Phase.dbc ids * 2 + if (phaseMask) + data << uint16(phaseMask); + + data.WriteGuidBytes<3, 0>(guid); + + data << uint32(mapId ? 2 : 0); // number of terrains swaps * 2 + if (mapId) + data << uint16(mapId); + + data.WriteGuidBytes<5>(guid); + SendPacket(&data); +} + +/* void WorldSession::SendSetPhaseShift(std::set const& phaseIds, std::set const& terrainswaps) { if (PlayerLoading()) @@ -707,6 +752,7 @@ void WorldSession::SendSetPhaseShift(std::set const& phaseIds, std::set< data.WriteGuidBytes<5>(guid); SendPacket(&data); } +*/ const char* WorldSession::GetMangosString(int32 entry) const { @@ -807,7 +853,7 @@ void WorldSession::LoadAccountData(QueryResult* result, uint32 mask) delete result; } -void WorldSession::SetAccountData(AccountDataType type, time_t time_, std::string data) +void WorldSession::SetAccountData(AccountDataType type, time_t time_, const std::string& data) { if ((1 << type) & GLOBAL_CACHE_MASK) { @@ -828,7 +874,7 @@ void WorldSession::SetAccountData(AccountDataType type, time_t time_, std::strin } else { - // _player can be NULL and packet received after logout but m_GUID still store correct guid + // _player can be nullptr and packet received after logout but m_GUID still store correct guid if (!m_GUIDLow) return; diff --git a/src/game/Server/WorldSession.h b/src/game/Server/WorldSession.h index ba8388201..14d9ac190 100644 --- a/src/game/Server/WorldSession.h +++ b/src/game/Server/WorldSession.h @@ -277,7 +277,7 @@ class WorldSession void SendGroupInvite(Player* player, bool alreadyInGroup = false); void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2, 3); void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0); - void SendSetPhaseShift(std::set const& phaseIds, std::set const& terrainswaps); + void SendSetPhaseShift(uint32 phaseMask, uint16 mapId = 0); void SendQueryTimeResponse(); void SendRedirectClient(std::string& ip, uint16 port); @@ -380,7 +380,7 @@ class WorldSession // Account Data AccountData* GetAccountData(AccountDataType type) { return &m_accountData[type]; } - void SetAccountData(AccountDataType type, time_t time_, std::string data); + void SetAccountData(AccountDataType type, time_t time_, const std::string& data); void SendAccountDataTimes(uint32 mask); void LoadGlobalAccountData(); void LoadAccountData(QueryResult* result, uint32 mask); @@ -778,8 +778,8 @@ class WorldSession void HandleQuestPushResult(WorldPacket& recvPacket); bool processChatmessageFurtherAfterSecurityChecks(std::string&, uint32); - void SendPlayerNotFoundNotice(std::string name); - void SendPlayerAmbiguousNotice(std::string name); + void SendPlayerNotFoundNotice(const std::string& name); + void SendPlayerAmbiguousNotice(const std::string& name); void SendWrongFactionNotice(); void SendChatRestrictedNotice(ChatRestrictionType restriction); void HandleMessagechatOpcode(WorldPacket& recvPacket); diff --git a/src/game/Tools/Language.h b/src/game/Tools/Language.h index 557e015f3..f4480d941 100644 --- a/src/game/Tools/Language.h +++ b/src/game/Tools/Language.h @@ -210,39 +210,39 @@ enum MangosStrings LANG_RESETALL_SPELLS = 218, LANG_RESETALL_TALENTS = 219, - LANG_WAYPOINT_NOTFOUND = 220, - LANG_WAYPOINT_NOTFOUNDLAST = 221, - LANG_WAYPOINT_NOTFOUNDSEARCH = 222, - LANG_WAYPOINT_NOTFOUNDDBPROBLEM = 223, - LANG_WAYPOINT_CREATSELECTED = 224, - LANG_WAYPOINT_CREATNOTFOUND = 225, - LANG_WAYPOINT_VP_SELECT = 226, - LANG_WAYPOINT_VP_NOTFOUND = 227, - LANG_WAYPOINT_VP_NOTCREATED = 228, - LANG_WAYPOINT_VP_ALLREMOVED = 229, - LANG_WAYPOINT_NOTCREATED = 230, - LANG_WAYPOINT_NOGUID = 231, - LANG_WAYPOINT_NOWAYPOINTGIVEN = 232, - LANG_WAYPOINT_ARGUMENTREQ = 233, - LANG_WAYPOINT_ADDED = 234, - LANG_WAYPOINT_ADDED_NO = 235, - LANG_WAYPOINT_CHANGED = 236, - LANG_WAYPOINT_CHANGED_NO = 237, - LANG_WAYPOINT_EXPORTED = 238, - LANG_WAYPOINT_NOTHINGTOEXPORT = 239, - LANG_WAYPOINT_IMPORTED = 240, - LANG_WAYPOINT_REMOVED = 241, - LANG_WAYPOINT_NOTREMOVED = 242, - LANG_WAYPOINT_TOOFAR1 = 243, - LANG_WAYPOINT_TOOFAR2 = 244, - LANG_WAYPOINT_TOOFAR3 = 245, - LANG_WAYPOINT_INFO_TITLE = 246, - LANG_WAYPOINT_INFO_WAITTIME = 247, - LANG_WAYPOINT_INFO_MODEL = 248, - LANG_WAYPOINT_INFO_EMOTE = 249, - LANG_WAYPOINT_INFO_SPELL = 250, - LANG_WAYPOINT_INFO_TEXT = 251, - LANG_WAYPOINT_INFO_AISCRIPT = 252, + LANG_WAYPOINT_NOTFOUND = 220, // Cannot find waypoint id %u for %s (in path %i, loaded from %s) + LANG_WAYPOINT_NOTFOUNDLAST = 221, // Last Waypoint not found for %s + LANG_WAYPOINT_NOTFOUNDPATH = 222, // %s has no path or path empty, path-id %i (loaded from %s) + LANG_WAYPOINT_NOTFOUNDDBPROBLEM = 223, // Creature (GUID: %u) No waypoints found - This is a MaNGOS db problem (single float). + LANG_WAYPOINT_NOTFOUND_NPC = 224, // Cannot access %s on map, maybe you are too far away from its spawn location + LANG_WAYPOINT_CREATNOTFOUND = 225, // Creature (GUID: %u) not found + LANG_WAYPOINT_VP_SELECT = 226, // You must select a visual waypoint. + LANG_WAYPOINT_VP_NOTFOUND = 227, // No visual waypoints found + LANG_WAYPOINT_VP_NOTCREATED = 228, // Could not create visual waypoint with creatureID: %d + LANG_WAYPOINT_VP_ALLREMOVED = 229, // All visual waypoints removed + LANG_WAYPOINT_NOTCREATED = 230, // Could not add waypoint %u to %s (pathId %i stored by %s) + LANG_WAYPOINT_NOGUID = 231, // No GUID provided. + LANG_WAYPOINT_NOWAYPOINTGIVEN = 232, // No waypoint number provided. + LANG_WAYPOINT_ARGUMENTREQ = 233, // Argument required for \'%s\'. + LANG_WAYPOINT_ADDED = 234, // Added Waypoint %u to %s (PathId %i, path stored by %s) + LANG_WAYPOINT_ADDED_NO = 235, // UNUSED + LANG_WAYPOINT_CHANGED = 236, // Waypoint changed. + LANG_WAYPOINT_CHANGED_NO = 237, // Waypoint %s modified. + LANG_WAYPOINT_EXPORTED = 238, // WP export successfull. + LANG_WAYPOINT_NOTHINGTOEXPORT = 239, // No waypoints found inside the database. + LANG_WAYPOINT_IMPORTED = 240, // File imported. + LANG_WAYPOINT_REMOVED = 241, // Waypoint removed. + LANG_WAYPOINT_NOTREMOVED = 242, // UNUSED + LANG_WAYPOINT_TOOFAR1 = 243, // UNUSED + LANG_WAYPOINT_TOOFAR2 = 244, // UNUSED + LANG_WAYPOINT_TOOFAR3 = 245, // UNUSED + LANG_WAYPOINT_INFO_TITLE = 246, // Waypoint %u for %s (from pathId %i, stored by %s) + LANG_WAYPOINT_INFO_WAITTIME = 247, // Waittime: %d + LANG_WAYPOINT_INFO_ORI = 248, // Orientation: %f + LANG_WAYPOINT_INFO_SCRIPTID = 249, // ScriptId: %u + LANG_WAYPOINT_INFO_UNK_SCRIPTID = 250, // ScriptID set to non-existing id %u, add it to DBScriptsEngine and reload the table. + LANG_WAYPOINT_INFO_TEXT = 251, // UNUSED + LANG_WAYPOINT_INFO_AISCRIPT = 252, // AIScriptName: %s LANG_RENAME_PLAYER = 253, LANG_RENAME_PLAYER_GUID = 254, @@ -742,13 +742,12 @@ enum MangosStrings LANG_DEBUG_ARENA_OFF = 738, LANG_DEBUG_BG_ON = 739, LANG_DEBUG_BG_OFF = 740, - - LANG_DIST_ARENA_POINTS_START = 741, - LANG_DIST_ARENA_POINTS_ONLINE_START = 742, - LANG_DIST_ARENA_POINTS_ONLINE_END = 743, - LANG_DIST_ARENA_POINTS_TEAM_START = 744, - LANG_DIST_ARENA_POINTS_TEAM_END = 745, - LANG_DIST_ARENA_POINTS_END = 746, +// = 741, not used +// = 742, not used +// = 743, not used +// = 744, not used +// = 745, not used +// = 746, not used // = 747, not used // = 748, not used // = 749, not used @@ -1026,14 +1025,6 @@ enum MangosStrings LANG_VENDOR_WRONG_ITEM_TYPE = 1700, LANG_VENDOR_WRONG_CURRENCY_MAXCOUNT = 1701, - LANG_PHASING_REPORT_STATUS = 1702, - LANG_PHASING_NO_DEFINITIONS = 1703, - LANG_PHASING_SUCCESS = 1704, - LANG_PHASING_FAILED = 1705, - LANG_PHASING_LAST_PHASE = 1706, - LANG_PHASING_LIST = 1707, - LANG_PHASING_PHASEMASK = 1708, - // FREE IDS 1800-9999 // Use for not-in-official-sources patches @@ -1045,4 +1036,5 @@ enum MangosStrings // `db_script_string` table index 2000000000-2000999999 (MIN_DB_SCRIPT_STRING_ID-MAX_DB_SCRIPT_STRING_ID) // For other tables maybe 2001000000-2147483647 (max index) }; + #endif diff --git a/src/game/Tools/PlayerDump.cpp b/src/game/Tools/PlayerDump.cpp index 9506feb20..556a7458e 100644 --- a/src/game/Tools/PlayerDump.cpp +++ b/src/game/Tools/PlayerDump.cpp @@ -557,8 +557,8 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s if (!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); - - if (name == "") + + if (name.empty()) { // check if the original name already exists name = getnth(line, 3); // characters.name diff --git a/src/game/WorldHandlers/AchievementMgr.cpp b/src/game/WorldHandlers/AchievementMgr.cpp index 969b47252..3c536c4d6 100644 --- a/src/game/WorldHandlers/AchievementMgr.cpp +++ b/src/game/WorldHandlers/AchievementMgr.cpp @@ -64,7 +64,7 @@ namespace MaNGOS { char const* text = sObjectMgr.GetMangosString(i_textId, loc_idx); - ChatHandler::BuildChatPacket(data, i_msgtype, text, LANG_UNIVERSAL, i_player.GetChatTag(), i_player.GetObjectGuid(), nullptr, i_player.GetObjectGuid(), nullptr, nullptr, + ChatHandler::BuildChatPacket(data, i_msgtype, text, LANG_UNIVERSAL, i_player.GetChatTag(), i_player.GetObjectGuid(), NULL, i_player.GetObjectGuid(), NULL, NULL, i_achievementId); } diff --git a/src/game/WorldHandlers/ChannelMgr.cpp b/src/game/WorldHandlers/ChannelMgr.cpp index 6309d346d..ed69a4738 100644 --- a/src/game/WorldHandlers/ChannelMgr.cpp +++ b/src/game/WorldHandlers/ChannelMgr.cpp @@ -50,7 +50,7 @@ ChannelMgr::~ChannelMgr() channels.clear(); } -Channel* ChannelMgr::GetJoinChannel(std::string name, uint32 channel_id) +Channel* ChannelMgr::GetJoinChannel(const std::string& name, uint32 channel_id) { std::wstring wname; Utf8toWStr(name, wname); @@ -66,7 +66,7 @@ Channel* ChannelMgr::GetJoinChannel(std::string name, uint32 channel_id) return channels[wname]; } -Channel* ChannelMgr::GetChannel(std::string name, Player* p, bool pkt) +Channel* ChannelMgr::GetChannel(const std::string& name, Player* p, bool pkt) { std::wstring wname; Utf8toWStr(name, wname); @@ -83,13 +83,13 @@ Channel* ChannelMgr::GetChannel(std::string name, Player* p, bool pkt) p->GetSession()->SendPacket(&data); } - return NULL; + return nullptr; } else return i->second; } -void ChannelMgr::LeftChannel(std::string name) +void ChannelMgr::LeftChannel(const std::string& name) { std::wstring wname; Utf8toWStr(name, wname); @@ -109,7 +109,7 @@ void ChannelMgr::LeftChannel(std::string name) } } -void ChannelMgr::MakeNotOnPacket(WorldPacket* data, std::string name) +void ChannelMgr::MakeNotOnPacket(WorldPacket* data, const std::string& name) { data->Initialize(SMSG_CHANNEL_NOTIFY, (1 + 10)); // we guess size (*data) << (uint8)CHAT_NOT_MEMBER_NOTICE << name; diff --git a/src/game/WorldHandlers/ChannelMgr.h b/src/game/WorldHandlers/ChannelMgr.h index b44c0c963..276d18146 100644 --- a/src/game/WorldHandlers/ChannelMgr.h +++ b/src/game/WorldHandlers/ChannelMgr.h @@ -38,12 +38,12 @@ class ChannelMgr ChannelMgr() {} ~ChannelMgr(); - Channel* GetJoinChannel(std::string name, uint32 channel_id); - Channel* GetChannel(std::string name, Player* p, bool pkt = true); - void LeftChannel(std::string name); + Channel* GetJoinChannel(const std::string& name, uint32 channel_id); + Channel* GetChannel(const std::string& name, Player* p, bool pkt = true); + void LeftChannel(const std::string& name); private: ChannelMap channels; - void MakeNotOnPacket(WorldPacket* data, std::string name); + void MakeNotOnPacket(WorldPacket* data, const std::string& name); }; class AllianceChannelMgr : public ChannelMgr {}; diff --git a/src/game/WorldHandlers/CharacterHandler.cpp b/src/game/WorldHandlers/CharacterHandler.cpp index 1d093b0db..cdaed7173 100644 --- a/src/game/WorldHandlers/CharacterHandler.cpp +++ b/src/game/WorldHandlers/CharacterHandler.cpp @@ -1047,7 +1047,7 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult* result, uin WorldSession* session = sWorld.FindSession(accountId); if (!session) { - if (result) delete result; + delete result; return; } @@ -1077,6 +1077,8 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult* result, uin data << guid; data << newname; session->SendPacket(&data); + + sWorld.InvalidatePlayerDataToAllClient(guid); } void WorldSession::HandleSetPlayerDeclinedNamesOpcode(WorldPacket& recv_data) @@ -1325,6 +1327,8 @@ void WorldSession::HandleCharCustomizeOpcode(WorldPacket& recv_data) data << uint8(hairColor); data << uint8(facialHair); SendPacket(&data); + + sWorld.InvalidatePlayerDataToAllClient(guid); } void WorldSession::HandleEquipmentSetSaveOpcode(WorldPacket& recv_data) diff --git a/src/game/WorldHandlers/Chat.cpp b/src/game/WorldHandlers/Chat.cpp index 14c6ef026..91052a51c 100644 --- a/src/game/WorldHandlers/Chat.cpp +++ b/src/game/WorldHandlers/Chat.cpp @@ -450,7 +450,6 @@ ChatCommand* ChatHandler::getCommandTable() { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddCommand, "", NULL }, { "addcurrency", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddVendorCurrencyCommand,"", NULL }, { "additem", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddVendorItemCommand, "", NULL }, - { "addmove", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAddMoveCommand, "", NULL }, { "aiinfo", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcAIInfoCommand, "", NULL }, { "allowmove", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcAllowMovementCommand, "", NULL }, { "changeentry", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcChangeEntryCommand, "", NULL }, @@ -536,13 +535,13 @@ ChatCommand* ChatHandler::getCommandTable() { "creature_ai_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAIScriptsCommand, "", NULL }, { "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL }, { "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL }, - { "creature_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL }, - { "creature_template_classlevelstats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreaturesStatsCommand, "", nullptr }, + { "creature_battleground", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadBattleEventCommand, "", NULL }, + { "creature_template_classlevelstats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreaturesStatsCommand, "", NULL }, { "creature_involvedrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestInvRelationsCommand, "", NULL }, { "creature_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesCreatureCommand, "", NULL }, { "creature_questrelation", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCreatureQuestRelationsCommand, "", NULL }, { "db_script_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDbScriptStringCommand, "", NULL }, - { "dbscripts_on_creature_death", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnCreatureDeathCommand,"", NULL }, + { "dbscripts_on_creature_death", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnCreatureDeathCommand, "", NULL }, { "dbscripts_on_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnEventCommand, "", NULL }, { "dbscripts_on_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnGossipCommand, "", NULL }, { "dbscripts_on_go_use", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadDBScriptsOnGoUseCommand, "", NULL }, @@ -583,7 +582,6 @@ ChatCommand* ChatHandler::getCommandTable() { "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL }, { "npc_vendor", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcVendorCommand, "", NULL }, { "page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPageTextsCommand, "", NULL }, - { "phase_definitions", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPhaseDefinitionsCommand, "", NULL }, { "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand, "", NULL}, { "points_of_interest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPointsOfInterestCommand, "", NULL }, { "prospecting_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesProspectingCommand, "", NULL }, @@ -690,8 +688,8 @@ ChatCommand* ChatHandler::getCommandTable() { { "corpses", SEC_GAMEMASTER, true, &ChatHandler::HandleServerCorpsesCommand, "", NULL }, { "exit", SEC_CONSOLE, true, &ChatHandler::HandleServerExitCommand, "", NULL }, - { "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable }, - { "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable }, + { "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable }, + { "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverIdleShutdownCommandTable }, { "info", SEC_PLAYER, true, &ChatHandler::HandleServerInfoCommand, "", NULL }, { "log", SEC_CONSOLE, true, NULL, "", serverLogCommandTable }, { "motd", SEC_PLAYER, true, &ChatHandler::HandleServerMotdCommand, "", NULL }, @@ -2637,9 +2635,7 @@ char* ChatHandler::ExtractLinkArg(char** args, char const* const* linkTypes /*= if (*tail == ':' && somethingPair) // optional data extraction { // :something...|h[name]|h|r - - if (*tail == ':') - ++tail; + ++tail; // something|h[name]|h|r or something:something2...|h[name]|h|r @@ -3626,9 +3622,9 @@ void ChatHandler::LogCommand(char const* fullcmd) } void ChatHandler::BuildChatPacket(WorldPacket& data, ChatMsg msgtype, char const* message, Language language /*= LANG_UNIVERSAL*/, ChatTagFlags chatTag /*= CHAT_TAG_NONE*/, - ObjectGuid const& senderGuid /*= ObjectGuid()*/, char const* senderName /*= nullptr*/, - ObjectGuid const& targetGuid /*= ObjectGuid()*/, char const* targetName /*= nullptr*/, - char const* channelName /*= nullptr*/, uint32 achievementId /*= 0*/, const char* addonPrefix /*= nullptr*/) + ObjectGuid const& senderGuid /*= ObjectGuid()*/, char const* senderName /*= NULL*/, + ObjectGuid const& targetGuid /*= ObjectGuid()*/, char const* targetName /*= NULL*/, + char const* channelName /*= NULL*/, uint32 achievementId /*= 0*/, const char* addonPrefix /*= NULL*/) { bool isGM = chatTag & CHAT_TAG_GM; bool isAchievement = false; diff --git a/src/game/WorldHandlers/Chat.h b/src/game/WorldHandlers/Chat.h index c8582f1ab..044f1b661 100644 --- a/src/game/WorldHandlers/Chat.h +++ b/src/game/WorldHandlers/Chat.h @@ -368,7 +368,6 @@ class ChatHandler //-----------------------Npc Commands----------------------- bool HandleNpcAddCommand(char* args); - bool HandleNpcAddMoveCommand(char* args); bool HandleNpcAddVendorCurrencyCommand(char* args); bool HandleNpcAddVendorItemCommand(char* args); bool HandleNpcAIInfoCommand(char* args); @@ -538,6 +537,7 @@ class ChatHandler bool HandleServerLogLevelCommand(char* args); bool HandleServerMotdCommand(char* args); bool HandleServerPLimitCommand(char* args); + bool HandleServerResetAllRaidCommand(char* args); bool HandleServerRestartCommand(char* args); bool HandleServerSetMotdCommand(char* args); bool HandleServerShutDownCommand(char* args); @@ -640,8 +640,6 @@ class ChatHandler bool HandleMmap(char* args); bool HandleMmapTestArea(char* args); - bool HandleReloadPhaseDefinitionsCommand(char* /*args*/); - //! Development Commands bool HandleSaveAllCommand(char* args); diff --git a/src/game/WorldHandlers/ChatHandler.cpp b/src/game/WorldHandlers/ChatHandler.cpp index 8102e1858..d4a44a461 100644 --- a/src/game/WorldHandlers/ChatHandler.cpp +++ b/src/game/WorldHandlers/ChatHandler.cpp @@ -774,14 +774,14 @@ void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data) player->GetSession()->SendPacket(&data); } -void WorldSession::SendPlayerNotFoundNotice(std::string name) +void WorldSession::SendPlayerNotFoundNotice(const std::string& name) { WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, name.size() + 1); data << name; SendPacket(&data); } -void WorldSession::SendPlayerAmbiguousNotice(std::string name) +void WorldSession::SendPlayerAmbiguousNotice(const std::string& name) { WorldPacket data(SMSG_CHAT_PLAYER_AMBIGUOUS, name.size() + 1); data << name; diff --git a/src/game/WorldHandlers/CreatureLinkingMgr.cpp b/src/game/WorldHandlers/CreatureLinkingMgr.cpp index e4cabe8b3..d41036085 100644 --- a/src/game/WorldHandlers/CreatureLinkingMgr.cpp +++ b/src/game/WorldHandlers/CreatureLinkingMgr.cpp @@ -261,6 +261,7 @@ enum EventMask EVENT_MASK_ON_DIE = FLAG_DESPAWN_ON_DEATH | FLAG_SELFKILL_ON_DEATH | FLAG_RESPAWN_ON_DEATH | FLAG_FOLLOW, EVENT_MASK_ON_RESPAWN = FLAG_RESPAWN_ON_RESPAWN | FLAG_DESPAWN_ON_RESPAWN | FLAG_FOLLOW, EVENT_MASK_TRIGGER_TO = FLAG_TO_AGGRO_ON_AGGRO | FLAG_TO_RESPAWN_ON_EVADE | FLAG_FOLLOW, + EVENT_MASK_ON_DESPAWN = FLAG_DESPAWN_ON_DESPAWN, }; // This functions checks if the NPC has linked NPCs for dynamic action @@ -413,6 +414,7 @@ void CreatureLinkingHolder::DoCreatureLinkingEvent(CreatureLinkingEvent eventTyp case LINKING_EVENT_EVADE: eventFlagFilter = EVENT_MASK_ON_EVADE; reverseEventFlagFilter = FLAG_TO_RESPAWN_ON_EVADE; break; case LINKING_EVENT_DIE: eventFlagFilter = EVENT_MASK_ON_DIE; reverseEventFlagFilter = 0; break; case LINKING_EVENT_RESPAWN: eventFlagFilter = EVENT_MASK_ON_RESPAWN; reverseEventFlagFilter = FLAG_FOLLOW; break; + case LINKING_EVENT_DESPAWN: eventFlagFilter = EVENT_MASK_ON_DESPAWN; reverseEventFlagFilter = 0; break; } // Process Slaves (by entry) @@ -470,6 +472,7 @@ void CreatureLinkingHolder::DoCreatureLinkingEvent(CreatureLinkingEvent eventTyp SetFollowing(pSource, pMaster); break; case LINKING_EVENT_DIE: // Nothing linked for this case + case LINKING_EVENT_DESPAWN: // Nothing linked for this case break; } } @@ -549,6 +552,11 @@ void CreatureLinkingHolder::ProcessSlave(CreatureLinkingEvent eventType, Creatur if (flag & FLAG_FOLLOW && pSlave->IsAlive() && !pSlave->IsInCombat()) SetFollowing(pSlave, pSource); + break; + case LINKING_EVENT_DESPAWN: + if (flag & FLAG_DESPAWN_ON_DESPAWN && !pSlave->IsDespawned()) + pSlave->ForcedDespawn(); + break; } } diff --git a/src/game/WorldHandlers/CreatureLinkingMgr.h b/src/game/WorldHandlers/CreatureLinkingMgr.h index e9d5f5f94..c99d7540e 100644 --- a/src/game/WorldHandlers/CreatureLinkingMgr.h +++ b/src/game/WorldHandlers/CreatureLinkingMgr.h @@ -56,6 +56,7 @@ enum CreatureLinkingEvent LINKING_EVENT_EVADE = 1, LINKING_EVENT_DIE = 2, LINKING_EVENT_RESPAWN = 3, + LINKING_EVENT_DESPAWN = 4, }; // enum describing possible flags action flags for NPCs linked to other NPCs @@ -77,12 +78,13 @@ enum CreatureLinkingFlags // Dynamic behaviour, out of combat FLAG_FOLLOW = 0x0200, + FLAG_DESPAWN_ON_DESPAWN = 0x2000, // Passive behaviour FLAG_CANT_SPAWN_IF_BOSS_DEAD = 0x0400, FLAG_CANT_SPAWN_IF_BOSS_ALIVE = 0x0800, - LINKING_FLAG_INVALID = 0x2000, // TODO adjust when other flags are implemented + LINKING_FLAG_INVALID = 0x4000, // TODO adjust when other flags are implemented }; // Structure holding the information for an entry diff --git a/src/game/WorldHandlers/GridNotifiers.h b/src/game/WorldHandlers/GridNotifiers.h index 31da135dc..e5ad936a7 100644 --- a/src/game/WorldHandlers/GridNotifiers.h +++ b/src/game/WorldHandlers/GridNotifiers.h @@ -555,8 +555,11 @@ namespace MaNGOS void Visit(CameraMapType& m) { for (CameraMapType::iterator itr = m.begin(); itr != m.end(); ++itr) - if (itr->getSource()->GetBody()->InSamePhase(i_searcher) && itr->getSource()->GetBody()->IsWithinDist(i_searcher, i_dist)) - i_do(itr->getSource()->GetOwner()); + { + Camera* camera = itr->getSource(); + if (camera->GetBody()->InSamePhase(i_searcher) && camera->GetBody()->IsWithinDist(i_searcher, i_dist)) + i_do(camera->GetOwner()); + } } template void Visit(GridRefManager &) {} }; @@ -678,13 +681,14 @@ namespace MaNGOS WorldObject const& GetFocusObject() const { return *i_unit; } bool operator()(GameObject* go) const { - if (go->GetGOInfo()->type != GAMEOBJECT_TYPE_SPELL_FOCUS) + GameObjectInfo const* goInfo = go->GetGOInfo(); + if (goInfo->type != GAMEOBJECT_TYPE_SPELL_FOCUS) return false; - if (go->GetGOInfo()->spellFocus.focusId != i_focusId) + if (goInfo->spellFocus.focusId != i_focusId) return false; - float dist = (float)go->GetGOInfo()->spellFocus.dist; + float dist = (float)goInfo->spellFocus.dist; return go->IsWithinDistInMap(i_unit, dist); } diff --git a/src/game/WorldHandlers/Group.cpp b/src/game/WorldHandlers/Group.cpp index 14f7dc38a..f81cc143f 100644 --- a/src/game/WorldHandlers/Group.cpp +++ b/src/game/WorldHandlers/Group.cpp @@ -485,7 +485,7 @@ void Group::Disband(bool hideDestroy) } m_leaderGuid.Clear(); - m_leaderName = ""; + m_leaderName.clear(); } /*********************************************************/ diff --git a/src/game/WorldHandlers/GroupHandler.cpp b/src/game/WorldHandlers/GroupHandler.cpp index e7abfbf1a..2b8150c3b 100644 --- a/src/game/WorldHandlers/GroupHandler.cpp +++ b/src/game/WorldHandlers/GroupHandler.cpp @@ -37,6 +37,8 @@ #include "Util.h" #include "DB2Structure.h" #include "DB2Stores.h" +#include "Vehicle.h" +#include "TransportSystem.h" /* differeces from off: -you can uninvite yourself - is is useful @@ -905,6 +907,14 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player* player, WorldPacke *data << uint32(0); *data << uint8(0); } + + if (mask & GROUP_UPDATE_FLAG_VEHICLE_SEAT) + { + if (player->GetTransportInfo()) + *data << uint32(((Unit*)player->GetTransportInfo()->GetTransport())->GetVehicleInfo()->GetVehicleEntry()->m_seatID[player->GetTransportInfo()->GetTransportSeat()]); + else + *data << uint32(0); + } } /*this procedure handles clients CMSG_REQUEST_PARTY_MEMBER_STATS request*/ @@ -1048,6 +1058,9 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode(WorldPacket& recv_data) data << uint32(0); // GROUP_UPDATE_FLAG_PET_AURAS } + if (player->GetTransportInfo()) // GROUP_UPDATE_FLAG_VEHICLE_SEAT + data << uint32(((Unit*)player->GetTransportInfo()->GetTransport())->GetVehicleInfo()->GetVehicleEntry()->m_seatID[player->GetTransportInfo()->GetTransportSeat()]); + data << uint32(8); // GROUP_UPDATE_FLAG_PHASE data << uint32(0); // GROUP_UPDATE_FLAG_PHASE data << uint8(0); // GROUP_UPDATE_FLAG_PHASE diff --git a/src/game/WorldHandlers/InstanceData.cpp b/src/game/WorldHandlers/InstanceData.cpp index 147e21157..b9527ed95 100644 --- a/src/game/WorldHandlers/InstanceData.cpp +++ b/src/game/WorldHandlers/InstanceData.cpp @@ -59,3 +59,39 @@ bool InstanceData::CheckConditionCriteriaMeet(Player const* /*source*/, uint32 i instance->GetId(), instance_condition_id, uint32(conditionSourceType)); return false; } + +void InstanceData::SendEncounterFrame(uint32 type, ObjectGuid sourceGuid /*= NULL*/, uint8 param1 /*= 0*/, uint8 param2 /*= 0*/) +{ + // size of this packet is at most 15 (usually less) + WorldPacket data(SMSG_INSTANCE_ENCOUNTER, 15); + data << uint32(type); + + switch (type) + { + case ENCOUNTER_FRAME_ENGAGE: + case ENCOUNTER_FRAME_DISENGAGE: + case ENCOUNTER_FRAME_UPDATE_PRIORITY: + MANGOS_ASSERT(sourceGuid); + + data << sourceGuid.WriteAsPacked(); + data << uint8(param1); + break; + case ENCOUNTER_FRAME_ADD_TIMER: + case ENCOUNTER_FRAME_ENABLE_OBJECTIVE: + case ENCOUNTER_FRAME_DISABLE_OBJECTIVE: + case ENCOUNTER_FRAME_SET_COMBAT_RES_LIMIT: + data << uint8(param1); + break; + case ENCOUNTER_FRAME_UPDATE_OBJECTIVE: + data << uint8(param1); + data << uint8(param2); + break; + case ENCOUNTER_FRAME_UNK7: + case ENCOUNTER_FRAME_ADD_COMBAT_RES_LIMIT: + case ENCOUNTER_FRAME_RESET_COMBAT_RES_LIMIT: + default: + break; + } + + instance->SendToPlayers(&data); +} diff --git a/src/game/WorldHandlers/InstanceData.h b/src/game/WorldHandlers/InstanceData.h index fabe36f5b..fed875746 100644 --- a/src/game/WorldHandlers/InstanceData.h +++ b/src/game/WorldHandlers/InstanceData.h @@ -27,6 +27,7 @@ #include "Common.h" #include "ObjectGuid.h" +#include "WorldPacket.h" class Map; class Unit; @@ -55,7 +56,22 @@ enum InstanceConditionIDs // Suggested values INSTANCE_CONDITION_ID_ULDUAR = 33113, }; -class InstanceData +enum EncounterFrameTypes // only raid UI specific +{ + ENCOUNTER_FRAME_SET_COMBAT_RES_LIMIT = 0, + ENCOUNTER_FRAME_RESET_COMBAT_RES_LIMIT = 1, + ENCOUNTER_FRAME_ENGAGE = 2, + ENCOUNTER_FRAME_DISENGAGE = 3, + ENCOUNTER_FRAME_UPDATE_PRIORITY = 4, + ENCOUNTER_FRAME_ADD_TIMER = 5, + ENCOUNTER_FRAME_ENABLE_OBJECTIVE = 6, + ENCOUNTER_FRAME_UPDATE_OBJECTIVE = 7, + ENCOUNTER_FRAME_DISABLE_OBJECTIVE = 8, + ENCOUNTER_FRAME_UNK7 = 9, // Seems to have something to do with sorting the encounter units + ENCOUNTER_FRAME_ADD_COMBAT_RES_LIMIT = 10 +}; + +class MANGOS_DLL_SPEC InstanceData { public: @@ -128,6 +144,9 @@ class InstanceData // This is used for such things are heroic loot // See ObjectMgr.h enum ConditionSource for possible values of conditionSourceType virtual bool CheckConditionCriteriaMeet(Player const* source, uint32 instance_condition_id, WorldObject const* conditionSource, uint32 conditionSourceType) const; + + // Special UI unit frame - sent mostly for raid bosses + void SendEncounterFrame(uint32 type, ObjectGuid sourceGuid = ObjectGuid(), uint8 param1 = 0, uint8 param2 = 0); }; #endif diff --git a/src/game/WorldHandlers/LFGHandler.cpp b/src/game/WorldHandlers/LFGHandler.cpp index cf29082c3..a4c87ce13 100644 --- a/src/game/WorldHandlers/LFGHandler.cpp +++ b/src/game/WorldHandlers/LFGHandler.cpp @@ -223,35 +223,6 @@ void WorldSession::SendLfgSearchResults(LfgType type, uint32 entry) SendPacket(&data); } -/* - * pre dev21 version - * delete this if the one below it proves to be good (chucky) -void WorldSession::SendLfgJoinResult(LfgJoinResult result) -{ - WorldPacket data(SMSG_LFG_JOIN_RESULT, 0); - data << uint32(result); - data << uint32(0); // ERR_LFG_ROLE_CHECK_FAILED_TIMEOUT = 3, ERR_LFG_ROLE_CHECK_FAILED_NOT_VIABLE = (value - 3 == result) - - if (result == ERR_LFG_NO_SLOTS_PARTY) - { - uint8 count1 = 0; - data << uint8(count1); // players count? - for (uint32 i = 0; i < count1; ++i) - { - data << uint64(0); // player guid? - uint32 count2 = 0; - for (uint32 j = 0; j < count2; ++j) - { - data << uint32(0); // dungeon id/type - data << uint32(0); // lock status? - } - } - } - - SendPacket(&data); -} -*/ - void WorldSession::SendLfgJoinResult(LfgJoinResult result, LFGState state, partyForbidden const& lockedDungeons) { uint32 packetSize = 0; diff --git a/src/game/WorldHandlers/Map.cpp b/src/game/WorldHandlers/Map.cpp index 343201056..246a87819 100644 --- a/src/game/WorldHandlers/Map.cpp +++ b/src/game/WorldHandlers/Map.cpp @@ -747,7 +747,7 @@ void Map::CreatureRelocation(Creature* creature, float x, float y, float z, floa MANGOS_ASSERT(CheckGridIntegrity(creature, true)); } -bool Map::CreatureCellRelocation(Creature* c, Cell new_cell) +bool Map::CreatureCellRelocation(Creature* c, const Cell& new_cell) { Cell const& old_cell = c->GetCurrentCell(); if (old_cell.DiffGrid(new_cell)) @@ -1311,6 +1311,32 @@ void Map::CreateInstanceData(bool load) } } */ +void Map::TeleportAllPlayersTo(TeleportLocation loc) +{ + while (HavePlayers()) + { + if (Player* plr = m_mapRefManager.getFirst()->getSource()) + { + // Teleport to specified location and removes the player from this map (if the map exists). + // Todo : we can add some specific location if needed (ex: map exit location for dungeon) + switch (loc) + { + case TELEPORT_LOCATION_HOMEBIND: + plr->TeleportToHomebind(); + break; + case TELEPORT_LOCATION_BG_ENTRY_POINT: + plr->TeleportToBGEntryPoint(); + break; + default: + break; + } + // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop + // note that this remove is not needed if the code works well in other places + plr->GetMapRef().unlink(); + } + } +} + void Map::SetWeather(uint32 zoneId, WeatherType type, float grade, bool permanently) { Weather* wth = m_weatherSystem->FindOrCreateWeather(zoneId); @@ -1565,15 +1591,7 @@ void DungeonMap::PermBindAllPlayers(Player* player) void DungeonMap::UnloadAll(bool pForce) { - if (HavePlayers()) - { - sLog.outError("DungeonMap::UnloadAll: there are still players in the instance at unload, should not happen!"); - for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr) - { - Player* plr = itr->getSource(); - plr->TeleportToHomebind(); - } - } + TeleportAllPlayersTo(TELEPORT_LOCATION_HOMEBIND); if (m_resetAfterUnload == true) GetPersistanceState()->DeleteRespawnTimes(); @@ -1669,17 +1687,10 @@ void BattleGroundMap::SetUnload() void BattleGroundMap::UnloadAll(bool pForce) { - while (HavePlayers()) - { - if (Player* plr = m_mapRefManager.getFirst()->getSource()) - { - plr->TeleportTo(plr->GetBattleGroundEntryPoint()); - // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator. - // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop - // note that this remove is not needed if the code works well in other places - plr->GetMapRef().unlink(); - } - } + TeleportAllPlayersTo(TELEPORT_LOCATION_BG_ENTRY_POINT); + + Map::UnloadAll(pForce); + TeleportAllPlayersTo(TELEPORT_LOCATION_BG_ENTRY_POINT); Map::UnloadAll(pForce); } diff --git a/src/game/WorldHandlers/Map.h b/src/game/WorldHandlers/Map.h index d2b4efb65..dc4ed4ee6 100644 --- a/src/game/WorldHandlers/Map.h +++ b/src/game/WorldHandlers/Map.h @@ -323,7 +323,7 @@ class Map : public GridRefManager void SendInitTransports(Player* player); void SendRemoveTransports(Player* player); - bool CreatureCellRelocation(Creature* creature, Cell new_cell); + bool CreatureCellRelocation(Creature* c, const Cell& new_cell); bool loaded(const GridPair&) const; void EnsureGridCreated(const GridPair&); diff --git a/src/game/WorldHandlers/MapPersistentStateMgr.cpp b/src/game/WorldHandlers/MapPersistentStateMgr.cpp index 609aa7b16..2996d99d6 100644 --- a/src/game/WorldHandlers/MapPersistentStateMgr.cpp +++ b/src/game/WorldHandlers/MapPersistentStateMgr.cpp @@ -44,7 +44,10 @@ INSTANTIATE_SINGLETON_1(MapPersistentStateManager); -static uint32 resetEventTypeDelay[MAX_RESET_EVENT_TYPE] = { 0, 3600, 900, 300, 60 }; +static uint32 resetEventTypeDelay[MAX_RESET_EVENT_TYPE] = { 0, // not used + 3600, 900, 300, 60, // (seconds) normal and official timer delay to inform player about instance reset + 60, 30, 10, 5 // (seconds) fast reset by gm command inform timer + }; //== MapPersistentState functions ========================== MapPersistentState::MapPersistentState(uint16 MapId, uint32 InstanceId, Difficulty difficulty) @@ -220,6 +223,11 @@ DungeonPersistentState::DungeonPersistentState(uint16 MapId, uint32 InstanceId, DungeonPersistentState::~DungeonPersistentState() { DEBUG_LOG("Unloading DungeonPersistantState of map %u instance %u", GetMapId(), GetInstanceId()); + UnbindThisState(); +} + +void DungeonPersistentState::UnbindThisState() +{ while (!m_playerList.empty()) { Player* player = *(m_playerList.begin()); @@ -537,7 +545,7 @@ void DungeonResetScheduler::ScheduleReset(bool add, time_t time, DungeonResetEve void DungeonResetScheduler::Update() { - time_t now = time(NULL), t; + time_t now = time(nullptr), t; while (!m_resetTimeQueue.empty() && (t = m_resetTimeQueue.begin()->first) < now) { DungeonResetEvent& event = m_resetTimeQueue.begin()->second; @@ -550,8 +558,10 @@ void DungeonResetScheduler::Update() { // global reset/warning for a certain map time_t resetTime = GetResetTimeFor(event.mapid, event.difficulty); - m_InstanceSaves._ResetOrWarnAll(event.mapid, event.difficulty, event.type != RESET_EVENT_INFORM_LAST, uint32(resetTime - now)); - if (event.type != RESET_EVENT_INFORM_LAST) + uint32 timeLeft = uint32(std::max(int32(resetTime - now), 0)); + bool warn = event.type != RESET_EVENT_INFORM_LAST && event.type != RESET_EVENT_FORCED_INFORM_LAST; + m_InstanceSaves._ResetOrWarnAll(event.mapid, event.difficulty, warn, timeLeft); + if (event.type != RESET_EVENT_INFORM_LAST && event.type != RESET_EVENT_FORCED_INFORM_LAST) { // schedule the next warning/reset event.type = ResetEventType(event.type + 1); @@ -584,6 +594,32 @@ void DungeonResetScheduler::Update() } } +void DungeonResetScheduler::ResetAllRaid() +{ + time_t now = time(nullptr); + ResetTimeQueue rTQ; + rTQ.clear(); + + time_t timeleft = resetEventTypeDelay[RESET_EVENT_FORCED_INFORM_1]; + + for (ResetTimeQueue::iterator itr = m_resetTimeQueue.begin(); itr != m_resetTimeQueue.end(); ++itr) + { + DungeonResetEvent& event = itr->second; + + // we only reset raid dungeon + if (event.type == RESET_EVENT_NORMAL_DUNGEON) + { + rTQ.insert(std::pair(itr->first, event)); + continue; + } + event.type = RESET_EVENT_FORCED_INFORM_1; + time_t next_reset = now + timeleft; + SetResetTimeFor(event.mapid, event.difficulty, next_reset); + rTQ.insert(std::pair(now, event)); + } + m_resetTimeQueue = rTQ; +} + //== MapPersistentStateManager functions ========================= MapPersistentStateManager::MapPersistentStateManager() : lock_instLists(false), m_Scheduler(*this) @@ -855,14 +891,37 @@ void MapPersistentStateManager::_ResetInstance(uint32 mapid, uint32 instanceId) DeleteInstanceFromDB(instanceId); // even if state not loaded } +struct MapPersistantStateResetWorker +{ + MapPersistantStateResetWorker() {}; + void operator()(Map* map) + { + ((DungeonMap*)map)->TeleportAllPlayersTo(TELEPORT_LOCATION_HOMEBIND); + ((DungeonMap*)map)->Reset(INSTANCE_RESET_GLOBAL); + } +}; + +struct MapPersistantStateWarnWorker +{ + MapPersistantStateWarnWorker(time_t _timeLeft) : timeLeft(_timeLeft) + {}; + + void operator()(Map* map) + { + ((DungeonMap*)map)->SendResetWarnings(timeLeft); + } + + time_t timeLeft; +}; + void MapPersistentStateManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficulty, bool warn, uint32 timeLeft) { // global reset for all instances of the given map MapEntry const* mapEntry = sMapStore.LookupEntry(mapid); - if (!mapEntry->Instanceable()) + if (!mapEntry->IsDungeon()) return; - time_t now = time(NULL); + time_t now = time(nullptr); if (!warn) { @@ -873,14 +932,21 @@ void MapPersistentStateManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficu return; } - // remove all binds to instances of the given map - for (PersistentStateMap::iterator itr = m_instanceSaveByInstanceId.begin(); itr != m_instanceSaveByInstanceId.end();) - { + // remove all binds for online player + std::list unbindList; + + // note that we must build a list of states to unbind and then unbind them in two steps. this is because the unbinding may + // trigger the modification of the collection, which would invalidate the iterator and cause a crash. + for (PersistentStateMap::iterator itr = m_instanceSaveByInstanceId.begin(); itr != m_instanceSaveByInstanceId.end(); ++itr) if (itr->second->GetMapId() == mapid && itr->second->GetDifficulty() == difficulty) - _ResetSave(m_instanceSaveByInstanceId, itr); - else - ++itr; - } + unbindList.push_back((DungeonPersistentState *)itr->second); + + for (auto i : unbindList) + i->UnbindThisState(); + + // reset maps, teleport player automaticaly to their homebinds and unload maps + MapPersistantStateResetWorker worker; + sMapMgr.DoForAllMapsWithMapId(mapid, worker); // delete them from the DB, even if not loaded CharacterDatabase.BeginTransaction(); @@ -893,23 +959,12 @@ void MapPersistentStateManager::_ResetOrWarnAll(uint32 mapid, Difficulty difficu time_t next_reset = DungeonResetScheduler::CalculateNextResetTime(mapDiff, now + timeLeft); // update it in the DB CharacterDatabase.PExecute("UPDATE instance_reset SET resettime = '" UI64FMTD "' WHERE mapid = '%u' AND difficulty = '%u'", (uint64)next_reset, mapid, difficulty); + return; } // note: this isn't fast but it's meant to be executed very rarely - const MapManager::MapMapType& maps = sMapMgr.Maps(); - - MapManager::MapMapType::const_iterator iter_last = maps.lower_bound(MapID(mapid + 1)); - for (MapManager::MapMapType::const_iterator mitr = maps.lower_bound(MapID(mapid)); mitr != iter_last; ++mitr) - { - Map* map2 = mitr->second; - if (map2->GetId() != mapid) - break; - - if (warn) - ((DungeonMap*)map2)->SendResetWarnings(timeLeft); - else - ((DungeonMap*)map2)->Reset(INSTANCE_RESET_GLOBAL); - } + MapPersistantStateWarnWorker worker(timeLeft); + sMapMgr.DoForAllMapsWithMapId(mapid, worker); } void MapPersistentStateManager::GetStatistics(uint32& numStates, uint32& numBoundPlayers, uint32& numBoundGroups) diff --git a/src/game/WorldHandlers/MapPersistentStateMgr.h b/src/game/WorldHandlers/MapPersistentStateMgr.h index 851c6ae52..d44838817 100644 --- a/src/game/WorldHandlers/MapPersistentStateMgr.h +++ b/src/game/WorldHandlers/MapPersistentStateMgr.h @@ -229,6 +229,8 @@ class DungeonPersistentState : public MapPersistentState void DeleteFromDB(); /* Delete respawn data at dungeon reset */ void DeleteRespawnTimes(); + /* Remove players bind to this state */ + void UnbindThisState(); protected: bool CanBeUnload() const override; // overwrite MapPersistentState::CanBeUnload @@ -273,14 +275,18 @@ class BattleGroundPersistentState : public MapPersistentState enum ResetEventType { - RESET_EVENT_NORMAL_DUNGEON = 0, // no fixed reset time - RESET_EVENT_INFORM_1 = 1, // raid/heroic warnings - RESET_EVENT_INFORM_2 = 2, - RESET_EVENT_INFORM_3 = 3, - RESET_EVENT_INFORM_LAST = 4, + RESET_EVENT_NORMAL_DUNGEON = 0, // no fixed reset time + RESET_EVENT_INFORM_1 = 1, // raid/heroic warnings + RESET_EVENT_INFORM_2 = 2, + RESET_EVENT_INFORM_3 = 3, + RESET_EVENT_INFORM_LAST = 4, + RESET_EVENT_FORCED_INFORM_1 = 5, + RESET_EVENT_FORCED_INFORM_2 = 6, + RESET_EVENT_FORCED_INFORM_3 = 7, + RESET_EVENT_FORCED_INFORM_LAST = 8, }; -#define MAX_RESET_EVENT_TYPE 5 +#define MAX_RESET_EVENT_TYPE 9 /* resetTime is a global propery of each (raid/heroic) map all instances of that map reset at the same time */ @@ -323,6 +329,7 @@ class DungeonResetScheduler void Update(); + void ResetAllRaid(); private: // fields MapPersistentStateManager& m_InstanceSaves; diff --git a/src/game/WorldHandlers/MassMailMgr.cpp b/src/game/WorldHandlers/MassMailMgr.cpp index f06e55c06..dc5eb24b4 100644 --- a/src/game/WorldHandlers/MassMailMgr.cpp +++ b/src/game/WorldHandlers/MassMailMgr.cpp @@ -41,7 +41,8 @@ INSTANTIATE_SINGLETON_1(MassMailMgr); -void MassMailMgr::AddMassMailTask(MailDraft* mailProto, MailSender sender, uint32 raceMask) + +void MassMailMgr::AddMassMailTask(MailDraft* mailProto, const MailSender& sender, uint32 raceMask) { if (RACEMASK_ALL_PLAYABLE & ~raceMask) // have races not included in mask { @@ -72,9 +73,9 @@ struct MassMailerQueryHandler } } massMailerQueryHandler; -void MassMailMgr::AddMassMailTask(MailDraft* mailProto, MailSender sender, char const* query) +void MassMailMgr::AddMassMailTask(MailDraft* mailProto, const MailSender& sender, char const* query) { - CharacterDatabase.AsyncPQuery(&massMailerQueryHandler, &MassMailerQueryHandler::HandleQueryCallback, mailProto, sender, query); + CharacterDatabase.AsyncPQuery(&massMailerQueryHandler, &MassMailerQueryHandler::HandleQueryCallback, mailProto, sender, "%s", query); } void MassMailMgr::Update(bool sendall /*= false*/) diff --git a/src/game/WorldHandlers/MassMailMgr.h b/src/game/WorldHandlers/MassMailMgr.h index 05a9a64dc..8043d58fa 100644 --- a/src/game/WorldHandlers/MassMailMgr.h +++ b/src/game/WorldHandlers/MassMailMgr.h @@ -70,7 +70,7 @@ class MassMailMgr * * Note: this function safe to be called from Map::Update content/etc, real data add will executed in next tick after query results ready */ - void AddMassMailTask(MailDraft* mailProto, MailSender sender, uint32 raceMask); + void AddMassMailTask(MailDraft* mailProto, const MailSender& sender, uint32 raceMask); /** * And new mass mail task with SQL query text for fill receivers list. @@ -80,7 +80,7 @@ class MassMailMgr * * Note: this function safe to be called from Map::Update content/etc, real data add will executed in next tick after query results ready */ - void AddMassMailTask(MailDraft* mailProto, MailSender sender, char const* queryStr); + void AddMassMailTask(MailDraft* mailProto, const MailSender& sender, char const* queryStr); /** * And new mass mail task and let fill receivers list returned as result. @@ -90,7 +90,7 @@ class MassMailMgr * * Note: this function NOT SAFE for call from Map::Update content/etc */ - ReceiversList& AddMassMailTask(MailDraft* mailProto, MailSender sender) + ReceiversList& AddMassMailTask(MailDraft* mailProto, const MailSender& sender) { m_massMails.push_back(MassMail(mailProto, sender)); return m_massMails.rbegin()->m_receivers; diff --git a/src/game/WorldHandlers/MiscHandler.cpp b/src/game/WorldHandlers/MiscHandler.cpp index f3782a614..4a658dd71 100644 --- a/src/game/WorldHandlers/MiscHandler.cpp +++ b/src/game/WorldHandlers/MiscHandler.cpp @@ -59,6 +59,9 @@ void WorldSession::HandleRepopRequestOpcode(WorldPacket& recv_data) if (GetPlayer()->IsAlive() || GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) return; + if (GetPlayer()->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) + return; + // the world update order is sessions, players, creatures // the netcode runs in parallel with all of these // creatures can kill players diff --git a/src/game/WorldHandlers/PhaseMgr.cpp b/src/game/WorldHandlers/PhaseMgr.cpp deleted file mode 100644 index e4c96f075..000000000 --- a/src/game/WorldHandlers/PhaseMgr.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - * This file is part of the MaNGOS Project. See AUTHORS file for Copyright information - * Copyright (C) 2008-2012 TrinityCore - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * World of Warcraft, and all World of Warcraft or Warcraft art, images, - * and lore are copyrighted by Blizzard Entertainment, Inc. - */ - -#include "PhaseMgr.h" -#include "Chat.h" -#include "Language.h" -#include "ObjectMgr.h" -#include "Player.h" -#include "SpellAuras.h" - -////////////////////////////////////////////////////////////////// -// Updating - -PhaseMgr::PhaseMgr(Player* _player) : player(_player), _UpdateFlags(0) -{ - phaseData = new PhaseData(_player); - _PhaseDefinitionStore = sObjectMgr.GetPhaseDefinitionStore(); - _SpellPhaseStore = sObjectMgr.GetSpellPhaseStore(); -} - -void PhaseMgr::Update() -{ - if (IsUpdateInProgress()) - return; - - if (_UpdateFlags & PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED) - phaseData->SendPhaseshiftToPlayer(); - - if (_UpdateFlags & PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED) - phaseData->SendPhaseMaskToPlayer(); - - _UpdateFlags = 0; -} - -void PhaseMgr::RemoveUpdateFlag(PhaseUpdateFlag updateFlag) -{ - _UpdateFlags &= ~updateFlag; - - if (updateFlag == PHASE_UPDATE_FLAG_ZONE_UPDATE) - { - // Update zone changes - if (phaseData->HasActiveDefinitions()) - { - phaseData->ResetDefinitions(); - _UpdateFlags |= (PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED | PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED); - } - - if (_PhaseDefinitionStore->find(player->GetZoneId()) != _PhaseDefinitionStore->end()) - Recalculate(); - } - - Update(); -} - -///////////////////////////////////////////////////////////////// -// Notifier - -void PhaseMgr::NotifyConditionChanged(PhaseUpdateData const& updateData) -{ - if (NeedsPhaseUpdateWithData(updateData)) - { - Recalculate(); - Update(); - } -} - -////////////////////////////////////////////////////////////////// -// Phasing Definitions - -void PhaseMgr::Recalculate() -{ - if (phaseData->HasActiveDefinitions()) - { - phaseData->ResetDefinitions(); - _UpdateFlags |= (PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED | PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED); - } - - PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId()); - if (itr != _PhaseDefinitionStore->end()) - for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase) - if (CheckDefinition(*phase)) - { - phaseData->AddPhaseDefinition(*phase); - - if ((*phase)->phasemask) - _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED; - - if ((*phase)->phaseId || (*phase)->terrainswapmap) - _UpdateFlags |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED; - - if ((*phase)->IsLastDefinition()) - break; - } -} - -inline bool PhaseMgr::CheckDefinition(PhaseDefinition const* phaseDefinition) -{ - return !phaseDefinition->conditionId || sObjectMgr.IsPlayerMeetToCondition(phaseDefinition->conditionId, player, player->GetMap(), player, CONDITION_FROM_PHASEMGR); -} - -bool PhaseMgr::NeedsPhaseUpdateWithData(PhaseUpdateData const updateData) -{ - PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId()); - if (itr != _PhaseDefinitionStore->end()) - { - for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase) - { - std::vector conditions; - sObjectMgr.GetConditions((*phase)->conditionId, conditions); - - for (std::vector::const_iterator itr = conditions.begin(); itr != conditions.end(); ++itr) - if (updateData.IsConditionRelated(*itr)) - return true; - } - } - return false; -} - -////////////////////////////////////////////////////////////////// -// Auras - -void PhaseMgr::RegisterPhasingAuraEffect(Aura const* auraEffect) -{ - PhaseInfo* phaseInfo = new PhaseInfo(); - - if (auraEffect->GetMiscValue()) - { - _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED; - phaseInfo->phasemask = auraEffect->GetMiscValue(); - } - else - { - SpellPhaseStore::const_iterator itr = _SpellPhaseStore->find(auraEffect->GetHolder()->GetId()); - if (itr != _SpellPhaseStore->end()) - { - if (itr->second->phasemask) - { - _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED; - phaseInfo->phasemask = itr->second->phasemask; - } - - if (itr->second->terrainswapmap) - phaseInfo->terrainswapmap = itr->second->terrainswapmap; - } - } - - // this is not Phase.dbc id... - // phaseInfo->phaseId = auraEffect->GetMiscBValue(); - - if (phaseInfo->NeedsClientSideUpdate()) - _UpdateFlags |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED; - - phaseData->AddAuraInfo(auraEffect->GetHolder()->GetId(), phaseInfo); - - Update(); -} - -void PhaseMgr::UnRegisterPhasingAuraEffect(Aura const* auraEffect) -{ - _UpdateFlags |= phaseData->RemoveAuraInfo(auraEffect->GetHolder()->GetId()); - - Update(); -} - -////////////////////////////////////////////////////////////////// -// Commands - -void PhaseMgr::SendDebugReportToPlayer(Player* const debugger) -{ - ChatHandler(debugger).PSendSysMessage(LANG_PHASING_REPORT_STATUS, player->GetName(), player->GetZoneId(), player->getLevel(), player->GetTeam(), _UpdateFlags); - - PhaseDefinitionStore::const_iterator itr = _PhaseDefinitionStore->find(player->GetZoneId()); - if (itr == _PhaseDefinitionStore->end()) - ChatHandler(debugger).PSendSysMessage(LANG_PHASING_NO_DEFINITIONS, player->GetZoneId()); - else - { - for (PhaseDefinitionContainer::const_iterator phase = itr->second.begin(); phase != itr->second.end(); ++phase) - { - if (CheckDefinition(*phase)) - ChatHandler(debugger->GetSession()).PSendSysMessage(LANG_PHASING_SUCCESS, (*phase)->entry, (*phase)->IsNegatingPhasemask() ? "negated Phase" : "Phase", (*phase)->phasemask); - else - ChatHandler(debugger).PSendSysMessage(LANG_PHASING_FAILED, (*phase)->phasemask, (*phase)->entry, (*phase)->zoneId); - - if ((*phase)->IsLastDefinition()) - { - ChatHandler(debugger).PSendSysMessage(LANG_PHASING_LAST_PHASE, (*phase)->phasemask, (*phase)->entry, (*phase)->zoneId); - break; - } - } - } - - ChatHandler(debugger).PSendSysMessage(LANG_PHASING_LIST, phaseData->_PhasemaskThroughDefinitions, phaseData->_PhasemaskThroughAuras, phaseData->_CustomPhasemask); - - ChatHandler(debugger).PSendSysMessage(LANG_PHASING_PHASEMASK, phaseData->GetPhaseMaskForSpawn(), player->GetPhaseMask()); -} - -void PhaseMgr::SetCustomPhase(uint32 const phaseMask) -{ - phaseData->_CustomPhasemask = phaseMask; - - // phase auras normally not expected at BG but anyway better check - if (BattleGround* bg = player->GetBattleGround()) - bg->EventPlayerDroppedFlag(player); - - _UpdateFlags |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED; - - Update(); -} - -////////////////////////////////////////////////////////////////// -// Phase Data - -uint32 PhaseData::GetCurrentPhasemask() const -{ - if (player->isGameMaster()) - return uint32(PHASEMASK_ANYWHERE); - - if (_CustomPhasemask) - return _CustomPhasemask; - - return GetPhaseMaskForSpawn(); -} - -inline uint32 PhaseData::GetPhaseMaskForSpawn() const -{ - uint32 const phase = (_PhasemaskThroughDefinitions | _PhasemaskThroughAuras); - return (phase ? phase : PHASEMASK_NORMAL); -} - -void PhaseData::SendPhaseMaskToPlayer() -{ - // Server side update - uint32 const phasemask = GetCurrentPhasemask(); - if (player->GetPhaseMask() == phasemask) - return; - - player->SetPhaseMask(phasemask, false); - - if (player->IsInWorld()) - player->UpdateVisibilityAndView(); -} - -void PhaseData::SendPhaseshiftToPlayer() -{ - // Client side update - std::set phaseIds; - std::set terrainswaps; - - for (PhaseInfoContainer::const_iterator itr = spellPhaseInfo.begin(); itr != spellPhaseInfo.end(); ++itr) - { - if (itr->second->terrainswapmap) - terrainswaps.insert(itr->second->terrainswapmap); - - if (itr->second->phaseId) - phaseIds.insert(itr->second->phaseId); - } - - // Phase Definitions - for (std::list::const_iterator itr = activePhaseDefinitions.begin(); itr != activePhaseDefinitions.end(); ++itr) - { - if ((*itr)->phaseId) - phaseIds.insert((*itr)->phaseId); - - if ((*itr)->terrainswapmap) - terrainswaps.insert((*itr)->terrainswapmap); - } - - player->GetSession()->SendSetPhaseShift(phaseIds, terrainswaps); -} - -void PhaseData::AddPhaseDefinition(PhaseDefinition const* phaseDefinition) -{ - if (phaseDefinition->IsOverwritingExistingPhases()) - { - activePhaseDefinitions.clear(); - _PhasemaskThroughDefinitions = phaseDefinition->phasemask; - } - else - { - if (phaseDefinition->IsNegatingPhasemask()) - _PhasemaskThroughDefinitions &= ~phaseDefinition->phasemask; - else - _PhasemaskThroughDefinitions |= phaseDefinition->phasemask; - } - - activePhaseDefinitions.push_back(phaseDefinition); -} - -void PhaseData::AddAuraInfo(uint32 const spellId, PhaseInfo* phaseInfo) -{ - if (phaseInfo->phasemask) - _PhasemaskThroughAuras |= phaseInfo->phasemask; - - spellPhaseInfo[spellId] = phaseInfo; -} - -uint32 PhaseData::RemoveAuraInfo(uint32 const spellId) -{ - PhaseInfoContainer::iterator rAura = spellPhaseInfo.find(spellId); - if (rAura != spellPhaseInfo.end()) - { - uint32 updateflag = 0; - - if (rAura->second->NeedsClientSideUpdate()) - updateflag |= PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED; - - if (rAura->second->NeedsServerSideUpdate()) - { - _PhasemaskThroughAuras = 0; - - updateflag |= PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED; - - spellPhaseInfo.erase(rAura); - - for (PhaseInfoContainer::const_iterator itr = spellPhaseInfo.begin(); itr != spellPhaseInfo.end(); ++itr) - _PhasemaskThroughAuras |= itr->second->phasemask; - } - - return updateflag; - } - else - return 0; -} - -////////////////////////////////////////////////////////////////// -// Phase Update Data - -void PhaseUpdateData::AddQuestUpdate(uint32 const questId) -{ - AddConditionType(CONDITION_QUESTREWARDED); - AddConditionType(CONDITION_QUESTTAKEN); - AddConditionType(CONDITION_QUEST_NONE); - - _questId = questId; -} - -bool PhaseUpdateData::IsConditionRelated(PlayerCondition const* condition) const -{ - switch (condition->m_condition) - { - case CONDITION_QUESTREWARDED: - case CONDITION_QUESTTAKEN: - case CONDITION_QUEST_NONE: - return condition->m_value1 == _questId && ((1 << condition->m_condition) & _conditionTypeFlags); - default: - return (1 << condition->m_condition) & _conditionTypeFlags; - } -} - -bool PhaseMgr::IsConditionTypeSupported(ConditionType const conditionType) -{ - switch (conditionType) - { - case CONDITION_QUESTREWARDED: - case CONDITION_QUESTTAKEN: - case CONDITION_QUEST_NONE: - case CONDITION_TEAM: - case CONDITION_RACE_CLASS: - case CONDITION_LEVEL: - return true; - default: - return false; - } -} \ No newline at end of file diff --git a/src/game/WorldHandlers/PhaseMgr.h b/src/game/WorldHandlers/PhaseMgr.h deleted file mode 100644 index 41409e711..000000000 --- a/src/game/WorldHandlers/PhaseMgr.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * This file is part of the MaNGOS Project. See AUTHORS file for Copyright information - * Copyright (C) 2008-2012 TrinityCore - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * World of Warcraft, and all World of Warcraft or Warcraft art, images, - * and lore are copyrighted by Blizzard Entertainment, Inc. - */ - -#ifndef MANGOS_PHASEMGR_H -#define MANGOS_PHASEMGR_H - -#include "SharedDefines.h" -#include "ObjectMgr.h" - -class ObjectMgr; -class Player; -class Aura; -class PlayerCondition; - -// Phasing (visibility) -enum PhasingFlags -{ - PHASE_FLAG_OVERWRITE_EXISTING = 0x01, // don't stack with existing phases, overwrites existing phases - PHASE_FLAG_NO_MORE_PHASES = 0x02, // stop calculating phases after this phase was applied (no more phases will be applied) - PHASE_FLAG_NEGATE_PHASE = 0x04 // negate instead to add the phasemask -}; - -enum PhaseUpdateFlag -{ - PHASE_UPDATE_FLAG_ZONE_UPDATE = 0x01, - PHASE_UPDATE_FLAG_AREA_UPDATE = 0x02, - - // Internal flags - PHASE_UPDATE_FLAG_CLIENTSIDE_CHANGED = 0x08, - PHASE_UPDATE_FLAG_SERVERSIDE_CHANGED = 0x10, -}; - -struct PhaseDefinition -{ - uint32 zoneId; - uint32 entry; - uint32 phasemask; - uint32 phaseId; - uint32 terrainswapmap; - uint8 flags; - uint16 conditionId; - - bool IsOverwritingExistingPhases() const { return flags & PHASE_FLAG_OVERWRITE_EXISTING; } - bool IsLastDefinition() const { return flags & PHASE_FLAG_NO_MORE_PHASES; } - bool IsNegatingPhasemask() const { return flags & PHASE_FLAG_NEGATE_PHASE; } -}; - -struct SpellPhaseInfo -{ - uint32 spellId; - uint32 phasemask; - uint32 terrainswapmap; -}; - -struct PhaseInfo -{ - PhaseInfo() : phasemask(0), terrainswapmap(0), phaseId(0) {} - - uint32 phasemask; - uint32 terrainswapmap; - uint32 phaseId; - - bool NeedsServerSideUpdate() const { return phasemask; } - bool NeedsClientSideUpdate() const { return terrainswapmap || phaseId; } -}; - -typedef UNORDERED_MAP PhaseInfoContainer; - -struct PhaseData -{ - PhaseData(Player* _player) : _PhasemaskThroughDefinitions(0), _PhasemaskThroughAuras(0), _CustomPhasemask(0), player(_player) {} - - uint32 _PhasemaskThroughDefinitions; - uint32 _PhasemaskThroughAuras; - uint32 _CustomPhasemask; - - uint32 GetCurrentPhasemask() const; - inline uint32 GetPhaseMaskForSpawn() const; - - void ResetDefinitions() { _PhasemaskThroughDefinitions = 0; activePhaseDefinitions.clear(); } - void AddPhaseDefinition(PhaseDefinition const* phaseDefinition); - bool HasActiveDefinitions() const { return !activePhaseDefinitions.empty(); } - - void AddAuraInfo(uint32 const spellId, PhaseInfo* phaseInfo); - uint32 RemoveAuraInfo(uint32 const spellId); - - void SendPhaseMaskToPlayer(); - void SendPhaseshiftToPlayer(); - - private: - Player* player; - std::list activePhaseDefinitions; - PhaseInfoContainer spellPhaseInfo; -}; - -struct PhaseUpdateData -{ - void AddConditionType(ConditionType const conditionType) { _conditionTypeFlags |= (1 << conditionType); } - void AddQuestUpdate(uint32 const questId); - - bool IsConditionRelated(PlayerCondition const* condition) const; - - private: - uint32 _conditionTypeFlags; - uint32 _questId; -}; - -class PhaseMgr -{ - public: - PhaseMgr(Player* _player); - ~PhaseMgr() { delete phaseData; } - - uint32 GetCurrentPhasemask() { return phaseData->GetCurrentPhasemask(); }; - inline uint32 GetPhaseMaskForSpawn() { return phaseData->GetCurrentPhasemask(); } - - // Phase definitions update handling - void NotifyConditionChanged(PhaseUpdateData const& updateData); - void NotifyStoresReloaded() { Recalculate(); Update(); } - - void Update(); - - // Aura phase effects - void RegisterPhasingAuraEffect(Aura const* auraEffect); - void UnRegisterPhasingAuraEffect(Aura const* auraEffect); - - // Update flags (delayed phasing) - void AddUpdateFlag(PhaseUpdateFlag const updateFlag) { _UpdateFlags |= updateFlag; } - void RemoveUpdateFlag(PhaseUpdateFlag const updateFlag); - - // Needed for modify phase command - void SetCustomPhase(uint32 const phaseMask); - - // Debug - void SendDebugReportToPlayer(Player* const debugger); - - static bool IsConditionTypeSupported(ConditionType const conditionType); - - private: - void Recalculate(); - - inline bool CheckDefinition(PhaseDefinition const* phaseDefinition); - - bool NeedsPhaseUpdateWithData(PhaseUpdateData const updateData); - - inline bool IsUpdateInProgress() const { return (_UpdateFlags & PHASE_UPDATE_FLAG_ZONE_UPDATE) || (_UpdateFlags & PHASE_UPDATE_FLAG_AREA_UPDATE); } - - PhaseDefinitionStore const* _PhaseDefinitionStore; - SpellPhaseStore const* _SpellPhaseStore; - - Player* player; - PhaseData* phaseData; - uint8 _UpdateFlags; -}; - -#endif diff --git a/src/game/WorldHandlers/QueryHandler.cpp b/src/game/WorldHandlers/QueryHandler.cpp index e9d2777ce..b96ac7241 100644 --- a/src/game/WorldHandlers/QueryHandler.cpp +++ b/src/game/WorldHandlers/QueryHandler.cpp @@ -100,7 +100,7 @@ void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult* result, uint32 uint32 lowguid = fields[0].GetUInt32(); std::string name = fields[1].GetCppString(); uint8 pRace = 0, pGender = 0, pClass = 0; - if (name == "") + if (name.empty()) name = session->GetMangosString(LANG_NON_EXIST_CHARACTER); else { @@ -120,7 +120,7 @@ void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult* result, uint32 data << uint8(pClass); // class // if the first declined name field (5) is empty, the rest must be too - if (sWorld.getConfig(CONFIG_BOOL_DECLINED_NAMES_USED) && fields[5].GetCppString() != "") + if (sWorld.getConfig(CONFIG_BOOL_DECLINED_NAMES_USED) && !fields[5].GetCppString().empty()) { data << uint8(1); // is declined for (int i = 5; i < MAX_DECLINED_NAME_CASES + 5; ++i) diff --git a/src/game/WorldHandlers/QuestHandler.cpp b/src/game/WorldHandlers/QuestHandler.cpp index 2620c1327..c608c9c11 100644 --- a/src/game/WorldHandlers/QuestHandler.cpp +++ b/src/game/WorldHandlers/QuestHandler.cpp @@ -35,7 +35,6 @@ #include "ObjectAccessor.h" #include "ScriptMgr.h" #include "Group.h" -#include "PhaseMgr.h" void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recv_data) { @@ -352,11 +351,6 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data) } _player->SetQuestStatus(quest, QUEST_STATUS_NONE); - - PhaseUpdateData phaseUdateData; - phaseUdateData.AddQuestUpdate(quest); - - _player->GetPhaseMgr()->NotifyConditionChanged(phaseUdateData); } _player->SetQuestSlot(slot, 0); diff --git a/src/game/WorldHandlers/ScriptMgr.cpp b/src/game/WorldHandlers/ScriptMgr.cpp index f4ccc5a0c..8c6047ad7 100644 --- a/src/game/WorldHandlers/ScriptMgr.cpp +++ b/src/game/WorldHandlers/ScriptMgr.cpp @@ -1547,12 +1547,12 @@ bool ScriptAction::HandleScriptStep() } // bitmask: 0/1=target-player, 0/2=with distance dependent, 0/4=map wide, 0/8=zone wide - Player* pSoundTarget = NULL; + Player* pSoundTarget = nullptr; if (m_script->playSound.flags & 1) { pSoundTarget = GetPlayerTargetOrSourceAndLog(pSource, pTarget); if (!pSoundTarget) - { break; } + break; } if (m_script->data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL) @@ -1560,11 +1560,11 @@ bool ScriptAction::HandleScriptStep() else { if (m_script->playSound.flags & 2) - { pSource->PlayDistanceSound(m_script->playSound.soundId, pSoundTarget); } + pSource->PlayDistanceSound(m_script->playSound.soundId, pSoundTarget); else if (m_script->playSound.flags & (4 | 8)) - { m_map->PlayDirectSoundToMap(m_script->playSound.soundId, m_script->playSound.flags & 8 ? pSource->GetZoneId() : 0); } + m_map->PlayDirectSoundToMap(m_script->playSound.soundId, m_script->playSound.flags & 8 ? pSource->GetZoneId() : 0); else - { pSource->PlayDirectSound(m_script->playSound.soundId, pSoundTarget); } + pSource->PlayDirectSound(m_script->playSound.soundId, pSoundTarget); } break; } @@ -2697,3 +2697,8 @@ uint32 GetScriptIdsCount() { return sScriptMgr.GetScriptIdsCount(); } + +bool AddWaypointFromExternal(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime) +{ + return sWaypointMgr.AddExternalNode(entry, pathId, pointId, x, y, z, o, waittime); +} diff --git a/src/game/WorldHandlers/Spell.cpp b/src/game/WorldHandlers/Spell.cpp index ac0428242..f993498bf 100644 --- a/src/game/WorldHandlers/Spell.cpp +++ b/src/game/WorldHandlers/Spell.cpp @@ -128,7 +128,7 @@ SpellCastTargets::SpellCastTargets() m_itemTargetEntry = 0; m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0.0f; - m_strTarget = ""; + m_strTarget.clear(); m_targetMask = 0; m_elevation = 0.0f; @@ -1406,7 +1406,7 @@ void Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask) if (m_applyMultiplierMask & (1 << effectNumber)) { // Get multiplier - float multiplier = spellEffect ? spellEffect->DmgMultiplier : 1.0f; + float multiplier = spellEffect ? spellEffect->EffectDamageMultiplier : 1.0f; // Apply multiplier mods if (realCaster) if (Player* modOwner = realCaster->GetSpellModOwner()) @@ -1529,7 +1529,7 @@ void Spell::HandleDelayedSpellLaunch(TargetInfo* target) if (m_applyMultiplierMask & (1 << effectNumber)) { // Get multiplier - float multiplier = spellEffect ? spellEffect->DmgMultiplier : 1.0f; + float multiplier = spellEffect ? spellEffect->EffectDamageMultiplier : 1.0f; // Apply multiplier mods if (real_caster) if (Player* modOwner = real_caster->GetSpellModOwner()) @@ -1685,7 +1685,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& // Get a random point in circle. Use sqrt(rand) to correct distribution when converting polar to Cartesian coordinates. radius *= sqrtf(rand_norm_f()); - // no 'break' expected since we use code in case TARGET_RANDOM_CIRCUMFERENCE_POINT!!! + // no 'break' expected since we use code in case TARGET_RANDOM_CIRCUMFERENCE_POINT!!! case TARGET_RANDOM_CIRCUMFERENCE_POINT: { // Get a random point AT the circumference @@ -1771,77 +1771,38 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& targetUnitMap.push_back(m_caster); break; case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: - { - m_targets.m_targetMask = 0; - unMaxTargets = EffectChainTarget; - float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; - - UnitList tempTargetUnitMap; - - { - MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, max_range); - MaNGOS::UnitListSearcher searcher(tempTargetUnitMap, u_check); - Cell::VisitAllObjects(m_caster, searcher, max_range); - } - - if (tempTargetUnitMap.empty()) - break; - - tempTargetUnitMap.sort(TargetDistanceOrderNear(m_caster)); - - // Now to get us a random target that's in the initial range of the spell - uint32 t = 0; - UnitList::iterator itr = tempTargetUnitMap.begin(); - while (itr != tempTargetUnitMap.end() && (*itr)->IsWithinDist(m_caster, radius)) - ++t, ++itr; - - if (!t) - break; - - itr = tempTargetUnitMap.begin(); - std::advance(itr, rand() % t); - Unit* pUnitTarget = *itr; - targetUnitMap.push_back(pUnitTarget); - - tempTargetUnitMap.erase(itr); - - tempTargetUnitMap.sort(TargetDistanceOrderNear(pUnitTarget)); - - t = unMaxTargets - 1; - Unit* prev = pUnitTarget; - UnitList::iterator next = tempTargetUnitMap.begin(); - - while (t && next != tempTargetUnitMap.end()) - { - if (!prev->IsWithinDist(*next, CHAIN_SPELL_JUMP_RADIUS)) - break; - - if (!m_spellInfo->HasAttribute(SPELL_ATTR_EX2_IGNORE_LOS) && !prev->IsWithinLOSInMap(*next)) - { - ++next; - continue; - } - - prev = *next; - targetUnitMap.push_back(prev); - tempTargetUnitMap.erase(next); - tempTargetUnitMap.sort(TargetDistanceOrderNear(prev)); - next = tempTargetUnitMap.begin(); - - --t; - } - break; - } case TARGET_RANDOM_FRIEND_CHAIN_IN_AREA: + case TARGET_RANDOM_UNIT_CHAIN_IN_AREA: { m_targets.m_targetMask = 0; unMaxTargets = EffectChainTarget; float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; + UnitList tempTargetUnitMap; + + switch (targetMode) { - MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, max_range); - MaNGOS::UnitListSearcher searcher(tempTargetUnitMap, u_check); - Cell::VisitAllObjects(m_caster, searcher, max_range); + case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: + { + MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, max_range); + MaNGOS::UnitListSearcher searcher(tempTargetUnitMap, u_check); + Cell::VisitAllObjects(m_caster, searcher, max_range); + break; + } + case TARGET_RANDOM_FRIEND_CHAIN_IN_AREA: + { + MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, max_range); + MaNGOS::UnitListSearcher searcher(tempTargetUnitMap, u_check); + Cell::VisitAllObjects(m_caster, searcher, max_range); + break; + } + case TARGET_RANDOM_UNIT_CHAIN_IN_AREA: + { + MaNGOS::AnyUnitInObjectRangeCheck u_check(m_caster, max_range); + MaNGOS::UnitListSearcher searcher(tempTargetUnitMap, u_check); + Cell::VisitAllObjects(m_caster, searcher, max_range); + break; + } } if (tempTargetUnitMap.empty()) @@ -1974,6 +1935,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& switch (m_spellInfo->Id) { // Do not target current victim + case 30769: // Pick Red Riding Hood case 30843: // Enfeeble case 31347: // Doom case 37676: // Insidious Whisper @@ -2010,10 +1972,12 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& case SPELL_EFFECT_KILL_CREDIT_PERSONAL: case SPELL_EFFECT_KILL_CREDIT_GROUP: targetB = SPELL_TARGETS_ALL; + break; default: // Select friendly targets for positive effect if (IsPositiveEffect(m_spellInfo, effIndex)) targetB = SPELL_TARGETS_FRIENDLY; + break; } UnitList tempTargetUnitMap; @@ -2055,9 +2019,6 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& } } } - - // exclude caster - targetUnitMap.remove(m_caster); break; } case TARGET_AREAEFFECT_CUSTOM: @@ -2172,7 +2133,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& tempTargetGOList.erase(itr++); continue; } - // no break here + // no break here case TARGET_AREAEFFECT_GO_AROUND_SOURCE: case TARGET_AREAEFFECT_GO_AROUND_DEST: default: @@ -2302,10 +2263,6 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: switch (m_spellInfo->Id) { - case 56153: // Guardian Aura - Ahn'Kahet - FillAreaTargets(targetUnitMap, radius, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); - targetUnitMap.remove(m_caster); - break; case 64844: // Divine Hymn // target amount stored in parent spell dummy effect but hard to access FillRaidOrPartyHealthPriorityTargets(targetUnitMap, m_caster, m_caster, radius, 3, true, false, true); @@ -2356,7 +2313,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& else FillAreaTargets(targetUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_FRIENDLY); break; - // TARGET_SINGLE_PARTY means that the spells can only be casted on a party member and not on the caster (some seals, fire shield from imp, etc..) + // TARGET_SINGLE_PARTY means that the spells can only be casted on a party member and not on the caster (some seals, fire shield from imp, etc..) case TARGET_SINGLE_PARTY: { Unit* target = m_targets.getUnitTarget(); @@ -2364,7 +2321,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& if (target && target != m_caster) { // Can only be casted on group's members or its pets - Group* pGroup = NULL; + Group* pGroup = nullptr; Unit* owner = m_caster->GetCharmerOrOwner(); Unit* targetOwner = target->GetCharmerOrOwner(); @@ -2431,9 +2388,57 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& case TARGET_LARGE_FRONTAL_CONE: FillAreaTargets(targetUnitMap, radius, PUSH_IN_FRONT_90, SPELL_TARGETS_AOE_DAMAGE); break; - case TARGET_NARROW_FRONTAL_CONE: - FillAreaTargets(targetUnitMap, radius, PUSH_IN_FRONT_15, SPELL_TARGETS_AOE_DAMAGE); + case TARGET_FRIENDLY_FRONTAL_CONE: + FillAreaTargets(targetUnitMap, radius, PUSH_IN_FRONT_30, SPELL_TARGETS_FRIENDLY); break; + case TARGET_NARROW_FRONTAL_CONE: + case TARGET_NARROW_FRONTAL_CONE_2: + { + SpellTargets targetB = SPELL_TARGETS_AOE_DAMAGE; + + if (spellEffect->Effect == SPELL_EFFECT_SCRIPT_EFFECT) + targetB = SPELL_TARGETS_ALL; + + UnitList tempTargetUnitMap; + SQLMultiStorage::SQLMSIteratorBounds bounds = sSpellScriptTargetStorage.getBounds(m_spellInfo->Id); + + // fill real target list if no spell script target defined + FillAreaTargets(bounds.first != bounds.second ? tempTargetUnitMap : targetUnitMap, + radius, PUSH_IN_FRONT_15, bounds.first != bounds.second ? SPELL_TARGETS_ALL : targetB); + + if (!tempTargetUnitMap.empty()) + { + for (UnitList::const_iterator iter = tempTargetUnitMap.begin(); iter != tempTargetUnitMap.end(); ++iter) + { + if ((*iter)->GetTypeId() != TYPEID_UNIT) + continue; + + for (SQLMultiStorage::SQLMultiSIterator i_spellST = bounds.first; i_spellST != bounds.second; ++i_spellST) + { + if (i_spellST->CanNotHitWithSpellEffect(effIndex)) + continue; + + // only creature entries supported for this target type + if (i_spellST->type == SPELL_TARGET_TYPE_GAMEOBJECT) + continue; + + if ((*iter)->GetEntry() == i_spellST->targetEntry) + { + if (i_spellST->type == SPELL_TARGET_TYPE_DEAD && ((Creature*)(*iter))->IsCorpse()) + { + targetUnitMap.push_back((*iter)); + } + else if (i_spellST->type == SPELL_TARGET_TYPE_CREATURE && (*iter)->IsAlive()) + { + targetUnitMap.push_back((*iter)); + } + break; + } + } + } + } + break; + } case TARGET_IN_FRONT_OF_CASTER_30: FillAreaTargets(targetUnitMap, radius, PUSH_IN_FRONT_30, SPELL_TARGETS_AOE_DAMAGE); break; @@ -2483,9 +2488,10 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& { if (Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), this, effIndex)) { - if (m_targets.getUnitTarget() && m_targets.getUnitTarget() != pUnitTarget) + if (m_targets.getUnitTarget() && m_targets.getUnitTarget() != pUnitTarget) m_spellFlags |= SPELL_FLAG_REDIRECTED; + m_targets.setUnitTarget(pUnitTarget); targetUnitMap.push_back(pUnitTarget); } break; @@ -2493,7 +2499,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& case TARGET_AREAEFFECT_PARTY: { Unit* owner = m_caster->GetCharmerOrOwner(); - Player* pTarget = NULL; + Player* pTarget = nullptr; if (owner) { @@ -2519,13 +2525,13 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& } } - Group* pGroup = pTarget ? pTarget->GetGroup() : NULL; + Group* pGroup = pTarget ? pTarget->GetGroup() : nullptr; if (pGroup) { uint8 subgroup = pTarget->GetSubGroup(); - for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + for (GroupReference* itr = pGroup->GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* Target = itr->getSource(); @@ -2641,12 +2647,12 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& case TARGET_AREAEFFECT_PARTY_AND_CLASS: { Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER - ? (Player*)m_targets.getUnitTarget() : NULL; + ? (Player*)m_targets.getUnitTarget() : nullptr; - Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL; + Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : nullptr; if (pGroup) { - for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + for (GroupReference* itr = pGroup->GetFirstMember(); itr != nullptr; itr = itr->next()) { Player* Target = itr->getSource(); @@ -2683,7 +2689,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& case TARGET_RIGHT_FROM_VICTIM: case TARGET_LEFT_FROM_VICTIM: { - Unit* pTarget = NULL; + Unit* pTarget = nullptr; // explicit cast data from client or server-side cast // some spell at client send caster @@ -2770,7 +2776,6 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& case TARGET_POINT_AT_SE: case TARGET_POINT_AT_SW: { - if (!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) { Unit* currentTarget = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster; @@ -2968,6 +2973,10 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList& break; } + // remove caster from the list if required by attribute + if (targetMode != TARGET_SELF && targetMode != TARGET_SELF2 && m_spellInfo->HasAttribute(SPELL_ATTR_EX_CANT_TARGET_SELF)) + targetUnitMap.remove(m_caster); + if (unMaxTargets && targetUnitMap.size() > unMaxTargets) { // make sure one unit is always removed per iteration @@ -6038,6 +6047,42 @@ SpellCastResult Spell::CheckCast(bool strict) } break; } + case SPELL_EFFECT_RESURRECT: + case SPELL_EFFECT_RESURRECT_NEW: + { + if (m_targets.m_targetMask & (TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE)) + { + if (Corpse* corpse = m_caster->GetMap()->GetCorpse(m_targets.getCorpseTargetGuid())) + { + if (Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGuid())) + { + if (owner->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) + return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; + } + else + return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; + } + else + return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; + } + else if (m_targets.m_targetMask & TARGET_FLAG_UNIT) + { + Unit* target = m_targets.getUnitTarget(); + if (!target || target->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) + return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; + } + else + return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; + + break; + } + case SPELL_EFFECT_SELF_RESURRECT: + { + if (m_caster->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) + return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; + + break; + } case SPELL_EFFECT_LEAP: case SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER: { @@ -6594,12 +6639,12 @@ SpellCastResult Spell::CheckRange(bool strict) // special range cases switch (m_spellInfo->rangeIndex) { - // self cast doesn't need range checking -- also for Starshards fix - // spells that can be cast anywhere also need no check + // self cast doesn't need range checking -- also for Starshards fix + // spells that can be cast anywhere also need no check case SPELL_RANGE_IDX_SELF_ONLY: case SPELL_RANGE_IDX_ANYWHERE: return SPELL_CAST_OK; - // combat range spells are treated differently + // combat range spells are treated differently case SPELL_RANGE_IDX_COMBAT: { if (target) @@ -6608,9 +6653,11 @@ SpellCastResult Spell::CheckRange(bool strict) return SPELL_CAST_OK; float range_mod = strict ? 0.0f : 5.0f; - float base = ATTACK_DISTANCE; if (Player* modOwner = m_caster->GetSpellModOwner()) - range_mod += modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, base, this); + { + float base = ATTACK_DISTANCE; + range_mod += modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, base); + } // with additional 5 dist for non stricted case (some melee spells have delay in apply return m_caster->CanReachWithMeleeAttack(target, range_mod) ? SPELL_CAST_OK : SPELL_FAILED_OUT_OF_RANGE; @@ -6628,7 +6675,7 @@ SpellCastResult Spell::CheckRange(bool strict) float min_range = GetSpellMinRange(srange, friendly); if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this); + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range); if (target && target != m_caster) { @@ -7382,16 +7429,22 @@ bool Spell::CheckTarget(Unit* target, SpellEffectIndex eff) if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return false; - // unselectable targets skipped in all cases except TARGET_SCRIPT targeting + // unselectable targets skipped in all cases except TARGET_SCRIPT targeting or vehicle passengers // in case TARGET_SCRIPT target selected by server always and can't be cheated if ((!m_IsTriggeredSpell || target != m_targets.getUnitTarget()) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) && + (!target->GetTransportInfo() || (target->GetTransportInfo() && + !((Unit*)target->GetTransportInfo()->GetTransport())->IsVehicle())) && spellEffect->EffectImplicitTargetA != TARGET_SCRIPT && spellEffect->EffectImplicitTargetB != TARGET_SCRIPT && spellEffect->EffectImplicitTargetA != TARGET_AREAEFFECT_INSTANT && spellEffect->EffectImplicitTargetB != TARGET_AREAEFFECT_INSTANT && spellEffect->EffectImplicitTargetA != TARGET_AREAEFFECT_CUSTOM && - spellEffect->EffectImplicitTargetB != TARGET_AREAEFFECT_CUSTOM ) + spellEffect->EffectImplicitTargetB != TARGET_AREAEFFECT_CUSTOM && + spellEffect->EffectImplicitTargetA != TARGET_NARROW_FRONTAL_CONE && + spellEffect->EffectImplicitTargetB != TARGET_NARROW_FRONTAL_CONE && + spellEffect->EffectImplicitTargetA != TARGET_NARROW_FRONTAL_CONE_2 && + spellEffect->EffectImplicitTargetB != TARGET_NARROW_FRONTAL_CONE_2) return false; } @@ -7999,15 +8052,21 @@ void Spell::GetSpellRangeAndRadius(SpellEffectEntry const* spellEffect, float& r case 62577: // Blizzard (Ulduar, Thorim) case 62603: // Blizzard (h) (Ulduar, Thorim) case 62797: // Storm Cloud (Ulduar, Hodir) + case 62978: // Summon Guardian (Ulduar, Yogg Saron) case 63018: // Searing Light (Ulduar, XT-002) case 63024: // Gravity Bomb (Ulduar, XT-002) case 63545: // Icicle (Ulduar, Hodir) + case 63744: // Sara's Anger (Ulduar, Yogg-Saron) + case 63745: // Sara's Blessing (Ulduar, Yogg-Saron) + case 63747: // Sara's Fervor (Ulduar, Yogg-Saron) case 63795: // Psychosis (Ulduar, Yogg-Saron) case 63820: // Summon Scrap Bot Trigger (Ulduar, Mimiron) use for Scrap Bots, hits npc 33856 + case 63830: // Malady of the Mind (Ulduar, Yogg-Saron) case 64218: // Overcharge (VoA, Emalon) case 64234: // Gravity Bomb (h) (Ulduar, XT-002) - case 64402: // Rocket Strike (Ulduar, Mimiron) + case 64402: // Rocket Strike (Ulduar, Mimiron) case 64425: // Summon Scrap Bot Trigger (Ulduar, Mimiron) use for Assault Bots, hits npc 33856 + case 64465: // Shadow Beacon (Ulduar, Yogg-Saron) case 64543: // Melt Ice (Ulduar, Hodir) case 64623: // Frost Bomb (Ulduar, Mimiron) case 65121: // Searing Light (h) (Ulduar, XT-002) @@ -8055,6 +8114,7 @@ void Spell::GetSpellRangeAndRadius(SpellEffectEntry const* spellEffect, float& r case 10258: // Awaken Vault Warder (Uldaman) case 28542: // Life Drain (Naxx, Sapphiron) case 62476: // Icicle (Ulduar, Hodir) + case 63802: // Brain Link (Ulduar, Yogg-Saron) case 66013: // Penetrating Cold (10 man) (ToCrusader, Anub'arak) case 67755: // Nerubian Burrower (Mode 1) (ToCrusader, Anub'arak) case 67756: // Nerubian Burrower (Mode 2) (ToCrusader, Anub'arak) @@ -8243,8 +8303,12 @@ void Spell::GetSpellRangeAndRadius(SpellEffectEntry const* spellEffect, float& r case 73143: // Bone Spike Graveyard (during Bone Storm) (Icecrown Citadel, Lord Marrowgar encounter, 25N) case 73144: // Bone Spike Graveyard (during Bone Storm) (Icecrown Citadel, Lord Marrowgar encounter, 10H) case 73145: // Bone Spike Graveyard (during Bone Storm) (Icecrown Citadel, Lord Marrowgar encounter, 25H) - radius = DEFAULT_VISIBILITY_INSTANCE; - break; + case 72350: // Fury of Frostmourne + case 72351: // Fury of Frostmourne + case 72706: // Achievement Check + case 72830: // Achievement Check + radius = DEFAULT_VISIBILITY_INSTANCE; + break; default: break; } diff --git a/src/game/WorldHandlers/Spell.h b/src/game/WorldHandlers/Spell.h index 3c5ca15e8..061f2f551 100644 --- a/src/game/WorldHandlers/Spell.h +++ b/src/game/WorldHandlers/Spell.h @@ -382,6 +382,8 @@ class Spell void EffectActivateSpec(SpellEffectEntry const* effect); void EffectCancelAura(SpellEffectEntry const* effect); void EffectKnockBackFromPosition(SpellEffectEntry const* effect); + void EffectGravityPull(SpellEffectEntry const* effect); + void EffectCreateTamedPet(SpellEffectEntry const* effect); Spell(Unit* caster, SpellEntry const* info, bool triggered, ObjectGuid originalCasterGUID = ObjectGuid(), SpellEntry const* triggeredBy = NULL); ~Spell(); diff --git a/src/game/WorldHandlers/SpellAuraDefines.h b/src/game/WorldHandlers/SpellAuraDefines.h index 922575da6..32696c9bf 100644 --- a/src/game/WorldHandlers/SpellAuraDefines.h +++ b/src/game/WorldHandlers/SpellAuraDefines.h @@ -52,474 +52,471 @@ enum AuraFlags */ enum AuraType { - SPELL_AURA_NONE = 0, - SPELL_AURA_BIND_SIGHT = 1, - SPELL_AURA_MOD_POSSESS = 2, + SPELL_AURA_NONE = 0, + SPELL_AURA_BIND_SIGHT = 1, + SPELL_AURA_MOD_POSSESS = 2, /** * The aura should do periodic damage, the function that handles * this is Aura::HandlePeriodicDamage, the amount is usually decided * by the Unit::SpellDamageBonusDone or Unit::MeleeDamageBonusDone * which increases/decreases the Modifier::m_amount */ - SPELL_AURA_PERIODIC_DAMAGE = 3, + SPELL_AURA_PERIODIC_DAMAGE = 3, /** * Used by Aura::HandleAuraDummy */ - SPELL_AURA_DUMMY = 4, + SPELL_AURA_DUMMY = 4, /** * Used by Aura::HandleModConfuse, will either confuse or unconfuse * the target depending on whether the apply flag is set */ - SPELL_AURA_MOD_CONFUSE = 5, - SPELL_AURA_MOD_CHARM = 6, - SPELL_AURA_MOD_FEAR = 7, + SPELL_AURA_MOD_CONFUSE = 5, + SPELL_AURA_MOD_CHARM = 6, + SPELL_AURA_MOD_FEAR = 7, /** * The aura will do periodic heals of a target, handled by * Aura::HandlePeriodicHeal, uses Unit::SpellHealingBonusDone * to calculate whether to increase or decrease Modifier::m_amount */ - SPELL_AURA_PERIODIC_HEAL = 8, + SPELL_AURA_PERIODIC_HEAL = 8, /** * Changes the attackspeed, the Modifier::m_amount decides * how much we change in percent, ie, if the m_amount is * 50 the attackspeed will increase by 50% */ - SPELL_AURA_MOD_ATTACKSPEED = 9, - //This doesn't make sense if you look at SpellAuras.cpp:2696 - //Where a bitwise check is made, but the SpellSchools enum is just - //a normal enumeration, not in the style: 1 2 4 8 ... + SPELL_AURA_MOD_ATTACKSPEED = 9, /** * Modifies the threat that the Aura does in percent, * the Modifier::m_miscvalue decides which of the SpellSchools * it should affect threat for. * \see SpellSchoolMask */ - SPELL_AURA_MOD_THREAT = 10, + SPELL_AURA_MOD_THREAT = 10, /** * Just applies a taunt which will change the threat a mob has * Taken care of in Aura::HandleModThreat */ - SPELL_AURA_MOD_TAUNT = 11, + SPELL_AURA_MOD_TAUNT = 11, /** * Stuns targets in different ways, taken care of in * Aura::HandleAuraModStun */ - SPELL_AURA_MOD_STUN = 12, + SPELL_AURA_MOD_STUN = 12, /** * Changes the damage done by a weapon in any hand, the Modifier::m_miscvalue * will tell what school the damage is from, it's used as a bitmask * \see SpellSchoolMask */ - SPELL_AURA_MOD_DAMAGE_DONE = 13, + SPELL_AURA_MOD_DAMAGE_DONE = 13, /** * Not handled by the Aura class but instead this is implemented in * Unit::MeleeDamageBonusTaken and Unit::SpellBaseDamageBonusTaken */ - SPELL_AURA_MOD_DAMAGE_TAKEN = 14, + SPELL_AURA_MOD_DAMAGE_TAKEN = 14, /** * Not handled by the Aura class, implemented in Unit::DealMeleeDamage */ - SPELL_AURA_DAMAGE_SHIELD = 15, + SPELL_AURA_DAMAGE_SHIELD = 15, /** * Taken care of in Aura::HandleModStealth, take note that this * is not the same thing as invisibility */ - SPELL_AURA_MOD_STEALTH = 16, + SPELL_AURA_MOD_STEALTH = 16, /** * Not handled by the Aura class, implemented in Unit::isVisibleForOrDetect * which does a lot of checks to determine whether the person is visible or not, * the SPELL_AURA_MOD_STEALTH seems to determine how in/visible ie a rogue is. */ - SPELL_AURA_MOD_STEALTH_DETECT = 17, + SPELL_AURA_MOD_STEALTH_DETECT = 17, /** * Handled by Aura::HandleInvisibility, the Modifier::m_miscvalue in the struct * seems to decide what kind of invisibility it is with a bitflag. the miscvalue * decides which bit is set, ie: 3 would make the 3rd bit be set. */ - SPELL_AURA_MOD_INVISIBILITY = 18, + SPELL_AURA_MOD_INVISIBILITY = 18, /** * Adds one of the kinds of detections to the possible detections. * As in SPEALL_AURA_MOD_INVISIBILITY the Modifier::m_miscvalue seems to decide * what kind of invisibility the Unit should be able to detect. */ - SPELL_AURA_MOD_INVISIBILITY_DETECTION = 19, - SPELL_AURA_OBS_MOD_HEALTH = 20, // 20,21 unofficial - SPELL_AURA_OBS_MOD_MANA = 21, + SPELL_AURA_MOD_INVISIBILITY_DETECTION = 19, + SPELL_AURA_OBS_MOD_HEALTH = 20, // 20,21 unofficial + SPELL_AURA_OBS_MOD_MANA = 21, /** * Handled by Aura::HandleAuraModResistance, changes the resistance for a unit * the field Modifier::m_miscvalue decides which kind of resistance that should * be changed, for possible values see SpellSchools. * \see SpellSchools */ - SPELL_AURA_MOD_RESISTANCE = 22, + SPELL_AURA_MOD_RESISTANCE = 22, /** * Currently just sets Aura::m_isPeriodic to apply and has a special case * for Curse of the Plaguebringer. */ - SPELL_AURA_PERIODIC_TRIGGER_SPELL = 23, + SPELL_AURA_PERIODIC_TRIGGER_SPELL = 23, /** * Just sets Aura::m_isPeriodic to apply */ - SPELL_AURA_PERIODIC_ENERGIZE = 24, + SPELL_AURA_PERIODIC_ENERGIZE = 24, /** * Changes whether the target is pacified or not depending on the apply flag. * Pacify makes the target silenced and have all it's attack skill disabled. * See: http://www.wowhead.com/spell=6462/pacified */ - SPELL_AURA_MOD_PACIFY = 25, + SPELL_AURA_MOD_PACIFY = 25, /** * Roots or unroots the target */ - SPELL_AURA_MOD_ROOT = 26, + SPELL_AURA_MOD_ROOT = 26, /** * Silences the target and stops and spell casts that should be stopped, * they have the flag SpellPreventionType::SPELL_PREVENTION_TYPE_SILENCE */ - SPELL_AURA_MOD_SILENCE = 27, - SPELL_AURA_REFLECT_SPELLS = 28, - SPELL_AURA_MOD_STAT = 29, - SPELL_AURA_MOD_SKILL = 30, - SPELL_AURA_MOD_INCREASE_SPEED = 31, - SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED = 32, - SPELL_AURA_MOD_DECREASE_SPEED = 33, - SPELL_AURA_MOD_INCREASE_HEALTH = 34, - SPELL_AURA_MOD_INCREASE_ENERGY = 35, - SPELL_AURA_MOD_SHAPESHIFT = 36, - SPELL_AURA_EFFECT_IMMUNITY = 37, - SPELL_AURA_STATE_IMMUNITY = 38, - SPELL_AURA_SCHOOL_IMMUNITY = 39, - SPELL_AURA_DAMAGE_IMMUNITY = 40, - SPELL_AURA_DISPEL_IMMUNITY = 41, - SPELL_AURA_PROC_TRIGGER_SPELL = 42, - SPELL_AURA_PROC_TRIGGER_DAMAGE = 43, - SPELL_AURA_TRACK_CREATURES = 44, - SPELL_AURA_TRACK_RESOURCES = 45, - SPELL_AURA_46 = 46, // Ignore all Gear test spells - SPELL_AURA_MOD_PARRY_PERCENT = 47, - SPELL_AURA_PERIODIC_TRIGGER_BY_CLIENT = 48, // Client periodic trigger spell by self (3 spells in 3.3.5a) - SPELL_AURA_MOD_DODGE_PERCENT = 49, - SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT = 50, - SPELL_AURA_MOD_BLOCK_CHANCE_PERCENT = 51, - SPELL_AURA_MOD_CRIT_PERCENT = 52, - SPELL_AURA_PERIODIC_LEECH = 53, - SPELL_AURA_MOD_HIT_CHANCE = 54, - SPELL_AURA_MOD_SPELL_HIT_CHANCE = 55, - SPELL_AURA_TRANSFORM = 56, - SPELL_AURA_MOD_SPELL_CRIT_CHANCE = 57, - SPELL_AURA_MOD_INCREASE_SWIM_SPEED = 58, - SPELL_AURA_MOD_DAMAGE_DONE_CREATURE = 59, - SPELL_AURA_MOD_PACIFY_SILENCE = 60, - SPELL_AURA_MOD_SCALE = 61, - SPELL_AURA_PERIODIC_HEALTH_FUNNEL = 62, - SPELL_AURA_63 = 63, // old SPELL_AURA_PERIODIC_MANA_FUNNEL - SPELL_AURA_PERIODIC_MANA_LEECH = 64, - SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK = 65, - SPELL_AURA_FEIGN_DEATH = 66, - SPELL_AURA_MOD_DISARM = 67, - SPELL_AURA_MOD_STALKED = 68, - SPELL_AURA_SCHOOL_ABSORB = 69, - SPELL_AURA_EXTRA_ATTACKS = 70, - SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL = 71, - SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT = 72, - SPELL_AURA_MOD_POWER_COST_SCHOOL = 73, - SPELL_AURA_REFLECT_SPELLS_SCHOOL = 74, - SPELL_AURA_MOD_LANGUAGE = 75, - SPELL_AURA_FAR_SIGHT = 76, - SPELL_AURA_MECHANIC_IMMUNITY = 77, - SPELL_AURA_MOUNTED = 78, - SPELL_AURA_MOD_DAMAGE_PERCENT_DONE = 79, - SPELL_AURA_MOD_PERCENT_STAT = 80, - SPELL_AURA_SPLIT_DAMAGE_PCT = 81, - SPELL_AURA_WATER_BREATHING = 82, - SPELL_AURA_MOD_BASE_RESISTANCE = 83, - SPELL_AURA_MOD_REGEN = 84, - SPELL_AURA_MOD_POWER_REGEN = 85, - SPELL_AURA_CHANNEL_DEATH_ITEM = 86, - SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN = 87, - SPELL_AURA_MOD_HEALTH_REGEN_PERCENT = 88, - SPELL_AURA_PERIODIC_DAMAGE_PERCENT = 89, - SPELL_AURA_90 = 90, // old SPELL_AURA_MOD_RESIST_CHANCE - SPELL_AURA_MOD_DETECT_RANGE = 91, - SPELL_AURA_PREVENTS_FLEEING = 92, - SPELL_AURA_MOD_UNATTACKABLE = 93, - SPELL_AURA_INTERRUPT_REGEN = 94, - SPELL_AURA_GHOST = 95, - SPELL_AURA_SPELL_MAGNET = 96, - SPELL_AURA_MANA_SHIELD = 97, - SPELL_AURA_MOD_SKILL_TALENT = 98, - SPELL_AURA_MOD_ATTACK_POWER = 99, - SPELL_AURA_AURAS_VISIBLE = 100, - SPELL_AURA_MOD_RESISTANCE_PCT = 101, - SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS = 102, - SPELL_AURA_MOD_TOTAL_THREAT = 103, - SPELL_AURA_WATER_WALK = 104, - SPELL_AURA_FEATHER_FALL = 105, - SPELL_AURA_HOVER = 106, - SPELL_AURA_ADD_FLAT_MODIFIER = 107, - SPELL_AURA_ADD_PCT_MODIFIER = 108, - SPELL_AURA_ADD_TARGET_TRIGGER = 109, - SPELL_AURA_MOD_POWER_REGEN_PERCENT = 110, - SPELL_AURA_ADD_CASTER_HIT_TRIGGER = 111, - SPELL_AURA_OVERRIDE_CLASS_SCRIPTS = 112, - SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN = 113, - SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT = 114, - SPELL_AURA_MOD_HEALING = 115, - SPELL_AURA_MOD_REGEN_DURING_COMBAT = 116, - SPELL_AURA_MOD_MECHANIC_RESISTANCE = 117, - SPELL_AURA_MOD_HEALING_PCT = 118, - SPELL_AURA_119 = 119, // old SPELL_AURA_SHARE_PET_TRACKING - SPELL_AURA_UNTRACKABLE = 120, - SPELL_AURA_EMPATHY = 121, - SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT = 122, - SPELL_AURA_MOD_TARGET_RESISTANCE = 123, - SPELL_AURA_MOD_RANGED_ATTACK_POWER = 124, - SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN = 125, - SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT = 126, + SPELL_AURA_MOD_SILENCE = 27, + SPELL_AURA_REFLECT_SPELLS = 28, + SPELL_AURA_MOD_STAT = 29, + SPELL_AURA_MOD_SKILL = 30, + SPELL_AURA_MOD_INCREASE_SPEED = 31, + SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED = 32, + SPELL_AURA_MOD_DECREASE_SPEED = 33, + SPELL_AURA_MOD_INCREASE_HEALTH = 34, + SPELL_AURA_MOD_INCREASE_ENERGY = 35, + SPELL_AURA_MOD_SHAPESHIFT = 36, + SPELL_AURA_EFFECT_IMMUNITY = 37, + SPELL_AURA_STATE_IMMUNITY = 38, + SPELL_AURA_SCHOOL_IMMUNITY = 39, + SPELL_AURA_DAMAGE_IMMUNITY = 40, + SPELL_AURA_DISPEL_IMMUNITY = 41, + SPELL_AURA_PROC_TRIGGER_SPELL = 42, + SPELL_AURA_PROC_TRIGGER_DAMAGE = 43, + SPELL_AURA_TRACK_CREATURES = 44, + SPELL_AURA_TRACK_RESOURCES = 45, + SPELL_AURA_46 = 46, // Ignore all Gear test spells + SPELL_AURA_MOD_PARRY_PERCENT = 47, + SPELL_AURA_PERIODIC_TRIGGER_BY_CLIENT = 48, // Client periodic trigger spell by self (3 spells in 3.3.5a) + SPELL_AURA_MOD_DODGE_PERCENT = 49, + SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT = 50, + SPELL_AURA_MOD_BLOCK_CHANCE_PERCENT = 51, + SPELL_AURA_MOD_CRIT_PERCENT = 52, + SPELL_AURA_PERIODIC_LEECH = 53, + SPELL_AURA_MOD_HIT_CHANCE = 54, + SPELL_AURA_MOD_SPELL_HIT_CHANCE = 55, + SPELL_AURA_TRANSFORM = 56, + SPELL_AURA_MOD_SPELL_CRIT_CHANCE = 57, + SPELL_AURA_MOD_INCREASE_SWIM_SPEED = 58, + SPELL_AURA_MOD_DAMAGE_DONE_CREATURE = 59, + SPELL_AURA_MOD_PACIFY_SILENCE = 60, + SPELL_AURA_MOD_SCALE = 61, + SPELL_AURA_PERIODIC_HEALTH_FUNNEL = 62, + SPELL_AURA_63 = 63, // old SPELL_AURA_PERIODIC_MANA_FUNNEL + SPELL_AURA_PERIODIC_MANA_LEECH = 64, + SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK = 65, + SPELL_AURA_FEIGN_DEATH = 66, + SPELL_AURA_MOD_DISARM = 67, + SPELL_AURA_MOD_STALKED = 68, + SPELL_AURA_SCHOOL_ABSORB = 69, + SPELL_AURA_EXTRA_ATTACKS = 70, + SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL = 71, + SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT = 72, + SPELL_AURA_MOD_POWER_COST_SCHOOL = 73, + SPELL_AURA_REFLECT_SPELLS_SCHOOL = 74, + SPELL_AURA_MOD_LANGUAGE = 75, + SPELL_AURA_FAR_SIGHT = 76, + SPELL_AURA_MECHANIC_IMMUNITY = 77, + SPELL_AURA_MOUNTED = 78, + SPELL_AURA_MOD_DAMAGE_PERCENT_DONE = 79, + SPELL_AURA_MOD_PERCENT_STAT = 80, + SPELL_AURA_SPLIT_DAMAGE_PCT = 81, + SPELL_AURA_WATER_BREATHING = 82, + SPELL_AURA_MOD_BASE_RESISTANCE = 83, + SPELL_AURA_MOD_REGEN = 84, + SPELL_AURA_MOD_POWER_REGEN = 85, + SPELL_AURA_CHANNEL_DEATH_ITEM = 86, + SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN = 87, + SPELL_AURA_MOD_HEALTH_REGEN_PERCENT = 88, + SPELL_AURA_PERIODIC_DAMAGE_PERCENT = 89, + SPELL_AURA_90 = 90, // old SPELL_AURA_MOD_RESIST_CHANCE + SPELL_AURA_MOD_DETECT_RANGE = 91, + SPELL_AURA_PREVENTS_FLEEING = 92, + SPELL_AURA_MOD_UNATTACKABLE = 93, + SPELL_AURA_INTERRUPT_REGEN = 94, + SPELL_AURA_GHOST = 95, + SPELL_AURA_SPELL_MAGNET = 96, + SPELL_AURA_MANA_SHIELD = 97, + SPELL_AURA_MOD_SKILL_TALENT = 98, + SPELL_AURA_MOD_ATTACK_POWER = 99, + SPELL_AURA_AURAS_VISIBLE = 100, + SPELL_AURA_MOD_RESISTANCE_PCT = 101, + SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS = 102, + SPELL_AURA_MOD_TOTAL_THREAT = 103, + SPELL_AURA_WATER_WALK = 104, + SPELL_AURA_FEATHER_FALL = 105, + SPELL_AURA_HOVER = 106, + SPELL_AURA_ADD_FLAT_MODIFIER = 107, + SPELL_AURA_ADD_PCT_MODIFIER = 108, + SPELL_AURA_ADD_TARGET_TRIGGER = 109, + SPELL_AURA_MOD_POWER_REGEN_PERCENT = 110, + SPELL_AURA_ADD_CASTER_HIT_TRIGGER = 111, + SPELL_AURA_OVERRIDE_CLASS_SCRIPTS = 112, + SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN = 113, + SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT = 114, + SPELL_AURA_MOD_HEALING = 115, + SPELL_AURA_MOD_REGEN_DURING_COMBAT = 116, + SPELL_AURA_MOD_MECHANIC_RESISTANCE = 117, + SPELL_AURA_MOD_HEALING_PCT = 118, + SPELL_AURA_119 = 119, // old SPELL_AURA_SHARE_PET_TRACKING + SPELL_AURA_UNTRACKABLE = 120, + SPELL_AURA_EMPATHY = 121, + SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT = 122, + SPELL_AURA_MOD_TARGET_RESISTANCE = 123, + SPELL_AURA_MOD_RANGED_ATTACK_POWER = 124, + SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN = 125, + SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT = 126, SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS = 127, - SPELL_AURA_MOD_POSSESS_PET = 128, - SPELL_AURA_MOD_SPEED_ALWAYS = 129, - SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS = 130, - SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS = 131, - SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT = 132, - SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT = 133, - SPELL_AURA_MOD_MANA_REGEN_INTERRUPT = 134, - SPELL_AURA_MOD_HEALING_DONE = 135, - SPELL_AURA_MOD_HEALING_DONE_PERCENT = 136, - SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE = 137, - SPELL_AURA_MOD_MELEE_HASTE = 138, - SPELL_AURA_FORCE_REACTION = 139, - SPELL_AURA_MOD_RANGED_HASTE = 140, - SPELL_AURA_MOD_RANGED_AMMO_HASTE = 141, - SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142, - SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143, - SPELL_AURA_SAFE_FALL = 144, - SPELL_AURA_MOD_PET_TALENT_POINTS = 145, - SPELL_AURA_ALLOW_TAME_PET_TYPE = 146, - SPELL_AURA_MECHANIC_IMMUNITY_MASK = 147, - SPELL_AURA_RETAIN_COMBO_POINTS = 148, - SPELL_AURA_REDUCE_PUSHBACK = 149, // Reduce Pushback - SPELL_AURA_MOD_SHIELD_BLOCKDAMAGE = 150, - SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed - SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range - SPELL_AURA_153 = 153, // old SPELL_AURA_SPLIT_DAMAGE_FLAT - SPELL_AURA_MOD_STEALTH_LEVEL = 154, // Stealth Level Modifier - SPELL_AURA_MOD_WATER_BREATHING = 155, // Mod Water Breathing - SPELL_AURA_MOD_REPUTATION_GAIN = 156, // Mod Reputation Gain - SPELL_AURA_PET_DAMAGE_MULTI = 157, // Mod Pet Damage - SPELL_AURA_MOD_SHIELD_BLOCKVALUE = 158, - SPELL_AURA_NO_PVP_CREDIT = 159, - SPELL_AURA_160 = 160, // old SPELL_AURA_MOD_AOE_AVOIDANCE - SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161, - SPELL_AURA_POWER_BURN_MANA = 162, - SPELL_AURA_MOD_CRIT_DAMAGE_BONUS = 163, - SPELL_AURA_164 = 164, + SPELL_AURA_MOD_POSSESS_PET = 128, + SPELL_AURA_MOD_SPEED_ALWAYS = 129, + SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS = 130, + SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS = 131, + SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT = 132, + SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT = 133, + SPELL_AURA_MOD_MANA_REGEN_INTERRUPT = 134, + SPELL_AURA_MOD_HEALING_DONE = 135, + SPELL_AURA_MOD_HEALING_DONE_PERCENT = 136, + SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE = 137, + SPELL_AURA_MOD_MELEE_HASTE = 138, + SPELL_AURA_FORCE_REACTION = 139, + SPELL_AURA_MOD_RANGED_HASTE = 140, + SPELL_AURA_MOD_RANGED_AMMO_HASTE = 141, + SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142, + SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143, + SPELL_AURA_SAFE_FALL = 144, + SPELL_AURA_MOD_PET_TALENT_POINTS = 145, + SPELL_AURA_ALLOW_TAME_PET_TYPE = 146, + SPELL_AURA_MECHANIC_IMMUNITY_MASK = 147, + SPELL_AURA_RETAIN_COMBO_POINTS = 148, + SPELL_AURA_REDUCE_PUSHBACK = 149, // Reduce Pushback + SPELL_AURA_MOD_SHIELD_BLOCKDAMAGE = 150, + SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed + SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range + SPELL_AURA_153 = 153, // old SPELL_AURA_SPLIT_DAMAGE_FLAT + SPELL_AURA_MOD_STEALTH_LEVEL = 154, // Stealth Level Modifier + SPELL_AURA_MOD_WATER_BREATHING = 155, // Mod Water Breathing + SPELL_AURA_MOD_REPUTATION_GAIN = 156, // Mod Reputation Gain + SPELL_AURA_PET_DAMAGE_MULTI = 157, // Mod Pet Damage + SPELL_AURA_MOD_SHIELD_BLOCKVALUE = 158, + SPELL_AURA_NO_PVP_CREDIT = 159, + SPELL_AURA_160 = 160, // old SPELL_AURA_MOD_AOE_AVOIDANCE + SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161, + SPELL_AURA_POWER_BURN_MANA = 162, + SPELL_AURA_MOD_CRIT_DAMAGE_BONUS = 163, + SPELL_AURA_164 = 164, SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS = 165, - SPELL_AURA_MOD_ATTACK_POWER_PCT = 166, - SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT = 167, - SPELL_AURA_MOD_DAMAGE_DONE_VERSUS = 168, - SPELL_AURA_169 = 169, // old SPELL_AURA_MOD_CRIT_PERCENT_VERSUS - SPELL_AURA_DETECT_AMORE = 170, - SPELL_AURA_MOD_SPEED_NOT_STACK = 171, - SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK = 172, - SPELL_AURA_173 = 173, // old SPELL_AURA_ALLOW_CHAMPION_SPELLS + SPELL_AURA_MOD_ATTACK_POWER_PCT = 166, + SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT = 167, + SPELL_AURA_MOD_DAMAGE_DONE_VERSUS = 168, + SPELL_AURA_169 = 169, // old SPELL_AURA_MOD_CRIT_PERCENT_VERSUS + SPELL_AURA_DETECT_AMORE = 170, + SPELL_AURA_MOD_SPEED_NOT_STACK = 171, + SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK = 172, + SPELL_AURA_173 = 173, // old SPELL_AURA_ALLOW_CHAMPION_SPELLS SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT = 174, // by defeult intelect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT = 175, - SPELL_AURA_SPIRIT_OF_REDEMPTION = 176, - SPELL_AURA_AOE_CHARM = 177, - SPELL_AURA_178 = 178, // old SPELL_AURA_MOD_DEBUFF_RESISTANCE - SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE = 179, - SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS = 180, - SPELL_AURA_181 = 181, // old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS - possible flat spell crit damage versus - SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT = 182, - SPELL_AURA_MOD_CRITICAL_THREAT = 183, - SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE = 184, - SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE = 185, - SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE = 186, - SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE = 187, - SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE = 188, - SPELL_AURA_MOD_RATING = 189, - SPELL_AURA_MOD_FACTION_REPUTATION_GAIN = 190, - SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191, - SPELL_AURA_MOD_MELEE_RANGED_HASTE = 192, - SPELL_AURA_HASTE_ALL = 193, - SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL = 194, - SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL = 195, - SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath + SPELL_AURA_SPIRIT_OF_REDEMPTION = 176, + SPELL_AURA_AOE_CHARM = 177, + SPELL_AURA_178 = 178, // old SPELL_AURA_MOD_DEBUFF_RESISTANCE + SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE = 179, + SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS = 180, + SPELL_AURA_181 = 181, // old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS - possible flat spell crit damage versus + SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT = 182, + SPELL_AURA_MOD_CRITICAL_THREAT = 183, + SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE = 184, + SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE = 185, + SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE = 186, + SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE = 187, + SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE = 188, + SPELL_AURA_MOD_RATING = 189, + SPELL_AURA_MOD_FACTION_REPUTATION_GAIN = 190, + SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191, + SPELL_AURA_MOD_MELEE_RANGED_HASTE = 192, + SPELL_AURA_HASTE_ALL = 193, + SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL = 194, + SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL = 195, + SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, - SPELL_AURA_198 = 198, // old SPELL_AURA_MOD_ALL_WEAPON_SKILLS - SPELL_AURA_199 = 199, // old SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT - SPELL_AURA_MOD_KILL_XP_PCT = 200, - SPELL_AURA_FLY = 201, - SPELL_AURA_IGNORE_COMBAT_RESULT = 202, - SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE = 203, - SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE = 204, - SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE = 205, - SPELL_AURA_MOD_FLIGHT_SPEED = 206, - SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED = 207, - SPELL_AURA_MOD_FLIGHT_SPEED_STACKING = 208, + SPELL_AURA_198 = 198, // old SPELL_AURA_MOD_ALL_WEAPON_SKILLS + SPELL_AURA_199 = 199, // old SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT + SPELL_AURA_MOD_KILL_XP_PCT = 200, + SPELL_AURA_FLY = 201, + SPELL_AURA_IGNORE_COMBAT_RESULT = 202, + SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE = 203, + SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE = 204, + SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE = 205, + SPELL_AURA_MOD_FLIGHT_SPEED = 206, + SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED = 207, + SPELL_AURA_MOD_FLIGHT_SPEED_STACKING = 208, SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED_STACKING = 209, - SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACKING = 210, + SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACKING = 210, SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED_NOT_STACKING = 211, - SPELL_AURA_212 = 212, // old SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT - SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT = 213, - SPELL_AURA_214 = 214, - SPELL_AURA_ARENA_PREPARATION = 215, - SPELL_AURA_HASTE_SPELLS = 216, - SPELL_AURA_217 = 217, - SPELL_AURA_HASTE_RANGED = 218, - SPELL_AURA_MOD_MANA_REGEN_FROM_STAT = 219, - SPELL_AURA_MOD_RATING_FROM_STAT = 220, - SPELL_AURA_IGNORED = 221, - SPELL_AURA_222 = 222, - SPELL_AURA_223 = 223, - SPELL_AURA_224 = 224, - SPELL_AURA_PRAYER_OF_MENDING = 225, - SPELL_AURA_PERIODIC_DUMMY = 226, + SPELL_AURA_212 = 212, // old SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT + SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT = 213, + SPELL_AURA_214 = 214, + SPELL_AURA_ARENA_PREPARATION = 215, + SPELL_AURA_HASTE_SPELLS = 216, + SPELL_AURA_217 = 217, + SPELL_AURA_HASTE_RANGED = 218, + SPELL_AURA_MOD_MANA_REGEN_FROM_STAT = 219, + SPELL_AURA_MOD_RATING_FROM_STAT = 220, + SPELL_AURA_IGNORED = 221, + SPELL_AURA_222 = 222, + SPELL_AURA_223 = 223, + SPELL_AURA_224 = 224, + SPELL_AURA_PRAYER_OF_MENDING = 225, + SPELL_AURA_PERIODIC_DUMMY = 226, SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE = 227, - SPELL_AURA_DETECT_STEALTH = 228, - SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE = 229, - SPELL_AURA_230 = 230, - SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE = 231, - SPELL_AURA_MECHANIC_DURATION_MOD = 232, - SPELL_AURA_233 = 233, - SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234, - SPELL_AURA_MOD_DISPEL_RESIST = 235, - SPELL_AURA_CONTROL_VEHICLE = 236, + SPELL_AURA_DETECT_STEALTH = 228, + SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE = 229, + SPELL_AURA_230 = 230, + SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE = 231, + SPELL_AURA_MECHANIC_DURATION_MOD = 232, + SPELL_AURA_233 = 233, + SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234, + SPELL_AURA_MOD_DISPEL_RESIST = 235, + SPELL_AURA_CONTROL_VEHICLE = 236, SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER = 237, SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER = 238, - SPELL_AURA_MOD_SCALE_2 = 239, - SPELL_AURA_MOD_EXPERTISE = 240, - SPELL_AURA_FORCE_MOVE_FORWARD = 241, - SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING = 242, - SPELL_AURA_243 = 243, - SPELL_AURA_COMPREHEND_LANGUAGE = 244, - SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS = 245, + SPELL_AURA_MOD_SCALE_2 = 239, + SPELL_AURA_MOD_EXPERTISE = 240, + SPELL_AURA_FORCE_MOVE_FORWARD = 241, + SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING = 242, + SPELL_AURA_FACTION_OVERRIDE = 243, + SPELL_AURA_COMPREHEND_LANGUAGE = 244, + SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS = 245, SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL = 246, - SPELL_AURA_MIRROR_IMAGE = 247, - SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248, - SPELL_AURA_CONVERT_RUNE = 249, - SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250, - SPELL_AURA_MOD_ENEMY_DODGE = 251, - SPELL_AURA_SLOW_ALL = 252, - SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253, - SPELL_AURA_MOD_DISARM_OFFHAND = 254, + SPELL_AURA_MIRROR_IMAGE = 247, + SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248, + SPELL_AURA_CONVERT_RUNE = 249, + SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250, + SPELL_AURA_MOD_ENEMY_DODGE = 251, + SPELL_AURA_SLOW_ALL = 252, + SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253, + SPELL_AURA_MOD_DISARM_OFFHAND = 254, SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT = 255, - SPELL_AURA_NO_REAGENT_USE = 256, + SPELL_AURA_NO_REAGENT_USE = 256, SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257, - SPELL_AURA_258 = 258, - SPELL_AURA_259 = 259, // old SPELL_AURA_MOD_PERIODIC_HEAL - SPELL_AURA_SCREEN_EFFECT = 260, - SPELL_AURA_PHASE = 261, - SPELL_AURA_IGNORE_UNIT_STATE = 262, - SPELL_AURA_ALLOW_ONLY_ABILITY = 263, - SPELL_AURA_264 = 264, - SPELL_AURA_265 = 265, - SPELL_AURA_266 = 266, - SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267, - SPELL_AURA_268 = 268, // old SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT + SPELL_AURA_258 = 258, + SPELL_AURA_259 = 259, // old SPELL_AURA_MOD_PERIODIC_HEAL + SPELL_AURA_SCREEN_EFFECT = 260, + SPELL_AURA_PHASE = 261, + SPELL_AURA_IGNORE_UNIT_STATE = 262, + SPELL_AURA_ALLOW_ONLY_ABILITY = 263, + SPELL_AURA_264 = 264, + SPELL_AURA_265 = 265, + SPELL_AURA_266 = 266, + SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267, + SPELL_AURA_268 = 268, // old SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT SPELL_AURA_MOD_IGNORE_DAMAGE_REDUCTION_SCHOOL = 269, - SPELL_AURA_270 = 270, // old SPELL_AURA_MOD_IGNORE_TARGET_RESIST - SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271, - SPELL_AURA_MAELSTROM_WEAPON = 272, - SPELL_AURA_X_RAY = 273, - SPELL_AURA_274 = 274, - SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275, - SPELL_AURA_MOD_DAMAGE_DONE_BY_MECHANIC = 276, - SPELL_AURA_277 = 277, // SPELL_AURA_MOD_MAX_AFFECTED_TARGETS - SPELL_AURA_MOD_DISARM_RANGED = 278, - SPELL_AURA_INITIALIZE_IMAGES = 279, - SPELL_AURA_280 = 280, // old SPELL_AURA_MOD_TARGET_ARMOR_PCT - SPELL_AURA_MOD_HONOR_GAIN = 281, - SPELL_AURA_MOD_BASE_HEALTH_PCT = 282, - SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells - SPELL_AURA_284 = 284, - SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285, - SPELL_AURA_ABILITY_PERIODIC_CRIT = 286, - SPELL_AURA_DEFLECT_SPELLS = 287, - SPELL_AURA_MOD_PARRY_FROM_BEHIND_PERCENT = 288, - SPELL_AURA_289 = 289, - SPELL_AURA_MOD_ALL_CRIT_CHANCE = 290, - SPELL_AURA_MOD_QUEST_XP_PCT = 291, - SPELL_AURA_OPEN_STABLE = 292, - SPELL_AURA_ADD_MECHANIC_ABILITIES = 293, - SPELL_AURA_STOP_NATURAL_MANA_REGEN = 294, - SPELL_AURA_295 = 295, - SPELL_AURA_SET_VEHICLE_ID = 296, - SPELL_AURA_297 = 297, - SPELL_AURA_298 = 298, - SPELL_AURA_299 = 299, - SPELL_AURA_SHARE_DAMAGE_PCT = 300, - SPELL_AURA_HEAL_ABSORB = 301, - SPELL_AURA_302 = 302, + SPELL_AURA_270 = 270, // old SPELL_AURA_MOD_IGNORE_TARGET_RESIST + SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271, + SPELL_AURA_MAELSTROM_WEAPON = 272, + SPELL_AURA_X_RAY = 273, + SPELL_AURA_274 = 274, + SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275, + SPELL_AURA_MOD_DAMAGE_DONE_BY_MECHANIC = 276, + SPELL_AURA_277 = 277, // SPELL_AURA_MOD_MAX_AFFECTED_TARGETS + SPELL_AURA_MOD_DISARM_RANGED = 278, + SPELL_AURA_MIRROR_NAME = 279, + SPELL_AURA_280 = 280, // old SPELL_AURA_MOD_TARGET_ARMOR_PCT + SPELL_AURA_MOD_HONOR_GAIN = 281, + SPELL_AURA_MOD_BASE_HEALTH_PCT = 282, + SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells + SPELL_AURA_TRIGGER_LINKED_AURA = 284, + SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285, + SPELL_AURA_ABILITY_PERIODIC_CRIT = 286, + SPELL_AURA_DEFLECT_SPELLS = 287, + SPELL_AURA_MOD_PARRY_FROM_BEHIND_PERCENT = 288, + SPELL_AURA_289 = 289, + SPELL_AURA_MOD_ALL_CRIT_CHANCE = 290, + SPELL_AURA_MOD_QUEST_XP_PCT = 291, + SPELL_AURA_OPEN_STABLE = 292, + SPELL_AURA_ADD_MECHANIC_ABILITIES = 293, + SPELL_AURA_STOP_NATURAL_MANA_REGEN = 294, + SPELL_AURA_295 = 295, + SPELL_AURA_SET_VEHICLE_ID = 296, + SPELL_AURA_297 = 297, + SPELL_AURA_298 = 298, + SPELL_AURA_299 = 299, + SPELL_AURA_SHARE_DAMAGE_PCT = 300, + SPELL_AURA_HEAL_ABSORB = 301, + SPELL_AURA_302 = 302, SPELL_AURA_MOD_DAMAGE_DONE_VERSUS_AURASTATE = 303, - SPELL_AURA_FAKE_INEBRIATE = 304, - SPELL_AURA_MOD_MINIMUM_SPEED = 305, - SPELL_AURA_306 = 306, - SPELL_AURA_307 = 307, - SPELL_AURA_MOD_CRIT_FROM_CASTER = 308, - SPELL_AURA_309 = 309, - SPELL_AURA_MOD_PET_AOE_DAMAGE_AVOIDANCE = 310, - SPELL_AURA_311 = 311, - SPELL_AURA_312 = 312, - SPELL_AURA_313 = 313, - SPELL_AURA_PREVENT_RESURRECTION = 314, - SPELL_AURA_UNDERWATER_WALKING = 315, - SPELL_AURA_316 = 316, // old SPELL_AURA_MOD_PERIODIC_HASTE - SPELL_AURA_MOD_INCREASE_SPELL_POWER_PCT = 317, - SPELL_AURA_MASTERY = 318, - SPELL_AURA_MOD_MELEE_ATTACK_SPEED = 319, - SPELL_AURA_MOD_RANGED_ATTACK_SPEED = 320, - SPELL_AURA_321 = 321, - SPELL_AURA_INTERFERE_TARGETING = 322, - SPELL_AURA_323 = 323, - SPELL_AURA_324 = 324, - SPELL_AURA_325 = 325, - SPELL_AURA_PHASE_2 = 326, - SPELL_AURA_327 = 327, - SPELL_AURA_PROC_ON_POWER_AMOUNT = 328, - SPELL_AURA_MOD_RUNIC_POWER_REGEN = 329, - SPELL_AURA_ALLOW_CAST_WHILE_MOVING = 330, - SPELL_AURA_MOD_WEATHER = 331, - SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS = 332, - SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2 = 333, - SPELL_AURA_BLIND_SIGHT = 334, - SPELL_AURA_SEE_WHILE_INVISIBLE = 335, - SPELL_AURA_FLIGHT_RESTRICTIONS = 336, - SPELL_AURA_MOD_VENDOR_PRICE = 337, - SPELL_AURA_MOD_DURABILITY_LOSS = 338, - SPELL_AURA_MOD_SKILLCHANCE = 339, - SPELL_AURA_MOD_RESSURECTED_HEALTH = 340, - SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN = 341, - SPELL_AURA_MOD_ATTACKSPEED_2 = 342, - SPELL_AURA_MOD_ALL_DAMAGE_FROM_CASTER = 343, - SPELL_AURA_MOD_AUTOATTACK_DAMAGE = 344, - SPELL_AURA_MOD_IGNORE_ARMOR_PCT = 345, - SPELL_AURA_ALT_POWER_INDICATOR = 346, - SPELL_AURA_MOD_CD_FROM_HASTE = 347, - SPELL_AURA_MOD_MONEY_TO_GUILD_BANK = 348, - SPELL_AURA_MOD_CURRENCY_GAIN = 349, - SPELL_AURA_MOD_ITEM_LOOT = 350, - SPELL_AURA_MOD_CURRENCY_LOOT = 351, - SPELL_AURA_ALLOW_WORGEN_TRANSFORM = 352, - SPELL_AURA_CAMOUFLAGE = 353, + SPELL_AURA_FAKE_INEBRIATE = 304, + SPELL_AURA_MOD_MINIMUM_SPEED = 305, + SPELL_AURA_306 = 306, + SPELL_AURA_307 = 307, + SPELL_AURA_MOD_CRIT_FROM_CASTER = 308, + SPELL_AURA_309 = 309, + SPELL_AURA_MOD_PET_AOE_DAMAGE_AVOIDANCE = 310, + SPELL_AURA_311 = 311, + SPELL_AURA_312 = 312, + SPELL_AURA_313 = 313, + SPELL_AURA_PREVENT_RESURRECTION = 314, + SPELL_AURA_UNDERWATER_WALKING = 315, + SPELL_AURA_316 = 316, // old SPELL_AURA_MOD_PERIODIC_HASTE + SPELL_AURA_MOD_INCREASE_SPELL_POWER_PCT = 317, + SPELL_AURA_MASTERY = 318, + SPELL_AURA_MOD_MELEE_ATTACK_SPEED = 319, + SPELL_AURA_MOD_RANGED_ATTACK_SPEED = 320, + SPELL_AURA_321 = 321, + SPELL_AURA_INTERFERE_TARGETING = 322, + SPELL_AURA_323 = 323, + SPELL_AURA_324 = 324, + SPELL_AURA_325 = 325, + SPELL_AURA_PHASE_2 = 326, + SPELL_AURA_327 = 327, + SPELL_AURA_PROC_ON_POWER_AMOUNT = 328, + SPELL_AURA_MOD_RUNIC_POWER_REGEN = 329, + SPELL_AURA_ALLOW_CAST_WHILE_MOVING = 330, + SPELL_AURA_MOD_WEATHER = 331, + SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS = 332, + SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_2 = 333, + SPELL_AURA_BLIND_SIGHT = 334, + SPELL_AURA_SEE_WHILE_INVISIBLE = 335, + SPELL_AURA_FLIGHT_RESTRICTIONS = 336, + SPELL_AURA_MOD_VENDOR_PRICE = 337, + SPELL_AURA_MOD_DURABILITY_LOSS = 338, + SPELL_AURA_MOD_SKILLCHANCE = 339, + SPELL_AURA_MOD_RESSURECTED_HEALTH = 340, + SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN = 341, + SPELL_AURA_MOD_ATTACKSPEED_2 = 342, + SPELL_AURA_MOD_ALL_DAMAGE_FROM_CASTER = 343, + SPELL_AURA_MOD_AUTOATTACK_DAMAGE = 344, + SPELL_AURA_MOD_IGNORE_ARMOR_PCT = 345, + SPELL_AURA_ALT_POWER_INDICATOR = 346, + SPELL_AURA_MOD_CD_FROM_HASTE = 347, + SPELL_AURA_MOD_MONEY_TO_GUILD_BANK = 348, + SPELL_AURA_MOD_CURRENCY_GAIN = 349, + SPELL_AURA_MOD_ITEM_LOOT = 350, + SPELL_AURA_MOD_CURRENCY_LOOT = 351, + SPELL_AURA_ALLOW_WORGEN_TRANSFORM = 352, + SPELL_AURA_CAMOUFLAGE = 353, SPELL_AURA_MOD_HEALING_DONE_FROM_PCT_HEALTH = 354, - SPELL_AURA_355 = 355, - SPELL_AURA_MOD_DAMAGE_DONE_FROM_PCT_POWER = 356, - SPELL_AURA_357 = 357, - SPELL_AURA_WORGEN_TRANSFORM = 358, - SPELL_AURA_359 = 359, - SPELL_AURA_PROC_DUPLICATE_SPELLS = 360, - SPELL_AURA_PROC_TRIGGER_SPELL_2 = 361, - SPELL_AURA_362 = 362, - SPELL_AURA_363 = 363, - SPELL_AURA_364 = 364, - SPELL_AURA_365 = 365, - SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT = 366, - SPELL_AURA_367 = 367, - SPELL_AURA_368 = 368, - SPELL_AURA_369 = 369, - SPELL_AURA_370 = 370, - TOTAL_AURAS = 371, + SPELL_AURA_355 = 355, + SPELL_AURA_MOD_DAMAGE_DONE_FROM_PCT_POWER = 356, + SPELL_AURA_357 = 357, + SPELL_AURA_WORGEN_TRANSFORM = 358, + SPELL_AURA_359 = 359, + SPELL_AURA_PROC_DUPLICATE_SPELLS = 360, + SPELL_AURA_PROC_TRIGGER_SPELL_2 = 361, + SPELL_AURA_362 = 362, + SPELL_AURA_363 = 363, + SPELL_AURA_364 = 364, + SPELL_AURA_365 = 365, + SPELL_AURA_OVERRIDE_SPELL_POWER_BY_AP_PCT = 366, + SPELL_AURA_367 = 367, + SPELL_AURA_368 = 368, + SPELL_AURA_369 = 369, + SPELL_AURA_370 = 370, + TOTAL_AURAS = 371, }; enum AreaAuraType diff --git a/src/game/WorldHandlers/SpellAuras.cpp b/src/game/WorldHandlers/SpellAuras.cpp index dd1170b5d..313e73b5c 100644 --- a/src/game/WorldHandlers/SpellAuras.cpp +++ b/src/game/WorldHandlers/SpellAuras.cpp @@ -54,7 +54,6 @@ #include "CellImpl.h" #include "Language.h" #include "MapManager.h" -#include "PhaseMgr.h" #define NULL_AURA_SLOT 0xFF @@ -307,7 +306,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS] = &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE &Aura::HandleForceMoveForward, //241 Forces the caster to move forward &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING (only 2 test spels in 3.2.2a) - &Aura::HandleNULL, //243 faction reaction override spells + &Aura::HandleFactionOverride, //243 SPELL_AURA_FACTION_OVERRIDE &Aura::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE &Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS implemented in Unit::CalculateAuraDuration &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL implemented in Unit::CalculateAuraDuration @@ -343,12 +342,12 @@ pAuraHandler AuraHandler[TOTAL_AURAS] = &Aura::HandleNULL, //276 SPELL_AURA_MOD_DAMAGE_DONE_BY_MECHANIC &Aura::HandleUnused, //277 old SPELL_AURA_MOD_MAX_AFFECTED_TARGETS &Aura::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon - &Aura::HandleNULL, //279 SPELL_AURA_INITIALIZE_IMAGES 9 spells in 4.3.4 visual effects? + &Aura::HandleMirrorName, //279 SPELL_AURA_MIRROR_NAME target receives the casters name &Aura::HandleUnused, //280 old SPELL_AURA_MOD_TARGET_ARMOR_PCT &Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN implemented in Player::RewardHonor &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT &Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonusTaken - &Aura::HandleNULL, //284 146 spells in 4.3.4 + &Aura::HandleTriggerLinkedAura, //284 SPELL_AURA_TRIGGER_LINKED_AURA &Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage &Aura::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in Aura::IsCritFromAbilityAura called from Aura::PeriodicTick &Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult @@ -378,7 +377,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS] = &Aura::HandleNULL, //311 2 spells in 4.3.4 some kind of stun effect &Aura::HandleNULL, //312 37 spells in 4.3.4 some cosmetic auras &Aura::HandleNULL, //313 0 spells in 4.3.4 - &Aura::HandleNULL, //314 SPELL_AURA_PREVENT_RESURRECTION 2 spells int 4.3.4 prevents ressurection ? + &Aura::HandlePreventResurrection, //314 SPELL_AURA_PREVENT_RESURRECTION &Aura::HandleNULL, //315 SPELL_AURA_UNDERWATER_WALKING 4 spells in 4.3.4 underwater walking &Aura::HandleUnused, //316 old SPELL_AURA_MOD_PERIODIC_HASTE 0 spells in 4.3.4 &Aura::HandleModIncreaseSpellPowerPct, //317 SPELL_AURA_MOD_INCREASE_SPELL_POWER_PCT 13 spells in 4.3.4, implemented in Unit::SpellBaseDamageBonusDone and Unit::SpellBaseHealingBonusDone @@ -1178,16 +1177,23 @@ void Aura::TriggerSpell() // // Polymorphic Ray // case 6965: break; case 9712: // Thaumaturgy Channel - trigger_spell_id = 21029; - break; + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, 21029, true); + return; // // Egan's Blaster // case 17368: break; // // Haunted // case 18347: break; // // Ranshalla Waiting -// case 18953: break; -// // Inferno -// case 19695: break; +// case 18953: break; + + case 19695: // Inferno + { + int32 damageForTick[8] = { 500, 500, 1000, 1000, 2000, 2000, 3000, 5000 }; + triggerTarget->CastCustomSpell(triggerTarget, 19698, &damageForTick[GetAuraTicks() - 1], nullptr, nullptr, true, nullptr); + return; + } + // // Frostwolf Muzzle DND // case 21794: break; // // Alterac Ram Collar DND @@ -1719,10 +1725,23 @@ void Aura::TriggerSpell() // case 41629: break; // // Alert Drums // case 42177: break; -// // Spout -// case 42581: break; -// // Spout -// case 42582: break; + case 42581: // Spout (left) + case 42582: // Spout (right) + { + float newAngle = target->GetOrientation(); + + if (auraId == 42581) + newAngle += 2 * M_PI_F / 100; + else + newAngle -= 2 * M_PI_F / 100; + + newAngle = NormalizeOrientation(newAngle); + + target->SetFacingTo(newAngle); + + target->CastSpell(target, auraSpellInfo->CalculateSimpleValue(m_effIndex), true); + return; + } // // Return to the Spirit Realm // case 44035: break; // // Curse of Boundless Agony @@ -2224,7 +2243,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { // spells required only Real aura add/remove if (!Real) - { return; } + return; Unit* target = GetTarget(); @@ -2256,7 +2275,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (Unit* caster = GetCaster()) { if (caster->GetTypeId() != TYPEID_UNIT) - { return; } + return; caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); caster->addUnitState(UNIT_STAT_ROOT); @@ -2266,7 +2285,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 13139: // net-o-matic // root to self part of (root_target->charge->root_self sequence if (Unit* caster = GetCaster()) - { caster->CastSpell(caster, 13138, true, NULL, this); } + caster->CastSpell(caster, 13138, true, nullptr, this); return; case 28832: // Mark of Korth'azz case 28833: // Mark of Blaumeux @@ -2289,7 +2308,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } if (Unit* caster = GetCaster()) - { caster->CastCustomSpell(target, 28836, &damage, NULL, NULL, true, NULL, this); } + caster->CastCustomSpell(target, 28836, &damage, nullptr, nullptr, true, nullptr, this); return; } case 31606: // Stormcrow Amulet @@ -2319,7 +2338,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } case 36587: // Vision Guide { - target->CastSpell(target, 36573, true, NULL, this); + target->CastSpell(target, 36573, true, nullptr, this); return; } // Gender spells @@ -2336,12 +2355,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 46354: spellId = (gender == GENDER_MALE ? 46355 : 46356); break; default: return; } - target->CastSpell(target, spellId, true, NULL, this); + target->CastSpell(target, spellId, true, nullptr, this); return; } case 39850: // Rocket Blast if (roll_chance_i(20)) // backfire stun - target->CastSpell(target, 51581, true, NULL, this); + target->CastSpell(target, 51581, true, nullptr, this); return; case 43873: // Headless Horseman Laugh target->PlayDistanceSound(11965); @@ -2354,21 +2373,30 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; } + case 46637: // Break Ice + target->CastSpell(target, 46638, true, nullptr, this); + return; case 46699: // Requires No Ammo if (target->GetTypeId() == TYPEID_PLAYER) // not use ammo and not allow use ((Player*)target)->RemoveAmmo(); return; case 47190: // Toalu'u's Spiritual Incense - target->CastSpell(target, 47189, true, NULL, this); + target->CastSpell(target, 47189, true, nullptr, this); // allow script to process further (text) break; + case 47563: // Freezing Cloud + target->CastSpell(target, 47574, true, nullptr, this); + return; + case 47593: // Freezing Cloud + target->CastSpell(target, 47594, true, nullptr, this); + return; case 48025: // Headless Horseman's Mount Spell::SelectMountByAreaAndSkill(target, GetSpellProto(), 51621, 48024, 51617, 48023, 0); return; case 48143: // Forgotten Aura // See Death's Door - target->CastSpell(target, 48814, true, NULL, this); + target->CastSpell(target, 48814, true, nullptr, this); return; case 51405: // Digging for Treasure target->HandleEmote(EMOTE_STATE_WORK); @@ -2378,7 +2406,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 54729: // Winged Steed of the Ebon Blade Spell::SelectMountByAreaAndSkill(target, GetSpellProto(), 0, 0, 54726, 54727, 0); return; - case 58600: // Restricted Flight Area + case 58600: // Restricted Flight Area { if (!target || target->GetTypeId() != TYPEID_PLAYER) return; @@ -2389,17 +2417,20 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 61187: // Twilight Shift (single target) case 61190: // Twilight Shift (many targets) target->RemoveAurasDueToSpell(57620); - target->CastSpell(target, 61885, true, NULL, this); + target->CastSpell(target, 61885, true, nullptr, this); return; case 62061: // Festive Holiday Mount if (target->HasAuraType(SPELL_AURA_MOUNTED)) // Reindeer Transformation - target->CastSpell(target, 25860, true, NULL, this); + target->CastSpell(target, 25860, true, nullptr, this); return; case 62109: // Tails Up: Aura target->setFaction(1990); // Ambient (hostile) target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); return; + case 63122: // Clear Insane + target->RemoveAurasDueToSpell(GetSpellProto()->CalculateSimpleValue(m_effIndex)); + return; case 63624: // Learn a Second Talent Specialization // Teach Learn Talent Specialization Switches, required for client triggered casts, allow after 30 sec delay if (target->GetTypeId() == TYPEID_PLAYER) @@ -2410,6 +2441,16 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (target->GetTypeId() == TYPEID_PLAYER) ((Player*)target)->removeSpell(63680); return; + case 64132: // Constrictor Tentacle + if (target->GetTypeId() == TYPEID_PLAYER) + target->CastSpell(target, 64133, true, nullptr, this); + return; + case 65684: // Dark Essence + target->RemoveAurasDueToSpell(65686); + return; + case 65686: // Light Essence + target->RemoveAurasDueToSpell(65684); + return; case 68912: // Wailing Souls if (Unit* caster = GetCaster()) { @@ -2421,17 +2462,17 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; case 70623: // Jaina's Call if (target->GetTypeId() == TYPEID_PLAYER) - target->CastSpell(target, 70525, true, NULL, this); + target->CastSpell(target, 70525, true, nullptr, this); return; case 70638: // Call of Sylvanas if (target->GetTypeId() == TYPEID_PLAYER) - target->CastSpell(target, 70639, true, NULL, this); + target->CastSpell(target, 70639, true, nullptr, this); return; case 71342: // Big Love Rocket Spell::SelectMountByAreaAndSkill(target, GetSpellProto(), 71344, 71345, 71346, 71347, 0); return; case 71563: // Deadly Precision - target->CastSpell(target, 71564, true, NULL, this); + target->CastSpell(target, 71564, true, nullptr, this); return; case 72286: // Invincible Spell::SelectMountByAreaAndSkill(target, GetSpellProto(), 72281, 72282, 72283, 72284, 0); @@ -2458,10 +2499,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // Stance Cooldown - target->CastSpell(target, 41102, true, NULL, this); + target->CastSpell(target, 41102, true, nullptr, this); // Battle Aura - target->CastSpell(target, 41106, true, NULL, this); + target->CastSpell(target, 41106, true, nullptr, this); // equipment ((Creature*)target)->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, 32614); @@ -2475,10 +2516,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // Stance Cooldown - target->CastSpell(target, 41102, true, NULL, this); + target->CastSpell(target, 41102, true, nullptr, this); // Berserker Aura - target->CastSpell(target, 41107, true, NULL, this); + target->CastSpell(target, 41107, true, nullptr, this); // equipment ((Creature*)target)->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, 32614); @@ -2492,10 +2533,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // Stance Cooldown - target->CastSpell(target, 41102, true, NULL, this); + target->CastSpell(target, 41102, true, nullptr, this); // Defensive Aura - target->CastSpell(target, 41105, true, NULL, this); + target->CastSpell(target, 41105, true, nullptr, this); // equipment ((Creature*)target)->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, 32604); @@ -2509,10 +2550,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // Stance Cooldown - target->CastSpell(target, 59526, true, NULL, this); + target->CastSpell(target, 59526, true, nullptr, this); // Defensive Aura - target->CastSpell(target, 41105, true, NULL, this); + target->CastSpell(target, 41105, true, nullptr, this); // equipment ((Creature*)target)->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, 43625); @@ -2526,10 +2567,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // Stance Cooldown - target->CastSpell(target, 59526, true, NULL, this); + target->CastSpell(target, 59526, true, nullptr, this); // Berserker Aura - target->CastSpell(target, 41107, true, NULL, this); + target->CastSpell(target, 41107, true, nullptr, this); // equipment ((Creature*)target)->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, 43625); @@ -2543,10 +2584,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // Stance Cooldown - target->CastSpell(target, 59526, true, NULL, this); + target->CastSpell(target, 59526, true, nullptr, this); // Battle Aura - target->CastSpell(target, 41106, true, NULL, this); + target->CastSpell(target, 41106, true, nullptr, this); // equipment ((Creature*)target)->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, 43623); @@ -2576,10 +2617,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real) switch ((*itr)->GetSpellProto()->Id) { case 46859: // Unrelenting Assault, rank 1 - target->CastSpell(target, 64849, true, NULL, (*itr)); + target->CastSpell(target, 64849, true, nullptr, (*itr)); break; case 46860: // Unrelenting Assault, rank 2 - target->CastSpell(target, 64850, true, NULL, (*itr)); + target->CastSpell(target, 64850, true, nullptr, (*itr)); break; default: break; @@ -2598,7 +2639,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) switch (GetId()) { case 34026: // Kill Command - target->CastSpell(target, 34027, true, NULL, this); + target->CastSpell(target, 34027, true, nullptr, this); return; } break; @@ -2608,7 +2649,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) switch (GetId()) { case 55198: // Tidal Force - target->CastSpell(target, 55166, true, NULL, this); + target->CastSpell(target, 55166, true, nullptr, this); return; } @@ -2637,7 +2678,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { Unit* caster = GetCaster(); if (!caster || !caster->IsAlive()) - { return; } + return; uint32 finalSpellId = 0; switch (GetId()) @@ -2663,7 +2704,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } if (finalSpellId) - { caster->CastSpell(target, finalSpellId, true, NULL, this); } + caster->CastSpell(target, finalSpellId, true, nullptr, this); return; } @@ -2675,7 +2716,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (Unit* caster = GetCaster()) { if (caster->GetTypeId() != TYPEID_UNIT) - { return; } + return; // see dummy effect of spell 10254 for removal of flags etc caster->CastSpell(caster, 10254, true); @@ -2683,52 +2724,52 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; } case 12479: // Hex of Jammal'an - target->CastSpell(target, 12480, true, NULL, this); + target->CastSpell(target, 12480, true, nullptr, this); return; case 12774: // (DND) Belnistrasz Idol Shutdown Visual { if (m_removeMode == AURA_REMOVE_BY_DEATH) - { return; } + return; // Idom Rool Camera Shake <- wtf, don't drink while making spellnames? if (Unit* caster = GetCaster()) - { caster->CastSpell(caster, 12816, true); } + caster->CastSpell(caster, 12816, true); return; } case 28169: // Mutating Injection { // Mutagen Explosion - target->CastSpell(target, 28206, true, NULL, this); + target->CastSpell(target, 28206, true, nullptr, this); // Poison Cloud - target->CastSpell(target, 28240, true, NULL, this); + target->CastSpell(target, 28240, true, nullptr, this); return; } case 32045: // Soul Charge { if (m_removeMode == AURA_REMOVE_BY_EXPIRE) - target->CastSpell(target, 32054, true, NULL, this); + target->CastSpell(target, 32054, true, nullptr, this); return; } case 32051: // Soul Charge { if (m_removeMode == AURA_REMOVE_BY_EXPIRE) - target->CastSpell(target, 32057, true, NULL, this); + target->CastSpell(target, 32057, true, nullptr, this); return; } case 32052: // Soul Charge { if (m_removeMode == AURA_REMOVE_BY_EXPIRE) - target->CastSpell(target, 32053, true, NULL, this); + target->CastSpell(target, 32053, true, nullptr, this); return; } case 32286: // Focus Target Visual { if (m_removeMode == AURA_REMOVE_BY_EXPIRE) - target->CastSpell(target, 32301, true, NULL, this); + target->CastSpell(target, 32301, true, nullptr, this); return; } @@ -2741,7 +2782,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } case 36730: // Flame Strike { - target->CastSpell(target, 36731, true, NULL, this); + target->CastSpell(target, 36731, true, nullptr, this); return; } case 41099: // Battle Stance @@ -2813,7 +2854,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { uint32 spellId = target->GetMap()->IsRegularDifficulty() ? 44190 : 46163; - target->CastSpell(target, spellId, true, NULL, this); + target->CastSpell(target, spellId, true, nullptr, this); } return; } @@ -2821,7 +2862,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { // Kill target if dispelled if (m_removeMode == AURA_REMOVE_BY_DISPEL) - target->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + target->DealDamage(target, target->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); return; } case 45963: // Call Alliance Deserter @@ -2833,12 +2874,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 46308: // Burning Winds { // casted only at creatures at spawn - target->CastSpell(target, 47287, true, NULL, this); + target->CastSpell(target, 47287, true, nullptr, this); return; } case 46637: // Break Ice { - target->CastSpell(target, 46638, true); + target->CastSpell(target, 47030, true, nullptr, this); return; } case 48385: // Create Spirit Fount Beam @@ -2850,7 +2891,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { // Blood Oath if (m_removeMode == AURA_REMOVE_BY_EXPIRE) - target->CastSpell(target, 50001, true, NULL, this); + target->CastSpell(target, 50001, true, nullptr, this); return; } @@ -2878,7 +2919,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (Unit* pCaster = GetCaster()) { if (m_removeMode == AURA_REMOVE_BY_EXPIRE) - pCaster->CastSpell(target, 51872, true, NULL, this); + pCaster->CastSpell(target, 51872, true, nullptr, this); } return; @@ -2886,7 +2927,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 52098: // Charge Up { if (m_removeMode == AURA_REMOVE_BY_EXPIRE) - target->CastSpell(target, 52092, true, NULL, this); + target->CastSpell(target, 52092, true, nullptr, this); return; } @@ -2924,14 +2965,14 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } case 58600: // Restricted Flight Area { - /*AreaTableEntry const* area = GetAreaEntryByAreaID(target->GetAreaId()); + //AreaTableEntry const* area = GetAreaEntryByAreaID(target->GetAreaId()); - // Dalaran restricted flight zone (recheck before apply unmount) - if (area && target->GetTypeId() == TYPEID_PLAYER && (area->flags & AREA_FLAG_CANNOT_FLY) && - ((Player*)target)->IsFreeFlying() && !((Player*)target)->isGameMaster()) - { - target->CastSpell(target, 58601, true); // Remove Flight Auras (also triggered Parachute (45472)) - }*/ + //// Dalaran restricted flight zone (recheck before apply unmount) + //if (area && target->GetTypeId() == TYPEID_PLAYER && (area->flags & AREA_FLAG_CANNOT_FLY) && + // ((Player*)target)->IsFreeFlying() && !((Player*)target)->isGameMaster()) + //{ + // target->CastSpell(target, 58601, true); // Remove Flight Auras (also triggered Parachute (45472)) + //} return; } case 61900: // Electrical Charge @@ -2941,26 +2982,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; } - case 62483: // Stonebark's Essence Channel - case 62484: // Ironbranch's Essence Channel - case 62485: // Brightleaf's Essence Channel - case 65587: // Brightleaf's Essence Channel (h) - case 65588: // Ironbranch's Essence Channel (h) - case 65589: // Stonebark's Essence Channel (h) - { - if (Unit* caster = GetCaster()) - { - if (m_removeMode == AURA_REMOVE_BY_EXPIRE) - caster->CastSpell(caster, 62467, true); - } - return; - } case 68839: // Corrupt Soul { // Knockdown Stun - target->CastSpell(target, 68848, true, NULL, this); + target->CastSpell(target, 68848, true, nullptr, this); // Draw Corrupted Soul - target->CastSpell(target, 68846, true, NULL, this); + target->CastSpell(target, 68846, true, nullptr, this); return; } } @@ -2969,7 +2996,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (classOptions && classOptions->SpellFamilyName == SPELLFAMILY_MAGE && (classOptions->SpellFamilyFlags & UI64LIT(0x2000000000000))) { if (m_removeMode == AURA_REMOVE_BY_EXPIRE || m_removeMode == AURA_REMOVE_BY_DISPEL) - target->CastSpell(target, m_modifier.m_amount, true, NULL, this); + target->CastSpell(target, m_modifier.m_amount, true, nullptr, this); return; } @@ -3006,12 +3033,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { Unit* caster = GetCaster(); if (!caster) - { return; } + return; - caster->CastSpell(target, 24659, true, NULL, NULL, GetCasterGuid()); + caster->CastSpell(target, 24659, true, nullptr, nullptr, GetCasterGuid()); } else - { target->RemoveAurasDueToSpell(24659); } + target->RemoveAurasDueToSpell(24659); return; } case 24661: // Restless Strength @@ -3020,12 +3047,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { Unit* caster = GetCaster(); if (!caster) - { return; } + return; - caster->CastSpell(target, 24662, true, NULL, NULL, GetCasterGuid()); + caster->CastSpell(target, 24662, true, nullptr, nullptr, GetCasterGuid()); } else - { target->RemoveAurasDueToSpell(24662); } + target->RemoveAurasDueToSpell(24662); return; } case 29266: // Permanent Feign Death @@ -3050,7 +3077,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) // Some appear to be used depending on creature location, in water, at solid ground, in air/suspended, etc // For now, just handle all the same way if (target->GetTypeId() == TYPEID_UNIT) - { target->SetFeignDeath(apply); } + target->SetFeignDeath(apply); return; } @@ -3148,7 +3175,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (apply) caster->FixateTarget(target); else if (target->GetObjectGuid() == caster->GetFixateTargetGuid()) - caster->FixateTarget(NULL); + caster->FixateTarget(nullptr); return; } @@ -3161,6 +3188,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) target->SetFeared(apply, GetCasterGuid(), GetId()); return; case 56422: // Nerubian Submerge + case 70733: // Stoneform // not known if there are other things todo, only flag are confirmed valid target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE, apply); return; @@ -3189,9 +3217,16 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 27978: case 40131: if (apply) - { target->m_AuraFlags |= UNIT_AURAFLAG_ALIVE_INVISIBLE; } + target->m_AuraFlags |= UNIT_AURAFLAG_ALIVE_INVISIBLE; else - { target->m_AuraFlags &= ~UNIT_AURAFLAG_ALIVE_INVISIBLE; } + target->m_AuraFlags &= ~UNIT_AURAFLAG_ALIVE_INVISIBLE; + return; + case 66936: // Submerge + case 66948: // Submerge + if (apply) + target->CastSpell(target, 66969, true); + else + target->RemoveAurasDueToSpell(66969); return; } break; @@ -3211,7 +3246,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) int32 bp0 = m_modifier.m_amount; if (Unit* caster = GetCaster()) - target->CastCustomSpell(caster, 48210, &bp0, NULL, NULL, true, NULL, this); + target->CastCustomSpell(caster, 48210, &bp0, nullptr, nullptr, true, nullptr, this); } } break; @@ -3241,7 +3276,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; int32 bp0 = int32(target->GetMaxHealth() * m_modifier.m_amount / 100); - target->CastCustomSpell(target, 50322, &bp0, NULL, NULL, true); + target->CastCustomSpell(target, 50322, &bp0, nullptr, nullptr, true); } else target->RemoveAurasDueToSpell(50322); @@ -3274,12 +3309,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (target->IsInWorld() && GetStackAmount() > 0) { int32 amount = m_modifier.m_amount; - target->CastCustomSpell(target, 33778, &amount, NULL, NULL, true, NULL, this, GetCasterGuid()); + target->CastCustomSpell(target, 33778, &amount, nullptr, nullptr, true, nullptr, this, GetCasterGuid()); if (Unit* caster = GetCaster()) { int32 returnmana = (GetSpellProto()->GetManaCostPercentage() * caster->GetCreateMana() / 100) * GetStackAmount() / 2; - caster->CastCustomSpell(caster, 64372, &returnmana, NULL, NULL, true, NULL, this, GetCasterGuid()); + caster->CastCustomSpell(caster, 64372, &returnmana, nullptr, nullptr, true, nullptr, this, GetCasterGuid()); } } } @@ -3363,7 +3398,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 25899: // Greater Blessing of Sanctuary { if (apply) - target->CastSpell(target, 67480, true, NULL, this); + target->CastSpell(target, 67480, true, nullptr, this); else target->RemoveAurasDueToSpell(67480); return; @@ -3377,14 +3412,14 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 6495: // Sentry Totem { if (target->GetTypeId() != TYPEID_PLAYER) - { return; } + return; Totem* totem = target->GetTotem(TOTEM_SLOT_AIR); if (totem && apply) - { ((Player*)target)->GetCamera().SetView(totem); } + ((Player*)target)->GetCamera().SetView(totem); else - { ((Player*)target)->GetCamera().ResetView(); } + ((Player*)target)->GetCamera().ResetView(); return; } @@ -3397,9 +3432,9 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (PetAura const* petSpell = sSpellMgr.GetPetAura(GetId(), m_effIndex)) { if (apply) - { target->AddPetAura(petSpell); } + target->AddPetAura(petSpell); else - { target->RemovePetAura(petSpell); } + target->RemovePetAura(petSpell); return; } @@ -3412,13 +3447,13 @@ void Aura::HandleAuraDummy(bool apply, bool Real) target->GetZoneAndAreaId(zone, area); for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - { itr->second->ApplyOrRemoveSpellIfCan((Player*)target, zone, area, false); } + itr->second->ApplyOrRemoveSpellIfCan((Player*)target, zone, area, false); } } // script has to "handle with care", only use where data are not ok to use in the above code. if (target->GetTypeId() == TYPEID_UNIT) - { sScriptMgr.OnAuraDummy(this, apply); } + sScriptMgr.OnAuraDummy(this, apply); } void Aura::HandleAuraMounted(bool apply, bool Real) @@ -3559,7 +3594,7 @@ void Aura::HandleWaterBreathing(bool /*apply*/, bool /*Real*/) void Aura::HandleAuraModShapeshift(bool apply, bool Real) { if (!Real) - { return; } + return; ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue); @@ -3571,9 +3606,11 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) } uint32 modelid = 0; - Powers PowerType = POWER_MANA; Unit* target = GetTarget(); + // remove SPELL_AURA_EMPATHY + target->RemoveSpellsCausingAura(SPELL_AURA_EMPATHY); + if (ssEntry->modelID_A) { // i will asume that creatures will always take the defined model from the dbc @@ -3646,6 +3683,8 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) if (apply) { + Powers PowerType = POWER_MANA; + // remove other shapeshift before applying a new one target->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT, GetHolder()); @@ -3672,7 +3711,7 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) { // reset power to default values only at power change if (target->GetPowerType() != PowerType) - { target->SetPowerType(PowerType); } + target->SetPowerType(PowerType); switch (form) { @@ -3698,14 +3737,14 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) if ((int32)target->GetPower(POWER_ENERGY) > furorChance) { target->SetPower(POWER_ENERGY, 0); - target->CastCustomSpell(target, 17099, &furorChance, NULL, NULL, true, NULL, this); + target->CastCustomSpell(target, 17099, &furorChance, nullptr, nullptr, true, nullptr, this); } } else if (furorChance) // only if talent known { target->SetPower(POWER_RAGE, 0); if (irand(1, 100) <= furorChance) - target->CastSpell(target, 17057, true, NULL, this); + target->CastSpell(target, 17057, true, nullptr, this); } break; } @@ -3728,7 +3767,7 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) } if (target->GetPower(POWER_RAGE) > Rage_val) - { target->SetPower(POWER_RAGE, Rage_val); } + target->SetPower(POWER_RAGE, Rage_val); break; } default: @@ -3751,22 +3790,22 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) target->SetDisplayId(target->GetNativeDisplayId()); if (target->getClass() == CLASS_DRUID) - { target->SetPowerType(POWER_MANA); } + target->SetPowerType(POWER_MANA); target->SetShapeshiftForm(FORM_NONE); switch (form) { - // Nordrassil Harness - bonus + // Nordrassil Harness - bonus case FORM_BEAR: case FORM_CAT: if (Aura* dummy = target->GetDummyAura(37315)) - target->CastSpell(target, 37316, true, NULL, dummy); + target->CastSpell(target, 37316, true, nullptr, dummy); break; - // Nordrassil Regalia - bonus + // Nordrassil Regalia - bonus case FORM_MOONKIN: if (Aura* dummy = target->GetDummyAura(37324)) - target->CastSpell(target, 37325, true, NULL, dummy); + target->CastSpell(target, 37325, true, nullptr, dummy); break; default: break; @@ -3784,7 +3823,7 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) HandleShapeshiftBoosts(apply); if (target->GetTypeId() == TYPEID_PLAYER) - { ((Player*)target)->InitDataForForm(); } + ((Player*)target)->InitDataForForm(); // update form-dependent armor specializations if (target->GetTypeId() == TYPEID_PLAYER && ((Player*)target)->getClass() == CLASS_DRUID) @@ -7618,6 +7657,10 @@ void Aura::PeriodicTick() if (!pCaster) return; + // Don't heal target if it is already at max health + if (target->GetHealth() == target->GetMaxHealth()) + return; + // heal for caster damage (must be alive) if (target != pCaster && spellProto->SpellVisual[0] == 163 && !pCaster->IsAlive()) { return; } @@ -7998,14 +8041,14 @@ void Aura::PeriodicDummyTick() SpellEntry const* spell = GetSpellProto(); SpellClassOptionsEntry const* classOptions = spell->GetSpellClassOptions(); - Unit* target = GetTarget(); + Unit *target = GetTarget(); switch (spell->GetSpellFamilyName()) { case SPELLFAMILY_GENERIC: { switch (spell->Id) { - // Forsaken Skills + // Forsaken Skills case 7054: { // Possibly need cast one of them (but @@ -8028,7 +8071,7 @@ void Aura::PeriodicDummyTick() } case 7057: // Haunting Spirits if (roll_chance_i(33)) - target->CastSpell(target, m_modifier.m_amount, true, NULL, this); + target->CastSpell(target, m_modifier.m_amount, true, nullptr, this); return; // // Panda // case 19230: break; @@ -8042,6 +8085,7 @@ void Aura::PeriodicDummyTick() { target->CastSpell(target, 30529, true); target->RemoveAurasDueToSpell(30019); + target->RemoveAurasDueToSpell(30532); } return; } @@ -8105,7 +8149,7 @@ void Aura::PeriodicDummyTick() break; } } - break; + return; } // // Headless Horseman - Conflagrate, Periodic Aura // case 42637: break; @@ -8113,8 +8157,9 @@ void Aura::PeriodicDummyTick() // case 42774: break; // // Headless Horseman Climax - Summoning Rhyme Aura // case 42879: break; -// // Tricky Treat -// case 42919: break; + case 42919: // Tricky Treat + target->CastSpell(target, 42966, true); + return; // // Giddyup! // case 42924: break; // // Ram - Trot @@ -8170,17 +8215,17 @@ void Aura::PeriodicDummyTick() // // Darkness // case 45996: break; case 46041: // Summon Blood Elves Periodic - target->CastSpell(target, 46037, true, NULL, this); - target->CastSpell(target, roll_chance_i(50) ? 46038 : 46039, true, NULL, this); - target->CastSpell(target, 46040, true, NULL, this); + target->CastSpell(target, 46037, true, nullptr, this); + target->CastSpell(target, roll_chance_i(50) ? 46038 : 46039, true, nullptr, this); + target->CastSpell(target, 46040, true, nullptr, this); return; // // Transform Visual Missile Periodic // case 46205: break; // // Find Opening Beam End // case 46333: break; case 46371: // Ice Spear Control Aura - target->CastSpell(target, 46372, true, NULL, this); - return; + target->CastSpell(target, 46372, true, nullptr, this); + return; // // Hailstone Chill // case 46458: break; // // Hailstone Chill, Internal @@ -8206,12 +8251,12 @@ void Aura::PeriodicDummyTick() { bool chance = roll_chance_i(50); - target->CastSpell(target, chance ? 48631 : 48632, true, NULL, this); + target->CastSpell(target, chance ? 48631 : 48632, true, nullptr, this); if (GetAuraTicks() % 2) // which doctor at odd tick - target->CastSpell(target, chance ? 48636 : 48635, true, NULL, this); + target->CastSpell(target, chance ? 48636 : 48635, true, nullptr, this); else // or harponeer, at even tick - target->CastSpell(target, chance ? 48634 : 48633, true, NULL, this); + target->CastSpell(target, chance ? 48634 : 48633, true, nullptr, this); return; } @@ -8240,18 +8285,18 @@ void Aura::PeriodicDummyTick() // case 50530: break; case 50789: // Summon iron dwarf (left or right) case 59860: - target->CastSpell(target, roll_chance_i(50) ? 50790 : 50791, true, NULL, this); + target->CastSpell(target, roll_chance_i(50) ? 50790 : 50791, true, nullptr, this); return; case 50792: // Summon iron trogg (left or right) case 59859: - target->CastSpell(target, roll_chance_i(50) ? 50793 : 50794, true, NULL, this); + target->CastSpell(target, roll_chance_i(50) ? 50793 : 50794, true, nullptr, this); return; case 50801: // Summon malformed ooze (left or right) case 59858: - target->CastSpell(target, roll_chance_i(50) ? 50802 : 50803, true, NULL, this); + target->CastSpell(target, roll_chance_i(50) ? 50802 : 50803, true, nullptr, this); return; case 50824: // Summon earthen dwarf - target->CastSpell(target, roll_chance_i(50) ? 50825 : 50826, true, NULL, this); + target->CastSpell(target, roll_chance_i(50) ? 50825 : 50826, true, nullptr, this); return; case 52441: // Cool Down target->CastSpell(target, 52443, true); @@ -8270,17 +8315,17 @@ void Aura::PeriodicDummyTick() // Cast different spell depending on trigger position // This will summon a different npc entry on each location - each of those has individual movement patern if (target->GetPositionZ() < 750.0f) - target->CastSpell(target, summonSpells[spell->Id - 53035][0], true, NULL, this); + target->CastSpell(target, summonSpells[spell->Id - 53035][0], true, nullptr, this); else if (target->GetPositionX() > 500.0f) - target->CastSpell(target, summonSpells[spell->Id - 53035][1], true, NULL, this); + target->CastSpell(target, summonSpells[spell->Id - 53035][1], true, nullptr, this); else - target->CastSpell(target, summonSpells[spell->Id - 53035][2], true, NULL, this); + target->CastSpell(target, summonSpells[spell->Id - 53035][2], true, nullptr, this); return; } case 53520: // Carrion Beetles - target->CastSpell(target, 53521, true, NULL, this); - target->CastSpell(target, 53521, true, NULL, this); + target->CastSpell(target, 53521, true, nullptr, this); + target->CastSpell(target, 53521, true, nullptr, this); return; case 55592: // Clean switch (urand(0, 2)) @@ -8293,18 +8338,18 @@ void Aura::PeriodicDummyTick() case 61968: // Flash Freeze { if (GetAuraTicks() == 1 && !target->HasAura(62464)) - target->CastSpell(target, 61970, true, NULL, this); + target->CastSpell(target, 61970, true, nullptr, this); return; } case 62018: // Collapse { // lose 1% of health every second - target->DealDamage(target, target->GetMaxHealth() * .01, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + target->DealDamage(target, target->GetMaxHealth() * .01, nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, nullptr, false); return; } case 62019: // Rune of Summoning { - target->CastSpell(target, 62020, true, NULL, this); + target->CastSpell(target, 62020, true, nullptr, this); return; } case 62038: // Biting Cold @@ -8317,7 +8362,7 @@ void Aura::PeriodicDummyTick() target->RemoveAuraHolderFromStack(62039); // otherwise add one aura stack each 3 seconds else if (GetAuraTicks() % 3 && !target->HasAura(62821)) - target->CastSpell(target, 62039, true, NULL, this); + target->CastSpell(target, 62039, true, nullptr, this); return; } case 62039: // Biting Cold @@ -8335,11 +8380,19 @@ void Aura::PeriodicDummyTick() } case 62717: // Slag Pot { - target->CastSpell(target, target->GetMap()->IsRegularDifficulty() ? 65722 : 65723, true, NULL, this); + target->CastSpell(target, target->GetMap()->IsRegularDifficulty() ? 65722 : 65723, true, nullptr, this); // cast Slag Imbued if the target survives up to the last tick if (GetAuraTicks() == 10) - target->CastSpell(target, 63536, true, NULL, this); + target->CastSpell(target, 63536, true, nullptr, this); + return; + } + case 63050: // Sanity + { + if (GetHolder()->GetStackAmount() <= 25 && !target->HasAura(63752)) + target->CastSpell(target, 63752, true); + else if (GetHolder()->GetStackAmount() > 25 && target->HasAura(63752)) + target->RemoveAurasDueToSpell(63752); return; } case 63382: // Rapid Burst @@ -8350,12 +8403,18 @@ void Aura::PeriodicDummyTick() target->CastSpell(target, target->GetMap()->IsRegularDifficulty() ? 63387 : 64531, true); return; } + case 64101: // Defend + { + target->CastSpell(target, 62719, true); + target->CastSpell(target, 64192, true); + return; + } case 64217: // Overcharged { if (GetHolder()->GetStackAmount() >= 10) { target->CastSpell(target, 64219, true); - target->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + target->DealDamage(target, target->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); } return; } @@ -8375,13 +8434,13 @@ void Aura::PeriodicDummyTick() if (uiAuraId && !target->HasAura(uiAuraId)) { - target->CastSpell(target, uiAuraId, true, NULL, this); + target->CastSpell(target, uiAuraId, true, nullptr, this); // remove original aura if phased if (uiAuraId == 64417) { target->RemoveAurasDueToSpell(64412); - target->CastSpell(target, 62169, true, NULL, this); + target->CastSpell(target, 62169, true, nullptr, this); } } } @@ -8389,7 +8448,7 @@ void Aura::PeriodicDummyTick() } case 65272: // Shatter Chest { - target->CastSpell(target, 62501, true, NULL, this); + target->CastSpell(target, 62501, true, nullptr, this); return; } case 66118: // Leeching Swarm @@ -8407,13 +8466,23 @@ void Aura::PeriodicDummyTick() lifeLeeched = 250; // Leeching swarm damage - caster->CastCustomSpell(target, 66240, &lifeLeeched, NULL, NULL, true, NULL, this); + caster->CastCustomSpell(target, 66240, &lifeLeeched, nullptr, nullptr, true, nullptr, this); // Leeching swarm heal - target->CastCustomSpell(caster, 66125, &lifeLeeched, NULL, NULL, true, NULL, this); + target->CastCustomSpell(caster, 66125, &lifeLeeched, nullptr, nullptr, true, nullptr, this); return; } + case 66798: // Death's Respite + { + Unit* caster = GetCaster(); + if (!caster) + return; + + caster->CastSpell(target, 66797, true, nullptr, this); + target->RemoveAurasDueToSpell(GetId()); + return; + } case 68875: // Wailing Souls case 68876: // Wailing Souls { @@ -8432,7 +8501,7 @@ void Aura::PeriodicDummyTick() target->CastSpell(target, 68873, true); return; } - // Exist more after, need add later +// Exist more after, need add later default: break; } @@ -8442,14 +8511,14 @@ void Aura::PeriodicDummyTick() { if (target->GetTypeId() != TYPEID_PLAYER) return; - // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus - if (Aura* aura = GetHolder()->GetAuraByEffectIndex(SpellEffectIndex(GetEffIndex()-1))) + if (Aura* aura = GetHolder()->GetAuraByEffectIndex(SpellEffectIndex(GetEffIndex() - 1))) { aura->GetModifier()->m_amount = m_modifier.m_amount; ((Player*)target)->UpdateManaRegen(); // Disable continue m_isPeriodic = false; + return; } return; } @@ -8473,16 +8542,26 @@ void Aura::PeriodicDummyTick() } case SPELLFAMILY_MAGE: { - // Mirror Image -// if (spell->Id == 55342) -// return; + switch (spell->Id) + { + case 55342: // Mirror Image + { + if (GetAuraTicks() != 1) + return; + if (Unit* pCaster = GetCaster()) + pCaster->CastSpell(pCaster, GetSpellProto()->CalculateSimpleValue(m_effIndex), true, nullptr, this); + return; + } + default: + break; + } break; } case SPELLFAMILY_DRUID: { switch (spell->Id) { - // Frenzied Regeneration + // Frenzied Regeneration case 22842: { // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health. @@ -8496,7 +8575,7 @@ void Aura::PeriodicDummyTick() int32 mod = (rage < 100) ? rage : 100; int32 points = target->CalculateSpellDamage(target, spell, EFFECT_INDEX_1); int32 regen = target->GetMaxHealth() * (mod * points / 10) / 1000; - target->CastCustomSpell(target, 22845, ®en, NULL, NULL, true, NULL, this); + target->CastCustomSpell(target, 22845, ®en, nullptr, nullptr, true, nullptr, this); target->SetPower(POWER_RAGE, rage - mod); return; } @@ -8512,7 +8591,7 @@ void Aura::PeriodicDummyTick() { switch (spell->Id) { - // Killing Spree + // Killing Spree case 51690: { if (target->hasUnitState(UNIT_STAT_STUNNED) || target->isFeared()) @@ -8554,16 +8633,16 @@ void Aura::PeriodicDummyTick() } switch (spell->Id) { - // Harpooner's Mark - // case 40084: - // return; - // Feeding Frenzy Rank 1 & 2 + // Harpooner's Mark + // case 40084: + // return; + // Feeding Frenzy Rank 1 & 2 case 53511: case 53512: { Unit* victim = target->getVictim(); if (victim && victim->GetHealth() * 100 < victim->GetMaxHealth() * 35) - target->CastSpell(target, spell->Id == 53511 ? 60096 : 60097, true, NULL, this); + target->CastSpell(target, spell->Id == 53511 ? 60096 : 60097, true, nullptr, this); return; } default: @@ -8589,7 +8668,7 @@ void Aura::PeriodicDummyTick() if (classOptions && classOptions->SpellFamilyFlags & UI64LIT(0x0000000000000020)) { if (Unit* caster = GetCaster()) - caster->CastCustomSpell(target, 52212, &m_modifier.m_amount, NULL, NULL, true, NULL, this); + caster->CastCustomSpell(target, 52212, &m_modifier.m_amount, nullptr, nullptr, true, nullptr, this); return; } // Raise Dead @@ -8622,7 +8701,7 @@ void Aura::PeriodicDummyTick() // Increases your attack power by $s1 for every $s2 armor value you have. // Calculate AP bonus (from 1 effect of this spell) int32 apBonus = m_modifier.m_amount * target->GetArmor() / target->CalculateSpellDamage(target, spell, EFFECT_INDEX_1); - target->CastCustomSpell(target, 61217, &apBonus, &apBonus, NULL, true, NULL, this); + target->CastCustomSpell(target, 61217, &apBonus, &apBonus, nullptr, true, nullptr, this); return; } // Reaping @@ -8636,7 +8715,7 @@ void Aura::PeriodicDummyTick() { // damage not expected to be show in logs, not any damage spell related to damage apply uint32 deal = m_modifier.m_amount * target->GetMaxHealth() / 100; - target->DealDamage(target, deal, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + target->DealDamage(target, deal, nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); return; } break; @@ -8648,7 +8727,7 @@ void Aura::PeriodicDummyTick() if (Unit* caster = GetCaster()) { if (target && target->GetTypeId() == TYPEID_UNIT) - { sScriptMgr.OnEffectDummy(caster, GetId(), GetEffIndex(), (Creature*)target, ObjectGuid()); } + sScriptMgr.OnEffectDummy(caster, GetId(), GetEffIndex(), (Creature*)target, ObjectGuid()); } } @@ -8840,6 +8919,29 @@ void Aura::HandleAuraMirrorImage(bool apply, bool Real) } } +void Aura::HandleMirrorName(bool apply, bool Real) +{ + if (!Real) + return; + + Unit* caster = GetCaster(); + Unit* target = GetTarget(); + + if (!target || !caster || target->GetTypeId() != TYPEID_UNIT) + return; + + if (apply) + target->SetName(caster->GetName()); + else + { + CreatureInfo const* cinfo = ((Creature*)target)->GetCreatureInfo(); + if (!cinfo) + return; + + target->SetName(cinfo->Name); + } +} + void Aura::HandleAuraConvertRune(bool apply, bool Real) { if (!Real) @@ -8888,43 +8990,19 @@ void Aura::HandlePhase(bool apply, bool Real) Unit* target = GetTarget(); // always non stackable - if (target->GetTypeId() == TYPEID_PLAYER) + if (apply) { - if (apply) - ((Player*)target)->GetPhaseMgr()->RegisterPhasingAuraEffect(this); - else - ((Player*)target)->GetPhaseMgr()->UnRegisterPhasingAuraEffect(this); - } - else - { - uint32 phaseMask = 0; - if (apply) - { - phaseMask = target->GetPhaseMask(); - if (target->GetAurasByType(SPELL_AURA_PHASE).size() == 1 && target->GetAurasByType(SPELL_AURA_PHASE_2).size() == 1) - phaseMask &= ~PHASEMASK_NORMAL; - - phaseMask |= GetMiscValue(); - } - else - { - Unit::AuraList const& phases = target->GetAurasByType(SPELL_AURA_PHASE); - for (Unit::AuraList::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) - phaseMask |= (*itr)->GetMiscValue(); - - Unit::AuraList const& phases2 = target->GetAurasByType(SPELL_AURA_PHASE_2); - for (Unit::AuraList::const_iterator itr = phases2.begin(); itr != phases2.end(); ++itr) - phaseMask |= (*itr)->GetMiscValue(); - } - - if (!phaseMask) - phaseMask = PHASEMASK_NORMAL; - - target->SetPhaseMask(phaseMask, true); + Unit::AuraList const& phases = target->GetAurasByType(SPELL_AURA_PHASE); + if (!phases.empty()) + target->RemoveAurasDueToSpell(phases.front()->GetId(), GetHolder()); + Unit::AuraList const& phases2 = target->GetAurasByType(SPELL_AURA_PHASE_2); + if (!phases2.empty()) + target->RemoveAurasDueToSpell(phases2.front()->GetId(), GetHolder()); } + target->SetPhaseMask(apply ? GetMiscValue() : uint32(PHASEMASK_NORMAL), true); // no-phase is also phase state so same code for apply and remove - if (GetEffIndex() == EFFECT_INDEX_0 && target->GetTypeId() == TYPEID_PLAYER) + if (target->GetTypeId() == TYPEID_PLAYER) { SpellAreaForAreaMapBounds saBounds = sSpellMgr.GetSpellAreaForAuraMapBounds(GetId()); if (saBounds.first != saBounds.second) @@ -8932,18 +9010,8 @@ void Aura::HandlePhase(bool apply, bool Real) uint32 zone, area; target->GetZoneAndAreaId(zone, area); - for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - { - // some auras remove at aura remove - if(!itr->second->IsFitToRequirements((Player*)target, zone, area)) - target->RemoveAurasDueToSpell(itr->second->spellId); - // some auras applied at aura apply - else if(itr->second->autocast) - { - if (!target->HasAura(itr->second->spellId, EFFECT_INDEX_0)) - target->CastSpell(target, itr->second->spellId, true); - } - } + for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + itr->second->ApplyOrRemoveSpellIfCan((Player*)target, zone, area, false); } } } @@ -9018,6 +9086,61 @@ void Aura::HandleAuraModBlockCritChance(bool apply, bool Real) ((Player*)GetTarget())->ApplyModUInt32Value(PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE, m_modifier.m_amount, apply); } +void Aura::HandlePreventResurrection(bool apply, bool Real) +{ + if (!Real) + return; + + Unit* target = GetTarget(); + if (!target || target->GetTypeId() != TYPEID_PLAYER) + return; + + if (apply) + target->RemoveByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER); + else if (!target->GetMap()->Instanceable()) + target->SetByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER); +} + +void Aura::HandleFactionOverride(bool apply, bool Real) +{ + if (!Real) + return; + + Unit* target = GetTarget(); + if (!target || !sFactionTemplateStore.LookupEntry(GetMiscValue())) + return; + + if (apply) + target->setFaction(GetMiscValue()); + else + target->RestoreOriginalFaction(); +} + + +void Aura::HandleTriggerLinkedAura(bool apply, bool Real) +{ + if (!Real) + return; + + uint32 linkedSpell = m_spellEffect->EffectTriggerSpell; + SpellEntry const* spellInfo = sSpellStore.LookupEntry(linkedSpell); + if (!spellInfo) + { + sLog.outError("Aura::HandleTriggerLinkedAura for spell %u effect %u triggering unknown spell id %u", GetSpellProto()->Id, m_effIndex, linkedSpell); + return; + } + + Unit* target = GetTarget(); + + if (apply) + { + // ToDo: handle various cases where base points need to be applied! + target->CastSpell(target, spellInfo, true, nullptr, this); + } + else + target->RemoveAurasByCasterSpell(linkedSpell, GetCasterGuid()); +} + bool Aura::IsLastAuraOnHolder() { for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i) @@ -9090,7 +9213,9 @@ SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit* target, Wor case 55166: // Tidal Force case 58914: // Kill Command (pet part) case 62519: // Attuned to Nature + case 63050: // Sanity case 64455: // Feral Essence + case 65294: // Empowered case 71564: // Deadly Precision case 74396: // Fingers of Frost m_stackAmount = m_spellProto->GetStackAmount(); diff --git a/src/game/WorldHandlers/SpellAuras.h b/src/game/WorldHandlers/SpellAuras.h index 4b959fafd..8195de6a1 100644 --- a/src/game/WorldHandlers/SpellAuras.h +++ b/src/game/WorldHandlers/SpellAuras.h @@ -414,6 +414,10 @@ class Aura void HandleAuraModBlockCritChance(bool apply, bool Real); void HandleModIncreaseSpellPowerPct(bool apply, bool Real); void HandleOverrideSpellPowerByAp(bool apply, bool Real); + void HandleMirrorName(bool apply, bool Real); + void HandlePreventResurrection(bool apply, bool Real); + void HandleFactionOverride(bool apply, bool Real); + void HandleTriggerLinkedAura(bool apply, bool Real); virtual ~Aura(); diff --git a/src/game/WorldHandlers/SpellEffects.cpp b/src/game/WorldHandlers/SpellEffects.cpp index b0dd31e90..3251b16ce 100644 --- a/src/game/WorldHandlers/SpellEffects.cpp +++ b/src/game/WorldHandlers/SpellEffects.cpp @@ -63,7 +63,9 @@ #include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" -#include "PhaseMgr.h" +#include "Vehicle.h" +#include "G3D/Vector3.h" +#include "LootMgr.h" pEffect SpellEffects[TOTAL_SPELL_EFFECTS] = { @@ -208,11 +210,11 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS] = &Spell::EffectLeapBack, //138 SPELL_EFFECT_LEAP_BACK Leap back &Spell::EffectClearQuest, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID) &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST - &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed? + &Spell::EffectForceCast, //141 SPELL_EFFECT_FORCE_CAST_WITH_VALUE &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER &Spell::EffectKnockBackFromPosition, //144 SPELL_EFFECT_KNOCKBACK_FROM_POSITION - &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect + &Spell::EffectGravityPull, //145 SPELL_EFFECT_GRAVITY_PULL &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail &Spell::EffectNULL, //148 SPELL_EFFECT_148 single spell: Inflicts Fire damage to an enemy. @@ -337,7 +339,7 @@ void Spell::EffectSchoolDMG(SpellEffectEntry const* effect) { switch (m_spellInfo->Id) // better way to check unknown { - // Meteor like spells (divided damage to targets) + // Meteor like spells (divided damage to targets) case 24340: case 26558: case 28884: // Meteor case 36837: case 38903: case 41276: // Meteor case 57467: // Meteor @@ -351,6 +353,17 @@ void Spell::EffectSchoolDMG(SpellEffectEntry const* effect) case 70492: case 72505: // Ooze Eruption case 71904: // Chaos Bane case 72624: case 72625: // Ooze Eruption + case 77679: case 92968: case 92969: case 92970: // Scorching Blast + case 82935: case 88915: case 88916: case 88917: // Caustic Slime + case 86014: case 92863: case 92864: case 92865: // Twilight Meteorite + case 86367: case 93135: case 93136: case 93137: // Sleet Storm + case 86825: case 92879: case 92880: case 92881: // Blackout + case 88942: case 95172: // Meteor Slash + case 89348: case 95178: // Demon Repellent Ray + case 98474: case 100212: case 100213: case 100214: //Flame Scythe + case 103414: case 108571: case 109033: case 109034: //Stomp + case 105069: case 108094: // Seething Hate + case 106375: case 109182: case 109183: case 109184: //Twilight Unstable { uint32 count = 0; for(TargetList::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) @@ -407,7 +420,7 @@ void Spell::EffectSchoolDMG(SpellEffectEntry const* effect) case 67485: damage += uint32(0.5f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK)); break; - // Magic Bane normal (Forge of Souls - Bronjahm) + // Magic Bane normal (Forge of Souls - Bronjahm) case 68793: { damage += uint32(unitTarget->GetMaxPower(POWER_MANA) / 2); @@ -524,7 +537,7 @@ void Spell::EffectSchoolDMG(SpellEffectEntry const* effect) // Conflagrate - consumes Immolate or Shadowflame else if (m_spellInfo->GetTargetAuraState() == AURA_STATE_CONFLAGRATE) { - Aura const* aura = NULL; // found req. aura for damage calculation + Aura const* aura = nullptr; // found req. aura for damage calculation Unit::AuraList const& mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); for (Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i) @@ -592,7 +605,7 @@ void Spell::EffectSchoolDMG(SpellEffectEntry const* effect) { // converts up to 30 points of energy into ($f1+$AP/410) additional damage float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); - float multiple = ap / 410 + effect->DmgMultiplier; + float multiple = ap / 410 + effect->EffectDamageMultiplier; damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100); uint32 energy = m_caster->GetPower(POWER_ENERGY); uint32 used_energy = energy > 30 ? 30 : energy; @@ -829,7 +842,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) case 4: spell_id = 8067; break; // Party Time! case 5: spell_id = 8068; break; // Healthy Spirit } - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true, nullptr); return; } case 8213: // Savory Deviate Delight @@ -840,13 +853,13 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) uint32 spell_id = 0; switch (urand(1, 2)) { - // Flip Out - ninja + // Flip Out - ninja case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break; - // Yaaarrrr - pirate + // Yaaarrrr - pirate case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break; } - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true, nullptr); return; } case 9976: // Polly Eats the E.C.A.C. @@ -886,7 +899,15 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) else // normal root spell_id = 13099; - m_caster->CastSpell(unitTarget, spell_id, true, NULL); + m_caster->CastSpell(unitTarget, spell_id, true, nullptr); + return; + } + case 13489: + { + if (!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 14744, true); return; } case 13567: // Dummy Trigger @@ -898,7 +919,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) switch (m_triggeredByAuraSpell->Id) { case 26467: // Persistent Shield - m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true); + m_caster->CastCustomSpell(unitTarget, 26470, &damage, nullptr, nullptr, true); break; default: sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u", m_triggeredByAuraSpell->Id); @@ -962,7 +983,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) default: spell_id = 16591; break; } - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true, nullptr); return; } case 17009: // Voodoo @@ -982,7 +1003,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) case 6: spell_id = 16716; break; // Launch } - m_caster->CastSpell(unitTarget, spell_id, true, NULL, NULL, m_originalCasterGUID, m_spellInfo); + m_caster->CastSpell(unitTarget, spell_id, true, nullptr, nullptr, m_originalCasterGUID, m_spellInfo); return; } case 17251: // Spirit Healer Res @@ -1009,12 +1030,12 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) ? 17269 // Create Resonating Skull : 17270; // Create Bone Dust - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true, nullptr); return; } case 17770: // Wolfshead Helm Energy { - m_caster->CastSpell(m_caster, 29940, true, NULL); + m_caster->CastSpell(m_caster, 29940, true, nullptr); return; } case 17950: // Shadow Portal @@ -1028,6 +1049,14 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, spell_list[urand(0, 5)], true); return; } + case 19395: // Gordunni Trap + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + unitTarget->CastSpell(unitTarget, urand(0, 1) ? 19394 : 11756, true); + return; + } case 19411: // Lava Bomb case 20474: // Lava Bomb { @@ -1087,7 +1116,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) case 20577: // Cannibalize { if (unitTarget) - m_caster->CastSpell(m_caster, 20578, false, NULL); + m_caster->CastSpell(m_caster, 20578, false, nullptr); return; } @@ -1128,7 +1157,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; } - pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime() - time(NULL)); + pGameObj->SetRespawnTime(creatureTarget->GetRespawnTime() - time(nullptr)); pGameObj->SetOwnerGuid(m_caster->GetObjectGuid()); pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()); pGameObj->SetSpellId(m_spellInfo->Id); @@ -1297,7 +1326,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) ? 29277 // Summon Purified Helboar Meat : 29278; // Summon Toxic Helboar Meat - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true, nullptr); return; } case 29858: // Soulshatter @@ -1312,7 +1341,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, 29952, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 29952, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 29979: // Massive Magnetic Pull @@ -1398,7 +1427,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) case 5: spell_id = 33064; break; // Mr. Pinchy's Gift } - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true, nullptr); return; } case 34803: // Summon Reinforcements @@ -1451,7 +1480,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; int32 basepoints0 = 100; - m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true); + m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, nullptr, nullptr, true); return; } case 39189: // Sha'tari Torch @@ -1474,7 +1503,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, 41466, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 41466, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets) @@ -1572,6 +1601,31 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; } + case 42485: // End of Ooze Channel + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + unitTarget->CastSpell(m_caster, 42486, true); + + // There is no known spell to kill the target + unitTarget->DealDamage(unitTarget, unitTarget->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); + return; + } + case 42489: // Cast Ooze Zap When Energized + { + // only process first effect + // the logic is described by spell 42488 - Caster Spell 1 Only if Aura 2 Is On Caster (not used here) + if (effect->EffectIndex != EFFECT_INDEX_0) + return; + + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || !m_caster->HasAura(m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1))) + return; + + m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); + ((Creature*)unitTarget)->AI()->AttackStart(m_caster); + return; + } case 42628: // Fire Bomb (throw) { if (!unitTarget) @@ -1652,7 +1706,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, 42493, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 42493, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 43209: // Place Ram Meat @@ -1705,7 +1759,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - ((Player*)m_caster)->CastSpell(unitTarget, 43753, true, m_CastItem, NULL, m_originalCasterGUID, m_spellInfo); + ((Player*)m_caster)->CastSpell(unitTarget, 43753, true, m_CastItem, nullptr, m_originalCasterGUID, m_spellInfo); return; } case 43882: // Scourging Crystal Controller Dummy @@ -1735,8 +1789,8 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; // Cast the spectral realm effect spell, visual spell and spectral blast rift summoning - unitTarget->CastSpell(unitTarget, 44866, true, NULL, NULL, m_caster->GetObjectGuid()); - unitTarget->CastSpell(unitTarget, 46648, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 44866, true, nullptr, nullptr, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 46648, true, nullptr, nullptr, m_caster->GetObjectGuid()); unitTarget->CastSpell(unitTarget, 44811, true); return; } @@ -1750,7 +1804,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) creatureTarget->ForcedDespawn(); // cast spell Raptor Capture Credit - m_caster->CastSpell(m_caster, 42337, true, NULL); + m_caster->CastSpell(m_caster, 42337, true, nullptr); return; } case 44997: // Converting Sentry @@ -1799,7 +1853,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) // look for gameobject within max spell range of unitTarget, and respawn if found // big fire - GameObject* pGo = NULL; + GameObject* pGo = nullptr; float fMaxDist = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); @@ -1907,6 +1961,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) case 51961: // Captured Chicken Cover case 55364: // Create Ghoul Drool Cover case 61832: // Rifle the Bodies: Create Magehunter Personal Effects Cover + case 63125: // Search Maloric case 74904: // Pickup Sen'jin Frog { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER) @@ -1924,6 +1979,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) case 51961: spellId = 51037; break; case 55364: spellId = 55363; break; case 61832: spellId = 47096; break; + case 63125: spellId = 63126; break; case 74904: spellId = 74905; break; } @@ -1946,7 +2002,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) ((Player*)m_caster)->KilledMonsterCredit(unitTarget->GetEntry(), unitTarget->GetObjectGuid()); // look for gameobject within max spell range of unitTarget, and respawn if found - GameObject* pGo = NULL; + GameObject* pGo = nullptr; float fMaxDist = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); @@ -1963,6 +2019,28 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; } + case 46292: // Cataclysm Breath + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + uint32 spellId = 0; + + switch (urand(0, 7)) + { + case 0: spellId = 46293; break; // Corrosive Poison + case 1: spellId = 46294; break; // Fevered Fatigue + case 2: spellId = 46295; break; // Hex + case 3: spellId = 46296; break; // Necrotic Poison + case 4: spellId = 46297; break; // Piercing Shadow + case 5: spellId = 46298; break; // Shrink + case 6: spellId = 46299; break; // Wavering Will + case 7: spellId = 46300; break; // Withered Touch + } + + m_caster->CastSpell(unitTarget, spellId, true); + return; + } case 46372: // Ice Spear Target Picker { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) @@ -1971,22 +2049,6 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, 46359, true); return; } - case 46289: // Negative Energy - { - if (!unitTarget) - return; - - m_caster->CastSpell(unitTarget, 46285, true); - return; - } - case 46430: // Synch Health - { - if (!unitTarget) - return; - - unitTarget->SetHealth(m_caster->GetHealth()); - return; - } case 46485: // Greatmother's Soulcatcher { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) @@ -2054,7 +2116,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) // The additional castspell arguments are needed here to remove reagents for triggered spells if (spellId) - m_caster->CastSpell(m_caster, spellId, true, m_CastItem, NULL, m_caster->GetObjectGuid(), m_spellInfo); + m_caster->CastSpell(m_caster, spellId, true, m_CastItem, nullptr, m_caster->GetObjectGuid(), m_spellInfo); return; } @@ -2141,7 +2203,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) // Need internal way to track if credit has been given for this object. // Iron Dwarf Snapshot Credit - m_caster->CastSpell(m_caster, 48047, true, m_CastItem, NULL, unitTarget->GetObjectGuid()); + m_caster->CastSpell(m_caster, 48047, true, m_CastItem, nullptr, unitTarget->GetObjectGuid()); return; } case 48790: // Neltharion's Flame @@ -2361,7 +2423,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (BattleGround* bg = ((Player*)m_caster)->GetBattleGround()) bg->EventPlayerDroppedFlag((Player*)m_caster); - m_caster->CastSpell(m_caster, 30452, true, NULL); + m_caster->CastSpell(m_caster, 30452, true, nullptr); return; } case 51840: // Despawn Fruit Tosser @@ -2406,7 +2468,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) // Expecting pTargetDummy to be summoned by AI at death of target creatures. - Creature* pTargetDummy = NULL; + Creature* pTargetDummy = nullptr; float fRange = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, 28523, true, false, fRange * 2); @@ -2477,7 +2539,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1); if (m_caster->HasAura(reqAuraID, EFFECT_INDEX_0)) - m_caster->CastSpell(m_caster, spellID, true, NULL); + m_caster->CastSpell(m_caster, spellID, true, nullptr); return; } case EFFECT_INDEX_1: // additional data for dummy[0] @@ -2521,7 +2583,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (!unitTarget) return; - m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true); + m_caster->CastCustomSpell(unitTarget, 52752, &damage, nullptr, nullptr, true); return; } case 52845: // Brewfest Mount Transformation (Faction Swap) @@ -2673,8 +2735,8 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, 56431, true, NULL, NULL, m_caster->GetObjectGuid()); - unitTarget->CastSpell(unitTarget, 56432, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 56431, true, nullptr, nullptr, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 56432, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 57578: // Lava Strike @@ -2718,7 +2780,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) case 3: spell_id = 59843; break; } - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true, nullptr); return; } case 60932: // Disengage (one from creature versions) @@ -2726,7 +2788,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (!unitTarget) return; - m_caster->CastSpell(unitTarget, 60934, true, NULL); + m_caster->CastSpell(unitTarget, 60934, true, nullptr); return; } case 62105: // To'kini's Blowgun @@ -2746,31 +2808,6 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) unitTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); return; } - case 62217: // Unstable Energy - case 62922: // Unstable Energy (h) - { - if (!unitTarget) - return; - - unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); - return; - } - case 62262: // Brightleaf Flux - { - if (!unitTarget) - return; - - if (unitTarget->HasAura(62239)) - unitTarget->RemoveAurasDueToSpell(62239); - else - { - uint32 stackAmount = urand(1, GetSpellStore()->LookupEntry(62239)->GetStackAmount()); - - for (uint8 i = 0; i < stackAmount; ++i) - unitTarget->CastSpell(unitTarget, 62239, true); - } - return; - } case 62278: // Lightning Orb Charger { if (!unitTarget) @@ -2805,13 +2842,12 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); return; } - case 63027: // Proximity Mines + case 63030: // Boil Ominously { - if (!unitTarget) + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - for (uint8 i = 0; i < 15; ++i) - unitTarget->CastSpell(unitTarget, 65347, true); + m_caster->CastSpell(unitTarget, 63031, true); return; } case 63499: // Dispel Magic @@ -2828,38 +2864,34 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); + return; } - case 63667: // Napalm Shell + case 63744: // Sara's Anger + case 63745: // Sara's Blessing + case 63747: // Sara's Fervor { if (!unitTarget) return; - m_caster->CastSpell(unitTarget, m_caster->GetMap()->IsRegularDifficulty() ? 63666 : 65026, true); + m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); return; } - case 63681: // Rocket Strike - { - if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - m_caster->CastSpell(unitTarget, 63036, true); - return; - } - case 63820: // Summon Scrap Bot Trigger (Ulduar - Mimiron) for Scrap Bots - case 64425: // Summon Scrap Bot Trigger (Ulduar - Mimiron) for Assault Bots - case 64620: // Summon Fire Bot Trigger (Ulduar - Mimiron) for Fire Bots + case 63984: // Hate to Zero { if (!unitTarget) return; - uint32 triggerSpell = 0; - switch (m_spellInfo->Id) - { - case 63820: triggerSpell = 64398; break; - case 64425: triggerSpell = 64426; break; - case 64620: triggerSpell = 64621; break; - } - unitTarget->CastSpell(unitTarget, triggerSpell, false); + if (m_caster->GetThreatManager().getThreat(unitTarget)) + m_caster->GetThreatManager().modifyThreatPercent(unitTarget, -100); + return; + } + case 64172: // Titanic Storm + { + if (!unitTarget || !unitTarget->HasAura(effect->CalculateSimpleValue())) + return; + + // There is no known spell to kill the target + m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); return; } case 64385: // Spinning (from Unusual Compass) @@ -2892,14 +2924,15 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->CastSpell(m_caster, 64540, true); return; } - case 64623: // Frost Bomb - { - if (!unitTarget) - return; + case 64555: // Insane Periodic + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->HasAura(63050) || unitTarget->HasAura(effect->CalculateSimpleValue())) + return; - m_caster->CastSpell(unitTarget, 64627, true); - return; - } + m_caster->CastSpell(unitTarget, 64464, true); + m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); + return; + } case 64673: // Feral Rush (h) { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) @@ -2908,14 +2941,6 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, 64674, true); return; } - case 64841: // Rapid Burst - { - if (!unitTarget) - return; - - unitTarget->CastSpell(m_caster, 63382, false); - return; - } case 64981: // Summon Random Vanquished Tentacle { uint32 spell_id = 0; @@ -2930,6 +2955,14 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->CastSpell(m_caster, spell_id, true); return; } + case 65206: // Destabilization Matrix + { + if (!unitTarget) + return; + + m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); + return; + } case 65346: // Proximity Mine { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) @@ -2940,6 +2973,46 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); return; } + case 65869: // Disengage + { + if (!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 65870, true); + return; + } + case 66312: // Light Ball Passive + { + if (!unitTarget || m_caster->GetTypeId() != TYPEID_UNIT) + return; + + if (unitTarget->GetTypeId() == TYPEID_PLAYER) + { + if (unitTarget->HasAuraOfDifficulty(65686)) + unitTarget->CastSpell(unitTarget, 67590, true); + else + m_caster->CastSpell(m_caster, 65795, true); + + ((Creature*)m_caster)->ForcedDespawn(); + } + return; + } + case 66314: // Dark Ball Passive + { + if (!unitTarget || m_caster->GetTypeId() != TYPEID_UNIT) + return; + + if (unitTarget->GetTypeId() == TYPEID_PLAYER) + { + if (unitTarget->HasAuraOfDifficulty(65684)) + unitTarget->CastSpell(unitTarget, 67590, true); + else + m_caster->CastSpell(m_caster, 65808, true); + + ((Creature*)m_caster)->ForcedDespawn(); + } + return; + } case 66390: // Read Last Rites { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->GetTypeId() != TYPEID_PLAYER) @@ -3004,6 +3077,14 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) unitTarget->CastSpell(m_caster, 69956, true); return; } + case 71307: // Vile Gas + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); + return; + } case 71445: // Twilight Bloodbolt case 71471: // Twilight Bloodbolt { @@ -3038,6 +3119,22 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, 71264, true); return; } + case 72202: // Blood Link + { + if (!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 72195, true); + return; + } + case 72254: // Mark of the Fallen Champion + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->HasAura(effect->CalculateSimpleValue())) + return; + + m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); + return; + } case 72261: // Delirious Slash { if (!unitTarget) @@ -3046,13 +3143,21 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, m_caster->CanReachWithMeleeAttack(unitTarget) ? 71623 : 72264, true); return; } + case 72285: // Vile Gas Trigger + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); + return; + } case 74452: // Conflagration { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; m_caster->CastSpell(unitTarget, 74453, true); - m_caster->CastSpell(unitTarget, 74454, true, NULL, NULL, m_caster->GetObjectGuid(), m_spellInfo); + m_caster->CastSpell(unitTarget, 74454, true, nullptr, nullptr, m_caster->GetObjectGuid(), m_spellInfo); return; } } @@ -3144,7 +3249,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (warClassOptions && (warClassOptions->SpellFamilyFlags & UI64LIT(0x1)) && m_spellInfo->SpellVisual[0] == 867) { int32 chargeBasePoints0 = damage; - m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, NULL, NULL, true); + m_caster->CastCustomSpell(m_caster, 34846, &chargeBasePoints0, nullptr, nullptr, true); return; } // Execute @@ -3165,10 +3270,10 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (Aura* aura = m_caster->GetDummyAura(58367)) rage_modified += aura->GetModifier()->m_amount * 10; - int32 basePoints0 = damage+int32(rage_modified * effect->DmgMultiplier + + int32 basePoints0 = damage+int32(rage_modified * effect->EffectDamageMultiplier + m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); - m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0); + m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, nullptr, nullptr, true, 0); // Sudden Death if (m_caster->HasAura(52437)) @@ -3198,7 +3303,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; // dummy cast itself ignored by client in logs - m_caster->CastCustomSpell(unitTarget, 50782, &damage, NULL, NULL, true); + m_caster->CastCustomSpell(unitTarget, 50782, &damage, nullptr, nullptr, true); return; } // Concussion Blow @@ -3210,7 +3315,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) switch (m_spellInfo->Id) { - // Warrior's Wrath + // Warrior's Wrath case 21977: { if (!unitTarget) @@ -3222,13 +3327,13 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) case 12975: { int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth() * 0.3); - m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); + m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, nullptr, nullptr, true, nullptr); return; } // Bloodthirst case 23881: { - m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL); + m_caster->CastCustomSpell(unitTarget, 23885, &damage, nullptr, nullptr, true, nullptr); return; } case 30012: // Move @@ -3283,7 +3388,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if((*itr)->GetSpellProto()->GetSpellFamilyName()==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208) mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100; - m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true); + m_caster->CastCustomSpell(unitTarget, 31818, &mana, nullptr, nullptr, true); // Mana Feed int32 manaFeedVal = 0; @@ -3296,7 +3401,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (manaFeedVal > 0) { manaFeedVal = manaFeedVal * mana / 100; - m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL); + m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, nullptr, nullptr, true, nullptr); } } else @@ -3340,34 +3445,6 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; } break; - - switch (m_spellInfo->Id) - { - case 21562: // Power Word: Fortitude - { - Unit* target = unitTarget; - if (!target) - target = m_caster; - - if (m_caster->GetTypeId() != TYPEID_PLAYER || target->GetTypeId() != TYPEID_PLAYER) - return; - - m_caster->CastSpell(target, ((Player*)m_caster)->GetGroup() != ((Player*)target)->GetGroup() ? 79104 : 79105, true, NULL, NULL, m_caster->GetObjectGuid()); - return; - } - case 27683: // Shadow Protection - { - Unit* target = unitTarget; - if (!target) - target = m_caster; - - if (m_caster->GetTypeId() != TYPEID_PLAYER || target->GetTypeId() != TYPEID_PLAYER) - return; - - m_caster->CastSpell(target, ((Player*)m_caster)->GetGroup() != ((Player*)target)->GetGroup() ? 79106 : 79107, true, NULL, NULL, m_caster->GetObjectGuid()); - return; - } - } } case SPELLFAMILY_DRUID: { @@ -3512,7 +3589,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) } if (!target || !target->IsAlive()) return; - m_caster->CastSpell(target, spellid, true, NULL); + m_caster->CastSpell(target, spellid, true, nullptr); } switch (m_spellInfo->Id) @@ -3552,7 +3629,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (!unitTarget) return; int32 healthModSpellBasePoints0 = int32(unitTarget->GetMaxHealth() * 0.3); - unitTarget->CastCustomSpell(unitTarget, 53479, &healthModSpellBasePoints0, NULL, NULL, true, NULL); + unitTarget->CastCustomSpell(unitTarget, 53479, &healthModSpellBasePoints0, nullptr, nullptr, true, nullptr); return; } // Master's Call @@ -3611,7 +3688,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (!spell_proto) return; - m_caster->CastSpell(unitTarget, spell_proto, true, NULL); + m_caster->CastSpell(unitTarget, spell_proto, true, nullptr); return; } } @@ -3632,7 +3709,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) { Player* player = friendTarget->GetCharmerOrOwnerPlayerOrPlayerItself(); if (!player || !player->IsInSameRaidWith((Player*)m_caster)) - friendTarget = NULL; + friendTarget = nullptr; } // non-standard cast requirement check @@ -3719,7 +3796,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) if (Aura* dummy = owner->GetDummyAura(55456)) damage += dummy->GetModifier()->m_amount * damage / 100; } - m_caster->CastCustomSpell(unitTarget, 52042, &damage, NULL, NULL, true, 0, 0, m_originalCasterGUID); + m_caster->CastCustomSpell(unitTarget, 52042, &damage, nullptr, nullptr, true, 0, 0, m_originalCasterGUID); } return; } @@ -3745,7 +3822,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) float weaponSpeed = (1.0f / IN_MILLISECONDS) * m_CastItem->GetProto()->Delay; int32 totalDamage = int32((damage + 3.85f * spellDamage) * 0.01 * weaponSpeed); - m_caster->CastCustomSpell(unitTarget, 10444, &totalDamage, NULL, NULL, true, m_CastItem); + m_caster->CastCustomSpell(unitTarget, 10444, &totalDamage, nullptr, nullptr, true, m_CastItem); return; } if (m_spellInfo->Id == 39610) // Mana Tide Totem effect @@ -3759,7 +3836,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) damage += dummy->GetModifier()->m_amount; // Regenerate 6% of Total Mana Every 3 secs int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100; - m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, NULL, NULL, true, NULL, NULL, m_originalCasterGUID); + m_caster->CastCustomSpell(unitTarget, 39609, &EffectBasePoints0, nullptr, nullptr, true, nullptr, nullptr, m_originalCasterGUID); return; } // Lava Lash @@ -3807,10 +3884,10 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) default: return; } - totem->CastSpell(totem, triggered_spell_id, true, NULL, NULL, m_caster->GetObjectGuid()); + totem->CastSpell(totem, triggered_spell_id, true, nullptr, nullptr, m_caster->GetObjectGuid()); // Fire Nova Visual - totem->CastSpell(totem, 19823, true, NULL, NULL, m_caster->GetObjectGuid()); + totem->CastSpell(totem, 19823, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } break; @@ -3827,12 +3904,12 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) return; int32 bp = int32(damage * 1.5f); - m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true); + m_caster->CastCustomSpell(unitTarget, 47633, &bp, nullptr, nullptr, true); } else { int32 bp = damage; - m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true); + m_caster->CastCustomSpell(unitTarget, 47632, &bp, nullptr, nullptr, true); } return; } @@ -3860,7 +3937,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) } SpellEffectEntry const* dsSpellEffect = m_spellInfo->GetSpellEffect(EFFECT_INDEX_0); - int32 bp = int32(count * m_caster->GetMaxHealth() * (dsSpellEffect ? dsSpellEffect->DmgMultiplier : 0.0f) / 100); + int32 bp = int32(count * m_caster->GetMaxHealth() * (dsSpellEffect ? dsSpellEffect->EffectDamageMultiplier : 0.0f) / 100); // Improved Death Strike (percent stored in nonexistent EFFECT_INDEX_2 effect base points) Unit::AuraList const& auraMod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); @@ -3874,7 +3951,28 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) } } - m_caster->CastCustomSpell(m_caster, 45470, &bp, NULL, NULL, true); + m_caster->CastCustomSpell(m_caster, 45470, &bp, nullptr, nullptr, true); + return; + } + // Death Grip + else if (m_spellInfo->Id == 49576) + { + if (!unitTarget) + return; + + m_caster->CastSpell(unitTarget, 49560, true); + return; + } + // Death Grip + else if (m_spellInfo->Id == 49560) + { + if (!unitTarget || unitTarget == m_caster) + return; + + uint32 spellId = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_0); + float dest_x, dest_y; + m_caster->GetNearPoint2D(dest_x, dest_y, m_caster->GetObjectBoundingRadius() + unitTarget->GetObjectBoundingRadius(), m_caster->GetOrientation()); + unitTarget->CastSpell(dest_x, dest_y, m_caster->GetPositionZ() + 0.5f, spellId, true, nullptr, nullptr, m_caster->GetObjectGuid(), m_spellInfo); return; } // Obliterate @@ -3916,7 +4014,7 @@ void Spell::EffectDummy(SpellEffectEntry const* effect) libraryResult = sScriptMgr.OnEffectDummy(m_caster, m_spellInfo->Id, SpellEffectIndex(effect->EffectIndex), (Creature*)unitTarget, m_originalCasterGUID); else if (itemTarget) libraryResult = sScriptMgr.OnEffectDummy(m_caster, m_spellInfo->Id, SpellEffectIndex(effect->EffectIndex), itemTarget, m_originalCasterGUID); - + if (libraryResult || !unitTarget) return; @@ -3942,7 +4040,7 @@ void Spell::EffectTriggerSpellWithValue(SpellEffectEntry const* effect) } int32 bp = damage; - m_caster->CastCustomSpell(unitTarget, triggered_spell_id, &bp, &bp, &bp, true, m_CastItem , NULL, m_originalCasterGUID, m_spellInfo); + m_caster->CastCustomSpell(unitTarget, triggered_spell_id, &bp, &bp, &bp, true, m_CastItem , nullptr, m_originalCasterGUID, m_spellInfo); } void Spell::EffectTriggerRitualOfSummoning(SpellEffectEntry const* effect) @@ -3991,11 +4089,6 @@ void Spell::EffectClearQuest(SpellEffectEntry const* effect) player->SetQuestStatus(quest_id, QUEST_STATUS_NONE); player->getQuestStatusMap()[quest_id].m_rewarded = false; - - PhaseUpdateData phaseUdateData; - phaseUdateData.AddQuestUpdate(quest_id); - - player->GetPhaseMgr()->NotifyConditionChanged(phaseUdateData); } void Spell::EffectForceCast(SpellEffectEntry const* effect) @@ -4014,7 +4107,21 @@ void Spell::EffectForceCast(SpellEffectEntry const* effect) return; } - unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID, m_spellInfo); + int32 basePoints = damage; + + // forced cast spells by vehicle on master always unboard the master + if (m_caster->IsVehicle() && m_caster->GetVehicleInfo()->HasOnBoard(unitTarget) && + effect->EffectImplicitTargetA == TARGET_MASTER) + { + if (sSpellStore.LookupEntry(basePoints)) + m_caster->RemoveAurasDueToSpell(basePoints); + } + + // spell effect 141 needs to be cast as custom with basePoints + if (effect->Effect == SPELL_EFFECT_FORCE_CAST_WITH_VALUE) + unitTarget->CastCustomSpell(unitTarget, spellInfo, &basePoints, &basePoints, &basePoints, true, nullptr , nullptr, m_originalCasterGUID, m_spellInfo); + else + unitTarget->CastSpell(unitTarget, spellInfo, true, nullptr, nullptr, m_originalCasterGUID, m_spellInfo); } void Spell::EffectTriggerSpell(SpellEffectEntry const* effect) @@ -7133,7 +7240,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) default: spell_id = 8855; break; } - m_caster->CastSpell(m_caster, spell_id, true, NULL); + m_caster->CastSpell(m_caster, spell_id, true, nullptr); return; } case 17512: // Piccolo of the Flaming Fire @@ -7218,7 +7325,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) } case 24320: // Poisonous Blood { - unitTarget->CastSpell(unitTarget, 24321, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 24321, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 24324: // Blood Siphon @@ -7453,7 +7560,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) int32 damage = unitTarget->GetHealth() - unitTarget->GetMaxHealth() * downToHealthPercent; if (damage > 0) - m_caster->CastCustomSpell(unitTarget, 28375, &damage, NULL, NULL, true); + m_caster->CastCustomSpell(unitTarget, 28375, &damage, nullptr, nullptr, true); return; } case 28560: // Summon Blizzard @@ -7530,6 +7637,60 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(unitTarget, 30542, true); break; } + case 30469: // Nether Beam + { + if (!unitTarget) + return; + + // The player and boss spells are different + if (unitTarget->GetTypeId() == TYPEID_PLAYER) + { + switch (m_caster->GetEntry()) + { + case 17367: + if (unitTarget->HasAura(38638)) + return; + + m_caster->CastSpell(unitTarget, 30401, true); + m_caster->CastSpell(unitTarget, 30422, true); + break; + case 17368: + if (unitTarget->HasAura(38639)) + return; + + m_caster->CastSpell(unitTarget, 30402, true); + m_caster->CastSpell(unitTarget, 30423, true); + break; + case 17369: + if (unitTarget->HasAura(38637)) + return; + + m_caster->CastSpell(unitTarget, 30400, true); + m_caster->CastSpell(unitTarget, 30421, true); + break; + } + } + // target boss + else if (unitTarget->GetEntry() == 15689) + { + switch (m_caster->GetEntry()) + { + case 17367: + m_caster->CastSpell(unitTarget, 30464, true); + m_caster->CastSpell(unitTarget, 30467, true); + break; + case 17368: + m_caster->CastSpell(unitTarget, 30463, true); + m_caster->CastSpell(unitTarget, 30468, true); + break; + case 17369: + m_caster->CastSpell(unitTarget, 30465, true); + m_caster->CastSpell(unitTarget, 30466, true); + break; + } + } + return; + } case 30769: // Pick Red Riding Hood { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) @@ -7544,7 +7705,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, 30836, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 30836, true, nullptr, nullptr, m_caster->GetObjectGuid()); break; } case 30918: // Improved Sprint @@ -7569,11 +7730,11 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) case 37345: // Karazhan - Chess NPC Action: Melee Attack: Orc Warlock case 37348: // Karazhan - Chess NPC Action: Melee Attack: Warchief Blackhand { - if (!unitTarget) - return; - - m_caster->CastSpell(unitTarget, 32247, true); + if (!unitTarget) return; + + m_caster->CastSpell(unitTarget, 32247, true); + return; } case 32301: // Ping Shirrak { @@ -7592,6 +7753,15 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, 33684, true); return; } + case 34653: // Fireball + case 36920: // Fireball (h) + { + if (!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, unitTarget->GetMap()->IsRegularDifficulty() ? 23971 : 30928, true, nullptr, nullptr, m_caster->GetObjectGuid()); + return; + } case 35865: // Summon Nether Vapor { if (!unitTarget) @@ -7634,7 +7804,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, 38353, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 38353, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 39338: // Karazhan - Chess, Medivh CHEAT: Hand of Medivh, Target Horde @@ -7656,6 +7826,8 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) return; } case 41055: // Copy Weapon + case 63416: // Copy Weapon + case 69891: // Copy Weapon (No Threat) { if (m_caster->GetTypeId() != TYPEID_UNIT || !unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; @@ -7670,6 +7842,14 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) return; } + case 41072: // Bloodbolt + { + if (!unitTarget) + return; + + m_caster->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); + return; + } case 41126: // Flame Crash { if (!unitTarget) @@ -7678,6 +7858,49 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(unitTarget, 41131, true); break; } + case 41213: // Throw Shield + case 43416: // Throw Shield + case 69222: // Throw Shield + case 73076: // Throw Shield + { + if (!unitTarget) + return; + + unitTarget->CastSpell(m_caster, effect->CalculateSimpleValue(), true); + return; + } + case 42281: // Sprouting + { + if (!unitTarget) + return; + + unitTarget->RemoveAurasDueToSpell(42280); + unitTarget->RemoveAurasDueToSpell(42294); + unitTarget->CastSpell(unitTarget, 42285, true); + unitTarget->CastSpell(unitTarget, 42291, true); + return; + } + case 42492: // Cast Energized + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + uint32 questId = m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1); + if (!questId || !GetQuestTemplateStore(questId) || !((Player*)unitTarget)->IsCurrentQuest(questId)) + return; + + m_caster->CastSpell(m_caster, effect->CalculateSimpleValue(), true); + return; + } + case 42578: // Cannon Blast + { + if (!unitTarget) + return; + + int32 basePoints = effect->CalculateSimpleValue(); + unitTarget->CastCustomSpell(unitTarget, 42576, &basePoints, nullptr, nullptr, true); + return; + } case 43365: // The Cleansing: Shrine Cast { if (m_caster->GetTypeId() != TYPEID_PLAYER) @@ -7721,7 +7944,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) // Are there anything special with this, a random chance or condition? // Feeding Rock Falcon - unitTarget->CastSpell(unitTarget, effect->CalculateSimpleValue(), true, NULL, NULL, unitTarget->GetObjectGuid(), m_spellInfo); + unitTarget->CastSpell(unitTarget, effect->CalculateSimpleValue(), true, nullptr, nullptr, unitTarget->GetObjectGuid(), m_spellInfo); return; } case 44455: // Character Script Effect Reverse Cast @@ -7768,7 +7991,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) if (m_caster->GetTypeId() != TYPEID_UNIT) return; - Creature* pQuestCow = NULL; + Creature* pQuestCow = nullptr; float range = 20.0f; @@ -7828,7 +8051,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, 46394, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 46394, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 45151: // Burn @@ -7858,6 +8081,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) return; } case 45206: // Copy Off-hand Weapon + case 69892: // Copy Off-hand Weapon (No Threat) { if (m_caster->GetTypeId() != TYPEID_UNIT || !unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; @@ -7877,7 +8101,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, 45236, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 45236, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 45260: // Karazhan - Chess - Force Player to Kill Bunny @@ -7888,6 +8112,14 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(unitTarget, 45259, true); return; } + case 45313: // Anchor Here + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + ((Creature*)unitTarget)->SetRespawnCoord(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetOrientation()); + return; + } case 45625: // Arcane Chains: Character Force Cast { if (!unitTarget) @@ -7950,7 +8182,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) if (m_caster->GetTypeId() != TYPEID_UNIT) return; - const CreatureInfo* cTemplate = NULL; + const CreatureInfo* cTemplate = nullptr; switch (m_caster->GetEntry()) { @@ -8039,7 +8271,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) // Summon 4 clones of the same player for (uint8 i = 0; i < 4; ++i) - unitTarget->CastSpell(unitTarget, 45891, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 45891, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 45918: // Soul Sever @@ -8076,6 +8308,22 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(unitTarget, spellId, true); break; } + case 46289: // Negative Energy + { + if (!unitTarget) + return; + + m_caster->CastSpell(unitTarget, 46285, true); + return; + } + case 46430: // Synch Health + { + if (!unitTarget) + return; + + unitTarget->SetHealth(m_caster->GetHealth()); + return; + } case 46642: // 5,000 Gold { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) @@ -8277,7 +8525,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) return; // Each target hit buffs the caster - unitTarget->CastSpell(m_caster, m_spellInfo->Id == 49380 ? 49381 : 59805, true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(m_caster, m_spellInfo->Id == 49380 ? 49381 : 59805, true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 49405: // Invader Taunt Trigger @@ -8353,7 +8601,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) if (!unitTarget) return; - unitTarget->CastSpell(unitTarget, effect->CalculateSimpleValue(), true, NULL, NULL, m_originalCasterGUID); + unitTarget->CastSpell(unitTarget, effect->CalculateSimpleValue(), true, nullptr, nullptr, m_originalCasterGUID); return; } case 50439: // Script Cast Summon Image of Drakuru 05 @@ -8397,7 +8645,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) return; unitTarget->RemoveAurasDueToSpell(50812); - unitTarget->CastSpell(unitTarget, m_spellInfo->Id == 50810 ? 50811 : 61547 , true, NULL, NULL, m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, m_spellInfo->Id == 50810 ? 50811 : 61547 , true, nullptr, nullptr, m_caster->GetObjectGuid()); return; } case 50894: // Zul'Drak Rat @@ -8490,7 +8738,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) // cast Summon Ghouls On Scarlet Crusade float x, y, z; m_targets.getDestination(x, y, z); - unitTarget->CastSpell(x, y, z, 54522, true, NULL, NULL, m_originalCasterGUID); + unitTarget->CastSpell(x, y, z, 54522, true, nullptr, nullptr, m_originalCasterGUID); return; } case 51910: // Kickin' Nass: Quest Completion @@ -8545,9 +8793,9 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) Creature* possessed = (Creature*)m_caster; player->RemoveAurasDueToSpell(51852); - player->SetCharm(NULL); + player->SetCharm(nullptr); player->SetClientControl(possessed, 0); - player->SetMover(NULL); + player->SetMover(nullptr); player->GetCamera().ResetView(); player->RemovePetActionBar(); @@ -8583,6 +8831,15 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) break; } + case 53110: // Devour Humanoid + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + unitTarget->CastSpell(m_caster, effect->CalculateSimpleValue(), true); + ((Creature*)unitTarget)->ForcedDespawn(8000); + return; + } case 54182: // An End to the Suffering: Quest Completion Script { if (!unitTarget) @@ -8723,7 +8980,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) case POWER_MANA: { int32 manapool = unitTarget->GetMaxPower(POWER_MANA) * 0.05; - unitTarget->CastCustomSpell(unitTarget, 59813, &manapool, NULL, NULL, true); + unitTarget->CastCustomSpell(unitTarget, 59813, &manapool, nullptr, nullptr, true); break; } case POWER_RAGE: @@ -8768,6 +9025,31 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(m_caster, 64909, true); return; } + case 62217: // Unstable Energy + case 62922: // Unstable Energy (h) + { + if (!unitTarget) + return; + + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } + case 62262: // Brightleaf Flux + { + if (!unitTarget) + return; + + if (unitTarget->HasAura(62239)) + unitTarget->RemoveAurasDueToSpell(62239); + else + { + uint32 stackAmount = urand(1, GetSpellStore()->LookupEntry(62239)->GetStackAmount()); + + for (uint8 i = 0; i < stackAmount; ++i) + unitTarget->CastSpell(unitTarget, 62239, true); + } + return; + } case 62282: // Iron Roots case 62440: // Strengthened Iron Roots case 63598: // Iron Roots (h) @@ -8832,6 +9114,25 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->RemoveAuraHolderFromStack(spellId, numStacks); return; } + case 62552: // Defend + { + if (!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 63119, true); + return; + } + case 62575: // Shield-Breaker (player) + case 68282: // Charge (player) + { + if (!unitTarget) + return; + + unitTarget->RemoveAuraHolderFromStack(62719); + unitTarget->RemoveAuraHolderFromStack(64100); + unitTarget->RemoveAuraHolderFromStack(64192); + return; + } case 62688: // Summon Wave - 10 Mob { uint32 spellId = effect->CalculateSimpleValue(); @@ -8849,6 +9150,74 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(unitTarget, 62708, true); return; } + case 63010: // Charge + case 68307: // Charge + case 68504: // Shield-Breaker + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + Unit* owner = unitTarget->GetCharmerOrOwnerPlayerOrPlayerItself(); + if (!owner) + return; + + owner->RemoveAuraHolderFromStack(62552); + owner->RemoveAuraHolderFromStack(63119); + + if (owner->HasAura(63132)) + { + owner->RemoveAurasDueToSpell(63132); + owner->CastSpell(unitTarget, 63131, true); + } + else if (owner->HasAura(63131)) + { + owner->RemoveAurasDueToSpell(63131); + owner->CastSpell(unitTarget, 63130, true); + } + else if (owner->HasAura(63130)) + owner->RemoveAurasDueToSpell(63130); + + return; + } + case 63027: // Proximity Mines + { + if (!unitTarget) + return; + + for (uint8 i = 0; i < 15; ++i) + unitTarget->CastSpell(unitTarget, 65347, true); + return; + } + case 63119: // Block! + case 64192: // Block! + { + if (!unitTarget) + return; + + if (unitTarget->HasAura(63132)) + return; + else if (unitTarget->HasAura(63131)) + { + unitTarget->RemoveAurasDueToSpell(63131); + unitTarget->CastSpell(unitTarget, 63132, true); // Shield Level 3 + } + else if (unitTarget->HasAura(63130)) + { + unitTarget->RemoveAurasDueToSpell(63130); + unitTarget->CastSpell(unitTarget, 63131, true); // Shield Level 2 + } + else + unitTarget->CastSpell(unitTarget, 63130, true); // Shield Level 1 + return; + } + case 63122: // Clear Insane + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } case 63633: // Summon Rubble { if (!unitTarget) @@ -8858,6 +9227,90 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); return; } + case 63667: // Napalm Shell + { + if (!unitTarget) + return; + + m_caster->CastSpell(unitTarget, m_caster->GetMap()->IsRegularDifficulty() ? 63666 : 65026, true); + return; + } + case 63681: // Rocket Strike + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + m_caster->CastSpell(unitTarget, 63036, true); + return; + } + case 63795: // Psychosis + case 65301: // Psychosis (h) + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->HasAura(effect->CalculateSimpleValue())) + return; + + unitTarget->RemoveAuraHolderFromStack(63050, 12); + return; + } + case 63803: // Brain Link + case 64164: // Lunatic Gaze (Yogg) + case 64168: // Lunatic Gaze (Skull) + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + uint8 removedAmount = 0; + switch (m_spellInfo->Id) + { + case 63803: removedAmount = 2; break; + case 64164: removedAmount = 4; break; + case 64168: removedAmount = 2; break; + } + + unitTarget->RemoveAuraHolderFromStack(63050, removedAmount); + return; + } + case 63993: // Cancel Illusion Room Aura + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + unitTarget->CastSpell(unitTarget, 63992, true); + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } + case 64059: // Induce Madness + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || !unitTarget->HasAura(effect->CalculateSimpleValue())) + return; + + unitTarget->RemoveAurasDueToSpell(63050); + return; + } + case 64069: // Match Health (Rank 1) + { + if (!unitTarget) + return; + + unitTarget->SetHealthPercent(m_caster->GetHealthPercent()); + return; + } + case 64123: // Lunge + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + unitTarget->CastSpell(unitTarget, unitTarget->GetMap()->IsRegularDifficulty() ? 64125 : 64126, true); + return; + } + case 64131: // Lunge + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + unitTarget->CastSpell(m_caster, effect->CalculateSimpleValue(), true); + return; + } case 64456: // Feral Essence Application Removal { if (!unitTarget) @@ -8867,6 +9320,22 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->RemoveAuraHolderFromStack(spellId); return; } + case 64466: // Empowering Shadows + { + if (!unitTarget) + return; + + unitTarget->CastSpell(m_caster, effect->CalculateSimpleValue(), true); + return; + } + case 64467: // Empowering Shadows + { + if (!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, m_caster->GetMap()->IsRegularDifficulty() ? 64468 : 64486, true); + return; + } case 64475: // Strength of the Creator { if (!unitTarget) @@ -8875,6 +9344,14 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->RemoveAuraHolderFromStack(64473); return; } + case 64623: // Frost Bomb + { + if (!unitTarget) + return; + + m_caster->CastSpell(unitTarget, 64627, true); + return; + } case 64767: // Stormhammer { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) @@ -8890,6 +9367,22 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) } return; } + case 64841: // Rapid Burst + { + if (!unitTarget) + return; + + unitTarget->CastSpell(m_caster, 63382, false); + return; + } + case 65238: // Shattered Illusion + { + if (!unitTarget) + return; + + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } case 66477: // Bountiful Feast { if (!unitTarget) @@ -8899,6 +9392,18 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(unitTarget, 66622, true); break; } + case 66545: // Summon Memory + { + if (!unitTarget) + return; + + uint32 memorySpells[25] = {66543, 66691, 66692, 66694, 66695, 66696, 66697, 66698, 66699, 66700, 66701, + 66702, 66703, 66704, 66705, 66706, 66707, 66708, 66709, 66710, 66711, 66712, 66713, 66714, 66715 + }; + + m_caster->CastSpell(unitTarget, memorySpells[urand(0, 24)], true); + return; + } case 66741: // Chum the Water { // maybe this check should be done sooner? @@ -8945,6 +9450,53 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) return; } + case 67547: // Clear Val'kyr Essence + { + if (!unitTarget) + return; + + unitTarget->RemoveAurasDueToSpell(67590); + unitTarget->RemoveAurasDueToSpell(65684); + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } + case 67590: // Powering Up + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + if (SpellAuraHolder* playerAura = unitTarget->GetSpellAuraHolder(m_spellInfo->Id)) + { + if (playerAura && playerAura->GetStackAmount() == 100) + { + if (unitTarget->HasAuraOfDifficulty(65684)) + unitTarget->CastSpell(unitTarget, 65724, true); + else if (unitTarget->HasAuraOfDifficulty(65686)) + unitTarget->CastSpell(unitTarget, 65748, true); + + unitTarget->RemoveAurasDueToSpell(m_spellInfo->Id); + } + } + return; + } + case 67751: // Ghoul Explode + { + if (!unitTarget) + return; + + unitTarget->InterruptNonMeleeSpells(false); + unitTarget->CastSpell(unitTarget, 67729, false); + return; + } + case 68084: // Clear Val'kyr Touch of Light/Dark + { + if (!unitTarget) + return; + + unitTarget->RemoveAurasDueToSpell(66001); + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } case 68861: // Consume Soul (ICC FoS: Bronjahm) if (unitTarget) unitTarget->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); @@ -8975,6 +9527,14 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(m_caster, 69023, true); return; } + case 69057: // Bone Spike Graveyard + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->HasAura(m_spellInfo->CalculateSimpleValue(EFFECT_INDEX_1))) + return; + + unitTarget->CastSpell(unitTarget, 69062, true); + return; + } case 69140: // Coldflame (random target selection) { if (!unitTarget) @@ -8991,6 +9551,22 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) unitTarget->CastSpell(unitTarget, effect->CalculateSimpleValue(), true); return; } + case 69195: // Pungent Blight + { + if (!unitTarget) + return; + + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } + case 69298: // Cancel Resistant to Blight + { + if (!unitTarget) + return; + + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } case 69377: // Fortitude { if (!unitTarget) @@ -9015,6 +9591,14 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, 72588, true); return; } + case 69828: // Halls of Reflection Clone + { + if (!unitTarget) + return; + + unitTarget->CastSpell(m_caster, effect->CalculateSimpleValue(), true); + return; + } case 71806: // Glittering Sparks { if (!unitTarget) @@ -9030,6 +9614,52 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) m_caster->CastSpell(unitTarget, 72036, true); return; } + case 72195: // Blood Link + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + uint32 auraStacks = 0; + if (SpellAuraHolder* playerAura = unitTarget->GetSpellAuraHolder(72371)) + auraStacks = playerAura->GetStackAmount(); + + int32 missingStacks = unitTarget->GetPower(unitTarget->GetPowerType()) - auraStacks; + if (missingStacks <= 0) + return; + + unitTarget->CastCustomSpell(unitTarget, 72371, &missingStacks, &missingStacks, nullptr, true); + return; + } + case 72219: // Gastric Bloat + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + uint32 auraStacks = 0; + if (SpellAuraHolder* playerAura = unitTarget->GetSpellAuraHolder(m_spellInfo->Id)) + auraStacks = playerAura->GetStackAmount(); + + // cast Gastric Explosion on 10 stacks + if (auraStacks >= 10) + unitTarget->CastSpell(unitTarget, 72227, true, NULL, NULL, m_caster->GetObjectGuid()); + return; + } + case 72257: // Remove Marks of the Fallen Champion + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + unitTarget->RemoveAurasDueToSpell(effect->CalculateSimpleValue()); + return; + } + case 72409: // Rune of Blood + { + if (!unitTarget) + return; + + unitTarget->CastSpell(m_caster, effect->CalculateSimpleValue(), true); + return; + } case 72705: // Coldflame (summon around the caster) { if (!unitTarget) @@ -9041,6 +9671,31 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) return; } + case 72900: // Start Halls of Reflection Quest AE + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + if (Player* target = (Player*)unitTarget) + target->CastSpell(target, target->GetTeam() == ALLIANCE ? 71351 : 71542, true); + return; + } + case 73142: // Bone Spike Graveyard (during storm) + { + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->HasAura(69065)) + return; + + uint32 spellId = 0; + switch (urand(0, 2)) + { + case 0: spellId = 69062; break; + case 1: spellId = 72669; break; + case 2: spellId = 72670; break; + } + + unitTarget->CastSpell(unitTarget, spellId, true); + return; + } case 74455: // Conflagration { if (!unitTarget) @@ -9289,7 +9944,7 @@ void Spell::EffectScriptEffect(SpellEffectEntry const* effect) { if (roll_chance_i((*i)->GetModifier()->m_amount)) { - unitTarget->CastSpell(unitTarget, 53398, true, NULL, (*i), m_caster->GetObjectGuid()); + unitTarget->CastSpell(unitTarget, 53398, true, nullptr, (*i), m_caster->GetObjectGuid()); break; } } @@ -10711,7 +11366,10 @@ void Spell::EffectWMODamage(SpellEffectEntry const* effect) { DEBUG_LOG("Effect: WMODamage"); - if (!gameObjTarget || gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) + if (!gameObjTarget) + return; + + if (gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) { sLog.outError("Spell::EffectWMODamage called without valid targets. Spell Id %u", m_spellInfo->Id); return; @@ -10732,7 +11390,10 @@ void Spell::EffectWMORepair(SpellEffectEntry const* effect) { DEBUG_LOG("Effect: WMORepair"); - if (!gameObjTarget || gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) + if (!gameObjTarget) + return; + + if (gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) { sLog.outError("Spell::EffectWMORepair called without valid targets. Spell Id %u", m_spellInfo->Id); return; @@ -10750,7 +11411,10 @@ void Spell::EffectWMOChange(SpellEffectEntry const* effect) { DEBUG_LOG("Effect: WMOChange"); - if (!gameObjTarget || gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) + if (!gameObjTarget) + return; + + if (gameObjTarget->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) { sLog.outError("Spell::EffectWMOChange called without valid targets. Spell Id %u", m_spellInfo->Id); return; @@ -11054,3 +11718,89 @@ void Spell::EffectKnockBackFromPosition(SpellEffectEntry const* effect) float verticalSpeed = damage * 0.1f; unitTarget->KnockBackWithAngle(angle, horizontalSpeed, verticalSpeed); } + +void Spell::EffectGravityPull(SpellEffectEntry const* effect) +{ + if (!unitTarget) + return; + + float x, y, z; + if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + m_targets.getDestination(x, y, z); + else + m_caster->GetPosition(x, y, z); + + float speed = float(effect->EffectMiscValue) * 0.15f; + float height = float(unitTarget->GetDistance(x, y, z) * 0.2f); + + unitTarget->GetMotionMaster()->MoveJump(x, y, z, speed, height); +} + +void Spell::EffectCreateTamedPet(SpellEffectEntry const* effect) +{ + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->getClass() != CLASS_HUNTER) + return; + + uint32 creatureEntry = effect->EffectMiscValue; + + CreatureInfo const* cInfo = ObjectMgr::GetCreatureTemplate(creatureEntry); + if (creatureEntry && !cInfo) + { + sLog.outErrorDb("EffectCreateTamedPet: Creature entry %u not found for spell %u.", creatureEntry, m_spellInfo->Id); + return; + } + + Pet* newTamedPet = new Pet; + CreatureCreatePos pos(unitTarget, unitTarget->GetOrientation()); + + Map* map = unitTarget->GetMap(); + uint32 petNumber = sObjectMgr.GeneratePetNumber(); + if (!newTamedPet->Create(map->GenerateLocalLowGuid(HIGHGUID_PET), pos, cInfo, petNumber)) + { + delete newTamedPet; + return; + } + + newTamedPet->SetRespawnCoord(pos); + newTamedPet->setPetType(HUNTER_PET); + + newTamedPet->SetOwnerGuid(unitTarget->GetObjectGuid()); + newTamedPet->SetCreatorGuid(unitTarget->GetObjectGuid()); + newTamedPet->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + newTamedPet->setFaction(unitTarget->getFaction()); + newTamedPet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); + newTamedPet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); + newTamedPet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000); + newTamedPet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + + newTamedPet->GetCharmInfo()->SetPetNumber(petNumber, true); + + if (unitTarget->IsPvP()) + newTamedPet->SetPvP(true); + + if (unitTarget->IsFFAPvP()) + newTamedPet->SetFFAPvP(true); + + newTamedPet->InitStatsForLevel(unitTarget->getLevel(), unitTarget); + newTamedPet->InitPetCreateSpells(); + newTamedPet->InitLevelupSpellsForLevel(); + newTamedPet->InitTalentForLevel(); + + newTamedPet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); + newTamedPet->SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_ABANDONED); + + newTamedPet->AIM_Initialize(); + newTamedPet->SetHealth(newTamedPet->GetMaxHealth()); + newTamedPet->SetPower(POWER_MANA, newTamedPet->GetMaxPower(POWER_MANA)); + + float x, y, z; + unitTarget->GetClosePoint(x, y, z, newTamedPet->GetObjectBoundingRadius()); + newTamedPet->Relocate(x, y, z, unitTarget->GetOrientation()); + + map->Add((Creature*)newTamedPet); + m_caster->SetPet(newTamedPet); + + newTamedPet->SavePetToDB(PET_SAVE_AS_CURRENT); + ((Player*)unitTarget)->PetSpellInitialize(); +} + diff --git a/src/game/WorldHandlers/SpellHandler.cpp b/src/game/WorldHandlers/SpellHandler.cpp index 9a3ab92b3..66a6eed19 100644 --- a/src/game/WorldHandlers/SpellHandler.cpp +++ b/src/game/WorldHandlers/SpellHandler.cpp @@ -602,6 +602,9 @@ void WorldSession::HandleSelfResOpcode(WorldPacket& /*recv_data*/) { DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "WORLD: CMSG_SELF_RES"); // empty opcode + if (_player->HasAuraType(SPELL_AURA_PREVENT_RESURRECTION)) + return; + if (_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)) { SpellEntry const* spellInfo = sSpellStore.LookupEntry(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)); @@ -617,7 +620,8 @@ void WorldSession::HandleSpellClick(WorldPacket& recv_data) ObjectGuid guid; recv_data >> guid; - if (_player->IsInCombat()) // client prevent click and set different icon at combat state + // client prevent click and set different icon at combat state; however combat state is allowed for dungeons + if (_player->IsInCombat() && !_player->GetMap()->IsDungeon()) return; Creature* unit = _player->GetMap()->GetAnyTypeCreature(guid); @@ -629,10 +633,16 @@ void WorldSession::HandleSpellClick(WorldPacket& recv_data) { if (itr->second.IsFitToRequirements(_player, unit)) { + if (sScriptMgr.OnNpcSpellClick(_player, unit, itr->second.spellId)) + return; + Unit* caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit; Unit* target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit; - caster->CastSpell(target, itr->second.spellId, true); + if (itr->second.spellId) + caster->CastSpell(target, itr->second.spellId, true); + else + sLog.outError("WorldSession::HandleSpellClick: npc_spell_click with entry %u has 0 in spell_id. Not handled custom case?", unit->GetEntry()); } } } diff --git a/src/game/WorldHandlers/TradeHandler.cpp b/src/game/WorldHandlers/TradeHandler.cpp index 8920d1746..77e7852a4 100644 --- a/src/game/WorldHandlers/TradeHandler.cpp +++ b/src/game/WorldHandlers/TradeHandler.cpp @@ -312,13 +312,19 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& recvPacket) if (!his_trade) return; - Item* myItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; - Item* hisItems[TRADE_SLOT_TRADED_COUNT] = { NULL, NULL, NULL, NULL, NULL, NULL }; - bool myCanCompleteTrade = true, hisCanCompleteTrade = true; + Item* myItems[TRADE_SLOT_TRADED_COUNT] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + Item* hisItems[TRADE_SLOT_TRADED_COUNT] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; // set before checks to properly undo at problems (it already set in to client) my_trade->SetAccepted(true); + if (!_player->IsWithinDistInMap(trader, TRADE_DISTANCE, false)) + { + SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); + my_trade->SetAccepted(false); + return; + } + // not accept case incorrect money amount if (my_trade->GetMoney() > _player->GetMoney()) { @@ -361,10 +367,10 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& recvPacket) { setAcceptTradeMode(my_trade, his_trade, myItems, hisItems); - Spell* my_spell = NULL; + Spell* my_spell = nullptr; SpellCastTargets my_targets; - Spell* his_spell = NULL; + Spell* his_spell = nullptr; SpellCastTargets his_targets; // not accept if spell can't be casted now (cheating) @@ -444,8 +450,8 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& recvPacket) trader->GetSession()->SendTradeStatus(TRADE_STATUS_TRADE_ACCEPT); // test if item will fit in each inventory - hisCanCompleteTrade = (trader->CanStoreItems(myItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); - myCanCompleteTrade = (_player->CanStoreItems(hisItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); + bool hisCanCompleteTrade = (trader->CanStoreItems(myItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); + bool myCanCompleteTrade = (_player->CanStoreItems(hisItems, TRADE_SLOT_TRADED_COUNT) == EQUIP_ERR_OK); clearAcceptTradeMode(myItems, hisItems); @@ -523,9 +529,9 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& recvPacket) // cleanup clearAcceptTradeMode(my_trade, his_trade); delete _player->m_trade; - _player->m_trade = NULL; + _player->m_trade = nullptr; delete trader->m_trade; - trader->m_trade = NULL; + trader->m_trade = nullptr; // desynchronized with the other saves here (SaveInventoryAndGoldToDB() not have own transaction guards) CharacterDatabase.BeginTransaction(); diff --git a/src/game/WorldHandlers/UnitAuraProcHandler.cpp b/src/game/WorldHandlers/UnitAuraProcHandler.cpp index 074b2dcba..fd04fc594 100644 --- a/src/game/WorldHandlers/UnitAuraProcHandler.cpp +++ b/src/game/WorldHandlers/UnitAuraProcHandler.cpp @@ -56,7 +56,7 @@ pAuraProcHandler AuraProcHandler[TOTAL_AURAS] = &Unit::HandleNULLProc, // 15 SPELL_AURA_DAMAGE_SHIELD &Unit::HandleNULLProc, // 16 SPELL_AURA_MOD_STEALTH &Unit::HandleNULLProc, // 17 SPELL_AURA_MOD_STEALTH_DETECT - &Unit::HandleNULLProc, // 18 SPELL_AURA_MOD_INVISIBILITY + &Unit::HandleInvisibilityAuraProc, // 18 SPELL_AURA_MOD_INVISIBILITY &Unit::HandleNULLProc, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION &Unit::HandleNULLProc, // 20 SPELL_AURA_OBS_MOD_HEALTH &Unit::HandleNULLProc, // 21 SPELL_AURA_OBS_MOD_MANA @@ -632,7 +632,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura int32 triggerAmount = triggeredByAura->GetModifier()->m_amount; Item* castItem = triggeredByAura->GetCastItemGuid() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGuid()) : NULL; + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGuid()) : nullptr; // some dummy spells have trigger spell in spell data already (from 3.0.3) uint32 triggered_spell_id = dummySpellEffect->EffectApplyAuraName == SPELL_AURA_DUMMY ? dummySpellEffect->EffectTriggerSpell : 0; @@ -645,7 +645,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura { switch (dummySpell->Id) { - // Eye for an Eye + // Eye for an Eye case 9799: case 25988: { @@ -676,7 +676,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura case 21063: triggered_spell_id = 21064; break; - // Unstable Power + // Unstable Power case 24658: { if (!procSpell || procSpell->Id == 24659) @@ -982,7 +982,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura // cast ??? Arcane Bolt if Exalted by Scryers*/ case 46569: return SPELL_AURA_PROC_FAILED; // old unused version - // Living Seed + // Living Seed case 48504: { triggered_spell_id = 48503; @@ -1021,31 +1021,56 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura if (triggeredByAura->GetStackAmount() > 1 && !triggeredByAura->GetHolder()->ModStackAmount(-1)) return SPELL_AURA_PROC_CANT_TRIGGER; } + // Grim Reprisal + case 63305: + { + // also update caster entry if required + if (Unit* caster = triggeredByAura->GetCaster()) + { + if (caster->GetEntry() != 33943 && caster->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)caster)->UpdateEntry(33943); + caster->CastSpell(caster, 64017, true); + } + } + + triggered_spell_id = 64039; + basepoints[EFFECT_INDEX_0] = damage; + break; + } // Glyph of Life Tap case 63320: triggered_spell_id = 63321; break; - // Meteor Fists + // Retaliation + case 65932: + triggered_spell_id = 65934; + break; + // Earth Shield + case 66063: + triggered_spell_id = 66064; + break; + // Meteor Fists case 66725: case 68161: triggered_spell_id = 66765; break; - // Meteor Fists + // Meteor Fists case 66808: case 68160: triggered_spell_id = 66809; break; - // Shiny Shard of the Scale - Equip Effect + // Shiny Shard of the Scale - Equip Effect case 69739: // Cauterizing Heal or Searing Flame triggered_spell_id = (procFlag & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL) ? 69734 : 69730; break; - // Purified Shard of the Scale - Equip Effect + // Purified Shard of the Scale - Equip Effect case 69755: // Cauterizing Heal or Searing Flame triggered_spell_id = (procFlag & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL) ? 69733 : 69729; break; - // Item - Shadowmourne Legendary + // Item - Shadowmourne Legendary case 71903: { if (!roll_chance_i(triggerAmount)) @@ -1070,6 +1095,10 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura } break; } + // Blood Link + case 72178: + triggered_spell_id = 72195; + break; } break; } @@ -1161,7 +1190,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura } switch (dummySpell->Id) { - // Ignite + // Ignite case 11119: case 11120: case 12846: @@ -1292,7 +1321,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura RemoveAurasDueToSpell(triggeredByAura->GetId()); // Cast finish spell (triggeredByAura already not exist!) - CastSpell(this, 27285, true, castItem, NULL, casterGuid); + CastSpell(this, 27285, true, castItem, nullptr, casterGuid); return SPELL_AURA_PROC_OK; // no hidden cooldown } @@ -1314,7 +1343,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura RemoveAurasDueToSpell(triggeredByAura->GetId()); // Cast finish spell (triggeredByAura already not exist!) - CastSpell(this, 32865, true, castItem, NULL, casterGuid); + CastSpell(this, 32865, true, castItem, nullptr, casterGuid); return SPELL_AURA_PROC_OK; // no hidden cooldown } // Damage counting @@ -1333,7 +1362,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura } switch (dummySpell->Id) { - // Nightfall & Glyph of Corruption + // Nightfall & Glyph of Corruption case 18094: case 18095: case 56218: @@ -1410,7 +1439,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura switch (dummySpell->SpellIconID) { - // Improved Shadowform + // Improved Shadowform case 217: { if (!roll_chance_i(triggerAmount)) @@ -1463,7 +1492,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura switch (dummySpell->Id) { - // Vampiric Embrace + // Vampiric Embrace case 15286: { // Return if self damage @@ -1473,7 +1502,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura // Heal amount - Self/Team int32 team = triggerAmount * damage / 500; int32 self = triggerAmount * damage / 100 - team; - CastCustomSpell(this, 15290, &team, &self, NULL, true, castItem, triggeredByAura); + CastCustomSpell(this, 15290, &team, &self, nullptr, true, castItem, triggeredByAura); return SPELL_AURA_PROC_OK; // no hidden cooldown } // Priest Tier 6 Trinket (Ashtongue Talisman of Acumen) @@ -1549,7 +1578,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura { switch (dummySpell->Id) { - // Leader of the Pack + // Leader of the Pack case 24932: { // dummy m_amount store health percent (!=0 if Improved Leader of the Pack applied) @@ -1572,7 +1601,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura if (SpellEntry const* manaCastEntry = sSpellStore.LookupEntry(60889)) { int32 mana_percent = manaCastEntry->CalculateSimpleValue(EFFECT_INDEX_0) * heal_percent; - CastCustomSpell(this, manaCastEntry, &mana_percent, NULL, NULL, true, castItem, triggeredByAura); + CastCustomSpell(this, manaCastEntry, &mana_percent, nullptr, nullptr, true, castItem, triggeredByAura); } } break; @@ -1669,14 +1698,14 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura else radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(procSpell->rangeIndex)); - ((Player*)this)->ApplySpellMod(procSpell->Id, SPELLMOD_RADIUS, radius, NULL); + ((Player*)this)->ApplySpellMod(procSpell->Id, SPELLMOD_RADIUS, radius); Unit* second = pVictim->SelectRandomFriendlyTarget(pVictim, radius); if (!second) return SPELL_AURA_PROC_FAILED; - pVictim->CastSpell(second, procSpell, true, NULL, triggeredByAura, GetObjectGuid()); + pVictim->CastSpell(second, procSpell, true, nullptr, triggeredByAura, GetObjectGuid()); return SPELL_AURA_PROC_OK; } // Item - Druid T10 Balance 4P Bonus @@ -1750,14 +1779,14 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura { switch (dummySpell->Id) { - // Clean Escape + // Clean Escape case 23582: // triggered spell have same masks and etc with main Vanish spell if (!procSpell || procSpell->GetSpellEffectIdByIndex(EFFECT_INDEX_0) == SPELL_EFFECT_NONE) return SPELL_AURA_PROC_FAILED; triggered_spell_id = 23583; break; - // Deadly Throw Interrupt + // Deadly Throw Interrupt case 32748: { // Prevent cast Deadly Throw Interrupt on self from last effect (apply dummy) of Deadly Throw @@ -1879,7 +1908,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura // Glyph of Mend Pet if (dummySpell->Id == 57870) { - pVictim->CastSpell(pVictim, 57894, true, NULL, NULL, GetObjectGuid()); + pVictim->CastSpell(pVictim, 57894, true, nullptr, nullptr, GetObjectGuid()); return SPELL_AURA_PROC_OK; } // Misdirection @@ -1920,7 +1949,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura } switch (dummySpell->Id) { - // Judgement of Light + // Judgement of Light case 20185: { // only at real damage @@ -1928,7 +1957,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura return SPELL_AURA_PROC_FAILED; basepoints[0] = int32(pVictim->GetMaxHealth() * triggeredByAura->GetModifier()->m_amount / 100); - pVictim->CastCustomSpell(pVictim, 20267, &basepoints[0], NULL, NULL, true, NULL, triggeredByAura); + pVictim->CastCustomSpell(pVictim, 20267, &basepoints[0], nullptr, nullptr, true, nullptr, triggeredByAura); return SPELL_AURA_PROC_OK; } // Judgement of Wisdom @@ -1942,7 +1971,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura { // 2% of maximum base mana basepoints[0] = int32(pVictim->GetCreateMana() * 2 / 100); - pVictim->CastCustomSpell(pVictim, 20268, &basepoints[0], NULL, NULL, true, NULL, triggeredByAura); + pVictim->CastCustomSpell(pVictim, 20268, &basepoints[0], nullptr, nullptr, true, nullptr, triggeredByAura); } return SPELL_AURA_PROC_OK; } @@ -1950,11 +1979,11 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura case 20335: triggered_spell_id = 21183; break; - // Heart of the Crusader (Rank 2) + // Heart of the Crusader (Rank 2) case 20336: triggered_spell_id = 54498; break; - // Heart of the Crusader (Rank 3) + // Heart of the Crusader (Rank 3) case 20337: triggered_spell_id = 54499; break; @@ -1971,6 +2000,8 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura return SPELL_AURA_PROC_FAILED; } break; + default: + break; } // Holy Power (Redemption Armor set) case 28789: @@ -2042,7 +2073,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura } } if (stacks >= 5) - CastSpell(target, 42463, true, NULL, triggeredByAura); + CastSpell(target, 42463, true, nullptr, triggeredByAura); break; } // Judgements of the Wise @@ -2057,9 +2088,9 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura triggered_spell_id = 31930; // Replenishment - CastSpell(this, 57669, true, NULL, triggeredByAura); + CastSpell(this, 57669, true, nullptr, triggeredByAura); break; - // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal) + // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal) case 40470: { if (!procSpell) @@ -2100,7 +2131,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura return SPELL_AURA_PROC_FAILED; // find caster main aura at beacon - Aura* dummy = NULL; + Aura* dummy = nullptr; Unit::AuraList const& baa = beacon->GetAurasByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL); for (Unit::AuraList::const_iterator i = baa.begin(); i != baa.end(); ++i) { @@ -2119,7 +2150,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura basepoints[0] = triggeredByAura->GetModifier()->m_amount * damage / 100; // cast with original caster set but beacon to beacon for apply caster mods and avoid LoS check - beacon->CastCustomSpell(beacon, triggered_spell_id, &basepoints[0], NULL, NULL, true, castItem, triggeredByAura, pVictim->GetObjectGuid()); + beacon->CastCustomSpell(beacon, triggered_spell_id, &basepoints[0], nullptr, nullptr, true, castItem, triggeredByAura, pVictim->GetObjectGuid()); return SPELL_AURA_PROC_OK; } // Seal of Corruption (damage calc on apply aura) @@ -2144,7 +2175,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura } } if (stacks >= 5) - CastSpell(target, 53739, true, NULL, triggeredByAura); + CastSpell(target, 53739, true, nullptr, triggeredByAura); break; } // Glyph of Holy Light @@ -2249,7 +2280,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura { switch (dummySpell->Id) { - // Totemic Power (The Earthshatterer set) + // Totemic Power (The Earthshatterer set) case 28823: { if (!pVictim) @@ -2351,11 +2382,11 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura // apply cooldown before cast to prevent processing itself if (cooldown) - ((Player*)this)->AddSpellCooldown(dummySpell->Id, 0, time(NULL) + cooldown); + ((Player*)this)->AddSpellCooldown(dummySpell->Id, 0, time(nullptr) + cooldown); // Attack Twice for (uint32 i = 0; i < 2; ++i) - CastCustomSpell(pVictim, triggered_spell_id, &basepoints[0], NULL, NULL, true, castItem, triggeredByAura); + CastCustomSpell(pVictim, triggered_spell_id, &basepoints[0], nullptr, nullptr, true, castItem, triggeredByAura); return SPELL_AURA_PROC_OK; } @@ -2574,7 +2605,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura // Every Lightning Bolt and Chain Lightning spell have duplicate vs half damage and zero cost switch (procSpell->Id) { - // Lightning Bolt + // Lightning Bolt case 403: spellId = 45284; break; // Rank 1 case 529: spellId = 45286; break; // Rank 2 case 548: spellId = 45287; break; // Rank 3 @@ -2589,7 +2620,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura case 25449: spellId = 45296; break; // Rank 12 case 49237: spellId = 49239; break; // Rank 13 case 49238: spellId = 49240; break; // Rank 14 - // Chain Lightning + // Chain Lightning case 421: spellId = 45297; break; // Rank 1 case 930: spellId = 45298; break; // Rank 2 case 2860: spellId = 45299; break; // Rank 3 @@ -2610,7 +2641,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura CastSpell(pVictim, spellId, true, castItem, triggeredByAura); if (cooldown && GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->AddSpellCooldown(dummySpell->Id, 0, time(NULL) + cooldown); + ((Player*)this)->AddSpellCooldown(dummySpell->Id, 0, time(nullptr) + cooldown); return SPELL_AURA_PROC_OK; } @@ -2729,7 +2760,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura switch (procSpell->Id) { - // Obliterate + // Obliterate case 49020: // Rank 1 triggered_spell_id = 66198; break; case 51423: // Rank 2 @@ -2738,7 +2769,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura triggered_spell_id = 66973; break; case 51425: // Rank 4 triggered_spell_id = 66974; break; - // Frost Strike + // Frost Strike case 49143: // Rank 1 triggered_spell_id = 66196; break; case 51416: // Rank 2 @@ -2751,7 +2782,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura triggered_spell_id = 66961; break; case 55268: // Rank 6 triggered_spell_id = 66962; break; - // Plague Strike + // Plague Strike case 45462: // Rank 1 triggered_spell_id = 66216; break; case 49917: // Rank 2 @@ -2764,7 +2795,7 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura triggered_spell_id = 66991; break; case 49921: // Rank 6 triggered_spell_id = 66992; break; - // Death Strike + // Death Strike case 49998: // Rank 1 triggered_spell_id = 66188; break; case 49999: // Rank 2 @@ -2775,10 +2806,10 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura triggered_spell_id = 66952; break; case 49924: // Rank 5 triggered_spell_id = 66953; break; - // Rune Strike + // Rune Strike case 56815: triggered_spell_id = 66217; break; - // Blood Strike + // Blood Strike case 45902: // Rank 1 triggered_spell_id = 66215; break; case 49926: // Rank 2 @@ -2828,13 +2859,6 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura // triggered_spell_id in spell data break; } - // Unholy Blight - if (dummySpell->SpellIconID == 1494) // id = 49194 in dbc, spelliconid = 1494 - { - basepoints[0] = int32(damage / 10); // Deal 10% of death coil damage - triggered_spell_id = 50536; - break; - } break; } default: @@ -2862,15 +2886,15 @@ SpellAuraProcResult Unit::HandleDummyAuraProc(Unit* pVictim, uint32 damage, Aura if (basepoints[EFFECT_INDEX_0] || basepoints[EFFECT_INDEX_1] || basepoints[EFFECT_INDEX_2]) CastCustomSpell(target, triggered_spell_id, - basepoints[EFFECT_INDEX_0] ? &basepoints[EFFECT_INDEX_0] : NULL, - basepoints[EFFECT_INDEX_1] ? &basepoints[EFFECT_INDEX_1] : NULL, - basepoints[EFFECT_INDEX_2] ? &basepoints[EFFECT_INDEX_2] : NULL, + basepoints[EFFECT_INDEX_0] ? &basepoints[EFFECT_INDEX_0] : nullptr, + basepoints[EFFECT_INDEX_1] ? &basepoints[EFFECT_INDEX_1] : nullptr, + basepoints[EFFECT_INDEX_2] ? &basepoints[EFFECT_INDEX_2] : nullptr, true, castItem, triggeredByAura); else CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura); if (cooldown && GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->AddSpellCooldown(triggered_spell_id, 0, time(NULL) + cooldown); + ((Player*)this)->AddSpellCooldown(triggered_spell_id, 0, time(nullptr) + cooldown); return SPELL_AURA_PROC_OK; } @@ -2888,14 +2912,14 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d // Set trigger spell id, target, custom basepoints SpellEffectEntry const* spellEffect = auraSpellInfo->GetSpellEffect(triggeredByAura->GetEffIndex()); uint32 trigger_spell_id = spellEffect ? spellEffect->EffectTriggerSpell : 0; - Unit* target = NULL; + Unit* target = nullptr; int32 basepoints[MAX_EFFECT_INDEX] = {0, 0, 0}; if (triggeredByAura->GetModifier()->m_auraname == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE) basepoints[0] = triggerAmount; Item* castItem = triggeredByAura->GetCastItemGuid() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGuid()) : NULL; + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGuid()) : nullptr; // Try handle unknown trigger spells // Custom requirements (not listed in procEx) Warning! damage dealing after this @@ -2906,33 +2930,33 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d { switch (auraSpellInfo->Id) { - // case 191: // Elemental Response - // switch (procSpell->School) - // { - // case SPELL_SCHOOL_FIRE: trigger_spell_id = 34192; break; - // case SPELL_SCHOOL_FROST: trigger_spell_id = 34193; break; - // case SPELL_SCHOOL_ARCANE:trigger_spell_id = 34194; break; - // case SPELL_SCHOOL_NATURE:trigger_spell_id = 34195; break; - // case SPELL_SCHOOL_SHADOW:trigger_spell_id = 34196; break; - // case SPELL_SCHOOL_HOLY: trigger_spell_id = 34197; break; - // case SPELL_SCHOOL_NORMAL:trigger_spell_id = 34198; break; - // } - // break; - // case 5301: break; // Defensive State (DND) - // case 7137: break: // Shadow Charge (Rank 1) - // case 7377: break: // Take Immune Periodic Damage - // case 13358: break; // Defensive State (DND) - // case 16092: break; // Defensive State (DND) - // case 18943: break; // Double Attack - // case 19194: break; // Double Attack - // case 19817: break; // Double Attack - // case 19818: break; // Double Attack - // case 22835: break; // Drunken Rage - // trigger_spell_id = 14822; break; + // case 191: // Elemental Response + // switch (procSpell->School) + // { + // case SPELL_SCHOOL_FIRE: trigger_spell_id = 34192; break; + // case SPELL_SCHOOL_FROST: trigger_spell_id = 34193; break; + // case SPELL_SCHOOL_ARCANE:trigger_spell_id = 34194; break; + // case SPELL_SCHOOL_NATURE:trigger_spell_id = 34195; break; + // case SPELL_SCHOOL_SHADOW:trigger_spell_id = 34196; break; + // case SPELL_SCHOOL_HOLY: trigger_spell_id = 34197; break; + // case SPELL_SCHOOL_NORMAL:trigger_spell_id = 34198; break; + // } + // break; + // case 5301: break; // Defensive State (DND) + // case 7137: break: // Shadow Charge (Rank 1) + // case 7377: break: // Take Immune Periodic Damage + // case 13358: break; // Defensive State (DND) + // case 16092: break; // Defensive State (DND) + // case 18943: break; // Double Attack + // case 19194: break; // Double Attack + // case 19817: break; // Double Attack + // case 19818: break; // Double Attack + // case 22835: break; // Drunken Rage + // trigger_spell_id = 14822; break; case 23780: // Aegis of Preservation (Aegis of Preservation trinket) trigger_spell_id = 23781; break; - // case 24949: break; // Defensive State 2 (DND) + // case 24949: break; // Defensive State 2 (DND) case 27522: // Mana Drain Trigger case 40336: // Mana Drain Trigger case 46939: // Black Bow of the Betrayer @@ -2956,56 +2980,56 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d case 33896: // Desperate Defense (Stonescythe Whelp, Stonescythe Alpha, Stonescythe Ambusher) trigger_spell_id = 33898; break; - // case 34082: break; // Advantaged State (DND) - // case 34783: break: // Spell Reflection - // case 35205: break: // Vanish - // case 35321: break; // Gushing Wound - // case 36096: break: // Spell Reflection - // case 36207: break: // Steal Weapon - // case 36576: break: // Shaleskin (Shaleskin Flayer, Shaleskin Ripper) 30023 trigger - // case 37030: break; // Chaotic Temperament - // case 38363: break; // Gushing Wound - // case 39215: break; // Gushing Wound - // case 40250: break; // Improved Duration - // case 40329: break; // Demo Shout Sensor - // case 40364: break; // Entangling Roots Sensor - // case 41054: break; // Copy Weapon - // trigger_spell_id = 41055; break; - // case 41248: break; // Consuming Strikes - // trigger_spell_id = 41249; break; - // case 42730: break: // Woe Strike - // case 43453: break: // Rune Ward - // case 43504: break; // Alterac Valley OnKill Proc Aura - // case 44326: break: // Pure Energy Passive - // case 44526: break; // Hate Monster (Spar) (30 sec) - // case 44527: break; // Hate Monster (Spar Buddy) (30 sec) - // case 44819: break; // Hate Monster (Spar Buddy) (>30% Health) - // case 44820: break; // Hate Monster (Spar) (<30%) + // case 34082: break; // Advantaged State (DND) + // case 34783: break: // Spell Reflection + // case 35205: break: // Vanish + // case 35321: break; // Gushing Wound + // case 36096: break: // Spell Reflection + // case 36207: break: // Steal Weapon + // case 36576: break: // Shaleskin (Shaleskin Flayer, Shaleskin Ripper) 30023 trigger + // case 37030: break; // Chaotic Temperament + // case 38363: break; // Gushing Wound + // case 39215: break; // Gushing Wound + // case 40250: break; // Improved Duration + // case 40329: break; // Demo Shout Sensor + // case 40364: break; // Entangling Roots Sensor + // case 41054: break; // Copy Weapon + // trigger_spell_id = 41055; break; + // case 41248: break; // Consuming Strikes + // trigger_spell_id = 41249; break; + // case 42730: break: // Woe Strike + // case 43453: break: // Rune Ward + // case 43504: break; // Alterac Valley OnKill Proc Aura + // case 44326: break: // Pure Energy Passive + // case 44526: break; // Hate Monster (Spar) (30 sec) + // case 44527: break; // Hate Monster (Spar Buddy) (30 sec) + // case 44819: break; // Hate Monster (Spar Buddy) (>30% Health) + // case 44820: break; // Hate Monster (Spar) (<30%) case 45057: // Evasive Maneuvers (Commendation of Kael`thas trinket) // reduce you below $s1% health (in fact in this specific case can proc from any attack while health in result less $s1%) if (int32(GetHealth()) - int32(damage) >= int32(GetMaxHealth() * triggerAmount / 100)) return SPELL_AURA_PROC_FAILED; break; - // case 45903: break: // Offensive State - // case 46146: break: // [PH] Ahune Spanky Hands + // case 45903: break: // Offensive State + // case 46146: break: // [PH] Ahune Spanky Hands case 43820: // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket) // Pct value stored in dummy basepoints[0] = pVictim->GetCreateHealth() * auraSpellInfo->CalculateSimpleValue(EFFECT_INDEX_1) / 100; target = pVictim; break; - // case 45205: break; // Copy Offhand Weapon - // case 45343: break; // Dark Flame Aura - // case 47300: break; // Dark Flame Aura - // case 48876: break; // Beast's Mark - // trigger_spell_id = 48877; break; - // case 49059: break; // Horde, Hate Monster (Spar Buddy) (>30% Health) - // case 50051: break; // Ethereal Pet Aura - // case 50689: break; // Blood Presence (Rank 1) - // case 50844: break; // Blood Mirror - // case 52856: break; // Charge - // case 54072: break; // Knockback Ball Passive - // case 54476: break; // Blood Presence - // case 54775: break; // Abandon Vehicle on Poly + // case 45205: break; // Copy Offhand Weapon + // case 45343: break; // Dark Flame Aura + // case 47300: break; // Dark Flame Aura + // case 48876: break; // Beast's Mark + // trigger_spell_id = 48877; break; + // case 49059: break; // Horde, Hate Monster (Spar Buddy) (>30% Health) + // case 50051: break; // Ethereal Pet Aura + // case 50689: break; // Blood Presence (Rank 1) + // case 50844: break; // Blood Mirror + // case 52856: break; // Charge + // case 54072: break; // Knockback Ball Passive + // case 54476: break; // Blood Presence + // case 54775: break; // Abandon Vehicle on Poly case 57345: // Darkmoon Card: Greatness { float stat = 0.0f; @@ -3027,6 +3051,12 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d // case 59288: break; // Infra-Green Shield // case 59532: break; // Abandon Passengers on Poly // case 59735: break: // Woe Strike + case 64148: // Diminsh Power + { + if (Unit* caster = triggeredByAura->GetCaster()) + caster->InterruptNonMeleeSpells(false); + return SPELL_AURA_PROC_OK; + } case 64415: // // Val'anyr Hammer of Ancient Kings - Equip Effect { // for DOT procs @@ -3038,7 +3068,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d { trigger_spell_id = 64442; - // need Scale damage base at stack size + // need scale damage base at stack size if (SpellEntry const* trigEntry = sSpellStore.LookupEntry(trigger_spell_id)) basepoints[EFFECT_INDEX_0] = trigEntry->CalculateSimpleValue(EFFECT_INDEX_0) * triggeredByAura->GetStackAmount(); @@ -3053,7 +3083,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d trigger_spell_id = 64569; - // need Scale damage base at stack size + // need scale damage base at stack size if (SpellEntry const* trigEntry = sSpellStore.LookupEntry(trigger_spell_id)) basepoints[EFFECT_INDEX_0] = trigEntry->CalculateSimpleValue(EFFECT_INDEX_0) * triggeredByAura->GetStackAmount(); @@ -3082,7 +3112,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d int32 basepoints = (int32)(damage * 0.45f); if (Unit* caster = triggeredByAura->GetCaster()) // Actually this spell should be sent with SMSG_SPELL_START - CastCustomSpell(caster, 69034, &basepoints, NULL, NULL, true, NULL, triggeredByAura, GetObjectGuid()); + CastCustomSpell(caster, 69034, &basepoints, nullptr, nullptr, true, nullptr, triggeredByAura, GetObjectGuid()); return SPELL_AURA_PROC_OK; } @@ -3133,7 +3163,6 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d { float weaponDamage; // DW should benefit of attack power, damage percent mods etc. - // TODO: check if using offhand damage is correct and if it should be divided by 2 if (haveOffhandWeapon() && getAttackTimer(BASE_ATTACK) > getAttackTimer(OFF_ATTACK)) weaponDamage = (GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE)) / 2; else @@ -3144,7 +3173,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d case 12834: basepoints[EFFECT_INDEX_0] = int32(weaponDamage * 16 / 100); break; case 12849: basepoints[EFFECT_INDEX_0] = int32(weaponDamage * 32 / 100); break; case 12867: basepoints[EFFECT_INDEX_0] = int32(weaponDamage * 48 / 100); break; - // Impossible case + // Impossible case default: sLog.outError("Unit::HandleProcTriggerSpellAuraProc: DW unknown spell rank %u", auraSpellInfo->Id); return SPELL_AURA_PROC_FAILED; @@ -3165,7 +3194,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d else if (auraSpellInfo->Id == 50421) // Scent of Blood { RemoveAuraHolderFromStack(50421); - trigger_spell_id = 50422; + trigger_spell_id = 50422; target = this; break; } @@ -3184,7 +3213,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d { // basepoints of trigger spell stored in dummyeffect of spellProto int32 basepoints = GetMaxPower(POWER_MANA) * (*i)->GetSpellProto()->CalculateSimpleValue(EFFECT_INDEX_2) / 100; - CastCustomSpell(this, 18371, &basepoints, NULL, NULL, true, castItem, triggeredByAura); + CastCustomSpell(this, 18371, &basepoints, nullptr, nullptr, true, castItem, triggeredByAura); break; } } @@ -3204,6 +3233,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d { if (!procSpell) return SPELL_AURA_PROC_FAILED; + switch (GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) { case SPELL_SCHOOL_HOLY: trigger_spell_id = 54370; break; @@ -3417,7 +3447,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d if (!pVictim || !pVictim->IsAlive()) return SPELL_AURA_PROC_FAILED; // stacking - CastSpell(this, 37658, true, NULL, triggeredByAura); + CastSpell(this, 37658, true, nullptr, triggeredByAura); Aura* dummy = GetDummyAura(37658); // release at 3 aura in stack (cont contain in basepoint of trigger aura) @@ -3441,7 +3471,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d if (!pVictim || !pVictim->IsAlive()) return SPELL_AURA_PROC_FAILED; // stacking - CastSpell(this, 54842, true, NULL, triggeredByAura); + CastSpell(this, 54842, true, nullptr, triggeredByAura); // counting Aura* dummy = GetDummyAura(54842); @@ -3462,7 +3492,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d uint32 castSpell = auraSpellInfo->Id == 67758 ? 67759 : 67713; // stacking - CastSpell(this, castSpell, true, NULL, triggeredByAura); + CastSpell(this, castSpell, true, nullptr, triggeredByAura); // counting Aura* dummy = GetDummyAura(castSpell); @@ -3589,7 +3619,6 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d break; } - // All ok. Check current trigger spell SpellEntry const* triggerEntry = sSpellStore.LookupEntry(trigger_spell_id); if (!triggerEntry) @@ -3607,7 +3636,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d // dummy basepoints or other customs switch (trigger_spell_id) { - // Cast positive spell on enemy target + // Cast positive spell on enemy target case 7099: // Curse of Mending case 39647: // Curse of Mending case 29494: // Temptation @@ -3776,7 +3805,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d return SPELL_AURA_PROC_FAILED; // try detect target manually if not set - if (target == NULL) + if (target == nullptr) target = !(procFlags & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL) && IsPositiveSpell(trigger_spell_id) ? this : pVictim; // default case @@ -3785,15 +3814,15 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d if (basepoints[EFFECT_INDEX_0] || basepoints[EFFECT_INDEX_1] || basepoints[EFFECT_INDEX_2]) CastCustomSpell(target, trigger_spell_id, - basepoints[EFFECT_INDEX_0] ? &basepoints[EFFECT_INDEX_0] : NULL, - basepoints[EFFECT_INDEX_1] ? &basepoints[EFFECT_INDEX_1] : NULL, - basepoints[EFFECT_INDEX_2] ? &basepoints[EFFECT_INDEX_2] : NULL, + basepoints[EFFECT_INDEX_0] ? &basepoints[EFFECT_INDEX_0] : nullptr, + basepoints[EFFECT_INDEX_1] ? &basepoints[EFFECT_INDEX_1] : nullptr, + basepoints[EFFECT_INDEX_2] ? &basepoints[EFFECT_INDEX_2] : nullptr, true, castItem, triggeredByAura); else CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura); if (cooldown && GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->AddSpellCooldown(trigger_spell_id, 0, time(NULL) + cooldown); + ((Player*)this)->AddSpellCooldown(trigger_spell_id, 0, time(nullptr) + cooldown); return SPELL_AURA_PROC_OK; } @@ -4231,3 +4260,12 @@ SpellAuraProcResult Unit::HandleRemoveByDamageChanceProc(Unit* /*pVictim*/, uint return SPELL_AURA_PROC_FAILED; } + +SpellAuraProcResult Unit::HandleInvisibilityAuraProc(Unit* pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown) +{ + if (triggeredByAura->GetSpellProto()->HasAttribute(SPELL_ATTR_PASSIVE) || triggeredByAura->GetSpellProto()->HasAttribute(SPELL_ATTR_EX_NEGATIVE)) + return SPELL_AURA_PROC_FAILED; + + RemoveAurasDueToSpell(triggeredByAura->GetId()); + return SPELL_AURA_PROC_OK; +} diff --git a/src/game/WorldHandlers/VehicleHandler.cpp b/src/game/WorldHandlers/VehicleHandler.cpp index 9c707b7ca..81c4cd79e 100644 --- a/src/game/WorldHandlers/VehicleHandler.cpp +++ b/src/game/WorldHandlers/VehicleHandler.cpp @@ -64,7 +64,12 @@ void WorldSession::HandleRequestVehicleExit(WorldPacket& recvPacket) if (!transportInfo || !transportInfo->IsOnVehicle()) return; - ((Unit*)transportInfo->GetTransport())->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, _player->GetObjectGuid()); + Unit* vehicle = (Unit*)transportInfo->GetTransport(); + + // Check for exit flag + if (VehicleSeatEntry const* seatEntry = vehicle->GetVehicleInfo()->GetSeatEntry(transportInfo->GetTransportSeat())) + if (seatEntry->m_flags & SEAT_FLAG_CAN_EXIT) + vehicle->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, _player->GetObjectGuid()); } void WorldSession::HandleRequestVehicleSwitchSeat(WorldPacket& recvPacket) @@ -166,11 +171,20 @@ void WorldSession::HandleEjectPassenger(WorldPacket& recvPacket) if (!passenger || !passenger->IsBoarded()) return; - // _player must be transporting passenger - if (!_player->IsVehicle() || !_player->GetVehicleInfo()->HasOnBoard(passenger)) + // _player is not a vehicle + if (!_player->IsVehicle()) return; - _player->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, passengerGuid); + VehicleInfo* vehicleInfo = _player->GetVehicleInfo(); + + // _player must be transporting passenger + if (!vehicleInfo->HasOnBoard(passenger)) + return; + + // Check for eject flag + if (VehicleSeatEntry const* seatEntry = vehicleInfo->GetSeatEntry(passenger->GetTransportInfo()->GetTransportSeat())) + if (seatEntry->m_flagsB & SEAT_FLAG_B_EJECTABLE) + _player->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE, passengerGuid); } void WorldSession::HandleRequestVehiclePrevSeat(WorldPacket& recv_data) diff --git a/src/game/WorldHandlers/WaypointManager.cpp b/src/game/WorldHandlers/WaypointManager.cpp index 35c6dcc13..971761e1f 100644 --- a/src/game/WorldHandlers/WaypointManager.cpp +++ b/src/game/WorldHandlers/WaypointManager.cpp @@ -222,7 +222,7 @@ void WaypointManager::Load() const CreatureData* cData = sObjectMgr.GetCreatureData(*itr); const CreatureInfo* cInfo = ObjectMgr::GetCreatureTemplate(cData->id); - sLog.outErrorDb("Table creature_movement has waypoint for creature guid %u (entry %u), but MovementType is not WAYPOINT_MOTION_TYPE(2). Creature will not use this path.", *itr, cData->id); + ERROR_DB_STRICT_LOG("Table creature_movement has waypoint for creature guid %u (entry %u), but MovementType is not WAYPOINT_MOTION_TYPE(2). Make sure that this is actually used in a script!", *itr, cData->id); if (cInfo->MovementType == WAYPOINT_MOTION_TYPE) sLog.outErrorDb(" creature_template for this entry has MovementType WAYPOINT_MOTION_TYPE(2), did you intend to use creature_movement_template ?"); @@ -406,49 +406,91 @@ void WaypointManager::_clearPath(WaypointPath& path) path.clear(); } -/// - Insert after the last point -void WaypointManager::AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid) +/// Insert a node into the storage for external access +bool WaypointManager::AddExternalNode(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime) { - _addNode(id, GetLastPoint(id, 0) + 1, x, y, z, o, delay, wpGuid); + if (pathId < 0 || pathId >= 0xFF) + { + sLog.outErrorScriptLib("WaypointManager::AddExternalNode: (Npc-Entry %u, PathId %i) Invalid pathId", entry, pathId); + return false; + } + + if (!MaNGOS::IsValidMapCoord(x, y, z, o)) + { + sLog.outErrorScriptLib("WaypointManager::AddExternalNode: (Npc-Entry %u, PathId %i) Invalid coordinates", entry, pathId); + return false; + } + + m_externalPathTemplateMap[(entry << 8) + pathId][pointId] = WaypointNode(x, y, z, o, waittime, 0, NULL); + return true; } -/// - Insert after a certain point -void WaypointManager::AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid) +/// - Insert at a certain point, if pointId == 0 insert last. In this case pointId will be changed to the id to which the node was added +WaypointNode const* WaypointManager::AddNode(uint32 entry, uint32 dbGuid, uint32& pointId, WaypointPathOrigin wpDest, float x, float y, float z) { - for (uint32 i = GetLastPoint(id, 0); i > point; --i) - WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point+1 WHERE id=%u AND point=%u", id, i); + // Support only normal movement tables + if (wpDest != PATH_FROM_GUID && wpDest != PATH_FROM_ENTRY) + return NULL; - _addNode(id, point + 1, x, y, z, o, delay, wpGuid); + // Prepare information + char const* const table = wpDest == PATH_FROM_GUID ? "creature_movement" : "creature_movement_template"; + char const* const key_field = wpDest == PATH_FROM_GUID ? "id" : "entry"; + uint32 const key = wpDest == PATH_FROM_GUID ? dbGuid : ((entry << 8) /*+ pathId*/); + WaypointPathMap* wpMap = wpDest == PATH_FROM_GUID ? &m_pathMap : &m_pathTemplateMap; + + WaypointPath& path = (*wpMap)[key]; + + if (pointId == 0 && !path.empty()) // Start with highest waypoint + pointId = path.rbegin()->first + 1; + else if (pointId == 0) + pointId = 1; + + uint32 nextPoint = pointId; + WaypointNode temp = WaypointNode(x, y, z, 100, 0, 0, NULL); + WaypointPath::iterator find = path.find(nextPoint); + if (find != path.end()) // Point already exists + { + do // Move points along until a free spot is found + { + std::swap(temp, find->second); + ++find; + ++nextPoint; + } while (find != path.end() && find->first == nextPoint); + // After this, we have: + // pointId, pointId+1, ..., nextPoint [ Can be == path.end ]] + } + + // Insert new or remaining + path[nextPoint] = temp; + + // Update original waypoints + for (WaypointPath::reverse_iterator rItr = path.rbegin(); rItr != path.rend() && rItr->first > pointId; ++rItr) + { + if (rItr->first <= nextPoint) + WorldDatabase.PExecuteLog("UPDATE %s SET point=point+1 WHERE %s=%u AND point=%u", table, key_field, key, rItr->first - 1); + } + // Insert new Point to database + WorldDatabase.PExecuteLog("INSERT INTO %s (%s,point,position_x,position_y,position_z,orientation) VALUES (%u,%u, %f,%f,%f, 100)", table, key_field, key, pointId, x, y, z); + + return &path[pointId]; } -/// - Insert without checking for collision -void WaypointManager::_addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid) +void WaypointManager::DeleteNode(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin) { - WorldDatabase.PExecuteLog("INSERT INTO creature_movement (id,point,position_x,position_y,position_z,orientation,wpguid,waittime) " - "VALUES (%u,%u, %f,%f,%f,%f, %u,%u)", - id, point, x, y, z, o, wpGuid, delay); - - m_pathMap[id][point] = WaypointNode(x, y, z, o, delay, 0, NULL); -} - -uint32 WaypointManager::GetLastPoint(uint32 id, uint32 default_notfound) -{ - WaypointPathMap::const_iterator itr = m_pathMap.find(id); - if (itr != m_pathMap.end() && itr->second.rbegin() != itr->second.rend()) - default_notfound = itr->second.rbegin()->first; - - return default_notfound; -} - -void WaypointManager::DeleteNode(uint32 id, uint32 point) -{ - WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id=%u AND point=%u", id, point); - WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point-1 WHERE id=%u AND point>%u", id, point); - WaypointPathMap::iterator itr = m_pathMap.find(id); - if (itr == m_pathMap.end()) + // Support only normal movement tables + if (wpOrigin != PATH_FROM_GUID && wpOrigin != PATH_FROM_ENTRY) return; - itr->second.erase(point); + WaypointPath* path = GetPathFromOrigin(entry, dbGuid, pathId, wpOrigin); + if (!path) + return; + + char const* const table = wpOrigin == PATH_FROM_GUID ? "creature_movement" : "creature_movement_template"; + char const* const key_field = wpOrigin == PATH_FROM_GUID ? "id" : "entry"; + uint32 const key = wpOrigin == PATH_FROM_GUID ? dbGuid : entry; + WorldDatabase.PExecuteLog("DELETE FROM %s WHERE %s=%u AND point=%u", table, key_field, key, point); + + path->erase(point); } void WaypointManager::DeletePath(uint32 id) @@ -463,15 +505,23 @@ void WaypointManager::DeletePath(uint32 id) // only meant to be called by GM commands } -void WaypointManager::SetNodePosition(uint32 id, uint32 point, float x, float y, float z) +void WaypointManager::SetNodePosition(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin, float x, float y, float z) { - WorldDatabase.PExecuteLog("UPDATE creature_movement SET position_x=%f, position_y=%f, position_z=%f WHERE id=%u AND point=%u", x, y, z, id, point); - WaypointPathMap::iterator itr = m_pathMap.find(id); - if (itr == m_pathMap.end()) + // Support only normal movement tables + if (wpOrigin != PATH_FROM_GUID && wpOrigin != PATH_FROM_ENTRY) return; - WaypointPath::iterator find = itr->second.find(point); - if (find != itr->second.end()) + WaypointPath* path = GetPathFromOrigin(entry, dbGuid, pathId, wpOrigin); + if (!path) + return; + + char const* const table = wpOrigin == PATH_FROM_GUID ? "creature_movement" : "creature_movement_template"; + char const* const key_field = wpOrigin == PATH_FROM_GUID ? "id" : "entry"; + uint32 const key = wpOrigin == PATH_FROM_GUID ? dbGuid : entry; + WorldDatabase.PExecuteLog("UPDATE %s SET position_x=%f, position_y=%f, position_z=%f WHERE %s=%u AND point=%u", table, x, y, z, key_field, key, point); + + WaypointPath::iterator find = path->find(point); + if (find != path->end()) { find->second.x = x; find->second.y = y; @@ -479,43 +529,67 @@ void WaypointManager::SetNodePosition(uint32 id, uint32 point, float x, float y, } } -void WaypointManager::SetNodeText(uint32 id, uint32 point, const char* text_field, const char* text) +void WaypointManager::SetNodeWaittime(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin, uint32 waittime) { - if (!text_field) return; - std::string field = text_field; - WorldDatabase.escape_string(field); - - if (!text) - { - WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s=NULL WHERE id='%u' AND point='%u'", field.c_str(), id, point); - } - else - { - std::string text2 = text; - WorldDatabase.escape_string(text2); - WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s='%s' WHERE id='%u' AND point='%u'", field.c_str(), text2.c_str(), id, point); - } - - WaypointPathMap::iterator itr = m_pathMap.find(id); - if (itr == m_pathMap.end()) + // Support only normal movement tables + if (wpOrigin != PATH_FROM_GUID && wpOrigin != PATH_FROM_ENTRY) return; - WaypointPath::iterator find = itr->second.find(point); - if (find != itr->second.end()) - { - WaypointNode& node = find->second; - if (!node.behavior) node.behavior = new WaypointBehavior(); + WaypointPath* path = GetPathFromOrigin(entry, dbGuid, pathId, wpOrigin); + if (!path) + return; -// if(field == "text1") node.behavior->text[0] = text ? text : ""; -// if(field == "text2") node.behavior->text[1] = text ? text : ""; -// if(field == "text3") node.behavior->text[2] = text ? text : ""; -// if(field == "text4") node.behavior->text[3] = text ? text : ""; -// if(field == "text5") node.behavior->text[4] = text ? text : ""; - if (field == "emote") node.behavior->emote = text ? atoi(text) : 0; - if (field == "spell") node.behavior->spell = text ? atoi(text) : 0; - if (field == "model1") node.behavior->model1 = text ? atoi(text) : 0; - if (field == "model2") node.behavior->model2 = text ? atoi(text) : 0; - } + char const* const table = wpOrigin == PATH_FROM_GUID ? "creature_movement" : "creature_movement_template"; + char const* const key_field = wpOrigin == PATH_FROM_GUID ? "id" : "entry"; + uint32 const key = wpOrigin == PATH_FROM_GUID ? dbGuid : entry; + WorldDatabase.PExecuteLog("UPDATE %s SET waittime=%u WHERE %s=%u AND point=%u", table, waittime, key_field, key, point); + + WaypointPath::iterator find = path->find(point); + if (find != path->end()) + find->second.delay = waittime; +} + +void WaypointManager::SetNodeOrientation(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin, float orientation) +{ + // Support only normal movement tables + if (wpOrigin != PATH_FROM_GUID && wpOrigin != PATH_FROM_ENTRY) + return; + + WaypointPath* path = GetPathFromOrigin(entry, dbGuid, pathId, wpOrigin); + if (!path) + return; + + char const* const table = wpOrigin == PATH_FROM_GUID ? "creature_movement" : "creature_movement_template"; + char const* const key_field = wpOrigin == PATH_FROM_GUID ? "id" : "entry"; + uint32 const key = wpOrigin == PATH_FROM_GUID ? dbGuid : entry; + WorldDatabase.PExecuteLog("UPDATE %s SET orientation=%f WHERE %s=%u AND point=%u", table, orientation, key_field, key, point); + + WaypointPath::iterator find = path->find(point); + if (find != path->end()) + find->second.orientation = orientation; +} + +/// return true if a valid scriptId is provided +bool WaypointManager::SetNodeScriptId(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin, uint32 scriptId) +{ + // Support only normal movement tables + if (wpOrigin != PATH_FROM_GUID && wpOrigin != PATH_FROM_ENTRY) + return false; + + WaypointPath* path = GetPathFromOrigin(entry, dbGuid, pathId, wpOrigin); + if (!path) + return false; + + char const* const table = wpOrigin == PATH_FROM_GUID ? "creature_movement" : "creature_movement_template"; + char const* const key_field = wpOrigin == PATH_FROM_GUID ? "id" : "entry"; + uint32 const key = wpOrigin == PATH_FROM_GUID ? dbGuid : entry; + WorldDatabase.PExecuteLog("UPDATE %s SET script_id=%u WHERE %s=%u AND point=%u", table, scriptId, key_field, key, point); + + WaypointPath::iterator find = path->find(point); + if (find != path->end()) + find->second.script_id = scriptId; + + return sCreatureMovementScripts.second.find(scriptId) != sCreatureMovementScripts.second.end(); } inline void CheckWPText(bool isTemplate, uint32 entryOrGuid, uint32 point, WaypointBehavior* be, std::set& ids) diff --git a/src/game/WorldHandlers/WaypointManager.h b/src/game/WorldHandlers/WaypointManager.h index 165c964e7..cddaef135 100644 --- a/src/game/WorldHandlers/WaypointManager.h +++ b/src/game/WorldHandlers/WaypointManager.h @@ -31,6 +31,14 @@ #include "Utilities/UnorderedMapSet.h" #include "Policies/Singleton.h" +enum WaypointPathOrigin +{ + PATH_NO_PATH = 0, + PATH_FROM_GUID = 1, + PATH_FROM_ENTRY = 2, + PATH_FROM_EXTERNAL = 3 +}; + #define MAX_WAYPOINT_TEXT 5 struct WaypointBehavior { @@ -64,12 +72,107 @@ typedef std::map WaypointPath; class WaypointManager { public: - WaypointManager() {} + WaypointManager() : m_externalTable("external.waypointTable") {} ~WaypointManager() { Unload(); } void Load(); void Unload(); + // We may get a path for several occasions: + + // 1: When creature.MovementType=2 + // 1a) Path is selected by creature.guid == creature_movement.id + // 1b) Path for 1a) does not exist and then use path from creature.GetEntry() == creature_movement_template.entry + + // 2: When creature_template.MovementType=2 + // 2a) Creature is summoned and has creature_template.MovementType=2 + // Creators need to be sure that creature_movement_template is always valid for summons. + // Mob that can be summoned anywhere should not have creature_movement_template for example. + + WaypointPath* GetDefaultPath(uint32 entry, uint32 lowGuid, WaypointPathOrigin* wpOrigin = NULL) + { + WaypointPath* path = NULL; + path = GetPath(lowGuid); + if (path && wpOrigin) + *wpOrigin = PATH_FROM_GUID; + + // No movement found for guid + if (!path) + { + path = GetPathTemplate(entry); + if (path && wpOrigin) + *wpOrigin = PATH_FROM_ENTRY; + } + + return path; + } + + // Helper function to get a path provided the required information + WaypointPath* GetPathFromOrigin(uint32 entry, uint32 lowGuid, int32 pathId, WaypointPathOrigin wpOrigin) + { + WaypointPathMap* wpMap = NULL; + uint32 key = 0; + + switch (wpOrigin) + { + case PATH_FROM_GUID: + key = lowGuid; + wpMap = &m_pathMap; + break; + case PATH_FROM_ENTRY: + if (pathId >= 0xFF || pathId < 0) + return NULL; + key = (entry << 8) + pathId; + wpMap = &m_pathTemplateMap; + break; + case PATH_FROM_EXTERNAL: + if (pathId >= 0xFF || pathId < 0) + return NULL; + key = (entry << 8) + pathId; + wpMap = &m_externalPathTemplateMap; + break; + case PATH_NO_PATH: + default: + return NULL; + } + WaypointPathMap::iterator find = wpMap->find(key); + return find != wpMap->end() ? &find->second : NULL; + } + + void DeletePath(uint32 id); + void CheckTextsExistance(std::set& ids); + + /// Set external source table + void SetExternalWPTable(char const* tableName) { m_externalTable = std::string(tableName); } + std::string GetExternalWPTable() const { return m_externalTable; } + /// Add Nodes from external sources + bool AddExternalNode(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime); + + // Toolbox for .wp add command + /// Add a node as position pointId. If pointId == 0 then as last point + WaypointNode const* AddNode(uint32 entry, uint32 dbGuid, uint32& pointId, WaypointPathOrigin wpDest, float x, float y, float z); + + // Toolbox for .wp modify command + void DeleteNode(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin); + void SetNodePosition(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin, float x, float y, float z); + void SetNodeWaittime(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin, uint32 waittime); + void SetNodeOrientation(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin, float orientation); + bool SetNodeScriptId(uint32 entry, uint32 dbGuid, uint32 point, int32 pathId, WaypointPathOrigin wpOrigin, uint32 scriptId); + + // Small Helper for nice output + static std::string GetOriginString(WaypointPathOrigin origin) + { + switch (origin) + { + case PATH_NO_PATH: return ""; + case PATH_FROM_GUID: return "guid"; + case PATH_FROM_ENTRY: return "entry"; + case PATH_FROM_EXTERNAL: return "external"; + default: return "invalid origin"; + } + } + + private: WaypointPath* GetPath(uint32 id) { WaypointPathMap::iterator itr = m_pathMap.find(id); @@ -78,28 +181,22 @@ class WaypointManager WaypointPath* GetPathTemplate(uint32 entry) { - WaypointPathMap::iterator itr = m_pathTemplateMap.find(entry); + WaypointPathMap::iterator itr = m_pathTemplateMap.find((entry << 8) /*+ pathId*/); return itr != m_pathTemplateMap.end() ? &itr->second : NULL; } - void AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid); - void AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid); - uint32 GetLastPoint(uint32 id, uint32 default_notfound); - void DeleteNode(uint32 id, uint32 point); - void DeletePath(uint32 id); - void SetNodePosition(uint32 id, uint32 point, float x, float y, float z); - void SetNodeText(uint32 id, uint32 point, const char* text_field, const char* text); - void CheckTextsExistance(std::set& ids); - - private: - void _addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid); void _clearPath(WaypointPath& path); typedef UNORDERED_MAP WaypointPathMap; WaypointPathMap m_pathMap; WaypointPathMap m_pathTemplateMap; + WaypointPathMap m_externalPathTemplateMap; + std::string m_externalTable; }; #define sWaypointMgr MaNGOS::Singleton::Instance() +/// Accessor for Scripting library +MANGOS_DLL_SPEC bool AddWaypointFromExternal(uint32 entry, int32 pathId, uint32 pointId, float x, float y, float z, float o, uint32 waittime); + #endif diff --git a/src/game/WorldHandlers/World.cpp b/src/game/WorldHandlers/World.cpp index 907c971e0..ab93c1de7 100644 --- a/src/game/WorldHandlers/World.cpp +++ b/src/game/WorldHandlers/World.cpp @@ -74,7 +74,6 @@ #include "CharacterDatabaseCleaner.h" #include "CreatureLinkingMgr.h" #include "Calendar.h" -#include "PhaseMgr.h" #include "Weather.h" #include "LFGMgr.h" #ifdef ENABLE_ELUNA @@ -87,6 +86,8 @@ #include #include +#include + INSTANTIATE_SINGLETON_1(World); extern void LoadGameObjectModelList(); @@ -140,28 +141,22 @@ World::World() /// World destructor World::~World() { + // it is assumed that no other thread is accessing this data when the destructor is called. therefore, no locks are necessary + ///- Empty the kicked session set - while (!m_sessions.empty()) - { - // not remove from queue, prevent loading new sessions - delete m_sessions.begin()->second; - m_sessions.erase(m_sessions.begin()); - } + std::for_each(m_sessions.begin(), m_sessions.end(), [](const SessionMap::value_type &p) { delete p.second; }); + m_sessions.clear(); - ///- Empty the WeatherMap - for (WeatherMap::const_iterator itr = m_weathers.begin(); itr != m_weathers.end(); ++itr) - delete itr->second; + std::for_each(m_cliCommandQueue.begin(), m_cliCommandQueue.end(), [](const CliCommandHolder *p) { delete p; }); + m_cliCommandQueue.clear(); - m_weathers.clear(); - - CliCommandHolder* command = NULL; - while (cliCmdQueue.next(command)) - { delete command; } + std::for_each(m_sessionAddQueue.begin(), m_sessionAddQueue.end(), [](const WorldSession *s) { delete s; }); + m_sessionAddQueue.clear(); VMAP::VMapFactory::clear(); MMAP::MMapFactory::clear(); - // TODO free addSessQueue + delete m_configForceLoadMapIds; } /// Cleanups before world stop @@ -225,7 +220,9 @@ bool World::RemoveSession(uint32 id) void World::AddSession(WorldSession* s) { - addSessQueue.add(s); + std::lock_guard guard(m_sessionAddQueueLock); + + m_sessionAddQueue.push_back(s); } void @@ -1803,10 +1800,12 @@ void World::SendWorldText(int32 string_id, ...) MaNGOS::LocalizedPacketListDo wt_do(wt_builder); for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { - if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld()) - continue; - - wt_do(itr->second->GetPlayer()); + if (WorldSession* session = itr->second) + { + Player* player = session->GetPlayer(); + if (player && player->IsInWorld()) + wt_do(player); + } } va_end(ap); @@ -1817,11 +1816,11 @@ void World::SendGlobalMessage(WorldPacket* packet) { for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld()) + if (WorldSession* session = itr->second) { - itr->second->SendPacket(packet); + Player* player = session->GetPlayer(); + if (player && player->IsInWorld()) + session->SendPacket(packet); } } } @@ -1847,13 +1846,11 @@ void World::SendZoneUnderAttackMessage(uint32 zoneId, Team team) for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - itr->second->GetPlayer()->GetTeam() == team && - !itr->second->GetPlayer()->GetMap()->Instanceable()) + if (WorldSession* session = itr->second) { - itr->second->SendPacket(&data); + Player* player = session->GetPlayer(); + if (player && player->IsInWorld() && player->GetTeam() == team && !player->GetMap()->Instanceable()) + itr->second->SendPacket(&data); } } } @@ -1863,19 +1860,20 @@ void World::SendDefenseMessage(uint32 zoneId, int32 textId) { for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { - if (itr->second && - itr->second->GetPlayer() && - itr->second->GetPlayer()->IsInWorld() && - !itr->second->GetPlayer()->GetMap()->Instanceable()) + if (WorldSession* session = itr->second) { - char const* message = itr->second->GetMangosString(textId); - uint32 messageLength = strlen(message) + 1; + Player* player = session->GetPlayer(); + if (player && player->IsInWorld() && !player->GetMap()->Instanceable()) + { + char const* message = session->GetMangosString(textId); + uint32 messageLength = strlen(message) + 1; - WorldPacket data(SMSG_DEFENSE_MESSAGE, 4 + 4 + messageLength); - data << uint32(zoneId); - data << uint32(messageLength); - data << message; - itr->second->SendPacket(&data); + WorldPacket data(SMSG_DEFENSE_MESSAGE, 4 + 4 + messageLength); + data << uint32(zoneId); + data << uint32(messageLength); + data << message; + session->SendPacket(&data); + } } } } @@ -1895,12 +1893,13 @@ void World::KickAllLess(AccountTypes sec) { // session not removed at kick and will removed in next update tick for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) - if (itr->second->GetSecurity() < sec) - itr->second->KickPlayer(); + if (WorldSession* session = itr->second) + if (session->GetSecurity() < sec) + session->KickPlayer(); } /// Ban an account or ban an IP address, duration_secs if it is positive used, otherwise permban -BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, uint32 duration_secs, std::string reason, std::string author) +BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, uint32 duration_secs, std::string reason, const std::string& author) { LoginDatabase.escape_string(nameOrIP); LoginDatabase.escape_string(reason); @@ -2087,12 +2086,16 @@ void World::ShutdownCancel() #endif /* ENABLE_ELUNA */ } -void World::UpdateSessions(uint32 diff) +void World::UpdateSessions(uint32 /*diff*/) { ///- Add new sessions - WorldSession* sess; - while (addSessQueue.next(sess)) - { AddSession_(sess); } + { + std::lock_guard guard(m_sessionAddQueueLock); + + std::for_each(m_sessionAddQueue.begin(), m_sessionAddQueue.end(), [&](WorldSession *session) { AddSession_(session); }); + + m_sessionAddQueue.clear(); + } ///- Then send an update signal to remaining ones for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next) @@ -2115,19 +2118,21 @@ void World::UpdateSessions(uint32 diff) // This handles the issued and queued CLI/RA commands void World::ProcessCliCommands() { - CliCommandHolder::Print* zprint = NULL; - void* callbackArg = NULL; - CliCommandHolder* command; - while (cliCmdQueue.next(command)) + std::lock_guard guard(m_cliCommandQueueLock); + + while (!m_cliCommandQueue.empty()) { + CliCommandHolder* command = m_cliCommandQueue.front(); + m_cliCommandQueue.pop_front(); + DEBUG_LOG("CLI command under processing..."); - zprint = command->m_print; - callbackArg = command->m_callbackArg; + CliCommandHolder::Print* zprint = command->m_print; + void* callbackArg = command->m_callbackArg; CliHandler handler(command->m_cliAccountId, command->m_cliAccessLevel, callbackArg, zprint); handler.ParseCommands(command->m_command); if (command->m_commandFinished) - { command->m_commandFinished(callbackArg, !handler.HasSentErrorMessage()); } + command->m_commandFinished(callbackArg, !handler.HasSentErrorMessage()); delete command; } @@ -2685,12 +2690,9 @@ bool World::configNoReload(bool reload, eConfigBoolValues index, char const* fie return false; } -void World::UpdatePhaseDefinitions() +void World::InvalidatePlayerDataToAllClient(ObjectGuid guid) { - SessionMap::const_iterator itr; - for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) - { - if (itr->second && itr->second->GetPlayer() && itr->second->GetPlayer()->IsInWorld()) - itr->second->GetPlayer()->GetPhaseMgr()->NotifyStoresReloaded(); - } + WorldPacket data(SMSG_INVALIDATE_PLAYER, 8); + data << guid; + SendGlobalMessage(&data); } diff --git a/src/game/WorldHandlers/World.h b/src/game/WorldHandlers/World.h index 3b3919626..189193835 100644 --- a/src/game/WorldHandlers/World.h +++ b/src/game/WorldHandlers/World.h @@ -37,6 +37,7 @@ #include #include #include +#include class Object; class ObjectGuid; @@ -616,7 +617,7 @@ class World void KickAll(); void KickAllLess(AccountTypes sec); - BanReturn BanAccount(BanMode mode, std::string nameOrIP, uint32 duration_secs, std::string reason, std::string author); + BanReturn BanAccount(BanMode mode, std::string nameOrIP, uint32 duration_secs, std::string reason, const std::string& author); bool RemoveBanAccount(BanMode mode, std::string nameOrIP); // for max speed access @@ -632,7 +633,7 @@ class World static uint32 GetRelocationAINotifyDelay() { return m_relocation_ai_notify_delay; } void ProcessCliCommands(); - void QueueCliCommand(CliCommandHolder* commandHolder) { cliCmdQueue.add(commandHolder); } + void QueueCliCommand(CliCommandHolder* commandHolder) { std::lock_guard guard(m_cliCommandQueueLock); m_cliCommandQueue.push_back(commandHolder); } void UpdateResultQueue(); void InitResultQueue(); @@ -647,6 +648,17 @@ class World void UpdatePhaseDefinitions(); + /** + * \brief: force all client to request player data + * \param: ObjectGuid guid : guid of the specified player + * \returns: void + * + * Description: InvalidatePlayerDataToAllClient force all connected clients to clear specified player cache + * FullName: World::InvalidatePlayerDataToAllClient + * Access: public + **/ + void InvalidatePlayerDataToAllClient(ObjectGuid guid); + protected: void _UpdateGameTime(); // callback for UpdateRealmCharacters @@ -732,7 +744,8 @@ class World static uint32 m_relocation_ai_notify_delay; // CLI command holder to be thread safe - ACE_Based::LockedQueue cliCmdQueue; + std::mutex m_cliCommandQueueLock; + std::deque m_cliCommandQueue; // scheduled reset times time_t m_NextCurrencyReset; @@ -746,10 +759,15 @@ class World // sessions that are added async void AddSession_(WorldSession* s); - ACE_Based::LockedQueue addSessQueue; + + std::mutex m_sessionAddQueueLock; + std::deque m_sessionAddQueue; // used versions std::string m_DBVersion; + + // List of Maps that should be force-loaded on startup + std::set* m_configForceLoadMapIds; }; extern uint32 realmID; diff --git a/src/game/movement/MoveSpline.cpp b/src/game/movement/MoveSpline.cpp index 9bdd7fb68..4785dbac9 100644 --- a/src/game/movement/MoveSpline.cpp +++ b/src/game/movement/MoveSpline.cpp @@ -179,6 +179,13 @@ namespace Movement vertical_acceleration = 0.f; effect_start_time = 0; + // detect Stop command + if (splineflags.done) + { + spline.clear(); + return; + } + init_spline(args); // init parabolic / animation diff --git a/src/game/movement/MoveSpline.h b/src/game/movement/MoveSpline.h index e92fa79cf..c35a93351 100644 --- a/src/game/movement/MoveSpline.h +++ b/src/game/movement/MoveSpline.h @@ -30,6 +30,15 @@ namespace Movement { + enum MonsterMoveType + { + MonsterMoveNormal = 0, + MonsterMoveStop = 1, + MonsterMoveFacingSpot = 2, + MonsterMoveFacingTarget = 3, + MonsterMoveFacingAngle = 4 + }; + struct Location : public Vector3 { /** diff --git a/src/game/movement/MoveSplineInit.cpp b/src/game/movement/MoveSplineInit.cpp index a005ea443..5ff8912ab 100644 --- a/src/game/movement/MoveSplineInit.cpp +++ b/src/game/movement/MoveSplineInit.cpp @@ -116,6 +116,57 @@ namespace Movement return move_spline.Duration(); } + void MoveSplineInit::Stop() + { + MoveSpline& move_spline = *unit.movespline; + + // No need to stop if we are not moving + if (move_spline.Finalized()) + return; + + TransportInfo* transportInfo = unit.GetTransportInfo(); + + Location real_position(unit.GetPositionX(), unit.GetPositionY(), unit.GetPositionZ(), unit.GetOrientation()); + + // If boarded use current local position + if (transportInfo) + transportInfo->GetLocalPosition(real_position.x, real_position.y, real_position.z, real_position.orientation); + + // there is a big chane that current position is unknown if current state is not finalized, need compute it + // this also allows calculate spline position and update map position in much greater intervals + if (!move_spline.Finalized() && !transportInfo) + real_position = move_spline.ComputePosition(); + + if (args.path.empty()) + { + // should i do the things that user should do? + MoveTo(real_position); + } + + // corrent first vertex + args.path[0] = real_position; + + args.flags = MoveSplineFlag::Done; + unit.m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEFLAG_FORWARD | MOVEFLAG_CAN_FLY)); + move_spline.Initialize(args); + + WorldPacket data(SMSG_MONSTER_MOVE, 64); + data << unit.GetPackGUID(); + + if (transportInfo) + { + data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT); + data << transportInfo->GetTransportGuid().WriteAsPacked(); + data << int8(transportInfo->GetTransportSeat()); + } + + data << uint8(0); + data << real_position.x << real_position.y << real_position.z; + data << move_spline.GetId(); + data << uint8(MonsterMoveStop); + unit.SendMessageToSet(&data, true); + } + MoveSplineInit::MoveSplineInit(Unit& m) : unit(m) { // mix existing state into new diff --git a/src/game/movement/MoveSplineInit.h b/src/game/movement/MoveSplineInit.h index fe9782094..5b63034d2 100644 --- a/src/game/movement/MoveSplineInit.h +++ b/src/game/movement/MoveSplineInit.h @@ -61,6 +61,9 @@ namespace Movement */ int32 Launch(); + /* Stop any creature movement */ + void Stop(); + /* Adds movement by parabolic trajectory * @param amplitude - the maximum height of parabola, value could be negative and positive * @param start_time - delay between movement starting time and beginning to move by parabolic trajectory diff --git a/src/game/movement/packet_builder.cpp b/src/game/movement/packet_builder.cpp index 89433fa2b..c39d91d6c 100644 --- a/src/game/movement/packet_builder.cpp +++ b/src/game/movement/packet_builder.cpp @@ -40,15 +40,6 @@ namespace Movement b >> v.x >> v.y >> v.z; } - enum MonsterMoveType - { - MonsterMoveNormal = 0, - MonsterMoveStop = 1, - MonsterMoveFacingSpot = 2, - MonsterMoveFacingTarget = 3, - MonsterMoveFacingAngle = 4 - }; - void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data) { MoveSplineFlag splineflags = move_spline.splineflags; diff --git a/src/game/vmap/BIH.cpp b/src/game/vmap/BIH.cpp index 7d1b1059c..56a66d463 100644 --- a/src/game/vmap/BIH.cpp +++ b/src/game/vmap/BIH.cpp @@ -48,14 +48,14 @@ void BIH::subdivide(int left, int right, std::vector& tempTree, buildDat return; } // calculate extents - int axis = -1, prevAxis, rightOrig; + int axis = -1, rightOrig; float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan(); - float split = G3D::fnan(), prevSplit; + float split = G3D::fnan(); bool wasLeft = true; while (true) { - prevAxis = axis; - prevSplit = split; + int prevAxis = axis; + float prevSplit = split; // perform quick consistency checks Vector3 d(gridBox.hi - gridBox.lo); if (d.x < 0 || d.y < 0 || d.z < 0) diff --git a/src/game/vmap/TileAssembler.cpp b/src/game/vmap/TileAssembler.cpp index 66cb90714..3333f1430 100644 --- a/src/game/vmap/TileAssembler.cpp +++ b/src/game/vmap/TileAssembler.cpp @@ -235,7 +235,7 @@ namespace VMAP MapData::iterator map_iter = mapData.find(mapID); if (map_iter == mapData.end()) { - printf("spawning Map %d\n", mapID); + printf("spawning Map %u\n", mapID); mapData[mapID] = current = new MapSpawns(); } else current = (*map_iter).second; diff --git a/src/shared/Utilities/Util.h b/src/shared/Utilities/Util.h index 5ff3c1f86..4770e1d74 100644 --- a/src/shared/Utilities/Util.h +++ b/src/shared/Utilities/Util.h @@ -508,7 +508,7 @@ inline bool isBasicLatinString(const std::wstring &wstr, bool numericOrSpace) { for (size_t i = 0; i < wstr.size(); ++i) if (!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - { return false; } + return false; return true; } @@ -523,7 +523,7 @@ inline bool isExtendedLatinString(const std::wstring &wstr, bool numericOrSpace) { for (size_t i = 0; i < wstr.size(); ++i) if (!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - { return false; } + return false; return true; } @@ -538,7 +538,7 @@ inline bool isCyrillicString(const std::wstring &wstr, bool numericOrSpace) { for (size_t i = 0; i < wstr.size(); ++i) if (!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - { return false; } + return false; return true; } @@ -553,7 +553,7 @@ inline bool isEastAsianString(const std::wstring &wstr, bool numericOrSpace) { for (size_t i = 0; i < wstr.size(); ++i) if (!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - { return false; } + return false; return true; } diff --git a/src/shared/revision.h b/src/shared/revision.h index 975314617..ab013079f 100644 --- a/src/shared/revision.h +++ b/src/shared/revision.h @@ -39,5 +39,5 @@ #define WORLD_DB_VERSION_NR 21 #define WORLD_DB_STRUCTURE_NR 2 #define WORLD_DB_CONTENT_NR 1 - #define WORLD_DB_UPDATE_DESCRIPTION "revision_refactor" + #define WORLD_DB_UPDATE_DESCRIPTION "script_binding populated" #endif // __REVISION_H__