diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 218 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 82 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Handlers/SkillHandler.cpp | 10 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 2 |
6 files changed, 179 insertions, 147 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 3585d38954c..452d1342ba6 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -194,9 +194,6 @@ Player::Player(WorldSession* session): Unit(true) if (!GetSession()->HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS)) SetAcceptWhispers(true); - m_usedTalentCount = 0; - m_questRewardTalentCount = 0; - m_regenTimer = 0; m_regenTimerCount = 0; m_foodEmoteTimerCount = 0; @@ -302,8 +299,6 @@ Player::Player(WorldSession* session): Unit(true) unReadMails = 0; m_nextMailDelivereTime = 0; - m_resetTalentsCost = 0; - m_resetTalentsTime = 0; m_itemUpdateQueueBlocked = false; /////////////////// Instance System ///////////////////// @@ -316,16 +311,7 @@ Player::Player(WorldSession* session): Unit(true) m_lastPotionId = 0; - m_activeSpec = 0; - m_specsCount = 1; - - for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) - { - for (uint8 g = 0; g < MAX_GLYPH_SLOT_INDEX; ++g) - m_Glyphs[i][g] = 0; - - m_talents[i] = new PlayerTalentMap(); - } + _talentMgr = new PlayerTalentInfo(); for (uint8 i = 0; i < BASEMOD_END; ++i) { @@ -412,12 +398,7 @@ Player::~Player() for (uint8 i = 0; i < PLAYER_SLOTS_COUNT; ++i) delete m_items[i]; - for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) - { - for (PlayerTalentMap::const_iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end(); ++itr) - delete itr->second; - delete m_talents[i]; - } + delete _talentMgr; //all mailed items should be deleted, also all mail should be deallocated for (PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr) @@ -2607,7 +2588,7 @@ void Player::InitTalentForLevel() if (level < 10) { // Remove all talent points - if (m_usedTalentCount > 0) // Free any used talents + if (GetUsedTalentCount() > 0) // Free any used talents { ResetTalents(true); SetFreeTalentPoints(0); @@ -2615,16 +2596,16 @@ void Player::InitTalentForLevel() } else { - if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || m_specsCount == 0) + if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || GetSpecsCount() == 0) { - m_specsCount = 1; - m_activeSpec = 0; + SetSpecsCount(1); + SetActiveSpec(0); } uint32 talentPointsForLevel = CalculateTalentsPoints(); // if used more that have then reset - if (m_usedTalentCount > talentPointsForLevel) + if (GetUsedTalentCount() > talentPointsForLevel) { if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED)) ResetTalents(true); @@ -2633,7 +2614,7 @@ void Player::InitTalentForLevel() } // else update amount of free points else - SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); + SetFreeTalentPoints(talentPointsForLevel - GetUsedTalentCount()); } if (!GetSession()->PlayerLoading()) @@ -3005,8 +2986,8 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) return false; } - PlayerTalentMap::iterator itr = m_talents[spec]->find(spellId); - if (itr != m_talents[spec]->end()) + PlayerTalentMap::iterator itr = GetTalentMap(spec)->find(spellId); + if (itr != GetTalentMap(spec)->end()) itr->second->state = PLAYERSPELL_UNCHANGED; else if (TalentSpellPos const* talentPos = GetTalentSpellPos(spellId)) { @@ -3019,8 +3000,8 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) if (!rankSpellId || rankSpellId == spellId) continue; - itr = m_talents[spec]->find(rankSpellId); - if (itr != m_talents[spec]->end()) + itr = GetTalentMap(spec)->find(rankSpellId); + if (itr != GetTalentMap(spec)->end()) itr->second->state = PLAYERSPELL_REMOVED; } } @@ -3030,7 +3011,7 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) newtalent->state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; newtalent->spec = spec; - (*m_talents[spec])[spellId] = newtalent; + (*GetTalentMap(spec))[spellId] = newtalent; return true; } return false; @@ -3323,7 +3304,7 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent } // update used talent points count - m_usedTalentCount += talentCost; + SetUsedTalentCount(GetUsedTalentCount() + talentCost); // update free primary prof.points (if any, can be none in case GM .learn prof. learning) if (uint32 freeProfs = GetFreePrimaryProfessionPoints()) @@ -3556,10 +3537,10 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) uint32 talentCosts = GetTalentSpellCost(spell_id); if (talentCosts > 0 && giveTalentPoints) { - if (talentCosts < m_usedTalentCount) - m_usedTalentCount -= talentCosts; + if (talentCosts < GetUsedTalentCount()) + SetUsedTalentCount(GetUsedTalentCount() - talentCosts); else - m_usedTalentCount = 0; + SetUsedTalentCount(0); } // update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning) @@ -3776,28 +3757,28 @@ uint32 Player::ResetTalentsCost() const return 0; // The first time reset costs 1 gold - if (m_resetTalentsCost < 1*GOLD) + if (GetTalentResetCost() < 1*GOLD) return 1*GOLD; // then 5 gold - else if (m_resetTalentsCost < 5*GOLD) + else if (GetTalentResetCost() < 5*GOLD) return 5*GOLD; // After that it increases in increments of 5 gold - else if (m_resetTalentsCost < 10*GOLD) + else if (GetTalentResetCost() < 10*GOLD) return 10*GOLD; else { - uint64 months = (GameTime::GetGameTime() - m_resetTalentsTime)/MONTH; + uint64 months = (GameTime::GetGameTime() - GetTalentResetTime())/MONTH; if (months > 0) { // This cost will be reduced by a rate of 5 gold per month - int32 new_cost = int32(m_resetTalentsCost - 5*GOLD*months); + int32 new_cost = int32(GetTalentResetCost() - 5*GOLD*months); // to a minimum of 10 gold. return (new_cost < 10*GOLD ? 10*GOLD : new_cost); } else { // After that it increases in increments of 5 gold - int32 new_cost = m_resetTalentsCost + 5*GOLD; + int32 new_cost = GetTalentResetCost() + 5*GOLD; // until it hits a cap of 50 gold. if (new_cost > 50*GOLD) new_cost = 50*GOLD; @@ -3809,9 +3790,9 @@ uint32 Player::ResetTalentsCost() const void Player::IncreaseResetTalentsCostAndCounters(uint32 lastResetTalentsCost) { if (lastResetTalentsCost > 0) // We don't want to reset the accumulated talent reset cost if we decide to temporarily enable CONFIG_NO_RESET_TALENT_COST - m_resetTalentsCost = lastResetTalentsCost; + _talentMgr->ResetTalentsCost = lastResetTalentsCost; - m_resetTalentsTime = GameTime::GetGameTime(); + _talentMgr->ResetTalentsTime = GameTime::GetGameTime(); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, lastResetTalentsCost); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS, 1); @@ -3827,7 +3808,7 @@ bool Player::ResetTalents(bool involuntarily /*= false*/) uint32 talentPointsForLevel = CalculateTalentsPoints(); - if (m_usedTalentCount == 0) + if (!GetUsedTalentCount()) { SetFreeTalentPoints(talentPointsForLevel); return false; @@ -3867,8 +3848,8 @@ bool Player::ResetTalents(bool involuntarily /*= false*/) if (spellEffectInfo.IsEffect(SPELL_EFFECT_LEARN_SPELL) && spellEffectInfo.TriggerSpell > 0) RemoveSpell(spellEffectInfo.TriggerSpell, true); // if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted - PlayerTalentMap::iterator plrTalent = m_talents[m_activeSpec]->find(talentInfo->SpellRank[rank]); - if (plrTalent != m_talents[m_activeSpec]->end()) + PlayerTalentMap::iterator plrTalent = GetTalentMap(GetActiveSpec())->find(talentInfo->SpellRank[rank]); + if (plrTalent != GetTalentMap(GetActiveSpec())->end()) plrTalent->second->state = PLAYERSPELL_REMOVED; } } @@ -3972,8 +3953,8 @@ bool Player::HasSpell(uint32 spell) const bool Player::HasTalent(uint32 spell, uint8 spec) const { - PlayerTalentMap::const_iterator itr = m_talents[spec]->find(spell); - return (itr != m_talents[spec]->end() && itr->second->state != PLAYERSPELL_REMOVED); + PlayerTalentMap::const_iterator itr = GetTalentMap(spec)->find(spell); + return (itr != GetTalentMap(spec)->end() && itr->second->state != PLAYERSPELL_REMOVED); } bool Player::HasActiveSpell(uint32 spell) const @@ -15128,9 +15109,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, SetTitle(titleEntry); } - if (quest->GetBonusTalents()) + if (uint32 talents = quest->GetBonusTalents()) { - m_questRewardTalentCount += quest->GetBonusTalents(); + AddQuestRewardedTalentCount(talents); InitTalentForLevel(); } @@ -17552,8 +17533,8 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol m_Played_time[PLAYED_TIME_TOTAL] = fields[24].GetUInt32(); m_Played_time[PLAYED_TIME_LEVEL] = fields[25].GetUInt32(); - m_resetTalentsCost = fields[29].GetUInt32(); - m_resetTalentsTime = time_t(fields[30].GetUInt32()); + SetTalentResetCost(fields[29].GetUInt32()); + SetTalentResetTime(time_t(fields[30].GetUInt32())); if (!m_taxi.LoadTaxiMask(fields[22].GetString())) // must be before InitTaxiNodesForLevel TC_LOG_WARN("entities.player.loading", "Player::LoadFromDB: Player ({}) has invalid taximask ({}) in DB. Forced partial load.", GetGUID().ToString(), fields[22].GetString()); @@ -17636,15 +17617,15 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol //mails are loaded only when needed ;-) - when player in game click on mailbox. //_LoadMail(); - m_specsCount = fields[64].GetUInt8(); - m_activeSpec = fields[65].GetUInt8(); + SetSpecsCount(fields[64].GetUInt8()); + SetActiveSpec(fields[65].GetUInt8()); // sanity check - if (m_specsCount > MAX_TALENT_SPECS || m_activeSpec > MAX_TALENT_SPEC || m_specsCount < MIN_TALENT_SPECS) + if (GetSpecsCount() > MAX_TALENT_SPECS || GetActiveSpec() > MAX_TALENT_SPEC || GetSpecsCount() < MIN_TALENT_SPECS) { TC_LOG_ERROR("entities.player.loading", "Player::LoadFromDB: Player {} ({}) has invalid SpecCount = {} and/or invalid ActiveSpec = {}.", - GetName(), GetGUID().ToString(), uint32(m_specsCount), uint32(m_activeSpec)); - m_activeSpec = 0; + GetName(), GetGUID().ToString(), uint32(GetSpecsCount()), uint32(GetActiveSpec())); + SetActiveSpec(0); } UpdateDisplayPower(); @@ -17965,7 +17946,7 @@ void Player::_LoadGlyphAuras() { for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) { - if (uint32 glyph = GetGlyph(i)) + if (uint32 glyph = GetGlyph(GetActiveSpec(), i)) { if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph)) { @@ -18502,8 +18483,8 @@ void Player::_LoadQuestStatusRewarded(PreparedQueryResult result) SetTitle(titleEntry); } - if (quest->GetBonusTalents()) - m_questRewardTalentCount += quest->GetBonusTalents(); + if (uint32 talents = quest->GetBonusTalents()) + AddQuestRewardedTalentCount(talents); if (quest->CanIncreaseRewardedQuestCounters()) m_RewardedQuests.insert(quest_id); @@ -19263,8 +19244,8 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0)); //save, far from tavern/city //save, but in tavern/city - stmt->setUInt32(index++, m_resetTalentsCost); - stmt->setUInt32(index++, uint32(m_resetTalentsTime)); + stmt->setUInt32(index++, GetTalentResetCost()); + stmt->setUInt32(index++, uint32(GetTalentResetTime())); stmt->setUInt16(index++, (uint16)m_ExtraFlags); stmt->setUInt8(index++, m_petStable ? m_petStable->MaxStabledPets : 0); stmt->setUInt16(index++, (uint16)m_atLoginFlags); @@ -19293,8 +19274,8 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false stmt->setUInt32(index++, GetSession()->GetLatency()); - stmt->setUInt8(index++, m_specsCount); - stmt->setUInt8(index++, m_activeSpec); + stmt->setUInt8(index++, GetSpecsCount()); + stmt->setUInt8(index++, GetActiveSpec()); ss.str(""); for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) @@ -19388,8 +19369,8 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false stmt->setUInt8(index++, (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0)); //save, far from tavern/city //save, but in tavern/city - stmt->setUInt32(index++, m_resetTalentsCost); - stmt->setUInt32(index++, uint32(m_resetTalentsTime)); + stmt->setUInt32(index++, GetTalentResetCost()); + stmt->setUInt32(index++, uint32(GetTalentResetTime())); stmt->setUInt16(index++, (uint16)m_ExtraFlags); stmt->setUInt8(index++, m_petStable ? m_petStable->MaxStabledPets : 0); stmt->setUInt16(index++, (uint16)m_atLoginFlags); @@ -19418,8 +19399,8 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false stmt->setUInt32(index++, GetSession()->GetLatency()); - stmt->setUInt8(index++, m_specsCount); - stmt->setUInt8(index++, m_activeSpec); + stmt->setUInt8(index++, GetSpecsCount()); + stmt->setUInt8(index++, GetActiveSpec()); ss.str(""); for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i) @@ -19527,7 +19508,7 @@ void Player::_SaveActions(CharacterDatabaseTransaction trans) case ACTIONBUTTON_NEW: stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACTION); stmt->setUInt32(0, GetGUID().GetCounter()); - stmt->setUInt8(1, m_activeSpec); + stmt->setUInt8(1, GetActiveSpec()); stmt->setUInt8(2, itr->first); stmt->setUInt32(3, itr->second.GetAction()); stmt->setUInt8(4, uint8(itr->second.GetType())); @@ -19542,7 +19523,7 @@ void Player::_SaveActions(CharacterDatabaseTransaction trans) stmt->setUInt8(1, uint8(itr->second.GetType())); stmt->setUInt32(2, GetGUID().GetCounter()); stmt->setUInt8(3, itr->first); - stmt->setUInt8(4, m_activeSpec); + stmt->setUInt8(4, GetActiveSpec()); trans->Append(stmt); itr->second.uState = ACTIONBUTTON_UNCHANGED; @@ -19552,7 +19533,7 @@ void Player::_SaveActions(CharacterDatabaseTransaction trans) stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC); stmt->setUInt32(0, GetGUID().GetCounter()); stmt->setUInt8(1, itr->first); - stmt->setUInt8(2, m_activeSpec); + stmt->setUInt8(2, GetActiveSpec()); trans->Append(stmt); m_actionButtons.erase(itr++); @@ -24457,7 +24438,7 @@ void Player::InitGlyphsForLevel() void Player::SetGlyph(uint8 slot, uint32 glyph) { - m_Glyphs[m_activeSpec][slot] = glyph; + _talentMgr->SpecInfo[GetActiveSpec()].Glyphs[slot] = glyph; SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); } @@ -24822,16 +24803,16 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot) uint32 Player::CalculateTalentsPoints() const { - uint32 base_talent = GetLevel() < 10 ? 0 : GetLevel()-9; + uint32 baseForLevel = GetLevel() < 10 ? 0 : GetLevel() - 9; if (GetClass() != CLASS_DEATH_KNIGHT || GetMapId() != 609) - return uint32(base_talent * sWorld->getRate(RATE_TALENT)); + return uint32(baseForLevel * sWorld->getRate(RATE_TALENT)); uint32 talentPointsForLevel = GetLevel() < 56 ? 0 : GetLevel() - 55; - talentPointsForLevel += m_questRewardTalentCount; + talentPointsForLevel += GetQuestRewardedTalentCount(); - if (talentPointsForLevel > base_talent) - talentPointsForLevel = base_talent; + if (talentPointsForLevel > baseForLevel) + talentPointsForLevel = baseForLevel; return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT)); } @@ -25133,29 +25114,29 @@ void Player::CompletedAchievement(AchievementEntry const* entry) m_achievementMgr->CompletedAchievement(entry); } -void Player::LearnTalent(uint32 talentId, uint32 talentRank) +bool Player::LearnTalent(uint32 talentId, uint32 talentRank) { uint32 CurTalentPoints = GetFreeTalentPoints(); if (CurTalentPoints == 0) - return; + return false; if (talentRank >= MAX_TALENT_RANK) - return; + return false; TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); if (!talentInfo) - return; + return false; TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TabID); if (!talentTabInfo) - return; + return false; // prevent learn talent for different class (cheating) if ((GetClassMask() & talentTabInfo->ClassMask) == 0) - return; + return false; // find current max talent rank (0~5) uint8 curtalent_maxrank = 0; // 0 = not learned any rank @@ -25170,11 +25151,11 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) // we already have same or higher talent rank learned if (curtalent_maxrank >= (talentRank + 1)) - return; + return false; // check if we have enough talent points if (CurTalentPoints < (talentRank - curtalent_maxrank + 1)) - return; + return false; // Check if it requires another talent if (talentInfo->PrereqTalent > 0) @@ -25189,7 +25170,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) hasEnoughRank = true; } if (!hasEnoughRank) - return; + return false; } } @@ -25198,8 +25179,8 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) uint32 tTab = talentInfo->TabID; if (talentInfo->TierID > 0) - for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) // Loop through all talents. - if (TalentEntry const* tmpTalent = sTalentStore.LookupEntry(i)) // the way talents are tracked + for (uint32 i = 0; i < sTalentStore.GetNumRows(); i++) // Loop through all talents. + if (TalentEntry const* tmpTalent = sTalentStore.LookupEntry(i)) // Someday, someone needs to revamp the way talents are tracked if (tmpTalent->TabID == tTab) for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++) if (tmpTalent->SpellRank[rank] != 0) @@ -25208,28 +25189,29 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank) // not have required min points spent in talent tree if (spentPoints < (talentInfo->TierID * MAX_TALENT_RANK)) - return; + return false; // spell not set in talent.dbc uint32 spellid = talentInfo->SpellRank[talentRank]; if (spellid == 0) { TC_LOG_ERROR("entities.player", "Player::LearnTalent: Talent.dbc has no spellInfo for talent: {} (spell id = 0)", talentId); - return; + return false; } // already known if (HasSpell(spellid)) - return; + return false; // learn! (other talent ranks will unlearned at learning) LearnSpell(spellid, false); - AddTalent(spellid, m_activeSpec, true); + AddTalent(spellid, GetActiveSpec(), true); - TC_LOG_DEBUG("misc", "Player::LearnTalent: TalentID: {} Spell: {} Group: {}\n", talentId, spellid, uint32(m_activeSpec)); + TC_LOG_DEBUG("misc", "Player::LearnTalent: TalentID: {} Spell: {} Group: {}\n", talentId, spellid, uint32(GetActiveSpec())); // update free talent points SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1)); + return true; } void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRank) @@ -25442,16 +25424,16 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const void Player::BuildPlayerTalentsInfoData(WorldPacket* data) { *data << uint32(GetFreeTalentPoints()); // unspentTalentPoints - *data << uint8(m_specsCount); // talent group count (0, 1 or 2) - *data << uint8(m_activeSpec); // talent group index (0 or 1) + *data << uint8(GetSpecsCount()); // talent group count (0, 1 or 2) + *data << uint8(GetActiveSpec()); // talent group index (0 or 1) - if (m_specsCount) + if (GetSpecsCount()) { - if (m_specsCount > MAX_TALENT_SPECS) - m_specsCount = MAX_TALENT_SPECS; + if (GetSpecsCount() > MAX_TALENT_SPECS) + SetSpecsCount(MAX_TALENT_SPECS); // loop through all specs (only 1 for now) - for (uint32 specIdx = 0; specIdx < m_specsCount; ++specIdx) + for (uint32 specIdx = 0; specIdx < GetSpecsCount(); ++specIdx) { uint8 talentIdCount = 0; size_t pos = data->wpos(); @@ -25501,7 +25483,7 @@ void Player::BuildPlayerTalentsInfoData(WorldPacket* data) *data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) - *data << uint16(m_Glyphs[specIdx][i]); // GlyphProperties.dbc + *data << uint16(GetGlyph(specIdx, i)); // GlyphProperties.dbc } } } @@ -25827,15 +25809,11 @@ void Player::_LoadGlyphs(PreparedQueryResult result) Field* fields = result->Fetch(); uint8 spec = fields[0].GetUInt8(); - if (spec >= m_specsCount) + if (spec >= GetSpecsCount()) continue; - m_Glyphs[spec][0] = fields[1].GetUInt16(); - m_Glyphs[spec][1] = fields[2].GetUInt16(); - m_Glyphs[spec][2] = fields[3].GetUInt16(); - m_Glyphs[spec][3] = fields[4].GetUInt16(); - m_Glyphs[spec][4] = fields[5].GetUInt16(); - m_Glyphs[spec][5] = fields[6].GetUInt16(); + for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) + _talentMgr->SpecInfo[spec].Glyphs[i] = fields[i + 1].GetUInt16(); } while (result->NextRow()); } @@ -25846,7 +25824,7 @@ void Player::_SaveGlyphs(CharacterDatabaseTransaction trans) const stmt->setUInt32(0, GetGUID().GetCounter()); trans->Append(stmt); - for (uint8 spec = 0; spec < m_specsCount; ++spec) + for (uint8 spec = 0; spec < GetSpecsCount(); ++spec) { uint8 index = 0; @@ -25856,7 +25834,7 @@ void Player::_SaveGlyphs(CharacterDatabaseTransaction trans) const stmt->setUInt8(index++, spec); for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) - stmt->setUInt16(index++, uint16(m_Glyphs[spec][i])); + stmt->setUInt16(index++, uint16(GetGlyph(spec, i))); trans->Append(stmt); } @@ -25879,7 +25857,7 @@ void Player::_SaveTalents(CharacterDatabaseTransaction trans) for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) { - for (PlayerTalentMap::iterator itr = m_talents[i]->begin(); itr != m_talents[i]->end();) + for (PlayerTalentMap::iterator itr = GetTalentMap(i)->begin(); itr != GetTalentMap(i)->end();) { if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED) { @@ -25902,7 +25880,7 @@ void Player::_SaveTalents(CharacterDatabaseTransaction trans) if (itr->second->state == PLAYERSPELL_REMOVED) { delete itr->second; - m_talents[i]->erase(itr++); + GetTalentMap(i)->erase(itr++); } else { @@ -25919,7 +25897,7 @@ void Player::UpdateSpecCount(uint8 count) if (curCount == count) return; - if (m_activeSpec >= count) + if (GetActiveSpec() >= count) ActivateSpec(0); CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); @@ -25946,11 +25924,11 @@ void Player::UpdateSpecCount(uint8 count) _SaveActions(trans); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC); - stmt->setUInt8(0, m_activeSpec); + stmt->setUInt8(0, GetActiveSpec()); stmt->setUInt32(1, GetGUID().GetCounter()); trans->Append(stmt); - m_activeSpec = 0; + SetActiveSpec(0); } CharacterDatabase.CommitTransaction(trans); @@ -26045,7 +26023,7 @@ void Player::ActivateSpec(uint8 spec) // set glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) // remove secondary glyph - if (uint32 oldglyph = m_Glyphs[m_activeSpec][slot]) + if (uint32 oldglyph = GetGlyph(GetActiveSpec(), slot)) if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph)) RemoveAurasDueToSpell(old_gp->SpellID); @@ -26075,7 +26053,7 @@ void Player::ActivateSpec(uint8 spec) if (talentInfo->SpellRank[rank] == 0) continue; // if the talent can be found in the newly activated PlayerTalentMap - if (HasTalent(talentInfo->SpellRank[rank], m_activeSpec)) + if (HasTalent(talentInfo->SpellRank[rank], GetActiveSpec())) { LearnSpell(talentInfo->SpellRank[rank], false); // add the talent to the PlayerSpellMap spentTalents += (rank + 1); // increment the spentTalents count @@ -26086,7 +26064,7 @@ void Player::ActivateSpec(uint8 spec) // set glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) { - uint32 glyph = m_Glyphs[m_activeSpec][slot]; + uint32 glyph = GetGlyph(GetActiveSpec(), slot); // apply primary glyph if (glyph) @@ -26096,14 +26074,14 @@ void Player::ActivateSpec(uint8 spec) SetGlyph(slot, glyph); } - m_usedTalentCount = spentTalents; + SetUsedTalentCount(spentTalents); InitTalentForLevel(); // load them asynchronously { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC); stmt->setUInt32(0, GetGUID().GetCounter()); - stmt->setUInt8(1, m_activeSpec); + stmt->setUInt8(1, GetActiveSpec()); WorldSession* mySess = GetSession(); mySess->GetQueryProcessor().AddCallback(CharacterDatabase.AsyncQuery(stmt) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 80125b66595..f8646c2f95e 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -877,6 +877,47 @@ struct ResurrectionData #define SPELL_DK_RAISE_ALLY 46619 +struct PlayerTalentInfo +{ + PlayerTalentInfo() : + UsedTalentCount(0), QuestRewardedTalentCount(0), + ResetTalentsCost(0), ResetTalentsTime(0), + ActiveSpec(0), SpecsCount(1) + { + for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) + { + SpecInfo[i].Talents = new PlayerTalentMap(); + memset(SpecInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32)); + } + } + + ~PlayerTalentInfo() + { + for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) + { + for (PlayerTalentMap::const_iterator itr = SpecInfo[i].Talents->begin(); itr != SpecInfo[i].Talents->end(); ++itr) + delete itr->second; + delete SpecInfo[i].Talents; + } + } + + struct TalentSpecInfo + { + PlayerTalentMap* Talents; + uint32 Glyphs[MAX_GLYPH_SLOT_INDEX]; + } SpecInfo[MAX_TALENT_SPECS]; + + uint32 UsedTalentCount; + uint32 QuestRewardedTalentCount; + uint32 ResetTalentsCost; + time_t ResetTalentsTime; + uint8 ActiveSpec; + uint8 SpecsCount; + +private: + PlayerTalentInfo(PlayerTalentInfo const&); +}; + class TC_GAME_API Player : public Unit, public GridObject<Player> { friend class WorldSession; @@ -1439,8 +1480,23 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void SetReputation(uint32 factionentry, uint32 value); uint32 GetReputation(uint32 factionentry) const; std::string const& GetGuildName() const; + + // Talents uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); } void SetFreeTalentPoints(uint32 points); + uint32 GetUsedTalentCount() const { return _talentMgr->UsedTalentCount; } + void SetUsedTalentCount(uint32 talents) { _talentMgr->UsedTalentCount = talents; } + uint32 GetQuestRewardedTalentCount() const { return _talentMgr->QuestRewardedTalentCount; } + void AddQuestRewardedTalentCount(uint32 points) { _talentMgr->QuestRewardedTalentCount += points; } + uint32 GetTalentResetCost() const { return _talentMgr->ResetTalentsCost; } + void SetTalentResetCost(uint32 cost) { _talentMgr->ResetTalentsCost = cost; } + time_t 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; } + bool ResetTalents(bool involuntarily = false); uint32 ResetTalentsCost() const; void IncreaseResetTalentsCostAndCounters(uint32 lastResetTalentsCost); @@ -1448,29 +1504,27 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void BuildPlayerTalentsInfoData(WorldPacket* data); void BuildPetTalentsInfoData(WorldPacket* data); void SendTalentsInfoData(bool pet); - void LearnTalent(uint32 talentId, uint32 talentRank); + bool LearnTalent(uint32 talentId, uint32 talentRank); void LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRank); void SendTameFailure(uint8 result); - bool AddTalent(uint32 spellId, uint8 spec, bool learning); bool HasTalent(uint32 spell_id, uint8 spec) const; - uint32 CalculateTalentsPoints() const; // Dual Spec void UpdateSpecCount(uint8 count); - uint32 GetActiveSpec() const { return m_activeSpec; } - void SetActiveSpec(uint8 spec){ m_activeSpec = spec; } - uint8 GetSpecsCount() const { return m_specsCount; } - void SetSpecsCount(uint8 count) { m_specsCount = count; } void ActivateSpec(uint8 spec); void LoadActions(PreparedQueryResult result); void InitGlyphsForLevel(); void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); } - uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); } + uint32 GetGlyphSlot(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); } void SetGlyph(uint8 slot, uint32 glyph); - uint32 GetGlyph(uint8 slot) { return m_Glyphs[m_activeSpec][slot]; } + uint32 GetGlyph(uint8 spec, uint8 slot) const { return _talentMgr->SpecInfo[spec].Glyphs[slot]; } + + PlayerTalentMap const* GetTalentMap(uint8 spec) const { return _talentMgr->SpecInfo[spec].Talents; } + PlayerTalentMap* GetTalentMap(uint8 spec) { return _talentMgr->SpecInfo[spec].Talents; } + ActionButtonList const& GetActionButtons() const { return m_actionButtons; } uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); } void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2, profs); } @@ -2334,13 +2388,9 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> PlayerMails m_mail; PlayerSpellMap m_spells; - PlayerTalentMap* m_talents[MAX_TALENT_SPECS]; uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use - uint8 m_activeSpec; - uint8 m_specsCount; - - uint32 m_Glyphs[MAX_TALENT_SPECS][MAX_GLYPH_SLOT_INDEX]; + PlayerTalentInfo* _talentMgr; ActionButtonList m_actionButtons; @@ -2403,10 +2453,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> float m_rest_bonus; uint32 _restFlagMask; ////////////////////Rest System///////////////////// - uint32 m_resetTalentsCost; - time_t m_resetTalentsTime; - uint32 m_usedTalentCount; - uint32 m_questRewardTalentCount; // Social PlayerSocial* m_social; diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 472f1556551..3431df6ef56 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -1339,7 +1339,7 @@ void WorldSession::HandleRemoveGlyph(WorldPacket& recvData) return; } - if (uint32 glyph = _player->GetGlyph(slot)) + if (uint32 glyph = _player->GetGlyph(_player->GetActiveSpec(), slot)) { if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph)) { diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index a75220e7b2c..8911b36fdc0 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -30,8 +30,8 @@ void WorldSession::HandleLearnTalentOpcode(WorldPacket& recvData) uint32 talentId, requestedRank; recvData >> talentId >> requestedRank; - _player->LearnTalent(talentId, requestedRank); - _player->SendTalentsInfoData(false); + if (_player->LearnTalent(talentId, requestedRank)) + _player->SendTalentsInfoData(false); } void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) @@ -50,7 +50,11 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) { recvPacket >> talentId >> talentRank; - _player->LearnTalent(talentId, talentRank); + if (!_player->LearnTalent(talentId, talentRank)) + { + recvPacket.rfinish(); + break; + } } _player->SendTalentsInfoData(false); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 98e89e73fff..1346f8682ae 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1168,7 +1168,9 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const if (target->GetTypeId() == TYPEID_PLAYER) { - PlayerSpellMap const& sp_list = target->ToPlayer()->GetSpellMap(); + Player* plrTarget = target->ToPlayer(); + + PlayerSpellMap const& sp_list = plrTarget->GetSpellMap(); for (auto itr = sp_list.begin(); itr != sp_list.end(); ++itr) { if (itr->second.state == PLAYERSPELL_REMOVED || itr->second.disabled) @@ -1188,7 +1190,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const // Also do it for Glyphs for (uint32 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) { - if (uint32 glyphId = target->ToPlayer()->GetGlyph(i)) + if (uint32 glyphId = plrTarget->GetGlyph(plrTarget->GetActiveSpec(), i)) { if (GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId)) { @@ -1203,19 +1205,21 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const } // Leader of the Pack - if (target->ToPlayer()->HasSpell(17007)) + if (plrTarget->HasSpell(17007)) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(24932); if (spellInfo && spellInfo->Stances & (UI64LIT(1) << (GetMiscValue() - 1))) target->CastSpell(target, 24932, this); } + // Improved Barkskin - apply/remove armor bonus due to shapeshift - if (target->ToPlayer()->HasSpell(63410) || target->ToPlayer()->HasSpell(63411)) + if (plrTarget->HasSpell(63410) || plrTarget->HasSpell(63411)) { target->RemoveAurasDueToSpell(66530); if (GetMiscValue() == FORM_TRAVEL || GetMiscValue() == FORM_NONE) // "while in Travel Form or while not shapeshifted" target->CastSpell(target, 66530, true); } + // Heart of the Wild if (HotWSpellId) { // hacky, but the only way as spell family is not SPELLFAMILY_DRUID diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index be1fefa8a51..423883689d7 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3805,7 +3805,7 @@ void Spell::EffectApplyGlyph() } // remove old glyph - if (uint32 oldglyph = player->GetGlyph(m_glyphIndex)) + if (uint32 oldglyph = player->GetGlyph(player->GetActiveSpec(), m_glyphIndex)) { if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph)) { |