Index: src/game/Pet.cpp =================================================================== --- src/game/Pet.cpp (revision 4889) +++ src/game/Pet.cpp (working copy) @@ -306,6 +306,8 @@ _LoadSpellCooldowns(); owner->SetPet(this); // in DB stored only full controlled creature + if(GetOwnerGUID()) + GetOwner()->_UpdatePetAuras(0, true); sLog.outDebug("New Pet has guid %u", GetGUIDLow()); if(owner->GetTypeId() == TYPEID_PLAYER) Index: src/game/Pet.h =================================================================== --- src/game/Pet.h (revision 4889) +++ src/game/Pet.h (working copy) @@ -201,6 +201,7 @@ time_t m_resetTalentsTime; bool m_removed; // prevent overwrite pet state in DB at next Pet::Update if pet already removed(saved) + bool m_been_banished; // Indicates need to reload auras (like Spirit Bond, Demonic Knowledge) protected: uint32 m_regenTimer; uint32 m_happinessTimer; Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (revision 4889) +++ src/game/Player.cpp (working copy) @@ -2561,6 +2561,10 @@ CastSpell(this, spell_id, true); } + //update pet based on talents + if (IsPassiveSpell(spell_id) || GetTalentSpellCost(spell_id)) + _UpdatePetAuras(0, true); + // update used talent points count m_usedTalentCount += talentCost; Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 4889) +++ src/game/SpellAuras.cpp (working copy) @@ -554,6 +554,12 @@ Group *pGroup = NULL; if (caster->GetTypeId() == TYPEID_PLAYER) pGroup = ((Player*)caster)->GetGroup(); + else if( ((Creature*)caster)->isPet() && isPetAura() ) + { + Unit *owner = ((Pet*)caster)->GetOwner(); + if(owner && owner->GetTypeId() == TYPEID_PLAYER) + pGroup = NULL; + } else if(caster->GetCharmerOrOwnerGUID() != 0) { Unit *owner = caster->GetCharmerOrOwner(); @@ -601,6 +607,29 @@ } } } + else if(((Creature*)caster)->isPet() && ((Pet*)caster)->GetOwnerGUID() && isPetAura()) + { + Unit *owner = ((Pet*)caster)->GetOwner(); + Aura *petAura = owner->GetAura(m_spellId, m_effIndex); + if(caster->IsWithinDistInMap(owner, m_radius) && caster->isAlive()) + { + if(!petAura) + { + AreaAura *aur = new AreaAura(GetSpellProto(), m_effIndex, &m_currentBasePoints, owner, caster); + owner->AddAura(aur); + } + + // Remove aura if pet is banished + // Implemented in Unit::_UpdatePetAuras + } + else + { + if(petAura) + owner->RemoveAurasDueToSpell(GetSpellProto()->Id); + } + if( !caster->IsInWorld() || caster->isDead()) + owner->RemoveAurasDueToSpell(GetSpellProto()->Id); + } else if (caster->GetCharmerOrOwnerGUID() != 0) { // add / remove auras from the totem's owner Index: src/game/SpellAuras.h =================================================================== --- src/game/SpellAuras.h (revision 4889) +++ src/game/SpellAuras.h (working copy) @@ -254,6 +254,9 @@ // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras void HandleShapeshiftBoosts(bool apply); + + bool isPetAura() const { return m_spellProto->Effect[GetEffIndex()] == 119 || m_spellProto->Effect[GetEffIndex()] == 143; } + protected: Modifier m_modifier; SpellModifier *m_spellmod; Index: src/game/SpellEffects.cpp =================================================================== --- src/game/SpellEffects.cpp (revision 4889) +++ src/game/SpellEffects.cpp (working copy) @@ -199,7 +199,7 @@ &Spell::EffectNULL, //140 SPELL_EFFECT_140 &Spell::EffectNULL, //141 SPELL_EFFECT_141 &Spell::EffectNULL, //142 SPELL_EFFECT_142 - &Spell::EffectNULL, //143 SPELL_EFFECT_143 probably apply aura again :) + &Spell::EffectApplyPetAura, //143 SPELL_EFFECT_143 probably apply aura again :) &Spell::EffectNULL, //144 SPELL_EFFECT_144 &Spell::EffectNULL, //145 SPELL_EFFECT_145 &Spell::EffectNULL, //146 SPELL_EFFECT_146 @@ -4237,15 +4237,16 @@ void Spell::EffectApplyPetAura(uint32 i) { - //spell aura for both pet and owner, think the pet has the aura and applies it to owner - EffectApplyAura(i); + if( !((Creature*)m_caster)->isPet() || ( ((Pet*)m_caster)->getPetType() != SUMMON_PET && ((Pet*)m_caster)->getPetType() != HUNTER_PET ) ) + return; - Unit* owner = unitTarget->GetCharmerOrOwner(); - if(owner) - { - unitTarget = owner; - EffectApplyAura(i); - } + if(!((Pet*)m_caster)->GetOwnerGUID() || !((Pet*)m_caster)->GetOwner()->isAlive()) + return; + + AreaAura* Aur = new AreaAura(m_spellInfo, i, m_currentBasePoints, unitTarget, m_caster); + m_caster->AddAura(Aur); + + return; } void Spell::EffectSummonDemon(uint32 i) Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 4889) +++ src/game/Unit.cpp (working copy) @@ -2803,8 +2803,266 @@ ++dnext1; } } + + _UpdatePetAuras(time); } +void Unit::_UpdatePetAuras( uint32 time, bool refreshAll ) +{ + Pet *pet = GetPet(); + if(!pet) + return; + + bool isBanished = false; + + // Check for banish before update + // Remove aura if pet is banished + Unit::AuraList const &mImmunity = pet->GetAurasByType(SPELL_AURA_SCHOOL_IMMUNITY); + for(Unit::AuraList::const_iterator i = mImmunity.begin(); i != mImmunity.end(); ++i) + { + if ((*i)->GetSpellProto()->SpellIconID == 96) + { + isBanished = true; + break; + } + } + + if(isBanished) + { + pet->_RemovePetAuras(); + pet->RemoveAurasDueToSpell(25228); // Soul Link remove + pet->m_been_banished = true; + return; + } + + // Following code needs to be executed only if we need to refresh pet's passive auras + if(!refreshAll && !pet->m_been_banished) + return; + + pet->m_been_banished = false; + _RemovePetAuras(); + + uint32 MD = 0; + + // TODO: Soul Link check + // Update auras + Unit::AuraList const &mDummy = GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) + { + switch((*itr)->GetSpellProto()->Id) + { + // Demonic Knowledge + case 35691: + case 35692: + case 35693: + { + pet->RemoveAurasDueToSpell(35696); + int32 totalBonus = (*itr)->GetSpellProto()->EffectBasePoints[(*itr)->GetEffIndex()] + 1; + totalBonus = int32( totalBonus * (pet->GetStat(STAT_STAMINA) + pet->GetStat(STAT_INTELLECT)) / 100.0f ); + pet->CastCustomSpell(pet, 35696, &totalBonus, 0, 0, true); + break; + } + + // Spirit Bond + case 19578: + pet->CastSpell(pet, 19579, true); + break; + case 20895: + pet->CastSpell(pet, 24529, true); + break; + + // Stalker's Ally + case 28757: + pet->CastSpell(pet, 28758, true); + break; + + // Master Demonologist + case 23785: + switch(pet->GetEntry()) + { + case 416: MD = 23759; break; // imp + case 1860: MD = 23760; break; // voidwalker + case 1863: MD = 23761; break; // succubus + case 417: MD = 23762; break; // felhunter + case 17252: MD = 35702; break; // felguard + default: break; + } + if(MD) pet->CastSpell(pet, MD, true); + break; + case 23822: + switch(pet->GetEntry()) + { + case 416: MD = 23826; break; // imp + case 1860: MD = 23841; break; // voidwalker + case 1863: MD = 23833; break; // succubus + case 417: MD = 23837; break; // felhunter + case 17252: MD = 35703; break; // felguard + default: break; + } + if(MD) pet->CastSpell(pet, MD, true); + break; + case 23823: + switch(pet->GetEntry()) + { + case 416: MD = 23827; break; // imp + case 1860: MD = 23842; break; // voidwalker + case 1863: MD = 23834; break; // succubus + case 417: MD = 23838; break; // felhunter + case 17252: MD = 35704; break; // felguard + default: break; + } + if(MD) pet->CastSpell(pet, MD, true); + break; + case 23824: + switch(pet->GetEntry()) + { + case 416: MD = 23828; break; // imp + case 1860: MD = 23842; break; // voidwalker + case 1863: MD = 23835; break; // succubus + case 417: MD = 23839; break; // felhunter + case 17252: MD = 35705; break; // felguard + default: break; + } + if(MD) pet->CastSpell(pet, MD, true); + break; + case 23825: + switch(pet->GetEntry()) + { + case 416: MD = 23829; break; // imp + case 1860: MD = 23844; break; // voidwalker + case 1863: MD = 23836; break; // succubus + case 417: MD = 23840; break; // felhunter + case 17252: MD = 35706; break; // felguard + default: break; + } + if(MD) pet->CastSpell(pet, MD, true); + break; + default: break; + } + } + + + // Additional auras + switch(pet->getPetType()) + { + case HUNTER_PET: + { + // Remove first + pet->RemoveAurasDueToSpell(8875); + pet->RemoveAurasDueToSpell(19580); + pet->RemoveAurasDueToSpell(19581); + pet->RemoveAurasDueToSpell(19582); + pet->RemoveAurasDueToSpell(19589); + pet->RemoveAurasDueToSpell(19591); + pet->RemoveAurasDueToSpell(20784); + pet->RemoveAurasDueToSpell(34457); + pet->RemoveAurasDueToSpell(34666); + pet->RemoveAurasDueToSpell(34667); + pet->RemoveAurasDueToSpell(34675); + // Apply passive auras again + pet->CastSpell(pet, 8875, true); // Damage + pet->CastSpell(pet, 19580, true); // Armor + pet->CastSpell(pet, 19581, true); // Health + pet->CastSpell(pet, 19582, true); // Speed + pet->CastSpell(pet, 19589, true); // Focus Regeneration + pet->CastSpell(pet, 19591, true); // Crit and Spell crit chance + pet->CastSpell(pet, 20784, true); // Chance to proc Frenzy + pet->CastSpell(pet, 34457, true); // Chance to proc Ferocious inspiration + pet->CastSpell(pet, 34666, true); // Chance to hit + pet->CastSpell(pet, 34667, true); // Chance to dodge + pet->CastSpell(pet, 34675, true); // Attack speed + } break; + case SUMMON_PET: + { + pet->RemoveAurasDueToSpell(35695); + pet->RemoveAurasDueToSpell(35697); + pet->CastSpell(this, 35695, true); // Demonic tactics (%crit+spellcrit) + pet->CastSpell(this, 35697, true); // Demonic resilience + switch(pet->GetEntry()) + { + case 416: + // Imp + // Remove first + pet->RemoveAurasDueToSpell(18728); + pet->RemoveAurasDueToSpell(18737); + pet->RemoveAurasDueToSpell(18740); + // Apply passive auras again + pet->CastSpell(pet, 18728, true); // All damage caused + pet->CastSpell(pet, 18737, true); // Stamina + pet->CastSpell(pet, 18740, true); // Intellect + break; + case 1860: + // Voidwalker + // Remove first + pet->RemoveAurasDueToSpell(18727); + pet->RemoveAurasDueToSpell(18735); + pet->RemoveAurasDueToSpell(18742); + // Apply passive auras again + pet->CastSpell(pet, 18727, true); // All damage caused + pet->CastSpell(pet, 18735, true); // Stamina + pet->CastSpell(pet, 18742, true); // Intellect + break; + case 1863: + // Succubus + // Remove first + pet->RemoveAurasDueToSpell(18729); + pet->RemoveAurasDueToSpell(18736); + pet->RemoveAurasDueToSpell(18741); + // Apply passive auras again + pet->CastSpell(pet, 18729, true); // All damage caused + pet->CastSpell(pet, 18736, true); // Stamina + pet->CastSpell(pet, 18741, true); // Intellect + break; + case 417: + // Felhunter + // Remove first + pet->RemoveAurasDueToSpell(18730); + pet->RemoveAurasDueToSpell(18738); + pet->RemoveAurasDueToSpell(18739); + pet->RemoveAurasDueToSpell(19007); + // Apply passive auras again + pet->CastSpell(pet, 18730, true); // All damage caused + pet->CastSpell(pet, 18738, true); // Stamina + pet->CastSpell(pet, 18739, true); // Intellect + pet->CastSpell(pet, 19007, true); // Felhunter Resistances + break; + case 17252: + // Felguard + // Remove first + pet->RemoveAurasDueToSpell(30147); + pet->RemoveAurasDueToSpell(30148); + pet->RemoveAurasDueToSpell(30149); + // Apply passive auras again + pet->CastSpell(pet, 30147, true); // All damage caused + pet->CastSpell(pet, 30148, true); // Stamina + pet->CastSpell(pet, 30149, true); // Intellect + break; + default: break; + } + } break; + default: break; + } +} + +void Unit::_RemovePetAuras() +{ + Pet *pet = GetPet(); + if(!pet || !pet->isAlive()) + return; + + std::vector toRemove; + + AuraList const &mPetAuras119 = pet->GetAurasByType(AuraType(119)); + for(AuraList::const_iterator itr = mPetAuras119.begin(); itr != mPetAuras119.end(); ++itr) + toRemove.push_back((*itr)->GetId()); + AuraList const &mPetAuras143 = pet->GetAurasByType(AuraType(143)); + for(AuraList::const_iterator itr = mPetAuras143.begin(); itr != mPetAuras143.end(); ++itr) + toRemove.push_back((*itr)->GetId()); + + for(int itr = 0; itr < toRemove.size(); itr++) + pet->RemoveAurasDueToSpell(itr); +} + void Unit::_UpdateAutoRepeatSpell( uint32 time ) { if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->getState() == SPELL_STATE_FINISHED) Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 4889) +++ src/game/Unit.h (working copy) @@ -1182,10 +1182,13 @@ void StartReactiveTimer( ReactiveType reactive ) { m_reactiveTimer[reactive] = REACTIVE_TIMER_START;} void UpdateReactives(uint32 p_time); + void _UpdatePetAuras(uint32 time, bool refreshAll = false); + protected: explicit Unit ( WorldObject *instantiator ); void _UpdateSpells(uint32 time); + void _RemovePetAuras(); void _UpdateAutoRepeatSpell(uint32 time); bool m_AutoRepeatFirstCast;