2010-10-07 15:35:36 +02:00
/*
2020-01-02 06:44:10 +01:00
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
2010-10-07 15:35:36 +02:00
*
* 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/>.
2008-10-02 16:23:55 -05:00
*/
2009-10-17 15:51:44 -07:00
2017-06-04 01:00:45 +02:00
#include "WorldSession.h"
2008-10-02 16:23:55 -05:00
#include "Common.h"
2017-04-06 23:39:34 +02:00
#include "ConditionMgr.h"
#include "Containers.h"
2017-08-12 01:40:25 +02:00
#include "Creature.h"
2010-06-08 17:01:03 -06:00
#include "DatabaseEnv.h"
2017-04-06 23:39:34 +02:00
#include "DB2Stores.h"
2017-12-11 22:15:52 +01:00
#include "FlightPathMovementGenerator.h"
2008-10-02 16:23:55 -05:00
#include "Log.h"
2017-08-12 01:40:25 +02:00
#include "MotionMaster.h"
2017-06-04 01:00:45 +02:00
#include "ObjectAccessor.h"
2008-10-02 16:23:55 -05:00
#include "ObjectMgr.h"
#include "Player.h"
2015-08-30 19:26:33 +02:00
#include "TaxiPackets.h"
#include "TaxiPathGraph.h"
2009-10-17 15:51:44 -07:00
2015-09-19 17:39:01 +02:00
void WorldSession :: HandleEnableTaxiNodeOpcode ( WorldPackets :: Taxi :: EnableTaxiNode & enableTaxiNode )
2008-10-02 16:23:55 -05:00
{
2019-06-03 20:40:34 +02:00
if ( Creature * unit = GetPlayer () -> GetNPCIfCanInteractWith ( enableTaxiNode . Unit , UNIT_NPC_FLAG_FLIGHTMASTER , UNIT_NPC_FLAG_2_NONE ))
2017-06-04 01:00:45 +02:00
SendLearnNewTaxiNode ( unit );
2015-08-30 19:26:33 +02:00
}
2015-09-19 17:39:01 +02:00
void WorldSession :: HandleTaxiNodeStatusQueryOpcode ( WorldPackets :: Taxi :: TaxiNodeStatusQuery & taxiNodeStatusQuery )
2015-08-30 19:26:33 +02:00
{
2015-09-19 17:39:01 +02:00
SendTaxiStatus ( taxiNodeStatusQuery . UnitGUID );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2014-09-14 16:14:12 +02:00
void WorldSession :: SendTaxiStatus ( ObjectGuid guid )
2008-10-02 16:23:55 -05:00
{
2017-07-18 15:55:31 +02:00
Player * const player = GetPlayer ();
Creature * unit = ObjectAccessor :: GetCreature ( * player , guid );
if ( ! unit || unit -> IsHostileTo ( player ) || ! unit -> HasNpcFlag ( UNIT_NPC_FLAG_FLIGHTMASTER ))
2008-10-02 16:23:55 -05:00
{
2020-09-04 13:38:24 +02:00
TC_LOG_DEBUG ( "network" , "WorldSession::SendTaxiStatus - %s not found or you can't interact with him." , guid . ToString (). c_str ());
2008-10-02 16:23:55 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2017-07-18 15:55:31 +02:00
// find taxi node
uint32 nearest = sObjectMgr -> GetNearestTaxiNode ( unit -> GetPositionX (), unit -> GetPositionY (), unit -> GetPositionZ (), unit -> GetMapId (), player -> GetTeam ());
2009-10-17 15:51:44 -07:00
2015-08-30 19:26:33 +02:00
WorldPackets :: Taxi :: TaxiNodeStatus data ;
data . Unit = guid ;
2009-10-17 15:51:44 -07:00
2017-07-18 15:55:31 +02:00
if ( ! nearest )
2015-08-30 19:26:33 +02:00
data . Status = TAXISTATUS_NONE ;
else if ( unit -> GetReactionTo ( GetPlayer ()) >= REP_NEUTRAL )
2017-07-18 15:55:31 +02:00
data . Status = GetPlayer () -> m_taxi . IsTaximaskNodeKnown ( nearest ) ? TAXISTATUS_LEARNED : TAXISTATUS_UNLEARNED ;
2015-08-30 19:26:33 +02:00
else
data . Status = TAXISTATUS_NOT_ELIGIBLE ;
2015-09-19 16:44:33 +02:00
2015-08-30 19:26:33 +02:00
SendPacket ( data . Write ());
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2015-09-19 17:39:01 +02:00
void WorldSession :: HandleTaxiQueryAvailableNodesOpcode ( WorldPackets :: Taxi :: TaxiQueryAvailableNodes & taxiQueryAvailableNodes )
2008-10-02 16:23:55 -05:00
{
// cheating checks
2019-06-03 20:40:34 +02:00
Creature * unit = GetPlayer () -> GetNPCIfCanInteractWith ( taxiQueryAvailableNodes . Unit , UNIT_NPC_FLAG_FLIGHTMASTER , UNIT_NPC_FLAG_2_NONE );
2008-10-02 16:23:55 -05:00
if ( ! unit )
{
2015-09-19 17:39:01 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleTaxiQueryAvailableNodes - %s not found or you can't interact with him." , taxiQueryAvailableNodes . Unit . ToString (). c_str ());
2008-10-02 16:23:55 -05:00
return ;
}
// remove fake death
2012-02-03 19:02:17 +02:00
if ( GetPlayer () -> HasUnitState ( UNIT_STATE_DIED ))
2009-04-06 13:31:14 +02:00
GetPlayer () -> RemoveAurasByType ( SPELL_AURA_FEIGN_DEATH );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// unknown taxi node case
2010-04-07 22:59:46 +02:00
if ( SendLearnNewTaxiNode ( unit ))
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// known taxi node case
2010-04-07 22:59:46 +02:00
SendTaxiMenu ( unit );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldSession :: SendTaxiMenu ( Creature * unit )
2008-10-02 16:23:55 -05:00
{
// find current node
2011-04-29 20:47:02 +02:00
uint32 curloc = sObjectMgr -> GetNearestTaxiNode ( unit -> GetPositionX (), unit -> GetPositionY (), unit -> GetPositionZ (), unit -> GetMapId (), GetPlayer () -> GetTeam ());
2012-08-14 15:29:43 +02:00
if ( ! curloc )
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-08-31 01:15:09 -07:00
bool lastTaxiCheaterState = GetPlayer () -> isTaxiCheater ();
2012-08-14 15:29:43 +02:00
if ( unit -> GetEntry () == 29480 )
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.
2009-10-17 15:51:44 -07:00
2013-11-08 10:50:51 +01:00
TC_LOG_DEBUG ( "network" , "WORLD: CMSG_TAXINODE_STATUS_QUERY %u " , curloc );
2009-10-17 15:51:44 -07:00
2015-08-30 19:26:33 +02:00
WorldPackets :: Taxi :: ShowTaxiNodes data ;
data . WindowInfo = boost :: in_place ();
data . WindowInfo -> UnitGUID = unit -> GetGUID ();
data . WindowInfo -> CurrentNode = curloc ;
2015-09-19 16:44:33 +02:00
2015-08-30 19:26:33 +02:00
GetPlayer () -> m_taxi . AppendTaximaskTo ( data , lastTaxiCheaterState );
2015-09-19 16:44:33 +02:00
2018-11-25 14:28:44 +01:00
TaxiMask reachableNodes ;
std :: fill ( reachableNodes . begin (), reachableNodes . end (), 0 );
sTaxiPathGraph . GetReachableNodesMask ( sTaxiNodesStore . LookupEntry ( curloc ), & reachableNodes );
for ( std :: size_t i = 0 ; i < TaxiMaskSize ; ++ i )
{
data . CanLandNodes [ i ] &= reachableNodes [ i ];
data . CanUseNodes [ i ] &= reachableNodes [ i ];
}
2015-08-30 19:26:33 +02:00
SendPacket ( data . Write ());
2009-10-17 15:51:44 -07:00
2009-08-31 01:15:09 -07:00
GetPlayer () -> SetTaxiCheater ( lastTaxiCheaterState );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldSession :: SendDoFlight ( uint32 mountDisplayId , uint32 path , uint32 pathNode )
2008-10-02 16:23:55 -05:00
{
// remove fake death
2012-02-03 19:02:17 +02:00
if ( GetPlayer () -> HasUnitState ( UNIT_STATE_DIED ))
2009-04-06 13:31:14 +02:00
GetPlayer () -> RemoveAurasByType ( SPELL_AURA_FEIGN_DEATH );
2009-10-17 15:51:44 -07:00
2018-06-03 10:06:57 -07:00
GetPlayer () -> GetMotionMaster () -> Remove ( FLIGHT_MOTION_TYPE );
2009-10-17 15:51:44 -07:00
2009-06-15 18:02:12 -05:00
if ( mountDisplayId )
2010-04-07 22:59:46 +02:00
GetPlayer () -> Mount ( mountDisplayId );
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
GetPlayer () -> GetMotionMaster () -> MoveTaxiFlight ( path , pathNode );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
bool WorldSession :: SendLearnNewTaxiNode ( Creature * unit )
2008-10-02 16:23:55 -05:00
{
// find current node
2011-04-29 20:47:02 +02:00
uint32 curloc = sObjectMgr -> GetNearestTaxiNode ( unit -> GetPositionX (), unit -> GetPositionY (), unit -> GetPositionZ (), unit -> GetMapId (), GetPlayer () -> GetTeam ());
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( curloc == 0 )
2008-10-02 16:23:55 -05:00
return true ; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result.
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if ( GetPlayer () -> m_taxi . SetTaximaskNode ( curloc ))
2008-10-02 16:23:55 -05:00
{
2015-08-30 19:26:33 +02:00
SendPacket ( WorldPackets :: Taxi :: NewTaxiPath (). Write ());
2009-10-17 15:51:44 -07:00
2015-08-30 19:26:33 +02:00
WorldPackets :: Taxi :: TaxiNodeStatus data ;
data . Unit = unit -> GetGUID ();
data . Status = TAXISTATUS_LEARNED ;
SendPacket ( data . Write ());
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
return true ;
}
else
return false ;
}
2009-10-17 15:51:44 -07:00
2010-07-20 18:27:18 +02:00
void WorldSession :: SendDiscoverNewTaxiNode ( uint32 nodeid )
{
if ( GetPlayer () -> m_taxi . SetTaximaskNode ( nodeid ))
2015-08-30 19:26:33 +02:00
SendPacket ( WorldPackets :: Taxi :: NewTaxiPath (). Write ());
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2015-09-19 17:39:01 +02:00
void WorldSession :: HandleActivateTaxiOpcode ( WorldPackets :: Taxi :: ActivateTaxi & activateTaxi )
2008-10-02 16:23:55 -05:00
{
2019-06-03 20:40:34 +02:00
Creature * unit = GetPlayer () -> GetNPCIfCanInteractWith ( activateTaxi . Vendor , UNIT_NPC_FLAG_FLIGHTMASTER , UNIT_NPC_FLAG_2_NONE );
2015-08-30 19:26:33 +02:00
if ( ! unit )
2008-10-02 16:23:55 -05:00
{
2015-09-19 17:39:01 +02:00
TC_LOG_DEBUG ( "network" , "WORLD: HandleActivateTaxiOpcode - %s not found or you can't interact with it." , activateTaxi . Vendor . ToString (). c_str ());
2017-01-21 13:16:06 +01:00
SendActivateTaxiReply ( ERR_TAXITOOFARAWAY );
2009-06-24 00:12:09 +02:00
return ;
2008-10-02 16:23:55 -05:00
}
2015-09-13 17:23:37 +02:00
2015-08-30 19:26:33 +02:00
uint32 curloc = sObjectMgr -> GetNearestTaxiNode ( unit -> GetPositionX (), unit -> GetPositionY (), unit -> GetPositionZ (), unit -> GetMapId (), GetPlayer () -> GetTeam ());
if ( ! curloc )
2008-10-02 16:23:55 -05:00
return ;
2015-09-19 16:44:33 +02:00
TaxiNodesEntry const * from = sTaxiNodesStore . LookupEntry ( curloc );
2015-09-19 17:39:01 +02:00
TaxiNodesEntry const * to = sTaxiNodesStore . LookupEntry ( activateTaxi . Node );
2015-09-19 16:44:33 +02:00
if ( ! to )
return ;
2014-01-23 15:29:02 +01:00
if ( ! GetPlayer () -> isTaxiCheater ())
{
2015-09-19 17:39:01 +02:00
if ( ! GetPlayer () -> m_taxi . IsTaximaskNodeKnown ( curloc ) || ! GetPlayer () -> m_taxi . IsTaximaskNodeKnown ( activateTaxi . Node ))
2014-01-23 15:29:02 +01:00
{
SendActivateTaxiReply ( ERR_TAXINOTVISITED );
return ;
}
}
2015-09-19 16:44:33 +02:00
2016-11-12 00:27:07 +01:00
uint32 preferredMountDisplay = 0 ;
if ( MountEntry const * mount = sMountStore . LookupEntry ( activateTaxi . FlyingMountID ))
2017-04-06 23:39:34 +02:00
{
2018-03-12 18:20:26 +01:00
if ( GetPlayer () -> HasSpell ( mount -> SourceSpellID ))
2017-04-06 23:39:34 +02:00
{
if ( DB2Manager :: MountXDisplayContainer const * mountDisplays = sDB2Manager . GetMountDisplays ( mount -> ID ))
{
DB2Manager :: MountXDisplayContainer usableDisplays ;
std :: copy_if ( mountDisplays -> begin (), mountDisplays -> end (), std :: back_inserter ( usableDisplays ), [ this ]( MountXDisplayEntry const * mountDisplay )
{
if ( PlayerConditionEntry const * playerCondition = sPlayerConditionStore . LookupEntry ( mountDisplay -> PlayerConditionID ))
return sConditionMgr -> IsPlayerMeetingCondition ( GetPlayer (), playerCondition );
return true ;
});
if ( ! usableDisplays . empty ())
2018-03-12 18:20:26 +01:00
preferredMountDisplay = Trinity :: Containers :: SelectRandomContainerElement ( usableDisplays ) -> CreatureDisplayInfoID ;
2017-04-06 23:39:34 +02:00
}
}
}
2016-11-12 00:27:07 +01:00
2015-08-30 19:26:33 +02:00
std :: vector < uint32 > nodes ;
2015-09-19 16:44:33 +02:00
sTaxiPathGraph . GetCompleteNodeRoute ( from , to , GetPlayer (), nodes );
2016-11-12 00:27:07 +01:00
GetPlayer () -> ActivateTaxiPathTo ( nodes , unit , 0 , preferredMountDisplay );
2008-10-02 16:23:55 -05:00
}
2012-02-18 23:03:41 +00:00
void WorldSession :: SendActivateTaxiReply ( ActivateTaxiReply reply )
{
2015-08-30 19:26:33 +02:00
WorldPackets :: Taxi :: ActivateTaxiReply data ;
data . Reply = reply ;
SendPacket ( data . Write ());
2012-02-18 23:03:41 +00:00
}
2015-08-30 19:26:33 +02:00
2015-09-19 17:39:01 +02:00
void WorldSession :: HandleTaxiRequestEarlyLanding ( WorldPackets :: Taxi :: TaxiRequestEarlyLanding & /*taxiRequestEarlyLanding*/ )
2015-08-30 19:26:33 +02:00
{
2018-06-03 10:06:57 -07:00
if ( FlightPathMovementGenerator * flight = dynamic_cast < FlightPathMovementGenerator *> ( GetPlayer () -> GetMotionMaster () -> GetCurrentMovementGenerator ()))
2015-09-21 00:01:44 +02:00
{
if ( GetPlayer () -> m_taxi . RequestEarlyLanding ())
{
flight -> LoadPath ( GetPlayer (), flight -> GetPath ()[ flight -> GetCurrentNode ()] -> NodeIndex );
flight -> Reset ( GetPlayer ());
}
}
2015-08-30 19:26:33 +02:00
}