aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp2
-rw-r--r--src/server/game/DataStores/DBCStores.cpp38
-rw-r--r--src/server/game/DataStores/DBCStores.h1
-rw-r--r--src/server/game/DataStores/DBCStructure.h8
-rw-r--r--src/server/game/DataStores/DBCfmt.h5
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp5
-rw-r--r--src/server/game/Entities/Player/Player.cpp416
-rw-r--r--src/server/game/Entities/Player/Player.h75
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp6
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp2
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp2
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h8
-rw-r--r--src/server/game/Server/Packets/TalentPackets.cpp38
-rw-r--r--src/server/game/Server/Packets/TalentPackets.h54
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp12
-rw-r--r--src/server/game/Tools/CharacterDatabaseCleaner.cpp2
-rw-r--r--src/server/scripts/Commands/cs_learn.cpp2
-rw-r--r--src/server/scripts/Commands/cs_reset.cpp6
-rw-r--r--src/server/scripts/Spells/spell_druid.cpp2
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp18
22 files changed, 327 insertions, 379 deletions
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 35956191f5e..d1aa2f77cf8 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -1070,7 +1070,7 @@ void Battleground::AddPlayer(Player* player)
BattlegroundPlayer bp;
bp.OfflineRemoveTime = 0;
bp.Team = team;
- bp.ActiveSpec = player->GetTalentSpec(player->GetActiveSpec());
+ bp.ActiveSpec = player->GetActiveTalentSpec();
// Add to list/maps
m_Players[player->GetGUID()] = bp;
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 598c2e5d5f3..333b7f5a2c2 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -163,6 +163,8 @@ DBCStorage <MapEntry> sMapStore(MapEntryfmt);
DBCStorage <MapDifficultyEntry> sMapDifficultyStore(MapDifficultyEntryfmt); // only for loading
MapDifficultyMap sMapDifficultyMap;
+DBCStorage <MinorTalentEntry> sMinorTalentStore(MinorTalentEntryfmt);
+
DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
DBCStorage <MountCapabilityEntry> sMountCapabilityStore(MountCapabilityfmt);
DBCStorage <MountTypeEntry> sMountTypeStore(MountTypefmt);
@@ -570,7 +572,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftStore, dbcPath, "SpellShapeshift.dbc");//19116
LoadDBC(availableDbcLocales, bad_dbc_files, sSpellShapeshiftFormStore, dbcPath, "SpellShapeshiftForm.dbc");//19116
//LoadDBC(availableDbcLocales, bad_dbc_files, sStableSlotPricesStore, dbcPath, "StableSlotPrices.dbc");
- LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc");//15595
+ LoadDBC(availableDbcLocales, bad_dbc_files, sSummonPropertiesStore, dbcPath, "SummonProperties.dbc");//19116
// Must be done when sSkillLineAbilityStore, sSpellStore, sSpellLevelsStore and sCreatureFamilyStore are all loaded
/* TODO: Requires spells attributes from SpellMisc.db2 is loaded after dbc
@@ -608,8 +610,6 @@ void LoadDBCStores(const std::string& dataPath)
}
*/
- LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc");//15595
-
// Create Spelldifficulty searcher
/* TODO: 6.x update to new spell diffs
for (uint32 i = 0; i < sSpellDifficultyStore.GetNumRows(); ++i)
@@ -640,6 +640,9 @@ void LoadDBCStores(const std::string& dataPath)
sSpellMgr->SetSpellDifficultyId(uint32(newEntry.SpellID[x]), spellDiff->ID);
}*/
+ LoadDBC(availableDbcLocales, bad_dbc_files, sTalentStore, dbcPath, "Talent.dbc");//19116
+ LoadDBC(availableDbcLocales, bad_dbc_files, sMinorTalentStore, dbcPath, "MinorTalent.dbc");//19116
+
for (unsigned int i = 0; i < sTalentStore.GetNumRows(); ++i)
{
TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
@@ -649,35 +652,6 @@ void LoadDBCStores(const std::string& dataPath)
sTalentBySpellIDMap[talentInfo->SpellID] = talentInfo;
}
- // 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
- {
- // now have all max ranks (and then bit amount used for store talent ranks in inspect)
- for (uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId)
- {
- TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabId);
- if (!talentTabInfo)
- continue;
-
- // prevent memory corruption; otherwise cls will become 12 below
- if ((talentTabInfo->ClassMask & CLASSMASK_ALL_PLAYABLE) == 0)
- continue;
-
- // store class talent tab pages
- for (uint32 cls = 1; cls < MAX_CLASSES; ++cls)
- if (talentTabInfo->ClassMask & (1 << (cls - 1)))
- sTalentTabPages[cls][talentTabInfo->tabpage] = talentTabId;
- }
- }
-
- LoadDBC(availableDbcLocales, bad_dbc_files, sTalentTreePrimarySpellsStore, dbcPath, "TalentTreePrimarySpells.dbc");
- for (uint32 i = 0; i < sTalentTreePrimarySpellsStore.GetNumRows(); ++i)
- if (TalentTreePrimarySpellsEntry const* talentSpell = sTalentTreePrimarySpellsStore.LookupEntry(i))
- sTalentTreePrimarySpellsMap[talentSpell->TalentTree].push_back(talentSpell->SpellId);
- 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)
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index bb75a5ed6b5..c59782983ec 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -179,6 +179,7 @@ extern DBCStorage <LiquidTypeEntry> sLiquidTypeStore;
extern DBCStorage <LockEntry> sLockStore;
extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
extern DBCStorage <MapEntry> sMapStore;
+extern DBCStorage <MinorTalentEntry> sMinorTalentStore;
extern DBCStorage <MountCapabilityEntry> sMountCapabilityStore;
extern DBCStorage <MountTypeEntry> sMountTypeStore;
extern DBCStorage <NameGenEntry> sNameGenStore;
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index 2556c141d8d..e1f6344e067 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1608,6 +1608,14 @@ struct MapDifficultyEntry
//char* LockID; // 6
};
+struct MinorTalentEntry
+{
+ uint32 ID; // 0
+ uint32 SpecID; // 1
+ uint32 SpellID; // 2
+ uint32 OrderIndex; // 3
+};
+
struct MountCapabilityEntry
{
uint32 ID; // 0
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index 4c590e8e6ee..640d10aae19 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -107,6 +107,7 @@ char const PhaseGroupfmt[] = "nii";
char const MailTemplateEntryfmt[] = "nxs";
char const MapEntryfmt[] = "nxiixxsixxixiffxiiiixx";
char const MapDifficultyEntryfmt[] = "diisiix";
+char const MinorTalentEntryfmt[] = "niii";
char const MovieEntryfmt[] = "nxxxx";
char const MountCapabilityfmt[] = "niiiiiii";
char const MountTypefmt[] = "niiiiiiiiiiiiiiiiiiiiiiii";
@@ -156,9 +157,7 @@ char const SpellShapeshiftEntryfmt[] = "niiiix";
char const SpellShapeshiftFormfmt[] = "nxxiixiiiiiiiiiiiiixx";
char const StableSlotPricesfmt[] = "ni";
char const SummonPropertiesfmt[] = "niiiii";
-char const TalentEntryfmt[] = "niiiiiiiiixxixxxxxx";
-char const TalentTabEntryfmt[] = "nxxiiixxxii";
-char const TalentTreePrimarySpellsfmt[] = "diix";
+char const TalentEntryfmt[] = "niiiiiiiiix";
char const TaxiNodesEntryfmt[] = "nifffsiiixx";
char const TaxiPathEntryfmt[] = "niii";
char const TaxiPathNodeEntryfmt[] = "diiifffiiii";
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 0fe830f861e..52045f46472 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -341,7 +341,8 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
if (owner->GetGroup())
owner->SetGroupUpdateFlag(GROUP_UPDATE_PET);
- owner->SendTalentsInfoData(true);
+ // TODO: 6.x remove/update pet talents
+ //owner->SendTalentsInfoData(true);
if (getPetType() == HUNTER_PET)
{
@@ -1735,6 +1736,7 @@ void Pet::resetTalentsForAllPetsOf(Player* owner, Pet* onlinePet /*= NULL*/)
void Pet::InitTalentForLevel()
{
+ /* TODO: 6.x remove/update pet talents
uint8 level = getLevel();
uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level);
// Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent)
@@ -1745,6 +1747,7 @@ void Pet::InitTalentForLevel()
if (!m_loading)
GetOwner()->SendTalentsInfoData(true);
+ */
}
uint8 Pet::GetMaxTalentPointsForLevel(uint8 level)
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index c0753f72942..e412aa43098 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -32,6 +32,7 @@
#include "ChannelMgr.h"
#include "CharacterDatabaseCleaner.h"
#include "CharacterPackets.h"
+#include "TalentPackets.h"
#include "Chat.h"
#include "Common.h"
#include "ConditionMgr.h"
@@ -2985,7 +2986,7 @@ void Player::GiveLevel(uint8 level)
void Player::InitTalentForLevel()
{
if (!GetSession()->PlayerLoading())
- SendTalentsInfoData(false); // update at client
+ SendTalentsInfoData(); // update at client
}
void Player::InitStatsForLevel(bool reapplyMods)
@@ -3308,20 +3309,29 @@ void DeleteSpellFromAllPlayers(uint32 spellId)
}
}
-bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
+bool Player::AddTalent(uint32 talentId, uint8 spec)
{
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
+ TalentEntry const* talentEntry = sTalentStore.LookupEntry(talentId);
+
+ // Check if talent exists in Talent.dbc
+ if (!talentEntry)
+ {
+ TC_LOG_ERROR("spells", "Player::addTalent: Talent %u not found", talentId);
+ return false;
+ }
+
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(talentEntry->SpellID);
if (!spellInfo)
{
// do character spell book cleanup (all characters)
- if (!IsInWorld() && !learning) // spell load case
+ if (!IsInWorld()) // spell load case
{
- TC_LOG_ERROR("spells", "Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.", spellId);
+ TC_LOG_ERROR("spells", "Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.", talentEntry->SpellID);
- DeleteSpellFromAllPlayers(spellId);
+ DeleteSpellFromAllPlayers(talentEntry->SpellID);
}
else
- TC_LOG_ERROR("spells", "Player::addSpell: Non-existed in SpellStore spell #%u request.", spellId);
+ TC_LOG_ERROR("spells", "Player::addSpell: Non-existed in SpellStore spell #%u request.", talentEntry->SpellID);
return false;
}
@@ -3329,35 +3339,25 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning)
if (!SpellMgr::IsSpellValid(spellInfo, this, false))
{
// do character spell book cleanup (all characters)
- if (!IsInWorld() && !learning) // spell load case
+ if (!IsInWorld()) // spell load case
{
- TC_LOG_ERROR("spells", "Player::addTalent: Broken spell #%u learning not allowed, deleting for all characters in `character_talent`.", spellId);
+ TC_LOG_ERROR("spells", "Player::addTalent: Broken spell #%u learning not allowed, deleting for all characters in `character_talent`.", talentEntry->SpellID);
- DeleteSpellFromAllPlayers(spellId);
+ DeleteSpellFromAllPlayers(talentEntry->SpellID);
}
else
- TC_LOG_ERROR("spells", "Player::addTalent: Broken spell #%u learning not allowed.", spellId);
-
- return false;
- }
+ TC_LOG_ERROR("spells", "Player::addTalent: Broken spell #%u learning not allowed.", talentEntry->SpellID);
- TalentEntry const* talentEntry = GetTalentBySpellID(spellId);
-
- // Check if talent exists in Talent.dbc
- if (!talentEntry) {
- TC_LOG_ERROR("spells", "Player::addTalent: Learning non-talent spell %u not allowed.", spellId);
return false;
}
- TalentSpecInfo* talentSpecInfo = GetTalentSpecInfo(spec);
+ TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(spec);
// Check if player already has this talent
- if (talentSpecInfo->HasTalent(spellId))
+ if (talentGroupInfo->HasTalent(talentId))
return false;
- talentSpecInfo->Talents[talentEntry->TierID].SpellID = spellId;
- if (learning)
- talentSpecInfo->Talents[talentEntry->TierID].State = PLAYERSPELL_NEW;
+ talentGroupInfo->Talents[talentEntry->TierID] = talentId;
return true;
}
@@ -3707,7 +3707,7 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const
bool Player::IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const
{
- if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec())))
+ if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec()))
return spellInfo->Id == chrSpec->MasterySpellID[0] || spellInfo->Id == chrSpec->MasterySpellID[1];
return false;
@@ -4121,7 +4121,8 @@ bool Player::ResetTalents(bool no_cost)
RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
- uint8 spec = GetActiveSpec();
+ uint8 group = GetActiveTalentGroup();
+ uint32 specID = GetActiveTalentSpec();
for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
{
@@ -4147,13 +4148,10 @@ bool Player::ResetTalents(bool no_cost)
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL)
RemoveSpell(_spellEntry->Effects[i].TriggerSpell, true);
-
- // Reset talents store
- GetTalentSpecInfo(spec)->Reset();
}
// Remove all specialization specific spells and give default ones which were overriden
- auto specSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(GetActiveSpec()));
+ auto specSpells = sSpecializationSpellsBySpecStore.find(specID);
if (specSpells != sSpecializationSpellsBySpecStore.end())
{
for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it)
@@ -4168,12 +4166,14 @@ bool Player::ResetTalents(bool no_cost)
}
// Unlearn masteries
- ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(spec));
+ ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(specID);
for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
if (uint32 mastery = chrSpec->MasterySpellID[i])
RemoveAurasDueToSpell(mastery);
- SetTalentSpec(spec, 0);
+ // Reset talents store
+ GetTalentGroupInfo(group)->Reset();
+ SetTalentSpec(group, 0);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
_SaveTalents(trans);
@@ -4265,9 +4265,9 @@ bool Player::HasSpell(uint32 spell) const
!itr->second->disabled);
}
-bool Player::HasTalent(uint32 spell, uint8 spec)
+bool Player::HasTalent(uint32 talentId, uint8 group)
{
- return GetTalentSpecInfo(spec)->HasTalent(spell);
+ return GetTalentGroupInfo(group)->HasTalent(talentId);
}
bool Player::HasActiveSpell(uint32 spell) const
@@ -6269,7 +6269,7 @@ void Player::SendActionButtons(uint32 state) const
data << uint8(state);
GetSession()->SendPacket(&data);
- TC_LOG_INFO("network", "Action Buttons for '%s' spec '%u' Sent", GetGUID().ToString().c_str(), GetActiveSpec());
+ TC_LOG_INFO("network", "Action Buttons for '%s' group '%u' Sent", GetGUID().ToString().c_str(), GetActiveTalentGroup());
}
bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
@@ -9684,6 +9684,7 @@ void Player::SendTalentWipeConfirm(ObjectGuid guid)
void Player::ResetPetTalents()
{
+ /* TODO: 6.x remove/update pet talents
// This needs another gossip option + NPC text as a confirmation.
// The confirmation gossip listid has the text: "Yes, please do."
Pet* pet = GetPet();
@@ -9699,6 +9700,7 @@ void Player::ResetPetTalents()
}
pet->resetTalents();
SendTalentsInfoData(true);
+ */
}
/*********************************************************/
@@ -14117,7 +14119,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
break;
}
case GOSSIP_OPTION_LEARNDUALSPEC:
- if (!(GetSpecsCount() == 1 && creature->isCanTrainingAndResetTalentsOf(this) && !(getLevel() < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL))))
+ if (!(GetTalentGroupsCount() == 1 && creature->isCanTrainingAndResetTalentsOf(this) && !(getLevel() < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL))))
canTalk = false;
break;
case GOSSIP_OPTION_UNLEARNTALENTS:
@@ -14331,7 +14333,7 @@ void Player::OnGossipSelect(WorldObject* source, uint32 gossipListId, uint32 men
GetSession()->SendTrainerList(guid);
break;
case GOSSIP_OPTION_LEARNDUALSPEC:
- if (GetSpecsCount() == 1 && getLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL))
+ if (GetTalentGroupsCount() == 1 && getLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL))
{
// Cast spells that teach dual spec
// Both are also ImplicitTarget self and must be cast by player
@@ -17431,19 +17433,19 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
//mails are loaded only when needed ;-) - when player in game click on mailbox.
//_LoadMail();
- SetSpecsCount(fields[53].GetUInt8());
- SetActiveSpec(fields[54].GetUInt8());
+ SetTalentGroupsCount(fields[53].GetUInt8());
+ SetActiveTalentGroup(fields[54].GetUInt8());
// sanity check
- if (GetSpecsCount() > MAX_TALENT_SPECS || GetActiveSpec() > MAX_TALENT_SPEC || GetSpecsCount() < MIN_TALENT_SPECS)
+ if (GetTalentGroupsCount() > MAX_TALENT_GROUPS || GetActiveTalentGroup() > MAX_TALENT_GROUP || GetTalentGroupsCount() < MIN_TALENT_GROUPS)
{
- SetActiveSpec(0);
- TC_LOG_ERROR("entities.player", "Player %s (%s) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUID().ToString().c_str(), GetSpecsCount(), GetActiveSpec());
+ TC_LOG_ERROR("entities.player", "Player %s (%s) has SpecCount = %u and ActiveSpec = %u.", GetName().c_str(), GetGUID().ToString().c_str(), GetTalentGroupsCount(), GetActiveTalentGroup());
+ SetActiveTalentGroup(0);
}
// Only load selected specializations, learning mastery spells requires this
- Tokenizer talentSpecs(fields[26].GetString(), ' ', MAX_TALENT_SPECS);
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ Tokenizer talentSpecs(fields[26].GetString(), ' ', MAX_TALENT_GROUPS);
+ for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i)
{
if (i >= talentSpecs.size())
break;
@@ -17804,7 +17806,7 @@ void Player::_LoadGlyphAuras()
{
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
- if (uint32 glyph = GetGlyph(GetActiveSpec(), i))
+ if (uint32 glyph = GetGlyph(GetActiveTalentGroup(), i))
{
if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
@@ -19104,7 +19106,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt32(index++, GetTalentResetTime());
ss.str("");
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i)
ss << GetTalentSpec(i) << " ";
stmt->setString(index++, ss.str());
stmt->setUInt16(index++, (uint16)m_ExtraFlags);
@@ -19141,8 +19143,8 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt32(index++, GetSession()->GetLatency());
- stmt->setUInt8(index++, GetSpecsCount());
- stmt->setUInt8(index++, GetActiveSpec());
+ stmt->setUInt8(index++, GetTalentGroupsCount());
+ stmt->setUInt8(index++, GetActiveTalentGroup());
ss.str("");
for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
@@ -19233,7 +19235,7 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt32(index++, GetTalentResetTime());
ss.str("");
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i)
ss << GetTalentSpec(i) << " ";
stmt->setString(index++, ss.str());
stmt->setUInt16(index++, (uint16)m_ExtraFlags);
@@ -19270,8 +19272,8 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setUInt32(index++, GetSession()->GetLatency());
- stmt->setUInt8(index++, GetSpecsCount());
- stmt->setUInt8(index++, GetActiveSpec());
+ stmt->setUInt8(index++, GetTalentGroupsCount());
+ stmt->setUInt8(index++, GetActiveTalentGroup());
ss.str("");
for (uint32 i = 0; i < PLAYER_EXPLORED_ZONES_SIZE; ++i)
@@ -19377,7 +19379,7 @@ void Player::_SaveActions(SQLTransaction& trans)
case ACTIONBUTTON_NEW:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACTION);
stmt->setUInt64(0, GetGUID().GetCounter());
- stmt->setUInt8(1, GetActiveSpec());
+ stmt->setUInt8(1, GetActiveTalentGroup());
stmt->setUInt8(2, itr->first);
stmt->setUInt32(3, itr->second.GetAction());
stmt->setUInt8(4, uint8(itr->second.GetType()));
@@ -19392,7 +19394,7 @@ void Player::_SaveActions(SQLTransaction& trans)
stmt->setUInt8(1, uint8(itr->second.GetType()));
stmt->setUInt64(2, GetGUID().GetCounter());
stmt->setUInt8(3, itr->first);
- stmt->setUInt8(4, GetActiveSpec());
+ stmt->setUInt8(4, GetActiveTalentGroup());
trans->Append(stmt);
itr->second.uState = ACTIONBUTTON_UNCHANGED;
@@ -19402,7 +19404,7 @@ void Player::_SaveActions(SQLTransaction& trans)
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC);
stmt->setUInt64(0, GetGUID().GetCounter());
stmt->setUInt8(1, itr->first);
- stmt->setUInt8(2, GetActiveSpec());
+ stmt->setUInt8(2, GetActiveTalentGroup());
trans->Append(stmt);
m_actionButtons.erase(itr++);
@@ -23054,7 +23056,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
// SMSG_SET_FLAT_SPELL_MODIFIER
// SMSG_UPDATE_AURA_DURATION
- SendTalentsInfoData(false);
+ SendTalentsInfoData();
data.Initialize(SMSG_WORLD_SERVER_INFO, 1 + 1 + 4 + 4);
data.WriteBit(0); // HasRestrictedLevel
@@ -24802,7 +24804,7 @@ void Player::InitGlyphsForLevel()
void Player::SetGlyph(uint8 slot, uint32 glyph)
{
- _talentMgr->SpecInfo[GetActiveSpec()].Glyphs[slot] = glyph;
+ _talentMgr->GroupInfo[GetActiveTalentGroup()].Glyphs[slot] = glyph;
SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph);
}
@@ -25487,7 +25489,7 @@ void Player::CompletedAchievement(AchievementEntry const* entry)
bool Player::LearnTalent(uint32 talentId)
{
- uint8 spec = GetActiveSpec();
+ uint8 group = GetActiveTalentGroup();
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
@@ -25498,13 +25500,15 @@ bool Player::LearnTalent(uint32 talentId)
if (getClass() != talentInfo->ClassID)
return false;
- // Check player level.
- if (getLevel() < (15*talentInfo->TierID + 15))
+ // Check player level
+ // TODO: fix level requirements for deathknights
+ uint8 levelReq = std::min(15*talentInfo->TierID + 15, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL));
+ if (getLevel() < levelReq)
return false;
// Check if such tier talent hasn't been picked already
- TalentSpecInfo* talentSpecInfo = GetTalentSpecInfo(spec);
- if (talentSpecInfo->Talents[talentInfo->TierID].SpellID != 0)
+ TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(group);
+ if (talentGroupInfo->Talents[talentInfo->TierID])
return false;
// spell not set in talent.dbc
@@ -25519,16 +25523,10 @@ bool Player::LearnTalent(uint32 talentId)
if (HasSpell(spellid))
return false;
- // learn! (other talent ranks will unlearned at learning)
- LearnSpell(spellid, false);
- AddTalent(spellid, spec, true);
-
- TC_LOG_INFO("misc", "TalentID: %u Spell: %u Spec: %u\n", talentId, spellid, spec);
-
- // set talent tree for player
- if (!GetTalentSpec(spec))
+ // set talent spec for player
+ if (!GetTalentSpec(group))
{
- SetTalentSpec(spec, talentInfo->SpecID);
+ SetTalentSpec(group, talentInfo->SpecID);
// Replace default spells by specialization spells
auto specSpells = sSpecializationSpellsBySpecStore.find(talentInfo->SpecID);
@@ -25553,6 +25551,16 @@ bool Player::LearnTalent(uint32 talentId)
}
}
+ // Check talent spec
+ if (talentInfo->SpecID != GetTalentSpec(group))
+ return false;
+
+ // learn! (other talent ranks will unlearned at learning)
+ LearnSpell(spellid, false);
+ AddTalent(talentId, group);
+
+ TC_LOG_INFO("misc", "TalentID: %u Spell: %u Group: %u\n", talentId, spellid, group);
+
return true;
}
@@ -25630,160 +25638,38 @@ bool Player::CanSeeSpellClickOn(Creature const* c) const
return false;
}
-void Player::BuildPlayerTalentsInfoData(WorldPacket* data)
-{
- /* TODO: 6.x update with new talent system (and move to packet class)
- *data << uint32(GetFreeTalentPoints()); // unspentTalentPoints
- *data << uint8(GetSpecsCount()); // talent group count (0, 1 or 2)
- *data << uint8(GetActiveSpec()); // talent group index (0 or 1)
-
- if (GetSpecsCount())
- {
- if (GetSpecsCount() > MAX_TALENT_SPECS)
- SetSpecsCount(MAX_TALENT_SPECS);
-
- // loop through all specs (only 1 for now)
- for (uint8 specIdx = 0; specIdx < GetSpecsCount(); ++specIdx)
- {
- *data << uint32(GetPrimaryTalentTree(specIdx));
- uint8 talentIdCount = 0;
- size_t pos = data->wpos();
- *data << uint8(talentIdCount); // [PH], talentIdCount
-
- // find class talent tabs (all players have 3 talent tabs)
- uint32 const* talentTabIds = GetTalentTabPages(getClass());
-
- for (uint8 i = 0; i < MAX_TALENT_TABS; ++i)
- {
- uint32 talentTabId = talentTabIds[i];
-
- for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
- {
- TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
- if (!talentInfo)
- continue;
-
- // skip another tab talents
- if (talentInfo->TalentTab != talentTabId)
- continue;
-
- // find max talent rank (0~4)
- int8 curtalent_maxrank = -1;
- for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank)
- {
- if (talentInfo->RankID[rank] && HasTalent(talentInfo->RankID[rank], specIdx))
- {
- curtalent_maxrank = rank;
- break;
- }
- }
-
- // not learned talent
- if (curtalent_maxrank < 0)
- continue;
-
- *data << uint32(talentInfo->TalentID); // Talent.dbc
- *data << uint8(curtalent_maxrank); // talentMaxRank (0-4)
-
- ++talentIdCount;
- }
- }
-
- data->put<uint8>(pos, talentIdCount); // put real count
-
- *data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count
-
- for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- *data << uint16(GetGlyph(specIdx, i)); // GlyphProperties.dbc
- }
- }
- */
-}
-
-void Player::BuildPetTalentsInfoData(WorldPacket* data)
+void Player::SendTalentsInfoData()
{
- /* TODO: 6.x update with new talent system (and move to packet class)
- uint32 unspentTalentPoints = 0;
- size_t pointsPos = data->wpos();
- *data << uint32(unspentTalentPoints); // [PH], unspentTalentPoints
-
- uint8 talentIdCount = 0;
- size_t countPos = data->wpos();
- *data << uint8(talentIdCount); // [PH], talentIdCount
-
- Pet* pet = GetPet();
- if (!pet)
- return;
+ WorldPackets::Talent::UpdateTalentData packet;
- unspentTalentPoints = pet->GetFreeTalentPoints();
+ packet.Info.ActiveGroup = GetActiveTalentGroup();
+
+ uint8 groupsCount = GetTalentGroupsCount();
- data->put<uint32>(pointsPos, unspentTalentPoints); // put real points
-
- CreatureTemplate const* ci = pet->GetCreatureTemplate();
- if (!ci)
- return;
-
- CreatureFamilyEntry const* pet_family = sCreatureFamilyStore.LookupEntry(ci->family);
- if (!pet_family || pet_family->PetTalentType < 0)
- return;
-
- for (uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId)
+ for (uint8 i = 0; i < groupsCount; ++i)
{
- TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentTabId);
- if (!talentTabInfo)
- continue;
-
- if (!((1 << pet_family->PetTalentType) & talentTabInfo->petTalentMask))
- continue;
-
- for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
+ TalentGroupInfo* groupInfo = GetTalentGroupInfo(i);
+ WorldPackets::Talent::TalentGroupInfo groupInfoPkt;
+
+ groupInfoPkt.SpecID = groupInfo->SpecID;
+
+ groupInfoPkt.TalentIDs.reserve(MAX_TALENT_TIERS);
+ for (uint32 x = 0; x < MAX_TALENT_TIERS; ++x)
{
- TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
- if (!talentInfo)
- continue;
-
- // skip another tab talents
- if (talentInfo->TalentTab != talentTabId)
- continue;
-
- // find max talent rank (0~4)
- int8 curtalent_maxrank = -1;
- for (int8 rank = MAX_TALENT_RANK-1; rank >= 0; --rank)
- {
- if (talentInfo->RankID[rank] && pet->HasSpell(talentInfo->RankID[rank]))
- {
- curtalent_maxrank = rank;
- break;
- }
- }
-
- // not learned talent
- if (curtalent_maxrank < 0)
- continue;
-
- *data << uint32(talentInfo->TalentID); // Talent.dbc
- *data << uint8(curtalent_maxrank); // talentMaxRank (0-4)
+ // Do not send empty talents
+ if (!groupInfo->Talents[x])
+ break;
- ++talentIdCount;
+ groupInfoPkt.TalentIDs.push_back(groupInfo->Talents[x]);
}
+
+ for (uint32 x = 0; x < MAX_GLYPH_SLOT_INDEX; ++x)
+ groupInfoPkt.GlyphIDs[x] = groupInfo->Glyphs[x];
+
+ packet.Info.TalentGroups.push_back(groupInfoPkt);
+ }
- data->put<uint8>(countPos, talentIdCount); // put real count
-
- break;
- }*/
-}
-
-void Player::SendTalentsInfoData(bool pet)
-{
- /* TODO: 6.x update with new talent system (and move to packet class)
- WorldPacket data(SMSG_TALENTS_INFO, 50);
- data << uint8(pet ? 1 : 0);
- if (pet)
- BuildPetTalentsInfoData(&data);
- else
- BuildPlayerTalentsInfoData(&data);
- GetSession()->SendPacket(&data);
- */
+ GetSession()->SendPacket(packet.Write());
}
void Player::BuildEnchantmentsInfoData(WorldPacket* data)
@@ -26064,7 +25950,7 @@ void Player::SetMap(Map* map)
void Player::_LoadGlyphs(PreparedQueryResult result)
{
- // SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = '%u'
+ // SELECT group, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = '%u'
if (!result)
return;
@@ -26072,12 +25958,12 @@ void Player::_LoadGlyphs(PreparedQueryResult result)
{
Field* fields = result->Fetch();
- uint8 spec = fields[0].GetUInt8();
- if (spec >= GetSpecsCount())
+ uint8 group = fields[0].GetUInt8();
+ if (group >= GetTalentGroupsCount())
continue;
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- _talentMgr->SpecInfo[spec].Glyphs[i] = fields[i + 1].GetUInt16();
+ _talentMgr->GroupInfo[group].Glyphs[i] = fields[i + 1].GetUInt16();
}
while (result->NextRow());
}
@@ -26089,17 +25975,17 @@ void Player::_SaveGlyphs(SQLTransaction& trans)
trans->Append(stmt);
- for (uint8 spec = 0; spec < GetSpecsCount(); ++spec)
+ for (uint8 group = 0; group < GetTalentGroupsCount(); ++group)
{
uint8 index = 0;
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_GLYPHS);
stmt->setUInt64(index++, GetGUID().GetCounter());
- stmt->setUInt8(index++, spec);
+ stmt->setUInt8(index++, group);
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
- stmt->setUInt16(index++, uint16(GetGlyph(spec, i)));
+ stmt->setUInt16(index++, uint16(GetGlyph(group, i)));
trans->Append(stmt);
}
@@ -26111,57 +25997,40 @@ void Player::_LoadTalents(PreparedQueryResult result)
if (result)
{
do
- AddTalent((*result)[0].GetUInt32(), (*result)[1].GetUInt8(), false);
+ AddTalent((*result)[0].GetUInt32(), (*result)[1].GetUInt8());
while (result->NextRow());
}
}
void Player::_SaveTalents(SQLTransaction& trans)
{
- PreparedStatement* stmt = NULL;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TALENT);
+ stmt->setUInt64(0, GetGUID().GetCounter());
+ trans->Append(stmt);
- for (uint8 spec = 0; spec < MAX_TALENT_SPECS; ++spec)
+ for (uint8 group = 0; group < MAX_TALENT_GROUPS; ++group)
{
- TalentSpecInfo* talentSpecInfo = GetTalentSpecInfo(spec);
+ TalentGroupInfo* talentGroupInfo = GetTalentGroupInfo(group);
for (uint32 tier = 0; tier < MAX_TALENT_TIERS; ++tier)
{
- PlayerTalent* talent = &talentSpecInfo->Talents[tier];
-
- if (talent->State == PLAYERSPELL_REMOVED || talent->State == PLAYERSPELL_CHANGED)
- {
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC);
- stmt->setUInt64(0, GetGUID().GetCounter());
- stmt->setUInt32(1, talent->SpellID);
- stmt->setUInt8(2, spec);
- trans->Append(stmt);
- }
-
- if (talent->State == PLAYERSPELL_NEW || talent->State == PLAYERSPELL_CHANGED)
- {
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT);
- stmt->setUInt64(0, GetGUID().GetCounter());
- stmt->setUInt32(1, talent->SpellID);
- stmt->setUInt8(2, spec);
- trans->Append(stmt);
- }
-
- if (talent->State == PLAYERSPELL_REMOVED)
- talent->SpellID = 0;
-
- talent->State = PLAYERSPELL_UNCHANGED;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_TALENT);
+ stmt->setUInt64(0, GetGUID().GetCounter());
+ stmt->setUInt32(1, talentGroupInfo->Talents[tier]);
+ stmt->setUInt8(2, group);
+ trans->Append(stmt);
}
}
}
-void Player::UpdateSpecCount(uint8 count)
+void Player::UpdateTalentGroupCount(uint8 count)
{
- uint32 curCount = GetSpecsCount();
+ uint32 curCount = GetTalentGroupsCount();
if (curCount == count)
return;
- if (GetActiveSpec() >= count)
- ActivateSpec(0);
+ if (GetActiveTalentGroup() >= count)
+ ActivateTalentGroup(0);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
PreparedStatement* stmt = NULL;
@@ -26187,7 +26056,7 @@ void Player::UpdateSpecCount(uint8 count)
_SaveActions(trans);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC);
- stmt->setUInt8(0, GetActiveSpec());
+ stmt->setUInt8(0, GetActiveTalentGroup());
stmt->setUInt64(1, GetGUID().GetCounter());
trans->Append(stmt);
@@ -26195,17 +26064,17 @@ void Player::UpdateSpecCount(uint8 count)
CharacterDatabase.CommitTransaction(trans);
- SetSpecsCount(count);
+ SetTalentGroupsCount(count);
- SendTalentsInfoData(false);
+ SendTalentsInfoData();
}
-void Player::ActivateSpec(uint8 spec)
+void Player::ActivateTalentGroup(uint8 group)
{
- if (GetActiveSpec() == spec)
+ if (GetActiveTalentGroup() == group)
return;
- if (spec > GetSpecsCount())
+ if (group > GetTalentGroupsCount())
return;
if (IsNonMeleeSpellCast(false))
@@ -26251,7 +26120,7 @@ void Player::ActivateSpec(uint8 spec)
}
// Unlearn specialization specific spells
- auto specSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(GetActiveSpec()));
+ auto specSpells = sSpecializationSpellsBySpecStore.find(GetActiveTalentSpec());
if (specSpells != sSpecializationSpellsBySpecStore.end())
{
for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it)
@@ -26265,7 +26134,7 @@ void Player::ActivateSpec(uint8 spec)
}
// Unlearn mastery spells
- ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec()));
+ ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec());
for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
if (chrSpec->MasterySpellID[i])
RemoveSpell(chrSpec->MasterySpellID[i], true);
@@ -26273,12 +26142,12 @@ void Player::ActivateSpec(uint8 spec)
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
// remove secondary glyph
- if (uint32 oldglyph = GetGlyph(GetActiveSpec(), slot))
+ if (uint32 oldglyph = GetGlyph(GetActiveTalentGroup(), slot))
if (GlyphPropertiesEntry const* old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph))
RemoveAurasDueToSpell(old_gp->SpellID);
- // Activate new spec
- SetActiveSpec(spec);
+ // Activate new group
+ SetActiveTalentGroup(group);
for (uint32 talentId = 0; talentId < sTalentStore.GetNumRows(); ++talentId)
{
@@ -26291,14 +26160,11 @@ void Player::ActivateSpec(uint8 spec)
if (getClass() != talentInfo->ClassID)
continue;
- if (HasTalent(talentInfo->SpellID, GetActiveSpec()))
- {
- LearnSpell(talentInfo->SpellID, false);
- }
+ LearnSpell(talentInfo->SpellID, false);
}
// Replace default spells with specialization specific spells
- auto newSpecSpells = sSpecializationSpellsBySpecStore.find(GetTalentSpec(spec));
+ auto newSpecSpells = sSpecializationSpellsBySpecStore.find(GetActiveTalentSpec());
if (newSpecSpells != sSpecializationSpellsBySpecStore.end())
{
for (auto it = newSpecSpells->second.begin(); it != newSpecSpells->second.end(); ++it)
@@ -26314,7 +26180,7 @@ void Player::ActivateSpec(uint8 spec)
}
if (CanUseMastery())
- if (ChrSpecializationEntry const* newChrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(spec)))
+ if (ChrSpecializationEntry const* newChrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec()))
for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
if (newChrSpec->MasterySpellID[i])
LearnSpell(newChrSpec->MasterySpellID[i], false);
@@ -26322,7 +26188,7 @@ void Player::ActivateSpec(uint8 spec)
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
{
- uint32 glyph = GetGlyph(GetActiveSpec(), slot);
+ uint32 glyph = GetGlyph(GetActiveTalentGroup(), slot);
// apply primary glyph
if (glyph)
@@ -26337,7 +26203,7 @@ void Player::ActivateSpec(uint8 spec)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC);
stmt->setUInt64(0, GetGUID().GetCounter());
- stmt->setUInt8(1, GetActiveSpec());
+ stmt->setUInt8(1, GetActiveTalentGroup());
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
_LoadActions(result);
}
@@ -26350,7 +26216,7 @@ void Player::ActivateSpec(uint8 spec)
SetPower(pw, 0);
- if (!sChrSpecializationStore.LookupEntry(GetTalentSpec(spec)))
+ if (!sChrSpecializationStore.LookupEntry(GetActiveTalentSpec()))
ResetTalents(true);
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 54d542011a1..11167097e89 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -115,12 +115,6 @@ struct PlayerSpell
bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks
};
-struct PlayerTalent
-{
- PlayerSpellState State : 8;
- uint32 SpellID : 32;
-};
-
extern uint32 const MasterySpells[MAX_CLASSES];
enum TalentSpecialization // talent tabs
@@ -1217,46 +1211,52 @@ private:
bool _isPvP;
};
-struct TalentSpecInfo
+struct TalentGroupInfo
{
- PlayerTalent Talents[MAX_TALENT_TIERS];
+ uint32 Talents[MAX_TALENT_TIERS];
uint32 Glyphs[MAX_GLYPH_SLOT_INDEX];
- uint32 TalentSpec;
+ uint32 SpecID;
- bool HasTalent(uint32 spellId)
+ bool HasTalent(uint32 talentId)
{
for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i)
- if (Talents[i].SpellID == spellId)
+ if (Talents[i] == talentId)
return true;
return false;
}
+ uint32 TalentCount()
+ {
+ for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i)
+ if (!Talents[i])
+ return i;
+ return MAX_TALENT_TIERS;
+ }
+
void Reset()
{
- for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i) {
- Talents[i].State = PLAYERSPELL_REMOVED;
- Talents[i].SpellID = 0;
- }
+ for (uint32 i = 0; i < MAX_TALENT_TIERS; ++i)
+ Talents[i] = 0;
}
};
struct PlayerTalentInfo
{
- PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), ActiveSpec(0), SpecsCount(1)
+ PlayerTalentInfo() : ResetTalentsCost(0), ResetTalentsTime(0), ActiveGroup(0), GroupsCount(1)
{
- for (uint8 i = 0; i < MAX_TALENT_SPECS; ++i)
+ for (uint8 i = 0; i < MAX_TALENT_GROUPS; ++i)
{
- memset(SpecInfo[i].Talents, 0, sizeof(PlayerTalent)*MAX_TALENT_TIERS);
- memset(SpecInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32));
- SpecInfo[i].TalentSpec = 0;
+ memset(GroupInfo[i].Talents, 0, sizeof(uint32)*MAX_TALENT_TIERS);
+ memset(GroupInfo[i].Glyphs, 0, MAX_GLYPH_SLOT_INDEX * sizeof(uint32));
+ GroupInfo[i].SpecID = 0;
}
}
- TalentSpecInfo SpecInfo[MAX_TALENT_SPECS];
+ TalentGroupInfo GroupInfo[MAX_TALENT_GROUPS];
uint32 ResetTalentsCost;
time_t ResetTalentsTime;
- uint8 ActiveSpec;
- uint8 SpecsCount;
+ uint8 ActiveGroup;
+ uint8 GroupsCount;
private:
PlayerTalentInfo(PlayerTalentInfo const&);
@@ -1825,35 +1825,34 @@ class Player : public Unit, public GridObject<Player>
void SetTalentResetCost(uint32 cost) { _talentMgr->ResetTalentsCost = cost; }
uint32 GetTalentResetTime() const { return _talentMgr->ResetTalentsTime; }
void SetTalentResetTime(time_t time_) { _talentMgr->ResetTalentsTime = time_; }
- uint8 GetActiveSpec() const { return _talentMgr->ActiveSpec; }
- void SetActiveSpec(uint8 spec){ _talentMgr->ActiveSpec = spec; }
- uint8 GetSpecsCount() const { return _talentMgr->SpecsCount; }
- void SetSpecsCount(uint8 count) { _talentMgr->SpecsCount = count; }
- uint32 GetTalentSpec(uint8 spec) const { return _talentMgr->SpecInfo[spec].TalentSpec; }
- void SetTalentSpec(uint8 spec, uint32 talentSpec) const { _talentMgr->SpecInfo[spec].TalentSpec = talentSpec; }
+ uint8 GetActiveTalentGroup() const { return _talentMgr->ActiveGroup; }
+ void SetActiveTalentGroup(uint8 group){ _talentMgr->ActiveGroup = group; }
+ uint8 GetTalentGroupsCount() const { return _talentMgr->GroupsCount; }
+ void SetTalentGroupsCount(uint8 count) { _talentMgr->GroupsCount = count; }
+ uint32 GetTalentSpec(uint8 group) const { return _talentMgr->GroupInfo[group].SpecID; }
+ void SetTalentSpec(uint8 group, uint32 talentSpec) const { _talentMgr->GroupInfo[group].SpecID = talentSpec; }
+ uint32 GetActiveTalentSpec() const { return _talentMgr->GroupInfo[_talentMgr->ActiveGroup].SpecID; }
bool ResetTalents(bool no_cost = false);
uint32 GetNextResetTalentsCost() const;
void InitTalentForLevel();
- void BuildPlayerTalentsInfoData(WorldPacket* data);
- void BuildPetTalentsInfoData(WorldPacket* data);
- void SendTalentsInfoData(bool pet);
+ void SendTalentsInfoData();
bool LearnTalent(uint32 talentId);
- bool AddTalent(uint32 spellId, uint8 spec, bool learning);
- bool HasTalent(uint32 spell_id, uint8 spec);
+ bool AddTalent(uint32 talentId, uint8 spec);
+ bool HasTalent(uint32 talentId, uint8 spec);
// Dual Spec
- void UpdateSpecCount(uint8 count);
- void ActivateSpec(uint8 spec);
+ void UpdateTalentGroupCount(uint8 count);
+ void ActivateTalentGroup(uint8 group);
void InitGlyphsForLevel();
void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
uint32 GetGlyphSlot(uint8 slot) const { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
void SetGlyph(uint8 slot, uint32 glyph);
- uint32 GetGlyph(uint8 spec, uint8 slot) const { return _talentMgr->SpecInfo[spec].Glyphs[slot]; }
+ uint32 GetGlyph(uint8 group, uint8 slot) const { return _talentMgr->GroupInfo[group].Glyphs[slot]; }
- TalentSpecInfo* GetTalentSpecInfo(uint8 spec) { return &_talentMgr->SpecInfo[spec]; }
+ TalentGroupInfo* GetTalentGroupInfo(uint8 group) { return &_talentMgr->GroupInfo[group]; }
ActionButtonList const& GetActionButtons() const { return m_actionButtons; }
uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS); }
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 37b4d4d97a0..ea15daed587 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -526,7 +526,7 @@ void Player::UpdateMastery()
value += GetRatingBonusValue(CR_MASTERY);
SetFloatValue(PLAYER_MASTERY, value);
- ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetTalentSpec(GetActiveSpec()));
+ ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetActiveTalentSpec());
if (!chrSpec)
return;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 6e9560ac22f..7d892371931 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1055,7 +1055,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS))
{
pCurrChar->ResetTalents(true);
- pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state
+ pCurrChar->SendTalentsInfoData(); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state
SendNotification(LANG_RESET_TALENTS);
}
@@ -1416,13 +1416,13 @@ void WorldSession::HandleRemoveGlyph(WorldPacket& recvData)
return;
}
- if (uint32 glyph = _player->GetGlyph(_player->GetActiveSpec(), slot))
+ if (uint32 glyph = _player->GetGlyph(_player->GetActiveTalentGroup(), slot))
{
if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
_player->RemoveAurasDueToSpell(gp->SpellID);
_player->SetGlyph(slot, 0);
- _player->SendTalentsInfoData(false);
+ _player->SendTalentsInfoData();
}
}
}
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index b28068538ce..6f2cf949dfe 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1242,6 +1242,7 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recvData)
WorldPacket data(SMSG_INSPECT_TALENT, 8 + 4 + 1 + 1 + talent_points + 8 + 4 + 8 + 4);
data << player->GetGUID();
+ /* TODO: 6.x update packet structure (BuildPlayerTalentsInfoData no longer exists)
if (sWorld->getBoolConfig(CONFIG_TALENTS_INSPECTING) || _player->IsGameMaster())
player->BuildPlayerTalentsInfoData(&data);
else
@@ -1250,6 +1251,7 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recvData)
data << uint8(0); // talentGroupCount
data << uint8(0); // talentGroupIndex
}
+ */
player->BuildEnchantmentsInfoData(&data);
if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp
index c3f9dfc2868..ef1e9031cb9 100644
--- a/src/server/game/Handlers/SkillHandler.cpp
+++ b/src/server/game/Handlers/SkillHandler.cpp
@@ -111,7 +111,7 @@ void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData)
return;
}
- _player->SendTalentsInfoData(false);
+ _player->SendTalentsInfoData();
unit->CastSpell(_player, 14867, true); //spell: "Untalent Visual Effect"
}
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index e2c82763161..9e8b5ca00f3 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -815,10 +815,10 @@ enum SpellAttr13
SPELL_ATTR13_UNK23 = 0x00800000 // 23
};
-#define MIN_TALENT_SPEC 0
-#define MAX_TALENT_SPEC 1
-#define MIN_TALENT_SPECS 1
-#define MAX_TALENT_SPECS 2
+#define MIN_TALENT_GROUP 0
+#define MAX_TALENT_GROUP 1
+#define MIN_TALENT_GROUPS 1
+#define MAX_TALENT_GROUPS 2
#define MAX_GLYPH_SLOT_INDEX 9
#define REQ_PRIMARY_TREE_TALENTS 31
diff --git a/src/server/game/Server/Packets/TalentPackets.cpp b/src/server/game/Server/Packets/TalentPackets.cpp
new file mode 100644
index 00000000000..3410fb273f7
--- /dev/null
+++ b/src/server/game/Server/Packets/TalentPackets.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "TalentPackets.h"
+
+WorldPacket const* WorldPackets::Talent::UpdateTalentData::Write()
+{
+ _worldPacket << Info.ActiveGroup;
+ _worldPacket << uint32(Info.TalentGroups.size());
+
+ for (auto& talentGroupInfo : Info.TalentGroups)
+ {
+ _worldPacket << talentGroupInfo.SpecID;
+ _worldPacket << uint32(talentGroupInfo.TalentIDs.size());
+
+ for (uint32 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
+ _worldPacket << talentGroupInfo.GlyphIDs[i];
+
+ for (uint16 talentID : talentGroupInfo.TalentIDs)
+ _worldPacket << talentID;
+ }
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/TalentPackets.h b/src/server/game/Server/Packets/TalentPackets.h
new file mode 100644
index 00000000000..c756c6962bb
--- /dev/null
+++ b/src/server/game/Server/Packets/TalentPackets.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TalentPackets_h__
+#define TalentPackets_h__
+
+#include "Packet.h"
+#include "Player.h"
+#include <vector>
+
+namespace WorldPackets
+{
+ namespace Talent
+ {
+ struct TalentGroupInfo
+ {
+ uint32 SpecID;
+ std::vector<uint16> TalentIDs;
+ uint16 GlyphIDs[MAX_GLYPH_SLOT_INDEX];
+ };
+
+ struct TalentInfoUpdate
+ {
+ uint8 ActiveGroup;
+ std::vector<TalentGroupInfo> TalentGroups;
+ };
+
+ class UpdateTalentData final : public ServerPacket
+ {
+ public:
+ UpdateTalentData() : ServerPacket(SMSG_TALENTS_INFO, 2+4+4+4+12) { }
+
+ WorldPacket const* Write() override;
+
+ TalentInfoUpdate Info;
+ };
+ }
+}
+
+#endif // TalentPackets_h__
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 4e31af725a9..292f126d8a4 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1246,7 +1246,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
// Also do it for Glyphs
for (uint32 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
- if (uint32 glyphId = plrTarget->GetGlyph(plrTarget->GetActiveSpec(), i))
+ if (uint32 glyphId = plrTarget->GetGlyph(plrTarget->GetActiveTalentGroup(), i))
{
if (GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId))
{
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index c3ba18cad2c..3579ba73c31 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -4034,7 +4034,7 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
}
// remove old glyph
- if (uint32 oldGlyph = player->GetGlyph(player->GetActiveSpec(), m_glyphIndex))
+ if (uint32 oldGlyph = player->GetGlyph(player->GetActiveTalentGroup(), m_glyphIndex))
{
if (GlyphPropertiesEntry const* oldGlyphProperties = sGlyphPropertiesStore.LookupEntry(oldGlyph))
{
@@ -4045,16 +4045,16 @@ void Spell::EffectApplyGlyph(SpellEffIndex effIndex)
player->CastSpell(m_caster, newGlyphProperties->SpellID, true);
player->SetGlyph(m_glyphIndex, newGlyph);
- player->SendTalentsInfoData(false);
+ player->SendTalentsInfoData();
}
}
- else if (uint32 oldGlyph = player->GetGlyph(player->GetActiveSpec(), m_glyphIndex)) // Removing the glyph, get the old one
+ else if (uint32 oldGlyph = player->GetGlyph(player->GetActiveTalentGroup(), m_glyphIndex)) // Removing the glyph, get the old one
{
if (GlyphPropertiesEntry const* oldGlyphProperties = sGlyphPropertiesStore.LookupEntry(oldGlyph))
{
player->RemoveAurasDueToSpell(oldGlyphProperties->SpellID);
player->SetGlyph(m_glyphIndex, 0);
- player->SendTalentsInfoData(false);
+ player->SendTalentsInfoData();
}
}
}
@@ -5494,7 +5494,7 @@ void Spell::EffectSpecCount(SpellEffIndex /*effIndex*/)
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- unitTarget->ToPlayer()->UpdateSpecCount(damage);
+ unitTarget->ToPlayer()->UpdateTalentGroupCount(damage);
}
void Spell::EffectActivateSpec(SpellEffIndex /*effIndex*/)
@@ -5505,7 +5505,7 @@ void Spell::EffectActivateSpec(SpellEffIndex /*effIndex*/)
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- unitTarget->ToPlayer()->ActivateSpec(damage-1); // damage is 1 or 2, spec is 0 or 1
+ unitTarget->ToPlayer()->ActivateTalentGroup(damage-1); // damage is 1 or 2, spec is 0 or 1
}
void Spell::EffectPlaySound(SpellEffIndex effIndex)
diff --git a/src/server/game/Tools/CharacterDatabaseCleaner.cpp b/src/server/game/Tools/CharacterDatabaseCleaner.cpp
index a63a8ae6cdd..ec96d092393 100644
--- a/src/server/game/Tools/CharacterDatabaseCleaner.cpp
+++ b/src/server/game/Tools/CharacterDatabaseCleaner.cpp
@@ -147,7 +147,7 @@ bool CharacterDatabaseCleaner::TalentCheck(uint32 talent_id)
void CharacterDatabaseCleaner::CleanCharacterTalent()
{
- CharacterDatabase.DirectPExecute("DELETE FROM character_talent WHERE spec > %u", MAX_TALENT_SPECS);
+ CharacterDatabase.DirectPExecute("DELETE FROM character_talent WHERE spec > %u", MAX_TALENT_GROUPS);
CheckUnique("spell", "character_talent", &TalentCheck);
}
diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp
index 81499567b72..2cf97403595 100644
--- a/src/server/scripts/Commands/cs_learn.cpp
+++ b/src/server/scripts/Commands/cs_learn.cpp
@@ -204,7 +204,7 @@ public:
// learn highest rank of talent and learn all non-talent spell ranks (recursive by tree)
player->LearnSpellHighestRank(talentInfo->SpellID);
- player->AddTalent(talentInfo->SpellID, player->GetActiveSpec(), true);
+ player->AddTalent(talentInfo->SpellID, player->GetActiveTalentGroup());
}
handler->SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS);
diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp
index 9d2621c0010..4a58a7f7e5d 100644
--- a/src/server/scripts/Commands/cs_reset.cpp
+++ b/src/server/scripts/Commands/cs_reset.cpp
@@ -204,6 +204,7 @@ public:
Player* target;
ObjectGuid targetGuid;
std::string targetName;
+ /* TODO: 6.x remove/update pet talents
if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName))
{
// Try reset talents as Hunter Pet
@@ -227,19 +228,22 @@ public:
handler->SetSentErrorMessage(true);
return false;
}
+ */
if (target)
{
target->ResetTalents(true);
- target->SendTalentsInfoData(false);
+ target->SendTalentsInfoData();
ChatHandler(target->GetSession()).SendSysMessage(LANG_RESET_TALENTS);
if (!handler->GetSession() || handler->GetSession()->GetPlayer() != target)
handler->PSendSysMessage(LANG_RESET_TALENTS_ONLINE, handler->GetNameLink(target).c_str());
+ /* TODO: 6.x remove/update pet talents
Pet* pet = target->GetPet();
Pet::resetTalentsForAllPetsOf(target, pet);
if (pet)
target->SendTalentsInfoData(true);
+ */
return true;
}
else if (!targetGuid.IsEmpty())
diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp
index ed0709c6ad9..184e12cdccb 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->GetTalentSpec(caster->GetActiveSpec()) != TALENT_SPEC_DRUID_BALANCE)
+ if (caster->GetActiveTalentSpec() != TALENT_SPEC_DRUID_BALANCE)
return;
switch (GetSpellInfo()->Id)
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index e91aa10c52d..9c27f876054 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -74,7 +74,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
"resettalents_time, talentTree, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, "
- "health, power1, power2, power3, power4, power5, instance_id, speccount, activespec, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels "
+ "health, power1, power2, power3, power4, power5, instance_id, talentGroupsCount, activeTalentGroup, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels "
"FROM characters WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH);
@@ -105,7 +105,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_INVENTORY, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, bag, slot, "
"item, itemEntry FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ? ORDER BY bag, slot", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS, "SELECT a.button, a.action, a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activespec AND a.guid = ? ORDER BY button", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS, "SELECT a.button, a.action, a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activeTalentGroup AND a.guid = ? ORDER BY button", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_MAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = ? AND (checked & 1) = 0 AND deliver_time <= ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_MAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = ? AND (checked & 1) = 0", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_MAIL_COUNT, "SELECT COUNT(*) FROM mail WHERE receiver = ?", CONNECTION_SYNCH);
@@ -122,8 +122,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, ignore_mask, item0, item1, item2, item3, item4, item5, item6, item7, item8, "
"item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_BGDATA, "SELECT instanceId, team, joinX, joinY, joinZ, joinO, joinMapId, taxiStart, taxiEnd, mountSpell FROM character_battleground_data WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT spell, spec FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT talentGroup, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9 FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT spell, talentGroup FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_SKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_RANDOMBG, "SELECT guid FROM character_battleground_random WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_BANNED, "SELECT guid FROM character_banned WHERE guid = ? AND active = 1", CONNECTION_ASYNC);
@@ -376,13 +376,13 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"extra_flags, stable_slots, at_login, zone, "
"death_expire_time, taxi_path, totalKills, "
"todayKills, yesterdayKills, chosenTitle, watchedFaction, drunk, health, power1, power2, power3, "
- "power4, power5, latency, speccount, activespec, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels) VALUES "
+ "power4, power5, latency, talentGroupsCount, activeTalentGroup, exploredZones, equipmentCache, knownTitles, actionBars, grantableLevels) VALUES "
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,gender=?,level=?,xp=?,money=?,playerBytes=?,playerBytes2=?,playerFlags=?,"
"map=?,instance_id=?,instance_mode_mask=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?,"
"logout_time=?,is_logout_resting=?,resettalents_cost=?,resettalents_time=?,talentTree=?,extra_flags=?,stable_slots=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?,"
"totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?,"
- "watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,latency=?,speccount=?,activespec=?,exploredZones=?,"
+ "watchedFaction=?,drunk=?,health=?,power1=?,power2=?,power3=?,power4=?,power5=?,latency=?,talentGroupsCount=?,activeTalentGroup=?,exploredZones=?,"
"equipmentCache=?,knownTitles=?,actionBars=?,grantableLevels=?,online=? WHERE guid=?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG, "UPDATE characters SET at_login = at_login | ? WHERE guid = ?", CONNECTION_ASYNC);
@@ -557,9 +557,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER, "DELETE FROM petition_sign WHERE ownerguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_BY_OWNER_AND_TYPE, "DELETE FROM petition WHERE ownerguid = ? AND type = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER_AND_TYPE, "DELETE FROM petition_sign WHERE ownerguid = ? AND type = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs (guid, spec, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC, "DELETE FROM character_talent WHERE guid = ? and spell = ? and spec = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHAR_TALENT, "INSERT INTO character_talent (guid, spell, spec) VALUES (?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs (guid, talentGroup, glyph1, glyph2, glyph3, glyph4, glyph5, glyph6, glyph7, glyph8, glyph9) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC, "DELETE FROM character_talent WHERE guid = ? and spell = ? and talentGroup = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_TALENT, "INSERT INTO character_talent (guid, spell, talentGroup) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC, "DELETE FROM character_action WHERE spec<>? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_LIST_SLOT, "UPDATE characters SET slot = ? WHERE guid = ? AND account = ?", CONNECTION_ASYNC);