aboutsummaryrefslogtreecommitdiff
path: root/src/game/NPCHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/NPCHandler.cpp')
-rw-r--r--src/game/NPCHandler.cpp271
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);