diff options
author | Intel <chemicstry@gmail.com> | 2014-11-16 00:05:42 +0200 |
---|---|---|
committer | Intel <chemicstry@gmail.com> | 2014-11-16 00:05:42 +0200 |
commit | 3bd83ff164b6bfa15ad876a16d76b29242038f85 (patch) | |
tree | 43a533c85f05a5055934844b31ad46b445bd3bd2 /src/server/game | |
parent | 2120868d34a2255c9b26012dc5168e204d8f8e91 (diff) |
Core/Packets: Added SMSG_SET_SPECIALIZATION
Diffstat (limited to 'src/server/game')
-rw-r--r-- | src/server/game/DataStores/DBCStores.cpp | 5 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.h | 3 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 61 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Handlers/SkillHandler.cpp | 34 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 13 | ||||
-rw-r--r-- | src/server/game/Server/Packets/TalentPackets.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Server/Packets/TalentPackets.h | 10 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 6 |
10 files changed, 107 insertions, 36 deletions
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index a4dd3db66a9..ed909a4f14e 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -75,6 +75,7 @@ DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt); DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt); DBCStorage <ChrPowerTypesEntry> sChrPowerTypesStore(ChrClassesXPowerTypesfmt); DBCStorage <ChrSpecializationEntry> sChrSpecializationStore(ChrSpecializationEntryfmt); +ChrSpecializationByIndexArray sChrSpecializationByIndexStore; SpecializationSpellsBySpecStore sSpecializationSpellsBySpecStore; DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequencesEntryfmt); DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt); @@ -352,6 +353,10 @@ void LoadDBCStores(const std::string& dataPath) } LoadDBC(availableDbcLocales, bad_dbc_files, sChrSpecializationStore, dbcPath, "ChrSpecialization.dbc"); + memset(sChrSpecializationByIndexStore, 0, sizeof(sChrSpecializationByIndexStore)); + for (uint32 i = 0; i < sChrSpecializationStore.GetNumRows(); ++i) + if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(i)) + sChrSpecializationByIndexStore[chrSpec->ClassID][chrSpec->OrderIndex] = chrSpec; LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc");//19116 LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc");//19116 diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index bb7885c8bc2..e9a9b3c692f 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -22,6 +22,7 @@ #include "Common.h" #include "DBCStore.h" #include "DBCStructure.h" +#include "SharedDefines.h" #include <list> @@ -90,6 +91,7 @@ SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, u typedef std::set<SpecializationSpellsEntry const*> SpecializationSpellsBySpecEntry; typedef std::unordered_map<uint32, SpecializationSpellsBySpecEntry> SpecializationSpellsBySpecStore; +typedef ChrSpecializationEntry const* ChrSpecializationByIndexArray[MAX_CLASSES][MAX_SPECIALIZATIONS]; typedef std::unordered_map<uint32, TalentEntry const*> TalentBySpellIDMap; extern DBCStorage <AchievementEntry> sAchievementStore; @@ -110,6 +112,7 @@ extern DBCStorage <ChrClassesEntry> sChrClassesStore; extern DBCStorage <ChrRacesEntry> sChrRacesStore; extern DBCStorage <ChrPowerTypesEntry> sChrPowerTypesStore; extern DBCStorage <ChrSpecializationEntry> sChrSpecializationStore; +extern ChrSpecializationByIndexArray sChrSpecializationByIndexStore; extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore; extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore; extern DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c0aac237d0d..3ba4f662426 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -25427,6 +25427,10 @@ void Player::CompletedAchievement(AchievementEntry const* entry) bool Player::LearnTalent(uint32 talentId) { uint8 group = GetActiveTalentGroup(); + + // check if talent specialization is learnt + if (!GetTalentSpec(group)) + return false; TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId); @@ -25460,34 +25464,6 @@ bool Player::LearnTalent(uint32 talentId) if (HasSpell(spellid)) return false; - // set talent spec for player - if (!GetTalentSpec(group)) - { - SetTalentSpec(group, talentInfo->SpecID); - - // Replace default spells by specialization spells - auto specSpells = sSpecializationSpellsBySpecStore.find(talentInfo->SpecID); - if (specSpells != sSpecializationSpellsBySpecStore.end()) - { - for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) - { - 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); - } - } - // Check talent spec if (talentInfo->SpecID != GetTalentSpec(group)) return false; @@ -25501,6 +25477,35 @@ bool Player::LearnTalent(uint32 talentId) return true; } +void Player::LearnTalentSpecialization(uint32 talentSpec) +{ + SetTalentSpec(GetActiveTalentGroup(), talentSpec); + + // Replace default spells by specialization spells + auto specSpells = sSpecializationSpellsBySpecStore.find(talentSpec); + if (specSpells != sSpecializationSpellsBySpecStore.end()) + { + for (auto it = specSpells->second.begin(); it != specSpells->second.end(); ++it) + { + SpecializationSpellsEntry const* specSpell = *it; + if (HasSpell(specSpell->OverridesSpellID)) { + RemoveSpell(specSpell->OverridesSpellID, true); + LearnSpell(specSpell->SpellID, false); + } + } + } + + if (CanUseMastery()) { + ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(talentSpec); + 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); + } + + SendTalentsInfoData(); +} + void Player::AddKnownCurrency(uint32 itemId) { if (CurrencyTypesEntry const* ctEntry = sCurrencyTypesStore.LookupEntry(itemId)) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index a5698740092..39eace840f3 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1841,6 +1841,7 @@ class Player : public Unit, public GridObject<Player> bool LearnTalent(uint32 talentId); bool AddTalent(uint32 talentId, uint8 spec); bool HasTalent(uint32 talentId, uint8 spec); + void LearnTalentSpecialization(uint32 talentSpec); // Dual Spec void UpdateTalentGroupCount(uint8 count); diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp index ef1e9031cb9..f0c1b28117b 100644 --- a/src/server/game/Handlers/SkillHandler.cpp +++ b/src/server/game/Handlers/SkillHandler.cpp @@ -26,6 +26,7 @@ #include "UpdateMask.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "TalentPackets.h" void WorldSession::HandleLearnTalentOpcode(WorldPacket& recvData) { @@ -126,3 +127,36 @@ void WorldSession::HandleUnlearnSkillOpcode(WorldPacket& recvData) GetPlayer()->SetSkill(skillId, 0, 0, 0); } + +void WorldSession::HandleSetSpecializationOpcode(WorldPackets::Talent::SetSpecialization& packet) +{ + Player* player = GetPlayer(); + + if (packet.SpecGroupIndex >= MAX_SPECIALIZATIONS) + { + TC_LOG_DEBUG("network", "WORLD: HandleSetSpecializationOpcode - specialization index %u out of range", packet.SpecGroupIndex); + return; + } + + ChrSpecializationEntry const* chrSpec = sChrSpecializationByIndexStore[player->getClass()][packet.SpecGroupIndex]; + + if (!chrSpec) + { + TC_LOG_DEBUG("network", "WORLD: HandleSetSpecializationOpcode - specialization index %u not found", packet.SpecGroupIndex); + return; + } + + if (chrSpec->ClassID != player->getClass()) + { + TC_LOG_DEBUG("network", "WORLD: HandleSetSpecializationOpcode - specialization %u does not belong to class %u", chrSpec->ID, player->getClass()); + return; + } + + if (player->getLevel() < MIN_SPECIALIZATION_LEVEL) + { + TC_LOG_DEBUG("network", "WORLD: HandleSetSpecializationOpcode - player level too low for specializations"); + return; + } + + player->LearnTalentSpecialization(chrSpec->ID); +} diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 9e8b5ca00f3..68c30716ad9 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -815,12 +815,13 @@ enum SpellAttr13 SPELL_ATTR13_UNK23 = 0x00800000 // 23 }; -#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 +#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 MIN_SPECIALIZATION_LEVEL 10 +#define MAX_SPECIALIZATIONS 4 // Custom values enum SpellClickUserTypes diff --git a/src/server/game/Server/Packets/TalentPackets.cpp b/src/server/game/Server/Packets/TalentPackets.cpp index 3410fb273f7..4855f663662 100644 --- a/src/server/game/Server/Packets/TalentPackets.cpp +++ b/src/server/game/Server/Packets/TalentPackets.cpp @@ -36,3 +36,8 @@ WorldPacket const* WorldPackets::Talent::UpdateTalentData::Write() return &_worldPacket; } + +void WorldPackets::Talent::SetSpecialization::Read() +{ + _worldPacket >> SpecGroupIndex; +} diff --git a/src/server/game/Server/Packets/TalentPackets.h b/src/server/game/Server/Packets/TalentPackets.h index c756c6962bb..82d2e7985c4 100644 --- a/src/server/game/Server/Packets/TalentPackets.h +++ b/src/server/game/Server/Packets/TalentPackets.h @@ -48,6 +48,16 @@ namespace WorldPackets TalentInfoUpdate Info; }; + + class SetSpecialization final : public ClientPacket + { + public: + SetSpecialization(WorldPacket&& packet) : ClientPacket(CMSG_SET_SPECIALIZATION, std::move(packet)) { } + + void Read() override; + + uint32 SpecGroupIndex = 0; + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 417a7420361..c7b3b549468 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -24,6 +24,7 @@ #include "Packets/MiscPackets.h" #include "Packets/MovementPackets.h" #include "Packets/QueryPackets.h" +#include "Packets/TalentPackets.h" #include "Packets/TradePackets.h" template<class PacketClass, void(WorldSession::*HandlerFunction)(PacketClass&)> @@ -591,7 +592,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SAVED_INSTANCE_EXTEND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SELECTION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleSetSelectionOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SKILL_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_HANDLER(CMSG_SET_SPECIALIZATION, STATUS_LOGGEDIN, PROCESS_INPLACE, WorldPackets::Talent::SetSpecialization, &WorldSession::HandleSetSpecializationOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TAXI_BENCHMARK_MODE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TITLE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTitleOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TRADE_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -1343,7 +1344,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_COMMS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_ERROR, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INFO, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INFO, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INVOLUNTARILY_RESET, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TAXINODE_STATUS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TEST_DROP_RATE_RESULT, STATUS_UNHANDLED); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 445e7412629..59049d12107 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -106,6 +106,11 @@ namespace WorldPackets { class QueryGuildInfo; } + + namespace Talent + { + class SetSpecialization; + } namespace Trade { @@ -787,6 +792,7 @@ class WorldSession void HandleLearnPreviewTalents(WorldPacket& recvPacket); void HandleTalentWipeConfirmOpcode(WorldPacket& recvPacket); void HandleUnlearnSkillOpcode(WorldPacket& recvPacket); + void HandleSetSpecializationOpcode(WorldPackets::Talent::SetSpecialization& packet); void HandleQuestgiverStatusQueryOpcode(WorldPacket& recvPacket); void HandleQuestgiverStatusMultipleQuery(WorldPacket& recvPacket); |