[11857] Fix sent level in trainer spell list - this fixes problems especially with druid trainers

* This allows to really  overwrite required level for spells
* Adds proper checks when buying
* Fixes default level requirement

Signed-off-by: Schmoozerd <schmoozerd@scriptdev2.com>
This commit is contained in:
Schmoozerd 2011-12-04 19:17:00 +01:00
parent 20e2dddd6c
commit adfa88d236
6 changed files with 31 additions and 19 deletions

View file

@ -362,10 +362,10 @@ typedef std::list<VendorItemCount> VendorItemCounts;
struct TrainerSpell
{
TrainerSpell() : spell(0), spellCost(0), reqSkill(0), reqSkillValue(0), reqLevel(0), learnedSpell(0) {}
TrainerSpell() : spell(0), spellCost(0), reqSkill(0), reqSkillValue(0), reqLevel(0), learnedSpell(0), isProvidedReqLevel(false) {}
TrainerSpell(uint32 _spell, uint32 _spellCost, uint32 _reqSkill, uint32 _reqSkillValue, uint32 _reqLevel, uint32 _learnedspell)
: spell(_spell), spellCost(_spellCost), reqSkill(_reqSkill), reqSkillValue(_reqSkillValue), reqLevel(_reqLevel), learnedSpell(_learnedspell)
TrainerSpell(uint32 _spell, uint32 _spellCost, uint32 _reqSkill, uint32 _reqSkillValue, uint32 _reqLevel, uint32 _learnedspell, bool _isProvidedReqLevel)
: spell(_spell), spellCost(_spellCost), reqSkill(_reqSkill), reqSkillValue(_reqSkillValue), reqLevel(_reqLevel), learnedSpell(_learnedspell), isProvidedReqLevel(_isProvidedReqLevel)
{}
uint32 spell;
@ -374,6 +374,7 @@ struct TrainerSpell
uint32 reqSkillValue;
uint32 reqLevel;
uint32 learnedSpell;
bool isProvidedReqLevel;
// helpers
bool IsCastable() const { return learnedSpell != spell; }

View file

@ -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, uint32 skillReqLevel)
static void SendTrainerSpellHelper(WorldPacket& data, TrainerSpell const* tSpell, TrainerSpellState state, float fDiscountMod, bool can_learn_primary_prof, uint32 reqLevel)
{
bool primary_prof_first_rank = sSpellMgr.IsPrimaryProfessionFirstRankSpell(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);
// 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 << uint8(skillReqLevel ? skillReqLevel : tSpell->reqLevel);
data << uint8(reqLevel);
data << uint32(tSpell->reqSkill);
data << uint32(tSpell->reqSkillValue);
data << uint32(!tSpell->IsCastable() && chain_node ? (chain_node->prev ? chain_node->prev : chain_node->req) : 0);
@ -193,13 +193,15 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
{
TrainerSpell const* tSpell = &itr->second;
uint32 skillReqLevel = 0;
if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell, &skillReqLevel))
uint32 reqLevel = 0;
if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell, &reqLevel))
continue;
TrainerSpellState state = _player->GetTrainerSpellState(tSpell);
reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel);
SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof, skillReqLevel);
TrainerSpellState state = _player->GetTrainerSpellState(tSpell, reqLevel);
SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof, reqLevel);
++count;
}
@ -211,13 +213,15 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle)
{
TrainerSpell const* tSpell = &itr->second;
uint32 skillReqLevel = 0;
if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell, &skillReqLevel))
uint32 reqLevel = 0;
if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell, &reqLevel))
continue;
TrainerSpellState state = _player->GetTrainerSpellState(tSpell);
reqLevel = tSpell->isProvidedReqLevel ? tSpell->reqLevel : std::max(reqLevel, tSpell->reqLevel);
SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof, skillReqLevel);
TrainerSpellState state = _player->GetTrainerSpellState(tSpell, reqLevel);
SendTrainerSpellHelper(data, tSpell, state, fDiscountMod, can_learn_primary_prof, reqLevel);
++count;
}
@ -270,7 +274,12 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data )
return;
// can't be learn, cheat? Or double learn with lags...
if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN)
uint32 reqLevel = 0;
if(!_player->IsSpellFitByClassAndRace(trainer_spell->learnedSpell, &reqLevel))
return;
reqLevel = trainer_spell->isProvidedReqLevel ? trainer_spell->reqLevel : std::max(reqLevel, trainer_spell->reqLevel);
if (_player->GetTrainerSpellState(trainer_spell, reqLevel) != TRAINER_SPELL_GREEN)
return;
// apply reputation discount

View file

@ -8269,6 +8269,8 @@ void ObjectMgr::LoadTrainers(char const* tableName, bool isTemplates)
trainerSpell.reqSkillValue = fields[4].GetUInt32();
trainerSpell.reqLevel = fields[5].GetUInt32();
trainerSpell.isProvidedReqLevel = trainerSpell.reqLevel > 0;
// calculate learned spell for profession case when stored cast-spell
trainerSpell.learnedSpell = spell;
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
@ -8290,7 +8292,7 @@ void ObjectMgr::LoadTrainers(char const* tableName, bool isTemplates)
}
// already checked as valid spell so exist.
SpellEntry const *learnSpellinfo = sSpellStore.LookupEntry(trainerSpell.learnedSpell);
SpellEntry const* learnSpellinfo = sSpellStore.LookupEntry(trainerSpell.learnedSpell);
if (SpellMgr::IsProfessionSpell(trainerSpell.learnedSpell))
{
data.trainerType = 2;

View file

@ -4003,7 +4003,7 @@ bool Player::HasActiveSpell(uint32 spell) const
itr->second.active && !itr->second.disabled);
}
TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell) const
TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell, uint32 reqLevel) const
{
if (!trainer_spell)
return TRAINER_SPELL_RED;
@ -4023,7 +4023,7 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell
// check level requirement
if (!prof || GetSession()->GetSecurity() < AccountTypes(sWorld.getConfig(CONFIG_UINT32_TRADE_SKILL_GMIGNORE_LEVEL)))
if (getLevel() < trainer_spell->reqLevel)
if (getLevel() < reqLevel)
return TRAINER_SPELL_RED;
if(SpellChainNode const* spell_chain = sSpellMgr.GetSpellChainNode(trainer_spell->learnedSpell))

View file

@ -1564,7 +1564,7 @@ class MANGOS_DLL_SPEC Player : public Unit
bool HasSpell(uint32 spell) const;
bool HasActiveSpell(uint32 spell) const; // show in spellbook
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const;
TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell, uint32 reqLevel) const;
bool IsSpellFitByClassAndRace(uint32 spell_id, uint32* pReqlevel = NULL) const;
bool IsNeedCastPassiveLikeSpellAtLearn(SpellEntry const* spellInfo) const;
bool IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectIndex index) const;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "11856"
#define REVISION_NR "11857"
#endif // __REVISION_NR_H__