diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 2da83263e..9a147e5a5 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -4792,13 +4792,10 @@ bool ChatHandler::HandleResetLevelCommand(const char * args) player->InitTalentForLevel(); player->SetUInt32Value(PLAYER_XP,0); - // reset level to summoned pet - Pet* pet = player->GetPet(); - if(pet && pet->getPetType()==SUMMON_PET) - { - pet->InitStatsForLevel(1); - pet->InitTalentForLevel(); - } + // reset level for pet + if(Pet* pet = player->GetPet()) + pet->SynchronizeLevelWithOwner(); + return true; } diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index e8b5bb04e..e7e195581 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -340,6 +340,8 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool } } + InitLevelupSpellsForLevel(); + m_loading = false; SynchronizeLevelWithOwner(); @@ -653,6 +655,9 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid) for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) { + if(itr->second.state == PETSPELL_REMOVED) + continue; + if(IsPassiveSpell(itr->first)) continue; @@ -746,6 +751,7 @@ void Pet::GivePetLevel(uint32 level) return; InitStatsForLevel(level); + InitLevelupSpellsForLevel(); InitTalentForLevel(); } @@ -994,9 +1000,6 @@ bool Pet::InitStatsForLevel(uint32 petlevel) for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i])); - if(cinfo->family) - learnLevelupSpells(); - UpdateAllStats(); SetHealth(GetMaxHealth()); @@ -1118,7 +1121,7 @@ void Pet::_LoadSpells() { 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() ); @@ -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); if (!spellInfo) @@ -1356,26 +1359,33 @@ bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState // skip unknown ranks if(!HasSpell(rankSpellId)) 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) { if(itr2->second.state == PETSPELL_REMOVED) continue; - if(spellmgr.GetFirstSpellInChain(itr2->first) == chainstart) + if( spellmgr.IsRankSpellDueToSpell(spellInfo,itr2->first) ) { - newspell.active = itr2->second.active; + // replace by new high rank + if(spellmgr.IsHighRankOfSpell(spell_id,itr2->first)) + { + newspell.active = itr2->second.active; - if(newspell.active == ACT_ENABLED) - ToggleAutocast(itr2->first, false); + if(newspell.active == ACT_ENABLED) + ToggleAutocast(itr2->first, false); - oldspell_id = itr2->first; - unlearnSpell(itr2->first); - break; + oldspell_id = itr2->first; + unlearnSpell(itr2->first,false); + 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)) CastSpell(this, spell_id, true); - else if(state == PETSPELL_NEW) + else m_charmInfo->AddSpellToAB(oldspell_id, spell_id); if(newspell.active == ACT_ENABLED) @@ -1422,26 +1432,33 @@ bool Pet::learnSpell(uint32 spell_id) 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) return; 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) - learnSpell(itr->second); + // will called first if level down + if(itr->first > level) + unlearnSpell(itr->second,true); // will learn prev rank if any + // will called if level up 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) { @@ -1457,7 +1474,7 @@ bool Pet::unlearnSpell(uint32 spell_id) 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); if (itr == m_spells.end()) @@ -1485,6 +1502,27 @@ bool Pet::removeSpell(uint32 spell_id) 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; } @@ -1620,7 +1658,7 @@ bool Pet::resetTalents(bool no_cost) // unlearn if first rank is talent or learned by talent if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId)) { - removeSpell(itr->first); + removeSpell(itr->first,false); itr = m_spells.begin(); continue; } diff --git a/src/game/Pet.h b/src/game/Pet.h index 07e1036ce..1b987b8ce 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -69,7 +69,7 @@ enum PetSpellType struct PetSpell { - uint16 active; + ActiveStates active : 16; PetSpellState state : 8; PetSpellType type : 8; @@ -196,12 +196,12 @@ class Pet : public Creature void _LoadSpells(); 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); void learnSpellHighRank(uint32 spellid); - void learnLevelupSpells(); - bool unlearnSpell(uint32 spell_id); - bool removeSpell(uint32 spell_id); + void InitLevelupSpellsForLevel(); + bool unlearnSpell(uint32 spell_id, bool learn_prev); + bool removeSpell(uint32 spell_id, bool learn_prev); PetSpellMap m_spells; TeachSpellMap m_teachspells; @@ -252,4 +252,4 @@ class Pet : public Creature assert(false); } }; -#endif +#endif \ No newline at end of file diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index ce4528ec0..c1cfd684d 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3259,6 +3259,7 @@ void Spell::EffectSummon(uint32 i) spawnCreature->AIM_Initialize(); spawnCreature->InitPetCreateSpells(); + spawnCreature->InitLevelupSpellsForLevel(); spawnCreature->SetHealth(spawnCreature->GetMaxHealth()); spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA)); @@ -4171,6 +4172,7 @@ void Spell::EffectSummonPet(uint32 i) NewSummon->InitStatsForLevel(petlevel); NewSummon->InitPetCreateSpells(); + NewSummon->InitLevelupSpellsForLevel(); NewSummon->InitTalentForLevel(); if(NewSummon->getPetType()==SUMMON_PET) @@ -5967,6 +5969,7 @@ void Spell::EffectSummonCritter(uint32 i) critter->AIM_Initialize(); 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->SetUInt32Value(UNIT_NPC_FLAGS, critter->GetCreatureInfo()->npcflag); // some mini-pets have quests diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 474b6009e..7f150e1df 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -10396,20 +10396,30 @@ void CharmInfo::InitCharmCreateSpells() 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) { - 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) { - PetActionBar[i].SpellOrAction = newid; - if(!oldid) + if (PetActionBar[i].SpellOrAction == oldid) { - if(newstate == ACT_DECIDE) - PetActionBar[i].Type = ACT_DISABLED; - else - PetActionBar[i].Type = newstate; - } + PetActionBar[i].SpellOrAction = newid; + if (!oldid) + { + if (newstate == ACT_DECIDE) + PetActionBar[i].Type = ACT_DISABLED; + else + PetActionBar[i].Type = newstate; + } - return true; + return true; + } } } return false; @@ -11399,6 +11409,7 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) // this enables pet details window (Shift+P) pet->AIM_Initialize(); pet->InitPetCreateSpells(); + pet->InitLevelupSpellsForLevel(); pet->InitTalentForLevel(); pet->SetHealth(pet->GetMaxHealth()); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 096e37697..d86a931cf 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7837" + #define REVISION_NR "7838" #endif // __REVISION_NR_H__