aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml2
-rw-r--r--src/server/game/CMakeLists.txt1
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp49
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/DataStores/DB2Structure.h2
-rw-r--r--src/server/game/DataStores/DBCEnums.h12
-rw-r--r--src/server/game/DataStores/DBCStores.cpp50
-rw-r--r--src/server/game/DataStores/DBCStores.h2
-rw-r--r--src/server/game/DataStores/DBCStructure.h14
-rw-r--r--src/server/game/DataStores/DBCfmt.h1
-rw-r--r--src/server/game/Entities/Object/Object.h33
-rw-r--r--src/server/game/Entities/Object/Position.h33
-rw-r--r--src/server/game/Entities/Player/Player.cpp147
-rw-r--r--src/server/game/Entities/Player/Player.h60
-rw-r--r--src/server/game/Entities/Player/PlayerTaxi.cpp180
-rw-r--r--src/server/game/Entities/Player/PlayerTaxi.h66
-rw-r--r--src/server/game/Entities/Taxi/TaxiPathGraph.cpp186
-rw-r--r--src/server/game/Entities/Taxi/TaxiPathGraph.h71
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp3
-rw-r--r--src/server/game/Globals/ObjectMgr.h1
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp39
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp44
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp192
-rw-r--r--src/server/game/Maps/TransportMgr.cpp2
-rw-r--r--src/server/game/Maps/TransportMgr.h2
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h32
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp2
-rw-r--r--src/server/game/Server/Packets/MovementPackets.cpp6
-rw-r--r--src/server/game/Server/Packets/MovementPackets.h11
-rw-r--r--src/server/game/Server/Packets/TaxiPackets.cpp74
-rw-r--r--src/server/game/Server/Packets/TaxiPackets.h126
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp21
-rw-r--r--src/server/game/Server/WorldSession.h22
-rw-r--r--src/server/game/World/World.cpp4
34 files changed, 1017 insertions, 474 deletions
diff --git a/.travis.yml b/.travis.yml
index 2d3ec5cce28..bbc76fa993c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,4 +31,4 @@ script:
- cat sql/updates/hotfixes/*.sql | mysql -utrinity -ptrinity hotfixes
- mysql -uroot < sql/create/drop_mysql.sql
- cd bin
- - make -j 10
+ - make -j 8
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 14bb8f25389..e4388c31e44 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -139,6 +139,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Object/Updates
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Pet
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Player
+ ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Taxi
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Totem
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Transport
${CMAKE_CURRENT_SOURCE_DIR}/Entities/Unit
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 68658586239..61b5da47b7f 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -134,7 +134,6 @@ TaxiMask sTaxiNodesMask;
TaxiMask sOldContinentsNodesMask;
TaxiMask sHordeTaxiNodesMask;
TaxiMask sAllianceTaxiNodesMask;
-TaxiMask sDeathKnightTaxiNodesMask;
TaxiPathSetBySource sTaxiPathSetBySource;
TaxiPathNodesByPath sTaxiPathNodesByPath;
@@ -455,55 +454,29 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
TaxiMaskSize, (((sTaxiNodesStore.GetNumRows() - 1) / 8) + 1));
}
- std::set<uint32> spellPaths;
- for (SpellEffectEntry const* sInfo : sSpellEffectStore)
- if (sInfo->Effect == SPELL_EFFECT_SEND_TAXI)
- spellPaths.insert(sInfo->EffectMiscValue);
-
- memset(sTaxiNodesMask, 0, sizeof(sTaxiNodesMask));
- memset(sOldContinentsNodesMask, 0, sizeof(sOldContinentsNodesMask));
- memset(sHordeTaxiNodesMask, 0, sizeof(sHordeTaxiNodesMask));
- memset(sAllianceTaxiNodesMask, 0, sizeof(sAllianceTaxiNodesMask));
- memset(sDeathKnightTaxiNodesMask, 0, sizeof(sDeathKnightTaxiNodesMask));
+ sTaxiNodesMask.fill(0);
+ sOldContinentsNodesMask.fill(0);
+ sHordeTaxiNodesMask.fill(0);
+ sAllianceTaxiNodesMask.fill(0);
for (TaxiNodesEntry const* node : sTaxiNodesStore)
{
- TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(node->ID);
- if (src_i != sTaxiPathSetBySource.end() && !src_i->second.empty())
- {
- bool ok = false;
- for (TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin(); dest_i != src_i->second.end(); ++dest_i)
- {
- // not spell path
- if (spellPaths.find(dest_i->second.ID) == spellPaths.end())
- {
- ok = true;
- break;
- }
- }
-
- if (!ok)
- continue;
- }
+ if (!(node->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE)))
+ continue;
// valid taxi network node
uint8 field = (uint8)((node->ID - 1) / 8);
uint32 submask = 1 << ((node->ID - 1) % 8);
sTaxiNodesMask[field] |= submask;
- if (node->MountCreatureID[0] && node->MountCreatureID[0] != 32981)
+ if (node->Flags & TAXI_NODE_FLAG_HORDE)
sHordeTaxiNodesMask[field] |= submask;
- if (node->MountCreatureID[1] && node->MountCreatureID[1] != 32981)
+ if (node->Flags & TAXI_NODE_FLAG_ALLIANCE)
sAllianceTaxiNodesMask[field] |= submask;
- if (node->MountCreatureID[0] == 32981 || node->MountCreatureID[1] == 32981)
- sDeathKnightTaxiNodesMask[field] |= submask;
- // old continent node (+ nodes virtually at old continents, check explicitly to avoid loading map files for zone info)
- if (node->MapID < 2 || node->ID == 82 || node->ID == 83 || node->ID == 93 || node->ID == 94)
+ uint32 nodeMap;
+ DeterminaAlternateMapPosition(node->MapID, node->Pos.X, node->Pos.Y, node->Pos.Z, &nodeMap);
+ if (nodeMap < 2)
sOldContinentsNodesMask[field] |= submask;
-
- // fix DK node at Ebon Hold and Shadow Vault flight master
- if (node->ID == 315 || node->ID == 333)
- ((TaxiNodesEntry*)node)->MountCreatureID[1] = 32981;
}
}
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 4184ab5b5d4..0769e6e9739 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -110,7 +110,6 @@ extern TaxiMask sTaxiNodesMask;
extern TaxiMask sOldContinentsNodesMask;
extern TaxiMask sHordeTaxiNodesMask;
extern TaxiMask sAllianceTaxiNodesMask;
-extern TaxiMask sDeathKnightTaxiNodesMask;
extern TaxiPathSetBySource sTaxiPathSetBySource;
extern TaxiPathNodesByPath sTaxiPathNodesByPath;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 9c898ea0101..0544ce82cea 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -1361,6 +1361,6 @@ typedef std::vector<TaxiPathNodeEntry const*> TaxiPathNodeList;
typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath;
#define TaxiMaskSize 217
-typedef uint8 TaxiMask[TaxiMaskSize];
+typedef std::array<uint8, TaxiMaskSize> TaxiMask;
#endif
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index ed1a1470e91..6a230bc9d1e 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -684,6 +684,18 @@ enum SummonPropFlags
SUMMON_PROP_FLAG_UNK21 = 0x00100000 // Totems
};
+enum TaxiNodeFlags
+{
+ TAXI_NODE_FLAG_ALLIANCE = 0x1,
+ TAXI_NODE_FLAG_HORDE = 0x2
+};
+
+enum TaxiPathNodeFlags
+{
+ TAXI_PATH_NODE_FLAG_TELEPORT = 0x1,
+ TAXI_PATH_NODE_FLAG_STOP = 0x2
+};
+
enum VehicleSeatFlags
{
VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_ENTER = 0x00000001,
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 8402c3989b3..1d3a982d586 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -156,6 +156,7 @@ DBCStorage<VehicleSeatEntry> sVehicleSeatStore(VehicleSeatfmt);
DBCStorage<WMOAreaTableEntry> sWMOAreaTableStore(WMOAreaTablefmt);
static WMOAreaInfoByTripple sWMOAreaInfoByTripple;
DBCStorage<WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreafmt);
+DBCStorage<WorldMapTransformsEntry> sWorldMapTransformsStore(WorldMapTransformsfmt);
DBCStorage<WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsfmt);
GameTable<GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore(GtBarberShopCostBasefmt);
@@ -376,6 +377,7 @@ void LoadDBCStores(const std::string& dataPath, uint32 defaultLocale)
LOAD_DBC(sVehicleStore, "Vehicle.dbc");//20444
LOAD_DBC(sWMOAreaTableStore, "WMOAreaTable.dbc");//20444
LOAD_DBC(sWorldMapAreaStore, "WorldMapArea.dbc");//20444
+ LOAD_DBC(sWorldMapTransformsStore, "WorldMapTransforms.dbc");//20444
LOAD_DBC(sWorldSafeLocsStore, "WorldSafeLocs.dbc"); // 20444
#undef LOAD_DBC
@@ -893,3 +895,51 @@ SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, u
return NULL;
}
+
+void DeterminaAlternateMapPosition(uint32 mapId, float x, float y, float z, uint32* newMapId /*= nullptr*/, DBCPosition2D* newPos /*= nullptr*/)
+{
+ WorldMapTransformsEntry const* transformation = nullptr;
+ for (WorldMapTransformsEntry const* transform : sWorldMapTransformsStore)
+ {
+ if (transform->MapID != mapId)
+ continue;
+
+ if (transform->RegionMin.X > x || transform->RegionMax.X < x)
+ continue;
+ if (transform->RegionMin.Y > y || transform->RegionMax.Y < y)
+ continue;
+ if (transform->RegionMin.Z > z || transform->RegionMax.Z < z)
+ continue;
+
+ transformation = transform;
+ break;
+ }
+
+ if (!transformation)
+ {
+ if (newMapId)
+ *newMapId = mapId;
+
+ if (newPos)
+ {
+ newPos->X = x;
+ newPos->Y = y;
+ }
+ return;
+ }
+
+ if (newMapId)
+ *newMapId = transformation->NewMapID;
+
+ if (!newPos)
+ return;
+
+ if (transformation->RegionScale > 0.0f && transformation->RegionScale < 1.0f)
+ {
+ newPos->X = (x - transformation->RegionMin.X) * transformation->RegionScale + transformation->RegionMin.X;
+ newPos->Y = (y - transformation->RegionMin.Y) * transformation->RegionScale + transformation->RegionMin.Y;
+ }
+
+ newPos->X += transformation->RegionOffset.X;
+ newPos->Y += transformation->RegionOffset.Y;
+}
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index c8e03ee95e7..63cff4a4fea 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -93,6 +93,8 @@ uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId);
void Zone2MapCoordinates(float &x, float &y, uint32 worldMapAreaId);
void Map2ZoneCoordinates(float &x, float &y, uint32 worldMapAreaId);
+// WorldMapTransforms
+void DeterminaAlternateMapPosition(uint32 mapId, float x, float y, float z, uint32* newMapId = nullptr, DBCPosition2D* newPos = nullptr);
uint32 GetMaxLevelForExpansion(uint32 expansion);
uint32 GetExpansionForLevel(uint32 level);
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index b2a2704307e..76487aadffc 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1411,6 +1411,20 @@ struct WorldMapAreaEntry
//uint32 LevelRangeMax; // 13 Maximum recommended level displayed on world map
};
+struct WorldMapTransformsEntry
+{
+ //uint32 ID; // 0
+ uint32 MapID; // 1
+ DBCPosition3D RegionMin; // 2
+ DBCPosition3D RegionMax; // 3
+ uint32 NewMapID; // 4
+ DBCPosition2D RegionOffset; // 5
+ //uint32 NewDungeonMapID; // 6
+ //uint32 Flags; // 7
+ //uint32 NewAreaID; // 8
+ float RegionScale; // 9
+};
+
struct WorldSafeLocsEntry
{
uint32 ID; // 0
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 6b2163cabca..900df980021 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -120,6 +120,7 @@ char const Vehiclefmt[] = "niiffffiiiiiiiifffffffffffffffxxxxfifiiii";
char const VehicleSeatfmt[] = "niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiiffffffffffffiiiiiiiii";
char const WMOAreaTablefmt[] = "niiixxxxxiixxxx";
char const WorldMapAreafmt[] = "xinxffffixxxxx";
+char const WorldMapTransformsfmt[] = "diffffffiffxxxf";
char const WorldSafeLocsfmt[] = "niffffx";
#endif
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 42e5137e6f9..54b6677f714 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -351,39 +351,6 @@ struct MovementInfo
void OutDebug();
};
-#define MAPID_INVALID 0xFFFFFFFF
-
-class WorldLocation : public Position
-{
- public:
- explicit WorldLocation(uint32 _mapId = MAPID_INVALID, float _x = 0.f, float _y = 0.f, float _z = 0.f, float _o = 0.f)
- : Position(_x, _y, _z, _o), m_mapId(_mapId) { }
-
- WorldLocation(WorldLocation const& loc)
- : Position(loc), m_mapId(loc.GetMapId()) { }
-
- void WorldRelocate(WorldLocation const& loc)
- {
- m_mapId = loc.GetMapId();
- Relocate(loc);
- }
-
- void WorldRelocate(uint32 _mapId = MAPID_INVALID, float _x = 0.f, float _y = 0.f, float _z = 0.f, float _o = 0.f)
- {
- m_mapId = _mapId;
- Relocate(_x, _y, _z, _o);
- }
-
- WorldLocation GetWorldLocation() const
- {
- return *this;
- }
-
- uint32 GetMapId() const { return m_mapId; }
-
- uint32 m_mapId;
-};
-
template<class T>
class GridObject
{
diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h
index 5bd37567811..109ff09d66c 100644
--- a/src/server/game/Entities/Object/Position.h
+++ b/src/server/game/Entities/Object/Position.h
@@ -215,6 +215,39 @@ public:
}
};
+#define MAPID_INVALID 0xFFFFFFFF
+
+class WorldLocation : public Position
+{
+public:
+ explicit WorldLocation(uint32 mapId = MAPID_INVALID, float x = 0.f, float y = 0.f, float z = 0.f, float o = 0.f)
+ : Position(x, y, z, o), m_mapId(mapId) { }
+
+ WorldLocation(WorldLocation const& loc)
+ : Position(loc), m_mapId(loc.GetMapId()) { }
+
+ void WorldRelocate(WorldLocation const& loc)
+ {
+ m_mapId = loc.GetMapId();
+ Relocate(loc);
+ }
+
+ void WorldRelocate(uint32 mapId = MAPID_INVALID, float x = 0.f, float y = 0.f, float z = 0.f, float o = 0.f)
+ {
+ m_mapId = mapId;
+ Relocate(x, y, z, o);
+ }
+
+ WorldLocation GetWorldLocation() const
+ {
+ return *this;
+ }
+
+ uint32 GetMapId() const { return m_mapId; }
+
+ uint32 m_mapId;
+};
+
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 33f3b3cab16..6af50b89b43 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -87,6 +87,7 @@
#include "SpellMgr.h"
#include "SpellPackets.h"
#include "TalentPackets.h"
+#include "TaxiPackets.h"
#include "ToyPackets.h"
#include "TradePackets.h"
#include "Transport.h"
@@ -129,148 +130,6 @@ uint32 const MasterySpells[MAX_CLASSES] =
uint64 const MAX_MONEY_AMOUNT = 9999999999ULL;
-// == PlayerTaxi ================================================
-
-PlayerTaxi::PlayerTaxi()
-{
- memset(m_taximask, 0, sizeof(m_taximask));
-}
-
-void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level)
-{
- // class specific initial known nodes
- switch (chrClass)
- {
- case CLASS_DEATH_KNIGHT:
- {
- for (uint8 i = 0; i < TaxiMaskSize; ++i)
- m_taximask[i] |= sOldContinentsNodesMask[i];
- break;
- }
- }
-
- // race specific initial known nodes: capital and taxi hub masks
- switch (race)
- {
- case RACE_HUMAN: SetTaximaskNode(2); break; // Human
- case RACE_ORC: SetTaximaskNode(23); break; // Orc
- case RACE_DWARF: SetTaximaskNode(6); break; // Dwarf
- case RACE_NIGHTELF: SetTaximaskNode(26);
- SetTaximaskNode(27); break; // Night Elf
- case RACE_UNDEAD_PLAYER: SetTaximaskNode(11); break;// Undead
- case RACE_TAUREN: SetTaximaskNode(22); break; // Tauren
- case RACE_GNOME: SetTaximaskNode(6); break; // Gnome
- case RACE_TROLL: SetTaximaskNode(23); break; // Troll
- case RACE_BLOODELF: SetTaximaskNode(82); break; // Blood Elf
- case RACE_DRAENEI: SetTaximaskNode(94); break; // Draenei
- }
-
- // new continent starting masks (It will be accessible only at new map)
- switch (Player::TeamForRace(race))
- {
- case ALLIANCE: SetTaximaskNode(100); break;
- case HORDE: SetTaximaskNode(99); break;
- }
- // level dependent taxi hubs
- if (level >= 68)
- SetTaximaskNode(213); //Shattered Sun Staging Area
-}
-
-void PlayerTaxi::LoadTaxiMask(std::string const &data)
-{
- Tokenizer tokens(data, ' ');
-
- uint8 index = 0;
- for (Tokenizer::const_iterator iter = tokens.begin(); index < TaxiMaskSize && iter != tokens.end(); ++iter, ++index)
- {
- // load and set bits only for existing taxi nodes
- m_taximask[index] = sTaxiNodesMask[index] & atoul(*iter);
- }
-}
-
-void PlayerTaxi::AppendTaximaskTo(ByteBuffer& data, bool all)
-{
- data << uint32(TaxiMaskSize);
- if (all)
- {
- for (uint8 i = 0; i < TaxiMaskSize; ++i)
- data << uint8(sTaxiNodesMask[i]); // all existed nodes
- }
- else
- {
- for (uint8 i = 0; i < TaxiMaskSize; ++i)
- data << uint8(m_taximask[i]); // known nodes
- }
-}
-
-bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, uint32 team)
-{
- ClearTaxiDestinations();
-
- Tokenizer Tokenizer(values, ' ');
-
- for (Tokenizer::const_iterator iter = Tokenizer.begin(); iter != Tokenizer.end(); ++iter)
- {
- uint32 node = atoul(*iter);
- AddTaxiDestination(node);
- }
-
- if (m_TaxiDestinations.empty())
- return true;
-
- // Check integrity
- if (m_TaxiDestinations.size() < 2)
- return false;
-
- for (size_t i = 1; i < m_TaxiDestinations.size(); ++i)
- {
- uint32 cost;
- uint32 path;
- sObjectMgr->GetTaxiPath(m_TaxiDestinations[i-1], m_TaxiDestinations[i], path, cost);
- if (!path)
- return false;
- }
-
- // can't load taxi path without mount set (quest taxi path?)
- if (!sObjectMgr->GetTaxiMountDisplayId(GetTaxiSource(), team, true))
- return false;
-
- return true;
-}
-
-std::string PlayerTaxi::SaveTaxiDestinationsToString()
-{
- if (m_TaxiDestinations.empty())
- return "";
-
- std::ostringstream ss;
-
- for (size_t i=0; i < m_TaxiDestinations.size(); ++i)
- ss << m_TaxiDestinations[i] << ' ';
-
- return ss.str();
-}
-
-uint32 PlayerTaxi::GetCurrentTaxiPath() const
-{
- if (m_TaxiDestinations.size() < 2)
- return 0;
-
- uint32 path;
- uint32 cost;
-
- sObjectMgr->GetTaxiPath(m_TaxiDestinations[0], m_TaxiDestinations[1], path, cost);
-
- return path;
-}
-
-std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
-{
- for (uint8 i = 0; i < TaxiMaskSize; ++i)
- ss << uint32(taxi.m_taximask[i]) << ' ';
- return ss;
-}
-
//== TradeData =================================================
TradeData* TradeData::GetTraderData() const
@@ -20916,7 +20775,10 @@ void Player::SetRestBonus(float rest_bonus_new)
bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc /*= NULL*/, uint32 spellid /*= 0*/)
{
if (nodes.size() < 2)
+ {
+ GetSession()->SendActivateTaxiReply(ERR_TAXINOSUCHPATH);
return false;
+ }
// not let cheating with start flight in time of logout process || while in combat || has type state: stunned || has type state: root
if (GetSession()->isLogingOut() || IsInCombat() || HasUnitState(UNIT_STATE_STUNNED) || HasUnitState(UNIT_STATE_ROOT))
@@ -20999,7 +20861,6 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
GetSession()->SendActivateTaxiReply(ERR_TAXIUNSPECIFIEDSERVERERROR);
return false;
}
-
// Prepare to flight start now
// stop combat at start taxi flight if any
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 20f6e201f0f..d16fc7a1fc1 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -31,10 +31,7 @@
#include "Unit.h"
#include "Opcodes.h"
#include "WorldSession.h"
-
-#include <limits>
-#include <string>
-#include <vector>
+#include "PlayerTaxi.h"
struct CreatureTemplate;
struct Mail;
@@ -1086,61 +1083,6 @@ enum PlayerLogXPReason
LOG_XP_REASON_NO_KILL = 1
};
-class PlayerTaxi
-{
- public:
- PlayerTaxi();
- ~PlayerTaxi() { }
- // Nodes
- void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level);
- void LoadTaxiMask(std::string const& data);
-
- bool IsTaximaskNodeKnown(uint32 nodeidx) const
- {
- uint8 field = uint8((nodeidx - 1) / 8);
- uint32 submask = 1 << ((nodeidx-1) % 8);
- return (m_taximask[field] & submask) == submask;
- }
- bool SetTaximaskNode(uint32 nodeidx)
- {
- uint8 field = uint8((nodeidx - 1) / 8);
- uint32 submask = 1 << ((nodeidx- 1) % 8);
- if ((m_taximask[field] & submask) != submask)
- {
- m_taximask[field] |= submask;
- return true;
- }
- else
- return false;
- }
- void AppendTaximaskTo(ByteBuffer& data, bool all);
-
- // Destinations
- bool LoadTaxiDestinationsFromString(std::string const& values, uint32 team);
- std::string SaveTaxiDestinationsToString();
-
- void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
- void AddTaxiDestination(uint32 dest) { m_TaxiDestinations.push_back(dest); }
- uint32 GetTaxiSource() const { return m_TaxiDestinations.empty() ? 0 : m_TaxiDestinations.front(); }
- uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() < 2 ? 0 : m_TaxiDestinations[1]; }
- uint32 GetCurrentTaxiPath() const;
- uint32 NextTaxiDestination()
- {
- m_TaxiDestinations.pop_front();
- return GetTaxiDestination();
- }
-
- std::deque<uint32> const& GetPath() const { return m_TaxiDestinations; }
- bool empty() const { return m_TaxiDestinations.empty(); }
-
- friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
- private:
- TaxiMask m_taximask;
- std::deque<uint32> m_TaxiDestinations;
-};
-
-std::ostringstream& operator << (std::ostringstream& ss, PlayerTaxi const& taxi);
-
class Player;
/// Holder for Battleground data
diff --git a/src/server/game/Entities/Player/PlayerTaxi.cpp b/src/server/game/Entities/Player/PlayerTaxi.cpp
new file mode 100644
index 00000000000..466cb7b947b
--- /dev/null
+++ b/src/server/game/Entities/Player/PlayerTaxi.cpp
@@ -0,0 +1,180 @@
+#include "Player.h"
+#include "TaxiPackets.h"
+#include "ObjectMgr.h"
+#include <limits>
+#include <math.h>
+
+void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level)
+{
+ // class specific initial known nodes
+ TaxiMask const& factionMask = Player::TeamForRace(race) == HORDE ? sHordeTaxiNodesMask : sAllianceTaxiNodesMask;
+ switch (chrClass)
+ {
+ case CLASS_DEATH_KNIGHT:
+ {
+ for (uint8 i = 0; i < TaxiMaskSize; ++i)
+ m_taximask[i] |= sOldContinentsNodesMask[i] & factionMask[i];
+ break;
+ }
+ }
+
+ // race specific initial known nodes: capital and taxi hub masks
+ switch (race)
+ {
+ case RACE_HUMAN:
+ case RACE_DWARF:
+ case RACE_NIGHTELF:
+ case RACE_GNOME:
+ case RACE_DRAENEI:
+ case RACE_WORGEN:
+ case RACE_PANDAREN_ALLIANCE:
+ SetTaximaskNode(2); // Stormwind, Elwynn
+ SetTaximaskNode(6); // Ironforge, Dun Morogh
+ SetTaximaskNode(26); // Lor'danel, Darkshore
+ SetTaximaskNode(27); // Rut'theran Village, Teldrassil
+ SetTaximaskNode(49); // Moonglade (Alliance)
+ SetTaximaskNode(94); // The Exodar
+ SetTaximaskNode(456); // Dolanaar, Teldrassil
+ SetTaximaskNode(457); // Darnassus, Teldrassil
+ SetTaximaskNode(582); // Goldshire, Elwynn
+ SetTaximaskNode(589); // Eastvale Logging Camp, Elwynn
+ SetTaximaskNode(619); // Kharanos, Dun Morogh
+ SetTaximaskNode(620); // Gol'Bolar Quarry, Dun Morogh
+ SetTaximaskNode(624); // Azure Watch, Azuremyst Isle
+ break;
+ case RACE_ORC:
+ case RACE_UNDEAD_PLAYER:
+ case RACE_TAUREN:
+ case RACE_TROLL:
+ case RACE_BLOODELF:
+ case RACE_GOBLIN:
+ case RACE_PANDAREN_HORDE:
+ SetTaximaskNode(11); // Undercity, Tirisfal
+ SetTaximaskNode(22); // Thunder Bluff, Mulgore
+ SetTaximaskNode(23); // Orgrimmar, Durotar
+ SetTaximaskNode(69); // Moonglade (Horde)
+ SetTaximaskNode(82); // Silvermoon City
+ SetTaximaskNode(384); // The Bulwark, Tirisfal
+ SetTaximaskNode(402); // Bloodhoof Village, Mulgore
+ SetTaximaskNode(460); // Brill, Tirisfal Glades
+ SetTaximaskNode(536); // Sen'jin Village, Durotar
+ SetTaximaskNode(537); // Razor Hill, Durotar
+ SetTaximaskNode(625); // Fairbreeze Village, Eversong Woods
+ SetTaximaskNode(631); // Falconwing Square, Eversong Woods
+ break;
+ }
+
+ // new continent starting masks (It will be accessible only at new map)
+ switch (Player::TeamForRace(race))
+ {
+ case ALLIANCE: SetTaximaskNode(100); break;
+ case HORDE: SetTaximaskNode(99); break;
+ }
+
+ // level dependent taxi hubs
+ if (level >= 68)
+ SetTaximaskNode(213); //Shattered Sun Staging Area
+}
+
+void PlayerTaxi::LoadTaxiMask(std::string const &data)
+{
+ Tokenizer tokens(data, ' ');
+
+ uint8 index = 0;
+ for (Tokenizer::const_iterator iter = tokens.begin(); index < TaxiMaskSize && iter != tokens.end(); ++iter, ++index)
+ {
+ // load and set bits only for existing taxi nodes
+ m_taximask[index] = sTaxiNodesMask[index] & atoul(*iter);
+ }
+}
+
+void PlayerTaxi::AppendTaximaskTo(WorldPackets::Taxi::ShowTaxiNodes& data, bool all)
+{
+ if (all)
+ data.Nodes = &sTaxiNodesMask; // all existed nodes
+ else
+ data.Nodes = &m_taximask; // known nodes
+}
+
+bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, uint32 team)
+{
+ ClearTaxiDestinations();
+
+ Tokenizer tokens(values, ' ');
+
+ for (Tokenizer::const_iterator iter = tokens.begin(); iter != tokens.end(); ++iter)
+ {
+ uint32 node = atoul(*iter);
+ AddTaxiDestination(node);
+ }
+
+ if (m_TaxiDestinations.empty())
+ return true;
+
+ // Check integrity
+ if (m_TaxiDestinations.size() < 2)
+ return false;
+
+ for (size_t i = 1; i < m_TaxiDestinations.size(); ++i)
+ {
+ uint32 cost;
+ uint32 path;
+ sObjectMgr->GetTaxiPath(m_TaxiDestinations[i - 1], m_TaxiDestinations[i], path, cost);
+ if (!path)
+ return false;
+ }
+
+ // can't load taxi path without mount set (quest taxi path?)
+ if (!sObjectMgr->GetTaxiMountDisplayId(GetTaxiSource(), team, true))
+ return false;
+
+ return true;
+}
+
+std::string PlayerTaxi::SaveTaxiDestinationsToString()
+{
+ if (m_TaxiDestinations.empty())
+ return "";
+
+ std::ostringstream ss;
+
+ for (size_t i = 0; i < m_TaxiDestinations.size(); ++i)
+ ss << m_TaxiDestinations[i] << ' ';
+
+ return ss.str();
+}
+
+uint32 PlayerTaxi::GetCurrentTaxiPath() const
+{
+ if (m_TaxiDestinations.size() < 2)
+ return 0;
+
+ uint32 path;
+ uint32 cost;
+
+ sObjectMgr->GetTaxiPath(m_TaxiDestinations[0], m_TaxiDestinations[1], path, cost);
+
+ return path;
+}
+
+std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi)
+{
+ for (uint8 i = 0; i < TaxiMaskSize; ++i)
+ ss << uint32(taxi.m_taximask[i]) << ' ';
+ return ss;
+}
+
+void PlayerTaxi::RequestEarlyLanding()
+{
+ if (m_TaxiDestinations.empty())
+ return;
+
+ for (std::deque<uint32>::iterator it = m_TaxiDestinations.begin(); it != m_TaxiDestinations.end(); it++)
+ {
+ if (IsTaximaskNodeKnown(*it))
+ {
+ m_TaxiDestinations.erase(++it, m_TaxiDestinations.end());
+ return;
+ }
+ }
+}
diff --git a/src/server/game/Entities/Player/PlayerTaxi.h b/src/server/game/Entities/Player/PlayerTaxi.h
new file mode 100644
index 00000000000..6739f5f6ab1
--- /dev/null
+++ b/src/server/game/Entities/Player/PlayerTaxi.h
@@ -0,0 +1,66 @@
+#ifndef __PLAYERTAXI_H__
+#define __PLAYERTAXI_H__
+
+#include "DB2Stores.h"
+#include "Define.h"
+#include "WorldSession.h"
+#include <map>
+
+class PlayerTaxi
+{
+ public:
+ PlayerTaxi() { }
+ ~PlayerTaxi() { }
+ // Nodes
+ void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint8 level);
+ void LoadTaxiMask(std::string const& data);
+
+ bool IsTaximaskNodeKnown(uint32 nodeidx) const
+ {
+ uint8 field = uint8((nodeidx - 1) / 8);
+ uint32 submask = 1 << ((nodeidx-1) % 8);
+ return (m_taximask[field] & submask) == submask;
+ }
+ bool SetTaximaskNode(uint32 nodeidx)
+ {
+ uint8 field = uint8((nodeidx - 1) / 8);
+ uint32 submask = 1 << ((nodeidx- 1) % 8);
+ if ((m_taximask[field] & submask) != submask)
+ {
+ m_taximask[field] |= submask;
+ return true;
+ }
+ else
+ return false;
+ }
+ void AppendTaximaskTo(WorldPackets::Taxi::ShowTaxiNodes& data, bool all);
+ TaxiMask const& GetTaxiMask() const { return m_taximask; }
+
+ // Destinations
+ bool LoadTaxiDestinationsFromString(std::string const& values, uint32 team);
+ std::string SaveTaxiDestinationsToString();
+
+ void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
+ void AddTaxiDestination(uint32 dest) { m_TaxiDestinations.push_back(dest); }
+ void SetTaxiDestination(std::vector<uint32>& nodes) { m_TaxiDestinations.clear(); m_TaxiDestinations.insert(m_TaxiDestinations.begin(), nodes.begin(), nodes.end()); }
+ uint32 GetTaxiSource() const { return m_TaxiDestinations.empty() ? 0 : m_TaxiDestinations.front(); }
+ uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() < 2 ? 0 : m_TaxiDestinations[1]; }
+ uint32 GetCurrentTaxiPath() const;
+ uint32 NextTaxiDestination()
+ {
+ m_TaxiDestinations.pop_front();
+ return GetTaxiDestination();
+ }
+ void RequestEarlyLanding();
+ std::deque<uint32> const& GetPath() const { return m_TaxiDestinations; }
+ bool empty() const { return m_TaxiDestinations.empty(); }
+
+ friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
+ private:
+ TaxiMask m_taximask = { };
+ std::deque<uint32> m_TaxiDestinations;
+};
+
+std::ostringstream& operator << (std::ostringstream& ss, PlayerTaxi const& taxi);
+
+#endif
diff --git a/src/server/game/Entities/Taxi/TaxiPathGraph.cpp b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp
new file mode 100644
index 00000000000..ef899795bfd
--- /dev/null
+++ b/src/server/game/Entities/Taxi/TaxiPathGraph.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "TaxiPathGraph.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+#include "DBCStores.h"
+#include "DB2Stores.h"
+#include "Config.h"
+#include "Util.h"
+#include <boost/graph/dijkstra_shortest_paths.hpp>
+#include <boost/property_map/transform_value_property_map.hpp>
+
+void TaxiPathGraph::Initialize()
+{
+ if (GetVertexCount() > 0)
+ return;
+
+ std::vector<std::pair<edge, EdgeCost>> edges;
+
+ // Initialize here
+ for (TaxiPathEntry const* path : sTaxiPathStore)
+ {
+ TaxiNodesEntry const* from = sTaxiNodesStore.LookupEntry(path->From);
+ TaxiNodesEntry const* to = sTaxiNodesStore.LookupEntry(path->To);
+ if (from && to && from->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE) && to->Flags & (TAXI_NODE_FLAG_ALLIANCE | TAXI_NODE_FLAG_HORDE))
+ AddVerticeAndEdgeFromNodeInfo(from, to, path->ID, edges);
+ }
+
+ // create graph
+ m_graph = Graph(GetVertexCount());
+ WeightMap weightmap = boost::get(boost::edge_weight, m_graph);
+
+ for (std::size_t j = 0; j < edges.size(); ++j)
+ {
+ edge_descriptor e = boost::add_edge(edges[j].first.first, edges[j].first.second, m_graph).first;
+ weightmap[e] = edges[j].second;
+ }
+}
+
+uint32 TaxiPathGraph::GetNodeIDFromVertexID(vertex_descriptor vertexID)
+{
+ if (vertexID < m_vertices.size())
+ return m_vertices[vertexID]->ID;
+
+ return std::numeric_limits<uint32>::max();
+}
+
+TaxiPathGraph::vertex_descriptor TaxiPathGraph::GetVertexIDFromNodeID(TaxiNodesEntry const* node)
+{
+ return node->LearnableIndex;
+}
+
+std::size_t TaxiPathGraph::GetVertexCount()
+{
+ //So we can use this function for readability, we define either max defined vertices or already loaded in graph count
+ return std::max(boost::num_vertices(m_graph), m_vertices.size());
+}
+
+void TaxiPathGraph::AddVerticeAndEdgeFromNodeInfo(TaxiNodesEntry const* from, TaxiNodesEntry const* to, uint32 pathId, std::vector<std::pair<edge, EdgeCost>>& edges)
+{
+ if (from != to)
+ {
+ vertex_descriptor fromVertexID = CreateVertexFromFromNodeInfoIfNeeded(from);
+ vertex_descriptor toVertexID = CreateVertexFromFromNodeInfoIfNeeded(to);
+
+ float totalDist = 0.0f;
+ TaxiPathNodeList const& nodes = sTaxiPathNodesByPath[pathId];
+ if (nodes.size() < 2)
+ {
+ edges.push_back(std::make_pair(edge(fromVertexID, toVertexID), EdgeCost{ to, 0xFFFF }));
+ return;
+ }
+
+ std::size_t last = nodes.size();
+ std::size_t first = 0;
+ if (nodes.size() > 2)
+ {
+ --last;
+ ++first;
+ }
+
+ for (std::size_t i = first + 1; i < last; ++i)
+ {
+ if (nodes[i - 1]->Flags & TAXI_PATH_NODE_FLAG_TELEPORT)
+ continue;
+
+ uint32 map1, map2;
+ DBCPosition2D pos1, pos2;
+
+ DeterminaAlternateMapPosition(nodes[i - 1]->MapID, nodes[i - 1]->Loc.X, nodes[i - 1]->Loc.Y, nodes[i - 1]->Loc.Z, &map1, &pos1);
+ DeterminaAlternateMapPosition(nodes[i]->MapID, nodes[i]->Loc.X, nodes[i]->Loc.Y, nodes[i]->Loc.Z, &map2, &pos2);
+
+ if (map1 != map2)
+ continue;
+
+ totalDist += std::sqrt(
+ std::pow(pos2.X - pos1.X, 2) +
+ std::pow(pos2.Y - pos1.Y, 2) +
+ std::pow(nodes[i]->Loc.Z - nodes[i - 1]->Loc.Z, 2));
+ }
+
+ uint32 dist = uint32(totalDist);
+ if (dist > 0xFFFF)
+ return;
+
+ edges.push_back(std::make_pair(edge(fromVertexID, toVertexID), EdgeCost{ to, dist }));
+ }
+}
+
+std::size_t TaxiPathGraph::GetCompleteNodeRoute(TaxiNodesEntry const* from, TaxiNodesEntry const* to, Player const* player, std::vector<uint32>& shortestPath)
+{
+ /*
+ Information about node algorithm from client
+ Since client does not give information about *ALL* nodes you have to pass by when going from sourceNodeID to destinationNodeID, we need to use Dijkstra algorithm.
+ Examining several paths I discovered the following algorithm:
+ * If destinationNodeID has is the next destination, connected directly to sourceNodeID, then, client just pick up this route regardless of distance
+ * else we use dijkstra to find the shortest path.
+ * When early landing is requested, according to behavior on retail, you can never end in a node you did not discovered before
+ */
+
+ // Find if we have a direct path
+ uint32 pathId, goldCost;
+ sObjectMgr->GetTaxiPath(from->ID, to->ID, pathId, goldCost);
+ if (pathId)
+ shortestPath = { from->ID, to->ID };
+ else
+ {
+ shortestPath.clear();
+ std::vector<vertex_descriptor> p(boost::num_vertices(m_graph));
+
+ boost::dijkstra_shortest_paths(m_graph, GetVertexIDFromNodeID(from),
+ boost::predecessor_map(boost::make_iterator_property_map(p.begin(), boost::get(boost::vertex_index, m_graph)))
+ .weight_map(boost::make_transform_value_property_map(
+ [player](EdgeCost const& edgeCost) { return edgeCost.EvaluateDistance(player); },
+ boost::get(boost::edge_weight, m_graph))));
+
+ // found a path to the goal
+ for (vertex_descriptor v = GetVertexIDFromNodeID(to); ; v = p[v])
+ {
+ shortestPath.push_back(GetNodeIDFromVertexID(v));
+ if (v == p[v])
+ break;
+ }
+
+ std::reverse(shortestPath.begin(), shortestPath.end());
+ }
+
+ return shortestPath.size();
+}
+
+TaxiPathGraph::vertex_descriptor TaxiPathGraph::CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesEntry const* node)
+{
+ //Check if we need a new one or if it may be already created
+ if (m_vertices.size() <= node->LearnableIndex)
+ m_vertices.resize(node->LearnableIndex + 1);
+
+ m_vertices[node->LearnableIndex] = node;
+ return node->LearnableIndex;
+}
+
+uint32 TaxiPathGraph::EdgeCost::EvaluateDistance(Player const* player) const
+{
+ uint32 requireFlag = (player->GetTeam() == ALLIANCE) ? TAXI_NODE_FLAG_ALLIANCE : TAXI_NODE_FLAG_HORDE;
+ if (!(To->Flags & requireFlag))
+ return std::numeric_limits<uint16>::max();
+
+ //if (To->ConditionID && !player->MeetsCondition(To->ConditionID))
+ // return std::numeric_limits<uint16>::max();
+
+ return Distance;
+}
diff --git a/src/server/game/Entities/Taxi/TaxiPathGraph.h b/src/server/game/Entities/Taxi/TaxiPathGraph.h
new file mode 100644
index 00000000000..15d139fb55d
--- /dev/null
+++ b/src/server/game/Entities/Taxi/TaxiPathGraph.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TAXIPATHGRAPH_HPP
+#define TAXIPATHGRAPH_HPP
+
+#include "Position.h"
+#include "Define.h"
+#include <boost/graph/adjacency_list.hpp>
+
+class Player;
+struct TaxiNodesEntry;
+
+class TaxiPathGraph
+{
+public:
+ static TaxiPathGraph& Instance()
+ {
+ static TaxiPathGraph instance;
+ return instance;
+ }
+
+ void Initialize();
+ std::size_t GetCompleteNodeRoute(TaxiNodesEntry const* from, TaxiNodesEntry const* to, Player const* player, std::vector<uint32>& shortestPath);
+
+private:
+ struct EdgeCost
+ {
+ TaxiNodesEntry const* To;
+ uint32 Distance;
+ uint32 EvaluateDistance(Player const* player) const;
+ };
+ typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, boost::property<boost::vertex_index_t, uint32>, boost::property<boost::edge_weight_t, EdgeCost>> Graph;
+ typedef boost::property_map<Graph, boost::edge_weight_t>::type WeightMap;
+ typedef Graph::vertex_descriptor vertex_descriptor;
+ typedef Graph::edge_descriptor edge_descriptor;
+ typedef std::pair<uint32, uint32> edge;
+
+ TaxiPathGraph() { }
+ ~TaxiPathGraph() { }
+
+ void AddVerticeAndEdgeFromNodeInfo(TaxiNodesEntry const* from, TaxiNodesEntry const* to, uint32 pathId, std::vector<std::pair<edge, EdgeCost>>& edges);
+ vertex_descriptor GetVertexIDFromNodeID(TaxiNodesEntry const* node);
+ uint32 GetNodeIDFromVertexID(vertex_descriptor vertexID);
+ vertex_descriptor CreateVertexFromFromNodeInfoIfNeeded(TaxiNodesEntry const* node);
+ std::size_t GetVertexCount();
+
+ Graph m_graph;
+ std::vector<TaxiNodesEntry const*> m_vertices;
+
+ TaxiPathGraph(TaxiPathGraph const&) = delete;
+ TaxiPathGraph& operator=(TaxiPathGraph const&) = delete;
+};
+
+#define sTaxiPathGraph TaxiPathGraph::Instance()
+
+#endif /* TAXIPATHGRAPH_HPP */
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 5352112caca..b048afe16a6 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -5673,9 +5673,10 @@ uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, ui
float dist = 10000;
uint32 id = 0;
+ uint32 requireFlag = (team == ALLIANCE) ? TAXI_NODE_FLAG_ALLIANCE : TAXI_NODE_FLAG_HORDE;
for (TaxiNodesEntry const* node : sTaxiNodesStore)
{
- if (!node || node->MapID != mapid || (!node->MountCreatureID[team == ALLIANCE ? 1 : 0] && node->MountCreatureID[0] != 32981)) // dk flight
+ if (!node || node->MapID != mapid || !(node->Flags & requireFlag))
continue;
uint8 field = (uint8)((node->ID - 1) / 8);
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 8e660e3f32c..c5f3fb908e7 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -796,6 +796,7 @@ class ObjectMgr
uint32 GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team);
void GetTaxiPath(uint32 source, uint32 destination, uint32 &path, uint32 &cost);
+ void GetTaxiPath(uint32 source, uint32 destination, std::vector<uint32>& path, uint32& cost);
uint32 GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt_team = false);
Quest const* GetQuestTemplate(uint32 quest_id) const
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 39a81b12336..c3ed19fdf71 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -2009,41 +2009,14 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
// 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;
- if (numFullTaximasks > 11)
- numFullTaximasks = 11;
-
- if (newTeamId == TEAM_ALLIANCE)
+ TaxiMask const& factionMask = newTeamId == TEAM_HORDE ? sHordeTaxiNodesMask : sAllianceTaxiNodesMask;
+ for (uint8 i = 0; i < TaxiMaskSize; ++i)
{
- if (playerClass != CLASS_DEATH_KNIGHT)
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sAllianceTaxiNodesMask[i]) << ' ';
- }
- else
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sAllianceTaxiNodesMask[i] | sDeathKnightTaxiNodesMask[i]) << ' ';
- }
+ // i = (315 - 1) / 8 = 39
+ // m = 1 << ((315 - 1) % 8) = 4
+ uint8 deathKnightExtraNode = playerClass != CLASS_DEATH_KNIGHT || i != 39 ? 0 : 4;
+ taximaskstream << uint32(factionMask[i] | deathKnightExtraNode) << ' ';
}
- else
- {
- if (playerClass != CLASS_DEATH_KNIGHT)
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sHordeTaxiNodesMask[i]) << ' ';
- }
- else
- {
- for (uint8 i = 0; i < numFullTaximasks; ++i)
- taximaskstream << uint32(sHordeTaxiNodesMask[i] | sDeathKnightTaxiNodesMask[i]) << ' ';
- }
- }
-
- uint32 numEmptyTaximasks = 11 - numFullTaximasks;
- for (uint8 i = 0; i < numEmptyTaximasks; ++i)
- taximaskstream << "0 ";
- taximaskstream << '0';
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_TAXIMASK);
stmt->setString(0, taximaskstream.str());
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 4256a41f80f..279345845a1 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -526,3 +526,47 @@ void WorldSession::HandleSetCollisionHeightAck(WorldPackets::Movement::MoveSetCo
void WorldSession::HandleMoveTimeSkippedOpcode(WorldPackets::Movement::MoveTimeSkipped& /*moveTimeSkipped*/)
{
}
+
+void WorldSession::HandleMoveSplineDoneOpcode(WorldPackets::Movement::MoveSplineDone& moveSplineDone)
+{
+ MovementInfo movementInfo = moveSplineDone.movementInfo;
+ _player->ValidateMovementInfo(&movementInfo);
+
+ // in taxi flight packet received in 2 case:
+ // 1) end taxi path in far (multi-node) flight
+ // 2) switch from one map to other in case multim-map taxi path
+ // we need process only (1)
+
+ uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination();
+ if (curDest)
+ {
+ TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
+
+ // far teleport case
+ if (curDestNode && curDestNode->MapID != GetPlayer()->GetMapId())
+ {
+ if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
+ {
+ // short preparations to continue flight
+ FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
+
+ flight->SetCurrentNodeAfterTeleport();
+ TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()];
+ flight->SkipCurrentNode();
+
+ GetPlayer()->TeleportTo(curDestNode->MapID, node->Loc.X, node->Loc.Y, node->Loc.Z, GetPlayer()->GetOrientation());
+ }
+ }
+
+ return;
+ }
+
+ // at this point only 1 node is expected (final destination)
+ if (GetPlayer()->m_taxi.GetPath().size() != 1)
+ return;
+
+ GetPlayer()->CleanupAfterTaxiFlight();
+ GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
+ if (GetPlayer()->pvpInfo.IsHostile)
+ GetPlayer()->CastSpell(GetPlayer(), 2479, true);
+}
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index 1669bc306d6..d3612e5a031 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -24,14 +24,19 @@
#include "Log.h"
#include "ObjectMgr.h"
#include "Player.h"
-#include "WaypointMovementGenerator.h"
+#include "TaxiPackets.h"
+#include "TaxiPathGraph.h"
-void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvData)
+void WorldSession::HandleEnableTaxiNodeOpcode(WorldPackets::Taxi::EnableTaxiNode& enableTaxiNode)
{
- ObjectGuid guid;
+ Creature* unit = GetPlayer()->GetMap()->GetCreature(enableTaxiNode.Unit);
+ SendLearnNewTaxiNode(unit);
+}
+
- recvData >> guid;
- SendTaxiStatus(guid);
+void WorldSession::HandleTaxiNodeStatusQueryOpcode(WorldPackets::Taxi::TaxiNodeStatusQuery& taxiNodeStatusQuery)
+{
+ SendTaxiStatus(taxiNodeStatusQuery.UnitGUID);
}
void WorldSession::SendTaxiStatus(ObjectGuid guid)
@@ -46,32 +51,30 @@ void WorldSession::SendTaxiStatus(ObjectGuid guid)
uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
- // not found nearest
- if (curloc == 0)
- return;
+ WorldPackets::Taxi::TaxiNodeStatus data;
+ data.Unit = guid;
+
+ if (!curloc)
+ data.Status = TAXISTATUS_NONE;
+ else if (unit->GetReactionTo(GetPlayer()) >= REP_NEUTRAL)
+ data.Status = GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? TAXISTATUS_LEARNED : TAXISTATUS_UNLEARNED;
+ else
+ data.Status = TAXISTATUS_NOT_ELIGIBLE;
- TC_LOG_DEBUG("network", "WORLD: current location %u ", curloc);
+ SendPacket(data.Write());
- WorldPacket data(SMSG_TAXI_NODE_STATUS, 9);
- data << guid;
- data << uint8(GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) ? 1 : 0);
- SendPacket(&data);
- TC_LOG_DEBUG("network", "WORLD: Sent SMSG_TAXINODE_STATUS");
+ TC_LOG_DEBUG("network", "WORLD: Sent SMSG_TAXI_NODE_STATUS");
}
-void WorldSession::HandleTaxiQueryAvailableNodes(WorldPacket& recvData)
+void WorldSession::HandleTaxiQueryAvailableNodesOpcode(WorldPackets::Taxi::TaxiQueryAvailableNodes& taxiQueryAvailableNodes)
{
- ObjectGuid guid;
- recvData >> guid;
-
// cheating checks
- Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
+ Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(taxiQueryAvailableNodes.Unit, UNIT_NPC_FLAG_FLIGHTMASTER);
if (!unit)
{
- TC_LOG_DEBUG("network", "WORLD: HandleTaxiQueryAvailableNodes - %s not found or you can't interact with him.", guid.ToString().c_str());
+ TC_LOG_DEBUG("network", "WORLD: HandleTaxiQueryAvailableNodes - %s not found or you can't interact with him.", taxiQueryAvailableNodes.Unit.ToString().c_str());
return;
}
-
// remove fake death
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
@@ -97,14 +100,14 @@ void WorldSession::SendTaxiMenu(Creature* unit)
TC_LOG_DEBUG("network", "WORLD: CMSG_TAXINODE_STATUS_QUERY %u ", curloc);
- WorldPacket data(SMSG_SHOW_TAXI_NODES, (4 + 8 + 4 + 8 * 4));
- data << uint32(1);
- data << unit->GetGUID();
- data << uint32(curloc);
- GetPlayer()->m_taxi.AppendTaximaskTo(data, GetPlayer()->isTaxiCheater());
- SendPacket(&data);
+ WorldPackets::Taxi::ShowTaxiNodes data;
+ data.WindowInfo = boost::in_place();
+ data.WindowInfo->UnitGUID = unit->GetGUID();
+ data.WindowInfo->CurrentNode = curloc;
- TC_LOG_DEBUG("network", "WORLD: Sent SMSG_SHOWTAXINODES");
+ GetPlayer()->m_taxi.AppendTaximaskTo(data, lastTaxiCheaterState);
+
+ SendPacket(data.Write());
GetPlayer()->SetTaxiCheater(lastTaxiCheaterState);
}
@@ -134,13 +137,12 @@ bool WorldSession::SendLearnNewTaxiNode(Creature* unit)
if (GetPlayer()->m_taxi.SetTaximaskNode(curloc))
{
- WorldPacket msg(SMSG_NEW_TAXI_PATH, 0);
- SendPacket(&msg);
+ SendPacket(WorldPackets::Taxi::NewTaxiPath().Write());
- WorldPacket update(SMSG_TAXI_NODE_STATUS, 9);
- update << unit->GetGUID();
- update << uint8(1);
- SendPacket(&update);
+ WorldPackets::Taxi::TaxiNodeStatus data;
+ data.Unit = unit->GetGUID();
+ data.Status = TAXISTATUS_LEARNED;
+ SendPacket(data.Write());
return true;
}
@@ -151,128 +153,50 @@ bool WorldSession::SendLearnNewTaxiNode(Creature* unit)
void WorldSession::SendDiscoverNewTaxiNode(uint32 nodeid)
{
if (GetPlayer()->m_taxi.SetTaximaskNode(nodeid))
- {
- WorldPacket msg(SMSG_NEW_TAXI_PATH, 0);
- SendPacket(&msg);
- }
+ SendPacket(WorldPackets::Taxi::NewTaxiPath().Write());
}
-void WorldSession::HandleActivateTaxiExpressOpcode (WorldPacket& recvData)
+void WorldSession::HandleActivateTaxiOpcode(WorldPackets::Taxi::ActivateTaxi& activateTaxi)
{
- ObjectGuid guid;
- uint32 node_count;
-
- recvData >> guid >> node_count;
-
- Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
- if (!npc)
- {
- TC_LOG_DEBUG("network", "WORLD: HandleActivateTaxiExpressOpcode - %s not found or you can't interact with it.", guid.ToString().c_str());
- return;
- }
- std::vector<uint32> nodes;
-
- for (uint32 i = 0; i < node_count; ++i)
- {
- uint32 node;
- recvData >> node;
-
- if (!GetPlayer()->m_taxi.IsTaximaskNodeKnown(node) && !GetPlayer()->isTaxiCheater())
- {
- SendActivateTaxiReply(ERR_TAXINOTVISITED);
- recvData.rfinish();
- return;
- }
-
- nodes.push_back(node);
- }
-
- if (nodes.empty())
- return;
-
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_ACTIVATETAXIEXPRESS from %d to %d", nodes.front(), nodes.back());
-
- GetPlayer()->ActivateTaxiPathTo(nodes, npc);
-}
-
-void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
-{
- recvData.read_skip<uint32>(); // spline id
-
- MovementInfo movementInfo; // used only for proper packet read
- _player->ValidateMovementInfo(&movementInfo);
-
- // in taxi flight packet received in 2 case:
- // 1) end taxi path in far (multi-node) flight
- // 2) switch from one map to other in case multim-map taxi path
- // we need process only (1)
-
- uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination();
- if (curDest)
+ Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(activateTaxi.Vendor, UNIT_NPC_FLAG_FLIGHTMASTER);
+ if (!unit)
{
- TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
-
- // far teleport case
- if (curDestNode && curDestNode->MapID != GetPlayer()->GetMapId())
- {
- if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
- {
- // short preparations to continue flight
- FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top());
-
- flight->SetCurrentNodeAfterTeleport();
- TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()];
- flight->SkipCurrentNode();
-
- GetPlayer()->TeleportTo(curDestNode->MapID, node->Loc.X, node->Loc.Y, node->Loc.Z, GetPlayer()->GetOrientation());
- }
- }
-
+ TC_LOG_DEBUG("network", "WORLD: HandleActivateTaxiOpcode - %s not found or you can't interact with it.", activateTaxi.Vendor.ToString().c_str());
return;
}
- // at this point only 1 node is expected (final destination)
- if (GetPlayer()->m_taxi.GetPath().size() != 1)
+ uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
+ if (!curloc)
return;
- GetPlayer()->CleanupAfterTaxiFlight();
- GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ());
- if (GetPlayer()->pvpInfo.IsHostile)
- GetPlayer()->CastSpell(GetPlayer(), 2479, true);
-}
-
-void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recvData)
-{
- ObjectGuid guid;
- std::vector<uint32> nodes;
- nodes.resize(2);
-
- recvData >> guid >> nodes[0] >> nodes[1];
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_ACTIVATETAXI from %d to %d", nodes[0], nodes[1]);
- Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_FLIGHTMASTER);
- if (!npc)
- {
- TC_LOG_DEBUG("network", "WORLD: HandleActivateTaxiOpcode - %s not found or you can't interact with it.", guid.ToString().c_str());
+ TaxiNodesEntry const* from = sTaxiNodesStore.LookupEntry(curloc);
+ TaxiNodesEntry const* to = sTaxiNodesStore.LookupEntry(activateTaxi.Node);
+ if (!to)
return;
- }
if (!GetPlayer()->isTaxiCheater())
{
- if (!GetPlayer()->m_taxi.IsTaximaskNodeKnown(nodes[0]) || !GetPlayer()->m_taxi.IsTaximaskNodeKnown(nodes[1]))
+ if (!GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) || !GetPlayer()->m_taxi.IsTaximaskNodeKnown(activateTaxi.Node))
{
SendActivateTaxiReply(ERR_TAXINOTVISITED);
return;
}
}
- GetPlayer()->ActivateTaxiPathTo(nodes, npc);
+ std::vector<uint32> nodes;
+ sTaxiPathGraph.GetCompleteNodeRoute(from, to, GetPlayer(), nodes);
+ GetPlayer()->ActivateTaxiPathTo(nodes, unit);
}
void WorldSession::SendActivateTaxiReply(ActivateTaxiReply reply)
{
- WorldPacket data(SMSG_ACTIVATE_TAXI_REPLY, 4);
- data << uint32(reply);
- SendPacket(&data);
-
+ WorldPackets::Taxi::ActivateTaxiReply data;
+ data.Reply = reply;
+ SendPacket(data.Write());
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_ACTIVATETAXIREPLY");
}
+
+void WorldSession::HandleTaxiRequestEarlyLanding(WorldPackets::Taxi::TaxiRequestEarlyLanding& /*taxiRequestEarlyLanding*/)
+{
+ GetPlayer()->m_taxi.RequestEarlyLanding();
+}
diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp
index 86c4fb73108..4540aba77c5 100644
--- a/src/server/game/Maps/TransportMgr.cpp
+++ b/src/server/game/Maps/TransportMgr.cpp
@@ -131,7 +131,7 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
if (!mapChange)
{
TaxiPathNodeEntry const* node_i = path[i];
- if (i != path.size() - 1 && (node_i->Flags & 1 || node_i->MapID != path[i + 1]->MapID))
+ if (i != path.size() - 1 && (node_i->Flags & TAXI_PATH_NODE_FLAG_TELEPORT || node_i->MapID != path[i + 1]->MapID))
{
keyFrames.back().Teleport = true;
mapChange = true;
diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h
index 5e032dbd71f..715d82877a0 100644
--- a/src/server/game/Maps/TransportMgr.h
+++ b/src/server/game/Maps/TransportMgr.h
@@ -63,7 +63,7 @@ struct KeyFrame
uint32 NextArriveTime;
bool IsTeleportFrame() const { return Teleport; }
- bool IsStopFrame() const { return Node->Flags == 2; }
+ bool IsStopFrame() const { return (Node->Flags & TAXI_PATH_NODE_FLAG_STOP) != 0; }
};
struct TransportTemplate
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index f13630188a9..fa53e28f749 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -4719,18 +4719,26 @@ enum RemoveMethod
enum ActivateTaxiReply
{
ERR_TAXINOVENDORNEARBY = 0,
- ERR_TAXINOSUCHPATH = 1,
- ERR_TAXIUNSPECIFIEDSERVERERROR = 2,
- ERR_TAXITOOFARAWAY = 3,
- ERR_TAXINOTSTANDING = 4,
- ERR_TAXISAMENODE = 5,
- ERR_TAXINOTENOUGHMONEY = 6,
- ERR_TAXIOK = 7,
- ERR_TAXINOTVISITED = 8,
- ERR_TAXIPLAYERSHAPESHIFTED = 9,
- ERR_TAXIPLAYERBUSY = 11,
- ERR_TAXIPLAYERALREADYMOUNTED = 12,
- ERR_TAXIPLAYERMOVING = 15
+ ERR_TAXIPLAYERMOVING = 1,
+ ERR_TAXIPLAYERALREADYMOUNTED = 2,
+ ERR_TAXIPLAYERBUSY = 3,
+ ERR_TAXINOTENOUGHMONEY = 5,
+ ERR_TAXINOTSTANDING = 6,
+ ERR_TAXIPLAYERSHAPESHIFTED = 8,
+ ERR_TAXIUNSPECIFIEDSERVERERROR = 9,
+ ERR_TAXINOSUCHPATH = 11,
+ ERR_TAXIOK = 12,
+ ERR_TAXISAMENODE = 13,
+ ERR_TAXITOOFARAWAY = 14,
+ ERR_TAXINOTVISITED = 15
+};
+
+enum TaxiNodeStatus
+{
+ TAXISTATUS_NOT_ELIGIBLE = 0,
+ TAXISTATUS_UNLEARNED = 1,
+ TAXISTATUS_LEARNED = 2,
+ TAXISTATUS_NONE = 3
};
enum ProfessionUI
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index a0858b35c17..bf2148fc0b8 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -329,7 +329,7 @@ void FlightPathMovementGenerator::DoFinalize(Player* player)
player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK);
}
-#define PLAYER_FLIGHT_SPEED 32.0f
+#define PLAYER_FLIGHT_SPEED 30.0f
void FlightPathMovementGenerator::DoReset(Player* player)
{
diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp
index cd6f1334682..5b6b9803b4a 100644
--- a/src/server/game/Server/Packets/MovementPackets.cpp
+++ b/src/server/game/Server/Packets/MovementPackets.cpp
@@ -687,3 +687,9 @@ WorldPacket const* WorldPackets::Movement::ControlUpdate::Write()
return &_worldPacket;
}
+
+void WorldPackets::Movement::MoveSplineDone::Read()
+{
+ _worldPacket >> movementInfo;
+ _worldPacket >> SplineID;
+}
diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h
index 011a74b07e0..66261564989 100644
--- a/src/server/game/Server/Packets/MovementPackets.h
+++ b/src/server/game/Server/Packets/MovementPackets.h
@@ -423,6 +423,17 @@ namespace WorldPackets
ObjectGuid Guid;
bool On = false;
};
+
+ class MoveSplineDone final : public ClientPacket
+ {
+ public:
+ MoveSplineDone(WorldPacket&& packet) : ClientPacket(CMSG_MOVE_SPLINE_DONE, std::move(packet)) { }
+
+ void Read() override;
+
+ MovementInfo movementInfo;
+ int32 SplineID;
+ };
}
ByteBuffer& operator<<(ByteBuffer& data, Movement::MonsterSplineFilterKey const& monsterSplineFilterKey);
diff --git a/src/server/game/Server/Packets/TaxiPackets.cpp b/src/server/game/Server/Packets/TaxiPackets.cpp
new file mode 100644
index 00000000000..1dfa44d68a0
--- /dev/null
+++ b/src/server/game/Server/Packets/TaxiPackets.cpp
@@ -0,0 +1,74 @@
+/*
+* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "TaxiPackets.h"
+
+void WorldPackets::Taxi::TaxiNodeStatusQuery::Read()
+{
+ _worldPacket >> UnitGUID;
+}
+
+WorldPacket const* WorldPackets::Taxi::TaxiNodeStatus::Write()
+{
+ _worldPacket << Unit;
+ _worldPacket.WriteBits(Status, 2);
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Taxi::ShowTaxiNodes::Write()
+{
+ _worldPacket.WriteBit(WindowInfo.is_initialized());
+ _worldPacket.FlushBits();
+
+ _worldPacket << uint32(Nodes->size());
+
+ if (WindowInfo.is_initialized())
+ {
+ _worldPacket << WindowInfo->UnitGUID;
+ _worldPacket << uint32(WindowInfo->CurrentNode);
+ }
+
+ _worldPacket.append(Nodes->data(), Nodes->size());
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Taxi::EnableTaxiNode::Read()
+{
+ _worldPacket >> Unit;
+}
+
+void WorldPackets::Taxi::TaxiQueryAvailableNodes::Read()
+{
+ _worldPacket >> Unit;
+}
+
+void WorldPackets::Taxi::ActivateTaxi::Read()
+{
+ _worldPacket >> Vendor;
+ _worldPacket >> Node;
+}
+
+WorldPacket const* WorldPackets::Taxi::ActivateTaxiReply::Write()
+{
+ _worldPacket.WriteBits(Reply, 4);
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/TaxiPackets.h b/src/server/game/Server/Packets/TaxiPackets.h
new file mode 100644
index 00000000000..0c916548bac
--- /dev/null
+++ b/src/server/game/Server/Packets/TaxiPackets.h
@@ -0,0 +1,126 @@
+/*
+* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef TaxiPackets_h__
+#define TaxiPackets_h__
+
+#include "Packet.h"
+#include "ObjectGuid.h"
+#include "DB2Structure.h"
+
+namespace WorldPackets
+{
+ namespace Taxi
+ {
+ class TaxiNodeStatusQuery final : public ClientPacket
+ {
+ public:
+ TaxiNodeStatusQuery(WorldPacket&& packet) : ClientPacket(CMSG_TAXI_NODE_STATUS_QUERY, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid UnitGUID;
+ };
+
+ class TaxiNodeStatus final : public ServerPacket
+ {
+ public:
+ TaxiNodeStatus() : ServerPacket(SMSG_TAXI_NODE_STATUS, 16 + 1) { }
+
+ WorldPacket const* Write() override;
+
+ uint8 Status = 0; // replace with TaxiStatus enum
+ ObjectGuid Unit;
+ };
+
+ struct ShowTaxiNodesWindowInfo
+ {
+ ObjectGuid UnitGUID;
+ int32 CurrentNode = 0;
+ };
+
+ class ShowTaxiNodes final : public ServerPacket
+ {
+ public:
+ ShowTaxiNodes() : ServerPacket(SMSG_SHOW_TAXI_NODES) { }
+
+ WorldPacket const* Write() override;
+
+ Optional<ShowTaxiNodesWindowInfo> WindowInfo;
+ TaxiMask const* Nodes = nullptr;
+ };
+
+ class EnableTaxiNode final : public ClientPacket
+ {
+ public:
+ EnableTaxiNode(WorldPacket&& packet) : ClientPacket(CMSG_ENABLE_TAXI_NODE, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid Unit;
+ };
+
+ class TaxiQueryAvailableNodes final : public ClientPacket
+ {
+ public:
+ TaxiQueryAvailableNodes(WorldPacket&& packet) : ClientPacket(CMSG_TAXI_QUERY_AVAILABLE_NODES, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid Unit;
+ };
+
+ class ActivateTaxi final : public ClientPacket
+ {
+ public:
+ ActivateTaxi(WorldPacket&& packet) : ClientPacket(CMSG_ACTIVATE_TAXI, std::move(packet)) { }
+
+ void Read() override;
+
+ ObjectGuid Vendor;
+ uint32 Node;
+ };
+
+ class NewTaxiPath final : public ServerPacket
+ {
+ public:
+ NewTaxiPath() : ServerPacket(SMSG_NEW_TAXI_PATH, 0) { }
+
+ WorldPacket const* Write() override { return &_worldPacket; }
+ };
+
+ class ActivateTaxiReply final : public ServerPacket
+ {
+ public:
+ ActivateTaxiReply() : ServerPacket(SMSG_ACTIVATE_TAXI_REPLY, 4) { }
+
+ WorldPacket const* Write() override;
+
+ uint8 Reply;
+ };
+
+ class TaxiRequestEarlyLanding final : public ClientPacket
+ {
+ public:
+ TaxiRequestEarlyLanding(WorldPacket&& packet) : ClientPacket(CMSG_TAXI_REQUEST_EARLY_LANDING, std::move(packet)) { }
+
+ void Read() override { }
+ };
+ }
+}
+
+#endif // TaxiPackets_h__
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index f5f7e3c4abf..fbbfb8cef53 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -52,6 +52,7 @@
#include "Packets/ScenePackets.h"
#include "Packets/SocialPackets.h"
#include "Packets/TalentPackets.h"
+#include "Packets/TaxiPackets.h"
#include "Packets/TicketPackets.h"
#include "Packets/TokenPackets.h"
#include "Packets/TotemPackets.h"
@@ -161,7 +162,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_ACCEPT_LEVEL_GRANT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::RaF::AcceptLevelGrant, &WorldSession::HandleAcceptGrantLevel);
DEFINE_HANDLER(CMSG_ACCEPT_TRADE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Trade::AcceptTrade, &WorldSession::HandleAcceptTradeOpcode);
DEFINE_HANDLER(CMSG_ACCEPT_WARGAME_INVITE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_ACTIVATE_TAXI, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleActivateTaxiOpcode );
+ DEFINE_HANDLER(CMSG_ACTIVATE_TAXI, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Taxi::ActivateTaxi, &WorldSession::HandleActivateTaxiOpcode);
DEFINE_HANDLER(CMSG_ADD_BATTLENET_FRIEND, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_ADD_FRIEND, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Social::AddFriend, &WorldSession::HandleAddFriendOpcode);
DEFINE_HANDLER(CMSG_ADD_IGNORE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Social::AddIgnore, &WorldSession::HandleAddIgnoreOpcode);
@@ -367,7 +368,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_EJECT_PASSENGER, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Vehicle::EjectPassenger, &WorldSession::HandleEjectPassenger);
DEFINE_HANDLER(CMSG_EMOTE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Chat::EmoteClient, &WorldSession::HandleEmoteOpcode);
DEFINE_HANDLER(CMSG_ENABLE_NAGLE, STATUS_NEVER, PROCESS_INPLACE, WorldPacket, &WorldSession::Handle_EarlyProccess);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_ENABLE_TAXI_NODE, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes );
+ DEFINE_HANDLER(CMSG_ENABLE_TAXI_NODE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Taxi::EnableTaxiNode, &WorldSession::HandleEnableTaxiNodeOpcode);
DEFINE_HANDLER(CMSG_ENGINE_SURVEY, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_ENUM_CHARACTERS, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::EnumCharacters, &WorldSession::HandleCharEnumOpcode);
DEFINE_HANDLER(CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::EnumCharacters, &WorldSession::HandleCharUndeleteEnumOpcode);
@@ -555,7 +556,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_MOVE_SET_RUN_MODE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Movement::ClientPlayerMovement, &WorldSession::HandleMovementOpcodes);
DEFINE_HANDLER(CMSG_MOVE_SET_VEHICLE_REC_ID_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Vehicle::MoveSetVehicleRecIdAck, &WorldSession::HandleMoveSetVehicleRecAck);
DEFINE_HANDLER(CMSG_MOVE_SET_WALK_MODE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Movement::ClientPlayerMovement, &WorldSession::HandleMovementOpcodes);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_SPLINE_DONE, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveSplineDoneOpcode );
+ DEFINE_HANDLER(CMSG_MOVE_SPLINE_DONE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Movement::MoveSplineDone, &WorldSession::HandleMoveSplineDoneOpcode);
DEFINE_HANDLER(CMSG_MOVE_START_ASCEND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Movement::ClientPlayerMovement, &WorldSession::HandleMovementOpcodes);
DEFINE_HANDLER(CMSG_MOVE_START_BACKWARD, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Movement::ClientPlayerMovement, &WorldSession::HandleMovementOpcodes);
DEFINE_HANDLER(CMSG_MOVE_START_DESCEND, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Movement::ClientPlayerMovement, &WorldSession::HandleMovementOpcodes);
@@ -777,9 +778,9 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_SWAP_VOID_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::VoidStorage::SwapVoidItem, &WorldSession::HandleVoidSwapItem);
DEFINE_HANDLER(CMSG_TABARD_VENDOR_ACTIVATE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleTabardVendorActivateOpcode);
DEFINE_HANDLER(CMSG_TALK_TO_GOSSIP, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::NPC::Hello, &WorldSession::HandleGossipHelloOpcode);
- DEFINE_OPCODE_HANDLER_OLD(CMSG_TAXI_NODE_STATUS_QUERY, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleTaxiNodeStatusQueryOpcode );
- DEFINE_OPCODE_HANDLER_OLD(CMSG_TAXI_QUERY_AVAILABLE_NODES, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleTaxiQueryAvailableNodes );
- DEFINE_HANDLER(CMSG_TAXI_REQUEST_EARLY_LANDING, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_TAXI_NODE_STATUS_QUERY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Taxi::TaxiNodeStatusQuery, &WorldSession::HandleTaxiNodeStatusQueryOpcode);
+ DEFINE_HANDLER(CMSG_TAXI_QUERY_AVAILABLE_NODES, STATUS_LOGGEDIN, PROCESS_THREADSAFE, WorldPackets::Taxi::TaxiQueryAvailableNodes, &WorldSession::HandleTaxiQueryAvailableNodesOpcode);
+ DEFINE_HANDLER(CMSG_TAXI_REQUEST_EARLY_LANDING, STATUS_UNHANDLED, PROCESS_THREADSAFE, WorldPackets::Taxi::TaxiRequestEarlyLanding, &WorldSession::HandleTaxiRequestEarlyLanding);
DEFINE_HANDLER(CMSG_TELEPORT_TO_UNIT, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_TIME_ADJUSTMENT_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, WorldPackets::Null, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_TIME_SYNC_RESPONSE, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Misc::TimeSyncResponse, &WorldSession::HandleTimeSyncResponse);
@@ -845,7 +846,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_TOYS_UPDATE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACHIEVEMENT_DELETED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACHIEVEMENT_EARNED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACTIVATE_TAXI_REPLY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACTIVATE_TAXI_REPLY, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADDON_INFO, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADD_BATTLENET_FRIEND_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ADD_ITEM_PASSIVE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1415,7 +1416,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_WALK_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_MULTIPLE_PACKETS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEUTRAL_PLAYER_FACTION_SELECT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_TAXI_PATH, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_TAXI_PATH, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_WORLD, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_DEST_LOC_SPELL_CAST, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_NOTIFY_MISSILE_TRAJECTORY_COLLISION, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1631,7 +1632,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_BANK, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_MAILBOX, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_NEUTRAL_PLAYER_FACTION_SELECT_UI, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_TAXI_NODES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_TAXI_NODES, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SHOW_TRADE_SKILL_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SOCKET_GEMS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SOR_START_EXPERIENCE_INCOMPLETE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
@@ -1677,7 +1678,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_COMMS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INVOLUNTARILY_RESET, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_TAXI_NODE_STATUS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_TAXI_NODE_STATUS, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_TEXT_EMOTE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_THREAT_CLEAR, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_THREAT_REMOVE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index b70d4da5596..79e50046d9a 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -400,6 +400,7 @@ namespace WorldPackets
class MoveSetCollisionHeightAck;
class MoveTimeSkipped;
class SummonResponse;
+ class MoveSplineDone;
}
namespace NPC
@@ -557,6 +558,16 @@ namespace WorldPackets
class LearnTalents;
}
+ namespace Taxi
+ {
+ class ShowTaxiNodes;
+ class TaxiNodeStatusQuery;
+ class EnableTaxiNode;
+ class TaxiQueryAvailableNodes;
+ class ActivateTaxi;
+ class TaxiRequestEarlyLanding;
+ }
+
namespace Ticket
{
class GMTicketGetSystemStatus;
@@ -1228,12 +1239,13 @@ class WorldSession
void HandleGuildFinderRemoveRecruit(WorldPacket& recvPacket);
void HandleGuildFinderSetGuildPost(WorldPacket& recvPacket);
- void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket);
- void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket);
- void HandleActivateTaxiOpcode(WorldPacket& recvPacket);
- void HandleActivateTaxiExpressOpcode(WorldPacket& recvPacket);
- void HandleMoveSplineDoneOpcode(WorldPacket& recvPacket);
+ void HandleEnableTaxiNodeOpcode(WorldPackets::Taxi::EnableTaxiNode& enableTaxiNode);
+ void HandleTaxiNodeStatusQueryOpcode(WorldPackets::Taxi::TaxiNodeStatusQuery& taxiNodeStatusQuery);
+ void HandleTaxiQueryAvailableNodesOpcode(WorldPackets::Taxi::TaxiQueryAvailableNodes& taxiQueryAvailableNodes);
+ void HandleActivateTaxiOpcode(WorldPackets::Taxi::ActivateTaxi& activateTaxi);
+ void HandleMoveSplineDoneOpcode(WorldPackets::Movement::MoveSplineDone& moveSplineDone);
void SendActivateTaxiReply(ActivateTaxiReply reply);
+ void HandleTaxiRequestEarlyLanding(WorldPackets::Taxi::TaxiRequestEarlyLanding& taxiRequestEarlyLanding);
void HandleTabardVendorActivateOpcode(WorldPackets::NPC::Hello& packet);
void HandleBankerActivateOpcode(WorldPackets::NPC::Hello& packet);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index d6cceac46fb..3acc8fb47f9 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -60,6 +60,7 @@
#include "SkillExtraItems.h"
#include "SmartAI.h"
#include "SupportMgr.h"
+#include "TaxiPathGraph.h"
#include "TransportMgr.h"
#include "Unit.h"
#include "VMapFactory.h"
@@ -1470,6 +1471,9 @@ void World::SetInitialWorldSettings()
///- Load GameTables
LoadGameTables(m_dataPath, m_defaultDbcLocale);
+ //Load weighted graph on taxi nodes path
+ sTaxiPathGraph.Initialize();
+
sSpellMgr->LoadPetFamilySpellsStore();
std::unordered_map<uint32, std::vector<uint32>> mapData;