From f0eb6d36a322b59bda7f851f44f5ba507409bc2d Mon Sep 17 00:00:00 2001 From: UltraNix <80540499+UltraNix@users.noreply.github.com> Date: Fri, 25 Mar 2022 11:45:07 +0100 Subject: [PATCH] =?UTF-8?q?fix(Core/Handlers):=20Faction=20Change=20servic?= =?UTF-8?q?e=20properly=20reset=20and=20give=20ne=E2=80=A6=20(#9729)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #7981 Fixes #8732 --- src/server/game/DataStores/DBCStores.cpp | 18 ++- src/server/game/DataStores/DBCStores.h | 2 + src/server/game/DungeonFinding/LFGMgr.h | 1 + src/server/game/Globals/ObjectMgr.cpp | 4 +- src/server/game/Handlers/CharacterHandler.cpp | 105 ++++++++++++++---- src/server/shared/DataStores/DBCStructure.h | 10 +- 6 files changed, 107 insertions(+), 33 deletions(-) diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index a276a9746..b9ff31654 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -20,6 +20,7 @@ #include "DBCFileLoader.h" #include "DBCfmt.h" #include "Errors.h" +#include "LFGMgr.h" #include "Log.h" #include "SharedDefines.h" #include "SpellMgr.h" @@ -510,7 +511,7 @@ void LoadDBCStores(const std::string& dataPath) for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) if (TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) - sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID, entry->price); + sTaxiPathSetBySource[entry->from][entry->to] = entry; // Calculate path nodes count uint32 pathCount = sTaxiPathStore.GetNumRows(); @@ -559,7 +560,7 @@ void LoadDBCStores(const std::string& dataPath) for (TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin(); dest_i != src_i->second.end(); ++dest_i) { // not spell path - if (dest_i->second.price || spellPaths.find(dest_i->second.ID) == spellPaths.end()) + if (dest_i->second->price || spellPaths.find(dest_i->second->ID) == spellPaths.end()) { ok = true; break; @@ -840,6 +841,19 @@ LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty) return nullptr; } +LFGDungeonEntry const* GetZoneLFGDungeonEntry(std::string const& zoneName, LocaleConstant locale) +{ + for (LFGDungeonEntry const* dungeon : sLFGDungeonStore) + { + if (dungeon->type == lfg::LFG_TYPE_ZONE && zoneName.find(dungeon->name[locale]) != std::string::npos) + { + return dungeon; + } + } + + return nullptr; +} + uint32 GetDefaultMapLight(uint32 mapId) { for (int32 i = sLightStore.GetNumRows(); i >= 0; --i) diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index b2913e309..046071e06 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -64,6 +64,8 @@ PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundB CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender); LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty); +LFGDungeonEntry const* GetZoneLFGDungeonEntry(std::string const& zoneName, LocaleConstant locale); + uint32 GetDefaultMapLight(uint32 mapId); typedef std::unordered_multimap SkillRaceClassInfoMap; diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 8f1ef6777..2e0abf067 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -69,6 +69,7 @@ namespace lfg LFG_TYPE_NONE = 0, LFG_TYPE_DUNGEON = 1, LFG_TYPE_RAID = 2, + LFG_TYPE_ZONE = 4, LFG_TYPE_HEROIC = 5, LFG_TYPE_RANDOM = 6 }; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 427cb7c6a..e5e18746e 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -6435,8 +6435,8 @@ void ObjectMgr::GetTaxiPath(uint32 source, uint32 destination, uint32& path, uin return; } - cost = dest_i->second.price; - path = dest_i->second.ID; + cost = dest_i->second->price; + path = dest_i->second->ID; } uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, TeamId teamId, bool allowed_alt_team /* = false */) diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index abd1f2b67..a9a8b78ad 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -33,6 +33,7 @@ #include "InstanceSaveMgr.h" #include "Language.h" #include "Log.h" +#include "MapMgr.h" #include "Metric.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" @@ -2174,33 +2175,97 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptrFactionChange) { - // Delete all Flypaths - stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXI_PATH); - stmt->SetData(0, lowGuid); - trans->Append(stmt); - - if (level > 7) { - // Update Taxi path - // this doesn't seem to be 100% blizzlike... but it can't really be helped. - std::ostringstream taximaskstream; - uint32 numFullTaximasks = level / 7; + // Delete all Flypaths + stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXI_PATH); + stmt->SetData(0, lowGuid); + trans->Append(stmt); - if (numFullTaximasks > 11) - numFullTaximasks = 11; + // Update Taxi path + TaxiMask newTaxiMask; + memset(newTaxiMask, 0, sizeof(newTaxiMask)); TaxiMask const& factionMask = newTeam == TEAM_HORDE ? sHordeTaxiNodesMask : sAllianceTaxiNodesMask; - for (uint8 i = 0; i < numFullTaximasks; ++i) + for (auto const& itr : sTaxiPathSetBySource) { - uint8 deathKnightExtraNode = (playerClass == CLASS_DEATH_KNIGHT) ? sDeathKnightTaxiNodesMask[i] : 0; - taximaskstream << uint32(factionMask[i] | deathKnightExtraNode) << ' '; + auto FillTaxiMask = [&](uint8 field, uint32 mask) + { + if (playerClass == CLASS_DEATH_KNIGHT) + { + newTaxiMask[field] |= uint32(mask | (sDeathKnightTaxiNodesMask[field] & mask)); + } + else + { + newTaxiMask[field] |= mask; + } + }; + + uint32 nodeId = itr.first; + uint8 field = (uint8)((nodeId - 1) / 32); + uint32 submask = 1 << ((nodeId - 1) % 32); + + if ((factionMask[field] & submask) == 0) + { + FillTaxiMask(field, 0); + continue; + } + + TaxiPathSetForSource const& taxiPaths = itr.second; + if (taxiPaths.empty()) + { + FillTaxiMask(field, 0); + continue; + } + + TaxiPathEntry const* taxiPath = taxiPaths.begin()->second; + if (!taxiPath) + { + FillTaxiMask(field, 0); + continue; + } + + TaxiPathNodeList const& taxiNodePaths = sTaxiPathNodesByPath[taxiPath->ID]; + if (taxiNodePaths.empty()) + { + FillTaxiMask(field, 0); + continue; + } + + TaxiPathNodeEntry const* pathNode = taxiNodePaths.front(); + if (!pathNode) + { + FillTaxiMask(field, 0); + continue; + } + + AreaTableEntry const* zone = sAreaTableStore.LookupEntry(sMapMgr->GetZoneId(PHASEMASK_NORMAL, pathNode->mapid, pathNode->x, pathNode->y, pathNode->z)); + if (!zone) + { + FillTaxiMask(field, 0); + continue; + } + + LFGDungeonEntry const* lfgDungeon = GetZoneLFGDungeonEntry(zone->area_name[GetSessionDbLocaleIndex()], GetSessionDbLocaleIndex()); + if (!lfgDungeon) + { + FillTaxiMask(field, 0); + continue; + } + + // Get level from LFGDungeonEntry because the one from AreaTableEntry is not valid + // If area level is too big, do not add new taxi + if (lfgDungeon->minlevel > level) + { + FillTaxiMask(field, 0); + continue; + } + + FillTaxiMask(field, submask); } - uint32 numEmptyTaximasks = 11 - numFullTaximasks; - for (uint8 i = 0; i < numEmptyTaximasks; ++i) - taximaskstream << "0 "; - - taximaskstream << '0'; + std::ostringstream taximaskstream; + for (uint8 i = 0; i < TaxiMaskSize; ++i) + taximaskstream << uint32(newTaxiMask[i]) << ' '; stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXIMASK); stmt->SetData(0, taximaskstream.str()); diff --git a/src/server/shared/DataStores/DBCStructure.h b/src/server/shared/DataStores/DBCStructure.h index 59b5f19e3..2bbc7c5bc 100644 --- a/src/server/shared/DataStores/DBCStructure.h +++ b/src/server/shared/DataStores/DBCStructure.h @@ -2159,15 +2159,7 @@ struct TalentSpellPos typedef std::map TalentSpellPosMap; -struct TaxiPathBySourceAndDestination -{ - TaxiPathBySourceAndDestination() = default; - TaxiPathBySourceAndDestination(uint32 _id, uint32 _price) : ID(_id), price(_price) {} - - uint32 ID{0}; - uint32 price{0}; -}; -typedef std::map TaxiPathSetForSource; +typedef std::map TaxiPathSetForSource; typedef std::map TaxiPathSetBySource; typedef std::vector TaxiPathNodeList;