diff options
Diffstat (limited to 'src/game/NPCHandler.cpp')
-rw-r--r-- | src/game/NPCHandler.cpp | 271 |
1 files changed, 162 insertions, 109 deletions
diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index df027a48acd..c60d368659a 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.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 @@ -25,17 +25,14 @@ #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" @@ -48,7 +45,7 @@ void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TABARDDESIGNER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -57,7 +54,7 @@ void WorldSession::HandleTabardVendorActivateOpcode( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); SendTabardVendorActivate(guid); } @@ -79,7 +76,7 @@ void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data ) recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_BANKER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -88,7 +85,7 @@ void WorldSession::HandleBankerActivateOpcode( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); SendShowBank(guid); } @@ -120,7 +117,7 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) { sLog.outDebug( "WORLD: SendTrainerList" ); - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_TRAINER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -129,7 +126,7 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // trainer list loaded at check; if(!unit->isCanTrainingOf(_player,true)) @@ -160,34 +157,37 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) // reputation discount float fDiscountMod = _player->GetReputationPriceDiscount(unit); + bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; uint32 count = 0; - for(TrainerSpellList::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) + for(TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) { - TrainerSpell const* tSpell = *itr; + TrainerSpell const* tSpell = &itr->second; - if(!_player->IsSpellFitByClassAndRace(tSpell->spell)) + if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell)) continue; - ++count; - - bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell); - - SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell); + bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell); + SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learnedSpell); uint32 req_spell = spellmgr.GetSpellRequired(tSpell->spell); + TrainerSpellState state = _player->GetTrainerSpellState(tSpell); - data << uint32(tSpell->spell); - data << uint8(_player->GetTrainerSpellState(tSpell)); - data << uint32(floor(tSpell->spellcost * fDiscountMod)); + data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) + data << uint8(state==TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); + 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 && can_learn_primary_prof ? 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 : req_spell); - data << uint32(chain_node && chain_node->prev ? req_spell : 0); + data << uint8(tSpell->reqLevel); + data << uint32(tSpell->reqSkill); + data << uint32(tSpell->reqSkillValue); + //prev + req or req + 0 + data << uint32(!tSpell->IsCastable() && chain_node && chain_node->prev ? chain_node->prev : req_spell); + data << uint32(!tSpell->IsCastable() && chain_node && chain_node->prev ? req_spell : 0); data << uint32(0); + + ++count; } data << strTitle; @@ -206,7 +206,7 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) 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); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -215,7 +215,7 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); if(!unit->isCanTrainingOf(_player,true)) return; @@ -235,12 +235,14 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) return; // apply reputation discount - uint32 nSpellCost = uint32(floor(trainer_spell->spellcost * _player->GetReputationPriceDiscount(unit))); + uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); // check money requirement if(_player->GetMoney() < nSpellCost ) return; + _player->ModifyMoney( -int32(nSpellCost) ); + WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer data << uint64(guid) << uint32(0xB3); SendPacket(&data); @@ -249,13 +251,15 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) 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); + // learn explicitly or cast explicitly + if(trainer_spell->IsCastable ()) + //FIXME: prof. spell entry in trainer list not marked gray until list re-open. + _player->CastSpell(_player,trainer_spell->spell,true); + else + _player->learnSpell(spellId,false); data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); - data << uint64(guid) << uint32(spellId); + data << uint64(guid) << uint32(trainer_spell->spell); SendPacket(&data); } @@ -268,7 +272,7 @@ void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -278,7 +282,7 @@ void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); // remove fake death //if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - // GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + // GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider()) { @@ -327,7 +331,7 @@ void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) sLog.outDebug("string read: %s", code.c_str()); } - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_NONE); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -336,7 +340,7 @@ void WorldSession::HandleGossipHelloOpcode( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); if(!code.empty()) { @@ -360,7 +364,7 @@ void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data ) recv_data >> guid; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_SPIRITHEALER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -369,7 +373,7 @@ void WorldSession::HandleSpiritHealerActivateOpcode( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); SendSpiritResurrect(); } @@ -421,7 +425,7 @@ void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data ) if(!GetPlayer()->isAlive()) return; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID,UNIT_NPC_FLAG_INNKEEPER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -430,25 +434,30 @@ void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); SendBindPoint(unit); } void WorldSession::SendBindPoint(Creature *npc) { + // prevent set homebind to instances in any case + if(sMapStore.LookupEntry(GetPlayer()->GetMapId())->Instanceable()) + return; + uint32 bindspell = 3286; + uint32 zone_id = _player->GetZoneId(); // 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()); + CharacterDatabase.PExecute("UPDATE character_homebind SET map = '%u', zone = '%u', position_x = '%f', position_y = '%f', position_z = '%f' WHERE guid = '%u'", _player->GetMapId(), zone_id, _player->GetPositionX(), _player->GetPositionY(), _player->GetPositionZ(), _player->GetGUIDLow()); _player->m_homebindMapId = _player->GetMapId(); - _player->m_homebindZoneId = _player->GetZoneId(); + _player->m_homebindZoneId = zone_id; _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); + _player->CastSpell(_player, bindspell, true); WorldPacket data( SMSG_TRAINER_BUY_SUCCEEDED, (8+4)); data << npc->GetGUID(); @@ -461,25 +470,24 @@ void WorldSession::SendBindPoint(Creature *npc) data << float(_player->GetPositionY()); data << float(_player->GetPositionZ()); data << uint32(_player->GetMapId()); - data << uint32(_player->GetZoneId()); + data << uint32(zone_id); 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()); + DEBUG_LOG("New Home ZoneId is %u",zone_id); // zone update data.Initialize( SMSG_PLAYERBOUND, 8+4 ); data << uint64(_player->GetGUID()); - data << uint32(_player->GetZoneId()); + data << uint32(zone_id); SendPacket( &data ); _player->PlayerTalkClass->CloseGossip(); } -//Need fix void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); @@ -489,7 +497,7 @@ void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data ) recv_data >> npcGUID; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -498,11 +506,11 @@ void WorldSession::HandleListStabledPetsOpcode( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // remove mounts this fix bug where getting pet from stable while mounted deletes pet. if(GetPlayer()->IsMounted()) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + GetPlayer()->RemoveAurasByType(SPELL_AURA_MOUNTED); SendStablePet(npcGUID); } @@ -516,7 +524,9 @@ void WorldSession::SendStablePet(uint64 guid ) Pet *pet = _player->GetPet(); + size_t wpos = data.wpos(); data << uint8(0); // place holder for slot show number + data << uint8(GetPlayer()->m_stableSlots); uint8 num = 0; // counter for place holder @@ -528,13 +538,13 @@ void WorldSession::SendStablePet(uint64 guid ) 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) + data << uint8(1); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show) ++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()); + // 0 1 2 3 4 + QueryResult* result = CharacterDatabase.PQuery("SELECT owner, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot", + _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); if(result) { @@ -542,12 +552,11 @@ void WorldSession::SendStablePet(uint64 guid ) { 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 + data << uint32(fields[1].GetUInt32()); // petnumber + data << uint32(fields[2].GetUInt32()); // creature entry + data << uint32(fields[3].GetUInt32()); // level + data << fields[4].GetString(); // name + data << uint8(2); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show) ++num; }while( result->NextRow() ); @@ -555,7 +564,7 @@ void WorldSession::SendStablePet(uint64 guid ) delete result; } - data.put<uint8>(8, num); // set real data to placeholder + data.put<uint8>(wpos, num); // set real data to placeholder SendPacket(&data); } @@ -571,7 +580,7 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data ) if(!GetPlayer()->isAlive()) return; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -580,15 +589,14 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(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) { + WorldPacket data(SMSG_STABLE_RESULT, 1); data << uint8(0x06); SendPacket(&data); return; @@ -596,7 +604,8 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data ) 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()); + QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot >= '%u' AND slot <= '%u' ORDER BY slot ", + _player->GetGUIDLow(),PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); if(result) { do @@ -605,12 +614,18 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data ) uint32 slot = fields[1].GetUInt32(); - if(slot==free_slot) // this slot not free - ++free_slot; + // slots ordered in query, and if not equal then free + if(slot!=free_slot) + break; + + // this slot not free, skip + ++free_slot; }while( result->NextRow() ); + + delete result; } - delete result; + WorldPacket data(SMSG_STABLE_RESULT, 1); if( free_slot > 0 && free_slot <= GetPlayer()->m_stableSlots) { _player->RemovePet(pet,PetSaveMode(free_slot)); @@ -632,7 +647,7 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data ) recv_data >> npcGUID >> petnumber; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -641,15 +656,43 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size + uint32 creature_id = 0; + + { + QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot >='%u' AND slot <= '%u'", + _player->GetGUIDLow(),petnumber,PET_SAVE_FIRST_STABLE_SLOT,PET_SAVE_LAST_STABLE_SLOT); + if(result) + { + Field *fields = result->Fetch(); + creature_id = fields[0].GetUInt32(); + delete result; + } + } + + if(!creature_id) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(creature_id); + if(!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets())) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } Pet* pet = _player->GetPet(); if(pet && pet->isAlive()) { - uint8 i = 0x06; - data << uint8(i); + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); SendPacket(&data); return; } @@ -658,27 +701,19 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data ) 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) + Pet *newpet = new Pet(_player, HUNTER_PET); + if(!newpet->LoadPetFromDB(_player,creature_id,petnumber)) { - 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; + delete newpet; + newpet = NULL; + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; } - if(newpet) - data << uint8(0x09); - else - data << uint8(0x06); + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x09); SendPacket(&data); } @@ -691,7 +726,7 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data ) recv_data >> npcGUID; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -700,11 +735,11 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); WorldPacket data(SMSG_STABLE_RESULT, 200); - if(GetPlayer()->m_stableSlots < 2) // max slots amount = 2 + if(GetPlayer()->m_stableSlots < MAX_PET_STABLES) { StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1); if(_player->GetMoney() >= SlotPrice->Price) @@ -737,7 +772,7 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data ) recv_data >> npcGUID >> pet_number; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_STABLEMASTER); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -746,7 +781,7 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); WorldPacket data(SMSG_STABLE_RESULT, 200); // guess size @@ -756,22 +791,40 @@ void WorldSession::HandleStableSwapPet( WorldPacket & recv_data ) 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); + 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(); + uint32 slot = fields[0].GetUInt32(); + uint32 creature_id = fields[1].GetUInt32(); delete result; - // move alive pet to slot or delele dead pet + if(!creature_id) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + CreatureInfo const* creatureInfo = objmgr.GetCreatureTemplate(creature_id); + if(!creatureInfo || !creatureInfo->isTameable(_player->CanTameExoticPets())) + { + WorldPacket data(SMSG_STABLE_RESULT, 1); + data << uint8(0x06); + SendPacket(&data); + return; + } + + // move alive pet to slot or delete 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)) + Pet *newpet = new Pet(_player); + if(!newpet->LoadPetFromDB(_player,creature_id,pet_number)) { delete newpet; data << uint8(0x06); @@ -793,7 +846,7 @@ void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data ) recv_data >> npcGUID >> itemGUID >> guildBank; - Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, npcGUID, UNIT_NPC_FLAG_REPAIR); + Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(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)) ); @@ -802,7 +855,7 @@ void WorldSession::HandleRepairItemOpcode( WorldPacket & recv_data ) // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // reputation discount float discountMod = _player->GetReputationPriceDiscount(unit); |