aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2018-12-02 17:39:41 +0100
committerShauren <shauren.trinity@gmail.com>2018-12-02 17:39:41 +0100
commit1b67a2626b77cf4bf04006cfcb09fdf46e6436fc (patch)
tree33bb8ba53c6d9c3ec222d7c0a682664518a03d44 /src
parent947771e6bdbeaa8788c373e0659cd8ca95cd96f2 (diff)
Core/Players: Update profession rank handling with new split skill values for each expansion
Diffstat (limited to 'src')
-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
7 files changed, 95 insertions, 71 deletions
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*/)