mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[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:
parent
c2199e7030
commit
108a167c46
13 changed files with 179 additions and 29 deletions
|
|
@ -313,6 +313,11 @@ enum AbilytyLearnType
|
||||||
ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2
|
ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum AbilitySkillFlags
|
||||||
|
{
|
||||||
|
ABILITY_SKILL_NONTRAINABLE = 0x100
|
||||||
|
};
|
||||||
|
|
||||||
enum ItemEnchantmentType
|
enum ItemEnchantmentType
|
||||||
{
|
{
|
||||||
ITEM_ENCHANTMENT_TYPE_NONE = 0,
|
ITEM_ENCHANTMENT_TYPE_NONE = 0,
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore(ScalingStatValuesfmt
|
||||||
|
|
||||||
DBCStorage <SkillLineEntry> sSkillLineStore(SkillLinefmt);
|
DBCStorage <SkillLineEntry> sSkillLineStore(SkillLinefmt);
|
||||||
DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore(SkillLineAbilityfmt);
|
DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore(SkillLineAbilityfmt);
|
||||||
|
DBCStorage <SkillRaceClassInfoEntry> sSkillRaceClassInfoStore(SkillRaceClassInfofmt);
|
||||||
|
|
||||||
DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt);
|
DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt);
|
||||||
|
|
||||||
|
|
@ -361,7 +362,7 @@ void LoadDBCStores(const std::string& dataPath)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32 DBCFilesCount = 91;
|
const uint32 DBCFilesCount = 92;
|
||||||
|
|
||||||
barGoLink bar( (int)DBCFilesCount );
|
barGoLink bar( (int)DBCFilesCount );
|
||||||
|
|
||||||
|
|
@ -477,6 +478,7 @@ void LoadDBCStores(const std::string& dataPath)
|
||||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatValuesStore, dbcPath,"ScalingStatValues.dbc");
|
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatValuesStore, dbcPath,"ScalingStatValues.dbc");
|
||||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc");
|
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc");
|
||||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc");
|
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc");
|
||||||
|
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillRaceClassInfoStore, dbcPath,"SkillRaceClassInfo.dbc");
|
||||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc");
|
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc");
|
||||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc");
|
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc");
|
||||||
for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
|
for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@ extern DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore;
|
||||||
extern DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore;
|
extern DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore;
|
||||||
extern DBCStorage <SkillLineEntry> sSkillLineStore;
|
extern DBCStorage <SkillLineEntry> sSkillLineStore;
|
||||||
extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore;
|
extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore;
|
||||||
|
extern DBCStorage <SkillRaceClassInfoEntry> sSkillRaceClassInfoStore;
|
||||||
extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore;
|
extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore;
|
||||||
extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore;
|
extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore;
|
||||||
extern DBCStorage <SpellDifficultyEntry> sSpellDifficultyStore;
|
extern DBCStorage <SpellDifficultyEntry> sSpellDifficultyStore;
|
||||||
|
|
|
||||||
|
|
@ -1434,17 +1434,17 @@ struct ScalingStatValuesEntry
|
||||||
uint32 displayOrder; // 19 m_sortIndex
|
uint32 displayOrder; // 19 m_sortIndex
|
||||||
};*/
|
};*/
|
||||||
|
|
||||||
/*struct SkillRaceClassInfoEntry
|
struct SkillRaceClassInfoEntry
|
||||||
{
|
{
|
||||||
uint32 id; // 0 m_ID
|
//uint32 id; // 0 m_ID
|
||||||
uint32 skillId; // 1 m_skillID
|
uint32 skillId; // 1 m_skillID
|
||||||
uint32 raceMask; // 2 m_raceMask
|
uint32 raceMask; // 2 m_raceMask
|
||||||
uint32 classMask; // 3 m_classMask
|
uint32 classMask; // 3 m_classMask
|
||||||
uint32 flags; // 4 m_flags
|
uint32 flags; // 4 m_flags
|
||||||
uint32 reqLevel; // 5 m_minLevel
|
uint32 reqLevel; // 5 m_minLevel
|
||||||
uint32 skillTierId; // 6 m_skillTierID
|
//uint32 skillTierId; // 6 m_skillTierID
|
||||||
uint32 skillCostID; // 7 m_skillCostIndex
|
//uint32 skillCostID; // 7 m_skillCostIndex
|
||||||
};*/
|
};
|
||||||
|
|
||||||
/*struct SkillTiersEntry{
|
/*struct SkillTiersEntry{
|
||||||
uint32 id; // 0 m_ID
|
uint32 id; // 0 m_ID
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii";
|
||||||
const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiixiiii";
|
const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiiixiiii";
|
||||||
const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi";
|
const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxi";
|
||||||
const char SkillLineAbilityfmt[]="niiiixxiiiiixx";
|
const char SkillLineAbilityfmt[]="niiiixxiiiiixx";
|
||||||
|
const char SkillRaceClassInfofmt[]="diiiiixx";
|
||||||
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||||
const char SpellCastTimefmt[]="nixx";
|
const char SpellCastTimefmt[]="nixx";
|
||||||
const char SpellDurationfmt[]="niii";
|
const char SpellDurationfmt[]="niii";
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ void WorldSession::SendTrainerList(ObjectGuid guid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void SendTrainerSpellHelper(WorldPacket& data, TrainerSpell const* tSpell, TrainerSpellState state, float fDiscountMod, bool can_learn_primary_prof)
|
static void SendTrainerSpellHelper(WorldPacket& data, TrainerSpell const* tSpell, TrainerSpellState state, float fDiscountMod, bool can_learn_primary_prof, uint32 skillReqLevel)
|
||||||
{
|
{
|
||||||
bool primary_prof_first_rank = sSpellMgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell);
|
bool primary_prof_first_rank = sSpellMgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell);
|
||||||
SpellChainNode const* chain_node = sSpellMgr.GetSpellChainNode(tSpell->learnedSpell);
|
SpellChainNode const* chain_node = sSpellMgr.GetSpellChainNode(tSpell->learnedSpell);
|
||||||
|
|
@ -131,7 +131,7 @@ static void SendTrainerSpellHelper(WorldPacket& data, TrainerSpell const* tSpell
|
||||||
data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0);
|
data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0);
|
||||||
// primary prof. learn confirmation dialog
|
// primary prof. learn confirmation dialog
|
||||||
data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
|
data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state
|
||||||
data << uint8(tSpell->reqLevel);
|
data << uint8(skillReqLevel ? skillReqLevel : tSpell->reqLevel);
|
||||||
data << uint32(tSpell->reqSkill);
|
data << uint32(tSpell->reqSkill);
|
||||||
data << uint32(tSpell->reqSkillValue);
|
data << uint32(tSpell->reqSkillValue);
|
||||||
data << uint32(!tSpell->IsCastable() && chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
|
data << uint32(!tSpell->IsCastable() && chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
|
||||||
|
|
@ -193,12 +193,13 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
|
||||||
{
|
{
|
||||||
TrainerSpell const* tSpell = &itr->second;
|
TrainerSpell const* tSpell = &itr->second;
|
||||||
|
|
||||||
if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell))
|
uint32 skillReqLevel = 0;
|
||||||
|
if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell, &skillReqLevel))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TrainerSpellState state = _player->GetTrainerSpellState(tSpell);
|
TrainerSpellState state = _player->GetTrainerSpellState(tSpell);
|
||||||
|
|
||||||
SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof);
|
SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof, skillReqLevel);
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
@ -210,12 +211,13 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
|
||||||
{
|
{
|
||||||
TrainerSpell const* tSpell = &itr->second;
|
TrainerSpell const* tSpell = &itr->second;
|
||||||
|
|
||||||
if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell))
|
uint32 skillReqLevel = 0;
|
||||||
|
if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell, &skillReqLevel))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TrainerSpellState state = _player->GetTrainerSpellState(tSpell);
|
TrainerSpellState state = _player->GetTrainerSpellState(tSpell);
|
||||||
|
|
||||||
SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof);
|
SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof, skillReqLevel);
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8041,13 +8041,13 @@ void ObjectMgr::LoadTrainers(char const* tableName, bool isTemplates)
|
||||||
SpellEntry const *spellinfo = sSpellStore.LookupEntry(spell);
|
SpellEntry const *spellinfo = sSpellStore.LookupEntry(spell);
|
||||||
if (!spellinfo)
|
if (!spellinfo)
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("Table `%s` for trainer (Entry: %u ) has non existing spell %u, ignore", tableName, entry, spell);
|
sLog.outErrorDb("Table `%s` (Entry: %u ) has non existing spell %u, ignore", tableName, entry, spell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SpellMgr::IsSpellValid(spellinfo))
|
if (!SpellMgr::IsSpellValid(spellinfo))
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("Table `%s` for trainer (Entry: %u) has broken learning spell %u, ignore", tableName, entry, spell);
|
sLog.outErrorDb("Table `%s` (Entry: %u) has broken learning spell %u, ignore", tableName, entry, spell);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -8085,7 +8085,7 @@ void ObjectMgr::LoadTrainers(char const* tableName, bool isTemplates)
|
||||||
{
|
{
|
||||||
if (tSpells->spellList.find(spell) != tSpells->spellList.end())
|
if (tSpells->spellList.find(spell) != tSpells->spellList.end())
|
||||||
{
|
{
|
||||||
sLog.outErrorDb("Table `%s` for trainer (Entry: %u) has spell %u listed in trainer template %u, ignore", tableName, entry, spell, cInfo->trainerId);
|
sLog.outErrorDb("Table `%s` (Entry: %u) has spell %u listed in trainer template %u, ignore", tableName, entry, spell, cInfo->trainerId);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -8100,25 +8100,52 @@ void ObjectMgr::LoadTrainers(char const* tableName, bool isTemplates)
|
||||||
trainerSpell.reqSkillValue = fields[4].GetUInt32();
|
trainerSpell.reqSkillValue = fields[4].GetUInt32();
|
||||||
trainerSpell.reqLevel = fields[5].GetUInt32();
|
trainerSpell.reqLevel = fields[5].GetUInt32();
|
||||||
|
|
||||||
if(!trainerSpell.reqLevel)
|
|
||||||
trainerSpell.reqLevel = spellinfo->spellLevel;
|
|
||||||
|
|
||||||
// calculate learned spell for profession case when stored cast-spell
|
// calculate learned spell for profession case when stored cast-spell
|
||||||
trainerSpell.learnedSpell = spell;
|
trainerSpell.learnedSpell = spell;
|
||||||
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
|
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||||
{
|
{
|
||||||
if (spellinfo->Effect[i] != SPELL_EFFECT_LEARN_SPELL)
|
if (spellinfo->Effect[i] == SPELL_EFFECT_LEARN_SPELL &&
|
||||||
continue;
|
SpellMgr::IsProfessionOrRidingSpell(spellinfo->EffectTriggerSpell[i]))
|
||||||
if (SpellMgr::IsProfessionOrRidingSpell(spellinfo->EffectTriggerSpell[i]))
|
|
||||||
{
|
{
|
||||||
trainerSpell.learnedSpell = spellinfo->EffectTriggerSpell[i];
|
// prof spells sometime only additions to main spell learn that have level data
|
||||||
|
for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
|
||||||
|
{
|
||||||
|
if (spellinfo->Effect[j] == SPELL_EFFECT_LEARN_SPELL)
|
||||||
|
{
|
||||||
|
trainerSpell.learnedSpell = spellinfo->EffectTriggerSpell[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// already checked as valid spell so exist.
|
||||||
|
SpellEntry const *learnSpellinfo = sSpellStore.LookupEntry(trainerSpell.learnedSpell);
|
||||||
|
if (trainerSpell.reqLevel)
|
||||||
|
{
|
||||||
|
if (trainerSpell.reqLevel == learnSpellinfo->spellLevel)
|
||||||
|
ERROR_DB_STRICT_LOG("Table `%s` (Entry: %u) has redundant reqlevel %u (=spell level) for spell %u", tableName, entry, trainerSpell.reqLevel, spell);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
trainerSpell.reqLevel = learnSpellinfo->spellLevel;
|
||||||
|
|
||||||
if (SpellMgr::IsProfessionSpell(trainerSpell.learnedSpell))
|
if (SpellMgr::IsProfessionSpell(trainerSpell.learnedSpell))
|
||||||
|
{
|
||||||
data.trainerType = 2;
|
data.trainerType = 2;
|
||||||
|
|
||||||
|
uint32 minLevel = sSpellMgr.GetProfessionSpellMinLevel(trainerSpell.learnedSpell);
|
||||||
|
if (trainerSpell.reqLevel)
|
||||||
|
{
|
||||||
|
if (minLevel == trainerSpell.reqLevel)
|
||||||
|
ERROR_DB_STRICT_LOG("Table `%s` (Entry: %u) has redundant reqlevel %u (=prof reqlevel) for spell %u", tableName, entry, trainerSpell.reqLevel, spell);
|
||||||
|
else
|
||||||
|
sLog.outErrorDb("Table `%s` (Entry: %u) has wrong redundant reqlevel %u (<>prof reqlevel %u) for spell %u", tableName, entry, trainerSpell.reqLevel, minLevel, spell);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
trainerSpell.reqLevel = minLevel;
|
||||||
|
}
|
||||||
|
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
} while (result->NextRow());
|
} while (result->NextRow());
|
||||||
|
|
|
||||||
|
|
@ -20556,7 +20556,16 @@ float Player::GetReputationPriceDiscount( Creature const* pCreature ) const
|
||||||
return 1.0f - 0.05f* (rank - REP_NEUTRAL);
|
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 racemask = getRaceMask();
|
||||||
uint32 classmask = getClassMask();
|
uint32 classmask = getClassMask();
|
||||||
|
|
@ -20565,16 +20574,42 @@ bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const
|
||||||
if (bounds.first==bounds.second)
|
if (bounds.first==bounds.second)
|
||||||
return true;
|
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
|
// skip wrong race skills
|
||||||
if (_spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0)
|
if (abilityEntry->racemask && (abilityEntry->racemask & racemask) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// skip wrong class skills
|
// skip wrong class skills
|
||||||
if (_spell_idx->second->classmask && (_spell_idx->second->classmask & classmask) == 0)
|
if (abilityEntry->classmask && (abilityEntry->classmask & classmask) == 0)
|
||||||
continue;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1576,7 +1576,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
bool HasSpell(uint32 spell) const;
|
bool HasSpell(uint32 spell) const;
|
||||||
bool HasActiveSpell(uint32 spell) const; // show in spellbook
|
bool HasActiveSpell(uint32 spell) const; // show in spellbook
|
||||||
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
|
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
|
||||||
bool IsSpellFitByClassAndRace( uint32 spell_id ) const;
|
bool IsSpellFitByClassAndRace(uint32 spell_id, uint32* pReqlevel = NULL) const;
|
||||||
bool IsNeedCastPassiveLikeSpellAtLearn(SpellEntry const* spellInfo) const;
|
bool IsNeedCastPassiveLikeSpellAtLearn(SpellEntry const* spellInfo) const;
|
||||||
bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index) const;
|
bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2426,6 +2426,42 @@ bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId)
|
||||||
return IsPrimaryProfessionSkill(skill);
|
return IsPrimaryProfessionSkill(skill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 SpellMgr::GetProfessionSpellMinLevel(uint32 spellId)
|
||||||
|
{
|
||||||
|
uint32 s2l[8][3] =
|
||||||
|
{ // 0 - gather 1 - non-gather 2 - fish
|
||||||
|
/*0*/ { 0, 5, 5 },
|
||||||
|
/*1*/ { 0, 5, 5 },
|
||||||
|
/*2*/ { 0, 10, 10 },
|
||||||
|
/*3*/ { 10, 20, 10 },
|
||||||
|
/*4*/ { 25, 35, 10 },
|
||||||
|
/*5*/ { 40, 50, 10 },
|
||||||
|
/*6*/ { 55, 65, 10 },
|
||||||
|
/*7*/ { 75, 75, 10 },
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32 rank = GetSpellRank(spellId);
|
||||||
|
if (rank >= 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
SkillLineAbilityMapBounds bounds = GetSkillLineAbilityMapBounds(spellId);
|
||||||
|
if (bounds.first == bounds.second)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (bounds.first->second->skillId)
|
||||||
|
{
|
||||||
|
case SKILL_FISHING:
|
||||||
|
return s2l[rank][2];
|
||||||
|
case SKILL_HERBALISM:
|
||||||
|
case SKILL_MINING:
|
||||||
|
case SKILL_SKINNING:
|
||||||
|
return s2l[rank][0];
|
||||||
|
default:
|
||||||
|
return s2l[rank][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const
|
bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const
|
||||||
{
|
{
|
||||||
return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1;
|
return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1;
|
||||||
|
|
@ -3931,6 +3967,33 @@ void SpellMgr::LoadSkillLineAbilityMap()
|
||||||
sLog.outString(">> Loaded %u SkillLineAbility MultiMap Data", count);
|
sLog.outString(">> Loaded %u SkillLineAbility MultiMap Data", count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpellMgr::LoadSkillRaceClassInfoMap()
|
||||||
|
{
|
||||||
|
mSkillRaceClassInfoMap.clear();
|
||||||
|
|
||||||
|
barGoLink bar( (int)sSkillRaceClassInfoStore.GetNumRows() );
|
||||||
|
uint32 count = 0;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < sSkillRaceClassInfoStore.GetNumRows(); ++i)
|
||||||
|
{
|
||||||
|
bar.step();
|
||||||
|
SkillRaceClassInfoEntry const *skillRCInfo = sSkillRaceClassInfoStore.LookupEntry(i);
|
||||||
|
if (!skillRCInfo)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// not all skills really listed in ability skills list
|
||||||
|
if (!sSkillLineStore.LookupEntry(skillRCInfo->skillId))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mSkillRaceClassInfoMap.insert(SkillRaceClassInfoMap::value_type(skillRCInfo->skillId,skillRCInfo));
|
||||||
|
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
sLog.outString();
|
||||||
|
sLog.outString(">> Loaded %u SkillRaceClassInfo MultiMap Data", count);
|
||||||
|
}
|
||||||
|
|
||||||
void SpellMgr::CheckUsedSpells(char const* table)
|
void SpellMgr::CheckUsedSpells(char const* table)
|
||||||
{
|
{
|
||||||
uint32 countSpells = 0;
|
uint32 countSpells = 0;
|
||||||
|
|
|
||||||
|
|
@ -802,6 +802,9 @@ typedef std::pair<SpellLearnSpellMap::const_iterator,SpellLearnSpellMap::const_i
|
||||||
typedef std::multimap<uint32, SkillLineAbilityEntry const*> SkillLineAbilityMap;
|
typedef std::multimap<uint32, SkillLineAbilityEntry const*> SkillLineAbilityMap;
|
||||||
typedef std::pair<SkillLineAbilityMap::const_iterator,SkillLineAbilityMap::const_iterator> SkillLineAbilityMapBounds;
|
typedef std::pair<SkillLineAbilityMap::const_iterator,SkillLineAbilityMap::const_iterator> SkillLineAbilityMapBounds;
|
||||||
|
|
||||||
|
typedef std::multimap<uint32, SkillRaceClassInfoEntry const*> SkillRaceClassInfoMap;
|
||||||
|
typedef std::pair<SkillRaceClassInfoMap::const_iterator,SkillRaceClassInfoMap::const_iterator> SkillRaceClassInfoMapBounds;
|
||||||
|
|
||||||
typedef std::multimap<uint32, uint32> PetLevelupSpellSet;
|
typedef std::multimap<uint32, uint32> PetLevelupSpellSet;
|
||||||
typedef std::map<uint32, PetLevelupSpellSet> PetLevelupSpellMap;
|
typedef std::map<uint32, PetLevelupSpellSet> PetLevelupSpellMap;
|
||||||
|
|
||||||
|
|
@ -1047,6 +1050,7 @@ class SpellMgr
|
||||||
static bool IsProfessionSpell(uint32 spellId);
|
static bool IsProfessionSpell(uint32 spellId);
|
||||||
static bool IsPrimaryProfessionSpell(uint32 spellId);
|
static bool IsPrimaryProfessionSpell(uint32 spellId);
|
||||||
bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const;
|
bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const;
|
||||||
|
uint32 GetProfessionSpellMinLevel(uint32 spellId);
|
||||||
|
|
||||||
bool IsSkillBonusSpell(uint32 spellId) const;
|
bool IsSkillBonusSpell(uint32 spellId) const;
|
||||||
|
|
||||||
|
|
@ -1065,6 +1069,11 @@ class SpellMgr
|
||||||
return mSkillLineAbilityMap.equal_range(spell_id);
|
return mSkillLineAbilityMap.equal_range(spell_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkillRaceClassInfoMapBounds GetSkillRaceClassInfoMapBounds(uint32 skill_id) const
|
||||||
|
{
|
||||||
|
return mSkillRaceClassInfoMap.equal_range(skill_id);
|
||||||
|
}
|
||||||
|
|
||||||
PetAura const* GetPetAura(uint32 spell_id, SpellEffectIndex eff)
|
PetAura const* GetPetAura(uint32 spell_id, SpellEffectIndex eff)
|
||||||
{
|
{
|
||||||
SpellPetAuraMap::const_iterator itr = mSpellPetAuraMap.find((spell_id<<8) + eff);
|
SpellPetAuraMap::const_iterator itr = mSpellPetAuraMap.find((spell_id<<8) + eff);
|
||||||
|
|
@ -1140,6 +1149,7 @@ class SpellMgr
|
||||||
void LoadSpellTargetPositions();
|
void LoadSpellTargetPositions();
|
||||||
void LoadSpellThreats();
|
void LoadSpellThreats();
|
||||||
void LoadSkillLineAbilityMap();
|
void LoadSkillLineAbilityMap();
|
||||||
|
void LoadSkillRaceClassInfoMap();
|
||||||
void LoadSpellPetAuras();
|
void LoadSpellPetAuras();
|
||||||
void LoadPetLevelupSpellMap();
|
void LoadPetLevelupSpellMap();
|
||||||
void LoadPetDefaultSpells();
|
void LoadPetDefaultSpells();
|
||||||
|
|
@ -1160,6 +1170,7 @@ class SpellMgr
|
||||||
SpellProcItemEnchantMap mSpellProcItemEnchantMap;
|
SpellProcItemEnchantMap mSpellProcItemEnchantMap;
|
||||||
SpellBonusMap mSpellBonusMap;
|
SpellBonusMap mSpellBonusMap;
|
||||||
SkillLineAbilityMap mSkillLineAbilityMap;
|
SkillLineAbilityMap mSkillLineAbilityMap;
|
||||||
|
SkillRaceClassInfoMap mSkillRaceClassInfoMap;
|
||||||
SpellPetAuraMap mSpellPetAuraMap;
|
SpellPetAuraMap mSpellPetAuraMap;
|
||||||
PetLevelupSpellMap mPetLevelupSpellMap;
|
PetLevelupSpellMap mPetLevelupSpellMap;
|
||||||
PetDefaultSpellsMap mPetDefaultSpellsMap; // only spells not listed in related mPetLevelupSpellMap entry
|
PetDefaultSpellsMap mPetDefaultSpellsMap; // only spells not listed in related mPetLevelupSpellMap entry
|
||||||
|
|
|
||||||
|
|
@ -949,9 +949,12 @@ void World::SetInitialWorldSettings()
|
||||||
sLog.outString( "Loading InstanceTemplate..." );
|
sLog.outString( "Loading InstanceTemplate..." );
|
||||||
sObjectMgr.LoadInstanceTemplate();
|
sObjectMgr.LoadInstanceTemplate();
|
||||||
|
|
||||||
sLog.outString( "Loading SkillLineAbilityMultiMap Data..." );
|
sLog.outString("Loading SkillLineAbilityMultiMap Data...");
|
||||||
sSpellMgr.LoadSkillLineAbilityMap();
|
sSpellMgr.LoadSkillLineAbilityMap();
|
||||||
|
|
||||||
|
sLog.outString("Loading SkillRaceClassInfoMultiMap Data...");
|
||||||
|
sSpellMgr.LoadSkillRaceClassInfoMap();
|
||||||
|
|
||||||
///- Clean up and pack instances
|
///- Clean up and pack instances
|
||||||
sLog.outString( "Cleaning up instances..." );
|
sLog.outString( "Cleaning up instances..." );
|
||||||
sMapPersistentStateMgr.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
|
sMapPersistentStateMgr.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "11586"
|
#define REVISION_NR "11587"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue