Core/Talents: Update talent system, remove talent points

This commit is contained in:
Intel
2014-11-10 21:09:18 +02:00
parent e90ef4fa24
commit 24850994b4
28 changed files with 314 additions and 798 deletions
+2 -1
View File
@@ -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
@@ -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;
+1 -1
View File
@@ -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
@@ -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
+1 -8
View File
@@ -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:
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
+28 -47
View File
@@ -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)
+10 -6
View File
@@ -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;
+47 -62
View File
@@ -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
{
+2
View File
@@ -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";
+5 -42
View File
@@ -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()
+128 -485
View File
@@ -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)
const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->SpellID);
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);
// 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)
{
// 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;
SpecializationSpellsEntry const* specSpell = *it;
if (HasSpell(specSpell->SpellID)) {
RemoveSpell(specSpell->SpellID, true);
if (specSpell->OverridesSpellID)
LearnSpell(specSpell->OverridesSpellID, false);
}
}
}
// 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);
TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabs[i]);
for (uint32 j = 0; j < MAX_MASTERY_SPELLS; ++j)
if (uint32 mastery = talentTabInfo->MasterySpellId[j])
RemoveAurasDueToSpell(mastery);
}
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()))
if (!GetTalentSpec(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);
SetTalentSpec(GetActiveSpec(), talentInfo->SpecID);
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]))
// Replace default spells by specialization spells
auto specSpells = sSpecializationSpellsBySpecStore.find(talentInfo->SpecID);
if (specSpells != sSpecializationSpellsBySpecStore.end())
{
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 (TalentEntry const* depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn))
{
bool hasEnoughRank = false;
for (uint8 rank = talentInfo->DependsOnRank; rank < MAX_TALENT_RANK; rank++)
for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it)
{
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;
uint32 tTab = talentInfo->TalentTab;
if (talentInfo->Row > 0)
{
uint32 numRows = sTalentStore.GetNumRows();
for (uint32 i = 0; i < numRows; ++i) // Loop through all talents.
{
// Someday, someone needs to revamp
const TalentEntry* tmpTalent = sTalentStore.LookupEntry(i);
if (tmpTalent) // the way talents are tracked
{
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);
}
}
}
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);
}
}
// 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;
}
// 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,48 +26265,34 @@ 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)
RemoveSpell(talentInfo->SpellID, true);
}
// Unlearn specialization specific spells
auto specSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(GetActiveSpec()));
if (specSpells != sSpecializationSpellsBySpecStore.end())
{
for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it)
{
// 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;
SpecializationSpellsEntry const* specSpell = *it;
if (HasSpell(specSpell->SpellID)) {
RemoveSpell(specSpell->SpellID, true);
LearnSpell(specSpell->OverridesSpellID, false);
}
}
}
// Remove spec specific spells
for (uint32 i = 0; i < MAX_TALENT_TABS; ++i)
{
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);
}
// 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)
@@ -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);
}
}
// 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);
}
}
}
std::vector<uint32> const* specSpells = GetTalentTreePrimarySpells(GetPrimaryTalentTree(GetActiveSpec()));
if (specSpells)
for (size_t i = 0; i < specSpells->size(); ++i)
LearnSpell(specSpells->at(i), 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);
}
+41 -51
View File
@@ -123,38 +123,42 @@ struct PlayerTalent
extern uint32 const MasterySpells[MAX_CLASSES];
enum TalentTree // talent tabs
enum TalentSpecialization // 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
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);
+2 -2
View File
@@ -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);
}
+4 -4
View File
@@ -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)
{
-20
View File
@@ -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];
+4 -2
View File
@@ -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();*/
}
+4 -2
View File
@@ -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)
+1 -1
View File
@@ -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:
+2 -1
View File
@@ -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);
+9 -8
View File
@@ -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;
@@ -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()
+7 -36
View File
@@ -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)
if (playerClass != talentInfo->ClassID)
continue;
if ((classMask & talentTabInfo->ClassMask) == 0)
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;
}
};
+1 -1
View File
@@ -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();
+4 -8
View File
@@ -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;
+2 -1
View File
@@ -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
+1 -1
View File
@@ -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)