diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e41239024c..c2652d90f2 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -84,6 +84,7 @@ #include "PetPackets.h" #include "PetitionMgr.h" #include "PhasingHandler.h" +#include "PlayerTalentInfo.h" #include "PoolMgr.h" #include "QueryCallback.h" #include "QueryHolder.h" @@ -2661,9 +2662,9 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) return false; } - PlayerTalentMap::iterator itr = GetTalentMap(spec)->find(spellId); - if (itr != GetTalentMap(spec)->end()) - itr->second->state = PLAYERSPELL_UNCHANGED; + PlayerTalentMap::iterator itr = GetTalentMap(spec).find(spellId); + if (itr != GetTalentMap(spec).end()) + itr->second.State = PLAYERSPELL_UNCHANGED; else if (TalentSpellPos const* talentPos = sDBCManager.GetTalentSpellPos(spellId)) { if (TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentPos->talent_id)) @@ -2675,18 +2676,16 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) if (!rankSpellId || rankSpellId == spellId) continue; - itr = GetTalentMap(spec)->find(rankSpellId); - if (itr != GetTalentMap(spec)->end()) - itr->second->state = PLAYERSPELL_REMOVED; + itr = GetTalentMap(spec).find(rankSpellId); + if (itr != GetTalentMap(spec).end()) + itr->second.State = PLAYERSPELL_REMOVED; } } - PlayerTalent* newtalent = new PlayerTalent(); - newtalent->state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; - newtalent->spec = spec; - - (*GetTalentMap(spec))[spellId] = newtalent; + PlayerTalent& newtalent = GetTalentMap(spec)[spellId]; + newtalent.State = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; + newtalent.Spec = spec; return true; } return false; @@ -3420,18 +3419,22 @@ bool Player::ResetTalents(bool no_cost) // skip non-existing talent ranks if (talentInfo->SpellRank[rank] == 0) continue; + SpellInfo const* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellRank[rank]); if (!_spellEntry) continue; + RemoveSpell(talentInfo->SpellRank[rank], true); + // search for spells that the talent teaches and unlearn them 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); + // if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted - PlayerTalentMap::iterator plrTalent = GetTalentMap(GetActiveSpec())->find(talentInfo->SpellRank[rank]); - if (plrTalent != GetTalentMap(GetActiveSpec())->end()) - plrTalent->second->state = PLAYERSPELL_REMOVED; + PlayerTalentMap::iterator plrTalent = GetTalentMap(GetActiveSpec()).find(talentInfo->SpellRank[rank]); + if (plrTalent != GetTalentMap(GetActiveSpec()).end()) + plrTalent->second.State = PLAYERSPELL_REMOVED; } } @@ -3548,8 +3551,8 @@ bool Player::HasSpell(uint32 spell) const bool Player::HasTalent(uint32 spell, uint8 spec) const { - PlayerTalentMap::const_iterator itr = GetTalentMap(spec)->find(spell); - return (itr != GetTalentMap(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 @@ -24745,6 +24748,20 @@ void Player::SetGlyph(uint8 slot, uint32 glyph) SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); } +uint32 Player::GetGlyph(uint8 spec, uint8 slot) const +{ + return _talentMgr->SpecInfo[spec].Glyphs[slot]; +} + +PlayerTalentMap const& Player::GetTalentMap(uint8 spec) const +{ + return _talentMgr->SpecInfo[spec].Talents; +} +PlayerTalentMap& Player::GetTalentMap(uint8 spec) +{ + return _talentMgr->SpecInfo[spec].Talents; +} + bool Player::isTotalImmune() const { AuraEffectList const& immune = GetAuraEffectsByType(SPELL_AURA_SCHOOL_IMMUNITY); @@ -26247,34 +26264,33 @@ void Player::_SaveTalents(CharacterDatabaseTransaction& trans) for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) { - for (PlayerTalentMap::iterator itr = GetTalentMap(i)->begin(); itr != GetTalentMap(i)->end();) + for (PlayerTalentMap::iterator itr = GetTalentMap(i).begin(); itr != GetTalentMap(i).end();) { - if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED) + if (itr->second.State == PLAYERSPELL_REMOVED || itr->second.State == PLAYERSPELL_CHANGED) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC); stmt->setUInt32(0, GetGUID().GetCounter()); stmt->setUInt32(1, itr->first); - stmt->setUInt8(2, itr->second->spec); + stmt->setUInt8(2, itr->second.Spec); trans->Append(stmt); } - if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED) + if (itr->second.State == PLAYERSPELL_NEW || itr->second.State == PLAYERSPELL_CHANGED) { stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT); stmt->setUInt32(0, GetGUID().GetCounter()); stmt->setUInt32(1, itr->first); - stmt->setUInt8(2, itr->second->spec); + stmt->setUInt8(2, itr->second.Spec); trans->Append(stmt); } - if (itr->second->state == PLAYERSPELL_REMOVED) + if (itr->second.State == PLAYERSPELL_REMOVED) { - delete itr->second; - GetTalentMap(i)->erase(itr++); + GetTalentMap(i).erase(itr++); } else { - itr->second->state = PLAYERSPELL_UNCHANGED; + itr->second.State = PLAYERSPELL_UNCHANGED; ++itr; } } @@ -27721,6 +27737,70 @@ void Player::SendRaidGroupOnlyMessage(RaidGroupReason reason, int32 delay) const SendDirectMessage(raidGroupOnly.Write()); } +uint32 Player::GetFreeTalentPoints() const +{ + return _talentMgr->FreeTalentPoints; +} + +void Player::SetFreeTalentPoints(uint32 points) +{ + _talentMgr->FreeTalentPoints = points; +} + +uint32 Player::GetUsedTalentCount() const +{ + return _talentMgr->UsedTalentCount; +} + +void Player::SetUsedTalentCount(uint32 talents) +{ + _talentMgr->UsedTalentCount = talents; +} + +uint32 Player::GetQuestRewardedTalentCount() const +{ + return _talentMgr->QuestRewardedTalentCount; +} + +void Player::AddQuestRewardedTalentCount(uint32 points) +{ + _talentMgr->QuestRewardedTalentCount += points; +} + +uint32 Player::GetTalentResetCost() const +{ + return _talentMgr->ResetTalentsCost; +} + +void Player::SetTalentResetCost(uint32 cost) +{ + _talentMgr->ResetTalentsCost = cost; +} + +uint32 Player::GetTalentResetTime() const +{ + return _talentMgr->ResetTalentsTime; +} + +void Player::SetTalentResetTime(time_t time_) +{ + _talentMgr->ResetTalentsTime = time_; +} +uint32 Player::GetPrimaryTalentTree(uint8 spec) const +{ + return _talentMgr->SpecInfo[spec].TalentTree; +} + +void Player::SetPrimaryTalentTree(uint8 spec, uint32 tree) +{ + _talentMgr->SpecInfo[spec].TalentTree = tree; UpdateArmorSpecialization(); +} + +uint8 Player::GetActiveSpec() const +{ + return _talentMgr->ActiveSpec; +} + void Player::SetActiveSpec(uint8 spec) { _talentMgr->ActiveSpec = spec; @@ -27728,6 +27808,16 @@ void Player::SetActiveSpec(uint8 spec) RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2::ChangeSpec); } +uint8 Player::GetSpecsCount() const +{ + return _talentMgr->SpecsCount; +} + +void Player::SetSpecsCount(uint8 count) +{ + _talentMgr->SpecsCount = count; +} + void Player::SetRestFlag(RestFlag restFlag) { uint32 oldRestMask = _restFlagMask; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index df3b73f676..7ff17d61ae 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -48,6 +48,8 @@ struct ItemSetEffect; struct ItemTemplate; struct Loot; struct Mail; +struct PlayerTalent; +struct PlayerTalentInfo; struct ScalingStatDistributionEntry; struct ScalingStatValuesEntry; struct TrainerSpell; @@ -120,7 +122,7 @@ enum BuyBankSlotResult ERR_BANKSLOT_OK = 3 }; -enum PlayerSpellState +enum PlayerSpellState : uint8 { PLAYERSPELL_UNCHANGED = 0, PLAYERSPELL_CHANGED = 1, @@ -139,8 +141,8 @@ struct PlayerSpell struct PlayerTalent { - PlayerSpellState state : 8; - uint8 spec : 8; + PlayerSpellState State; + uint8 Spec; }; extern uint32 const MasterySpells[MAX_CLASSES]; @@ -239,7 +241,7 @@ struct PlayerCurrency uint8 Flags; }; -typedef std::unordered_map PlayerTalentMap; +typedef std::unordered_map PlayerTalentMap; typedef std::unordered_map PlayerSpellMap; typedef Trinity::Containers::FlatSet SpellModContainer; typedef std::unordered_map PlayerCurrenciesMap; @@ -977,55 +979,6 @@ struct ResurrectionData uint32 Aura; }; -struct PlayerTalentInfo -{ - PlayerTalentInfo() : - FreeTalentPoints(0), 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)); - SpecInfo[i].TalentTree = 0; - } - } - - ~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 - { - TalentSpecInfo() : Talents(nullptr), TalentTree(0) - { - memset(Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32)); - } - - PlayerTalentMap* Talents; - uint32 Glyphs[MAX_GLYPH_SLOT_INDEX]; - uint32 TalentTree; - } SpecInfo[MAX_TALENT_SPECS]; - - uint32 FreeTalentPoints; - 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 { friend class WorldSession; @@ -1606,23 +1559,22 @@ class TC_GAME_API Player : public Unit, public GridObject void SendRaidGroupOnlyMessage(RaidGroupReason reason, int32 delay) const; // Talents - uint32 GetFreeTalentPoints() const { return _talentMgr->FreeTalentPoints; } - void SetFreeTalentPoints(uint32 points) { _talentMgr->FreeTalentPoints = 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; } - uint32 GetTalentResetTime() const { return _talentMgr->ResetTalentsTime; } - void SetTalentResetTime(time_t time_) { _talentMgr->ResetTalentsTime = time_; } - uint32 GetPrimaryTalentTree(uint8 spec) const { return _talentMgr->SpecInfo[spec].TalentTree; } - void SetPrimaryTalentTree(uint8 spec, uint32 tree) { _talentMgr->SpecInfo[spec].TalentTree = tree; UpdateArmorSpecialization(); } - uint8 GetActiveSpec() const { return _talentMgr->ActiveSpec; } + uint32 GetFreeTalentPoints() const; + void SetFreeTalentPoints(uint32 points); + uint32 GetUsedTalentCount() const; + void SetUsedTalentCount(uint32 talents); + uint32 GetQuestRewardedTalentCount() const; + void AddQuestRewardedTalentCount(uint32 points); + uint32 GetTalentResetCost() const; + void SetTalentResetCost(uint32 cost); + uint32 GetTalentResetTime() const; + void SetTalentResetTime(time_t time_); + uint32 GetPrimaryTalentTree(uint8 spec) const; + void SetPrimaryTalentTree(uint8 spec, uint32 tree); + uint8 GetActiveSpec() const; void SetActiveSpec(uint8 spec); - uint8 GetSpecsCount() const { return _talentMgr->SpecsCount; } - void SetSpecsCount(uint8 count) { _talentMgr->SpecsCount = count; } - + uint8 GetSpecsCount() const; + void SetSpecsCount(uint8 count); bool ResetTalents(bool no_cost = false); uint32 GetNextResetTalentsCost() const; void InitTalentForLevel(); @@ -1648,10 +1600,10 @@ class TC_GAME_API Player : public Unit, public GridObject 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 spec, uint8 slot) const; - PlayerTalentMap const* GetTalentMap(uint8 spec) const { return _talentMgr->SpecInfo[spec].Talents; } - PlayerTalentMap* GetTalentMap(uint8 spec) { return _talentMgr->SpecInfo[spec].Talents; } + PlayerTalentMap const& GetTalentMap(uint8 spec) const; + PlayerTalentMap& GetTalentMap(uint8 spec); ActionButtonList const& GetActionButtons() const { return m_actionButtons; } uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); } diff --git a/src/server/game/Entities/Player/PlayerTalentInfo.h b/src/server/game/Entities/Player/PlayerTalentInfo.h new file mode 100644 index 0000000000..2108679710 --- /dev/null +++ b/src/server/game/Entities/Player/PlayerTalentInfo.h @@ -0,0 +1,47 @@ +/* +* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __PlayerTalentInfo_h_ +#define __PlayerTalentInfo_h_ + +#include "Define.h" +#include "SharedDefines.h" + +struct PlayerTalent; + +struct TalentSpecInfo +{ + std::unordered_map Talents; + std::array Glyphs = { }; + uint32 TalentTree = 0; +}; + +struct PlayerTalentInfo +{ + PlayerTalentInfo() = default; + + std::array SpecInfo = { }; + uint32 FreeTalentPoints = 0; + uint32 UsedTalentCount = 0; + uint32 QuestRewardedTalentCount = 0; + uint32 ResetTalentsCost = 0; + time_t ResetTalentsTime = 0; + uint8 ActiveSpec = 0; + uint8 SpecsCount = 0; +}; + +#endif // __PlayerTalentInfo_h_