diff options
| author | Neo2003 <none@none> | 2008-10-04 06:17:19 -0500 |
|---|---|---|
| committer | Neo2003 <none@none> | 2008-10-04 06:17:19 -0500 |
| commit | 5651828bf74edb760d67700942fc65d51c816e0a (patch) | |
| tree | 1631f319bbc293794109f990beaccfd5b6cee8fe /src/game/NPCHandler.cpp | |
| parent | ca7a4bf1a78a1ddc6eb21238cc2a1633194a11cc (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.cpp | 1658 |
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());
+ }
+}
|
