From 6446541738727d57f90a3da06de4fffcbe358e60 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Fri, 14 May 2021 12:32:25 +0200 Subject: [PATCH] Core/Skills: ported master branch handling for learning skills on levelup --- .../world/4.3.4/2021_05_14_00_world.sql | 1 + src/server/game/Accounts/RBAC.h | 2 +- src/server/game/DataStores/DBCStores.cpp | 13 ++ src/server/game/DataStores/DBCStores.h | 3 +- src/server/game/Entities/Player/Player.cpp | 136 +++++------------- src/server/game/Entities/Player/Player.h | 1 - src/server/game/World/World.cpp | 1 - src/server/game/World/World.h | 1 - src/server/scripts/Commands/cs_misc.cpp | 17 --- src/server/worldserver/worldserver.conf.dist | 9 -- 10 files changed, 54 insertions(+), 130 deletions(-) create mode 100644 sql/updates/world/4.3.4/2021_05_14_00_world.sql diff --git a/sql/updates/world/4.3.4/2021_05_14_00_world.sql b/sql/updates/world/4.3.4/2021_05_14_00_world.sql new file mode 100644 index 00000000000..888c1305097 --- /dev/null +++ b/sql/updates/world/4.3.4/2021_05_14_00_world.sql @@ -0,0 +1 @@ +DELETE FROM `command` WHERE `permission`= 513; diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index b9f9c329d5f..99d3a56d301 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -410,7 +410,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_KICK = 510, RBAC_PERM_COMMAND_LINKGRAVE = 511, RBAC_PERM_COMMAND_LISTFREEZE = 512, - RBAC_PERM_COMMAND_MAXSKILL = 513, + RBAC_PERM_COMMAND_MAXSKILL = 513, // DEPRECATED: DON'T REUSE RBAC_PERM_COMMAND_MOVEGENS = 514, RBAC_PERM_COMMAND_MUTE = 515, RBAC_PERM_COMMAND_NEARGRAVE = 516, diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 89359494686..db1baa3dff5 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -283,6 +283,11 @@ static bool LoadDBC_assert_print(uint32 fsize, uint32 rsize, const std::string& return false; } +namespace +{ + std::unordered_map> _skillLineAbilitiesBySkillupSkill; +} + template inline void LoadDBC(uint32& availableDbcLocales, StoreProblemList& errors, DBCStorage& storage, std::string const& dbcPath, std::string const& filename, uint32 defaultLocale, std::string const& customFormat = std::string(), std::string const& customIndexName = std::string()) { @@ -616,6 +621,9 @@ void DBCManager::LoadStores(const std::string& dataPath, uint32 defaultLocale) if (entry->RangeIndex > MAX_BATTLEGROUND_BRACKETS) ASSERT(false && "Need update MAX_BATTLEGROUND_BRACKETS by DBC data"); + for (SkillLineAbilityEntry const* skillLineAbility : sSkillLineAbilityStore) + _skillLineAbilitiesBySkillupSkill[skillLineAbility->SkillLine].push_back(skillLineAbility); + for (SkillRaceClassInfoEntry const* entry : sSkillRaceClassInfoStore) if (sSkillLineStore.LookupEntry(entry->SkillID)) SkillRaceClassInfoBySkill.emplace(entry->SkillID, entry); @@ -1268,6 +1276,11 @@ uint32 DBCManager::GetDefaultMapLight(uint32 mapId) return 0; } +std::vector const* DBCManager::GetSkillLineAbilitiesBySkill(uint32 skillId) const +{ + return Trinity::Containers::MapGetValuePtr(_skillLineAbilitiesBySkillupSkill, skillId); +} + SkillRaceClassInfoEntry const* DBCManager::GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_) { SkillRaceClassInfoBounds bounds = SkillRaceClassInfoBySkill.equal_range(skill); diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 0886dc6fd9f..019443773ac 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -244,7 +244,8 @@ public: uint32 GetPowerIndexByClass(Powers power, uint32 classId); static bool IsInArea(uint32 objectAreaId, uint32 areaId); static LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty); - std::vector const* GetPhasesForGroup(uint32 group); + std::vector const* GetPhasesForGroup(uint32 group); + std::vector const* GetSkillLineAbilitiesBySkill(uint32 skillId) const; SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_); ResponseCodes ValidateName(std::wstring const& name, LocaleConstant locale); EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 64363de5514..ca2c4ac0abc 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2337,6 +2337,8 @@ void Player::GiveLevel(uint8 level) SetLevel(level); + UpdateSkillsForLevel(); + // save base values (bonuses already included in stored stats for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) SetCreateStat(Stats(i), info.stats[i]); @@ -2350,9 +2352,6 @@ void Player::GiveLevel(uint8 level) UpdateAllStats(); - if (sWorld->getBoolConfig(CONFIG_ALWAYS_MAXSKILL)) // Max weapon skill when leveling up - UpdateWeaponsSkillsToMaxSkillsForLevel(); - _ApplyAllLevelScaleItemMods(true); // Moved to above SetFullHealth so player will have full health from Heirlooms // set current level health and mana/energy to maximum after applying all mods. @@ -2387,10 +2386,6 @@ void Player::GiveLevel(uint8 level) SetByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL, 0x01); } - // Leaning Running Wild - if (getRace() == RACE_WORGEN && level == 20) - CastSpell(this, SPELL_RUNNING_WILD_LEARN, true); - sScriptMgr->OnPlayerLevelChanged(this, oldLevel); } @@ -3062,9 +3057,6 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent if (skill_max_value < new_skill_max_value) skill_max_value = new_skill_max_value; - if (sWorld->getBoolConfig(CONFIG_ALWAYS_MAXSKILL) && !IsProfessionOrRidingSkill(spellLearnSkill->skill)) - skill_value = skill_max_value; - SetSkill(spellLearnSkill->skill, spellLearnSkill->step, skill_value, skill_max_value); } } @@ -5403,55 +5395,18 @@ void Player::UpdateSkillsForLevel() if (GetSkillRangeType(rcEntry) != SKILL_RANGE_LEVEL) continue; - if (IsWeaponSkill(rcEntry->SkillID)) - continue; - - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - - uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); - - /// update only level dependent max skill values - if (max != 1) + if (GetSkillRangeType(rcEntry) == SKILL_RANGE_LEVEL) { - SetSkillRank(itr->second.pos, maxSkill); + if (rcEntry->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) + SetSkillRank(itr->second.pos, maxSkill); + SetSkillMaxRank(itr->second.pos, maxSkill); if (itr->second.uState != SKILL_NEW) itr->second.uState = SKILL_CHANGED; } - } -} -void Player::UpdateWeaponsSkillsToMaxSkillsForLevel() -{ - for (SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr) - { - if (itr->second.uState == SKILL_DELETED || !GetSkillRank(itr->second.pos)) - continue; - - uint32 pskill = itr->first; - SkillRaceClassInfoEntry const* rcEntry = sDBCManager.GetSkillRaceClassInfo(pskill, getRace(), getClass()); - if (!rcEntry) - continue; - - if (IsProfessionOrRidingSkill(rcEntry->SkillID)) - continue; - - if (IsWeaponSkill(rcEntry->SkillID)) - continue; - - uint16 field = itr->second.pos / 2; - uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - - uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); - - if (max > 1) - { - SetSkillRank(itr->second.pos, max); - - if (itr->second.uState != SKILL_NEW) - itr->second.uState = SKILL_CHANGED; - } + // Update level dependent skillline spells + LearnSkillRewardedSpells(rcEntry->SkillID, GetSkillRank(itr->second.pos)); } } @@ -5542,9 +5497,9 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal) itr->second.uState = SKILL_UNCHANGED; // remove all spells that related to this skill - for (SkillLineAbilityEntry const* skillLineAbilities : sSkillLineAbilityStore) - if (skillLineAbilities->SkillLine == id) - RemoveSpell(sSpellMgr->GetFirstSpellInChain(skillLineAbilities->Spell)); + if (std::vector const* skillLineAbilities = sDBCManager.GetSkillLineAbilitiesBySkill(id)) + for (SkillLineAbilityEntry const* skillLineAbility : *skillLineAbilities) + RemoveSpell(sSpellMgr->GetFirstSpellInChain(skillLineAbility->Spell)); // Clear profession lines if (GetUInt32Value(PLAYER_PROFESSION_SKILL_LINE_1) == id) @@ -23719,9 +23674,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank) { uint16 skillValue = 1; uint16 maxValue = GetMaxSkillValueForLevel(); - if (sWorld->getBoolConfig(CONFIG_ALWAYS_MAXSKILL) && !IsProfessionOrRidingSkill(skillId)) - skillValue = maxValue; - else if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) + if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE) skillValue = maxValue; else if (getClass() == CLASS_DEATH_KNIGHT) skillValue = std::min(std::max({ 1, uint16((getLevel() - 1) * 5) }), maxValue); @@ -23822,28 +23775,29 @@ void Player::LearnQuestRewardedSpells() void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue) { - // bad hack to work around data being suited only for the client - AcquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN for riding - // client uses it to show riding in spellbook as trainable - if (skillId == SKILL_RIDING) - return; - uint32 raceMask = getRaceMask(); uint32 classMask = getClassMask(); - for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) + std::vector const* skillLineAbilities = sDBCManager.GetSkillLineAbilitiesBySkill(skillId); + if (!skillLineAbilities) + return; + + for (SkillLineAbilityEntry const* ability : *skillLineAbilities) { - SkillLineAbilityEntry const* ability = sSkillLineAbilityStore.LookupEntry(j); - if (!ability || ability->SkillLine != skillId) + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(ability->Spell); + if (!spellInfo) continue; - SpellInfo const* spell = sSpellMgr->GetSpellInfo(ability->Spell); - if (!spell) - continue; + switch (ability->AcquireMethod) + { + case SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE: + case SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN: + break; + default: + continue; + } - // Check if we fulfill the level requirement for the spell - if (getLevel() < spell->SpellLevel) - continue; - - if (ability->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE && ability->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN) + // AcquireMethod == 2 && NumSkillUps == 1 --> automatically learn riding skill spell, else we skip it (client shows riding in spellbook as trainable). + if (skillId == SKILL_RIDING && (ability->AcquireMethod != SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN || ability->NumSkillUps != 1)) continue; // Check race if set @@ -23854,35 +23808,19 @@ void Player::LearnSkillRewardedSpells(uint32 skillId, uint32 skillValue) if (ability->ClassMask && !(ability->ClassMask & classMask)) continue; + // check level, skip class spells if not high enough + if (getLevel() < spellInfo->SpellLevel) + continue; + // need unlearn spell if (skillValue < ability->MinSkillLineRank && ability->AcquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_VALUE) RemoveSpell(ability->Spell); + // need learn + else if (!IsInWorld()) + AddSpell(ability->Spell, true, true, true, false, false, ability->SkillLine); else - { - // used to avoid double Seal of Righteousness on paladins, it's the only player spell which has both spell and forward spell in auto learn - if (ability->AcquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && ability->SupercededBySpell) - { - bool skipCurrent = false; - auto bounds = sSpellMgr->GetSkillLineAbilityMapBounds(ability->SupercededBySpell); - for (auto itr = bounds.first; itr != bounds.second; ++itr) - { - if (itr->second->AcquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && skillValue >= itr->second->MinSkillLineRank) - { - skipCurrent = true; - break; - } - } - - if (skipCurrent) - continue; - } - - if (!IsInWorld()) - AddSpell(ability->Spell, true, true, true, false, false, ability->SkillLine); - else - LearnSpell(ability->Spell, true, ability->SkillLine); - } + LearnSpell(ability->Spell, true, ability->SkillLine); } } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 5a6b034e393..df4d476f76c 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1974,7 +1974,6 @@ class TC_GAME_API Player : public Unit, public GridObject int32 CalculateReputationGain(ReputationSource source, uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool noQuestBonus = false); void UpdateSkillsForLevel(); - void UpdateWeaponsSkillsToMaxSkillsForLevel(); // for .levelup void ModifySkillBonus(uint32 skillid, int32 val, bool talent); void SetLastSoulburnSpell(SpellInfo const* spell) { m_lastSoulburnSpell = spell; } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 330d5e8bec7..6435a0c22c4 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1463,7 +1463,6 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_RESET_DUEL_HEALTH_MANA] = sConfigMgr->GetBoolDefault("ResetDuelHealthMana", false); m_bool_configs[CONFIG_START_ALL_EXPLORED] = sConfigMgr->GetBoolDefault("PlayerStart.MapsExplored", false); m_bool_configs[CONFIG_START_ALL_REP] = sConfigMgr->GetBoolDefault("PlayerStart.AllReputation", false); - m_bool_configs[CONFIG_ALWAYS_MAXSKILL] = sConfigMgr->GetBoolDefault("AlwaysMaxWeaponSkill", false); m_bool_configs[CONFIG_PVP_TOKEN_ENABLE] = sConfigMgr->GetBoolDefault("PvPToken.Enable", false); m_int_configs[CONFIG_PVP_TOKEN_MAP_TYPE] = sConfigMgr->GetIntDefault("PvPToken.MapAllowType", 4); m_int_configs[CONFIG_PVP_TOKEN_ID] = sConfigMgr->GetIntDefault("PvPToken.ItemID", 29434); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index d199a71b3b7..7dda5f7f164 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -142,7 +142,6 @@ enum WorldBoolConfigs CONFIG_START_ALL_SPELLS, CONFIG_START_ALL_EXPLORED, CONFIG_START_ALL_REP, - CONFIG_ALWAYS_MAXSKILL, CONFIG_PVP_TOKEN_ENABLE, CONFIG_NO_RESET_TALENT_COST, CONFIG_SHOW_KICK_IN_WORLD, diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 7ab1e956c07..a0220e756da 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -87,7 +87,6 @@ public: { "kick", rbac::RBAC_PERM_COMMAND_KICK, true, &HandleKickPlayerCommand, "" }, { "linkgrave", rbac::RBAC_PERM_COMMAND_LINKGRAVE, false, &HandleLinkGraveCommand, "" }, { "listfreeze", rbac::RBAC_PERM_COMMAND_LISTFREEZE, false, &HandleListFreezeCommand, "" }, - { "maxskill", rbac::RBAC_PERM_COMMAND_MAXSKILL, false, &HandleMaxSkillCommand, "" }, { "movegens", rbac::RBAC_PERM_COMMAND_MOVEGENS, false, &HandleMovegensCommand, "" }, { "mute", rbac::RBAC_PERM_COMMAND_MUTE, true, &HandleMuteCommand, "" }, { "mutehistory", rbac::RBAC_PERM_COMMAND_MUTEHISTORY, true, &HandleMuteInfoCommand, "" }, @@ -1436,22 +1435,6 @@ public: return true; } - - static bool HandleMaxSkillCommand(ChatHandler* handler, char const* /*args*/) - { - Player* player = handler->getSelectedPlayerOrSelf(); - if (!player) - { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; - } - - // each skills that have max skill value dependent from level seted to current level max skill value - player->UpdateWeaponsSkillsToMaxSkillsForLevel(); - return true; - } - static bool HandleSetSkillCommand(ChatHandler* handler, char const* args) { // number or [name] Shift-click form |color|Hskill:skill_id|h[name]|h|r diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 5f0ac5178ad..9c82fcb0358 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -3135,15 +3135,6 @@ ResetDuelCooldowns = 0 ResetDuelHealthMana = 0 -# -# AlwaysMaxWeaponSkill -# Description: Players will automatically gain max weapon/defense skill when logging in, -# or leveling. -# Default: 0 - (Disabled) -# 1 - (Enabled) - -AlwaysMaxWeaponSkill = 0 - # # PvPToken.Enable # Description: Character will receive a token after defeating another character that yields