[11587] Use SkillRaceClassInfo.dbc data for check spell training.

* Show race/class specific min level in trainer list (for weapon master for example)
  and use it for check spell traing possibility.
* Hide for specific race/class some spells marked by flag  ABILITY_SKILL_NONTRAINABLE
  This possible in cases when spell available for race/class but learned from talent/etc
  and then don't must be show for race/calss pair in trainer list. Single case in 3.3.5a.
* Add to code tables for profession ranks for seelct correct rank related reqlevel
  and check DB side data for it. Note: DB reqlevel values redundant for profession rank
  spells now.
* Use for reqlevel selection (if DB value not provided) learned spell insteed cast-spell
  spellLevel field. This let in more cases select training reqlevel without provided DB value.
  For LogFilter_DbStrictedCheck = 0 mode output data about like redundant reqlevel values
  in traner tables.
This commit is contained in:
VladimirMangos 2011-06-02 09:17:08 +04:00
parent c2199e7030
commit 108a167c46
13 changed files with 179 additions and 29 deletions

View file

@ -20556,7 +20556,16 @@ float Player::GetReputationPriceDiscount( Creature const* pCreature ) const
return 1.0f - 0.05f* (rank - REP_NEUTRAL);
}
bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const
/**
* Check spell availability for training base at SkillLineAbility/SkillRaceClassInfo data.
* Checked allowed race/class and dependent from race/class allowed min level
*
* @param spell_id checked spell id
* @param pReqlevel if arg provided then function work in view mode (level check not applied but detected minlevel returned to var by arg pointer.
if arg not provided then considered train action mode and level checked
* @return true if spell available for show in trainer list (with skip level check) or training.
*/
bool Player::IsSpellFitByClassAndRace(uint32 spell_id, uint32* pReqlevel /*= NULL*/) const
{
uint32 racemask = getRaceMask();
uint32 classmask = getClassMask();
@ -20565,16 +20574,42 @@ bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const
if (bounds.first==bounds.second)
return true;
for(SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
{
SkillLineAbilityEntry const* abilityEntry = _spell_idx->second;
// skip wrong race skills
if (_spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0)
if (abilityEntry->racemask && (abilityEntry->racemask & racemask) == 0)
continue;
// skip wrong class skills
if (_spell_idx->second->classmask && (_spell_idx->second->classmask & classmask) == 0)
if (abilityEntry->classmask && (abilityEntry->classmask & classmask) == 0)
continue;
SkillRaceClassInfoMapBounds bounds = sSpellMgr.GetSkillRaceClassInfoMapBounds(abilityEntry->skillId);
for (SkillRaceClassInfoMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
{
SkillRaceClassInfoEntry const* skillRCEntry = itr->second;
if ((skillRCEntry->raceMask & racemask) && (skillRCEntry->classMask & classmask))
{
if (skillRCEntry->flags & ABILITY_SKILL_NONTRAINABLE)
return false;
if (pReqlevel) // show trainers list case
{
if (skillRCEntry->reqLevel)
{
*pReqlevel = skillRCEntry->reqLevel;
return true;
}
}
else // check availble case at train
{
if (skillRCEntry->reqLevel && getLevel() < skillRCEntry->reqLevel)
return false;
}
}
}
return true;
}