[7838] More fixes in pet's levelup spells.

* Fixed not updating levelup spells at warlock pet summon firsy time (overwriting by default original ranks in fact)
* Correctly upgrade/doungrade spell ranks in action bar.
* Fixed spell learning spam at warlock pet re-summon in some cases.

TODO: currently (before this commit and in it) PetSpellInitialize() called too oftern. Maybe possible cache update flag and do it one time somewhere in Pet::Update....
This commit is contained in:
VladimirMangos 2009-05-16 17:01:03 +04:00
parent 8cf9dc035b
commit 122c9c5785
6 changed files with 97 additions and 48 deletions

View file

@ -4792,13 +4792,10 @@ bool ChatHandler::HandleResetLevelCommand(const char * args)
player->InitTalentForLevel(); player->InitTalentForLevel();
player->SetUInt32Value(PLAYER_XP,0); player->SetUInt32Value(PLAYER_XP,0);
// reset level to summoned pet // reset level for pet
Pet* pet = player->GetPet(); if(Pet* pet = player->GetPet())
if(pet && pet->getPetType()==SUMMON_PET) pet->SynchronizeLevelWithOwner();
{
pet->InitStatsForLevel(1);
pet->InitTalentForLevel();
}
return true; return true;
} }

View file

@ -340,6 +340,8 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool
} }
} }
InitLevelupSpellsForLevel();
m_loading = false; m_loading = false;
SynchronizeLevelWithOwner(); SynchronizeLevelWithOwner();
@ -653,6 +655,9 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid)
for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
{ {
if(itr->second.state == PETSPELL_REMOVED)
continue;
if(IsPassiveSpell(itr->first)) if(IsPassiveSpell(itr->first))
continue; continue;
@ -746,6 +751,7 @@ void Pet::GivePetLevel(uint32 level)
return; return;
InitStatsForLevel(level); InitStatsForLevel(level);
InitLevelupSpellsForLevel();
InitTalentForLevel(); InitTalentForLevel();
} }
@ -994,9 +1000,6 @@ bool Pet::InitStatsForLevel(uint32 petlevel)
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i])); SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i]));
if(cinfo->family)
learnLevelupSpells();
UpdateAllStats(); UpdateAllStats();
SetHealth(GetMaxHealth()); SetHealth(GetMaxHealth());
@ -1118,7 +1121,7 @@ void Pet::_LoadSpells()
{ {
Field *fields = result->Fetch(); Field *fields = result->Fetch();
addSpell(fields[0].GetUInt32(), fields[1].GetUInt16(), PETSPELL_UNCHANGED); addSpell(fields[0].GetUInt32(), ActiveStates(fields[1].GetUInt16()), PETSPELL_UNCHANGED);
} }
while( result->NextRow() ); while( result->NextRow() );
@ -1284,7 +1287,7 @@ void Pet::_SaveAuras()
} }
} }
bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/) bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/)
{ {
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id);
if (!spellInfo) if (!spellInfo)
@ -1356,17 +1359,20 @@ bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState
// skip unknown ranks // skip unknown ranks
if(!HasSpell(rankSpellId)) if(!HasSpell(rankSpellId))
continue; continue;
removeSpell(rankSpellId); removeSpell(rankSpellId,false);
} }
} }
} }
else if(uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id)) else if(spellmgr.GetSpellRank(spell_id)!=0)
{ {
for (PetSpellMap::const_iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2) for (PetSpellMap::const_iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2)
{ {
if(itr2->second.state == PETSPELL_REMOVED) continue; if(itr2->second.state == PETSPELL_REMOVED) continue;
if(spellmgr.GetFirstSpellInChain(itr2->first) == chainstart) if( spellmgr.IsRankSpellDueToSpell(spellInfo,itr2->first) )
{
// replace by new high rank
if(spellmgr.IsHighRankOfSpell(spell_id,itr2->first))
{ {
newspell.active = itr2->second.active; newspell.active = itr2->second.active;
@ -1374,9 +1380,13 @@ bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState
ToggleAutocast(itr2->first, false); ToggleAutocast(itr2->first, false);
oldspell_id = itr2->first; oldspell_id = itr2->first;
unlearnSpell(itr2->first); unlearnSpell(itr2->first,false);
break; break;
} }
// ignore new lesser rank
else if(spellmgr.IsHighRankOfSpell(itr2->first,spell_id))
return false;
}
} }
} }
@ -1384,7 +1394,7 @@ bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState
if (IsPassiveSpell(spell_id)) if (IsPassiveSpell(spell_id))
CastSpell(this, spell_id, true); CastSpell(this, spell_id, true);
else if(state == PETSPELL_NEW) else
m_charmInfo->AddSpellToAB(oldspell_id, spell_id); m_charmInfo->AddSpellToAB(oldspell_id, spell_id);
if(newspell.active == ACT_ENABLED) if(newspell.active == ACT_ENABLED)
@ -1422,26 +1432,33 @@ bool Pet::learnSpell(uint32 spell_id)
return true; return true;
} }
void Pet::learnLevelupSpells() void Pet::InitLevelupSpellsForLevel()
{ {
PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family); uint32 family = GetCreatureInfo()->family;
if(!family)
return;
PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(family);
if(!levelupSpells) if(!levelupSpells)
return; return;
uint32 level = getLevel(); uint32 level = getLevel();
for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) // PetLevelupSpellSet ordered by levels, process in reversed order
for(PetLevelupSpellSet::const_reverse_iterator itr = levelupSpells->rbegin(); itr != levelupSpells->rend(); ++itr)
{ {
if(itr->first <= level) // will called first if level down
learnSpell(itr->second); if(itr->first > level)
unlearnSpell(itr->second,true); // will learn prev rank if any
// will called if level up
else else
unlearnSpell(itr->second); learnSpell(itr->second); // will unlearn prev rank if any
} }
} }
bool Pet::unlearnSpell(uint32 spell_id) bool Pet::unlearnSpell(uint32 spell_id, bool learn_prev)
{ {
if(removeSpell(spell_id)) if(removeSpell(spell_id,learn_prev))
{ {
if(GetOwner()->GetTypeId() == TYPEID_PLAYER) if(GetOwner()->GetTypeId() == TYPEID_PLAYER)
{ {
@ -1457,7 +1474,7 @@ bool Pet::unlearnSpell(uint32 spell_id)
return false; return false;
} }
bool Pet::removeSpell(uint32 spell_id) bool Pet::removeSpell(uint32 spell_id, bool learn_prev)
{ {
PetSpellMap::iterator itr = m_spells.find(spell_id); PetSpellMap::iterator itr = m_spells.find(spell_id);
if (itr == m_spells.end()) if (itr == m_spells.end())
@ -1485,6 +1502,27 @@ bool Pet::removeSpell(uint32 spell_id)
SetFreeTalentPoints(free_points > 0 ? free_points : 0); SetFreeTalentPoints(free_points > 0 ? free_points : 0);
} }
if (learn_prev)
{
if (uint32 prev_id = spellmgr.GetPrevSpellInChain (spell_id))
{
// replace to next spell
if(!talentCost && !IsPassiveSpell(prev_id))
m_charmInfo->AddSpellToAB(spell_id, prev_id);
learnSpell(prev_id);
}
else
{
m_charmInfo->AddSpellToAB(spell_id, 0);
// need update action bar for last removed rank
if (Unit* owner = GetOwner())
if (owner->GetTypeId() == TYPEID_PLAYER)
((Player*)owner)->PetSpellInitialize();
}
}
return true; return true;
} }
@ -1620,7 +1658,7 @@ bool Pet::resetTalents(bool no_cost)
// unlearn if first rank is talent or learned by talent // unlearn if first rank is talent or learned by talent
if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId)) if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId))
{ {
removeSpell(itr->first); removeSpell(itr->first,false);
itr = m_spells.begin(); itr = m_spells.begin();
continue; continue;
} }

View file

@ -69,7 +69,7 @@ enum PetSpellType
struct PetSpell struct PetSpell
{ {
uint16 active; ActiveStates active : 16;
PetSpellState state : 8; PetSpellState state : 8;
PetSpellType type : 8; PetSpellType type : 8;
@ -196,12 +196,12 @@ class Pet : public Creature
void _LoadSpells(); void _LoadSpells();
void _SaveSpells(); void _SaveSpells();
bool addSpell(uint32 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL); bool addSpell(uint32 spell_id,ActiveStates active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL);
bool learnSpell(uint32 spell_id); bool learnSpell(uint32 spell_id);
void learnSpellHighRank(uint32 spellid); void learnSpellHighRank(uint32 spellid);
void learnLevelupSpells(); void InitLevelupSpellsForLevel();
bool unlearnSpell(uint32 spell_id); bool unlearnSpell(uint32 spell_id, bool learn_prev);
bool removeSpell(uint32 spell_id); bool removeSpell(uint32 spell_id, bool learn_prev);
PetSpellMap m_spells; PetSpellMap m_spells;
TeachSpellMap m_teachspells; TeachSpellMap m_teachspells;

View file

@ -3259,6 +3259,7 @@ void Spell::EffectSummon(uint32 i)
spawnCreature->AIM_Initialize(); spawnCreature->AIM_Initialize();
spawnCreature->InitPetCreateSpells(); spawnCreature->InitPetCreateSpells();
spawnCreature->InitLevelupSpellsForLevel();
spawnCreature->SetHealth(spawnCreature->GetMaxHealth()); spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA)); spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
@ -4171,6 +4172,7 @@ void Spell::EffectSummonPet(uint32 i)
NewSummon->InitStatsForLevel(petlevel); NewSummon->InitStatsForLevel(petlevel);
NewSummon->InitPetCreateSpells(); NewSummon->InitPetCreateSpells();
NewSummon->InitLevelupSpellsForLevel();
NewSummon->InitTalentForLevel(); NewSummon->InitTalentForLevel();
if(NewSummon->getPetType()==SUMMON_PET) if(NewSummon->getPetType()==SUMMON_PET)
@ -5967,6 +5969,7 @@ void Spell::EffectSummonCritter(uint32 i)
critter->AIM_Initialize(); critter->AIM_Initialize();
critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter... critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter...
//critter->InitLevelupSpellsForLevel(); // none?
critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp critter->SelectLevel(critter->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp
critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag); critter->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag);
// some mini-pets have quests // some mini-pets have quests

View file

@ -10396,9 +10396,18 @@ void CharmInfo::InitCharmCreateSpells()
bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate) bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate)
{ {
// new spell already listed for example in case prepered switch to lesser rank in Pet::removeSpell
for(uint8 i = 0; i < 10; ++i)
if (PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE)
if (newid && PetActionBar[i].SpellOrAction == newid)
return true;
// old spell can be leasted for example in case learn high rank
for(uint8 i = 0; i < 10; ++i) for(uint8 i = 0; i < 10; ++i)
{ {
if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE) && PetActionBar[i].SpellOrAction == oldid) if (PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE)
{
if (PetActionBar[i].SpellOrAction == oldid)
{ {
PetActionBar[i].SpellOrAction = newid; PetActionBar[i].SpellOrAction = newid;
if (!oldid) if (!oldid)
@ -10412,6 +10421,7 @@ bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate)
return true; return true;
} }
} }
}
return false; return false;
} }
@ -11399,6 +11409,7 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id)
// this enables pet details window (Shift+P) // this enables pet details window (Shift+P)
pet->AIM_Initialize(); pet->AIM_Initialize();
pet->InitPetCreateSpells(); pet->InitPetCreateSpells();
pet->InitLevelupSpellsForLevel();
pet->InitTalentForLevel(); pet->InitTalentForLevel();
pet->SetHealth(pet->GetMaxHealth()); pet->SetHealth(pet->GetMaxHealth());

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7837" #define REVISION_NR "7838"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__