diff options
author | Intel <chemicstry@gmail.com> | 2014-11-10 21:09:18 +0200 |
---|---|---|
committer | Intel <chemicstry@gmail.com> | 2014-11-10 21:09:18 +0200 |
commit | 24850994b4fc1b285e84f2f44f2278bf3a091900 (patch) | |
tree | 774312cc1e1918f7878947a7024e13827eb6eabd /src | |
parent | e90ef4fa24a1da7f4d7433a1522e5cb43ef68d29 (diff) |
Core/Talents: Update talent system, remove talent points
Diffstat (limited to 'src')
28 files changed, 313 insertions, 797 deletions
diff --git a/src/server/game/Battlegrounds/ArenaScore.h b/src/server/game/Battlegrounds/ArenaScore.h index a1847f546ea..b6b79405ab8 100644 --- a/src/server/game/Battlegrounds/ArenaScore.h +++ b/src/server/game/Battlegrounds/ArenaScore.h @@ -33,8 +33,9 @@ struct ArenaScore : public BattlegroundScore void AppendToPacket(WorldPacket& data, ByteBuffer& content) final override { uint32 primaryTree = 0; + /* TODO: 6.x update to new talent system (and probably rewrite this packet) if (Player* player = ObjectAccessor::FindPlayer(PlayerGuid)) - primaryTree = player->GetPrimaryTalentTree(player->GetActiveSpec()); + primaryTree = player->GetPrimaryTalentTree(player->GetActiveSpec());*/ data.WriteBit(0); // Unk 1 data.WriteBit(0); // Unk 2 diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index c021b731714..46c2e5739ab 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -1066,12 +1066,11 @@ void Battleground::AddPlayer(Player* player) // score struct must be created in inherited class uint32 team = player->GetBGTeam(); - int32 primaryTree = player->GetPrimaryTalentTree(player->GetActiveSpec()); BattlegroundPlayer bp; bp.OfflineRemoveTime = 0; bp.Team = team; - bp.PrimaryTree = primaryTree; + bp.ActiveSpec = player->GetActiveSpec(); // Add to list/maps m_Players[player->GetGUID()] = bp; diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index aa0bb6fbb4c..5bd18977c3d 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -160,7 +160,7 @@ struct BattlegroundPlayer { time_t OfflineRemoveTime; // for tracking and removing offline players from queue after 5 minutes uint32 Team; // Player's team - int32 PrimaryTree; // Player's primary tree + int32 ActiveSpec; // Player's active spec }; struct BattlegroundObjectInfo diff --git a/src/server/game/Battlegrounds/BattlegroundScore.h b/src/server/game/Battlegrounds/BattlegroundScore.h index 2bca2788c61..8d197869ed6 100644 --- a/src/server/game/Battlegrounds/BattlegroundScore.h +++ b/src/server/game/Battlegrounds/BattlegroundScore.h @@ -93,8 +93,9 @@ struct BattlegroundScore virtual void AppendToPacket(WorldPacket& data, ByteBuffer& content) { uint32 primaryTree = 0; + /* TODO: 6.x update to new talent system (and probably rewrite this packet) if (Player* player = ObjectAccessor::FindPlayer(PlayerGuid)) - primaryTree = player->GetPrimaryTalentTree(player->GetActiveSpec()); + primaryTree = player->GetPrimaryTalentTree(player->GetActiveSpec());*/ data.WriteBit(0); // Unk 1 data.WriteBit(0); // Unk 2 diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index fce0fc99b4a..83c39349593 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -1013,14 +1013,7 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) if (!talentEntry) return 0; - int32 rank = param1_str ? (uint32)atol(param1_str) : 0; - if (rank >= MAX_TALENT_RANK) - return 0; - - if (rank < 0) - rank = 0; - - return talentEntry->RankID[rank]; + return talentEntry->SpellID; } case SPELL_LINK_ENCHANT: case SPELL_LINK_TRADE: diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp index e671713c643..eb99a19cf78 100644 --- a/src/server/game/Chat/ChatLink.cpp +++ b/src/server/game/Chat/ChatLink.cpp @@ -451,10 +451,10 @@ bool TalentChatLink::Initialize(std::istringstream& iss) return false; } // Validate talent's spell - _spell = sSpellMgr->GetSpellInfo(talentInfo->RankID[0]); + _spell = sSpellMgr->GetSpellInfo(talentInfo->SpellID); if (!_spell) { - TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): got invalid spell id %u in |trade command", iss.str().c_str(), talentInfo->RankID[0]); + TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): got invalid spell id %u in |trade command", iss.str().c_str(), talentInfo->SpellID); return false; } // Delimiter diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 02fcbc0898b..84967343120 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -191,7 +191,7 @@ struct SpellMiscEntry uint32 CastingTimeIndex; // 15 uint32 DurationIndex; // 16 uint32 RangeIndex; // 17 - uint32 Speed; // 18 + float Speed; // 18 uint32 SpellVisualID[2]; // 19-20 uint32 SpellIconID; // 21 uint32 ActiveIconID; // 22 diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index d1cfa2c1720..598c2e5d5f3 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -74,6 +74,8 @@ DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt); DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt); DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt); DBCStorage <ChrPowerTypesEntry> sChrPowerTypesStore(ChrClassesXPowerTypesfmt); +DBCStorage <ChrSpecializationEntry> sChrSpecializationStore(ChrSpecializationEntryfmt); +SpecializationSpellsBySpecStore sSpecializationSpellsBySpecStore; DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequencesEntryfmt); DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt); DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore(CreatureDisplayInfoExtrafmt); @@ -188,6 +190,7 @@ DBCStorage <SkillTiersEntry> sSkillTiersStore(SkillTiersfmt); DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt); +DBCStorage <SpecializationSpellsEntry> sSpecializationSpellsStore(SpecializationSpellsEntryfmt); DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore(SpellItemEnchantmentfmt); DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt); DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt); @@ -217,14 +220,7 @@ DBCStorage <SpellShapeshiftFormEntry> sSpellShapeshiftFormStore(SpellShapeshiftF DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt); DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt); DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt); -TalentSpellPosMap sTalentSpellPosMap; -DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt); -DBCStorage <TalentTreePrimarySpellsEntry> sTalentTreePrimarySpellsStore(TalentTreePrimarySpellsfmt); -typedef std::map<uint32, std::vector<uint32> > TalentTreePrimarySpellsMap; -TalentTreePrimarySpellsMap sTalentTreePrimarySpellsMap; - -// store absolute bit position for first rank for talent inspect -static uint32 sTalentTabPages[MAX_CLASSES][3]; +TalentBySpellIDMap sTalentBySpellIDMap; DBCStorage <TaxiNodesEntry> sTaxiNodesStore(TaxiNodesEntryfmt); TaxiMask sTaxiNodesMask; @@ -375,6 +371,8 @@ void LoadDBCStores(const std::string& dataPath) PowersByClass[power->ClassID][power->PowerType] = index; } } + + LoadDBC(availableDbcLocales, bad_dbc_files, sChrSpecializationStore, dbcPath, "ChrSpecialization.dbc"); LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc");//19116 @@ -529,10 +527,18 @@ void LoadDBCStores(const std::string& dataPath) if (sSkillLineStore.LookupEntry(entry->SkillID)) SkillRaceClassInfoBySkill.emplace(entry->SkillID, entry); - LoadDBC(availableDbcLocales, bad_dbc_files, sSkillTiersStore, dbcPath, "SkillTiers.dbc");//19116 - LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");//19116 - LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc"/*, &CustomSpellEntryfmt, &CustomSpellEntryIndex*/);//19116 - LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoriesStore, dbcPath,"SpellCategories.dbc");//19116 + LoadDBC(availableDbcLocales, bad_dbc_files, sSkillTiersStore, dbcPath, "SkillTiers.dbc"); + LoadDBC(availableDbcLocales, bad_dbc_files, sSoundEntriesStore, dbcPath, "SoundEntries.dbc");//15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sSpecializationSpellsStore, dbcPath, "SpecializationSpells.dbc"); + for (uint32 i = 1; i < sSpecializationSpellsStore.GetNumRows(); ++i) + { + SpecializationSpellsEntry const* specSpells = sSpecializationSpellsStore.LookupEntry(i); + if (!specSpells) + continue; + sSpecializationSpellsBySpecStore[specSpells->SpecID].insert(specSpells); + } + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellStore, dbcPath, "Spell.dbc"/*, &CustomSpellEntryfmt, &CustomSpellEntryIndex*/); + LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoriesStore, dbcPath, "SpellCategories.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sSpellCategoryStore, dbcPath, "SpellCategory.dbc"); for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i) { @@ -634,19 +640,17 @@ void LoadDBCStores(const std::string& dataPath) sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID); }*/ - // create talent spells set for (unsigned int i = 0; i < sTalentStore.GetNumRows(); ++i) { TalentEntry const* talentInfo = sTalentStore.LookupEntry(i); if (!talentInfo) continue; - for (int j = 0; j < MAX_TALENT_RANK; j++) - if (talentInfo->RankID[j]) - sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i, j); + sTalentBySpellIDMap[talentInfo->SpellID] = talentInfo; } - LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTabStore, dbcPath, "TalentTab.dbc");//15595 + // create talent spells set + /* TODO: 6.x update to new talent system // prepare fast data access to bit pos of talent ranks for use at inspecting { @@ -672,8 +676,8 @@ void LoadDBCStores(const std::string& dataPath) for (uint32 i = 0; i < sTalentTreePrimarySpellsStore.GetNumRows(); ++i) if (TalentTreePrimarySpellsEntry const* talentSpell = sTalentTreePrimarySpellsStore.LookupEntry(i)) sTalentTreePrimarySpellsMap[talentSpell->TalentTree].push_back(talentSpell->SpellId); - sTalentTreePrimarySpellsStore.Clear(); - + sTalentTreePrimarySpellsStore.Clear();*/ + LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiNodesStore, dbcPath, "TaxiNodes.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sTaxiPathStore, dbcPath, "TaxiPath.dbc");//15595 for (uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) @@ -851,23 +855,6 @@ char const* GetPetName(uint32 petfamily, uint32 /*dbclang*/) return pet_family->Name_lang ? pet_family->Name_lang : NULL; } -TalentSpellPos const* GetTalentSpellPos(uint32 spellId) -{ - TalentSpellPosMap::const_iterator itr = sTalentSpellPosMap.find(spellId); - if (itr == sTalentSpellPosMap.end()) - return NULL; - - return &itr->second; -} - -uint32 GetTalentSpellCost(uint32 spellId) -{ - if (TalentSpellPos const* pos = GetTalentSpellPos(spellId)) - return pos->rank+1; - - return 0; -} - int32 GetAreaFlagByAreaID(uint32 area_id) { AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id); @@ -1097,18 +1084,12 @@ PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundB return NULL; } -uint32 const* GetTalentTabPages(uint8 cls) +TalentEntry const* GetTalentBySpellID(uint32 spellID) { - return sTalentTabPages[cls]; -} - -std::vector<uint32> const* GetTalentTreePrimarySpells(uint32 talentTree) -{ - TalentTreePrimarySpellsMap::const_iterator itr = sTalentTreePrimarySpellsMap.find(talentTree); - if (itr == sTalentTreePrimarySpellsMap.end()) - return NULL; - - return &itr->second; + auto itr = sTalentBySpellIDMap.find(spellID); + if (itr != sTalentBySpellIDMap.end()) + return itr->second; + return nullptr; } uint32 GetLiquidFlags(uint32 liquidType) diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 53be6a0ebb9..bb75a5ed6b5 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -29,8 +29,8 @@ typedef std::list<uint32> SimpleFactionsList; SimpleFactionsList const* GetFactionTeamList(uint32 faction); char const* GetPetName(uint32 petfamily, uint32 dbclang); -uint32 GetTalentSpellCost(uint32 spellId); -TalentSpellPos const* GetTalentSpellPos(uint32 spellId); + +TalentEntry const* GetTalentBySpellID(uint32 spellID); int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id); @@ -70,9 +70,6 @@ typedef std::map<uint32/*pair32(map, diff)*/, MapDifficulty> MapDifficultyMap; MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty); MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty); -uint32 const* /*[MAX_TALENT_TABS]*/ GetTalentTabPages(uint8 cls); -std::vector<uint32> const* GetTalentTreePrimarySpells(uint32 talentTree); - uint32 GetLiquidFlags(uint32 liquidType); PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level); @@ -91,6 +88,10 @@ typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRac typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds; SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_); +typedef std::set<SpecializationSpellsEntry const*> SpecializationSpellsBySpecEntry; +typedef std::unordered_map<uint32, SpecializationSpellsBySpecEntry> SpecializationSpellsBySpecStore; +typedef std::unordered_map<uint32, TalentEntry const*> TalentBySpellIDMap; + extern DBCStorage <AchievementEntry> sAchievementStore; extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore; extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions @@ -108,6 +109,7 @@ extern DBCStorage <CharTitlesEntry> sCharTitlesStore; extern DBCStorage <ChrClassesEntry> sChrClassesStore; extern DBCStorage <ChrRacesEntry> sChrRacesStore; extern DBCStorage <ChrPowerTypesEntry> sChrPowerTypesStore; +extern DBCStorage <ChrSpecializationEntry> sChrSpecializationStore; extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore; extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore; extern DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore; @@ -197,6 +199,8 @@ extern DBCStorage <SkillLineEntry> sSkillLineStore; extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore; extern DBCStorage <SkillTiersEntry> sSkillTiersStore; extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore; +extern DBCStorage <SpecializationSpellsEntry> sSpecializationSpellsStore; +extern SpecializationSpellsBySpecStore sSpecializationSpellsBySpecStore; extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore; extern DBCStorage <SpellCategoryEntry> sSpellCategoryStore; extern DBCStorage <SpellDurationEntry> sSpellDurationStore; @@ -224,7 +228,7 @@ extern DBCStorage <SpellTotemsEntry> sSpellTotemsStore; //extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore; extern DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore; extern DBCStorage <TalentEntry> sTalentStore; -extern DBCStorage <TalentTabEntry> sTalentTabStore; +extern TalentBySpellIDMap sTalentBySpellIDMap; extern DBCStorage <TaxiNodesEntry> sTaxiNodesStore; extern DBCStorage <TaxiPathEntry> sTaxiPathStore; extern TaxiMask sTaxiNodesMask; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 366db74dd8b..f3b6355091e 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -776,6 +776,26 @@ struct ChrPowerTypesEntry uint32 PowerType; // 2 }; +#define MAX_MASTERY_SPELLS 2 + +struct ChrSpecializationEntry +{ + uint32 ID; // 0 Specialization ID + //char* BackgroundFile; // 1 + uint32 ClassID; // 2 + uint32 MasterySpellID[MAX_MASTERY_SPELLS]; // 3 + uint32 OrderIndex; // 4 + uint32 PetTalentType; // 5 + uint32 Role; // 6 (0 - Tank, 1 - Healer, 2 - DPS) + uint32 SpellIconID; // 7 + uint32 RaidBuffs; // 8 + uint32 Flags; // 9 + //char* Name_lang; // 10 + //char* Name2_lang; // 11 Same as name_lang? + //char* Description_lang; // 12 + uint32 PrimaryStatOrder[2]; // 13-14 +}; + struct CinematicSequencesEntry { uint32 ID; // 0 @@ -1787,6 +1807,16 @@ struct SoundEntriesEntry //uint32 BusOverwriteID; // 55 }; +// SpecializationSpells.dbc +struct SpecializationSpellsEntry +{ + uint32 ID; // 0 + uint32 SpecID; // 1 + uint32 SpellID; // 2 + uint32 OverridesSpellID; // 3 + //char* Description_lang; // 4 +}; + // SpellEffect.dbc struct SpellEffectEntry { @@ -2091,14 +2121,6 @@ struct SpellItemEnchantmentConditionEntry uint32 RTOperand[5]; // 10-14 uint8 Logic[5]; // 15-16 //uint8 Padding[3]; // 16 - - /*uint32 ID; // 0 m_ID - uint8 Color[5]; // 1-5 m_lt_operandType[5] - //uint32 LT_Operand[5]; // 6-10 m_lt_operand[5] - uint8 Comparator[5]; // 11-15 m_operator[5] - uint8 CompareColor[5]; // 15-20 m_rt_operandType[5] - uint32 Value[5]; // 21-25 m_rt_operand[5] - //uint8 Logic[5] // 25-30 m_logic[5]*/ }; struct StableSlotPricesEntry @@ -2109,56 +2131,28 @@ struct StableSlotPricesEntry struct SummonPropertiesEntry { - uint32 Id; // 0 - uint32 Category; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount? - uint32 Faction; // 2, 14 rows > 0 - uint32 Type; // 3, see enum - int32 Slot; // 4, 0-6 - uint32 Flags; // 5 + uint32 ID; // 0 + uint32 Category; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount? + uint32 Faction; // 2, 14 rows > 0 + uint32 Type; // 3, see enum + int32 Slot; // 4, 0-6 + uint32 Flags; // 5 }; -#define MAX_TALENT_RANK 5 #define MAX_PET_TALENT_RANK 3 // use in calculations, expected <= MAX_TALENT_RANK -#define MAX_TALENT_TABS 3 struct TalentEntry { - uint32 TalentID; // 0 - uint32 TalentTab; // 1 index in TalentTab.dbc (TalentTabEntry) - uint32 Row; // 2 - uint32 Col; // 3 - uint32 RankID[MAX_TALENT_RANK]; // 4-8 - uint32 DependsOn; // 9 m_prereqTalent (Talent.dbc) - // 10-11 part of prev field - uint32 DependsOnRank; // 12 m_prereqRank - // 13-14 part of prev field - //uint32 needAddInSpellBook; // 15 m_flags also need disable higest ranks on reset talent tree - //uint32 unk2; // 16 m_requiredSpellID - //uint64 allowForPet; // 17 m_categoryMask its a 64 bit mask for pet 1<<m_categoryEnumID in CreatureFamily.dbc -}; - -#define MAX_MASTERY_SPELLS 2 - -struct TalentTabEntry -{ - uint32 TalentTabID; // 0 - //char* name; // 1 m_name_lang - //unit32 spellicon; // 2 m_spellIconID - uint32 ClassMask; // 3 m_classMask - uint32 petTalentMask; // 4 m_petTalentMask - uint32 tabpage; // 5 m_orderIndex - //char* internalname; // 6 m_backgroundFile - //char* description; // 7 - //uint32 rolesMask; // 8 4.0.0 - uint32 MasterySpellId[MAX_MASTERY_SPELLS]; // 9-10 passive mastery bonus spells? -}; - -struct TalentTreePrimarySpellsEntry -{ - //uint32 Id; // 0 index - uint32 TalentTree; // 1 entry from TalentTab.dbc - uint32 SpellId; // 2 spell id to learn - //uint32 Flags; // 3 some kind of flags + uint32 ID; // 0 + uint32 SpecID; // 1 0 - any specialization + uint32 TierID; // 2 0-6 + uint32 ColumnIndex; // 3 0-2 + uint32 SpellID; // 4 + uint32 Flags; // 5 All 0 + uint32 CategoryMask[2]; // 6 All 0 + uint32 ClassID; // 7 + uint32 OverridesSpellID; // 8 spellid that is replaced by talent + //char* Description_lang }; struct TaxiNodesEntry @@ -2471,16 +2465,7 @@ struct MapDifficulty bool hasErrorMessage; }; -struct TalentSpellPos -{ - TalentSpellPos() : talent_id(0), rank(0) { } - TalentSpellPos(uint16 _talent_id, uint8 _rank) : talent_id(_talent_id), rank(_rank) { } - - uint16 talent_id; - uint8 rank; -}; - -typedef std::map<uint32, TalentSpellPos> TalentSpellPosMap; +typedef std::map<uint32, uint32> TalentSpellPosMap; struct TaxiPathBySourceAndDestination { diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index c6b2fc34afe..362d4579bee 100644 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -41,6 +41,7 @@ char const ChatChannelsEntryfmt[] = "nixsx"; char const ChrClassesEntryfmt[] = "nixsxxxixiiiixxxxx"; char const ChrRacesEntryfmt[] = "niixiixxxxxxiisxxxxxxxxxxxxxxxxxxxxxxxxx"; char const ChrClassesXPowerTypesfmt[] = "nii"; +char const ChrSpecializationEntryfmt[] = "nxiiiiiiiiixxxii"; char const CinematicSequencesEntryfmt[] = "nxxxxxxxxx"; char const CreatureDisplayInfofmt[] = "nixifxxxxxxxxxxxxxxxx"; char const CreatureDisplayInfoExtrafmt[] = "dixxxxxxxxxxxxxxxxxxx"; @@ -125,6 +126,7 @@ char const SkillLineAbilityfmt[] = "niiiiiiiiiiii"; char const SkillRaceClassInfofmt[] = "diiiixxi"; char const SkillTiersfmt[] = "niiiiiiiiiiiiiiii"; char const SoundEntriesfmt[] = "nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +char const SpecializationSpellsEntryfmt[] = "niiix"; char const SpellCastTimefmt[] = "nixx"; char const SpellCategoriesEntryfmt[] = "diiiiiiiix"; char const SpellCategoryfmt[] = "nixxxx"; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 9d8d0d1f6e9..0fe830f861e 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -1405,25 +1405,7 @@ bool Pet::addSpell(uint32 spellId, ActiveStates active /*= ACT_DECIDE*/, PetSpel newspell.active = active; // talent: unlearn all other talent ranks (high and low) - if (TalentSpellPos const* talentPos = GetTalentSpellPos(spellId)) - { - if (TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentPos->talent_id)) - { - for (uint8 i = 0; i < MAX_TALENT_RANK; ++i) - { - // skip learning spell and no rank spell case - uint32 rankSpellId = talentInfo->RankID[i]; - if (!rankSpellId || rankSpellId == spellId) - continue; - - // skip unknown ranks - if (!HasSpell(rankSpellId)) - continue; - removeSpell(rankSpellId, false, false); - } - } - } - else if (spellInfo->IsRanked()) + if (spellInfo->IsRanked()) { for (PetSpellMap::const_iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2) { @@ -1465,15 +1447,6 @@ bool Pet::addSpell(uint32 spellId, ActiveStates active /*= ACT_DECIDE*/, PetSpel if (newspell.active == ACT_ENABLED) ToggleAutocast(spellInfo, true); - uint32 talentCost = GetTalentSpellCost(spellId); - if (talentCost) - { - int32 free_points = GetMaxTalentPointsForLevel(getLevel()); - m_usedTalentCount += talentCost; - // update free talent points - free_points-=m_usedTalentCount; - SetFreeTalentPoints(free_points > 0 ? free_points : 0); - } return true; } @@ -1563,18 +1536,6 @@ bool Pet::removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab) RemoveAurasDueToSpell(spell_id); - uint32 talentCost = GetTalentSpellCost(spell_id); - if (talentCost > 0) - { - if (m_usedTalentCount > talentCost) - m_usedTalentCount -= talentCost; - else - m_usedTalentCount = 0; - // update free talent points - int32 free_points = GetMaxTalentPointsForLevel(getLevel()) - m_usedTalentCount; - SetFreeTalentPoints(free_points > 0 ? free_points : 0); - } - if (learn_prev) { if (uint32 prev_id = sSpellMgr->GetPrevSpellInChain (spell_id)) @@ -1622,6 +1583,7 @@ void Pet::InitPetCreateSpells() bool Pet::resetTalents() { + /* TODO: 6.x remove pet talents Player* player = GetOwner(); // not need after this call @@ -1689,12 +1651,13 @@ bool Pet::resetTalents() SetFreeTalentPoints(talentPointsForLevel); if (!m_loading) - player->PetSpellInitialize(); + player->PetSpellInitialize();*/ return true; } void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= NULL*/) { + /* TODO: 6.x remove pet talents // not need after this call if (owner->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) owner->RemoveAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS, true); @@ -1767,7 +1730,7 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= NULL*/) ss << ')'; - CharacterDatabase.Execute(ss.str().c_str()); + CharacterDatabase.Execute(ss.str().c_str());*/ } void Pet::InitTalentForLevel() diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 6b1e8fc95fa..016666e2945 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2984,40 +2984,6 @@ void Player::GiveLevel(uint8 level) void Player::InitTalentForLevel() { - uint8 level = getLevel(); - // talents base at level diff (talents = level - 9 but some can be used already) - if (level < 10) - { - // Remove all talent points - if (GetUsedTalentCount() > 0) // Free any used talents - { - ResetTalents(true); - SetFreeTalentPoints(0); - } - } - else - { - if (level < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL) || GetSpecsCount() == 0) - { - SetSpecsCount(1); - SetActiveSpec(0); - } - - uint32 talentPointsForLevel = CalculateTalentsPoints(); - - // if used more that have then reset - if (GetUsedTalentCount() > talentPointsForLevel) - { - if (!GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED)) - ResetTalents(true); - else - SetFreeTalentPoints(0); - } - // else update amount of free points - else - SetFreeTalentPoints(talentPointsForLevel - GetUsedTalentCount()); - } - if (!GetSession()->PlayerLoading()) SendTalentsInfoData(false); // update at client } @@ -3344,6 +3310,7 @@ void DeleteSpellFromAllPlayers(uint32 spellId) bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) { + /* TODO: 6.x update talent system SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { @@ -3404,6 +3371,7 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) (*GetTalentMap(spec))[spellId] = newtalent; return true; } + */ return false; } @@ -3552,24 +3520,8 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent if (!disabled_case) // skip new spell adding if spell already known (disabled spells case) { - // talent: unlearn all other talent ranks (high and low) - if (TalentSpellPos const* talentPos = GetTalentSpellPos(spellId)) - { - if (TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentPos->talent_id)) - { - for (uint8 rank = 0; rank < MAX_TALENT_RANK; ++rank) - { - // skip learning spell and no rank spell case - uint32 rankSpellId = talentInfo->RankID[rank]; - if (!rankSpellId || rankSpellId == spellId) - continue; - - RemoveSpell(rankSpellId, false, false); - } - } - } // non talent spell: learn low ranks (recursive call) - else if (uint32 prev_spell = sSpellMgr->GetPrevSpellInChain(spellId)) + if (uint32 prev_spell = sSpellMgr->GetPrevSpellInChain(spellId)) { if (!IsInWorld() || disabled) // at spells loading, no output, but allow save AddSpell(prev_spell, active, true, true, disabled, false, fromSkill); @@ -3632,11 +3584,9 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent return false; } - uint32 talentCost = GetTalentSpellCost(spellId); - // cast talents with SPELL_EFFECT_LEARN_SPELL (other dependent spells will learned later as not auto-learned) // note: all spells with SPELL_EFFECT_LEARN_SPELL isn't passive - if (!loading && talentCost > 0 && spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL)) + if (!loading && spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL)) { // ignore stance requirement for talent learn spell (stance set for spell only for client spell description show) CastSpell(this, spellId, true); @@ -3653,9 +3603,6 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent return false; } - // update used talent points count - SetUsedTalentCount(GetUsedTalentCount() + talentCost); - // update free primary prof.points (if any, can be none in case GM .learn prof. learning) if (uint32 freeProfs = GetFreePrimaryProfessionPoints()) { @@ -3773,8 +3720,8 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const bool Player::IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const { - if (TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec()))) - return spellInfo->Id == talentTab->MasterySpellId[0] || spellInfo->Id == talentTab->MasterySpellId[1]; + if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec()))) + return spellInfo->Id == chrSpec->MasterySpellID[0] || spellInfo->Id == chrSpec->MasterySpellID[1]; return false; } @@ -3829,7 +3776,7 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) // unlearn non talent higher ranks (recursive) if (uint32 nextSpell = sSpellMgr->GetNextSpellInChain(spell_id)) { - if (HasSpell(nextSpell) && !GetTalentSpellPos(nextSpell)) + if (HasSpell(nextSpell) && !GetTalentBySpellID(nextSpell)) RemoveSpell(nextSpell, disabled, false); } //unlearn spells dependent from recently removed spells @@ -3842,8 +3789,6 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) if (itr == m_spells.end()) return; // already unleared - bool giveTalentPoints = disabled || !itr->second->disabled; - bool cur_active = itr->second->active; bool cur_dependent = itr->second->dependent; @@ -3871,16 +3816,6 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) if (PetAura const* petSpell = sSpellMgr->GetPetAura(spell_id, i)) RemovePetAura(petSpell); - // free talent points - uint32 talentCosts = GetTalentSpellCost(spell_id); - if (talentCosts > 0 && giveTalentPoints) - { - if (talentCosts < GetUsedTalentCount()) - SetUsedTalentCount(GetUsedTalentCount() - talentCosts); - else - SetUsedTalentCount(0); - } - // update free primary prof.points (if not overflow setting, can be in case GM use before .learn prof. learning) SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id); if (spellInfo && spellInfo->IsPrimaryProfessionFirstRank()) @@ -3938,16 +3873,9 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank) if (uint32 prev_id = sSpellMgr->GetPrevSpellInChain(spell_id)) { - // if talent then lesser rank also talent and need learn - if (talentCosts) - { - // I cannot see why mangos has these lines. - //if (learn_low_rank) - // learnSpell(prev_id, false); - } // if ranked non-stackable spell: need activate lesser rank and update dendence state /// No need to check for spellInfo != NULL here because if cur_active is true, then that means that the spell was already in m_spells, and only valid spells can be pushed there. - else if (cur_active && !spellInfo->IsStackableWithRanks() && spellInfo->IsRanked()) + if (cur_active && !spellInfo->IsStackableWithRanks() && spellInfo->IsRanked()) { // need manually update dependence state (learn spell ignore like attempts) PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id); @@ -4191,14 +4119,6 @@ bool Player::ResetTalents(bool no_cost) if (HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) RemoveAtLoginFlag(AT_LOGIN_RESET_TALENTS, true); - uint32 talentPointsForLevel = CalculateTalentsPoints(); - - if (!GetUsedTalentCount()) - { - SetFreeTalentPoints(talentPointsForLevel); - return false; - } - uint32 cost = 0; if (!no_cost && !sWorld->getBoolConfig(CONFIG_NO_RESET_TALENT_COST)) @@ -4221,54 +4141,52 @@ bool Player::ResetTalents(bool no_cost) if (!talentInfo) continue; - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - - if (!talentTabInfo) - continue; - // unlearn only talents for character class // some spell learned by one class as normal spells or know at creation but another class learn it as talent, // to prevent unexpected lost normal learned spell skip another class talents - if ((getClassMask() & talentTabInfo->ClassMask) == 0) + if (getClass() != talentInfo->ClassID) continue; - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) - { - // skip non-existant talent ranks - if (talentInfo->RankID[rank] == 0) - continue; - const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->RankID[rank]); - if (!_spellEntry) - continue; - RemoveSpell(talentInfo->RankID[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->RankID[rank]); - if (plrTalent != GetTalentMap(GetActiveSpec())->end()) - plrTalent->second->state = PLAYERSPELL_REMOVED; - } - } + const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID); - // Remove spec specific spells - uint32 const* talentTabs = GetTalentTabPages(getClass()); - for (uint32 i = 0; i < MAX_TALENT_TABS; ++i) - { - if (std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentTabs[i])) - for (size_t j = 0; j < specSpells->size(); ++j) - RemoveSpell(specSpells->at(j), true); + if (!_spellEntry) + continue; + + RemoveSpell(talentInfo->SpellID, 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); - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabs[i]); - for (uint32 j = 0; j < MAX_MASTERY_SPELLS; ++j) - if (uint32 mastery = talentTabInfo->MasterySpellId[j]) - RemoveAurasDueToSpell(mastery); + // 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->SpellID); + if (plrTalent != GetTalentMap(GetActiveSpec())->end()) + plrTalent->second->state = PLAYERSPELL_REMOVED; } + // Remove all specialization specific spells and give default ones which were overriden + auto specSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(GetActiveSpec())); + if (specSpells != sSpecializationSpellsBySpecStore.end()) + { + for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) + { + SpecializationSpellsEntry const* specSpell = *it; + if (HasSpell(specSpell->SpellID)) { + RemoveSpell(specSpell->SpellID, true); + if (specSpell->OverridesSpellID) + LearnSpell(specSpell->OverridesSpellID, false); + } + } + } - SetPrimaryTalentTree(GetActiveSpec(), 0); - SetFreeTalentPoints(talentPointsForLevel); + // Unlearn masteries + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec())); + for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) + if (uint32 mastery = chrSpec->MasterySpellID[i]) + RemoveAurasDueToSpell(mastery); + + SetTalentSpec(GetActiveSpec(), 0); SQLTransaction trans = CharacterDatabase.BeginTransaction(); _SaveTalents(trans); @@ -15229,12 +15147,6 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver, SetTitle(titleEntry); } - if (uint32 talents = quest->GetBonusTalents()) - { - AddQuestRewardedTalentCount(talents); - InitTalentForLevel(); - } - // Send reward mail if (uint32 mail_template_id = quest->GetRewMailTemplateId()) { @@ -17534,15 +17446,17 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) } // Only load selected specializations, learning mastery spells requires this - Tokenizer talentTrees(fields[26].GetString(), ' ', MAX_TALENT_SPECS); + Tokenizer talentSpecs(fields[26].GetString(), ' ', MAX_TALENT_SPECS); for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) { - if (i >= talentTrees.size()) + if (i >= talentSpecs.size()) break; - uint32 talentTree = atol(talentTrees[i]); - if (sTalentTabStore.LookupEntry(talentTree)) - SetPrimaryTalentTree(i, talentTree); + uint32 talentSpec = atol(talentSpecs[i]); + if (sChrSpecializationStore.LookupEntry(talentSpec)) + SetTalentSpec(i, talentSpec); + else + SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); } _LoadTalents(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_TALENTS)); @@ -17632,17 +17546,6 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder) SetPower(POWER_ECLIPSE, 0); - // Verify loaded talent specializations - for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) - { - if (i >= talentTrees.size()) - break; - - uint32 talentTree = atol(talentTrees[i]); - if (talentTree != 0 && !sTalentTabStore.LookupEntry(talentTree) && i == GetActiveSpec()) - SetAtLoginFlag(AT_LOGIN_RESET_TALENTS); // invalid tree, reset talents - } - TC_LOG_DEBUG("entities.player.loading", "The value of player %s after load item and aura is: ", m_name.c_str()); outDebugValues(); @@ -18494,9 +18397,6 @@ void Player::_LoadQuestStatusRewarded(PreparedQueryResult result) if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(quest->GetCharTitleId())) SetTitle(titleEntry); } - - if (uint32 talents = quest->GetBonusTalents()) - AddQuestRewardedTalentCount(talents); } m_RewardedQuests.insert(quest_id); @@ -19209,7 +19109,7 @@ void Player::SaveToDB(bool create /*=false*/) ss.str(""); for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) - ss << GetPrimaryTalentTree(i) << " "; + ss << GetTalentSpec(i) << " "; stmt->setString(index++, ss.str()); stmt->setUInt16(index++, (uint16)m_ExtraFlags); stmt->setUInt8(index++, m_stableSlots); @@ -19338,7 +19238,7 @@ void Player::SaveToDB(bool create /*=false*/) ss.str(""); for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i) - ss << GetPrimaryTalentTree(i) << " "; + ss << GetTalentSpec(i) << " "; stmt->setString(index++, ss.str()); stmt->setUInt16(index++, (uint16)m_ExtraFlags); stmt->setUInt8(index++, m_stableSlots); @@ -23404,11 +23304,6 @@ void Player::ResetSpells(bool myClassOnly) if (spellInfo->SpellFamilyName != family) continue; - // skip spells with first rank learned as talent (and all talents then also) - uint32 firstRank = spellInfo->GetFirstRankSpell()->Id; - if (GetTalentSpellCost(firstRank) > 0) - continue; - // skip broken spells if (!SpellMgr::IsSpellValid(spellInfo, this, false)) continue; @@ -25314,38 +25209,6 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot) SendEquipError(msg, NULL, NULL, item->itemid); } -// 6.x - removeme -uint32 Player::CalculateTalentsPoints() const -{ - // this dbc file has entries only up to level 100 - /*NumTalentsAtLevelEntry const* count = sNumTalentsAtLevelStore.LookupEntry(std::min<uint32>(getLevel(), 100)); - if (!count) - return 0; - - float baseForLevel = count->Talents; - - if (getClass() != CLASS_DEATH_KNIGHT || GetMapId() != 609) - return uint32(baseForLevel * sWorld->getRate(RATE_TALENT)); - - // Death Knight starting level - // hardcoded here - number of quest awarded talents is equal to number of talents any other class would have at level 55 - if (getLevel() < 55) - return 0; - - NumTalentsAtLevelEntry const* dkBase = sNumTalentsAtLevelStore.LookupEntry(55); - if (!dkBase) - return 0; - - float talentPointsForLevel = count->Talents - dkBase->Talents; - talentPointsForLevel += float(GetQuestRewardedTalentCount()); - - if (talentPointsForLevel > baseForLevel) - talentPointsForLevel = baseForLevel; - - return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT));*/ - return 0; -} - bool Player::IsKnowHowFlyIn(uint32 mapid, uint32 zone) const { // continent checked in SpellInfo::CheckLocation at cast and area update @@ -25651,108 +25514,26 @@ void Player::CompletedAchievement(AchievementEntry const* entry) m_achievementMgr->CompletedAchievement(entry, this); } -bool Player::LearnTalent(uint32 talentId, uint32 talentRank) +bool Player::LearnTalent(uint32 talentId) { - uint32 CurTalentPoints = GetFreeTalentPoints(); - - if (CurTalentPoints == 0) - return false; - - if (talentRank >= MAX_TALENT_RANK) - return false; - TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); if (!talentInfo) return false; - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - - if (!talentTabInfo) - return false; - // prevent learn talent for different class (cheating) - if ((getClassMask() & talentTabInfo->ClassMask) == 0) + if (getClass() != talentInfo->ClassID) return false; - // find current max talent rank (0~5) - uint8 curtalent_maxrank = 0; // 0 = not learned any rank - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) - { - if (talentInfo->RankID[rank] && HasSpell(talentInfo->RankID[rank])) - { - curtalent_maxrank = (rank + 1); - break; - } - } - - // we already have same or higher talent rank learned - if (curtalent_maxrank >= (talentRank + 1)) - return false; - - // check if we have enough talent points - if (CurTalentPoints < (talentRank - curtalent_maxrank + 1)) - return false; - - // Check if it requires another talent - if (talentInfo->DependsOn > 0) - { - if (TalentEntry const* depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) - { - bool hasEnoughRank = false; - for (uint8 rank = talentInfo->DependsOnRank; rank < MAX_TALENT_RANK; rank++) - { - if (depTalentInfo->RankID[rank] != 0) - if (HasSpell(depTalentInfo->RankID[rank])) - hasEnoughRank = true; - } - if (!hasEnoughRank) - return false; - } - } - - // Find out how many points we have in this field - uint32 spentPoints = 0; - uint32 primaryTreeTalents = 0; - uint32 tTab = talentInfo->TalentTab; - bool isMainTree = GetPrimaryTalentTree(GetActiveSpec()) == tTab || !GetPrimaryTalentTree(GetActiveSpec()); - - if (talentInfo->Row > 0 || !isMainTree) - { - 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 - { - for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++) - { - if (tmpTalent->RankID[rank] != 0) - { - if (HasSpell(tmpTalent->RankID[rank])) - { - if (tmpTalent->TalentTab == tTab) - spentPoints += (rank + 1); - if (tmpTalent->TalentTab == GetPrimaryTalentTree(GetActiveSpec())) - primaryTreeTalents += (rank + 1); - } - } - } - } - } - } - - // not have required min points spent in talent tree - if (spentPoints < (talentInfo->Row * MAX_TALENT_RANK)) - return false; - - // player has not spent 31 talents in main tree before attempting to learn other tree's talents - if (!isMainTree && primaryTreeTalents < REQ_PRIMARY_TREE_TALENTS) + // Check player level. + if (getLevel() < (15*talentInfo->TierID + 15)) return false; // spell not set in talent.dbc - uint32 spellid = talentInfo->RankID[talentRank]; + uint32 spellid = talentInfo->SpellID; if (spellid == 0) { - TC_LOG_ERROR("entities.player", "Talent.dbc have for talent: %u Rank: %u spell id = 0", talentId, talentRank); + TC_LOG_ERROR("entities.player", "Talent.dbc have for talent: %u spell id = 0", talentId); return false; } @@ -25764,162 +25545,37 @@ bool Player::LearnTalent(uint32 talentId, uint32 talentRank) LearnSpell(spellid, false); AddTalent(spellid, GetActiveSpec(), true); - TC_LOG_INFO("misc", "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, GetActiveSpec()); + TC_LOG_INFO("misc", "TalentID: %u Spell: %u Spec: %u\n", talentId, spellid, GetActiveSpec()); // set talent tree for player - if (!GetPrimaryTalentTree(GetActiveSpec())) - { - SetPrimaryTalentTree(GetActiveSpec(), talentInfo->TalentTab); - std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentInfo->TalentTab); - if (specSpells) - for (size_t i = 0; i < specSpells->size(); ++i) - LearnSpell(specSpells->at(i), false); - - if (CanUseMastery()) - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (SpellInfo const* masterySpell = sSpellMgr->GetSpellInfo(talentTabInfo->MasterySpellId[i])) - if (masterySpell->IsPassive() && IsNeedCastPassiveSpellAtLearn(masterySpell)) - CastSpell(this, masterySpell->Id, true); - } - - // update free talent points - SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1)); - return true; -} - -void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRank) -{ - Pet* pet = GetPet(); - - if (!pet) - return; - - if (petGuid != pet->GetGUID()) - return; - - uint32 CurTalentPoints = pet->GetFreeTalentPoints(); - - if (CurTalentPoints == 0) - return; - - if (talentRank >= MAX_PET_TALENT_RANK) - return; - - TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); - - if (!talentInfo) - return; - - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - - if (!talentTabInfo) - return; - - CreatureTemplate const* ci = pet->GetCreatureTemplate(); - - if (!ci) - return; - - CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->family); - - if (!pet_family) - return; - - if (pet_family->PetTalentType < 0) // not hunter pet - return; - - // prevent learn talent for different family (cheating) - if (!((1 << pet_family->PetTalentType) & talentTabInfo->petTalentMask)) - return; - - // find current max talent rank (0~5) - uint8 curtalent_maxrank = 0; // 0 = not learned any rank - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) - { - if (talentInfo->RankID[rank] && pet->HasSpell(talentInfo->RankID[rank])) - { - curtalent_maxrank = (rank + 1); - break; - } - } - - // we already have same or higher talent rank learned - if (curtalent_maxrank >= (talentRank + 1)) - return; - - // check if we have enough talent points - if (CurTalentPoints < (talentRank - curtalent_maxrank + 1)) - return; - - // Check if it requires another talent - if (talentInfo->DependsOn > 0) + if (!GetTalentSpec(GetActiveSpec())) { - if (TalentEntry const* depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) - { - bool hasEnoughRank = false; - for (uint8 rank = talentInfo->DependsOnRank; rank < MAX_TALENT_RANK; rank++) - { - if (depTalentInfo->RankID[rank] != 0) - if (pet->HasSpell(depTalentInfo->RankID[rank])) - hasEnoughRank = true; - } - if (!hasEnoughRank) - return; - } - } - - // Find out how many points we have in this field - uint32 spentPoints = 0; + SetTalentSpec(GetActiveSpec(), talentInfo->SpecID); - uint32 tTab = talentInfo->TalentTab; - if (talentInfo->Row > 0) - { - uint32 numRows = sTalentStore.GetNumRows(); - for (uint32 i = 0; i < numRows; ++i) // Loop through all talents. + // Replace default spells by specialization spells + auto specSpells = sSpecializationSpellsBySpecStore.find(talentInfo->SpecID); + if (specSpells != sSpecializationSpellsBySpecStore.end()) { - // Someday, someone needs to revamp - const TalentEntry* tmpTalent = sTalentStore.LookupEntry(i); - if (tmpTalent) // the way talents are tracked + for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) { - if (tmpTalent->TalentTab == tTab) - { - for (uint8 rank = 0; rank < MAX_TALENT_RANK; rank++) - { - if (tmpTalent->RankID[rank] != 0) - { - if (pet->HasSpell(tmpTalent->RankID[rank])) - { - spentPoints += (rank + 1); - } - } - } + SpecializationSpellsEntry const* specSpell = *it; + if (HasSpell(specSpell->OverridesSpellID)) { + RemoveSpell(specSpell->OverridesSpellID, true); + LearnSpell(specSpell->SpellID, false); } } } - } - - // not have required min points spent in talent tree - if (spentPoints < (talentInfo->Row * MAX_PET_TALENT_RANK)) - return; - // spell not set in talent.dbc - uint32 spellid = talentInfo->RankID[talentRank]; - if (spellid == 0) - { - TC_LOG_ERROR("entities.player", "Talent.dbc have for talent: %u Rank: %u spell id = 0", talentId, talentRank); - return; + if (CanUseMastery()) { + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(talentInfo->SpecID); + for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) + if (SpellInfo const* masterySpell = sSpellMgr->GetSpellInfo(chrSpec->MasterySpellID[i])) + if (masterySpell->IsPassive() && IsNeedCastPassiveSpellAtLearn(masterySpell)) + CastSpell(this, masterySpell->Id, true); + } } - // already known - if (pet->HasSpell(spellid)) - return; - - // learn! (other talent ranks will unlearned at learning) - pet->learnSpell(spellid); - TC_LOG_INFO("entities.player", "PetTalentID: %u Rank: %u Spell: %u\n", talentId, talentRank, spellid); - - // update free talent points - pet->SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1)); + return true; } void Player::AddKnownCurrency(uint32 itemId) @@ -25998,6 +25654,7 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const 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) @@ -26062,10 +25719,12 @@ void Player::BuildPlayerTalentsInfoData(WorldPacket* data) *data << uint16(GetGlyph(specIdx, i)); // GlyphProperties.dbc } } + */ } void Player::BuildPetTalentsInfoData(WorldPacket* data) { + /* 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 @@ -26133,11 +25792,12 @@ void Player::BuildPetTalentsInfoData(WorldPacket* data) 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) @@ -26145,6 +25805,7 @@ void Player::SendTalentsInfoData(bool pet) else BuildPlayerTalentsInfoData(&data); GetSession()->SendPacket(&data); + */ } void Player::BuildEnchantmentsInfoData(WorldPacket* data) @@ -26604,49 +26265,35 @@ void Player::ActivateSpec(uint8 spec) if (!talentInfo) continue; - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - - if (!talentTabInfo) - continue; - // unlearn only talents for character class // some spell learned by one class as normal spells or know at creation but another class learn it as talent, // to prevent unexpected lost normal learned spell skip another class talents - if ((getClassMask() & talentTabInfo->ClassMask) == 0) + if (getClass() != talentInfo->ClassID) continue; - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) - { - // skip non-existant talent ranks - if (talentInfo->RankID[rank] == 0) - continue; - RemoveSpell(talentInfo->RankID[rank], true); // removes the talent, and all dependant, learned, and chained spells.. - if (const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->RankID[rank])) - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) // search through the SpellInfo for valid trigger spells - if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL) - RemoveSpell(_spellEntry->Effects[i].TriggerSpell, true); // and remove any spells that the talent teaches - // 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->RankID[rank]); - //if (plrTalent != m_talents[m_activeSpec]->end()) - // plrTalent->second->state = PLAYERSPELL_REMOVED; - } + RemoveSpell(talentInfo->SpellID, true); } - // Remove spec specific spells - for (uint32 i = 0; i < MAX_TALENT_TABS; ++i) + // Unlearn specialization specific spells + auto specSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(GetActiveSpec())); + if (specSpells != sSpecializationSpellsBySpecStore.end()) { - uint32 const* talentTabs = GetTalentTabPages(getClass()); - std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(talentTabs[i]); - if (specSpells) - for (size_t i = 0; i < specSpells->size(); ++i) - RemoveSpell(specSpells->at(i), true); - - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabs[i]); - for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (uint32 mastery = talentTabInfo->MasterySpellId[i]) - RemoveSpell(mastery, true); + for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) + { + SpecializationSpellsEntry const* specSpell = *it; + if (HasSpell(specSpell->SpellID)) { + RemoveSpell(specSpell->SpellID, true); + LearnSpell(specSpell->OverridesSpellID, false); + } + } } + // Unlearn mastery spells + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec())); + for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) + if (chrSpec->MasterySpellID[i]) + RemoveSpell(chrSpec->MasterySpellID[i], true); + // set glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) // remove secondary glyph @@ -26654,8 +26301,8 @@ void Player::ActivateSpec(uint8 spec) if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph)) RemoveAurasDueToSpell(old_gp->SpellID); + // Activate new spec SetActiveSpec(spec); - uint32 spentTalents = 0; for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId) { @@ -26664,40 +26311,37 @@ void Player::ActivateSpec(uint8 spec) if (!talentInfo) continue; - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - - if (!talentTabInfo) - continue; - // learn only talents for character class - if ((getClassMask() & talentTabInfo->ClassMask) == 0) + if (getClass() != talentInfo->ClassID) continue; - // learn highest talent rank that exists in newly activated spec - for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank) + if (HasTalent(talentInfo->SpellID, GetActiveSpec())) { - // skip non-existant talent ranks - if (talentInfo->RankID[rank] == 0) - continue; - // if the talent can be found in the newly activated PlayerTalentMap - if (HasTalent(talentInfo->RankID[rank], GetActiveSpec())) - { - LearnSpell(talentInfo->RankID[rank], false); // add the talent to the PlayerSpellMap - spentTalents += (rank + 1); // increment the spentTalents count - } + LearnSpell(talentInfo->SpellID, false); } } - std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(GetPrimaryTalentTree(GetActiveSpec())); - if (specSpells) - for (size_t i = 0; i < specSpells->size(); ++i) - LearnSpell(specSpells->at(i), false); + // Replace default spells with specialization specific spells + auto newSpecSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(spec)); + if (newSpecSpells != sSpecializationSpellsBySpecStore.end()) + { + for (auto it = newSpecSpells->second.begin(); it != newSpecSpells->second.end(); ++it) + { + SpecializationSpellsEntry const* specSpell = *it; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(specSpell->SpellID); + if (getLevel() >= spellInfo->BaseLevel) { + if (specSpell->OverridesSpellID) + RemoveSpell(specSpell->OverridesSpellID, true); + LearnSpell(specSpell->SpellID, false); + } + } + } if (CanUseMastery()) - if (TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec()))) + if (ChrSpecializationEntry const* newChrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(spec))) for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) - if (uint32 mastery = talentTabInfo->MasterySpellId[i]) - LearnSpell(mastery, false); + if (newChrSpec->MasterySpellID[i]) + LearnSpell(newChrSpec->MasterySpellID[i], false); // set glyphs for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot) @@ -26712,7 +26356,6 @@ void Player::ActivateSpec(uint8 spec) SetGlyph(slot, glyph); } - SetUsedTalentCount(spentTalents); InitTalentForLevel(); { @@ -26731,7 +26374,7 @@ void Player::ActivateSpec(uint8 spec) SetPower(pw, 0); - if (!sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec()))) + if (!sChrSpecializationStore.LookupEntry(GetTalentSpec(spec))) ResetTalents(true); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index f01846f5593..d1a477ac5e1 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -123,38 +123,42 @@ struct PlayerTalent extern uint32 const MasterySpells[MAX_CLASSES]; -enum TalentTree // talent tabs -{ - TALENT_TREE_WARRIOR_ARMS = 746, - TALENT_TREE_WARRIOR_FURY = 815, - TALENT_TREE_WARRIOR_PROTECTION = 845, - TALENT_TREE_PALADIN_HOLY = 831, - TALENT_TREE_PALADIN_PROTECTION = 839, - TALENT_TREE_PALADIN_RETRIBUTION = 855, - TALENT_TREE_HUNTER_BEAST_MASTERY = 811, - TALENT_TREE_HUNTER_MARKSMANSHIP = 807, - TALENT_TREE_HUNTER_SURVIVAL = 809, - TALENT_TREE_ROGUE_ASSASSINATION = 182, - TALENT_TREE_ROGUE_COMBAT = 181, - TALENT_TREE_ROGUE_SUBTLETY = 183, - TALENT_TREE_PRIEST_DISCIPLINE = 760, - TALENT_TREE_PRIEST_HOLY = 813, - TALENT_TREE_PRIEST_SHADOW = 795, - TALENT_TREE_DEATH_KNIGHT_BLOOD = 398, - TALENT_TREE_DEATH_KNIGHT_FROST = 399, - TALENT_TREE_DEATH_KNIGHT_UNHOLY = 400, - TALENT_TREE_SHAMAN_ELEMENTAL = 261, - TALENT_TREE_SHAMAN_ENHANCEMENT = 263, - TALENT_TREE_SHAMAN_RESTORATION = 262, - TALENT_TREE_MAGE_ARCANE = 799, - TALENT_TREE_MAGE_FIRE = 851, - TALENT_TREE_MAGE_FROST = 823, - TALENT_TREE_WARLOCK_AFFLICTION = 871, - TALENT_TREE_WARLOCK_DEMONOLOGY = 867, - TALENT_TREE_WARLOCK_DESTRUCTION = 865, - TALENT_TREE_DRUID_BALANCE = 752, - TALENT_TREE_DRUID_FERAL_COMBAT = 750, - TALENT_TREE_DRUID_RESTORATION = 748 +enum TalentSpecialization // talent tabs +{ + TALENT_SPEC_MAGE_ARCANE = 62, + TALENT_SPEC_MAGE_FIRE = 63, + TALENT_SPEC_MAGE_FROST = 64, + TALENT_SPEC_PALADIN_HOLY = 65, + TALENT_SPEC_PALADIN_PROTECTION = 66, + TALENT_SPEC_PALADIN_RETRIBUTION = 70, + TALENT_SPEC_WARRIOR_ARMS = 71, + TALENT_SPEC_WARRIOR_FURY = 72, + TALENT_SPEC_WARRIOR_PROTECTION = 73, + TALENT_SPEC_DRUID_BALANCE = 102, + TALENT_SPEC_DRUID_CAT = 103, + TALENT_SPEC_DRUID_BEAR = 104, + TALENT_SPEC_DRUID_RESTORATION = 105, + TALENT_SPEC_DEATHKNIGHT_BLOOD = 250, + TALENT_SPEC_DEATHKNIGHT_FROST = 251, + TALENT_SPEC_DEATHKNIGHT_UNHOLY = 252, + TALENT_SPEC_HUNTER_BEASTMASTER = 253, + TALENT_SPEC_HUNTER_MARKSMAN = 254, + TALENT_SPEC_HUNTER_SURVIVAL = 255, + TALENT_SPEC_PRIEST_DISCIPLINE = 256, + TALENT_SPEC_PRIEST_HOLY = 257, + TALENT_SPEC_PRIEST_SHADOW = 258, + TALENT_SPEC_ROGUE_ASSASSINATION = 259, + TALENT_SPEC_ROGUE_COMBAT = 260, + TALENT_SPEC_ROGUE_SUBTLETY = 261, + TALENT_SPEC_SHAMAN_ELEMENTAL = 262, + TALENT_SPEC_SHAMAN_ENCHANCEMENT = 263, + TALENT_SPEC_SHAMAN_RESTORATION = 264, + TALENT_SPEC_WARLOCK_AFFLICTION = 265, + TALENT_SPEC_WARLOCK_DEMONOLOGY = 266, + TALENT_SPEC_WARLOCK_DESTRUCTION = 267, + TALENT_SPEC_MONK_BREWMASTER = 268, + TALENT_SPEC_MONK_BATTLEDANCER = 269, + TALENT_SPEC_MONK_MISTWEAVER = 270 }; // Spell modifier (used for modify other spells) @@ -1216,16 +1220,13 @@ private: struct PlayerTalentInfo { - PlayerTalentInfo() : - FreeTalentPoints(0), UsedTalentCount(0), QuestRewardedTalentCount(0), - ResetTalentsCost(0), ResetTalentsTime(0), - ActiveSpec(0), SpecsCount(1) + PlayerTalentInfo() : 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; + SpecInfo[i].TalentSpec = 0; } } @@ -1243,12 +1244,9 @@ struct PlayerTalentInfo { PlayerTalentMap* Talents; uint32 Glyphs[MAX_GLYPH_SLOT_INDEX]; - uint32 TalentTree; + uint32 TalentSpec; } SpecInfo[MAX_TALENT_SPECS]; - uint32 FreeTalentPoints; - uint32 UsedTalentCount; - uint32 QuestRewardedTalentCount; uint32 ResetTalentsCost; time_t ResetTalentsTime; uint8 ActiveSpec; @@ -1818,22 +1816,16 @@ class Player : public Unit, public GridObject<Player> std::string GetGuildName(); // 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; } 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; } bool ResetTalents(bool no_cost = false); uint32 GetNextResetTalentsCost() const; @@ -1841,11 +1833,9 @@ class Player : public Unit, public GridObject<Player> void BuildPlayerTalentsInfoData(WorldPacket* data); void BuildPetTalentsInfoData(WorldPacket* data); void SendTalentsInfoData(bool pet); - bool LearnTalent(uint32 talentId, uint32 talentRank); - void LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRank); + bool LearnTalent(uint32 talentId); 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); diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp index 81a1ae73832..54956e591b4 100644 --- a/src/server/game/Entities/Totem/Totem.cpp +++ b/src/server/game/Entities/Totem/Totem.cpp @@ -67,7 +67,7 @@ void Totem::InitStats(uint32 duration) GetOwner()->ToPlayer()->SendDirectMessage(&data); // set display id depending on caster's race - SetDisplayId(GetOwner()->GetModelForTotem(PlayerTotemType(m_Properties->Id))); + SetDisplayId(GetOwner()->GetModelForTotem(PlayerTotemType(m_Properties->ID))); } Minion::InitStats(duration); @@ -91,7 +91,7 @@ void Totem::InitSummon() if (GetSpell(1)) CastSpell(this, GetSpell(1), true); - if (m_Properties->Id == SUMMON_TYPE_TOTEM_FIRE && GetOwner()->HasAura(SPELL_TOTEMIC_WRATH_TALENT)) + if (m_Properties->ID == SUMMON_TYPE_TOTEM_FIRE && GetOwner()->HasAura(SPELL_TOTEMIC_WRATH_TALENT)) CastSpell(this, SPELL_TOTEMIC_WRATH, true); } diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index b832292d89b..37b4d4d97a0 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -526,16 +526,16 @@ void Player::UpdateMastery() value += GetRatingBonusValue(CR_MASTERY); SetFloatValue(PLAYER_MASTERY, value); - TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(GetPrimaryTalentTree(GetActiveSpec())); - if (!talentTab) + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec())); + if (!chrSpec) return; for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i) { - if (!talentTab->MasterySpellId[i]) + if (!chrSpec->MasterySpellID[i]) continue; - if (Aura* aura = GetAura(talentTab->MasterySpellId[i])) + if (Aura* aura = GetAura(chrSpec->MasterySpellID[i])) { for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) { diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 49b9c2c45ae..70f8eb4d0fa 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -4301,13 +4301,6 @@ void ObjectMgr::LoadQuests() qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell); qinfo->RewardSpell = 0; // no spell reward will display for this quest } - - else if (GetTalentSpellCost(qinfo->RewardSpell)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is talent, quest will not have a spell reward.", - qinfo->GetQuestId(), qinfo->RewardSpell, qinfo->RewardSpell); - qinfo->RewardSpell = 0; // no spell reward will display for this quest - } } if (qinfo->RewardSpellCast > 0) @@ -4327,13 +4320,6 @@ void ObjectMgr::LoadQuests() qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast); qinfo->RewardSpellCast = 0; // no spell will be cast on player } - - else if (GetTalentSpellCost(qinfo->RewardSpellCast)) - { - TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is talent, quest will not have a spell reward.", - qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast); - qinfo->RewardSpellCast = 0; // no spell will be cast on player - } } if (qinfo->RewardMailTemplateId) @@ -8134,12 +8120,6 @@ void ObjectMgr::AddSpellToTrainer(uint32 ID, uint32 SpellID, uint32 MoneyCost, u return; } - if (GetTalentSpellCost(SpellID)) - { - TC_LOG_ERROR("sql.sql", "Table `npc_trainer` contains an ID (%u) for a non-existing spell (Spell: %u) which is a talent, ignoring", ID, SpellID); - return; - } - TrainerSpellData& data = _cacheTrainerSpellStore[ID]; TrainerSpell& trainerSpell = data.spellList[SpellID]; diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 180e9bae74c..699d91c4cc9 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -853,6 +853,7 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec void WorldSession::HandlePetLearnTalent(WorldPacket& recvData) { + /* TODO: 6.x remove pet talents (add pet specializations) TC_LOG_DEBUG("network", "WORLD: CMSG_PET_LEARN_TALENT"); ObjectGuid guid; @@ -860,11 +861,12 @@ void WorldSession::HandlePetLearnTalent(WorldPacket& recvData) recvData >> guid >> talentId >> requestedRank; _player->LearnPetTalent(guid, talentId, requestedRank); - _player->SendTalentsInfoData(true); + _player->SendTalentsInfoData(true);*/ } void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData) { + /* TODO: 6.x remove pet talents (add pet specializations) TC_LOG_DEBUG("network", "CMSG_LEARN_PREVIEW_TALENTS_PET"); ObjectGuid guid; @@ -887,5 +889,5 @@ void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData) _player->SendTalentsInfoData(true); - recvData.rfinish(); + recvData.rfinish();*/ } diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index 61868a8616a..c3f9dfc2868 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -29,15 +29,17 @@ void WorldSession::HandleLearnTalentOpcode(WorldPacket& recvData) { + /* TODO: 6.x update packet struct (note: LearnTalent no longer has rank argument) uint32 talentId, requestedRank; recvData >> talentId >> requestedRank; if (_player->LearnTalent(talentId, requestedRank)) - _player->SendTalentsInfoData(false); + _player->SendTalentsInfoData(false);*/ } void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) { + /* TODO: 6.x update packet struct TC_LOG_DEBUG("network", "CMSG_LEARN_PREVIEW_TALENTS"); int32 tabPage; @@ -77,7 +79,7 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket) _player->SendTalentsInfoData(false); - recvPacket.rfinish(); + recvPacket.rfinish();*/ } void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index c383ba0d51f..c3ba18cad2c 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2049,7 +2049,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex) // however so far noone found a generic check to find all of those (there's no related data in summonproperties.dbc // and in spell attributes, possibly we need to add a table for those) // so here's a list of MiscValueB values, which is currently most generic check - switch (properties->Id) + switch (properties->ID) { case 64: case 61: diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 9fc99e431d3..8bef55128c4 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1478,9 +1478,10 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const { // talents that learn spells can have stance requirements that need ignore // (this requirement only for client-side stance show in talent description) + /* TODO: 6.x fix this in proper way (probably spell flags/attributes?) if (GetTalentSpellCost(Id) > 0 && (Effects[0].Effect == SPELL_EFFECT_LEARN_SPELL || Effects[1].Effect == SPELL_EFFECT_LEARN_SPELL || Effects[2].Effect == SPELL_EFFECT_LEARN_SPELL)) - return SPELL_CAST_OK; + return SPELL_CAST_OK;*/ uint32 stanceMask = (form ? 1 << (form - 1) : 0); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index b3f2f283c4c..2c5d5c76bbe 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1227,6 +1227,7 @@ void SpellMgr::UnloadSpellInfoChains() void SpellMgr::LoadSpellTalentRanks() { + /* TODO: 6.x remove this // cleanup core data before reload - remove reference to ChainNode from SpellInfo UnloadSpellInfoChains(); @@ -1283,7 +1284,7 @@ void SpellMgr::LoadSpellTalentRanks() prevSpell = currentSpell; } - } + }*/ } void SpellMgr::LoadSpellRanks() @@ -1538,7 +1539,7 @@ void SpellMgr::LoadSpellLearnSpells() continue; } - if (GetTalentSpellCost(node.spell)) + if (GetTalentBySpellID(node.spell)) { TC_LOG_ERROR("sql.sql", "Spell %u listed in `spell_learn_spell` attempt learning talent spell %u, skipped", spell_id, node.spell); continue; @@ -1576,7 +1577,7 @@ void SpellMgr::LoadSpellLearnSpells() // talent or passive spells or skill-step spells auto-cast and not need dependent learning, // pet teaching spells must not be dependent learning (cast) // other required explicit dependent learning - dbc_node.autoLearned = entry->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET || GetTalentSpellCost(spell) > 0 || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP); + dbc_node.autoLearned = entry->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET || GetTalentBySpellID(spell) || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP); SpellLearnSpellMapBounds db_node_bounds = dbSpellLearnSpells.equal_range(spell); @@ -1602,22 +1603,22 @@ void SpellMgr::LoadSpellLearnSpells() } uint32 mastery_count = 0; - for (uint32 i = 0; i < sTalentTabStore.GetNumRows(); ++i) + for (uint32 i = 0; i < sChrSpecializationStore.GetNumRows(); ++i) { - TalentTabEntry const* talentTab = sTalentTabStore.LookupEntry(i); - if (!talentTab) + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(i); + if (!chrSpec) continue; for (uint32 c = CLASS_WARRIOR; c < MAX_CLASSES; ++c) { - if (!(talentTab->ClassMask & (1 << (c - 1)))) + if (chrSpec->ClassID != c) continue; uint32 masteryMainSpell = MasterySpells[c]; for (uint32 m = 0; m < MAX_MASTERY_SPELLS; ++m) { - uint32 mastery = talentTab->MasterySpellId[m]; + uint32 mastery = chrSpec->MasterySpellID[m]; if (!mastery) continue; diff --git a/src/server/game/Tools/CharacterDatabaseCleaner.cpp b/src/server/game/Tools/CharacterDatabaseCleaner.cpp index 11ed54bfa81..a63a8ae6cdd 100644 --- a/src/server/game/Tools/CharacterDatabaseCleaner.cpp +++ b/src/server/game/Tools/CharacterDatabaseCleaner.cpp @@ -128,7 +128,7 @@ void CharacterDatabaseCleaner::CleanCharacterSkills() bool CharacterDatabaseCleaner::SpellCheck(uint32 spell_id) { - return sSpellMgr->GetSpellInfo(spell_id) && !GetTalentSpellPos(spell_id); + return sSpellMgr->GetSpellInfo(spell_id) && GetTalentBySpellID(spell_id) != nullptr; } void CharacterDatabaseCleaner::CleanCharacterSpell() @@ -142,7 +142,7 @@ bool CharacterDatabaseCleaner::TalentCheck(uint32 talent_id) if (!talentInfo) return false; - return sTalentTabStore.LookupEntry(talentInfo->TalentTab) != nullptr; + return sChrSpecializationStore.LookupEntry(talentInfo->SpecID) != nullptr; } void CharacterDatabaseCleaner::CleanCharacterTalent() diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp index eb5be0950aa..81499567b72 100644 --- a/src/server/scripts/Commands/cs_learn.cpp +++ b/src/server/scripts/Commands/cs_learn.cpp @@ -116,9 +116,6 @@ public: else targetPlayer->LearnSpell(spell, false); - if (GetTalentSpellCost(spellInfo->GetFirstRankSpell()->Id)) - targetPlayer->SendTalentsInfoData(false); - return true; } @@ -176,10 +173,6 @@ public: if (spellInfo->SpellFamilyName != family) continue; - // skip spells with first rank learned as talent (and all talents then also) - if (GetTalentSpellCost(spellInfo->GetFirstRankSpell()->Id) > 0) - continue; - // skip broken spells if (!SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer(), false)) continue; @@ -194,7 +187,7 @@ public: static bool HandleLearnAllMyTalentsCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); - uint32 classMask = player->getClassMask(); + uint32 playerClass = player->getClass(); for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i) { @@ -202,44 +195,25 @@ public: if (!talentInfo) continue; - TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); - if (!talentTabInfo) - continue; - - if ((classMask & talentTabInfo->ClassMask) == 0) + if (playerClass != talentInfo->ClassID) continue; - // search highest talent rank - uint32 spellId = 0; - for (int8 rank = MAX_TALENT_RANK - 1; rank >= 0; --rank) - { - if (talentInfo->RankID[rank] != 0) - { - spellId = talentInfo->RankID[rank]; - break; - } - } - - if (!spellId) // ??? none spells in talent - continue; - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentInfo->SpellID); if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, handler->GetSession()->GetPlayer(), false)) continue; // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) - player->LearnSpellHighestRank(spellId); - player->AddTalent(spellId, player->GetActiveSpec(), true); + player->LearnSpellHighestRank(talentInfo->SpellID); + player->AddTalent(talentInfo->SpellID, player->GetActiveSpec(), true); } - player->SetFreeTalentPoints(0); - handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); return true; } static bool HandleLearnAllMyPetTalentsCommand(ChatHandler* handler, char const* /*args*/) { + /* TODO: 6.x remove pet talents Player* player = handler->GetSession()->GetPlayer(); Pet* pet = player->GetPet(); @@ -312,7 +286,7 @@ public: pet->SetFreeTalentPoints(0); - handler->SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS); + handler->SendSysMessage(LANG_COMMAND_LEARN_PET_TALENTS);*/ return true; } @@ -484,9 +458,6 @@ public: else handler->SendSysMessage(LANG_FORGET_SPELL); - if (GetTalentSpellCost(spellId)) - target->SendTalentsInfoData(false); - return true; } }; diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index 2a090aa70a8..deb714d1ef8 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -435,7 +435,7 @@ public: handler->PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, auras.size()); for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { - bool talent = GetTalentSpellCost(itr->second->GetBase()->GetId()) > 0; + bool talent = (GetTalentBySpellID(itr->second->GetBase()->GetId()) != nullptr); AuraApplication const* aurApp = itr->second; Aura const* aura = aurApp->GetBase(); diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index 7d8fec52143..55468788d9f 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -812,15 +812,13 @@ public: SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[0].TriggerSpell); - uint32 talentCost = GetTalentSpellCost(id); - - bool talent = (talentCost > 0); + bool talent = (GetTalentBySpellID(id) != nullptr); bool passive = spellInfo->IsPassive(); bool active = target && target->HasAura(id); // unit32 used to prevent interpreting uint8 as char at output // find rank of learned spell for learning spell, or talent rank - uint32 rank = talentCost ? talentCost : learn && learnSpellInfo ? learnSpellInfo->GetRank() : spellInfo->GetRank(); + uint32 rank = learn && learnSpellInfo ? learnSpellInfo->GetRank() : spellInfo->GetRank(); // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format std::ostringstream ss; @@ -884,15 +882,13 @@ public: SpellInfo const* learnSpellInfo = sSpellMgr->GetSpellInfo(spellInfo->Effects[0].TriggerSpell); - uint32 talentCost = GetTalentSpellCost(id); - - bool talent = (talentCost > 0); + bool talent = (GetTalentBySpellID(id) != nullptr); bool passive = spellInfo->IsPassive(); bool active = target && target->HasAura(id); // unit32 used to prevent interpreting uint8 as char at output // find rank of learned spell for learning spell, or talent rank - uint32 rank = talentCost ? talentCost : learn && learnSpellInfo ? learnSpellInfo->GetRank() : spellInfo->GetRank(); + uint32 rank = learn && learnSpellInfo ? learnSpellInfo->GetRank() : spellInfo->GetRank(); // send spell in "id - [name, rank N] [talent] [passive] [learn] [known]" format std::ostringstream ss; diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index 24283dca7ac..d520c1cf765 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -419,6 +419,7 @@ public: //Edit Player TP static bool HandleModifyTalentCommand (ChatHandler* handler, const char* args) { + /* TODO: 6.x remove this if (!*args) return false; @@ -459,7 +460,7 @@ public: handler->SendSysMessage(LANG_NO_CHAR_SELECTED); handler->SetSentErrorMessage(true); - return false; + return false;*/ } //Edit Player Aspeed diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index 7049ad90a27..ed0709c6ad9 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -168,7 +168,7 @@ class spell_dru_eclipse_energize : public SpellScriptLoader Player* caster = GetCaster()->ToPlayer(); // No boomy, no deal. - if (caster->GetPrimaryTalentTree(caster->GetActiveSpec()) != TALENT_TREE_DRUID_BALANCE) + if (caster->GetTalentSpec(caster->GetActiveSpec()) != TALENT_SPEC_DRUID_BALANCE) return; switch (GetSpellInfo()->Id) |