void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) { sLog.outDetail("CMSG_PET_UNLEARN"); uint64 guid; recvPacket >> guid; // Pet guid Pet* pet = _player->GetPet(); if(!pet || pet->getPetType() != HUNTER_PET || pet->m_usedTalentCount == 0) return; if(guid != pet->GetGUID()) { sLog.outError( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) { sLog.outError("WorldSession::HandlePetUnlearnOpcode: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } pet->resetTalents(); _player->SendTalentsInfoData(true); }
void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) { DETAIL_LOG("CMSG_PET_UNLEARN"); ObjectGuid guid; recvPacket >> guid; // Pet guid Pet* pet = _player->GetPet(); if (!pet || guid != pet->GetObjectGuid()) { sLog.outError("HandlePetUnlearnOpcode. %s isn't pet of %s .", guid.GetString().c_str(), GetPlayer()->GetGuidStr().c_str()); return; } if (pet->getPetType() != HUNTER_PET || pet->m_usedTalentCount == 0) return; CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetUnlearnOpcode: %s is considered pet-like but doesn't have a charminfo!", pet->GetGuidStr().c_str()); return; } pet->resetTalents(); _player->SendTalentsInfoData(true); }
void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) { CHECK_PACKET_SIZE(recvPacket,8); sLog.outDetail("CMSG_PET_UNLEARN"); uint64 guid; recvPacket >> guid; Pet* pet = _player->GetPet(); if(!pet || pet->getPetType() != HUNTER_PET || pet->m_spells.size() <= 1) return; if(guid != pet->GetGUID()) { sLog.outError( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s .\n", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) { sLog.outError("WorldSession::HandlePetUnlearnOpcode: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID()); return; } uint32 cost = pet->resetTalentsCost(); if (GetPlayer()->GetMoney() < cost) { GetPlayer()->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); return; } for(PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end();) { uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell ++itr; pet->removeSpell(spell_id); } pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1)); for(uint8 i = 0; i < 10; i++) { if(charmInfo->GetActionBarEntry(i)->SpellOrAction && charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED) charmInfo->GetActionBarEntry(i)->SpellOrAction = 0; } // relearn pet passives pet->LearnPetPassives(); pet->m_resetTalentsTime = time(NULL); pet->m_resetTalentsCost = cost; GetPlayer()->ModifyMoney(-(int32)cost); GetPlayer()->PetSpellInitialize(); }
void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) { DETAIL_LOG("CMSG_PET_UNLEARN"); ObjectGuid guid; recvPacket >> guid; // Pet guid Pet* pet = _player->GetPet(); if (!pet || guid != pet->GetObjectGuid()) { sLog.outError("HandlePetUnlearnOpcode. %s isn't pet of %s .", guid.GetString().c_str(), _player->GetGuidStr().c_str()); return; } if (pet->getPetType() != HUNTER_PET || pet->m_spells.size() <= 1) return; CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetUnlearnOpcode: %s is considered pet-like but doesn't have a charminfo!", pet->GetGuidStr().c_str()); return; } uint32 cost = pet->resetTalentsCost(); if (_player->GetMoney() < cost) { _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); return; } for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end();) { uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell ++itr; pet->unlearnSpell(spell_id, false); } pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1)); for (int i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) if (UnitActionBarEntry const* ab = charmInfo->GetActionBarEntry(i)) if (ab->GetAction() && ab->IsActionBarForSpell()) charmInfo->SetActionBar(i, 0, ACT_DISABLED); // relearn pet passives pet->LearnPetPassives(); pet->m_resetTalentsTime = time(nullptr); pet->m_resetTalentsCost = cost; _player->ModifyMoney(-(int32)cost); _player->PetSpellInitialize(); }
void WorldSession::SendStablePetCallback(PreparedQueryResult result, uint64 guid) { if (!GetPlayer()) return; TC_LOG_DEBUG("network", "WORLD: Recv MSG_LIST_STABLED_PETS Send."); WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size data << 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 // not let move dead pet in slot if (pet && pet->IsAlive() && pet->getPetType() == HUNTER_PET) { data << uint32(num); // 4.x unknown, some kind of order? 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) ++num; } if (result) { do { Field* fields = result->Fetch(); data << uint32(num); 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) ++num; } while (result->NextRow()); } data.put<uint8>(wpos, num); // set real data to placeholder SendPacket(&data); SendStableResult(STABLE_ERR_NONE); }
void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) { sLog.outDetail("CMSG_PET_UNLEARN"); uint64 guid; recvPacket >> guid; Pet* pet = _player->GetPet(); if(!pet || pet->getPetType() != HUNTER_PET || pet->m_spells.size() <= 1) return; if(guid != pet->GetGUID()) { sLog.outError( "HandlePetUnlearnOpcode.Pet %u isn't pet of player %s .", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); return; } CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) { sLog.outError("WorldSession::HandlePetUnlearnOpcode: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } uint32 cost = pet->resetTalentsCost(); if (GetPlayer()->GetMoney() < cost) { GetPlayer()->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); return; } for(PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end();) { uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell ++itr; pet->unlearnSpell(spell_id,false); } pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1)); for(int i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i) if(UnitActionBarEntry const* ab = charmInfo->GetActionBarEntry(i)) if(ab->GetAction() && ab->IsActionBarForSpell()) charmInfo->SetActionBar(i,0,ACT_DISABLED); // relearn pet passives pet->LearnPetPassives(); pet->m_resetTalentsTime = time(NULL); pet->m_resetTalentsCost = cost; GetPlayer()->ModifyMoney(-(int32)cost); GetPlayer()->PetSpellInitialize(); }
void WorldSession::HandleStableSwapPet(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_STABLE_SWAP_PET."); uint64 npcGUID; uint32 pet_number; uint8 new_slot; recv_data >> new_slot >> pet_number >> npcGUID; if (!CheckStableMaster(npcGUID)) { SendStableResult(STABLE_ERR_STABLE); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Pet* pet = _player->GetPet(); /* if (!pet || pet->getPetType() != HUNTER_PET) { SendStableResult(STABLE_ERR_STABLE); return; } */ //If we move the pet already summoned... if (pet && pet->GetCharmInfo() && pet->GetCharmInfo()->GetPetNumber() == pet_number) _player->RemovePet(pet, PET_SLOT_ACTUAL_PET_SLOT); //If we move to the pet already summoned... if (pet && GetPlayer()->_currentPetSlot == new_slot) _player->RemovePet(pet, PET_SLOT_ACTUAL_PET_SLOT); // find swapped pet slot in stable _stableSwapCallback.SetParam(new_slot); _stableSwapCallback.SetFutureResult( CharacterDatabase.AsyncPQuery("SELECT slot, entry, id FROM character_pet WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet_number) ); }
void WorldSession::HandleStableChangeSlot(WorldPacket & recv_data) { sLog->outDebug("WORLD: Recv CMSG_STABLE_CHANGE_SLOT."); uint32 pet_number; uint64 npcGUID; uint8 new_slot; recv_data >> pet_number >> npcGUID >> new_slot; if (!CheckStableMaster(npcGUID)) { SendStableResult(STABLE_ERR_STABLE); return; } if(new_slot > MAX_PET_STABLES) { SendStableResult(STABLE_ERR_STABLE); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Pet* pet = _player->GetPet(); //If we move the pet already summoned... if(pet && pet->GetCharmInfo() && pet->GetCharmInfo()->GetPetNumber() == pet_number) _player->RemovePet(pet, PET_SLOT_ACTUAL_PET_SLOT); //If we move to the pet already summoned... if(pet && GetPlayer()->m_currentPetSlot == new_slot) _player->RemovePet(pet, PET_SLOT_ACTUAL_PET_SLOT); m_stableChangeSlotCallback.SetParam(new_slot); m_stableChangeSlotCallback.SetFutureResult( CharacterDatabase.PQuery("SELECT slot,entry,id FROM character_pet WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet_number) ); }
void WorldSession::SendStablePetCallback(QueryResult result, uint64 guid) { if (!GetPlayer()) return; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv MSG_LIST_STABLED_PETS Send."); WorldPacket data(MSG_LIST_STABLED_PETS, 200); // guess size data << uint64 (guid); Pet* pet = _player->GetPet(); size_t wpos = data.wpos(); data << uint8(0); // place holder for slot show number data << uint8(GetPlayer()->_petSlotUsed); uint8 num = 0; // counter for place holder // not let move dead pet in slot if (pet && pet->isAlive() && pet->getPetType() == HUNTER_PET) { data << uint32(_player->_currentPetSlot); 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) ++num; } if (result) { do { Field *fields = result->Fetch(); data << uint32(fields[1].GetUInt32()); // slot data << uint32(fields[2].GetUInt32()); // petnumber data << uint32(fields[3].GetUInt32()); // creature entry data << uint32(fields[4].GetUInt16()); // level data << fields[5].GetString(); // name data << uint8(fields[1].GetUInt32() <= PET_SLOT_STABLE_FIRST ? 1 : 2); // 1 = current, 2/3 = in stable (any from 4, 5, ... create problems with proper show) ++num; } while (result->NextRow()); } data.put<uint8>(wpos, num); // set real data to placeholder SendPacket(&data); }
void CreatePet(Player *player, Creature * m_creature, uint32 entry) { if(player->getClass() != CLASS_HUNTER) { player->PlayerTalkClass->SendCloseGossip(); return; } if(player->GetPet()) { player->PlayerTalkClass->SendCloseGossip(); return; } Creature *creatureTarget = m_creature->SummonCreature(entry, player->GetPositionX(), player->GetPositionY()+2, player->GetPositionZ(), player->GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 500); if(!creatureTarget) return; Pet* pet = player->CreateTamedPetFrom(creatureTarget, 0); if (!pet) return; // kill original creature creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view pet->SetPower(POWER_HAPPINESS, 1048000); pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, player->getLevel() - 1); pet->GetMap()->AddToMap(pet->ToCreature()); // visual effect for levelup for lulz pet->SetUInt32Value(UNIT_FIELD_LEVEL, player->getLevel()); pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); if (!pet->InitStatsForLevel(player->getLevel())) pet->UpdateAllStats(); // caster has pet now player->SetMinion(pet, true); pet->SavePetToDB(PET_SAVE_AS_CURRENT); pet->InitTalentForLevel(); player->PetSpellInitialize(); //inform that has da pet player->PlayerTalkClass->SendCloseGossip(); }
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(); 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 // 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 << uint8(1); // 1 = current, 2/3 = in stable (any from 4,5,... create problems with proper show) ++num; } // 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) { do { Field *fields = result->Fetch(); 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() ); delete result; } data.put<uint8>(wpos, num); // set real data to placeholder SendPacket(&data); }
void CreatePet(Player *player, Creature * m_creature, uint32 entry) { if(player->getClass() != CLASS_HUNTER) { player->PlayerTalkClass->SendCloseGossip(); return; } if(player->GetPet()) { m_creature->MonsterWhisper("First you must drop your Pet!", player->GetGUID()); m_creature->MonsterWhisper("First you must drop your Pet!", player->GetGUID(), true); player->PlayerTalkClass->SendCloseGossip(); return; } Creature *creatureTarget = m_creature->SummonCreature(entry, player->GetPositionX(), player->GetPositionY()+2, player->GetPositionZ(), player->GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 500); if(!creatureTarget) return; Pet* pet = player->CreateTamedPetFrom(creatureTarget, 0); if(!pet) return; // kill original creature creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, player->getLevel() - 1); pet->GetMap()->AddToMap(pet->ToCreature()); // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, player->getLevel()); pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); if(!pet->InitStatsForLevel(player->getLevel())) sLog->outInfo(LOG_FILTER_PETS, "Pet Create fail: no init stats for entry %u", entry); pet->UpdateAllStats(); // caster have pet now player->SetMinion(pet, true); pet->SavePetToDB(PET_SAVE_AS_CURRENT); pet->InitTalentForLevel(); player->PetSpellInitialize(); //end player->PlayerTalkClass->SendCloseGossip(); m_creature->MonsterWhisper("Pet added. You might want to feed it and name it somehow.", player->GetGUID()); m_creature->MonsterWhisper("Pet added. You might want to feed it and name it somehow.", player->GetGUID(), true); }
void WorldSession::HandleStableSwapPet(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recv CMSG_STABLE_SWAP_PET."); uint64 npcGUID; uint32 pet_number; uint8 new_slot; recvData >> new_slot >> pet_number >> npcGUID; if (!CheckStableMaster(npcGUID)) { SendStableResult(STABLE_ERR_STABLE); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Pet* pet = _player->GetPet(); /* if (!pet || pet->getPetType() != HUNTER_PET) { SendStableResult(STABLE_ERR_STABLE); return; } */ //If we move the pet already summoned... if (pet && pet->GetCharmInfo() && pet->GetCharmInfo()->GetPetNumber() == pet_number) _player->RemovePet(pet, PET_SAVE_AS_CURRENT); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHARACTER_SELECT_PET_SLOT_BY_ID); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt32(1, pet_number); _stableSwapCallback.SetParam(new_slot); _stableSwapCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); }
void WorldSession::SendStablePetCallback(ObjectGuid guid, PreparedQueryResult result) { if (!GetPlayer()) return; WorldPackets::Pet::PetStableList packet; packet.StableMaster = guid; Pet* pet = _player->GetPet(); int32 petSlot = 0; // not let move dead pet in slot if (pet && pet->IsAlive() && pet->getPetType() == HUNTER_PET) { WorldPackets::Pet::PetStableInfo stableEntry; stableEntry.PetSlot = petSlot; stableEntry.PetNumber = pet->GetCharmInfo()->GetPetNumber(); stableEntry.CreatureID = pet->GetEntry(); stableEntry.DisplayID = pet->GetDisplayId(); stableEntry.ExperienceLevel = pet->getLevel(); stableEntry.PetFlags = PET_STABLE_ACTIVE; stableEntry.PetName = pet->GetName(); ++petSlot; packet.Pets.push_back(stableEntry); } if (result) { do { Field* fields = result->Fetch(); WorldPackets::Pet::PetStableInfo stableEntry; stableEntry.PetSlot = petSlot; stableEntry.PetNumber = fields[1].GetUInt32(); // petnumber stableEntry.CreatureID = fields[2].GetUInt32(); // creature entry stableEntry.DisplayID = fields[5].GetUInt32(); // creature displayid stableEntry.ExperienceLevel = fields[3].GetUInt16(); // level stableEntry.PetFlags = PET_STABLE_INACTIVE; stableEntry.PetName = fields[4].GetString(); // Name ++petSlot; packet.Pets.push_back(stableEntry); } while (result->NextRow()); } SendPacket(packet.Write()); }
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_AutoPtr 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()); } data.put<uint8>(8, num); // set real data to placeholder SendPacket(&data); }
void WorldSession::HandlePetRename( WorldPacket & recv_data ) { sLog.outDetail( "HandlePetRename. CMSG_PET_RENAME" ); uint64 petguid; std::string name; recv_data >> petguid; recv_data >> name; Pet* pet = ObjectAccessor::GetPet(petguid); // check it! if( !pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || pet->GetByteValue(UNIT_FIELD_BYTES_2, 2) != UNIT_RENAME_ALLOWED || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo() ) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if(res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name); return; } if(sObjectMgr.IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name); return; } pet->SetName(name); Unit *owner = pet->GetOwner(); if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); CharacterDatabase.BeginTransaction(); CharacterDatabase.escape_string(name); CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); }
void WorldSession::HandlePetRename(WorldPacket& recv_data) { DETAIL_LOG("HandlePetRename. CMSG_PET_RENAME"); ObjectGuid petGuid; std::string name; recv_data >> petGuid; recv_data >> name; Pet* pet = _player->GetMap()->GetPet(petGuid); // check it! if (!pet || pet->getPetType() != HUNTER_PET || !pet->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_RENAME) || pet->GetOwnerGuid() != _player->GetObjectGuid() || !pet->GetCharmInfo()) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if (res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name); return; } if (sObjectMgr.IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name); return; } pet->SetName(name); if (_player->GetGroup()) _player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_RENAME); CharacterDatabase.BeginTransaction(); CharacterDatabase.escape_string(name); CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(nullptr))); }
void WorldSession::HandlePetRename( WorldPacket & recv_data ) { DETAIL_LOG( "HandlePetRename. CMSG_PET_RENAME" ); uint64 petguid; uint8 isdeclined; std::string name; DeclinedName declinedname; recv_data >> petguid; recv_data >> name; recv_data >> isdeclined; Pet* pet = _player->GetMap()->GetPet(petguid); // check it! if( !pet || pet->getPetType() != HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || pet->GetOwnerGuid() != _player->GetObjectGuid() || !pet->GetCharmInfo() ) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if(res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name, NULL); return; } if(sObjectMgr.IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); if(_player->GetGroup()) _player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); if(isdeclined) { for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recv_data >> declinedname.name[i]; } std::wstring wname; Utf8toWStr(name, wname); if(!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname,0),declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } CharacterDatabase.BeginTransaction(); if(isdeclined) { for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.escape_string(declinedname.name[i]); CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.PExecute("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); } CharacterDatabase.escape_string(name); CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); }
void WorldSession::HandlePetRename(WorldPacket& recvData) { sLog->outInfo(LOG_FILTER_NETWORKIO, "HandlePetRename. CMSG_PET_RENAME"); uint64 petguid; uint8 isdeclined; std::string name; DeclinedName declinedname; recvData >> petguid; recvData >> name; recvData >> isdeclined; Pet* pet = ObjectAccessor::FindPet(petguid); // check it! if (!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if (res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name, NULL); return; } if (sObjectMgr->IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); Unit* owner = pet->GetOwner(); if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recvData >> declinedname.name[i]; } std::wstring wname; Utf8toWStr(name, wname); if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (isdeclined) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME); stmt->setUInt32(0, pet->GetCharmInfo()->GetPetNumber()); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_CHAR_PET_DECLINEDNAME); stmt->setUInt32(0, _player->GetGUIDLow()); for (uint8 i = 0; i < 5; i++) stmt->setString(i+1, declinedname.name[i]); trans->Append(stmt); } CharacterDatabase.CommitTransaction(trans); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped }
void PlayerbotHunterAI::DoNextCombatManeuver(Unit *pTarget) { if (!pTarget || pTarget->isDead()) return; PlayerbotAI *ai = GetAI(); if (!ai) return; Player *m_bot = GetPlayerBot(); if (!m_bot || m_bot->isDead()) return; Unit *pVictim = pTarget->getVictim(); Unit *m_tank = FindMainTankInRaid(GetMaster()); if (!m_tank && m_bot->GetGroup() && GetMaster()->GetGroup() != m_bot->GetGroup()) { FindMainTankInRaid(m_bot); } if (!m_tank) { m_tank = m_bot; } uint32 masterHP = GetMaster()->GetHealth()*100 / GetMaster()->GetMaxHealth(); float pDist = m_bot->GetDistance(pTarget); uint8 pThreat = GetThreatPercent(pTarget); Pet *pet = m_bot->GetPet(); if (m_tank->GetGUID() == m_bot->GetGUID() && pet && pet->isAlive() && pet->isInCombat()) { m_tank = pet; } uint8 petThreat = 0; if (pet) { GetThreatPercent(pTarget,pet); } // switch (ai->GetScenarioType()) // { // case PlayerbotAI::SCENARIO_DUEL: // ai->CastSpell(RAPTOR_STRIKE); // return; // } // ------- Non Duel combat ---------- #pragma region Choose Target // Choose Target if (isUnderAttack()) // I am under attack { if (pVictim && pVictim->GetGUID() == m_bot->GetGUID() && pDist <= 2) { } // My target is almost up to me, no need to search else //Have to select nearest target { Unit *curAtt = GetNearestAttackerOf(m_bot); if (curAtt && curAtt->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(curAtt->GetGUID()); //ai->AddLootGUID(curAtt->GetGUID()); DoNextCombatManeuver(curAtt); //Restart new update to get variables fixed.. return; } } //my target is attacking me } #pragma endregion #pragma region Pet Actions // Pet's own Actions if( pet && pet->isAlive() ) { // Setup pet if (pet->GetCharmInfo()->IsAtStay()) {pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); } //Heal pet if ( ( ((float)pet->GetHealth()/(float)pet->GetMaxHealth()) < 0.5f ) && ( PET_MEND>0 && !pet->getDeathState() != ALIVE && pVictim != m_bot && CastSpell(PET_MEND,m_bot) )) { return; } // Set pet to attack hunter's attacker > its own attackers > hunter's target if (!pet->getVictim()) { pet->AI()->AttackStart(pTarget); } else if (isUnderAttack(m_bot)) { pet->AI()->AttackStart(pTarget); } //Always help hunter if she's under attack else if (pet->getVictim()->GetGUID() != pTarget->GetGUID() && !isUnderAttack(pet)) { pet->AI()->AttackStart(pTarget); } else if (isUnderAttack(pet)) // Pet is under attack and hunter has no attackers { if ( pet->getVictim()->getVictim() && pet->getVictim()->getVictim()->GetGUID() == pet->GetGUID() && pDist <= 2) { } // My target is almost up to me, no need to search else //Have to select nearest target { Unit *curAtt = GetNearestAttackerOf(pet,true); if (curAtt && (!pet->getVictim() || curAtt->GetGUID() != pet->getVictim()->GetGUID())) { pet->AI()->AttackStart(curAtt); //Attack nearest attacker } } //Actions to do under attack (Always tank it, and try to kill it, until someone (!= hunter) takes aggro back) //Hunter should help her pet whether main tank or not, unless she's being attacked (BEWARE Targeting Loop possibility) if (pet->getVictim() && !isUnderAttack(m_bot) && pet->getVictim()->GetGUID() != pTarget->GetGUID()) { m_bot->SetSelection(pet->getVictim()->GetGUID()); DoNextCombatManeuver(pet->getVictim()); //Restart new update to get variables fixed.. return; } } // Pet tanking behaviour if (pet->GetGUID() == m_tank->GetGUID() || isUnderAttack(m_bot) || isUnderAttack(pet)) { if (GROWL) pet->GetCharmInfo()->SetSpellAutocast(GROWL,true); //Autocast growl if (BAD_ATTITUDE) pet->GetCharmInfo()->SetSpellAutocast(BAD_ATTITUDE,true); if (COWER) pet->GetCharmInfo()->SetSpellAutocast(COWER,false); if (CastSpell(INTIMIDATION,m_bot)) { return; } } else { if (GROWL) pet->GetCharmInfo()->SetSpellAutocast(GROWL,false); //Do not try to get aggro if (BAD_ATTITUDE) pet->GetCharmInfo()->SetSpellAutocast(BAD_ATTITUDE,false); if (COWER) pet->GetCharmInfo()->SetSpellAutocast(COWER,true); //Autocast cower } // NORMAL PET dps attacks if (petThreat < threatThreshold || pet->GetGUID() == m_tank->GetGUID() || isUnderAttack(m_bot)) { if (CastSpell(KILL_COMMAND,m_bot)) { } else if (CastSpell(BESTIAL_WRATH,m_bot)) { } } // NETHERSHOCK DEMORALIZINGSCREECH } #pragma endregion // If there's a cast stop if(m_bot->HasUnitState(UNIT_STAT_CASTING)) return; // Cast CC breakers if any match found (does not work yet) // uint32 ccSpells[4] = { R_ESCAPE_ARTIST, R_EVERY_MAN_FOR_HIMSELF, R_WILL_OF_FORSAKEN, R_STONEFORM }; // if (castSelfCCBreakers(ccSpells)) { } //most of them dont have gcd #pragma region Evasive manuevers // Do evasive manuevers if under attack if (isUnderAttack()) { if (m_tank->GetGUID() == m_bot->GetGUID()) { } // i am tank and my pet is probably dead, so i have to face the attackers else if (CastSpell(FEIGN_DEATH,m_bot)) { return; } //avoid attack //else if (m_bot->getRace() == (uint8) RACE_NIGHTELF && CastSpell(R_SHADOWMELD,m_bot) ) { return; } else if (CastSpell(CONCUSSIVE_SHOT,pTarget)) { return; } else if (CastSpell(WYVERN_STING,pTarget)) { return; } else if (CastSpell(SCATTER_SHOT,pTarget)) { return; } else if (CastSpell(FREEZING_ARROW,pTarget)) { return; } else if (CastSpell(MISDIRECTION,m_tank)) { return; } else if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget) ) { return; } //no gcd but is cast else if (pTarget->GetCreatureType() == (uint32) CREATURE_TYPE_BEAST && CastSpell(SCARE_BEAST,pTarget)) { return; } else if (pDist <= 2 && CastSpell(FREEZING_TRAP,pTarget)) { return; } } #pragma endregion //Select combat mode m_role = BOT_ROLE_DPS_RANGED; if ((isUnderAttack() && pDist <= ATTACK_DISTANCE) || !m_bot->GetUInt32Value(PLAYER_AMMO_ID) ) { m_role = BOT_ROLE_DPS_MELEE; } TakePosition(pTarget); #pragma region Buff / Protect //Buff UP if (m_bot->getRace() == (uint8) RACE_TROLL && CastSpell(R_BERSERKING,m_bot) ) { } //no GCD if (m_bot->getRace() == (uint8) RACE_ORC && CastSpell(R_BLOOD_FURY,m_bot) ) { } //no GCD if (CastSpell(TRUESHOT_AURA, m_bot)) { return; } if (CastSpell(RAPID_FIRE,m_bot)) { return; } if (CastSpell(HUNTERS_MARK,pTarget)) { return; } if ((ai->GetHealthPercent() < 80 || ai->GetManaPercent() < 60 ) && CastSpell(READINESS,m_bot)) { } //no gcd //Protect yourself if needed if (m_bot->getRace() == (uint8) RACE_DWARF && ai->GetHealthPercent() < 75 && CastSpell(R_STONEFORM,m_bot) ) { } //no gcd if (ai->GetHealthPercent() < 20 && CastSpell(DETERRENCE,m_bot)) {} //No GCD if (m_bot->getRace() == (uint8) RACE_DRAENEI && ai->GetHealthPercent() < 55 && CastSpell(R_GIFT_OF_NAARU,m_bot)) { return; } //Break Spells if (m_bot->getRace() == (uint8) RACE_BLOODELF && pDist < 8 && ( pTarget->IsNonMeleeSpellCasted(true) || ai->GetManaPercent() < 20 ) && CastSpell(R_ARCANE_TORRENT, pTarget) ) { } //no gcd if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(SILENCING_SHOT, pTarget) ) { return; } if (pTarget->IsNonMeleeSpellCasted(true) && CastSpell(SCATTER_SHOT, pTarget) ) { return; } //Catch if (pTarget->HasUnitMovementFlag(UNIT_FLAG_FLEEING)) { if (CastSpell(WING_CLIP,pTarget)) return; if (CastSpell(CONCUSSIVE_SHOT,pTarget)) return; if (CastSpell(SCATTER_SHOT, pTarget) ) { return; } } #pragma endregion //Do combat switch (m_role) { #pragma region BOT_ROLE_DPS_MELEE case BOT_ROLE_DPS_MELEE: if (AUTO_SHOT) { m_bot->InterruptNonMeleeSpells( true, AUTO_SHOT ); } //Stop autoshot if (CastSpell(ASPECT_OF_THE_MONKEY,m_bot)) { return; } //Get Monkey aspect if (m_bot->getRace() == (uint8) RACE_TAUREN && pDist < 8 && CastSpell(R_WAR_STOMP, pTarget)) { return; } //no gcd but is cast // Threat control if (pThreat < threatThreshold || m_tank->GetGUID() == m_bot->GetGUID() || m_bot->HasAura(MISDIRECTION) ) { } //Continue attack else { if (pet && isUnderAttack(pet) && pet->getVictim() && pet->getVictim()->GetGUID() != pTarget->GetGUID()) //Should be helping pet { m_bot->SetSelection(pet->getVictim()->GetGUID()); return; } else if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!! { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); return; } else if (CastSpell(FEIGN_DEATH,m_bot)) { return; } else { return; } // No more threat reducing spells, just slow down } if (CastSpell(RAPTOR_STRIKE,pTarget,true,true)) {} //No gcd if (CastSpell(MONGOOSE_BITE,pTarget,true,true)) { return; } // Cannot be sure if casted or not else if (CastSpell(COUNTERATTACK,pTarget,true,true)) { return; } // Cannot be sure if casted or not if (CastSpell(WING_CLIP,pTarget)) { return; } if (isUnderAttack(m_tank,6) && CastSpell(SNAKE_TRAP,m_bot)) { return; } if (isUnderAttack(m_tank,4) && CastSpell(EXPLOSIVE_TRAP,m_bot)) { return; } if (CastSpell(IMMOLATION_TRAP,m_bot)) { return; } break; #pragma endregion #pragma region BOT_ROLE_DPS_RANGED case BOT_ROLE_DPS_RANGED: if (m_pulling) { if (GetAI()->CastSpell(CONCUSSIVE_SHOT,pTarget) || GetAI()->CastSpell(AUTO_SHOT,pTarget)) { m_pulling = false; GetAI()->SetCombatOrder(ORDERS_NONE); GetAI()->Follow(*GetMaster()); GetAI()->SetIgnoreUpdateTime(2); if(HasPet(GetPlayerBot())) m_bot->GetPet()->SetReactState(REACT_DEFENSIVE); } return; } if (AUTO_SHOT && !m_bot->FindCurrentSpellBySpellId(AUTO_SHOT)) { ai->CastSpell(AUTO_SHOT,pTarget); } //Start autoshot if (!(ai->GetManaPercent() < 85 && m_bot->HasAura(ASPECT_OF_THE_VIPER)) && CastSpell(ASPECT_OF_THE_HAWK,m_bot)) { return; } //Get Hawk aspect if ((ai->GetManaPercent() < 25) && CastSpell(ASPECT_OF_THE_VIPER,m_bot,true,false,true)) { return; } //Build up mana // if i am main tank, protect master by taunt if(m_tank->GetGUID() == m_bot->GetGUID()) { // Taunt if needed (Only for master) Unit *curAtt = GetAttackerOf(GetMaster()); if (curAtt && CastSpell(DISTRACTING_SHOT, curAtt)) { return; } // My target is not attacking me, taunt.. if (pVictim && pVictim->GetGUID() != m_bot->GetGUID() && CastSpell(DISTRACTING_SHOT, pTarget) ) { return; } } // If i am not tank, transfer threat to tank or pet.. else { if (CastSpell(MISDIRECTION,m_tank)) { return; } if (pet && pet->isAlive() && CastSpell(MISDIRECTION,pet)) { return; } // Threat control if (pThreat < threatThreshold || m_bot->HasAura(MISDIRECTION) ) { } //Continue attack else { if (pet && isUnderAttack(pet) && pet->getVictim() && pet->getVictim()->GetGUID() != pTarget->GetGUID()) //Should be helping pet { m_bot->SetSelection(pet->getVictim()->GetGUID()); return; } else if (m_tank->getVictim() && m_tank->getVictim()->GetGUID() != pTarget->GetGUID()) // I am attacking wrong target!! { m_bot->SetSelection(m_tank->getVictim()->GetGUID()); return; } else if (CastSpell(FEIGN_DEATH,m_bot)) { return; } else { return; } // No more threat reducing spells, just slow down } } // DO dps if (ai->GetHealthPercent(*pTarget) < 20 && CastSpell(KILL_SHOT,pTarget)) { return; } if (isUnderAttack(m_tank,4) && CastSpell(MULTI_SHOT,pTarget)) { return; } if (isUnderAttack(m_tank,4) && CastSpell(VOLLEY,pTarget)) { GetAI()->SetIgnoreUpdateTime(7); return; } if (CanCast(CHIMERA_SHOT,pTarget) && (pTarget->HasAura(VIPER_STING,m_bot->GetGUID()) || pTarget->HasAura(SERPENT_STING,m_bot->GetGUID()) ) && CastSpell(CHIMERA_SHOT,pTarget,false) ) { return; } if (ai->GetManaPercent() < 60 && ai->GetManaPercent(*pTarget) > 4 && CastSpell(VIPER_STING,pTarget)) { return; } if (!pTarget->HasAura(VIPER_STING,m_bot->GetGUID()) && CastSpell(SERPENT_STING,pTarget)) { return; } if (CastSpell(ARCANE_SHOT,pTarget)) { return; } if (CastSpell(BLACK_ARROW,pTarget)) { return; } if (CastSpell(EXPLOSIVE_SHOT,pTarget)) { return; } if (CastSpell(STEADY_SHOT,pTarget)) { return; } break; #pragma endregion } /*// drink potion if support / healer (Other builds simply overuse mana and waste mana pots) if(ai->GetManaPercent() < 5 && (m_role == BOT_ROLE_SUPPORT || m_role == BOT_ROLE_HEALER) ) { Item *pItem = ai->FindPotion(); if(pItem != NULL) { if (pItem->GetSpell() && m_bot->HasSpellCooldown(pItem->GetSpell()) ) { return; } //pot is in cooldown ai->UseItem(*pItem); } }*/ } // end DoNextCombatManeuver
void WorldSession::HandlePetRename( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+1); sLog.outDetail( "HandlePetRename. CMSG_PET_RENAME\n" ); uint64 petguid; uint8 isdeclined; std::string name; DeclinedName declinedname; recv_data >> petguid; recv_data >> name; CHECK_PACKET_SIZE(recv_data, recv_data.rpos() + 1); recv_data >> isdeclined; Pet* pet = ObjectAccessor::GetPet(petguid); // check it! if( !pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || pet->GetByteValue(UNIT_FIELD_BYTES_2, 2) != UNIT_RENAME_ALLOWED || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo() ) return; if(!ObjectMgr::IsValidPetName(name)) { SendPetNameInvalid(PET_NAME_INVALID, name, NULL); return; } if(objmgr.IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); Unit *owner = pet->GetOwner(); if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); if(isdeclined) { for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { CHECK_PACKET_SIZE(recv_data, recv_data.rpos() + 1); recv_data >> declinedname.name[i]; } std::wstring wname; Utf8toWStr(name, wname); if(!ObjectMgr::CheckDeclinedNames(GetMainPartOfName(wname,0),declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } CharacterDatabase.BeginTransaction(); if(isdeclined) { for(int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.escape_string(declinedname.name[i]); CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.PExecute("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u','%u','%s','%s','%s','%s','%s')", pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); } CharacterDatabase.escape_string(name); CharacterDatabase.PExecute("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); }
void WorldSession::HandlePetAction(WorldPacket& recv_data) { ObjectGuid petGuid; uint32 data; ObjectGuid targetGuid; recv_data >> petGuid; recv_data >> data; recv_data >> targetGuid; uint32 spellid = UNIT_ACTION_BUTTON_ACTION(data); uint8 flag = UNIT_ACTION_BUTTON_TYPE(data); // delete = 0x07 CastSpell = C1 DETAIL_LOG("HandlePetAction: %s flag is %u, spellid is %u, target %s.", petGuid.GetString().c_str(), uint32(flag), spellid, targetGuid.GetString().c_str()); // used also for charmed creature/player Unit* petUnit = _player->GetMap()->GetUnit(petGuid); if (!petUnit) { sLog.outError("HandlePetAction: %s not exist.", petGuid.GetString().c_str()); return; } if (_player->GetObjectGuid() != petUnit->GetCharmerOrOwnerGuid()) { sLog.outError("HandlePetAction: %s isn't controlled by %s.", petGuid.GetString().c_str(), _player->GetGuidStr().c_str()); return; } if (!petUnit->isAlive()) return; CharmInfo* charmInfo = petUnit->GetCharmInfo(); if (!charmInfo) { sLog.outError("WorldSession::HandlePetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", petUnit->GetGUIDLow(), petUnit->GetTypeId()); return; } Pet* pet = nullptr; Creature* creature = nullptr; if (petUnit->GetTypeId() == TYPEID_UNIT) { creature = static_cast<Creature*>(petUnit); if (creature->IsPet()) { pet = static_cast<Pet*>(petUnit); if (pet->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) return; } } if (!pet && petUnit->hasUnitState(UNIT_STAT_CONTROLLED)) { // possess case if (flag != uint8(ACT_COMMAND)) { sLog.outError("PetHAndler: unknown PET flag Action %i and spellid %i. For possessed %s", uint32(flag), spellid, petUnit->GetGuidStr().c_str()); return; } switch (spellid) { case COMMAND_STAY: case COMMAND_FOLLOW: charmInfo->SetCommandState(CommandStates(spellid)); break; case COMMAND_ATTACK: { Unit* targetUnit = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr; if (targetUnit && targetUnit != petUnit && targetUnit->isTargetableForAttack()) { _player->SetInCombatState(true, targetUnit); // This is true if pet has no target or has target but targets differs. if (petUnit->getVictim() != targetUnit) petUnit->Attack(targetUnit, true); } break; } case COMMAND_ABANDON: _player->Uncharm(); break; default: sLog.outError("PetHandler: Not allowed action %i and spellid %i. Pet %s owner is %s", uint32(flag), spellid, petUnit->GetGuidStr().c_str(), _player->GetGuidStr().c_str()); break; } return; } // only real pet should go there if (!pet) { sLog.outError("PetHandler: A not pet trying to do unknown Action %i and spellid %i. Pet %s owner is %s", uint32(flag), spellid, petUnit->GetGuidStr().c_str(), _player->GetGuidStr().c_str()); return; } switch (flag) { case ACT_COMMAND: // 0x07 switch (spellid) { case COMMAND_STAY: // flat=1792 // STAY { if (!petUnit->hasUnitState(UNIT_STAT_CONTROLLED)) { petUnit->StopMoving(); petUnit->GetMotionMaster()->Clear(); } petUnit->AttackStop(true, true); pet->SetIsRetreating(); pet->SetStayPosition(true); pet->SetSpellOpener(); charmInfo->SetCommandState(COMMAND_STAY); break; } case COMMAND_FOLLOW: // spellid=1792 // FOLLOW { if (!petUnit->hasUnitState(UNIT_STAT_CONTROLLED)) { petUnit->StopMoving(); petUnit->GetMotionMaster()->Clear(); pet->SetIsRetreating(true); } petUnit->AttackStop(true, true); pet->SetStayPosition(); pet->SetSpellOpener(); charmInfo->SetCommandState(COMMAND_FOLLOW); break; } case COMMAND_ATTACK: // spellid=1792 // ATTACK { pet->SetIsRetreating(); pet->SetSpellOpener(); Unit* targetUnit = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr; if (targetUnit && targetUnit != petUnit && targetUnit->isTargetableForAttack() && targetUnit->isInAccessablePlaceFor((Creature*)petUnit)) { _player->SetInCombatState(true, targetUnit); // This is true if pet has no target or has target but targets differs. if (petUnit->getVictim() != targetUnit) { petUnit->AttackStop(); if (!petUnit->hasUnitState(UNIT_STAT_CONTROLLED)) { petUnit->GetMotionMaster()->Clear(); pet->AI()->AttackStart(targetUnit); // 10% chance to play special warlock pet attack talk, else growl if (pet->getPetType() == SUMMON_PET && roll_chance_i(10)) pet->SendPetTalk((uint32)PET_TALK_ATTACK); pet->SendPetAIReaction(); } else pet->Attack(targetUnit, true); } } break; } case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) { if (pet->getPetType() == HUNTER_PET) pet->Unsummon(PET_SAVE_AS_DELETED, _player); else // dismissing a summoned pet is like killing them (this prevents returning a soulshard...) pet->SetDeathState(CORPSE); pet->SetStayPosition(); break; } default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } break; case ACT_REACTION: // 0x6 switch (spellid) { case REACT_PASSIVE: // passive { pet->AttackStop(true, true); pet->SetSpellOpener(); } case REACT_DEFENSIVE: // recovery case REACT_AGGRESSIVE: // activete { charmInfo->SetReactState(ReactStates(spellid)); break; } } break; case ACT_DISABLED: // 0x81 spell (disabled), ignore case ACT_PASSIVE: // 0x01 case ACT_ENABLED: // 0xC1 spell { pet->SetIsRetreating(); pet->SetSpellOpener(); Unit* unit_target = targetGuid ? _player->GetMap()->GetUnit(targetGuid) : nullptr; // do not cast unknown spells SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellid); if (!spellInfo) { sLog.outError("WORLD: unknown PET spell id %i", spellid); return; } if (pet->GetCharmInfo() && pet->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo)) return; for (int i = 0; i < MAX_EFFECT_INDEX; ++i) { if (spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED) return; } // do not cast not learned spells if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo)) return; _player->SetInCombatState(true, unit_target); pet->clearUnitState(UNIT_STAT_MOVING); Spell* spell = new Spell(pet, spellInfo, false); SpellCastResult result = spell->CheckPetCast(unit_target); const SpellRangeEntry* sRange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); if (unit_target && !(pet->IsWithinDistInMap(unit_target, sRange->maxRange) && pet->IsWithinLOSInMap(unit_target)) && !(GetPlayer()->IsFriendlyTo(unit_target) || pet->HasAuraType(SPELL_AURA_MOD_POSSESS))) { pet->SetSpellOpener(spellid, sRange->minRange, sRange->maxRange); spell->finish(false); delete spell; pet->AttackStop(); if (!pet->hasUnitState(UNIT_STAT_CONTROLLED)) { pet->GetMotionMaster()->Clear(); pet->AI()->AttackStart(unit_target); // 10% chance to play special warlock pet attack talk, else growl if (pet->IsPet() && pet->getPetType() == SUMMON_PET && pet != unit_target && roll_chance_i(10)) pet->SendPetTalk((uint32)PET_TALK_ATTACK); pet->SendPetAIReaction(); } else petUnit->Attack(unit_target, true); return; } // auto turn to target unless possessed if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->hasUnitState(UNIT_STAT_CONTROLLED)) { if (unit_target) { pet->SetInFront(unit_target); if (unit_target->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)unit_target); } else if (Unit* unit_target2 = spell->m_targets.getUnitTarget()) { pet->SetInFront(unit_target2); if (unit_target2->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)unit_target2); } if (Unit* powner = pet->GetCharmerOrOwner()) if (powner->GetTypeId() == TYPEID_PLAYER) pet->SendCreateUpdateToPlayer((Player*)powner); result = SPELL_CAST_OK; } if (result == SPELL_CAST_OK) { pet->AddCreatureSpellCooldown(spellid); unit_target = spell->m_targets.getUnitTarget(); pet->SetSpellOpener(); spell->SpellStart(&(spell->m_targets)); } else { if (pet->hasUnitState(UNIT_STAT_CONTROLLED)) Spell::SendCastResult(GetPlayer(), spellInfo, 0, result); else { Unit* owner = pet->GetCharmerOrOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER) Spell::SendCastResult((Player*)owner, spellInfo, 0, result, true); } if (!pet->HasSpellCooldown(spellid)) GetPlayer()->SendClearCooldown(spellid, pet); pet->SetSpellOpener(); spell->finish(false); delete spell; } break; } default: sLog.outError("WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } }
void WorldSession::HandleLoadPetFromDBSecondCallback(LoadPetFromDBQueryHolder* holder) { if (!GetPlayer()) return; Player* owner = GetPlayer(); Pet* pet = owner->GetPet(); if (!pet) return; pet->_LoadAuras(holder->GetPreparedResult(PET_LOAD_QUERY_LOADAURAS), holder->GetDiffTime()); bool current = holder->GetCurrent(); uint32 summon_spell_id = pet->GetUInt32Value(UNIT_CREATED_BY_SPELL); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id); // CANT BE NULL bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0; // load action bar, if data broken will fill later by default spells. if (!is_temporary_summoned) { pet->_LoadSpells(holder->GetPreparedResult(PET_LOAD_QUERY_LOADSPELLS)); pet->InitTalentForLevel(); // re-init to check talent count pet->_LoadSpellCooldowns(holder->GetPreparedResult(PET_LOAD_QUERY_LOADSPELLCOOLDOWN)); pet->LearnPetPassives(); pet->InitLevelupSpellsForLevel(); pet->CastPetAuras(current); pet->GetCharmInfo()->LoadPetActionBar(holder->GetActionBar()); // action bar stored in already read string } pet->CleanupActionBar(); // remove unknown spells from action bar after load owner->PetSpellInitialize(); owner->SendTalentsInfoData(true); if (owner->GetGroup()) owner->SetGroupUpdateFlag(GROUP_UPDATE_PET); //set last used pet number (for use in BG's) if (owner->GetTypeId() == TYPEID_PLAYER && pet->isControlled() && !pet->isTemporarySummoned() && (pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET)) { owner->ToPlayer()->SetLastPetNumber(holder->GetPetNumber()); owner->SetLastPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL)); } if (pet->getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current { pet->SetPower(POWER_MANA, pet->GetMaxPower(POWER_MANA)); pet->SetHealth(pet->GetMaxHealth()); } else { if (!holder->GetSavedHealth() && pet->getPetType() == HUNTER_PET && pet->GetAsynchLoadType() != PET_LOAD_SUMMON_DEAD_PET) pet->setDeathState(JUST_DIED); else { pet->SetHealth(holder->GetSavedHealth() > pet->GetMaxHealth() ? pet->GetMaxHealth() : holder->GetSavedHealth()); pet->SetPower(POWER_MANA, holder->GetSavedMana() > pet->GetMaxPower(POWER_MANA) ? pet->GetMaxPower(POWER_MANA) : holder->GetSavedMana()); } } pet->SetLoading(false); owner->SetTemporaryUnsummonedPetNumber(0); // clear this only if pet is loaded successfuly // current if (current && owner->IsPetNeedBeTemporaryUnsummoned()) { owner->UnsummonPetTemporaryIfAny(); return; } pet->HandleAsynchLoadSucceed(); return; }
void WorldSession::HandlePetRename(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_RENAME"); ObjectGuid petguid; uint8 isdeclined; std::string name; DeclinedName declinedname; recvData >> petguid; recvData >> name; recvData >> isdeclined; Pet* pet = ObjectAccessor::GetPet(*_player, petguid); // check it! if (!pet || !pet->IsPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name, GetSessionDbcLocale()); if (res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name, NULL); return; } if (sObjectMgr->IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); if (pet->GetOwner()->GetGroup()) pet->GetOwner()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recvData >> declinedname.name[i]; } std::wstring wname; if (!Utf8toWStr(name, wname)) return; if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (isdeclined) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME); stmt->setUInt32(0, pet->GetCharmInfo()->GetPetNumber()); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_PET_DECLINEDNAME); stmt->setUInt32(0, _player->GetGUID().GetCounter()); for (uint8 i = 0; i < 5; i++) stmt->setString(i + 1, declinedname.name[i]); trans->Append(stmt); } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_NAME); stmt->setString(0, name); stmt->setUInt32(1, _player->GetGUID().GetCounter()); stmt->setUInt32(2, pet->GetCharmInfo()->GetPetNumber()); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped }
uint8 WorldSession::HandleLoadPetFromDBFirstCallback(PreparedQueryResult result, uint8 asynchLoadType) { if (!GetPlayer() || GetPlayer()->GetPet() || GetPlayer()->GetVehicle() || GetPlayer()->IsSpectator()) return PET_LOAD_ERROR; if (!result) return PET_LOAD_NO_RESULT; Field* fields = result->Fetch(); // Xinef: this can happen if fetch is called twice, impossibru. if (!fields) return PET_LOAD_ERROR; Player* owner = GetPlayer(); // update for case of current pet "slot = 0" uint32 petentry = fields[1].GetUInt32(); if (!petentry) return PET_LOAD_NO_RESULT; uint8 petSlot = fields[7].GetUInt8(); bool current = petSlot == PET_SAVE_AS_CURRENT; uint32 summon_spell_id = fields[15].GetUInt32(); SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(summon_spell_id); // CANT BE NULL bool is_temporary_summoned = spellInfo && spellInfo->GetDuration() > 0; uint32 pet_number = fields[0].GetUInt32(); uint32 savedhealth = fields[10].GetUInt32(); uint32 savedmana = fields[11].GetUInt32(); PetType pet_type = PetType(fields[16].GetUInt8()); // xinef: BG resurrect, overwrite saved value if (asynchLoadType == PET_LOAD_BG_RESURRECT) savedhealth = 1; if (pet_type == HUNTER_PET && savedhealth == 0 && asynchLoadType != PET_LOAD_SUMMON_DEAD_PET) { WorldPacket data(SMSG_CAST_FAILED, 1+4+1+4); data << uint8(0); data << uint32(883); data << uint8(SPELL_FAILED_TARGETS_DEAD); SendPacket(&data); owner->RemoveSpellCooldown(883, false); return PET_LOAD_ERROR; } // check temporary summoned pets like mage water elemental if (current && is_temporary_summoned) return PET_LOAD_ERROR; if (pet_type == HUNTER_PET) { CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(petentry); if (!creatureInfo || !creatureInfo->IsTameable(owner->CanTameExoticPets())) return PET_LOAD_ERROR; } Map* map = owner->GetMap(); uint32 guid = sObjectMgr->GenerateLowGuid(HIGHGUID_PET); Pet* pet = new Pet(owner, pet_type); LoadPetFromDBQueryHolder* holder = new LoadPetFromDBQueryHolder(pet_number, current, uint32(time(NULL) - fields[14].GetUInt32()), fields[13].GetString(), savedhealth, savedmana); if (!pet->Create(guid, map, owner->GetPhaseMask(), petentry, pet_number) || !holder->Initialize()) { delete pet; delete holder; return PET_LOAD_ERROR; } float px, py, pz; owner->GetClosePoint(px, py, pz, pet->GetObjectSize(), PET_FOLLOW_DIST, pet->GetFollowAngle()); if (!pet->IsPositionValid()) { sLog->outError("Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", pet->GetGUIDLow(), pet->GetEntry(), pet->GetPositionX(), pet->GetPositionY()); delete pet; delete holder; return PET_LOAD_ERROR; } pet->SetLoading(true); pet->Relocate(px, py, pz, owner->GetOrientation()); pet->setPetType(pet_type); pet->setFaction(owner->getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); if (pet->IsCritter()) { map->AddToMap(pet->ToCreature(), true); pet->SetLoading(false); // xinef, mine delete holder; return PET_LOAD_OK; } pet->GetCharmInfo()->SetPetNumber(pet_number, pet->IsPermanentPetFor(owner)); pet->SetDisplayId(fields[3].GetUInt32()); pet->SetNativeDisplayId(fields[3].GetUInt32()); uint32 petlevel = fields[4].GetUInt8(); pet->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); pet->SetName(fields[8].GetString()); switch (pet->getPetType()) { case SUMMON_PET: petlevel = owner->getLevel(); if (pet->IsPetGhoul()) pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x400); // class = rogue else pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus pet->SetSheath(SHEATH_STATE_MELEE); pet->SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED); pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet abandon, cancel) pet->SetMaxPower(POWER_HAPPINESS, pet->GetCreatePowers(POWER_HAPPINESS)); pet->SetPower(POWER_HAPPINESS, fields[12].GetUInt32()); pet->setPowerType(POWER_FOCUS); break; default: if (!pet->IsPetGhoul()) sLog->outError("Pet have incorrect type (%u) for pet loading.", pet->getPetType()); break; } pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped here pet->SetCreatorGUID(owner->GetGUID()); owner->SetMinion(pet, true); pet->InitStatsForLevel(petlevel); pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); pet->SynchronizeLevelWithOwner(); pet->SetReactState(ReactStates(fields[6].GetUInt8())); pet->SetCanModifyStats(true); // set current pet as current // 0=current // 1..MAX_PET_STABLES in stable slot // PET_SAVE_NOT_IN_SLOT(100) = not stable slot (summoning)) if (petSlot) { SQLTransaction trans = CharacterDatabase.BeginTransaction(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID); stmt->setUInt8(0, uint8(PET_SAVE_NOT_IN_SLOT)); stmt->setUInt32(1, owner->GetGUIDLow()); stmt->setUInt8(2, uint8(PET_SAVE_AS_CURRENT)); stmt->setUInt32(3, pet_number); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID); stmt->setUInt8(0, uint8(PET_SAVE_AS_CURRENT)); stmt->setUInt32(1, owner->GetGUIDLow()); stmt->setUInt32(2, pet_number); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); } // Send fake summon spell cast - this is needed for correct cooldown application for spells // Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside // TODO: pets should be summoned from real cast instead of just faking it? if (summon_spell_id) { WorldPacket data(SMSG_SPELL_GO, (8+8+4+4+2)); data.append(owner->GetPackGUID()); data.append(owner->GetPackGUID()); data << uint8(0); data << uint32(summon_spell_id); data << uint32(256); // CAST_FLAG_UNKNOWN3 data << uint32(0); owner->SendMessageToSet(&data, true); } // do it as early as possible! pet->InitTalentForLevel(); // set original talents points before spell loading if (!is_temporary_summoned) pet->GetCharmInfo()->InitPetActionBar(); map->AddToMap(pet->ToCreature(), true); if (pet->getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current pet->SetPower(POWER_MANA, pet->GetMaxPower(POWER_MANA)); else { pet->SetHealth(savedhealth > pet->GetMaxHealth() ? pet->GetMaxHealth() : savedhealth); pet->SetPower(POWER_MANA, savedmana > pet->GetMaxPower(POWER_MANA) ? pet->GetMaxPower(POWER_MANA) : savedmana); } pet->SetAsynchLoadType(asynchLoadType); // xinef: clear any old result if (_loadPetFromDBSecondCallback.ready()) { SQLQueryHolder* param; _loadPetFromDBSecondCallback.get(param); delete param; } _loadPetFromDBSecondCallback.cancel(); _loadPetFromDBSecondCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder); return PET_LOAD_OK; }
void CPlayer::CreatePet(uint32 entry, bool classcheck) { if (classcheck && getClass() != CLASS_HUNTER) return; CreatureInfo const *cinfo = sObjectMgr.GetCreatureTemplate(entry); if (!cinfo) { BoxChat << MSG_COLOR_WHITE << " This pet doesn't exist in our database. Please report that creature " << entry << " is missing." << std::endl; return; } CreatureCreatePos pos(GetSession()->GetPlayer(), GetOrientation()); Creature* pCreature = new Creature; // used guids from specially reserved range (can be 0 if no free values) uint32 lowguid = sObjectMgr.GenerateStaticCreatureLowGuid(); if (!lowguid) return; if (!pCreature->Create(lowguid, pos, cinfo)) { delete pCreature; return; } //-------------------------------------------------- if (GetPetGuid()) UnsummonPetTemporaryIfAny(); Pet* pet = new Pet(HUNTER_PET); if (!pet->CreateBaseAtCreature(pCreature)) { delete pet; return; } pet->SetOwnerGuid(GetObjectGuid()); pet->SetCreatorGuid(GetObjectGuid()); pet->setFaction(getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, 13481); if (IsPvP()) pet->SetPvP(true); if (!pet->InitStatsForLevel(pCreature->getLevel())) { sLog.outError("Pet::InitStatsForLevel() failed for creature (Entry: %u)!", pCreature->GetEntry()); delete pet; return; } pet->GetCharmInfo()->SetPetNumber(sObjectMgr.GeneratePetNumber(), true); // this enables pet details window (Shift+P) pet->AIM_Initialize(); pet->InitPetCreateSpells(); pet->SetHealth(pet->GetMaxHealth()); // add to world pet->GetMap()->Add((Creature*)pet); // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, 70); for (auto x = 0; x < 6; x++) { pet->SetPower(POWER_HAPPINESS, 66600000); pet->ModifyLoyalty(150000); pet->TickLoyaltyChange(); pet->SetTP(350); } // caster have pet now SetPet(pet); pet->SavePetToDB(PET_SAVE_AS_CURRENT); PetSpellInitialize(); pet->learnSpell(27052); pet->learnSpell(35698); pet->learnSpell(25076); pet->learnSpell(27048); pet->learnSpell(27053); pet->learnSpell(27054); pet->learnSpell(27062); pet->learnSpell(27047); pet->learnSpell(24551); delete pCreature; }
void WorldSession::HandlePetRename(WorldPacket & recv_data) { sLog->outDetail("HandlePetRename. CMSG_PET_RENAME"); uint64 petguid; uint8 isdeclined; std::string name; DeclinedName declinedname; recv_data >> petguid; recv_data >> name; recv_data >> isdeclined; Pet* pet = ObjectAccessor::FindPet(petguid); // check it! if (!pet || !pet->isPet() || ((Pet*)pet)->getPetType()!= HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) return; PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if (res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name, NULL); return; } if (sObjectMgr->IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); Unit* owner = pet->GetOwner(); if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) { recv_data >> declinedname.name[i]; } std::wstring wname; Utf8toWStr(name, wname); if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) CharacterDatabase.EscapeString(declinedname.name[i]); trans->PAppend("DELETE FROM character_pet_declinedname WHERE owner = '%u' AND id = '%u'", _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); trans->PAppend("INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES ('%u', '%u', '%s', '%s', '%s', '%s', '%s')", pet->GetCharmInfo()->GetPetNumber(), _player->GetGUIDLow(), declinedname.name[0].c_str(), declinedname.name[1].c_str(), declinedname.name[2].c_str(), declinedname.name[3].c_str(), declinedname.name[4].c_str()); } CharacterDatabase.EscapeString(name); trans->PAppend("UPDATE character_pet SET name = '%s', renamed = '1' WHERE owner = '%u' AND id = '%u'", name.c_str(), _player->GetGUIDLow(), pet->GetCharmInfo()->GetPetNumber()); CharacterDatabase.CommitTransaction(trans); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped }
bool ChatHandler::HandleCreatePetCommand(const char* /*args*/) { Player* player = m_session->GetPlayer(); Creature* creatureTarget = getSelectedCreature(); if (!creatureTarget || creatureTarget->isPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) { PSendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); return false; } CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creatureTarget->GetEntry()); // Creatures with family 0 crashes the server if (cInfo->family == 0) { PSendSysMessage("This creature cannot be tamed. (family id: 0)."); SetSentErrorMessage(true); return false; } if (player->GetPetGUID()) { PSendSysMessage("You already have a pet"); SetSentErrorMessage(true); return false; } // Everything looks OK, create new pet Pet* pet = new Pet(player, HUNTER_PET); if (!pet->CreateBaseAtCreature(creatureTarget)) { delete pet; PSendSysMessage("Error 1"); return false; } creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); if (!pet->InitStatsForLevel(creatureTarget->getLevel())) { sLog->outError("InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); PSendSysMessage("Error 2"); delete pet; return false; } // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()-1); pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); // this enables pet details window (Shift+P) pet->InitPetCreateSpells(); pet->SetFullHealth(); pet->GetMap()->AddToMap(pet->ToCreature()); // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()); player->SetMinion(pet, true); pet->SavePetToDB(PET_SAVE_AS_CURRENT); player->PetSpellInitialize(); return true; }
void WorldSession::HandlePetRename(WorldPacket & recvData) { TC_LOG_INFO("network", "HandlePetRename. CMSG_PET_RENAME"); std::string name; DeclinedName declinedname; uint8 declinedNameLength[MAX_DECLINED_NAME_CASES] = {0, 0, 0, 0, 0}; recvData.read_skip<uint32>(); // unk, client send 2048, maybe flags ? bool hasName = !recvData.ReadBit(); bool isdeclined = recvData.ReadBit(); if (isdeclined) for(int i = 0; i < MAX_DECLINED_NAME_CASES; i++) declinedNameLength[i] = recvData.ReadBits(7); if (hasName) { uint8 nameLenght = recvData.ReadBits(8); name = recvData.ReadString(nameLenght); } Pet* pet = GetPlayer()->GetPet(); // check it! if (!pet || !pet->isPet() || pet->getPetType() != HUNTER_PET || !pet->HasByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED) || pet->GetOwnerGUID() != _player->GetGUID() || !pet->GetCharmInfo()) { return; } PetNameInvalidReason res = ObjectMgr::CheckPetName(name); if (res != PET_NAME_SUCCESS) { SendPetNameInvalid(res, name, NULL); return; } if (sObjectMgr->IsReservedName(name)) { SendPetNameInvalid(PET_NAME_RESERVED, name, NULL); return; } pet->SetName(name); Player* owner = pet->GetOwner(); if (owner && owner->GetGroup()) owner->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_NAME); pet->RemoveByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED); if (isdeclined) { for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) declinedname.name[i] = recvData.ReadString(declinedNameLength[i]); std::wstring wname; Utf8toWStr(name, wname); if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); return; } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (isdeclined) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_DECLINED_NAME); stmt->setUInt32(0, pet->GetCharmInfo()->GetPetNumber()); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_ADD_PET_DECLINED_NAME); stmt->setUInt32(0, _player->GetGUIDLow()); for (uint8 i = 0; i < 5; i++) stmt->setString(i+1, declinedname.name[i]); trans->Append(stmt); } CharacterDatabase.CommitTransaction(trans); pet->SavePetToDB(); pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, uint32(time(NULL))); // cast can't be helped }