void WorldSession::HandleMoveWorldportAckOpcode() { // ignore unexpected far teleports if(!GetPlayer()->IsBeingTeleportedFar()) return; // get start teleport coordinates (will used later in fail case) WorldLocation old_loc; GetPlayer()->GetPosition(old_loc); // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check (only cheating case possible) if (!MapManager::IsValidMapCoord(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation)) { sLog.outError("WorldSession::HandleMoveWorldportAckOpcode: %s was teleported far to a not valid location " "(map:%u, x:%f, y:%f, z:%f) We port him to his homebind instead..", GetPlayer()->GetGuidStr().c_str(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); // stop teleportation else we would try this again and again in LogoutPlayer... GetPlayer()->SetSemaphoreTeleportFar(false); // and teleport the player to a valid place GetPlayer()->TeleportToHomebind(); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid); Map* map = NULL; // prevent crash at attempt landing to not existed battleground instance if(mEntry->IsBattleGround()) { if (GetPlayer()->GetBattleGroundId()) map = sMapMgr.FindMap(loc.mapid, GetPlayer()->GetBattleGroundId()); if (!map) { DETAIL_LOG("WorldSession::HandleMoveWorldportAckOpcode: %s was teleported far to nonexisten battleground instance " " (map:%u, x:%f, y:%f, z:%f) Trying to port him to his previous place..", GetPlayer()->GetGuidStr().c_str(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); GetPlayer()->SetSemaphoreTeleportFar(false); // Teleport to previous place, if cannot be ported back TP to homebind place if (!GetPlayer()->TeleportTo(old_loc)) { DETAIL_LOG("WorldSession::HandleMoveWorldportAckOpcode: %s cannot be ported to his previous place, teleporting him to his homebind place...", GetPlayer()->GetGuidStr().c_str()); GetPlayer()->TeleportToHomebind(); } return; } } InstanceTemplate const* mInstance = ObjectMgr::GetInstanceTemplate(loc.mapid); // reset instance validity, except if going to an instance inside an instance if (GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; GetPlayer()->SetSemaphoreTeleportFar(false); // relocate the player to the teleport destination if (!map) map = sMapMgr.CreateMap(loc.mapid, GetPlayer()); GetPlayer()->SetMap(map); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if (!GetPlayer()->GetMap()->Add(GetPlayer())) { // if player wasn't added to map, reset his map pointer! GetPlayer()->ResetMap(); DETAIL_LOG("WorldSession::HandleMoveWorldportAckOpcode: %s was teleported far but couldn't be added to map " " (map:%u, x:%f, y:%f, z:%f) Trying to port him to his previous place..", GetPlayer()->GetGuidStr().c_str(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); // Teleport to previous place, if cannot be ported back TP to homebind place if (!GetPlayer()->TeleportTo(old_loc)) { DETAIL_LOG("WorldSession::HandleMoveWorldportAckOpcode: %s cannot be ported to his previous place, teleporting him to his homebind place...", GetPlayer()->GetGuidStr().c_str()); GetPlayer()->TeleportToHomebind(); } return; } // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if(_player->InBattleGround()) { // cleanup seting if outdated if(!mEntry->IsBattleGround()) { // We're not in BG _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // reset destination bg team _player->SetBGTeam(TEAM_NONE); } // join to bg case else if(BattleGround *bg = _player->GetBattleGround()) { if(_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) bg->AddPlayer(_player); } } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { if(!_player->InBattleGround()) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Reset(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->m_taxi.ClearTaxiDestinations(); } if(mEntry->IsRaid() && mInstance) { if (time_t timeReset = sMapPersistentStateMgr.GetScheduler().GetResetTimeFor(mEntry->MapID)) { uint32 timeleft = uint32(timeReset - time(NULL)); GetPlayer()->SendInstanceResetWarning(mEntry->MapID, timeleft); } } // mount allow check if(!mEntry->IsMountAllowed()) _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // honorless target if(GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // resummon pet GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); }
void WorldSession::HandleMoveWorldportAckOpcode() { // ignore unexpected far teleports if(!GetPlayer()->IsBeingTeleportedFar()) return; GetPlayer()->SetSemaphoreTeleportFar(false); // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if(!MapManager::IsValidMapCoord(loc)) { LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId()); InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId()); // reset instance validity, except if going to an instance inside an instance if(GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; Map * oldMap = GetPlayer()->GetMap(); ASSERT(oldMap); if(GetPlayer()->IsInWorld()) { sLog->outCrash("Player is still in world when teleported from map %u! to new map %u", oldMap->GetId(), loc.GetMapId()); oldMap->Remove(GetPlayer(), false); } // relocate the player to the teleport destination Map * newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer(), 0); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if(!newMap || !newMap->CanEnter(GetPlayer())) { sLog->outError("Map %d could not be created for player %d, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUIDLow()); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); return; } else GetPlayer()->Relocate(&loc); GetPlayer()->ResetMap(); GetPlayer()->SetMap(newMap); GetPlayer()->SendInitialPacketsBeforeAddToMap(); if(!GetPlayer()->GetMap()->Add(GetPlayer())) { sLog->outError("WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.GetMapId()); GetPlayer()->ResetMap(); GetPlayer()->SetMap(oldMap); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); return; } // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if(_player->InBattleground()) { // cleanup setting if outdated if(!mEntry->IsBattlegroundOrArena()) { // We're not in BG _player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE); // reset destination bg team _player->SetBGTeam(0); } // join to bg case else if(Battleground *bg = _player->GetBattleground()) { if(_player->IsInvitedForBattlegroundInstance(_player->GetBattlegroundId())) bg->AddPlayer(_player); } } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { if(!_player->InBattleground()) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Initialize(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->CleanupAfterTaxiFlight(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse *corpse = GetPlayer()->GetCorpse(); if(corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if(mEntry->IsDungeon()) { GetPlayer()->ResurrectPlayer(0.5f, false); GetPlayer()->SpawnCorpseBones(); } } bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena(); if(mInstance) { Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid()); if(MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID, diff)) { if(mapDiff->resetTime) { if(time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff)) { uint32 timeleft = uint32(timeReset - time(NULL)); GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft); } } } allowMount = mInstance->AllowMount; } // mount allow check if(!allowMount) _player->RemoveAurasByType(SPELL_AURA_MOUNTED); // update zone immediately, otherwise leave channel will cause crash in mtmap uint32 newzone, newarea; GetPlayer()->GetZoneAndAreaId(newzone, newarea); GetPlayer()->UpdateZone(newzone, newarea); // honorless target if(GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // in friendly area else if(GetPlayer()->IsPvP() && !GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) GetPlayer()->UpdatePvP(false, false); // resummon pet GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); }
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_SPLINE_DONE"); recvData.rfinish(); // 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) return; TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case if (curDestNode && curDestNode->map_id != 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->map_id, node.x, node.y, node.z, GetPlayer()->GetOrientation()); } return; } uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); if (destinationnode > 0) // if more destinations to go { // current source node for next destination uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (GetPlayer()->isTaxiCheater()) { if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); _player->GetSession()->SendPacket(&data); } } sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode); uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam()); uint32 path, cost; sObjectMgr->GetTaxiPath(sourcenode, destinationnode, path, cost); if (path && mountDisplayId) SendDoFlight(mountDisplayId, path, 1); // skip start fly node else GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next return; } else GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node GetPlayer()->CleanupAfterTaxiFlight(); GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ()); if (GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); }
void WorldSession::HandleMoveWorldportAckOpcode() { // ignore unexpected far teleports if(!GetPlayer()->IsBeingTeleportedFar()) return; // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if(!MapManager::IsValidMapCoord(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation)) { sLog.outError("WorldSession::HandleMoveWorldportAckOpcode: player got's teleported far to a not valid location. (map:%u, x:%f, y:%f, z:%f) We log him out and don't save him..", loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); // stop teleportation else we would try this again in the beginning of WorldSession::LogoutPlayer... GetPlayer()->SetSemaphoreTeleportFar(false); // player don't gets saved - so his coords will stay at the point where // he was last saved LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid); InstanceTemplate const* mInstance = ObjectMgr::GetInstanceTemplate(loc.mapid); // reset instance validity, except if going to an instance inside an instance if(GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; GetPlayer()->SetSemaphoreTeleportFar(false); // relocate the player to the teleport destination GetPlayer()->SetMap(sMapMgr.CreateMap(loc.mapid, GetPlayer())); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if(!GetPlayer()->GetMap()->Add(GetPlayer())) { //if player wasn't added to map, reset his map pointer! GetPlayer()->ResetMap(); sLog.outDebug("WORLD: teleport of player %s (%d) to location %d, %f, %f, %f, %f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); // teleport the player home if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation())) { // the player must always be able to teleport home sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d, %f, %f, %f, %f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); assert(false); } return; } // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if(_player->InBattleGround()) { // cleanup setting if outdated if(!mEntry->IsBattleGroundOrArena()) { // We're not in BG _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // reset destination bg team _player->SetBGTeam(0); } // join to bg case else if(BattleGround *bg = _player->GetBattleGround()) { if(_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) bg->AddPlayer(_player); } } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { if(!_player->InBattleGround()) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Initialize(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->m_taxi.ClearTaxiDestinations(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse *corpse = GetPlayer()->GetCorpse(); if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if( mEntry->IsDungeon() ) { GetPlayer()->ResurrectPlayer(0.5f); GetPlayer()->SpawnCorpseBones(); GetPlayer()->SaveToDB(); } } if (mInstance) { if(mEntry->IsRaid()) { uint32 timeleft = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), GetPlayer()->GetRaidDifficulty(), timeleft); } else if(mEntry->IsNonRaidDungeon() && GetPlayer()->GetDungeonDifficulty() > DUNGEON_DIFFICULTY_NORMAL) { if(MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID,GetPlayer()->GetDungeonDifficulty())) { uint32 timeleft = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), GetPlayer()->GetDungeonDifficulty(), timeleft); } } } // mount allow check if(!mEntry->IsMountAllowed()) _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // honorless target if(GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // resummon pet GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); }
void WorldSession::HandleMoveWorldportAckOpcode() { // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if(!MapManager::IsValidMapCoord(loc.mapid,loc.x,loc.y,loc.z,loc.o)) { LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid); InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.mapid); // reset instance validity, except if going to an instance inside an instance if(GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; GetPlayer()->SetSemaphoreTeleport(false); // relocate the player to the teleport destination GetPlayer()->SetMapId(loc.mapid); GetPlayer()->Relocate(loc.x, loc.y, loc.z, loc.o); // since the MapId is set before the GetInstance call, the InstanceId must be set to 0 // to let GetInstance() determine the proper InstanceId based on the player's binds GetPlayer()->SetInstanceId(0); // check this before Map::Add(player), because that will create the instance save! bool reset_notify = (GetPlayer()->GetBoundInstance(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty()) == NULL); GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if(!GetPlayer()->GetMap()->Add(GetPlayer())) { sLog.outDebug("WORLD: teleport of player %s (%d) to location %d,%f,%f,%f,%f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.x, loc.y, loc.z, loc.o); // teleport the player home GetPlayer()->SetDontMove(false); if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation())) { // the player must always be able to teleport home sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d,%f,%f,%f,%f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); assert(false); } return; } // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if(_player->InBattleGround()) { // cleanup seting if outdated if(!mEntry->IsBattleGroundOrArena()) { _player->SetBattleGroundId(0, BATTLEGROUND_TYPE_NONE); // We're not in BG. // reset destination bg team _player->SetBGTeam(0); } // join to bg case else if(BattleGround *bg = _player->GetBattleGround()) { if(_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) bg->AddPlayer(_player); } } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) { if(!_player->InBattleGround()) { // short preparations to continue flight GetPlayer()->SetDontMove(false); FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Initialize(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->m_taxi.ClearTaxiDestinations(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse *corpse = GetPlayer()->GetCorpse(); if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if( mEntry->IsDungeon() ) { GetPlayer()->ResurrectPlayer(0.5f); GetPlayer()->SpawnCorpseBones(); GetPlayer()->SaveToDB(); } } if(mEntry->IsRaid() && mInstance) { if(reset_notify) { uint32 timeleft = sInstanceSaveManager.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), timeleft); // greeting at the entrance of the resort raid instance } } // mount allow check if(!mEntry->IsMountAllowed()) _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // honorless target if(GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // resummon pet if(GetPlayer()->m_temporaryUnsummonedPetNumber) { Pet* NewPet = new Pet; if(!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true)) delete NewPet; GetPlayer()->m_temporaryUnsummonedPetNumber = 0; } GetPlayer()->SetDontMove(false); }
void PlayerbotMgr::HandleMasterIncomingPacket(const WorldPacket& packet) { switch (packet.GetOpcode()) { case CMSG_OFFER_PETITION: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid petitionGuid; ObjectGuid playerGuid; uint32 junk; p >> junk; // this is not petition type! p >> petitionGuid; // petition guid p >> playerGuid; // player guid Player* player = ObjectAccessor::FindPlayer(playerGuid); if (!player) return; uint32 petitionLowGuid = petitionGuid.GetCounter(); QueryResult *result = CharacterDatabase.PQuery("SELECT * FROM petition_sign WHERE playerguid = '%u' AND petitionguid = '%u'", player->GetGUIDLow(), petitionLowGuid); if(result) { ChatHandler(m_master).PSendSysMessage("%s has already signed the petition",player->GetName()); delete result; return; } CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GetMaster()->GetGUIDLow(), petitionLowGuid, player->GetGUIDLow(), GetMaster()->GetSession()->GetAccountId()); p.Initialize(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); p << ObjectGuid(petitionGuid); p << ObjectGuid(playerGuid); p << uint32(PETITION_SIGN_OK); // close at signer side GetMaster()->GetSession()->SendPacket(&p); return; } case CMSG_ACTIVATETAXI: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; std::vector<uint32> nodes; nodes.resize(2); uint8 delay = 9; p >> guid >> nodes[0] >> nodes[1]; // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_ACTIVATETAXI from %d to %d", nodes[0], nodes[1]); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { delay = delay + 3; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) continue; Unit *target = ObjectAccessor::GetUnit(*bot, guid); bot->GetPlayerbotAI()->SetIgnoreUpdateTime(delay); bot->GetMotionMaster()->Clear(true); bot->GetMotionMaster()->MoveFollow(target, INTERACTION_DISTANCE, bot->GetOrientation()); bot->GetPlayerbotAI()->GetTaxi(guid, nodes); } return; } case CMSG_ACTIVATETAXIEXPRESS: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; uint32 node_count; uint8 delay = 9; p >> guid; p.read_skip<uint32>(); p >> node_count; std::vector<uint32> nodes; for (uint32 i = 0; i < node_count; ++i) { uint32 node; p >> node; nodes.push_back(node); } if (nodes.empty()) return; // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_ACTIVATETAXIEXPRESS from %d to %d", nodes.front(), nodes.back()); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { delay = delay + 3; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) continue; Unit *target = ObjectAccessor::GetUnit(*bot, guid); bot->GetPlayerbotAI()->SetIgnoreUpdateTime(delay); bot->GetMotionMaster()->Clear(true); bot->GetMotionMaster()->MoveFollow(target, INTERACTION_DISTANCE, bot->GetOrientation()); bot->GetPlayerbotAI()->GetTaxi(guid, nodes); } return; } case CMSG_MOVE_SPLINE_DONE: { // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_MOVE_SPLINE_DONE"); WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; // used only for proper packet read MovementInfo movementInfo; // used only for proper packet read p >> guid.ReadAsPacked(); p >> movementInfo; p >> Unused<uint32>(); // unk for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot) return; // 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 multi-map taxi path // we need process only (1) uint32 curDest = bot->m_taxi.GetTaxiDestination(); if (!curDest) return; TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case if (curDestNode && curDestNode->map_id != bot->GetMapId()) { if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator *) (bot->GetMotionMaster()->top()); flight->Interrupt(*bot); // will reset at map landing flight->SetCurrentNodeAfterTeleport(); TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); bot->TeleportTo(curDestNode->map_id, node.x, node.y, node.z, bot->GetOrientation()); } return; } uint32 destinationnode = bot->m_taxi.NextTaxiDestination(); if (destinationnode > 0) // if more destinations to go { // current source node for next destination uint32 sourcenode = bot->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (bot->isTaxiCheater()) if (bot->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); bot->GetSession()->SendPacket(&data); } // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_MOVE_SPLINE_DONE Taxi has to go from %u to %u", sourcenode, destinationnode); uint32 mountDisplayId = sObjectMgr.GetTaxiMountDisplayId(sourcenode, bot->GetTeam()); uint32 path, cost; sObjectMgr.GetTaxiPath(sourcenode, destinationnode, path, cost); if (path && mountDisplayId) bot->GetSession()->SendDoFlight(mountDisplayId, path, 1); // skip start fly node else bot->m_taxi.ClearTaxiDestinations(); // clear problematic path and next } else /* std::ostringstream out; out << "Destination reached" << bot->GetName(); ChatHandler ch(m_master); ch.SendSysMessage(out.str().c_str()); */ bot->m_taxi.ClearTaxiDestinations(); // Destination, clear source node } return; } // if master is logging out, log out all bots case CMSG_LOGOUT_REQUEST: { LogoutAllBots(); return; } // If master inspects one of his bots, give the master useful info in chat window // such as inventory that can be equipped case CMSG_INSPECT: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; p >> guid; Player* const bot = GetPlayerBot(guid); if (bot) bot->GetPlayerbotAI()->SendNotEquipList(*bot); return; } // handle emotes from the master //case CMSG_EMOTE: case CMSG_TEXT_EMOTE: { WorldPacket p(packet); p.rpos(0); // reset reader uint32 emoteNum; p >> emoteNum; /* std::ostringstream out; out << "emote is: " << emoteNum; ChatHandler ch(m_master); ch.SendSysMessage(out.str().c_str()); */ switch (emoteNum) { case TEXTEMOTE_BOW: { // Buff anyone who bows before me. Useful for players not in bot's group // How do I get correct target??? //Player* const pPlayer = GetPlayerBot(m_master->GetSelection()); //if (pPlayer->GetPlayerbotAI()->GetClassAI()) // pPlayer->GetPlayerbotAI()->GetClassAI()->BuffPlayer(pPlayer); return; } /* case TEXTEMOTE_BONK: { Player* const pPlayer = GetPlayerBot(m_master->GetSelection()); if (!pPlayer || !pPlayer->GetPlayerbotAI()) return; PlayerbotAI* const pBot = pPlayer->GetPlayerbotAI(); ChatHandler ch(m_master); { std::ostringstream out; out << "CurrentTime: " << CurrentTime() << " m_ignoreAIUpdatesUntilTime: " << pBot->m_ignoreAIUpdatesUntilTime; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "m_TimeDoneEating: " << pBot->m_TimeDoneEating << " m_TimeDoneDrinking: " << pBot->m_TimeDoneDrinking; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "m_CurrentlyCastingSpellId: " << pBot->m_CurrentlyCastingSpellId; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "IsBeingTeleported() " << pBot->GetPlayer()->IsBeingTeleported(); ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; bool tradeActive = (pBot->GetPlayer()->GetTrader()) ? true : false; out << "tradeActive: " << tradeActive; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "IsCharmed() " << pBot->getPlayer()->isCharmed(); ch.SendSysMessage(out.str().c_str()); } return; } */ case TEXTEMOTE_EAT: case TEXTEMOTE_DRINK: { for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->Feast(); } return; } // emote to attack selected target case TEXTEMOTE_POINT: { ObjectGuid attackOnGuid = m_master->GetSelectionGuid(); if (!attackOnGuid) return; Unit* thingToAttack = ObjectAccessor::GetUnit(*m_master, attackOnGuid); if (!thingToAttack) return; Player* bot = 0; for (PlayerBotMap::iterator itr = m_playerBots.begin(); itr != m_playerBots.end(); ++itr) { bot = itr->second; if (!bot->IsFriendlyTo(thingToAttack)) { if (!bot->IsWithinLOSInMap(thingToAttack)) bot->GetPlayerbotAI()->DoTeleport(*m_master); if (bot->IsWithinLOSInMap(thingToAttack)) bot->GetPlayerbotAI()->Attack(thingToAttack); } } return; } // emote to stay case TEXTEMOTE_STAND: { Player* const bot = GetPlayerBot(m_master->GetSelectionGuid()); if (bot) bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_STAY); else for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_STAY); } return; } // 324 is the followme emote (not defined in enum) // if master has bot selected then only bot follows, else all bots follow case 324: case TEXTEMOTE_WAVE: { Player* const bot = GetPlayerBot(m_master->GetSelectionGuid()); if (bot) bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_FOLLOW, m_master); else for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_FOLLOW, m_master); } return; } } return; } /* EMOTE ends here */ case CMSG_GAMEOBJ_USE: // not sure if we still need this one case CMSG_GAMEOBJ_REPORT_USE: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid objGUID; p >> objGUID; for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->FollowAutoReset(); GameObject *obj = m_master->GetMap()->GetGameObject(objGUID); if (!obj) return; // add other go types here, i.e.: // GAMEOBJECT_TYPE_CHEST - loot quest items of chest if (obj->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) { bot->GetPlayerbotAI()->TurnInQuests(obj); // auto accept every available quest this NPC has bot->PrepareQuestMenu(objGUID); QuestMenu& questMenu = bot->PlayerTalkClass->GetQuestMenu(); for (uint32 iI = 0; iI < questMenu.MenuItemCount(); ++iI) { QuestMenuItem const& qItem = questMenu.GetItem(iI); uint32 questID = qItem.m_qId; if (!bot->GetPlayerbotAI()->AddQuest(questID, obj)) DEBUG_LOG("Couldn't take quest"); } } } } break; case CMSG_QUESTGIVER_HELLO: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid npcGUID; p >> npcGUID; WorldObject* pNpc = m_master->GetMap()->GetWorldObject(npcGUID); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->FollowAutoReset(); bot->GetPlayerbotAI()->TurnInQuests(pNpc); } return; } // if master accepts a quest, bots should also try to accept quest case CMSG_QUESTGIVER_ACCEPT_QUEST: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; uint32 quest; uint32 unk1; p >> guid >> quest >> unk1; // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %s, quest = %u, unk1 = %u", guid.GetString().c_str(), quest, unk1); Quest const* qInfo = sObjectMgr.GetQuestTemplate(quest); if (qInfo) for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->FollowAutoReset(); if (bot->GetQuestStatus(quest) == QUEST_STATUS_COMPLETE) bot->GetPlayerbotAI()->TellMaster("I already completed that quest."); else if (!bot->CanTakeQuest(qInfo, false)) { if (!bot->SatisfyQuestStatus(qInfo, false)) bot->GetPlayerbotAI()->TellMaster("I already have that quest."); else bot->GetPlayerbotAI()->TellMaster("I can't take that quest."); } else if (!bot->SatisfyQuestLog(false)) bot->GetPlayerbotAI()->TellMaster("My quest log is full."); else if (!bot->CanAddQuest(qInfo, false)) bot->GetPlayerbotAI()->TellMaster("I can't take that quest because it requires that I take items, but my bags are full!"); else { p.rpos(0); // reset reader bot->GetSession()->HandleQuestgiverAcceptQuestOpcode(p); bot->GetPlayerbotAI()->TellMaster("Got the quest."); // build needed items if quest contains any for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++) if (qInfo->ReqItemCount[i] > 0) { bot->GetPlayerbotAI()->SetQuestNeedItems(); break; } // build needed creatures if quest contains any for (int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) if (qInfo->ReqCreatureOrGOCount[i] > 0) { bot->GetPlayerbotAI()->SetQuestNeedCreatures(); break; } } } return; } case CMSG_AREATRIGGER: { WorldPacket p(packet); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot) continue; if (bot->IsWithinDistInMap(GetMaster(), 50)) { p.rpos(0); // reset reader bot->GetSession()->HandleAreaTriggerOpcode(p); } } return; } case CMSG_QUESTGIVER_COMPLETE_QUEST: { WorldPacket p(packet); p.rpos(0); // reset reader uint32 quest; ObjectGuid npcGUID; p >> npcGUID >> quest; // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %s, quest = %u", npcGUID.GetString().c_str(), quest); WorldObject* pNpc = m_master->GetMap()->GetWorldObject(npcGUID); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->FollowAutoReset(); bot->GetPlayerbotAI()->TurnInQuests(pNpc); } return; } case CMSG_LOOT_ROLL: { WorldPacket p(packet); //WorldPacket packet for CMSG_LOOT_ROLL, (8+4+1) ObjectGuid Guid; uint32 itemSlot; uint8 rollType; p.rpos(0); //reset packet pointer p >> Guid; //guid of the lootable target p >> itemSlot; //loot index p >> rollType; //need,greed or pass on roll for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { uint32 choice = 2; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) return; // check that the bot did not already vote if (rollType >= ROLL_NOT_EMITED_YET) return; Loot* loot = sLootMgr.GetLoot(bot, Guid); if (!loot) { sLog.outError("LootMgr::PlayerVote> Error cannot get loot object info!"); return; } LootItem* lootItem = loot->GetLootItemInSlot(itemSlot); ItemPrototype const *pProto = lootItem->itemProto; if (!pProto) return; if (bot->GetPlayerbotAI()->CanStore()) { uint8 slots[4]; if (bot->ViableEquipSlots(pProto, &slots[0])) { int iSlot = 0; // First we check what we are currently wearing while (slots[iSlot] != NULL_SLOT && iSlot < 4) { Item* const pItem2 = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, slots[iSlot]); // Make sure there is something slotted if (pItem2) { if (bot->GetPlayerbotAI()->EquipPrototypeComparison(pItem2->GetProto(), pProto)) { choice = 1; break; } } iSlot++; } // TODO: Need to add logic for those cases where secondary equipment is // used. For instance - 2H is used by Tank, but sword and board are in // inventory for specific encounters. Upgrading thsoe should be taken // into consideration. Also, more specific logic for 'sets'. } else { if (bot->HasSkill(SKILL_ENCHANTING)) { choice = 3; // Disenchant } } } else choice = 0; // Pass sLootMgr.PlayerVote(bot, Guid, itemSlot, RollVote(choice)); switch (choice) { case ROLL_NEED: bot->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1); break; case ROLL_GREED: case ROLL_DISENCHANT: bot->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1); break; } } return; } // Handle GOSSIP activate actions, prior to GOSSIP select menu actions case CMSG_GOSSIP_HELLO: { // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_GOSSIP_HELLO"); WorldPacket p(packet); //WorldPacket packet for CMSG_GOSSIP_HELLO, (8) ObjectGuid guid; p.rpos(0); //reset packet pointer p >> guid; for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot) continue; bot->GetPlayerbotAI()->FollowAutoReset(); Creature *pCreature = bot->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!pCreature) { DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_GOSSIP_HELLO %s not found or you can't interact with him.", guid.GetString().c_str()); continue; } GossipMenuItemsMapBounds pMenuItemBounds = sObjectMgr.GetGossipMenuItemsMapBounds(pCreature->GetCreatureInfo()->GossipMenuId); for (GossipMenuItemsMap::const_iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr) { uint32 npcflags = pCreature->GetUInt32Value(UNIT_NPC_FLAGS); if (!(itr->second.npc_option_npcflag & npcflags)) continue; switch (itr->second.option_id) { case GOSSIP_OPTION_TAXIVENDOR: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_TAXIVENDOR"); bot->GetSession()->SendLearnNewTaxiNode(pCreature); break; } case GOSSIP_OPTION_QUESTGIVER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_QUESTGIVER"); bot->GetPlayerbotAI()->TurnInQuests(pCreature); break; } case GOSSIP_OPTION_VENDOR: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_VENDOR"); if (!botConfig.GetBoolDefault("PlayerbotAI.SellGarbage", true)) continue; // changed the SellGarbage() function to support ch.SendSysMessaage() bot->GetPlayerbotAI()->SellGarbage(*bot); break; } case GOSSIP_OPTION_STABLEPET: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_STABLEPET"); break; } case GOSSIP_OPTION_AUCTIONEER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_AUCTIONEER"); break; } case GOSSIP_OPTION_BANKER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_BANKER"); break; } case GOSSIP_OPTION_INNKEEPER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_INNKEEPER"); break; } } } } return; } case CMSG_SPIRIT_HEALER_ACTIVATE: { // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_SPIRIT_HEALER_ACTIVATE SpiritHealer is resurrecting the Player %s",m_master->GetName()); for (PlayerBotMap::iterator itr = m_playerBots.begin(); itr != m_playerBots.end(); ++itr) { Player* const bot = itr->second; Group *grp = bot->GetGroup(); if (grp) grp->RemoveMember(bot->GetObjectGuid(), 1); } return; } case CMSG_LIST_INVENTORY: { if (!botConfig.GetBoolDefault("PlayerbotAI.SellGarbage", true)) return; WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid npcGUID; p >> npcGUID; Object* const pNpc = (WorldObject *) m_master->GetObjectByTypeMask(npcGUID, TYPEMASK_CREATURE_OR_GAMEOBJECT); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot->IsInMap(static_cast<WorldObject *>(pNpc))) { bot->GetPlayerbotAI()->TellMaster("I'm too far away to sell items!"); continue; } else { // changed the SellGarbage() function to support ch.SendSysMessaage() bot->GetPlayerbotAI()->FollowAutoReset(); bot->GetPlayerbotAI()->SellGarbage(*bot); } } return; } /* case CMSG_NAME_QUERY: case MSG_MOVE_START_FORWARD: case MSG_MOVE_STOP: case MSG_MOVE_SET_FACING: case MSG_MOVE_START_STRAFE_LEFT: case MSG_MOVE_START_STRAFE_RIGHT: case MSG_MOVE_STOP_STRAFE: case MSG_MOVE_START_BACKWARD: case MSG_MOVE_HEARTBEAT: case CMSG_STANDSTATECHANGE: case CMSG_QUERY_TIME: case CMSG_CREATURE_QUERY: case CMSG_GAMEOBJECT_QUERY: case MSG_MOVE_JUMP: case MSG_MOVE_FALL_LAND: return;*/ default: { /*const char* oc = LookupOpcodeName(packet.GetOpcode()); // ChatHandler ch(m_master); // ch.SendSysMessage(oc); std::ostringstream out; out << "masterin: " << oc; sLog.outError(out.str().c_str()); */ } } }
void PlayerbotMgr::HandleMasterIncomingPacket(const WorldPacket& packet) { switch (packet.GetOpcode()) { case CMSG_ACTIVATETAXI: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; std::vector<uint32> nodes; nodes.resize(2); uint8 delay = 9; p >> guid >> nodes[0] >> nodes[1]; DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_ACTIVATETAXI from %d to %d", nodes[0], nodes[1]); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { delay = delay + 3; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) continue; Unit *target = ObjectAccessor::GetUnit(*bot, guid); bot->GetPlayerbotAI()->SetIgnoreUpdateTime(delay); bot->GetMotionMaster()->Clear(true); bot->GetMotionMaster()->MoveFollow(target, INTERACTION_DISTANCE, bot->GetOrientation()); bot->GetPlayerbotAI()->GetTaxi(guid, nodes); } return; } case CMSG_ACTIVATETAXIEXPRESS: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; uint32 node_count; uint8 delay = 9; p >> guid >> node_count; std::vector<uint32> nodes; for (uint32 i = 0; i < node_count; ++i) { uint32 node; p >> node; nodes.push_back(node); } if (nodes.empty()) return; DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_ACTIVATETAXIEXPRESS from %d to %d", nodes.front(), nodes.back()); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { delay = delay + 3; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) continue; Unit *target = ObjectAccessor::GetUnit(*bot, guid); bot->GetPlayerbotAI()->SetIgnoreUpdateTime(delay); bot->GetMotionMaster()->Clear(true); bot->GetMotionMaster()->MoveFollow(target, INTERACTION_DISTANCE, bot->GetOrientation()); bot->GetPlayerbotAI()->GetTaxi(guid, nodes); } return; } case CMSG_MOVE_SPLINE_DONE: { DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_MOVE_SPLINE_DONE"); WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; // used only for proper packet read MovementInfo movementInfo; // used only for proper packet read p >> guid.ReadAsPacked(); p >> movementInfo; p >> Unused<uint32>(); // unk for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot) return; // 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 multi-map taxi path // we need process only (1) uint32 curDest = bot->m_taxi.GetTaxiDestination(); if (!curDest) return; TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case if (curDestNode && curDestNode->map_id != bot->GetMapId()) { if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator *) (bot->GetMotionMaster()->top()); flight->Interrupt(*bot); // will reset at map landing flight->SetCurrentNodeAfterTeleport(); TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); bot->TeleportTo(curDestNode->map_id, node.x, node.y, node.z, bot->GetOrientation()); } return; } uint32 destinationnode = bot->m_taxi.NextTaxiDestination(); if (destinationnode > 0) // if more destinations to go { // current source node for next destination uint32 sourcenode = bot->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (bot->isTaxiCheater()) if (bot->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); bot->GetSession()->SendPacket(&data); } DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_MOVE_SPLINE_DONE Taxi has to go from %u to %u", sourcenode, destinationnode); uint32 mountDisplayId = sObjectMgr.GetTaxiMountDisplayId(sourcenode, bot->GetTeam()); uint32 path, cost; sObjectMgr.GetTaxiPath(sourcenode, destinationnode, path, cost); if (path && mountDisplayId) bot->GetSession()->SendDoFlight(mountDisplayId, path, 1); // skip start fly node else bot->m_taxi.ClearTaxiDestinations(); // clear problematic path and next } else /* std::ostringstream out; out << "Destination reached" << bot->GetName(); ChatHandler ch(m_master); ch.SendSysMessage(out.str().c_str()); */ bot->m_taxi.ClearTaxiDestinations(); // Destination, clear source node } return; } // if master is logging out, log out all bots & remove them from group case CMSG_LOGOUT_REQUEST: { LogoutAllBots(); return; } // If master inspects one of his bots, give the master useful info in chat window // such as inventory that can be equipped case CMSG_INSPECT: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; p >> guid; Player* const bot = GetPlayerBot(guid); if (bot) bot->GetPlayerbotAI()->SendNotEquipList(*bot); return; } // handle emotes from the master //case CMSG_EMOTE: case CMSG_TEXT_EMOTE: { WorldPacket p(packet); p.rpos(0); // reset reader uint32 emoteNum; p >> emoteNum; /* std::ostringstream out; out << "emote is: " << emoteNum; ChatHandler ch(m_master); ch.SendSysMessage(out.str().c_str()); */ switch (emoteNum) { case TEXTEMOTE_BOW: { // Buff anyone who bows before me. Useful for players not in bot's group // How do I get correct target??? //Player* const pPlayer = GetPlayerBot(m_master->GetSelection()); //if (pPlayer->GetPlayerbotAI()->GetClassAI()) // pPlayer->GetPlayerbotAI()->GetClassAI()->BuffPlayer(pPlayer); return; } /* case TEXTEMOTE_BONK: { Player* const pPlayer = GetPlayerBot(m_master->GetSelection()); if (!pPlayer || !pPlayer->GetPlayerbotAI()) return; PlayerbotAI* const pBot = pPlayer->GetPlayerbotAI(); ChatHandler ch(m_master); { std::ostringstream out; out << "time(0): " << time(0) << " m_ignoreAIUpdatesUntilTime: " << pBot->m_ignoreAIUpdatesUntilTime; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "m_TimeDoneEating: " << pBot->m_TimeDoneEating << " m_TimeDoneDrinking: " << pBot->m_TimeDoneDrinking; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "m_CurrentlyCastingSpellId: " << pBot->m_CurrentlyCastingSpellId; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "IsBeingTeleported() " << pBot->GetPlayer()->IsBeingTeleported(); ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; bool tradeActive = (pBot->GetPlayer()->GetTrader()) ? true : false; out << "tradeActive: " << tradeActive; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "IsCharmed() " << pBot->getPlayer()->isCharmed(); ch.SendSysMessage(out.str().c_str()); } return; } */ case TEXTEMOTE_EAT: case TEXTEMOTE_DRINK: { for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->Feast(); } return; } // emote to attack selected target case TEXTEMOTE_POINT: { ObjectGuid attackOnGuid = m_master->GetSelectionGuid(); if (attackOnGuid.IsEmpty()) return; Unit* thingToAttack = ObjectAccessor::GetUnit(*m_master, attackOnGuid); if (!thingToAttack) return; Player *bot = 0; for (PlayerBotMap::iterator itr = m_playerBots.begin(); itr != m_playerBots.end(); ++itr) { bot = itr->second; if (!bot->IsFriendlyTo(thingToAttack) && bot->IsWithinLOSInMap(thingToAttack)) bot->GetPlayerbotAI()->GetCombatTarget(thingToAttack); } return; } // emote to stay case TEXTEMOTE_STAND: { Player* const bot = GetPlayerBot(m_master->GetSelectionGuid()); if (bot) bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_STAY); else for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_STAY); } return; } // 324 is the followme emote (not defined in enum) // if master has bot selected then only bot follows, else all bots follow case 324: case TEXTEMOTE_WAVE: { Player* const bot = GetPlayerBot(m_master->GetSelectionGuid()); if (bot) bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_FOLLOW, m_master); else for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_FOLLOW, m_master); } return; } } return; } /* EMOTE ends here */ case CMSG_GAMEOBJ_USE: // not sure if we still need this one case CMSG_GAMEOBJ_REPORT_USE: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid objGUID; p >> objGUID; for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; GameObject *obj = m_master->GetMap()->GetGameObject(objGUID); if (!obj) return; // add other go types here, i.e.: // GAMEOBJECT_TYPE_CHEST - loot quest items of chest if (obj->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) { bot->GetPlayerbotAI()->TurnInQuests(obj); // auto accept every available quest this NPC has bot->PrepareQuestMenu(objGUID); QuestMenu& questMenu = bot->PlayerTalkClass->GetQuestMenu(); for (uint32 iI = 0; iI < questMenu.MenuItemCount(); ++iI) { QuestMenuItem const& qItem = questMenu.GetItem(iI); uint32 questID = qItem.m_qId; if (!bot->GetPlayerbotAI()->AddQuest(questID, obj)) DEBUG_LOG("Couldn't take quest"); } } } } break; case CMSG_QUESTGIVER_HELLO: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid npcGUID; p >> npcGUID; WorldObject* pNpc = m_master->GetMap()->GetWorldObject(npcGUID); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->TurnInQuests(pNpc); } return; } // if master accepts a quest, bots should also try to accept quest case CMSG_QUESTGIVER_ACCEPT_QUEST: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; uint32 quest; uint32 unk1; p >> guid >> quest >> unk1; DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %s, quest = %u, unk1 = %u", guid.GetString().c_str(), quest, unk1); Quest const* qInfo = sObjectMgr.GetQuestTemplate(quest); if (qInfo) for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (bot->GetQuestStatus(quest) == QUEST_STATUS_COMPLETE) bot->GetPlayerbotAI()->TellMaster("I already completed that quest."); else if (!bot->CanTakeQuest(qInfo, false)) { if (!bot->SatisfyQuestStatus(qInfo, false)) bot->GetPlayerbotAI()->TellMaster("I already have that quest."); else bot->GetPlayerbotAI()->TellMaster("I can't take that quest."); } else if (!bot->SatisfyQuestLog(false)) bot->GetPlayerbotAI()->TellMaster("My quest log is full."); else if (!bot->CanAddQuest(qInfo, false)) bot->GetPlayerbotAI()->TellMaster("I can't take that quest because it requires that I take items, but my bags are full!"); else { p.rpos(0); // reset reader bot->GetSession()->HandleQuestgiverAcceptQuestOpcode(p); bot->GetPlayerbotAI()->TellMaster("Got the quest."); // build needed items if quest contains any for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++) if (qInfo->ReqItemCount[i] > 0) { bot->GetPlayerbotAI()->SetQuestNeedItems(); break; } // build needed creatures if quest contains any for (int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) if (qInfo->ReqCreatureOrGOCount[i] > 0) { bot->GetPlayerbotAI()->SetQuestNeedCreatures(); break; } } } return; } case CMSG_AREATRIGGER: { WorldPacket p(packet); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; p.rpos(0); // reset reader bot->GetSession()->HandleAreaTriggerOpcode(p); } return; } case CMSG_QUESTGIVER_COMPLETE_QUEST: { WorldPacket p(packet); p.rpos(0); // reset reader uint32 quest; ObjectGuid npcGUID; p >> npcGUID >> quest; DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %s, quest = %u", npcGUID.GetString().c_str(), quest); WorldObject* pNpc = m_master->GetMap()->GetWorldObject(npcGUID); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->TurnInQuests(pNpc); } return; } case CMSG_LOOT_ROLL: { WorldPacket p(packet); //WorldPacket packet for CMSG_LOOT_ROLL, (8+4+1) ObjectGuid Guid; uint32 NumberOfPlayers; uint8 rollType; p.rpos(0); //reset packet pointer p >> Guid; //guid of the item rolled p >> NumberOfPlayers; //number of players invited to roll p >> rollType; //need,greed or pass on roll for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { uint32 choice; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) return; (bot->GetPlayerbotAI()->CanStore()) ? choice = urand(0, 3) : choice = 0; // pass = 0, need = 1, greed = 2, disenchant = 3 group->CountRollVote(bot, Guid, NumberOfPlayers, RollVote(choice)); switch (choice) { case ROLL_NEED: bot->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1); break; case ROLL_GREED: bot->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1); break; } } return; } // Handle GOSSIP activate actions, prior to GOSSIP select menu actions case CMSG_GOSSIP_HELLO: { DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_GOSSIP_HELLO"); WorldPacket p(packet); //WorldPacket packet for CMSG_GOSSIP_HELLO, (8) ObjectGuid guid; p.rpos(0); //reset packet pointer p >> guid; for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot) return; Creature *pCreature = bot->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!pCreature) { DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_GOSSIP_HELLO %s not found or you can't interact with him.", guid.GetString().c_str()); return; } GossipMenuItemsMapBounds pMenuItemBounds = sObjectMgr.GetGossipMenuItemsMapBounds(pCreature->GetCreatureInfo()->GossipMenuId); for (GossipMenuItemsMap::const_iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr) { uint32 npcflags = pCreature->GetUInt32Value(UNIT_NPC_FLAGS); if (!(itr->second.npc_option_npcflag & npcflags)) continue; switch (itr->second.option_id) { case GOSSIP_OPTION_TAXIVENDOR: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_TAXIVENDOR"); bot->GetSession()->SendLearnNewTaxiNode(pCreature); break; } case GOSSIP_OPTION_QUESTGIVER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_QUESTGIVER"); bot->GetPlayerbotAI()->TurnInQuests(pCreature); break; } case GOSSIP_OPTION_VENDOR: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_VENDOR"); break; } case GOSSIP_OPTION_STABLEPET: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_STABLEPET"); break; } case GOSSIP_OPTION_AUCTIONEER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_AUCTIONEER"); break; } case GOSSIP_OPTION_BANKER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_BANKER"); break; } case GOSSIP_OPTION_INNKEEPER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_INNKEEPER"); break; } } } } return; } case CMSG_SPIRIT_HEALER_ACTIVATE: { // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_SPIRIT_HEALER_ACTIVATE SpiritHealer is resurrecting the Player %s",m_master->GetName()); for (PlayerBotMap::iterator itr = m_playerBots.begin(); itr != m_playerBots.end(); ++itr) { Player* const bot = itr->second; Group *grp = bot->GetGroup(); if (grp) grp->RemoveMember(bot->GetObjectGuid(), 1); } return; } case CMSG_LIST_INVENTORY: { if (sWorld.getConfig(CONFIG_BOOL_PLAYERBOT_SELL_TRASH)) return; WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid npcGUID; p >> npcGUID; Object* const pNpc = (WorldObject *) m_master->GetObjectByTypeMask(npcGUID, TYPEMASK_CREATURE_OR_GAMEOBJECT); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot->IsInMap(static_cast<WorldObject *>(pNpc))) { bot->GetPlayerbotAI()->TellMaster("I'm too far away to sell items!"); continue; } else bot->GetPlayerbotAI()->SellGarbage(); } return; } /* case CMSG_NAME_QUERY: case MSG_MOVE_START_FORWARD: case MSG_MOVE_STOP: case MSG_MOVE_SET_FACING: case MSG_MOVE_START_STRAFE_LEFT: case MSG_MOVE_START_STRAFE_RIGHT: case MSG_MOVE_STOP_STRAFE: case MSG_MOVE_START_BACKWARD: case MSG_MOVE_HEARTBEAT: case CMSG_STANDSTATECHANGE: case CMSG_QUERY_TIME: case CMSG_CREATURE_QUERY: case CMSG_GAMEOBJECT_QUERY: case MSG_MOVE_JUMP: case MSG_MOVE_FALL_LAND: return; default: { const char* oc = LookupOpcodeName(packet.GetOpcode()); // ChatHandler ch(m_master); // ch.SendSysMessage(oc); std::ostringstream out; out << "masterin: " << oc; sLog.outError(out.str().c_str()); } */ } }
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_MOVE_SPLINE_DONE"); uint64 guid; // used only for proper packet read recv_data.readPackGUID(guid); // movement anticheat const Unit *mover = _player->m_mover; const Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; if (!plMover) return; // end movement anticheat MovementInfo movementInfo; // used only for proper packet read ReadMovementInfo(recv_data, &movementInfo); recv_data.read_skip<uint32>(); // unk // 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) { // movement anticheat code GetPlayer()->SetPosition(movementInfo.pos.m_positionX, movementInfo.pos.m_positionY, movementInfo.pos.m_positionZ, movementInfo.pos.m_orientation); GetPlayer()->m_movementInfo = movementInfo; GetPlayer()->SetUnitMovementFlags(movementInfo.flags); // calc time deltas int32 cClientTimeDelta = 0; if (GetPlayer()->m_anti_LastClientTime != 0) { cClientTimeDelta = movementInfo.time - GetPlayer()->m_anti_LastClientTime; GetPlayer()->m_anti_DeltaClientTime += cClientTimeDelta; GetPlayer()->m_anti_LastClientTime = movementInfo.time; } else GetPlayer()->m_anti_LastClientTime = movementInfo.time; const uint64 cServerTime = getMSTime(); uint32 cServerTimeDelta = 0; if (GetPlayer()->m_anti_LastServerTime != 0) { cServerTimeDelta = cServerTime - GetPlayer()->m_anti_LastServerTime; GetPlayer()->m_anti_DeltaServerTime += cServerTimeDelta; GetPlayer()->m_anti_LastServerTime = cServerTime; } else GetPlayer()->m_anti_LastServerTime = cServerTime; // end movement anticheat return; } // movment anticheat const uint32 curloc = sObjectMgr->GetNearestTaxiNode(movementInfo.pos.m_positionX,movementInfo.pos.m_positionY,movementInfo.pos.m_positionZ,GetPlayer()->GetMapId(),GetPlayer()->GetTeam(), curDest); // end movement anticheat TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // ** QUESTIONABLE PART ** if (curDestNode && curDestNode->map_id == GetPlayer()->GetMapId()) while (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) GetPlayer()->GetMotionMaster()->MovementExpired(false); // end of QUESTIONABLE PART // movement anticheat code GetPlayer()->SetPosition(movementInfo.pos.m_positionX, movementInfo.pos.m_positionY, movementInfo.pos.m_positionZ, movementInfo.pos.m_orientation); GetPlayer()->m_movementInfo = movementInfo; GetPlayer()->SetUnitMovementFlags(movementInfo.flags); // calc time deltas int32 cClientTimeDelta = 0; if (GetPlayer()->m_anti_LastClientTime != 0) { cClientTimeDelta = movementInfo.time - GetPlayer()->m_anti_LastClientTime; GetPlayer()->m_anti_DeltaClientTime += cClientTimeDelta; GetPlayer()->m_anti_LastClientTime = movementInfo.time; } else GetPlayer()->m_anti_LastClientTime = movementInfo.time; const uint64 cServerTime = getMSTime(); uint32 cServerTimeDelta = 0; if (GetPlayer()->m_anti_LastServerTime != 0) { cServerTimeDelta = cServerTime - GetPlayer()->m_anti_LastServerTime; GetPlayer()->m_anti_DeltaServerTime += cServerTimeDelta; GetPlayer()->m_anti_LastServerTime = cServerTime; } else GetPlayer()->m_anti_LastServerTime = cServerTime; // end movement anticheat // far teleport case if (curDestNode && curDestNode->map_id != 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->map_id,node.x,node.y,node.z,GetPlayer()->GetOrientation()); } return; } // movement anticheat fix - disallow unmount from taxi // NOTE: this fix is of a BAD STYLE! rewrite all down to the end of the method if (curloc != curDest) { // current source node for next destination uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); uint16 MountId = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam()); uint32 path, cost; sObjectMgr->GetTaxiPath(sourcenode, curDest, path, cost); if (path && MountId) SendDoFlight(MountId, path, 1); // skip start fly node else GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next return; } // end movement anticheat uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); if (destinationnode > 0) // if more destinations to go { // current source node for next destination uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (GetPlayer()->isTaxiCheater()) { if (GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); _player->GetSession()->SendPacket(&data); } } sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode); uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam()); uint32 path, cost; sObjectMgr->GetTaxiPath(sourcenode, destinationnode, path, cost); if (path && mountDisplayId) SendDoFlight(mountDisplayId, path, 1); // skip start fly node else GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next return; } else GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node GetPlayer()->CleanupAfterTaxiFlight(); GetPlayer()->SetFallInformation(0, GetPlayer()->GetPositionZ()); if (GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); }
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_MOVE_SPLINE_DONE"); MovementInfo movementInfo; // used only for proper packet read recv_data >> movementInfo; recv_data >> Unused<uint32>(); // unk recv_data >> Unused<uint32>(); // unk2 // 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 multi-map taxi path // we need process only (1) uint32 curDest = _player->m_taxi.GetTaxiDestination(); if (!curDest) { return; } TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case if (curDestNode && curDestNode->map_id != _player->GetMapId()) { if (_player->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(_player->GetMotionMaster()->top()); flight->Interrupt(*_player); // will reset at map landing flight->SetCurrentNodeAfterTeleport(); TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); _player->TeleportTo(curDestNode->map_id, node.x, node.y, node.z, _player->GetOrientation()); } return; } uint32 destinationnode = _player->m_taxi.NextTaxiDestination(); if (destinationnode > 0) // if more destinations to go { // current source node for next destination uint32 sourcenode = _player->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (_player->IsTaxiCheater()) { if (_player->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); _player->GetSession()->SendPacket(&data); } } DEBUG_LOG("WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode); uint32 mountDisplayId = sObjectMgr.GetTaxiMountDisplayId(sourcenode, _player->GetTeam()); uint32 path, cost; sObjectMgr.GetTaxiPath(sourcenode, destinationnode, path, cost); if (path && mountDisplayId) { SendDoFlight(mountDisplayId, path, 1); } // skip start fly node else { _player->m_taxi.ClearTaxiDestinations(); } // clear problematic path and next } else { _player->m_taxi.ClearTaxiDestinations(); } // not destinations, clear source node }
void WorldSession::HandleMoveWorldportAckOpcode() { // ignore unexpected far teleports if (!GetPlayer()->IsBeingTeleportedFar()) return; // get the teleport destination WorldLocation const& loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if (!MapManager::IsValidMapCoord(loc)) { sLog.outError("WorldSession::HandleMoveWorldportAckOpcode: player %s (%d) was teleported far to a not valid location. (map:%u, x:%f, y:%f, " "z:%f) We port him to his homebind instead..", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ()); // stop teleportation else we would try this again and again in LogoutPlayer... GetPlayer()->SetSemaphoreTeleportFar(false); // and teleport the player to a valid place GetPlayer()->TeleportToHomebind(); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId()); InstanceTemplate const* mInstance = sObjectMgr.GetInstanceTemplate(loc.GetMapId()); // reset instance validity, except if going to an instance inside an instance if (GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; GetPlayer()->SetSemaphoreTeleportFar(false); Map* oldMap = GetPlayer()->GetMap(); ASSERT(oldMap); if (GetPlayer()->IsInWorld()) { sLog.outError("Crash alert! Player is still in world when teleported from map %u! to new map %u", oldMap->GetId(), loc.GetMapId()); oldMap->RemoveFromMap(GetPlayer(), false); } // relocate the player to the teleport destination Map* newMap = MapManager::Instance().CreateMap(loc.GetMapId(), GetPlayer(), 0); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if (!newMap || !newMap->CanEnter(GetPlayer())) { sLog.outError("Map %d could not be created for player %d, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUIDLow()); GetPlayer()->TeleportToHomebind(); return; } else GetPlayer()->Relocate(&loc); GetPlayer()->ResetMap(); GetPlayer()->SetMap(newMap); // check this before Map::AddToMap(player), because that will create the instance save! bool reset_notify = (GetPlayer()->GetBoundInstance(GetPlayer()->GetMapId(), GetPlayer()->GetDifficulty()) == NULL); GetPlayer()->SendInitialPacketsBeforeAddToMap(); if (!GetPlayer()->GetMap()->AddToMap(GetPlayer())) { sLog.outError("WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.GetMapId()); GetPlayer()->ResetMap(); GetPlayer()->SetMap(oldMap); GetPlayer()->TeleportToHomebind(); return; } // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) if (GetPlayer()->InBattleGround()) { // cleanup setting if outdated if (!mEntry->IsBattleGroundOrArena()) { // We're not in BG GetPlayer()->SetBattleGroundId(0); // We're not in BG. // reset destination bg team GetPlayer()->SetBGTeam(0); } // join to bg case else if (BattleGround* bg = GetPlayer()->GetBattleGround()) { if (GetPlayer()->IsInvitedForBattleGroundInstance(GetPlayer()->GetBattleGroundId())) bg->AddPlayer(GetPlayer()); } } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if (GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { if (!GetPlayer()->InBattleGround()) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Initialize(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->CleanupAfterTaxiFlight(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse* corpse = GetPlayer()->GetCorpse(); if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if (mEntry->IsDungeon()) { GetPlayer()->ResurrectPlayer(0.5f, false); GetPlayer()->SpawnCorpseBones(); } } bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattleGroundOrArena(); if (mInstance) { if (reset_notify) { if (uint32 timeReset = sInstanceSaveMgr.GetResetTimeFor(mEntry->MapID)) { uint32 timeleft = timeReset - time(NULL); GetPlayer()->SendInstanceResetWarning(mEntry->MapID, timeleft); // greeting at the entrance of the resort raid instance } } allowMount = mInstance->allowMount; } // mount allow check if (!allowMount) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // honorless target if (GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // resummon pet if (GetPlayer()->m_temporaryUnsummonedPetNumber) { Pet* NewPet = new Pet(GetPlayer()); if (!NewPet->LoadPetFromDB(GetPlayer(), 0, GetPlayer()->m_temporaryUnsummonedPetNumber, true)) delete NewPet; GetPlayer()->m_temporaryUnsummonedPetNumber = 0; } //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); }
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recv_data) { DEBUG_LOG( "WORLD: Received CMSG_MOVE_SPLINE_DONE" ); ObjectGuid guid; // used only for proper packet read MovementInfo movementInfo; // used only for proper packet read recv_data >> guid.ReadAsPacked(); recv_data >> movementInfo; recv_data >> Unused<uint32>(); // unk // 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 multi-map taxi path // we need process only (1) uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); if(!curDest) { //movement anticheat code GetPlayer()->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o); GetPlayer()->m_movementInfo = movementInfo; //GetPlayer()->SetUnitMovementFlags(movementInfo.moveFlags); //calc time deltas int32 cClientTimeDelta = 0; if (GetPlayer()->m_anti_LastClientTime !=0) { cClientTimeDelta = movementInfo.GetTime() - GetPlayer()->m_anti_LastClientTime; GetPlayer()->m_anti_DeltaClientTime += cClientTimeDelta; GetPlayer()->m_anti_LastClientTime = movementInfo.GetTime(); } else { GetPlayer()->m_anti_LastClientTime = movementInfo.GetTime(); } uint32 cServerTime = WorldTimer::getMSTime(); uint32 cServerTimeDelta = 0; if (GetPlayer()->m_anti_LastServerTime != 0) { cServerTimeDelta = cServerTime - GetPlayer()->m_anti_LastServerTime; GetPlayer()->m_anti_DeltaServerTime += cServerTimeDelta; GetPlayer()->m_anti_LastServerTime = cServerTime; } else { GetPlayer()->m_anti_LastServerTime = cServerTime; } GetPlayer()->m_anti_JustTeleported = true; //end movement anticheat return; } //movment anticheat uint32 curloc = sObjectMgr.GetNearestTaxiNode(movementInfo.GetPos()->x,movementInfo.GetPos()->y,movementInfo.GetPos()->z, GetPlayer()->GetMapId(),GetPlayer( )->GetTeam()); //end movement anticheat TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); //movement anticheat code GetPlayer()->SetPosition(movementInfo.GetPos()->x, movementInfo.GetPos()->y, movementInfo.GetPos()->z, movementInfo.GetPos()->o); GetPlayer()->m_movementInfo = movementInfo; //GetPlayer()->SetUnitMovementFlags(movementInfo.moveFlags); //calc time deltas int32 cClientTimeDelta = 0; if (GetPlayer()->m_anti_LastClientTime !=0) { cClientTimeDelta = movementInfo.GetTime() - GetPlayer()->m_anti_LastClientTime; GetPlayer()->m_anti_DeltaClientTime += cClientTimeDelta; GetPlayer()->m_anti_LastClientTime = movementInfo.GetTime(); } else { GetPlayer()->m_anti_LastClientTime = movementInfo.GetTime(); } uint32 cServerTime = WorldTimer::getMSTime(); uint32 cServerTimeDelta = 0; if (GetPlayer()->m_anti_LastServerTime != 0) { cServerTimeDelta = cServerTime - GetPlayer()->m_anti_LastServerTime; GetPlayer()->m_anti_DeltaServerTime += cServerTimeDelta; GetPlayer()->m_anti_LastServerTime = cServerTime; } else { GetPlayer()->m_anti_LastServerTime = cServerTime; } //<< end movement anticheat // far teleport case if(curDestNode && curDestNode->map_id != GetPlayer()->GetMapId()) { if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Interrupt(*GetPlayer()); // will reset at map landing flight->SetCurrentNodeAfterTeleport(); TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); GetPlayer()->TeleportTo(curDestNode->map_id,node.x,node.y,node.z,GetPlayer()->GetOrientation()); } return; } uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); if ( destinationnode > 0 ) // if more destinations to go { // current source node for next destination uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (GetPlayer()->isTaxiCheater()) { if(GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); _player->GetSession()->SendPacket( &data ); } } DEBUG_LOG( "WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode ); uint32 mountDisplayId = sObjectMgr.GetTaxiMountDisplayId(sourcenode, GetPlayer()->GetTeam()); uint32 path, cost; sObjectMgr.GetTaxiPath( sourcenode, destinationnode, path, cost); if(path && mountDisplayId) SendDoFlight( mountDisplayId, path, 1 ); // skip start fly node else GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next } else GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node }
void WorldSession::HandleMoveWorldportAckOpcode() { // ignore unexpected far teleports if(!GetPlayer()->IsBeingTeleportedFar()) return; // get the teleport destination WorldLocation &loc = GetPlayer()->GetTeleportDest(); // possible errors in the coordinate validity check if(!MapManager::IsValidMapCoord(loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation)) { sLog.outError("WorldSession::HandleMoveWorldportAckOpcode: player got's teleported far to a not valid location. (map:%u, x:%f, y:%f, z:%f) We log him out and don't save him..", loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z); // stop teleportation else we would try this again in the beginning of WorldSession::LogoutPlayer... GetPlayer()->SetSemaphoreTeleportFar(false); // player don't gets saved - so his coords will stay at the point where // he was last saved LogoutPlayer(false); return; } // get the destination map entry, not the current one, this will fix homebind and reset greeting MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid); InstanceTemplate const* mInstance = ObjectMgr::GetInstanceTemplate(loc.mapid); // reset instance validity, except if going to an instance inside an instance if(GetPlayer()->m_InstanceValid == false && !mInstance) GetPlayer()->m_InstanceValid = true; GetPlayer()->SetSemaphoreTeleportFar(false); // relocate the player to the teleport destination GetPlayer()->SetMap(MapManager::Instance().CreateMap(loc.mapid, GetPlayer())); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); // check this before Map::Add(player), because that will create the instance save! bool reset_notify = (GetPlayer()->GetBoundInstance(GetPlayer()->GetMapId()) == NULL); GetPlayer()->SendInitialPacketsBeforeAddToMap(); // the CanEnter checks are done in TeleporTo but conditions may change // while the player is in transit, for example the map may get full if(!GetPlayer()->GetMap()->Add(GetPlayer())) { //if player wasn't added to map, reset his map pointer! GetPlayer()->ResetMap(); DEBUG_LOG("WORLD: teleport of player %s (%d) to location %d, %f, %f, %f, %f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); // teleport the player home GetPlayer()->TeleportToHomebind(); return; } GetPlayer()->SendInitialPacketsAfterAddToMap(); // flight fast teleport case if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { if(!_player->InBattleGround()) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->Reset(*GetPlayer()); return; } // battleground state prepare, stop flight GetPlayer()->GetMotionMaster()->MovementExpired(); GetPlayer()->m_taxi.ClearTaxiDestinations(); } // resurrect character at enter into instance where his corpse exist after add to map Corpse *corpse = GetPlayer()->GetCorpse(); if (corpse && corpse->GetType() != CORPSE_BONES && corpse->GetMapId() == GetPlayer()->GetMapId()) { if( mEntry->IsDungeon() ) { GetPlayer()->ResurrectPlayer(0.5f); GetPlayer()->SpawnCorpseBones(); } } if(mEntry->IsRaid() && mInstance) { if(reset_notify) { uint32 timeleft = sInstanceSaveMgr.GetResetTimeFor(GetPlayer()->GetMapId()) - time(NULL); GetPlayer()->SendInstanceResetWarning(GetPlayer()->GetMapId(), timeleft); // greeting at the entrance of the resort raid instance } } // mount allow check if(!mEntry->IsMountAllowed()) _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // battleground state prepare // only add to bg group and object, if the player was invited (else he entered through command) if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) { BattleGround *bg = _player->GetBattleGround(); if(bg) { bg->AddPlayer(_player); if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg { // get the team this way, because arenas might 'override' the teams. uint32 team = bg->GetPlayerTeam(_player->GetGUID()); if(!team) team = _player->GetTeam(); if(!bg->GetBgRaid(team)) // first player joined { Group *group = new Group; bg->SetBgRaid(team, group); group->Create(_player->GetGUIDLow(), _player->GetName()); } else // raid already exist { bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName()); } } } } // honorless target if(GetPlayer()->pvpInfo.inHostileArea) GetPlayer()->CastSpell(GetPlayer(), 2479, true); // resummon pet GetPlayer()->ResummonPetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport GetPlayer()->ProcessDelayedOperations(); }
void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& /*recv_data*/) { sLog.outDebug( "WORLD: Received CMSG_MOVE_SPLINE_DONE" ); // 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 proccess only (1) uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); if(!curDest) return; TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case if(curDestNode && curDestNode->map_id != GetPlayer()->GetMapId()) { if(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator*)(GetPlayer()->GetMotionMaster()->top()); flight->SetCurrentNodeAfterTeleport(); Path::PathNode const& node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); GetPlayer()->TeleportTo(curDestNode->map_id,node.x,node.y,node.z,GetPlayer()->GetOrientation()); } return; } uint32 destinationnode = GetPlayer()->m_taxi.NextTaxiDestination(); if ( destinationnode > 0 ) // if more destinations to go { // current source node for next destination uint32 sourcenode = GetPlayer()->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (GetPlayer()->isTaxiCheater()) { if(GetPlayer()->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); _player->GetSession()->SendPacket( &data ); } } sLog.outDebug( "WORLD: Taxi has to go from %u to %u", sourcenode, destinationnode ); uint16 MountId = objmgr.GetTaxiMount(sourcenode, GetPlayer()->GetTeam()); uint32 path, cost; objmgr.GetTaxiPath( sourcenode, destinationnode, path, cost); if(path && MountId) SendDoFlight( MountId, path, 1 ); // skip start fly node else GetPlayer()->m_taxi.ClearTaxiDestinations(); // clear problematic path and next } else GetPlayer()->m_taxi.ClearTaxiDestinations(); // not destinations, clear source node }