aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql3
-rw-r--r--sql/updates/characters/master/2018_12_02_00_characters.sql135
-rw-r--r--sql/updates/world/master/2018_12_02_00_world.sql8
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp9
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/Entities/Player/Player.cpp141
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Server/Packets/SystemPackets.cpp4
-rw-r--r--src/server/game/Server/Packets/SystemPackets.h4
-rw-r--r--src/server/game/Spells/SpellEffects.cpp4
10 files changed, 240 insertions, 72 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 17bf37bc811..248f489fc5a 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -3570,7 +3570,8 @@ INSERT INTO `updates` VALUES
('2018_07_28_00_characters.sql','31F66AE7831251A8915625EC7F10FA138AB8B654','RELEASED','2018-07-28 18:30:19',0),
('2018_07_31_00_characters.sql','7DA8D4A4534520B23E6F5BBD5B8EE205B799C798','RELEASED','2018-07-31 20:54:39',0),
('2018_09_18_00_characters.sql','7FE9641C93ED762597C08F1E9B6649C9EC2F0E47','RELEASED','2018-09-18 23:34:29',0),
-('2018_10_10_00_characters.sql','C80B936AAD94C58A0F33382CED08CFB4E0B6AC34','RELEASED','2018-10-10 22:05:28',0);
+('2018_10_10_00_characters.sql','C80B936AAD94C58A0F33382CED08CFB4E0B6AC34','RELEASED','2018-10-10 22:05:28',0),
+('2018_12_02_00_characters.sql','DBBA0C06985CE8AC4E6E7E94BD6B2673E9ADFAE2','RELEASED','2018-12-02 17:32:31',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/characters/master/2018_12_02_00_characters.sql b/sql/updates/characters/master/2018_12_02_00_characters.sql
new file mode 100644
index 00000000000..6c95b00778d
--- /dev/null
+++ b/sql/updates/characters/master/2018_12_02_00_characters.sql
@@ -0,0 +1,135 @@
+--
+-- Table structure for table `profession_skill_migration_data`
+--
+DROP TABLE IF EXISTS `profession_skill_migration_data`;
+CREATE TABLE `profession_skill_migration_data` (
+ `SkillID` int(10) unsigned,
+ `ParentSkillLineID` int(10) unsigned,
+ `MaxValue` int(10) unsigned,
+ `NewMaxValue` int(10) unsigned,
+ `SpellID_A` int(10) unsigned,
+ `SpellID_H` int(10) unsigned,
+ PRIMARY KEY (`SkillID`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+--
+-- Dumping data for table `profession_skill_migration_data`
+--
+INSERT INTO `profession_skill_migration_data` VALUES
+(2437,164,900,150,264448,265803),
+(2454,164,800,100,264446,264446),
+(2472,164,700,100,264444,264444),
+(2473,164,600,75,264442,264442),
+(2474,164,525,75,264440,264440),
+(2475,164,450,75,264438,264438),
+(2476,164,375,75,264436,264436),
+(2477,164,300,300,264434,264434),
+(2478,171,900,150,264255,265787),
+(2479,171,800,100,264250,264250),
+(2480,171,700,100,264247,264247),
+(2481,171,600,75,264245,264245),
+(2482,171,525,75,264243,264243),
+(2483,171,450,75,264220,264220),
+(2484,171,375,75,264213,264213),
+(2485,171,300,300,264211,264211),
+(2486,333,900,150,264473,265805),
+(2487,333,800,100,264471,264471),
+(2488,333,700,100,264469,264469),
+(2489,333,600,75,264467,264467),
+(2491,333,525,75,264464,264464),
+(2492,333,450,75,264462,264462),
+(2493,333,375,75,264460,264460),
+(2494,333,300,300,264455,264455),
+(2499,202,900,150,264492,265807),
+(2500,202,800,100,264490,264490),
+(2501,202,700,100,264487,264487),
+(2502,202,600,75,264485,264485),
+(2503,202,525,75,264483,264483),
+(2504,202,450,75,264481,264481),
+(2505,202,375,75,264479,264479),
+(2506,202,300,300,264475,264475),
+(2507,773,900,150,264508,265809),
+(2508,773,800,100,264506,264506),
+(2509,773,700,100,264504,264504),
+(2510,773,600,75,264502,264502),
+(2511,773,525,75,264500,264500),
+(2512,773,450,75,264498,264498),
+(2513,773,375,75,264496,264496),
+(2514,773,300,300,264494,264494),
+(2517,755,900,150,264548,265811),
+(2518,755,800,100,264546,264546),
+(2519,755,700,100,264544,264544),
+(2520,755,600,75,264542,264542),
+(2521,755,525,75,264539,264539),
+(2522,755,450,75,264537,264537),
+(2523,755,375,75,264534,264534),
+(2524,755,300,300,264532,264532),
+(2525,165,900,150,264592,265813),
+(2526,165,800,100,264590,264590),
+(2527,165,700,100,264588,264588),
+(2528,165,600,75,264585,264585),
+(2529,165,525,75,264583,264583),
+(2530,165,450,75,264581,264581),
+(2531,165,375,75,264579,264579),
+(2532,165,300,300,264577,264577),
+(2533,197,900,150,264630,265815),
+(2534,197,800,100,264628,264628),
+(2535,197,700,100,264626,264626),
+(2536,197,600,75,264624,264624),
+(2537,197,525,75,264622,264622),
+(2538,197,450,75,264620,264620),
+(2539,197,375,75,264618,264618),
+(2540,197,300,300,264616,264616),
+(2541,185,825,150,264646,265817),
+(2542,185,750,100,264644,264644),
+(2543,185,700,100,264642,264642),
+(2544,185,600,75,264640,264640),
+(2545,185,525,75,264638,264638),
+(2546,185,450,75,264636,264636),
+(2547,185,375,75,264634,264634),
+(2548,185,300,300,264632,264632),
+(2549,182,900,150,265831,265835),
+(2550,182,800,100,265834,265834),
+(2551,182,700,100,265829,265829),
+(2552,182,600,75,265827,265827),
+(2553,182,525,75,265825,265825),
+(2554,182,450,75,265823,265823),
+(2555,182,375,75,265821,265821),
+(2556,182,300,300,265819,265819),
+(2557,393,900,150,265869,265871),
+(2558,393,800,100,265867,265867),
+(2559,393,700,100,265865,265865),
+(2560,393,600,75,265863,265863),
+(2561,393,525,75,265861,265861),
+(2562,393,450,75,265859,265859),
+(2563,393,375,75,265857,265857),
+(2564,393,300,300,265855,265855),
+(2565,186,900,150,265851,265853),
+(2566,186,800,100,265849,265849),
+(2567,186,700,100,265847,265847),
+(2568,186,600,75,265845,265845),
+(2569,186,525,75,265843,265843),
+(2570,186,450,75,265841,265841),
+(2571,186,375,75,265839,265839),
+(2572,186,300,300,265837,265837),
+(2585,356,825,150,271675,271677),
+(2586,356,750,100,271672,271672),
+(2587,356,700,100,271664,271664),
+(2588,356,600,75,271662,271662),
+(2589,356,525,75,271660,271660),
+(2590,356,450,75,271658,271658),
+(2591,356,375,75,271656,271656),
+(2592,356,300,300,271616,271616);
+
+INSERT IGNORE INTO `character_spell`
+SELECT cs.`guid`, IF(c.`race` IN (1,3,4,7,11,22,25,29,30,34), psmd.`SpellID_A`, psmd.`SpellID_H`), 1, 0
+FROM `profession_skill_migration_data` psmd
+INNER JOIN `character_skills` cs ON psmd.`ParentSkillLineID` = cs.`skill` AND psmd.`MaxValue` <= cs.`max`
+INNER JOIN `characters` c ON cs.`guid` = c.`guid`;
+
+INSERT IGNORE INTO `character_skills`
+SELECT cs.`guid`, psmd.`SkillID`, CASE WHEN psmd.`MaxValue` < cs.`value` THEN psmd.`NewMaxValue` WHEN psmd.`MaxValue` - cs.`value` < psmd.`NewMaxValue` THEN psmd.`NewMaxValue` + cs.`value` - psmd.`MaxValue` ELSE 1 END, psmd.`NewMaxValue`
+FROM `profession_skill_migration_data` psmd
+INNER JOIN `character_skills` cs ON psmd.`ParentSkillLineID` = cs.`skill` AND psmd.`MaxValue` <= cs.`max`;
+
+DROP TABLE IF EXISTS `profession_skill_migration_data`;
diff --git a/sql/updates/world/master/2018_12_02_00_world.sql b/sql/updates/world/master/2018_12_02_00_world.sql
new file mode 100644
index 00000000000..9228a56d2b8
--- /dev/null
+++ b/sql/updates/world/master/2018_12_02_00_world.sql
@@ -0,0 +1,8 @@
+DELETE FROM `skill_tiers` WHERE `ID` IN (333,335,336,338);
+INSERT INTO `skill_tiers` (`ID`,`Value1`,`Value2`,`Value3`,`Value4`,`Value5`,`Value6`,`Value7`,`Value8`,`Value9`,`Value10`,`Value11`,`Value12`,`Value13`,`Value14`,`Value15`,`Value16`) VALUES
+(333,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
+(335,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
+(336,300,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
+(338,150,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+
+UPDATE `skill_tiers` SET `Value10`=800,`Value11`=950 WHERE `ID`=224;
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 03e2e872c65..a2639077eb4 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -392,6 +392,7 @@ namespace
std::unordered_map<uint32, std::vector<RewardPackXCurrencyTypeEntry const*>> _rewardPackCurrencyTypes;
std::unordered_map<uint32, std::vector<RewardPackXItemEntry const*>> _rewardPackItems;
RulesetItemUpgradeContainer _rulesetItemUpgrade;
+ std::unordered_map<uint32, std::vector<SkillLineAbilityEntry const*>> _skillLineAbilitiesBySkillupSkill;
SkillRaceClassInfoContainer _skillRaceClassInfoBySkill;
SpecializationSpellsContainer _specializationSpellsBySpec;
std::unordered_set<uint8> _spellFamilyNames;
@@ -1023,6 +1024,9 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
for (RulesetItemUpgradeEntry const* rulesetItemUpgrade : sRulesetItemUpgradeStore)
_rulesetItemUpgrade[rulesetItemUpgrade->ItemID] = rulesetItemUpgrade->ItemUpgradeID;
+ for (SkillLineAbilityEntry const* skillLineAbility : sSkillLineAbilityStore)
+ _skillLineAbilitiesBySkillupSkill[skillLineAbility->SkillupSkillLineID ? skillLineAbility->SkillupSkillLineID : skillLineAbility->SkillLine].push_back(skillLineAbility);
+
for (SkillRaceClassInfoEntry const* entry : sSkillRaceClassInfoStore)
if (sSkillLineStore.LookupEntry(entry->SkillID))
_skillRaceClassInfoBySkill.insert(SkillRaceClassInfoContainer::value_type(entry->SkillID, entry));
@@ -2278,6 +2282,11 @@ uint32 DB2Manager::GetRulesetItemUpgrade(uint32 itemId) const
return 0;
}
+std::vector<SkillLineAbilityEntry const*> const* DB2Manager::GetSkillLineAbilitiesBySkill(uint32 skillId) const
+{
+ return Trinity::Containers::MapGetValuePtr(_skillLineAbilitiesBySkillupSkill, skillId);
+}
+
SkillRaceClassInfoEntry const* DB2Manager::GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_)
{
auto bounds = _skillRaceClassInfoBySkill.equal_range(skill);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index 06f8635c908..389a19e952e 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -323,6 +323,7 @@ public:
std::vector<RewardPackXCurrencyTypeEntry const*> const* GetRewardPackCurrencyTypesByRewardID(uint32 rewardPackID) const;
std::vector<RewardPackXItemEntry const*> const* GetRewardPackItemsByRewardID(uint32 rewardPackID) const;
uint32 GetRulesetItemUpgrade(uint32 itemId) const;
+ std::vector<SkillLineAbilityEntry const*> const* GetSkillLineAbilitiesBySkill(uint32 skillId) const;
SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_);
std::vector<SpecializationSpellsEntry const*> const* GetSpecializationSpells(uint32 specId) const;
static bool IsValidSpellFamiliyName(SpellFamilyNames family);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 51db53c9c61..b3e8bd33097 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -5172,43 +5172,6 @@ void Player::SetRegularAttackTime()
}
}
-//skill+step, checking for max value
-bool Player::UpdateSkill(uint32 skill_id, uint32 step)
-{
- if (!skill_id)
- return false;
-
- SkillStatusMap::iterator itr = mSkillStatus.find(skill_id);
- if (itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
- return false;
-
- uint16 field = itr->second.pos / 2;
- uint8 offset = itr->second.pos & 1; // itr->second.pos % 2
-
- uint16 value = GetUInt16Value(ACTIVE_PLAYER_FIELD_SKILL_LINEID + SKILL_RANK_OFFSET + field, offset);
- uint16 max = GetUInt16Value(ACTIVE_PLAYER_FIELD_SKILL_LINEID + SKILL_MAX_RANK_OFFSET + field, offset);
-
- if (!max || !value || value >= max)
- return false;
-
- if (value < max)
- {
- uint32 new_value = value + step;
- if (new_value > max)
- new_value = max;
-
- SetUInt16Value(ACTIVE_PLAYER_FIELD_SKILL_LINEID + SKILL_RANK_OFFSET + field, offset, new_value);
- if (itr->second.uState != SKILL_NEW)
- itr->second.uState = SKILL_CHANGED;
-
- UpdateSkillEnchantments(skill_id, value, new_value);
- UpdateCriteria(CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id);
- return true;
- }
-
- return false;
-}
-
inline int SkillGainChance(uint32 SkillValue, uint32 GrayLevel, uint32 GreenLevel, uint32 YellowLevel)
{
if (SkillValue >= GrayLevel)
@@ -5229,21 +5192,21 @@ bool Player::UpdateCraftSkill(uint32 spellid)
for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
{
- if (_spell_idx->second->SkillLine)
+ if (_spell_idx->second->SkillupSkillLineID)
{
- uint32 SkillValue = GetPureSkillValue(_spell_idx->second->SkillLine);
+ uint32 SkillValue = GetPureSkillValue(_spell_idx->second->SkillupSkillLineID);
// Alchemy Discoveries here
SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spellid);
if (spellEntry && spellEntry->Mechanic == MECHANIC_DISCOVERY)
{
- if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->SkillLine, spellid, this))
+ if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->SkillupSkillLineID, spellid, this))
LearnSpell(discoveredSpell, false);
}
uint32 craft_skill_gain = _spell_idx->second->NumSkillUps * sWorld->getIntConfig(CONFIG_SKILL_GAIN_CRAFTING);
- return UpdateSkillPro(_spell_idx->second->SkillLine, SkillGainChance(SkillValue,
+ return UpdateSkillPro(_spell_idx->second->SkillupSkillLineID, SkillGainChance(SkillValue,
_spell_idx->second->TrivialSkillLineRankHigh,
(_spell_idx->second->TrivialSkillLineRankHigh + _spell_idx->second->TrivialSkillLineRankLow)/2,
_spell_idx->second->TrivialSkillLineRankLow),
@@ -5321,8 +5284,7 @@ bool Player::UpdateSkillPro(uint16 skillId, int32 chance, uint32 step)
// levels sync. with spell requirement for skill levels to learn
// bonus abilities in sSkillLineAbilityStore
// Used only to avoid scan DBC at each skill grow
- static uint32 bonusSkillLevels[] = { 75, 150, 225, 300, 375, 450, 525 };
- static const size_t bonusSkillLevelsSize = sizeof(bonusSkillLevels) / sizeof(uint32);
+ uint32 const bonusSkillLevels[] = { 75, 150, 225, 300, 375, 450, 525, 600, 700, 850 };
TC_LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro: Player '%s' (%s), SkillID: %u, Chance: %3.1f%%)",
GetName().c_str(), GetGUID().ToString().c_str(), skillId, chance / 10.0f);
@@ -5364,9 +5326,8 @@ bool Player::UpdateSkillPro(uint16 skillId, int32 chance, uint32 step)
if (itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
- for (size_t i = 0; i < bonusSkillLevelsSize; ++i)
+ for (uint32 bsl : bonusSkillLevels)
{
- uint32 bsl = bonusSkillLevels[i];
if (value < bsl && new_value >= bsl)
{
LearnSkillRewardedSpells(skillId, new_value);
@@ -5525,10 +5486,13 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
mSkillStatus.erase(itr);
// remove all spells that related to this skill
- for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
- if (SkillLineAbilityEntry const* pAbility = sSkillLineAbilityStore.LookupEntry(j))
- if (pAbility->SkillLine == id)
- RemoveSpell(sSpellMgr->GetFirstSpellInChain(pAbility->Spell));
+ if (std::vector<SkillLineAbilityEntry const*> const* skillLineAbilities = sDB2Manager.GetSkillLineAbilitiesBySkill(id))
+ for (SkillLineAbilityEntry const* skillLineAbility : *skillLineAbilities)
+ RemoveSpell(sSpellMgr->GetFirstSpellInChain(skillLineAbility->Spell));
+
+ for (SkillLineEntry const* childSkillLine : sSkillLineStore)
+ if (childSkillLine->ParentSkillLineID == id)
+ SetSkill(childSkillLine->ID, 0, 0, 0);
// Clear profession lines
if (GetUInt32Value(ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE) == id)
@@ -5555,15 +5519,27 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
return;
}
- SetUInt16Value(ACTIVE_PLAYER_FIELD_SKILL_LINEID + SKILL_ID_OFFSET + field, offset, id);
- if (skillEntry->CategoryID == SKILL_CATEGORY_PROFESSION)
+ if (skillEntry->ParentSkillLineID && skillEntry->ParentTierIndex > 0)
{
- if (!GetUInt32Value(ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE))
- SetUInt32Value(ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE, id);
- else if (!GetUInt32Value(ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE + 1))
- SetUInt32Value(ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE + 1, id);
+ if (SkillRaceClassInfoEntry const* rcEntry = sDB2Manager.GetSkillRaceClassInfo(skillEntry->ParentSkillLineID, getRace(), getClass()))
+ {
+ if (SkillTiersEntry const* tier = sObjectMgr->GetSkillTier(rcEntry->SkillTierID))
+ {
+ uint16 skillval = GetPureSkillValue(skillEntry->ParentSkillLineID);
+ SetSkill(skillEntry->ParentSkillLineID, skillEntry->ParentTierIndex, std::max<uint16>(skillval, 1), tier->Value[skillEntry->ParentTierIndex - 1]);
+ }
+ }
+
+ if (skillEntry->CategoryID == SKILL_CATEGORY_PROFESSION)
+ {
+ int32 freeProfessionSlot = FindProfessionSlotFor(id);
+ if (freeProfessionSlot != -1)
+ SetUInt32Value(ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE + freeProfessionSlot, id);
+ }
}
+ SetUInt16Value(ACTIVE_PLAYER_FIELD_SKILL_LINEID + SKILL_ID_OFFSET + field, offset, id);
+
SetUInt16Value(ACTIVE_PLAYER_FIELD_SKILL_LINEID + SKILL_STEP_OFFSET + field, offset, step);
SetUInt16Value(ACTIVE_PLAYER_FIELD_SKILL_LINEID + SKILL_RANK_OFFSET + field, offset, newVal);
SetUInt16Value(ACTIVE_PLAYER_FIELD_SKILL_LINEID + SKILL_MAX_RANK_OFFSET + field, offset, maxVal);
@@ -24119,12 +24095,12 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue)
{
uint64 raceMask = getRaceMask();
uint32 classMask = getClassMask();
- for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
- {
- SkillLineAbilityEntry const* ability = sSkillLineAbilityStore.LookupEntry(j);
- if (!ability || ability->SkillLine != int32(skillId))
- continue;
+ std::vector<SkillLineAbilityEntry const*> const* skillLineAbilities = sDB2Manager.GetSkillLineAbilitiesBySkill(skillId);
+ if (!skillLineAbilities)
+ return;
+ for (SkillLineAbilityEntry const* ability : *skillLineAbilities)
+ {
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ability->Spell);
if (!spellInfo)
continue;
@@ -24159,6 +24135,42 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue)
}
}
+int32 Player::FindProfessionSlotFor(uint32 skillId) const
+{
+ SkillLineEntry const* skillEntry = sSkillLineStore.LookupEntry(skillId);
+ if (!skillEntry)
+ return -1;
+
+ uint32 constexpr professionSlots = 2;
+ uint32 const* professionsBegin = &m_uint32Values[ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE];
+ uint32 const* professionsEnd = professionsBegin + professionSlots;
+
+ // both free, return first slot
+ if (std::none_of(professionsBegin, professionsEnd, [](uint32 slot) { return slot != 0; }))
+ return 0;
+
+ // when any slot is filled we need to check both - one of them might be earlier step of the same profession
+ auto sameProfessionSlot = std::find_if(professionsBegin, professionsEnd, [&](uint32 slot)
+ {
+ if (SkillLineEntry const* slotProfession = sSkillLineStore.LookupEntry(slot))
+ if (slotProfession->ParentSkillLineID == skillEntry->ParentSkillLineID)
+ return true;
+ return false;
+ });
+
+ if (sameProfessionSlot != professionsEnd)
+ {
+ if (sSkillLineStore.AssertEntry(*sameProfessionSlot)->ParentTierIndex < skillEntry->ParentTierIndex)
+ return std::distance(professionsBegin, sameProfessionSlot);
+
+ return -1;
+ }
+
+ // if there is no same profession, find any free slot
+ auto freeSlot = std::find(professionsBegin, professionsEnd, 0u);
+ return freeSlot != professionsEnd ? std::distance(professionsBegin, freeSlot) : -1;
+}
+
void Player::SendAurasForTarget(Unit* target) const
{
if (!target || target->GetVisibleAuras().empty()) // speedup things
@@ -25792,7 +25804,6 @@ void Player::_LoadSkills(PreparedQueryResult result)
// SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid));
uint32 count = 0;
- uint8 professionCount = 0;
std::unordered_map<uint32, uint32> loadedSkillValues;
if (result)
{
@@ -25859,8 +25870,12 @@ void Player::_LoadSkills(PreparedQueryResult result)
{
step = max / 75;
- if (professionCount < 2)
- SetUInt32Value(ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE + professionCount++, skill);
+ if (skillLine->ParentSkillLineID && skillLine->ParentTierIndex)
+ {
+ int32 professionSlot = FindProfessionSlotFor(skill);
+ if (professionSlot != -1)
+ SetUInt32Value(ACTIVE_PLAYER_FIELD_PROFESSION_SKILL_LINE + professionSlot, skill);
+ }
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index e3092f0279c..d53dbf33db0 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1786,9 +1786,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
static Difficulty CheckLoadedLegacyRaidDifficultyID(Difficulty difficulty);
void SendRaidGroupOnlyMessage(RaidGroupReason reason, int32 delay) const;
- bool UpdateSkill(uint32 skill_id, uint32 step);
bool UpdateSkillPro(uint16 skillId, int32 chance, uint32 step);
-
bool UpdateCraftSkill(uint32 spellid);
bool UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLevel, uint32 Multiplicator = 1);
bool UpdateFishingSkill();
@@ -1928,6 +1926,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint16 GetSkillStep(uint16 skill) const; // 0...6
bool HasSkill(uint32 skill) const;
void LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue);
+ int32 FindProfessionSlotFor(uint32 skillId) const;
WorldLocation& GetTeleportDest() { return m_teleport_dest; }
bool IsBeingTeleported() const { return mSemaphoreTeleport_Near || mSemaphoreTeleport_Far; }
diff --git a/src/server/game/Server/Packets/SystemPackets.cpp b/src/server/game/Server/Packets/SystemPackets.cpp
index 71dbce750e7..853e35fce5c 100644
--- a/src/server/game/Server/Packets/SystemPackets.cpp
+++ b/src/server/game/Server/Packets/SystemPackets.cpp
@@ -112,8 +112,8 @@ WorldPacket const* WorldPackets::System::FeatureSystemStatus::Write()
{
_worldPacket.WriteBit(VoiceChatManagerSettings.Enabled);
- _worldPacket << VoiceChatManagerSettings.Unused_801_1;
- _worldPacket << VoiceChatManagerSettings.Unused_801_2;
+ _worldPacket << VoiceChatManagerSettings.BnetAccountGuid;
+ _worldPacket << VoiceChatManagerSettings.GuildGuid;
}
if (EuropaTicketSystemStatus)
diff --git a/src/server/game/Server/Packets/SystemPackets.h b/src/server/game/Server/Packets/SystemPackets.h
index 8fe1f515590..4d0812e7e67 100644
--- a/src/server/game/Server/Packets/SystemPackets.h
+++ b/src/server/game/Server/Packets/SystemPackets.h
@@ -83,8 +83,8 @@ namespace WorldPackets
struct VoiceChatProxySettings
{
bool Enabled = false;
- ObjectGuid Unused_801_1;
- ObjectGuid Unused_801_2;
+ ObjectGuid BnetAccountGuid;
+ ObjectGuid GuildGuid;
};
FeatureSystemStatus() : ServerPacket(SMSG_FEATURE_SYSTEM_STATUS, 48) { }
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 6cfb2764f08..4a1061b6425 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2366,7 +2366,7 @@ void Spell::EffectLearnSkill(SpellEffIndex /*effIndex*/)
if (unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- if (damage < 0)
+ if (damage < 1)
return;
uint32 skillid = effectInfo->MiscValue;
@@ -2379,7 +2379,7 @@ void Spell::EffectLearnSkill(SpellEffIndex /*effIndex*/)
return;
uint16 skillval = unitTarget->ToPlayer()->GetPureSkillValue(skillid);
- unitTarget->ToPlayer()->SetSkill(skillid, effectInfo->CalcValue(), std::max<uint16>(skillval, 1), tier->Value[damage - 1]);
+ unitTarget->ToPlayer()->SetSkill(skillid, damage, std::max<uint16>(skillval, 1), tier->Value[damage - 1]);
}
void Spell::EffectPlayMovie(SpellEffIndex /*effIndex*/)