Core/Skills: ported master branch handling for learning skills on levelup

This commit is contained in:
Ovahlord committed 2021-05-14 14:52:52 +02:00
1 parent 7cc3577d75
commit 6446541738
10 files changed
+54 -130

No files matched your search

@@ -0,0 +1 @@
DELETE FROM `command` WHERE `permission`= 513;
+1 -1
View File
@@ -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,
+13
View File
@@ -283,6 +283,11 @@ static bool LoadDBC_assert_print(uint32 fsize, uint32 rsize, const std::string&
return false;
}
namespace
{
std::unordered_map<uint32, std::vector<SkillLineAbilityEntry const*>> _skillLineAbilitiesBySkillupSkill;
}
template<class T>
inline void LoadDBC(uint32& availableDbcLocales, StoreProblemList& errors, DBCStorage<T>& 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<SkillLineAbilityEntry const*> 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);
+2 -1
View File
@@ -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<uint32> const* GetPhasesForGroup(uint32 group);
std::vector<uint32> const* GetPhasesForGroup(uint32 group);
std::vector<SkillLineAbilityEntry const*> 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);
+37 -99
View File
@@ -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<SkillLineAbilityEntry const*> 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<uint16>({ 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<SkillLineAbilityEntry const*> 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);
}
}
-1
View File
@@ -1974,7 +1974,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
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; }
-1
View File
@@ -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);
-1
View File
@@ -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,
-17
View File
@@ -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
@@ -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