mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 21:56:22 +00:00
feat(Core/Pets): Management refactoring (#9712)
* feat(Core/Pets): rework managment * 1 * 2 * 3 * 4 * 5 * cs pet * check before ressurect * pet DECLINED_NAMES * display - https://github.com/azerothcore/azerothcore-wotlk/issues/9297 * ArenaSpectator * 1
This commit is contained in:
@@ -488,74 +488,61 @@ void WorldSession::HandleListStabledPetsOpcode(WorldPacket& recvData)
|
||||
|
||||
void WorldSession::SendStablePet(ObjectGuid guid)
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOTS_DETAIL);
|
||||
|
||||
stmt->setUInt32(0, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
|
||||
stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
|
||||
|
||||
_queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::SendStablePetCallback, this, guid, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void WorldSession::SendStablePetCallback(ObjectGuid guid, PreparedQueryResult result)
|
||||
{
|
||||
if (!GetPlayer())
|
||||
return;
|
||||
|
||||
LOG_DEBUG("network", "WORLD: Recv MSG_LIST_STABLED_PETS Send.");
|
||||
|
||||
WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size
|
||||
data << guid;
|
||||
size_t wpos = data.wpos();
|
||||
data << uint8(0); // place holder for slot show number
|
||||
data << uint8(GetPlayer()->m_stableSlots);
|
||||
|
||||
Pet* pet = _player->GetPet();
|
||||
PetStable* petStable = GetPlayer()->GetPetStable();
|
||||
if (!petStable)
|
||||
{
|
||||
data << uint8(0); // stable slots
|
||||
SendPacket(&data);
|
||||
return;
|
||||
}
|
||||
|
||||
data << uint8(petStable->MaxStabledPets);
|
||||
|
||||
uint8 num = 0; // counter for place holder
|
||||
|
||||
// not let move dead pet in slot
|
||||
if (pet && pet->IsAlive() && pet->getPetType() == HUNTER_PET)
|
||||
if (petStable->CurrentPet)
|
||||
{
|
||||
data << uint32(pet->GetCharmInfo()->GetPetNumber());
|
||||
data << uint32(pet->GetEntry());
|
||||
data << uint32(pet->getLevel());
|
||||
data << pet->GetName(); // petname
|
||||
data << uint8(1); // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show)
|
||||
PetStable::PetInfo const& pet = *petStable->CurrentPet;
|
||||
data << uint32(pet.PetNumber);
|
||||
data << uint32(pet.CreatureId);
|
||||
data << uint32(pet.Level);
|
||||
data << pet.Name; // petname
|
||||
data << uint8(1); // flags: 1 active, 2 inactive
|
||||
++num;
|
||||
}
|
||||
else if (_player->IsPetDismissed() || _player->GetTemporaryUnsummonedPetNumber())
|
||||
else
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT_SYNS);
|
||||
stmt->setUInt32(0, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt8(1, uint8(_player->GetTemporaryUnsummonedPetNumber() ? PET_SAVE_AS_CURRENT : PET_SAVE_NOT_IN_SLOT));
|
||||
|
||||
if (PreparedQueryResult _result = CharacterDatabase.Query(stmt))
|
||||
if (PetStable::PetInfo const* pet = petStable->GetUnslottedHunterPet())
|
||||
{
|
||||
Field* fields = _result->Fetch();
|
||||
|
||||
data << uint32(fields[0].GetUInt32()); // id
|
||||
data << uint32(fields[1].GetUInt32()); // entry
|
||||
data << uint32(fields[4].GetUInt16()); // level
|
||||
data << fields[8].GetString(); // petname
|
||||
data << uint8(1);
|
||||
data << uint32(pet->PetNumber);
|
||||
data << uint32(pet->CreatureId);
|
||||
data << uint32(pet->Level);
|
||||
data << pet->Name; // petname
|
||||
data << uint8(1); // flags: 1 active, 2 inactive
|
||||
++num;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
for (Optional<PetStable::PetInfo> const& stabledSlot : petStable->StabledPets)
|
||||
{
|
||||
do
|
||||
if (stabledSlot)
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
data << uint32(fields[1].GetUInt32()); // petnumber
|
||||
data << uint32(fields[2].GetUInt32()); // creature entry
|
||||
data << uint32(fields[3].GetUInt16()); // level
|
||||
data << fields[4].GetString(); // name
|
||||
data << uint8(2); // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show)
|
||||
|
||||
PetStable::PetInfo const& pet = *stabledSlot;
|
||||
data << uint32(pet.PetNumber);
|
||||
data << uint32(pet.CreatureId);
|
||||
data << uint32(pet.Level);
|
||||
data << pet.Name; // petname
|
||||
data << uint8(2); // flags: 1 active, 2 inactive
|
||||
++num;
|
||||
} while (result->NextRow());
|
||||
}
|
||||
}
|
||||
|
||||
data.put<uint8>(wpos, num); // set real data to placeholder
|
||||
@@ -592,81 +579,49 @@ void WorldSession::HandleStablePet(WorldPacket& recvData)
|
||||
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
|
||||
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
|
||||
|
||||
PetStable* petStable = GetPlayer()->GetPetStable();
|
||||
if (!petStable)
|
||||
return;
|
||||
|
||||
Pet* pet = _player->GetPet();
|
||||
|
||||
// can't place in stable dead pet
|
||||
if (pet)
|
||||
if ((pet && (!pet->IsAlive() || pet->getPetType() != HUNTER_PET))
|
||||
|| (!pet && (petStable->UnslottedPets.size() != 1 || !petStable->UnslottedPets[0].Health || petStable->UnslottedPets[0].Type != HUNTER_PET)))
|
||||
{
|
||||
if (!pet->IsAlive() || pet->getPetType() != HUNTER_PET)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SpellCastResult loadResult = Pet::TryLoadFromDB(_player, _player->GetTemporaryUnsummonedPetNumber() != 0, HUNTER_PET);
|
||||
if (loadResult != SPELL_CAST_OK)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOTS);
|
||||
|
||||
stmt->setUInt32(0, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
|
||||
stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
|
||||
|
||||
_queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStablePetCallback, this, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void WorldSession::HandleStablePetCallback(PreparedQueryResult result)
|
||||
{
|
||||
if (!GetPlayer())
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
|
||||
uint8 freeSlot = 1;
|
||||
if (result)
|
||||
{
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint8 slot = fields[1].GetUInt8();
|
||||
|
||||
// slots ordered in query, and if not equal then free
|
||||
if (slot != freeSlot)
|
||||
break;
|
||||
|
||||
// this slot not free, skip
|
||||
++freeSlot;
|
||||
} while (result->NextRow());
|
||||
}
|
||||
|
||||
WorldPacket data(SMSG_STABLE_RESULT, 1);
|
||||
if (freeSlot > 0 && freeSlot <= GetPlayer()->m_stableSlots)
|
||||
for (uint32 freeSlot = 0; freeSlot < petStable->MaxStabledPets; ++freeSlot)
|
||||
{
|
||||
if (_player->GetPetGUID())
|
||||
if (!petStable->StabledPets[freeSlot])
|
||||
{
|
||||
_player->RemovePet(_player->GetPet(), PetSaveMode(freeSlot));
|
||||
if (pet)
|
||||
{
|
||||
// stable summoned pet
|
||||
_player->RemovePet(pet, PetSaveMode(PET_SAVE_FIRST_STABLE_SLOT + freeSlot));
|
||||
std::swap(petStable->StabledPets[freeSlot], petStable->CurrentPet);
|
||||
SendStableResult(STABLE_SUCCESS_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt->setUInt8(0, PetSaveMode(PET_SAVE_FIRST_STABLE_SLOT + freeSlot));
|
||||
stmt->setUInt32(1, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt32(2, petStable->UnslottedPets[0].PetNumber);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
// stable unsummoned pet
|
||||
petStable->StabledPets[freeSlot] = std::move(petStable->UnslottedPets.back());
|
||||
petStable->UnslottedPets.pop_back();
|
||||
SendStableResult(STABLE_SUCCESS_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT);
|
||||
stmt->setUInt8(0, freeSlot);
|
||||
stmt->setUInt32(1, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt8(2, uint8(_player->GetTemporaryUnsummonedPetNumber() ? PET_SAVE_AS_CURRENT : PET_SAVE_NOT_IN_SLOT));
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
_player->SetTemporaryUnsummonedPetNumber(0);
|
||||
SendStableResult(STABLE_SUCCESS_STABLE);
|
||||
return;
|
||||
}
|
||||
else
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
|
||||
// not free stable slot
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
}
|
||||
|
||||
void WorldSession::HandleUnstablePet(WorldPacket& recvData)
|
||||
@@ -687,37 +642,25 @@ void WorldSession::HandleUnstablePet(WorldPacket& recvData)
|
||||
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
|
||||
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_ENTRY);
|
||||
|
||||
stmt->setUInt32(0, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt32(1, petnumber);
|
||||
stmt->setUInt8(2, PET_SAVE_FIRST_STABLE_SLOT);
|
||||
stmt->setUInt8(3, PET_SAVE_LAST_STABLE_SLOT);
|
||||
|
||||
_queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleUnstablePetCallback, this, petnumber, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void WorldSession::HandleUnstablePetCallback(uint32 petId, PreparedQueryResult result)
|
||||
{
|
||||
if (!GetPlayer())
|
||||
return;
|
||||
|
||||
uint32 petEntry = 0;
|
||||
uint32 slot = 0;
|
||||
if (result)
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
petEntry = fields[0].GetUInt32();
|
||||
slot = fields[1].GetUInt32();
|
||||
}
|
||||
|
||||
if (!petEntry)
|
||||
PetStable* petStable = GetPlayer()->GetPetStable();
|
||||
if (!petStable)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry);
|
||||
auto stabledPet = std::find_if(petStable->StabledPets.begin(), petStable->StabledPets.end(), [petnumber](Optional<PetStable::PetInfo> const& pet)
|
||||
{
|
||||
return pet && pet->PetNumber == petnumber;
|
||||
});
|
||||
|
||||
if (stabledPet == petStable->StabledPets.end())
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate((*stabledPet)->CreatureId);
|
||||
if (!creatureInfo || !creatureInfo->IsTameable(_player->CanTameExoticPets()))
|
||||
{
|
||||
// if problem in exotic pet
|
||||
@@ -725,45 +668,74 @@ void WorldSession::HandleUnstablePetCallback(uint32 petId, PreparedQueryResult r
|
||||
SendStableResult(STABLE_ERR_EXOTIC);
|
||||
else
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Pet* pet = _player->GetPet();
|
||||
if (pet && pet->IsAlive())
|
||||
Pet* oldPet = _player->GetPet();
|
||||
if (oldPet)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
// delete dead pet
|
||||
if (pet)
|
||||
{
|
||||
_player->RemovePet(pet, PET_SAVE_AS_DELETED);
|
||||
}
|
||||
else if (_player->IsPetDismissed() || _player->GetTemporaryUnsummonedPetNumber())
|
||||
{
|
||||
// try to find if pet is actually temporary unsummoned and alive
|
||||
SpellCastResult loadResult = Pet::TryLoadFromDB(_player, _player->GetTemporaryUnsummonedPetNumber() != 0, HUNTER_PET);
|
||||
if (loadResult != SPELL_CAST_OK)
|
||||
// try performing a swap, client sends this packet instead of swap when starting from stabled slot
|
||||
if (!oldPet->IsAlive() || !oldPet->IsHunterPet())
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT);
|
||||
stmt->setUInt8(0, slot);
|
||||
_player->RemovePet(oldPet, PetSaveMode(PET_SAVE_FIRST_STABLE_SLOT + std::distance(petStable->StabledPets.begin(), stabledPet)));
|
||||
}
|
||||
else if (petStable->UnslottedPets.size() == 1)
|
||||
{
|
||||
if (petStable->CurrentPet || !petStable->UnslottedPets[0].Health || petStable->UnslottedPets[0].Type != HUNTER_PET)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt->setUInt8(0, PetSaveMode(PET_SAVE_FIRST_STABLE_SLOT + std::distance(petStable->StabledPets.begin(), stabledPet)));
|
||||
stmt->setUInt32(1, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt8(2, uint8(_player->GetTemporaryUnsummonedPetNumber() ? PET_SAVE_AS_CURRENT : PET_SAVE_NOT_IN_SLOT));
|
||||
stmt->setUInt32(2, petStable->UnslottedPets[0].PetNumber);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
_player->SetTemporaryUnsummonedPetNumber(0);
|
||||
// move unsummoned pet into CurrentPet slot so that it gets moved into stable slot later
|
||||
petStable->CurrentPet = std::move(petStable->UnslottedPets.back());
|
||||
petStable->UnslottedPets.pop_back();
|
||||
}
|
||||
|
||||
if (!Pet::LoadPetFromDB(_player, PET_LOAD_HANDLE_UNSTABLE_CALLBACK, petEntry, petId))
|
||||
else if (petStable->CurrentPet || !petStable->UnslottedPets.empty())
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
Pet* newPet = new Pet(_player, HUNTER_PET);
|
||||
if (!newPet->LoadPetFromDB(_player, 0, petnumber, false))
|
||||
{
|
||||
delete newPet;
|
||||
|
||||
petStable->UnslottedPets.push_back(std::move(*petStable->CurrentPet));
|
||||
petStable->CurrentPet.reset();
|
||||
|
||||
// update current pet slot in db immediately to maintain slot consistency, dismissed pet was already saved
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt->setUInt8(0, PET_SAVE_NOT_IN_SLOT);
|
||||
stmt->setUInt32(1, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt32(2, petnumber);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// update current pet slot in db immediately to maintain slot consistency, dismissed pet was already saved
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
|
||||
stmt->setUInt32(1, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt32(2, petnumber);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
SendStableResult(STABLE_SUCCESS_UNSTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleBuyStableSlot(WorldPacket& recvData)
|
||||
@@ -783,12 +755,13 @@ void WorldSession::HandleBuyStableSlot(WorldPacket& recvData)
|
||||
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
|
||||
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
|
||||
|
||||
if (GetPlayer()->m_stableSlots < MAX_PET_STABLES)
|
||||
PetStable& petStable = GetPlayer()->GetOrInitPetStable();
|
||||
if (petStable.MaxStabledPets < MAX_PET_STABLES)
|
||||
{
|
||||
StableSlotPricesEntry const* SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots + 1);
|
||||
StableSlotPricesEntry const* SlotPrice = sStableSlotPricesStore.LookupEntry(petStable.MaxStabledPets + 1);
|
||||
if (_player->HasEnoughMoney(SlotPrice->Price))
|
||||
{
|
||||
++GetPlayer()->m_stableSlots;
|
||||
++petStable.MaxStabledPets;
|
||||
_player->ModifyMoney(-int32(SlotPrice->Price));
|
||||
SendStableResult(STABLE_SUCCESS_BUY_SLOT);
|
||||
}
|
||||
@@ -822,58 +795,26 @@ void WorldSession::HandleStableSwapPet(WorldPacket& recvData)
|
||||
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
|
||||
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
|
||||
|
||||
Pet* pet = _player->GetPet();
|
||||
|
||||
if (pet)
|
||||
PetStable* petStable = GetPlayer()->GetPetStable();
|
||||
if (!petStable)
|
||||
{
|
||||
if (pet->getPetType() != HUNTER_PET)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (_player->IsPetDismissed() || _player->GetTemporaryUnsummonedPetNumber())
|
||||
{
|
||||
// try to find if pet is actually temporary unsummoned and alive
|
||||
SpellCastResult loadResult = Pet::TryLoadFromDB(_player, _player->GetTemporaryUnsummonedPetNumber() != 0, HUNTER_PET);
|
||||
if (loadResult != SPELL_CAST_OK)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find swapped pet slot in stable
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SLOT_BY_ID);
|
||||
auto stabledPet = std::find_if(petStable->StabledPets.begin(), petStable->StabledPets.end(), [petId](Optional<PetStable::PetInfo> const& pet)
|
||||
{
|
||||
return pet && pet->PetNumber == petId;
|
||||
});
|
||||
|
||||
stmt->setUInt32(0, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt32(1, petId);
|
||||
|
||||
_queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStableSwapPetCallback, this, petId, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
void WorldSession::HandleStableSwapPetCallback(uint32 petId, PreparedQueryResult result)
|
||||
{
|
||||
if (!GetPlayer())
|
||||
return;
|
||||
|
||||
if (!result)
|
||||
if (stabledPet == petStable->StabledPets.end())
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
Field* fields = result->Fetch();
|
||||
uint32 slot = fields[0].GetUInt8();
|
||||
uint32 petEntry = fields[1].GetUInt32();
|
||||
|
||||
if (!petEntry)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petEntry);
|
||||
CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate((*stabledPet)->CreatureId);
|
||||
if (!creatureInfo || !creatureInfo->IsTameable(_player->CanTameExoticPets()))
|
||||
{
|
||||
// if problem in exotic pet
|
||||
@@ -884,29 +825,69 @@ void WorldSession::HandleStableSwapPetCallback(uint32 petId, PreparedQueryResult
|
||||
return;
|
||||
}
|
||||
|
||||
Pet* pet = _player->GetPet();
|
||||
|
||||
// move alive pet to slot or delete dead pet
|
||||
if (pet)
|
||||
_player->RemovePet(pet, pet->IsAlive() ? PetSaveMode(slot) : PET_SAVE_AS_DELETED);
|
||||
else if (_player->IsPetDismissed() || _player->GetTemporaryUnsummonedPetNumber())
|
||||
Pet* oldPet = _player->GetPet();
|
||||
if (oldPet)
|
||||
{
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT);
|
||||
stmt->setUInt8(0, slot);
|
||||
if (!oldPet->IsAlive() || !oldPet->IsHunterPet())
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
_player->RemovePet(oldPet, PetSaveMode(PET_SAVE_FIRST_STABLE_SLOT + std::distance(petStable->StabledPets.begin(), stabledPet)));
|
||||
}
|
||||
else if (petStable->UnslottedPets.size() == 1)
|
||||
{
|
||||
if (petStable->CurrentPet || !petStable->UnslottedPets[0].Health || petStable->UnslottedPets[0].Type != HUNTER_PET)
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt->setUInt8(0, PetSaveMode(PET_SAVE_FIRST_STABLE_SLOT + std::distance(petStable->StabledPets.begin(), stabledPet)));
|
||||
stmt->setUInt32(1, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt8(2, uint8(_player->GetTemporaryUnsummonedPetNumber() ? PET_SAVE_AS_CURRENT : PET_SAVE_NOT_IN_SLOT));
|
||||
stmt->setUInt32(2, petStable->UnslottedPets[0].PetNumber);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
_player->SetTemporaryUnsummonedPetNumber(0);
|
||||
// move unsummoned pet into CurrentPet slot so that it gets moved into stable slot later
|
||||
petStable->CurrentPet = std::move(petStable->UnslottedPets.back());
|
||||
petStable->UnslottedPets.pop_back();
|
||||
}
|
||||
else if (petStable->CurrentPet || !petStable->UnslottedPets.empty())
|
||||
{
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
// summon unstabled pet
|
||||
if (!Pet::LoadPetFromDB(_player, PET_LOAD_HANDLE_UNSTABLE_CALLBACK, petEntry, petId))
|
||||
Pet* newPet = new Pet(_player, HUNTER_PET);
|
||||
if (!newPet->LoadPetFromDB(_player, 0, petId, false))
|
||||
{
|
||||
delete newPet;
|
||||
SendStableResult(STABLE_ERR_STABLE);
|
||||
|
||||
petStable->UnslottedPets.push_back(std::move(*petStable->CurrentPet));
|
||||
petStable->CurrentPet.reset();
|
||||
|
||||
// update current pet slot in db immediately to maintain slot consistency, dismissed pet was already saved
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt->setUInt8(0, PET_SAVE_NOT_IN_SLOT);
|
||||
stmt->setUInt32(1, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt32(2, petId);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// update current pet slot in db immediately to maintain slot consistency, dismissed pet was already saved
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID);
|
||||
stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
|
||||
stmt->setUInt32(1, _player->GetGUID().GetCounter());
|
||||
stmt->setUInt32(2, petId);
|
||||
CharacterDatabase.Execute(stmt);
|
||||
|
||||
SendStableResult(STABLE_SUCCESS_UNSTABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleRepairItemOpcode(WorldPacket& recvData)
|
||||
|
||||
Reference in New Issue
Block a user