diff options
Diffstat (limited to 'src/server/game/Entities')
| -rw-r--r-- | src/server/game/Entities/Pet/Pet.cpp | 5 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 416 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 75 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/StatSystem.cpp | 2 |
4 files changed, 183 insertions, 315 deletions
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 0fe830f861e..52045f46472 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -341,7 +341,8 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c if (owner->GetGroup()) owner->SetGroupUpdateFlag(GROUP_UPDATE_PET); - owner->SendTalentsInfoData(true); + // TODO: 6.x remove/update pet talents + //owner->SendTalentsInfoData(true); if (getPetType() == HUNTER_PET) { @@ -1735,6 +1736,7 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= NULL*/) void Pet::InitTalentForLevel() { + /* TODO: 6.x remove/update pet talents uint8 level = getLevel(); uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); // Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent) @@ -1745,6 +1747,7 @@ void Pet::InitTalentForLevel() if (!m_loading) GetOwner()->SendTalentsInfoData(true); + */ } uint8 Pet::GetMaxTalentPointsForLevel(uint8 level) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c0753f72942..e412aa43098 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -32,6 +32,7 @@ #include "ChannelMgr.h" #include "CharacterDatabaseCleaner.h" #include "CharacterPackets.h" +#include "TalentPackets.h" #include "Chat.h" #include "Common.h" #include "ConditionMgr.h" @@ -2985,7 +2986,7 @@ void Player::GiveLevel(uint8 level) void Player::InitTalentForLevel() { if (!GetSession()->PlayerLoading()) - SendTalentsInfoData(false); // update at client + SendTalentsInfoData(); // update at client } void Player::InitStatsForLevel(bool reapplyMods) @@ -3308,20 +3309,29 @@ void DeleteSpellFromAllPlayers(uint32 spellId) } } -bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) +bool Player::AddTalent(uint32 talentId, uint8 spec) { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + TalentEntry const* talentEntry = sTalentStore.LookupEntry(talentId); + + // Check if talent exists in Talent.dbc + if (!talentEntry) + { + TC_LOG_ERROR("spells", "Player::addTalent: Talent %u not found", talentId); + return false; + } + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentEntry->SpellID); if (!spellInfo) { // do character spell book cleanup (all characters) - if (!IsInWorld() && !learning) // spell load case + if (!IsInWorld()) // spell load case { - TC_LOG_ERROR("spells", "Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.", spellId); + TC_LOG_ERROR("spells", "Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.", talentEntry->SpellID); - DeleteSpellFromAllPlayers(spellId); + DeleteSpellFromAllPlayers(talentEntry->SpellID); } else - TC_LOG_ERROR("spells", "Player::addSpell: Non-existed in SpellStore spell #%u request.", spellId); + TC_LOG_ERROR("spells", "Player::addSpell: Non-existed in SpellStore spell #%u request.", talentEntry->SpellID); return false; } @@ -3329,35 +3339,25 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) if (!SpellMgr::IsSpellValid(spellInfo, this, false)) { // do character spell book cleanup (all characters) - if (!IsInWorld() && !learning) // spell load case + if (!IsInWorld()) // spell load case { - TC_LOG_ERROR("spells", "Player::addTalent: Broken spell #%u learning not allowed, deleting for all characters in `character_talent`.", spellId); + TC_LOG_ERROR("spells", "Player::addTalent: Broken spell #%u learning not allowed, deleting for all characters in `character_talent`.", talentEntry->SpellID); - DeleteSpellFromAllPlayers(spellId); + DeleteSpellFromAllPlayers(talentEntry->SpellID); } else - TC_LOG_ERROR("spells", "Player::addTalent: Broken spell #%u learning not allowed.", spellId); - - return false; - } + TC_LOG_ERROR("spells", "Player::addTalent: Broken spell #%u learning not allowed.", talentEntry->SpellID); - TalentEntry const* talentEntry = GetTalentBySpellID(spellId); - - // Check if talent exists in Talent.dbc - if (!talentEntry) { - TC_LOG_ERROR("spells", "Player::addTalent: Learning non-talent spell %u not allowed.", spellId); return false; } - TalentSpecInfo* talentSpecInfo = GetTalentSpecInfo(spec); + TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(spec); // Check if player already has this talent - if (talentSpecInfo->HasTalent(spellId)) + if (talentGroupInfo->HasTalent(talentId)) return false; - talentSpecInfo->Talents[talentEntry->TierID].SpellID = spellId; - if (learning) - talentSpecInfo->Talents[talentEntry->TierID].State = PLAYERSPELL_NEW; + talentGroupInfo->Talents[talentEntry->TierID] = talentId; return true; } @@ -3707,7 +3707,7 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const bool Player::IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const { - if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec()))) + if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) return spellInfo->Id == chrSpec->MasterySpellID[0] || spellInfo->Id == chrSpec->MasterySpellID[1]; return false; @@ -4121,7 +4121,8 @@ bool Player::ResetTalents(bool no_cost) RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - uint8 spec = GetActiveSpec(); + uint8 group = GetActiveTalentGroup(); + uint32 specID = GetActiveTalentSpec(); for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) { @@ -4147,13 +4148,10 @@ bool Player::ResetTalents(bool no_cost) for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL) RemoveSpell(_spellEntry->Effects[i].TriggerSpell, true); - - // Reset talents store - GetTalentSpecInfo(spec)->Reset(); } // Remove all specialization specific spells and give default ones which were overriden - auto specSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(GetActiveSpec())); + auto specSpells = sSpecializationSpellsBySpecStore.find(specID); if (specSpells != sSpecializationSpellsBySpecStore.end()) { for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) @@ -4168,12 +4166,14 @@ bool Player::ResetTalents(bool no_cost) } // Unlearn masteries - ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(spec)); + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(specID); for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) if (uint32 mastery = chrSpec->MasterySpellID[i]) RemoveAurasDueToSpell(mastery); - SetTalentSpec(spec, 0); + // Reset talents store + GetTalentGroupInfo(group)->Reset(); + SetTalentSpec(group, 0); SQLTransaction trans = CharacterDatabase.BeginTransaction(); _SaveTalents(trans); @@ -4265,9 +4265,9 @@ bool Player::HasSpell(uint32 spell) const !itr->second->disabled); } -bool Player::HasTalent(uint32 spell, uint8 spec) +bool Player::HasTalent(uint32 talentId, uint8 group) { - return GetTalentSpecInfo(spec)->HasTalent(spell); + return GetTalentGroupInfo(group)->HasTalent(talentId); } bool Player::HasActiveSpell(uint32 spell) const @@ -6269,7 +6269,7 @@ void Player::SendActionButtons(uint32 state) const data << uint8(state); GetSession()->SendPacket(&data); - TC_LOG_INFO("network", "Action Buttons for '%s' spec '%u' Sent", GetGUID().ToString().c_str(), GetActiveSpec()); + TC_LOG_INFO("network", "Action Buttons for '%s' group '%u' Sent", GetGUID().ToString().c_str(), GetActiveTalentGroup()); } bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type) @@ -9684,6 +9684,7 @@ void Player::SendTalentWipeConfirm(ObjectGuid guid) void Player::ResetPetTalents() { + /* TODO: 6.x remove/update pet talents // This needs another gossip option + NPC text as a confirmation. // The confirmation gossip listid has the text: "Yes, please do." Pet* pet = GetPet(); @@ -9699,6 +9700,7 @@ void Player::ResetPetTalents() } pet->resetTalents(); SendTalentsInfoData(true); + */ } /*********************************************************/ @@ -14117,7 +14119,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool break; } case GOSSIP_OPTION_LEARNDUALSPEC: - if (!(GetSpecsCount() == 1 && creature->isCanTrainingAndResetTalentsOf(this) && !(getLevel() < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)))) + if (!(GetTalentGroupsCount() == 1 && creature->isCanTrainingAndResetTalentsOf(this) && !(getLevel() < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)))) canTalk = false; break; case GOSSIP_OPTION_UNLEARNTALENTS: @@ -14331,7 +14333,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men GetSession()->SendTrainerList(guid); break; case GOSSIP_OPTION_LEARNDUALSPEC: - if (GetSpecsCount() == 1 && getLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)) + if (GetTalentGroupsCount() == 1 && getLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)) { // Cast spells that teach dual spec // Both are also ImplicitTarget self and must be cast by player @@ -17431,19 +17433,19 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) //mails are loaded only when needed ;-) - when player in game click on mailbox. //_LoadMail(); - SetSpecsCount(fields[53].GetUInt8()); - SetActiveSpec(fields[54].GetUInt8()); + SetTalentGroupsCount(fields[53].GetUInt8()); + SetActiveTalentGroup(fields[54].GetUInt8()); // sanity check - if (GetSpecsCount() > MAX_TALENT_SPECS || GetActiveSpec() > MAX_TALENT_SPEC || GetSpecsCount() < MIN_TALENT_SPECS) + if (GetTalentGroupsCount() > MAX_TALENT_GROUPS || GetActiveTalentGroup() > MAX_TALENT_GROUP || GetTalentGroupsCount() < MIN_TALENT_GROUPS) { - SetActiveSpec(0); - TC_LOG_ERROR("entities.player", "Player %s (%s) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUID().ToString().c_str(), GetSpecsCount(), GetActiveSpec()); + TC_LOG_ERROR("entities.player", "Player %s (%s) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUID().ToString().c_str(), GetTalentGroupsCount(), GetActiveTalentGroup()); + SetActiveTalentGroup(0); } // Only load selected specializations, learning mastery spells requires this - Tokenizer talentSpecs(fields[26].GetString(), ' ', MAX_TALENT_SPECS); - for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) + Tokenizer talentSpecs(fields[26].GetString(), ' ', MAX_TALENT_GROUPS); + for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i) { if (i >= talentSpecs.size()) break; @@ -17804,7 +17806,7 @@ void Player::_LoadGlyphAuras() { for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) { - if (uint32 glyph = GetGlyph(GetActiveSpec(), i)) + if (uint32 glyph = GetGlyph(GetActiveTalentGroup(), i)) { if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph)) { @@ -19104,7 +19106,7 @@ void Player::SaveToDB(bool create /*=false*/) stmt->setUInt32(index++, GetTalentResetTime()); ss.str(""); - for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) + for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i) ss << GetTalentSpec(i) << " "; stmt->setString(index++, ss.str()); stmt->setUInt16(index++, (uint16)m_ExtraFlags); @@ -19141,8 +19143,8 @@ void Player::SaveToDB(bool create /*=false*/) stmt->setUInt32(index++, GetSession()->GetLatency()); - stmt->setUInt8(index++, GetSpecsCount()); - stmt->setUInt8(index++, GetActiveSpec()); + stmt->setUInt8(index++, GetTalentGroupsCount()); + stmt->setUInt8(index++, GetActiveTalentGroup()); ss.str(""); for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) @@ -19233,7 +19235,7 @@ void Player::SaveToDB(bool create /*=false*/) stmt->setUInt32(index++, GetTalentResetTime()); ss.str(""); - for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) + for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i) ss << GetTalentSpec(i) << " "; stmt->setString(index++, ss.str()); stmt->setUInt16(index++, (uint16)m_ExtraFlags); @@ -19270,8 +19272,8 @@ void Player::SaveToDB(bool create /*=false*/) stmt->setUInt32(index++, GetSession()->GetLatency()); - stmt->setUInt8(index++, GetSpecsCount()); - stmt->setUInt8(index++, GetActiveSpec()); + stmt->setUInt8(index++, GetTalentGroupsCount()); + stmt->setUInt8(index++, GetActiveTalentGroup()); ss.str(""); for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) @@ -19377,7 +19379,7 @@ void Player::_SaveActions(SQLTransaction& trans) case ACTIONBUTTON_NEW: stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACTION); stmt->setUInt64(0, GetGUID().GetCounter()); - stmt->setUInt8(1, GetActiveSpec()); + stmt->setUInt8(1, GetActiveTalentGroup()); stmt->setUInt8(2, itr->first); stmt->setUInt32(3, itr->second.GetAction()); stmt->setUInt8(4, uint8(itr->second.GetType())); @@ -19392,7 +19394,7 @@ void Player::_SaveActions(SQLTransaction& trans) stmt->setUInt8(1, uint8(itr->second.GetType())); stmt->setUInt64(2, GetGUID().GetCounter()); stmt->setUInt8(3, itr->first); - stmt->setUInt8(4, GetActiveSpec()); + stmt->setUInt8(4, GetActiveTalentGroup()); trans->Append(stmt); itr->second.uState = ACTIONBUTTON_UNCHANGED; @@ -19402,7 +19404,7 @@ void Player::_SaveActions(SQLTransaction& trans) stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC); stmt->setUInt64(0, GetGUID().GetCounter()); stmt->setUInt8(1, itr->first); - stmt->setUInt8(2, GetActiveSpec()); + stmt->setUInt8(2, GetActiveTalentGroup()); trans->Append(stmt); m_actionButtons.erase(itr++); @@ -23054,7 +23056,7 @@ void Player::SendInitialPacketsBeforeAddToMap() // SMSG_SET_FLAT_SPELL_MODIFIER // SMSG_UPDATE_AURA_DURATION - SendTalentsInfoData(false); + SendTalentsInfoData(); data.Initialize(SMSG_WORLD_SERVER_INFO, 1 + 1 + 4 + 4); data.WriteBit(0); // HasRestrictedLevel @@ -24802,7 +24804,7 @@ void Player::InitGlyphsForLevel() void Player::SetGlyph(uint8 slot, uint32 glyph) { - _talentMgr->SpecInfo[GetActiveSpec()].Glyphs[slot] = glyph; + _talentMgr->GroupInfo[GetActiveTalentGroup()].Glyphs[slot] = glyph; SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); } @@ -25487,7 +25489,7 @@ void Player::CompletedAchievement(AchievementEntry const* entry) bool Player::LearnTalent(uint32 talentId) { - uint8 spec = GetActiveSpec(); + uint8 group = GetActiveTalentGroup(); TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); @@ -25498,13 +25500,15 @@ bool Player::LearnTalent(uint32 talentId) if (getClass() != talentInfo->ClassID) return false; - // Check player level. - if (getLevel() < (15*talentInfo->TierID + 15)) + // Check player level + // TODO: fix level requirements for deathknights + uint8 levelReq = std::min(15*talentInfo->TierID + 15, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); + if (getLevel() < levelReq) return false; // Check if such tier talent hasn't been picked already - TalentSpecInfo* talentSpecInfo = GetTalentSpecInfo(spec); - if (talentSpecInfo->Talents[talentInfo->TierID].SpellID != 0) + TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(group); + if (talentGroupInfo->Talents[talentInfo->TierID]) return false; // spell not set in talent.dbc @@ -25519,16 +25523,10 @@ bool Player::LearnTalent(uint32 talentId) if (HasSpell(spellid)) return false; - // learn! (other talent ranks will unlearned at learning) - LearnSpell(spellid, false); - AddTalent(spellid, spec, true); - - TC_LOG_INFO("misc", "TalentID: %u Spell: %u Spec: %u\n", talentId, spellid, spec); - - // set talent tree for player - if (!GetTalentSpec(spec)) + // set talent spec for player + if (!GetTalentSpec(group)) { - SetTalentSpec(spec, talentInfo->SpecID); + SetTalentSpec(group, talentInfo->SpecID); // Replace default spells by specialization spells auto specSpells = sSpecializationSpellsBySpecStore.find(talentInfo->SpecID); @@ -25553,6 +25551,16 @@ bool Player::LearnTalent(uint32 talentId) } } + // Check talent spec + if (talentInfo->SpecID != GetTalentSpec(group)) + return false; + + // learn! (other talent ranks will unlearned at learning) + LearnSpell(spellid, false); + AddTalent(talentId, group); + + TC_LOG_INFO("misc", "TalentID: %u Spell: %u Group: %u\n", talentId, spellid, group); + return true; } @@ -25630,160 +25638,38 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const return false; } -void Player::BuildPlayerTalentsInfoData(WorldPacket* data) -{ - /* TODO: 6.x update with new talent system (and move to packet class) - *data << uint32(GetFreeTalentPoints()); // unspentTalentPoints - *data << uint8(GetSpecsCount()); // talent group count (0, 1 or 2) - *data << uint8(GetActiveSpec()); // talent group index (0 or 1) - - if (GetSpecsCount()) - { - if (GetSpecsCount() > MAX_TALENT_SPECS) - SetSpecsCount(MAX_TALENT_SPECS); - - // loop through all specs (only 1 for now) - for (uint8 specIdx = 0; specIdx < GetSpecsCount(); ++specIdx) - { - *data << uint32(GetPrimaryTalentTree(specIdx)); - uint8 talentIdCount = 0; - size_t pos = data->wpos(); - *data << uint8(talentIdCount); // [PH], talentIdCount - - // find class talent tabs (all players have 3 talent tabs) - uint32 const* talentTabIds = GetTalentTabPages(getClass()); - - for (uint8 i = 0; i < MAX_TALENT_TABS; ++i) - { - uint32 talentTabId = talentTabIds[i]; - - 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 (0~4) - int8 curtalent_maxrank = -1; - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) - { - if (talentInfo->RankID[rank] && HasTalent(talentInfo->RankID[rank], specIdx)) - { - curtalent_maxrank = rank; - 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<uint8>(pos, talentIdCount); // put real count - - *data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count - - for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) - *data << uint16(GetGlyph(specIdx, i)); // GlyphProperties.dbc - } - } - */ -} - -void Player::BuildPetTalentsInfoData(WorldPacket* data) +void Player::SendTalentsInfoData() { - /* TODO: 6.x update with new talent system (and move to packet class) - 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; + WorldPackets::Talent::UpdateTalentData packet; - unspentTalentPoints = pet->GetFreeTalentPoints(); + packet.Info.ActiveGroup = GetActiveTalentGroup(); + + uint8 groupsCount = GetTalentGroupsCount(); - data->put<uint32>(pointsPos, unspentTalentPoints); // put real points - - CreatureTemplate const* ci = pet->GetCreatureTemplate(); - 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) + for (uint8 i = 0; i < groupsCount; ++i) { - 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) + TalentGroupInfo* groupInfo = GetTalentGroupInfo(i); + WorldPackets::Talent::TalentGroupInfo groupInfoPkt; + + groupInfoPkt.SpecID = groupInfo->SpecID; + + groupInfoPkt.TalentIDs.reserve(MAX_TALENT_TIERS); + for (uint32 x = 0; x < MAX_TALENT_TIERS; ++x) { - TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); - if (!talentInfo) - continue; - - // skip another tab talents - if (talentInfo->TalentTab != talentTabId) - continue; - - // find max talent rank (0~4) - int8 curtalent_maxrank = -1; - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) - { - if (talentInfo->RankID[rank] && pet->HasSpell(talentInfo->RankID[rank])) - { - curtalent_maxrank = rank; - break; - } - } - - // not learned talent - if (curtalent_maxrank < 0) - continue; - - *data << uint32(talentInfo->TalentID); // Talent.dbc - *data << uint8(curtalent_maxrank); // talentMaxRank (0-4) + // Do not send empty talents + if (!groupInfo->Talents[x]) + break; - ++talentIdCount; + groupInfoPkt.TalentIDs.push_back(groupInfo->Talents[x]); } + + for (uint32 x = 0; x < MAX_GLYPH_SLOT_INDEX; ++x) + groupInfoPkt.GlyphIDs[x] = groupInfo->Glyphs[x]; + + packet.Info.TalentGroups.push_back(groupInfoPkt); + } - data->put<uint8>(countPos, talentIdCount); // put real count - - break; - }*/ -} - -void Player::SendTalentsInfoData(bool pet) -{ - /* TODO: 6.x update with new talent system (and move to packet class) - WorldPacket data(SMSG_TALENTS_INFO, 50); - data << uint8(pet ? 1 : 0); - if (pet) - BuildPetTalentsInfoData(&data); - else - BuildPlayerTalentsInfoData(&data); - GetSession()->SendPacket(&data); - */ + GetSession()->SendPacket(packet.Write()); } void Player::BuildEnchantmentsInfoData(WorldPacket* data) @@ -26064,7 +25950,7 @@ void Player::SetMap(Map* map) void Player::_LoadGlyphs(PreparedQueryResult result) { - // SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = '%u' + // SELECT group, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = '%u' if (!result) return; @@ -26072,12 +25958,12 @@ void Player::_LoadGlyphs(PreparedQueryResult result) { Field* fields = result->Fetch(); - uint8 spec = fields[0].GetUInt8(); - if (spec >= GetSpecsCount()) + uint8 group = fields[0].GetUInt8(); + if (group >= GetTalentGroupsCount()) continue; for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) - _talentMgr->SpecInfo[spec].Glyphs[i] = fields[i + 1].GetUInt16(); + _talentMgr->GroupInfo[group].Glyphs[i] = fields[i + 1].GetUInt16(); } while (result->NextRow()); } @@ -26089,17 +25975,17 @@ void Player::_SaveGlyphs(SQLTransaction& trans) trans->Append(stmt); - for (uint8 spec = 0; spec < GetSpecsCount(); ++spec) + for (uint8 group = 0; group < GetTalentGroupsCount(); ++group) { uint8 index = 0; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_GLYPHS); stmt->setUInt64(index++, GetGUID().GetCounter()); - stmt->setUInt8(index++, spec); + stmt->setUInt8(index++, group); for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) - stmt->setUInt16(index++, uint16(GetGlyph(spec, i))); + stmt->setUInt16(index++, uint16(GetGlyph(group, i))); trans->Append(stmt); } @@ -26111,57 +25997,40 @@ void Player::_LoadTalents(PreparedQueryResult result) if (result) { do - AddTalent((*result)[0].GetUInt32(), (*result)[1].GetUInt8(), false); + AddTalent((*result)[0].GetUInt32(), (*result)[1].GetUInt8()); while (result->NextRow()); } } void Player::_SaveTalents(SQLTransaction& trans) { - PreparedStatement* stmt = NULL; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TALENT); + stmt->setUInt64(0, GetGUID().GetCounter()); + trans->Append(stmt); - for (uint8 spec = 0; spec < MAX_TALENT_SPECS; ++spec) + for (uint8 group = 0; group < MAX_TALENT_GROUPS; ++group) { - TalentSpecInfo* talentSpecInfo = GetTalentSpecInfo(spec); + TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(group); for (uint32 tier = 0; tier < MAX_TALENT_TIERS; ++tier) { - PlayerTalent* talent = &talentSpecInfo->Talents[tier]; - - if (talent->State == PLAYERSPELL_REMOVED || talent->State == PLAYERSPELL_CHANGED) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC); - stmt->setUInt64(0, GetGUID().GetCounter()); - stmt->setUInt32(1, talent->SpellID); - stmt->setUInt8(2, spec); - trans->Append(stmt); - } - - if (talent->State == PLAYERSPELL_NEW || talent->State == PLAYERSPELL_CHANGED) - { - stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT); - stmt->setUInt64(0, GetGUID().GetCounter()); - stmt->setUInt32(1, talent->SpellID); - stmt->setUInt8(2, spec); - trans->Append(stmt); - } - - if (talent->State == PLAYERSPELL_REMOVED) - talent->SpellID = 0; - - talent->State = PLAYERSPELL_UNCHANGED; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT); + stmt->setUInt64(0, GetGUID().GetCounter()); + stmt->setUInt32(1, talentGroupInfo->Talents[tier]); + stmt->setUInt8(2, group); + trans->Append(stmt); } } } -void Player::UpdateSpecCount(uint8 count) +void Player::UpdateTalentGroupCount(uint8 count) { - uint32 curCount = GetSpecsCount(); + uint32 curCount = GetTalentGroupsCount(); if (curCount == count) return; - if (GetActiveSpec() >= count) - ActivateSpec(0); + if (GetActiveTalentGroup() >= count) + ActivateTalentGroup(0); SQLTransaction trans = CharacterDatabase.BeginTransaction(); PreparedStatement* stmt = NULL; @@ -26187,7 +26056,7 @@ void Player::UpdateSpecCount(uint8 count) _SaveActions(trans); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC); - stmt->setUInt8(0, GetActiveSpec()); + stmt->setUInt8(0, GetActiveTalentGroup()); stmt->setUInt64(1, GetGUID().GetCounter()); trans->Append(stmt); @@ -26195,17 +26064,17 @@ void Player::UpdateSpecCount(uint8 count) CharacterDatabase.CommitTransaction(trans); - SetSpecsCount(count); + SetTalentGroupsCount(count); - SendTalentsInfoData(false); + SendTalentsInfoData(); } -void Player::ActivateSpec(uint8 spec) +void Player::ActivateTalentGroup(uint8 group) { - if (GetActiveSpec() == spec) + if (GetActiveTalentGroup() == group) return; - if (spec > GetSpecsCount()) + if (group > GetTalentGroupsCount()) return; if (IsNonMeleeSpellCast(false)) @@ -26251,7 +26120,7 @@ void Player::ActivateSpec(uint8 spec) } // Unlearn specialization specific spells - auto specSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(GetActiveSpec())); + auto specSpells = sSpecializationSpellsBySpecStore.find(GetActiveTalentSpec()); if (specSpells != sSpecializationSpellsBySpecStore.end()) { for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) @@ -26265,7 +26134,7 @@ void Player::ActivateSpec(uint8 spec) } // Unlearn mastery spells - ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec())); + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec()); for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) if (chrSpec->MasterySpellID[i]) RemoveSpell(chrSpec->MasterySpellID[i], true); @@ -26273,12 +26142,12 @@ void Player::ActivateSpec(uint8 spec) // set glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) // remove secondary glyph - if (uint32 oldglyph = GetGlyph(GetActiveSpec(), slot)) + if (uint32 oldglyph = GetGlyph(GetActiveTalentGroup(), slot)) if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph)) RemoveAurasDueToSpell(old_gp->SpellID); - // Activate new spec - SetActiveSpec(spec); + // Activate new group + SetActiveTalentGroup(group); for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) { @@ -26291,14 +26160,11 @@ void Player::ActivateSpec(uint8 spec) if (getClass() != talentInfo->ClassID) continue; - if (HasTalent(talentInfo->SpellID, GetActiveSpec())) - { - LearnSpell(talentInfo->SpellID, false); - } + LearnSpell(talentInfo->SpellID, false); } // Replace default spells with specialization specific spells - auto newSpecSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(spec)); + auto newSpecSpells = sSpecializationSpellsBySpecStore.find(GetActiveTalentSpec()); if (newSpecSpells != sSpecializationSpellsBySpecStore.end()) { for (auto it = newSpecSpells->second.begin(); it != newSpecSpells->second.end(); ++it) @@ -26314,7 +26180,7 @@ void Player::ActivateSpec(uint8 spec) } if (CanUseMastery()) - if (ChrSpecializationEntry const* newChrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(spec))) + if (ChrSpecializationEntry const* newChrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) if (newChrSpec->MasterySpellID[i]) LearnSpell(newChrSpec->MasterySpellID[i], false); @@ -26322,7 +26188,7 @@ void Player::ActivateSpec(uint8 spec) // set glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) { - uint32 glyph = GetGlyph(GetActiveSpec(), slot); + uint32 glyph = GetGlyph(GetActiveTalentGroup(), slot); // apply primary glyph if (glyph) @@ -26337,7 +26203,7 @@ void Player::ActivateSpec(uint8 spec) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC); stmt->setUInt64(0, GetGUID().GetCounter()); - stmt->setUInt8(1, GetActiveSpec()); + stmt->setUInt8(1, GetActiveTalentGroup()); if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) _LoadActions(result); } @@ -26350,7 +26216,7 @@ void Player::ActivateSpec(uint8 spec) SetPower(pw, 0); - if (!sChrSpecializationStore.LookupEntry(GetTalentSpec(spec))) + if (!sChrSpecializationStore.LookupEntry(GetActiveTalentSpec())) ResetTalents(true); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 54d542011a1..11167097e89 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -115,12 +115,6 @@ struct PlayerSpell bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks }; -struct PlayerTalent -{ - PlayerSpellState State : 8; - uint32 SpellID : 32; -}; - extern uint32 const MasterySpells[MAX_CLASSES]; enum TalentSpecialization // talent tabs @@ -1217,46 +1211,52 @@ private: bool _isPvP; }; -struct TalentSpecInfo +struct TalentGroupInfo { - PlayerTalent Talents[MAX_TALENT_TIERS]; + uint32 Talents[MAX_TALENT_TIERS]; uint32 Glyphs[MAX_GLYPH_SLOT_INDEX]; - uint32 TalentSpec; + uint32 SpecID; - bool HasTalent(uint32 spellId) + bool HasTalent(uint32 talentId) { for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) - if (Talents[i].SpellID == spellId) + if (Talents[i] == talentId) return true; return false; } + uint32 TalentCount() + { + for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) + if (!Talents[i]) + return i; + return MAX_TALENT_TIERS; + } + void Reset() { - for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) { - Talents[i].State = PLAYERSPELL_REMOVED; - Talents[i].SpellID = 0; - } + for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) + Talents[i] = 0; } }; struct PlayerTalentInfo { - PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), ActiveSpec(0), SpecsCount(1) + PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), ActiveGroup(0), GroupsCount(1) { - for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) + for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i) { - memset(SpecInfo[i].Talents, 0, sizeof(PlayerTalent)*MAX_TALENT_TIERS); - memset(SpecInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32)); - SpecInfo[i].TalentSpec = 0; + memset(GroupInfo[i].Talents, 0, sizeof(uint32)*MAX_TALENT_TIERS); + memset(GroupInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32)); + GroupInfo[i].SpecID = 0; } } - TalentSpecInfo SpecInfo[MAX_TALENT_SPECS]; + TalentGroupInfo GroupInfo[MAX_TALENT_GROUPS]; uint32 ResetTalentsCost; time_t ResetTalentsTime; - uint8 ActiveSpec; - uint8 SpecsCount; + uint8 ActiveGroup; + uint8 GroupsCount; private: PlayerTalentInfo(PlayerTalentInfo const&); @@ -1825,35 +1825,34 @@ class Player : public Unit, public GridObject<Player> void SetTalentResetCost(uint32 cost) { _talentMgr->ResetTalentsCost = cost; } uint32 GetTalentResetTime() const { return _talentMgr->ResetTalentsTime; } void SetTalentResetTime(time_t time_) { _talentMgr->ResetTalentsTime = time_; } - uint8 GetActiveSpec() const { return _talentMgr->ActiveSpec; } - void SetActiveSpec(uint8 spec){ _talentMgr->ActiveSpec = spec; } - uint8 GetSpecsCount() const { return _talentMgr->SpecsCount; } - void SetSpecsCount(uint8 count) { _talentMgr->SpecsCount = count; } - uint32 GetTalentSpec(uint8 spec) const { return _talentMgr->SpecInfo[spec].TalentSpec; } - void SetTalentSpec(uint8 spec, uint32 talentSpec) const { _talentMgr->SpecInfo[spec].TalentSpec = talentSpec; } + uint8 GetActiveTalentGroup() const { return _talentMgr->ActiveGroup; } + void SetActiveTalentGroup(uint8 group){ _talentMgr->ActiveGroup = group; } + uint8 GetTalentGroupsCount() const { return _talentMgr->GroupsCount; } + void SetTalentGroupsCount(uint8 count) { _talentMgr->GroupsCount = count; } + uint32 GetTalentSpec(uint8 group) const { return _talentMgr->GroupInfo[group].SpecID; } + void SetTalentSpec(uint8 group, uint32 talentSpec) const { _talentMgr->GroupInfo[group].SpecID = talentSpec; } + uint32 GetActiveTalentSpec() const { return _talentMgr->GroupInfo[_talentMgr->ActiveGroup].SpecID; } bool ResetTalents(bool no_cost = false); uint32 GetNextResetTalentsCost() const; void InitTalentForLevel(); - void BuildPlayerTalentsInfoData(WorldPacket* data); - void BuildPetTalentsInfoData(WorldPacket* data); - void SendTalentsInfoData(bool pet); + void SendTalentsInfoData(); bool LearnTalent(uint32 talentId); - bool AddTalent(uint32 spellId, uint8 spec, bool learning); - bool HasTalent(uint32 spell_id, uint8 spec); + bool AddTalent(uint32 talentId, uint8 spec); + bool HasTalent(uint32 talentId, uint8 spec); // Dual Spec - void UpdateSpecCount(uint8 count); - void ActivateSpec(uint8 spec); + void UpdateTalentGroupCount(uint8 count); + void ActivateTalentGroup(uint8 group); void InitGlyphsForLevel(); void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); } uint32 GetGlyphSlot(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); } void SetGlyph(uint8 slot, uint32 glyph); - uint32 GetGlyph(uint8 spec, uint8 slot) const { return _talentMgr->SpecInfo[spec].Glyphs[slot]; } + uint32 GetGlyph(uint8 group, uint8 slot) const { return _talentMgr->GroupInfo[group].Glyphs[slot]; } - TalentSpecInfo* GetTalentSpecInfo(uint8 spec) { return &_talentMgr->SpecInfo[spec]; } + TalentGroupInfo* GetTalentGroupInfo(uint8 group) { return &_talentMgr->GroupInfo[group]; } ActionButtonList const& GetActionButtons() const { return m_actionButtons; } uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); } diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 37b4d4d97a0..ea15daed587 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -526,7 +526,7 @@ void Player::UpdateMastery() value += GetRatingBonusValue(CR_MASTERY); SetFloatValue(PLAYER_MASTERY, value); - ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec())); + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec()); if (!chrSpec) return; |
