diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 1e6172b74..c8efc8367 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -3848,7 +3848,7 @@ bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/) if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) continue; - m_session->GetPlayer()->learnSpell(skillLine->spellId); + m_session->GetPlayer()->learnSpell(skillLine->spellId,false); } } } @@ -3919,7 +3919,7 @@ bool ChatHandler::HandleLearnAllRecipesCommand(const char* args) continue; if( !target->HasSpell(spellInfo->Id) ) - m_session->GetPlayer()->learnSpell(skillLine->spellId); + m_session->GetPlayer()->learnSpell(skillLine->spellId,false); } uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index cd011e16a..8ab22b392 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1638,7 +1638,7 @@ bool ChatHandler::HandleLearnAllCommand(const char* /*args*/) continue; } - m_session->GetPlayer()->learnSpell(spell); + m_session->GetPlayer()->learnSpell(spell,false); } SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS); @@ -1678,7 +1678,7 @@ bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/) continue; } - m_session->GetPlayer()->learnSpell(spell); + m_session->GetPlayer()->learnSpell(spell,false); } SendSysMessage(LANG_LEARNING_GM_SKILLS); @@ -1726,7 +1726,7 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) if(!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) continue; - m_session->GetPlayer()->learnSpell(i); + m_session->GetPlayer()->learnSpell(i,false); } SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); @@ -1738,7 +1738,7 @@ static void learnAllHighRanks(Player* player, uint32 spellid) SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); for(SpellChainMapNext::const_iterator itr = nextMap.lower_bound(spellid); itr != nextMap.upper_bound(spellid); ++itr) { - player->learnSpell(itr->second); + player->learnSpell(itr->second,false); learnAllHighRanks(player,itr->second); } } @@ -1781,7 +1781,7 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) continue; // learn highest rank of talent - player->learnSpell(spellid); + player->learnSpell(spellid,false); // and learn all non-talent spell ranks (recursive by tree) learnAllHighRanks(player,spellid); @@ -1795,7 +1795,7 @@ bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) { // skipping UNIVERSAL language (0) for(int i = 1; i < LANGUAGES_COUNT; ++i) - m_session->GetPlayer()->learnSpell(lang_description[i].spell_id); + m_session->GetPlayer()->learnSpell(lang_description[i].spell_id,false); SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); return true; @@ -1869,7 +1869,7 @@ bool ChatHandler::HandleLearnCommand(const char* args) return false; } - targetPlayer->learnSpell(spell); + targetPlayer->learnSpell(spell,false); return true; } diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 5e3580088..db021e0ed 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -254,7 +254,7 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) data << uint64(_player->GetGUID()) << uint32(0x016A); SendPacket(&data); - _player->learnSpell(spellId); + _player->learnSpell(spellId,false); } WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12); diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 450779658..b8182544f 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1479,7 +1479,7 @@ void Pet::InitPetCreateSpells() if(owner->GetTypeId() == TYPEID_PLAYER && !((Player*)owner)->HasSpell(learn_spellproto->Id)) { if(IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right - ((Player*)owner)->learnSpell(learn_spellproto->Id); + ((Player*)owner)->learnSpell(learn_spellproto->Id,false); else AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id); } @@ -1513,7 +1513,7 @@ void Pet::CheckLearning(uint32 spellid) if(urand(0, 100) < 10) { - ((Player*)owner)->learnSpell(itr->second); + ((Player*)owner)->learnSpell(itr->second,false); m_teachspells.erase(itr); } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index da8adc693..a0321ff83 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2541,7 +2541,7 @@ void Player::AddNewMailDeliverTime(time_t deliver_time) } } -bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled) +bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); if (!spellInfo) @@ -2574,29 +2574,78 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; + bool dependent_set = false; bool disabled_case = false; bool superceded_old = false; PlayerSpellMap::iterator itr = m_spells.find(spell_id); if (itr != m_spells.end()) { + uint32 next_active_spell_id = 0; + // fix activate state for non-stackable low rank (and find next spell for !active case) + if(!SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0) + { + SpellChainMapNext const& nextMap = spellmgr.GetSpellChainNext(); + for(SpellChainMapNext::const_iterator next_itr = nextMap.lower_bound(spell_id); next_itr != nextMap.upper_bound(spell_id); ++next_itr) + { + if(HasSpell(next_itr->second)) + { + // high rank already known so this must !active + active = false; + next_active_spell_id = next_itr->second; + break; + } + } + } + + // not do anything if already known in expected state + if(itr->second->state != PLAYERSPELL_REMOVED && itr->second->active == active && + itr->second->dependent == dependent && itr->second->disabled == disabled) + return false; + + // dependent spell known as not dependent, overwrite state + if (itr->second->state != PLAYERSPELL_REMOVED && !itr->second->dependent && dependent) + { + itr->second->dependent = dependent; + if (itr->second->state != PLAYERSPELL_NEW) + itr->second->state = PLAYERSPELL_CHANGED; + dependent_set = true; + } + // update active state for known spell if(itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled) { itr->second->active = active; // !IsInWorld() && !learning == explicitly load from DB and then exist in it already and set correctly - if(!IsInWorld() && !learning) + if(!IsInWorld() && !learning && !dependent_set) itr->second->state = PLAYERSPELL_UNCHANGED; else if(itr->second->state != PLAYERSPELL_NEW) itr->second->state = PLAYERSPELL_CHANGED; - if(!active) + if(active) { - WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint16(spell_id); - GetSession()->SendPacket(&data); + if (IsPassiveSpell(spell_id) && IsNeedCastPassiveSpellAtLearn(spellInfo)) + CastSpell (this,spell_id,true); } + else if(IsInWorld()) + { + if(next_active_spell_id) + { + // update spell ranks in spellbook and action bar + WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); + data << uint16(spell_id); + data << uint16(next_active_spell_id); + GetSession()->SendPacket( &data ); + } + else + { + WorldPacket data(SMSG_REMOVED_SPELL, 4); + data << uint16(spell_id); + GetSession()->SendPacket(&data); + } + } + return active; // learn (show in spell book if active now) } @@ -2625,7 +2674,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled default: // known not saved yet spell (new or modified) { // can be in case spell loading but learned at some previous spell loading - if(!IsInWorld() && !learning) + if(!IsInWorld() && !learning && !dependent_set) itr->second->state = PLAYERSPELL_UNCHANGED; return false; @@ -2658,16 +2707,17 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled // non talent spell: learn low ranks (recursive call) else if(uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id)) { - if(!IsInWorld()) // at spells loading, no output, but allow save - addSpell(prev_spell,active,true,disabled); + if(!IsInWorld() || disabled) // at spells loading, no output, but allow save + addSpell(prev_spell,active,true,true,disabled); else // at normal learning - learnSpell(prev_spell); + learnSpell(prev_spell,true); } PlayerSpell *newspell = new PlayerSpell; - newspell->active = active; - newspell->state = state; - newspell->disabled = disabled; + newspell->state = state; + newspell->active = active; + newspell->dependent = dependent; + newspell->disabled = disabled; // replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible if(newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0) @@ -2694,7 +2744,8 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled // mark old spell as disable (SMSG_SUPERCEDED_SPELL replace it in client by new) itr->second->active = false; - itr->second->state = PLAYERSPELL_CHANGED; + if(itr->second->state != PLAYERSPELL_NEW) + itr->second->state = PLAYERSPELL_CHANGED; superceded_old = true; // new spell replace old in action bars and spell book. } else if(spellmgr.IsHighRankOfSpell(itr->first,spell_id)) @@ -2736,26 +2787,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled // also cast passive spells (including all talents without SPELL_EFFECT_LEARN_SPELL) with additional checks else if (IsPassiveSpell(spell_id)) { - bool need_cast = false; - - switch(spell_id) - { - // some spells not have stance data expacted cast at form change or present - case 5420: need_cast = (m_form == FORM_TREE); break; - case 5419: need_cast = (m_form == FORM_TRAVEL); break; - case 7376: need_cast = (m_form == FORM_DEFENSIVESTANCE); break; - case 7381: need_cast = (m_form == FORM_BERSERKERSTANCE); break; - case 21156: need_cast = (m_form == FORM_BATTLESTANCE); break; - case 21178: need_cast = (m_form == FORM_BEAR || m_form == FORM_DIREBEAR); break; - case 33948: need_cast = (m_form == FORM_FLIGHT); break; - case 34764: need_cast = (m_form == FORM_FLIGHT); break; - case 40121: need_cast = (m_form == FORM_FLIGHT_EPIC); break; - case 40122: need_cast = (m_form == FORM_FLIGHT_EPIC); break; - // another spells have proper stance data - default: need_cast = !spellInfo->Stances || m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))); break; - } - //Check CasterAuraStates - if (need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState)))) + if(IsNeedCastPassiveSpellAtLearn(spellInfo)) CastSpell(this, spell_id, true); } else if( IsSpellHaveEffect(spellInfo,SPELL_EFFECT_SKILL_STEP) ) @@ -2840,9 +2872,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled if(!itr->second.autoLearned) { if(!IsInWorld() || !itr->second.active) // at spells loading, no output, but allow save - addSpell(itr->second.spell,itr->second.active,true,false); + addSpell(itr->second.spell,itr->second.active,true,true,false); else // at normal learning - learnSpell(itr->second.spell); + learnSpell(itr->second.spell,true); } } @@ -2856,14 +2888,39 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool disabled return active && !disabled && !superceded_old; } -void Player::learnSpell(uint32 spell_id) +bool Player::IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const +{ + bool need_cast = false; + + switch(spellInfo->Id) + { + // some spells not have stance data expacted cast at form change or present + case 5420: need_cast = (m_form == FORM_TREE); break; + case 5419: need_cast = (m_form == FORM_TRAVEL); break; + case 7376: need_cast = (m_form == FORM_DEFENSIVESTANCE); break; + case 7381: need_cast = (m_form == FORM_BERSERKERSTANCE); break; + case 21156: need_cast = (m_form == FORM_BATTLESTANCE); break; + case 21178: need_cast = (m_form == FORM_BEAR || m_form == FORM_DIREBEAR); break; + case 33948: need_cast = (m_form == FORM_FLIGHT); break; + case 34764: need_cast = (m_form == FORM_FLIGHT); break; + case 40121: need_cast = (m_form == FORM_FLIGHT_EPIC); break; + case 40122: need_cast = (m_form == FORM_FLIGHT_EPIC); break; + // another spells have proper stance data + default: need_cast = !spellInfo->Stances || m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))); break; + } + + //Check CasterAuraStates + return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState))); +} + +void Player::learnSpell(uint32 spell_id, bool dependent) { PlayerSpellMap::iterator itr = m_spells.find(spell_id); bool disabled = (itr != m_spells.end()) ? itr->second->disabled : false; bool active = disabled ? itr->second->active : true; - bool learning = addSpell(spell_id,active,true,false); + bool learning = addSpell(spell_id,active,true,dependent,false); // learn all disabled higher ranks (recursive) if(disabled) @@ -2873,7 +2930,7 @@ void Player::learnSpell(uint32 spell_id) { PlayerSpellMap::iterator iter = m_spells.find(i->second); if (iter != m_spells.end() && iter->second->disabled) - learnSpell(i->second); + learnSpell(i->second,false); } } @@ -2901,10 +2958,8 @@ void Player::removeSpell(uint32 spell_id, bool disabled) if(HasSpell(itr2->second) && !GetTalentSpellPos(itr2->second)) removeSpell(itr2->second,disabled); - // removing - WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint16(spell_id); - GetSession()->SendPacket(&data); + bool cur_active = itr->second->active; + bool cur_dependent = itr->second->dependent; if (disabled) { @@ -3017,7 +3072,54 @@ void Player::removeSpell(uint32 spell_id, bool disabled) for(SpellLearnSpellMap::const_iterator itr2 = spell_begin; itr2 != spell_end; ++itr2) removeSpell(itr2->second.spell, disabled); - // TODO: recast if need lesser ranks spell for passive with IsPassiveSpellStackableWithRanks + // activate lesser rank in spellbook/action bar, and cast it if need + bool prev_activate = false; + + if(uint32 prev_id = spellmgr.GetPrevSpellInChain (spell_id)) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); + + // if talent then lesser rank also talen and need learn + if(talentCosts) + learnSpell (prev_id,false); + // if ranked non-stackable spell: need activate lesser rank and update dendence state + else if(cur_active && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0) + { + // need manually update dependence state (learn spell ignore like attempts) + PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id); + if (prev_itr != m_spells.end()) + { + if(prev_itr->second->dependent != cur_dependent) + { + prev_itr->second->dependent = cur_dependent; + if(prev_itr->second->state != PLAYERSPELL_NEW) + prev_itr->second->state = PLAYERSPELL_CHANGED; + } + + // now re-learn if need re-activate + if(cur_active && !prev_itr->second->active) + { + if(addSpell(prev_id,true,false,prev_itr->second->dependent,prev_itr->second->disabled)) + { + // downgrade spell ranks in spellbook and action bar + WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); + data << uint16(spell_id); + data << uint16(prev_id); + GetSession()->SendPacket( &data ); + prev_activate = true; + } + } + } + } + } + + // remove from spell book if not replaced by lesser rank + if(!prev_activate) + { + WorldPacket data(SMSG_REMOVED_SPELL, 4); + data << uint16(spell_id); + GetSession()->SendPacket(&data); + } } void Player::RemoveArenaSpellCooldowns() @@ -4708,7 +4810,7 @@ bool Player::UpdateCraftSkill(uint32 spellid) if(spellEntry && spellEntry->Mechanic==MECHANIC_DISCOVERY) { if(uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this)) - learnSpell(discoveredSpell); + learnSpell(discoveredSpell,false); } uint32 craft_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_CRAFTING); @@ -15148,7 +15250,7 @@ void Player::_LoadSpells(QueryResult *result) { Field *fields = result->Fetch(); - addSpell(fields[0].GetUInt16(), fields[1].GetBool(), false, fields[2].GetBool()); + addSpell(fields[0].GetUInt16(), fields[1].GetBool(), false, false, fields[2].GetBool()); } while( result->NextRow() ); @@ -15910,7 +16012,9 @@ void Player::_SaveSpells() ++next; if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED) CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u' and spell = '%u'", GetGUIDLow(), itr->first); - if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED) + + // add only changed/new not dependent spells + if (!itr->second->dependent && (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED)) CharacterDatabase.PExecute("INSERT INTO character_spell (guid,spell,active,disabled) VALUES ('%u', '%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0); if (itr->second->state == PLAYERSPELL_REMOVED) @@ -18129,9 +18233,9 @@ void Player::learnDefaultSpells() uint32 tspell = *itr; sLog.outDebug("PLAYER (Class: %u Race: %u): Adding initial spell, id = %u",uint32(getClass()),uint32(getRace()), tspell); if(!IsInWorld()) // will send in INITIAL_SPELLS in list anyway at map add - addSpell(tspell,true,true,false); + addSpell(tspell,true,true,true,false); else // but send in normal spell in game learn case - learnSpell(tspell); + learnSpell(tspell,true); } } @@ -18241,8 +18345,8 @@ void Player::learnSkillRewardedSpells(uint32 skill_id ) if (sSpellStore.LookupEntry(pAbility->spellId)) { - // Ok need learn spell - learnSpell(pAbility->spellId); + // Ok need learn dependent spell + learnSpell(pAbility->spellId,true); } } } diff --git a/src/game/Player.h b/src/game/Player.h index 15895daf5..917d9e1cc 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -85,8 +85,9 @@ enum PlayerSpellState struct PlayerSpell { PlayerSpellState state : 8; - bool active : 1; - bool disabled : 1; + bool active : 1; // show in spellbook + bool dependent : 1; // learned as result another spell learn, skill grow, quest reward, etc + bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks }; // Spell modifier (used for modify other spells) @@ -1477,11 +1478,12 @@ class MANGOS_DLL_SPEC Player : public Unit bool HasSpell(uint32 spell) const; TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const; bool IsSpellFitByClassAndRace( uint32 spell_id ) const; + bool IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const; void SendProficiency(uint8 pr1, uint32 pr2); void SendInitialSpells(); - bool addSpell(uint32 spell_id, bool active, bool learning, bool disabled); - void learnSpell(uint32 spell_id); + bool addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled); + void learnSpell(uint32 spell_id, bool dependent); void removeSpell(uint32 spell_id, bool disabled = false); void resetSpells(); void learnDefaultSpells(); @@ -1768,7 +1770,7 @@ class MANGOS_DLL_SPEC Player : public Unit int16 GetSkillPermBonusValue(uint32 skill) const; int16 GetSkillTempBonusValue(uint32 skill) const; bool HasSkill(uint32 skill) const; - void learnSkillRewardedSpells( uint32 id ); + void learnSkillRewardedSpells(uint32 id); void learnSkillRewardedSpells(); void SetDontMove(bool dontMove); diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index c5d190e7c..8f854dd52 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -127,7 +127,7 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) return; // learn! (other talent ranks will unlearned at learning) - GetPlayer( )->learnSpell(spellid); + GetPlayer( )->learnSpell(spellid,false); sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); // update free talent points diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 4ce2ada80..b8b4657a0 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3345,7 +3345,7 @@ void Spell::EffectLearnSpell(uint32 i) Player *player = (Player*)unitTarget; uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i]; - player->learnSpell(spellToLearn); + player->learnSpell(spellToLearn,false); sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() ); } @@ -4866,7 +4866,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) // learn random explicit discovery recipe (if any) if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player)) - player->learnSpell(discoveredSpell); + player->learnSpell(discoveredSpell,false); return; } } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7e270e19c..7414c20b8 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1016,28 +1016,38 @@ bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellI bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo) { + if(IsPassiveSpell(spellInfo->Id)) // ranked passive spell + return false; if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH) return false; if(IsProfessionOrRidingSpell(spellInfo->Id)) return false; + if(spellmgr.IsSkillBonusSpell(spellInfo->Id)) + return false; + // All stance spells. if any better way, change it. for (int i = 0; i < 3; i++) { - // Paladin aura Spell - if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN - && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID) - return false; - // Druid form Spell - if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID - && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA - && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) - return false; - // Rogue Stealth - if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE - && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA - && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) - return false; + switch(spellInfo->SpellFamilyName) + { + case SPELLFAMILY_PALADIN: + // Paladin aura Spell + if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID) + return false; + break; + case SPELLFAMILY_DRUID: + // Druid form Spell + if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA && + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) + return false; + break; + case SPELLFAMILY_ROGUE: + // Rogue Stealth + if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA && + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) + return false; + } } return true; } @@ -1450,6 +1460,24 @@ bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1; } +bool SpellMgr::IsSkillBonusSpell(uint32 spellId) const +{ + SkillLineAbilityMap::const_iterator lower = GetBeginSkillLineAbilityMap(spellId); + SkillLineAbilityMap::const_iterator upper = GetEndSkillLineAbilityMap(spellId); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + SkillLineAbilityEntry const *pAbility = _spell_idx->second; + if (!pAbility || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL) + continue; + + if(pAbility->req_skill_value > 0) + return true; + } + + return false; +} + SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const { // ignore passive spells diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 62f73f9b7..c09abbacd 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -897,6 +897,9 @@ class SpellMgr static bool IsPrimaryProfessionSpell(uint32 spellId); bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const; + bool IsSkillBonusSpell(uint32 spellId) const; + + // Spell script targets SpellScriptTarget::const_iterator GetBeginSpellScriptTarget(uint32 spell_id) const {