mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +00:00
Not store dependent spells in character_spell
* Mark spells learned in result character creating, another spell learning, skill grow, quest reward as dependent and not store its in `character_spell`. * Prevent re-learning known spell in expected state * Prevent re-learning low rank spell as active if higher rank known. * New type of non-stacked ranked spells check: skill dependent spell bonuses. * Activate (show propetly and cast if need) lesser spell rank for non-stackable in spellbooks spells at unlearn high rank
This commit is contained in:
parent
4b5aba18f8
commit
bbf8fd0742
10 changed files with 222 additions and 85 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue