Index: src/game/Chat.cpp =================================================================== --- src/game/Chat.cpp (revision 6488) +++ src/game/Chat.cpp (working copy) @@ -219,6 +219,7 @@ { "spell_chain", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellChainCommand, "", NULL }, { "spell_elixir", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, { "spell_learn_spell", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, + { "spell_pet_auras", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL }, { "spell_proc_event", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL }, { "spell_script_target", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL }, { "spell_scripts", SEC_ADMINISTRATOR, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL }, Index: src/game/Chat.h =================================================================== --- src/game/Chat.h (revision 6488) +++ src/game/Chat.h (working copy) @@ -191,6 +191,7 @@ bool HandleReloadSpellScriptsCommand(const char* args); bool HandleReloadSpellTargetPositionCommand(const char* args); bool HandleReloadSpellThreatsCommand(const char* args); + bool HandleReloadSpellPetAurasCommand(const char* args); bool HandleReloadPageTextsCommand(const char* args); bool HandleReloadItemEnchantementsCommand(const char* args); Index: src/game/Level3.cpp =================================================================== --- src/game/Level3.cpp (revision 6488) +++ src/game/Level3.cpp (working copy) @@ -133,6 +133,7 @@ HandleReloadSpellScriptTargetCommand("a"); HandleReloadSpellTargetPositionCommand("a"); HandleReloadSpellThreatsCommand("a"); + HandleReloadSpellPetAurasCommand("a"); return true; } @@ -390,6 +391,14 @@ return true; } +bool ChatHandler::HandleReloadSpellPetAurasCommand(const char*) +{ + sLog.outString( "Re-Loading Spell pet auras..."); + spellmgr.LoadSpellPetAuras(); + SendGlobalSysMessage("DB table `spell_pet_auras` reloaded."); + return true; +} + bool ChatHandler::HandleReloadPageTextsCommand(const char*) { sLog.outString( "Re-Loading Page Texts..." ); Index: src/game/Pet.cpp =================================================================== --- src/game/Pet.cpp (revision 6488) +++ src/game/Pet.cpp (working copy) @@ -316,6 +316,7 @@ else { LearnPetPassives(); + CastPetAuras(); } if(getPetType() == SUMMON_PET && !current) //all (?) summon pets come with full health when called, but not when they are current @@ -514,7 +515,10 @@ } } else if(getDeathState()==ALIVE) + { RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + CastPetAuras(); + } } void Pet::Update(uint32 diff) @@ -1366,11 +1370,13 @@ AuraMap const& auras = GetAuras(); for(AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { - // skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or SPELL_AURA_MOD_STEALTH auras. + // skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or pet area auras. SpellEntry const *spellInfo = itr->second->GetSpellProto(); uint8 i; for (i = 0; i < 3; i++) - if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH) + if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH || + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_OWNER || + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PET ) break; if (i == 3 && !itr->second->IsPassive()) @@ -1570,6 +1576,8 @@ LearnPetPassives(); + CastPetAuras(); + SetTP(-usedtrainpoints); } @@ -1690,3 +1698,21 @@ addSpell(*petSet); } } + +void Pet::CastPetAuras() +{ + Unit* owner = GetOwner(); + if(!owner) + return; + + if(getPetType() != HUNTER_PET && (getPetType() != SUMMON_PET || owner->getClass() != CLASS_WARLOCK)) + return; + + for(std::list::iterator itr = owner->m_petAuras.begin(); itr != owner->m_petAuras.end(); ++itr) + { + if(uint16 aura = (*itr)->GetAura(GetEntry())) + { + CastSpell(this, aura, true); + } + } +} Index: src/game/Pet.h =================================================================== --- src/game/Pet.h (revision 6488) +++ src/game/Pet.h (working copy) @@ -176,6 +176,7 @@ void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; } void LearnPetPassives(); + void CastPetAuras(); void _LoadSpellCooldowns(); void _SaveSpellCooldowns(); Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 6488) +++ src/game/SpellAuras.cpp (working copy) @@ -2174,6 +2174,24 @@ break; } } + + // pet auras + if(PetAura const* petSpell = spellmgr.GetPetAura(GetId())) + { + if(apply) + { + m_target->m_petAuras.push_back(petSpell); + if(Pet* pet = m_target->GetPet()) + pet->CastSpell(pet, petSpell->GetAura(pet->GetEntry()), true); + } + else + { + m_target->m_petAuras.remove(petSpell); + if(Pet* pet = m_target->GetPet()) + pet->RemoveAurasDueToSpell(petSpell->GetAura(pet->GetEntry())); + } + return; + } } void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) Index: src/game/SpellMgr.cpp =================================================================== --- src/game/SpellMgr.cpp (revision 6488) +++ src/game/SpellMgr.cpp (working copy) @@ -1808,6 +1808,88 @@ sLog.outString(">> Loaded %u Spell Script Targets", count); } +void SpellMgr::LoadSpellPetAuras() +{ + mSpellPetAuraMap.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 + QueryResult *result = WorldDatabase.Query("SELECT spell, pet, aura FROM spell_pet_auras"); + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u spell pet auras", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field *fields = result->Fetch(); + + bar.step(); + + uint16 spell = fields[0].GetUInt16(); + uint16 pet = fields[1].GetUInt16(); + uint16 aura = fields[2].GetUInt16(); + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if (!spellInfo) + { + sLog.outErrorDb("Spell %u listed in `spell_pet_auras` does not exist", spell); + continue; + } + bool foundDummy = false; + for(int i = 0; i < 3; ++i) + { + if( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA && + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_DUMMY ) + { + foundDummy = true; + break; + } + } + if(!foundDummy) + { + sLog.outError("Spell %u listed in `spell_pet_auras` does not have dummy aura", spell); + continue; + } + + SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(aura); + if (!spellInfo2) + { + sLog.outErrorDb("Aura %u listed in `spell_pet_auras` does not exist", aura); + continue; + } + + SpellPetAuraMap::iterator itr = mSpellPetAuraMap.find(spell); + if(itr != mSpellPetAuraMap.end()) + { + itr->second.auras[pet] = aura; + } + else + { + PetAura pa; + pa.auras[pet] = aura; + mSpellPetAuraMap[spell] = pa; + } + + ++count; + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u spell pet auras", count ); +} + /// Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) { Index: src/game/SpellMgr.h =================================================================== --- src/game/SpellMgr.h (revision 6488) +++ src/game/SpellMgr.h (working copy) @@ -524,6 +524,28 @@ typedef HM_NAMESPACE::hash_map SpellTargetPositionMap; +// Spell pet auras +class PetAura +{ + public: + std::map auras; + uint16 GetAura(uint16 petEntry) const + { + std::map::const_iterator itr = auras.find(petEntry); + if(itr != auras.end()) + return itr->second; + else + { + std::map::const_iterator itr = auras.find(0); + if(itr != auras.end()) + return itr->second; + else + return 0; + } + } +}; +typedef std::map SpellPetAuraMap; + // Spell rank chain (accessed using SpellMgr functions) struct SpellChainNode { @@ -755,6 +777,15 @@ return mSkillLineAbilityMap.upper_bound(spell_id); } + PetAura const* GetPetAura(uint16 spell_id) + { + SpellPetAuraMap::const_iterator itr = mSpellPetAuraMap.find(spell_id); + if(itr != mSpellPetAuraMap.end()) + return &itr->second; + else + return NULL; + } + // Modifiers public: static SpellMgr& Instance(); @@ -770,6 +801,7 @@ void LoadSpellTargetPositions(); void LoadSpellThreats(); void LoadSkillLineAbilityMap(); + void LoadSpellPetAuras(); private: SpellScriptTarget mSpellScriptTarget; @@ -782,6 +814,7 @@ SpellElixirMap mSpellElixirs; SpellProcEventMap mSpellProcEventMap; SkillLineAbilityMap mSkillLineAbilityMap; + SpellPetAuraMap mSpellPetAuraMap; }; #define spellmgr SpellMgr::Instance() Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 6488) +++ src/game/Unit.h (working copy) @@ -234,6 +234,7 @@ class Item; class Pet; class Path; +class PetAura; struct SpellImmune { @@ -1208,6 +1209,8 @@ // group updates void UpdateAuraForGroup(uint8 slot); + std::list m_petAuras; + protected: explicit Unit (); Index: src/game/World.cpp =================================================================== --- src/game/World.cpp (revision 6488) +++ src/game/World.cpp (working copy) @@ -841,6 +841,9 @@ sLog.outString( "Loading SpellAffect definitions..." ); spellmgr.LoadSpellAffects(); + sLog.outString( "Loading spell pet auras..." ); + spellmgr.LoadSpellPetAuras(); + sLog.outString( "Loading player Create Info & Level Stats..." ); objmgr.LoadPlayerInfo();