diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 3dc225241..7cd41ff47 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1244,7 +1244,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x4BF*/ { "SMSG_UNKNOWN_1215", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4C0*/ { "SMSG_TALENTS_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4C1*/ { "CMSG_LEARN_PREVIEW_TALENTS", STATUS_LOGGEDIN, &WorldSession::HandleLearnPreviewTalents }, - /*0x4C2*/ { "CMSG_LEARN_PREVIEW_TALENTS_PET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4C2*/ { "CMSG_LEARN_PREVIEW_TALENTS_PET", STATUS_LOGGEDIN, &WorldSession::HandleLearnPreviewTalentsPet }, /*0x4C3*/ { "UMSG_UNKNOWN_1219", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4C4*/ { "UMSG_UNKNOWN_1220", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4C5*/ { "UMSG_UNKNOWN_1221", STATUS_NEVER, &WorldSession::Handle_NULL }, diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 9168cd974..cc4fb8412 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -510,6 +510,7 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) return; } pet->resetTalents(); + _player->SendTalentsInfoData(true); } void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) @@ -669,4 +670,31 @@ void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data ) recv_data >> guid >> talent_id >> requested_rank; _player->LearnPetTalent(guid, talent_id, requested_rank); + _player->SendTalentsInfoData(true); +} + +void WorldSession::HandleLearnPreviewTalentsPet( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_LEARN_PREVIEW_TALENTS_PET"); + + CHECK_PACKET_SIZE(recv_data, 8+4); + + uint64 guid; + recv_data >> guid; + + uint32 talentsCount; + recv_data >> talentsCount; + + uint32 talentId, talentRank; + + for(uint32 i = 0; i < talentsCount; ++i) + { + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4); + + recv_data >> talentId >> talentRank; + + _player->LearnPetTalent(guid, talentId, talentRank, true); + } + + _player->SendTalentsInfoData(true); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index cdda08259..c165c5fd5 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18080,25 +18080,7 @@ void Player::SendInitialPacketsBeforeAddToMap() m_achievementMgr.SendAllAchievementData(); UpdateZone(GetZoneId()); - uint32 count = 0; - data.Initialize(SMSG_EQUIPMENT_SET_LIST, 4); - size_t count_pos = data.wpos(); - data << uint32(count); // count placeholder - for(EquipmentSets::iterator itr = m_EquipmentSets.begin(); itr != m_EquipmentSets.end(); ++itr) - { - if(itr->second.state==EQUIPMENT_SET_DELETED) - continue; - data.appendPackGUID(itr->second.Guid); - data << uint32(itr->first); - data << itr->second.Name; - data << itr->second.IconName; - for(uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) - data.appendPackGUID(MAKE_NEW_GUID(itr->second.Items[i], 0, HIGHGUID_ITEM)); - - ++count; // client have limit but it checked at loading and set - } - data.put(count_pos,count); - GetSession()->SendPacket(&data); + SendEquipmentSetList(); data.Initialize(SMSG_LOGIN_SETTIMESPEED, 8); data << uint32(secsToTimeBitFields(sWorld.GetGameTime())); @@ -19669,19 +19651,80 @@ void Player::BuildPlayerTalentsInfoData(WorldPacket *data) void Player::BuildPetTalentsInfoData(WorldPacket *data) { - *data << uint32(0); // unspentTalentPoints - *data << uint8(0); // talentCount - /*for(talentCount) + uint32 unspentTalentPoints = 0; + size_t pointsPos = data->wpos(); + *data << uint32(unspentTalentPoints); // [PH], unspentTalentPoints + + uint8 talentIdCount = 0; + size_t countPos = data->wpos(); + *data << uint8(talentIdCount); // [PH], talentIdCount + + Pet *pet = GetPet(); + if(!pet) + return; + + unspentTalentPoints = pet->GetFreeTalentPoints(); + + data->put(pointsPos, unspentTalentPoints); // put real points + + CreatureInfo const *ci = pet->GetCreatureInfo(); + if(!ci) + return; + + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); + if(!pet_family || pet_family->petTalentType < 0) + return; + + for(uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId) { - *data << uint32(0); // Talent.dbc - *data << uint8(0); // maxRank - }*/ + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentTabId ); + if(!talentTabInfo) + continue; + + if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) + continue; + + for(uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) + { + TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); + if(!talentInfo) + continue; + + // skip another tab talents + if(talentInfo->TalentTab != talentTabId) + continue; + + // find max talent rank + int32 curtalent_maxrank = -1; + for(int32 k = 4; k > -1; --k) + { + if(talentInfo->RankID[k] && pet->HasSpell(talentInfo->RankID[k])) + { + curtalent_maxrank = k; + break; + } + } + + // not learned talent + if(curtalent_maxrank < 0) + continue; + + *data << uint32(talentInfo->TalentID); // Talent.dbc + *data << uint8(curtalent_maxrank); // talentMaxRank (0-4) + + ++talentIdCount; + } + + data->put(countPos, talentIdCount); // put real count + + break; + } } void Player::SendTalentsInfoData(bool pet) { WorldPacket data(SMSG_TALENTS_INFO, 50); - data << uint8(pet); + data << uint8(pet ? 1 : 0); if(pet) BuildPetTalentsInfoData(&data); else @@ -19721,7 +19764,7 @@ void Player::BuildEnchantmentsInfoData(WorldPacket *data) } } -void Player::LearnTalent(uint32 talentId, uint32 talentRank) +void Player::LearnTalent(uint32 talentId, uint32 talentRank, bool skipPrevRanks) { uint32 CurTalentPoints = GetFreeTalentPoints(); @@ -19745,8 +19788,12 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) if( (getClassMask() & talentTabInfo->ClassMask) == 0 ) return; + // check for LearnPreviewTalents case + if(skipPrevRanks && (CurTalentPoints < (talentRank + 1))) + return; + // prevent skip talent ranks (cheating) - if(talentRank > 0 && !HasSpell(talentInfo->RankID[talentRank-1])) + if(talentRank > 0 && !HasSpell(talentInfo->RankID[talentRank-1]) && !skipPrevRanks) return; // Check if it requires another talent @@ -19820,7 +19867,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) SetFreeTalentPoints(CurTalentPoints - 1); } -void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank) +void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank, bool skipPrevRanks) { Pet *pet = GetPet(); @@ -19865,8 +19912,12 @@ void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank) if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) return; + // check for LearnPreviewTalents case + if(skipPrevRanks && (CurTalentPoints < (talentRank + 1))) + return; + // prevent skip talent ranks (cheating) - if(talentRank > 0 && !pet->HasSpell(talentInfo->RankID[talentRank-1])) + if(talentRank > 0 && !pet->HasSpell(talentInfo->RankID[talentRank-1]) && !skipPrevRanks) return; // Check if it requires another talent @@ -19937,6 +19988,29 @@ void Player::LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank) sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talentId, talentRank, spellid); } +void Player::SendEquipmentSetList() +{ + uint32 count = 0; + WorldPacket data(SMSG_EQUIPMENT_SET_LIST, 4); + size_t count_pos = data.wpos(); + data << uint32(count); // count placeholder + for(EquipmentSets::iterator itr = m_EquipmentSets.begin(); itr != m_EquipmentSets.end(); ++itr) + { + if(itr->second.state==EQUIPMENT_SET_DELETED) + continue; + data.appendPackGUID(itr->second.Guid); + data << uint32(itr->first); + data << itr->second.Name; + data << itr->second.IconName; + for(uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) + data.appendPackGUID(MAKE_NEW_GUID(itr->second.Items[i], 0, HIGHGUID_ITEM)); + + ++count; // client have limit but it checked at loading and set + } + data.put(count_pos,count); + GetSession()->SendPacket(&data); +} + void Player::SetEquipmentSet(uint32 index, EquipmentSet eqset) { EquipmentSet& eqslot = m_EquipmentSets[index]; diff --git a/src/game/Player.h b/src/game/Player.h index 2fa1477f6..a3190acab 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1475,8 +1475,8 @@ class MANGOS_DLL_SPEC Player : public Unit void BuildPlayerTalentsInfoData(WorldPacket *data); void BuildPetTalentsInfoData(WorldPacket *data); void SendTalentsInfoData(bool pet); - void LearnTalent(uint32 talentId, uint32 talentRank); - void LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank); + void LearnTalent(uint32 talentId, uint32 talentRank, bool skipPrevRanks = false); + void LearnPetTalent(uint64 petGuid, uint32 talentId, uint32 talentRank, bool skipPrevRanks = false); uint32 CalculateTalentsPoints() const; @@ -1867,6 +1867,7 @@ class MANGOS_DLL_SPEC Player : public Unit void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType); void CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex); + void SendEquipmentSetList(); void SetEquipmentSet(uint32 index, EquipmentSet eqset); void DeleteEquipmentSet(uint64 setGuid); diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index 32a2340fe..5697bfd6e 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -41,7 +41,7 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) { - sLog.outDebug("CMSG_UNKNOWN_1217"); + sLog.outDebug("CMSG_LEARN_PREVIEW_TALENTS"); CHECK_PACKET_SIZE(recvPacket, 4); @@ -56,7 +56,7 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) recvPacket >> talentId >> talentRank; - _player->LearnTalent(talentId, talentRank); + _player->LearnTalent(talentId, talentRank, true); } _player->SendTalentsInfoData(false); diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 043927d7a..d41f8d2b8 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -579,6 +579,7 @@ class MANGOS_DLL_SPEC WorldSession void HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ); void HandlePetCastSpellOpcode( WorldPacket& recvPacket ); void HandlePetLearnTalent( WorldPacket& recvPacket ); + void HandleLearnPreviewTalentsPet( WorldPacket& recvPacket ); void HandleSetActionBar(WorldPacket& recv_data);