aboutsummaryrefslogtreecommitdiff
path: root/src/game/NPCHandler.cpp
diff options
context:
space:
mode:
authorNeo2003 <none@none>2008-10-04 06:17:19 -0500
committerNeo2003 <none@none>2008-10-04 06:17:19 -0500
commit5651828bf74edb760d67700942fc65d51c816e0a (patch)
tree1631f319bbc293794109f990beaccfd5b6cee8fe /src/game/NPCHandler.cpp
parentca7a4bf1a78a1ddc6eb21238cc2a1633194a11cc (diff)
[svn] * Added ACE for Linux and Windows (Thanks Derex for Linux part and partial Windows part)
* Updated to 6721 and 676 * Fixed TrinityScript logo * Version updated to 0.2.6721.676 --HG-- branch : trunk rename : 6700-670 => 6721-676
Diffstat (limited to 'src/game/NPCHandler.cpp')
-rw-r--r--src/game/NPCHandler.cpp1658
1 files changed, 826 insertions, 832 deletions
diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp
index 5739f56e328..5d3e9b61aa2 100644
--- a/src/game/NPCHandler.cpp
+++ b/src/game/NPCHandler.cpp
@@ -1,832 +1,826 @@
-/*
- * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "Common.h"
-#include "Language.h"
-#include "Database/DatabaseEnv.h"
-#include "WorldPacket.h"
-#include "WorldSession.h"
-#include "Opcodes.h"
-#include "Log.h"
-#include "World.h"
-#include "ObjectMgr.h"
-#include "SpellMgr.h"
-#include "Player.h"
-#include "GossipDef.h"
-#include "SpellAuras.h"
-#include "UpdateMask.h"
-#include "ScriptCalls.h"
-#include "ObjectAccessor.h"
-#include "Creature.h"
-#include "MapManager.h"
-#include "Pet.h"
-#include "BattleGroundMgr.h"
-#include "BattleGround.h"
-#include "Guild.h"
-
-void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- uint64 guid;
- recv_data >> guid;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TABARDDESIGNER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- SendTabardVendorActivate(guid);
-}
-
-void WorldSession::SendTabardVendorActivate( uint64 guid )
-{
- WorldPacket data( MSG_TABARDVENDOR_ACTIVATE, 8 );
- data << guid;
- SendPacket( &data );
-}
-
-void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- uint64 guid;
-
- sLog.outDebug( "WORLD: Received CMSG_BANKER_ACTIVATE" );
-
- recv_data >> guid;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_BANKER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- SendShowBank(guid);
-}
-
-void WorldSession::SendShowBank( uint64 guid )
-{
- WorldPacket data( SMSG_SHOW_BANK, 8 );
- data << guid;
- SendPacket( &data );
-}
-
-void WorldSession::HandleTrainerListOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- uint64 guid;
-
- recv_data >> guid;
- SendTrainerList( guid );
-}
-
-void WorldSession::SendTrainerList( uint64 guid )
-{
- std::string str = GetMangosString(LANG_NPC_TAINER_HELLO);
- SendTrainerList( guid, str );
-}
-
-void WorldSession::SendTrainerList( uint64 guid,std::string strTitle )
-{
- sLog.outDebug( "WORLD: SendTrainerList" );
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- // Lazy loading at first access
- unit->LoadTrainerSpells();
-
- // trainer list loaded at check;
- if(!unit->isCanTrainingOf(_player,true))
- return;
-
- CreatureInfo const *ci = unit->GetCreatureInfo();
-
- if (!ci)
- {
- sLog.outDebug( "WORLD: SendTrainerList - (%u) NO CREATUREINFO! (GUID: %u)", uint32(GUID_LOPART(guid)), guid );
- return;
- }
-
- Creature::SpellsList const& trainer_spells = unit->GetTrainerSpells();
-
- WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells.size()*38 + strTitle.size()+1);
- data << guid;
- data << uint32(unit->GetTrainerType());
-
- size_t count_pos = data.wpos();
- data << uint32(trainer_spells.size());
-
- // reputation discount
- float fDiscountMod = _player->GetReputationPriceDiscount(unit);
-
- uint32 count = 0;
- for(Creature::SpellsList::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr)
- {
- if(!_player->IsSpellFitByClassAndRace(itr->spell->Id))
- continue;
-
- ++count;
-
- bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(itr->spell->Id);
-
- SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(itr->spell->Id);
-
- data << uint32(itr->spell->Id);
- data << uint8(_player->GetTrainerSpellState(&*itr));
- data << uint32(floor(itr->spellcost * fDiscountMod));
-
- data << uint32(primary_prof_first_rank ? 1 : 0); // primary prof. learn confirmation dialog
- data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
- data << uint8(itr->reqlevel ? itr->reqlevel : itr->spell->spellLevel);
- data << uint32(itr->reqskill);
- data << uint32(itr->reqskillvalue);
- data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
- data << uint32(chain_node && chain_node->prev ? chain_node->req : 0);
- data << uint32(0);
- }
-
- data << strTitle;
-
- data.put<uint32>(count_pos,count);
- SendPacket( &data );
-}
-
-void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8+4);
-
- uint64 guid;
- uint32 spellId = 0;
-
- recv_data >> guid >> spellId;
- sLog.outDebug( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId );
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- // Lazy loading at first access
- unit->LoadTrainerSpells();
-
- if(!unit->isCanTrainingOf(_player,true))
- return;
-
- TrainerSpell const* trainer_spell = NULL;
-
- // check present spell in trainer spell list
- Creature::SpellsList const& trainer_spells = unit->GetTrainerSpells();
- for(Creature::SpellsList::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr)
- {
- if(itr->spell->Id == spellId)
- {
- trainer_spell = &*itr;
- break;
- }
- }
-
- // not found, cheat?
- if(!trainer_spell)
- return;
-
- // can't be learn, cheat? Or double learn with lags...
- if(_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
- return;
-
- // apply reputation discount
- uint32 nSpellCost = uint32(floor(trainer_spell->spellcost * _player->GetReputationPriceDiscount(unit)));
-
- // check money requirement
- if(_player->GetMoney() < nSpellCost )
- return;
-
- WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer
- data << uint64(guid) << uint32(0xB3);
- SendPacket(&data);
-
- data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player
- data << uint64(_player->GetGUID()) << uint32(0x016A);
- SendPacket(&data);
-
- _player->ModifyMoney( -int32(nSpellCost) );
-
- // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
- _player->learnSpell(trainer_spell->spell->Id);
-
- data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
- data << uint64(guid) << uint32(spellId);
- SendPacket(&data);
-}
-
-void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- sLog.outDebug( "WORLD: Received CMSG_GOSSIP_HELLO" );
-
- uint64 guid;
- recv_data >> guid;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
- {
- unit->StopMoving();
- }
-
- // If spiritguide, no need for gossip menu, just put player into resurrect queue
- if (unit->isSpiritGuide())
- {
- BattleGround *bg = _player->GetBattleGround();
- if(bg)
- {
- bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
- sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
- return;
- }
- }
-
- if(!Script->GossipHello( _player, unit ))
- {
- _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
- unit->prepareGossipMenu(_player,0);
- unit->sendPreparedGossip( _player );
- }
-}
-
-void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8+4+4);
-
- sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
-
- uint32 option;
- uint32 unk;
- uint64 guid;
- std::string code = "";
-
- recv_data >> guid >> unk >> option;
-
- if(_player->PlayerTalkClass->GossipOptionCoded( option ))
- {
- // recheck
- CHECK_PACKET_SIZE(recv_data,8+4+1);
- sLog.outBasic("reading string");
- recv_data >> code;
- sLog.outBasic("string read: %s", code.c_str());
- }
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- if(!code.empty())
- {
-
- if(!Script->GossipSelectWithCode( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()) )
- unit->OnGossipSelect( _player, option );
- }
- else
-
- if(!Script->GossipSelect( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option )) )
- unit->OnGossipSelect( _player, option );
-}
-
-void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE");
-
- uint64 guid;
-
- recv_data >> guid;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- SendSpiritResurrect();
-}
-
-void WorldSession::SendSpiritResurrect()
-{
- _player->ResurrectPlayer(0.5f,false, true);
-
- _player->DurabilityLossAll(0.25f,true);
-
- // get corpse nearest graveyard
- WorldSafeLocsEntry const *corpseGrave = NULL;
- Corpse *corpse = _player->GetCorpse();
- if(corpse)
- corpseGrave = objmgr.GetClosestGraveYard(
- corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam() );
-
- // now can spawn bones
- _player->SpawnCorpseBones();
-
- // teleport to nearest from corpse graveyard, if different from nearest to player ghost
- if(corpseGrave)
- {
- WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard(
- _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam() );
-
- if(corpseGrave != ghostGrave)
- _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
- // or update at original position
- else
- ObjectAccessor::UpdateVisibilityForPlayer(_player);
- }
- // or update at original position
- else
- ObjectAccessor::UpdateVisibilityForPlayer(_player);
-
- _player->SaveToDB();
-}
-
-void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- uint64 npcGUID;
- recv_data >> npcGUID;
-
- if(!GetPlayer()->isAlive())
- return;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- SendBindPoint(unit);
-}
-
-void WorldSession::SendBindPoint(Creature *npc)
-{
- uint32 bindspell = 3286;
-
- // update sql homebind
- CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), _player->GetZoneId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow());
- _player->m_homebindMapId = _player->GetMapId();
- _player->m_homebindZoneId = _player->GetZoneId();
- _player->m_homebindX = _player->GetPositionX();
- _player->m_homebindY = _player->GetPositionY();
- _player->m_homebindZ = _player->GetPositionZ();
-
- // send spell for bind 3286 bind magic
- npc->CastSpell(_player, bindspell, true);
-
- WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
- data << npc->GetGUID();
- data << bindspell;
- SendPacket( &data );
-
- // binding
- data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) );
- data << float(_player->GetPositionX());
- data << float(_player->GetPositionY());
- data << float(_player->GetPositionZ());
- data << uint32(_player->GetMapId());
- data << uint32(_player->GetZoneId());
- SendPacket( &data );
-
- DEBUG_LOG("New Home Position X is %f",_player->GetPositionX());
- DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY());
- DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ());
- DEBUG_LOG("New Home MapId is %u",_player->GetMapId());
- DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId());
-
- // zone update
- data.Initialize( SMSG_PLAYERBOUND, 8+4 );
- data << uint64(_player->GetGUID());
- data << uint32(_player->GetZoneId());
- SendPacket( &data );
-
- _player->PlayerTalkClass->CloseGossip();
-}
-
-//Need fix
-void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS");
- uint64 npcGUID;
-
- recv_data >> npcGUID;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- SendStablePet(npcGUID);
-}
-
-void WorldSession::SendStablePet(uint64 guid )
-{
- sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");
-
- WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size
- data << uint64 ( guid );
-
- Pet *pet = _player->GetPet();
-
- data << uint8(0); // place holder for slot show number
- data << uint8(GetPlayer()->m_stableSlots);
-
- uint8 num = 0; // counter for place holder
-
- // not let move dead pet in slot
- if(pet && pet->isAlive() && pet->getPetType()==HUNTER_PET)
- {
- data << uint32(pet->GetCharmInfo()->GetPetNumber());
- data << uint32(pet->GetEntry());
- data << uint32(pet->getLevel());
- data << pet->GetName(); // petname
- data << uint32(pet->GetLoyaltyLevel()); // loyalty
- data << uint8(0x01); // client slot 1 == current pet (0)
- ++num;
- }
-
- // 0 1 2 3 4 5 6
- QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow());
-
- if(result)
- {
- do
- {
- Field *fields = result->Fetch();
-
- data << uint32(fields[2].GetUInt32()); // petnumber
- data << uint32(fields[3].GetUInt32()); // creature entry
- data << uint32(fields[4].GetUInt32()); // level
- data << fields[6].GetString(); // name
- data << uint32(fields[5].GetUInt32()); // loyalty
- data << uint8(fields[1].GetUInt32()+1); // slot
-
- ++num;
- }while( result->NextRow() );
-
- delete result;
- }
-
- data.put<uint8>(8, num); // set real data to placeholder
- SendPacket(&data);
-}
-
-void WorldSession::HandleStablePet( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- sLog.outDebug("WORLD: Recv CMSG_STABLE_PET not dispose.");
- uint64 npcGUID;
-
- recv_data >> npcGUID;
-
- if(!GetPlayer()->isAlive())
- return;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- Pet *pet = _player->GetPet();
-
- WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
-
- // can't place in stable dead pet
- if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET)
- {
- data << uint8(0x06);
- SendPacket(&data);
- return;
- }
-
- uint32 free_slot = 1;
-
- QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3 ORDER BY slot ",_player->GetGUIDLow());
- if(result)
- {
- do
- {
- Field *fields = result->Fetch();
-
- uint32 slot = fields[1].GetUInt32();
-
- if(slot==free_slot) // this slot not free
- ++free_slot;
- }while( result->NextRow() );
- }
- delete result;
-
- if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
- {
- _player->RemovePet(pet,PetSaveMode(free_slot));
- data << uint8(0x08);
- }
- else
- data << uint8(0x06);
-
- SendPacket(&data);
-}
-
-void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8+4);
-
- sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET.");
- uint64 npcGUID;
- uint32 petnumber;
-
- recv_data >> npcGUID >> petnumber;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
-
- Pet* pet = _player->GetPet();
- if(pet && pet->isAlive())
- {
- uint8 i = 0x06;
- data << uint8(i);
- SendPacket(&data);
- return;
- }
-
- // delete dead pet
- if(pet)
- _player->RemovePet(pet,PET_SAVE_AS_DELETED);
-
- Pet *newpet = NULL;
-
- QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber);
- if(result)
- {
- Field *fields = result->Fetch();
- uint32 petentry = fields[0].GetUInt32();
-
- newpet = new Pet(HUNTER_PET);
- if(!newpet->LoadPetFromDB(_player,petentry,petnumber))
- {
- delete newpet;
- newpet = NULL;
- }
- delete result;
- }
-
- if(newpet)
- data << uint8(0x09);
- else
- data << uint8(0x06);
- SendPacket(&data);
-}
-
-void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8);
-
- sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT.");
- uint64 npcGUID;
-
- recv_data >> npcGUID;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- WorldPacket data(SMSG_STABLE_RESULT, 200);
-
- if(GetPlayer()->m_stableSlots < 2) // max slots amount = 2
- {
- StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
- if(_player->GetMoney() >= SlotPrice->Price)
- {
- ++GetPlayer()->m_stableSlots;
- _player->ModifyMoney(-int32(SlotPrice->Price));
- data << uint8(0x0A); // success buy
- }
- else
- data << uint8(0x06);
- }
- else
- data << uint8(0x06);
-
- SendPacket(&data);
-}
-
-void WorldSession::HandleStableRevivePet( WorldPacket &/* recv_data */)
-{
- sLog.outDebug("HandleStableRevivePet: Not implemented");
-}
-
-void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8+4);
-
- sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET.");
- uint64 npcGUID;
- uint32 pet_number;
-
- recv_data >> npcGUID >> pet_number;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
-
- Pet* pet = _player->GetPet();
-
- if(!pet || pet->getPetType()!=HUNTER_PET)
- return;
-
- // find swapped pet slot in stable
- QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number);
- if(!result)
- return;
-
- Field *fields = result->Fetch();
-
- uint32 slot = fields[0].GetUInt32();
- uint32 petentry = fields[1].GetUInt32();
- delete result;
-
- // move alive pet to slot or delele dead pet
- _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
-
- // summon unstabled pet
- Pet *newpet = new Pet;
- if(!newpet->LoadPetFromDB(_player,petentry,pet_number))
- {
- delete newpet;
- data << uint8(0x06);
- }
- else
- data << uint8(0x09);
-
- SendPacket(&data);
-}
-
-void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data )
-{
- CHECK_PACKET_SIZE(recv_data,8+8+1);
-
- sLog.outDebug("WORLD: CMSG_REPAIR_ITEM");
-
- uint64 npcGUID, itemGUID;
- uint8 guildBank; // new in 2.3.2, bool that means from guild bank money
-
- recv_data >> npcGUID >> itemGUID >> guildBank;
-
- Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR);
- if (!unit)
- {
- sLog.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
- return;
- }
-
- // remove fake death
- if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
-
- // reputation discount
- float discountMod = _player->GetReputationPriceDiscount(unit);
-
- uint32 TotalCost = 0;
- if (itemGUID)
- {
- sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID));
-
- Item* item = _player->GetItemByGuid(itemGUID);
-
- if(item)
- TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false);
- }
- else
- {
- sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID));
-
- TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false);
- }
- if (guildBank)
- {
- uint32 GuildId = _player->GetGuildId();
- if (!GuildId)
- return;
- Guild *pGuild = objmgr.GetGuildById(GuildId);
- if (!pGuild)
- return;
- pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost);
- pGuild->SendMoneyInfo(this, _player->GetGUIDLow());
- }
-}
+/*
+ * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "Language.h"
+#include "Database/DatabaseEnv.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+#include "Opcodes.h"
+#include "Log.h"
+#include "World.h"
+#include "ObjectMgr.h"
+#include "SpellMgr.h"
+#include "Player.h"
+#include "GossipDef.h"
+#include "SpellAuras.h"
+#include "UpdateMask.h"
+#include "ScriptCalls.h"
+#include "ObjectAccessor.h"
+#include "Creature.h"
+#include "MapManager.h"
+#include "Pet.h"
+#include "BattleGroundMgr.h"
+#include "BattleGround.h"
+#include "Guild.h"
+
+void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ uint64 guid;
+ recv_data >> guid;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TABARDDESIGNER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleTabardVendorActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ SendTabardVendorActivate(guid);
+}
+
+void WorldSession::SendTabardVendorActivate( uint64 guid )
+{
+ WorldPacket data( MSG_TABARDVENDOR_ACTIVATE, 8 );
+ data << guid;
+ SendPacket( &data );
+}
+
+void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ uint64 guid;
+
+ sLog.outDebug( "WORLD: Received CMSG_BANKER_ACTIVATE" );
+
+ recv_data >> guid;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_BANKER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleBankerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ SendShowBank(guid);
+}
+
+void WorldSession::SendShowBank( uint64 guid )
+{
+ WorldPacket data( SMSG_SHOW_BANK, 8 );
+ data << guid;
+ SendPacket( &data );
+}
+
+void WorldSession::HandleTrainerListOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ uint64 guid;
+
+ recv_data >> guid;
+ SendTrainerList( guid );
+}
+
+void WorldSession::SendTrainerList( uint64 guid )
+{
+ std::string str = GetMangosString(LANG_NPC_TAINER_HELLO);
+ SendTrainerList( guid, str );
+}
+
+void WorldSession::SendTrainerList( uint64 guid,std::string strTitle )
+{
+ sLog.outDebug( "WORLD: SendTrainerList" );
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ // trainer list loaded at check;
+ if(!unit->isCanTrainingOf(_player,true))
+ return;
+
+ CreatureInfo const *ci = unit->GetCreatureInfo();
+
+ if (!ci)
+ {
+ sLog.outDebug( "WORLD: SendTrainerList - (%u) NO CREATUREINFO! (GUID: %u)", uint32(GUID_LOPART(guid)), guid );
+ return;
+ }
+
+ TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
+ if(!trainer_spells)
+ {
+ sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", guid, unit->GetEntry());
+ return;
+ }
+
+ WorldPacket data( SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1);
+ data << guid;
+ data << uint32(trainer_spells->trainerType);
+
+ size_t count_pos = data.wpos();
+ data << uint32(trainer_spells->spellList.size());
+
+ // reputation discount
+ float fDiscountMod = _player->GetReputationPriceDiscount(unit);
+
+ uint32 count = 0;
+ for(TrainerSpellList::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr)
+ {
+ TrainerSpell const* tSpell = *itr;
+
+ if(!_player->IsSpellFitByClassAndRace(tSpell->spell))
+ continue;
+
+ ++count;
+
+ bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell);
+
+ SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell);
+
+ data << uint32(tSpell->spell);
+ data << uint8(_player->GetTrainerSpellState(tSpell));
+ data << uint32(floor(tSpell->spellcost * fDiscountMod));
+
+ data << uint32(primary_prof_first_rank ? 1 : 0); // primary prof. learn confirmation dialog
+ data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
+ data << uint8(tSpell->reqlevel);
+ data << uint32(tSpell->reqskill);
+ data << uint32(tSpell->reqskillvalue);
+ data << uint32(chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
+ data << uint32(chain_node && chain_node->prev ? chain_node->req : 0);
+ data << uint32(0);
+ }
+
+ data << strTitle;
+
+ data.put<uint32>(count_pos,count);
+ SendPacket( &data );
+}
+
+void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8+4);
+
+ uint64 guid;
+ uint32 spellId = 0;
+
+ recv_data >> guid >> spellId;
+ sLog.outDebug( "WORLD: Received CMSG_TRAINER_BUY_SPELL NpcGUID=%u, learn spell id is: %u",uint32(GUID_LOPART(guid)), spellId );
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_TRAINER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleTrainerBuySpellOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ if(!unit->isCanTrainingOf(_player,true))
+ return;
+
+ // check present spell in trainer spell list
+ TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
+ if(!trainer_spells)
+ return;
+
+ // not found, cheat?
+ TrainerSpell const* trainer_spell = trainer_spells->Find(spellId);
+ if(!trainer_spell)
+ return;
+
+ // can't be learn, cheat? Or double learn with lags...
+ if(_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
+ return;
+
+ // apply reputation discount
+ uint32 nSpellCost = uint32(floor(trainer_spell->spellcost * _player->GetReputationPriceDiscount(unit)));
+
+ // check money requirement
+ if(_player->GetMoney() < nSpellCost )
+ return;
+
+ WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer
+ data << uint64(guid) << uint32(0xB3);
+ SendPacket(&data);
+
+ data.Initialize(SMSG_PLAY_SPELL_IMPACT, 12); // visual effect on player
+ data << uint64(_player->GetGUID()) << uint32(0x016A);
+ SendPacket(&data);
+
+ _player->ModifyMoney( -int32(nSpellCost) );
+
+ // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation
+ _player->learnSpell(trainer_spell->spell);
+
+ data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12);
+ data << uint64(guid) << uint32(spellId);
+ SendPacket(&data);
+}
+
+void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ sLog.outDebug( "WORLD: Received CMSG_GOSSIP_HELLO" );
+
+ uint64 guid;
+ recv_data >> guid;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
+ {
+ unit->StopMoving();
+ }
+
+ // If spiritguide, no need for gossip menu, just put player into resurrect queue
+ if (unit->isSpiritGuide())
+ {
+ BattleGround *bg = _player->GetBattleGround();
+ if(bg)
+ {
+ bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID());
+ sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID());
+ return;
+ }
+ }
+
+ if(!Script->GossipHello( _player, unit ))
+ {
+ _player->TalkedToCreature(unit->GetEntry(),unit->GetGUID());
+ unit->prepareGossipMenu(_player,0);
+ unit->sendPreparedGossip( _player );
+ }
+}
+
+void WorldSession::HandleGossipSelectOptionOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8+4+4);
+
+ sLog.outDebug("WORLD: CMSG_GOSSIP_SELECT_OPTION");
+
+ uint32 option;
+ uint32 unk;
+ uint64 guid;
+ std::string code = "";
+
+ recv_data >> guid >> unk >> option;
+
+ if(_player->PlayerTalkClass->GossipOptionCoded( option ))
+ {
+ // recheck
+ CHECK_PACKET_SIZE(recv_data,8+4+1);
+ sLog.outBasic("reading string");
+ recv_data >> code;
+ sLog.outBasic("string read: %s", code.c_str());
+ }
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleGossipSelectOptionOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ if(!code.empty())
+ {
+
+ if(!Script->GossipSelectWithCode( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option ), code.c_str()) )
+ unit->OnGossipSelect( _player, option );
+ }
+ else
+
+ if(!Script->GossipSelect( _player, unit, _player->PlayerTalkClass->GossipOptionSender( option ), _player->PlayerTalkClass->GossipOptionAction( option )) )
+ unit->OnGossipSelect( _player, option );
+}
+
+void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ sLog.outDebug("WORLD: CMSG_SPIRIT_HEALER_ACTIVATE");
+
+ uint64 guid;
+
+ recv_data >> guid;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleSpiritHealerActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ SendSpiritResurrect();
+}
+
+void WorldSession::SendSpiritResurrect()
+{
+ _player->ResurrectPlayer(0.5f,false, true);
+
+ _player->DurabilityLossAll(0.25f,true);
+
+ // get corpse nearest graveyard
+ WorldSafeLocsEntry const *corpseGrave = NULL;
+ Corpse *corpse = _player->GetCorpse();
+ if(corpse)
+ corpseGrave = objmgr.GetClosestGraveYard(
+ corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetMapId(), _player->GetTeam() );
+
+ // now can spawn bones
+ _player->SpawnCorpseBones();
+
+ // teleport to nearest from corpse graveyard, if different from nearest to player ghost
+ if(corpseGrave)
+ {
+ WorldSafeLocsEntry const *ghostGrave = objmgr.GetClosestGraveYard(
+ _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetMapId(), _player->GetTeam() );
+
+ if(corpseGrave != ghostGrave)
+ _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
+ // or update at original position
+ else
+ ObjectAccessor::UpdateVisibilityForPlayer(_player);
+ }
+ // or update at original position
+ else
+ ObjectAccessor::UpdateVisibilityForPlayer(_player);
+
+ _player->SaveToDB();
+}
+
+void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ uint64 npcGUID;
+ recv_data >> npcGUID;
+
+ if(!GetPlayer()->isAlive())
+ return;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleBinderActivateOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ SendBindPoint(unit);
+}
+
+void WorldSession::SendBindPoint(Creature *npc)
+{
+ uint32 bindspell = 3286;
+
+ // update sql homebind
+ CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), _player->GetZoneId(), _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow());
+ _player->m_homebindMapId = _player->GetMapId();
+ _player->m_homebindZoneId = _player->GetZoneId();
+ _player->m_homebindX = _player->GetPositionX();
+ _player->m_homebindY = _player->GetPositionY();
+ _player->m_homebindZ = _player->GetPositionZ();
+
+ // send spell for bind 3286 bind magic
+ npc->CastSpell(_player, bindspell, true);
+
+ WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4));
+ data << npc->GetGUID();
+ data << bindspell;
+ SendPacket( &data );
+
+ // binding
+ data.Initialize( SMSG_BINDPOINTUPDATE, (4+4+4+4+4) );
+ data << float(_player->GetPositionX());
+ data << float(_player->GetPositionY());
+ data << float(_player->GetPositionZ());
+ data << uint32(_player->GetMapId());
+ data << uint32(_player->GetZoneId());
+ SendPacket( &data );
+
+ DEBUG_LOG("New Home Position X is %f",_player->GetPositionX());
+ DEBUG_LOG("New Home Position Y is %f",_player->GetPositionY());
+ DEBUG_LOG("New Home Position Z is %f",_player->GetPositionZ());
+ DEBUG_LOG("New Home MapId is %u",_player->GetMapId());
+ DEBUG_LOG("New Home ZoneId is %u",_player->GetZoneId());
+
+ // zone update
+ data.Initialize( SMSG_PLAYERBOUND, 8+4 );
+ data << uint64(_player->GetGUID());
+ data << uint32(_player->GetZoneId());
+ SendPacket( &data );
+
+ _player->PlayerTalkClass->CloseGossip();
+}
+
+//Need fix
+void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS");
+ uint64 npcGUID;
+
+ recv_data >> npcGUID;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleListStabledPetsOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ SendStablePet(npcGUID);
+}
+
+void WorldSession::SendStablePet(uint64 guid )
+{
+ sLog.outDebug("WORLD: Recv MSG_LIST_STABLED_PETS Send.");
+
+ WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size
+ data << uint64 ( guid );
+
+ Pet *pet = _player->GetPet();
+
+ data << uint8(0); // place holder for slot show number
+ data << uint8(GetPlayer()->m_stableSlots);
+
+ uint8 num = 0; // counter for place holder
+
+ // not let move dead pet in slot
+ if(pet && pet->isAlive() && pet->getPetType()==HUNTER_PET)
+ {
+ data << uint32(pet->GetCharmInfo()->GetPetNumber());
+ data << uint32(pet->GetEntry());
+ data << uint32(pet->getLevel());
+ data << pet->GetName(); // petname
+ data << uint32(pet->GetLoyaltyLevel()); // loyalty
+ data << uint8(0x01); // client slot 1 == current pet (0)
+ ++num;
+ }
+
+ // 0 1 2 3 4 5 6
+ QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow());
+
+ if(result)
+ {
+ do
+ {
+ Field *fields = result->Fetch();
+
+ data << uint32(fields[2].GetUInt32()); // petnumber
+ data << uint32(fields[3].GetUInt32()); // creature entry
+ data << uint32(fields[4].GetUInt32()); // level
+ data << fields[6].GetString(); // name
+ data << uint32(fields[5].GetUInt32()); // loyalty
+ data << uint8(fields[1].GetUInt32()+1); // slot
+
+ ++num;
+ }while( result->NextRow() );
+
+ delete result;
+ }
+
+ data.put<uint8>(8, num); // set real data to placeholder
+ SendPacket(&data);
+}
+
+void WorldSession::HandleStablePet( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ sLog.outDebug("WORLD: Recv CMSG_STABLE_PET not dispose.");
+ uint64 npcGUID;
+
+ recv_data >> npcGUID;
+
+ if(!GetPlayer()->isAlive())
+ return;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleStablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ Pet *pet = _player->GetPet();
+
+ WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
+
+ // can't place in stable dead pet
+ if(!pet||!pet->isAlive()||pet->getPetType()!=HUNTER_PET)
+ {
+ data << uint8(0x06);
+ SendPacket(&data);
+ return;
+ }
+
+ uint32 free_slot = 1;
+
+ QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3 ORDER BY slot ",_player->GetGUIDLow());
+ if(result)
+ {
+ do
+ {
+ Field *fields = result->Fetch();
+
+ uint32 slot = fields[1].GetUInt32();
+
+ if(slot==free_slot) // this slot not free
+ ++free_slot;
+ }while( result->NextRow() );
+ }
+ delete result;
+
+ if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots)
+ {
+ _player->RemovePet(pet,PetSaveMode(free_slot));
+ data << uint8(0x08);
+ }
+ else
+ data << uint8(0x06);
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleUnstablePet( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8+4);
+
+ sLog.outDebug("WORLD: Recv CMSG_UNSTABLE_PET.");
+ uint64 npcGUID;
+ uint32 petnumber;
+
+ recv_data >> npcGUID >> petnumber;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleUnstablePet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
+
+ Pet* pet = _player->GetPet();
+ if(pet && pet->isAlive())
+ {
+ uint8 i = 0x06;
+ data << uint8(i);
+ SendPacket(&data);
+ return;
+ }
+
+ // delete dead pet
+ if(pet)
+ _player->RemovePet(pet,PET_SAVE_AS_DELETED);
+
+ Pet *newpet = NULL;
+
+ QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber);
+ if(result)
+ {
+ Field *fields = result->Fetch();
+ uint32 petentry = fields[0].GetUInt32();
+
+ newpet = new Pet(HUNTER_PET);
+ if(!newpet->LoadPetFromDB(_player,petentry,petnumber))
+ {
+ delete newpet;
+ newpet = NULL;
+ }
+ delete result;
+ }
+
+ if(newpet)
+ data << uint8(0x09);
+ else
+ data << uint8(0x06);
+ SendPacket(&data);
+}
+
+void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ sLog.outDebug("WORLD: Recv CMSG_BUY_STABLE_SLOT.");
+ uint64 npcGUID;
+
+ recv_data >> npcGUID;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleBuyStableSlot - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ WorldPacket data(SMSG_STABLE_RESULT, 200);
+
+ if(GetPlayer()->m_stableSlots < 2) // max slots amount = 2
+ {
+ StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1);
+ if(_player->GetMoney() >= SlotPrice->Price)
+ {
+ ++GetPlayer()->m_stableSlots;
+ _player->ModifyMoney(-int32(SlotPrice->Price));
+ data << uint8(0x0A); // success buy
+ }
+ else
+ data << uint8(0x06);
+ }
+ else
+ data << uint8(0x06);
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleStableRevivePet( WorldPacket &/* recv_data */)
+{
+ sLog.outDebug("HandleStableRevivePet: Not implemented");
+}
+
+void WorldSession::HandleStableSwapPet( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8+4);
+
+ sLog.outDebug("WORLD: Recv CMSG_STABLE_SWAP_PET.");
+ uint64 npcGUID;
+ uint32 pet_number;
+
+ recv_data >> npcGUID >> pet_number;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleStableSwapPet - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size
+
+ Pet* pet = _player->GetPet();
+
+ if(!pet || pet->getPetType()!=HUNTER_PET)
+ return;
+
+ // find swapped pet slot in stable
+ QueryResult *result = CharacterDatabase.PQuery("SELECT slot,entry FROM character_pet WHERE owner = '%u' AND id = '%u'",_player->GetGUIDLow(),pet_number);
+ if(!result)
+ return;
+
+ Field *fields = result->Fetch();
+
+ uint32 slot = fields[0].GetUInt32();
+ uint32 petentry = fields[1].GetUInt32();
+ delete result;
+
+ // move alive pet to slot or delele dead pet
+ _player->RemovePet(pet,pet->isAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
+
+ // summon unstabled pet
+ Pet *newpet = new Pet;
+ if(!newpet->LoadPetFromDB(_player,petentry,pet_number))
+ {
+ delete newpet;
+ data << uint8(0x06);
+ }
+ else
+ data << uint8(0x09);
+
+ SendPacket(&data);
+}
+
+void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8+8+1);
+
+ sLog.outDebug("WORLD: CMSG_REPAIR_ITEM");
+
+ uint64 npcGUID, itemGUID;
+ uint8 guildBank; // new in 2.3.2, bool that means from guild bank money
+
+ recv_data >> npcGUID >> itemGUID >> guildBank;
+
+ Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR);
+ if (!unit)
+ {
+ sLog.outDebug( "WORLD: HandleRepairItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(npcGUID)) );
+ return;
+ }
+
+ // remove fake death
+ if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+
+ // reputation discount
+ float discountMod = _player->GetReputationPriceDiscount(unit);
+
+ uint32 TotalCost = 0;
+ if (itemGUID)
+ {
+ sLog.outDebug("ITEM: Repair item, itemGUID = %u, npcGUID = %u", GUID_LOPART(itemGUID), GUID_LOPART(npcGUID));
+
+ Item* item = _player->GetItemByGuid(itemGUID);
+
+ if(item)
+ TotalCost= _player->DurabilityRepair(item->GetPos(),true,discountMod,guildBank>0?true:false);
+ }
+ else
+ {
+ sLog.outDebug("ITEM: Repair all items, npcGUID = %u", GUID_LOPART(npcGUID));
+
+ TotalCost = _player->DurabilityRepairAll(true,discountMod,guildBank>0?true:false);
+ }
+ if (guildBank)
+ {
+ uint32 GuildId = _player->GetGuildId();
+ if (!GuildId)
+ return;
+ Guild *pGuild = objmgr.GetGuildById(GuildId);
+ if (!pGuild)
+ return;
+ pGuild->LogBankEvent(GUILD_BANK_LOG_REPAIR_MONEY, 0, _player->GetGUIDLow(), TotalCost);
+ pGuild->SendMoneyInfo(this, _player->GetGUIDLow());
+ }
+}