Core/Players: Update profession rank handling with new split skill values for each expansion

This commit is contained in:
Shauren
2018-12-02 17:39:41 +01:00
parent 947771e6bd
commit 1b67a2626b
10 changed files with 240 additions and 72 deletions

View File

@@ -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;

View File

@@ -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`;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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; }

View File

@@ -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)

View File

@@ -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) { }

View File

@@ -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*/)