TrinityCore
TaxiHandler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WorldSession.h"
19#include "Common.h"
20#include "ConditionMgr.h"
21#include "Containers.h"
22#include "Creature.h"
23#include "DatabaseEnv.h"
24#include "DB2Stores.h"
26#include "Log.h"
27#include "MotionMaster.h"
28#include "ObjectAccessor.h"
29#include "ObjectMgr.h"
30#include "Player.h"
31#include "TaxiPackets.h"
32#include "TaxiPathGraph.h"
33
35{
36 if (Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(enableTaxiNode.Unit, UNIT_NPC_FLAG_FLIGHTMASTER, UNIT_NPC_FLAG_2_NONE))
38}
39
41{
42 SendTaxiStatus(taxiNodeStatusQuery.UnitGUID);
43}
44
46{
47 Player* const player = GetPlayer();
48 Creature* unit = ObjectAccessor::GetCreature(*player, guid);
49 if (!unit || unit->IsHostileTo(player) || !unit->HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER))
50 {
51 TC_LOG_DEBUG("network", "WorldSession::SendTaxiStatus - {} not found or you can't interact with him.", guid.ToString());
52 return;
53 }
54
55 // find taxi node
56 uint32 nearest = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), player->GetTeam());
57
59 data.Unit = guid;
60
61 if (!nearest)
63 else if (unit->GetReactionTo(GetPlayer()) >= REP_NEUTRAL)
65 else
67
68 SendPacket(data.Write());
69}
70
72{
73 // cheating checks
75 if (!unit)
76 {
77 TC_LOG_DEBUG("network", "WORLD: HandleTaxiQueryAvailableNodes - {} not found or you can't interact with him.", taxiQueryAvailableNodes.Unit.ToString());
78 return;
79 }
80 // remove fake death
81 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
83
84 // unknown taxi node case
85 if (SendLearnNewTaxiNode(unit))
86 return;
87
88 // known taxi node case
89 SendTaxiMenu(unit);
90}
91
93{
94 // find current node
95 uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
96 if (!curloc)
97 return;
98
99 bool lastTaxiCheaterState = GetPlayer()->isTaxiCheater();
100 if (unit->GetEntry() == 29480)
101 GetPlayer()->SetTaxiCheater(true); // Grimwing in Ebon Hold, special case. NOTE: Not perfect, Zul'Aman should not be included according to WoWhead, and I think taxicheat includes it.
102
103 TC_LOG_DEBUG("network", "WORLD: CMSG_TAXINODE_STATUS_QUERY {} ", curloc);
104
106 data.WindowInfo.emplace();
107 data.WindowInfo->UnitGUID = unit->GetGUID();
108 data.WindowInfo->CurrentNode = curloc;
109
110 GetPlayer()->m_taxi.AppendTaximaskTo(data, lastTaxiCheaterState);
111
112 TaxiMask reachableNodes;
113 TaxiPathGraph::GetReachableNodesMask(sTaxiNodesStore.LookupEntry(curloc), &reachableNodes);
114
115 for (std::size_t i = 0; i < reachableNodes.size(); ++i)
116 {
117 data.CanLandNodes[i] &= reachableNodes[i];
118 data.CanUseNodes[i] &= reachableNodes[i];
119 }
120
121 SendPacket(data.Write());
122
123 GetPlayer()->SetTaxiCheater(lastTaxiCheaterState);
124}
125
126void WorldSession::SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode)
127{
128 // remove fake death
129 if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
131
132 if (mountDisplayId)
133 GetPlayer()->Mount(mountDisplayId);
134
135 GetPlayer()->GetMotionMaster()->MoveTaxiFlight(path, pathNode);
136}
137
139{
140 // find current node
141 uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
142
143 if (curloc == 0)
144 return true; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result.
145
146 if (GetPlayer()->m_taxi.SetTaximaskNode(curloc))
147 {
149
151 data.Unit = unit->GetGUID();
153 SendPacket(data.Write());
154
155 return true;
156 }
157 else
158 return false;
159}
160
162{
163 if (GetPlayer()->m_taxi.SetTaximaskNode(nodeid))
165}
166
168{
170 if (!unit)
171 {
172 TC_LOG_DEBUG("network", "WORLD: HandleActivateTaxiOpcode - {} not found or you can't interact with it.", activateTaxi.Vendor.ToString());
174 return;
175 }
176
177 uint32 curloc = sObjectMgr->GetNearestTaxiNode(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ(), unit->GetMapId(), GetPlayer()->GetTeam());
178 if (!curloc)
179 return;
180
181 TaxiNodesEntry const* from = sTaxiNodesStore.LookupEntry(curloc);
182 TaxiNodesEntry const* to = sTaxiNodesStore.LookupEntry(activateTaxi.Node);
183 if (!to)
184 return;
185
186 if (!GetPlayer()->isTaxiCheater())
187 {
188 if (!GetPlayer()->m_taxi.IsTaximaskNodeKnown(curloc) || !GetPlayer()->m_taxi.IsTaximaskNodeKnown(activateTaxi.Node))
189 {
191 return;
192 }
193 }
194
195 uint32 preferredMountDisplay = 0;
196 if (MountEntry const* mount = sMountStore.LookupEntry(activateTaxi.FlyingMountID))
197 {
198 if (GetPlayer()->HasSpell(mount->SourceSpellID))
199 {
200 if (DB2Manager::MountXDisplayContainer const* mountDisplays = sDB2Manager.GetMountDisplays(mount->ID))
201 {
203 std::copy_if(mountDisplays->begin(), mountDisplays->end(), std::back_inserter(usableDisplays), [this](MountXDisplayEntry const* mountDisplay)
204 {
205 if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(mountDisplay->PlayerConditionID))
206 return sConditionMgr->IsPlayerMeetingCondition(GetPlayer(), playerCondition);
207
208 return true;
209 });
210
211 if (!usableDisplays.empty())
212 preferredMountDisplay = Trinity::Containers::SelectRandomContainerElement(usableDisplays)->CreatureDisplayInfoID;
213 }
214 }
215 }
216
217 std::vector<uint32> nodes;
219 GetPlayer()->ActivateTaxiPathTo(nodes, unit, 0, preferredMountDisplay);
220}
221
223{
225 data.Reply = reply;
226 SendPacket(data.Write());
227}
228
230{
231 if (FlightPathMovementGenerator* flight = dynamic_cast<FlightPathMovementGenerator*>(GetPlayer()->GetMotionMaster()->GetCurrentMovementGenerator()))
232 {
233 if (GetPlayer()->m_taxi.RequestEarlyLanding())
234 {
235 flight->LoadPath(GetPlayer(), flight->GetPath()[flight->GetCurrentNode()]->NodeIndex);
236 flight->Reset(GetPlayer());
237 }
238 }
239}
DB2Storage< TaxiNodesEntry > sTaxiNodesStore("TaxiNodes.db2", &TaxiNodesLoadInfo::Instance)
DB2Storage< MountEntry > sMountStore("Mount.db2", &MountLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:538
uint32_t uint32
Definition: Define.h:142
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define sObjectMgr
Definition: ObjectMgr.h:1946
@ ERR_TAXITOOFARAWAY
@ ERR_TAXINOTVISITED
@ REP_NEUTRAL
@ TAXISTATUS_LEARNED
@ TAXISTATUS_UNLEARNED
@ TAXISTATUS_NONE
@ TAXISTATUS_NOT_ELIGIBLE
ActivateTaxiReply
@ SPELL_AURA_FEIGN_DEATH
@ UNIT_NPC_FLAG_FLIGHTMASTER
Definition: UnitDefines.h:310
@ UNIT_NPC_FLAG_2_NONE
Definition: UnitDefines.h:336
@ UNIT_STATE_DIED
Definition: Unit.h:255
std::vector< MountXDisplayEntry const * > MountXDisplayContainer
Definition: DB2Stores.h:409
void MoveTaxiFlight(uint32 path, uint32 pathnode)
std::string ToString() const
Definition: ObjectGuid.cpp:554
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
void AppendTaximaskTo(WorldPackets::Taxi::ShowTaxiNodes &data, bool all)
Definition: PlayerTaxi.cpp:122
bool IsTaximaskNodeKnown(uint32 nodeidx) const
Definition: PlayerTaxi.h:45
Creature * GetNPCIfCanInteractWith(ObjectGuid const &guid, NPCFlags npcFlags, NPCFlags2 npcFlags2) const
Definition: Player.cpp:1947
bool ActivateTaxiPathTo(std::vector< uint32 > const &nodes, Creature *npc=nullptr, uint32 spellid=0, uint32 preferredMountDisplay=0)
Definition: Player.cpp:22506
PlayerTaxi m_taxi
Definition: Player.h:1166
void SetTaxiCheater(bool on)
Definition: Player.h:1185
bool isTaxiCheater() const
Definition: Player.h:1184
Team GetTeam() const
Definition: Player.h:2235
size_t size() const
Definition: DBCEnums.h:2035
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3812
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
void Mount(uint32 mount, uint32 vehicleId=0, uint32 creatureEntry=0)
Definition: Unit.cpp:7887
bool HasNpcFlag(NPCFlags flags) const
Definition: Unit.h:981
constexpr uint32 GetMapId() const
Definition: Position.h:201
bool IsHostileTo(WorldObject const *target) const
Definition: Object.cpp:2860
ReputationRank GetReactionTo(WorldObject const *target) const
Definition: Object.cpp:2707
WorldPacket const * Write() override
Definition: TaxiPackets.cpp:72
Optional< ShowTaxiNodesWindowInfo > WindowInfo
Definition: TaxiPackets.h:64
WorldPacket const * Write() override
Definition: TaxiPackets.cpp:34
WorldPacket const * Write() override
Definition: TaxiPackets.cpp:25
void HandleActivateTaxiOpcode(WorldPackets::Taxi::ActivateTaxi &activateTaxi)
void HandleTaxiQueryAvailableNodesOpcode(WorldPackets::Taxi::TaxiQueryAvailableNodes &taxiQueryAvailableNodes)
Definition: TaxiHandler.cpp:71
void HandleTaxiRequestEarlyLanding(WorldPackets::Taxi::TaxiRequestEarlyLanding &taxiRequestEarlyLanding)
bool SendLearnNewTaxiNode(Creature *unit)
void SendTaxiMenu(Creature *unit)
Definition: TaxiHandler.cpp:92
void HandleTaxiNodeStatusQueryOpcode(WorldPackets::Taxi::TaxiNodeStatusQuery &taxiNodeStatusQuery)
Definition: TaxiHandler.cpp:40
void SendTaxiStatus(ObjectGuid guid)
Definition: TaxiHandler.cpp:45
void HandleEnableTaxiNodeOpcode(WorldPackets::Taxi::EnableTaxiNode &enableTaxiNode)
Definition: TaxiHandler.cpp:34
Player * GetPlayer() const
void SendActivateTaxiReply(ActivateTaxiReply reply)
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
void SendDiscoverNewTaxiNode(uint32 nodeid)
void SendDoFlight(uint32 mountDisplayId, uint32 path, uint32 pathNode=0)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
void GetReachableNodesMask(TaxiNodesEntry const *from, TaxiMask *mask)
std::size_t GetCompleteNodeRoute(TaxiNodesEntry const *from, TaxiNodesEntry const *to, Player const *player, std::vector< uint32 > &shortestPath)
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:109
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
constexpr float GetPositionZ() const
Definition: Position.h:78