Core/Player: All spells and skills are now automatically learned without any need for external data

* Fixes learning mail/plate at level 40 for shamans/warriors/paladins
* Fixes learning riding for worgen/paladins/warlocks at level 20
This commit is contained in:
Shauren
2015-03-07 12:24:25 +01:00
parent 02ccf53ad1
commit c927acf1f4
7 changed files with 32 additions and 92 deletions
@@ -0,0 +1 @@
DROP TABLE IF EXISTS `playercreateinfo_skills`;
+1
View File
@@ -231,6 +231,7 @@ extern DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore;
extern DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore;
extern DBCStorage <SkillLineEntry> sSkillLineStore;
extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore;
extern DBCStorage <SkillRaceClassInfoEntry> sSkillRaceClassInfoStore;
extern DBCStorage <SkillTiersEntry> sSkillTiersStore;
extern SpellEffectScallingByEffectId sSpellEffectScallingByEffectId;
extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore;
+4 -4
View File
@@ -1400,11 +1400,11 @@ struct SkillRaceClassInfoEntry
{
//uint32 ID; // 0
uint32 SkillID; // 1
uint32 RaceMask; // 2
uint32 ClassMask; // 3
int32 RaceMask; // 2
int32 ClassMask; // 3
uint32 Flags; // 4
//uint32 Availability; // 5
//uint32 MinLevel; // 6
uint32 Availability; // 5
uint32 MinLevel; // 6
uint32 SkillTierID; // 7
};
+1 -1
View File
@@ -129,7 +129,7 @@ char const RandomPropertiesPointsfmt[] = "niiiiiiiiiiiiiii";
char const ScalingStatDistributionfmt[] = "niii";
char const SkillLinefmt[] = "nisxixixx";
char const SkillLineAbilityfmt[] = "niiiiiiiiiiii";
char const SkillRaceClassInfofmt[] = "diiiixxi";
char const SkillRaceClassInfofmt[] = "diiiiiii";
char const SkillTiersfmt[] = "niiiiiiiiiiiiiiii";
char const SpecializationSpellsEntryfmt[] = "niiix";
char const SpellCastTimefmt[] = "nixx";
+17 -16
View File
@@ -2909,7 +2909,7 @@ void Player::GiveLevel(uint8 level)
packet.HealthDelta = int32(basehp) - int32(GetCreateHealth());
/// @todo find some better solution
// for (int i = 0; i < MAX_STORED_POWERS; ++i)
// for (int i = 0; i < MAX_STORED_POWERS; ++i)
packet.PowerDelta[0] = int32(basemana) - int32(GetCreateMana());
packet.PowerDelta[1] = 0;
packet.PowerDelta[2] = 0;
@@ -2936,6 +2936,7 @@ void Player::GiveLevel(uint8 level)
SetLevel(level);
UpdateSkillsForLevel();
LearnDefaultSkills();
LearnSpecializationSpells();
// save base values (bonuses already included in stored stats
@@ -3048,7 +3049,6 @@ void Player::InitStatsForLevel(bool reapplyMods)
SetUInt32Value(UNIT_FIELD_AURASTATE, 0);
UpdateSkillsForLevel();
LearnSpecializationSpells();
// set default cast time multiplier
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
@@ -3645,9 +3645,9 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
if (!pSkill)
continue;
///@todo: confirm if rogues start with lockpicking skill at level 1 but only receive the spell to use it at level 16
if ((_spell_idx->second->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->ID)) || (pSkill->ID == SKILL_LOCKPICKING && _spell_idx->second->TrivialSkillLineRankHigh == 0))
LearnDefaultSkill(pSkill->ID, 0);
if ((_spell_idx->second->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->ID)))
if (SkillRaceClassInfoEntry const* rcInfo = GetSkillRaceClassInfo(pSkill->ID, getRace(), getClass()))
LearnDefaultSkill(rcInfo);
}
}
}
@@ -22675,20 +22675,20 @@ void Player::LearnDefaultSkills()
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
for (PlayerCreateInfoSkills::const_iterator itr = info->skills.begin(); itr != info->skills.end(); ++itr)
{
uint32 skillId = itr->SkillId;
if (HasSkill(skillId))
SkillRaceClassInfoEntry const* rcInfo = *itr;
if (HasSkill(rcInfo->SkillID))
continue;
LearnDefaultSkill(skillId, itr->Rank);
if (rcInfo->MinLevel > getLevel())
continue;
LearnDefaultSkill(rcInfo);
}
}
void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
void Player::LearnDefaultSkill(SkillRaceClassInfoEntry const* rcInfo)
{
SkillRaceClassInfoEntry const* rcInfo = GetSkillRaceClassInfo(skillId, getRace(), getClass());
if (!rcInfo)
return;
uint16 skillId = rcInfo->SkillID;
switch (GetSkillRangeType(rcInfo))
{
case SKILL_RANGE_LANGUAGE:
@@ -22715,8 +22715,9 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
break;
case SKILL_RANGE_RANK:
{
if (!rank)
break;
uint16 rank = 1;
if (getClass() == CLASS_DEATH_KNIGHT && skillId == SKILL_FIRST_AID)
rank = 4;
SkillTiersEntry const* tier = sSkillTiersStore.LookupEntry(rcInfo->SkillTierID);
uint16 maxValue = tier->Value[std::max<int32>(rank - 1, 0)];
@@ -22724,7 +22725,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
if (rcInfo->Flags & SKILL_FLAG_ALWAYS_MAX_VALUE)
skillValue = maxValue;
else if (getClass() == CLASS_DEATH_KNIGHT)
skillValue = std::min(std::max<uint16>({ uint16(1), uint16((getLevel() - 1) * 5) }), maxValue);
skillValue = std::min(std::max(uint16(1), uint16((getLevel() - 1) * 5)), maxValue);
SetSkill(skillId, rank, skillValue, maxValue);
break;
+2 -8
View File
@@ -386,13 +386,7 @@ struct PlayerCreateInfoAction
typedef std::list<PlayerCreateInfoAction> PlayerCreateInfoActions;
struct PlayerCreateInfoSkill
{
uint16 SkillId;
uint16 Rank;
};
typedef std::list<PlayerCreateInfoSkill> PlayerCreateInfoSkills;
typedef std::list<SkillRaceClassInfoEntry const*> PlayerCreateInfoSkills;
struct PlayerInfo
{
@@ -1874,7 +1868,7 @@ class Player : public Unit, public GridObject<Player>
void ResetSpells(bool myClassOnly = false);
void LearnCustomSpells();
void LearnDefaultSkills();
void LearnDefaultSkill(uint32 skillId, uint16 rank);
void LearnDefaultSkill(SkillRaceClassInfoEntry const* rcInfo);
void LearnQuestRewardedSpells();
void LearnQuestRewardedSpells(Quest const* quest);
void LearnSpellHighestRank(uint32 spellid);
+6 -63
View File
@@ -2899,73 +2899,16 @@ void ObjectMgr::LoadPlayerInfo()
{
uint32 oldMSTime = getMSTime();
QueryResult result = WorldDatabase.PQuery("SELECT raceMask, classMask, skill, rank FROM playercreateinfo_skills");
if (!result)
{
TC_LOG_ERROR("server.loading", ">> Loaded 0 player create skills. DB table `playercreateinfo_skills` is empty.");
}
else
{
uint32 count = 0;
do
{
Field* fields = result->Fetch();
uint32 raceMask = fields[0].GetUInt32();
uint32 classMask = fields[1].GetUInt32();
PlayerCreateInfoSkill skill;
skill.SkillId = fields[2].GetUInt16();
skill.Rank = fields[3].GetUInt16();
if (skill.Rank >= MAX_SKILL_STEP)
{
TC_LOG_ERROR("sql.sql", "Skill rank value %hu set for skill %hu raceMask %u classMask %u is too high, max allowed value is %d", skill.Rank, skill.SkillId, raceMask, classMask, MAX_SKILL_STEP);
continue;
}
if (raceMask != 0 && !(raceMask & RACEMASK_ALL_PLAYABLE))
{
TC_LOG_ERROR("sql.sql", "Wrong race mask %u in `playercreateinfo_skills` table, ignoring.", raceMask);
continue;
}
if (classMask != 0 && !(classMask & CLASSMASK_ALL_PLAYABLE))
{
TC_LOG_ERROR("sql.sql", "Wrong class mask %u in `playercreateinfo_skills` table, ignoring.", classMask);
continue;
}
if (!sSkillLineStore.LookupEntry(skill.SkillId))
{
TC_LOG_ERROR("sql.sql", "Wrong skill id %u in `playercreateinfo_skills` table, ignoring.", skill.SkillId);
continue;
}
for (SkillRaceClassInfoEntry const* rcInfo : sSkillRaceClassInfoStore)
if (rcInfo->Availability == 1)
for (uint32 raceIndex = RACE_HUMAN; raceIndex < MAX_RACES; ++raceIndex)
{
if (raceMask == 0 || ((1 << (raceIndex - 1)) & raceMask))
{
if (rcInfo->RaceMask == -1 || ((1 << (raceIndex - 1)) & rcInfo->RaceMask))
for (uint32 classIndex = CLASS_WARRIOR; classIndex < MAX_CLASSES; ++classIndex)
{
if (classMask == 0 || ((1 << (classIndex - 1)) & classMask))
{
if (!GetSkillRaceClassInfo(skill.SkillId, raceIndex, classIndex))
continue;
if (rcInfo->ClassMask == -1 || ((1 << (classIndex - 1)) & rcInfo->ClassMask))
if (PlayerInfo* info = _playerInfo[raceIndex][classIndex])
{
info->skills.push_back(skill);
++count;
}
}
}
}
}
} while (result->NextRow());
info->skills.push_back(rcInfo);
TC_LOG_INFO("server.loading", ">> Loaded %u player create skills in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
TC_LOG_INFO("server.loading", ">> Loaded player create skills in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
// Load playercreate custom spells