diff options
Diffstat (limited to 'src')
49 files changed, 9606 insertions, 9409 deletions
diff --git a/src/bindings/scripts/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp b/src/bindings/scripts/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp index 1ff205162a4..cbfc86ea183 100644 --- a/src/bindings/scripts/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp +++ b/src/bindings/scripts/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp @@ -413,15 +413,7 @@ struct TRINITY_DLL_DECL boss_veknilashAI : public boss_twinemperorsAI { pTarget->setFaction(14); pTarget->AI()->AttackStart(m_creature->getThreatManager().getHostilTarget()); - SpellEntry *spell = GET_SPELL(SPELL_MUTATE_BUG); - uint8 eff_mask=0; - for (int i=0; i<3; ++i) - { - if (!spell->Effect[i]) - continue; - eff_mask|=1<<i; - } - pTarget->AddAura(new Aura(spell, eff_mask, pTarget, pTarget, pTarget)); + pTarget->AddAura(SPELL_MUTATE_BUG, pTarget); pTarget->SetHealth(pTarget->GetMaxHealth()); } @@ -498,15 +490,7 @@ struct TRINITY_DLL_DECL boss_veklorAI : public boss_twinemperorsAI void CastSpellOnBug(Creature *pTarget) { pTarget->setFaction(14); - SpellEntry *spell = GET_SPELL(SPELL_EXPLODEBUG); - uint8 eff_mask=0; - for (int i=0; i<3; ++i) - { - if (!spell->Effect[i]) - continue; - eff_mask|=1<<i; - } - pTarget->AddAura(new Aura(spell, eff_mask, pTarget, pTarget, pTarget)); + pTarget->AddAura(SPELL_EXPLODEBUG, pTarget); pTarget->SetHealth(pTarget->GetMaxHealth()); } diff --git a/src/bindings/scripts/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp b/src/bindings/scripts/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp index d548ff7155e..0d715785140 100644 --- a/src/bindings/scripts/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp +++ b/src/bindings/scripts/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp @@ -53,19 +53,6 @@ EndScriptData */ #define SPELL_STORM_BUFF 2148 #define SPELL_STORM 26546 -struct TRINITY_DLL_DECL aqsentinelAI; -class TRINITY_DLL_DECL SentinelAbilityAura : public Aura -{ - public: - ~SentinelAbilityAura(); - Unit* GetTriggerTarget() const; - SentinelAbilityAura(aqsentinelAI *abilityOwner, SpellEntry *spell, uint32 ability, uint32 eff); - protected: - aqsentinelAI *aOwner; - int32 currentBasePoints; - uint32 abilityId; -}; - struct TRINITY_DLL_DECL aqsentinelAI : public ScriptedAI { uint32 ability; @@ -222,16 +209,7 @@ struct TRINITY_DLL_DECL aqsentinelAI : public ScriptedAI void GainSentinelAbility(uint32 id) { - const SpellEntry *spell = GetSpellStore()->LookupEntry(id); - uint8 eff_mask=0; - for (int i=0; i<3; ++i) - { - if (!spell->Effect[i]) - continue; - eff_mask=1<<i; - } - SentinelAbilityAura *a = new SentinelAbilityAura(this, (SpellEntry*)spell, id, eff_mask); - m_creature->AddAura(a); + m_creature->AddAura(id, m_creature); } void EnterCombat(Unit *who) @@ -260,7 +238,7 @@ struct TRINITY_DLL_DECL aqsentinelAI : public ScriptedAI } } - Unit *GetHatedManaUser() + Unit *GetHatedManaUser() const { std::list<HostilReference*>::iterator i; for (i = m_creature->getThreatManager().getThreatList().begin(); i != m_creature->getThreatManager().getThreatList().end(); ++i) @@ -271,6 +249,28 @@ struct TRINITY_DLL_DECL aqsentinelAI : public ScriptedAI } return NULL; } + + Unit* GetAuraEffectTriggerTarget(uint32 spellId, uint8 effIndex) const + { + switch (spellId) + { + case SPELL_KNOCK_BUFF: + case SPELL_THUNDER_BUFF: + case SPELL_MSTRIKE_BUFF: + case SPELL_STORM_BUFF: + return m_creature->getVictim(); + + case SPELL_MANAB_BUFF: + return GetHatedManaUser(); + + case SPELL_MENDING_BUFF: + case SPELL_REFLECTAF_BUFF: + case SPELL_REFLECTSFr_BUFF: + case SPELL_THORNS_BUFF: + default: + return m_creature; + } + } }; CreatureAI* GetAI_mob_anubisath_sentinelAI(Creature* pCreature) { @@ -285,34 +285,3 @@ void AddSC_mob_anubisath_sentinel() newscript->GetAI = &GetAI_mob_anubisath_sentinelAI; newscript->RegisterSelf(); } - -SentinelAbilityAura::~SentinelAbilityAura() {} -Unit* SentinelAbilityAura::GetTriggerTarget() const -{ - switch (abilityId) - { - case SPELL_KNOCK_BUFF: - case SPELL_THUNDER_BUFF: - case SPELL_MSTRIKE_BUFF: - case SPELL_STORM_BUFF: - return aOwner->m_creature->getVictim(); - - case SPELL_MANAB_BUFF: - return aOwner->GetHatedManaUser(); - - case SPELL_MENDING_BUFF: - case SPELL_REFLECTAF_BUFF: - case SPELL_REFLECTSFr_BUFF: - case SPELL_THORNS_BUFF: - default: - return aOwner->m_creature; - } -} - -SentinelAbilityAura::SentinelAbilityAura(aqsentinelAI *abilityOwner, SpellEntry *spell, uint32 ability, uint32 eff) -: Aura(spell, eff, abilityOwner->m_creature, abilityOwner->m_creature, abilityOwner->m_creature, NULL) -{ - aOwner = abilityOwner; - abilityId = ability; -} - diff --git a/src/bindings/scripts/scripts/northrend/draktharon_keep/boss_trollgore.cpp b/src/bindings/scripts/scripts/northrend/draktharon_keep/boss_trollgore.cpp index a2c7d44a7c3..ed54bd05eb8 100644 --- a/src/bindings/scripts/scripts/northrend/draktharon_keep/boss_trollgore.cpp +++ b/src/bindings/scripts/scripts/northrend/draktharon_keep/boss_trollgore.cpp @@ -133,9 +133,8 @@ struct TRINITY_DLL_DECL boss_trollgoreAI : public ScriptedAI { if (uiAuraCountTimer <= diff) { - if (m_creature->HasAura(HEROIC(SPELL_CONSUME,H_SPELL_CONSUME))) + if (Aura *pConsumeAura = m_creature->GetAura(HEROIC(SPELL_CONSUME,H_SPELL_CONSUME))) { - Aura *pConsumeAura = m_creature->GetAura(HEROIC(SPELL_CONSUME,H_SPELL_CONSUME)); if (pConsumeAura && pConsumeAura->GetStackAmount() > 9) bAchiev = false; } diff --git a/src/bindings/scripts/scripts/northrend/vault_of_archavon/boss_emalon.cpp b/src/bindings/scripts/scripts/northrend/vault_of_archavon/boss_emalon.cpp index 1260cd98557..412920961a6 100644 --- a/src/bindings/scripts/scripts/northrend/vault_of_archavon/boss_emalon.cpp +++ b/src/bindings/scripts/scripts/northrend/vault_of_archavon/boss_emalon.cpp @@ -225,7 +225,7 @@ struct TRINITY_DLL_DECL mob_tempest_minionAI : public ScriptedAI if(me->hasUnitState(UNIT_STAT_CASTING)) return; - if(Aura *OverchargedAura = m_creature->GetAura(SPELL_OVERCHARGED)) + if(Aura * OverchargedAura = m_creature->GetAura(SPELL_OVERCHARGED)) { if(OverchargedAura->GetStackAmount() < 10) { diff --git a/src/bindings/scripts/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/bindings/scripts/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp index e94c8953117..0a4fe3e8cd1 100644 --- a/src/bindings/scripts/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp +++ b/src/bindings/scripts/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp @@ -92,10 +92,8 @@ struct TRINITY_DLL_DECL mob_voidtravelerAI : public ScriptedAI { if (sacrificed) { - SpellEntry *spell = GET_SPELL(HeroicMode?H_SPELL_EMPOWERING_SHADOWS:SPELL_EMPOWERING_SHADOWS); - if (spell) - Vorpil->AddAura(new Aura(spell, 1, Vorpil, me, me)); - Vorpil->SetHealth(Vorpil->GetHealth()+Vorpil->GetMaxHealth()/25); + m_creature->AddAura(HEROIC(H_SPELL_EMPOWERING_SHADOWS, SPELL_EMPOWERING_SHADOWS), Vorpil); + Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth()/25); DoCast(m_creature, SPELL_SHADOW_NOVA, true); m_creature->Kill(m_creature); return; diff --git a/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp b/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp index d0c7753f0ac..db440ef0cc1 100644 --- a/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp +++ b/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp @@ -636,21 +636,7 @@ struct TRINITY_DLL_DECL mob_enchanted_elementalAI : public ScriptedAI { m_creature->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); if (m_creature->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) - { - SpellEntry *spell = GET_SPELL(SPELL_SURGE); - if (spell) - { - uint8 eff_mask=0; - for (uint8 i = 0; i < 3; ++i) - { - if (!spell->Effect[i]) - continue; - eff_mask|=1<<i; - } - Vashj->AddAura(new Aura(spell, eff_mask, Vashj, Vashj, Vashj)); - } - m_creature->Kill(m_creature); - } + DoCast(m_creature, SPELL_SURGE); } if (!Vashj->isInCombat() || CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase != 2 || Vashj->isDead()) { diff --git a/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp index eaa5ce84174..24f47dff4a6 100644 --- a/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp +++ b/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp @@ -497,14 +497,8 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI demon->AI()->AttackStart((*itr)); CAST_AI(mob_inner_demonAI, demon->AI())->victimGUID = (*itr)->GetGUID(); - uint8 eff_mask=0; - for (int i=0; i<3; ++i) - { - if (!spell->Effect[i]) - continue; - eff_mask|=1<<i; - } - (*itr)->AddAura(new Aura(spell, eff_mask, *itr, *itr, *itr)); + (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); + if (InnerDemon_Count > 4) InnerDemon_Count = 0; diff --git a/src/bindings/scripts/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp b/src/bindings/scripts/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp index 615d242018a..49b167422af 100644 --- a/src/bindings/scripts/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp +++ b/src/bindings/scripts/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp @@ -232,14 +232,8 @@ struct TRINITY_DLL_DECL boss_kelidan_the_breakerAI : public ScriptedAI if (SpellEntry *nova = GET_SPELL(SPELL_BURNING_NOVA)) { - uint8 eff_mask=0; - for (int i=0; i<3; ++i) - { - if (!nova->Effect[i]) - continue; - eff_mask|=1<<i; - } - m_creature->AddAura(new Aura(nova, eff_mask, me, me, me)); + if (Aura * aura = Aura::TryCreate(nova, me, me)) + aura->ApplyForTargets(); } if (HeroicMode) diff --git a/src/bindings/scripts/scripts/world/npcs_special.cpp b/src/bindings/scripts/scripts/world/npcs_special.cpp index d5c7d48b607..f3ccb1076cc 100644 --- a/src/bindings/scripts/scripts/world/npcs_special.cpp +++ b/src/bindings/scripts/scripts/world/npcs_special.cpp @@ -190,7 +190,7 @@ struct TRINITY_DLL_DECL npc_air_force_botsAI : public ScriptedAI if (!pWho->IsWithinDistInMap(m_creature, RANGE_GUARDS_MARK)) return; - Aura* pMarkAura = pWho->GetAura(SPELL_GUARDS_MARK, 0); + Aura* pMarkAura = pWho->GetAura(SPELL_GUARDS_MARK); if (pMarkAura) { // the target wasn't able to move out of our range within 25 seconds @@ -202,7 +202,7 @@ struct TRINITY_DLL_DECL npc_air_force_botsAI : public ScriptedAI return; } - if (pMarkAura->GetAuraDuration() < AURA_DURATION_TIME_LEFT) + if (pMarkAura->GetDuration() < AURA_DURATION_TIME_LEFT) { if (!pLastSpawnedGuard->getVictim()) pLastSpawnedGuard->AI()->AttackStart(pWho); diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 554f8555627..19643a6003e 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -34,6 +34,7 @@ #include "MapManager.h" #include "Object.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" #include "Util.h" namespace Trinity @@ -427,15 +428,16 @@ void BattleGround::Update(uint32 diff) { plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); // remove auras with duration lower than 30s - Unit::AuraMap & aurMap = plr->GetAuras(); - for (Unit::AuraMap::iterator iter = aurMap.begin(); iter != aurMap.end();) + Unit::AuraMap & auraMap = plr->GetOwnedAuras(); + for (Unit::AuraMap::iterator iter = auraMap.begin(); iter != auraMap.end();) { - if (!iter->second->IsPermanent() - && iter->second->GetAuraDuration()<=30*IN_MILISECONDS - && iter->second->IsPositive() - && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY)) - && (!iter->second->IsAuraType(SPELL_AURA_MOD_INVISIBILITY))) - plr->RemoveAura(iter); + Aura * aura = iter->second; + if (!aura->IsPermanent() + && aura->GetDuration() <= 30*IN_MILISECONDS + && aura->IsPositive(plr) + && (!(aura->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY)) + && (!aura->HasEffectType(SPELL_AURA_MOD_INVISIBILITY))) + plr->RemoveOwnedAura(iter); else ++iter; } diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index 435271c6a20..96abf30a72c 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -232,6 +232,8 @@ SET(game_STAT_SRCS SpellAuraDefines.h SpellAuras.cpp SpellAuras.h + SpellAuraEffects.cpp + SpellAuraEffects.h Spell.cpp SpellEffects.cpp SpellId.h diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index f5b7e0ac7f2..1deda64ead9 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -68,7 +68,7 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points, instance_id, speccount, activespec FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_mask,stackcount,amount0, amount1, amount2 ,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid)); @@ -454,6 +454,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) if(!pNewChar->Create( objmgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId )) { // Player not create (race/class problem?) + pNewChar->CleanupsBeforeDelete(); delete pNewChar; data << (uint8)CHAR_CREATE_ERROR; @@ -472,6 +473,7 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); + pNewChar->CleanupsBeforeDelete(); delete pNewChar; // created only to call SaveToDB() data << (uint8)CHAR_CREATE_SUCCESS; diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index 47e89bf4fff..d36a7cfd50b 100644 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -38,6 +38,7 @@ #include "Player.h" #include "ScriptCalls.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" #include "Util.h" bool WorldSession::processChatmessageFurtherAfterSecurityChecks(std::string& msg, uint32 lang) @@ -88,7 +89,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) if(langDesc->skill_id != 0 && !_player->HasSkill(langDesc->skill_id)) { // also check SPELL_AURA_COMPREHEND_LANGUAGE (client offers option to speak in that language) - Unit::AuraEffectList const& langAuras = _player->GetAurasByType(SPELL_AURA_COMPREHEND_LANGUAGE); + Unit::AuraEffectList const& langAuras = _player->GetAuraEffectsByType(SPELL_AURA_COMPREHEND_LANGUAGE); bool foundAura = false; for (Unit::AuraEffectList::const_iterator i = langAuras.begin(); i != langAuras.end(); ++i) { @@ -159,7 +160,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) } // but overwrite it by SPELL_AURA_MOD_LANGUAGE auras (only single case used) - Unit::AuraEffectList const& ModLangAuras = _player->GetAurasByType(SPELL_AURA_MOD_LANGUAGE); + Unit::AuraEffectList const& ModLangAuras = _player->GetAuraEffectsByType(SPELL_AURA_MOD_LANGUAGE); if(!ModLangAuras.empty()) lang = ModLangAuras.front()->GetMiscValue(); } diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 4bcf866632c..9795671ef22 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -47,6 +47,7 @@ #include "GameEventMgr.h" #include "CreatureGroups.h" #include "Vehicle.h" +#include "SpellAuraEffects.h" // apply implementation of the singletons #include "Policies/SingletonImp.h" @@ -142,7 +143,7 @@ m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formation(NULL) , m_AlreadySearchedAssistance(false) , m_creatureData(NULL), m_PlayerDamageReq(0) { - m_regenTimer = 2000; + m_regenTimer = CREATURE_REGEN_INTERVAL; m_valuesCount = UNIT_END; for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) @@ -571,12 +572,12 @@ void Creature::Update(uint32 diff) RegenerateMana(); /*if(!bIsPolymorphed) // only increase the timer if not polymorphed - m_regenTimer += 2000 - diff; + m_regenTimer += CREATURE_REGEN_INTERVAL - diff; } else if(!bIsPolymorphed) // if polymorphed, skip the timer m_regenTimer -= diff;*/ - m_regenTimer = 2000; + m_regenTimer = CREATURE_REGEN_INTERVAL; break; } case DEAD_FALLING: @@ -611,6 +612,14 @@ void Creature::RegenerateMana() else addvalue = maxValue/3; + // Apply modifiers (if any). + AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); + for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) + if ((*i)->GetMiscValue() == POWER_MANA) + addvalue *= ((*i)->GetAmount() + 100) / 100.0f; + + addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) * CREATURE_REGEN_INTERVAL / (5 * IN_MILISECONDS); + ModifyPower(POWER_MANA, addvalue); } @@ -641,6 +650,13 @@ void Creature::RegenerateHealth() else addvalue = maxValue/3; + // Apply modifiers (if any). + AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); + for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) + addvalue *= ((*i)->GetAmount() + 100) / 100.0f; + + addvalue += GetTotalAuraModifier(SPELL_AURA_MOD_REGEN) * CREATURE_REGEN_INTERVAL / (5 * IN_MILISECONDS); + ModifyHealth(addvalue); } @@ -1988,16 +2004,16 @@ bool Creature::LoadCreaturesAddon(bool reload) } // skip already applied aura - if(HasAuraEffect(cAura->spell_id,cAura->effect_idx)) + if(HasAura(cAura->spell_id)) { if(!reload) - sLog.outErrorDb("Creature (GUID: %u Entry: %u) has duplicate aura (spell %u effect %u) in `auras` field.",GetGUIDLow(),GetEntry(),cAura->spell_id,cAura->effect_idx); + sLog.outErrorDb("Creature (GUID: %u Entry: %u) has duplicate aura (spell %u) in `auras` field.",GetGUIDLow(),GetEntry(),cAura->spell_id); continue; } - AddAuraEffect(AdditionalSpellInfo, cAura->effect_idx, this, this); - sLog.outDebug("Spell: %u with Aura %u added to creature (GUID: %u Entry: %u)", cAura->spell_id, AdditionalSpellInfo->EffectApplyAuraName[cAura->effect_idx],GetGUIDLow(),GetEntry()); + AddAura(AdditionalSpellInfo, cAura->effectMask, this); + sLog.outDebug("Spell: %u with AuraEffectMask %u added to creature (GUID: %u Entry: %u)", cAura->spell_id, cAura->effectMask,GetGUIDLow(),GetEntry()); } } return true; diff --git a/src/game/Creature.h b/src/game/Creature.h index efe77737dcd..2ec18efbcff 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -64,6 +64,7 @@ enum CreatureFlagsExtra #endif #define MAX_KILL_CREDIT 2 +#define CREATURE_REGEN_INTERVAL 2 * IN_MILISECONDS // from `creature_template` table struct CreatureInfo @@ -241,7 +242,7 @@ struct CreatureData struct CreatureDataAddonAura { uint32 spell_id; - uint8 effect_idx; + uint8 effectMask; }; // from `creature_addon` table diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index ce2c7098623..c0b713c0d5a 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -121,6 +121,9 @@ class TRINITY_DLL_SPEC CreatureAI : public UnitAI // Called when spell hits a target virtual void SpellHitTarget(Unit* target, const SpellEntry*) {} + // Called to get trigger target for aura effect + virtual Unit * GetAuraEffectTriggerTarget(uint32 spellId, uint8 effIndex) {return NULL;} + // Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc) //virtual void AttackedBy(Unit* attacker); virtual bool IsEscorted() { return false; } diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 3bef84e87b4..2f64a75ca7b 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -295,7 +295,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction { //Note: checked only aura for effect 0, if need check aura for effect 1/2 then // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx) - Aura* aura = m_creature->GetAura(event.buffed.spellId,0); + Aura const * aura = m_creature->GetAura(event.buffed.spellId); if(!aura || aura->GetStackAmount() < event.buffed.amount) return false; @@ -311,7 +311,7 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction //Note: checked only aura for effect 0, if need check aura for effect 1/2 then // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx) - Aura* aura = pActionInvoker->GetAura(event.buffed.spellId,0); + Aura const * aura = m_creature->GetAura(event.buffed.spellId); if(!aura || aura->GetStackAmount() < event.buffed.amount) return false; diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 9f84cda3155..b8663bbcd0a 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1342,6 +1342,7 @@ struct SoundEntriesEntry }; #define MAX_SPELL_EFFECTS 3 +#define MAX_EFFECT_MASK 7 struct SpellEntry { diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index 1cd85fa0946..6105ece654e 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -36,6 +36,9 @@ DynamicObject::DynamicObject() : WorldObject() m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_POSITION); m_valuesCount = DYNAMICOBJECT_END; + + m_aura = 0; + m_duration = 0; } void DynamicObject::AddToWorld() @@ -70,13 +73,13 @@ void DynamicObject::RemoveFromWorld() } } -bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, uint32 effMask, const Position &pos, int32 duration, float radius, bool active) +bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, const Position &pos, float radius, bool active) { SetMap(caster->GetMap()); Relocate(pos); if(!IsPositionValid()) { - sLog.outError("DynamicObject (spell %u eff %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",spellId,effMask,GetPositionX(),GetPositionY()); + sLog.outError("DynamicObject (spell %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)",spellId,GetPositionX(),GetPositionY()); return false; } @@ -85,17 +88,11 @@ bool DynamicObject::Create(uint32 guidlow, Unit *caster, uint32 spellId, uint32 SetEntry(spellId); SetFloatValue( OBJECT_FIELD_SCALE_X, 1 ); SetUInt64Value( DYNAMICOBJECT_CASTER, caster->GetGUID() ); - SetUInt32Value( DYNAMICOBJECT_BYTES, 0x00000001 ); + SetUInt32Value( DYNAMICOBJECT_BYTES, 0x00000001 ); // effectMask? SetUInt32Value( DYNAMICOBJECT_SPELLID, spellId ); - SetFloatValue( DYNAMICOBJECT_RADIUS, radius); + SetFloatValue( DYNAMICOBJECT_RADIUS, radius ); SetUInt32Value( DYNAMICOBJECT_CASTTIME, getMSTime() ); // new 2.4.0 - m_aliveDuration = duration; - m_radius = radius; - m_effMask = effMask; - m_spellId = spellId; - m_updateTimer = 0; - m_isWorldObject = active; return true; } @@ -116,45 +113,25 @@ void DynamicObject::Update(uint32 p_time) return; } - bool deleteThis = false; + bool expired = false; - if(m_aliveDuration > int32(p_time)) - m_aliveDuration -= p_time; - else - deleteThis = true; - - /* - // have radius and work as persistent effect - if(m_radius) + if (m_aura) { - // TODO: make a timer and update this in larger intervals - CellPair p(Trinity::ComputeCellPair(GetPositionX(), GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::DynamicObjectUpdater notifier(*this, caster); + if (!m_aura->IsRemoved()) + m_aura->UpdateOwner(p_time, this); - TypeContainerVisitor<Trinity::DynamicObjectUpdater, WorldTypeMapContainer > world_object_notifier(notifier); - TypeContainerVisitor<Trinity::DynamicObjectUpdater, GridTypeMapContainer > grid_object_notifier(notifier); - - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_object_notifier, *GetMap(), *this, m_radius); - cell_lock->Visit(cell_lock, grid_object_notifier, *GetMap(), *this, m_radius); + if (m_aura->IsRemoved() || m_aura->IsExpired()) + expired = true; } - */ - - if (m_effMask) + else { - if (m_updateTimer < p_time) - { - Trinity::DynamicObjectUpdater notifier(*this,caster); - VisitNearbyObject(GetRadius(), notifier); - m_updateTimer = 500; // is this official-like? - } else m_updateTimer -= p_time; + if(GetDuration() > int32(p_time)) + m_duration -= p_time; + else + expired = true; } - if (deleteThis) + if (expired) { caster->RemoveDynObjectWithGUID(GetGUID()); Delete(); @@ -163,21 +140,43 @@ void DynamicObject::Update(uint32 p_time) void DynamicObject::Delete() { + if (m_aura) + { + // dynObj may be removed in Aura::Remove - we cannot delete there + // so recheck aura here + if (!m_aura->IsRemoved()) + m_aura->_Remove(AURA_REMOVE_BY_DEFAULT); + delete m_aura; + m_aura = NULL; + } SendObjectDeSpawnAnim(GetGUID()); RemoveFromWorld(); AddObjectToRemoveList(); } +int32 DynamicObject::GetDuration() const +{ + if (!m_aura) + return m_duration; + else + return m_aura->GetDuration(); +} + +void DynamicObject::SetDuration(int32 newDuration) +{ + if (!m_aura) + m_duration = newDuration; + else + m_aura->SetDuration(newDuration); +} + void DynamicObject::Delay(int32 delaytime) { - m_aliveDuration -= delaytime; - for (AffectedSet::iterator iunit = m_affected.begin(); iunit != m_affected.end(); ++iunit) - if (*iunit) - (*iunit)->DelayAura(m_spellId, GetCaster()->GetGUID(), delaytime); + SetDuration(GetDuration() - delaytime); } bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const { return IsInWorld() && u->IsInWorld() && (IsWithinDistInMap(u->m_seer,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false)); -} +}
\ No newline at end of file diff --git a/src/game/DynamicObject.h b/src/game/DynamicObject.h index 11cf030a6c6..de94b5877bd 100644 --- a/src/game/DynamicObject.h +++ b/src/game/DynamicObject.h @@ -24,32 +24,28 @@ #include "Object.h" class Unit; +class Aura; struct SpellEntry; class DynamicObject : public WorldObject, public GridObject<DynamicObject> { public: - typedef std::set<Unit*> AffectedSet; explicit DynamicObject(); void AddToWorld(); void RemoveFromWorld(); - bool Create(uint32 guidlow, Unit *caster, uint32 spellId, uint32 effMask, const Position &pos, int32 duration, float radius, bool active); + bool Create(uint32 guidlow, Unit *caster, uint32 spellId, const Position &pos, float radius, bool active); void Update(uint32 p_time); void Delete(); - uint32 GetSpellId() const { return m_spellId; } - uint32 GetEffectMask() const { return m_effMask; } - void AddEffect(uint32 effIndex) { m_effMask |= (1<<effIndex); } - bool HasEffect(uint32 effIndex) const { return m_effMask & (1<<effIndex); } - uint32 GetDuration() const { return m_aliveDuration; } + void SetDuration(int32 newDuration); + int32 GetDuration() const; + void SetAura(Aura * aura) {assert (!m_aura && aura); m_aura = aura;} + void Delay(int32 delaytime); + uint32 GetSpellId() const { return GetUInt32Value(DYNAMICOBJECT_SPELLID); } uint64 GetCasterGUID() const { return GetUInt64Value(DYNAMICOBJECT_CASTER); } + float GetRadius() const { return GetFloatValue(DYNAMICOBJECT_RADIUS); } Unit* GetCaster() const; - float GetRadius() const { return m_radius; } - bool IsAffecting(Unit *unit) const { return m_affected.find(unit) != m_affected.end(); } - void AddAffected(Unit *unit) { m_affected.insert(unit); } - void RemoveAffected(Unit *unit) { m_affected.erase(unit); } - void Delay(int32 delaytime); bool isVisibleForInState(Player const* u, bool inVisibleList) const; void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } @@ -59,11 +55,7 @@ class DynamicObject : public WorldObject, public GridObject<DynamicObject> void YellToZone(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYellToZone(textId,language,TargetGuid); } protected: - uint32 m_spellId; - uint32 m_effMask; - int32 m_aliveDuration; - uint32 m_updateTimer; - float m_radius; - AffectedSet m_affected; + int32 m_duration; // for non-aura dynobjects + Aura * m_aura; }; -#endif +#endif
\ No newline at end of file diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index f5d7b988fca..ca7844db21b 100644 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -221,27 +221,6 @@ namespace Trinity template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {} }; - struct TRINITY_DLL_DECL DynamicObjectUpdater - { - DynamicObject &i_dynobject; - Unit* i_check; - DynamicObjectUpdater(DynamicObject &dynobject, Unit* caster) : i_dynobject(dynobject) - { - i_check = caster; - Unit* owner = i_check->GetOwner(); - if(owner) - i_check = owner; - } - - template<class T> inline void Visit(GridRefManager<T> &) {} - #ifdef WIN32 - template<> inline void Visit<Player>(PlayerMapType &); - template<> inline void Visit<Creature>(CreatureMapType &); - #endif - - void VisitHelper(Unit* target); - }; - // SEARCHERS & LIST SEARCHERS & WORKERS // WorldObject searchers & workers @@ -1292,8 +1271,6 @@ namespace Trinity template<> inline void PlayerRelocationNotifier::Visit<Creature>(CreatureMapType &); template<> inline void CreatureRelocationNotifier::Visit<Player>(PlayerMapType &); template<> inline void CreatureRelocationNotifier::Visit<Creature>(CreatureMapType &); - template<> inline void DynamicObjectUpdater::Visit<Creature>(CreatureMapType &); - template<> inline void DynamicObjectUpdater::Visit<Player>(PlayerMapType &); #endif } #endif diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index c19dc66139c..6f8b191d551 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -170,92 +170,6 @@ Trinity::CreatureRelocationNotifier::Visit(CreatureMapType &m) } } -inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target) -{ - if(!target->isAlive() || target->isInFlight() ) - return; - - if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) - return; - - if (!i_dynobject.IsWithinDistInMap(target, i_dynobject.GetRadius())) - return; - - //Check targets for not_selectable unit flag and remove - if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) - return; - - // Evade target - if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->IsInEvadeMode() ) - return; - - //Check player targets and remove if in GM mode or GM invisibility (for not self casting case) - if( target->GetTypeId() == TYPEID_PLAYER && target != i_check && (((Player*)target)->isGameMaster() || ((Player*)target)->GetVisibility()==VISIBILITY_OFF) ) - return; - - if (i_dynobject.IsAffecting(target)) - return; - - if(target->HasAura(i_dynobject.GetSpellId(), i_check->GetGUID())) - return; - - uint32 eff_index = 0; - for (; eff_index < MAX_SPELL_EFFECTS; ++eff_index) - if(i_dynobject.HasEffect(eff_index)) - break; - - if(eff_index == MAX_SPELL_EFFECTS) - return; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId()); - if(spellInfo->EffectImplicitTargetB[eff_index] == TARGET_DEST_DYNOBJ_ALLY - || spellInfo->EffectImplicitTargetB[eff_index] == TARGET_UNIT_AREA_ALLY_DST) - { - if(!i_check->IsFriendlyTo(target)) - return; - } - else if( i_check->GetTypeId() == TYPEID_PLAYER ) - { - if (i_check->IsFriendlyTo( target )) - return; - - i_check->CombatStart(target); - } - else - { - if (!i_check->IsHostileTo( target )) - return; - - i_check->CombatStart(target); - } - - // Check target immune to spell or aura - if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo, eff_index)) - return; - - // Apply PersistentAreaAura on target - Aura *aur = new Aura(spellInfo, i_dynobject.GetEffectMask(), target, &i_dynobject, i_check); - aur->SetAuraDuration(i_dynobject.GetDuration()); - if(target->AddAura(aur, true)) - i_dynobject.AddAffected(target); -} - -template<> -inline void -Trinity::DynamicObjectUpdater::Visit(CreatureMapType &m) -{ - for (CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - VisitHelper(itr->getSource()); -} - -template<> -inline void -Trinity::DynamicObjectUpdater::Visit(PlayerMapType &m) -{ - for (PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - VisitHelper(itr->getSource()); -} - // SEARCHERS & LIST SEARCHERS & WORKERS // WorldObject searchers & workers diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index ef7cee5cfa4..c074d275614 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -703,8 +703,8 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke { if(auramask & (uint64(1) << i)) { - Aura * pAura = player->GetVisibleAura(i); - *data << uint32(pAura ? pAura->GetId() : 0); + AuraApplication const * aurApp = player->GetVisibleAura(i); + *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } @@ -785,8 +785,8 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke { if(auramask & (uint64(1) << i)) { - Aura * pAura = pet->GetVisibleAura(i); - *data << uint32(pAura ? pAura->GetId() : 0); + AuraApplication const * aurApp = player->GetVisibleAura(i); + *data << uint32(aurApp ? aurApp->GetBase()->GetId() : 0); *data << uint8(1); } } @@ -843,10 +843,10 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) auramask; // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { - if(Aura * pAura = player->GetVisibleAura(i)) + if(AuraApplication * aurApp = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); - data << (uint32) pAura->GetId(); + data << (uint32) aurApp->GetBase()->GetId(); data << (uint8) 1; } } @@ -869,10 +869,10 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) petauramask; // placeholder for (uint8 i = 0; i < MAX_AURAS; ++i) { - if(Aura * pAura = pet->GetVisibleAura(i)) + if(AuraApplication * auraApp = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); - data << (uint32) pAura->GetId(); + data << (uint32) auraApp->GetBase()->GetId(); data << (uint8) 1; } } diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index d616a93e2d6..7aee776c710 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -54,6 +54,7 @@ #include "InstanceData.h" #include "AuctionHouseBot.h" #include "CreatureEventAIMgr.h" +#include "SpellAuraEffects.h" #include "DBCEnums.h" bool ChatHandler::HandleAHBotOptionsCommand(const char *args) @@ -4387,25 +4388,8 @@ bool ChatHandler::HandleAuraCommand(const char *args) // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellID = extractSpellIdFromLink((char*)args); - SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellID ); - uint8 eff_mask=0; - if(spellInfo) - { - for (uint32 i = 0; i<3; ++i) - { - uint8 eff = spellInfo->Effect[i]; - if (eff>=TOTAL_SPELL_EFFECTS) - continue; - if( IsAreaAuraEffect(eff) || - eff == SPELL_EFFECT_APPLY_AURA || - eff == SPELL_EFFECT_PERSISTENT_AREA_AURA ) - { - eff_mask|=1<<i; - } - } - Aura *Aur = new Aura(spellInfo, eff_mask, target, target, target); - target->AddAura(Aur); - } + if (SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellID )) + Aura::TryCreate(spellInfo, target, target); return true; } @@ -5117,39 +5101,41 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/) char const* talentStr = GetTrinityString(LANG_TALENT); char const* passiveStr = GetTrinityString(LANG_PASSIVE); - Unit::AuraMap const& uAuras = unit->GetAuras(); + Unit::AuraApplicationMap const& uAuras = unit->GetAppliedAuras(); PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size()); - for (Unit::AuraMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) + for (Unit::AuraApplicationMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) { - bool talent = GetTalentSpellCost(itr->second->GetId()) > 0; + bool talent = GetTalentSpellCost(itr->second->GetBase()->GetId()) > 0; - char const* name = itr->second->GetSpellProto()->SpellName[GetSessionDbcLocale()]; + AuraApplication const * aurApp = itr->second; + Aura const * aura = aurApp->GetBase(); + char const* name = aura->GetSpellProto()->SpellName[GetSessionDbcLocale()]; if (m_session) { std::ostringstream ss_name; - ss_name << "|cffffffff|Hspell:" << itr->second->GetId() << "|h[" << name << "]|h|r"; + ss_name << "|cffffffff|Hspell:" << aura->GetId() << "|h[" << name << "]|h|r"; - PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffectMask(), - itr->second->GetAuraCharges(), itr->second->GetStackAmount(),itr->second->GetAuraSlot(), - itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(), + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), aurApp->GetEffectMask(), + aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), + aura->GetDuration(), aura->GetMaxDuration(), ss_name.str().c_str(), - (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), - IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID())); + (aura->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(aura->GetCasterGUID())); } else { - PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffectMask(), - itr->second->GetAuraCharges(), itr->second->GetStackAmount(),itr->second->GetAuraSlot(), - itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(), + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, aura->GetId(), aurApp->GetEffectMask(), + aura->GetCharges(), aura->GetStackAmount(), aurApp->GetSlot(), + aura->GetDuration(), aura->GetMaxDuration(), name, - (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), - IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID())); + (aura->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(aura->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(aura->GetCasterGUID())); } } for (uint16 i = 0; i < TOTAL_AURAS; ++i) { - Unit::AuraEffectList const& uAuraList = unit->GetAurasByType(AuraType(i)); + Unit::AuraEffectList const& uAuraList = unit->GetAuraEffectsByType(AuraType(i)); if (uAuraList.empty()) continue; PSendSysMessage(LANG_COMMAND_TARGET_LISTAURATYPE, uAuraList.size(), i); for (Unit::AuraEffectList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) @@ -7376,9 +7362,8 @@ bool ChatHandler::HandleFreezeCommand(const char *args) } //m_session->GetPlayer()->CastSpell(player,spellID,false); - SpellEntry const *spellInfo = sSpellStore.LookupEntry( 9454 ); - Aura *Aur = new Aura(spellInfo, 1, player, player, player); - player->AddAura(Aur); + if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(9454)) + Aura::TryCreate(spellInfo, player, player); //save player player->SaveToDB(); diff --git a/src/game/Object.cpp b/src/game/Object.cpp index ca622edb9c6..2d08dfe6110 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -42,6 +42,7 @@ #include "CellImpl.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" +#include "SpellAuraEffects.h" #include "TemporarySummon.h" #include "Totem.h" @@ -1805,7 +1806,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy if(petType == SUMMON_PET && pet->LoadPetFromDB(this, entry)) { // Remove Demonic Sacrifice auras (known pet) - Unit::AuraEffectList const& auraClassScripts = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + Unit::AuraEffectList const& auraClassScripts = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (Unit::AuraEffectList::const_iterator itr = auraClassScripts.begin(); itr!=auraClassScripts.end();) { if((*itr)->GetMiscValue()==2228) @@ -1886,7 +1887,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy if(petType == SUMMON_PET) { // Remove Demonic Sacrifice auras (known pet) - Unit::AuraEffectList const& auraClassScripts = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + Unit::AuraEffectList const& auraClassScripts = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (Unit::AuraEffectList::const_iterator itr = auraClassScripts.begin(); itr!=auraClassScripts.end();) { if((*itr)->GetMiscValue()==2228) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 4197f52c689..7faca78d73a 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -781,27 +781,40 @@ void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* { // Now add the auras, format "spellid effectindex spellid effectindex..." char *p,*s; - std::vector<int> val; + std::map<uint32, uint32> val; s=p=(char*)reinterpret_cast<char const*>(addon->auras); if(p) { + uint32 currSpellId = 0; + bool spell = true; while (p[0]!=0) { ++p; - if (p[0]==' ') + if (p[0] == ' ' || p[0] == 0) { - val.push_back(atoi(s)); + if (spell) + currSpellId = atoi(s); + else + { + uint8 eff = atoi(s); + if (eff >=3) + { + sLog.outErrorDb("Creature (%s: %u) has wrong `auras` data in `%s`(too high aura effect: %d for spell: %d)",guidEntryStr,addon->guidOrEntry,table,eff,currSpellId); + } + val[currSpellId] |= 1<<eff; + } + spell = !spell; + if (p[0] == 0) + break; s=++p; } } - if (p!=s) - val.push_back(atoi(s)); // free char* loaded memory delete[] (char*)reinterpret_cast<char const*>(addon->auras); // wrong list - if (val.size()%2) + if (!spell) { addon->auras = NULL; sLog.outErrorDb("Creature (%s: %u) has wrong `auras` data in `%s`.",guidEntryStr,addon->guidOrEntry,table); @@ -817,17 +830,17 @@ void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* } // replace by new structures array - const_cast<CreatureDataAddonAura*&>(addon->auras) = new CreatureDataAddonAura[val.size()/2+1]; + const_cast<CreatureDataAddonAura*&>(addon->auras) = new CreatureDataAddonAura[val.size()+1]; uint32 i=0; - for (uint32 j = 0; j < val.size()/2; ++j) + for (std::map<uint32, uint32>::iterator itr = val.begin(); itr!=val.end();++itr) { CreatureDataAddonAura& cAura = const_cast<CreatureDataAddonAura&>(addon->auras[i]); - cAura.spell_id = (uint32)val[2*j+0]; - cAura.effect_idx = (uint32)val[2*j+1]; - if ( cAura.effect_idx > 2 ) + cAura.spell_id = itr->first; + cAura.effectMask = itr->second; + if ( cAura.effectMask > 7 || !cAura.effectMask) { - sLog.outErrorDb("Creature (%s: %u) has wrong effect %u for spell %u in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.effect_idx,cAura.spell_id,table); + sLog.outErrorDb("Creature (%s: %u) has wrong effect for spell %u in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.spell_id,table); continue; } SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(cAura.spell_id); @@ -836,11 +849,21 @@ void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* sLog.outErrorDb("Creature (%s: %u) has wrong spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.spell_id,table); continue; } - - if (!AdditionalSpellInfo->Effect[cAura.effect_idx] || !AdditionalSpellInfo->EffectApplyAuraName[cAura.effect_idx]) + for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) { - sLog.outErrorDb("Creature (%s: %u) has not aura effect %u of spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,cAura.effect_idx,cAura.spell_id,table); - continue; + if ((1<<eff) & cAura.effectMask) + { + if (!AdditionalSpellInfo->Effect[eff] || !AdditionalSpellInfo->EffectApplyAuraName[eff]) + { + sLog.outErrorDb("Creature (%s: %u) has not aura effect %u of spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,eff,cAura.spell_id,table); + continue; + } + else if (AdditionalSpellInfo->Effect[eff] == SPELL_EFFECT_PERSISTENT_AREA_AURA) + { + sLog.outErrorDb("Creature (%s: %u) has persistent area aura effect %u of spell %u defined in `auras` field in `%s`.",guidEntryStr,addon->guidOrEntry,eff,cAura.spell_id,table); + continue; + } + } } ++i; @@ -849,7 +872,7 @@ void ObjectMgr::ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* // fill terminator element (after last added) CreatureDataAddonAura& endAura = const_cast<CreatureDataAddonAura&>(addon->auras[i]); endAura.spell_id = 0; - endAura.effect_idx = 0; + endAura.effectMask = 0; } void ObjectMgr::LoadCreatureAddons(SQLStorage& creatureaddons, char const* entryName, char const* comment) @@ -7641,9 +7664,9 @@ bool PlayerCondition::Meets(Player const * player) const } case CONDITION_AD_COMMISSION_AURA: { - Unit::AuraMap const& auras = player->GetAuras(); - for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual[0]==3580) + Unit::AuraApplicationMap const& auras = player->GetAppliedAuras(); + for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + if((itr->second->GetBase()->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetBase()->GetSpellProto()->SpellVisual[0]==3580) return true; return false; } diff --git a/src/game/OutdoorPvPWG.cpp b/src/game/OutdoorPvPWG.cpp index 27a9a026f79..2fbf5359a40 100644 --- a/src/game/OutdoorPvPWG.cpp +++ b/src/game/OutdoorPvPWG.cpp @@ -1078,7 +1078,7 @@ void OutdoorPvPWG::HandlePlayerLeaveZone(Player * plr, uint32 zone) void OutdoorPvPWG::PromotePlayer(Player *killer) const { - Aura *aur; + Aura * aur; if (aur = killer->GetAura(SPELL_RECRUIT)) { if (aur->GetStackAmount() >= 5) diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 8cee92c485e..71827be8bc9 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -27,6 +27,7 @@ #include "Pet.h" #include "Formulas.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" #include "CreatureAI.h" #include "Unit.h" #include "Util.h" @@ -57,7 +58,7 @@ m_declinedname(NULL), m_owner(owner) } m_name = "Pet"; - m_regenTimer = 4000; + m_regenTimer = PET_FOCUS_REGEN_INTERVAL; m_isWorldObject = true; } @@ -553,13 +554,13 @@ void Pet::Update(uint32 diff) { case POWER_FOCUS: Regenerate(POWER_FOCUS); - m_regenTimer += 4000 - diff; + m_regenTimer += PET_FOCUS_REGEN_INTERVAL - diff; if(!m_regenTimer) ++m_regenTimer; break; // in creature::update //case POWER_ENERGY: // Regenerate(POWER_ENERGY); - // m_regenTimer += 2000 - diff; + // m_regenTimer += CREATURE_REGEN_INTERVAL - diff; // if(!m_regenTimer) ++m_regenTimer; // break; default: @@ -617,11 +618,13 @@ void Creature::Regenerate(Powers power) } // Apply modifiers (if any). - AuraEffectList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); + AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) if ((*i)->GetMiscValue() == power) addvalue *= ((*i)->GetAmount() + 100) / 100.0f; + addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, power) * (isHunterPet()? PET_FOCUS_REGEN_INTERVAL : CREATURE_REGEN_INTERVAL) / (5 * IN_MILISECONDS); + ModifyPower(power, (int32)addvalue); } @@ -1154,24 +1157,29 @@ void Pet::_LoadAuras(uint32 timediff) { sLog.outDebug("Loading auras for pet %u",GetGUIDLow()); - QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_mask,stackcount,amount0,amount1,amount2,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber()); + QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber()); if (result) { do { int32 damage[3]; + int32 baseDamage[3]; Field *fields = result->Fetch(); uint64 caster_guid = fields[0].GetUInt64(); uint32 spellid = fields[1].GetUInt32(); uint8 effmask = fields[2].GetUInt8(); - uint8 stackcount = fields[3].GetUInt8(); - damage[0] = fields[4].GetInt32(); - damage[1] = fields[5].GetInt32(); - damage[2] = fields[6].GetInt32(); - int32 maxduration = fields[7].GetInt32(); - int32 remaintime = fields[8].GetInt32(); - uint8 remaincharges = fields[9].GetUInt8(); + uint8 recalculatemask = fields[3].GetUInt8(); + uint8 stackcount = fields[4].GetUInt8(); + damage[0] = fields[5].GetInt32(); + damage[1] = fields[6].GetInt32(); + damage[2] = fields[7].GetInt32(); + baseDamage[0] = fields[8].GetInt32(); + baseDamage[1] = fields[9].GetInt32(); + baseDamage[2] = fields[10].GetInt32(); + int32 maxduration = fields[11].GetInt32(); + int32 remaintime = fields[12].GetInt32(); + uint8 remaincharges = fields[13].GetUInt8(); SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid); if(!spellproto) @@ -1198,15 +1206,17 @@ void Pet::_LoadAuras(uint32 timediff) else remaincharges = 0; - Aura* aura = new Aura(spellproto, effmask, this, this, this); - aura->SetLoadedState(caster_guid,maxduration,remaintime,remaincharges, stackcount, &damage[0]); - if(!aura->CanBeSaved()) + if (Aura * aura = Aura::TryCreate( spellproto, effmask, this, NULL, &baseDamage[0], NULL, caster_guid)) { - delete aura; - continue; + if (!aura->CanBeSaved()) + { + aura->Remove(); + continue; + } + aura->SetLoadedState(maxduration,remaintime,remaincharges,stackcount,recalculatemask,&damage[0]); + aura->ApplyForTargets(); + sLog.outDetail("Added aura spellid %u, effectmask %u", spellproto->Id, effmask); } - AddAura(aura); - sLog.outDetail("Added aura spellid %u, effectmask %u", spellproto->Id, effmask); } while (result->NextRow()); @@ -1218,26 +1228,39 @@ void Pet::_SaveAuras() { CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber()); - AuraMap const& auras = GetAuras(); - for (AuraMap::const_iterator itr = auras.begin(); itr !=auras.end() ; ++itr) + for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end() ; ++itr) { if (!itr->second->CanBeSaved()) continue; - int32 amounts[MAX_SPELL_EFFECTS]; + Aura * aura = itr->second; + + int32 damage[MAX_SPELL_EFFECTS]; + int32 baseDamage[MAX_SPELL_EFFECTS]; + uint8 effMask = 0; + uint8 recalculateMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (AuraEffect *partAura = itr->second->GetPartAura(i)) - amounts[i] = partAura->GetAmount(); + if (aura->GetEffect(i)) + { + baseDamage[i] = aura->GetEffect(i)->GetBaseAmount(); + damage[i] = aura->GetEffect(i)->GetAmount(); + effMask |= (1<<i); + if (aura->GetEffect(i)->CanBeRecalculated()) + recalculateMask |= (1<<i); + } else - amounts[i] = 0; + { + baseDamage[i] = NULL; + damage[i] = NULL; + } } - CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_mask,stackcount,amount0,amount1,amount2,maxduration,remaintime,remaincharges) " - "VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%u')", - m_charmInfo->GetPetNumber(), itr->second->GetCasterGUID(), itr->second->GetId(), itr->second->GetEffectMask(), - itr->second->GetStackAmount(), amounts[0], amounts[1], amounts[2], - itr->second->GetAuraMaxDuration(), itr->second->GetAuraDuration(),itr->second->GetAuraCharges()); + CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges) " + "VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u')", + m_charmInfo->GetPetNumber(), itr->second->GetCasterGUID(), itr->second->GetId(), effMask, recalculateMask, + itr->second->GetStackAmount(), damage[0], damage[1], damage[2], baseDamage[0], baseDamage[1], baseDamage[2], + itr->second->GetMaxDuration(), itr->second->GetDuration(),itr->second->GetCharges()); } } diff --git a/src/game/Pet.h b/src/game/Pet.h index 17df70b0a65..7c1334c4b56 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -118,6 +118,7 @@ typedef std::vector<uint32> AutoSpellList; #define PET_FOLLOW_DIST 1 #define PET_FOLLOW_ANGLE (M_PI/2) +#define PET_FOCUS_REGEN_INTERVAL 4 * IN_MILISECONDS class Player; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 03078a35b3e..1f94d5a78fd 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -65,6 +65,7 @@ #include "GameEventMgr.h" #include "AchievementMgr.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" #include <cmath> @@ -945,7 +946,7 @@ int32 Player::getMaxTimer(MirrorTimerType timer) if (!isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) return DISABLED_MIRROR_TIMER; int32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS; - AuraEffectList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING); + AuraEffectList const& mModWaterBreathing = GetAuraEffectsByType(SPELL_AURA_MOD_WATER_BREATHING); for (AuraEffectList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetAmount()) / 100.0f); return UnderWaterTime; @@ -2022,14 +2023,12 @@ void Player::RegenerateAll() HasAuraType(SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT) || IsPolymorphed() ) { RegenerateHealth(); - if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) - { - Regenerate(POWER_RAGE); - if (getClass() == CLASS_DEATH_KNIGHT) - Regenerate(POWER_RUNIC_POWER); - } } + Regenerate(POWER_RAGE); + if (getClass() == CLASS_DEATH_KNIGHT) + Regenerate(POWER_RUNIC_POWER); + if(getClass() == CLASS_DEATH_KNIGHT) Regenerate(POWER_RUNE); @@ -2051,18 +2050,6 @@ void Player::Regenerate(Powers power) return; uint32 curValue = GetPower(power); - switch (power) - { - case POWER_RAGE: - case POWER_RUNIC_POWER: - if (curValue == 0) - return; - break; - default: - if (curValue == maxValue) - return; - break; - } // TODO: possible use of miscvalueb instead of amount if (HasAuraTypeWithValue(SPELL_AURA_PREVENT_REGENERATE_POWER, power)) @@ -2077,22 +2064,28 @@ void Player::Regenerate(Powers power) bool recentCast = IsUnderLastManaUseEffect(); float ManaIncreaseRate = sWorld.getRate(RATE_POWER_MANA); if (recentCast) // Trinity Updates Mana in intervals of 2s, which is correct - addvalue = GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * 0.001f * m_regenTimer; + addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * 0.001f * m_regenTimer; else - addvalue = GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * 0.001f * m_regenTimer; + addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * 0.001f * m_regenTimer; } break; case POWER_RAGE: // Regenerate rage { - float RageDecreaseRate = sWorld.getRate(RATE_POWER_RAGE_LOSS); - addvalue = 20 * RageDecreaseRate; // 2 rage by tick (= 2 seconds => 1 rage/sec) + if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) + { + float RageDecreaseRate = sWorld.getRate(RATE_POWER_RAGE_LOSS); + addvalue += -20 * RageDecreaseRate; // 2 rage by tick (= 2 seconds => 1 rage/sec) + } } break; case POWER_ENERGY: // Regenerate energy (rogue) - addvalue = 0.01f * m_regenTimer; + addvalue += 0.01f * m_regenTimer; break; case POWER_RUNIC_POWER: { - float RunicPowerDecreaseRate = sWorld.getRate(RATE_POWER_RUNICPOWER_LOSS); - addvalue = 30 * RunicPowerDecreaseRate; // 3 RunicPower by tick + if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) + { + float RunicPowerDecreaseRate = sWorld.getRate(RATE_POWER_RUNICPOWER_LOSS); + addvalue += -30 * RunicPowerDecreaseRate; // 3 RunicPower by tick + } } break; case POWER_RUNE: case POWER_FOCUS: @@ -2102,44 +2095,58 @@ void Player::Regenerate(Powers power) } // Mana regen calculated in Player::UpdateManaRegen() - // Exist only for POWER_MANA, POWER_ENERGY, POWER_FOCUS auras if (power != POWER_MANA) { - AuraEffectList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); + AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) if ((*i)->GetMiscValue() == power) addvalue *= ((*i)->GetAmount() + 100) / 100.0f; + + // Butchery requires combat for this effect + if (power != POWER_RUNIC_POWER || isInCombat()) + addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, power) * ((power != POWER_ENERGY) ? m_regenTimerCount : m_regenTimer) / (5 * IN_MILISECONDS); } + if (addvalue < 0.0f) + { + if (curValue == 0) + return; + } + else if (addvalue > 0.0f) + { + if (curValue == maxValue) + return; + } + else + return; + addvalue += m_powerFraction[power]; - uint32 integerValue = uint32(addvalue); + uint32 integerValue = uint32(abs(addvalue)); - switch (power) + if (addvalue < 0.0f) { - case POWER_RAGE: - case POWER_RUNIC_POWER: - if(curValue > integerValue) - { - curValue -= integerValue; - m_powerFraction[power] = addvalue - integerValue; - } - else - { - curValue = 0; - m_powerFraction[power] = 0; - } - break; - default: - curValue += integerValue; + if(curValue > integerValue) + { + curValue -= integerValue; + m_powerFraction[power] = addvalue + integerValue; + } + else + { + curValue = 0; + m_powerFraction[power] = 0; + } + } + else + { + curValue += integerValue; - if (curValue > maxValue) - { - curValue = maxValue; - m_powerFraction[power] = 0; - } - else - m_powerFraction[power] = addvalue - integerValue; - break; + if (curValue > maxValue) + { + curValue = maxValue; + m_powerFraction[power] = 0; + } + else + m_powerFraction[power] = addvalue - integerValue; } if(m_regenTimerCount >= 2000) SetPower(power, curValue); @@ -2168,9 +2175,11 @@ void Player::RegenerateHealth() addvalue = OCTRegenHPPerSpirit()* HealthIncreaseRate; if (!isInCombat()) { - AuraEffectList const& mModHealthRegenPct = GetAurasByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); + AuraEffectList const& mModHealthRegenPct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); for (AuraEffectList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i) addvalue *= (100.0f + (*i)->GetAmount()) / 100.0f; + + addvalue += GetTotalAuraModifier(SPELL_AURA_MOD_REGEN) * 2 * IN_MILISECONDS / (5 * IN_MILISECONDS); } else if (HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT)) addvalue *= GetTotalAuraModifier(SPELL_AURA_MOD_REGEN_DURING_COMBAT) / 100.0f; @@ -2330,7 +2339,7 @@ void Player::SetGameMaster(bool on) else { // restore phase - AuraEffectList const& phases = GetAurasByType(SPELL_AURA_PHASE); + AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE); SetPhaseMask(!phases.empty() ? phases.front()->GetMiscValue() : PHASEMASK_NORMAL,false); m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON; @@ -4454,9 +4463,9 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) { int32 delta = (int32(getLevel()) - startLevel + 1)*MINUTE; - if(Aura* Aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS, GetGUID())) + if(Aura * aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS, GetGUID())) { - Aur->SetAuraDuration(delta*IN_MILISECONDS); + aur->SetDuration(delta*IN_MILISECONDS); } } } @@ -5194,10 +5203,10 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) int32 amount = uint32(m_baseRatingValue[cr]); // Apply bonus from SPELL_AURA_MOD_RATING_FROM_STAT // stat used stored in miscValueB for this aura - AuraEffectList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); + AuraEffectList const& modRatingFromStat = GetAuraEffectsByType(SPELL_AURA_MOD_RATING_FROM_STAT); for (AuraEffectList::const_iterator i = modRatingFromStat.begin(); i != modRatingFromStat.end(); ++i) if ((*i)->GetMiscValue() & (1<<cr)) - amount += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetAmount() / 100.0f); + amount += int32(GetStat(Stats((*i)->GetMiscValueB())) * (*i)->GetAmount() / 100.0f); if (amount < 0) amount = 0; SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, uint32(amount)); @@ -5723,16 +5732,16 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); // temporary bonuses - AuraEffectList const& mModSkill = GetAurasByType(SPELL_AURA_MOD_SKILL); + AuraEffectList const& mModSkill = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL); for (AuraEffectList::const_iterator j = mModSkill.begin(); j != mModSkill.end(); ++j) if ((*j)->GetMiscValue() == int32(id)) - (*j)->ApplyModifier(true); + (*j)->HandleEffect(this, 0, true); // permanent bonuses - AuraEffectList const& mModSkillTalent = GetAurasByType(SPELL_AURA_MOD_SKILL_TALENT); + AuraEffectList const& mModSkillTalent = GetAuraEffectsByType(SPELL_AURA_MOD_SKILL_TALENT); for (AuraEffectList::const_iterator j = mModSkillTalent.begin(); j != mModSkillTalent.end(); ++j) if ((*j)->GetMiscValue() == int32(id)) - (*j)->ApplyModifier(true); + (*j)->HandleEffect(this, 0, true); // Learn all spells for skill learnSkillRewardedSpells(id, currVal); @@ -6826,19 +6835,21 @@ void Player::DuelComplete(DuelCompleteType type) duel->initiator->RemoveGameObject(obj,true); /* remove auras */ - AuraMap &itsAuras = duel->opponent->GetAuras(); - for (AuraMap::iterator i = itsAuras.begin(); i != itsAuras.end();) + AuraApplicationMap &itsAuras = duel->opponent->GetAppliedAuras(); + for (AuraApplicationMap::iterator i = itsAuras.begin(); i != itsAuras.end();) { - if (!i->second->IsPositive() && i->second->GetCasterGUID() == GetGUID() && i->second->GetAuraApplyTime() >= duel->startTime) + Aura const * aura = i->second->GetBase(); + if (!i->second->IsPositive() && aura->GetCasterGUID() == GetGUID() && aura->GetApplyTime() >= duel->startTime) duel->opponent->RemoveAura(i); else ++i; } - AuraMap &myAuras = GetAuras(); - for (AuraMap::iterator i = myAuras.begin(); i != myAuras.end();) + AuraApplicationMap &myAuras = GetAppliedAuras(); + for (AuraApplicationMap::iterator i = myAuras.begin(); i != myAuras.end();) { - if (!i->second->IsPositive() && i->second->GetCasterGUID() == duel->opponent->GetGUID() && i->second->GetAuraApplyTime() >= duel->startTime) + Aura const * aura = i->second->GetBase(); + if (!i->second->IsPositive() && aura->GetCasterGUID() == duel->opponent->GetGUID() && aura->GetApplyTime() >= duel->startTime) RemoveAura(i); else ++i; @@ -7215,20 +7226,20 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl void Player::_ApplyWeaponDependentAuraMods(Item *item,WeaponAttackType attackType,bool apply) { - AuraEffectList const& auraCritList = GetAurasByType(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); + AuraEffectList const& auraCritList = GetAuraEffectsByType(SPELL_AURA_MOD_WEAPON_CRIT_PERCENT); for (AuraEffectList::const_iterator itr = auraCritList.begin(); itr!=auraCritList.end(); ++itr) _ApplyWeaponDependentAuraCritMod(item,attackType,*itr,apply); - AuraEffectList const& auraDamageFlatList = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE); + AuraEffectList const& auraDamageFlatList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE); for (AuraEffectList::const_iterator itr = auraDamageFlatList.begin(); itr!=auraDamageFlatList.end(); ++itr) _ApplyWeaponDependentAuraDamageMod(item,attackType,*itr,apply); - AuraEffectList const& auraDamagePCTList = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + AuraEffectList const& auraDamagePCTList = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for (AuraEffectList::const_iterator itr = auraDamagePCTList.begin(); itr!=auraDamagePCTList.end(); ++itr) _ApplyWeaponDependentAuraDamageMod(item,attackType,*itr,apply); } -void Player::_ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, AuraEffect* aura, bool apply) +void Player::_ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, AuraEffect const* aura, bool apply) { // generic not weapon specific case processes in aura code if (aura->GetSpellProto()->EquippedItemClass == -1) @@ -7247,7 +7258,7 @@ void Player::_ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attac HandleBaseModValue(mod, FLAT_MOD, float (aura->GetAmount()), apply); } -void Player::_ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType attackType, AuraEffect* aura, bool apply) +void Player::_ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType attackType, AuraEffect const* aura, bool apply) { //don't apply mod if item is broken if (item->IsBroken()) @@ -7271,7 +7282,7 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType att } UnitModifierType unitModType = TOTAL_VALUE; - switch (aura->GetAuraName()) + switch (aura->GetAuraType()) { case SPELL_AURA_MOD_DAMAGE_DONE: unitModType = TOTAL_VALUE; break; case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE: unitModType = TOTAL_PCT; break; @@ -7322,9 +7333,9 @@ void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply if (form_change) // check aura active state from other form { - AuraMap const& auras = GetAuras(); - for (AuraMap::const_iterator itr = auras.lower_bound(spellInfo->Id); itr != auras.upper_bound(spellInfo->Id); ++itr) - if (!item || itr->second->GetCastItemGUID()==item->GetGUID()) + AuraApplicationMap const& auras = GetAppliedAuras(); + for (AuraApplicationMap::const_iterator itr = auras.lower_bound(spellInfo->Id); itr != auras.upper_bound(spellInfo->Id); ++itr) + if (!item || itr->second->GetBase()->GetCastItemGUID() == item->GetGUID()) return; } @@ -13851,7 +13862,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver uint32 XP = q_status.m_rewarded ? 0 : uint32(pQuest->XPValue( this )*sWorld.getRate(RATE_XP_QUEST)); // handle SPELL_AURA_MOD_XP_QUEST_PCT auras - Unit::AuraEffectList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_XP_QUEST_PCT); + Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT); for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i) XP = uint32(XP*(1.0f + (*i)->GetAmount() / 100.0f)); @@ -16007,24 +16018,29 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) { sLog.outDebug("Loading auras for player %u",GetGUIDLow()); - //QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_mask,stackcount,amount0,amount1,amount2,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow()); + //QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow()); if (result) { do { int32 damage[3]; + int32 baseDamage[3]; Field *fields = result->Fetch(); uint64 caster_guid = fields[0].GetUInt64(); uint32 spellid = fields[1].GetUInt32(); uint8 effmask = fields[2].GetUInt8(); - uint8 stackcount = fields[3].GetUInt8(); - damage[0] = fields[4].GetInt32(); - damage[1] = fields[5].GetInt32(); - damage[2] = fields[6].GetInt32(); - int32 maxduration = fields[7].GetInt32(); - int32 remaintime = fields[8].GetInt32(); - uint8 remaincharges = fields[9].GetUInt8(); + uint8 recalculatemask = fields[3].GetUInt8(); + uint8 stackcount = fields[4].GetUInt8(); + damage[0] = fields[5].GetInt32(); + damage[1] = fields[6].GetInt32(); + damage[2] = fields[7].GetInt32(); + baseDamage[0] = fields[8].GetInt32(); + baseDamage[1] = fields[9].GetInt32(); + baseDamage[2] = fields[10].GetInt32(); + int32 maxduration = fields[11].GetInt32(); + int32 remaintime = fields[12].GetInt32(); + uint8 remaincharges = fields[13].GetUInt8(); SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid); if (!spellproto) @@ -16051,15 +16067,17 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) else remaincharges = 0; - Aura* aura = new Aura(spellproto, effmask, this, this, this); - aura->SetLoadedState(caster_guid,maxduration,remaintime,remaincharges, stackcount, &damage[0]); - if (!aura->CanBeSaved()) + if (Aura * aura = Aura::TryCreate(spellproto, effmask, this, NULL, &baseDamage[0], NULL, caster_guid)) { - delete aura; - continue; + if (!aura->CanBeSaved()) + { + aura->Remove(); + continue; + } + aura->SetLoadedState(maxduration,remaintime,remaincharges,stackcount,recalculatemask,&damage[0]); + aura->ApplyForTargets(); + sLog.outDetail("Added aura spellid %u, effectmask %u", spellproto->Id, effmask); } - AddAura(aura); - sLog.outDetail("Added aura spellid %u, effectmask %u", spellproto->Id, effmask); } while (result->NextRow()); @@ -17170,26 +17188,39 @@ void Player::_SaveAuras() { CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",GetGUIDLow()); - AuraMap const& auras = GetAuras(); - for (AuraMap::const_iterator itr = auras.begin(); itr !=auras.end() ; ++itr) + for (AuraMap::const_iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end() ; ++itr) { if (!itr->second->CanBeSaved()) continue; - int32 amounts[MAX_SPELL_EFFECTS]; + Aura * aura = itr->second; + + int32 damage[MAX_SPELL_EFFECTS]; + int32 baseDamage[MAX_SPELL_EFFECTS]; + uint8 effMask = 0; + uint8 recalculateMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (AuraEffect * partAura = itr->second->GetPartAura(i)) - amounts[i] = partAura->GetAmount(); + if (aura->GetEffect(i)) + { + baseDamage[i] = aura->GetEffect(i)->GetBaseAmount(); + damage[i] = aura->GetEffect(i)->GetAmount(); + effMask |= (1<<i); + if (aura->GetEffect(i)->CanBeRecalculated()) + recalculateMask |= (1<<i); + } else - amounts[i] = 0; + { + baseDamage[i] = NULL; + damage[i] = NULL; + } } - CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_mask,stackcount,amount0,amount1,amount2,maxduration,remaintime,remaincharges) " - "VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%u')", - GetGUIDLow(), itr->second->GetCasterGUID(), itr->second->GetId(), itr->second->GetEffectMask(), - itr->second->GetStackAmount(), amounts[0], amounts[1], amounts[2], - itr->second->GetAuraMaxDuration(),itr->second->GetAuraDuration(),itr->second->GetAuraCharges()); + CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_mask,recalculate_mask,stackcount,amount0,amount1,amount2,base_amount0,base_amount1,base_amount2,maxduration,remaintime,remaincharges) " + "VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u')", + GetGUIDLow(), itr->second->GetCasterGUID(), itr->second->GetId(), effMask, recalculateMask, + itr->second->GetStackAmount(), damage[0], damage[1], damage[2], baseDamage[0], baseDamage[1], baseDamage[2], + itr->second->GetMaxDuration(), itr->second->GetDuration(),itr->second->GetCharges()); } } @@ -18204,6 +18235,7 @@ bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mo void Player::AddSpellMod(SpellModifier* mod, bool apply) { + sLog.outDebug("Player::AddSpellMod %d", mod->spellId); uint16 Opcode = (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER; int i = 0; @@ -18236,7 +18268,9 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply) else { m_spellMods[mod->op].remove(mod); - delete mod; + // mods bound to aura will be removed in AuraEffect::~AuraEffect + if (!mod->ownerAura) + delete mod; } } @@ -18253,7 +18287,7 @@ void Player::RestoreSpellMods(Spell * spell) SpellModifier *mod = *itr; // spellmods without aura set cannot be charged - if (!mod->ownerAura || !mod->ownerAura->GetAuraCharges()) + if (!mod->ownerAura || !mod->ownerAura->GetCharges()) continue; // check if mod affected this spell @@ -18271,12 +18305,12 @@ void Player::RestoreSpellMods(Spell * spell) mod->charges++; // Do not set more spellmods than avalible - if (mod->ownerAura->GetAuraCharges() < mod->charges) - mod->charges = mod->ownerAura->GetAuraCharges(); + if (mod->ownerAura->GetCharges() < mod->charges) + mod->charges = mod->ownerAura->GetCharges(); // Skip this check for now - aura charges may change due to various reason // TODO: trac these changes correctly - //assert (mod->ownerAura->GetAuraCharges() <= mod->charges); + //assert (mod->ownerAura->GetCharges() <= mod->charges); } } } @@ -18287,27 +18321,28 @@ void Player::RemoveSpellMods(Spell * spell) return; std::set <Aura *> checkedSpells; - AuraEffectList const & auraList = GetAurasByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); + AuraEffectList const & auraList = GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); for (AuraEffectList::const_iterator itr = auraList.begin(); itr != auraList.end();) { - AuraEffect * aur = *itr; + AuraEffect * aurEff = *itr; + Aura * aura = aurEff->GetBase(); ++itr; - if (!aur->GetParentAura()->GetAuraCharges()) + if (!aura->GetCharges()) continue; - SpellEntry const * spellInfo = aur->GetSpellProto(); + SpellEntry const * spellInfo = aura->GetSpellProto(); if (spellInfo->SpellFamilyName != spell->m_spellInfo->SpellFamilyName || - checkedSpells.find(aur->GetParentAura()) != checkedSpells.end()) + checkedSpells.find(aura) != checkedSpells.end()) continue; - if (spell->m_spellInfo->SpellFamilyFlags & spellInfo->EffectSpellClassMask[aur->GetEffIndex()] + if (spell->m_spellInfo->SpellFamilyFlags & spellInfo->EffectSpellClassMask[aurEff->GetEffIndex()] // this is for fingers of frost, look at spell::finish part, a charge will be taken by the triggering spell - && aur->GetParentAura()->GetAuraDuration() != aur->GetParentAura()->GetAuraMaxDuration()) + && aura->GetDuration() != aura->GetMaxDuration()) { - checkedSpells.insert(aur->GetParentAura()); - spell->m_appliedMods.erase(aur->GetParentAura()); - if (aur->GetParentAura()->DropAuraCharge()) + checkedSpells.insert(aura); + spell->m_appliedMods.erase(aura); + if (aura->DropCharge()) itr = auraList.begin(); } } @@ -18323,7 +18358,7 @@ void Player::RemoveSpellMods(Spell * spell) ++itr; // spellmods without aura set cannot be charged - if (!mod->ownerAura || !mod->ownerAura->GetAuraCharges()) + if (!mod->ownerAura || !mod->ownerAura->GetCharges()) continue; // check if mod affected this spell @@ -18334,7 +18369,7 @@ void Player::RemoveSpellMods(Spell * spell) // remove from list spell->m_appliedMods.erase(iterMod); - if (mod->ownerAura->DropAuraCharge()) + if (mod->ownerAura->DropCharge()) itr = m_spellMods[i].begin(); } } @@ -19565,7 +19600,7 @@ void Player::SetBattleGroundEntryPoint() // Mount spell id storing if (IsMounted()) { - AuraEffectList const& auras = GetAurasByType(SPELL_AURA_MOUNTED); + AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_MOUNTED); if (!auras.empty()) m_bgData.mountSpell = (*auras.begin())->GetId(); } @@ -20181,15 +20216,15 @@ void Player::SendInitialPacketsAfterAddToMap() }; for (AuraType const* itr = &auratypes[0]; itr && itr[0] != SPELL_AURA_NONE; ++itr) { - Unit::AuraEffectList const& auraList = GetAurasByType(*itr); + Unit::AuraEffectList const& auraList = GetAuraEffectsByType(*itr); if(!auraList.empty()) - auraList.front()->ApplyModifier(true,true); + auraList.front()->HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); } if(HasAuraType(SPELL_AURA_MOD_STUN)) SetMovement(MOVE_ROOT); - // manual send package (have code in ApplyModifier(true,true); that don't must be re-applied. + // manual send package (have code in HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); that don't must be re-applied. if(HasAuraType(SPELL_AURA_MOD_ROOT)) { WorldPacket data2(SMSG_FORCE_MOVE_ROOT, 10); @@ -20489,29 +20524,28 @@ void Player::SendAurasForTarget(Unit *target) Unit::VisibleAuraMap const *visibleAuras = target->GetVisibleAuras(); for (Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr) { - Aura * aura=itr->second; - data << uint8(aura->GetAuraSlot()); + AuraApplication * auraApp = itr->second; + Aura * aura = auraApp->GetBase(); + data << uint8(auraApp->GetSlot()); data << uint32(aura->GetId()); // flags - data << aura->m_auraFlags; + uint32 flags = auraApp->GetFlags(); + if (aura->GetMaxDuration() > 0) + flags |= AFLAG_DURATION; + data << uint8(flags); // level - data << aura->m_auraLevel; + data << uint8(aura->GetCasterLevel()); // charges - data << uint8(aura->GetStackAmount()>1 ? aura->GetStackAmount() : aura->GetAuraCharges()); + data << uint8(aura->GetStackAmount() > 1 ? aura->GetStackAmount() : (aura->GetCharges()) ? aura->GetCharges() : 1); - if(!(aura->m_auraFlags & AFLAG_CASTER)) - { - if (Unit * caster = aura->GetCaster()) - data.append(caster->GetPackGUID()); - else - data << uint8(0); - } + if(!(flags & AFLAG_CASTER)) + data.appendPackGUID(aura->GetCasterGUID()); - if(aura->m_auraFlags & AFLAG_DURATION) // include aura duration + if(flags & AFLAG_DURATION) // include aura duration { - data << uint32(aura->GetAuraMaxDuration()); - data << uint32(aura->GetAuraDuration()); + data << uint32(aura->GetMaxDuration()); + data << uint32(aura->GetDuration()); } } @@ -20847,14 +20881,13 @@ bool Player::CanNoReagentCast(SpellEntry const* spellInfo) const void Player::RemoveItemDependentAurasAndCasts( Item * pItem ) { - AuraMap& auras = GetAuras(); - for (AuraMap::iterator itr = auras.begin(); itr != auras.end();) + for (AuraMap::iterator itr = m_ownedAuras.begin(); itr != m_ownedAuras.end();) { - Aura* aura = itr->second; + Aura * aura = itr->second; // skip passive (passive item dependent spells work in another way) and not self applied auras SpellEntry const* spellInfo = aura->GetSpellProto(); - if(aura->IsPassive() || aura->GetCasterGUID()!=GetGUID()) + if(aura->IsPassive() || aura->GetCasterGUID() != GetGUID()) { ++itr; continue; @@ -20868,7 +20901,7 @@ void Player::RemoveItemDependentAurasAndCasts( Item * pItem ) } // no alt item, remove aura, restart check - RemoveAura(itr); + RemoveOwnedAura(itr); } // currently casted spells can be dependent from item @@ -20883,7 +20916,7 @@ uint32 Player::GetResurrectionSpellId() // search priceless resurrection possibilities uint32 prio = 0; uint32 spell_id = 0; - AuraEffectList const& dummyAuras = GetAurasByType(SPELL_AURA_DUMMY); + AuraEffectList const& dummyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (AuraEffectList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) { // Soulstone Resurrection // prio: 3 (max, non death persistent) @@ -20997,7 +21030,7 @@ bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim) uint32 itr_xp = (member_with_max_level == not_gray_member_with_max_level) ? uint32(xp*rate) : uint32((xp*rate/2)+1); // handle SPELL_AURA_MOD_XP_PCT auras - Unit::AuraEffectList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_XP_PCT); + Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT); for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i) itr_xp = uint32(itr_xp*(1.0f + (*i)->GetAmount() / 100.0f)); @@ -21031,7 +21064,7 @@ bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim) RewardReputation(pVictim,1); // handle SPELL_AURA_MOD_XP_PCT auras - Unit::AuraEffectList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_XP_PCT); + Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_PCT); for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i) xp = uint32(xp*(1.0f + (*i)->GetAmount() / 100.0f)); @@ -21158,11 +21191,11 @@ void Player::UpdateZoneDependentAuras( uint32 newZone ) void Player::UpdateAreaDependentAuras( uint32 newArea ) { // remove auras from spells with area limitations - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) + for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();) { // use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date if(spellmgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,this) != SPELL_CAST_OK) - RemoveAura(iter); + RemoveOwnedAura(iter); else ++iter; } @@ -21575,7 +21608,7 @@ void Player::InitGlyphsForLevel() bool Player::isTotalImmune() { - AuraEffectList const& immune = GetAurasByType(SPELL_AURA_SCHOOL_IMMUNITY); + AuraEffectList const& immune = GetAuraEffectsByType(SPELL_AURA_SCHOOL_IMMUNITY); uint32 immuneMask = 0; for (AuraEffectList::const_iterator itr = immune.begin(); itr != immune.end(); ++itr) @@ -21626,7 +21659,7 @@ void Player::SetTitle(CharTitlesEntry const* title, bool lost) /*-----------------------TRINITY--------------------------*/ bool Player::isTotalImmunity() { - AuraEffectList const& immune = GetAurasByType(SPELL_AURA_SCHOOL_IMMUNITY); + AuraEffectList const& immune = GetAuraEffectsByType(SPELL_AURA_SCHOOL_IMMUNITY); for (AuraEffectList::const_iterator itr = immune.begin(); itr != immune.end(); ++itr) { @@ -21656,9 +21689,9 @@ void Player::UpdateCharmedAI() //kill self if charm aura has infinite duration if(charmer->IsInEvadeMode()) { - AuraEffectList const& auras = GetAurasByType(SPELL_AURA_MOD_CHARM); + AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_MOD_CHARM); for (AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) - if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetParentAura()->IsPermanent()) + if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent()) { charmer->DealDamage(this, GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return; @@ -21680,6 +21713,34 @@ void Player::UpdateCharmedAI() } } +void Player::RemoveRunesByAuraEffect(AuraEffect const * aura) +{ + for(uint8 i = 0; i < MAX_RUNES; ++i) + { + if (m_runes->runes[i].ConvertAura == aura) + { + ConvertRune(i, GetBaseRune(i)); + SetRuneConvertAura(i, NULL); + } + } +} + +void Player::RestoreBaseRune(uint8 index) +{ + AuraEffect const * aura = m_runes->runes[index].ConvertAura; + ConvertRune(index, GetBaseRune(index)); + SetRuneConvertAura(index, NULL); + // Don't drop passive talents providing rune convertion + if (!aura || aura->GetAuraType() != SPELL_AURA_CONVERT_RUNE) + return; + for(uint8 i = 0; i < MAX_RUNES; ++i) + { + if (aura == m_runes->runes[i].ConvertAura) + return; + } + aura->GetBase()->Remove(); +} + void Player::ConvertRune(uint8 index, RuneType newType) { SetCurrentRune(index, newType); @@ -21732,6 +21793,7 @@ void Player::InitRunes() SetBaseRune(i, runeSlotTypes[i]); // init base types SetCurrentRune(i, runeSlotTypes[i]); // init current types SetRuneCooldown(i, 0); // reset cooldowns + SetRuneConvertAura(i, NULL); m_runes->SetRuneState(i); } @@ -21915,7 +21977,7 @@ uint32 Player::GetPhaseMaskForSpawn() const phase = GetPhaseMask(); else { - AuraEffectList const& phases = GetAurasByType(SPELL_AURA_PHASE); + AuraEffectList const& phases = GetAuraEffectsByType(SPELL_AURA_PHASE); if (!phases.empty()) phase = phases.front()->GetMiscValue(); } @@ -22034,7 +22096,7 @@ void Player::HandleFall(MovementInfo const& movementInfo) DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); } } - RemoveAura(44795); // No fly zone - Parachute + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // No fly zone - Parachute } void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 miscvalue1/*=0*/, uint32 miscvalue2/*=0*/, Unit *unit/*=NULL*/, uint32 time/*=0*/ ) diff --git a/src/game/Player.h b/src/game/Player.h index 53358c03817..cac6e889345 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -111,7 +111,7 @@ struct SpellModifier int32 value; flag96 mask; uint32 spellId; - Aura *const ownerAura; + Aura * const ownerAura; }; typedef UNORDERED_MAP<uint32, PlayerTalent*> PlayerTalentMap; @@ -297,6 +297,7 @@ struct RuneInfo uint8 BaseRune; uint8 CurrentRune; uint8 Cooldown; + AuraEffect const * ConvertAura; }; struct Runes @@ -1924,8 +1925,8 @@ class TRINITY_DLL_SPEC Player : public Unit, public GridObject<Player> void _RemoveAllStatBonuses(); void _ApplyWeaponDependentAuraMods(Item *item, WeaponAttackType attackType, bool apply); - void _ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, AuraEffect* aura, bool apply); - void _ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType attackType, AuraEffect* aura, bool apply); + void _ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attackType, AuraEffect const * aura, bool apply); + void _ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType attackType, AuraEffect const * aura, bool apply); void _ApplyItemMods(Item *item,uint8 slot,bool apply); void _RemoveAllItemMods(); @@ -2259,6 +2260,10 @@ class TRINITY_DLL_SPEC Player : public Unit, public GridObject<Player> void SetBaseRune(uint8 index, RuneType baseRune) { m_runes->runes[index].BaseRune = baseRune; } void SetCurrentRune(uint8 index, RuneType currentRune) { m_runes->runes[index].CurrentRune = currentRune; } void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); } + void SetRuneConvertAura(uint8 index, AuraEffect const * aura) { m_runes->runes[index].ConvertAura = aura; } + void AddRuneByAuraEffect(uint8 index, RuneType newType, AuraEffect const * aura) { SetRuneConvertAura(index, aura); ConvertRune(index, newType); } + void RemoveRunesByAuraEffect(AuraEffect const * aura); + void RestoreBaseRune(uint8 index); void ConvertRune(uint8 index, RuneType newType); void ResyncRunes(uint8 count); void AddRunePower(uint8 index); @@ -2594,6 +2599,7 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas if(!IsAffectedBySpellmod(spellInfo,mod,spell)) continue; + if (mod->type == SPELLMOD_FLAT) totalflat += mod->value; else if (mod->type == SPELLMOD_PCT) @@ -2611,7 +2617,6 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas DropModCharge(mod, spell); } - float diff = (float)basevalue*(float)totalpct/100.0f + (float)totalflat; basevalue = T((float)basevalue + diff); return T(diff); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 1b5c094e28c..d08ad736819 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2495,7 +2495,7 @@ enum DiminishingReturnsType enum DiminishingGroup { // Common Groups - DIMINISHING_NONE, + DIMINISHING_NONE = 0, DIMINISHING_CONTROL_STUN, // Player Controlled stuns DIMINISHING_TRIGGER_STUN, // By aura proced stuns, usualy chance on hit talents DIMINISHING_CONTROL_ROOT, // Immobilizing effects from casted spells diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 3d053ebb8b9..569602ad680 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -50,6 +50,7 @@ #include "TemporarySummon.h" #include "Vehicle.h" #include "ScriptCalls.h" +#include "SpellAuraEffects.h" #define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILISECONDS) @@ -382,8 +383,6 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi m_delayStart = 0; m_delayAtDamageCount = 0; - m_canTrigger=true; - m_applyMultiplierMask = 0; m_effectMask = 0; m_auraScaleMask = 0; @@ -455,7 +454,6 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi m_preCastSpell = 0; m_triggeredByAuraSpell = NULL; m_spellAura = NULL; - m_spellDynObj = NULL; //Auto Shot & Shoot (wand) m_autoRepeat = IsAutoRepeatRangedSpell(m_spellInfo); @@ -773,7 +771,7 @@ void Spell::SelectSpellTargets() } } -void Spell::prepareDataForTriggerSystem(AuraEffect * triggeredByAura) +void Spell::prepareDataForTriggerSystem(AuraEffect const * triggeredByAura) { //========================================================================================== // Now fill data for trigger system, need know: @@ -828,10 +826,6 @@ void Spell::prepareDataForTriggerSystem(AuraEffect * triggeredByAura) Effects which are result of aura proc from triggered spell cannot proc to prevent chain proc of these spells */ - if ((triggeredByAura && !triggeredByAura->GetParentAura()->GetTarget()->CanProc())) - { - m_canTrigger=false; - } // Ranged autorepeat attack is set as triggered spell - ignore it if (!(m_procAttacker & PROC_FLAG_SUCCESSFUL_RANGED_HIT)) @@ -1072,7 +1066,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) //Spells with this flag cannot trigger if effect is casted on self // Slice and Dice, relentless strikes, eviscerate - bool canEffectTrigger = m_canTrigger && (m_spellInfo->AttributesEx4 & (SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST) ? m_caster!=unitTarget : true); + bool canEffectTrigger = unitTarget->CanProc() && (m_spellInfo->AttributesEx4 & (SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST) ? m_caster!=unitTarget : true); Unit * spellHitTarget = NULL; if (missInfo==SPELL_MISS_NONE) // In case spell hit target, do all effect on that target @@ -1166,9 +1160,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT) caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell); - if (m_spellAura) - m_spellAura->SetProcDamage(addhealth); - int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo, crit); unitTarget->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, m_spellInfo); } @@ -1197,10 +1188,14 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) ((Player *)caster)->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx); } - if (m_spellAura) - m_spellAura->SetProcDamage(damageInfo.damage); caster->DealSpellDamage(&damageInfo, true); + // Haunt + if(m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags[1] & 0x40000 && m_spellAura && m_spellAura->GetEffect(1)) + { + AuraEffect * aurEff = m_spellAura->GetEffect(1); + aurEff->SetAmount(aurEff->GetAmount() * damageInfo.damage / 100); + } } // Passive spell hits/misses or active spells only misses (only triggers) else @@ -1339,7 +1334,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask, bool uint8 aura_effmask = 0; for (uint8 i = 0; i < 3; ++i) - if (effectMask & (1<<i) && (m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || IsAreaAuraEffect(m_spellInfo->Effect[i]))) + if (effectMask & (1<<i) && IsUnitOwnedAuraEffect(m_spellInfo->Effect[i])) aura_effmask |= 1<<i; if (aura_effmask) @@ -1355,52 +1350,50 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask, bool for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { basePoints[i] = aurSpellInfo->EffectBasePoints[i]; - } - } - else - { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - basePoints[i] = m_currentBasePoints[i]; + if (m_spellInfo->Effect[i] != aurSpellInfo->Effect[i]) + { + aurSpellInfo = m_spellInfo; + break; + } } } if(m_originalCaster) { - Aura *Aur = new Aura(aurSpellInfo, aura_effmask, unit, m_caster, m_originalCaster, basePoints, m_CastItem); + if (m_spellAura = Aura::TryCreate(aurSpellInfo, effectMask, unit, + m_originalCaster,(aurSpellInfo == m_spellInfo)? &m_currentBasePoints[0] : &basePoints[0], m_CastItem)) + { + // Now Reduce spell duration using data received at spell hit + int32 duration = m_spellAura->GetMaxDuration(); + int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,aurSpellInfo); + unit->ApplyDiminishingToDuration(m_diminishGroup, duration, m_originalCaster, m_diminishLevel,limitduration); + ((UnitAura*)m_spellAura)->SetDiminishGroup(m_diminishGroup); - if (!Aur->IsAreaAura()) - { - // Now Reduce spell duration using data received at spell hit - int32 duration = Aur->GetAuraMaxDuration(); - int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,aurSpellInfo); - unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_originalCaster, m_diminishLevel,limitduration); - Aur->setDiminishGroup(m_diminishGroup); + bool positive = IsPositiveSpell(m_spellAura->GetId()); + AuraApplication * aurApp = m_spellAura->GetApplicationOfTarget(m_originalCaster->GetGUID()); + if (aurApp) + positive = aurApp->IsPositive(); - duration = m_originalCaster->ModSpellDuration(aurSpellInfo, unit, duration, Aur->IsPositive()); + duration = m_originalCaster->ModSpellDuration(aurSpellInfo, unit, duration, positive); - //mod duration of channeled aura by spell haste - if (IsChanneledSpell(m_spellInfo)) - m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this); + //mod duration of channeled aura by spell haste + if (IsChanneledSpell(m_spellInfo)) + m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this); - if(duration != Aur->GetAuraMaxDuration()) - { - Aur->SetAuraMaxDuration(duration); - Aur->SetAuraDuration(duration); - } + if(duration != m_spellAura->GetMaxDuration()) + { + m_spellAura->SetMaxDuration(duration); + m_spellAura->SetDuration(duration); + } - // Prayer of Mending (jump animation), we need formal caster instead original for correct animation - if( aurSpellInfo->SpellFamilyName == SPELLFAMILY_PRIEST) - { - if(aurSpellInfo->SpellFamilyFlags[1] & 0x000020) - m_caster->CastSpell(unit, 41637, true, NULL, NULL, m_originalCasterGUID); + // Prayer of Mending (jump animation), we need formal caster instead original for correct animation + if(aurSpellInfo->SpellFamilyName == SPELLFAMILY_PRIEST) + { + if(aurSpellInfo->SpellFamilyFlags[1] & 0x000020) + m_caster->CastSpell(unit, 41637, true, NULL, NULL, m_originalCasterGUID); + } } } - // Set aura only when successfully applied - if (unit->AddAura(Aur, false)) - m_spellAura = Aur; - - } } for (uint32 effectNumber = 0; effectNumber < 3; ++effectNumber) @@ -1451,10 +1444,9 @@ void Spell::DoTriggersOnSpellHit(Unit *unit) if (!_duration) { Aura * aur = unit->GetAura(m_spellInfo->Id, m_caster->GetGUID()); - _duration = aur ? aur->GetAuraDuration() : -1; + _duration = aur ? aur->GetDuration() : -1; } - triggeredAur->SetAuraDuration(_duration); - triggeredAur->SetPermanent(false); + triggeredAur->SetDuration(_duration); } } } @@ -1541,12 +1533,12 @@ bool Spell::UpdateChanneledTargetList() { if (needAuraMask & ihit->effectMask) { - if(Aura * aur = unit->GetAura(m_spellInfo->Id, m_originalCasterGUID)) + if(AuraApplication * aurApp = unit->GetAuraApplication(m_spellInfo->Id, m_originalCasterGUID)) { if (m_caster != unit && !m_caster->IsWithinDistInMap(unit,range)) { - ihit->effectMask &= ~aur->GetEffectMask(); - unit->RemoveAura(aur); + ihit->effectMask &= ~aurApp->GetEffectMask(); + unit->RemoveAura(aurApp); continue; } } @@ -1615,10 +1607,10 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin // Get spell max affected targets /*uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets; - Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); + Unit::AuraList const& mod = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); for (Unit::AuraList::const_iterator m = mod.begin(); m != mod.end(); ++m) { - if (!(*m)->isAffectedOnSpell(m_spellInfo)) + if (!(*m)->IsAffectedOnSpell(m_spellInfo)) continue; unMaxTargets+=(*m)->GetAmount(); }*/ @@ -2448,9 +2440,9 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) { if(uint32 maxTargets = m_spellValue->MaxAffectedTargets) { - Unit::AuraEffectList const& Auras = m_caster->GetAurasByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); + Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j) - if((*j)->isAffectedOnSpell(m_spellInfo)) + if((*j)->IsAffectedOnSpell(m_spellInfo)) maxTargets += (*j)->GetAmount(); if(m_spellInfo->Id == 5246) //Intimidating Shout @@ -2572,7 +2564,7 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) } } -void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura) +void Spell::prepare(SpellCastTargets const* targets, AuraEffect const * triggeredByAura) { if (m_CastItem) m_castItemGUID = m_CastItem->GetGUID(); @@ -2677,7 +2669,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura if(triggeredByAura) { SendChannelUpdate(0); - triggeredByAura->GetParentAura()->SetAuraDuration(0); + triggeredByAura->GetBase()->SetDuration(0); } SendCastResult(result); @@ -2761,11 +2753,10 @@ void Spell::cancel() case SPELL_STATE_CASTING: { - for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) - if(ihit->missCondition == SPELL_MISS_NONE) - if(Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID)) - if(unit->isAlive()) - unit->RemoveAurasDueToSpell(m_spellInfo->Id, m_originalCasterGUID, AURA_REMOVE_BY_CANCEL); + for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + if ((*ihit).missCondition == SPELL_MISS_NONE) + if (Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID)) + unit->RemoveOwnedAura(m_spellInfo->Id, m_originalCasterGUID, 0, AURA_REMOVE_BY_CANCEL); SendChannelUpdate(0); SendInterrupted(0); @@ -2912,18 +2903,18 @@ void Spell::cast(bool skipCheck) // are there any spells need to be triggered after hit? // handle SPELL_AURA_ADD_TARGET_TRIGGER auras - Unit::AuraEffectList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER); + Unit::AuraEffectList const& targetTriggers = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_TARGET_TRIGGER); for (Unit::AuraEffectList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i) { - if (!(*i)->isAffectedOnSpell(m_spellInfo)) + if (!(*i)->IsAffectedOnSpell(m_spellInfo)) continue; SpellEntry const *auraSpellInfo = (*i)->GetSpellProto(); uint32 auraSpellIdx = (*i)->GetEffIndex(); if(SpellEntry const *spellInfo = sSpellStore.LookupEntry(auraSpellInfo->EffectTriggerSpell[auraSpellIdx])) { // Calculate chance at that moment (can be depend for example from combo points) - int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBasePoints(), NULL); - m_ChanceTriggerSpells.push_back(std::make_pair(spellInfo, chance * (*i)->GetParentAura()->GetStackAmount())); + int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBaseAmount(), NULL); + m_ChanceTriggerSpells.push_back(std::make_pair(spellInfo, chance * (*i)->GetBase()->GetStackAmount())); } } @@ -3091,6 +3082,7 @@ uint64 Spell::handle_delayed(uint64 t_offset) void Spell::_handle_immediate_phase() { + m_spellAura = NULL; // handle some immediate features of the spell here HandleThreatSpells(m_spellInfo->Id); @@ -4204,52 +4196,8 @@ void Spell::TakeRunePower() plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec plr->SetLastUsedRune(RuneType(rune)); runeCost[rune]--; - bool auraFound = false; - plr->ConvertRune(i, plr->GetBaseRune(i)); - // * * * * * * * * * * * - // update convert rune auras - // * * * * * * * * * * * - // Remove rune from SPELL_AURA_CONVERT_RUNE when rune is used - // To prevent overriding other rune convert effects - Unit::AuraEffectList const& runeconvert = m_caster->GetAurasByType(SPELL_AURA_CONVERT_RUNE); - for (Unit::AuraEffectList::const_iterator itr = runeconvert.begin(); itr != runeconvert.end(); ++itr) - { - // Remove rune of aura if avalible - if ((*itr)->GetAmount() & (1<<i)) - { - (*itr)->SetAmount((*itr)->GetAmount() & ~(1<<i)); - auraFound = true; - } - // All runes from aura used - remove aura - if (!(*itr)->GetAmount()) - plr->RemoveAura((*itr)->GetParentAura(), AURA_REMOVE_BY_EXPIRE); - break; - } - if (!auraFound) - { - // Decrease used rune count for dk talent auras - // To prevent overriding other rune convert effects - Unit::AuraEffectList const& runeconvert = m_caster->GetAurasByType(SPELL_AURA_CONVERT_RUNE); - for (Unit::AuraEffectList::const_iterator itr = runeconvert.begin(); itr != runeconvert.end(); ++itr) - { - if (plr->GetBaseRune(i) != RUNE_DEATH) - { - // Death Rune Mastery - if ((*itr)->GetSpellProto()->SpellIconID != 2622) - continue; - } - // Blood of the North - // Reaping - else if ((*itr)->GetSpellProto()->SpellIconID != 3041 && - (*itr)->GetSpellProto()->SpellIconID != 22) - continue; - // Remove rune of aura if avalible - if ((*itr)->GetAmount() & (1<<i)) - (*itr)->SetAmount((*itr)->GetAmount() & ~(1<<i)); - break; - } - } + plr->RestoreBaseRune(i); if(runeCost[RUNE_DEATH] == 0) break; @@ -4401,10 +4349,10 @@ SpellCastResult Spell::CheckCast(bool strict) { bool checkForm = true; // Ignore form req aura - Unit::AuraEffectList const& ignore = m_caster->GetAurasByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT); + Unit::AuraEffectList const& ignore = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT); for (Unit::AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) { - if (!(*i)->isAffectedOnSpell(m_spellInfo)) + if (!(*i)->IsAffectedOnSpell(m_spellInfo)) continue; checkForm = false; break; @@ -4422,10 +4370,10 @@ SpellCastResult Spell::CheckCast(bool strict) } bool reqCombat=true; - Unit::AuraEffectList const& stateAuras = m_caster->GetAurasByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); + Unit::AuraEffectList const& stateAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); for (Unit::AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j) { - if((*j)->isAffectedOnSpell(m_spellInfo)) + if((*j)->IsAffectedOnSpell(m_spellInfo)) { if ((*j)->GetMiscValue()==1) { @@ -5395,48 +5343,46 @@ SpellCastResult Spell::CheckCasterAuras() const if(school_immune || mechanic_immune || dispel_immune) { //Checking auras is needed now, because you are prevented by some state but the spell grants immunity. - Unit::AuraMap const& auras = m_caster->GetAuras(); - for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + Unit::AuraApplicationMap const& auras = m_caster->GetAppliedAuras(); + for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { - if(itr->second) - { - if( GetAllSpellMechanicMask(itr->second->GetSpellProto()) & mechanic_immune ) - continue; - if( GetSpellSchoolMask(itr->second->GetSpellProto()) & school_immune ) - continue; - if( (1<<(itr->second->GetSpellProto()->Dispel)) & dispel_immune) - continue; + Aura const * aura = itr->second->GetBase(); + if( GetAllSpellMechanicMask(aura->GetSpellProto()) & mechanic_immune ) + continue; + if( GetSpellSchoolMask(aura->GetSpellProto()) & school_immune ) + continue; + if( (1<<(aura->GetSpellProto()->Dispel)) & dispel_immune) + continue; - //Make a second check for spell failed so the right SPELL_FAILED message is returned. - //That is needed when your casting is prevented by multiple states and you are only immune to some of them. - for (uint8 i=0; i<MAX_SPELL_EFFECTS; ++i) + //Make a second check for spell failed so the right SPELL_FAILED message is returned. + //That is needed when your casting is prevented by multiple states and you are only immune to some of them. + for (uint8 i=0; i<MAX_SPELL_EFFECTS; ++i) + { + if (AuraEffect * part = aura->GetEffect(i)) { - if (AuraEffect * part = itr->second->GetPartAura(i)) + switch(part->GetAuraType()) { - switch(part->GetAuraName()) - { - case SPELL_AURA_MOD_STUN: - if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED)) - return SPELL_FAILED_STUNNED; - break; - case SPELL_AURA_MOD_CONFUSE: - if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED)) - return SPELL_FAILED_CONFUSED; - break; - case SPELL_AURA_MOD_FEAR: - if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED)) - return SPELL_FAILED_FLEEING; - break; - case SPELL_AURA_MOD_SILENCE: - case SPELL_AURA_MOD_PACIFY: - case SPELL_AURA_MOD_PACIFY_SILENCE: - if( m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) - return SPELL_FAILED_PACIFIED; - else if ( m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE) - return SPELL_FAILED_SILENCED; - break; - default: break; - } + case SPELL_AURA_MOD_STUN: + if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED)) + return SPELL_FAILED_STUNNED; + break; + case SPELL_AURA_MOD_CONFUSE: + if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED)) + return SPELL_FAILED_CONFUSED; + break; + case SPELL_AURA_MOD_FEAR: + if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED)) + return SPELL_FAILED_FLEEING; + break; + case SPELL_AURA_MOD_SILENCE: + case SPELL_AURA_MOD_PACIFY: + case SPELL_AURA_MOD_PACIFY_SILENCE: + if( m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) + return SPELL_FAILED_PACIFIED; + else if ( m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE) + return SPELL_FAILED_SILENCED; + break; + default: break; } } } @@ -5465,7 +5411,7 @@ bool Spell::CanAutoCast(Unit* target) else { if( AuraEffect * aureff = target->GetAuraEffect(m_spellInfo->Id, j)) - if (aureff->GetParentAura()->GetStackAmount() >= m_spellInfo->StackAmount) + if (aureff->GetBase()->GetStackAmount() >= m_spellInfo->StackAmount) return false; } } @@ -6134,8 +6080,8 @@ void Spell::DelayedChannel() for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) if ((*ihit).missCondition == SPELL_MISS_NONE) - if (Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID)) - unit->DelayAura(m_spellInfo->Id, m_caster->GetGUID(), delaytime); + if (Unit* unit = (m_caster->GetGUID() == ihit->targetGUID) ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID)) + unit->DelayOwnedAuras(m_spellInfo->Id, m_originalCasterGUID, delaytime); // partially interrupt persistent area auras if(DynamicObject* dynObj = m_caster->GetDynObject(m_spellInfo->Id)) @@ -6509,10 +6455,10 @@ void Spell::CalculateDamageDoneForAllTargets() } bool usesAmmo = true; - Unit::AuraEffectList const& Auras = m_caster->GetAurasByType(SPELL_AURA_ABILITY_CONSUME_NO_AMMO); + Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_CONSUME_NO_AMMO); for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j) { - if((*j)->isAffectedOnSpell(m_spellInfo)) + if((*j)->IsAffectedOnSpell(m_spellInfo)) usesAmmo=false; } diff --git a/src/game/Spell.h b/src/game/Spell.h index 96d220bd696..04f3984ed91 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -363,6 +363,7 @@ class Spell void EffectPlayMusic(uint32 i); void EffectSpecCount(uint32 i); void EffectActivateSpec(uint32 i); + void EffectPlayerNotification(uint32 i); void EffectCastButtons(uint32 i); void EffectRechargeManaGem(uint32 i); @@ -371,7 +372,7 @@ class Spell Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL, bool skipCheck = false ); ~Spell(); - void prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura = NULL); + void prepare(SpellCastTargets const* targets, AuraEffect const * triggeredByAura = NULL); void cancel(); void update(uint32 difftime); void cast(bool skipCheck = false); @@ -440,8 +441,7 @@ class Spell void HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,uint32 i); void HandleThreatSpells(uint32 spellId); - //void HandleAddAura(Unit* Target); - + const SpellEntry * const m_spellInfo; int32 m_currentBasePoints[3]; // cache SpellEntry::EffectBasePoints and use for set custom base points Item* m_CastItem; @@ -492,7 +492,6 @@ class Spell void CleanupTargetList(); void SetSpellValue(SpellValueMod mod, int32 value); - //void SetSpellValue(SpellValueMod mod, float value); protected: void SendLoot(uint64 guid, LootType loottype); @@ -545,8 +544,8 @@ class Spell Item* itemTarget; GameObject* gameObjTarget; int32 damage; - Aura * m_spellAura; // only used in DoAllEffectOnTarget - DynamicObject *m_spellDynObj; // only used in DoAllEffectOnTarget + // used in effects handlers + Aura * m_spellAura; // this is set in Spell Hit, but used in Apply Aura handler DiminishingLevels m_diminishLevel; @@ -566,8 +565,7 @@ class Spell uint32 m_procAttacker; // Attacker trigger flags uint32 m_procVictim; // Victim trigger flags uint32 m_procEx; - bool m_canTrigger; - void prepareDataForTriggerSystem(AuraEffect * triggeredByAura); + void prepareDataForTriggerSystem(AuraEffect const * triggeredByAura); //***************************************** // Spell target subsystem diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index e95c1bb9620..3a3942e9840 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -21,7 +21,6 @@ #define TRINITY_SPELLAURADEFINES_H #define MAX_AURAS 64 // client support up to 255, but it will cause problems with group auras updating -#define FRIENDLY_AA_REMOVE_TIME 2*IN_MILISECONDS enum AURA_FLAGS { @@ -349,19 +348,15 @@ enum AuraType SPELL_AURA_301 = 301, SPELL_AURA_302 = 302, SPELL_AURA_303 = 303, - SPELL_AURA_MOD_INEBRIATION = 304, + SPELL_AURA_304 = 304, SPELL_AURA_MOD_MINIMUM_SPEED = 305, SPELL_AURA_306 = 306, TOTAL_AURAS = 307 }; -enum AreaAuraType +enum AuraObjectType { - AREA_AURA_PARTY, - AREA_AURA_RAID, - AREA_AURA_FRIEND, - AREA_AURA_ENEMY, - AREA_AURA_PET, - AREA_AURA_OWNER + UNIT_AURA_TYPE, + DYNOBJ_AURA_TYPE, }; #endif diff --git a/src/game/SpellAuraEffects.cpp b/src/game/SpellAuraEffects.cpp new file mode 100644 index 00000000000..e9aa7b194ac --- /dev/null +++ b/src/game/SpellAuraEffects.cpp @@ -0,0 +1,6064 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "WorldPacket.h" +#include "Opcodes.h" +#include "Log.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Player.h" +#include "Unit.h" +#include "ObjectAccessor.h" +#include "Util.h" +#include "Spell.h" +#include "SpellAuraEffects.h" +#include "SpellId.h" +#include "BattleGround.h" +#include "OutdoorPvPMgr.h" +#include "Formulas.h" +#include "ScriptCalls.h" +#include "GridNotifiers.h" +#include "GridNotifiersImpl.h" +#include "CellImpl.h" + +class Aura; +// +// EFFECT HANDLER NOTES +// +// in aura handler there should be check for modes: +// AURA_EFFECT_HANDLE_REAL set - aura mod is just applied/removed on the target +// AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK set - aura is just applied/removed, or aura packet request is made +// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK set - aura is recalculated or is just applied/removed - need to redo all things related to m_amount +// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK - logical or of above conditions +// AURA_EFFECT_HANDLE_STAT - set when stats are reapplied +// such checks will speedup trinity change amount/send for client operations +// because for change amount operation packets will not be send +// aura effect handlers shouldn't contain any AuraEffect or Aura object modifications + +pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= +{ + &AuraEffect::HandleNULL, // 0 SPELL_AURA_NONE + &AuraEffect::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT + &AuraEffect::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS + &AuraEffect::HandleNoImmediateEffect, // 3 SPELL_AURA_PERIODIC_DAMAGE implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleAuraDummy, // 4 SPELL_AURA_DUMMY + &AuraEffect::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE + &AuraEffect::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM + &AuraEffect::HandleModFear, // 7 SPELL_AURA_MOD_FEAR + &AuraEffect::HandleNoImmediateEffect, // 8 SPELL_AURA_PERIODIC_HEAL implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED + &AuraEffect::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT + &AuraEffect::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT + &AuraEffect::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN + &AuraEffect::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE + &AuraEffect::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus + &AuraEffect::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage + &AuraEffect::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH + &AuraEffect::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_DETECT implement in GameObject::canDetectTrap and Unit::canDetectStealthOf + &AuraEffect::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY + &AuraEffect::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION + &AuraEffect::HandleNoImmediateEffect, // 20 SPELL_AURA_OBS_MOD_HEALTH implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleNoImmediateEffect, // 21 SPELL_AURA_OBS_MOD_POWER implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE + &AuraEffect::HandleNoImmediateEffect, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleNoImmediateEffect, // 24 SPELL_AURA_PERIODIC_ENERGIZE implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY + &AuraEffect::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT + &AuraEffect::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE + &AuraEffect::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult + &AuraEffect::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT + &AuraEffect::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL + &AuraEffect::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED + &AuraEffect::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED + &AuraEffect::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED + &AuraEffect::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH + &AuraEffect::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY + &AuraEffect::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT + &AuraEffect::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY + &AuraEffect::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY + &AuraEffect::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY + &AuraEffect::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY + &AuraEffect::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY + &AuraEffect::HandleNoImmediateEffect, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell + &AuraEffect::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor + &AuraEffect::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES + &AuraEffect::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES + &AuraEffect::HandleNULL, // 46 SPELL_AURA_46 (used in test spells 54054 and 54058, and spell 48050) (3.0.8a) + &AuraEffect::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT + &AuraEffect::HandleNULL, // 48 SPELL_AURA_48 spell Napalm (area damage spell with additional delayed damage effect) + &AuraEffect::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT + &AuraEffect::HandleNoImmediateEffect, // 50 SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT implemented in Unit::SpellCriticalHealingBonus + &AuraEffect::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT + &AuraEffect::HandleAuraModWeaponCritPercent, // 52 SPELL_AURA_MOD_WEAPON_CRIT_PERCENT + &AuraEffect::HandleNoImmediateEffect, // 53 SPELL_AURA_PERIODIC_LEECH implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE + &AuraEffect::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE + &AuraEffect::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM + &AuraEffect::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE + &AuraEffect::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED + &AuraEffect::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus + &AuraEffect::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE + &AuraEffect::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE + &AuraEffect::HandleNoImmediateEffect, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleNULL, // 63 unused (3.2.0) old SPELL_AURA_PERIODIC_MANA_FUNNEL + &AuraEffect::HandleNoImmediateEffect, // 64 SPELL_AURA_PERIODIC_MANA_LEECH implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK + &AuraEffect::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH + &AuraEffect::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM + &AuraEffect::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED + &AuraEffect::HandleNoImmediateEffect, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist + &AuraEffect::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS clientside + &AuraEffect::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL + &AuraEffect::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT + &AuraEffect::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL + &AuraEffect::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult + &AuraEffect::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE + &AuraEffect::HandleNoImmediateEffect, // 76 SPELL_AURA_FAR_SIGHT + &AuraEffect::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY + &AuraEffect::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED + &AuraEffect::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE + &AuraEffect::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT + &AuraEffect::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT implemented in Unit::CalcAbsorbResist + &AuraEffect::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING + &AuraEffect::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE + &AuraEffect::HandleNoImmediateEffect, // 84 SPELL_AURA_MOD_REGEN implemented in Player::RegenerateHealth + &AuraEffect::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN implemented in Player::Regenerate + &AuraEffect::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM + &AuraEffect::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus + &AuraEffect::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT implemented in Player::RegenerateHealth + &AuraEffect::HandleNoImmediateEffect, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT + &AuraEffect::HandleNULL, // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE + &AuraEffect::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance + &AuraEffect::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING + &AuraEffect::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE + &AuraEffect::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::Regenerate + &AuraEffect::HandleAuraGhost, // 95 SPELL_AURA_GHOST + &AuraEffect::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Unit::SelectMagnetTarget + &AuraEffect::HandleNoImmediateEffect, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist + &AuraEffect::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT + &AuraEffect::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER + &AuraEffect::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now, but still have spells including GM-spell + &AuraEffect::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT + &AuraEffect::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus + &AuraEffect::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT + &AuraEffect::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK + &AuraEffect::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL + &AuraEffect::HandleAuraHover, //106 SPELL_AURA_HOVER + &AuraEffect::HandleNoImmediateEffect, //107 SPELL_AURA_ADD_FLAT_MODIFIER implemented in AuraEffect::CalculateSpellMod() + &AuraEffect::HandleNoImmediateEffect, //108 SPELL_AURA_ADD_PCT_MODIFIER implemented in AuraEffect::CalculateSpellMod() + &AuraEffect::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER + &AuraEffect::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT implemented in Player::Regenerate, Creature::Regenerate + &AuraEffect::HandleNoImmediateEffect, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER implemented in Unit::SelectMagnetTarget + &AuraEffect::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS + &AuraEffect::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus + &AuraEffect::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus + &AuraEffect::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim + &AuraEffect::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT + &AuraEffect::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult + &AuraEffect::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus + &AuraEffect::HandleNULL, //119 unused (3.2.0) old SPELL_AURA_SHARE_PET_TRACKING + &AuraEffect::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE + &AuraEffect::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY + &AuraEffect::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT + &AuraEffect::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE + &AuraEffect::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER + &AuraEffect::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus + &AuraEffect::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus + &AuraEffect::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus + &AuraEffect::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET + &AuraEffect::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS + &AuraEffect::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS + &AuraEffect::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus + &AuraEffect::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT + &AuraEffect::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT + &AuraEffect::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT + &AuraEffect::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE + &AuraEffect::HandleNoImmediateEffect, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus + &AuraEffect::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE + &AuraEffect::HandleHaste, //138 SPELL_AURA_MOD_HASTE + &AuraEffect::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION + &AuraEffect::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE + &AuraEffect::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE + &AuraEffect::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT + &AuraEffect::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE + &AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes + &AuraEffect::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS + &AuraEffect::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE + &AuraEffect::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK + &AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS + &AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK + &AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT + &AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED + &AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance + &AuraEffect::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT + &AuraEffect::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL + &AuraEffect::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING + &AuraEffect::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN + &AuraEffect::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI + &AuraEffect::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE + &AuraEffect::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell + &AuraEffect::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult + &AuraEffect::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT + &AuraEffect::HandleNoImmediateEffect, //162 SPELL_AURA_POWER_BURN_MANA implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE + &AuraEffect::HandleUnused, //164 unused (3.2.0), only one test spell + &AuraEffect::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus + &AuraEffect::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT + &AuraEffect::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT + &AuraEffect::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus + &AuraEffect::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus + &AuraEffect::HandleNULL, //170 SPELL_AURA_DETECT_AMORE various spells that change visual of units for aura target (clientside?) + &AuraEffect::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK + &AuraEffect::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK + &AuraEffect::HandleNULL, //173 unused (3.2.0) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell + &AuraEffect::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus + &AuraEffect::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus + &AuraEffect::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end + &AuraEffect::HandleCharmConvert, //177 SPELL_AURA_AOE_CHARM + &AuraEffect::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult + &AuraEffect::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus + &AuraEffect::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus + &AuraEffect::HandleNULL, //181 unused (3.2.0) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS + &AuraEffect::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT + &AuraEffect::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 - miscvalue - spell school + &AuraEffect::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst + &AuraEffect::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst + &AuraEffect::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult + &AuraEffect::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance + &AuraEffect::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance + &AuraEffect::HandleModRating, //189 SPELL_AURA_MOD_RATING + &AuraEffect::HandleNoImmediateEffect, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN implemented in Player::CalculateReputationGain + &AuraEffect::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED + &AuraEffect::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE + &AuraEffect::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) + &AuraEffect::HandleNoImmediateEffect, //194 SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist + &AuraEffect::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist + &AuraEffect::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN - flat mod of spell cooldowns + &AuraEffect::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance + &AuraEffect::HandleNULL, //198 unused (3.2.0) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS + &AuraEffect::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult + &AuraEffect::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::RewardPlayerAndGroupAtKill + &AuraEffect::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode... + &AuraEffect::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst + &AuraEffect::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage + &AuraEffect::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage + &AuraEffect::HandleNULL, //205 SPELL_AURA_MOD_SCHOOL_CRIT_DMG_TAKEN + &AuraEffect::HandleAuraModIncreaseFlightSpeed, //206 SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED + &AuraEffect::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED + &AuraEffect::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED + &AuraEffect::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS + &AuraEffect::HandleAuraModIncreaseFlightSpeed, //210 SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS + &AuraEffect::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK + &AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT + &AuraEffect::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage + &AuraEffect::HandleNULL, //214 Tamed Pet Passive + &AuraEffect::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION + &AuraEffect::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS + &AuraEffect::HandleUnused, //217 unused (3.2.0) + &AuraEffect::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED + &AuraEffect::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT + &AuraEffect::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT + &AuraEffect::HandleNULL, //221 SPELL_AURA_MOD_DETAUNT + &AuraEffect::HandleUnused, //222 unused (3.2.0) only for spell 44586 that not used in real spell cast + &AuraEffect::HandleNoImmediateEffect, //223 SPELL_AURA_RAID_PROC_FROM_CHARGE + &AuraEffect::HandleUnused, //224 unused (3.0.8a) + &AuraEffect::HandleNoImmediateEffect, //225 SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE + &AuraEffect::HandleNoImmediateEffect, //226 SPELL_AURA_PERIODIC_DUMMY implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleNoImmediateEffect, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleNoImmediateEffect, //228 SPELL_AURA_DETECT_STEALTH stealth detection + &AuraEffect::HandleNoImmediateEffect, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE + &AuraEffect::HandleAuraModIncreaseHealth, //230 SPELL_AURA_MOD_INCREASE_HEALTH_2 + &AuraEffect::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE + &AuraEffect::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration + &AuraEffect::HandleUnused, //233 set model id to the one of the creature with id GetMiscValue() - clientside + &AuraEffect::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration + &AuraEffect::HandleNoImmediateEffect, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult + &AuraEffect::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE + &AuraEffect::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus + &AuraEffect::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus + &AuraEffect::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61 + &AuraEffect::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE + &AuraEffect::HandleForceMoveForward, //241 SPELL_AURA_FORCE_MOVE_FORWARD Forces the player to move forward + &AuraEffect::HandleNULL, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING - 2 test spells: 44183 and 44182 + &AuraEffect::HandleNULL, //243 faction reaction override spells + &AuraEffect::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE + &AuraEffect::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL + &AuraEffect::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura + &AuraEffect::HandleAuraCloneCaster, //247 SPELL_AURA_CLONE_CASTER + &AuraEffect::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst + &AuraEffect::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE + &AuraEffect::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2 + &AuraEffect::HandleNoImmediateEffect, //251 SPELL_AURA_MOD_ENEMY_DODGE + &AuraEffect::HandleModCombatSpeedPct, //252 SPELL_AURA_252 Is there any difference between this and SPELL_AURA_MELEE_SLOW ? maybe not stacking mod? + &AuraEffect::HandleNoImmediateEffect, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE implemented in Unit::isBlockCritical + &AuraEffect::HandleAuraModDisarm, //254 SPELL_AURA_MOD_DISARM_OFFHAND + &AuraEffect::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus + &AuraEffect::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select + &AuraEffect::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select + &AuraEffect::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL + &AuraEffect::HandleNoImmediateEffect, //259 SPELL_AURA_MOD_HOT_PCT implemented in Unit::SpellHealingBonus + &AuraEffect::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code + &AuraEffect::HandlePhase, //261 SPELL_AURA_PHASE undetactable invisibility? implemented in Unit::isVisibleForOrDetect + &AuraEffect::HandleNoImmediateEffect, //262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in spell::cancast + &AuraEffect::HandleAuraAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask + &AuraEffect::HandleUnused, //264 unused (3.2.0) + &AuraEffect::HandleUnused, //265 unused (3.2.0) + &AuraEffect::HandleUnused, //266 unused (3.2.0) + &AuraEffect::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect + &AuraEffect::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT + &AuraEffect::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage + &AuraEffect::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage + &AuraEffect::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus + &AuraEffect::HandleUnused, //272 unknown use for this aura + &AuraEffect::HandleUnused, //273 clientside + &AuraEffect::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets + &AuraEffect::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select + &AuraEffect::HandleNULL, //276 mod damage % mechanic? + &AuraEffect::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap + &AuraEffect::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon + &AuraEffect::HandleNoImmediateEffect, //279 SPELL_AURA_INITIALIZE_IMAGES + &AuraEffect::HandleNoImmediateEffect, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT + &AuraEffect::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor + &AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT + &AuraEffect::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus + &AuraEffect::HandleAuraLinked, //284 SPELL_AURA_LINKED + &AuraEffect::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage + &AuraEffect::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in AuraEffect::PeriodicTick + &AuraEffect::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult + &AuraEffect::HandleNoImmediateEffect, //288 SPELL_AURA_IGNORE_HIT_DIRECTION implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst + &AuraEffect::HandleNULL, //289 unused (3.2.0) + &AuraEffect::HandleAuraModCritPct, //290 SPELL_AURA_MOD_CRIT_PCT + &AuraEffect::HandleNoImmediateEffect, //291 SPELL_AURA_MOD_XP_QUEST_PCT implemented in Player::RewardQuest + &AuraEffect::HandleNULL, //292 call stabled pet + &AuraEffect::HandleNULL, //293 2 test spells + &AuraEffect::HandleNoImmediateEffect, //294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power) + &AuraEffect::HandleNULL, //296 2 spells + &AuraEffect::HandleNULL, //297 1 spell (counter spell school?) + &AuraEffect::HandleNULL, //298 unused + &AuraEffect::HandleNULL, //299 unused + &AuraEffect::HandleNULL, //300 3 spells (share damage?) + &AuraEffect::HandleNULL, //301 5 spells + &AuraEffect::HandleNULL, //302 unused + &AuraEffect::HandleNULL, //303 17 spells + &AuraEffect::HandleNULL, //304 2 spells (alcohol effect?) + &AuraEffect::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED + &AuraEffect::HandleNULL //306 1 spell +}; + +AuraEffect::AuraEffect(Aura * base, uint8 effIndex, int32 *baseAmount, Unit * caster) : + m_base(base), m_spellProto(base->GetSpellProto()), m_spellmod(NULL), m_periodicTimer(0), + m_tickNumber(0), m_effIndex(effIndex), m_isPeriodic(false), m_canBeRecalculated(true), + m_baseAmount (baseAmount ? *baseAmount : m_spellProto->EffectBasePoints[m_effIndex]) +{ + CalculatePeriodic(caster, true); + + m_amount = CalculateAmount(caster); + + CalculateSpellMod(); +} + +AuraEffect::~AuraEffect() +{ + if (m_spellmod) + delete m_spellmod; +} + +void AuraEffect::GetTargetList(std::list<Unit *> & targetList) const +{ + Aura::ApplicationMap const & targetMap = GetBase()->GetApplicationMap(); + // remove all targets which were not added to new list - they no longer deserve area aura + for (Aura::ApplicationMap::const_iterator appIter = targetMap.begin(); appIter != targetMap.end(); appIter++) + { + if(appIter->second->HasEffect(GetEffIndex())) + targetList.push_back(appIter->second->GetTarget()); + } +} + +int32 AuraEffect::CalculateAmount(Unit * caster) +{ + int32 amount; + // default amount calculation + if(caster) + amount = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_baseAmount, NULL); + else + amount = m_baseAmount + m_spellProto->EffectBaseDice[m_effIndex]; + + // check item enchant aura cast + if(!amount && caster) + if(uint64 itemGUID = GetBase()->GetCastItemGUID()) + if(Player *playerCaster = dynamic_cast<Player*>(caster)) + if(Item *castItem = playerCaster->GetItemByGuid(itemGUID)) + if (castItem->GetItemSuffixFactor()) + { + ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId())); + if(item_rand_suffix) + { + for (int k=0; k<MAX_SPELL_EFFECTS; k++) + { + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]); + if(pEnchant) + { + for (int t=0; t<MAX_SPELL_EFFECTS; t++) + if(pEnchant->spellid[t] == m_spellProto->Id) + { + amount = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 ); + break; + } + } + + if(amount) + break; + } + } + } + + float DoneActualBenefit = 0.0f; + + // custom amount calculations go here + switch(GetAuraType()) + { + // crowd control auras + case SPELL_AURA_MOD_CONFUSE: + case SPELL_AURA_MOD_FEAR: + case SPELL_AURA_MOD_STUN: + case SPELL_AURA_MOD_ROOT: + case SPELL_AURA_TRANSFORM: + m_canBeRecalculated = false; + if (!m_spellProto->procFlags) + break; + amount = GetBase()->GetUnitOwner()->GetMaxHealth()*0.10f; + if (caster) + { + // Glyphs increasing damage cap + Unit::AuraEffectList const& overrideClassScripts = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for (Unit::AuraEffectList::const_iterator itr = overrideClassScripts.begin(); itr != overrideClassScripts.end(); ++itr) + { + if((*itr)->IsAffectedOnSpell(m_spellProto)) + { + // Glyph of Fear, Glyph of Frost nova and similar auras + if ((*itr)->GetMiscValue() == 7801) + { + amount += (int32)(amount*(*itr)->GetAmount()/100.0f); + break; + } + } + } + } + break; + case SPELL_AURA_SCHOOL_ABSORB: + m_canBeRecalculated = false; + if (!caster) + break; + switch(GetSpellProto()->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + // Ice Barrier + if(GetSpellProto()->SpellFamilyFlags[1] & 0x1 && GetSpellProto()->SpellFamilyFlags[2] & 0x8) + { + // +80.67% from sp bonus + DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8067f; + } + break; + case SPELLFAMILY_WARLOCK: + // Shadow Ward + if(m_spellProto->SpellFamilyFlags[2]& 0x40) + { + // +30% from sp bonus + DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f; + } + break; + case SPELLFAMILY_PRIEST: + // Power Word: Shield + if(GetSpellProto()->SpellFamilyFlags[0] & 0x1 && GetSpellProto()->SpellFamilyFlags[2] & 0x400) + { + //+80.68% from sp bonus + float bonus = 0.8068f; + // Borrowed Time + if (AuraEffect const * aurEff = caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_PRIEST, 2899, 1)) + bonus += aurEff->GetAmount() / 100; + + DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(GetSpellProto())) * bonus; + } + break; + case SPELLFAMILY_PALADIN: + // Sacred Shield + if (m_spellProto->SpellFamilyFlags[1] & 0x80000) + { + // 0.75 from sp bonus + DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.75f; + } + break; + } + break; + case SPELL_AURA_MANA_SHIELD: + m_canBeRecalculated = false; + if (!caster) + break; + // Mana Shield + if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellProto()->SpellFamilyFlags[0] & 0x8000 && m_spellProto->SpellFamilyFlags[2] & 0x8) + { + // +80.53% from +spd bonus + DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8053f;; + } + break; + case SPELL_AURA_DUMMY: + if (!caster) + break; + // Earth Shield + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellProto->SpellFamilyFlags[1] & 0x400) + amount = caster->SpellHealingBonus(GetBase()->GetUnitOwner(), GetSpellProto(), amount, SPELL_DIRECT_DAMAGE); + break; + case SPELL_AURA_DAMAGE_SHIELD: + if (!caster) + break; + // Thorns + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x100) + // 3.3% from sp bonus + DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.033f; + break; + case SPELL_AURA_PERIODIC_DAMAGE: + if (!caster) + break; + // Rupture + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x100000) + { + m_canBeRecalculated = false; + if (caster->GetTypeId() != TYPEID_PLAYER) + break; + //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs + //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs + //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs + //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs + //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs + float AP_per_combo[6] = {0.0f, 0.015f, 0.024f, 0.03f, 0.03428571f, 0.0375f}; + uint8 cp = ((Player*)caster)->GetComboPoints(); + if (cp > 5) cp = 5; + amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]); + } + // Rip + else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x00800000 && GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE) + { + m_canBeRecalculated = false; + // 0.01*$AP*cp + if (caster->GetTypeId() != TYPEID_PLAYER) + break; + + uint8 cp = ((Player*)caster)->GetComboPoints(); + + // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs + if (AuraEffect const * aurEff = caster->GetAuraEffect(34241,0)) + amount += cp * aurEff->GetAmount(); + + amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); + } + // Rend + else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARRIOR && GetSpellProto()->SpellFamilyFlags[0] & 0x20) + { + m_canBeRecalculated = false; + // $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 mws = caster->GetAttackTime(BASE_ATTACK); + float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); + float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); + amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f); + // "If used while your target is above 75% health, Rend does 35% more damage." + // as for 3.1.3 only ranks above 9 (wrong tooltip?) + if (spellmgr.GetSpellRank(m_spellProto->Id) >= 9) + { + if (GetBase()->GetUnitOwner()->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, m_spellProto, caster)) + amount += int32(amount * m_spellProto->CalculateSimpleValue(2) / 100.0f); + } + } + break; + case SPELL_AURA_PERIODIC_ENERGIZE: + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_GENERIC) + { + // Replenishment (0.25% from max) + // Infinite Replenishment + if (m_spellProto->SpellIconID == 3184 && m_spellProto->SpellVisual[0] == 12495) + amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 25 / 10000; + } + // Innervate + else if (m_spellProto->Id == 29166) + amount = GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA) * amount / (GetTotalTicks() * 100.0f); + // Owlkin Frenzy + else if (m_spellProto->Id == 48391) + amount = GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA) * amount / 100; + break; + case SPELL_AURA_PERIODIC_HEAL: + if (!caster) + break; + // Lightwell Renew + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellProto->SpellFamilyFlags[2] & 0x4000) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + // Bonus from Glyph of Lightwell + if (AuraEffect* modHealing = caster->GetAuraEffect(55673, 0)) + amount *= (100.0f + modHealing->GetAmount()) / 100.0f; + } + break; + case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: + if (!caster) + break; + // Icebound Fortitude + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellProto->SpellFamilyFlags[0] & 0x00100000) + { + if (caster->GetTypeId() == TYPEID_PLAYER) + { + int32 value = int32((amount*-1)-10); + uint32 defva = uint32(((Player*)caster)->GetSkillValue(SKILL_DEFENSE) + ((Player*)caster)->GetRatingBonusValue(CR_DEFENSE_SKILL)); + + if(defva > 400) + value += int32((defva-400)*0.15); + + // Glyph of Icebound Fortitude + if (AuraEffect const * aurEff = caster->GetAuraEffect(58625,0)) + { + uint32 valMax = aurEff->GetAmount(); + if(value < valMax) + value = valMax; + } + amount = -value; + } + } + break; + case SPELL_AURA_MOD_THREAT: + { + uint8 level_diff = 0; + float multiplier = 0.0; + switch (GetId()) + { + // Arcane Shroud + case 26400: + level_diff = GetBase()->GetUnitOwner()->getLevel() - 60; + multiplier = 2; + break; + // The Eye of Diminution + case 28862: + level_diff = GetBase()->GetUnitOwner()->getLevel() - 60; + multiplier = 1; + break; + } + if (level_diff > 0) + amount += multiplier * level_diff; + break; + } + case SPELL_AURA_MOD_INCREASE_HEALTH: + // Vampiric Blood + if (GetId() == 55233) + amount = GetBase()->GetUnitOwner()->GetMaxHealth() * amount / 100; + break; + case SPELL_AURA_MOD_INCREASE_ENERGY: + // Hymn of Hope + if (GetId() == 64904) + amount = GetBase()->GetUnitOwner()->GetMaxPower(GetBase()->GetUnitOwner()->getPowerType()) * amount / 100; + break; + case SPELL_AURA_MOD_INCREASE_SPEED: + // Dash - do not set speed if not in cat form + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags[2] & 0x00000008) + amount = GetBase()->GetUnitOwner()->m_form == FORM_CAT ? amount : 0; + } + if (DoneActualBenefit != 0.0f) + { + DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto()); + amount += (int32)DoneActualBenefit; + } + amount *= GetBase()->GetStackAmount(); + return amount; +} + +void AuraEffect::CalculatePeriodic(Unit * caster, bool create) +{ + m_amplitude = m_spellProto->EffectAmplitude[m_effIndex]; + + // prepare periodics + switch (GetAuraType()) + { + case SPELL_AURA_OBS_MOD_POWER: + // 3 spells have no amplitude set + if (!m_amplitude) + m_amplitude = 1 * IN_MILISECONDS; + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_POWER_BURN_MANA: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: + case SPELL_AURA_PERIODIC_DUMMY: + m_isPeriodic = true; + break; + case SPELL_AURA_DUMMY: + // Haunting Spirits - perdiodic trigger demon + if (GetId() == 7057) + { + m_isPeriodic = true; + m_amplitude = irand (0, 60) + 30; + m_amplitude *= IN_MILISECONDS; + } + break; + } + + if (!m_isPeriodic) + return; + + Player* modOwner = caster ? caster->GetSpellModOwner() : NULL; + //apply casting time mods for channeled spells + if(modOwner && m_amplitude && IsChanneledSpell(m_spellProto)) + modOwner->ModSpellCastTime(m_spellProto, m_amplitude); + + // Apply periodic time mod + if(modOwner && m_amplitude) + modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_amplitude); + + if (create) + { + // Start periodic on next tick or at aura apply + if (m_amplitude && !(m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY)) + m_periodicTimer += m_amplitude; + } + else if (m_amplitude) // load aura from character_aura + { + m_tickNumber = GetBase()->GetDuration() / m_amplitude; + m_periodicTimer = GetBase()->GetDuration() % m_amplitude; + if (m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY) + ++m_tickNumber; + } +} + +void AuraEffect::CalculateSpellMod() +{ + switch (GetAuraType()) + { + case SPELL_AURA_DUMMY: + switch(GetSpellProto()->SpellFamilyName) + { + case SPELLFAMILY_PRIEST: + // Pain and Suffering + if(m_spellProto->SpellIconID == 2874) + { + if (!m_spellmod) + { + m_spellmod = new SpellModifier(GetBase()); + m_spellmod->op = SPELLMOD_DOT; + m_spellmod->type = SPELLMOD_PCT; + m_spellmod->spellId = GetId(); + m_spellmod->mask[1] = 0x00002000; + } + m_spellmod->value = GetAmount(); + } + break; + case SPELLFAMILY_DRUID: + switch (GetId()) + { + case 34246: // Idol of the Emerald Queen + case 60779: // Idol of Lush Moss + { + if (!m_spellmod) + { + m_spellmod = new SpellModifier(GetBase()); + m_spellmod->op = SPELLMOD_DOT; + m_spellmod->type = SPELLMOD_FLAT; + m_spellmod->spellId = GetId(); + m_spellmod->mask[1] = 0x0010; + } + m_spellmod->value = GetAmount()/7; + } + break; + } + break; + } + case SPELL_AURA_PROC_TRIGGER_SPELL: + switch(GetId()) + { + case 51466: // Elemental oath + case 51470: // Elemental oath + // "while Clearcasting from Elemental Focus is active, you deal 5%/10% more spell damage." + if (!m_spellmod) + { + m_spellmod = new SpellModifier(GetBase()); + m_spellmod->op = SPELLMOD_EFFECT2; + m_spellmod->type = SPELLMOD_FLAT; + m_spellmod->spellId = GetId(); + m_spellmod->mask[1] = 0x0004000; + } + m_spellmod->value = GetBase()->GetUnitOwner()->CalculateSpellDamage(GetSpellProto(), 1, GetSpellProto()->EffectBasePoints[1], GetBase()->GetUnitOwner()); + break; + } + // Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && GetSpellProto()->SpellFamilyFlags[0] & 0x00004000) + { + if (!m_spellmod) + { + m_spellmod = new SpellModifier(GetBase()); + m_spellmod->op = SPELLMOD_DOT; + m_spellmod->type = SPELLMOD_PCT; + m_spellmod->spellId = GetId(); + m_spellmod->mask[0] = 0x00004000; + // 300% more dmg + if (GetBase()->GetUnitOwner()->GetMaxHealth() / 4 > GetBase()->GetUnitOwner()->GetHealth()) + m_spellmod->value = 300; + else + m_spellmod->value = 0; + } + } + break; + case SPELL_AURA_ADD_FLAT_MODIFIER: + case SPELL_AURA_ADD_PCT_MODIFIER: + if (!m_spellmod) + { + m_spellmod = new SpellModifier(GetBase()); + m_spellmod->op = SpellModOp(GetMiscValue()); + assert(m_spellmod->op < MAX_SPELLMOD); + + m_spellmod->type = SpellModType(GetAuraType()); // SpellModType value == spell aura types + m_spellmod->spellId = GetId(); + m_spellmod->mask = GetSpellProto()->EffectSpellClassMask[GetEffIndex()]; + m_spellmod->charges = GetBase()->GetCharges(); + } + m_spellmod->value = GetAmount(); + break; + } +} + +void AuraEffect::ChangeAmount(int32 newAmount, bool mark) +{ + Unit * caster = GetCaster(); + // Reapply if amount change + if (newAmount!=GetAmount()) + { + UnitList targetList; + GetTargetList(targetList); + for (UnitList::iterator aurEffTarget = targetList.begin(); aurEffTarget != targetList.end(); ++aurEffTarget) + { + HandleEffect(*aurEffTarget, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, false); + } + if (!mark) + m_amount = newAmount; + else + SetAmount(newAmount); + CalculateSpellMod(); + for (UnitList::iterator aurEffTarget = targetList.begin(); aurEffTarget != targetList.end(); ++aurEffTarget) + { + HandleEffect(*aurEffTarget, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, true); + } + } +} + +void AuraEffect::HandleEffect(AuraApplication const * aurApp, uint8 mode, bool apply) +{ + // check if call is correct + assert(!mode + || mode == AURA_EFFECT_HANDLE_REAL + || mode == AURA_EFFECT_HANDLE_SEND_FOR_CLIENT + || mode == AURA_EFFECT_HANDLE_CHANGE_AMOUNT + || mode == AURA_EFFECT_HANDLE_STAT); + + // real aura apply/remove, handle modifier + if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK) + ApplySpellMod(aurApp->GetTarget(), apply); + + (*this.*AuraEffectHandler [GetAuraType()])(aurApp, mode, apply); +} + +void AuraEffect::HandleEffect(Unit * target, uint8 mode, bool apply) +{ + AuraApplication const * aurApp = GetBase()->GetApplicationOfTarget(target->GetGUID()); + assert(aurApp); + HandleEffect(aurApp, mode, apply); +} + +void AuraEffect::ApplySpellMod(Unit * target, bool apply) +{ + if(!m_spellmod || target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)target)->AddSpellMod(m_spellmod, apply); + + // Auras with charges do not mod amount of passive auras + if (GetBase()->GetCharges()) + return; + // reapply some passive spells after add/remove related spellmods + // Warning: it is a dead loop if 2 auras each other amount-shouldn't happen + switch (GetMiscValue()) + { + case SPELLMOD_ALL_EFFECTS: + case SPELLMOD_EFFECT1: + case SPELLMOD_EFFECT2: + case SPELLMOD_EFFECT3: + { + uint64 guid = target->GetGUID(); + Unit::AuraApplicationMap & auras = target->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator iter = auras.begin(); iter != auras.end(); ++iter) + { + Aura * aura = iter->second->GetBase(); + // only passive auras-active auras should have amount set on spellcast and not be affected + // if aura is casted by others, it will not be affected + if (aura->IsPassive() && aura->GetCasterGUID() == guid && spellmgr.IsAffectedByMod(aura->GetSpellProto(), m_spellmod)) + { + if (GetMiscValue() == SPELLMOD_ALL_EFFECTS) + { + for (uint8 i = 0; i<MAX_SPELL_EFFECTS; ++i) + { + if (AuraEffect * aurEff = aura->GetEffect(i)) + aurEff->RecalculateAmount(); + } + } + else if (GetMiscValue() == SPELLMOD_EFFECT1) + { + if (AuraEffect * aurEff = aura->GetEffect(0)) + aurEff->RecalculateAmount(); + } + else if (GetMiscValue() == SPELLMOD_EFFECT2) + { + if (AuraEffect * aurEff = aura->GetEffect(1)) + aurEff->RecalculateAmount(); + } + else //if (modOp ==SPELLMOD_EFFECT3) + { + if (AuraEffect * aurEff = aura->GetEffect(2)) + aurEff->RecalculateAmount(); + } + } + } + } + default: + break; + } +} + +void AuraEffect::Update(uint32 diff, Unit * caster) +{ + if (m_isPeriodic && (GetBase()->GetDuration() >=0 || GetBase()->IsPassive() || GetBase()->IsPermanent())) + { + if(m_periodicTimer > diff) + m_periodicTimer -= diff; + else // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N + { + ++m_tickNumber; + + // update before tick (aura can be removed in TriggerSpell or PeriodicTick calls) + m_periodicTimer += m_amplitude - diff; + UpdatePeriodic(caster); + + UnitList effectTargets; + GetTargetList(effectTargets); + // tick on targets of effects + if (!caster || !caster->hasUnitState(UNIT_STAT_ISOLATED)) + { + for (UnitList::iterator targetItr = effectTargets.begin(); targetItr != effectTargets.end(); ++targetItr) + PeriodicTick(*targetItr, caster); + } + } + } +} + +void AuraEffect::UpdatePeriodic(Unit * caster) +{ + switch(GetAuraType()) + { + case SPELL_AURA_PERIODIC_DAMAGE: + switch (GetId()) + { + case 41337: // Aura of Anger + if (AuraEffect * aurEff = GetBase()->GetEffect(1)) + aurEff->ChangeAmount(aurEff->GetAmount()+5); + SetAmount(100 * m_tickNumber); + break; + case 46394: // Brutallus Burn + if (m_tickNumber % 11 == 0) + SetAmount(GetAmount() * 2); ; + break; + } + break; + case SPELL_AURA_DUMMY: + // Haunting Spirits + if (GetId() == 7057) + { + m_amplitude = irand (0 , 60 ) + 30; + m_amplitude *= IN_MILISECONDS; + } + break; + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + switch (GetId()) + { + // Sniper training + case 53302: + case 53303: + case 53304: + Unit * target = GetBase()->GetUnitOwner(); + if (target->GetTypeId() != TYPEID_PLAYER) + break; + + if (((Player*)target)->isMoving()) + m_amount = target->CalculateSpellDamage(m_spellProto,m_effIndex,m_baseAmount,target); + else + --m_amount; + break; + } + break; + case SPELL_AURA_PERIODIC_DUMMY: + switch(GetSpellProto()->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + switch(GetId()) + { + // Drink + case 430: + case 431: + case 432: + case 1133: + case 1135: + case 1137: + case 10250: + case 22734: + case 27089: + case 34291: + case 43182: + case 43183: + case 46755: + case 49472: // Drink Coffee + case 57073: + case 61830: + if (!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + // Get SPELL_AURA_MOD_POWER_REGEN aura from spell + if (AuraEffect * aurEff = GetBase()->GetEffect(0)) + { + if (aurEff->GetAuraType() != SPELL_AURA_MOD_POWER_REGEN) + { + m_isPeriodic = false; + sLog.outError("Aura %d structure has been changed - first aura is no longer SPELL_AURA_MOD_POWER_REGEN", GetId()); + } + else + { + // default case - not in arena + if (!((Player*)caster)->InArena()) + { + aurEff->ChangeAmount(GetAmount()); + m_isPeriodic = false; + } + else + { + //********************************************** + // This feature uses only in arenas + //********************************************** + // Here need increase mana regen per tick (6 second rule) + // on 0 tick - 0 (handled in 2 second) + // on 1 tick - 166% (handled in 4 second) + // on 2 tick - 133% (handled in 6 second) + + // Apply bonus for 1 - 4 tick + switch (m_tickNumber) + { + case 1: // 0% + aurEff->ChangeAmount(0); + break; + case 2: // 166% + aurEff->ChangeAmount(GetAmount() * 5 / 3); + break; + case 3: // 133% + aurEff->ChangeAmount(GetAmount() * 4 / 3); + break; + default: // 100% - normal regen + aurEff->ChangeAmount(GetAmount()); + // No need to update after 4th tick + m_isPeriodic = false; + break; + } + } + } + } + break; + case 58549: // Tenacity + case 59911: // Tenacity (vehicle) + GetBase()->RefreshDuration(); + break; + } + break; + case SPELLFAMILY_MAGE: + if (GetId() == 55342)// Mirror Image + m_isPeriodic = false; + break; + case SPELLFAMILY_DEATHKNIGHT: + // Chains of Ice + if (GetSpellProto()->SpellFamilyFlags[1] & 0x00004000) + { + // Get 0 effect aura + if (AuraEffect *slow = GetBase()->GetEffect(0)) + { + int32 newAmount = slow->GetAmount() + GetAmount(); + if (newAmount > 0) + newAmount = 0; + slow->ChangeAmount(newAmount); + } + return; + } + } + } +} + +bool AuraEffect::IsPeriodicTickCrit(Unit * target, Unit const * caster) const +{ + assert(caster); + Unit::AuraEffectList const& mPeriodicCritAuras= caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_PERIODIC_CRIT); + for (Unit::AuraEffectList::const_iterator itr = mPeriodicCritAuras.begin(); itr != mPeriodicCritAuras.end(); ++itr) + { + if ((*itr)->IsAffectedOnSpell(m_spellProto) && caster->isSpellCrit(target, m_spellProto, GetSpellSchoolMask(m_spellProto))) + return true; + } + return false; +} + +void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const +{ + if(!target->isAlive() || target->hasUnitState(UNIT_STAT_ISOLATED)) + return; + + switch(GetAuraType()) + { + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + { + if(!caster) + break; + + // Consecrate ticks can miss and will not show up in the combat log + if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && + caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE) + break; + + // Check for immune (not use charges) + if (target->IsImmunedToDamage(GetSpellProto())) + break; + + // some auras remove at specific health level or more + if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE) + { + switch (GetId()) + { + case 43093: case 31956: case 38801: // Grievous Wound + case 35321: case 38363: case 39215: // Gushing Wound + if(target->GetHealth() == target->GetMaxHealth()) + { + target->RemoveAurasDueToSpell(GetId()); + return; + } + break; + case 38772: // Grievous Wound + { + uint32 percent = + GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ? + caster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],target) : + 100; + if(target->GetHealth()*100 >= target->GetMaxHealth()*percent) + { + target->RemoveAurasDueToSpell(GetId()); + return; + } + break; + } + } + } + + uint32 absorb=0; + uint32 resist=0; + CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL ); + + // ignore non positive values (can be result apply spellmods to aura damage + uint32 damage = GetAmount() > 0 ? GetAmount() : 0; + + if(GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE) + { + damage = caster->SpellDamageBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount()); + + // Calculate armor mitigation if it is a physical spell + // But not for bleed mechanic spells + if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL && + GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED) + { + uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto()); + cleanDamage.mitigated_damage += damage - damageReductedArmor; + damage = damageReductedArmor; + } + + // Curse of Agony damage-per-tick calculation + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID==544) + { + uint32 totalTick = GetTotalTicks(); + // 1..4 ticks, 1/2 from normal tick damage + if(m_tickNumber <= totalTick / 3) + damage = damage/2; + // 9..12 ticks, 3/2 from normal tick damage + else if(m_tickNumber > totalTick * 2 / 3) + damage += (damage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks + // 5..8 ticks have normal tick damage + } + // There is a Chance to make a Soul Shard when Drain soul does damage + if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x00004000)) + { + if(caster && roll_chance_i(20)) + caster->CastSpell(caster, 24827, true, 0, this); + } + } + else + damage = uint32(target->GetMaxHealth()*damage/100); + + bool crit = IsPeriodicTickCrit(target, caster); + if (crit) + damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target); + + // only from players + if (IS_PLAYER_GUID(GetCasterGUID())) + damage -= target->GetSpellDamageReduction(damage); + + caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto); + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(),absorb); + + caster->DealDamageMods(target,damage,&absorb); + + // Set trigger flag + uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; + uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; + uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_DOT; + damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist); + if (damage) + procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; + + int32 overkill = damage - target->GetHealth(); + if (overkill < 0) + overkill = 0; + + SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit); + target->SendPeriodicAuraLog(&pInfo); + + caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto()); + + caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); + break; + } + case SPELL_AURA_PERIODIC_LEECH: + { + if(!caster) + return; + + if(!caster->isAlive()) + return; + + if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && + caster->SpellHitResult(target,GetSpellProto(),false)!=SPELL_MISS_NONE) + return; + + // Check for immune + if(target->IsImmunedToDamage(GetSpellProto())) + return; + + uint32 absorb=0; + uint32 resist=0; + CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL ); + + //uint32 damage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 damage = GetAmount() > 0 ? GetAmount() : 0; + damage = caster->SpellDamageBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount()); + + bool crit = IsPeriodicTickCrit(target, caster); + if (crit) + damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target); + + //Calculate armor mitigation if it is a physical spell + if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL) + { + uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto()); + cleanDamage.mitigated_damage += damage - damageReductedArmor; + damage = damageReductedArmor; + } + + // Reduce dot damage from resilience for players. + if (target->GetTypeId() == TYPEID_PLAYER) + damage-=target->GetSpellDamageReduction(damage); + + caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto); + + if(target->GetHealth() < damage) + damage = uint32(target->GetHealth()); + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(),absorb); + + caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0, crit); + + // Set trigger flag + uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; + uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; + uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_DOT; + damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist); + if (damage) + procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; + caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto()); + int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false); + + if (!target->isAlive() && caster->IsNonMeleeSpellCasted(false)) + for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) + if (Spell* spell = caster->GetCurrentSpell(CurrentSpellTypes(i))) + if (spell->m_spellInfo->Id == GetId()) + spell->cancel(); + + float multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()]; + + if(Player *modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetSpellProto()->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); + + uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellProto(), uint32(new_damage * multiplier), DOT, GetBase()->GetStackAmount())); + + int32 gain = caster->DealHeal(caster, heal, GetSpellProto()); + caster->getHostilRefManager().threatAssist(caster, gain * 0.5f, GetSpellProto()); + break; + } + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: // only three spells + { + if(!caster || !caster->GetHealth()) + break; + + uint32 damage = GetAmount(); + // do not kill health donator + if(caster->GetHealth() < damage) + damage = caster->GetHealth() - 1; + if(!damage) + break; + + //donator->SendSpellNonMeleeDamageLog(donator, GetId(), damage, GetSpellSchoolMask(spellProto), 0, 0, false, 0); + caster->ModifyHealth(-(int32)damage); + sLog.outDebug("PeriodicTick: donator %u target %u damage %u.", target->GetEntry(), target->GetEntry(), damage); + + float multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()]; + + if(Player *modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetSpellProto()->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); + + damage *= multiplier; + + caster->DealHeal(target, damage, GetSpellProto()); + break; + } + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_OBS_MOD_HEALTH: + { + if(!caster) + break; + + // heal for caster damage (must be alive) + if(target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL && !caster->isAlive()) + break; + + if(GetBase()->GetDuration() == -1 && target->GetHealth() == target->GetMaxHealth()) + break; + + // ignore non positive values (can be result apply spellmods to aura damage + int32 damage = m_amount > 0 ? m_amount : 0; + + if(GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH) + damage = uint32(target->GetMaxHealth() * damage / 100); + else + { + // Wild Growth = amount + (6 - 2*doneTicks) * ticks* amount / 100 + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellIconID == 2864) + { + damage += float(damage * GetTotalTicks()) * ((6-float(2*(GetTickNumber()-1)))/100); + } + + damage = caster->SpellHealingBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount()); + } + + bool crit = IsPeriodicTickCrit(target, caster); + if (crit) + damage = caster->SpellCriticalHealingBonus(m_spellProto, damage, target); + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId()); + + int32 gain = target->ModifyHealth(damage); + + SpellPeriodicAuraLogInfo pInfo(this, damage, damage - gain, 0, 0, 0.0f, crit); + target->SendPeriodicAuraLog(&pInfo); + + // add HoTs to amount healed in bgs + if( caster->GetTypeId() == TYPEID_PLAYER ) + if( BattleGround *bg = ((Player*)caster)->GetBattleGround() ) + bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain); + + target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto()); + + bool haveCastItem = GetBase()->GetCastItemGUID() != 0; + + // Health Funnel + // damage caster for heal amount + if(target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL) + { + uint32 damage = gain; + uint32 absorb = 0; + caster->DealDamageMods(caster,damage,&absorb); + caster->SendSpellNonMeleeDamageLog(caster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false); + + CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL ); + caster->DealDamage(caster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); + } + + uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; + uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; + uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_HOT; + // ignore item heals + if(!haveCastItem) + caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto()); + break; + } + case SPELL_AURA_PERIODIC_MANA_LEECH: + { + if(GetMiscValue() < 0 || GetMiscValue() >= MAX_POWERS) + break; + + Powers power = Powers(GetMiscValue()); + + // power type might have changed between aura applying and tick (druid's shapeshift) + if(target->getPowerType() != power) + break; + + if(!caster || !caster->isAlive()) + break; + + if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && + caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE) + break; + + // Check for immune (not use charges) + if(target->IsImmunedToDamage(GetSpellProto())) + break; + + // ignore non positive values (can be result apply spellmods to aura damage + uint32 damage = m_amount > 0 ? m_amount : 0; + + // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana) + // It's mana percent cost spells, m_amount is percent drain from target + if (m_spellProto->ManaCostPercentage) + { + // max value + uint32 maxmana = caster->GetMaxPower(power) * damage * 2 / 100; + damage = target->GetMaxPower(power) * damage / 100; + if(damage > maxmana) + damage = maxmana; + } + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId()); + + int32 drain_amount = target->GetPower(power) > damage ? damage : target->GetPower(power); + + // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) + if (power == POWER_MANA) + drain_amount -= target->GetSpellCritDamageReduction(drain_amount); + + target->ModifyPower(power, -drain_amount); + + float gain_multiplier = 0.0f; + + if(caster->GetMaxPower(power) > 0) + { + gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()]; + + if(Player *modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier); + } + + SpellPeriodicAuraLogInfo pInfo(this, drain_amount, 0, 0, 0, gain_multiplier, false); + target->SendPeriodicAuraLog(&pInfo); + + int32 gain_amount = int32(drain_amount*gain_multiplier); + + if(gain_amount) + { + int32 gain = caster->ModifyPower(power,gain_amount); + target->AddThreat(caster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); + } + + switch(GetId()) + { + case 31447: // Mark of Kaz'rogal + if(target->GetPower(power) == 0) + { + target->CastSpell(target, 31463, true, 0, this); + // Remove aura + GetBase()->SetDuration(0); + } + break; + + case 32960: // Mark of Kazzak + int32 modifier = (target->GetPower(power) * 0.05f); + target->ModifyPower(power, -modifier); + + if(target->GetPower(power) == 0) + { + target->CastSpell(target, 32961, true, 0, this); + // Remove aura + GetBase()->SetDuration(0); + } + } + // Drain Mana + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK + && m_spellProto->SpellFamilyFlags[0] & 0x00000010) + { + int32 manaFeedVal = 0; + if (AuraEffect const * aurEff = GetBase()->GetEffect(1)) + manaFeedVal = aurEff->GetAmount(); + // Mana Feed - Drain Mana + if(manaFeedVal > 0) + { + manaFeedVal = manaFeedVal * gain_amount / 100; + caster->CastCustomSpell(caster, 32554, &manaFeedVal, NULL, NULL, true, NULL, this); + } + } + break; + } + case SPELL_AURA_OBS_MOD_POWER: + { + if(GetMiscValue() < 0) + return; + + Powers power; + if (GetMiscValue() == POWER_ALL) + power = target->getPowerType(); + else + power = Powers(GetMiscValue()); + + if(target->GetMaxPower(power) == 0) + return; + + if(GetBase()->GetDuration() == -1 && target->GetPower(power) == target->GetMaxPower(power)) + return; + + uint32 amount = m_amount * target->GetMaxPower(power) /100; + sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId()); + + SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false); + target->SendPeriodicAuraLog(&pInfo); + + int32 gain = target->ModifyPower(power,amount); + + if(caster) + target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto()); + break; + } + case SPELL_AURA_PERIODIC_ENERGIZE: + { + // ignore non positive values (can be result apply spellmods to aura damage + if(m_amount < 0 || GetMiscValue() >= MAX_POWERS) + return; + + Powers power = Powers(GetMiscValue()); + + if(target->GetMaxPower(power) == 0) + return; + + if(GetBase()->GetDuration() ==-1 && target->GetPower(power)==target->GetMaxPower(power)) + return; + + uint32 amount = m_amount; + + SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false); + target->SendPeriodicAuraLog(&pInfo); + + sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId()); + + int32 gain = target->ModifyPower(power,amount); + + if(caster) + target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto()); + break; + } + case SPELL_AURA_POWER_BURN_MANA: + { + if(!caster) + return; + + // Check for immune (not use charges) + if(target->IsImmunedToDamage(GetSpellProto())) + return; + + int32 damage = m_amount > 0 ? m_amount : 0; + + Powers powerType = Powers(GetMiscValue()); + + if(!target->isAlive() || target->getPowerType() != powerType) + return; + + // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) + if (powerType == POWER_MANA) + damage -= target->GetSpellCritDamageReduction(damage); + + uint32 gain = uint32(-target->ModifyPower(powerType, -damage)); + + gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]); + + SpellEntry const* spellProto = GetSpellProto(); + //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG + SpellNonMeleeDamage damageInfo(caster, target, spellProto->Id, spellProto->SchoolMask); + //no SpellDamageBonus for burn mana + caster->CalculateSpellDamageTaken(&damageInfo, gain, spellProto); + + caster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb); + + caster->SendSpellNonMeleeDamageLog(&damageInfo); + + // Set trigger flag + uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; + uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; + uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE) | PROC_EX_INTERNAL_DOT; + if (damageInfo.damage) + procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; + + caster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto); + + caster->DealSpellDamage(&damageInfo, true); + break; + } + case SPELL_AURA_DUMMY: + // Haunting Spirits + if (GetId() == 7057) + target->CastSpell((Unit*)NULL , GetAmount() , true); + break; + case SPELL_AURA_PERIODIC_DUMMY: + PeriodicDummyTick(target, caster); + break; + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + TriggerSpell(target, caster); + break; + case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: + TriggerSpellWithValue(target, caster); + break; + } +} + +void AuraEffect::PeriodicDummyTick(Unit * target, Unit * caster) const +{ + switch (GetSpellProto()->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + switch (GetId()) + { + // Forsaken Skills + case 7054: + { + // Possibly need cast one of them (but + // 7038 Forsaken Skill: Swords + // 7039 Forsaken Skill: Axes + // 7040 Forsaken Skill: Daggers + // 7041 Forsaken Skill: Maces + // 7042 Forsaken Skill: Staves + // 7043 Forsaken Skill: Bows + // 7044 Forsaken Skill: Guns + // 7045 Forsaken Skill: 2H Axes + // 7046 Forsaken Skill: 2H Maces + // 7047 Forsaken Skill: 2H Swords + // 7048 Forsaken Skill: Defense + // 7049 Forsaken Skill: Fire + // 7050 Forsaken Skill: Frost + // 7051 Forsaken Skill: Holy + // 7053 Forsaken Skill: Shadow + return; + } + case 45472: // Parachute + if (target->GetTypeId() == TYPEID_PLAYER) + { + Player *plr = (Player*)target; + if (plr->IsFalling()) + { + plr->RemoveAurasDueToSpell(45472); + plr->CastSpell(plr, 44795, true); + } + } + break; + case SPELL_RESTRICTED_FLIGHT_AREA_58730: // No Fly Zone - Wintergrasp + case SPELL_RESTRICTED_FLIGHT_AREA_58600: // No fly Zone - Dalaran + if (GetTickNumber() == 10) + { + target->RemoveAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED); + target->RemoveAurasByType(SPELL_AURA_FLY); + } + break; + case 62292: // Blaze (Pool of Tar) + // should we use custom damage? + target->CastSpell((Unit*)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true); + break; + case 62399: // Overload Circuit + if(target->GetMap()->IsDungeon() && target->GetAppliedAuras().count(62399) >= (target->GetMap()->IsHeroic() ? 4 : 2)) + { + target->CastSpell(target, 62475, true); // System Shutdown + if(Unit *veh = target->GetVehicleBase()) + veh->CastSpell(target, 62475, true); + } + break; + case 64821: // Fuse Armor (Razorscale) + if(GetBase()->GetStackAmount() == GetSpellProto()->StackAmount) + { + target->CastSpell(target, 64774, true, NULL, NULL, GetCasterGUID()); + target->RemoveAura(64821); + } + break; + } + break; + case SPELLFAMILY_MAGE: + { + // Mirror Image + if (GetId() == 55342) + // Set name of summons to name of caster + target->CastSpell((Unit *)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true); + break; + } + case SPELLFAMILY_WARLOCK: + { + switch (GetSpellProto()->Id) + { + // Demonic Circle + case 48018: + if(GameObject* obj = target->GetGameObject(GetSpellProto()->Id)) + { + if (target->IsWithinDist(obj, GetSpellMaxRange(48020, true))) + { + if (!target->HasAura(62388)) + target->CastSpell(target, 62388, true); + } + else + target->RemoveAura(62388); + } + break; + } + break; + } + case SPELLFAMILY_DRUID: + { + switch (GetSpellProto()->Id) + { + // Frenzied Regeneration + case 22842: + { + // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health. + // Should be manauser + if (target->getPowerType()!=POWER_RAGE) + break; + uint32 rage = target->GetPower(POWER_RAGE); + // Nothing todo + if (rage == 0) + break; + int32 mod = (rage < 100) ? rage : 100; + int32 points = target->CalculateSpellDamage(GetSpellProto(), 1, GetSpellProto()->EffectBasePoints[1], target); + int32 regen = target->GetMaxHealth() * (mod * points / 10) / 1000; + target->CastCustomSpell(target, 22845, ®en, 0, 0, true, 0, this); + target->SetPower(POWER_RAGE, rage-mod); + break; + } + // Force of Nature + case 33831: + break; + } + break; + } + case SPELLFAMILY_ROGUE: + { + switch (GetSpellProto()->Id) + { + // Master of Subtlety + case 31666: + if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH)) + target->RemoveAurasDueToSpell(31665); + break; + // Killing Spree + case 51690: + { + // TODO: this should use effect[1] of 51690 + UnitList targets; + { + // eff_radius ==0 + float radius = GetSpellMaxRange(GetSpellProto(), false); + + CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(),caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(caster, caster, radius); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(caster,targets, u_check); + + TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); + TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); + + CellLock<GridReadGuard> cell_lock(cell, p); + + cell_lock->Visit(cell_lock, grid_object_checker, *GetBase()->GetOwner()->GetMap(), *caster, radius); + cell_lock->Visit(cell_lock, world_object_checker, *GetBase()->GetOwner()->GetMap(), *caster, radius); + } + + if(targets.empty()) + return; + + UnitList::const_iterator itr = targets.begin(); + std::advance(itr, rand()%targets.size()); + Unit* spellTarget = *itr; + + target->CastSpell(spellTarget, 57840, true); + target->CastSpell(spellTarget, 57841, true); + break; + } + // Overkill + case 58428: + if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH)) + target->RemoveAurasDueToSpell(58427); + break; + } + break; + } + case SPELLFAMILY_HUNTER: + { + // Explosive Shot + if (GetSpellProto()->SpellFamilyFlags[1] & 0x80000000) + { + if(caster) + caster->CastCustomSpell(53352, SPELLVALUE_BASE_POINT0, m_amount, target, true, NULL, this); + break; + } + switch (GetSpellProto()->Id) + { + // Feeding Frenzy Rank 1 + case 53511: + if ( target->getVictim() && target->getVictim()->GetHealth() * 100 < target->getVictim()->GetMaxHealth() * 35 ) + target->CastSpell(target, 60096, true, 0, this); + return; + // Feeding Frenzy Rank 2 + case 53512: + if ( target->getVictim() && target->getVictim()->GetHealth() * 100 < target->getVictim()->GetMaxHealth() * 35 ) + target->CastSpell(target, 60097, true, 0, this); + return; + default: + break; + } + break; + } + case SPELLFAMILY_SHAMAN: + if (GetId() == 52179) // Astral Shift + { + // Periodic need for remove visual on stun/fear/silence lost + if (!(target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))) + target->RemoveAurasDueToSpell(52179); + break; + } + break; + case SPELLFAMILY_DEATHKNIGHT: + switch (GetId()) + { + case 49016: // Hysteria + uint32 damage = uint32(target->GetMaxHealth()*0.01f); + target->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + break; + } + // Death and Decay + if (GetSpellProto()->SpellFamilyFlags[0] & 0x20) + { + if (caster) + caster->CastCustomSpell(target, 52212, &m_amount, NULL, NULL, true, 0, this); + break; + } + // Blood of the North + // Reaping + // Death Rune Mastery + if (GetSpellProto()->SpellIconID == 3041 || GetSpellProto()->SpellIconID == 22 || GetSpellProto()->SpellIconID == 2622) + { + if (target->GetTypeId() != TYPEID_PLAYER) + return; + if(((Player*)target)->getClass() != CLASS_DEATH_KNIGHT) + return; + + // timer expired - remove death runes + ((Player*)target)->RemoveRunesByAuraEffect(this); + } + break; + } +} + +Unit* AuraEffect::GetTriggerTarget(Unit * target) const +{ + Unit * triggerTarget = NULL; + if (target->GetTypeId() == TYPEID_UNIT) + triggerTarget = ((Creature*)target)->AI()->GetAuraEffectTriggerTarget(GetId(), GetEffIndex()); + return triggerTarget ? triggerTarget : ObjectAccessor::GetUnit(*target, target->GetUInt64Value(UNIT_FIELD_TARGET)); +} + +void AuraEffect::TriggerSpell(Unit * target, Unit * caster) const +{ + Unit* triggerTarget = GetTriggerTarget(target); + if (!triggerTarget) + triggerTarget = target; + + if(!caster || !target) + return; + + // generic casting code with custom spells and target/caster customs + uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[GetEffIndex()]; + + SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId); + SpellEntry const *auraSpellInfo = GetSpellProto(); + uint32 auraId = auraSpellInfo->Id; + + // specific code for cases with no trigger spell provided in field + if (triggeredSpellInfo == NULL) + { + switch(auraSpellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + switch(auraId) + { + // Thaumaturgy Channel + case 9712: + triggerSpellId = 21029; + break; + // Brood Affliction: Bronze + case 23170: + target->CastSpell(target, 23171, true, 0, this); + return; + // Restoration + case 23493: + { + int32 heal = caster->GetMaxHealth() / 10; + caster->DealHeal(target, heal, auraSpellInfo); + + int32 mana = caster->GetMaxPower(POWER_MANA); + if (mana) + { + mana /= 10; + caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA); + } + return; + } + // Nitrous Boost + case 27746: + if (target->GetPower(POWER_MANA) >= 10) + { + target->ModifyPower( POWER_MANA, -10 ); + target->SendEnergizeSpellLog(caster, 27746, -10, POWER_MANA); + } + else + target->RemoveAurasDueToSpell(27746); + return; + // Frost Blast + case 27808: + caster->CastCustomSpell(29879, SPELLVALUE_BASE_POINT0, (float)target->GetMaxHealth()*0.26f, target, true, NULL, this); + return; + // Detonate Mana + case 27819: + if(int32 mana = (int32)(target->GetMaxPower(POWER_MANA) / 4)) + { + mana = target->ModifyPower(POWER_MANA, -mana); + target->CastCustomSpell(27820, SPELLVALUE_BASE_POINT0, -mana*4, NULL, true, NULL, this, caster->GetGUID()); + } + return; + // Inoculate Nestlewood Owlkin + case 29528: + if(triggerTarget->GetTypeId()!=TYPEID_UNIT)// prevent error reports in case ignored player target + return; + break; + // Feed Captured Animal + case 29917: + triggerSpellId = 29916; + break; + // Extract Gas + case 30427: + { + // move loot to player inventory and despawn target + if(caster->GetTypeId() ==TYPEID_PLAYER && + triggerTarget->GetTypeId() == TYPEID_UNIT && + ((Creature*)triggerTarget)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD) + { + Player* player = (Player*)caster; + Creature* creature = (Creature*)triggerTarget; + // missing lootid has been reported on startup - just return + if (!creature->GetCreatureInfo()->SkinLootId) + return; + + player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId,LootTemplates_Skinning,true); + + creature->ForcedDespawn(); + } + return; + } + // Quake + case 30576: triggerSpellId = 30571; break; + // Doom + case 31347: + { + target->CastSpell(target,31350,true, NULL, this); + target->Kill(target); + return; + } + // Spellcloth + case 31373: + { + // Summon Elemental after create item + target->SummonCreature(17870, 0, 0, 0, target->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); + return; + } + // Flame Quills + case 34229: + { + // cast 24 spells 34269-34289, 34314-34316 + for (uint32 spell_id = 34269; spell_id != 34290; ++spell_id) + caster->CastSpell(target,spell_id,true, NULL, this); + for (uint32 spell_id = 34314; spell_id != 34317; ++spell_id) + caster->CastSpell(target,spell_id,true, NULL, this); + return; + } + // Remote Toy + case 37027: triggerSpellId = 37029; break; + // Eye of Grillok + case 38495: + { + target->CastSpell(target, 38530, true, NULL, this); + return; + } + // Absorb Eye of Grillok (Zezzak's Shard) + case 38554: + { + if(target->GetTypeId() != TYPEID_UNIT) + return; + + caster->CastSpell(caster, 38495, true, NULL, this); + + Creature* creatureTarget = (Creature*)target; + + creatureTarget->ForcedDespawn(); + return; + } + // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam + case 39857: triggerSpellId = 39856; break; + // Personalized Weather + case 46736: triggerSpellId = 46737; break; + } + break; + } + case SPELLFAMILY_MAGE: + { + switch(auraId) + { + // Invisibility + case 66: + // Here need periodic triger reducing threat spell (or do it manually) + return; + } + break; + } + case SPELLFAMILY_DRUID: + { + switch(auraId) + { + // Cat Form + // triggerSpellId not set and unknown effect triggered in this case, ignoring for while + case 768: + return; + } + break; + } + case SPELLFAMILY_HUNTER: + { + switch (auraId) + { + // Sniper training + case 53302: + case 53303: + case 53304: + // We are standing at the moment + if (GetAmount() != -1) + return; + + triggerSpellId = 64418 + auraId - 53302; + + // If aura is active - no need to continue + if (target->HasAura(triggerSpellId)) + return; + break; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + switch(auraId) + { + // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield) + case 28820: + { + // Need remove self if Lightning Shield not active + if (!target->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN,0x400)) + target->RemoveAurasDueToSpell(28820); + return; + } + // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus) + case 38443: + { + bool all = true; + for (int i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i) + { + if(!target->m_SummonSlot[i]) + { + all = false; + break; + } + } + + if(all) + caster->CastSpell(target,38437,true, NULL, this); + else + target->RemoveAurasDueToSpell(38437); + return; + } + } + break; + } + } + + // Reget trigger spell proto + triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId); + } + else + { + // Spell exist but require custom code + switch(auraId) + { + // Mana Tide + case 16191: + { + caster->CastCustomSpell(triggerTarget, triggerSpellId, &m_amount, NULL, NULL, true, NULL, this); + return; + } + // Negative Energy Periodic + case 46284: + caster->CastCustomSpell(triggerSpellId, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this); + return; + // Poison (Grobbulus) + case 28158: + case 54362: + target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000), NULL, true, NULL, this); + return; + // Mind Sear (target 76/16) if let target cast, will damage caster + case 48045: + case 53023: + // Curse of the Plaguebringer (22/15) + case 29213: + case 54835: + caster->CastSpell(target, triggerSpellId, true, NULL, this); + return; + // Ground Slam + case 33525: + target->CastSpell(triggerTarget, triggerSpellId, true); + return; + } + } + + if(triggeredSpellInfo) + { + if(!caster->GetSpellMaxRangeForTarget(target,sSpellRangeStore.LookupEntry(triggeredSpellInfo->rangeIndex))) + triggerTarget = target; //for druid dispel poison + target->CastSpell(triggerTarget, triggeredSpellInfo, true, 0, this, GetCasterGUID()); + } + else if(target->GetTypeId()!=TYPEID_UNIT || !Script->EffectDummyCreature(caster, GetId(), GetEffIndex(), (Creature*)target)) + sLog.outError("AuraEffect::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex()); +} + +void AuraEffect::TriggerSpellWithValue(Unit * target, Unit * caster) const +{ + Unit* triggerTarget = GetTriggerTarget(target); + if (!triggerTarget) + triggerTarget = target; + + if(!caster || !target) + return; + + // generic casting code with custom spells and target/caster customs + uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; + int32 basepoints0 = GetAmount(); + + caster->CastCustomSpell(triggerTarget, trigger_spell_id, &basepoints0, 0, 0, true, 0, this); +} + +bool AuraEffect::IsAffectedOnSpell(SpellEntry const *spell) const +{ + if (!spell) + return false; + // Check family name + if (spell->SpellFamilyName != m_spellProto->SpellFamilyName) + return false; + + // Check EffectClassMask + if (m_spellProto->EffectSpellClassMask[m_effIndex] & spell->SpellFamilyFlags) + return true; + return false; +} + +void AuraEffect::CleanupTriggeredSpells(Unit * target) +{ + uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; + if(!tSpellId) + return; + + SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId); + if(!tProto) + return; + + if(GetSpellDuration(tProto) != -1) + return; + + // needed for spell 43680, maybe others + // TODO: is there a spell flag, which can solve this in a more sophisticated way? + if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && + GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()]) + return; + + target->RemoveAurasDueToSpell(tSpellId, GetCasterGUID()); +} + +void AuraEffect::HandleShapeshiftBoosts(Unit * target, bool apply) const +{ + uint32 spellId = 0; + uint32 spellId2 = 0; + uint32 spellId3 = 0; + uint32 HotWSpellId = 0; + + switch(GetMiscValue()) + { + case FORM_CAT: + spellId = 3025; + HotWSpellId = 24900; + break; + case FORM_TREE: + spellId = 34123; + break; + case FORM_TRAVEL: + spellId = 5419; + break; + case FORM_AQUA: + spellId = 5421; + break; + case FORM_BEAR: + spellId = 1178; + spellId2 = 21178; + HotWSpellId = 24899; + break; + case FORM_DIREBEAR: + spellId = 9635; + spellId2 = 21178; + HotWSpellId = 24899; + break; + case FORM_BATTLESTANCE: + spellId = 21156; + break; + case FORM_DEFENSIVESTANCE: + spellId = 7376; + break; + case FORM_BERSERKERSTANCE: + spellId = 7381; + break; + case FORM_MOONKIN: + spellId = 24905; + break; + case FORM_FLIGHT: + spellId = 33948; + spellId2 = 34764; + break; + case FORM_FLIGHT_EPIC: + spellId = 40122; + spellId2 = 40121; + break; + case FORM_METAMORPHOSIS: + spellId = 54817; + spellId2 = 54879; + break; + case FORM_SPIRITOFREDEMPTION: + spellId = 27792; + spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation. + break; + case FORM_SHADOW: + spellId = 49868; + break; + case FORM_GHOSTWOLF: + spellId = 67116; + break; + case FORM_GHOUL: + case FORM_AMBIENT: + case FORM_STEALTH: + case FORM_CREATURECAT: + case FORM_CREATUREBEAR: + break; + } + + if(apply) + { + // Remove cooldown of spells triggered on stance change - they may share cooldown with stance spell + if (spellId) + { + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player *)target)->RemoveSpellCooldown(spellId); + target->CastSpell(target, spellId, true, NULL, this ); + } + + if (spellId2) + { + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player *)target)->RemoveSpellCooldown(spellId2); + target->CastSpell(target, spellId2, true, NULL, this); + } + + if(target->GetTypeId() == TYPEID_PLAYER) + { + const PlayerSpellMap& sp_list = ((Player *)target)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED) continue; + if(itr->first==spellId || itr->first==spellId2) continue; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue; + if (spellInfo->Stances & (1<<(GetMiscValue()-1))) + target->CastSpell(target, itr->first, true, NULL, this); + } + // Leader of the Pack + if (((Player*)target)->HasSpell(17007)) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932); + if (spellInfo && spellInfo->Stances & (1<<(GetMiscValue()-1))) + target->CastSpell(target, 24932, true, NULL, this); + } + // Improved Barkskin - apply/remove armor bonus due to shapeshift + if (((Player*)target)->HasSpell(63410) || ((Player*)target)->HasSpell(63411)) + { + target->RemoveAurasDueToSpell(66530); + if (GetMiscValue() == FORM_TRAVEL || GetMiscValue() == FORM_NONE) // "while in Travel Form or while not shapeshifted" + target->CastSpell(target, 66530, true); + } + // Heart of the Wild + if (HotWSpellId) + { + Unit::AuraEffectList const& mModTotalStatPct = target->GetAuraEffectsByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); + for (Unit::AuraEffectList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) + { + if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetMiscValue() == 3) + { + int32 HotWMod = (*i)->GetAmount(); + if(GetMiscValue() == FORM_CAT) + HotWMod /= 2; + + target->CastCustomSpell(target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this); + break; + } + } + } + switch(GetMiscValue()) + { + case FORM_CAT: + // Nurturing Instinct + if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT, SPELLFAMILY_DRUID, 2254,0)) + { + uint32 spellId = 0; + switch (aurEff->GetId()) + { + case 33872: + spellId = 47179; + break; + case 33873: + spellId = 47180; + break; + } + target->CastSpell(target, spellId, true, NULL, this); + } + // Master Shapeshifter - Cat + if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) + { + int32 bp = aurEff->GetAmount(); + target->CastCustomSpell(target, 48420, &bp, NULL, NULL, true); + } + break; + case FORM_DIREBEAR: + case FORM_BEAR: + // Master Shapeshifter - Bear + if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) + { + int32 bp = aurEff->GetAmount(); + target->CastCustomSpell(target, 48418, &bp, NULL, NULL, true); + } + // Survival of the Fittest + if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE,SPELLFAMILY_DRUID, 961, 0)) + { + int32 bp = target->CalculateSpellDamage(aurEff->GetSpellProto(),2,aurEff->GetSpellProto()->EffectBasePoints[2],target); + target->CastCustomSpell(target, 62069,&bp, NULL, NULL, true, 0, this); + } + break; + case FORM_MOONKIN: + // Master Shapeshifter - Moonkin + if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) + { + int32 bp = aurEff->GetAmount(); + target->CastCustomSpell(target, 48421, &bp, NULL, NULL, true); + } + break; + // Master Shapeshifter - Tree of Life + case FORM_TREE: + if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0)) + { + int32 bp = aurEff->GetAmount(); + target->CastCustomSpell(target, 48422, &bp, NULL, NULL, true); + } + break; + } + } + } + else + { + if (spellId) + target->RemoveAurasDueToSpell(spellId); + if (spellId2) + target->RemoveAurasDueToSpell(spellId2); + + // Improved Barkskin - apply/remove armor bonus due to shapeshift + if (((Player*)target)->HasSpell(63410) || ((Player*)target)->HasSpell(63411)) + { + target->RemoveAurasDueToSpell(66530); + target->CastSpell(target,66530,true); + } + + Unit::AuraApplicationMap& tAuras = target->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();) + { + if (itr->second->GetBase()->IsRemovedOnShapeLost(target)) + target->RemoveAura(itr); + else + ++itr; + } + } +} + +/*********************************************************/ +/*** AURA EFFECT HANDLERS ***/ +/*********************************************************/ + +/**************************************/ +/*** VISIBILITY & PHASES ***/ +/**************************************/ + +void AuraEffect::HandleInvisibilityDetect(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + { + target->m_detectInvisibilityMask |= (1 << GetMiscValue()); + } + else + { + // recalculate value at modifier remove (current aura already removed) + target->m_detectInvisibilityMask = 0; + Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); + for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + target->m_detectInvisibilityMask |= (1 << GetMiscValue()); + } + if(target->GetTypeId() == TYPEID_PLAYER) + target->SetToNotify(); +} + +void AuraEffect::HandleInvisibility(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + { + target->m_invisibilityMask |= (1 << GetMiscValue()); + + if (mode & AURA_EFFECT_HANDLE_REAL) + { + // drop flag at invisibiliy in bg + target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + } + + // apply glow vision + if(target->GetTypeId() == TYPEID_PLAYER) + target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); + + target->SetToNotify(); + } + else + { + // recalculate value at modifier remove (current aura already removed) + target->m_invisibilityMask = 0; + Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY); + for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + target->m_invisibilityMask |= (1 << GetMiscValue()); + + // if not have different invisibility auras. + // remove glow vision + if(!target->m_invisibilityMask && target->GetTypeId() == TYPEID_PLAYER) + target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); + + target->SetToNotify(); + } +} + +void AuraEffect::HandleModStealth(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + { + if (mode & AURA_EFFECT_HANDLE_REAL) + { + // drop flag at stealth in bg + target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + } + + target->SetStandFlags(UNIT_STAND_FLAGS_CREEP); + if(target->GetTypeId() == TYPEID_PLAYER) + target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); + + // apply only if not in GM invisibility (and overwrite invisibility state) + if(target->GetVisibility() != VISIBILITY_OFF) + target->SetVisibility(VISIBILITY_GROUP_STEALTH); + } + else if(!target->HasAuraType(SPELL_AURA_MOD_STEALTH)) // if last SPELL_AURA_MOD_STEALTH + { + target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP); + if(target->GetTypeId() == TYPEID_PLAYER) + target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); + + if(target->GetVisibility() != VISIBILITY_OFF) + target->SetVisibility(VISIBILITY_ON); + } +} + +void AuraEffect::HandleSpiritOfRedemption(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + // prepare spirit state + if(apply) + { + if(target->GetTypeId() == TYPEID_PLAYER) + { + // disable breath/etc timers + ((Player*)target)->StopMirrorTimers(); + + // set stand state (expected in this form) + if(!target->IsStandState()) + target->SetStandState(UNIT_STAND_STATE_STAND); + } + + target->SetHealth(1); + } + // die at aura end + else + target->setDeathState(JUST_DIED); +} + +void AuraEffect::HandleAuraGhost(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); + else + { + if (target->HasAuraType(SPELL_AURA_GHOST)) + return; + target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); + } +} + +void AuraEffect::HandlePhase(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + // no-phase is also phase state so same code for apply and remove + + // phase auras normally not expected at BG but anyway better check + if(target->GetTypeId() == TYPEID_PLAYER) + { + // drop flag at invisible in bg + if(((Player*)target)->InBattleGround()) + if(BattleGround *bg = ((Player*)target)->GetBattleGround()) + bg->EventPlayerDroppedFlag((Player*)target); + + // GM-mode have mask 0xFFFFFFFF + if(!((Player*)target)->isGameMaster()) + target->SetPhaseMask((apply) ? GetMiscValue() : PHASEMASK_NORMAL,false); + + ((Player*)target)->GetSession()->SendSetPhaseShift((apply) ? GetMiscValue() : PHASEMASK_NORMAL); + } + else + target->SetPhaseMask((apply) ? GetMiscValue() : PHASEMASK_NORMAL,false); + + // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases) + if(target->GetVisibility()!=VISIBILITY_OFF) + target->SetVisibility(target->GetVisibility()); +} + +/**********************/ +/*** UNIT MODEL ***/ +/**********************/ + +void AuraEffect::HandleAuraModShapeshift(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + uint32 modelid = 0; + Powers PowerType = POWER_MANA; + ShapeshiftForm form = ShapeshiftForm(GetMiscValue()); + switch(form) + { + case FORM_CAT: + case FORM_GHOUL: + PowerType = POWER_ENERGY; + break; + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_BATTLESTANCE: + case FORM_BERSERKERSTANCE: + case FORM_DEFENSIVESTANCE: + PowerType = POWER_RAGE; + break; + case FORM_TRAVEL: + case FORM_AQUA: + case FORM_CREATUREBEAR: + case FORM_GHOSTWOLF: + case FORM_FLIGHT: + case FORM_MOONKIN: + case FORM_FLIGHT_EPIC: + case FORM_METAMORPHOSIS: + case FORM_MASTER_ANGLER: + case FORM_AMBIENT: + case FORM_SHADOW: + case FORM_STEALTH: + case FORM_UNDEAD: + case FORM_SHADOW_DANCE: + case FORM_TREE: + case FORM_SPIRITOFREDEMPTION: + break; + default: + sLog.outError("Auras: Unknown Shapeshift Type: %u", GetMiscValue()); + } + + modelid = target->GetModelForForm(form); + + // remove polymorph before changing display id to keep new display id + switch ( form ) + { + case FORM_CAT: + case FORM_TREE: + case FORM_TRAVEL: + case FORM_AQUA: + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_FLIGHT_EPIC: + case FORM_FLIGHT: + case FORM_MOONKIN: + { + // remove movement affects + target->RemoveMovementImpairingAuras(); + + // and polymorphic affects + if(target->IsPolymorphed()) + target->RemoveAurasDueToSpell(target->getTransForm()); + break; + } + default: + break; + } + + if (apply) + { + // remove other shapeshift before applying a new one + if(target->m_ShapeShiftFormSpellId) + target->RemoveAurasDueToSpell(target->m_ShapeShiftFormSpellId); + + target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form); + + if (modelid > 0) + target->SetDisplayId(modelid); + + if (PowerType != POWER_MANA) + { + uint32 oldPower = target->GetPower(PowerType); + // reset power to default values only at power change + if(target->getPowerType() != PowerType) + target->setPowerType(PowerType); + + switch (form) + { + case FORM_CAT: + case FORM_BEAR: + case FORM_DIREBEAR: + { + // get furor proc chance + uint32 FurorChance = 0; + if (AuraEffect const *dummy = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, 238, 0)) + FurorChance = std::max(dummy->GetAmount(), 0); + + switch (GetMiscValue()) + { + case FORM_CAT: + { + int32 basePoints = int32(std::min(oldPower, FurorChance)); + target->CastCustomSpell(target, 17099, &basePoints, NULL, NULL, true, NULL, this); + } + break; + case FORM_BEAR: + case FORM_DIREBEAR: + if (urand(0,99) < FurorChance) + target->CastSpell(target, 17057, true); + default: + { + uint32 newEnergy = std::min(target->GetPower(POWER_ENERGY), FurorChance); + target->SetPower(POWER_ENERGY, newEnergy); + } + break; + } + break; + } + default: + break; + } + } + + target->m_ShapeShiftFormSpellId = GetId(); + target->m_form = form; + } + else + { + if(modelid > 0) + target->SetDisplayId(target->GetNativeDisplayId()); + target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE); + if(target->getClass() == CLASS_DRUID) + target->setPowerType(POWER_MANA); + target->m_ShapeShiftFormSpellId = 0; + target->m_form = FORM_NONE; + + switch(form) + { + // Nordrassil Harness - bonus + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_CAT: + if(AuraEffect* dummy = target->GetAuraEffect(37315, 0) ) + target->CastSpell(target,37316,true,NULL,dummy); + break; + // Nordrassil Regalia - bonus + case FORM_MOONKIN: + if(AuraEffect* dummy = target->GetAuraEffect(37324, 0) ) + target->CastSpell(target,37325,true,NULL,dummy); + break; + case FORM_BATTLESTANCE: + case FORM_DEFENSIVESTANCE: + case FORM_BERSERKERSTANCE: + { + uint32 Rage_val = 0; + // Defensive Tactics + if (form == FORM_DEFENSIVESTANCE) + { + if (AuraEffect const * aurEff = target->IsScriptOverriden(m_spellProto,831)) + Rage_val += aurEff->GetAmount() * 10; + } + // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch) + if(target->GetTypeId() == TYPEID_PLAYER) + { + PlayerSpellMap const& sp_list = ((Player *)target)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED) continue; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139) + Rage_val += target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],target) * 10; + } + } + if (target->GetPower(POWER_RAGE) > Rage_val) + target->SetPower(POWER_RAGE,Rage_val); + break; + } + default: + break; + } + } + + // adding/removing linked auras + // add/remove the shapeshift aura's boosts + HandleShapeshiftBoosts(target, apply); + + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->InitDataForForm(); + + if(target->getClass() == CLASS_DRUID) + { + // Dash + if(AuraEffect * aurEff =target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8)) + aurEff->RecalculateAmount(); + } + if (target->GetTypeId() == TYPEID_PLAYER) + { + SpellShapeshiftEntry const *shapeInfo = sSpellShapeshiftStore.LookupEntry(form); + // Learn spells for shapeshift form - no need to send action bars or add spells to spellbook + for (uint8 i = 0; i<MAX_SHAPESHIFT_SPELLS; ++i) + { + if (!shapeInfo->stanceSpell[i]) + continue; + if (apply) + ((Player*)target)->AddTemporarySpell(shapeInfo->stanceSpell[i]); + else + ((Player*)target)->RemoveTemporarySpell(shapeInfo->stanceSpell[i]); + } + } +} + +void AuraEffect::HandleAuraTransform(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if (apply) + { + // special case (spell specific functionality) + if(GetMiscValue()==0) + { + // player applied only + if (target->GetTypeId() != TYPEID_PLAYER) + return; + + switch (GetId()) + { + // Orb of Deception + case 16739: + { + uint32 orb_model = target->GetNativeDisplayId(); + switch(orb_model) + { + // Troll Female + case 1479: target->SetDisplayId(10134); break; + // Troll Male + case 1478: target->SetDisplayId(10135); break; + // Tauren Male + case 59: target->SetDisplayId(10136); break; + // Human Male + case 49: target->SetDisplayId(10137); break; + // Human Female + case 50: target->SetDisplayId(10138); break; + // Orc Male + case 51: target->SetDisplayId(10139); break; + // Orc Female + case 52: target->SetDisplayId(10140); break; + // Dwarf Male + case 53: target->SetDisplayId(10141); break; + // Dwarf Female + case 54: target->SetDisplayId(10142); break; + // NightElf Male + case 55: target->SetDisplayId(10143); break; + // NightElf Female + case 56: target->SetDisplayId(10144); break; + // Undead Female + case 58: target->SetDisplayId(10145); break; + // Undead Male + case 57: target->SetDisplayId(10146); break; + // Tauren Female + case 60: target->SetDisplayId(10147); break; + // Gnome Male + case 1563: target->SetDisplayId(10148); break; + // Gnome Female + case 1564: target->SetDisplayId(10149); break; + // BloodElf Female + case 15475: target->SetDisplayId(17830); break; + // BloodElf Male + case 15476: target->SetDisplayId(17829); break; + // Dranei Female + case 16126: target->SetDisplayId(17828); break; + // Dranei Male + case 16125: target->SetDisplayId(17827); break; + default: break; + } + break; + } + // Murloc costume + case 42365: target->SetDisplayId(21723); break; + default: break; + } + } + else + { + CreatureInfo const * ci = objmgr.GetCreatureTemplate(GetMiscValue()); + if(!ci) + { + target->SetDisplayId(16358); // pig pink ^_^ + sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", GetMiscValue(), GetId()); + } + else + { + uint32 model_id; + + if (uint32 modelid = ci->GetRandomValidModelId()) + model_id = modelid; // Will use the default model here + + // Polymorph (sheep) + if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellProto()->SpellIconID == 82 && GetSpellProto()->SpellVisual[0] == 12978) + if (Unit * caster = GetCaster()) + if (caster->HasAura(52648)) // Glyph of the Penguin + model_id = 26452; + + target->SetDisplayId(model_id); + + // Dragonmaw Illusion (set mount model also) + if(GetId()==42016 && target->GetMountID() && !target->GetAuraEffectsByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED).empty()) + target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); + } + } + + // update active transform spell only not set or not overwriting negative by positive case + if (!target->getTransForm() || !IsPositiveSpell(GetId()) || IsPositiveSpell(target->getTransForm())) + target->setTransForm(GetId()); + + // polymorph case + if ((mode & AURA_EFFECT_HANDLE_REAL) && target->GetTypeId() == TYPEID_PLAYER && target->IsPolymorphed()) + { + // for players, start regeneration after 1s (in polymorph fast regeneration case) + // only if caster is Player (after patch 2.4.2) + if (IS_PLAYER_GUID(GetCasterGUID()) ) + ((Player*)target)->setRegenTimerCount(1*IN_MILISECONDS); + + //dismount polymorphed target (after patch 2.4.2) + if (target->IsMounted()) + target->RemoveAurasByType(SPELL_AURA_MOUNTED); + } + } + else + { + // HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true) will reapply it if need + target->setTransForm(0); + target->SetDisplayId(target->GetNativeDisplayId()); + + // re-aplly some from still active with preference negative cases + Unit::AuraEffectList const& otherTransforms = target->GetAuraEffectsByType(SPELL_AURA_TRANSFORM); + if (!otherTransforms.empty()) + { + // look for other transform auras + AuraEffect* handledAura = *otherTransforms.begin(); + for (Unit::AuraEffectList::const_iterator i = otherTransforms.begin(); i != otherTransforms.end(); ++i) + { + // negative auras are preferred + if (!IsPositiveSpell((*i)->GetSpellProto()->Id)) + { + handledAura = *i; + break; + } + } + handledAura->HandleEffect(target, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); + } + + // Dragonmaw Illusion (restore mount model) + if (GetId() == 42016 && target->GetMountID() == 16314) + { + if (!target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).empty()) + { + uint32 cr_id = target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetMiscValue(); + if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id)) + { + uint32 team = 0; + if (target->GetTypeId() == TYPEID_PLAYER) + team = ((Player*)target)->GetTeam(); + + uint32 display_id = objmgr.ChooseDisplayId(team,ci); + CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); + if (minfo) + display_id = minfo->modelid; + + target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id); + } + } + } + } +} + +void AuraEffect::HandleAuraModScale(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,GetAmount(),apply); +} + +void AuraEffect::HandleAuraCloneCaster(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if (apply) + { + Unit * caster = GetCaster(); + if (!caster) + return; + // Set display id (probably for portrait?) + target->SetDisplayId(caster->GetDisplayId()); + target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE); + } + else + { + target->SetDisplayId(target->GetNativeDisplayId()); + target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE); + } +} + +/************************/ +/*** FIGHT ***/ +/************************/ + +void AuraEffect::HandleFeignDeath(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + if( apply ) + { + /* + WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); + data<<target->GetGUID(); + data<<uint8(0); + target->SendMessageToSet(&data,true); + */ + + UnitList targets; + Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(target, target, target->GetMap()->GetVisibilityDistance()); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, targets, u_check); + target->VisitNearbyObject(target->GetMap()->GetVisibilityDistance(), searcher); + for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter) + { + if(!(*iter)->hasUnitState(UNIT_STAT_CASTING)) + continue; + + for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) + { + if((*iter)->GetCurrentSpell(i) + && (*iter)->GetCurrentSpell(i)->m_targets.getUnitTargetGUID() == target->GetGUID()) + { + (*iter)->InterruptSpell(CurrentSpellTypes(i), false); + } + } + } + // blizz like 2.0.x + target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); + // blizz like 2.0.x + target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + // blizz like 2.0.x + target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + + target->addUnitState(UNIT_STAT_DIED); + target->CombatStop(); + target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + + // prevent interrupt message + if(GetCasterGUID()==target->GetGUID() && target->GetCurrentSpell(CURRENT_GENERIC_SPELL)) + target->FinishSpell(CURRENT_GENERIC_SPELL, false); + target->InterruptNonMeleeSpells(true); + target->getHostilRefManager().deleteReferences(); + } + else + { + /* + WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); + data<<target->GetGUID(); + data<<uint8(1); + target->SendMessageToSet(&data,true); + */ + // blizz like 2.0.x + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); + // blizz like 2.0.x + target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + // blizz like 2.0.x + target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + + target->clearUnitState(UNIT_STAT_DIED); + } +} + +void AuraEffect::HandleModUnattackable(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + { + if (mode & AURA_EFFECT_HANDLE_REAL) + { + target->CombatStop(); + target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + } + } + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + else if (target->HasAuraType(SPELL_AURA_MOD_UNATTACKABLE)) + return; + + target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, apply); +} + +void AuraEffect::HandleAuraModDisarm(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + AuraType type = GetAuraType(); + + //Prevent handling aura twice + if((apply) ? target->GetAuraEffectsByType(type).size() > 1 : target->HasAuraType(type)) + return; + + uint32 field, flag, slot; + WeaponAttackType attType; + switch (type) + { + case SPELL_AURA_MOD_DISARM: + field=UNIT_FIELD_FLAGS; + flag=UNIT_FLAG_DISARMED; + slot=EQUIPMENT_SLOT_MAINHAND; + attType=BASE_ATTACK; + break; + case SPELL_AURA_MOD_DISARM_OFFHAND: + field=UNIT_FIELD_FLAGS_2; + flag=UNIT_FLAG2_DISARM_OFFHAND; + slot=EQUIPMENT_SLOT_OFFHAND; + attType=OFF_ATTACK; + break; + case SPELL_AURA_MOD_DISARM_RANGED: + field=UNIT_FIELD_FLAGS_2; + flag=UNIT_FLAG2_DISARM_RANGED; + slot=EQUIPMENT_SLOT_RANGED; + attType=RANGED_ATTACK; + break; + default: + return; + } + + if(!(apply)) + target->RemoveFlag(field, flag); + + if (target->GetTypeId() == TYPEID_PLAYER) + { + // This is between the two because there is a check in _ApplyItemMods + // we must make sure that flag is always removed when call that function + // refer to DurabilityPointsLoss + if(Item *pItem = ((Player*)target)->GetItemByPos( INVENTORY_SLOT_BAG_0, slot )) + ((Player*)target)->_ApplyItemMods(pItem, slot, !apply); + } + + if(apply) + target->SetFlag(field, flag); + + if (target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->GetCurrentEquipmentId()) + target->UpdateDamagePhysical(attType); +} + +void AuraEffect::HandleAuraModSilence(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + { + target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); + // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE + for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) + if (Spell* spell = target->GetCurrentSpell(CurrentSpellTypes(i))) + if(spell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + // Stop spells on prepare or casting state + target->InterruptSpell(CurrentSpellTypes(i), false); + } + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(SPELL_AURA_MOD_SILENCE) || target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE)) + return; + + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); + } +} + +void AuraEffect::HandleAuraModPacify(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(SPELL_AURA_MOD_PACIFY) || target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE)) + return; + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); + } +} + +void AuraEffect::HandleAuraModPacifyAndSilence(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + // Vengeance of the Blue Flight (TODO: REMOVE THIS!) + if(m_spellProto->Id == 45839) + { + if(apply) + target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + else + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + if(!(apply)) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE)) + return; + } + HandleAuraModPacify(aurApp, mode, apply); + HandleAuraModSilence(aurApp, mode, apply); +} + +void AuraEffect::HandleAuraAllowOnlyAbility(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() == TYPEID_PLAYER) + { + if (apply) + target->SetFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(SPELL_AURA_ALLOW_ONLY_ABILITY)) + return; + target->RemoveFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); + } + } +} + +/****************************/ +/*** TRACKING ***/ +/****************************/ + +void AuraEffect::HandleAuraTrackCreatures(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + target->SetUInt32Value(PLAYER_TRACK_CREATURES, (apply) ? ((uint32)1)<<(GetMiscValue()-1) : 0 ); +} + +void AuraEffect::HandleAuraTrackResources(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + target->SetUInt32Value(PLAYER_TRACK_RESOURCES, (apply) ? ((uint32)1)<<(GetMiscValue()-1): 0 ); +} + +void AuraEffect::HandleAuraTrackStealthed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + if(!(apply)) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + } + target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply); +} + +void AuraEffect::HandleAuraModStalked(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND + if(apply) + target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + + target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); + } +} + +void AuraEffect::HandleAuraUntrackable(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + target->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE); + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + target->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE); + } +} + +/****************************/ +/*** SKILLS & TALENTS ***/ +/****************************/ + +void AuraEffect::HandleAuraModPetTalentsPoints(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + // Recalculate pet talent points + if (Pet *pet = ((Player*)target)->GetPet()) + pet->InitTalentForLevel(); +} + +void AuraEffect::HandleAuraModSkill(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + uint32 prot = GetSpellProto()->EffectMiscValue[m_effIndex]; + int32 points = GetAmount(); + + ((Player*)target)->ModifySkillBonus(prot,((apply) ? points: -points),GetAuraType() == SPELL_AURA_MOD_SKILL_TALENT); + if(prot == SKILL_DEFENSE) + ((Player*)target)->UpdateDefenseBonusesMod(); +} + +/****************************/ +/*** MOVEMENT ***/ +/****************************/ + +void AuraEffect::HandleAuraMounted(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + { + CreatureInfo const* ci = objmgr.GetCreatureTemplate(GetMiscValue()); + if(!ci) + { + sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)",GetMiscValue()); + return; + } + + uint32 team = 0; + if (target->GetTypeId() == TYPEID_PLAYER) + team = ((Player*)target)->GetTeam(); + + uint32 display_id = objmgr.ChooseDisplayId(team,ci); + CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); + if (minfo) + display_id = minfo->modelid; + + //some spell has one aura of mount and one of vehicle + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if(GetSpellProto()->Effect[i] == SPELL_EFFECT_SUMMON + && GetSpellProto()->EffectMiscValue[i] == GetMiscValue()) + display_id = 0; + target->Mount(display_id); + } + else + { + target->Unmount(); + //some mounts like Headless Horseman's Mount or broom stick are skill based spell + // need to remove ALL arura related to mounts, this will stop client crash with broom stick + // and never endless flying after using Headless Horseman's Mount + if(mode & AURA_EFFECT_HANDLE_REAL) + target->RemoveAurasByType(SPELL_AURA_MOUNTED); + } +} + +void AuraEffect::HandleAuraAllowFlight(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(!apply) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType()) || target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED)) + return; + } + + if(target->GetTypeId() == TYPEID_UNIT) + target->SetFlying(apply); + + if(Player *plr = target->m_movedPlayer) + { + // allow fly + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); + else + data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); + data.append(target->GetPackGUID()); + data << uint32(0); // unk + plr->SendDirectMessage(&data); + } +} + +void AuraEffect::HandleAuraWaterWalk(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(!(apply)) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + } + + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_WATER_WALK, 8+4); + else + data.Initialize(SMSG_MOVE_LAND_WALK, 8+4); + data.append(target->GetPackGUID()); + data << uint32(0); + target->SendMessageToSet(&data,true); +} + +void AuraEffect::HandleAuraFeatherFall(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(!(apply)) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + } + + WorldPacket data; + if (apply) + data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4); + else + data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4); + data.append(target->GetPackGUID()); + data << uint32(0); + target->SendMessageToSet(&data, true); + + // start fall from current height + if(!apply && target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->SetFallInformation(0, target->GetPositionZ()); +} + +void AuraEffect::HandleAuraHover(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(!(apply)) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + } + + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_SET_HOVER, 8+4); + else + data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4); + data.append(target->GetPackGUID()); + data << uint32(0); + target->SendMessageToSet(&data,true); +} + +void AuraEffect::HandleWaterBreathing(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + // update timers in client + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->UpdateMirrorTimers(); +} + +void AuraEffect::HandleForceMoveForward(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); + } +} + +/****************************/ +/*** THREAT ***/ +/****************************/ + +void AuraEffect::HandleModThreat(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if (!target->isAlive()) + return; + + Unit * caster = GetCaster(); + if (!caster || !caster->isAlive()) + return; + + if (target->GetTypeId() == TYPEID_PLAYER) + for (int8 x=0; x < MAX_SPELL_SCHOOL; x++) + if (GetMiscValue() & int32(1<<x)) + ApplyPercentModFloatVar(target->m_threatModifier[x], GetAmount(), apply); +} + +void AuraEffect::HandleAuraModTotalThreat(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if (!target->isAlive() || target->GetTypeId() != TYPEID_PLAYER) + return; + + Unit * caster = GetCaster(); + if (!caster || !caster->isAlive()) + return; + + float threatMod = (apply) ? float(GetAmount()) : float(-GetAmount()); + + target->getHostilRefManager().threatAssist(caster, threatMod); +} + +void AuraEffect::HandleModTaunt(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if (!target->isAlive() || !target->CanHaveThreatList()) + return; + + Unit * caster = GetCaster(); + if (!caster || !caster->isAlive()) + return; + + if (apply) + target->TauntApply(caster); + else + { + // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat + target->TauntFadeOut(caster); + } +} + +/*****************************/ +/*** CONTROL ***/ +/*****************************/ + +void AuraEffect::HandleModConfuse(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + target->SetControlled(apply, UNIT_STAT_CONFUSED); +} + +void AuraEffect::HandleModFear(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + target->SetControlled(apply, UNIT_STAT_FLEEING); +} + +void AuraEffect::HandleAuraModStun(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + target->SetControlled(apply, UNIT_STAT_STUNNED); +} + +void AuraEffect::HandleAuraModRoot(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + target->SetControlled(apply, UNIT_STAT_ROOT); +} + +void AuraEffect::HandlePreventFleeing(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + Unit::AuraEffectList const& fearAuras = target->GetAuraEffectsByType(SPELL_AURA_MOD_FEAR); + if( !fearAuras.empty() ) + target->SetControlled(!(apply), UNIT_STAT_FLEEING); +} + +/***************************/ +/*** CHARM ***/ +/***************************/ + +void AuraEffect::HandleModPossess(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + Unit * caster = GetCaster(); + if(caster && caster->GetTypeId() == TYPEID_UNIT) + { + HandleModCharm(aurApp, mode, apply); + return; + } + + if(apply) + target->SetCharmedBy(caster, CHARM_TYPE_POSSESS); + else + target->RemoveCharmedBy(caster); +} + +// only one spell has this aura +void AuraEffect::HandleModPossessPet(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + Unit * caster = GetCaster(); + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + + //seems it may happen that when removing it is no longer owner's pet + //if(((Player*)caster)->GetPet() != target) + // return; + + if(apply) + { + if(((Player*)caster)->GetPet() != target) + return; + + target->SetCharmedBy(caster, CHARM_TYPE_POSSESS); + } + else + { + target->RemoveCharmedBy(caster); + + // Reinitialize the pet bar and make the pet come back to the owner + ((Player*)caster)->PetSpellInitialize(); + if(!target->getVictim()) + { + target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, target->GetFollowAngle()); + //if(target->GetCharmInfo()) + // target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); + } + } +} + +void AuraEffect::HandleModCharm(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + Unit * caster = GetCaster(); + + if(apply) + target->SetCharmedBy(caster, CHARM_TYPE_CHARM); + else + target->RemoveCharmedBy(caster); +} + +void AuraEffect::HandleCharmConvert(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + Unit * caster = GetCaster(); + + if(apply) + target->SetCharmedBy(caster, CHARM_TYPE_CONVERT); + else + target->RemoveCharmedBy(caster); +} + +/** + * Such auras are applied from a caster(=player) to a vehicle. + * This has been verified using spell #49256 + */ +void AuraEffect::HandleAuraControlVehicle(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(!target->IsVehicle()) + return; + + Unit * caster = GetCaster(); + + if(!caster || caster == target) + return; + + if (apply) + { + //if(caster->GetTypeId() == TYPEID_PLAYER) + // if(Pet *pet = ((Player*)caster)->GetPet()) + // pet->Remove(PET_SAVE_AS_CURRENT); + caster->EnterVehicle(target->GetVehicleKit(), m_amount - 1); + } + else + { + if(GetId() == 53111) // Devour Humanoid + { + target->Kill(caster); + if(caster->GetTypeId() == TYPEID_UNIT) + ((Creature*)caster)->RemoveCorpse(); + } + + // some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them + caster->RemoveAurasDueToSpell(GetId()); + caster->ExitVehicle(); + } +} + +/*********************************************************/ +/*** MODIFY SPEED ***/ +/*********************************************************/ +void AuraEffect::HandleAuraModIncreaseSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + target->UpdateSpeed(MOVE_RUN, true); +} + +void AuraEffect::HandleAuraModIncreaseMountedSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + target->UpdateSpeed(MOVE_RUN, true); +} + +void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + // Enable Fly mode for flying mounts + if (GetAuraType() == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if (mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK && (apply || (!target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !target->HasAuraType(SPELL_AURA_FLY)))) + { + WorldPacket data; + if(apply) + data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); + else + data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); + data.append(target->GetPackGUID()); + data << uint32(0); // unknown + target->SendMessageToSet(&data, true); + } + + if (mode & AURA_EFFECT_HANDLE_REAL) + { + //Players on flying mounts must be immune to polymorph + if (target->GetTypeId() == TYPEID_PLAYER) + target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply); + + // Dragonmaw Illusion (overwrite mount model, mounted aura already applied) + if( apply && target->HasAuraEffect(42016,0) && target->GetMountID()) + target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); + } + } + + if(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK) + target->UpdateSpeed(MOVE_FLIGHT, true); +} + +void AuraEffect::HandleAuraModIncreaseSwimSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + target->UpdateSpeed(MOVE_SWIM, true); +} + +void AuraEffect::HandleAuraModDecreaseSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + target->UpdateSpeed(MOVE_RUN, true); + target->UpdateSpeed(MOVE_SWIM, true); + target->UpdateSpeed(MOVE_FLIGHT, true); + target->UpdateSpeed(MOVE_RUN_BACK, true); + target->UpdateSpeed(MOVE_SWIM_BACK, true); + target->UpdateSpeed(MOVE_FLIGHT_BACK, true); +} + +void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + target->UpdateSpeed(MOVE_RUN, true); + target->UpdateSpeed(MOVE_SWIM, true); + target->UpdateSpeed(MOVE_FLIGHT, true); +} + +/*********************************************************/ +/*** IMMUNITY ***/ +/*********************************************************/ + +void AuraEffect::HandleModStateImmunityMask(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + std::list <AuraType> immunity_list; + if (GetMiscValue() & (1<<10)) + immunity_list.push_back(SPELL_AURA_MOD_STUN); + if (GetMiscValue() & (1<<7)) + immunity_list.push_back(SPELL_AURA_MOD_DISARM); + if (GetMiscValue() & (1<<1)) + immunity_list.push_back(SPELL_AURA_TRANSFORM); + + // These flag can be recognized wrong: + if (GetMiscValue() & (1<<6)) + immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); + if (GetMiscValue() & (1<<0)) + immunity_list.push_back(SPELL_AURA_MOD_ROOT); + if (GetMiscValue() & (1<<2)) + immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); + if (GetMiscValue() & (1<<9)) + immunity_list.push_back(SPELL_AURA_MOD_FEAR); + + // Patch 3.0.3 Bladestorm now breaks all snares and roots on the warrior when activated. + // however not all mechanic specified in immunity + if (apply && GetId()==46924) + { + target->RemoveAurasByType(SPELL_AURA_MOD_ROOT); + target->RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); + } + + if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + { + for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter) + { + target->RemoveAurasByType(*iter); + } + } + for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter) + { + target->ApplySpellImmune(GetId(),IMMUNITY_STATE,*iter, apply); + } +} + +void AuraEffect::HandleModMechanicImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + uint32 mechanic; + mechanic = 1 << GetMiscValue(); + + //immune movement impairment and loss of control + if(GetId()==42292 || GetId()==59752) + mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; + // Forbearance + // in DBC wrong mechanic immune since 3.0.x + else if (GetId() == 25771) + mechanic = 1 << MECHANIC_IMMUNE_SHIELD; + + if (!mechanic) + return; + + if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + { + Unit::AuraApplicationMap& Auras = target->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator iter = Auras.begin(); iter != Auras.end();) + { + SpellEntry const *spell = iter->second->GetBase()->GetSpellProto(); + if (spell->Id != GetId()) + { + //check for mechanic mask + if(GetAllSpellMechanicMask(spell) & mechanic) + { + target->RemoveAura(iter); + } + else + ++iter; + } + else + ++iter; + } + } + + target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,GetMiscValue(), apply); + + // Demonic Empowerment -- voidwalker -- missing movement impairing effects immunity + if (GetId() == 54508) + { + if (apply) + target->RemoveMovementImpairingAuras(); + + target->ApplySpellImmune(GetId(),IMMUNITY_STATE,SPELL_AURA_MOD_ROOT, apply); + target->ApplySpellImmune(GetId(),IMMUNITY_STATE,SPELL_AURA_MOD_DECREASE_SPEED, apply); + } +} + +void AuraEffect::HandleAuraModEffectImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + // when removing flag aura, handle flag drop + if( !(apply) && target->GetTypeId() == TYPEID_PLAYER + && (GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION) ) + { + if(target->GetTypeId() == TYPEID_PLAYER) + { + if(((Player*)target)->InBattleGround()) + { + if( BattleGround *bg = ((Player*)target)->GetBattleGround() ) + bg->EventPlayerDroppedFlag(((Player*)target)); + } + else + sOutdoorPvPMgr.HandleDropFlag((Player*)target,GetSpellProto()->Id); + } + } + + target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,GetMiscValue(),apply); +} + +void AuraEffect::HandleAuraModStateImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if((apply) && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + { + target->RemoveAurasByType(AuraType(GetMiscValue()), NULL , GetBase()); + } + + target->ApplySpellImmune(GetId(), IMMUNITY_STATE, GetMiscValue(), apply); +} + +void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if((apply) && GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL) + target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + + target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,GetMiscValue(),(apply)); + + // remove all flag auras (they are positive, but they must be removed when you are immune) + if( GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY + && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD ) + target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + + // TODO: optimalize this cycle - use RemoveAurasWithInterruptFlags call or something else + if((apply) + && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY + && IsPositiveSpell(GetId()) ) //Only positive immunity removes auras + { + uint32 school_mask = GetMiscValue(); + Unit::AuraApplicationMap& Auras = target->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator iter = Auras.begin(); iter != Auras.end();) + { + SpellEntry const *spell = iter->second->GetBase()->GetSpellProto(); + if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask + && IsDispelableBySpell(GetSpellProto(),spell->Id, true) + && !iter->second->IsPositive() //Don't remove positive spells + && spell->Id != GetId() ) //Don't remove self + { + target->RemoveAura(iter); + } + else + ++iter; + } + } + if(GetSpellProto()->Mechanic == MECHANIC_BANISH) + { + if( apply ) + target->addUnitState(UNIT_STAT_ISOLATED); + else + { + bool banishFound = false; + Unit::AuraEffectList const& banishAuras = target->GetAuraEffectsByType(GetAuraType()); + for (Unit::AuraEffectList::const_iterator i = banishAuras.begin(); i != banishAuras.end(); ++i) + if ((*i)->GetSpellProto()->Mechanic == MECHANIC_BANISH) + { + banishFound = true; + break; + } + if (!banishFound) + target->clearUnitState(UNIT_STAT_ISOLATED); + } + } +} + +void AuraEffect::HandleAuraModDmgImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,GetMiscValue(), apply); +} + +void AuraEffect::HandleAuraModDispelImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplySpellDispelImmunity(m_spellProto, DispelType(GetMiscValue()), (apply)); +} + +/*********************************************************/ +/*** MODIFY STATS ***/ +/*********************************************************/ + +/********************************/ +/*** RESISTANCE ***/ +/********************************/ + +void AuraEffect::HandleAuraModResistanceExclusive(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) + { + if(GetMiscValue() & int32(1<<x)) + { + target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(GetAmount()), apply); + if(target->GetTypeId() == TYPEID_PLAYER) + target->ApplyResistanceBuffModsMod(SpellSchools(x),aurApp->IsPositive(),GetAmount(), apply); + } + } +} + +void AuraEffect::HandleAuraModResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) + { + if(GetMiscValue() & int32(1<<x)) + { + target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply); + if(target->GetTypeId() == TYPEID_PLAYER || ((Creature*)target)->isPet()) + target->ApplyResistanceBuffModsMod(SpellSchools(x),GetAmount() > 0,GetAmount(), apply); + } + } +} + +void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + // only players have base stats + if(target->GetTypeId() != TYPEID_PLAYER) + { + //pets only have base armor + if(((Creature*)target)->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()), apply); + } + else + { + for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) + { + if(GetMiscValue() & int32(1<<x)) + target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()), apply); + } + } +} + +void AuraEffect::HandleModResistancePercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) + { + if(GetMiscValue() & int32(1<<i)) + { + target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply); + if(target->GetTypeId() == TYPEID_PLAYER || ((Creature*)target)->isPet()) + { + target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,GetAmount(), apply); + target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,GetAmount(), apply); + } + } + } +} + +void AuraEffect::HandleModBaseResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + // only players have base stats + if(target->GetTypeId() != TYPEID_PLAYER) + { + //only pets have base stats + if(((Creature*)target)->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply); + } + else + { + for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) + if(GetMiscValue() & (1<<i)) + target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply); + } +} + +void AuraEffect::HandleModTargetResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage + + // show armor penetration + if (target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,GetAmount(), apply); + + // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy + if (target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL) + target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,GetAmount(), apply); +} + +/********************************/ +/*** STAT ***/ +/********************************/ + +void AuraEffect::HandleAuraModStat(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if (GetMiscValue() < -2 || GetMiscValue() > 4) + { + sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),GetMiscValue()); + return; + } + + for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) + { + // -1 or -2 is all stats ( misc < -2 checked in function beginning ) + if (GetMiscValue() < 0 || GetMiscValue() == i) + { + //target->ApplyStatMod(Stats(i), m_amount,apply); + target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply); + if(target->GetTypeId() == TYPEID_PLAYER || ((Creature*)target)->isPet()) + target->ApplyStatBuffMod(Stats(i),GetAmount(),apply); + } + } +} + +void AuraEffect::HandleModPercentStat(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if (GetMiscValue() < -1 || GetMiscValue() > 4) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); + return; + } + + // only players have base stats + if (target->GetTypeId() != TYPEID_PLAYER) + return; + + for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) + { + if(GetMiscValue() == i || GetMiscValue() == -1) + target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply); + } +} + +void AuraEffect::HandleModSpellDamagePercentFromStat(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + // Magic damage modifiers implemented in Unit::SpellDamageBonus + // This information for client side use only + // Recalculate bonus + ((Player*)target)->UpdateSpellDamageAndHealingBonus(); +} + +void AuraEffect::HandleModSpellHealingPercentFromStat(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + // Recalculate bonus + ((Player*)target)->UpdateSpellDamageAndHealingBonus(); +} + +void AuraEffect::HandleModSpellDamagePercentFromAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + // Magic damage modifiers implemented in Unit::SpellDamageBonus + // This information for client side use only + // Recalculate bonus + ((Player*)target)->UpdateSpellDamageAndHealingBonus(); +} + +void AuraEffect::HandleModSpellHealingPercentFromAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + // Recalculate bonus + ((Player*)target)->UpdateSpellDamageAndHealingBonus(); +} + +void AuraEffect::HandleModHealingDone(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + // implemented in Unit::SpellHealingBonus + // this information is for client side only + ((Player*)target)->UpdateSpellDamageAndHealingBonus(); +} + +void AuraEffect::HandleModTotalPercentStat(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if (GetMiscValue() < -1 || GetMiscValue() > 4) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); + return; + } + + //save current and max HP before applying aura + uint32 curHPValue = target->GetHealth(); + uint32 maxHPValue = target->GetMaxHealth(); + + for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) + { + if(GetMiscValue() == i || GetMiscValue() == -1) + { + target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply); + if(target->GetTypeId() == TYPEID_PLAYER || ((Creature*)target)->isPet()) + target->ApplyStatPercentBuffMod(Stats(i), GetAmount(), apply ); + } + } + + //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag) + if ((GetMiscValue() == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10)) + { + // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed + uint32 newHPValue = (target->GetMaxHealth() * curHPValue) / maxHPValue; + target->SetHealth(newHPValue); + } +} + +void AuraEffect::HandleAuraModResistenceOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + if(GetMiscValue() != SPELL_SCHOOL_MASK_NORMAL) + { + // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update + // and include in UpdateResistence same code as in UpdateArmor for aura mod apply. + sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!"); + return; + } + + // Recalculate Armor + target->UpdateArmor(); +} + +void AuraEffect::HandleAuraModExpertise(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)target)->UpdateExpertise(BASE_ATTACK); + ((Player*)target)->UpdateExpertise(OFF_ATTACK); +} + +/********************************/ +/*** HEAL & ENERGIZE ***/ +/********************************/ +void AuraEffect::HandleModPowerRegen(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if (target->GetTypeId() != TYPEID_PLAYER) + return; + + // Update manaregen value + if (GetMiscValue() == POWER_MANA) + ((Player*)target)->UpdateManaRegen(); + // other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate +} + +void AuraEffect::HandleModPowerRegenPCT(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if (target->GetTypeId() != TYPEID_PLAYER) + return; + + // Update manaregen value + if (GetMiscValue() == POWER_MANA) + ((Player*)target)->UpdateManaRegen(); + // other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate +} + +void AuraEffect::HandleModManaRegen(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if (target->GetTypeId() != TYPEID_PLAYER) + return; + + //Note: an increase in regen does NOT cause threat. + ((Player*)target)->UpdateManaRegen(); +} + +void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + { + target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + target->ModifyHealth(GetAmount()); + } + else + { + if (int32(target->GetHealth()) > GetAmount()) + target->ModifyHealth(-GetAmount()); + else + target->SetHealth(1); + target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + } +} + +void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + uint32 oldhealth = target->GetHealth(); + double healthPercentage = (double)oldhealth / (double)target->GetMaxHealth(); + + target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply); + + // refresh percentage + if(oldhealth > 0) + { + uint32 newhealth = uint32(ceil((double)target->GetMaxHealth() * healthPercentage)); + if(newhealth==0) + newhealth = 1; + + target->SetHealth(newhealth); + } +} + +void AuraEffect::HandleAuraModIncreaseEnergy(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + Powers powerType = target->getPowerType(); + if(int32(powerType) != GetMiscValue()) + return; + + UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); + + // Special case with temporary increase max/current power (percent) + if (GetId()==64904) // Hymn of Hope + { + if(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK) + target->SetPower(powerType, apply ? GetAmount() + target->GetPower(powerType) : target->GetPower(powerType) - GetAmount()); + } + + // generic flat case + target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply); +} + +void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + Powers powerType = target->getPowerType(); + if(int32(powerType) != GetMiscValue()) + return; + + UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); + + target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetAmount()), apply); +} + +void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + // Unit will keep hp% after MaxHealth being modified if unit is alive. + float percent = ((float)target->GetHealth()) / target->GetMaxHealth(); + target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply); + if (target->isAlive()) + target->SetHealth(uint32(target->GetMaxHealth()*percent)); +} + +void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply); +} + +/********************************/ +/*** FIGHT ***/ +/********************************/ + +void AuraEffect::HandleAuraModParryPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)target)->UpdateParryPercentage(); +} + +void AuraEffect::HandleAuraModDodgePercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)target)->UpdateDodgePercentage(); +} + +void AuraEffect::HandleAuraModBlockPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)target)->UpdateBlockPercentage(); +} + +void AuraEffect::HandleAuraModRegenInterrupt(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)target)->UpdateManaRegen(); +} + +void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + for (int i = 0; i < MAX_ATTACK; ++i) + if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i))) + ((Player*)target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply); + + // mods must be applied base at equipped weapon class and subclass comparison + // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask + // GetMiscValue() comparison with item generated damage types + + if (GetSpellProto()->EquippedItemClass == -1) + { + ((Player*)target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); + ((Player*)target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); + ((Player*)target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); + } + else + { + // done in Player::_ApplyWeaponDependentAuraMods + } +} + +void AuraEffect::HandleModHitChance(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)target)->UpdateMeleeHitChances(); + ((Player*)target)->UpdateRangedHitChances(); + } + else + { + target->m_modMeleeHitChance += (apply) ? GetAmount() : (-GetAmount()); + target->m_modRangedHitChance += (apply) ? GetAmount() : (-GetAmount()); + } +} + +void AuraEffect::HandleModSpellHitChance(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->UpdateSpellHitChances(); + else + target->m_modSpellHitChance += (apply) ? GetAmount(): (-GetAmount()); +} + +void AuraEffect::HandleModSpellCritChance(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->UpdateAllSpellCritChances(); + else + target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount(); +} + +void AuraEffect::HandleModSpellCritChanceShool(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + for (int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school) + if (GetMiscValue() & (1<<school)) + ((Player*)target)->UpdateSpellCritChance(school); +} + +void AuraEffect::HandleAuraModCritPct(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + { + target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount(); + return; + } + + ((Player*)target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); + ((Player*)target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); + ((Player*)target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply); + + // included in Player::UpdateSpellCritChance calculation + ((Player*)target)->UpdateAllSpellCritChances(); +} + +/********************************/ +/*** ATTACK SPEED ***/ +/********************************/ + +void AuraEffect::HandleModCastingSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplyCastTimePercentMod(GetAmount(),apply); +} + +void AuraEffect::HandleModMeleeRangedSpeedPct(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplyAttackTimePercentMod(BASE_ATTACK,GetAmount(),apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK,GetAmount(),apply); + target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetAmount(), apply); +} + +void AuraEffect::HandleModCombatSpeedPct(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplyCastTimePercentMod(m_amount,apply); + target->ApplyAttackTimePercentMod(BASE_ATTACK,GetAmount(),apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK,GetAmount(),apply); + target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetAmount(), apply); +} + +void AuraEffect::HandleModAttackSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplyAttackTimePercentMod(BASE_ATTACK,GetAmount(),apply); + target->UpdateDamagePhysical(BASE_ATTACK); +} + +void AuraEffect::HandleHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplyAttackTimePercentMod(BASE_ATTACK, GetAmount(),apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK, GetAmount(),apply); + target->ApplyAttackTimePercentMod(RANGED_ATTACK,GetAmount(),apply); +} + +void AuraEffect::HandleAuraModRangedHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetAmount(), apply); +} + +void AuraEffect::HandleRangedAmmoHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetAmount(), apply); +} + +/********************************/ +/*** COMBAT RATING ***/ +/********************************/ + +void AuraEffect::HandleModRating(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + if (GetMiscValue() & (1 << rating)) + ((Player*)target)->ApplyRatingMod(CombatRating(rating), GetAmount(), apply); +} + +void AuraEffect::HandleModRatingFromStat(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + // Just recalculate ratings + for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + if (GetMiscValue() & (1 << rating)) + ((Player*)target)->ApplyRatingMod(CombatRating(rating), 0, apply); +} + +/********************************/ +/*** ATTACK POWER ***/ +/********************************/ + +void AuraEffect::HandleAuraModAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply); +} + +void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if((target->getClassMask() & CLASSMASK_WAND_USERS)!=0) + return; + + target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply); +} + +void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 + target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()), apply); +} + +void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + if((target->getClassMask() & CLASSMASK_WAND_USERS)!=0) + return; + + //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1 + target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply); +} + +void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + // Recalculate bonus + if(target->GetTypeId() == TYPEID_PLAYER && !(target->getClassMask() & CLASSMASK_WAND_USERS)) + ((Player*)target)->UpdateAttackPowerAndDamage(true); +} + +void AuraEffect::HandleAuraModAttackPowerOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + // Recalculate bonus + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->UpdateAttackPowerAndDamage(false); +} + +void AuraEffect::HandleAuraModAttackPowerOfArmor(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + // Recalculate bonus + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->UpdateAttackPowerAndDamage(false); +} +/********************************/ +/*** DAMAGE BONUS ***/ +/********************************/ +void AuraEffect::HandleModDamageDone(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + // apply item specific bonuses for already equipped weapon + if(target->GetTypeId() == TYPEID_PLAYER) + { + for (int i = 0; i < MAX_ATTACK; ++i) + if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i))) + ((Player*)target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); + } + + // GetMiscValue() is bitmask of spell schools + // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) + // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands + // 127 - full bitmask any damages + // + // mods must be applied base at equipped weapon class and subclass comparison + // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask + // GetMiscValue() comparison with item generated damage types + + if((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0) + { + // apply generic physical damage bonuses including wand case + if (GetSpellProto()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER) + { + target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply); + } + else + { + // done in Player::_ApplyWeaponDependentAuraMods + } + + if(target->GetTypeId() == TYPEID_PLAYER) + { + if(GetAmount() > 0) + target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,GetAmount(),apply); + else + target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,GetAmount(),apply); + } + } + + // Skip non magic case for speedup + if((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0) + return; + + if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) + { + // wand magic case (skip generic to all item spell bonuses) + // done in Player::_ApplyWeaponDependentAuraMods + + // Skip item specific requirements for not wand magic damage + return; + } + + // Magic damage modifiers implemented in Unit::SpellDamageBonus + // This information for client side use only + if(target->GetTypeId() == TYPEID_PLAYER) + { + if(GetAmount() > 0) + { + for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + { + if((GetMiscValue() & (1<<i)) != 0) + target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,GetAmount(),apply); + } + } + else + { + for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + { + if((GetMiscValue() & (1<<i)) != 0) + target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,GetAmount(),apply); + } + } + if(Guardian* pet = ((Player*)target)->GetGuardianPet()) + pet->UpdateAttackPowerAndDamage(); + } +} + +void AuraEffect::HandleModDamagePercentDone(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", GetMiscValue(), GetAmount() > 0); + + // apply item specific bonuses for already equipped weapon + if(target->GetTypeId() == TYPEID_PLAYER) + { + for (int i = 0; i < MAX_ATTACK; ++i) + if(Item* pItem = ((Player*)target)->GetWeaponForAttack(WeaponAttackType(i))) + ((Player*)target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); + } + + // GetMiscValue() is bitmask of spell schools + // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) + // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand + // 127 - full bitmask any damages + // + // mods must be applied base at equipped weapon class and subclass comparison + // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask + // GetMiscValue() comparison with item generated damage types + + if((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0) + { + // apply generic physical damage bonuses including wand case + if (GetSpellProto()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER) + { + target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); + target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply); + } + else + { + // done in Player::_ApplyWeaponDependentAuraMods + } + // For show in client + if(target->GetTypeId() == TYPEID_PLAYER) + target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,GetAmount()/100.0f,apply); + } + + // Skip non magic case for speedup + if((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0) + return; + + if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) + { + // wand magic case (skip generic to all item spell bonuses) + // done in Player::_ApplyWeaponDependentAuraMods + + // Skip item specific requirements for not wand magic damage + return; + } + + // Magic damage percent modifiers implemented in Unit::SpellDamageBonus + // Send info to client + if(target->GetTypeId() == TYPEID_PLAYER) + for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) + target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,GetAmount()/100.0f,apply); +} + +void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply); +} + +void AuraEffect::HandleShieldBlockValue(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) + return; + + Unit * target = aurApp->GetTarget(); + + BaseModType modType = FLAT_MOD; + if(GetAuraType() == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT) + modType = PCT_MOD; + + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetAmount()), apply); +} + +/********************************/ +/*** POWER COST ***/ +/********************************/ + +void AuraEffect::HandleModPowerCostPCT(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + float amount = GetAmount() /100.0f; + for (int i = 0; i < MAX_SPELL_SCHOOL; ++i) + if(GetMiscValue() & (1<<i)) + target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply); +} + +void AuraEffect::HandleModPowerCost(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + for (int i = 0; i < MAX_SPELL_SCHOOL; ++i) + if(GetMiscValue() & (1<<i)) + target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,GetAmount(),apply); +} + +void AuraEffect::HandleArenaPreparation(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); + else + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); + } +} + +void AuraEffect::HandleNoReagentUseAura(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + flag96 mask; + Unit::AuraEffectList const& noReagent = target->GetAuraEffectsByType(SPELL_AURA_NO_REAGENT_USE); + for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) + mask |= (*i)->m_spellProto->EffectSpellClassMask[(*i)->m_effIndex]; + + target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); + target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); + target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]); +} + +void AuraEffect::HandleAuraRetainComboPoints(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler + // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost) + if( !(apply) && GetBase()->GetDuration()==0 && ((Player*)target)->GetComboTarget()) + if(Unit* unit = ObjectAccessor::GetUnit(*target,((Player*)target)->GetComboTarget())) + ((Player*)target)->AddComboPoints(unit, -GetAmount()); +} + +/*********************************************************/ +/*** OTHERS ***/ +/*********************************************************/ + +void AuraEffect::HandleAuraDummy(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + Unit * caster = GetCaster(); + + if (mode & AURA_EFFECT_HANDLE_REAL) + { + // AT APPLY + if(apply) + { + // Overpower + if (caster && m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && + m_spellProto->SpellFamilyFlags[0] & 0x4) + { + // Must be casting target + if (target->IsNonMeleeSpellCasted(false, false, true)) + { + if (AuraEffect * aurEff = caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARRIOR, 2775, 0)) + { + switch (aurEff->GetId()) + { + // Unrelenting Assault, rank 1 + case 46859: + target->CastSpell(target,64849,true,NULL,aurEff); + break; + // Unrelenting Assault, rank 2 + case 46860: + target->CastSpell(target,64850,true,NULL,aurEff); + break; + } + } + } + } + switch(GetId()) + { + case 1515: // Tame beast + // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness + if( caster && target->CanHaveThreatList()) + target->AddThreat(caster, 10.0f); + break; + case 13139: // net-o-matic + // root to self part of (root_target->charge->root_self sequence + if(caster) + caster->CastSpell(caster,13138,true,NULL,this); + break; + case 34026: // kill command + { + Unit * pet = target->GetGuardianPet(); + if (!pet) + break; + + target->CastSpell(target,34027,true,NULL,this); + + // set 3 stacks and 3 charges (to make all auras not disappear at once) + Aura * owner_aura = target->GetAura(34027,GetCasterGUID()); + Aura * pet_aura = pet->GetAura(58914, GetCasterGUID()); + if( owner_aura ) + { + owner_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount); + } + if( pet_aura ) + { + pet_aura->SetCharges(0); + pet_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount); + } + break; + } + case 37096: // Blood Elf Illusion + { + if(caster) + { + switch(caster->getGender()) + { + case GENDER_FEMALE: + caster->CastSpell(target,37095,true,NULL,this); // Blood Elf Disguise + break; + case GENDER_MALE: + caster->CastSpell(target,37093,true,NULL,this); + break; + default: + break; + } + } + break; + } + case 55198: // Tidal Force + { + target->CastSpell(target,55166,true,NULL,this); + // set 3 stacks and 3 charges (to make all auras not disappear at once) + Aura * owner_aura = target->GetAura(55166,GetCasterGUID()); + if( owner_aura ) + { + // This aura lasts 2 sec, need this hack to properly proc spells + // TODO: drop aura charges for ApplySpellMod in ProcDamageAndSpell + GetBase()->SetDuration(owner_aura->GetDuration()); + // Make aura be not charged-this prevents removing charge on not crit spells + owner_aura->SetCharges(0); + owner_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount); + } + break; + } + case 39850: // Rocket Blast + if(roll_chance_i(20)) // backfire stun + target->CastSpell(target, 51581, true, NULL, this); + break; + case 43873: // Headless Horseman Laugh + target->PlayDistanceSound(11965); + break; + case 46354: // Blood Elf Illusion + if(caster) + { + switch(caster->getGender()) + { + case GENDER_FEMALE: + caster->CastSpell(target,46356,true,NULL,this); + break; + case GENDER_MALE: + caster->CastSpell(target,46355,true,NULL,this); + break; + } + } + break; + case 46699: // Requires No Ammo + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->RemoveAmmo(); // not use ammo and not allow use + break; + case 49028: + GetBase()->SetDuration(GetBase()->GetDuration() + (caster->GetPower(POWER_RUNIC_POWER) * 10)); + caster->SetPower(POWER_RUNIC_POWER, 0); + break; + case 62061: // Festive Holiday Mount + if(target->HasAuraType(SPELL_AURA_MOUNTED)) + target->CastSpell(target, 25860, true, NULL, this); // Reindeer Transformation + break; + case 52916: // Honor Among Thieves + if(target->GetTypeId() == TYPEID_PLAYER) + if (Unit * spellTarget = ObjectAccessor::GetUnit(*target,((Player*)target)->GetComboTarget())) + target->CastSpell(spellTarget, 51699, true); + break; + case 28832: // Mark of Korth'azz + case 28833: // Mark of Blaumeux + case 28834: // Mark of Rivendare + case 28835: // Mark of Zeliek + if(caster) // actually we can also use cast(this, originalcasterguid) + { + int32 damage; + switch(GetBase()->GetStackAmount()) + { + case 1: damage = 0; break; + case 2: damage = 500; break; + case 3: damage = 1000; break; + case 4: damage = 1500; break; + case 5: damage = 4000; break; + case 6: damage = 12000; break; + default:damage = 20000 + 1000 * (GetBase()->GetStackAmount() - 7); break; + } + if(damage) + caster->CastCustomSpell(28836, SPELLVALUE_BASE_POINT0, damage, target); + } + break; + } + } + // AT REMOVE + else + { + if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && target->isAlive()) + { + uint32 finalSpelId = 0; + switch(GetId()) + { + case 19548: finalSpelId = 19597; break; + case 19674: finalSpelId = 19677; break; + case 19687: finalSpelId = 19676; break; + case 19688: finalSpelId = 19678; break; + case 19689: finalSpelId = 19679; break; + case 19692: finalSpelId = 19680; break; + case 19693: finalSpelId = 19684; break; + case 19694: finalSpelId = 19681; break; + case 19696: finalSpelId = 19682; break; + case 19697: finalSpelId = 19683; break; + case 19699: finalSpelId = 19685; break; + case 19700: finalSpelId = 19686; break; + case 30646: finalSpelId = 30647; break; + case 30653: finalSpelId = 30648; break; + case 30654: finalSpelId = 30652; break; + case 30099: finalSpelId = 30100; break; + case 30102: finalSpelId = 30103; break; + case 30105: finalSpelId = 30104; break; + } + + if(finalSpelId) + caster->CastSpell(target,finalSpelId,true,NULL,this); + } + + switch(m_spellProto->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + switch(GetId()) + { + case 2584: // Waiting to Resurrect + // Waiting to resurrect spell cancel, we must remove player from resurrect queue + if(target->GetTypeId() == TYPEID_PLAYER) + if(BattleGround *bg = ((Player*)target)->GetBattleGround()) + bg->RemovePlayerFromResurrectQueue(target->GetGUID()); + break; + case 28169: // Mutating Injection + { + // Mutagen Explosion + target->CastSpell(target, 28206, true, NULL, this); + // Poison Cloud + target->CastSpell(target, 28240, true, NULL, this); + return; + } + case 36730: // Flame Strike + { + target->CastSpell(target, 36731, true, NULL, this); + break; + } + case 44191: // Flame Strike + { + if (target->GetMap()->IsDungeon()) + { + uint32 spellId = target->GetMap()->IsHeroic() ? 46163 : 44190; + + target->CastSpell(target, spellId, true, NULL, this); + } + break; + } + case 42783: // Wrath of the Astromancer + target->CastSpell(target,GetAmount(),true,NULL,this); + break; + case 46308: // Burning Winds casted only at creatures at spawn + target->CastSpell(target,47287,true,NULL,this); + break; + case 52172: // Coyote Spirit Despawn Aura + case 60244: // Blood Parrot Despawn Aura + target->CastSpell((Unit*)NULL, GetAmount(), true, NULL, this); + break; + } + break; + case SPELLFAMILY_MAGE: + // Living Bomb + if(m_spellProto->SpellFamilyFlags[1] & 0x20000) + { + AuraRemoveMode mode = aurApp->GetRemoveMode(); + if(caster && (mode == AURA_REMOVE_BY_ENEMY_SPELL || mode == AURA_REMOVE_BY_EXPIRE)) + caster->CastSpell(target, GetAmount(), true); + } + break; + case SPELLFAMILY_WARLOCK: + // Haunt + if(m_spellProto->SpellFamilyFlags[1] & 0x40000) + { + if(caster) + caster->CastCustomSpell(caster, 48210, &m_amount, 0, 0, true, NULL, this); + } + break; + case SPELLFAMILY_DRUID: + // Lifebloom + if ( GetSpellProto()->SpellFamilyFlags[1] & 0x10 ) + { + if (!apply) + { + // Final heal only on dispelled or duration end + if (aurApp->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && aurApp->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + return; + + // final heal + target->CastCustomSpell(target,33778,&m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + + // restore mana + if (caster) + { + int32 returnmana = (GetSpellProto()->ManaCostPercentage * caster->GetCreateMana() / 100) * GetBase()->GetStackAmount() / 2; + caster->CastCustomSpell(caster, 64372, &returnmana, NULL, NULL, true, NULL, this, GetCasterGUID()); + } + } + } + break; + case SPELLFAMILY_PRIEST: + // Vampiric Touch + if (m_spellProto->SpellFamilyFlags[1] & 0x0400 && aurApp->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL) + { + if (AuraEffect const * aurEff = GetBase()->GetEffect(1)) + { + int32 damage = aurEff->GetAmount()*4; + // backfire damage + target->CastCustomSpell(target, 64085, &damage, NULL, NULL, true, NULL, NULL,GetCasterGUID()); + } + } + break; + case SPELLFAMILY_HUNTER: + // Misdirection + if(GetId()==34477) + target->SetReducedThreatPercent(0, 0); + break; + case SPELLFAMILY_DEATHKNIGHT: + // Summon Gargoyle ( will start feeding gargoyle ) + if(GetId()==61777) + target->CastSpell(target,m_spellProto->EffectTriggerSpell[m_effIndex],true); + break; + default: + break; + } + } + } + + // AT APPLY & REMOVE + + switch(m_spellProto->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + break; + switch(GetId()) + { + // Recently Bandaged + case 11196: + target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, GetMiscValue(), apply); + break; + // Unstable Power + case 24658: + { + uint32 spellId = 24659; + if (apply && caster) + { + SpellEntry const * spell = sSpellStore.LookupEntry(spellId); + + for (int i=0; i < spell->StackAmount; ++i) + caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID()); + break; + } + target->RemoveAurasDueToSpell(spellId); + break; + } + // Restless Strength + case 24661: + { + uint32 spellId = 24662; + if (apply && caster) + { + SpellEntry const * spell = sSpellStore.LookupEntry(spellId); + for (int i=0; i < spell->StackAmount; ++i) + caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID()); + break; + } + target->RemoveAurasDueToSpell(spellId); + break; + } + //Summon Fire Elemental + case 40133: + { + if (!caster) + break; + + Unit *owner = caster->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + { + if(apply) + owner->CastSpell(owner,8985,true); + else + ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + } + break; + } + //Summon Earth Elemental + case 40132 : + { + if (!caster) + break; + + Unit *owner = caster->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + { + if(apply) + owner->CastSpell(owner,19704,true); + else + ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + } + break; + } + case 57723: // Exhaustion + case 57724: // Sated + { + switch(GetId()) + { + case 57723: target->ApplySpellImmune(GetId(), IMMUNITY_ID, 32182, apply); break; // Heroism + case 57724: target->ApplySpellImmune(GetId(), IMMUNITY_ID, 2825, apply); break; // Bloodlust + } + break; + } + case 57819: // Argent Champion + case 57820: // Ebon Champion + case 57821: // Champion of the Kirin Tor + case 57822: // Wyrmrest Champion + { + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + break; + + uint32 FactionID = 0; + + if(apply) + { + switch(m_spellProto->Id) + { + case 57819: FactionID = 1106; break; // Argent Crusade + case 57820: FactionID = 1098; break; // Knights of the Ebon Blade + case 57821: FactionID = 1090; break; // Kirin Tor + case 57822: FactionID = 1091; break; // The Wyrmrest Accord + } + } + ((Player*)caster)->SetChampioningFaction(FactionID); + break; + } + // LK Intro VO (1) + case 58204: + if(target->GetTypeId() == TYPEID_PLAYER) + { + // Play part 1 + if(apply) + target->PlayDirectSound(14970, (Player *)target); + // continue in 58205 + else + target->CastSpell(target, 58205, true); + } + break; + // LK Intro VO (2) + case 58205: + if(target->GetTypeId() == TYPEID_PLAYER) + { + // Play part 2 + if(apply) + target->PlayDirectSound(14971, (Player *)target); + // Play part 3 + else + target->PlayDirectSound(14972, (Player *)target); + } + break; + } + + break; + } + case SPELLFAMILY_MAGE: + { + //if (!(mode & AURA_EFFECT_HANDLE_REAL)) + //break; + break; + } + case SPELLFAMILY_PRIEST: + { + //if (!(mode & AURA_EFFECT_HANDLE_REAL)) + //break; + break; + } + case SPELLFAMILY_DRUID: + { + if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + break; + switch(GetId()) + { + case 61336: // Survival Instincts + { + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + break; + if(apply) + { + if (!target->IsInFeralForm()) + break; + + int32 bp0 = int32(target->GetMaxHealth() * GetAmount() / 100); + target->CastCustomSpell(target, 50322, &bp0, NULL, NULL, true); + } + else + target-> RemoveAurasDueToSpell(50322); + break; + } + } + // Predatory Strikes + if(target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563) + { + ((Player*)target)->UpdateAttackPowerAndDamage(); + } + break; + } + case SPELLFAMILY_SHAMAN: + { + if (!(mode & AURA_EFFECT_HANDLE_REAL)) + break; + // Sentry Totem + if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER) + { + if (apply) + { + uint64 guid = caster->m_SummonSlot[3]; + if (guid) + { + Creature *totem = caster->GetMap()->GetCreature(guid); + if (totem && totem->isTotem()) + ((Player*)caster)->CastSpell(totem, 6277, true); + } + } + else + ((Player*)caster)->StopCastingBindSight(); + return; + } + break; + } + case SPELLFAMILY_PALADIN: + switch (GetSpellProto()->SpellIconID) + { + // Blessing of Sanctuary + // Greater Blessing of Sanctuary + case 19: + case 1804: + { + if (!caster || !target) + return; + + if (apply) + { + // Greater Blessing of Sanctuary does not provide strength bonus + int32 bp1 = 0; + caster->CastCustomSpell(target, 67480, NULL, (GetSpellProto()->SpellIconID == 1804) ? &bp1 : NULL, NULL, true); + } + else + target->RemoveAura(67480, GetCasterGUID()); + + return; + } + } + break; + } + + if (mode & AURA_EFFECT_HANDLE_REAL) + { + // pet auras + if(PetAura const* petSpell = spellmgr.GetPetAura(GetId(), m_effIndex)) + { + if(apply) + target->AddPetAura(petSpell); + else + target->RemovePetAura(petSpell); + } + } +} + +void AuraEffect::HandleChannelDeathItem(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(!(apply)) + { + Unit * caster = GetCaster(); + + if(!caster || caster->GetTypeId() != TYPEID_PLAYER)// || m_removeMode!=AURA_REMOVE_BY_DEATH) + return; + + //we cannot check removemode = death + //talent will remove the caster's aura->interrupt channel->remove victim aura + if(target->GetHealth() > 0) + return; + // Item amount + if (GetAmount() <= 0) + return; + + if(GetSpellProto()->EffectItemType[m_effIndex] == 0) + return; + + // Soul Shard only from non-grey units + if( GetSpellProto()->EffectItemType[m_effIndex] == 6265 && + (target->getLevel() <= Trinity::XP::GetGrayLevel(caster->getLevel()) || + target->GetTypeId() == TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)target)) ) + return; + //Adding items + uint32 noSpaceForCount = 0; + uint32 count = m_amount; + + ItemPosCountVec dest; + uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, GetSpellProto()->EffectItemType[m_effIndex], count, &noSpaceForCount); + if( msg != EQUIP_ERR_OK ) + { + count-=noSpaceForCount; + ((Player*)caster)->SendEquipError( msg, NULL, NULL ); + if (count==0) + return; + } + + Item* newitem = ((Player*)caster)->StoreNewItem(dest, GetSpellProto()->EffectItemType[m_effIndex], true); + ((Player*)caster)->SendNewItem(newitem, count, true, false); + } +} + +void AuraEffect::HandleBindSight(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + Unit * caster = GetCaster(); + + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)caster)->SetViewpoint(target, (apply)); +} + +void AuraEffect::HandleForceReaction(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + Player* player = (Player*)target; + + uint32 faction_id = GetMiscValue(); + ReputationRank faction_rank = ReputationRank(m_amount); + + player->GetReputationMgr().ApplyForceReaction(faction_id,faction_rank,apply); + player->GetReputationMgr().SendForceReactions(); + + // stop fighting if at apply forced rank friendly or at remove real rank friendly + if (apply && faction_rank >= REP_FRIENDLY || !apply && player->GetReputationRank(faction_id) >= REP_FRIENDLY) + player->StopAttackFaction(faction_id); +} + +void AuraEffect::HandleAuraEmpathy(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if (target->GetTypeId() != TYPEID_UNIT) + return; + + if(!(apply)) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if(target->HasAuraType(GetAuraType())) + return; + } + + CreatureInfo const * ci = objmgr.GetCreatureTemplate(target->GetEntry()); + if(ci && ci->type == CREATURE_TYPE_BEAST) + target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply); +} + +void AuraEffect::HandleComprehendLanguage(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + return; + + Unit * target = aurApp->GetTarget(); + + if(apply) + target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); + else + { + if (target->HasAuraType(GetAuraType())) + return; + + target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); + } +} + +void AuraEffect::HandleAuraConvertRune(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if(target->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)target; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + uint32 runes = m_amount; + // convert number of runes specified in aura amount of rune type in miscvalue to runetype in miscvalueb + if(apply) + { + for (uint32 i = 0; i < MAX_RUNES && runes; ++i) + { + if (GetMiscValue() != plr->GetCurrentRune(i)) + continue; + if(!plr->GetRuneCooldown(i)) + { + // ConvertRune(i, + plr->AddRuneByAuraEffect(i, RuneType(GetMiscValueB()), this); + --runes; + } + } + } + else + plr->RemoveRunesByAuraEffect(this); +} + +void AuraEffect::HandleAuraLinked(AuraApplication const * aurApp, uint8 mode, bool apply) const +{ + if(!(mode & AURA_EFFECT_HANDLE_REAL)) + return; + + Unit * target = aurApp->GetTarget(); + + if (apply) + { + Unit * caster = GetCaster(); + + if (!caster) + return; + // If amount avalible cast with basepoints (Crypt Fever for example) + if (GetAmount()) + caster->CastCustomSpell(target, m_spellProto->EffectTriggerSpell[m_effIndex], &m_amount, NULL, NULL, true, NULL, this); + else + caster->CastSpell(target, m_spellProto->EffectTriggerSpell[m_effIndex],true, NULL, this); + } + else + target->RemoveAura(m_spellProto->EffectTriggerSpell[m_effIndex], GetCasterGUID(), 0, AuraRemoveMode(aurApp->GetRemoveMode())); +} diff --git a/src/game/SpellAuraEffects.h b/src/game/SpellAuraEffects.h new file mode 100644 index 00000000000..75e061da5fe --- /dev/null +++ b/src/game/SpellAuraEffects.h @@ -0,0 +1,263 @@ + +#ifndef TRINITY_SPELLAURAEFFECTS_H +#define TRINITY_SPELLAURAEFFECTS_H + +class Unit; +class DynamicObject; +class AuraEffect; +class Aura; + +#include "SpellAuras.h" + +#define AURA_EFFECT_HANDLE_DEFAULT 0 +#define AURA_EFFECT_HANDLE_REAL 0x01 +#define AURA_EFFECT_HANDLE_SEND_FOR_CLIENT 0x02 +#define AURA_EFFECT_HANDLE_CHANGE_AMOUNT 0x04 +#define AURA_EFFECT_HANDLE_STAT 0x08 +#define AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK (AURA_EFFECT_HANDLE_SEND_FOR_CLIENT | AURA_EFFECT_HANDLE_REAL) +#define AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK (AURA_EFFECT_HANDLE_CHANGE_AMOUNT | AURA_EFFECT_HANDLE_REAL) +#define AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK) + +typedef void(AuraEffect::*pAuraEffectHandler)(AuraApplication const * aurApp, uint8 mode, bool apply) const; + +class TRINITY_DLL_SPEC AuraEffect +{ + friend Aura::Aura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); + friend Aura::~Aura(); + private: + ~AuraEffect(); + explicit AuraEffect(Aura * base, uint8 effIndex, int32 *baseAmount, Unit * caster); + public: + Unit * GetCaster() const { return GetBase()->GetCaster(); } + uint64 GetCasterGUID() const { return GetBase()->GetCasterGUID(); } + Aura * GetBase() const { return m_base; } + void GetTargetList(std::list<Unit*> & targetList) const; + + SpellEntry const * GetSpellProto() const { return m_spellProto; } + uint32 GetId() const { return m_spellProto->Id; } + uint32 GetEffIndex() const { return m_effIndex; } + int32 GetBaseAmount() const { return m_baseAmount; } + int32 GetAmplitude() const { return m_amplitude; } + + int32 GetMiscValueB() const { return m_spellProto->EffectMiscValueB[m_effIndex]; } + int32 GetMiscValue() const { return m_spellProto->EffectMiscValue[m_effIndex]; } + AuraType GetAuraType() const { return (AuraType)m_spellProto->EffectApplyAuraName[m_effIndex]; } + int32 GetAmount() const { return m_amount; } + void SetAmount(int32 amount) { m_amount = amount; m_canBeRecalculated = false;} + + int32 CalculateAmount(Unit * caster); + void CalculatePeriodic(Unit * caster, bool create = false); + void CalculateSpellMod(); + void ChangeAmount(int32 newAmount, bool mark = true); + void RecalculateAmount() { if(!CanBeRecalculated()) return; ChangeAmount(CalculateAmount(GetCaster()), false); } + void RecalculateAmount(Unit * caster) { if(!CanBeRecalculated()) return; ChangeAmount(CalculateAmount(caster), false); } + bool CanBeRecalculated() const { return m_canBeRecalculated; } + void SetCanBeRecalculated(bool val) { m_canBeRecalculated = val; } + void HandleEffect(AuraApplication const * aurApp, uint8 mode, bool apply); + void HandleEffect(Unit * target, uint8 mode, bool apply); + void ApplySpellMod(Unit * target, bool apply); + + void Update(uint32 diff, Unit * caster); + void UpdatePeriodic(Unit * caster); + + uint32 GetTickNumber() const { return m_tickNumber; } + int32 GetTotalTicks() const { return m_amplitude ? (GetBase()->GetMaxDuration() / m_amplitude) : 1;} + void ResetPeriodic() {m_periodicTimer = m_amplitude; m_tickNumber = 0;} + + bool IsPeriodic() const { return m_isPeriodic; } + bool IsAffectedOnSpell(SpellEntry const *spell) const; + + void PeriodicTick(Unit * target, Unit * caster) const; + void PeriodicDummyTick(Unit * target, Unit * caster) const; + Unit* GetTriggerTarget(Unit * target) const; + void TriggerSpell(Unit * target, Unit * caster) const; + void TriggerSpellWithValue(Unit * target, Unit * caster) const; + + void CleanupTriggeredSpells(Unit * target); + + static bool IsPeriodicAuraType(uint32 type); + // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras + void HandleShapeshiftBoosts(Unit * target, bool apply) const; + private: + Aura * const m_base; + + SpellEntry const * const m_spellProto; + uint8 const m_effIndex; + int32 const m_baseAmount; + + int32 m_amount; + bool m_canBeRecalculated:1; + + SpellModifier *m_spellmod; + + bool m_isPeriodic:1; + int32 m_periodicTimer; + int32 m_amplitude; + uint32 m_tickNumber; + private: + bool IsPeriodicTickCrit(Unit * target, Unit const * caster) const; + + public: + // aura effect handlers + void HandleNULL(AuraApplication const * aurApp, uint8 mode, bool apply) const + { + // not implemented + } + void HandleUnused(AuraApplication const * aurApp, uint8 mode, bool apply) const + { + // useless + } + void HandleNoImmediateEffect(AuraApplication const * aurApp, uint8 mode, bool apply) const + { + // aura type not have immediate effect at add/remove and handled by ID in other code place + } + // visibility & phases + void HandleInvisibilityDetect(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleInvisibility(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModStealth(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleSpiritOfRedemption(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraGhost(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandlePhase(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // unit model + void HandleAuraModShapeshift(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraTransform(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModScale(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraCloneCaster(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // fight + void HandleFeignDeath(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModUnattackable(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModDisarm(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModSilence(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModPacify(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModPacifyAndSilence(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraAllowOnlyAbility(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // tracking + void HandleAuraTrackResources(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraTrackCreatures(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraTrackStealthed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModStalked(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraUntrackable(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // skills & talents + void HandleAuraModPetTalentsPoints(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModSkill(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // movement + void HandleAuraMounted(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraAllowFlight(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraWaterWalk(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraFeatherFall(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraHover(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleWaterBreathing(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleForceMoveForward(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // threat + void HandleModThreat(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModTotalThreat(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModTaunt(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // control + void HandleModConfuse(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModFear(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModStun(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModRoot(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandlePreventFleeing(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // charm + void HandleModPossess(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModPossessPet(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModCharm(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleCharmConvert(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraControlVehicle(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // modify speed + void HandleAuraModIncreaseSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModIncreaseMountedSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModIncreaseFlightSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModIncreaseSwimSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModDecreaseSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModUseNormalSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // immunity + void HandleModStateImmunityMask(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModMechanicImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModEffectImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModStateImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModSchoolImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModDmgImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModDispelImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // modify stats + // resistance + void HandleAuraModResistanceExclusive(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModBaseResistancePCT(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModResistancePercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModBaseResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModTargetResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // stat + void HandleAuraModStat(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModPercentStat(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModSpellDamagePercentFromStat(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModSpellHealingPercentFromStat(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModSpellDamagePercentFromAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModSpellHealingPercentFromAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModHealingDone(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModTotalPercentStat(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModResistenceOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModExpertise(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // heal and energize + void HandleModPowerRegen(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModPowerRegenPCT(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModManaRegen(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModIncreaseHealth(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModIncreaseMaxHealth(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModIncreaseEnergy(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModIncreaseEnergyPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModIncreaseHealthPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraIncreaseBaseHealthPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // fight + void HandleAuraModParryPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModDodgePercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModBlockPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModRegenInterrupt(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModWeaponCritPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModHitChance(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModSpellHitChance(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModSpellCritChance(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModSpellCritChanceShool(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModCritPct(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // attack speed + void HandleModCastingSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModMeleeRangedSpeedPct(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModCombatSpeedPct(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModAttackSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModRangedHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleRangedAmmoHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // combat rating + void HandleModRating(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModRatingFromStat(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // attack power + void HandleAuraModAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModRangedAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModAttackPowerPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModRangedAttackPowerPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModAttackPowerOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraModAttackPowerOfArmor(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // damage bonus + void HandleModDamageDone(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModDamagePercentDone(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModOffhandDamagePercent(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleShieldBlockValue(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // power cost + void HandleModPowerCostPCT(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleModPowerCost(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleArenaPreparation(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleNoReagentUseAura(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraRetainComboPoints(AuraApplication const * aurApp, uint8 mode, bool apply) const; + // others + void HandleAuraDummy(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleChannelDeathItem(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleBindSight(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleForceReaction(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraEmpathy(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleComprehendLanguage(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraConvertRune(AuraApplication const * aurApp, uint8 mode, bool apply) const; + void HandleAuraLinked(AuraApplication const * aurApp, uint8 mode, bool apply) const; +}; + +#endif
\ No newline at end of file diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 36490425400..19d484c0a4b 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -19,1664 +19,469 @@ */ #include "Common.h" -#include "Database/DatabaseEnv.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "Opcodes.h" #include "Log.h" -#include "UpdateMask.h" -#include "World.h" #include "ObjectMgr.h" #include "SpellMgr.h" #include "Player.h" #include "Unit.h" #include "Spell.h" +#include "SpellAuraEffects.h" #include "SpellId.h" #include "DynamicObject.h" -#include "Group.h" -#include "UpdateData.h" #include "ObjectAccessor.h" -#include "Policies/SingletonImp.h" -#include "Totem.h" -#include "Creature.h" -#include "Formulas.h" -#include "BattleGround.h" -#include "OutdoorPvP.h" -#include "OutdoorPvPMgr.h" -#include "CreatureAI.h" -#include "ScriptCalls.h" #include "Util.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" -#include "Vehicle.h" #include "CellImpl.h" -#define Aura AuraEffect -pAuraHandler AuraHandler[TOTAL_AURAS]= +AuraApplication::AuraApplication(Unit * target, Unit * caster, Aura * aura) + : m_target(target), m_base(aura), m_slot(MAX_AURAS), m_flags(AFLAG_NONE), m_needClientUpdate(false), m_removeMode(AURA_REMOVE_NONE), m_canBeRemoved(false) { - &Aura::HandleNULL, // 0 SPELL_AURA_NONE - &Aura::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT - &Aura::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS - &Aura::HandlePeriodicDamage, // 3 SPELL_AURA_PERIODIC_DAMAGE - &Aura::HandleAuraDummy, // 4 SPELL_AURA_DUMMY - &Aura::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE - &Aura::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM - &Aura::HandleModFear, // 7 SPELL_AURA_MOD_FEAR - &Aura::HandlePeriodicHeal, // 8 SPELL_AURA_PERIODIC_HEAL - &Aura::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED - &Aura::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT - &Aura::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT - &Aura::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN - &Aura::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE - &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus - &Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage - &Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH - &Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT - &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY - &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION - &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH - &Aura::HandleAuraModTotalEnergyPercentRegen, // 21 SPELL_AURA_OBS_MOD_POWER - &Aura::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE - &Aura::HandlePeriodicTriggerSpell, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL - &Aura::HandlePeriodicEnergize, // 24 SPELL_AURA_PERIODIC_ENERGIZE - &Aura::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY - &Aura::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT - &Aura::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE - &Aura::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult - &Aura::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT - &Aura::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL - &Aura::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED - &Aura::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED - &Aura::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED - &Aura::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH - &Aura::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY - &Aura::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT - &Aura::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY - &Aura::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY - &Aura::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY - &Aura::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY - &Aura::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY - &Aura::HandleAuraProcTriggerSpell, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell - &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor - &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES - &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES - &Aura::HandleNULL, // 46 SPELL_AURA_46 (used in test spells 54054 and 54058, and spell 48050) (3.0.8a) - &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT - &Aura::HandleNULL, // 48 SPELL_AURA_48 spell Napalm (area damage spell with additional delayed damage effect) - &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT - &Aura::HandleNoImmediateEffect, // 50 SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT implemented in Unit::SpellCriticalHealingBonus - &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT - &Aura::HandleAuraModWeaponCritPercent, // 52 SPELL_AURA_MOD_WEAPON_CRIT_PERCENT - &Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH - &Aura::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE - &Aura::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE - &Aura::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM - &Aura::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE - &Aura::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED - &Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus - &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE - &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE - &Aura::HandlePeriodicHealthFunnel, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL - &Aura::HandleNULL, // 63 unused (3.0.8a) old SPELL_AURA_PERIODIC_MANA_FUNNEL - &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH - &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK - &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH - &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM - &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED - &Aura::HandleNoImmediateEffect, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist - &Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect - &Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL - &Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT - &Aura::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL - &Aura::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult - &Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE - &Aura::HandleFarSight, // 76 SPELL_AURA_FAR_SIGHT - &Aura::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY - &Aura::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED - &Aura::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE - &Aura::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT - &Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT - &Aura::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING - &Aura::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE - &Aura::HandleModRegen, // 84 SPELL_AURA_MOD_REGEN - &Aura::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN - &Aura::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM - &Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus - &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT - &Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT - &Aura::HandleUnused, // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE - &Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance - &Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING - &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE - &Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll - &Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST - &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Unit::SelectMagnetTarget - &Aura::HandleNoImmediateEffect, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist - &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT - &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER - &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now, but still have spells including GM-spell - &Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT - &Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus - &Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT - &Aura::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK - &Aura::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL - &Aura::HandleAuraHover, //106 SPELL_AURA_HOVER - &Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER - &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER - &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER - &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT - &Aura::HandleNoImmediateEffect, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER implemented in Unit::SelectMagnetTarget - &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS - &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim - &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT - &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus - &Aura::HandleUnused, //119 unused (3.0.8a) old SPELL_AURA_SHARE_PET_TRACKING - &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE - &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY - &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT - &Aura::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE - &Aura::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER - &Aura::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus - &Aura::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET - &Aura::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS - &Aura::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS - &Aura::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus - &Aura::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT - &Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT - &Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT - &Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE - &Aura::HandleNoImmediateEffect, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus - &Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE - &Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE - &Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION - &Aura::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE - &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE - &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT - &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE - &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes - &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS - &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE - &Aura::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK - &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS - &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK - &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT - &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED - &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance - &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT - &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL - &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING - &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN - &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI - &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE - &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell - &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT - &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA - &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE - &Aura::HandleUnused, //164 unused (3.0.8a), only one test spell - &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus - &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT - &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT - &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus - &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE various spells that change visual of units for aura target (clientside?) - &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK - &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK - &Aura::HandleUnused, //173 unused (3.0.8a) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell - &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus - &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus - &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end - &Aura::HandleCharmConvert, //177 SPELL_AURA_AOE_CHARM - &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus - &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus - &Aura::HandleUnused, //181 unused (3.0.8a) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS - &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT - &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 - miscvalue - spell school - &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance - &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance - &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING - &Aura::HandleNoImmediateEffect, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN implemented in Player::CalculateReputationGain - &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED - &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE - &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) - &Aura::HandleNoImmediateEffect, //194 SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist - &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist - &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN - flat mod of spell cooldowns - &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance - &Aura::HandleUnused, //198 unused (3.0.8a) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS - &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::RewardPlayerAndGroupAtKill - &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode... - &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst - &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage - &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage - &Aura::HandleNoImmediateEffect, //205 SPELL_AURA_MOD_SCHOOL_CRIT_DMG_TAKEN - &Aura::HandleAuraModIncreaseFlightSpeed, //206 SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED - &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED - &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED - &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS - &Aura::HandleAuraModIncreaseFlightSpeed, //210 SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS - &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK - &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT - &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage - &Aura::HandleNULL, //214 Tamed Pet Passive - &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION - &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS - &Aura::HandleUnused, //217 unused (3.0.8a) - &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED - &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT - &Aura::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT - &Aura::HandleNULL, //221 SPELL_AURA_MOD_DETAUNT - &Aura::HandleUnused, //222 unused (3.0.8a) only for spell 44586 that not used in real spell cast - &Aura::HandleNoImmediateEffect, //223 SPELL_AURA_RAID_PROC_FROM_CHARGE - &Aura::HandleUnused, //224 unused (3.0.8a) - &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE - &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY - &Aura::HandlePeriodicTriggerSpellWithValue, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE - &Aura::HandleNoImmediateEffect, //228 SPELL_AURA_DETECT_STEALTH stealth detection - &Aura::HandleNoImmediateEffect, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE - &Aura::HandleAuraModIncreaseHealth, //230 SPELL_AURA_MOD_INCREASE_HEALTH_2 - &Aura::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE - &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration - &Aura::HandleUnused, //233 set model id to the one of the creature with id GetMiscValue() - clientside - &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration - &Aura::HandleNoImmediateEffect, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult - &Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE - &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus - &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus - &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61 - &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE - &Aura::HandleForceMoveForward, //241 SPELL_AURA_FORCE_MOVE_FORWARD Forces the player to move forward - &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING - 2 test spells: 44183 and 44182 - &Aura::HandleNULL, //243 faction reaction override spells - &Aura::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE - &Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL - &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura - &Aura::HandleAuraCloneCaster, //247 SPELL_AURA_CLONE_CASTER - &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE - &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2 - &Aura::HandleNoImmediateEffect, //251 SPELL_AURA_MOD_ENEMY_DODGE - &Aura::HandleModCombatSpeedPct, //252 SPELL_AURA_252 Is there any difference between this and SPELL_AURA_MELEE_SLOW ? maybe not stacking mod? - &Aura::HandleNoImmediateEffect, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE implemented in Unit::isBlockCritical - &Aura::HandleAuraModDisarm, //254 SPELL_AURA_MOD_DISARM_OFFHAND - &Aura::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus - &Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select - &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select - &Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL - &Aura::HandleNoImmediateEffect, //259 SPELL_AURA_MOD_HOT_PCT implemented in Unit::SpellHealingBonus - &Aura::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code - &Aura::HandlePhase, //261 SPELL_AURA_PHASE undetactable invisibility? implemented in Unit::isVisibleForOrDetect - &Aura::HandleNoImmediateEffect, //262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in spell::cancast - &Aura::HandleAuraAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask - &Aura::HandleUnused, //264 unused (3.0.8a) - &Aura::HandleUnused, //265 unused (3.0.8a) - &Aura::HandleUnused, //266 unused (3.0.8a) - &Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect - &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT - &Aura::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage - &Aura::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage - &Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus - &Aura::HandleNULL, //272 unknown - &Aura::HandleNoImmediateEffect, //273 SPELL_AURA_X_RAY (client side implementation) - &Aura::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets - &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select - &Aura::HandleNULL, //276 mod damage % mechanic? - &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap - &Aura::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon - &Aura::HandleAuraInitializeImages, //279 SPELL_AURA_INITIALIZE_IMAGES - &Aura::HandleNoImmediateEffect, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT - &Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor - &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT - &Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus - &Aura::HandleAuraLinked, //284 SPELL_AURA_LINKED 51 spells using - &Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage - &Aura::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in AuraEffect::PeriodicTick - &Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult - &Aura::HandleNoImmediateEffect, //288 SPELL_AURA_IGNORE_HIT_DIRECTION implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst - &Aura::HandleUnused, //289 unused (3.2.2a) - &Aura::HandleAuraModCritPct, //290 SPELL_AURA_MOD_CRIT_PCT - &Aura::HandleNoImmediateEffect, //291 SPELL_AURA_MOD_XP_QUEST_PCT implemented in Player::RewardQuest - &Aura::HandleNULL, //292 call stabled pet - &Aura::HandleNULL, //293 2 test spells - &Aura::HandleNoImmediateEffect, //294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power) - &Aura::HandleNULL, //295 unused - &Aura::HandleNULL, //296 2 spells - &Aura::HandleNULL, //297 1 spell (counter spell school?) - &Aura::HandleNULL, //298 unused - &Aura::HandleNULL, //299 unused - &Aura::HandleNULL, //300 3 spells (share damage?) - &Aura::HandleNULL, //301 5 spells - &Aura::HandleNULL, //302 unused - &Aura::HandleNULL, //303 17 spells - &Aura::HandleAuraModInebriation, //304 2 spells - &Aura::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED - &Aura::HandleNULL //306 1 spell -}; -#undef Aura - -Aura::Aura(SpellEntry const* spellproto, uint32 effMask, Unit *target, WorldObject *source, Unit *caster, int32 *currentBasePoints, Item* castItem) : - m_spellProto(spellproto), - m_target(target), m_sourceGuid(source->GetGUID()), m_casterGuid(caster->GetGUID()), m_castItemGuid(castItem ? castItem->GetGUID() : 0), - m_applyTime(time(NULL)), - m_timeCla(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE), - m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1), m_isRemoved(false) -{ - assert(target); - assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element"); - - m_auraFlags = effMask; - - if(m_spellProto->manaPerSecond || m_spellProto->manaPerSecondPerLevel) - m_timeCla = 1000; - - m_isPassive = IsPassiveSpell(GetId()); - - m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto); - - //damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target); - m_maxduration = caster->CalcSpellDuration(m_spellProto); - - if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0) - m_permanent = true; - else - m_permanent = false; - - Player* modOwner = caster->GetSpellModOwner(); - - if(!m_permanent && modOwner) - { - modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration); - // Get zero duration aura after - need set m_maxduration > 0 for apply/remove aura work - if (m_maxduration<=0) - m_maxduration = 1; - } - - m_duration = m_maxduration; - - m_isDeathPersist = IsDeathPersistentSpell(m_spellProto); - - m_procCharges = m_spellProto->procCharges; - if(modOwner) - modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); + assert(GetTarget() && GetBase()); - m_isRemovedOnShapeLost = (caster == target && - m_spellProto->Stances && - !(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && - !(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT)); - - for (uint8 i=0 ; i<MAX_SPELL_EFFECTS; ++i) + if(GetBase()->IsVisible()) { - if (m_auraFlags & (uint8(1) << i)) + // Try find slot for aura + uint8 slot = MAX_AURAS; + // Lookup for auras already applied from spell + if (AuraApplication * foundAura = m_target->GetAuraApplication(m_base->GetId(), m_base->GetCasterGUID())) { - if(!(m_partAuras[i] = CreateAuraEffect(this, i, currentBasePoints ? currentBasePoints + i : NULL))) - m_auraFlags &= uint8(~(1<< i)); // correct flags if aura couldn't be created + // allow use single slot only by auras from same caster + slot = foundAura->GetSlot(); } else { - m_partAuras[i] = NULL; + Unit::VisibleAuraMap const * visibleAuras = m_target->GetVisibleAuras(); + // lookup for free slots in units visibleAuras + Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(0); + for (uint32 freeSlot = 0; freeSlot < MAX_AURAS; ++itr , ++freeSlot) + { + if(itr == visibleAuras->end() || itr->first != freeSlot) + { + slot = freeSlot; + break; + } + } } - } - // Aura is positive when it is casted by friend and at least one aura is positive - // or when it is casted by enemy and at least one aura is negative - bool swap = false; - if (caster == target) // caster == target - 1 negative effect is enough for aura to be negative - m_positive = false; - else - m_positive = !caster->IsHostileTo(m_target); - - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if((1<<i & GetEffectMask()) && m_positive == IsPositiveEffect(GetId(), i)) + // Register Visible Aura + if(slot < MAX_AURAS) { - swap = true; - break; + m_slot = slot; + m_target->SetVisibleAura(slot, this); + SetNeedClientUpdate(); + sLog.outDebug("Aura: %u Effect: %d put to unit visible auras slot: %u", GetBase()->GetId(), GetEffectMask(), slot); } + else + sLog.outDebug("Aura: %u Effect: %d could not find empty unit visible slot", GetBase()->GetId(), GetEffectMask()); } - if (!swap) - m_positive = !m_positive; -} + m_flags |= (_CheckPositive(caster) ? AFLAG_POSITIVE : AFLAG_NEGATIVE) | + (GetBase()->GetCasterGUID() == GetTarget()->GetGUID() ? AFLAG_CASTER : AFLAG_NONE); -Aura::~Aura() -{ - // free part auras memory - for (uint8 i=0 ; i<MAX_SPELL_EFFECTS; ++i) - if (m_partAuras[i]) - delete m_partAuras[i]; + m_isNeedManyNegativeEffects = false; + if (GetBase()->GetCasterGUID() == GetTarget()->GetGUID()) // caster == target - 1 negative effect is enough for aura to be negative + m_isNeedManyNegativeEffects = false; + else if (caster) + m_isNeedManyNegativeEffects = caster->IsFriendlyTo(m_target); } -AuraEffect::AuraEffect(Aura *parentAura, uint8 effIndex, int32 *currentBasePoints) : -m_parentAura(parentAura), m_spellmod(NULL), m_periodicTimer(0), m_isPeriodic(false), m_isAreaAura(false), m_isPersistent(false), -m_target(parentAura->GetTarget()), m_tickNumber(0) -, m_spellProto(parentAura->GetSpellProto()), m_effIndex(effIndex), m_auraName(AuraType(m_spellProto->EffectApplyAuraName[m_effIndex])) +void AuraApplication::_Remove() { - assert(m_auraName < TOTAL_AURAS); - - if(currentBasePoints) - m_currentBasePoints = *currentBasePoints; - else - m_currentBasePoints = m_spellProto->EffectBasePoints[m_effIndex]; - - Unit *caster = GetParentAura()->GetCaster(); - if(caster) - m_amount = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); - else - m_amount = m_currentBasePoints + m_spellProto->EffectBaseDice[m_effIndex]; + uint8 slot = GetSlot(); - if (int32 amount = CalculateCrowdControlAuraAmount(caster)) - m_amount = amount; + if (slot >= MAX_AURAS) + return; - if(!m_amount && caster) - if(uint64 itemGUID = GetParentAura()->GetCastItemGUID()) - if(Player *playerCaster = dynamic_cast<Player*>(caster)) - if(Item *castItem = playerCaster->GetItemByGuid(itemGUID)) - if (castItem->GetItemSuffixFactor()) + if (AuraApplication * foundAura = m_target->GetAuraApplication(GetBase()->GetId(), GetBase()->GetCasterGUID())) { - ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId())); - if(item_rand_suffix) + // Reuse visible aura slot by aura which is still applied - prevent storing dead pointers + if (slot == foundAura->GetSlot()) { - for (int k=0; k<3; k++) + if (GetTarget()->GetVisibleAura(slot) == this) { - SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]); - if(pEnchant) - { - for (int t=0; t<3; t++) - if(pEnchant->spellid[t] == m_spellProto->Id) - { - m_amount = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 ); - break; - } - } - - if(m_amount) - break; + GetTarget()->SetVisibleAura(slot, foundAura); + foundAura->SetNeedClientUpdate(); } + // set not valid slot for aura - prevent removing other visible aura + slot = MAX_AURAS; } } - Player* modOwner = caster ? caster->GetSpellModOwner() : NULL; - m_amplitude = m_spellProto->EffectAmplitude[m_effIndex]; - - //apply casting time mods for channeled spells - if (modOwner && m_amplitude && IsChanneledSpell(m_spellProto)) - modOwner->ModSpellCastTime(m_spellProto, m_amplitude); - - // Apply periodic time mod - if(modOwner && m_amplitude) - modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_amplitude); - - // Start periodic on next tick or at aura apply - if (!(m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY)) - m_periodicTimer += m_amplitude; - - m_isApplied = false; + // update for out of range group members + if (slot < MAX_AURAS) + { + GetTarget()->RemoveVisibleAura(slot); + ClientUpdate(true); + } } -AreaAuraEffect::AreaAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints) -: AuraEffect(parentAura, effIndex, currentBasePoints) +bool AuraApplication::_CheckPositive(Unit * caster) const { - m_removeTime = FRIENDLY_AA_REMOVE_TIME; - m_isAreaAura = true; - - if (m_spellProto->Effect[effIndex] == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY) - m_radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); - else - m_radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); - - Unit *source = GetSource(); - assert(source); - if(Player* modOwner = source->GetSpellModOwner()) // source or caster? should be the same - modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius); + // Aura is positive when it is casted by friend and at least one aura is positive + // or when it is casted by enemy and at least one aura is negative - switch(m_spellProto->Effect[effIndex]) + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: - m_areaAuraType = AREA_AURA_PARTY; - if(m_target->GetTypeId() == TYPEID_UNIT && ((Creature*)m_target)->isTotem()) - *const_cast<AuraType*>(&m_auraName) = SPELL_AURA_NONE; - break; - case SPELL_EFFECT_APPLY_AREA_AURA_RAID: - m_areaAuraType = AREA_AURA_RAID; - if(m_target->GetTypeId() == TYPEID_UNIT && ((Creature*)m_target)->isTotem()) - *const_cast<AuraType*>(&m_auraName) = SPELL_AURA_NONE; - break; - case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: - m_areaAuraType = AREA_AURA_FRIEND; - break; - case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: - m_areaAuraType = AREA_AURA_ENEMY; - if(m_target == source) - *const_cast<AuraType*>(&m_auraName) = SPELL_AURA_NONE; // Do not do any effect on self - break; - case SPELL_EFFECT_APPLY_AREA_AURA_PET: - m_areaAuraType = AREA_AURA_PET; - break; - case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: - m_areaAuraType = AREA_AURA_OWNER; - if(m_target == source) - *const_cast<AuraType*>(&m_auraName) = SPELL_AURA_NONE; - break; - default: - sLog.outError("Wrong spell effect in AreaAura constructor"); - ASSERT(false); - break; + if((1<<i & GetEffectMask())) + { + if (m_isNeedManyNegativeEffects == IsPositiveEffect(GetBase()->GetId(), i)) + return m_isNeedManyNegativeEffects; + } } + return !m_isNeedManyNegativeEffects; } -PersistentAreaAuraEffect::PersistentAreaAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints) -: AuraEffect(parentAura, effIndex, currentBasePoints) +void AuraApplication::_HandleEffect(uint8 effIndex, bool apply) { - m_isPersistent = true; -} + AuraEffect * aurEff = GetBase()->GetEffect(effIndex); + assert(aurEff); + assert(HasEffect(effIndex) == (!apply)); + sLog.outDebug("AuraApplication::_HandleEffect: %u, apply: %u: amount: %u", aurEff->GetAuraType(), apply, aurEff->GetAmount()); -DynamicObject *PersistentAreaAuraEffect::GetSource() const -{ - uint64 guid = GetParentAura()->GetSourceGUID(); - if(IS_DYNAMICOBJECT_GUID(guid)) - return ObjectAccessor::GetObjectInWorld(guid, (DynamicObject*)NULL); - return NULL; -} + Unit * caster = GetBase()->GetCaster(); + m_flags &= ~(AFLAG_POSITIVE | AFLAG_NEGATIVE); -AuraEffect* CreateAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints) -{ - // TODO: source should belong to aura, but not areaeffect. multiple areaaura/persistent aura should use one source - assert(parentAura); - uint64 sourceGuid = parentAura->GetSourceGUID(); - //assert(source); - if (IsAreaAuraEffect(parentAura->GetSpellProto()->Effect[effIndex])) + if (apply) { - //assert(source->isType(TYPEMASK_UNIT)); - assert(IS_UNIT_GUID(sourceGuid)); - if(!parentAura->GetUnitSource()) - { - // TODO: there is a crash here when a new aura is added by source aura update, confirmed - sLog.outCrash("CreateAuraEffect: cannot find source " I64FMT " in world for spell %u", sourceGuid, parentAura->GetId()); - return NULL; - } - return new AreaAuraEffect(parentAura, effIndex, currentBasePoints); + m_flags |= 1<<effIndex; + m_flags |=_CheckPositive(caster) ? AFLAG_POSITIVE : AFLAG_NEGATIVE; + GetTarget()->_HandleAuraEffect(aurEff, true); + aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, true); } - else if (parentAura->GetSpellProto()->Effect[effIndex] == SPELL_EFFECT_APPLY_AURA) - return new AuraEffect(parentAura, effIndex, currentBasePoints); - else if (parentAura->GetSpellProto()->Effect[effIndex] == SPELL_EFFECT_PERSISTENT_AREA_AURA) + else { - //assert(source->isType(TYPEMASK_DYNAMICOBJECT)); - // TODO: creature addon or save? may add persistent AA without correct source - if(IS_DYNAMICOBJECT_GUID(sourceGuid)) - return new PersistentAreaAuraEffect(parentAura, effIndex, currentBasePoints); - } - return NULL; -} + m_flags &= ~(1<<effIndex); + m_flags |=_CheckPositive(caster) ? AFLAG_POSITIVE : AFLAG_NEGATIVE; -Unit* Aura::GetCaster() const -{ - if(m_casterGuid == m_target->GetGUID()) - return m_target; + // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) + GetTarget()->_HandleAuraEffect(aurEff, false); + aurEff->HandleEffect(this, AURA_EFFECT_HANDLE_REAL, false); - //return ObjectAccessor::GetUnit(*m_target,m_casterGuid); - //must return caster even if it's in another grid/map - return ObjectAccessor::GetObjectInWorld(m_casterGuid, (Unit*)NULL); + // Remove all triggered by aura spells vs unlimited duration + aurEff->CleanupTriggeredSpells(GetTarget()); + } + SetNeedClientUpdate(); } -Unit* Aura::GetUnitSource() const +void AuraApplication::ClientUpdate(bool remove) { - if(m_sourceGuid == m_target->GetGUID()) - return m_target; + m_needClientUpdate = false; - return ObjectAccessor::GetObjectInWorld(m_sourceGuid, (Unit*)NULL); -} - -void Aura::Update(uint32 diff) -{ - // TODO: store pointer to caster in aura class for update/mod handling code + WorldPacket data(SMSG_AURA_UPDATE); + data.append(GetTarget()->GetPackGUID()); + data << uint8(m_slot); - if (m_duration > 0) + if(remove) { - m_duration -= diff; - if (m_duration < 0) - m_duration = 0; - - // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0 - if(m_timeCla) - { - if(m_timeCla > diff) - m_timeCla -= diff; - else if(Unit* caster = GetCaster()) - { - if(int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel()) - { - m_timeCla += 1000 - diff; - - Powers powertype = Powers(m_spellProto->powerType); - if(powertype == POWER_HEALTH) - { - if (caster->GetHealth() > manaPerSecond) - caster->ModifyHealth(-manaPerSecond); - else - { - m_target->RemoveAura(this); - return; - } - } - else - { - if (caster->GetPower(powertype) >= manaPerSecond) - caster->ModifyPower(powertype, -manaPerSecond); - else - { - m_target->RemoveAura(this); - return; - } - } - } - } - } + assert(!m_target->GetVisibleAura(m_slot)); + data << uint32(0); + sLog.outDebug("Aura %u removed slot %u",GetBase()->GetId(), m_slot); + m_target->SendMessageToSet(&data, true); + return; } + assert(m_target->GetVisibleAura(m_slot)); - // Apply charged spellmods for channeled auras - // used for example when triggered spell of spell:10 is modded - Spell *modSpell = NULL; - Player *modOwner = NULL; - if(IS_PLAYER_GUID(GetCasterGUID()) && (modOwner = (Player*)GetCaster()) - && (modSpell = modOwner->FindCurrentSpellBySpellId(GetId()))) - modOwner->SetSpellModTakingSpell(modSpell, true); - - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if (m_partAuras[i]) - m_partAuras[i]->Update(diff); + Aura const * aura = GetBase(); + data << uint32(aura->GetId()); + uint32 flags = m_flags; + if (aura->GetMaxDuration() > 0) + flags |= AFLAG_DURATION; + data << uint8(flags); + data << uint8(aura->GetCasterLevel()); + data << uint8(aura->GetStackAmount() > 1 ? aura->GetStackAmount() : (aura->GetCharges()) ? aura->GetCharges() : 1); - if (modOwner) - modOwner->SetSpellModTakingSpell(modSpell, false); -} + if(!(flags & AFLAG_CASTER)) + data.appendPackGUID(aura->GetCasterGUID()); -void AuraEffect::Update(uint32 diff) -{ - if (m_isPeriodic && (GetParentAura()->GetAuraDuration() >=0 || GetParentAura()->IsPassive() || GetParentAura()->IsPermanent())) + if(flags & AFLAG_DURATION) { - if(m_periodicTimer > diff) - m_periodicTimer -= diff; - else // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N - { - ++m_tickNumber; - - // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls) - m_periodicTimer += m_amplitude - diff; - - if(!m_target->hasUnitState(UNIT_STAT_ISOLATED)) - PeriodicTick(); - } + data << uint32(aura->GetMaxDuration()); + data << uint32(aura->GetDuration()); } + + m_target->SendMessageToSet(&data, true); } -void AreaAuraEffect::Update(uint32 diff) +Aura * Aura::TryCreate(SpellEntry const* spellproto, uint8 tryEffMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID) { - // update for the source of the aura - if(GetParentAura()->GetSourceGUID() == m_target->GetGUID()) + assert(spellproto); + assert(owner); + assert(caster || casterGUID); + assert(tryEffMask <= MAX_EFFECT_MASK); + uint8 effMask = 0; + switch(owner->GetTypeId()) { - Unit *source = m_target; - Unit *caster = GetCaster(); - if (!caster) - { - m_target->RemoveAura(GetParentAura()); - return; - } - - if( !source->hasUnitState(UNIT_STAT_ISOLATED) ) - { - std::list<Unit *> targets; - - switch(m_areaAuraType) + case TYPEID_UNIT: + case TYPEID_PLAYER: + for(uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) { - case AREA_AURA_PARTY: - source->GetPartyMemberInDist(targets, m_radius); - break; - case AREA_AURA_RAID: - source->GetRaidMember(targets, m_radius); - break; - case AREA_AURA_FRIEND: - { - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(source, caster, m_radius); - Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(source, targets, u_check); - source->VisitNearbyObject(m_radius, searcher); - break; - } - case AREA_AURA_ENEMY: - { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(source, caster, m_radius); // No GetCharmer in searcher - Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(source, targets, u_check); - source->VisitNearbyObject(m_radius, searcher); - break; - } - case AREA_AURA_OWNER: - case AREA_AURA_PET: - { - if(Unit *owner = caster->GetCharmerOrOwner()) - if (caster->IsWithinDistInMap(owner, m_radius)) - targets.push_back(owner); - break; - } + if (IsUnitOwnedAuraEffect(spellproto->Effect[i])) + effMask |= 1 << i; } - - for (std::list<Unit*>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++) + break; + case TYPEID_DYNAMICOBJECT: + for(uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) { - if(Aura *aur = (*tIter)->GetAura(GetId(), GetCasterGUID())) - { - if(aur->HasEffect(GetEffIndex())) - continue; - } - else - { - bool skip = false; - for (Unit::AuraMap::iterator iter = (*tIter)->GetAuras().begin(); iter != (*tIter)->GetAuras().end(); ++iter) - { - if(!spellmgr.CanAurasStack(GetSpellProto(), iter->second->GetSpellProto(), iter->second->GetCasterGUID() == GetCasterGUID())) - { - skip = true; - break; - } - } - if(skip) - continue; - } - - // Select lower rank of aura if needed - if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel())) - { - int32 newBp = m_currentBasePoints; - // Check if basepoints can be safely reduced - if (newBp == m_spellProto->EffectBasePoints[m_effIndex]) - newBp = actualSpellInfo->EffectBasePoints[m_effIndex]; - (*tIter)->AddAuraEffect(actualSpellInfo, GetEffIndex(), source, caster, &newBp); - - if(m_areaAuraType == AREA_AURA_ENEMY) - caster->CombatStart(*tIter); - } + if (spellproto->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA) + effMask |= 1 << i; } - } - AuraEffect::Update(diff); + break; } - else // aura at non-caster - { - // WARNING: the aura may get deleted during the update - // DO NOT access its members after update! - AuraEffect::Update(diff); - - // Speedup - no need to do more checks - if (GetParentAura()->IsRemoved()) - return; - - // Caster may be deleted due to update - Unit *caster = GetCaster(); - Unit *source = GetSource(); + if (uint8 realMask = effMask & tryEffMask) + return Create(spellproto,realMask,owner,caster,baseAmount,castItem,casterGUID); + return NULL; +} - // remove aura if out-of-range from caster (after teleport for example) - // or caster is isolated or caster no longer has the aura - // or caster is (no longer) friendly - bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true); - if( !source || !caster || - source->hasUnitState(UNIT_STAT_ISOLATED) || !source->HasAuraEffect(GetId(), m_effIndex) || - caster->IsFriendlyTo(m_target) != needFriendly - ) - { - m_target->RemoveAura(GetParentAura()); - } - else if (!source->IsWithinDistInMap(m_target, m_radius)) - { - if (needFriendly && source->isMoving()) - { - m_removeTime -= diff; - if (m_removeTime < 0) - m_target->RemoveAura(GetParentAura()); - } - else - m_target->RemoveAura(GetParentAura()); - } - else - { - // Reset aura remove timer - m_removeTime = FRIENDLY_AA_REMOVE_TIME; - if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group - { - if(!m_target->IsInPartyWith(caster)) - m_target->RemoveAura(GetParentAura()); - } - else if( m_areaAuraType == AREA_AURA_RAID) +Aura * Aura::TryCreate(SpellEntry const* spellproto, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID) +{ + assert(spellproto); + assert(owner); + assert(caster || casterGUID); + uint8 effMask = 0; + switch(owner->GetTypeId()) + { + case TYPEID_UNIT: + case TYPEID_PLAYER: + for(uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) { - if(!m_target->IsInRaidWith(caster)) - m_target->RemoveAura(GetParentAura()); + if (IsUnitOwnedAuraEffect(spellproto->Effect[i])) + effMask |= 1 << i; } - else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) + break; + case TYPEID_DYNAMICOBJECT: + for(uint8 i = 0; i< MAX_SPELL_EFFECTS; ++i) { - if( m_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) - m_target->RemoveAura(GetParentAura()); + if (spellproto->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA) + effMask |= 1 << i; } - } + break; } + if (effMask) + return Create(spellproto,effMask,owner,caster,baseAmount,castItem,casterGUID); + return NULL; } -void PersistentAreaAuraEffect::Update(uint32 diff) +Aura * Aura::Create(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID) { - /* - if(Unit *caster = GetParentAura()->GetCaster()) - { - if(DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex())) - { - if(m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius())) - { - AuraEffect::Update(diff); - return; - } - } - } - */ - if(DynamicObject *dynObj = GetSource()) + assert(effMask); + assert(spellproto); + assert(owner); + assert(caster || casterGUID); + assert(effMask <= MAX_EFFECT_MASK); + switch(owner->GetTypeId()) { - if(m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius())) - { - AuraEffect::Update(diff); - return; - } + case TYPEID_UNIT: + case TYPEID_PLAYER: + return new UnitAura(spellproto,effMask,owner,caster,baseAmount,castItem, casterGUID); + case TYPEID_DYNAMICOBJECT: + return new DynObjAura(spellproto,effMask,owner,caster,baseAmount,castItem, casterGUID); + default: + assert(false); + return NULL; } - - // remove the aura if its caster or the dynamic object causing it was removed - // or if the target moves too far from the dynamic object - m_target->RemoveAura(GetParentAura()); } -void AuraEffect::ApplyModifier(bool apply, bool Real, bool changeAmount) +Aura::Aura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID) : +m_spellProto(spellproto), m_owner(owner), m_casterGuid(casterGUID ? casterGUID : caster->GetGUID()), m_castItemGuid(castItem ? castItem->GetGUID() : 0), + m_applyTime(time(NULL)), m_timeCla(0), + m_procCharges(0), m_stackAmount(1), m_isRemoved(false), m_casterLevel(caster ? caster->getLevel() : m_spellProto->spellLevel) { - if (GetParentAura()->IsRemoved()) - return; - - if (apply) - HandleAuraEffectSpecificMods(true, Real, changeAmount); - - (*this.*AuraHandler [m_auraName])(apply,Real, changeAmount); + if(m_spellProto->manaPerSecond || m_spellProto->manaPerSecondPerLevel) + m_timeCla = 1 * IN_MILISECONDS; - if (!apply) - HandleAuraEffectSpecificMods(false, Real, changeAmount); -} + Player* modOwner = NULL; -void AuraEffect::RecalculateAmount(bool applied) -{ - Unit *caster = GetParentAura()->GetCaster(); - int32 amount = GetParentAura()->GetStackAmount() * (caster ? (caster->CalculateSpellDamage(m_spellProto, GetEffIndex(), GetBasePoints(), NULL)) : (m_currentBasePoints + m_spellProto->EffectBaseDice[m_effIndex])); - // Reapply if amount change - if (amount!=GetAmount()) + if (caster) { - // Auras which are applying spellmod should have removed spellmods for real - if (applied) - ApplyModifier(false,false,true); - SetAmount(amount); - if (applied) - ApplyModifier(true,false,true); + modOwner = caster->GetSpellModOwner(); + m_maxDuration = caster->CalcSpellDuration(m_spellProto); } -} + else + m_maxDuration = GetSpellDuration(m_spellProto); -void AuraEffect::CleanupTriggeredSpells() -{ - uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; - if(!tSpellId) - return; + if(IsPassive() && m_spellProto->DurationIndex == 0) + m_maxDuration = -1; - SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId); - if(!tProto) - return; + if(!IsPermanent() && modOwner) + modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxDuration); - if(GetSpellDuration(tProto) != -1) - return; + m_duration = m_maxDuration; - // needed for spell 43680, maybe others - // TODO: is there a spell flag, which can solve this in a more sophisticated way? - if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && - GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()]) - return; + m_procCharges = m_spellProto->procCharges; + if(modOwner) + modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); - m_target->RemoveAurasDueToSpell(tSpellId, GetCasterGUID()); -} + for (uint8 i=0 ; i<MAX_SPELL_EFFECTS; ++i) + { + if (effMask & (uint8(1) << i)) + m_effects[i] = new AuraEffect(this, i, baseAmount ? baseAmount + i : NULL, caster); + else + m_effects[i] = NULL; + } -void Aura::ApplyAllModifiers(bool apply, bool Real) -{ - for (uint8 i = 0; i<MAX_SPELL_EFFECTS; ++i) - if (m_partAuras[i]) - m_partAuras[i]->ApplyModifier(apply, Real); + m_isSingleTarget = IsSingleTargetSpell(GetSpellProto()); } -void Aura::HandleAuraSpecificMods(bool apply) +Aura::~Aura() { - //************************************************************************************** - // Function called after applying all mods from aura or after removing all mods from it - //************************************************************************************** + // free effects memory + for (uint8 i = 0 ; i < MAX_SPELL_EFFECTS; ++i) + if (m_effects[i]) + delete m_effects[i]; - //******************** - // MODS AT AURA APPLY - //******************** - if (apply) - { - // Update auras for specific phase - if(IsAuraType(SPELL_AURA_PHASE)) - { - SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); - if(saBounds.first != saBounds.second) - { - uint32 zone, area; - m_target->GetZoneAndAreaId(zone,area); - - for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - { - // some auras remove at aura remove - if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area)) - m_target->RemoveAurasDueToSpell(itr->second->spellId); - // some auras applied at aura apply - else if(itr->second->autocast) - { - if( !m_target->HasAura(itr->second->spellId) ) - m_target->CastSpell(m_target,itr->second->spellId,true); - } - } - } - } + assert(m_applications.empty()); + _DeleteRemovedApplications(); +} - if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE) - { - if (m_spellProto->SpellFamilyFlags[1] & 0x00000002 && m_spellProto->SpellFamilyFlags[2] & 0x00000008) - { - // Arcane Potency - if (Unit * caster = GetCaster()) - { - if (AuraEffect* aureff = caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_MAGE, 2120, 0)) - { - if (roll_chance_i(aureff->GetAmount())) - { - uint32 spell_id = 0; +Unit* Aura::GetCaster() const +{ + if (GetOwner()->GetGUID() == GetCasterGUID()) + return GetUnitOwner(); + if(AuraApplication const * aurApp = GetApplicationOfTarget(GetCasterGUID())) + return aurApp->GetTarget(); - switch (aureff->GetId()) - { - case 31571: spell_id = 57529; break; - case 31572: spell_id = 57531; break; - default: return; - } - if(spell_id) - caster->CastSpell(caster,spell_id,true); - } - } - } - } - else if (m_spellProto->SpellFamilyFlags[0] & 0x00000001 && m_spellProto->SpellFamilyFlags[2] & 0x00000008) - { - // Glyph of Fireball - if (Unit * caster = GetCaster()) - if (caster->HasAura(56368)) - SetAuraDuration(0); - } - else if (m_spellProto->SpellFamilyFlags[0] & 0x00000020 && m_spellProto->SpellVisual[0] == 13) - { - // Glyph of Frostbolt - if (Unit * caster = GetCaster()) - if (caster->HasAura(56370)) - SetAuraDuration(0); - } - // Todo: This should be moved to similar function in spell::hit - else if (m_spellProto->SpellFamilyFlags[0] & 0x01000000) - { - Unit * caster = GetCaster(); - if (!caster) - return; + return ObjectAccessor::GetUnit(*GetOwner(), GetCasterGUID()); +} - // Polymorph Sound - Sheep && Penguin - if (m_spellProto->SpellIconID == 82 && m_spellProto->SpellVisual[0] == 12978) - { - // Glyph of the Penguin - if (caster->HasAura(52648)) - caster->CastSpell(m_target,61635,true); - else - caster->CastSpell(m_target,61634,true); - } - } - } - else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST) - { - // Devouring Plague - if (GetSpellProto()->SpellFamilyFlags[0] & 0x02000000 && GetPartAura(0)) - { - Unit * caster = GetCaster(); - if (!caster) - return; +AuraObjectType Aura::GetType() const +{ + return (m_owner->GetTypeId() == TYPEID_DYNAMICOBJECT) ? DYNOBJ_AURA_TYPE : UNIT_AURA_TYPE; +} - // Improved Devouring Plague - if (AuraEffect const * aurEff = caster->GetDummyAura(SPELLFAMILY_PRIEST, 3790, 1)) - { - int32 basepoints0 = aurEff->GetAmount() * GetPartAura(0)->GetTotalTicks() * GetPartAura(0)->GetAmount() / 100; - caster->CastCustomSpell(m_target, 63675, &basepoints0, NULL, NULL, true, NULL, GetPartAura(0)); - } - } - // Renew - else if (GetSpellProto()->SpellFamilyFlags[0] & 0x00000040 && GetPartAura(0)) - { - Unit * caster = GetCaster(); - if (!caster) - return; +void Aura::_ApplyForTarget(Unit * target, Unit * caster, AuraApplication * auraApp) +{ + assert(target); + assert(auraApp); + // aura mustn't be already applied + assert (m_applications.find(target->GetGUID()) == m_applications.end()); - // Empowered Renew - if (AuraEffect const * aurEff = caster->GetDummyAura(SPELLFAMILY_PRIEST, 3021, 1)) - { - int32 basepoints0 = aurEff->GetAmount() * GetPartAura(0)->GetTotalTicks() * caster->SpellHealingBonus(m_target, GetSpellProto(), GetPartAura(0)->GetAmount(), HEAL) / 100; - caster->CastCustomSpell(m_target, 63544, &basepoints0, NULL, NULL, true, NULL, GetPartAura(0)); - } - } - } - else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE) - { - // Sprint (skip non player casted spells by category) - if(GetSpellProto()->SpellFamilyFlags[0] & 0x40 && GetSpellProto()->Category == 44) - // in official maybe there is only one icon? - if(m_target->HasAura(58039)) // Glyph of Blurred Speed - m_target->CastSpell(m_target, 61922, true); // Sprint (waterwalk) - } - else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT) - { - // Frost Fever and Blood Plague - if(GetSpellProto()->SpellFamilyFlags[2] & 0x2) - { - // Can't proc on self - if (GetCasterGUID() == m_target->GetGUID()) - return; - Unit * caster = GetCaster(); - if (!caster) - return; + m_applications[target->GetGUID()] = auraApp; - AuraEffect * aurEff = NULL; - // Ebon Plaguebringer / Crypt Fever - Unit::AuraEffectList const& TalentAuras = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for (Unit::AuraEffectList::const_iterator itr = TalentAuras.begin(); itr != TalentAuras.end(); ++itr) - { - if ((*itr)->GetMiscValue() == 7282) - { - aurEff = *itr; - // Ebon Plaguebringer - end search if found - if ((*itr)->GetSpellProto()->SpellIconID == 1766) - break; - } - } - if (aurEff) - { - uint32 spellId = 0; - switch (aurEff->GetId()) - { - // Ebon Plague - case 51161: spellId = 51735; break; - case 51160: spellId = 51734; break; - case 51099: spellId = 51726; break; - // Crypt Fever - case 49632: spellId = 50510; break; - case 49631: spellId = 50509; break; - case 49032: spellId = 50508; break; - default: - sLog.outError("Unknown rank of Crypt Fever/Ebon Plague %d", aurEff->GetId()); - } - caster->CastSpell(m_target, spellId, true, 0, GetPartAura(0)); - } - } - } - else + // set infinity cooldown state for spells + if(caster && caster->GetTypeId() == TYPEID_PLAYER) + { + if (m_spellProto->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) { - switch(GetId()) - { - case 32474: // Buffeting Winds of Susurrus - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->ActivateTaxiPathTo(506, GetId()); - break; - case 33572: // Gronn Lord's Grasp, becomes stoned - if(GetStackAmount() >= 5 && !m_target->HasAura(33652)) - m_target->CastSpell(m_target, 33652, true); - break; - case 48020: // Demonic Circle - if(m_target->GetTypeId() == TYPEID_PLAYER) - if(GameObject* obj = m_target->GetGameObject(48018)) - ((Player*)m_target)->TeleportTo(obj->GetMapId(),obj->GetPositionX(),obj->GetPositionY(),obj->GetPositionZ(),obj->GetOrientation()); - break; - case 60970: // Heroic Fury (remove Intercept cooldown) - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->RemoveSpellCooldown(20252, true); - break; - } + Item* castItem = m_castItemGuid ? ((Player*)caster)->GetItemByGuid(m_castItemGuid) : NULL; + ((Player*)caster)->AddSpellAndCategoryCooldowns(m_spellProto,castItem ? castItem->GetEntry() : 0, NULL,true); } } +} - //******************************* - // MODS AT AURA APPLY AND REMOVE - //******************************* +void Aura::_UnapplyForTarget(Unit * target, Unit * caster, AuraApplication * auraApp) +{ + assert(target); + assert(auraApp->GetRemoveMode()); + assert(auraApp); - // Aura Mastery Triggered Spell Handler - // If apply Concentration Aura -> trigger -> apply Aura Mastery Immunity - // If remove Concentration Aura -> trigger -> remove Aura Mastery Immunity - // If remove Aura Mastery -> trigger -> remove Aura Mastery Immunity - if (m_spellProto->Id == 19746 || m_spellProto->Id == 31821) + ApplicationMap::iterator itr = m_applications.find(target->GetGUID()); + // aura has to be already applied + assert(itr->second == auraApp); + m_applications.erase(itr); + m_removedApplications.push_back(auraApp); + + // reset cooldown state for spells + if(caster && caster->GetTypeId() == TYPEID_PLAYER) { - if (GetCasterGUID() != m_target->GetGUID()) - return; - if (apply) - { - if ((m_spellProto->Id == 31821 && m_target->HasAura(19746, GetCasterGUID())) || (m_spellProto->Id == 19746 && m_target->HasAura(31821))) - { - m_target->CastSpell(m_target,64364,true); - return; - } - } - else - { - m_target->RemoveAurasDueToSpell(64364, GetCasterGUID()); - return; - } + if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) + // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) + ((Player*)caster)->SendCooldownEvent(GetSpellProto()); } +} - // Bestial Wrath - if (GetSpellProto()->Id == 19574) +// removes aura from all targets +// and marks aura as removed +void Aura::_Remove(AuraRemoveMode removeMode) +{ + assert (!m_isRemoved); + m_isRemoved = true; + for (ApplicationMap::iterator appItr = m_applications.begin() ; appItr != m_applications.end() ;) { - // The Beast Within cast on owner if talent present - if ( Unit* owner = m_target->GetOwner() ) - { - // Search talent - if (owner->HasAura(34692)) - { - if (apply) - owner->CastSpell(owner, 34471, true, 0, GetPartAura(0)); - else - owner->RemoveAurasDueToSpell(34471); - } - } + AuraApplication * aurApp = appItr->second; + Unit * target = aurApp->GetTarget(); + ++appItr; + target->_UnapplyAura(aurApp, removeMode); } +} - if (GetSpellSpecific(m_spellProto->Id) == SPELL_PRESENCE) - { - AuraEffect *bloodPresenceAura=0; // healing by damage done - AuraEffect *frostPresenceAura=0; // increased health - AuraEffect *unholyPresenceAura=0; // increased movement speed, faster rune recovery +void Aura::UpdateTargetMap(Unit * caster) +{ + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if(m_effects[i] && !IsRemoved()) + UpdateTargetMapForEffect(caster, i); +} - // Improved Presences - Unit::AuraEffectList const& vDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY); - for (Unit::AuraEffectList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr) - { - switch((*itr)->GetId()) - { - // Improved Blood Presence - case 50365: - case 50371: - { - bloodPresenceAura = (*itr); - break; - } - // Improved Frost Presence - case 50384: - case 50385: - { - frostPresenceAura = (*itr); - break; - } - // Improved Unholy Presence - case 50391: - case 50392: - { - unholyPresenceAura = (*itr); - break; - } - } - } +void Aura::UpdateOwner(uint32 diff, WorldObject * owner) +{ + assert(owner == m_owner); - uint32 presence=GetId(); - if (apply) - { - // Blood Presence bonus - if (presence == SPELL_ID_BLOOD_PRESENCE) - m_target->CastSpell(m_target,63611,true); - else if (bloodPresenceAura) - { - int32 basePoints1=bloodPresenceAura->GetAmount(); - m_target->CastCustomSpell(m_target,63611,NULL,&basePoints1,NULL,true,0,bloodPresenceAura); - } - // Frost Presence bonus - if (presence == SPELL_ID_FROST_PRESENCE) - m_target->CastSpell(m_target,61261,true); - else if (frostPresenceAura) - { - int32 basePoints0=frostPresenceAura->GetAmount(); - m_target->CastCustomSpell(m_target,61261,&basePoints0,NULL,NULL,true,0,frostPresenceAura); - } - // Unholy Presence bonus - if (presence == SPELL_ID_UNHOLY_PRESENCE) - { - if(unholyPresenceAura) - { - // Not listed as any effect, only base points set - int32 basePoints0 = unholyPresenceAura->GetSpellProto()->EffectBasePoints[1]; - //m_target->CastCustomSpell(m_target,63622,&basePoints0 ,NULL,NULL,true,0,unholyPresenceAura); - m_target->CastCustomSpell(m_target,65095,&basePoints0 ,NULL,NULL,true,0,unholyPresenceAura); - } - m_target->CastSpell(m_target,49772, true); - } - else if (unholyPresenceAura) - { - int32 basePoints0=unholyPresenceAura->GetAmount(); - m_target->CastCustomSpell(m_target,49772,&basePoints0,NULL,NULL,true,0,unholyPresenceAura); - } - } - else - { - // Remove passive auras - if (presence == SPELL_ID_BLOOD_PRESENCE || bloodPresenceAura) - m_target->RemoveAurasDueToSpell(63611); - if (presence == SPELL_ID_FROST_PRESENCE || frostPresenceAura) - m_target->RemoveAurasDueToSpell(61261); - if (presence == SPELL_ID_UNHOLY_PRESENCE || unholyPresenceAura) - { - if(presence == SPELL_ID_UNHOLY_PRESENCE && unholyPresenceAura) - { - //m_target->RemoveAurasDueToSpell(63622); - m_target->RemoveAurasDueToSpell(65095); - } - m_target->RemoveAurasDueToSpell(49772); - } - } - } + Unit * caster = GetCaster(); + // Apply spellmods for channeled auras + // used for example when triggered spell of spell:10 is modded + Spell * modSpell = NULL; + Player * modOwner = NULL; + if(caster) + if ((modOwner = caster->GetSpellModOwner()) + && (modSpell = modOwner->FindCurrentSpellBySpellId(GetId()))) + modOwner->SetSpellModTakingSpell(modSpell, true); - //********************* - // MODS AT AURA REMOVE - //********************* + Update(diff, caster); - if(!apply) - { - // Spell Reflection - if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x2 - && GetRemoveMode() != AURA_REMOVE_BY_DEFAULT) - { - if (Unit * caster = GetCaster()) - { - // Improved Spell Reflection - if (caster->GetDummyAura(SPELLFAMILY_WARRIOR,1935, 1)) - { - // aura remove - remove auras from all party members - std::list<Unit*> PartyMembers; - m_target->GetPartyMembers(PartyMembers); - for (std::list<Unit*>::iterator itr = PartyMembers.begin(); itr!=PartyMembers.end(); ++itr) - { - if ((*itr)!= m_target) - (*itr)->RemoveAurasWithFamily(SPELLFAMILY_WARRIOR, 0, 0x2, 0, GetCasterGUID()); - } - } - } - } - // Guardian Spirit - else if(m_spellProto->Id == 47788) - { - if (GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) - return; - Unit *caster = GetCaster(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; + UpdateTargetMap(caster); - Player *player = ((Player*)caster); - // Glyph of Guardian Spirit - if(AuraEffect * aurEff = player->GetAuraEffect(63231, 0)) - { - if (!player->HasSpellCooldown(47788)) - return; + // update aura effects + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if (m_effects[i]) + m_effects[i]->Update(diff, caster); - player->RemoveSpellCooldown(m_spellProto->Id, true); - player->AddSpellCooldown(m_spellProto->Id, 0, uint32(time(NULL) + aurEff->GetAmount())); + // remove spellmods after effects update + if (modSpell) + modOwner->SetSpellModTakingSpell(modSpell, false); - WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4+4); - data << uint64(player->GetGUID()); - data << uint8(0x0); // flags (0x1, 0x2) - data << uint32(m_spellProto->Id); - data << uint32(aurEff->GetAmount()*IN_MILISECONDS); - player->SendDirectMessage(&data); - } - } - // Invisibility - else if (m_spellProto->Id == 66) - { - if (GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) - return; - m_target->CastSpell(m_target, 32612, true, NULL, GetPartAura(1)); - } - // Summon Gargoyle - else if (m_spellProto->Id == 50514) - { - m_target->CastSpell(m_target, GetPartAura(0)->GetAmount(), true, NULL, GetPartAura(0)); - } - // Curse of Doom - else if (m_spellProto->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags[1] & 0x02) - { - if (GetRemoveMode()==AURA_REMOVE_BY_DEATH) - { - if (Unit * caster = GetCaster()) - { - if (caster->GetTypeId() == TYPEID_PLAYER && ((Player*)caster)->isHonorOrXPTarget(m_target)) - caster->CastSpell(m_target, 18662, true, NULL, GetPartAura(0)); - } - } - } - // Improved Fear - else if (m_spellProto->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags[1] & 0x00000400) - { - if (Unit * caster = GetCaster()) - { - if (caster->GetTypeId() != TYPEID_PLAYER) - { - if (AuraEffect* aureff = caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_WARLOCK, 98, 0)) - { - uint32 spell_id = 0; - switch (aureff->GetId()) - { - case 53759: spell_id = 60947; break; - case 53754: spell_id = 60946; break; - default: return; - } - if (spell_id) - caster->CastSpell(caster,spell_id,true); - } - } - } - } - } + _DeleteRemovedApplications(); } -void AuraEffect::HandleAuraEffectSpecificMods(bool apply, bool Real, bool changeAmount) +void Aura::Update(uint32 diff, Unit * caster) { - //*********************************************************************** - // Function called before aura effect handler apply or after it's remove - //*********************************************************************** - - if(!Real && !changeAmount) - return; - - Unit* caster = GetCaster(); - - if (!caster) - return; - - if(apply) + if (m_duration > 0) { - // prevent double apply bonuses - if (!m_target->isBeingLoaded()) - if(caster) + m_duration -= diff; + if (m_duration < 0) + m_duration = 0; + + // handle manaPerSecond/manaPerSecondPerLevel + if(m_timeCla) { - float DoneActualBenefit = 0.0f; - float BenefitMod = 1.0f; - switch(m_spellProto->SpellFamilyName) + if(m_timeCla > diff) + m_timeCla -= diff; + else if(caster) { - case SPELLFAMILY_GENERIC: - // Replenishment (0.25% from max) - // Infinite Replenishment - if (m_spellProto->SpellIconID == 3184 && m_spellProto->SpellVisual[0] == 12495 && GetAuraName() == SPELL_AURA_PERIODIC_ENERGIZE) - m_amount = m_target->GetMaxPower(POWER_MANA) * 20 / 10000; - break; - case SPELLFAMILY_MAGE: - // Mana Shield - if(m_spellProto->SpellFamilyFlags[0] & 0x8000 && m_spellProto->SpellFamilyFlags[2] & 0x8 && GetAuraName() == SPELL_AURA_MANA_SHIELD) - { - // +80.53% from +spd bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8053f;; - } - // Ice Barrier - else if(m_spellProto->SpellFamilyFlags[1] & 0x1 && m_spellProto->SpellFamilyFlags[2] & 0x8 && GetAuraName() == SPELL_AURA_SCHOOL_ABSORB) - { - // +80.67% from sp bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8067f; - } - // Frost Ward, Fire Ward - else if (m_spellProto->SpellFamilyFlags[0] & 0x00000108 && GetAuraName() == SPELL_AURA_SCHOOL_ABSORB) - { - //+10% from +spell bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f; - } - break; - case SPELLFAMILY_WARRIOR: - { - // Rend - if (m_spellProto->SpellFamilyFlags[0] & 0x20 && GetAuraName() == SPELL_AURA_PERIODIC_DAMAGE) - { - // $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 mws = caster->GetAttackTime(BASE_ATTACK); - float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); - float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); - m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f); - // "If used while your target is above 75% health, Rend does 35% more damage." - // as for 3.1.3 only ranks above 9 (wrong tooltip?) - if (spellmgr.GetSpellRank(m_spellProto->Id) >= 9) - { - if (m_target->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, m_spellProto, caster)) - m_amount += int32(m_amount*0.35); - } - } - break; - } - case SPELLFAMILY_WARLOCK: - // shadow ward - if(m_spellProto->SpellFamilyFlags[2]& 0x40 && GetAuraName() == SPELL_AURA_SCHOOL_ABSORB) - { - // +30% from sp bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f; - } - // Drain Soul - If the target is at or below 25% health, Drain Soul causes four times the normal damage - else if (m_spellProto->SpellFamilyFlags[0] & 0x00004000 && GetAuraName() == SPELL_AURA_PERIODIC_DAMAGE) - { - // if victim is below 25% of hp - if (m_target->GetMaxHealth() / 4 > m_target->GetHealth()) - m_amount *= 4; - } - break; - case SPELLFAMILY_PRIEST: - { - // Power Word: Shield - if(m_spellProto->SpellFamilyFlags[0] & 0x1 && m_spellProto->SpellFamilyFlags[2] & 0x400 && GetAuraName() == SPELL_AURA_SCHOOL_ABSORB) - { - //+80.68% from sp bonus - DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f; - // Borrowed Time - if (AuraEffect* aureff = caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_PRIEST, 2899, 1)) - DoneActualBenefit += caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * (aureff->GetAmount() / 100.0f); - } - // Lightwell Renew - else if (m_spellProto->SpellFamilyFlags[2] & UI64LIT(0x4000) && GetAuraName() == SPELL_AURA_PERIODIC_HEAL) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - // Bonus from Glyph of Lightwell - if (AuraEffect* modHealing = caster->GetAuraEffect(55673, 0)) - m_amount *= (100.0f + modHealing->GetAmount()) / 100.0f; - } - break; - } - case SPELLFAMILY_DRUID: - { - // Rip - if (m_spellProto->SpellFamilyFlags[0] & 0x00800000 && GetAuraName() == SPELL_AURA_PERIODIC_DAMAGE) - { - // 0.01*$AP*cp - if (caster->GetTypeId() != TYPEID_PLAYER) - return; - - uint8 cp = ((Player*)caster)->GetComboPoints(); - - // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs - if (AuraEffect const * aurEff = caster->GetAuraEffect(34241,0)) - m_amount += cp * aurEff->GetAmount(); - - m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); - } - // TODO: i do not know what is this for so i simply disable it - // Lifebloom - //else if (m_spellProto->SpellFamilyFlags[1] & 0x10 && GetAuraName() == SPELL_AURA_PERIODIC_HEAL) - // m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_amount, SPELL_DIRECT_DAMAGE); - // Innervate - else if (m_spellProto->Id == 29166 && GetAuraName() == SPELL_AURA_PERIODIC_ENERGIZE) - m_amount = m_target->GetCreatePowers(POWER_MANA) * m_amount / (GetTotalTicks() * 100.0f); - // Owlkin Frenzy - else if (m_spellProto->Id == 48391 && GetAuraName() == SPELL_AURA_PERIODIC_ENERGIZE) - m_amount = m_target->GetCreatePowers(POWER_MANA) * m_amount / 100.0f; - // Thorns - else if (m_spellProto->SpellFamilyFlags[0] & 0x100 && GetAuraName() == SPELL_AURA_DAMAGE_SHIELD) - // 3.3% from sp bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.033f; - break; - } - case SPELLFAMILY_ROGUE: + if(int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel()) { - // Rupture - if (m_spellProto->SpellFamilyFlags[0] & 0x100000 && GetAuraName() == SPELL_AURA_PERIODIC_DAMAGE) - { - if (caster->GetTypeId() != TYPEID_PLAYER) - return; - //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs - //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs - //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs - //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs - //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs - float AP_per_combo[6] = {0.0f, 0.015f, 0.024f, 0.03f, 0.03428571f, 0.0375f}; - uint8 cp = ((Player*)caster)->GetComboPoints(); - if (cp > 5) cp = 5; - m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]); - } - break; - } - case SPELLFAMILY_PALADIN: - // Sacred Shield - if (m_spellProto->SpellFamilyFlags[1] & 0x80000 && GetAuraName() == SPELL_AURA_SCHOOL_ABSORB) - { - // 0.75 from sp bonus - float koef = 1.0f; - if (caster->HasAura(53527)) - koef = 1.1f; - if (caster->HasAura(53530)) - koef = 1.2f; + m_timeCla += 1000 - diff; - DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.75f * koef; - } - break; - case SPELLFAMILY_SHAMAN: - // Earth Shield - if (m_spellProto->SpellFamilyFlags[1] & 0x400 && GetAuraName() == SPELL_AURA_DUMMY) - m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_amount, SPELL_DIRECT_DAMAGE); - break; - case SPELLFAMILY_DEATHKNIGHT: - { - // Vampiric Blood - if(GetSpellProto()->Id == 55233 && GetAuraName() == SPELL_AURA_MOD_INCREASE_HEALTH) - m_amount = m_target->GetMaxHealth() * m_amount / 100; - // Icebound Fortitude - else if (m_spellProto->SpellFamilyFlags[0] & 0x00100000 && GetAuraName() == SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN) + Powers powertype = Powers(m_spellProto->powerType); + if(powertype == POWER_HEALTH) { - if (caster->GetTypeId() == TYPEID_PLAYER) + if (caster->GetHealth() > manaPerSecond) + caster->ModifyHealth(-manaPerSecond); + else { - int32 value = int32((m_amount*-1)-10); - uint32 defva = uint32(((Player*)caster)->GetSkillValue(SKILL_DEFENSE) + ((Player*)caster)->GetRatingBonusValue(CR_DEFENSE_SKILL)); - - if(defva > 400) - value += int32((defva-400)*0.15); - - // Glyph of Icebound Fortitude - if (AuraEffect *auradummy = caster->GetAuraEffect(58625,0)) - { - uint32 valmax = auradummy->GetAmount(); - if(value < valmax) - value = valmax; - } - m_amount = -value; + Remove(); + return; } } - break; - } - default: - break; - } - - if (DoneActualBenefit != 0.0f) - { - // Handle SPELL_AURA_ADD_PCT_MODIFIERs - Unit::AuraEffectList const& AuraPctMmodifiers = caster->GetAurasByType(SPELL_AURA_ADD_PCT_MODIFIER); - for (Unit::AuraEffectList::const_iterator i = AuraPctMmodifiers.begin(); i != AuraPctMmodifiers.end(); ++i) - { - if ((*i)->isAffectedOnSpell(m_spellProto) && (*i)->GetMiscValue() == SPELLMOD_ALL_EFFECTS) - BenefitMod += (*i)->GetAmount() / 100.0f; - } - - DoneActualBenefit *= BenefitMod; - DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto()); - m_amount += (int32)DoneActualBenefit; - } - } - } - else - { - if (caster && - // Power Word: Shield - m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellProto->Mechanic == MECHANIC_SHIELD && - (m_spellProto->SpellFamilyFlags[0] & 0x00000001) && - // completely absorbed or dispelled - ((m_parentAura->GetRemoveMode() == AURA_REMOVE_BY_DEFAULT && m_amount) || m_parentAura->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)) - { - Unit::AuraEffectList const& vDummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraEffectList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr) - { - SpellEntry const* vSpell = (*itr)->GetSpellProto(); - - // Rapture (main spell) - if(vSpell->SpellFamilyName == SPELLFAMILY_PRIEST && vSpell->SpellIconID == 2894 && vSpell->Effect[1]) - { - switch((*itr)->m_effIndex) + else { - case 0: - { - // energize caster - int32 manapct1000 = 5 * ((*itr)->m_amount + spellmgr.GetSpellRank(vSpell->Id)); - int32 basepoints0 = caster->GetMaxPower(POWER_MANA) * manapct1000 / 1000; - caster->CastCustomSpell(caster, 47755, &basepoints0, NULL, NULL, true); - break; - } - case 1: + if (caster->GetPower(powertype) >= manaPerSecond) + caster->ModifyPower(powertype, -manaPerSecond); + else { - // energize target - if (!roll_chance_i((*itr)->m_amount) || caster->HasAura(63853)) - break; - - switch(m_target->getPowerType()) - { - case POWER_RUNIC_POWER: - m_target->CastSpell(m_target, 63652, true, NULL, NULL, GetCasterGUID()); - break; - case POWER_RAGE: - m_target->CastSpell(m_target, 63653, true, NULL, NULL, GetCasterGUID()); - break; - case POWER_MANA: - { - int32 basepoints0 = m_target->GetMaxPower(POWER_MANA) * 2 / 100; - m_target->CastCustomSpell(m_target, 63654, &basepoints0, NULL, NULL, true); - break; - } - case POWER_ENERGY: - m_target->CastSpell(m_target, 63655, true, NULL, NULL, GetCasterGUID()); - break; - default: - break; - } - - //cooldwon aura - caster->CastSpell(caster, 63853, true); - break; + Remove(); + return; } - default: - sLog.outError("Changes in R-dummy spell???: effect 3"); - break; } } } @@ -1684,304 +489,66 @@ void AuraEffect::HandleAuraEffectSpecificMods(bool apply, bool Real, bool change } } -void Aura::SendAuraUpdate() +void Aura::SetDuration(int32 duration, bool withMods) { - if (m_auraSlot>=MAX_AURAS) - return; - WorldPacket data(SMSG_AURA_UPDATE); - - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - - if(!m_target->GetVisibleAura(m_auraSlot)) - { - data << uint32(0); - sLog.outDebug("Aura %u removed slot %u",GetId(), m_auraSlot); - m_target->SendMessageToSet(&data, true); - return; - } - - data << uint32(GetId()); - data << uint8(m_auraFlags); - data << uint8(m_auraLevel); - data << uint8(m_stackAmount > 1 ? m_stackAmount : (m_procCharges) ? m_procCharges : 1); - - if(!(m_auraFlags & AFLAG_CASTER)) + if (withMods) { if (Unit * caster = GetCaster()) - data.append(caster->GetPackGUID()); - else - data << uint8(0); - } - - if(m_auraFlags & AFLAG_DURATION) - { - data << uint32(m_maxduration); - data << uint32(m_duration); + if (Player * modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, duration); } - - m_target->SendMessageToSet(&data, true); + m_duration = duration; + SetNeedClientUpdateForTargets(); } -bool Aura::IsVisible() const +void Aura::RefreshDuration() { - // passive auras (except totem auras) do not get placed in the slots - // area auras with SPELL_AURA_NONE are not shown on target - //(m_spellProto->Attributes & 0x80 && GetTalentSpellPos(GetId())) - - if(!m_isPassive) - return true; - - bool noneAreaAura = true; + SetDuration(GetMaxDuration()); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if(m_partAuras[i]) - { - if(m_partAuras[i]->IsAreaAura()) - { - if(Unit *source = ((AreaAuraEffect*)m_partAuras[i])->GetSource()) - if(source->isTotem()) - return true; + if(m_effects[i]) + m_effects[i]->ResetPeriodic(); - if(m_partAuras[i]->GetAuraName() != SPELL_AURA_NONE) - noneAreaAura = false; - } - else - noneAreaAura = false; - } - } - - if(noneAreaAura) - return false; - - return IsAuraType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); + if(m_spellProto->manaPerSecond || m_spellProto->manaPerSecondPerLevel) + m_timeCla = 1 * IN_MILISECONDS; } -void Aura::_AddAura() +void Aura::SetCharges(uint8 charges) { - if (!GetId()) - return; - if(!m_target) + if (m_procCharges == charges) return; - - Unit* caster = GetCaster(); - - // set infinity cooldown state for spells - if(caster && caster->GetTypeId() == TYPEID_PLAYER) - { - if (m_spellProto->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) - { - Item* castItem = m_castItemGuid ? ((Player*)caster)->GetItemByGuid(m_castItemGuid) : NULL; - ((Player*)caster)->AddSpellAndCategoryCooldowns(m_spellProto,castItem ? castItem->GetEntry() : 0, NULL,true); - } - } - - if(IsVisible()) - { - // Try find slot for aura - uint8 slot = MAX_AURAS; - // Lookup for auras already applied from spell - if (Aura * foundAura = m_target->GetAura(GetId(), GetCasterGUID())) - { - // allow use single slot only by auras from same caster - slot = foundAura->GetAuraSlot(); - } - else - { - Unit::VisibleAuraMap const * visibleAuras= m_target->GetVisibleAuras(); - // lookup for free slots in units visibleAuras - Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(0); - for (uint32 freeSlot = 0; freeSlot < MAX_AURAS; ++itr , ++freeSlot) - { - if(itr == visibleAuras->end() || itr->first != freeSlot) - { - slot = freeSlot; - break; - } - } - } - - // Register Visible Aura - if(slot < MAX_AURAS) - { - m_auraFlags |= (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE) | - (GetCasterGUID() == m_target->GetGUID() ? AFLAG_CASTER : AFLAG_NONE) | - (GetAuraMaxDuration() > 0 ? AFLAG_DURATION : AFLAG_NONE); - m_auraLevel = (caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - SetAuraSlot( slot ); - m_target->SetVisibleAura(slot, this); - m_target->UpdateAuraForGroup(slot); - SendAuraUpdate(); - sLog.outDebug("Aura: %u Effect: %d put to unit visible auras slot: %u",GetId(), GetEffectMask(), slot); - } - else - sLog.outDebug("Aura: %u Effect: %d could not find empty unit visible slot",GetId(), GetEffectMask()); - } - - // Sitdown on apply aura req seated - if (m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !m_target->IsSitState()) - m_target->SetStandState(UNIT_STAND_STATE_SIT); - - // register aura diminishing on apply - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),true); - - // Apply linked auras (On first aura apply) - uint32 id = GetId(); - if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA) - { - if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA)) - for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) - { - if(*itr < 0) - m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), true); - else if(Unit* caster = GetCaster()) - caster->AddAura(*itr, m_target); - } - } - - HandleAuraSpecificMods(true); -} - -bool Aura::SetPartAura(AuraEffect* aurEff, uint8 effIndex) -{ - if (IsRemoved()) - return false; - if (m_auraFlags & (1<<effIndex)) - return false; - m_auraFlags |= 1<<effIndex; - m_partAuras[effIndex]=aurEff; - m_target->HandleAuraEffect(aurEff, true); - SendAuraUpdate(); - return true; + m_procCharges = charges; + SetNeedClientUpdateForTargets(); } -void Aura::_RemoveAura() +bool Aura::DropCharge() { - Unit* caster = GetCaster(); - - uint8 slot = GetAuraSlot(); - - if (Aura * foundAura = m_target->GetAura(GetId(), GetCasterGUID())) - { - // allow use single slot only by auras from same caster - slot = foundAura->GetAuraSlot(); - if(slot < MAX_AURAS) // slot not set - if (Aura *entry = m_target->GetVisibleAura(slot)) - { - // set not valid slot for aura - prevent removing other visible aura - slot = MAX_AURAS; - } - } - - // update for out of range group members - if (slot < MAX_AURAS) - { - m_target->RemoveVisibleAura(slot); - m_target->UpdateAuraForGroup(slot); - SendAuraUpdate(); - } - - // unregister aura diminishing (and store last time) - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),false); - - // since now aura cannot apply/remove it's modifiers - m_isRemoved = true; - // disable client server communication for removed aura - SetAuraSlot(MAX_AURAS); - - // reset cooldown state for spells - if(caster && caster->GetTypeId() == TYPEID_PLAYER) - { - if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) - // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) - ((Player*)caster)->SendCooldownEvent(GetSpellProto()); - } - uint32 id = GetId(); - // Remove Linked Auras - if(m_removeMode != AURA_REMOVE_BY_STACK && m_removeMode != AURA_REMOVE_BY_DEATH) - { - if(uint32 customAttr = spellmgr.GetSpellCustomAttr(id)) - { - if(customAttr & SPELL_ATTR_CU_LINK_REMOVE) - { - if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)id)) - for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) - { - if(*itr < 0) - m_target->RemoveAurasDueToSpell(-(*itr)); - else if (m_removeMode != AURA_REMOVE_BY_DEFAULT) - m_target->CastSpell(m_target, *itr, true, 0, 0, GetCasterGUID()); - } - } - if(customAttr & SPELL_ATTR_CU_LINK_AURA) - { - if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA)) - for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) - { - if(*itr < 0) - m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), false); - else - m_target->RemoveAurasDueToSpell(*itr); - } - } - } - } - - // Proc on aura remove (only spell flags for now) - if (caster) + if(m_procCharges) //auras without charges always have charge = 0 { - uint32 procEx=0; - if (m_removeMode == AURA_REMOVE_BY_ENEMY_SPELL) - procEx = PROC_EX_AURA_REMOVE_DESTROY; - else if (m_removeMode == AURA_REMOVE_BY_EXPIRE || m_removeMode == AURA_REMOVE_BY_CANCEL) - procEx = PROC_EX_AURA_REMOVE_EXPIRE; - if (procEx) + if(--m_procCharges) // Send charge change + SetNeedClientUpdateForTargets(); + else // Last charge dropped { - uint32 ProcCaster, ProcVictim; - if (IsPositive()) - { - ProcCaster = PROC_FLAG_SUCCESSFUL_POSITIVE_MAGIC_SPELL | PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL_HIT; - ProcVictim = PROC_FLAG_TAKEN_POSITIVE_MAGIC_SPELL | PROC_FLAG_TAKEN_POSITIVE_SPELL; - } - else - { - ProcCaster = PROC_FLAG_SUCCESSFUL_NEGATIVE_MAGIC_SPELL | PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT; - ProcVictim = PROC_FLAG_TAKEN_NEGATIVE_MAGIC_SPELL | PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT; - } - caster->ProcDamageAndSpell(m_target,ProcCaster, ProcVictim, procEx, m_procDamage, BASE_ATTACK, m_spellProto); + Remove(AURA_REMOVE_BY_EXPIRE); + return true; } } - HandleAuraSpecificMods(false); + return false; } void Aura::SetStackAmount(uint8 stackAmount, bool applied) { - bool refresh = stackAmount >= m_stackAmount; if (stackAmount != m_stackAmount) { m_stackAmount = stackAmount; - for (uint8 i=0; i<MAX_SPELL_EFFECTS; ++i) - { - if (AuraEffect * part = GetPartAura(i)) - { - part->RecalculateAmount(applied); - } - } + RecalculateAmountOfEffects(); } - - if (refresh) - RefreshAura(); - else - SendAuraUpdate(); + SetNeedClientUpdateForTargets(); } -// TODO: lifebloom should bloom when each stack is dispelled -bool Aura::modStackAmount(int32 num) +bool Aura::ModStackAmount(int32 num) { // Can`t mod - if (!m_spellProto->StackAmount) + if (!m_spellProto->StackAmount || !GetStackAmount()) return true; // Modify stack but limit it @@ -1993,48 +560,27 @@ bool Aura::modStackAmount(int32 num) m_stackAmount = 0; return true; // need remove aura } + bool refresh = stackAmount >= GetStackAmount(); // Update stack amount SetStackAmount(stackAmount); + + if (refresh) + RefreshDuration(); + SetNeedClientUpdateForTargets(); + return false; } -void Aura::SetAuraDuration(int32 duration, bool withMods) -{ - if (withMods) - { - if (Player * modOwner = m_target->GetSpellModOwner()) - modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, duration); - } - m_duration = duration; - //if (duration<0) - //m_permanent=true; - //else - //m_permanent=false; - SendAuraUpdate(); -} -void Aura::SetAuraCharges(uint8 charges) +bool Aura::IsPassive() const { - if (m_procCharges == charges) - return; - m_procCharges = charges; - SendAuraUpdate(); + return IsPassiveSpell(GetSpellProto()); } -bool Aura::DropAuraCharge() +bool Aura::IsDeathPersistent() const { - if(m_procCharges) //auras without charges always have charge = 0 - { - if(--m_procCharges) // Send charge change - SendAuraUpdate(); - else // Last charge dropped - { - m_target->RemoveAura(this, AURA_REMOVE_BY_EXPIRE); - return true; - } - } - return false; + return IsDeathPersistentSpell(GetSpellProto()); } bool Aura::CanBeSaved() const @@ -2042,5294 +588,924 @@ bool Aura::CanBeSaved() const if (IsPassive()) return false; - if(IsPersistent()) - return false; - - if (GetCasterGUID() != m_target->GetGUID()) - if (IsSingleTargetSpell(GetSpellProto()) || IsAreaAura()) + if (GetCasterGUID() != GetOwner()->GetGUID()) + if (IsSingleTargetSpell(GetSpellProto())) return false; // Can't be saved - aura handler relies on calculated amount and changes it - if (IsAuraType(SPELL_AURA_CONVERT_RUNE)) + if (HasEffectType(SPELL_AURA_CONVERT_RUNE)) return false; return true; } -bool Aura::IsPersistent() const +bool Aura::HasEffectType(AuraType type) const { - return IS_DYNAMICOBJECT_GUID(m_sourceGuid); - /* for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if(m_partAuras[i] && m_partAuras[i]->IsPersistent()) + { + if(m_effects[i] && m_effects[i]->GetAuraType() == type) return true; + } return false; - */ } -bool Aura::IsAreaAura() const +void Aura::RecalculateAmountOfEffects() { + assert (!IsRemoved()); + Unit * caster = GetCaster(); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if(m_partAuras[i] && m_partAuras[i]->IsAreaAura()) - return true; - return false; + if(m_effects[i]) + m_effects[i]->RecalculateAmount(caster); } -bool Aura::IsAuraType(AuraType type) const +void Aura::HandleAllEffects(AuraApplication const * aurApp, uint8 mode, bool apply) { + assert (!IsRemoved()); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if(m_partAuras[i] && m_partAuras[i]->GetAuraName() == type) - return true; - } - return false; + if(m_effects[i] && !IsRemoved()) + m_effects[i]->HandleEffect(aurApp, mode, apply); } -void Aura::SetLoadedState(uint64 caster_guid,int32 maxduration,int32 duration,int32 charges, uint8 stackamount, int32 * amount) +bool Aura::IsVisible() const { - *const_cast<uint64*>(&m_casterGuid) = caster_guid; - m_maxduration = maxduration; + // Is this blizzlike? show totem passive auras + if (GetOwner()->GetTypeId() == TYPEID_UNIT && ((Creature*)m_owner)->isTotem() && IsPassive()) + return true; + return !IsPassive() || HasEffectType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); +} + +void Aura::SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount) +{ + m_maxDuration = maxduration; m_duration = duration; m_procCharges = charges; m_stackAmount = stackamount; + Unit * caster = GetCaster(); for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if(m_partAuras[i]) - m_partAuras[i]->SetAmount(amount[i]); + if(m_effects[i]) + { + m_effects[i]->SetAmount(amount[i]); + m_effects[i]->SetCanBeRecalculated(recalculateMask & (1<<i)); + m_effects[i]->CalculatePeriodic(caster); + m_effects[i]->CalculateSpellMod(); + m_effects[i]->RecalculateAmount(caster); + } } -void AuraEffect::HandleShapeshiftBoosts(bool apply) +// trigger effects on real aura apply/remove +void Aura::HandleAuraSpecificMods(AuraApplication const * aurApp, Unit * caster, bool apply) { - uint32 spellId = 0; - uint32 spellId2 = 0; - uint32 spellId3 = 0; - uint32 HotWSpellId = 0; - - switch(GetMiscValue()) - { - case FORM_CAT: - spellId = 3025; - HotWSpellId = 24900; - break; - case FORM_TREE: - spellId = 34123; - break; - case FORM_TRAVEL: - spellId = 5419; - break; - case FORM_AQUA: - spellId = 5421; - break; - case FORM_BEAR: - spellId = 1178; - spellId2 = 21178; - HotWSpellId = 24899; - break; - case FORM_DIREBEAR: - spellId = 9635; - spellId2 = 21178; - HotWSpellId = 24899; - break; - case FORM_BATTLESTANCE: - spellId = 21156; - break; - case FORM_DEFENSIVESTANCE: - spellId = 7376; - break; - case FORM_BERSERKERSTANCE: - spellId = 7381; - break; - case FORM_MOONKIN: - spellId = 24905; - break; - case FORM_FLIGHT: - spellId = 33948; - spellId2 = 34764; - break; - case FORM_FLIGHT_EPIC: - spellId = 40122; - spellId2 = 40121; - break; - case FORM_METAMORPHOSIS: - spellId = 54817; - spellId2 = 54879; - break; - case FORM_SPIRITOFREDEMPTION: - spellId = 27792; - spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation. - break; - case FORM_SHADOW: - spellId = 49868; - break; - case FORM_GHOSTWOLF: - spellId = 67116; - break; - case FORM_GHOUL: - case FORM_AMBIENT: - case FORM_STEALTH: - case FORM_CREATURECAT: - case FORM_CREATUREBEAR: - break; - } - - uint32 form = GetMiscValue()-1; - - if(apply) + Unit * target = aurApp->GetTarget(); + AuraRemoveMode removeMode = aurApp->GetRemoveMode(); + // spell_area table + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); + if(saBounds.first != saBounds.second) { - // Remove cooldown of spells triggered on stance change - they may share cooldown with stance spell - if (spellId) - { - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player *)m_target)->RemoveSpellCooldown(spellId); - m_target->CastSpell(m_target, spellId, true, NULL, this ); - } + uint32 zone, area; + target->GetZoneAndAreaId(zone,area); - if (spellId2) + for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) { - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player *)m_target)->RemoveSpellCooldown(spellId2); - m_target->CastSpell(m_target, spellId2, true, NULL, this); - } - - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - if(itr->second->state == PLAYERSPELL_REMOVED) continue; - if(itr->first==spellId || itr->first==spellId2) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue; - if (spellInfo->Stances & (1<<(form))) - m_target->CastSpell(m_target, itr->first, true, NULL, this); - } - // Leader of the Pack - if (((Player*)m_target)->HasSpell(17007)) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932); - if (spellInfo && spellInfo->Stances & (1<<(form))) - m_target->CastSpell(m_target, 24932, true, NULL, this); - } - // Improved Barkskin - apply/remove armor bonus due to shapeshift - if (((Player*)m_target)->HasSpell(63410) || ((Player*)m_target)->HasSpell(63411)) - { - m_target->RemoveAurasDueToSpell(66530); - if (form == FORM_TRAVEL || form == FORM_NONE) // "while in Travel Form or while not shapeshifted" - m_target->CastSpell(m_target, 66530, true); - } - // Heart of the Wild - if (HotWSpellId) - { - Unit::AuraEffectList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); - for (Unit::AuraEffectList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetMiscValue() == 3) - { - int32 HotWMod = (*i)->GetAmount(); - if(GetMiscValue() == FORM_CAT) - HotWMod /= 2; - - m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this); - break; - } - } - } - switch(GetMiscValue()) + // some auras remove at aura remove + if(!itr->second->IsFitToRequirements((Player*)target,zone,area)) + target->RemoveAurasDueToSpell(itr->second->spellId); + // some auras applied at aura apply + else if(itr->second->autocast) { - case FORM_CAT: - // Nurturing Instinct - if (AuraEffect const * aurEff = m_target->GetAuraEffect(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT, SPELLFAMILY_DRUID, 2254,0)) - { - uint32 spellId = 0; - switch (aurEff->GetId()) - { - case 33872: - spellId = 47179; - break; - case 33873: - spellId = 47180; - break; - } - m_target->CastSpell(m_target, spellId, true, NULL, this); - } - // Master Shapeshifter - Cat - if (AuraEffect const * aurEff = m_target->GetDummyAura(SPELLFAMILY_GENERIC, 2851, 0)) - { - int32 bp = aurEff->GetAmount(); - m_target->CastCustomSpell(m_target, 48420, &bp, NULL, NULL, true); - } - break; - case FORM_DIREBEAR: - case FORM_BEAR: - // Master Shapeshifter - Bear - if (AuraEffect const * aurEff = m_target->GetDummyAura(SPELLFAMILY_GENERIC, 2851, 0)) - { - int32 bp = aurEff->GetAmount(); - m_target->CastCustomSpell(m_target, 48418, &bp, NULL, NULL, true); - } - // Survival of the Fittest - if (AuraEffect const * aurEff = m_target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE,SPELLFAMILY_DRUID, 961, 0)) - { - int32 bp = m_target->CalculateSpellDamage(aurEff->GetSpellProto(),2,aurEff->GetSpellProto()->EffectBasePoints[2],m_target); - m_target->CastCustomSpell(m_target, 62069,&bp, NULL, NULL, true, 0, this); - } - break; - case FORM_MOONKIN: - // Master Shapeshifter - Moonkin - if (AuraEffect const * aurEff = m_target->GetDummyAura(SPELLFAMILY_GENERIC, 2851, 0)) - { - int32 bp = aurEff->GetAmount(); - m_target->CastCustomSpell(m_target, 48421, &bp, NULL, NULL, true); - } - break; - // Master Shapeshifter - Tree of Life - case FORM_TREE: - if (AuraEffect const * aurEff = m_target->GetDummyAura(SPELLFAMILY_GENERIC, 2851, 0)) - { - int32 bp = aurEff->GetAmount(); - m_target->CastCustomSpell(m_target, 48422, &bp, NULL, NULL, true); - } - break; + if( !target->HasAura(itr->second->spellId) ) + target->CastSpell(target,itr->second->spellId,true); } } } - else - { - if (spellId) - m_target->RemoveAurasDueToSpell(spellId); - if (spellId2) - m_target->RemoveAurasDueToSpell(spellId2); - - // Improved Barkskin - apply/remove armor bonus due to shapeshift - if (((Player*)m_target)->HasSpell(63410) || ((Player*)m_target)->HasSpell(63411)) - { - m_target->RemoveAurasDueToSpell(66530); - m_target->CastSpell(m_target,66530,true); - } - - Unit::AuraMap& tAuras = m_target->GetAuras(); - for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) - { - if (itr->second->IsRemovedOnShapeLost()) - m_target->RemoveAura(itr); - else - ++itr; - } - } -} - -bool AuraEffect::isAffectedOnSpell(SpellEntry const *spell) const -{ - if (!spell) - return false; - // Check family name - if (spell->SpellFamilyName != m_spellProto->SpellFamilyName) - return false; - - // Check EffectClassMask - if (m_spellProto->EffectSpellClassMask[m_effIndex] & spell->SpellFamilyFlags) - return true; - return false; -} - -void Aura::UnregisterSingleCastAura() -{ - if (IsSingleTarget()) - { - Unit* caster = NULL; - caster = GetCaster(); - if(caster) - { - caster->GetSingleCastAuras().remove(this); - } - else - { - sLog.outCrash("Couldn't find the caster (guid: "UI64FMTD") of the single target aura %u which is on unit entry %u class %u, may crash later!", GetCasterGUID(), GetId(), m_target->GetEntry(), m_target->getClass()); - assert(false); - } - m_isSingleTargetAura = false; - } -} - -/*********************************************************/ -/*** BASIC AURA FUNCTION ***/ -/*********************************************************/ -void AuraEffect::HandleAddModifier(bool apply, bool Real, bool changeAmount) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER || (!Real && !changeAmount)) - return; - - uint32 modOp = GetMiscValue(); - - if(modOp >= MAX_SPELLMOD) - return; - + // mods at aura apply if (apply) { - SpellModifier *mod = new SpellModifier(GetParentAura()); - mod->op = SpellModOp(modOp); - mod->value = m_amount; - mod->type = SpellModType(m_auraName); // SpellModType value == spell aura types - mod->spellId = GetId(); - mod->mask = m_spellProto->EffectSpellClassMask[m_effIndex]; - mod->charges = GetParentAura()->GetAuraCharges(); - - m_spellmod = mod; - } - - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - - // Auras with charges do not mod amount of passive auras - if (GetParentAura()->GetAuraCharges()) - return; - - // reapply some passive spells after add/remove related spellmods - // Warning: it is a dead loop if 2 auras each other amount-shouldn't happen - switch (modOp) - { - case SPELLMOD_ALL_EFFECTS: - case SPELLMOD_EFFECT1: - case SPELLMOD_EFFECT2: - case SPELLMOD_EFFECT3: + // Apply linked auras (On first aura apply) + if(spellmgr.GetSpellCustomAttr(GetId()) & SPELL_ATTR_CU_LINK_AURA) { - uint64 guid = m_target->GetGUID(); - Unit::AuraMap & auras = m_target->GetAuras(); - for (Unit::AuraMap::iterator iter = auras.begin(); iter != auras.end(); ++iter) - { - Aura * aur = iter->second; - // only passive auras-active auras should have amount set on spellcast and not be affected - // if aura is casted by others, it will not be affected - if (aur->IsPassive() && aur->GetCasterGUID() == guid && spellmgr.IsAffectedByMod(aur->GetSpellProto(), m_spellmod)) + if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(GetId() + SPELL_LINK_AURA)) + for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) { - if (modOp == SPELLMOD_ALL_EFFECTS) - { - for (uint8 i = 0; i<MAX_SPELL_EFFECTS; ++i) - { - if (AuraEffect * aurEff = aur->GetPartAura(i)) - aurEff->RecalculateAmount(); - } - } - else if (modOp ==SPELLMOD_EFFECT1) - { - if (AuraEffect * aurEff = aur->GetPartAura(0)) - aurEff->RecalculateAmount(); - } - else if (modOp ==SPELLMOD_EFFECT2) - { - if (AuraEffect * aurEff = aur->GetPartAura(1)) - aurEff->RecalculateAmount(); - } - else //if (modOp ==SPELLMOD_EFFECT3) - { - if (AuraEffect * aurEff = aur->GetPartAura(2)) - aurEff->RecalculateAmount(); - } + if(*itr < 0) + target->ApplySpellImmune(GetId(), IMMUNITY_ID, -(*itr), true); + else if(caster) + caster->AddAura(*itr, target); } - } } - default: - break; - } - if (m_spellProto->Id == 11129 && !apply) - { - m_target->RemoveAurasDueToSpell(28682); - } -} - -void AuraEffect::TriggerSpell() -{ - Unit* caster = GetCaster(); - Unit* target = GetTriggerTarget(); - - if(!caster || !target) - return; - - // generic casting code with custom spells and target/caster customs - uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; - - SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); - SpellEntry const *auraSpellInfo = GetSpellProto(); - uint32 auraId = auraSpellInfo->Id; - - // specific code for cases with no trigger spell provided in field - if (triggeredSpellInfo == NULL) - { - switch(auraSpellInfo->SpellFamilyName) + switch (GetSpellProto()->SpellFamilyName) { case SPELLFAMILY_GENERIC: - { - switch(auraId) + switch(GetId()) { - // Firestone Passive (1-5 ranks) - case 758: - case 17945: - case 17947: - case 17949: - case 27252: - { - if (caster->GetTypeId() != TYPEID_PLAYER) - return; - Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK); - if (!item) - return; - uint32 enchant_id = 0; - switch (GetId()) - { - case 758: enchant_id = 1803; break; // Rank 1 - case 17945: enchant_id = 1823; break; // Rank 2 - case 17947: enchant_id = 1824; break; // Rank 3 - case 17949: enchant_id = 1825; break; // Rank 4 - case 27252: enchant_id = 2645; break; // Rank 5 - default: - return; - } - // remove old enchanting before applying new - ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); - item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_amplitude+1000, 0); - // add new enchanting - ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true); - return; - } - // Thaumaturgy Channel - case 9712: trigger_spell_id = 21029; break; - case 23170: - { - m_target->CastSpell(m_target, 23171, true, 0, this); - return; - } - // Restoration - case 23493: - { - int32 heal = caster->GetMaxHealth() / 10; - caster->DealHeal(m_target, heal, auraSpellInfo); - - int32 mana = caster->GetMaxPower(POWER_MANA); - if (mana) - { - mana /= 10; - caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA); - } - return; - } - // Nitrous Boost - case 27746: - { - if (caster->GetPower(POWER_MANA) >= 10) - { - caster->ModifyPower( POWER_MANA, -10 ); - caster->SendEnergizeSpellLog(caster, 27746, -10, POWER_MANA); - } else - { - caster->RemoveAurasDueToSpell(27746); - return; - } - } break; - // Frost Blast - case 27808: - caster->CastCustomSpell(29879, SPELLVALUE_BASE_POINT0, (float)m_target->GetMaxHealth()*0.26f, m_target, true, NULL, this); - return; - // Detonate Mana - case 27819: - if(int32 mana = (int32)(m_target->GetMaxPower(POWER_MANA) / 4)) - { - mana = m_target->ModifyPower(POWER_MANA, -mana); - m_target->CastCustomSpell(27820, SPELLVALUE_BASE_POINT0, -mana*4, NULL, true, NULL, this, caster->GetGUID()); - } - return; - // Inoculate Nestlewood Owlkin - case 29528: - if(target->GetTypeId()!=TYPEID_UNIT)// prevent error reports in case ignored player target - return; + case 32474: // Buffeting Winds of Susurrus + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->ActivateTaxiPathTo(506, GetId()); break; - // Feed Captured Animal - case 29917: trigger_spell_id = 29916; break; - // Extract Gas - case 30427: - { - // move loot to player inventory and despawn target - if(caster->GetTypeId() ==TYPEID_PLAYER && - target->GetTypeId() == TYPEID_UNIT && - ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD) - { - Player* player = (Player*)caster; - Creature* creature = (Creature*)target; - // missing lootid has been reported on startup - just return - if (!creature->GetCreatureInfo()->SkinLootId) - return; - - player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId,LootTemplates_Skinning,true); - - creature->ForcedDespawn(); - } - return; - } - // Quake - case 30576: trigger_spell_id = 30571; break; - // Doom - case 31347: - { - m_target->CastSpell(m_target,31350,true, NULL, this); - m_target->Kill(m_target); - return; - } - // Spellcloth - case 31373: - { - // Summon Elemental after create item - caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); - return; - } - // Flame Quills - case 34229: - { - // cast 24 spells 34269-34289, 34314-34316 - for (uint32 spell_id = 34269; spell_id != 34290; ++spell_id) - caster->CastSpell(m_target,spell_id,true, NULL, this); - for (uint32 spell_id = 34314; spell_id != 34317; ++spell_id) - caster->CastSpell(m_target,spell_id,true, NULL, this); - return; - } - // Remote Toy - case 37027: trigger_spell_id = 37029; break; - // Eye of Grillok - case 38495: - { - m_target->CastSpell(m_target, 38530, true, NULL, this); - return; - } - // Absorb Eye of Grillok (Zezzak's Shard) - case 38554: - { - if(m_target->GetTypeId() != TYPEID_UNIT) - return; - - caster->CastSpell(caster, 38495, true, NULL, this); - - Creature* creatureTarget = (Creature*)m_target; - - creatureTarget->ForcedDespawn(); - return; - } - // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam - case 39857: trigger_spell_id = 39856; break; - // Aura of Desire - case 41350: - { - AuraEffect * aurEff = GetParentAura()->GetPartAura(1); - aurEff->ApplyModifier(false, false, true); - aurEff->SetAmount(aurEff->GetAmount()-5); - aurEff->ApplyModifier(true, false, true); + case 33572: // Gronn Lord's Grasp, becomes stoned + if(GetStackAmount() >= 5 && !target->HasAura(33652)) + target->CastSpell(target, 33652, true); break; - } - case 46736: trigger_spell_id = 46737; break; - default: + case 60970: // Heroic Fury (remove Intercept cooldown) + if(target->GetTypeId() == TYPEID_PLAYER) + ((Player*)target)->RemoveSpellCooldown(20252, true); break; } break; - } case SPELLFAMILY_MAGE: - { - switch(auraId) - { - // Invisibility - case 66: - // Here need periodic triger reducing threat spell (or do it manually) - return; - default: - break; - } - break; - } - case SPELLFAMILY_DRUID: - { - switch(auraId) + if (!caster) + break; + if (GetSpellProto()->SpellFamilyFlags[0] & 0x00000001 && GetSpellProto()->SpellFamilyFlags[2] & 0x00000008) { - // Cat Form - // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while - case 768: - return; - default: - break; + // Glyph of Fireball + if (caster->HasAura(56368)) + SetDuration(0); } - break; - } - case SPELLFAMILY_HUNTER: - { - switch (auraId) + else if (GetSpellProto()->SpellFamilyFlags[0] & 0x00000020 && GetSpellProto()->SpellVisual[0] == 13) { - // Sniper training - case 53302: - case 53303: - case 53304: - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if (((Player*)m_target)->isMoving()) - { - m_amount = m_target->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,m_target); - return; - } - - // We are standing at the moment - if (m_amount > 0) - { - --m_amount; - return; - } - - trigger_spell_id = 64418 + auraId - 53302; - - // If aura is active - no need to continue - if (target->HasAura(trigger_spell_id)) - return; - - break; - default: - break; + // Glyph of Frostbolt + if (caster->HasAura(56370)) + SetDuration(0); } - break; - } - case SPELLFAMILY_SHAMAN: - { - switch(auraId) + // Todo: This should be moved to similar function in spell::hit + else if (GetSpellProto()->SpellFamilyFlags[0] & 0x01000000) { - // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield) - case 28820: + // Polymorph Sound - Sheep && Penguin + if (GetSpellProto()->SpellIconID == 82 && GetSpellProto()->SpellVisual[0] == 12978) { - // Need remove self if Lightning Shield not active - if (!target->GetAura(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN,0x400)) - target->RemoveAurasDueToSpell(28820); - return; + // Glyph of the Penguin + if (caster->HasAura(52648)) + caster->CastSpell(target,61635,true); + else + caster->CastSpell(target,61634,true); } - // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus) - case 38443: - { - bool all = true; - for (int i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i) + } + switch(GetId()) + { + case 12536: // Clearcasting + case 12043: // Presence of Mind + // Arcane Potency + if (AuraEffect const * aurEff = caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_MAGE, 2120, 0)) { - if(!caster->m_SummonSlot[i]) + if (roll_chance_i(aurEff->GetAmount())) { - all = false; - break; + uint32 spellId = 0; + + switch (aurEff->GetId()) + { + case 31571: spellId = 57529; break; + case 31572: spellId = 57531; break; + default: + sLog.outError("Aura::HandleAuraSpecificMods: Unknown rank of Arcane Potency (%d) found", aurEff->GetId()); + } + if(spellId) + caster->CastSpell(caster, spellId, true); } } - - if(all) - caster->CastSpell(caster,38437,true, NULL, this); - else - caster->RemoveAurasDueToSpell(38437); - return; - } - default: break; } break; - } - default: - break; - } - - // Reget trigger spell proto - triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); - } - else - { - // Spell exist but require custom code - switch(auraId) - { - // Mana Tide - case 16191: - { - caster->CastCustomSpell(target, trigger_spell_id, &m_amount, NULL, NULL, true, NULL, this); - return; - } - // Negative Energy Periodic - case 46284: - caster->CastCustomSpell(trigger_spell_id, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this); - return; - // Poison (Grobbulus) - case 28158: - case 54362: - m_target->CastCustomSpell(trigger_spell_id, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000), NULL, true, NULL, this); - return; - // Mind Sear (target 76/16) if let m_target cast, will damage caster - case 48045: - case 53023: - // Curse of the Plaguebringer (22/15) - case 29213: - case 54835: - caster->CastSpell(m_target, trigger_spell_id, true, NULL, this); - return; - // Ground Slam - case 33525: - target->CastSpell(target, trigger_spell_id, true); - return; - } - } - - if(triggeredSpellInfo) - { - if(!caster->GetSpellMaxRangeForTarget(m_target,sSpellRangeStore.LookupEntry(triggeredSpellInfo->rangeIndex))) - target = m_target; //for druid dispel poison - m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, GetCasterGUID()); - } - else if(target->GetTypeId()!=TYPEID_UNIT || !Script->EffectDummyCreature(caster, GetId(), GetEffIndex(), (Creature*)target)) - sLog.outError("AuraEffect::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex()); -} - -Unit* AuraEffect::GetTriggerTarget() const -{ - Unit* target = ObjectAccessor::GetUnit(*m_target, m_target->GetUInt64Value(UNIT_FIELD_TARGET)); - return target ? target : m_target; -} - -void AuraEffect::TriggerSpellWithValue() -{ - Unit* caster = GetCaster(); - Unit* target = GetTriggerTarget(); - - if(!caster || !target) - return; - - // generic casting code with custom spells and target/caster customs - uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; - int32 basepoints0 = this->GetAmount(); - - caster->CastCustomSpell(target, trigger_spell_id, &basepoints0, 0, 0, true, 0, this); -} - -/*********************************************************/ -/*** AURA EFFECTS ***/ -/*********************************************************/ - -void AuraEffect::HandleAuraDummy(bool apply, bool Real, bool changeAmount) -{ - Unit* caster = GetCaster(); - - // spells required only Real aura add/remove - if (Real) - { - // AT APPLY - if(apply) - { - // Overpower - if (caster && m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && - m_spellProto->SpellFamilyFlags[0] & 0x4) - { - // Must be casting target - if (!m_target->IsNonMeleeSpellCasted(false, false, true)) - return; - if (AuraEffect * aurEff = caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARRIOR, 2775, 0)) - { - switch (aurEff->GetId()) + case SPELLFAMILY_WARLOCK: + switch(GetId()) { - // Unrelenting Assault, rank 1 - case 46859: - m_target->CastSpell(m_target,64849,true,NULL,aurEff); - break; - // Unrelenting Assault, rank 2 - case 46860: - m_target->CastSpell(m_target,64850,true,NULL,aurEff); + case 48020: // Demonic Circle + if(target->GetTypeId() == TYPEID_PLAYER) + if(GameObject* obj = target->GetGameObject(48018)) + ((Player*)target)->TeleportTo(obj->GetMapId(),obj->GetPositionX(),obj->GetPositionY(),obj->GetPositionZ(),obj->GetOrientation()); break; } - } - return; - } - switch(GetId()) - { - // Haunting Spirits - perdiodic trigger demon - case 7057: - m_isPeriodic = true; - m_amplitude = irand (0, 60) + 30; - m_amplitude *= IN_MILISECONDS; - return; - case 1515: // Tame beast - // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness - if( caster && m_target->CanHaveThreatList()) - m_target->AddThreat(caster, 10.0f); - return; - case 13139: // net-o-matic - // root to self part of (root_target->charge->root_self sequence - if(caster) - caster->CastSpell(caster,13138,true,NULL,this); - return; - case 34026: // kill command - { - Unit * pet = m_target->GetGuardianPet(); - if (!pet) - return; - - m_target->CastSpell(m_target,34027,true,NULL,this); - - // set 3 stacks and 3 charges (to make all auras not disappear at once) - Aura* owner_aura = m_target->GetAura(34027,GetCasterGUID()); - Aura* pet_aura = pet->GetAura(58914, GetCasterGUID()); - if( owner_aura ) - { - owner_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount); - } - if( pet_aura ) + break; + case SPELLFAMILY_PRIEST: + if (!caster) + break; + // Devouring Plague + if (GetSpellProto()->SpellFamilyFlags[0] & 0x02000000 && GetEffect(0)) { - pet_aura->SetAuraCharges(0); - pet_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount); + // Improved Devouring Plague + if (AuraEffect const * aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 1)) + { + int32 basepoints0 = aurEff->GetAmount() * GetEffect(0)->GetTotalTicks() * GetEffect(0)->GetAmount() / 100; + caster->CastCustomSpell(target, 63675, &basepoints0, NULL, NULL, true, NULL, GetEffect(0)); + } } - return; - } - case 37096: // Blood Elf Illusion - { - if(caster) + // Renew + else if (GetSpellProto()->SpellFamilyFlags[0] & 0x00000040 && GetEffect(0)) { - switch(caster->getGender()) + // Empowered Renew + if (AuraEffect const * aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3021, 1)) { - case GENDER_FEMALE: - caster->CastSpell(m_target,37095,true,NULL,this); // Blood Elf Disguise - break; - case GENDER_MALE: - caster->CastSpell(m_target,37093,true,NULL,this); - break; - default: - break; + int32 basepoints0 = aurEff->GetAmount() * GetEffect(0)->GetTotalTicks() * caster->SpellHealingBonus(target, GetSpellProto(), GetEffect(0)->GetAmount(), HEAL) / 100; + caster->CastCustomSpell(target, 63544, &basepoints0, NULL, NULL, true, NULL, GetEffect(0)); } } - return; - } - case 55198: // Tidal Force - { - m_target->CastSpell(m_target,55166,true,NULL,this); - // set 3 stacks and 3 charges (to make all auras not disappear at once) - Aura* owner_aura = m_target->GetAura(55166,GetCasterGUID()); - if( owner_aura ) + // Power Word: Shield + else if (m_spellProto->SpellFamilyFlags[0] & 0x1 && m_spellProto->SpellFamilyFlags[2] & 0x400 && GetEffect(0)) { - // This aura lasts 2 sec, need this hack to properly proc spells - // TODO: drop aura charges for ApplySpellMod in ProcDamageAndSpell - GetParentAura()->SetAuraDuration(owner_aura->GetAuraDuration()); - // Make aura be not charged-this prevents removing charge on not crit spells - owner_aura->SetAuraCharges(0); - owner_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount); + // Glyph of Power Word: Shield + if (AuraEffect* glyph = caster->GetAuraEffect(55672,0)) + { + // instantly heal m_amount% of the absorb-value + int32 heal = glyph->GetAmount() * GetEffect(0)->GetAmount()/100; + caster->CastCustomSpell(GetUnitOwner(), 56160, &heal, NULL, NULL, true, 0, GetEffect(0)); + } } - return; - } - case 49028: - GetParentAura()->SetAuraDuration(GetParentAura()->GetAuraDuration() + (caster->GetPower(POWER_RUNIC_POWER) * 10)); - caster->SetPower(POWER_RUNIC_POWER, 0); break; - case 39850: // Rocket Blast - if(roll_chance_i(20)) // backfire stun - m_target->CastSpell(m_target, 51581, true, NULL, this); - return; - case 43873: // Headless Horseman Laugh - m_target->PlayDistanceSound(11965); - return; - case 46354: // Blood Elf Illusion - if(caster) + case SPELLFAMILY_ROGUE: + // Sprint (skip non player casted spells by category) + if(GetSpellProto()->SpellFamilyFlags[0] & 0x40 && GetSpellProto()->Category == 44) + // in official maybe there is only one icon? + if(target->HasAura(58039)) // Glyph of Blurred Speed + target->CastSpell(target, 61922, true); // Sprint (waterwalk) + break; + case SPELLFAMILY_DEATHKNIGHT: + if (!caster) + break; + // Frost Fever and Blood Plague + if(GetSpellProto()->SpellFamilyFlags[2] & 0x2) { - switch(caster->getGender()) + // Can't proc on self + if (GetCasterGUID() == target->GetGUID()) + break; + + AuraEffect * aurEff = NULL; + // Ebon Plaguebringer / Crypt Fever + Unit::AuraEffectList const& TalentAuras = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for (Unit::AuraEffectList::const_iterator itr = TalentAuras.begin(); itr != TalentAuras.end(); ++itr) { - case GENDER_FEMALE: - caster->CastSpell(m_target,46356,true,NULL,this); - break; - case GENDER_MALE: - caster->CastSpell(m_target,46355,true,NULL,this); - break; - default: - break; + if ((*itr)->GetMiscValue() == 7282) + { + aurEff = *itr; + // Ebon Plaguebringer - end search if found + if ((*itr)->GetSpellProto()->SpellIconID == 1766) + break; + } + } + if (aurEff) + { + uint32 spellId = 0; + switch (aurEff->GetId()) + { + // Ebon Plague + case 51161: spellId = 51735; break; + case 51160: spellId = 51734; break; + case 51099: spellId = 51726; break; + // Crypt Fever + case 49632: spellId = 50510; break; + case 49631: spellId = 50509; break; + case 49032: spellId = 50508; break; + default: + sLog.outError("Aura::HandleAuraSpecificMods: Unknown rank of Crypt Fever/Ebon Plague (%d) found", aurEff->GetId()); + } + caster->CastSpell(target, spellId, true, 0, GetEffect(0)); } } - return; - case 46699: // Requires No Ammo - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use - return; - case 62061: // Festive Holiday Mount - if(m_target->HasAuraType(SPELL_AURA_MOUNTED)) - m_target->CastSpell(m_target, 25860, true, NULL, this); // Reindeer Transformation - return; - case 52916: // Honor Among Thieves - if(m_target->GetTypeId() == TYPEID_PLAYER) - if (Unit * target = ObjectAccessor::GetUnit(*m_target,((Player*)m_target)->GetComboTarget())) - m_target->CastSpell(target, 51699, true); - return; - } - - //Druid, Survival Instincts - if(GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags[2]& 0x40 ) - { - if(!m_target) - return; - - int32 bp0 = int32(m_target->GetMaxHealth() * m_amount / 100); - m_target->CastCustomSpell(m_target, 50322, &bp0, NULL, NULL, true); + break; } } - // AT REMOVE + // mods at aura remove else { - if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive()) + // Remove Linked Auras + if(removeMode != AURA_REMOVE_BY_STACK && removeMode != AURA_REMOVE_BY_DEATH) { - uint32 finalSpelId = 0; - switch(GetId()) + if(uint32 customAttr = spellmgr.GetSpellCustomAttr(GetId())) { - case 19548: finalSpelId = 19597; break; - case 19674: finalSpelId = 19677; break; - case 19687: finalSpelId = 19676; break; - case 19688: finalSpelId = 19678; break; - case 19689: finalSpelId = 19679; break; - case 19692: finalSpelId = 19680; break; - case 19693: finalSpelId = 19684; break; - case 19694: finalSpelId = 19681; break; - case 19696: finalSpelId = 19682; break; - case 19697: finalSpelId = 19683; break; - case 19699: finalSpelId = 19685; break; - case 19700: finalSpelId = 19686; break; - case 30646: finalSpelId = 30647; break; - case 30653: finalSpelId = 30648; break; - case 30654: finalSpelId = 30652; break; - case 30099: finalSpelId = 30100; break; - case 30102: finalSpelId = 30103; break; - case 30105: finalSpelId = 30104; break; - } - - if(finalSpelId) - caster->CastSpell(m_target,finalSpelId,true,NULL,this); - return; - } - - switch(m_spellProto->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - switch(GetId()) + if(customAttr & SPELL_ATTR_CU_LINK_REMOVE) { - case 2584: // Waiting to Resurrect - { - // Waiting to resurrect spell cancel, we must remove player from resurrect queue - if (m_target->GetTypeId() == TYPEID_PLAYER) - if (BattleGround *bg = ((Player*)m_target)->GetBattleGround()) - bg->RemovePlayerFromResurrectQueue(m_target->GetGUID()); - return; - } - case 28169: // Mutating Injection - { - // Mutagen Explosion - m_target->CastSpell(m_target, 28206, true, NULL, this); - // Poison Cloud - m_target->CastSpell(m_target, 28240, true, NULL, this); - return; - } - case 36730: // Flame Strike - { - m_target->CastSpell(m_target, 36731, true, NULL, this); - return; - } - case 44191: // Flame Strike - { - if (m_target->GetMap()->IsDungeon()) + if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)GetId())) + for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) { - uint32 spellId = ((InstanceMap*)m_target->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY ? 44190 : 46163; - - m_target->CastSpell(m_target, spellId, true, NULL, this); + if(*itr < 0) + target->RemoveAurasDueToSpell(-(*itr)); + else if (removeMode != AURA_REMOVE_BY_DEFAULT) + target->CastSpell(target, *itr, true, 0, 0, GetCasterGUID()); } - return; - } - case 42783: // Wrath of the Astromancer - m_target->CastSpell(m_target,m_amount,true,NULL,this); - return; - case 46308: // Burning Winds casted only at creatures at spawn - m_target->CastSpell(m_target,47287,true,NULL,this); - return; - case 52172: // Coyote Spirit Despawn Aura - case 60244: // Blood Parrot Despawn Aura - m_target->CastSpell((Unit*)NULL, GetAmount(), true, NULL, this); - return; - } - break; - case SPELLFAMILY_MAGE: - // Living Bomb - if(m_spellProto->SpellFamilyFlags[1] & 0x20000) - { - if(caster && (GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL || GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)) - caster->CastSpell(m_target, GetAmount(), true); - return; - } - break; - case SPELLFAMILY_WARLOCK: - // Haunt - if(m_spellProto->SpellFamilyFlags[1] & 0x40000) - { - int32 bp0 = GetParentAura()->GetProcDamage() * m_amount / 100; - if(caster) - caster->CastCustomSpell(caster, 48210, &bp0, 0, 0, true, NULL, this); - return; } - break; - case SPELLFAMILY_PALADIN: - switch (GetSpellProto()->SpellIconID) - { - // Blessing of Sanctuary - // Greater Blessing of Sanctuary - case 19: - case 1804: + if(customAttr & SPELL_ATTR_CU_LINK_AURA) { - if (!caster || !m_target) - return; - - if (apply) - { - // Greater Blessing of Sanctuary does not provide strength bonus - int32 bp1 = 0; - caster->CastCustomSpell(m_target, 67480, NULL, (GetSpellProto()->SpellIconID == 1804) ? &bp1 : NULL, NULL, true); - } - else - m_target->RemoveAurasDueToSpell(67480); - - return; + if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(GetId() + SPELL_LINK_AURA)) + for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) + { + if(*itr < 0) + target->ApplySpellImmune(GetId(), IMMUNITY_ID, -(*itr), false); + else + target->RemoveAurasDueToSpell(*itr); + } } } - break; - case SPELLFAMILY_PRIEST: - // Vampiric Touch - if (m_spellProto->SpellFamilyFlags[1] & 0x0400 && GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL) + } + switch(GetSpellProto()->SpellFamilyName) + { + case SPELLFAMILY_MAGE: + switch(GetId()) { - if (AuraEffect const * aurEff = GetParentAura()->GetPartAura(1)) - { - int32 damage = aurEff->GetAmount()*4; - // backfire damage - m_target->CastCustomSpell(m_target, 64085, &damage, NULL, NULL, true, NULL, NULL,GetCasterGUID()); - } + case 66: // Invisibility + if (removeMode != AURA_REMOVE_BY_EXPIRE) + break; + target->CastSpell(target, 32612, true, NULL, GetEffect(1)); + break; } - break; - case SPELLFAMILY_HUNTER: - // Misdirection - if(GetId()==34477) + if (!caster) + break; + // Ice barrier - dispel/absorb remove + if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellProto()->SpellFamilyFlags[1] & 0x1) { - m_target->SetReducedThreatPercent(0, 0); - return; + // Shattered Barrier + if (caster->GetDummyAuraEffect(SPELLFAMILY_MAGE, 2945, 0)) + caster->CastSpell(target, 55080, true, NULL, GetEffect(0)); } break; - case SPELLFAMILY_DEATHKNIGHT: - // Summon Gargoyle ( will start feeding gargoyle ) - if(GetId()==61777) + case SPELLFAMILY_WARRIOR: + if (!caster) + break; + // Spell Reflection + if (GetSpellProto()->SpellFamilyFlags[1] & 0x2) { - m_target->CastSpell(m_target,m_spellProto->EffectTriggerSpell[m_effIndex],true); - return; + if (removeMode != AURA_REMOVE_BY_DEFAULT) + { + // Improved Spell Reflection + if (caster->GetDummyAuraEffect(SPELLFAMILY_WARRIOR,1935, 1)) + { + // aura remove - remove auras from all party members + std::list<Unit*> PartyMembers; + target->GetPartyMembers(PartyMembers); + for (std::list<Unit*>::iterator itr = PartyMembers.begin(); itr!=PartyMembers.end(); ++itr) + { + if ((*itr)!= target) + (*itr)->RemoveAurasWithFamily(SPELLFAMILY_WARRIOR, 0, 0x2, 0, GetCasterGUID()); + } + } + } } break; - default: - break; - } - } - } - - // AT APPLY & REMOVE - - switch(m_spellProto->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - if (!Real) - break; - switch(GetId()) - { - // Recently Bandaged - case 11196: - m_target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, GetMiscValue(), apply); - return; - // Unstable Power - case 24658: + case SPELLFAMILY_WARLOCK: + if (!caster) + break; + // Curse of Doom + if (GetSpellProto()->SpellFamilyFlags[1] & 0x02) { - uint32 spellId = 24659; - if (apply && caster) + if (removeMode == AURA_REMOVE_BY_DEATH) { - const SpellEntry *spell = sSpellStore.LookupEntry(spellId); - if (!spell) - return; - - for (int i=0; i < spell->StackAmount; ++i) - caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); - return; + if (caster->GetTypeId() == TYPEID_PLAYER && ((Player*)caster)->isHonorOrXPTarget(target)) + caster->CastSpell(target, 18662, true, NULL, GetEffect(0)); } - m_target->RemoveAurasDueToSpell(spellId); - return; } - // Restless Strength - case 24661: + // Improved Fear + else if (GetSpellProto()->SpellFamilyFlags[1] & 0x00000400) { - uint32 spellId = 24662; - if (apply && caster) + if (caster->GetTypeId() == TYPEID_UNIT) { - const SpellEntry *spell = sSpellStore.LookupEntry(spellId); - if (!spell) - return; - for (int i=0; i < spell->StackAmount; ++i) - caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); - return; + if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_WARLOCK, 98, 0)) + { + uint32 spellId = 0; + switch (aurEff->GetId()) + { + case 53759: spellId = 60947; break; + case 53754: spellId = 60946; break; + default: + sLog.outError("Aura::HandleAuraSpecificMods: Unknown rank of Improved Fear (%d) found", aurEff->GetId()); + } + if (spellId) + caster->CastSpell(caster, spellId, true); + } } - m_target->RemoveAurasDueToSpell(spellId); - return; } - //Summon Fire Elemental - case 40133: + switch(GetId()) { - if (!caster) - return; - - Unit *owner = caster->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER) - { - if(apply) - owner->CastSpell(owner,8985,true); - else - ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - } - return; + case 48018: // Demonic Circle + // Do not remove GO when aura is removed by stack + // to prevent remove GO added by new spell + // old one is already removed + if (removeMode!=AURA_REMOVE_BY_STACK) + target->RemoveGameObject(GetId(), true); + target->RemoveAura(62388); + break; } - //Summon Earth Elemental - case 40132 : + break; + case SPELLFAMILY_PRIEST: + if (!caster) + break; + // Shadow word: Pain // Vampiric Touch + if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && (GetSpellProto()->SpellFamilyFlags[0] & 0x00008000 || GetSpellProto()->SpellFamilyFlags[1] & 0x00000400)) { - if (!caster) - return; - - Unit *owner = caster->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER) + // Shadow Affinity + if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 178, 1)) { - if(apply) - owner->CastSpell(owner,19704,true); - else - ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + int32 basepoints0 = aurEff->GetAmount() * target->GetCreateMana() / 100; + caster->CastCustomSpell(caster, 64103, &basepoints0, NULL, NULL, true, NULL, GetEffect(0)); } - return; } - case 57723: // Exhaustion - case 57724: // Sated + // Power word: shield + else if (removeMode == AURA_REMOVE_BY_ENEMY_SPELL && GetSpellProto()->SpellFamilyFlags[0] & 0x00000001) { - switch(GetId()) + // Rapture + if (Aura const * aura = caster->GetAuraOfRankedSpell(47535)) { - case 57723: m_target->ApplySpellImmune(GetId(), IMMUNITY_ID, 32182, apply); break; // Heroism - case 57724: m_target->ApplySpellImmune(GetId(), IMMUNITY_ID, 2825, apply); break; // Bloodlust + // check cooldown + if (caster->GetTypeId() == TYPEID_PLAYER) + { + if (((Player*)caster)->HasSpellCooldown(aura->GetId())) + break; + // and add if needed + ((Player*)caster)->AddSpellCooldown(aura->GetId(), 0, uint32(time(NULL) + 12)); + } + // effect on caster + if (AuraEffect const * aurEff = aura->GetEffect(0)) + { + float multiplier = aurEff->GetAmount(); + if (aurEff->GetId() == 47535) + multiplier -= 0.5f; + else if (aurEff->GetId() == 47537) + multiplier += 0.5f; + + int32 basepoints0 = (multiplier * caster->GetMaxPower(POWER_MANA) / 100); + caster->CastCustomSpell(caster, 47755, &basepoints0, NULL, NULL, true); + } + // effect on aura target + if (AuraEffect const * aurEff = aura->GetEffect(1)) + { + if (!roll_chance_i(aurEff->GetAmount())) + break; + + int32 triggeredSpellId = 0; + switch(target->getPowerType()) + { + case POWER_MANA: + { + int32 basepoints0 = 2 * (target->GetMaxPower(POWER_MANA) / 100); + caster->CastCustomSpell(target, 63654, &basepoints0, NULL, NULL, true); + break; + } + case POWER_RAGE: triggeredSpellId = 63653; break; + case POWER_ENERGY: triggeredSpellId = 63655; break; + case POWER_RUNIC_POWER: triggeredSpellId = 63652; break; + } + if (triggeredSpellId) + caster->CastSpell(target, triggeredSpellId, true); + } } - return; } - case 57819: // Argent Champion - case 57820: // Ebon Champion - case 57821: // Champion of the Kirin Tor - case 57822: // Wyrmrest Champion + switch(GetId()) { - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; - - uint32 FactionID = 0; + case 47788: // Guardian Spirit + if (removeMode != AURA_REMOVE_BY_EXPIRE) + break; + if(caster->GetTypeId() != TYPEID_PLAYER) + break; - if(apply) - { - switch(m_spellProto->Id) + Player *player = ((Player*)caster); + // Glyph of Guardian Spirit + if(AuraEffect * aurEff = player->GetAuraEffect(63231, 0)) { - case 57819: FactionID = 1106; break; // Argent Crusade - case 57820: FactionID = 1098; break; // Knights of the Ebon Blade - case 57821: FactionID = 1090; break; // Kirin Tor - case 57822: FactionID = 1091; break; // The Wyrmrest Accord + if (!player->HasSpellCooldown(47788)) + break; + + player->RemoveSpellCooldown(GetSpellProto()->Id, true); + player->AddSpellCooldown(GetSpellProto()->Id, 0, uint32(time(NULL) + aurEff->GetAmount())); + + WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4+4); + data << uint64(player->GetGUID()); + data << uint8(0x0); // flags (0x1, 0x2) + data << uint32(GetSpellProto()->Id); + data << uint32(aurEff->GetAmount()*IN_MILISECONDS); + player->SendDirectMessage(&data); } - } - ((Player*)caster)->SetChampioningFaction(FactionID); - return; + break; } - // LK Intro VO (1) - case 58204: - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - // Play part 1 - if(apply) - m_target->PlayDirectSound(14970, (Player *)m_target); - // continue in 58205 - else - m_target->CastSpell(m_target, 58205, true); - } - return; - // LK Intro VO (2) - case 58205: - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - // Play part 2 - if(apply) - m_target->PlayDirectSound(14971, (Player *)m_target); - // Play part 3 - else - m_target->PlayDirectSound(14972, (Player *)m_target); - } - return; - } - - break; - } - case SPELLFAMILY_MAGE: - { - //if (!Real) - //break; - break; - } - case SPELLFAMILY_PRIEST: - { - if (!Real && !changeAmount) break; - // Pain and Suffering - if( m_spellProto->SpellIconID == 2874 && m_target->GetTypeId() == TYPEID_PLAYER ) - { - if(apply) + case SPELLFAMILY_DEATHKNIGHT: + switch(GetId()) { - // Reduce backfire damage (dot damage) from Shadow Word: Death - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_DOT; - mod->value = m_amount; - mod->type = SPELLMOD_PCT; - mod->spellId = GetId(); - mod->mask[1] = 0x00002000; - m_spellmod = mod; + case 50514: // Summon Gargoyle + if (removeMode != AURA_REMOVE_BY_EXPIRE) + break; + target->CastSpell(target, GetEffect(0)->GetAmount(), true, NULL, GetEffect(0)); + break; } - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - return; - } - break; - } - case SPELLFAMILY_DRUID: - { - if (!Real && !changeAmount) break; - switch(GetId()) + } + } + + // mods at aura apply or remove + switch (GetSpellProto()->SpellFamilyName) + { + case SPELLFAMILY_ROGUE: + // Stealth + if (GetSpellProto()->SpellFamilyFlags[0] & 0x00400000) { - case 34246: // Idol of the Emerald Queen - case 60779: // Idol of Lush Moss + // Master of subtlety + if (AuraEffect const * aurEff = target->GetAuraEffectOfRankedSpell(31221, 0)) { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if(apply) + if (!apply) + target->CastSpell(target,31666,true); + else { - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_DOT; - mod->value = m_amount/7; - mod->type = SPELLMOD_FLAT; - mod->spellId = GetId(); - mod->mask[1] = 0x0010; - - m_spellmod = mod; + int32 basepoints0 = aurEff->GetAmount(); + target->CastCustomSpell(target,31665, &basepoints0, NULL, NULL ,true); } - - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - return; } - case 61336: // Survival Instincts + // Overkill + if (target->HasAura(58426)) { - if (!Real) - break; - if(apply) - { - if (!m_target->IsInFeralForm()) - return; - - int32 bp0 = int32(m_target->GetMaxHealth() * m_amount / 100); - m_target->CastCustomSpell(m_target, 50322, &bp0, NULL, NULL, true); - } + if (!apply) + target->CastSpell(target,58428,true); else - m_target-> RemoveAurasDueToSpell(50322); - return; + target->CastSpell(target,58427,true); } - } - // Predatory Strikes - if(m_target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563) - { - ((Player*)m_target)->UpdateAttackPowerAndDamage(); - return; - } - if (!Real) break; - // Lifebloom - if ( GetSpellProto()->SpellFamilyFlags[1] & 0x10 ) - { - if (!apply) - { - // Final heal only on dispelled or duration end - if (GetParentAura()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetParentAura()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) - return; - - // final heal - //if(m_target->IsInWorld()) - // This may be a hack, but we need a way to count healing bonus three times - //for (uint8 i = 0; i < GetParentAura()->GetStackAmount(); ++i) - // Update: apparently not anymore, it should only count once, so.. commented out. - m_target->CastCustomSpell(m_target,33778,&m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); - - // restore mana - if (caster) - { - int32 returnmana = (GetSpellProto()->ManaCostPercentage * caster->GetCreateMana() / 100) * GetParentAura()->GetStackAmount() / 2; - caster->CastCustomSpell(caster, 64372, &returnmana, NULL, NULL, true, NULL, this, GetCasterGUID()); - } - } - return; } break; - } - case SPELLFAMILY_SHAMAN: - { - if (!Real) - break; - // Sentry Totem - if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER) + case SPELLFAMILY_HUNTER: + switch(GetId()) { - if (apply) - { - uint64 guid = caster->m_SummonSlot[3]; - if (guid) + case 19574: // Bestial Wrath + // The Beast Within cast on owner if talent present + if ( Unit* owner = target->GetOwner() ) { - Creature *totem = caster->GetMap()->GetCreature(guid); - if (totem && totem->isTotem()) - ((Player*)caster)->CastSpell(totem, 6277, true); + // Search talent + if (owner->HasAura(34692)) + { + if (apply) + owner->CastSpell(owner, 34471, true, 0, GetEffect(0)); + else + owner->RemoveAurasDueToSpell(34471); + } } - } - else - ((Player*)caster)->StopCastingBindSight(); - return; + break; } break; - } - } - - if (Real) - { - // pet auras - if(PetAura const* petSpell = spellmgr.GetPetAura(GetId(), m_effIndex)) - { - if(apply) - m_target->AddPetAura(petSpell); - else - m_target->RemovePetAura(petSpell); - return; - } - - if(GetEffIndex()==0 && m_target->GetTypeId() == TYPEID_PLAYER) - { - SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); - if(saBounds.first != saBounds.second) + case SPELLFAMILY_PALADIN: + switch(GetId()) { - uint32 zone, area; - m_target->GetZoneAndAreaId(zone,area); - - for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - { - // some auras remove at aura remove - if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area)) - m_target->RemoveAurasDueToSpell(itr->second->spellId); - // some auras applied at aura apply - else if(itr->second->autocast) + case 19746: + case 31821: + // Aura Mastery Triggered Spell Handler + // If apply Concentration Aura -> trigger -> apply Aura Mastery Immunity + // If remove Concentration Aura -> trigger -> remove Aura Mastery Immunity + // If remove Aura Mastery -> trigger -> remove Aura Mastery Immunity + // Do effects only on aura owner + if (GetCasterGUID() != target->GetGUID()) + break; + if (apply) { - if( !m_target->HasAuraEffect(itr->second->spellId,0) ) - m_target->CastSpell(m_target,itr->second->spellId,true); + if ((GetSpellProto()->Id == 31821 && target->HasAura(19746, GetCasterGUID())) || (GetSpellProto()->Id == 19746 && target->HasAura(31821))) + target->CastSpell(target,64364,true); } - } + else + target->RemoveAurasDueToSpell(64364, GetCasterGUID()); + break; } - } - } -} - -void AuraEffect::HandleAuraMounted(bool apply, bool Real, bool /*changeAmount*/) -{ - // only at real add/remove aura - if(!Real) - return; - - if(apply) - { - CreatureInfo const* ci = objmgr.GetCreatureTemplate(GetMiscValue()); - if(!ci) - { - sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)",GetMiscValue()); - return; - } - - uint32 team = 0; - if (m_target->GetTypeId() == TYPEID_PLAYER) - team = ((Player*)m_target)->GetTeam(); - - uint32 display_id = objmgr.ChooseDisplayId(team,ci); - CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); - if (minfo) - display_id = minfo->modelid; - - //some spell has one aura of mount and one of vehicle - for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) - if(GetSpellProto()->Effect[i] == SPELL_EFFECT_SUMMON - && GetSpellProto()->EffectMiscValue[i] == GetMiscValue()) - display_id = 0; - m_target->Mount(display_id); - } - else - { - m_target->Unmount(); - //some mounts like Headless Horseman's Mount or broom stick are skill based spell - // need to remove ALL arura related to mounts, this will stop client crash with broom stick - // and never endless flying after using Headless Horseman's Mount - m_target->RemoveAurasByType(SPELL_AURA_MOUNTED); - } -} - -void AuraEffect::HandleAuraWaterWalk(bool apply, bool Real, bool /*changeAmount*/) -{ - // only at real add/remove aura - if(!Real) - return; - - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_WATER_WALK, 8+4); - else - data.Initialize(SMSG_MOVE_LAND_WALK, 8+4); - data.append(m_target->GetPackGUID()); - data << uint32(0); - m_target->SendMessageToSet(&data,true); -} - -void AuraEffect::HandleAuraFeatherFall(bool apply, bool Real, bool /*changeAmount*/) -{ - // only at real add/remove aura - if (!Real) - return; - - if (!m_target) - return; - - WorldPacket data; - if (apply) - data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4); - else - data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4); - data.append(m_target->GetPackGUID()); - data << uint32(0); - m_target->SendMessageToSet(&data, true); - - // start fall from current height - if(!apply && m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->SetFallInformation(0, m_target->GetPositionZ()); -} - -void AuraEffect::HandleAuraHover(bool apply, bool Real, bool /*changeAmount*/) -{ - // only at real add/remove aura - if(!Real) - return; - - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_SET_HOVER, 8+4); - else - data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4); - data.append(m_target->GetPackGUID()); - data << uint32(0); - m_target->SendMessageToSet(&data,true); -} - -void AuraEffect::HandleWaterBreathing(bool apply, bool Real, bool /*changeAmount*/) -{ - // update timers in client - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->UpdateMirrorTimers(); -} - -void AuraEffect::HandleAuraModShapeshift(bool apply, bool Real, bool changeAmount) -{ - if(!Real && !changeAmount) - return; - - uint32 modelid = 0; - Powers PowerType = POWER_MANA; - ShapeshiftForm form = ShapeshiftForm(GetMiscValue()); - switch(form) - { - case FORM_CAT: - case FORM_GHOUL: - PowerType = POWER_ENERGY; - break; - case FORM_BEAR: - case FORM_DIREBEAR: - case FORM_BATTLESTANCE: - case FORM_BERSERKERSTANCE: - case FORM_DEFENSIVESTANCE: - PowerType = POWER_RAGE; - break; - case FORM_TRAVEL: - case FORM_AQUA: - case FORM_CREATUREBEAR: - case FORM_GHOSTWOLF: - case FORM_FLIGHT: - case FORM_MOONKIN: - case FORM_FLIGHT_EPIC: - case FORM_METAMORPHOSIS: - case FORM_MASTER_ANGLER: - case FORM_AMBIENT: - case FORM_SHADOW: - case FORM_STEALTH: - case FORM_UNDEAD: - case FORM_SHADOW_DANCE: - case FORM_TREE: - case FORM_SPIRITOFREDEMPTION: - break; - default: - sLog.outError("Auras: Unknown Shapeshift Type: %u", GetMiscValue()); - } - modelid = m_target->GetModelForForm(form); - - // remove polymorph before changing display id to keep new display id - switch ( form ) - { - case FORM_CAT: - case FORM_TREE: - case FORM_TRAVEL: - case FORM_AQUA: - case FORM_BEAR: - case FORM_DIREBEAR: - case FORM_FLIGHT_EPIC: - case FORM_FLIGHT: - case FORM_MOONKIN: - { - // remove movement affects - m_target->RemoveMovementImpairingAuras(); - - // and polymorphic affects - if(m_target->IsPolymorphed()) - m_target->RemoveAurasDueToSpell(m_target->getTransForm()); break; - } - default: - break; - } - - if (apply) - { - // remove other shapeshift before applying a new one - if(m_target->m_ShapeShiftFormSpellId) - m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId); - - m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form); - - if (modelid > 0) - m_target->SetDisplayId(modelid); - - if (PowerType != POWER_MANA) - { - uint32 oldPower = m_target->GetPower(PowerType); - // reset power to default values only at power change - if(m_target->getPowerType() != PowerType) - m_target->setPowerType(PowerType); - - switch (form) + case SPELLFAMILY_DEATHKNIGHT: + if (GetSpellSpecific(GetId()) == SPELL_SPECIFIC_PRESENCE) { - case FORM_CAT: - case FORM_BEAR: - case FORM_DIREBEAR: - { - // get furor proc chance - uint32 FurorChance = 0; - if (AuraEffect const *dummy = m_target->GetDummyAura(SPELLFAMILY_DRUID, 238, 0)) - FurorChance = std::max(dummy->GetAmount(), 0); + AuraEffect *bloodPresenceAura=0; // healing by damage done + AuraEffect *frostPresenceAura=0; // increased health + AuraEffect *unholyPresenceAura=0; // increased movement speed, faster rune recovery - switch (GetMiscValue()) + // Improved Presences + Unit::AuraEffectList const& vDummyAuras = target->GetAuraEffectsByType(SPELL_AURA_DUMMY); + for (Unit::AuraEffectList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr) + { + switch((*itr)->GetId()) { - case FORM_CAT: + // Improved Blood Presence + case 50365: + case 50371: { - int32 basePoints = int32(std::min(oldPower, FurorChance)); - m_target->CastCustomSpell(m_target, 17099, &basePoints, NULL, NULL, true, NULL, this); + bloodPresenceAura = (*itr); + break; } - break; - case FORM_BEAR: - case FORM_DIREBEAR: - if (urand(0,99) < FurorChance) + // Improved Frost Presence + case 50384: + case 50385: { - int32 basePoints = 100; // Not sure if 100 is correct basePoints, maybe it should be 10? - m_target->CastCustomSpell(m_target, 17057, &basePoints, NULL, NULL, true, NULL, this); + frostPresenceAura = (*itr); + break; } - default: + // Improved Unholy Presence + case 50391: + case 50392: { - uint32 newEnergy = std::min(m_target->GetPower(POWER_ENERGY), FurorChance); - m_target->SetPower(POWER_ENERGY, newEnergy); + unholyPresenceAura = (*itr); + break; } - break; } - break; } - default: - break; - } - } - m_target->m_ShapeShiftFormSpellId = GetId(); - m_target->m_form = form; - } - else - { - if(modelid > 0) - m_target->SetDisplayId(m_target->GetNativeDisplayId()); - m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE); - if(m_target->getClass() == CLASS_DRUID) - m_target->setPowerType(POWER_MANA); - m_target->m_ShapeShiftFormSpellId = 0; - m_target->m_form = FORM_NONE; - - switch(form) - { - // Nordrassil Harness - bonus - case FORM_BEAR: - case FORM_DIREBEAR: - case FORM_CAT: - if(AuraEffect* dummy = m_target->GetAuraEffect(37315, 0) ) - m_target->CastSpell(m_target,37316,true,NULL,dummy); - break; - // Nordrassil Regalia - bonus - case FORM_MOONKIN: - if(AuraEffect* dummy = m_target->GetAuraEffect(37324, 0) ) - m_target->CastSpell(m_target,37325,true,NULL,dummy); - break; - case FORM_BATTLESTANCE: - case FORM_DEFENSIVESTANCE: - case FORM_BERSERKERSTANCE: - { - uint32 Rage_val = 0; - // Defensive Tactics - if (form == FORM_DEFENSIVESTANCE) - { - if (AuraEffect const * aurEff = m_target->IsScriptOverriden(m_spellProto,831)) - Rage_val += aurEff->GetAmount() * 10; - } - // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch) - if(m_target->GetTypeId() == TYPEID_PLAYER) + uint32 presence=GetId(); + if (apply) { - PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + // Blood Presence bonus + if (presence == SPELL_ID_BLOOD_PRESENCE) + target->CastSpell(target,63611,true); + else if (bloodPresenceAura) { - if(itr->second->state == PLAYERSPELL_REMOVED) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139) - Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10; + int32 basePoints1=bloodPresenceAura->GetAmount(); + target->CastCustomSpell(target,63611,NULL,&basePoints1,NULL,true,0,bloodPresenceAura); } - } - if (m_target->GetPower(POWER_RAGE) > Rage_val) - m_target->SetPower(POWER_RAGE,Rage_val); - break; - } - default: - break; - } - } - - // adding/removing linked auras - // add/remove the shapeshift aura's boosts - HandleShapeshiftBoosts(apply); - - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->InitDataForForm(); - - if(m_target->getClass() == CLASS_DRUID) - { - if(form == FORM_CAT && apply) - { - // add dash if in cat-from - Unit::AuraMap & auras = m_target->GetAuras(); - for (Unit::AuraMap::iterator iter = auras.begin(); iter != auras.end(); ++iter) - { - Aura * aur = iter->second; - if (aur->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID && aur->GetSpellProto()->SpellFamilyFlags[2] & 0x8) - { - m_target->HandleAuraEffect(aur->GetPartAura(0), true); - } - } - } - else // remove dash effect(not buff) if out of cat-from - { - if(AuraEffect * aurEff =m_target->GetAura(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8)) - m_target->HandleAuraEffect(aurEff, false); - } - } - if (m_target->GetTypeId() == TYPEID_PLAYER) - { - SpellShapeshiftEntry const *shapeInfo = sSpellShapeshiftStore.LookupEntry(form); - // Learn spells for shapeshift form - no need to send action bars or add spells to spellbook - for (uint8 i = 0; i<MAX_SHAPESHIFT_SPELLS; ++i) - { - if (!shapeInfo->stanceSpell[i]) - continue; - if (apply) - ((Player*)m_target)->AddTemporarySpell(shapeInfo->stanceSpell[i]); - else - ((Player*)m_target)->RemoveTemporarySpell(shapeInfo->stanceSpell[i]); - } - } -} - -void AuraEffect::HandleAuraTransform(bool apply, bool Real, bool /*changeAmount*/) -{ - if (apply) - { - // special case (spell specific functionality) - if(GetMiscValue()==0) - { - // player applied only - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - switch (GetId()) - { - // Orb of Deception - case 16739: - { - uint32 orb_model = m_target->GetNativeDisplayId(); - switch(orb_model) + // Frost Presence bonus + if (presence == SPELL_ID_FROST_PRESENCE) + target->CastSpell(target,61261,true); + else if (frostPresenceAura) { - // Troll Female - case 1479: m_target->SetDisplayId(10134); break; - // Troll Male - case 1478: m_target->SetDisplayId(10135); break; - // Tauren Male - case 59: m_target->SetDisplayId(10136); break; - // Human Male - case 49: m_target->SetDisplayId(10137); break; - // Human Female - case 50: m_target->SetDisplayId(10138); break; - // Orc Male - case 51: m_target->SetDisplayId(10139); break; - // Orc Female - case 52: m_target->SetDisplayId(10140); break; - // Dwarf Male - case 53: m_target->SetDisplayId(10141); break; - // Dwarf Female - case 54: m_target->SetDisplayId(10142); break; - // NightElf Male - case 55: m_target->SetDisplayId(10143); break; - // NightElf Female - case 56: m_target->SetDisplayId(10144); break; - // Undead Female - case 58: m_target->SetDisplayId(10145); break; - // Undead Male - case 57: m_target->SetDisplayId(10146); break; - // Tauren Female - case 60: m_target->SetDisplayId(10147); break; - // Gnome Male - case 1563: m_target->SetDisplayId(10148); break; - // Gnome Female - case 1564: m_target->SetDisplayId(10149); break; - // BloodElf Female - case 15475: m_target->SetDisplayId(17830); break; - // BloodElf Male - case 15476: m_target->SetDisplayId(17829); break; - // Dranei Female - case 16126: m_target->SetDisplayId(17828); break; - // Dranei Male - case 16125: m_target->SetDisplayId(17827); break; - default: break; + int32 basePoints0=frostPresenceAura->GetAmount(); + target->CastCustomSpell(target,61261,&basePoints0,NULL,NULL,true,0,frostPresenceAura); + } + // Unholy Presence bonus + if (presence == SPELL_ID_UNHOLY_PRESENCE) + { + if(unholyPresenceAura) + { + // Not listed as any effect, only base points set + int32 basePoints0 = unholyPresenceAura->GetSpellProto()->EffectBasePoints[1]; + //target->CastCustomSpell(target,63622,&basePoints0 ,NULL,NULL,true,0,unholyPresenceAura); + target->CastCustomSpell(target,65095,&basePoints0 ,NULL,NULL,true,0,unholyPresenceAura); + } + target->CastSpell(target,49772, true); + } + else if (unholyPresenceAura) + { + int32 basePoints0=unholyPresenceAura->GetAmount(); + target->CastCustomSpell(target,49772,&basePoints0,NULL,NULL,true,0,unholyPresenceAura); } - break; - } - // Murloc costume - case 42365: m_target->SetDisplayId(21723); break; - default: break; - } - } - else - { - CreatureInfo const * ci = objmgr.GetCreatureTemplate(GetMiscValue()); - if(!ci) - { - m_target->SetDisplayId(16358); // pig pink ^_^ - sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", GetMiscValue(), GetId()); - } - else - { - uint32 model_id; - - if (uint32 modelid = ci->GetRandomValidModelId()) - model_id = modelid; // Will use the default model here - - // Polymorph (sheep) - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellProto()->SpellIconID == 82 && GetSpellProto()->SpellVisual[0] == 12978) - if (Unit * caster = GetCaster()) - if (caster->HasAura(52648)) // Glyph of the Penguin - model_id = 26452; - - m_target->SetDisplayId(model_id); - - // Dragonmaw Illusion (set mount model also) - if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED).empty()) - m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); - } - } - - // update active transform spell only not set or not overwriting negative by positive case - if (!m_target->getTransForm() || !IsPositiveSpell(GetId()) || IsPositiveSpell(m_target->getTransForm())) - m_target->setTransForm(GetId()); - - // polymorph case - if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed()) - { - // for players, start regeneration after 1s (in polymorph fast regeneration case) - // only if caster is Player (after patch 2.4.2) - if (IS_PLAYER_GUID(GetCasterGUID()) ) - ((Player*)m_target)->setRegenTimerCount(1*IN_MILISECONDS); - - //dismount polymorphed target (after patch 2.4.2) - if (m_target->IsMounted()) - m_target->RemoveAurasByType(SPELL_AURA_MOUNTED); - } - } - else - { - // ApplyModifier(true) will reapply it if need - m_target->setTransForm(0); - m_target->SetDisplayId(m_target->GetNativeDisplayId()); - - // re-aplly some from still active with preference negative cases - Unit::AuraEffectList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM); - if (!otherTransforms.empty()) - { - // look for other transform auras - AuraEffect* handledAura = *otherTransforms.begin(); - for (Unit::AuraEffectList::const_iterator i = otherTransforms.begin(); i != otherTransforms.end(); ++i) - { - // negative auras are preferred - if (!IsPositiveSpell((*i)->GetSpellProto()->Id)) - { - handledAura = *i; - break; } - } - handledAura->ApplyModifier(true); - } - - // Dragonmaw Illusion (restore mount model) - if (GetId()==42016 && m_target->GetMountID()==16314) - { - if (!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty()) - { - uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetMiscValue(); - if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id)) + else { - uint32 team = 0; - if (m_target->GetTypeId() == TYPEID_PLAYER) - team = ((Player*)m_target)->GetTeam(); - - uint32 display_id = objmgr.ChooseDisplayId(team,ci); - CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); - if (minfo) - display_id = minfo->modelid; - - m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id); + // Remove passive auras + if (presence == SPELL_ID_BLOOD_PRESENCE || bloodPresenceAura) + target->RemoveAurasDueToSpell(63611); + if (presence == SPELL_ID_FROST_PRESENCE || frostPresenceAura) + target->RemoveAurasDueToSpell(61261); + if (presence == SPELL_ID_UNHOLY_PRESENCE || unholyPresenceAura) + { + if(presence == SPELL_ID_UNHOLY_PRESENCE && unholyPresenceAura) + { + //target->RemoveAurasDueToSpell(63622); + target->RemoveAurasDueToSpell(65095); + } + target->RemoveAurasDueToSpell(49772); + } } } - } + break; } } -void AuraEffect::HandleForceReaction(bool apply, bool Real, bool changeAmount) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if(!Real && !changeAmount) - return; - - Player* player = (Player*)m_target; - - uint32 faction_id = GetMiscValue(); - ReputationRank faction_rank = ReputationRank(m_amount); - - player->GetReputationMgr().ApplyForceReaction(faction_id,faction_rank,apply); - player->GetReputationMgr().SendForceReactions(); - - // stop fighting if at apply forced rank friendly or at remove real rank friendly - if (apply && faction_rank >= REP_FRIENDLY || !apply && player->GetReputationRank(faction_id) >= REP_FRIENDLY) - player->StopAttackFaction(faction_id); -} - -void AuraEffect::HandleAuraModSkill(bool apply, bool Real, bool /*changeAmount*/) +void Aura::SetNeedClientUpdateForTargets() const { - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex]; - int32 points = m_amount; - - ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_auraName==SPELL_AURA_MOD_SKILL_TALENT); - if(prot == SKILL_DEFENSE) - ((Player*)m_target)->UpdateDefenseBonusesMod(); + for (ApplicationMap::const_iterator appIter = m_applications.begin(); appIter != m_applications.end(); ++appIter) + appIter->second->SetNeedClientUpdate(); } -void AuraEffect::HandleChannelDeathItem(bool apply, bool Real, bool /*changeAmount*/) +void Aura::_DeleteRemovedApplications() { - if(Real && !apply) + while(!m_removedApplications.empty()) { - Unit* caster = GetCaster(); - Unit* victim = m_target; - if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim)// || m_removeMode!=AURA_REMOVE_BY_DEATH) - return; - - //we cannot check removemode = death - //talent will remove the caster's aura->interrupt channel->remove victim aura - if(victim->GetHealth() > 0) - return; - // Item amount - if (m_amount <= 0) - return; - - SpellEntry const *spellInfo = GetSpellProto(); - if(spellInfo->EffectItemType[m_effIndex] == 0) - return; - - // Soul Shard only from non-grey units - if( spellInfo->EffectItemType[m_effIndex] == 6265 && - (victim->getLevel() <= Trinity::XP::GetGrayLevel(caster->getLevel()) || - victim->GetTypeId() == TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) ) - return; - //Adding items - uint32 noSpaceForCount = 0; - uint32 count = m_amount; - - ItemPosCountVec dest; - uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], count, &noSpaceForCount); - if( msg != EQUIP_ERR_OK ) - { - count-=noSpaceForCount; - ((Player*)caster)->SendEquipError( msg, NULL, NULL ); - if (count==0) - return; - } - - Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true); - ((Player*)caster)->SendNewItem(newitem, count, true, false); + delete m_removedApplications.front(); + m_removedApplications.pop_front(); } } -void AuraEffect::HandleBindSight(bool apply, bool Real, bool /*changeAmount*/) -{ - if (!Real) - return; - Unit* caster = GetCaster(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)caster)->SetViewpoint(m_target, apply); -} - -void AuraEffect::HandleFarSight(bool apply, bool Real, bool /*changeAmount*/) -{ - //Handled by client -} - -void AuraEffect::HandleAuraTrackCreatures(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(GetMiscValue()-1) : 0 ); -} - -void AuraEffect::HandleAuraTrackResources(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(GetMiscValue()-1): 0 ); -} - -void AuraEffect::HandleAuraTrackStealthed(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply); -} - -void AuraEffect::HandleAuraModScale(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_amount,apply); -} - -void AuraEffect::HandleAuraModPetTalentsPoints(bool Apply, bool Real, bool changeAmount) +UnitAura::UnitAura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID) + : Aura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID) { - if(!Real && !changeAmount) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Recalculate pet tlaent points - if (Pet *pet = ((Player*)m_target)->GetPet()) - pet->InitTalentForLevel(); -} + m_AuraDRGroup = DIMINISHING_NONE; + GetUnitOwner()->_AddAura(this); +}; -void AuraEffect::HandleModConfuse(bool apply, bool Real, bool /*changeAmount*/) +void UnitAura::_ApplyForTarget(Unit * target, Unit * caster, AuraApplication * aurApp) { - if(!Real) - return; + Aura::_ApplyForTarget(target, caster, aurApp); - //m_target->SetConfused(apply, GetCasterGUID(), GetId()); - m_target->SetControlled(apply, UNIT_STAT_CONFUSED); + // register aura diminishing on apply + if (DiminishingGroup group = GetDiminishGroup()) + target->ApplyDiminishingAura(group,true); } -void AuraEffect::HandleModFear(bool apply, bool Real, bool /*changeAmount*/) +void UnitAura::_UnapplyForTarget(Unit * target, Unit * caster, AuraApplication * aurApp) { - if (!Real) - return; + Aura::_UnapplyForTarget(target, caster, aurApp); - //m_target->SetFeared(apply, GetCasterGUID(), GetId()); - m_target->SetControlled(apply, UNIT_STAT_FLEEING); + // unregister aura diminishing (and store last time) + if (DiminishingGroup group = GetDiminishGroup()) + target->ApplyDiminishingAura(group,false); } -void AuraEffect::HandleFeignDeath(bool apply, bool Real, bool /*changeAmount*/) +void UnitAura::Remove(AuraRemoveMode removeMode) { - if(!Real) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) + if (IsRemoved()) return; - - if( apply ) - { - /* - WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); - data<<m_target->GetGUID(); - data<<uint8(0); - m_target->SendMessageToSet(&data,true); - */ - - std::list<Unit*> targets; - Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_target, m_target, m_target->GetMap()->GetVisibilityDistance()); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_target, targets, u_check); - m_target->VisitNearbyObject(m_target->GetMap()->GetVisibilityDistance(), searcher); - for (std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter) - { - if(!(*iter)->hasUnitState(UNIT_STAT_CASTING)) - continue; - - for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) - { - if((*iter)->GetCurrentSpell(i) - && (*iter)->GetCurrentSpell(i)->m_targets.getUnitTargetGUID() == m_target->GetGUID()) - { - (*iter)->InterruptSpell(CurrentSpellTypes(i), false); - } - } - } - // blizz like 2.0.x - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); - // blizz like 2.0.x - m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - // blizz like 2.0.x - m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - - m_target->addUnitState(UNIT_STAT_DIED); - m_target->CombatStop(); - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - - // prevent interrupt message - if(GetCasterGUID()==m_target->GetGUID() && m_target->GetCurrentSpell(CURRENT_GENERIC_SPELL)) - m_target->FinishSpell(CURRENT_GENERIC_SPELL, false); - m_target->InterruptNonMeleeSpells(true); - m_target->getHostilRefManager().deleteReferences(); - } - else - { - /* - WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); - data<<m_target->GetGUID(); - data<<uint8(1); - m_target->SendMessageToSet(&data,true); - */ - // blizz like 2.0.x - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); - // blizz like 2.0.x - m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - // blizz like 2.0.x - m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - - m_target->clearUnitState(UNIT_STAT_DIED); - } + GetUnitOwner()->RemoveOwnedAura(this, removeMode); } -void AuraEffect::HandleAuraModDisarm(bool apply, bool Real, bool /*changeAmount*/) +void UnitAura::UpdateTargetMapForEffect(Unit * caster, uint8 effIndex) { - if (!Real) - return; - AuraType type = AuraType(GetAuraName()); - - //Prevent handling aura twice - if(apply ? m_target->GetAurasByType(type).size() > 1 : m_target->HasAuraType(type)) - return; - - uint32 field, flag, slot; - WeaponAttackType attType; - switch (type) + if (GetSpellProto()->Effect[effIndex] == SPELL_EFFECT_APPLY_AURA) { - case SPELL_AURA_MOD_DISARM: - field=UNIT_FIELD_FLAGS; - flag=UNIT_FLAG_DISARMED; - slot=EQUIPMENT_SLOT_MAINHAND; - attType=BASE_ATTACK; - break; - case SPELL_AURA_MOD_DISARM_OFFHAND: - field=UNIT_FIELD_FLAGS_2; - flag=UNIT_FLAG2_DISARM_OFFHAND; - slot=EQUIPMENT_SLOT_OFFHAND; - attType=OFF_ATTACK; - break; - case SPELL_AURA_MOD_DISARM_RANGED: - field=UNIT_FIELD_FLAGS_2; - flag=UNIT_FLAG2_DISARM_RANGED; - slot=EQUIPMENT_SLOT_RANGED; - attType=RANGED_ATTACK; - break; - default: - return; - } - - if(!apply) - m_target->RemoveFlag(field, flag); - - if (m_target->GetTypeId() == TYPEID_PLAYER) - { - // This is between the two because there is a check in _ApplyItemMods - // we must make sure that flag is always removed when call that function - // refer to DurabilityPointsLoss - if(Item *pItem = ((Player*)m_target)->GetItemByPos( INVENTORY_SLOT_BAG_0, slot )) - ((Player*)m_target)->_ApplyItemMods(pItem, slot, !apply); - } - - if(apply) - m_target->SetFlag(field, flag); - - if (m_target->GetTypeId() == TYPEID_UNIT && ((Creature*)m_target)->GetCurrentEquipmentId()) - m_target->UpdateDamagePhysical(attType); -} - -void AuraEffect::HandleModStealth(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) + AuraApplication * aurApp = GetApplicationOfTarget(GetOwner()->GetGUID()); + if (!aurApp || !aurApp->HasEffect(effIndex)) + GetUnitOwner()->_ApplyAuraEffect(this, effIndex); return; - - if(apply) - { - // drop flag at stealth in bg - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - - m_target->SetStandFlags(UNIT_STAND_FLAGS_CREEP); - if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); - - // apply only if not in GM invisibility (and overwrite invisibility state) - if(m_target->GetVisibility() != VISIBILITY_OFF) - m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); - } - else if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) // if last SPELL_AURA_MOD_STEALTH - { - m_target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP); - if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); - - if(m_target->GetVisibility() != VISIBILITY_OFF) - m_target->SetVisibility(VISIBILITY_ON); - } -} - -void AuraEffect::HandleInvisibility(bool apply, bool Real, bool /*changeAmount*/) -{ - if(apply) - { - m_target->m_invisibilityMask |= (1 << GetMiscValue()); - - if(Real) - { - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - - // apply glow vision - if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); - - m_target->SetToNotify(); - } - } - else - { - // recalculate value at modifier remove (current aura already removed) - m_target->m_invisibilityMask = 0; - Unit::AuraEffectList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); - for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - m_target->m_invisibilityMask |= (1 << GetMiscValue()); - - // only at real aura remove and if not have different invisibility auras. - if(Real) - { - // remove glow vision - if(!m_target->m_invisibilityMask && m_target->GetTypeId() == TYPEID_PLAYER) - m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); - - m_target->SetToNotify(); - } - } -} - -void AuraEffect::HandleInvisibilityDetect(bool apply, bool Real, bool /*changeAmount*/) -{ - if(apply) - { - m_target->m_detectInvisibilityMask |= (1 << GetMiscValue()); } - else - { - // recalculate value at modifier remove (current aura already removed) - m_target->m_detectInvisibilityMask = 0; - Unit::AuraEffectList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); - for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - m_target->m_detectInvisibilityMask |= (1 << GetMiscValue()); - } - if(Real && m_target->GetTypeId() == TYPEID_PLAYER) - m_target->SetToNotify(); -} -void AuraEffect::HandleAuraModSilence(bool apply, bool Real, bool /*changeAmount*/) -{ - // only at real add/remove aura - if(!Real) - return; - - if(apply) - { - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); - // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE - for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) - if (Spell* spell = m_target->GetCurrentSpell(CurrentSpellTypes(i))) - if(spell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) - // Stop spells on prepare or casting state - m_target->InterruptSpell(CurrentSpellTypes(i), false); - } + float radius; + if (GetSpellProto()->Effect[effIndex] == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY) + radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[effIndex])); else - { - // Real remove called after current aura remove from lists, check if other similar auras active - if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE)) - return; - - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); - } -} - -void AuraEffect::HandleModThreat(bool apply, bool Real, bool changeAmount) -{ - // only at real add/remove aura - if(!Real && !changeAmount) - return; + radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[effIndex])); - if (!m_target->isAlive()) - return; - - Unit* caster = GetCaster(); + if (caster) + if(Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, radius); - if (!caster || !caster->isAlive()) - return; + // fill up to date target list + UnitList targets; - int level_diff = 0; - int multiplier = 0; - if (apply && !m_target->isBeingLoaded()) + if (!GetUnitOwner()->hasUnitState(UNIT_STAT_ISOLATED)) { - switch (GetId()) + switch(GetSpellProto()->Effect[effIndex]) { - // Arcane Shroud - case 26400: - level_diff = m_target->getLevel() - 60; - multiplier = 2; + case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: + targets.push_back(GetUnitOwner()); + GetUnitOwner()->GetPartyMemberInDist(targets, radius); break; - // The Eye of Diminution - case 28862: - level_diff = m_target->getLevel() - 60; - multiplier = 1; + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + targets.push_back(GetUnitOwner()); + GetUnitOwner()->GetRaidMember(targets, radius); break; - } - - if (level_diff > 0) - m_amount += multiplier * level_diff; - } - - if (m_target->GetTypeId() == TYPEID_PLAYER) - for (int8 x=0; x < MAX_SPELL_SCHOOL; x++) - if (GetMiscValue() & int32(1<<x)) - ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_amount, apply); -} - -void AuraEffect::HandleAuraModTotalThreat(bool apply, bool Real, bool changeAmount) -{ - // only at real add/remove aura - if(!Real && !changeAmount) - return; - - if (!m_target->isAlive() || m_target->GetTypeId() != TYPEID_PLAYER) - return; - - Unit* caster = GetCaster(); - - if (!caster || !caster->isAlive()) - return; - - float threatMod = apply ? float(m_amount) : float(-m_amount); - - m_target->getHostilRefManager().threatAssist(caster, threatMod); -} - -void AuraEffect::HandleModTaunt(bool apply, bool Real, bool /*changeAmount*/) -{ - // only at real add/remove aura - if (!Real) - return; - - if (!m_target->isAlive() || !m_target->CanHaveThreatList()) - return; - - Unit* caster = GetCaster(); - - if (!caster || !caster->isAlive()) - return; - - if (apply) - m_target->TauntApply(caster); - else - { - // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat - m_target->TauntFadeOut(caster); - } -} - -/*********************************************************/ -/*** MODIFY SPEED ***/ -/*********************************************************/ -void AuraEffect::HandleAuraModIncreaseSpeed(bool apply, bool Real, bool changeAmount) -{ - // all applied/removed only at real aura add/remove - if(!Real && !changeAmount) - return; - - if(apply) // Dash wont work if you are not in cat form - if(m_spellProto->SpellFamilyName==SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[2] & 0x8 && m_target->m_form != FORM_CAT ) - { - m_target->HandleAuraEffect(this, false); - return; - } - - m_target->UpdateSpeed(MOVE_RUN, true); -} - -void AuraEffect::HandleAuraModIncreaseMountedSpeed(bool apply, bool Real, bool changeAmount) -{ - // all applied/removed only at real aura add/remove - if(!Real && !changeAmount) - return; - - if(apply) - { - // Festive Holiday Mount - if(m_target->HasAura(62061) && GetSpellProto()->SpellIconID != 1794) - m_target->CastSpell(m_target, 25860, true, NULL, this); // Reindeer Transformation - } - - m_target->UpdateSpeed(MOVE_RUN, true); -} - -void AuraEffect::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real, bool changeAmount) -{ - // all applied/removed only at real aura add/remove - if(!Real && !changeAmount) - return; - - // Enable Fly mode for flying mounts - if (m_auraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) - { - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); - else - data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); - data.append(m_target->GetPackGUID()); - data << uint32(0); // unknown - m_target->SendMessageToSet(&data, true); - - //Players on flying mounts must be immune to polymorph - if (m_target->GetTypeId() == TYPEID_PLAYER) - m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply); - - if(apply) - { - // Dragonmaw Illusion (overwrite mount model, mounted aura already applied) - if(m_target->HasAuraEffect(42016,0) && m_target->GetMountID()) - m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); - - // Festive Holiday Mount - if(m_target->HasAura(62061) && GetSpellProto()->SpellIconID != 1794) - m_target->CastSpell(m_target, 25860, true, NULL, this); // Reindeer Transformation - } - } - - m_target->UpdateSpeed(MOVE_FLIGHT, true); -} - -void AuraEffect::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real, bool changeAmount) -{ - // all applied/removed only at real aura add/remove - if(!Real && !changeAmount) - return; - - m_target->UpdateSpeed(MOVE_SWIM, true); -} - -void AuraEffect::HandleAuraModDecreaseSpeed(bool apply, bool Real, bool changeAmount) -{ - // all applied/removed only at real aura add/remove - if(!Real && !changeAmount) - return; - - m_target->UpdateSpeed(MOVE_RUN, true); - m_target->UpdateSpeed(MOVE_SWIM, true); - m_target->UpdateSpeed(MOVE_FLIGHT, true); - m_target->UpdateSpeed(MOVE_RUN_BACK, true); - m_target->UpdateSpeed(MOVE_SWIM_BACK, true); - m_target->UpdateSpeed(MOVE_FLIGHT_BACK, true); -} - -void AuraEffect::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real, bool changeAmount) -{ - // all applied/removed only at real aura add/remove - if(!Real && !changeAmount) - return; - - m_target->UpdateSpeed(MOVE_RUN, true); - m_target->UpdateSpeed(MOVE_SWIM, true); - m_target->UpdateSpeed(MOVE_FLIGHT, true); -} - -/*********************************************************/ -/*** IMMUNITY ***/ -/*********************************************************/ - -void AuraEffect::HandleModStateImmunityMask(bool apply, bool Real, bool /*changeAmount*/) -{ - if (!Real) - return; - std::list <AuraType> immunity_list; - if (GetMiscValue() & (1<<10)) - immunity_list.push_back(SPELL_AURA_MOD_STUN); - if (GetMiscValue() & (1<<7)) - immunity_list.push_back(SPELL_AURA_MOD_DISARM); - if (GetMiscValue() & (1<<1)) - immunity_list.push_back(SPELL_AURA_TRANSFORM); - - // These flag can be recognized wrong: - if (GetMiscValue() & (1<<6)) - immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED); - if (GetMiscValue() & (1<<0)) - immunity_list.push_back(SPELL_AURA_MOD_ROOT); - if (GetMiscValue() & (1<<2)) - immunity_list.push_back(SPELL_AURA_MOD_CONFUSE); - if (GetMiscValue() & (1<<9)) - immunity_list.push_back(SPELL_AURA_MOD_FEAR); - - // Patch 3.0.3 Bladestorm now breaks all snares and roots on the warrior when activated. - // however not all mechanic specified in immunity - if (apply && GetId()==46924) - { - m_target->RemoveAurasByType(SPELL_AURA_MOD_ROOT); - m_target->RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); - } - - if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) - { - for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter) - { - m_target->RemoveAurasByType(*iter); - } - } - for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter) - { - m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,*iter,apply); - } -} - -void AuraEffect::HandleModMechanicImmunity(bool apply, bool Real, bool /*changeAmount*/) -{ - if (!Real) - return; - uint32 mechanic; - mechanic = 1 << GetMiscValue(); - - //immune movement impairment and loss of control - if(GetId()==42292 || GetId()==59752) - mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; - // Forbearance - // in DBC wrong mechanic immune since 3.0.x - else if (GetId() == 25771) - mechanic = 1 << MECHANIC_IMMUNE_SHIELD; - - if (!mechanic) - return; - - if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) - { - Unit::AuraMap& Auras = m_target->GetAuras(); - for (Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) - { - SpellEntry const *spell = iter->second->GetSpellProto(); - if (spell->Id != GetId()) + case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: { - //check for mechanic mask - if(GetAllSpellMechanicMask(spell) & mechanic) - { - m_target->RemoveAura(iter); - } - else - ++iter; - } - else - ++iter; - } - } - - m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,GetMiscValue(),apply); - - // Demonic Empowerment -- voidwalker -- missing movement impairing effects immunity - if (GetId() == 54508) - { - if (apply) - m_target->RemoveMovementImpairingAuras(); - - m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,SPELL_AURA_MOD_ROOT,apply); - m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,SPELL_AURA_MOD_DECREASE_SPEED,apply); - } -} - -void AuraEffect::HandleAuraModEffectImmunity(bool apply, bool Real, bool /*changeAmount*/) -{ - // when removing flag aura, handle flag drop - if( !apply && m_target->GetTypeId() == TYPEID_PLAYER - && (GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION) ) - { - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - if(((Player*)m_target)->InBattleGround()) - { - if( BattleGround *bg = ((Player*)m_target)->GetBattleGround() ) - bg->EventPlayerDroppedFlag(((Player*)m_target)); - } - else - sOutdoorPvPMgr.HandleDropFlag((Player*)m_target,GetSpellProto()->Id); - } - } - - m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,GetMiscValue(),apply); -} - -void AuraEffect::HandleAuraModStateImmunity(bool apply, bool Real, bool /*changeAmount*/) -{ - if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) - { - m_target->RemoveAurasByType(AuraType(GetMiscValue()), NULL , GetParentAura()); - } - - m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,GetMiscValue(),apply); -} - -void AuraEffect::HandleAuraModSchoolImmunity(bool apply, bool Real, bool /*changeAmount*/) -{ - if(apply && GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL) - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - - m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,GetMiscValue(),apply); - - // remove all flag auras (they are positive, but they must be removed when you are immune) - if( this->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY - && this->GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD ) - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - - // TODO: optimalize this cycle - use RemoveAurasWithInterruptFlags call or something else - if( Real && apply - && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY - && IsPositiveSpell(GetId()) ) //Only positive immunity removes auras - { - uint32 school_mask = GetMiscValue(); - Unit::AuraMap& Auras = m_target->GetAuras(); - for (Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) - { - SpellEntry const *spell = iter->second->GetSpellProto(); - if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask - && IsDispelableBySpell(GetSpellProto(),spell->Id, true) - && !iter->second->IsPositive() //Don't remove positive spells - && spell->Id != GetId() ) //Don't remove self - { - m_target->RemoveAura(iter); - } - else - ++iter; - } - } - if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH ) - { - if( apply ) - m_target->addUnitState(UNIT_STAT_ISOLATED); - else - m_target->clearUnitState(UNIT_STAT_ISOLATED); - } -} - -void AuraEffect::HandleAuraModDmgImmunity(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,GetMiscValue(),apply); -} - -void AuraEffect::HandleAuraModDispelImmunity(bool apply, bool Real, bool /*changeAmount*/) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(GetMiscValue()), apply); -} - -void AuraEffect::HandleAuraProcTriggerSpell(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - // Elemental oath - "while Clearcasting from Elemental Focus is active, you deal 5%/10% more spell damage." - if (m_target->GetTypeId() == TYPEID_PLAYER && (GetId() == 51466 || GetId() == 51470)) - { - if (apply) - { - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_EFFECT2; - mod->value = m_target->CalculateSpellDamage(GetSpellProto(), 1, GetSpellProto()->EffectBasePoints[1], m_target); - mod->type = SPELLMOD_FLAT; - mod->spellId = GetId(); - mod->mask[1] = 0x0004000; - m_spellmod = mod; - } - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - } -} - -void AuraEffect::HandleAuraModStalked(bool apply, bool Real, bool /*changeAmount*/) -{ - // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND - if(apply) - m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); - else - m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); -} - -/*********************************************************/ -/*** PERIODIC ***/ -/*********************************************************/ - -void AuraEffect::HandlePeriodicTriggerSpell(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; - if (!apply) - { - switch(m_spellProto->Id) - { - case 66: // Invisibility - m_target->CastSpell(m_target, 32612, true, NULL, this); - - return; - case 42783: //Wrath of the Astrom... - m_target->CastSpell(m_target, m_spellProto->CalculateSimpleValue(GetEffIndex()+1), true); - return; - default: - break; - } - } -} - -void AuraEffect::HandlePeriodicTriggerSpellWithValue(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandlePeriodicEnergize(bool apply, bool Real, bool changeAmount) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandleAuraPowerBurn(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandleAuraPeriodicDummy(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - Unit* caster = GetCaster(); - - SpellEntry const*spell = GetSpellProto(); - switch( spell->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - switch(spell->Id) - { - case 62399: // Overload Circuit - if(m_target->GetMap()->IsDungeon() && m_target->GetAuras().count(62399) >= (m_target->GetMap()->IsHeroic() ? 4 : 2)) - { - m_target->CastSpell(m_target, 62475, true); // System Shutdown - if(Unit *veh = m_target->GetVehicleBase()) - veh->CastSpell(m_target, 62475, true); - } - break; - case 58600: // No fly zone - Dalaran - if (apply && m_target->GetTypeId() == TYPEID_PLAYER) - ((Player *)m_target)->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE); - break; - default: - break; - } - break; - } - case SPELLFAMILY_WARLOCK: - { - switch (spell->Id) - { - // Demonic Circle - case 48018: - if (!apply) - { - // Do not remove GO when aura is removed by stack - // to prevent remove GO added by new spell - // old one is already removed - if (GetParentAura()->GetRemoveMode()!=AURA_REMOVE_BY_STACK) - m_target->RemoveGameObject(spell->Id,true); - m_target->RemoveAura(62388); - } + targets.push_back(GetUnitOwner()); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius); + Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetUnitOwner(), targets, u_check); + GetUnitOwner()->VisitNearbyObject(radius, searcher); break; } - } - case SPELLFAMILY_DEATHKNIGHT: - { - // Reaping - // Blood of the North - // Death Rune Mastery - if (spell->SpellIconID == 3041 || spell->SpellIconID == 22 || spell->SpellIconID == 2622) - m_amount = 0; - break; - } - } - - m_isPeriodic = apply; -} - -void AuraEffect::HandlePeriodicHeal(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandlePeriodicDamage(bool apply, bool Real, bool changeAmount) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandlePeriodicDamagePCT(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandlePeriodicLeech(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandlePeriodicManaLeech(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandlePeriodicHealthFunnel(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; -} - -/*********************************************************/ -/*** MODIFY STATS ***/ -/*********************************************************/ - -/********************************/ -/*** RESISTANCE ***/ -/********************************/ - -void AuraEffect::HandleAuraModResistanceExclusive(bool apply, bool Rea, bool /*changeAmount*/) -{ - for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) - { - if(GetMiscValue() & int32(1<<x)) - { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->ApplyResistanceBuffModsMod(SpellSchools(x),GetParentAura()->IsPositive(),m_amount, apply); - } - } -} - -void AuraEffect::HandleAuraModResistance(bool apply, bool Real, bool /*changeAmount*/) -{ - for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) - { - if(GetMiscValue() & int32(1<<x)) - { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_amount > 0,m_amount, apply); - } - } -} - -void AuraEffect::HandleAuraModBaseResistancePCT(bool apply, bool Real, bool /*changeAmount*/) -{ - // only players have base stats - if(m_target->GetTypeId() != TYPEID_PLAYER) - { - //pets only have base armor - if(((Creature*)m_target)->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) - m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_amount), apply); - } - else - { - for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++) - { - if(GetMiscValue() & int32(1<<x)) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_amount), apply); - } - } -} - -void AuraEffect::HandleModResistancePercent(bool apply, bool Real, bool /*changeAmount*/) -{ - for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) - { - if(GetMiscValue() & int32(1<<i)) - { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - { - m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_amount, apply); - m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_amount, apply); - } - } - } -} - -void AuraEffect::HandleModBaseResistance(bool apply, bool Real, bool /*changeAmount*/) -{ - // only players have base stats - if(m_target->GetTypeId() != TYPEID_PLAYER) - { - //only pets have base stats - if(((Creature*)m_target)->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) - m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_amount), apply); - } - else - { - for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) - if(GetMiscValue() & (1<<i)) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_amount), apply); - } -} - -/********************************/ -/*** STAT ***/ -/********************************/ - -void AuraEffect::HandleAuraModStat(bool apply, bool Real, bool /*changeAmount*/) -{ - if (GetMiscValue() < -2 || GetMiscValue() > 4) - { - sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),GetMiscValue()); - return; - } - - for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) - { - // -1 or -2 is all stats ( misc < -2 checked in function beginning ) - if (GetMiscValue() < 0 || GetMiscValue() == i) - { - //m_target->ApplyStatMod(Stats(i), m_amount,apply); - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyStatBuffMod(Stats(i),m_amount,apply); - } - } -} - -void AuraEffect::HandleModPercentStat(bool apply, bool Real, bool /*changeAmount*/) -{ - if (GetMiscValue() < -1 || GetMiscValue() > 4) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); - return; - } - - // only players have base stats - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) - { - if(GetMiscValue() == i || GetMiscValue() == -1) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply); - } -} - -void AuraEffect::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Magic damage modifiers implemented in Unit::SpellDamageBonus - // This information for client side use only - // Recalculate bonus - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void AuraEffect::HandleModSpellHealingPercentFromStat(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Recalculate bonus - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void AuraEffect::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Magic damage modifiers implemented in Unit::SpellDamageBonus - // This information for client side use only - // Recalculate bonus - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void AuraEffect::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Recalculate bonus - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void AuraEffect::HandleModHealingDone(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - // implemented in Unit::SpellHealingBonus - // this information is for client side only - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void AuraEffect::HandleModTotalPercentStat(bool apply, bool Real, bool /*changeAmount*/) -{ - if (GetMiscValue() < -1 || GetMiscValue() > 4) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); - return; - } - - //save current and max HP before applying aura - uint32 curHPValue = m_target->GetHealth(); - uint32 maxHPValue = m_target->GetMaxHealth(); - - for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) - { - if(GetMiscValue() == i || GetMiscValue() == -1) - { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyStatPercentBuffMod(Stats(i), m_amount, apply ); - } - } - - //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag) - if ((GetMiscValue() == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10)) - { - // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed - uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue; - m_target->SetHealth(newHPValue); - } -} - -void AuraEffect::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if(GetMiscValue() != SPELL_SCHOOL_MASK_NORMAL) - { - // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update - // and include in UpdateResistence same code as in UpdateArmor for aura mod apply. - sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!"); - return; - } - - // Recalculate Armor - m_target->UpdateArmor(); -} - -/********************************/ -/*** HEAL & ENERGIZE ***/ -/********************************/ -void AuraEffect::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real, bool /*changeAmount*/) -{ - m_isPeriodic = apply; -} - -void AuraEffect::HandleAuraModTotalEnergyPercentRegen(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_amplitude == 0) - m_amplitude = 1000; - - m_periodicTimer = m_amplitude; - m_isPeriodic = apply; -} - -void AuraEffect::HandleModRegen(bool apply, bool Real, bool /*changeAmount*/) // eating -{ - if(m_amplitude == 0) - m_amplitude = 5000; - - m_periodicTimer = 5000; - m_isPeriodic = apply; -} - -void AuraEffect::HandleModPowerRegen(bool apply, bool Real, bool changeAmount) // drinking -{ - if(!Real && !changeAmount) - return; - - Powers pt = m_target->getPowerType(); - if(m_amplitude == 0) - { - // Anger Management (only spell use this aura for rage) - if (pt == POWER_RAGE) - m_amplitude = 3000; - else - m_amplitude = 2000; - } - - m_periodicTimer = 5000; - - if (m_target->GetTypeId() == TYPEID_PLAYER && GetMiscValue() == POWER_MANA) - ((Player*)m_target)->UpdateManaRegen(); - - m_isPeriodic = apply; -} - -void AuraEffect::HandleModPowerRegenPCT(bool /*apply*/, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Update manaregen value - if (GetMiscValue() == POWER_MANA) - ((Player*)m_target)->UpdateManaRegen(); -} - -void AuraEffect::HandleModManaRegen(bool /*apply*/, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - //Note: an increase in regen does NOT cause threat. - ((Player*)m_target)->UpdateManaRegen(); -} - -void AuraEffect::HandleComprehendLanguage(bool apply, bool Real, bool /*changeAmount*/) -{ - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); -} - -void AuraEffect::HandleAuraModIncreaseHealth(bool apply, bool Real, bool changeAmount) -{ - if(Real || changeAmount) - { - if(apply) - { - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_amount), apply); - m_target->ModifyHealth(m_amount); - } - else - { - if (int32(m_target->GetHealth()) > m_amount) - m_target->ModifyHealth(-m_amount); - else - m_target->SetHealth(1); - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_amount), apply); - } - } -} - -void AuraEffect::HandleAuraModIncreaseMaxHealth(bool apply, bool Real, bool /*changeAmount*/) -{ - uint32 oldhealth = m_target->GetHealth(); - double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth(); - - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_amount), apply); - - // refresh percentage - if(oldhealth > 0) - { - uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)); - if(newhealth==0) - newhealth = 1; - - m_target->SetHealth(newhealth); - } -} - -void AuraEffect::HandleAuraModIncreaseEnergy(bool apply, bool Real, bool /*changeAmount*/) -{ - Powers powerType = m_target->getPowerType(); - if(int32(powerType) != GetMiscValue()) - return; - - UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); - - // Special case with temporary increase max/current power (percent) - if (GetId()==64904) // Hymn of Hope - { - if(Real) - { - uint32 val = m_target->GetPower(powerType); - m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_amount), apply); - m_target->SetPower(powerType, apply ? val*(100+m_amount)/100 : val*100/(100+m_amount)); - } - return; - } - - // generic flat case - m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_amount), apply); -} - -void AuraEffect::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/, bool /*changeAmount*/) -{ - Powers powerType = m_target->getPowerType(); - if(int32(powerType) != GetMiscValue()) - return; - - UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); - - m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_amount), apply); -} - -void AuraEffect::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/, bool /*changeAmount*/) -{ - // Unit will keep hp% after MaxHealth being modified if unit is alive. - float percent = ((float)m_target->GetHealth()) / m_target->GetMaxHealth(); - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_amount), apply); - if (m_target->isAlive()) - m_target->SetHealth(uint32(m_target->GetMaxHealth()*percent)); -} - -void AuraEffect::HandleAuraIncreaseBaseHealthPercent(bool apply, bool /*Real*/, bool /*changeAmount*/) -{ - m_target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(m_amount), apply); -} - -/********************************/ -/*** FIGHT ***/ -/********************************/ - -void AuraEffect::HandleAuraModParryPercent(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateParryPercentage(); -} - -void AuraEffect::HandleAuraModDodgePercent(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateDodgePercentage(); - //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_amount)); -} - -void AuraEffect::HandleAuraModBlockPercent(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateBlockPercentage(); - //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_amount)); -} - -void AuraEffect::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateManaRegen(); -} - -void AuraEffect::HandleAuraModWeaponCritPercent(bool apply, bool Real, bool changeAmount) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // apply item specific bonuses for already equipped weapon - if(Real || changeAmount) - { - for (int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) - ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply); - } - - // mods must be applied base at equipped weapon class and subclass comparison - // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // GetMiscValue() comparison with item generated damage types - - if (GetSpellProto()->EquippedItemClass == -1) - { - ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods - } -} - -void AuraEffect::HandleModHitChance(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)m_target)->UpdateMeleeHitChances(); - ((Player*)m_target)->UpdateRangedHitChances(); - } - else - { - m_target->m_modMeleeHitChance += apply ? m_amount : (-m_amount); - m_target->m_modRangedHitChance += apply ? m_amount : (-m_amount); - } -} - -void AuraEffect::HandleModSpellHitChance(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->UpdateSpellHitChances(); - else - m_target->m_modSpellHitChance += apply ? m_amount: (-m_amount); -} - -void AuraEffect::HandleModSpellCritChance(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->UpdateAllSpellCritChances(); - else - m_target->m_baseSpellCritChance += apply ? m_amount:-m_amount; -} - -void AuraEffect::HandleModSpellCritChanceShool(bool /*apply*/, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - for (int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school) - if (GetMiscValue() & (1<<school)) - ((Player*)m_target)->UpdateSpellCritChance(school); -} - -/********************************/ -/*** ATTACK SPEED ***/ -/********************************/ - -void AuraEffect::HandleModCastingSpeed(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->ApplyCastTimePercentMod(m_amount,apply); -} - -void AuraEffect::HandleModMeleeRangedSpeedPct(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_amount,apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_amount,apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_amount, apply); -} - -void AuraEffect::HandleModCombatSpeedPct(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->ApplyCastTimePercentMod(m_amount,apply); - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_amount,apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_amount,apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_amount, apply); -} - -void AuraEffect::HandleModAttackSpeed(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_amount,apply); - m_target->UpdateDamagePhysical(BASE_ATTACK); -} - -void AuraEffect::HandleHaste(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_amount,apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_amount,apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_amount,apply); -} - -void AuraEffect::HandleAuraModRangedHaste(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_amount, apply); -} - -void AuraEffect::HandleRangedAmmoHaste(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_amount, apply); -} - -/********************************/ -/*** ATTACK POWER ***/ -/********************************/ - -void AuraEffect::HandleAuraModAttackPower(bool apply, bool Real, bool /*changeAmount*/) -{ - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_amount), apply); -} - -void AuraEffect::HandleAuraModRangedAttackPower(bool apply, bool Real, bool /*changeAmount*/) -{ - if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) - return; - - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_amount), apply); -} - -void AuraEffect::HandleAuraModAttackPowerPercent(bool apply, bool Real, bool /*changeAmount*/) -{ - //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_amount), apply); -} - -void AuraEffect::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real, bool /*changeAmount*/) -{ - if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) - return; - - //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1 - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_amount), apply); -} - -void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - // Recalculate bonus - if(m_target->GetTypeId() == TYPEID_PLAYER && !(m_target->getClassMask() & CLASSMASK_WAND_USERS)) - ((Player*)m_target)->UpdateAttackPowerAndDamage(true); -} - -void AuraEffect::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - // Recalculate bonus - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->UpdateAttackPowerAndDamage(false); -} - -void AuraEffect::HandleAuraModAttackPowerOfArmor(bool /*apply*/, bool Real, bool /*changeAmount*/) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - // Recalculate bonus - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->UpdateAttackPowerAndDamage(false); -} -/********************************/ -/*** DAMAGE BONUS ***/ -/********************************/ -void AuraEffect::HandleModDamageDone(bool apply, bool Real, bool changeAmount) -{ - // apply item specific bonuses for already equipped weapon - if((Real || changeAmount) && m_target->GetTypeId() == TYPEID_PLAYER) - { - for (int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) - ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); - } - - // GetMiscValue() is bitmask of spell schools - // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) - // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands - // 127 - full bitmask any damages - // - // mods must be applied base at equipped weapon class and subclass comparison - // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // GetMiscValue() comparison with item generated damage types - - if((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0) - { - // apply generic physical damage bonuses including wand case - if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) - { - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_amount), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_amount), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_amount), apply); - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods - } - - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - if(m_amount > 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_amount,apply); - else - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_amount,apply); - } - } - - // Skip non magic case for speedup - if((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0) - return; - - if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) - { - // wand magic case (skip generic to all item spell bonuses) - // done in Player::_ApplyWeaponDependentAuraMods - - // Skip item specific requirements for not wand magic damage - return; - } - - // Magic damage modifiers implemented in Unit::SpellDamageBonus - // This information for client side use only - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - if(m_amount > 0) - { - for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: { - if((GetMiscValue() & (1<<i)) != 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_amount,apply); + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius); // No GetCharmer in searcher + Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetUnitOwner(), targets, u_check); + GetUnitOwner()->VisitNearbyObject(radius, searcher); + break; } - } - else - { - for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + case SPELL_EFFECT_APPLY_AREA_AURA_PET: + targets.push_back(GetUnitOwner()); + case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: { - if((GetMiscValue() & (1<<i)) != 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_amount,apply); + if(Unit *owner = GetUnitOwner()->GetCharmerOrOwner()) + if (GetUnitOwner()->IsWithinDistInMap(owner, radius)) + targets.push_back(owner); + break; } } - if(Guardian* pet = ((Player*)m_target)->GetGuardianPet()) - pet->UpdateAttackPowerAndDamage(); } -} -void AuraEffect::HandleModDamagePercentDone(bool apply, bool Real, bool changeAmount) -{ - sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", GetMiscValue(), m_amount > 0); - - // apply item specific bonuses for already equipped weapon - if((Real || changeAmount) && m_target->GetTypeId() == TYPEID_PLAYER) + // mark all auras as ready to remove + for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end(); appIter++) + if (appIter->second->HasEffect(effIndex)) + appIter->second->_SetCanBeRemoved(true); + + for (UnitList::iterator appIter = targets.begin(); appIter != targets.end(); appIter++) { - for (int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) - ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); - } + // add an aura to units new in list + ApplicationMap::iterator itr = m_applications.find((*appIter)->GetGUID()); - // GetMiscValue() is bitmask of spell schools - // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) - // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand - // 127 - full bitmask any damages - // - // mods must be applied base at equipped weapon class and subclass comparison - // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // GetMiscValue() comparison with item generated damage types - - if((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0) - { - // apply generic physical damage bonuses including wand case - if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) + if (itr == m_applications.end()) { - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_amount), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_amount), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_amount), apply); - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods - } - // For show in client - if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_amount/100.0f,apply); - } - - // Skip non magic case for speedup - if((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0) - return; - - if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) - { - // wand magic case (skip generic to all item spell bonuses) - // done in Player::_ApplyWeaponDependentAuraMods - - // Skip item specific requirements for not wand magic damage - return; - } - - // Magic damage percent modifiers implemented in Unit::SpellDamageBonus - // Send info to client - if(m_target->GetTypeId() == TYPEID_PLAYER) - for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) - m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_amount/100.0f,apply); -} - -void AuraEffect::HandleModOffhandDamagePercent(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - sLog.outDebug("AURA MOD OFFHAND DAMAGE"); - - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_amount), apply); -} - -/********************************/ -/*** POWER COST ***/ -/********************************/ - -void AuraEffect::HandleModPowerCostPCT(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - float amount = m_amount /100.0f; - for (int i = 0; i < MAX_SPELL_SCHOOL; ++i) - if(GetMiscValue() & (1<<i)) - m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply); -} - -void AuraEffect::HandleModPowerCost(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - for (int i = 0; i < MAX_SPELL_SCHOOL; ++i) - if(GetMiscValue() & (1<<i)) - m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_amount,apply); -} - -void AuraEffect::HandleNoReagentUseAura(bool Apply, bool Real, bool /*changeAmount*/) -{ - // spells required only Real aura add/remove - if(!Real) - return; - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - flag96 mask; - Unit::AuraEffectList const& noReagent = m_target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE); - for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) - mask |= (*i)->m_spellProto->EffectSpellClassMask[(*i)->m_effIndex]; - - m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); - m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); - m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]); -} - -/*********************************************************/ -/*** OTHERS ***/ -/*********************************************************/ - -void AuraEffect::HandleAuraAllowOnlyAbility(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - if(!apply && m_target->HasAuraType(SPELL_AURA_ALLOW_ONLY_ABILITY)) - return; - - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - if (apply) - m_target->SetFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); - else - m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); - } -} - -void AuraEffect::HandleAuraEmpathy(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real || m_target->GetTypeId() != TYPEID_UNIT) - return; - - CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry()); - if(ci && ci->type == CREATURE_TYPE_BEAST) - m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply); -} - -void AuraEffect::HandleAuraUntrackable(bool apply, bool Real, bool /*changeAmount*/) -{ - if (!Real) - return; - if(apply) - m_target->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE); - else - m_target->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE); -} - -void AuraEffect::HandleAuraModPacify(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); -} - -void AuraEffect::HandleAuraModPacifyAndSilence(bool apply, bool Real, bool changeAmount) -{ - // Vengeance of the Blue Flight - if(m_spellProto->Id == 45839) - { - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - HandleAuraModPacify(apply,Real, changeAmount); - HandleAuraModSilence(apply,Real, changeAmount); -} - -void AuraEffect::HandleAuraGhost(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if(apply) - m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); - else - m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); -} - -void AuraEffect::HandleAuraAllowFlight(bool apply, bool Real, bool /*changeAmount*/) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - if(m_target->GetTypeId() == TYPEID_UNIT) - m_target->SetFlying(apply); - - if(Player *plr = m_target->m_movedPlayer) - { - // allow fly - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); - else - data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); - data.append(m_target->GetPackGUID()); - data << uint32(0); // unk - plr->SendDirectMessage(&data); - } - - //m_target->SendMessageToSet(&data, true); -} - -void AuraEffect::HandleModRating(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) - if (GetMiscValue() & (1 << rating)) - ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_amount, apply); -} - -void AuraEffect::HandleModRatingFromStat(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Just recalculate ratings - for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) - if (GetMiscValue() & (1 << rating)) - ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), 0, apply); -} - -void AuraEffect::HandleForceMoveForward(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) - return; - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); -} - -void AuraEffect::HandleAuraModExpertise(bool /*apply*/, bool Real, bool changeAmount) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateExpertise(BASE_ATTACK); - ((Player*)m_target)->UpdateExpertise(OFF_ATTACK); -} - -void AuraEffect::HandleModTargetResistance(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage - - // show armor penetration - if (m_target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) - m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_amount, apply); - - // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy - if (m_target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL) - m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_amount, apply); -} - -void AuraEffect::HandleShieldBlockValue(bool apply, bool Real, bool /*changeAmount*/) -{ - BaseModType modType = FLAT_MOD; - if(m_auraName == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT) - modType = PCT_MOD; - - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_amount), apply); -} - -void AuraEffect::HandleAuraRetainComboPoints(bool apply, bool Real, bool changeAmount) -{ - // spells required only Real aura add/remove - if(!Real && !changeAmount) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - Player *target = (Player*)m_target; - - // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler - // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost) - if( !apply && GetParentAura()->GetAuraDuration()==0 && target->GetComboTarget()) - if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget())) - target->AddComboPoints(unit, -m_amount); -} - -void AuraEffect::HandleModUnattackable( bool Apply, bool Real , bool /*changeAmount*/) -{ - if(!Real) - return; - - if(Apply) - { - m_target->CombatStop(); - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - } - - m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, Apply); -} - -void AuraEffect::HandleSpiritOfRedemption( bool apply, bool Real , bool /*changeAmount*/) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - // prepare spirit state - if(apply) - { - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - // disable breath/etc timers - ((Player*)m_target)->StopMirrorTimers(); - - // set stand state (expected in this form) - if(!m_target->IsStandState()) - m_target->SetStandState(UNIT_STAND_STATE_STAND); - } - - m_target->SetHealth(1); - } - // die at aura end - else - m_target->setDeathState(JUST_DIED); -} - -void AuraEffect::PeriodicTick() -{ - if(!m_target->isAlive()) - return; - - switch(GetAuraName()) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - // Consecrate ticks can miss and will not show up in the combat log - if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA && - pCaster->SpellHitResult(m_target,GetSpellProto(),false) != SPELL_MISS_NONE) - return; - - // Check for immune (not use charges) - if (m_target->IsImmunedToDamage(GetSpellProto())) - return; + // check target immunities + if ((*appIter)->IsImmunedToSpell(GetSpellProto()) + || (*appIter)->hasUnitState(UNIT_STAT_ISOLATED)) + continue; - // some auras remove at specific health level or more - if (m_auraName == SPELL_AURA_PERIODIC_DAMAGE) + // Allow to remove by stack when aura is going to be applied on owner + if (*appIter != GetOwner()) { - switch (GetId()) + bool addUnit = true; + // check if not stacking aura already on target + // this one prevents unwanted usefull buff loss because of stacking and prevents overriding auras periodicaly by 2 near area aura owners + for (Unit::AuraApplicationMap::iterator iter = (*appIter)->GetAppliedAuras().begin(); iter != (*appIter)->GetAppliedAuras().end(); ++iter) { - case 43093: case 31956: case 38801: // Grievous Wound - case 35321: case 38363: case 39215: // Gushing Wound - if(m_target->GetHealth() == m_target->GetMaxHealth()) - { - m_target->RemoveAurasDueToSpell(GetId()); - return; - } - break; - case 38772: // Grievous Wound + Aura const * aura = iter->second->GetBase(); + if(!spellmgr.CanAurasStack(GetSpellProto(), aura->GetSpellProto(), aura->GetCasterGUID() == GetCasterGUID())) { - uint32 percent = - GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ? - pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) : - 100; - if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent) - { - m_target->RemoveAurasDueToSpell(GetId()); - return; - } - break; - } - case 41337: // Aura of Anger - { - if (AuraEffect * aurEff = GetParentAura()->GetPartAura(1)) - { - aurEff->ApplyModifier(false, false, true); - aurEff->SetAmount(aurEff->GetAmount()+5); - aurEff->ApplyModifier(true, false, true); - } - m_amount = 100 * m_tickNumber; - break; - } - // Brutallus Burn - case 46394: - { - if (m_tickNumber % 11 == 0) - m_amount *= 2; + addUnit = false; break; } - case 31803: - case 53742: - { - float ap = pCaster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 holy = pCaster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) + - pCaster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellProto), m_target); - - m_amount = (0.013f * holy + 0.025f * ap) * 6 / 5 * m_tickNumber; - break; - } - default: - break; - } - } - - uint32 absorb=0; - uint32 resist=0; - CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL ); - - // ignore non positive values (can be result apply spellmods to aura damage - //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - uint32 pdamage = GetAmount() > 0 ? GetAmount() : 0; - - if(GetAuraName() == SPELL_AURA_PERIODIC_DAMAGE) - { - pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetParentAura()->GetStackAmount()); - - // Calculate armor mitigation if it is a physical spell - // But not for bleed mechanic spells - if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL && - GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED) - { - uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage, GetSpellProto()); - cleanDamage.mitigated_damage += pdamage - pdamageReductedArmor; - pdamage = pdamageReductedArmor; - } - - // Curse of Agony damage-per-tick calculation - if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID==544) - { - uint32 totalTick = GetParentAura()->GetAuraMaxDuration() / m_amplitude; - // 1..4 ticks, 1/2 from normal tick damage - if(m_tickNumber <= totalTick / 3) - pdamage = pdamage/2; - // 9..12 ticks, 3/2 from normal tick damage - else if(m_tickNumber > totalTick * 2 / 3) - pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks - // 5..8 ticks have normal tick damage - } - // There is a Chance to make a Soul Shard when Drain soul does damage - if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x00004000)) - { - if(roll_chance_i(20)) - pCaster->CastSpell(pCaster, 24827, true, 0, this); } + if (!addUnit) + continue; } - else - pdamage = uint32(m_target->GetMaxHealth()*pdamage/100); - - bool crit = IsPeriodicTickCrit(pCaster); - if (crit) - pdamage = pCaster->SpellCriticalDamageBonus(m_spellProto, pdamage, m_target); - - // only from players - if (IS_PLAYER_GUID(GetCasterGUID())) - pdamage -= m_target->GetSpellDamageReduction(pdamage); - - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto); - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); - - pCaster->DealDamageMods(m_target,pdamage,&absorb); - - Unit* target = m_target; // aura can be deleted in DealDamage - SpellEntry const* spellProto = GetSpellProto(); - - // Set trigger flag - uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; - uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; - uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_DOT; - pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist); - if (pdamage) - procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; - - int32 overkill = pdamage - m_target->GetHealth(); - if (overkill < 0) - overkill = 0; - - SpellPeriodicAuraLogInfo pInfo(this, pdamage, overkill, absorb, resist, 0.0f, crit); - m_target->SendPeriodicAuraLog(&pInfo); - - pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, pdamage, BASE_ATTACK, spellProto); - - pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true); - break; } - case SPELL_AURA_PERIODIC_LEECH: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - if(!pCaster->isAlive()) - return; - - if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && - pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) - return; - // Check for immune - if(m_target->IsImmunedToDamage(GetSpellProto())) - return; - - uint32 absorb=0; - uint32 resist=0; - CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL ); - - //uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - uint32 pdamage = GetAmount() > 0 ? GetAmount() : 0; - pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetParentAura()->GetStackAmount()); - - bool crit = IsPeriodicTickCrit(pCaster); - if (crit) - pdamage = pCaster->SpellCriticalDamageBonus(m_spellProto, pdamage, m_target); - - //Calculate armor mitigation if it is a physical spell - if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL) - { - uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage, GetSpellProto()); - cleanDamage.mitigated_damage += pdamage - pdamageReductedArmor; - pdamage = pdamageReductedArmor; - } - - // Reduce dot damage from resilience for players. - if (m_target->GetTypeId() == TYPEID_PLAYER) - pdamage-=((Player*)m_target)->GetSpellDamageReduction(pdamage); - - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto); - - if(m_target->GetHealth() < pdamage) - pdamage = uint32(m_target->GetHealth()); - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); - - pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0, crit); - - Unit* target = m_target; // aura can be deleted in DealDamage - SpellEntry const* spellProto = GetSpellProto(); - float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1; - int32 stackAmount = GetParentAura()->GetStackAmount(); - - // Set trigger flag - uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; - uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; - uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_DOT; - pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist); - if (pdamage) - procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; - pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, pdamage, BASE_ATTACK, spellProto); - int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false); - - if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false)) - for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i) - if (Spell* spell = pCaster->GetCurrentSpell(CurrentSpellTypes(i))) - if (spell->m_spellInfo->Id == GetId()) - spell->cancel(); - - if(Player *modOwner = pCaster->GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); - - uint32 heal = uint32(pCaster->SpellHealingBonus(pCaster, spellProto, uint32(new_damage * multiplier), DOT, stackAmount)); - - int32 gain = pCaster->DealHeal(pCaster, heal, spellProto); - pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto); - break; - } - case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: // only three spells + if (itr == m_applications.end() || !itr->second->HasEffect(effIndex)) { - Unit *donator = GetCaster(); - if(!donator || !donator->GetHealth()) - return; - - uint32 pdamage = GetAmount() * GetParentAura()->GetStackAmount(); - if(donator->GetHealth() < pdamage) - pdamage = donator->GetHealth() - 1; - if(!pdamage) - return; - - Unit* target = m_target; // aura can be deleted in DealDamage - SpellEntry const* spellProto = GetSpellProto(); - //donator->SendSpellNonMeleeDamageLog(donator, GetId(), pdamage, GetSpellSchoolMask(spellProto), 0, 0, false, 0); - donator->ModifyHealth(-(int32)pdamage); - sLog.outDetail("PeriodicTick: donator %u target %u damage %u.", donator->GetEntry(), target->GetEntry(), pdamage); - - if(spellProto->EffectMultipleValue[GetEffIndex()] > 0) - pdamage *= spellProto->EffectMultipleValue[GetEffIndex()]; - - donator->DealHeal(target, pdamage, spellProto); - break; - } - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_OBS_MOD_HEALTH: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - // heal for caster damage (must be alive) - if(m_target != pCaster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL && !pCaster->isAlive()) - return; - - if(GetParentAura()->GetAuraDuration() ==-1 && m_target->GetHealth()==m_target->GetMaxHealth()) - return; - - // ignore non positive values (can be result apply spellmods to aura damage - //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - int32 pdamage = GetAmount() > 0 ? GetAmount() : 0; - - if(m_auraName==SPELL_AURA_OBS_MOD_HEALTH) - pdamage = uint32(m_target->GetMaxHealth() * pdamage * GetParentAura()->GetStackAmount() / 100); - else - { - // Wild Growth (1/7 - 6 + 2*ramainTicks) % - if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellIconID == 2864) - { - int32 ticks = GetParentAura()->GetAuraMaxDuration()/m_amplitude; - int32 remainingTicks = int32(float(GetParentAura()->GetAuraDuration()) / m_amplitude + 0.5); - pdamage = int32(pdamage) + int32(pdamage)*ticks*(-6+2*remainingTicks)/100; - } - - pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetParentAura()->GetStackAmount()); - } - - bool crit = IsPeriodicTickCrit(pCaster); - if (crit) - pdamage = pCaster->SpellCriticalHealingBonus(m_spellProto, pdamage, m_target); - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - - int32 gain = m_target->ModifyHealth(pdamage); - - SpellPeriodicAuraLogInfo pInfo(this, pdamage, pdamage - gain, 0, 0, 0.0f, crit); - m_target->SendPeriodicAuraLog(&pInfo); - - // add HoTs to amount healed in bgs - if( pCaster->GetTypeId() == TYPEID_PLAYER ) - if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() ) - bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain); - - m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); - - Unit* target = m_target; // aura can be deleted in DealDamage - SpellEntry const* spellProto = GetSpellProto(); - bool haveCastItem = GetParentAura()->GetCastItemGUID()!=0; - - // Health Funnel - // heal for caster damage - if(m_target!=pCaster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL) - { - uint32 dmg = spellProto->manaPerSecond; - if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId() == TYPEID_PLAYER) - { - pCaster->RemoveAurasDueToSpell(GetId()); - - // finish current generic/channeling spells, don't affect autorepeat - pCaster->FinishSpell(CURRENT_GENERIC_SPELL); - pCaster->FinishSpell(CURRENT_CHANNELED_SPELL); - } - else - { - uint32 damage = gain; - uint32 absorb = 0; - pCaster->DealDamageMods(pCaster,damage,&absorb); - pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false); - - CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL ); - pCaster->DealDamage(pCaster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); - } - } - - uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; - uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; - uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_HOT; - // ignore item heals - if(!haveCastItem) - pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, pdamage, BASE_ATTACK, spellProto); - break; - } - case SPELL_AURA_PERIODIC_MANA_LEECH: - { - if(GetMiscValue() < 0 || GetMiscValue() >= MAX_POWERS) - return; - - Powers power = Powers(GetMiscValue()); - - // power type might have changed between aura applying and tick (druid's shapeshift) - if(m_target->getPowerType() != power) - return; - - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - if(!pCaster->isAlive()) - return; - - if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && - pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) - return; - - // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellProto())) - return; - - // ignore non positive values (can be result apply spellmods to aura damage - uint32 pdamage = m_amount > 0 ? m_amount : 0; - - // Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana) - // It's mana percent cost spells, m_amount is percent drain from target - if (m_spellProto->ManaCostPercentage) - { - // max value - uint32 maxmana = pCaster->GetMaxPower(power) * pdamage * 2 / 100; - pdamage = m_target->GetMaxPower(power) * pdamage / 100; - if(pdamage > maxmana) - pdamage = maxmana; - } - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - - int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power); - - // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) - if (power == POWER_MANA) - drain_amount -= m_target->GetSpellCritDamageReduction(drain_amount); - - m_target->ModifyPower(power, -drain_amount); - - float gain_multiplier = 0; - - if(pCaster->GetMaxPower(power) > 0) - { - gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()]; - - if(Player *modOwner = pCaster->GetSpellModOwner()) - modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier); - } - - SpellPeriodicAuraLogInfo pInfo(this, drain_amount, 0, 0, 0, gain_multiplier, false); - m_target->SendPeriodicAuraLog(&pInfo); - - int32 gain_amount = int32(drain_amount*gain_multiplier); - - if(gain_amount) - { - int32 gain = pCaster->ModifyPower(power,gain_amount); - m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); - } - - // Mark of Kaz'rogal - if(GetId() == 31447 && m_target->GetPower(power) == 0) - { - m_target->CastSpell(m_target, 31463, true, 0, this); - // Remove aura - GetParentAura()->SetAuraDuration(0); - } - - // Mark of Kazzak - if(GetId() == 32960) - { - int32 modifier = (m_target->GetPower(power) * 0.05f); - m_target->ModifyPower(power, -modifier); - - if(m_target->GetPower(power) == 0) - { - m_target->CastSpell(m_target, 32961, true, 0, this); - // Remove aura - GetParentAura()->SetAuraDuration(0); - } - } - // Mana Feed - Drain Mana - if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK - && m_spellProto->SpellFamilyFlags[0] & 0x00000010) - { - int32 manaFeedVal = 0; - if (AuraEffect const * aurEff = GetParentAura()->GetPartAura(1)) - manaFeedVal = aurEff->GetAmount(); - - if(manaFeedVal > 0) - { - manaFeedVal = manaFeedVal * gain_amount / 100; - pCaster->CastCustomSpell(pCaster, 32554, &manaFeedVal, NULL, NULL, true, NULL, this); - } - } - break; - } - case SPELL_AURA_OBS_MOD_POWER: - { - if(GetMiscValue() < 0) - return; - - Powers power; - if (GetMiscValue() == POWER_ALL) - power = m_target->getPowerType(); - else - power = Powers(GetMiscValue()); - - if(m_target->GetMaxPower(power) == 0) - return; - - if(GetParentAura()->GetAuraDuration() ==-1 && m_target->GetPower(power)==m_target->GetMaxPower(power)) - return; - - uint32 amount = m_amount * m_target->GetMaxPower(power) /100; - sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), amount, GetId()); - - SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false); - m_target->SendPeriodicAuraLog(&pInfo); - - int32 gain = m_target->ModifyPower(power,amount); - - if(Unit* pCaster = GetCaster()) - m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); - break; - } - case SPELL_AURA_PERIODIC_ENERGIZE: - { - // ignore non positive values (can be result apply spellmods to aura damage - if(m_amount < 0 || GetMiscValue() >= MAX_POWERS) - return; - - Powers power = Powers(GetMiscValue()); - - if(m_target->GetMaxPower(power) == 0) - return; - - if(GetParentAura()->GetAuraDuration() ==-1 && m_target->GetPower(power)==m_target->GetMaxPower(power)) - return; - - uint32 amount = m_amount; - - SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false); - m_target->SendPeriodicAuraLog(&pInfo); - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), amount, GetId()); - - int32 gain = m_target->ModifyPower(power,amount); - - if(Unit* pCaster = GetCaster()) - m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); - break; - } - case SPELL_AURA_POWER_BURN_MANA: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellProto())) - return; - - int32 pdamage = m_amount > 0 ? m_amount : 0; - - Powers powerType = Powers(GetMiscValue()); - - if(!m_target->isAlive() || m_target->getPowerType() != powerType) - return; - - // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) - if (powerType == POWER_MANA) - pdamage -= m_target->GetSpellCritDamageReduction(pdamage); - - uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage)); - - gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]); - - SpellEntry const* spellProto = GetSpellProto(); - //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG - SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask); - //no SpellDamageBonus for burn mana - pCaster->CalculateSpellDamageTaken(&damageInfo, gain, spellProto); - - pCaster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb); - - pCaster->SendSpellNonMeleeDamageLog(&damageInfo); - - // Set trigger flag - uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; - uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; - uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE) | PROC_EX_INTERNAL_DOT; - if (damageInfo.damage) - procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; - - pCaster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto); - - pCaster->DealSpellDamage(&damageInfo, true); - break; - } - case SPELL_AURA_MOD_REGEN: - { - int32 gain = m_target->ModifyHealth(m_amount); - if (Unit *caster = GetCaster()) - m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto()); - break; - } - case SPELL_AURA_MOD_POWER_REGEN: - { - Powers pt = m_target->getPowerType(); - if(int32(pt) != GetMiscValue()) - return; - - if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED ) - { - // eating anim - m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT); - } - // Butchery - else if (m_spellProto->SpellFamilyName==SPELLFAMILY_DEATHKNIGHT - && m_spellProto->SpellIconID==2664) - { - if (m_target->isInCombat()) - m_target->ModifyPower(pt,m_amount); - } + if((*appIter)->IsImmunedToSpellEffect(GetSpellProto(), effIndex)) + continue; + // add new unit to persistent area aura + (*appIter)->_ApplyAuraEffect(this, effIndex); - // Anger Management - // amount = 1+ 16 = 17 = 3,4*5 = 10,2*5/3 - // so 17 is rounded amount for 5 sec tick grow ~ 1 range grow in 3 sec - if(pt == POWER_RAGE) - m_target->ModifyPower(pt, m_amount*3/5); - break; - } - case SPELL_AURA_DUMMY: - { - // Haunting Spirits - if (GetId() == 7057) - { - m_target->CastSpell((Unit*)NULL , m_amount , true); - m_amplitude = irand (0 , 60 ) + 30; - m_amplitude *= IN_MILISECONDS; - break; - } - break; - } - // Here tick dummy auras - case SPELL_AURA_PERIODIC_DUMMY: - { - PeriodicDummyTick(); - break; + // start combat with targeted enemy + if(GetSpellProto()->Effect[effIndex] == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY) + GetUnitOwner()->CombatStart(*appIter); } - case SPELL_AURA_PERIODIC_TRIGGER_SPELL: - { - Unit *pCaster = GetCaster(); - if (!pCaster) - return; - - if (pCaster->GetTypeId() == TYPEID_UNIT && ((Creature*)pCaster)->isTotem() && ((Totem*)pCaster)->GetTotemType() != TOTEM_STATUE) - { - uint32 procAttacker = PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT; - uint32 procVictim = PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT; - SpellEntry const *spellProto = GetSpellProto(); - if (spellProto->SpellFamilyName == SPELLFAMILY_GENERIC) // SPELLFAMILY_GENERIC proc by triggered spell - { - uint32 trigger_spell_id = spellProto->EffectTriggerSpell[m_effIndex]; - SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); - ((Totem*)pCaster)->GetOwner()->ProcDamageAndSpell(pCaster, procAttacker, procVictim, PROC_EX_NORMAL_HIT, 0, BASE_ATTACK, triggeredSpellInfo); - } - else - ((Totem*)pCaster)->GetOwner()->ProcDamageAndSpell(pCaster, procAttacker, procVictim, PROC_EX_NORMAL_HIT, 0, BASE_ATTACK, spellProto); - } - - TriggerSpell(); - break; - } - case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: - { - TriggerSpellWithValue(); - break; - } - default: - break; + itr = m_applications.find((*appIter)->GetGUID()); + if (itr != m_applications.end()) + // mark aura of unit already in list to be not removed + itr->second->_SetCanBeRemoved(false); } -} -void AuraEffect::PeriodicDummyTick() -{ - Unit *caster = GetCaster(); - SpellEntry const* spell = GetSpellProto(); - switch (spell->SpellFamilyName) + // remove auras which are not in current area + for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end();) { - case SPELLFAMILY_GENERIC: - switch (spell->Id) - { - // Drink - case 430: - case 431: - case 432: - case 1133: - case 1135: - case 1137: - case 10250: - case 22734: - case 27089: - case 34291: - case 43182: - case 43183: - case 46755: - case 49472: // Drink Coffee - case 57073: - case 61830: - { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Get SPELL_AURA_MOD_POWER_REGEN aura from spell - if (AuraEffect * aurEff = GetParentAura()->GetPartAura(0)) - { - if (aurEff->GetAuraName() !=SPELL_AURA_MOD_POWER_REGEN) - { - m_isPeriodic = false; - sLog.outError("Aura %d structure has been changed - first aura is no longer SPELL_AURA_MOD_POWER_REGEN", spell->Id); - } - else - { - // default case - not in arena - if (!((Player*)m_target)->InArena()) - { - aurEff->SetAmount(GetAmount()); - ((Player*)m_target)->UpdateManaRegen(); - m_isPeriodic = false; - } - else - { - //********************************************** - // This feature uses only in arenas - //********************************************** - // Here need increase mana regen per tick (6 second rule) - // on 0 tick - 0 (handled in 2 second) - // on 1 tick - 166% (handled in 4 second) - // on 2 tick - 133% (handled in 6 second) - - // Apply bonus for 1 - 4 tick - switch (m_tickNumber) - { - case 1: // 0% - aurEff->SetAmount(0); - break; - case 2: // 166% - aurEff->SetAmount(GetAmount() * 5 / 3); - break; - case 3: // 133% - aurEff->SetAmount(GetAmount() * 4 / 3); - break; - default: // 100% - normal regen - aurEff->SetAmount(GetAmount()); - // No need to update after 4th tick - m_isPeriodic = false; - break; - } - ((Player*)m_target)->UpdateManaRegen(); - } - } - } - return; - } - // Forsaken Skills - case 7054: - { - // Possibly need cast one of them (but - // 7038 Forsaken Skill: Swords - // 7039 Forsaken Skill: Axes - // 7040 Forsaken Skill: Daggers - // 7041 Forsaken Skill: Maces - // 7042 Forsaken Skill: Staves - // 7043 Forsaken Skill: Bows - // 7044 Forsaken Skill: Guns - // 7045 Forsaken Skill: 2H Axes - // 7046 Forsaken Skill: 2H Maces - // 7047 Forsaken Skill: 2H Swords - // 7048 Forsaken Skill: Defense - // 7049 Forsaken Skill: Fire - // 7050 Forsaken Skill: Frost - // 7051 Forsaken Skill: Holy - // 7053 Forsaken Skill: Shadow - return; - } - case 45472: // Parachute - if (m_target->GetTypeId() == TYPEID_PLAYER) - { - Player *plr = (Player*)m_target; - if (plr->IsFalling()) - { - plr->RemoveAurasDueToSpell(45472); - plr->CastSpell(plr, 44795, true); - } - } - break; - case SPELL_RESTRICTED_FLIGHT_AREA_58730: // No Fly Zone - Wintergrasp - case SPELL_RESTRICTED_FLIGHT_AREA_58600: // No fly Zone - Dalaran - if (m_tickNumber == 10) - { - m_target->RemoveAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED); - m_target->RemoveAurasByType(SPELL_AURA_FLY); - } - break; - case 58549: // Tenacity - case 59911: // Tenacity (vehicle) - GetParentAura()->RefreshAura(); - break; - case 62292: // Blaze (Pool of Tar) - // should we use custom damage? - m_target->CastSpell((Unit*)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true); - break; - default: - break; - } - break; - case SPELLFAMILY_MAGE: - { - // Mirror Image - if (spell->Id == 55342) - { - // Set name of summons to name of caster - m_target->CastSpell((Unit *)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true); - m_isPeriodic = false; - } - break; - } - case SPELLFAMILY_WARLOCK: - { - switch (spell->Id) - { - // Demonic Circle - case 48018: - if(GameObject* obj = m_target->GetGameObject(spell->Id)) - { - if (m_target->IsWithinDist(obj, GetSpellMaxRange(48020, true))) - { - if (!m_target->HasAura(62388)) - m_target->CastSpell(m_target, 62388, true); - } - else - m_target->RemoveAura(62388); - } - return; - } - break; - } - case SPELLFAMILY_DRUID: - { - switch (spell->Id) - { - // Frenzied Regeneration - case 22842: - { - // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health. - // Should be manauser - if (m_target->getPowerType()!=POWER_RAGE) - return; - uint32 rage = m_target->GetPower(POWER_RAGE); - // Nothing todo - if (rage == 0) - return; - int32 mod = (rage < 100) ? rage : 100; - int32 points = m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); - int32 regen = m_target->GetMaxHealth() * (mod * points / 10) / 1000; - m_target->CastCustomSpell(m_target, 22845, ®en, 0, 0, true, 0, this); - m_target->SetPower(POWER_RAGE, rage-mod); - return; - } - // Force of Nature - case 33831: - return; - default: - break; - } - break; - } - case SPELLFAMILY_ROGUE: - { - switch (spell->Id) - { - // Master of Subtlety - case 31666: - if (!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) - m_target->RemoveAurasDueToSpell(31665); - break; - // Killing Spree - case 51690: - { - // TODO: this should use effect[1] of 51690 - std::list<Unit*> targets; - { - // eff_radius ==0 - float radius = GetSpellMaxRange(spell, false); - - CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(),caster->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - - Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(caster, caster, radius); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(caster,targets, u_check); - - TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); - TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); - - CellLock<GridReadGuard> cell_lock(cell, p); - - cell_lock->Visit(cell_lock, grid_object_checker, *caster->GetMap(), *caster, radius); - cell_lock->Visit(cell_lock, world_object_checker, *caster->GetMap(), *caster, radius); - } - - if(targets.empty()) - return; - - std::list<Unit*>::const_iterator itr = targets.begin(); - std::advance(itr, rand()%targets.size()); - Unit* target = *itr; - - caster->CastSpell(target, 57840, true); - caster->CastSpell(target, 57841, true); - return; - } - // Overkill - case 58428: - if (!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) - m_target->RemoveAurasDueToSpell(58427); - break; -// default: -// break; - } - break; - } - case SPELLFAMILY_HUNTER: - { - // Explosive Shot - if (spell->SpellFamilyFlags[1] & 0x80000000) - { - if(caster) - caster->CastCustomSpell(53352, SPELLVALUE_BASE_POINT0, m_amount, m_target, true, NULL, this); - return; - } - switch (spell->Id) - { - // Feeding Frenzy Rank 1 - case 53511: - if ( m_target->getVictim() && m_target->getVictim()->GetHealth() * 100 < m_target->getVictim()->GetMaxHealth() * 35 ) - m_target->CastSpell(m_target, 60096, true, 0, this); - return; - // Feeding Frenzy Rank 2 - case 53512: - if ( m_target->getVictim() && m_target->getVictim()->GetHealth() * 100 < m_target->getVictim()->GetMaxHealth() * 35 ) - m_target->CastSpell(m_target, 60097, true, 0, this); - return; - default: - break; - } - break; - } - case SPELLFAMILY_SHAMAN: - { - // Astral Shift - if (spell->Id == 52179) - { - // Periodic need for remove visual on stun/fear/silence lost - if (!(m_target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))) - m_target->RemoveAurasDueToSpell(52179); - return; - } - break; - } - case SPELLFAMILY_DEATHKNIGHT: - { - switch (spell->Id) - { - case 49016: //Hysteria - uint32 damage = uint32(m_target->GetMaxHealth()*0.01f); - m_target->DealDamage(m_target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - break; - } - - // Death and Decay - if (spell->SpellFamilyFlags[0] & 0x20) - { - if (caster) - caster->CastCustomSpell(m_target, 52212, &m_amount, NULL, NULL, true, 0, this); - return; - } - // Chains of Ice - if (spell->SpellFamilyFlags[1] & 0x00004000) - { - // Get 0 effect aura - if (AuraEffect *slow = GetParentAura()->GetPartAura(0)) - { - slow->ApplyModifier(false, true); - slow->SetAmount(slow->GetAmount() + GetAmount()); - if (slow->GetAmount() > 0) slow->SetAmount(0); - slow->ApplyModifier(true, true); - } - return; - } - // Summon Gargoyle - // Being pursuaded by Gargoyle - AI related? - // if (spell->SpellFamilyFlags[1] & 0x00000080) - // break; - // Blood of the North - // Reaping - // Death Rune Mastery - if (spell->SpellIconID == 3041 || spell->SpellIconID == 22 || spell->SpellIconID == 2622) - { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Aura not used - prevent removing death runes from other effects - if (!GetAmount()) - return; - if(((Player*)m_target)->getClass() != CLASS_DEATH_KNIGHT) - return; - - // Remove death rune added on proc - for (uint8 i = 0; i < MAX_RUNES && m_amount; ++i) - { - if (m_spellProto->SpellIconID == 2622) - { - if (((Player*)m_target)->GetCurrentRune(i) != RUNE_DEATH || - ((Player*)m_target)->GetBaseRune(i) == RUNE_BLOOD) - continue; - } - else - { - if (((Player*)m_target)->GetCurrentRune(i) != RUNE_DEATH || - ((Player*)m_target)->GetBaseRune(i) != RUNE_BLOOD) - continue; - } - - if (!(m_amount & (1<<i))) - continue; - - ((Player*)m_target)->ConvertRune(i,((Player*)m_target)->GetBaseRune(i)); - } - m_amount = 0; - return; - } - break; - } - default: - break; + AuraApplication * aurApp = appIter->second; + ++appIter; + if (aurApp->_CanBeRemoved()) + aurApp->GetTarget()->_UnapplyAuraEffect(aurApp, effIndex, AURA_REMOVE_BY_DEFAULT); } } -void AuraEffect::HandlePreventFleeing(bool apply, bool Real, bool /*changeAmount*/) +DynObjAura::DynObjAura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID) + : Aura(spellproto, effMask, owner, caster, baseAmount, castItem, casterGUID) { - if(!Real) - return; - - Unit::AuraEffectList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR); - if( !fearAuras.empty() ) - { - m_target->SetControlled(!apply, UNIT_STAT_FLEEING); - /*if (apply) - m_target->SetFeared(false, fearAuras.front()->GetCasterGUID()); - else - m_target->SetFeared(true);*/ - } + GetDynobjOwner()->SetAura(this); } -void AuraEffect::HandleArenaPreparation(bool apply, bool Real, bool /*changeAmount*/) +void DynObjAura::Remove(AuraRemoveMode removeMode) { - if(!Real) + if (IsRemoved()) return; - - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); + _Remove(removeMode); } -/** - * Such auras are applied from a caster(=player) to a vehicle. - * This has been verified using spell #49256 - */ -void AuraEffect::HandleAuraControlVehicle(bool apply, bool Real, bool /*changeAmount*/) +void DynObjAura::UpdateTargetMapForEffect(Unit * caster, uint8 effIndex) { - if(!Real) - return; + float radius = GetDynobjOwner()->GetRadius(); - if(!m_target->IsVehicle()) - return; + // fill up to date target list + UnitList targets; - Unit *caster = GetParentAura()->GetUnitSource(); - if(!caster || caster == m_target) - return; + Unit * dynObjOwnerCaster = GetDynobjOwner()->GetCaster(); - if (apply) + if(GetSpellProto()->EffectImplicitTargetB[effIndex] == TARGET_DEST_DYNOBJ_ALLY + || GetSpellProto()->EffectImplicitTargetB[effIndex] == TARGET_UNIT_AREA_ALLY_DST) { - //if(caster->GetTypeId() == TYPEID_PLAYER) - // if(Pet *pet = ((Player*)caster)->GetPet()) - // pet->Remove(PET_SAVE_AS_CURRENT); - caster->EnterVehicle(m_target->GetVehicleKit(), m_amount - 1); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius); + Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), targets, u_check); + GetDynobjOwner()->VisitNearbyObject(radius, searcher); } else { - if(GetId() == 53111) // Devour Humanoid - { - m_target->Kill(caster); - if(caster->GetTypeId() == TYPEID_UNIT) - ((Creature*)caster)->RemoveCorpse(); - } - - // some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them - caster->RemoveAurasDueToSpell(GetId()); - caster->ExitVehicle(); + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius); + Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetDynobjOwner(), targets, u_check); + GetDynobjOwner()->VisitNearbyObject(radius, searcher); } -} -void AuraEffect::HandleAuraConvertRune(bool apply, bool Real, bool changeAmount) -{ - if(!Real && !changeAmount) - return; + // mark all auras as ready to remove + for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end(); appIter++) + if (appIter->second->HasEffect(effIndex)) + appIter->second->_SetCanBeRemoved(true); - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - Player *plr = (Player*)m_target; - - if(plr->getClass() != CLASS_DEATH_KNIGHT) - return; - - uint32 runes = 0; - // convert number of runes specified in aura amount of rune type in miscvalue to runetype in miscvalueb - for (uint32 i = 0; i < MAX_RUNES && m_amount; ++i) + for (UnitList::iterator appIter = targets.begin(); appIter != targets.end(); appIter++) { - if(apply) + // add an aura to units new in list + ApplicationMap::iterator itr = m_applications.find((*appIter)->GetGUID()); + + if (itr == m_applications.end()) { - if (GetMiscValue() != plr->GetCurrentRune(i)) + // persistent area aura does not hit flying targets + if ((*appIter)->isInFlight() + // check target immunities + || (*appIter)->IsImmunedToSpell(GetSpellProto()) + || (*appIter)->hasUnitState(UNIT_STAT_ISOLATED)) continue; - if(!plr->GetRuneCooldown(i)) - { - plr->ConvertRune(i, RuneType(GetSpellProto()->EffectMiscValueB[m_effIndex])); - runes |= 1<<i; - --m_amount; - } } - else - { - if(plr->GetCurrentRune(i) == RuneType(GetSpellProto()->EffectMiscValueB[m_effIndex])) - { - if (m_amount & (1<<i)) - plr->ConvertRune(i, plr->GetBaseRune(i)); - } - } - } - if (apply) - m_amount = runes; -} - -// Control Auras -void AuraEffect::HandleAuraModStun(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - m_target->SetControlled(apply, UNIT_STAT_STUNNED); -} - -void AuraEffect::HandleAuraModRoot(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - m_target->SetControlled(apply, UNIT_STAT_ROOT); -} - -// Charm Auras - -void AuraEffect::HandleModPossess(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - Unit* caster = GetCaster(); - if(caster && caster->GetTypeId() == TYPEID_UNIT) - { - HandleModCharm(apply, Real, false); - return; - } - - if(apply) - m_target->SetCharmedBy(caster, CHARM_TYPE_POSSESS); - else - m_target->RemoveCharmedBy(caster); -} - -// only one spell has this aura -void AuraEffect::HandleModPossessPet(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - Unit* caster = GetCaster(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; - - //seems it may happen that when removing it is no longer owner's pet - //if(((Player*)caster)->GetPet() != m_target) - // return; - - if(apply) - { - if(((Player*)caster)->GetPet() != m_target) - return; - - m_target->SetCharmedBy(caster, CHARM_TYPE_POSSESS); - } - else - { - m_target->RemoveCharmedBy(caster); - - // Reinitialize the pet bar and make the pet come back to the owner - ((Player*)caster)->PetSpellInitialize(); - if(!m_target->getVictim()) + if (itr == m_applications.end() || !itr->second->HasEffect(effIndex)) { - m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, m_target->GetFollowAngle()); - //if(m_target->GetCharmInfo()) - // m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); - } - } -} - -void AuraEffect::HandleModCharm(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - Unit* caster = GetCaster(); - - if(apply) - m_target->SetCharmedBy(caster, CHARM_TYPE_CHARM); - else - m_target->RemoveCharmedBy(caster); -} - -void AuraEffect::HandleCharmConvert(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - Unit* caster = GetCaster(); - - if(apply) - m_target->SetCharmedBy(caster, CHARM_TYPE_CONVERT); - else - m_target->RemoveCharmedBy(caster); -} - -void AuraEffect::HandlePhase(bool apply, bool Real, bool /*changeAmount*/) -{ - if(!Real) - return; - - // no-phase is also phase state so same code for apply and remove - - // phase auras normally not expected at BG but anyway better check - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - // drop flag at invisible in bg - if(((Player*)m_target)->InBattleGround()) - if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) - bg->EventPlayerDroppedFlag((Player*)m_target); - - // GM-mode have mask 0xFFFFFFFF - if(!((Player*)m_target)->isGameMaster()) - m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false); - - ((Player*)m_target)->GetSession()->SendSetPhaseShift(apply ? GetMiscValue() : PHASEMASK_NORMAL); - } - else - m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false); - - // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases) - if(m_target->GetVisibility()!=VISIBILITY_OFF) - m_target->SetVisibility(m_target->GetVisibility()); -} + if((*appIter)->IsImmunedToSpellEffect(GetSpellProto(), effIndex)) + continue; + // add new unit to persistent area aura + (*appIter)->_ApplyAuraEffect(this, effIndex); -void AuraEffect::HandleAuraInitializeImages( bool Apply, bool Real , bool /*changeAmount*/) -{ - if (!Real) - return; - if (Apply) - { - Unit * caster = GetCaster(); - if (!caster) - return; - // Set item visual - if (caster->GetTypeId()== TYPEID_PLAYER) - { - if (Item const * item = ((Player *)caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) - m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, item->GetProto()->ItemId); - if (Item const * item = ((Player *)caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) - m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, item->GetProto()->ItemId); - } - else // TYPEID_UNIT - { - m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)); - m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1)); - m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, caster->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2)); + // start combat with targeted enemy + if(GetSpellProto()->EffectImplicitTargetB[effIndex] != TARGET_DEST_DYNOBJ_ALLY + && GetSpellProto()->EffectImplicitTargetB[effIndex] != TARGET_UNIT_AREA_ALLY_DST) + dynObjOwnerCaster->CombatStart(*appIter); } - } - else - { - // Remove equipment visual - if (m_target->GetTypeId() == TYPEID_PLAYER) - { - for (uint8 i = 0; i < 3; ++i) - m_target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0); - } - else // TYPEID_UNIT - { - ((Creature*)m_target)->LoadEquipment(((Creature*)m_target)->GetEquipmentId()); - } - } -} - -void AuraEffect::HandleAuraCloneCaster( bool Apply, bool Real , bool /*changeAmount*/) -{ - if (!Real) - return; - if (Apply) - { - Unit * caster = GetCaster(); - if (!caster) - return; - // Set display id (probably for portrait?) - m_target->SetDisplayId(caster->GetDisplayId()); - m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE); + itr = m_applications.find((*appIter)->GetGUID()); + if (itr != m_applications.end()) + // mark aura of unit already in list to be not removed + itr->second->_SetCanBeRemoved(false); } - else - { - m_target->SetDisplayId(m_target->GetNativeDisplayId()); - m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE); - } -} -void AuraEffect::HandleAuraModCritPct(bool apply, bool Real, bool changeAmount) -{ - /* - if(m_target->GetTypeId() != TYPEID_PLAYER) + // remove auras which are not in current area + for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end();) { - m_target->m_baseSpellCritChance += apply ? m_amount:-m_amount; - return; + AuraApplication * aurApp = appIter->second; + ++appIter; + if (aurApp->_CanBeRemoved()) + aurApp->GetTarget()->_UnapplyAuraEffect(aurApp, effIndex, AURA_REMOVE_BY_DEFAULT); } - - if(Real || changeAmount) - ((Player*)m_target)->UpdateAllSpellCritChances(); - - ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - */ - // spells required only Real aura add/remove - if(!Real) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); - - // included in Player::UpdateSpellCritChance calculation - ((Player*)m_target)->UpdateAllSpellCritChances(); -} - -void AuraEffect::HandleAuraLinked(bool apply, bool Real, bool /*changeAmount*/) -{ - if (!Real) - return; - - if (apply) - { - Unit * caster = GetCaster(); - if (!caster) - return; - // If amount avalible cast with basepoints (Crypt Fever for example) - if (m_amount) - caster->CastCustomSpell(m_target, m_spellProto->EffectTriggerSpell[m_effIndex], &m_amount, NULL, NULL, true, NULL, this); - else - caster->CastSpell(m_target, m_spellProto->EffectTriggerSpell[m_effIndex],true, NULL, this); - } - else - m_target->RemoveAura(m_spellProto->EffectTriggerSpell[m_effIndex], GetCasterGUID(), AuraRemoveMode(GetParentAura()->GetRemoveMode())); -} - -int32 AuraEffect::CalculateCrowdControlAuraAmount(Unit * caster) -{ - // Damage cap for CC effects - if (!m_spellProto->procFlags) - return 0; - - if (m_auraName !=SPELL_AURA_MOD_CONFUSE && - m_auraName !=SPELL_AURA_MOD_FEAR && - m_auraName !=SPELL_AURA_MOD_STUN && - m_auraName !=SPELL_AURA_MOD_ROOT && - m_auraName !=SPELL_AURA_TRANSFORM) - return 0; - - int32 damageCap = (int32)(m_target->GetMaxHealth()*0.10f); - - if (!caster) - return damageCap; - - // Glyphs increasing damage cap - Unit::AuraEffectList const& overrideClassScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for (Unit::AuraEffectList::const_iterator itr = overrideClassScripts.begin(); itr != overrideClassScripts.end(); ++itr) - { - if((*itr)->isAffectedOnSpell(m_spellProto)) - { - // Glyph of Fear, Glyph of Frost nova and similar auras - if ((*itr)->GetMiscValue() == 7801) - { - damageCap += (int32)(damageCap*(*itr)->GetAmount()/100.0f); - break; - } - } - } - return damageCap; -} - -bool AuraEffect::IsPeriodicTickCrit(Unit const * pCaster) const -{ - Unit::AuraEffectList const& mPeriodicCritAuras= pCaster->GetAurasByType(SPELL_AURA_ABILITY_PERIODIC_CRIT); - for (Unit::AuraEffectList::const_iterator itr = mPeriodicCritAuras.begin(); itr != mPeriodicCritAuras.end(); ++itr) - { - if ((*itr)->isAffectedOnSpell(m_spellProto) && pCaster->isSpellCrit(m_target, m_spellProto, GetSpellSchoolMask(m_spellProto))) - return true; - } - return false; -} - -void AuraEffect::HandleAuraModInebriation(bool apply, bool Real, bool /*changeAmount*/) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - m_target->SetUInt32Value(PLAYER_FAKE_INEBRIATION, apply ? ((uint32)1)<<(GetMiscValue()-1) : 0 ); } diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 83576d6be34..0d855fd0647 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -17,419 +17,207 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef TRINITY_SPELLAURAS_H #define TRINITY_SPELLAURAS_H #include "SpellAuraDefines.h" -class Unit; +class Unit; struct SpellEntry; struct SpellModifier; struct ProcTriggerSpell; // forward decl -class Aura; class AuraEffect; +class Aura; +class DynamicObject; + +class AuraApplication +{ + friend AuraApplication * Unit::__ApplyAura(Aura * aura); + friend void Unit::__UnapplyAura(AuraApplicationMap::iterator &i); + friend bool Unit::_ApplyAuraEffect(Aura * aura, uint8 effIndex); + private: + Unit * const m_target; + Aura * const m_base; + uint8 m_slot; // Aura slot on unit + uint8 m_flags; // Aura info flag + AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason + bool m_needClientUpdate:1; + bool m_isNeedManyNegativeEffects:1; + bool m_canBeRemoved:1; // used only in aura list update of AuraBase + + explicit AuraApplication(Unit * target, Unit * caster, Aura * base); + void _Remove(); + private: + bool _CheckPositive(Unit * caster) const; + void _HandleEffect(uint8 effIndex, bool apply); + public: + bool _CanBeRemoved() const {return m_canBeRemoved;} + void _SetCanBeRemoved(bool val) {m_canBeRemoved = val;} -typedef void(AuraEffect::*pAuraHandler)(bool Apply, bool Real, bool changeAmount); -// Real == true at aura add/remove -// Real == false at aura mod unapply/reapply; when adding/removing dependent aura/item/stat mods -// -// Code in aura handler can be guarded by if(Real) check if it should execution only at real add/remove of aura -// -// MAIN RULE: Code MUST NOT be guarded by if(Real) check if it modifies any stats -// (percent auras, stats mods, etc) -// Second rule: Code must be guarded by if(Real) check if it modifies object state (start/stop attack, send packets to client, etc) -// -// Other case choice: each code line moved under if(Real) check is Trinity speedup, -// each setting object update field code line moved under if(Real) check is significant Trinity speedup, and less server->client data sends -// each packet sending code moved under if(Real) check is _large_ Trinity speedup, and lot less server->client data sends -// -// changeAmount == true at changing existing aura amount - called wit real == false -// if aura has amount dependant effect handler has to allow proceeding it -// example: change speed aura, modifier aura + Unit * GetTarget() const { return m_target; } + Aura * GetBase() const { return m_base; } + + uint8 GetSlot() const { return m_slot; } + uint8 GetFlags() const { return m_flags; } + uint8 GetEffectMask() const { return m_flags & (AFLAG_EFF_INDEX_0 | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2); } + bool HasEffect(uint8 effect) const { assert(effect < MAX_SPELL_EFFECTS); return m_flags & (1<<effect); } + bool IsPositive() const { return m_flags & AFLAG_POSITIVE; } + + void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } + AuraRemoveMode GetRemoveMode() const {return m_removeMode;} + + void SetNeedClientUpdate() { m_needClientUpdate = true;} + bool IsNeedClientUpdate() const { return m_needClientUpdate;} + void ClientUpdate(bool remove = false); +}; class TRINITY_DLL_SPEC Aura { - friend void Player::SendAurasForTarget(Unit *target); public: - virtual ~Aura(); - explicit Aura(SpellEntry const* spellproto, uint32 effMask, Unit *target, WorldObject *source, Unit *caster, int32 *currentBasePoints = NULL, Item *castItem = NULL); + typedef UNORDERED_MAP<uint64, AuraApplication *> ApplicationMap; + + static Aura * TryCreate(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount = NULL, Item * castItem = NULL, uint64 casterGUID = 0); + static Aura * TryCreate(SpellEntry const* spellproto, WorldObject * owner, Unit * caster, int32 *baseAmount = NULL, Item * castItem = NULL, uint64 casterGUID = 0); + static Aura * Create(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount = NULL, Item * castItem = NULL, uint64 casterGUID = 0); + explicit Aura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); + ~Aura(); SpellEntry const* GetSpellProto() const { return m_spellProto; } - uint32 GetId() const{ return m_spellProto->Id; } - uint64 GetCastItemGUID() const { return m_castItemGuid; } + uint32 GetId() const{ return GetSpellProto()->Id; } + uint64 GetCastItemGUID() const { return m_castItemGuid; } uint64 const& GetCasterGUID() const { return m_casterGuid; } Unit* GetCaster() const; - uint64 const& GetSourceGUID() const { return m_sourceGuid; } - Unit *GetUnitSource() const; - Unit* GetTarget() const { return m_target; } - time_t GetAuraApplyTime() const { return m_applyTime; } - - int32 GetAuraMaxDuration() const { return m_maxduration; } - void SetAuraMaxDuration(int32 duration) { m_maxduration = duration; } - int32 GetAuraDuration() const { return m_duration; } - void SetAuraDuration(int32 duration, bool withMods = false); - void RefreshAura() { SetAuraDuration(m_maxduration);} - bool IsExpired() const { return !GetAuraDuration() && !(IsPermanent() || IsPassive()); } - - void SendAuraUpdate(); - uint8 GetAuraSlot() const { return m_auraSlot; } - void SetAuraSlot(uint8 slot) { m_auraSlot = slot; } - uint8 GetAuraCharges() const { return m_procCharges; } - void SetAuraCharges(uint8 charges); - bool DropAuraCharge(); - void SetProcDamage(uint32 val) { m_procDamage = val; } - uint32 GetProcDamage() const { return m_procDamage; } + WorldObject * GetOwner() const { return m_owner; } + Unit * GetUnitOwner() const { assert(GetType() == UNIT_AURA_TYPE); return (Unit*)m_owner; } + DynamicObject * GetDynobjOwner() const { assert(GetType() == DYNOBJ_AURA_TYPE); return (DynamicObject*)m_owner; } - uint8 GetStackAmount() const { return m_stackAmount; } - void SetStackAmount(uint8 num, bool applied = true); - bool modStackAmount(int32 num); // return true if last charge dropped + AuraObjectType GetType() const; - void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } - uint8 GetRemoveMode() const {return m_removeMode;} + virtual void _ApplyForTarget(Unit * target, Unit * caster, AuraApplication * auraApp); + virtual void _UnapplyForTarget(Unit * target, Unit * caster, AuraApplication * auraApp); + void _Remove(AuraRemoveMode removeMode); + virtual void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) = 0; - inline uint8 GetEffectMask() const {return m_auraFlags & 7;} - AuraEffect * GetPartAura (uint8 effIndex) const {assert (effIndex < MAX_SPELL_EFFECTS); return m_partAuras[effIndex];} - bool SetPartAura(AuraEffect* aurEff, uint8 effIndex); + virtual void UpdateTargetMapForEffect(Unit * caster, uint8 effIndex) = 0; + void UpdateTargetMap(Unit * caster); - bool IsPositive() const { return m_positive; } - void SetNegative() { m_positive = false; } - void SetPositive() { m_positive = true; } - bool IsPermanent() const { return m_permanent; } - void SetPermanent(bool val) { m_permanent = val; } + void ApplyForTargets() {Unit * caster = GetCaster(); UpdateTargetMap(caster);} + void ApplyEffectForTargets(uint8 effIndex) {Unit * caster = GetCaster(); UpdateTargetMapForEffect(caster, effIndex);} - bool IsPassive() const { return m_isPassive; } - bool IsDeathPersistent() const { return m_isDeathPersist; } - bool IsRemovedOnShapeLost() const { return m_isRemovedOnShapeLost; } - bool CanBeSaved() const; - bool IsRemoved() const { return m_isRemoved; } + void UpdateOwner(uint32 diff, WorldObject * owner); + void Update(uint32 diff, Unit * caster); - bool IsPersistent() const; - bool IsAreaAura() const; - bool IsAuraType(AuraType type) const; - void SetLoadedState(uint64 caster_guid,int32 maxduration,int32 duration,int32 charges, uint8 stackamount, int32 * amount); - bool HasEffect(uint8 effIndex) const {return bool (m_partAuras[effIndex]);} - inline void HandleEffects(bool apply) - { - for (uint8 i = 0; i<MAX_SPELL_EFFECTS; ++i) - if (m_partAuras[i]) - m_target->HandleAuraEffect(m_partAuras[i], apply); - } - void ApplyAllModifiers(bool apply, bool Real=false); - void HandleAuraSpecificMods(bool apply); - - void Update(uint32 diff); - - void _AddAura(); - void _RemoveAura(); + time_t GetApplyTime() const { return m_applyTime; } + int32 GetMaxDuration() const { return m_maxDuration; } + void SetMaxDuration(int32 duration) { m_maxDuration = duration; } + int32 GetDuration() const { return m_duration; } + void SetDuration(int32 duration, bool withMods = false); + void RefreshDuration(); + bool IsExpired() const { return !GetDuration();} + bool IsPermanent() const { return GetMaxDuration() == -1; } - // Allow Apply Aura Handler to modify and access m_AuraDRGroup - void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } - DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; } + uint8 GetCharges() const { return m_procCharges; } + void SetCharges(uint8 charges); + bool DropCharge(); - // Single cast aura helpers - void UnregisterSingleCastAura(); - bool IsSingleTarget() const {return m_isSingleTargetAura;} - void SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;} + uint8 GetStackAmount() const { return m_stackAmount; } + void SetStackAmount(uint8 num, bool applied = true); + bool ModStackAmount(int32 num); // return true if last charge dropped + + uint8 GetCasterLevel() const { return m_casterLevel; } + bool IsPassive() const; + bool IsDeathPersistent() const; + bool IsRemovedOnShapeLost(Unit * target) const { return (GetCasterGUID() == target->GetGUID() && m_spellProto->Stances && !(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && !(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT)); } + bool CanBeSaved() const; + bool IsRemoved() const { return m_isRemoved; } + bool IsVisible() const; + // Single cast aura helpers + bool IsSingleTarget() const {return m_isSingleTarget;} + void SetIsSingleTarget(bool val) { m_isSingleTarget = val;} + + void SetLoadedState(int32 maxduration, int32 duration, int32 charges, uint8 stackamount, uint8 recalculateMask, int32 * amount); + + // helpers for aura effects + bool HasEffect(uint8 effIndex) const { return bool(GetEffect(effIndex)); } + bool HasEffectType(AuraType type) const; + AuraEffect * GetEffect (uint8 effIndex) const { assert (effIndex < MAX_SPELL_EFFECTS); return m_effects[effIndex]; } + uint8 GetEffectMask() const { uint8 effMask = 0; for(uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) if (m_effects[i]) effMask |= 1<<i; return effMask; } + void RecalculateAmountOfEffects(); + void HandleAllEffects(AuraApplication const * aurApp, uint8 mode, bool apply); + + // Helpers for targets + ApplicationMap const & GetApplicationMap() {return m_applications;} + const AuraApplication * GetApplicationOfTarget (uint64 const & guid) const { ApplicationMap::const_iterator itr = m_applications.find(guid); if (itr != m_applications.end()) return itr->second; return NULL; } + AuraApplication * GetApplicationOfTarget (uint64 const & guid) { ApplicationMap::iterator itr = m_applications.find(guid); if (itr != m_applications.end()) return itr->second; return NULL; } + bool IsAppliedOnTarget (uint64 const & guid) const { return m_applications.find(guid) != m_applications.end(); } + + bool IsPositive(Unit * const target) const { return (GetApplicationOfTarget(target->GetGUID()))->IsPositive(); } + bool GetEffectMask(Unit * const target) const { return (GetApplicationOfTarget(target->GetGUID()))->GetEffectMask(); } + uint8 GetSlot(Unit * const target) const { return (GetApplicationOfTarget(target->GetGUID()))->GetSlot(); } + bool HasEffect(Unit * const target, uint8 eff) const { return (GetApplicationOfTarget(target->GetGUID()))->HasEffect(eff); } + void SetNeedClientUpdateForTargets() const; + void HandleAuraSpecificMods(AuraApplication const * aurApp, Unit * caster, bool apply); private: - const SpellEntry * const m_spellProto; - Unit * const m_target; - //WorldObject * const m_source; - const uint64 m_sourceGuid; - const uint64 m_casterGuid; - const uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted - const time_t m_applyTime; - - int32 m_maxduration; // Max aura duration + void _DeleteRemovedApplications(); + protected: + SpellEntry const * const m_spellProto; + uint64 const m_casterGuid; + uint64 const m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted + time_t const m_applyTime; + WorldObject * const m_owner; // + + int32 m_maxDuration; // Max aura duration int32 m_duration; // Current time int32 m_timeCla; // Timer for power per sec calcultion - AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason - DiminishingGroup m_AuraDRGroup:8; // Diminishing - - uint8 m_auraSlot; // Aura slot on unit (for show in client) - uint8 m_auraFlags; // Aura info flag (for send data to client) - uint8 m_auraLevel; // Aura level (store caster level for correct show level dep amount) + uint8 const m_casterLevel; // Aura level (store caster level for correct show level dep amount) uint8 m_procCharges; // Aura charges (0 for infinite) uint8 m_stackAmount; // Aura stack amount - AuraEffect * m_partAuras[3]; - uint32 m_procDamage; // used in aura proc code + AuraEffect * m_effects[3]; + ApplicationMap m_applications; - bool m_isDeathPersist:1; - bool m_isRemovedOnShapeLost:1; - bool m_isPassive:1; - bool m_positive:1; - bool m_permanent:1; bool m_isRemoved:1; - bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example + bool m_isSingleTarget:1; // true if it's a single target spell and registered at caster - can change at spell steal for example - bool IsVisible() const; + private: + Unit::AuraApplicationList m_removedApplications; }; -class TRINITY_DLL_SPEC AuraEffect +class TRINITY_DLL_SPEC UnitAura : public Aura { - public: - friend AuraEffect* CreateAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints); - friend void Aura::SetStackAmount(uint8 stackAmount, bool applied); - //aura handlers - void HandleNULL(bool, bool, bool) - { - // NOT IMPLEMENTED - } - void HandleUnused(bool, bool, bool) - { - // NOT USED BY ANY SPELL OR USELESS - } - void HandleNoImmediateEffect(bool, bool, bool) - { - // aura not have immediate effect at add/remove and handled by ID in other code place - } - void HandleBindSight(bool Apply, bool Real, bool changeAmount); - void HandleModPossess(bool Apply, bool Real, bool changeAmount); - void HandlePeriodicDamage(bool Apply, bool Real, bool changeAmount); - void HandleAuraDummy(bool Apply, bool Real, bool changeAmount); - void HandleAuraPeriodicDummy(bool apply, bool Real, bool changeAmount); - void HandleModConfuse(bool Apply, bool Real, bool changeAmount); - void HandleModCharm(bool Apply, bool Real, bool changeAmount); - void HandleModFear(bool Apply, bool Real, bool changeAmount); - void HandlePeriodicHeal(bool Apply, bool Real, bool changeAmount); - void HandleModAttackSpeed(bool Apply, bool Real, bool changeAmount); - void HandleModMeleeRangedSpeedPct(bool apply, bool Real, bool changeAmount); - void HandleModCombatSpeedPct(bool apply, bool Real, bool changeAmount); - void HandleModThreat(bool Apply, bool Real, bool changeAmount); - void HandleModTaunt(bool Apply, bool Real, bool changeAmount); - void HandleFeignDeath(bool Apply, bool Real, bool changeAmount); - void HandleAuraModDisarm(bool Apply, bool Real, bool changeAmount); - void HandleAuraModStalked(bool Apply, bool Real, bool changeAmount); - void HandleAuraWaterWalk(bool Apply, bool Real, bool changeAmount); - void HandleAuraFeatherFall(bool Apply, bool Real, bool changeAmount); - void HandleAuraHover(bool Apply, bool Real, bool changeAmount); - void HandleAddModifier(bool Apply, bool Real, bool changeAmount); - void HandleAuraModStun(bool Apply, bool Real, bool changeAmount); - void HandleModDamageDone(bool Apply, bool Real, bool changeAmount); - void HandleAuraUntrackable(bool Apply, bool Real, bool changeAmount); - void HandleAuraEmpathy(bool Apply, bool Real, bool changeAmount); - void HandleModOffhandDamagePercent(bool apply, bool Real, bool changeAmount); - void HandleAuraModRangedAttackPower(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseEnergyPercent(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseHealthPercent(bool Apply, bool Real, bool changeAmount); - void HandleAuraModRegenInterrupt(bool Apply, bool Real, bool changeAmount); - void HandleHaste(bool Apply, bool Real, bool changeAmount); - void HandlePeriodicTriggerSpell(bool Apply, bool Real, bool changeAmount); - void HandlePeriodicTriggerSpellWithValue(bool apply, bool Real, bool changeAmount); - void HandlePeriodicEnergize(bool Apply, bool Real, bool changeAmount); - void HandleAuraModResistanceExclusive(bool Apply, bool Real, bool changeAmount); - void HandleAuraModPetTalentsPoints(bool Apply, bool Real, bool changeAmount); - void HandleModStealth(bool Apply, bool Real, bool changeAmount); - void HandleInvisibility(bool Apply, bool Real, bool changeAmount); - void HandleInvisibilityDetect(bool Apply, bool Real, bool changeAmount); - void HandleAuraModTotalHealthPercentRegen(bool Apply, bool Real, bool changeAmount); - void HandleAuraModTotalEnergyPercentRegen(bool Apply, bool Real, bool changeAmount); - void HandleAuraModResistance(bool Apply, bool Real, bool changeAmount); - void HandleAuraModRoot(bool Apply, bool Real, bool changeAmount); - void HandleAuraModSilence(bool Apply, bool Real, bool changeAmount); - void HandleAuraModStat(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseSpeed(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseMountedSpeed(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseFlightSpeed(bool Apply, bool Real, bool changeAmount); - void HandleAuraModDecreaseSpeed(bool Apply, bool Real, bool changeAmount); - void HandleAuraModUseNormalSpeed(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseHealth(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseEnergy(bool Apply, bool Real, bool changeAmount); - void HandleAuraModShapeshift(bool Apply, bool Real, bool changeAmount); - void HandleAuraModEffectImmunity(bool Apply, bool Real, bool changeAmount); - void HandleAuraModStateImmunity(bool Apply, bool Real, bool changeAmount); - void HandleAuraModSchoolImmunity(bool Apply, bool Real, bool changeAmount); - void HandleAuraModDmgImmunity(bool Apply, bool Real, bool changeAmount); - void HandleAuraModDispelImmunity(bool Apply, bool Real, bool changeAmount); - void HandleAuraProcTriggerSpell(bool Apply, bool Real, bool changeAmount); - void HandleAuraTrackCreatures(bool Apply, bool Real, bool changeAmount); - void HandleAuraTrackResources(bool Apply, bool Real, bool changeAmount); - void HandleAuraModParryPercent(bool Apply, bool Real, bool changeAmount); - void HandleAuraModDodgePercent(bool Apply, bool Real, bool changeAmount); - void HandleAuraModBlockPercent(bool Apply, bool Real, bool changeAmount); - void HandleAuraModWeaponCritPercent(bool Apply, bool Real, bool changeAmount); - void HandlePeriodicLeech(bool Apply, bool Real, bool changeAmount); - void HandleModHitChance(bool Apply, bool Real, bool changeAmount); - void HandleModSpellHitChance(bool Apply, bool Real, bool changeAmount); - void HandleAuraModScale(bool Apply, bool Real, bool changeAmount); - void HandlePeriodicManaLeech(bool Apply, bool Real, bool changeAmount); - void HandlePeriodicHealthFunnel(bool apply, bool Real, bool changeAmount); - void HandleModCastingSpeed(bool Apply, bool Real, bool changeAmount); - void HandleAuraMounted(bool Apply, bool Real, bool changeAmount); - void HandleWaterBreathing(bool Apply, bool Real, bool changeAmount); - void HandleModBaseResistance(bool Apply, bool Real, bool changeAmount); - void HandleModRegen(bool Apply, bool Real, bool changeAmount); - void HandleModPowerRegen(bool Apply, bool Real, bool changeAmount); - void HandleModPowerRegenPCT(bool Apply, bool Real, bool changeAmount); - void HandleChannelDeathItem(bool Apply, bool Real, bool changeAmount); - void HandlePeriodicDamagePCT(bool Apply, bool Real, bool changeAmount); - void HandleAuraModAttackPower(bool Apply, bool Real, bool changeAmount); - void HandleAuraTransform(bool Apply, bool Real, bool changeAmount); - void HandleModSpellCritChance(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseSwimSpeed(bool Apply, bool Real, bool changeAmount); - void HandleModPowerCostPCT(bool Apply, bool Real, bool changeAmount); - void HandleModPowerCost(bool Apply, bool Real, bool changeAmount); - void HandleFarSight(bool Apply, bool Real, bool changeAmount); - void HandleModPossessPet(bool Apply, bool Real, bool changeAmount); - void HandleModMechanicImmunity(bool Apply, bool Real, bool changeAmount); - void HandleModStateImmunityMask(bool apply, bool Real, bool changeAmount); - void HandleAuraModSkill(bool Apply, bool Real, bool changeAmount); - void HandleModDamagePercentDone(bool Apply, bool Real, bool changeAmount); - void HandleModPercentStat(bool Apply, bool Real, bool changeAmount); - void HandleModResistancePercent(bool Apply, bool Real, bool changeAmount); - void HandleAuraModBaseResistancePCT(bool Apply, bool Real, bool changeAmount); - void HandleModShieldBlockPCT(bool Apply, bool Real, bool changeAmount); - void HandleAuraTrackStealthed(bool Apply, bool Real, bool changeAmount); - void HandleModShieldBlock(bool Apply, bool Real, bool changeAmount); - void HandleForceReaction(bool Apply, bool Real, bool changeAmount); - void HandleAuraModRangedHaste(bool Apply, bool Real, bool changeAmount); - void HandleRangedAmmoHaste(bool Apply, bool Real, bool changeAmount); - void HandleModHealingDone(bool Apply, bool Real, bool changeAmount); - void HandleModTotalPercentStat(bool Apply, bool Real, bool changeAmount); - void HandleAuraModTotalThreat(bool Apply, bool Real, bool changeAmount); - void HandleModUnattackable(bool Apply, bool Real, bool changeAmount); - void HandleAuraModPacify(bool Apply, bool Real, bool changeAmount); - void HandleAuraGhost(bool Apply, bool Real, bool changeAmount); - void HandleAuraAllowFlight(bool Apply, bool Real, bool changeAmount); - void HandleModRating(bool apply, bool Real, bool changeAmount); - void HandleModRatingFromStat(bool apply, bool Real, bool changeAmount); - void HandleModTargetResistance(bool apply, bool Real, bool changeAmount); - void HandleAuraModAttackPowerPercent(bool apply, bool Real, bool changeAmount); - void HandleAuraModRangedAttackPowerPercent(bool apply, bool Real, bool changeAmount); - void HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real, bool changeAmount); - void HandleAuraModAttackPowerOfArmor(bool apply, bool Real, bool changeAmount); - void HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real, bool changeAmount); - void HandleSpiritOfRedemption(bool apply, bool Real, bool changeAmount); - void HandleModManaRegen(bool apply, bool Real, bool changeAmount); - void HandleComprehendLanguage(bool apply, bool Real, bool changeAmount); - void HandleShieldBlockValue(bool apply, bool Real, bool changeAmount); - void HandleModSpellCritChanceShool(bool apply, bool Real, bool changeAmount); - void HandleAuraRetainComboPoints(bool apply, bool Real, bool changeAmount); - void HandleModSpellDamagePercentFromStat(bool apply, bool Real, bool changeAmount); - void HandleModSpellHealingPercentFromStat(bool apply, bool Real, bool changeAmount); - void HandleAuraControlVehicle(bool apply, bool Real, bool changeAmount); - void HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real, bool changeAmount); - void HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real, bool changeAmount); - void HandleAuraModPacifyAndSilence(bool Apply, bool Real, bool changeAmount); - void HandleAuraModIncreaseMaxHealth(bool apply, bool Real, bool changeAmount); - void HandleAuraModExpertise(bool apply, bool Real, bool changeAmount); - void HandleForceMoveForward(bool apply, bool Real, bool changeAmount); - void HandleAuraModResistenceOfStatPercent(bool apply, bool Real, bool changeAmount); - void HandleAuraPowerBurn(bool apply, bool Real, bool changeAmount); - void HandlePreventFleeing(bool apply, bool Real, bool changeAmount); - void HandleArenaPreparation(bool apply, bool Real, bool changeAmount); - void HandleAuraConvertRune(bool apply, bool Real, bool changeAmount); - void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real, bool changeAmount); - void HandleNoReagentUseAura(bool Apply, bool Real, bool changeAmount); - void HandlePhase(bool Apply, bool Real, bool changeAmount); - void HandleAuraAllowOnlyAbility(bool apply, bool Real, bool changeAmount); - void HandleCharmConvert(bool apply, bool Real, bool changeAmount); - void HandleAuraInitializeImages(bool Apply, bool Real, bool changeAmount); - void HandleAuraCloneCaster(bool Apply, bool Real, bool changeAmount); - void HandleAuraModCritPct(bool Apply, bool Real, bool changeAmount); - void HandleAuraLinked(bool Apply, bool Real, bool changeAmount); - void HandleAuraModInebriation(bool apply, bool Real, bool changeAmount); - - void HandleAuraEffectSpecificMods(bool apply, bool Real, bool changeAmount); - int32 CalculateCrowdControlAuraAmount(Unit * caster); - - // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras - void HandleShapeshiftBoosts(bool apply); - - Unit * GetCaster() const { return m_parentAura->GetCaster(); } - uint64 GetCasterGUID() const{ return m_parentAura->GetCasterGUID(); } - Aura * GetParentAura() const { return m_parentAura; } - - SpellEntry const* GetSpellProto() const { return m_spellProto; } - uint32 GetId() const { return m_spellProto->Id; } - uint32 GetEffIndex() const { return m_effIndex; } - int32 GetBasePoints() const { return m_currentBasePoints; } - int32 GetAuraAmplitude(){return m_amplitude;} - void ResetPeriodicTimer(){m_periodicTimer = m_amplitude;} - - virtual void Update(uint32 diff); - - uint32 GetTickNumber() const { return m_tickNumber; } - int32 GetTotalTicks () const { return m_amplitude ? (GetParentAura()->GetAuraMaxDuration() / m_amplitude) : 1;} - bool IsAreaAura() const { return m_isAreaAura; } - bool IsPeriodic() const { return m_isPeriodic; } - bool IsPersistent() const { return m_isPersistent; } - bool IsApplied() const { return m_isApplied; } - void SetApplied (bool val) {m_isApplied = val; } - bool isAffectedOnSpell(SpellEntry const *spell) const; - - void ApplyModifier(bool apply, bool Real = false, bool changeAmount=false); - void RecalculateAmount(bool applied = true); - void HandleAuraEffect(bool apply); - void ApplyAllModifiers(bool apply, bool Real); - - Unit* GetTriggerTarget() const; - void TriggerSpell(); - void TriggerSpellWithValue(); - void PeriodicTick(); - void PeriodicDummyTick(); - - int32 GetMiscBValue() const {return m_spellProto->EffectMiscValueB[m_effIndex];} - int32 GetMiscValue() const {return m_spellProto->EffectMiscValue[m_effIndex];} - uint32 GetAuraName() const {return m_auraName;} - int32 GetAmount() const {return m_amount;} - void SetAmount(int32 amount) { m_amount = amount; } - void CleanupTriggeredSpells(); - + friend Aura * Aura::Create(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); protected: - explicit AuraEffect(Aura * parentAura, uint8 effIndex, int32 *currentBasePoints = NULL); - Aura * const m_parentAura; - Unit * const m_target; - - uint32 m_tickNumber; + explicit UnitAura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); + public: + void _ApplyForTarget(Unit * target, Unit * caster, AuraApplication * aurApp); + void _UnapplyForTarget(Unit * target, Unit * caster, AuraApplication * aurApp); - const SpellEntry * const m_spellProto; - const uint8 m_effIndex; - const AuraType m_auraName; - int32 m_currentBasePoints; - int32 m_amount; + void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); - SpellModifier *m_spellmod; + void UpdateTargetMapForEffect(Unit * caster, uint8 effIndex); - int32 m_periodicTimer; // Timer for periodic auras - int32 m_amplitude; + // Allow Apply Aura Handler to modify and access m_AuraDRGroup + void SetDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } + DiminishingGroup GetDiminishGroup() const { return m_AuraDRGroup; } - bool m_isPeriodic:1; - bool m_isAreaAura:1; - bool m_isPersistent:1; - bool m_isApplied:1; private: - bool IsPeriodicTickCrit(Unit const * pCaster) const; + DiminishingGroup m_AuraDRGroup:8; // Diminishing }; -class TRINITY_DLL_SPEC AreaAuraEffect : public AuraEffect +class TRINITY_DLL_SPEC DynObjAura : public Aura { - public: - friend AuraEffect* CreateAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints); - void Update(uint32 diff); - Unit *GetSource() const { return GetParentAura()->GetUnitSource(); } + friend Aura * Aura::Create(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); protected: - explicit AreaAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints = NULL); - float m_radius; - int32 m_removeTime; - AreaAuraType m_areaAuraType; -}; - -class TRINITY_DLL_SPEC PersistentAreaAuraEffect : public AuraEffect -{ + explicit DynObjAura(SpellEntry const* spellproto, uint8 effMask, WorldObject * owner, Unit * caster, int32 *baseAmount, Item * castItem, uint64 casterGUID); public: - friend AuraEffect* CreateAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints); - void Update(uint32 diff); - DynamicObject *GetSource() const; - protected: - explicit PersistentAreaAuraEffect(Aura * parentAura, uint32 eff, int32 *currentBasePoints = NULL); -}; - -AuraEffect* CreateAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints = NULL); + void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void UpdateTargetMapForEffect(Unit * caster, uint8 effIndex); +}; #endif diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index a39c7adbc77..8e3af99e89c 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -34,6 +34,7 @@ #include "SpellId.h" #include "DynamicObject.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" #include "Group.h" #include "UpdateData.h" #include "MapManager.h" @@ -196,7 +197,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectApplyAreaAura, //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY &Spell::EffectRedirectThreat, //130 SPELL_EFFECT_REDIRECT_THREAT - &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells + &Spell::EffectPlayerNotification, //131 SPELL_EFFECT_PLAYER_NOTIFICATION &Spell::EffectPlayMusic, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc) &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry @@ -362,14 +363,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) case SPELL_POSITIVE_CHARGE_39090: spellId = SPELL_POSITIVE_CHARGE_39089; break; case SPELL_NEGATIVE_CHARGE_39093: spellId = SPELL_NEGATIVE_CHARGE_39092; break; } - Aura *aur = m_caster->GetAura(spellId); - if (!aur) - { - m_caster->CastSpell(m_caster, spellId, true); - aur = m_caster->GetAura(spellId); - } - if (aur) - aur->SetStackAmount(count); + m_caster->SetAuraStack(spellId, m_caster, count); } } @@ -464,7 +458,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) // Check aura state for speed but aura state set not only for Immolate spell if(unitTarget->HasAuraState(AURA_STATE_CONFLAGRATE)) { - if (unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x4)) + if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x4, 0, 0)) damage += damage/4; } } @@ -473,7 +467,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) { AuraEffect const* aura = NULL; // found req. aura for damage calculation - Unit::AuraEffectList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + Unit::AuraEffectList const &mPeriodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE); for (Unit::AuraEffectList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i) { // for caster applied auras only @@ -497,7 +491,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if (aura) { uint32 pdamage = aura->GetAmount() > 0 ? aura->GetAmount() : 0; - pdamage = m_caster->SpellDamageBonus(unitTarget, aura->GetSpellProto(), pdamage, DOT, aura->GetParentAura()->GetStackAmount()); + pdamage = m_caster->SpellDamageBonus(unitTarget, aura->GetSpellProto(), pdamage, DOT, aura->GetBase()->GetStackAmount()); damage += pdamage * 4; // 4 ticks of 3 seconds = 12 secs apply_direct_bonus = false; // Glyph of Conflagrate @@ -525,7 +519,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) { int32 back_damage = m_caster->SpellDamageBonus(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE); // Pain and Suffering reduces damage - if (AuraEffect * aurEff = m_caster->GetDummyAura(SPELLFAMILY_PRIEST, 2874, 0)) + if (AuraEffect * aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 2874, 0)) back_damage -= aurEff->GetAmount() * back_damage / 100; if(back_damage < unitTarget->GetHealth()) @@ -537,7 +531,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) // We are in Shadow Form if (m_caster->m_form == FORM_SHADOW) // We have Improved Mind Blast - if (AuraEffect * aurEff = m_caster->GetDummyAura(SPELLFAMILY_PRIEST,95,0)) + if (AuraEffect * aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST,95,0)) // Chance has been successfully rolled if (roll_chance_i(aurEff->GetAmount())) m_caster->CastSpell(unitTarget, SPELL_MIND_TRAUMA_48301, true); @@ -547,13 +541,13 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) { // Glyph of Smite if (AuraEffect * aurEff = m_caster->GetAuraEffect(55692, 0)) - if (unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x100000, 0, 0, m_caster->GetGUID())) + if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x100000, 0, 0, m_caster->GetGUID())) damage += damage * aurEff->GetAmount() / 100; } // Improved Mind Blast (Mind Blast in shadow form bonus) else if (m_caster->m_form == FORM_SHADOW && (m_spellInfo->SpellFamilyFlags[0] & 0x00002000)) { - Unit::AuraEffectList const& ImprMindBlast = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); + Unit::AuraEffectList const& ImprMindBlast = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_FLAT_MODIFIER); for(Unit::AuraEffectList::const_iterator i = ImprMindBlast.begin(); i != ImprMindBlast.end(); ++i) { if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && @@ -585,8 +579,8 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) else if (m_spellInfo->SpellFamilyFlags[0] & 0x00000001) { // Improved Insect Swarm - if (AuraEffect const * aurEff = m_caster->GetDummyAura(SPELLFAMILY_DRUID, 1771, 0)) - if (unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00200000)) + if (AuraEffect const * aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0)) + if (unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00200000, 0, 0)) damage = int32(damage*(100.0f+aurEff->GetAmount())/100.0f); } break; @@ -600,16 +594,16 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if (uint32 combo = ((Player*)m_caster)->GetComboPoints()) { // Lookup for Deadly poison (only attacker applied) - if (AuraEffect const * aurEff = unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x10000, 0, 0, m_caster->GetGUID())) + if (AuraEffect const * aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x10000, 0, 0, m_caster->GetGUID())) { // count consumed deadly poison doses at target bool needConsume = true; uint32 spellId = aurEff->GetId(); - uint32 doses = aurEff->GetParentAura()->GetStackAmount(); + uint32 doses = aurEff->GetBase()->GetStackAmount(); if (doses > combo) doses = combo; // Master Poisoner - Unit::AuraEffectList const& auraList = ((Player*)m_caster)->GetAurasByType(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK); + Unit::AuraEffectList const& auraList = ((Player*)m_caster)->GetAuraEffectsByType(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK); for (Unit::AuraEffectList::const_iterator iter = auraList.begin(); iter != auraList.end(); ++iter) { if ((*iter)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && (*iter)->GetSpellProto()->SpellIconID == 1960) @@ -662,7 +656,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) { bool found = false; // check dazed affect - Unit::AuraEffectList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); + Unit::AuraEffectList const& decSpeedList = unitTarget->GetAuraEffectsByType(SPELL_AURA_MOD_DECREASE_SPEED); for (Unit::AuraEffectList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter) { if ((*iter)->GetSpellProto()->SpellIconID == 15 && (*iter)->GetSpellProto()->Dispel == 0) @@ -729,7 +723,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) case SPELLFAMILY_DEATHKNIGHT: { // Blood Boil - bonus for diseased targets - if (m_spellInfo->SpellFamilyFlags[0] & 0x00040000 && unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0, 0x00000002, m_caster->GetGUID())) + if (m_spellInfo->SpellFamilyFlags[0] & 0x00040000 && unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0, 0, 0x00000002, m_caster->GetGUID())) { damage += m_damage / 2; damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)* 0.035f); @@ -853,7 +847,7 @@ void Spell::EffectDummy(uint32 i) AuraEffect* deepWound = unitTarget->GetAuraEffect(SPELL_DEEP_WOUNDS_12721, 0); if (deepWound) { - int32 remainingTicks = deepWound->GetParentAura()->GetAuraDuration() / deepWound->GetAuraAmplitude(); + int32 remainingTicks = deepWound->GetBase()->GetDuration() / deepWound->GetAmplitude(); damage += remainingTicks * deepWound->GetAmount(); } @@ -1637,7 +1631,7 @@ void Spell::EffectDummy(uint32 i) int32 mana = damage; // Improved Life Tap mod - if (AuraEffect const * aurEff = m_caster->GetDummyAura(SPELLFAMILY_WARLOCK, 208, 0)) + if (AuraEffect const * aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 208, 0)) mana = (aurEff->GetAmount() + 100)* mana / 100; m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true); @@ -1994,7 +1988,7 @@ void Spell::EffectDummy(uint32 i) if (Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) { // Damage is increased by 25% if your off-hand weapon is enchanted with Flametongue. - if (m_caster->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0x200000)) + if (m_caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0x200000, 0, 0)) m_damage += m_damage * damage / 100; } return; @@ -2339,15 +2333,15 @@ void Spell::EffectTriggerSpell(uint32 effIndex) case 35729: { uint32 dispelMask = GetDispellMask(DISPEL_ALL); - Unit::AuraMap& Auras = unitTarget->GetAuras(); - for (Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) + Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator iter = Auras.begin(); iter != Auras.end();) { // remove all harmful spells on you... - SpellEntry const* spell = iter->second->GetSpellProto(); + SpellEntry const* spell = iter->second->GetBase()->GetSpellProto(); if((spell->DmgClass == SPELL_DAMAGE_CLASS_MAGIC // only affect magic spells || ((1<<spell->Dispel) & dispelMask)) // ignore positive and passive auras - && !iter->second->IsPositive() && !iter->second->IsPassive()) + && !iter->second->IsPositive() && !iter->second->GetBase()->IsPassive()) { m_caster->RemoveAura(iter); } @@ -2596,16 +2590,20 @@ void Spell::EffectTeleportUnits(uint32 i) void Spell::EffectApplyAura(uint32 i) { - if (m_spellAura) - if (AuraEffect * AurEff = m_spellAura->GetPartAura(i)) - unitTarget->HandleAuraEffect(AurEff, true); + if (!m_spellAura) + return; + assert (unitTarget == m_spellAura->GetOwner()); + if (!m_spellAura->IsRemoved()) + m_spellAura->ApplyEffectForTargets(i); } void Spell::EffectApplyAreaAura(uint32 i) { - if (m_spellAura) - if (AuraEffect * AurEff = m_spellAura->GetPartAura(i)) - unitTarget->HandleAuraEffect(AurEff, true); + if (!m_spellAura) + return; + assert (unitTarget == m_spellAura->GetOwner()); + if (!m_spellAura->IsRemoved()) + m_spellAura->ApplyEffectForTargets(i); } void Spell::EffectUnlearnSpecialization( uint32 i ) @@ -2764,7 +2762,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/) // Swiftmend - consumes Regrowth or Rejuvenation else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND, m_spellInfo, m_caster)) { - Unit::AuraEffectList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); + Unit::AuraEffectList const& RejorRegr = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL); // find most short by duration AuraEffect *targetAura = NULL; for (Unit::AuraEffectList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) @@ -2772,7 +2770,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/) if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && (*i)->GetSpellProto()->SpellFamilyFlags[0] & 0x50) { - if(!targetAura || (*i)->GetParentAura()->GetAuraDuration() < targetAura->GetParentAura()->GetAuraDuration()) + if(!targetAura || (*i)->GetBase()->GetDuration() < targetAura->GetBase()->GetDuration()) targetAura = *i; } } @@ -2813,11 +2811,11 @@ void Spell::SpellDamageHeal(uint32 /*i*/) if (AuraEffect const* aurEff = m_caster->GetAuraEffect(62971, 0)) { - Unit::AuraEffectList const& Periodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); + Unit::AuraEffectList const& Periodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL); for (Unit::AuraEffectList::const_iterator i = Periodic.begin(); i != Periodic.end(); ++i) { if (m_caster->GetGUID() == (*i)->GetCasterGUID()) - addhealth += addhealth * (*i)->GetParentAura()->GetStackAmount() * aurEff->GetAmount() / 100; + addhealth += addhealth * aurEff->GetAmount() / 100; } } } @@ -2825,11 +2823,11 @@ void Spell::SpellDamageHeal(uint32 /*i*/) else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x100) { addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL); - if (AuraEffect * aurEff = unitTarget->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, m_originalCasterGUID)) + if (AuraEffect * aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, m_originalCasterGUID)) { addhealth *= 1.25f; // consume aura - unitTarget->RemoveAura(aurEff->GetParentAura()); + unitTarget->RemoveAura(aurEff->GetBase()); } } // Death Pact - return pct of max health to caster @@ -3099,29 +3097,34 @@ void Spell::EffectCreateRandomItem(uint32 i) void Spell::EffectPersistentAA(uint32 i) { - if(m_spellDynObj) + if (!m_spellAura) { - assert(ObjectAccessor::GetObjectInWorld(m_spellDynObj->GetGUID(), (DynamicObject*)NULL) == m_spellDynObj); - m_spellDynObj->AddEffect(i); - return; - } + float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius); - float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); - if(Player* modOwner = m_originalCaster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius); + Unit *caster = m_caster->GetEntry() == WORLD_TRIGGER ? m_originalCaster : m_caster; + DynamicObject* dynObj = new DynamicObject; + if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, m_targets.m_dstPos, radius, false)) + { + delete dynObj; + return; + } + dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee); + caster->AddDynObject(dynObj); + dynObj->GetMap()->Add(dynObj); - Unit *caster = m_caster->GetEntry() == WORLD_TRIGGER ? m_originalCaster : m_caster; - int32 duration = GetSpellDuration(m_spellInfo); - DynamicObject* dynObj = new DynamicObject; - if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), caster, m_spellInfo->Id, 1<<i, m_targets.m_dstPos, duration, radius, false)) - { - delete dynObj; - return; + if (Aura * aura = Aura::TryCreate(m_spellInfo, dynObj, caster, &m_currentBasePoints[0])) + m_spellAura = aura; + else + { + assert(false); + return; + } } - dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee); - caster->AddDynObject(dynObj); - dynObj->GetMap()->Add(dynObj); - m_spellDynObj = dynObj; + assert(m_spellAura->GetDynobjOwner()); + if (!m_spellAura->IsRemoved()) + m_spellAura->ApplyEffectForTargets(i); } void Spell::EffectEnergize(uint32 i) @@ -3181,10 +3184,10 @@ void Spell::EffectEnergize(uint32 i) { // find elixirs on target uint32 elixir_mask = 0; - Unit::AuraMap& Auras = unitTarget->GetAuras(); - for (Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr) + Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr) { - uint32 spell_id = itr->second->GetId(); + uint32 spell_id = itr->second->GetBase()->GetId(); if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id)) elixir_mask |= mask; } @@ -3724,7 +3727,7 @@ void Spell::EffectLearnSpell(uint32 i) sLog.outDebug("Spell: Player %u has learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow()); } -typedef std::list< std::pair<uint32, uint64> > DispelList; +typedef std::list< uint32 > DispelList; void Spell::EffectDispel(uint32 i) { if(!unitTarget) @@ -3735,15 +3738,15 @@ void Spell::EffectDispel(uint32 i) // Create dispel mask by dispel type uint32 dispel_type = m_spellInfo->EffectMiscValue[i]; uint32 dispelMask = GetDispellMask( DispelType(dispel_type)); - Unit::AuraMap const& auras = unitTarget->GetAuras(); + Unit::AuraMap const& auras = unitTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { - Aura *aur = itr->second; - if ((1<<aur->GetSpellProto()->Dispel) & dispelMask) + Aura * aura = itr->second; + if ((1<<aura->GetSpellProto()->Dispel) & dispelMask) { - if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC) + if(aura->GetSpellProto()->Dispel == DISPEL_MAGIC) { - bool positive = aur->IsPositive() ? (!(aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)) : false; + bool positive = aura->IsPositive(unitTarget) ? (!(aura->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)) : false; // do not remove positive auras if friendly target // negative auras if non-friendly target @@ -3751,10 +3754,10 @@ void Spell::EffectDispel(uint32 i) continue; } - bool dispel_charges = aur->GetSpellProto()->AttributesEx7 & SPELL_ATTR_EX7_DISPEL_CHARGES; + bool dispel_charges = aura->GetSpellProto()->AttributesEx7 & SPELL_ATTR_EX7_DISPEL_CHARGES; - for (uint8 i = dispel_charges ? aur->GetAuraCharges() : aur->GetStackAmount(); i; --i) - dispel_list.push_back(aur); + for (uint8 i = dispel_charges ? aura->GetCharges() : aura->GetStackAmount(); i; --i) + dispel_list.push_back(aura); } } @@ -3774,7 +3777,8 @@ void Spell::EffectDispel(uint32 i) if (GetDispelChance((*itr)->GetCaster(), (*itr)->GetId())) { - success_list.push_back(std::make_pair((*itr)->GetId(), (*itr)->GetCasterGUID())); + unitTarget->RemoveAurasDueToSpellByDispel(*itr, m_caster); + success_list.push_back((*itr)->GetId()); dispel_list.erase(itr); } else @@ -3807,9 +3811,8 @@ void Spell::EffectDispel(uint32 i) for (DispelList::iterator itr = success_list.begin(); itr != success_list.end(); ++itr) { // Send dispelled spell info - dataSuccess << uint32(itr->first); // Spell Id + dataSuccess << uint32(*itr); // Spell Id dataSuccess << uint8(0); // 0 - dispelled !=0 cleansed - unitTarget->RemoveAurasDueToSpellByDispel(itr->first, itr->second, m_caster); } m_caster->SendMessageToSet(&dataSuccess, true); @@ -3899,11 +3902,12 @@ void Spell::EffectAddFarsight(uint32 i) float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); int32 duration = GetSpellDuration(m_spellInfo); DynamicObject* dynObj = new DynamicObject; - if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, 0, m_targets.m_dstPos, duration, radius, true)) + if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, m_targets.m_dstPos, radius, true)) { delete dynObj; return; } + dynObj->SetDuration(duration); dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002); m_caster->AddDynObject(dynObj); @@ -4138,6 +4142,7 @@ void Spell::EffectEnchantItemTmp(uint32 i) { sLog.outError("Spell::EffectEnchantItemTmp: unknown spell id %i", spell_id); return; + } for(int j = BASE_ATTACK; j <= OFF_ATTACK; ++j) @@ -4461,11 +4466,11 @@ void Spell::SpellDamageWeaponDmg(uint32 i) if (needCast) m_caster->CastSpell(unitTarget, 58567, true); - if (Aura* aur = unitTarget->GetAura(58567, m_caster->GetGUID())) + if (Aura * aur = unitTarget->GetAura(58567, m_caster->GetGUID())) { // 58388 - Glyph of Devastate dummy aura. if (int32 num = (needCast ? 0 : 1) + (m_caster->HasAura(58388) ? 1 : 0)) - aur->modStackAmount(num); + aur->ModStackAmount(num); fixed_bonus += (aur->GetStackAmount() - 1) * CalculateDamage(2, unitTarget); } } @@ -4498,10 +4503,10 @@ void Spell::SpellDamageWeaponDmg(uint32 i) // full aura scan else { - Unit::AuraMap const& auras = unitTarget->GetAuras(); - for (Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) + Unit::AuraApplicationMap const& auras = unitTarget->GetAppliedAuras(); + for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) { - if (itr->second->GetSpellProto()->Dispel == DISPEL_POISON) + if (itr->second->GetBase()->GetSpellProto()->Dispel == DISPEL_POISON) { found = true; break; @@ -4558,7 +4563,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) // Shred, Maul - Rend and Tear else if (m_spellInfo->SpellFamilyFlags[0] & 0x00008800 && unitTarget->HasAuraState(AURA_STATE_BLEEDING, m_spellInfo, m_caster)) { - if (AuraEffect const* rendAndTear = m_caster->GetDummyAura(SPELLFAMILY_DRUID, 2859, 0)) + if (AuraEffect const* rendAndTear = m_caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 2859, 0)) { totalDamagePercentMod *= float((rendAndTear->GetAmount() + 100.0f) / 100.0f); } @@ -4616,7 +4621,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) { bool consumeDiseases = true; // Annihilation - if (AuraEffect * aurEff = m_caster->GetDummyAura(SPELLFAMILY_DEATHKNIGHT, 2710, 0)) + if (AuraEffect * aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2710, 0)) { // Do not consume diseases if roll sucesses if (roll_chance_i(aurEff->GetAmount())) @@ -4897,17 +4902,17 @@ void Spell::EffectScriptEffect(uint32 effIndex) // Glyph of Starfire case 54846: { - if (AuraEffect const * aurEff = unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE,SPELLFAMILY_DRUID,0x00000002,0,0,m_caster->GetGUID())) + if (AuraEffect const * aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE,SPELLFAMILY_DRUID,0x00000002,0,0,m_caster->GetGUID())) { - uint32 countMin = aurEff->GetParentAura()->GetAuraMaxDuration(); + uint32 countMin = aurEff->GetBase()->GetMaxDuration(); uint32 countMax = 18000; countMax += m_caster->HasAura(38414) ? 3000 : 0; countMax += m_caster->HasAura(57865) ? 3000 : 0; if (countMin < countMax) { - aurEff->GetParentAura()->SetAuraDuration(uint32(aurEff->GetParentAura()->GetAuraDuration()+3000)); - aurEff->GetParentAura()->SetAuraMaxDuration(countMin+3000); + aurEff->GetBase()->SetDuration(uint32(aurEff->GetBase()->GetDuration()+3000)); + aurEff->GetBase()->SetMaxDuration(countMin+3000); } } return; @@ -4915,17 +4920,17 @@ void Spell::EffectScriptEffect(uint32 effIndex) // Glyph of Shred case 63974: { - if (AuraEffect const * aurEff = unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE,SPELLFAMILY_DRUID,0x00800000,0,0,m_caster->GetGUID())) + if (AuraEffect const * aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE,SPELLFAMILY_DRUID,0x00800000,0,0,m_caster->GetGUID())) { - uint32 countMin = aurEff->GetParentAura()->GetAuraMaxDuration(); + uint32 countMin = aurEff->GetBase()->GetMaxDuration(); uint32 countMax = 20000; countMax += m_caster->HasAura(54818) ? 4000 : 0; countMax += m_caster->HasAura(60141) ? 4000 : 0; if (countMin < countMax) { - aurEff->GetParentAura()->SetAuraDuration(uint32(aurEff->GetParentAura()->GetAuraDuration()+3000)); - aurEff->GetParentAura()->SetAuraMaxDuration(countMin+2000); + aurEff->GetBase()->SetDuration(uint32(aurEff->GetBase()->GetDuration()+3000)); + aurEff->GetBase()->SetMaxDuration(countMin+2000); } } @@ -4934,16 +4939,16 @@ void Spell::EffectScriptEffect(uint32 effIndex) // Glyph of Backstab case 63975: { - if (AuraEffect const * aurEff = unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE,SPELLFAMILY_ROGUE,0x00100000,0,0,m_caster->GetGUID())) + if (AuraEffect const * aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE,SPELLFAMILY_ROGUE,0x00100000,0,0,m_caster->GetGUID())) { - uint32 countMin = aurEff->GetParentAura()->GetAuraMaxDuration(); + uint32 countMin = aurEff->GetBase()->GetMaxDuration(); uint32 countMax = 12000; countMax += m_caster->HasAura(56801) ? 4000 : 0; if (countMin < countMax) { - aurEff->GetParentAura()->SetAuraDuration(uint32(aurEff->GetParentAura()->GetAuraDuration()+3000)); - aurEff->GetParentAura()->SetAuraMaxDuration(countMin+2000); + aurEff->GetBase()->SetDuration(uint32(aurEff->GetBase()->GetDuration()+3000)); + aurEff->GetBase()->SetMaxDuration(countMin+2000); } } @@ -5602,9 +5607,9 @@ void Spell::EffectScriptEffect(uint32 effIndex) } Aura * chargesaura = m_caster->GetAura(59907); - if(chargesaura && chargesaura->GetAuraCharges() > 1) + if(chargesaura && chargesaura->GetCharges() > 1) { - chargesaura->SetAuraCharges(chargesaura->GetAuraCharges() - 1); + chargesaura->SetCharges(chargesaura->GetCharges() - 1); m_caster->CastSpell(unitTarget, spell_heal, true, NULL, NULL, ((TempSummon*)m_caster)->GetSummonerGUID()); } else @@ -5678,7 +5683,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) uint32 rank = 0; // Improved Healthstone - if (AuraEffect const * aurEff = unitTarget->GetDummyAura(SPELLFAMILY_WARLOCK, 284, 0)) + if (AuraEffect const * aurEff = unitTarget->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 284, 0)) { if(aurEff->GetId() == 18692) rank = 1; @@ -5726,8 +5731,8 @@ void Spell::EffectScriptEffect(uint32 effIndex) // Everlasting Affliction case 47422: // Refresh corruption on target - if (AuraEffect * aur = unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, m_caster->GetGUID())) - aur->GetParentAura()->RefreshAura(); + if (AuraEffect * aur = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, m_caster->GetGUID())) + aur->GetBase()->RefreshDuration(); return; // Demonic Empowerment case 47193: @@ -5764,8 +5769,8 @@ void Spell::EffectScriptEffect(uint32 effIndex) case 63521: { // Divine Plea - if(Aura *AuraDivinePlea = m_caster->GetAura(54428)) - AuraDivinePlea->RefreshAura(); + if(Aura * aura = m_caster->GetAura(54428)) + aura->RefreshDuration(); return; } } @@ -5781,8 +5786,8 @@ void Spell::EffectScriptEffect(uint32 effIndex) if (!unitTarget) return; // Refresh Shadow Word: Pain on target - if (AuraEffect * aur = unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, m_caster->GetGUID())) - aur->GetParentAura()->RefreshAura(); + if (AuraEffect * aur = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, m_caster->GetGUID())) + aur->GetBase()->RefreshDuration(); return; } default: @@ -5797,7 +5802,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) // Invigoration case 53412: { - if (AuraEffect * aurEff = unitTarget->GetDummyAura(SPELLFAMILY_HUNTER, 3487, 0)) + if (AuraEffect * aurEff = unitTarget->GetDummyAuraEffect(SPELLFAMILY_HUNTER, 3487, 0)) { if (roll_chance_i(aurEff->GetAmount())) unitTarget->CastSpell(unitTarget, 53398, true); @@ -5818,51 +5823,51 @@ void Spell::EffectScriptEffect(uint32 effIndex) { uint32 spellId = 0; int32 basePoint = 0; - Unit::AuraMap& Auras = unitTarget->GetAuras(); - for (Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator i = Auras.begin(); i != Auras.end(); ++i) { - Aura *aura = (*i).second; + Aura * aura = (*i).second->GetBase(); if (aura->GetCasterGUID() != m_caster->GetGUID()) continue; // Search only Serpent Sting, Viper Sting, Scorpid Sting auras flag96 familyFlag = aura->GetSpellProto()->SpellFamilyFlags; if (!(familyFlag[1] & 0x00000080 || familyFlag[0] & 0x0000C000)) continue; - if (!aura->GetPartAura(0)) - continue; - - // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. - if (familyFlag[0] & 0x4000) - { - int32 TickCount = aura->GetPartAura(0)->GetTotalTicks(); - spellId = 53353; // 53353 Chimera Shot - Serpent - basePoint = aura->GetPartAura(0)->GetAmount() * TickCount * 40 / 100; - } - // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. - else if (familyFlag[1] & 0x00000080) + if (AuraEffect const * aurEff = aura->GetEffect(0)) { - int32 TickCount = aura->GetPartAura(0)->GetTotalTicks(); - spellId = 53358; // 53358 Chimera Shot - Viper - - // Amount of one aura tick - basePoint = aura->GetPartAura(0)->GetAmount() * aura->GetTarget()->GetMaxPower(POWER_MANA) / 100 ; - int32 casterBasePoint = aura->GetPartAura(0)->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 50 ; - if (basePoint > casterBasePoint) - basePoint = casterBasePoint; - basePoint = basePoint * TickCount * 60 / 100; + // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. + if (familyFlag[0] & 0x4000) + { + int32 TickCount = aurEff->GetTotalTicks(); + spellId = 53353; // 53353 Chimera Shot - Serpent + basePoint = aurEff->GetAmount() * TickCount * 40 / 100; + } + // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. + else if (familyFlag[1] & 0x00000080) + { + int32 TickCount = aura->GetEffect(0)->GetTotalTicks(); + spellId = 53358; // 53358 Chimera Shot - Viper + + // Amount of one aura tick + basePoint = aurEff->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 100 ; + int32 casterBasePoint = aurEff->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 50 ; + if (basePoint > casterBasePoint) + basePoint = casterBasePoint; + basePoint = basePoint * TickCount * 60 / 100; + } + // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. + else if (familyFlag[0] & 0x00008000) + spellId = 53359; // 53359 Chimera Shot - Scorpid + // ?? nothing say in spell desc (possibly need addition check) + //if (familyFlag & 0x0000010000000000LL || // dot + // familyFlag & 0x0000100000000000LL) // stun + //{ + // spellId = 53366; // 53366 Chimera Shot - Wyvern + //} + + // Refresh aura duration + aura->RefreshDuration(); } - // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. - else if (familyFlag[0] & 0x00008000) - spellId = 53359; // 53359 Chimera Shot - Scorpid - // ?? nothing say in spell desc (possibly need addition check) - //if (familyFlag & 0x0000010000000000LL || // dot - // familyFlag & 0x0000100000000000LL) // stun - //{ - // spellId = 53366; // 53366 Chimera Shot - Wyvern - //} - - // Refresh aura duration - aura->RefreshAura(); break; } if (spellId) @@ -5907,10 +5912,10 @@ void Spell::EffectScriptEffect(uint32 effIndex) return; } // all seals have aura dummy in 2 effect - Unit::AuraMap & sealAuras = m_caster->GetAuras(); - for (Unit::AuraMap::iterator iter = sealAuras.begin(); iter != sealAuras.end();) + Unit::AuraApplicationMap & sealAuras = m_caster->GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator iter = sealAuras.begin(); iter != sealAuras.end();) { - switch (iter->second->GetId()) + switch (iter->first) { // Heart of the Crusader case 20335: // Rank 1 @@ -5923,11 +5928,11 @@ void Spell::EffectScriptEffect(uint32 effIndex) spellId3 = 54499; break; } - - if (IsSealSpell(iter->second->GetSpellProto())) + Aura * aura = iter->second->GetBase(); + if (IsSealSpell(aura->GetSpellProto())) { - if (AuraEffect * aureff = iter->second->GetPartAura(2)) - if (aureff->GetAuraName() == SPELL_AURA_DUMMY) + if (AuraEffect * aureff = aura->GetEffect(2)) + if (aureff->GetAuraType() == SPELL_AURA_DUMMY) { if (sSpellStore.LookupEntry(aureff->GetAmount())) spellId2 = aureff->GetAmount(); @@ -6807,18 +6812,19 @@ void Spell::EffectDispelMechanic(uint32 i) std::queue < std::pair < uint32, uint64 > > dispel_list; - Unit::AuraMap& Auras = unitTarget->GetAuras(); + Unit::AuraMap& Auras = unitTarget->GetOwnedAuras(); for (Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); iter++) { - if((GetAllSpellMechanicMask(iter->second->GetSpellProto()) & (1<<(mechanic))) && GetDispelChance(iter->second->GetCaster(), iter->second->GetId())) - { - dispel_list.push(std::make_pair(iter->second->GetId(), iter->second->GetCasterGUID() ) ); - } + Aura * aura = iter->second; + if((GetAllSpellMechanicMask(aura->GetSpellProto()) & (1<<(mechanic))) && GetDispelChance(aura->GetCaster(), aura->GetId())) + { + dispel_list.push(std::make_pair(aura->GetId(), aura->GetCasterGUID() ) ); + } } for (; dispel_list.size(); dispel_list.pop()) { - unitTarget->RemoveAura(dispel_list.front().first, dispel_list.front().second, AURA_REMOVE_BY_ENEMY_SPELL); + unitTarget->RemoveAura(dispel_list.front().first, dispel_list.front().second, 0, AURA_REMOVE_BY_ENEMY_SPELL); } } @@ -7163,15 +7169,15 @@ void Spell::EffectStealBeneficialBuff(uint32 i) std::list <Aura *> steal_list; // Create dispel mask by dispel type uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) ); - Unit::AuraMap const& auras = unitTarget->GetAuras(); + Unit::AuraMap const& auras = unitTarget->GetOwnedAuras(); for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { - Aura *aur = (*itr).second; - if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask) + Aura * aura = itr->second; + if ((1<<aura->GetSpellProto()->Dispel) & dispelMask) { // Need check for passive? this - if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE)) - steal_list.push_back(aur); + if (aura->IsPositive(unitTarget) && !aura->IsPassive() && !(aura->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE)) + steal_list.push_back(aura); } } // Ok if exist some buffs for dispel try dispel it @@ -7187,6 +7193,7 @@ void Spell::EffectStealBeneficialBuff(uint32 i) for (uint32 i=urand(0, list_size-1); i>0; --i) itr++; success_list.push_back(*itr); + unitTarget->RemoveAurasDueToSpellBySteal(*itr, m_caster); steal_list.erase(itr); } if (success_list.size()) @@ -7197,11 +7204,10 @@ void Spell::EffectStealBeneficialBuff(uint32 i) data << uint32(m_spellInfo->Id); // dispel spell id data << uint8(0); // not used data << uint32(success_list.size()); // count - for (std::list < Aura * > ::iterator itr = success_list.begin(); itr!=success_list.end(); ++itr) + for (std::list < Aura * >::iterator itr = success_list.begin(); itr!=success_list.end(); ++itr) { - data << uint32((*itr)->GetId()); // Spell Id + data << uint32((*itr)->GetId()); // Spell Id data << uint8(0); // 0 - steals !=0 transfers - unitTarget->RemoveAurasDueToSpellBySteal((*itr)->GetId(), (*itr)->GetCasterGUID(), m_caster); } m_caster->SendMessageToSet(&data, true); } @@ -7443,6 +7449,20 @@ void Spell::EffectActivateSpec(uint32 /*eff_idx*/) ((Player*)unitTarget)->ActivateSpec(damage-1); // damage is 1 or 2, spec is 0 or 1 } +void Spell::EffectPlayerNotification(uint32 /*eff_idx*/) +{ + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + switch(m_spellInfo->Id) + { + case 58730: // Restricted Flight Area + case 58600: // Restricted Flight Area + ((Player *)unitTarget)->GetSession()->SendNotification(LANG_ZONE_NOFLYZONE); + break; + } +} + void Spell::EffectCastButtons(uint32 i) { if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER) diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 6a03d13bf6d..c3e72c94561 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -420,7 +420,7 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) // non channeled case // maybe should only remove one buff when there are multiple? - _player->RemoveAurasDueToSpell(spellId, 0, AURA_REMOVE_BY_CANCEL); + _player->RemoveOwnedAura(spellId, 0, 0, AURA_REMOVE_BY_CANCEL); } void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket) @@ -458,7 +458,7 @@ void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket) return; } - pet->RemoveAurasDueToSpell(spellId); + pet->RemoveOwnedAura(spellId, 0, 0, AURA_REMOVE_BY_CANCEL); pet->AddCreatureSpellCooldown(spellId); } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 0a20cb1eefe..3534a9da14e 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -319,6 +319,11 @@ bool IsPassiveSpell(uint32 spellId) SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) return false; + return IsPassiveSpell(spellInfo); +} + +bool IsPassiveSpell(SpellEntry const * spellInfo) +{ if(spellInfo->Attributes & SPELL_ATTR_PASSIVE) return true; return false; @@ -463,7 +468,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); if(!spellInfo) - return SPELL_NORMAL; + return SPELL_SPECIFIC_NORMAL; switch(spellInfo->SpellFamilyName) { @@ -494,16 +499,16 @@ SpellSpecific GetSpellSpecific(uint32 spellId) } if(food && drink) - return SPELL_FOOD_AND_DRINK; + return SPELL_SPECIFIC_FOOD_AND_DRINK; else if(food) - return SPELL_FOOD; + return SPELL_SPECIFIC_FOOD; else if(drink) - return SPELL_DRINK; + return SPELL_SPECIFIC_DRINK; } // Well Fed buffs (must be exclusive with Food / Drink replenishment effects, or else Well Fed will cause them to be removed) // SpellIcon 2560 is Spell 46687, does not have this flag else if ((spellInfo->AttributesEx2 & SPELL_ATTR_EX2_FOOD_BUFF) || spellInfo->SpellIconID == 2560) - return SPELL_WELL_FED; + return SPELL_SPECIFIC_WELL_FED; // this may be a hack //else if((spellInfo->AttributesEx2 & SPELL_ATTR_EX2_FOOD_BUFF) // && !spellInfo->Category) @@ -520,10 +525,10 @@ SpellSpecific GetSpellSpecific(uint32 spellId) case 8096: // Intellect case 8115: // Agility case 8091: // Armor - return SPELL_SCROLL; + return SPELL_SPECIFIC_SCROLL; case 12880: // Enrage (Enrage) case 57518: // Enrage (Wrecking Crew) - return SPELL_WARRIOR_ENRAGE; + return SPELL_SPECIFIC_WARRIOR_ENRAGE; } } break; @@ -532,23 +537,23 @@ SpellSpecific GetSpellSpecific(uint32 spellId) { // family flags 18(Molten), 25(Frost/Ice), 28(Mage) if (spellInfo->SpellFamilyFlags[0] & 0x12040000) - return SPELL_MAGE_ARMOR; + return SPELL_SPECIFIC_MAGE_ARMOR; // Arcane brillance and Arcane intelect (normal check fails because of flags difference) if (spellInfo->SpellFamilyFlags[0] & 0x400) - return SPELL_MAGE_ARCANE_BRILLANCE; + return SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE; if ((spellInfo->SpellFamilyFlags[0] & 0x1000000) && spellInfo->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) - return SPELL_MAGE_POLYMORPH; + return SPELL_SPECIFIC_MAGE_POLYMORPH; break; } case SPELLFAMILY_WARRIOR: { if (spellInfo->SpellFamilyFlags[1] & 0x000080 || spellInfo->SpellFamilyFlags[0] & 0x10000) - return SPELL_POSITIVE_SHOUT; + return SPELL_SPECIFIC_POSITIVE_SHOUT; if (spellInfo->Id == 12292) // Death Wish - return SPELL_WARRIOR_ENRAGE; + return SPELL_SPECIFIC_WARRIOR_ENRAGE; break; } @@ -556,15 +561,15 @@ SpellSpecific GetSpellSpecific(uint32 spellId) { // only warlock curses have this if (spellInfo->Dispel == DISPEL_CURSE) - return SPELL_CURSE; + return SPELL_SPECIFIC_CURSE; // Warlock (Demon Armor | Demon Skin | Fel Armor) if (spellInfo->SpellFamilyFlags[1] & 0x20000020 || spellInfo->SpellFamilyFlags[2] & 0x00000010) - return SPELL_WARLOCK_ARMOR; + return SPELL_SPECIFIC_WARLOCK_ARMOR; //seed of corruption and corruption if (spellInfo->SpellFamilyFlags[1] & 0x10 || spellInfo->SpellFamilyFlags[0] & 0x2) - return SPELL_WARLOCK_CORRUPTION; + return SPELL_SPECIFIC_WARLOCK_CORRUPTION; break; } case SPELLFAMILY_PRIEST: @@ -573,11 +578,11 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if ((spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_SITTING) && (spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_AUTOATTACK) && (spellInfo->SpellIconID == 52 || spellInfo->SpellIconID == 79)) - return SPELL_WELL_FED; + return SPELL_SPECIFIC_WELL_FED; // Divine Spirit and Prayer of Spirit if (spellInfo->SpellFamilyFlags[0] & 0x20) - return SPELL_PRIEST_DIVINE_SPIRIT; + return SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT; break; } @@ -585,39 +590,39 @@ SpellSpecific GetSpellSpecific(uint32 spellId) { // only hunter stings have this if (spellInfo->Dispel == DISPEL_POISON) - return SPELL_STING; + return SPELL_SPECIFIC_STING; // only hunter aspects have this (but not all aspects in hunter family) if( spellInfo->SpellFamilyFlags.HasFlag(0x00380000, 0x00440000, 0x00001010)) - return SPELL_ASPECT; + return SPELL_SPECIFIC_ASPECT; break; } case SPELLFAMILY_PALADIN: { if (IsSealSpell(spellInfo)) - return SPELL_SEAL; + return SPELL_SPECIFIC_SEAL; if (spellInfo->SpellFamilyFlags[0] & 0x11010002) - return SPELL_BLESSING; + return SPELL_SPECIFIC_BLESSING; if (spellInfo->SpellFamilyFlags[0] & 0x00002190) - return SPELL_HAND; + return SPELL_SPECIFIC_HAND; // Judgement of Wisdom, Judgement of Light, Judgement of Justice if (spellInfo->Id == 20184 || spellInfo->Id == 20185 || spellInfo->Id == 20186) - return SPELL_JUDGEMENT; + return SPELL_SPECIFIC_JUDGEMENT; // only paladin auras have this (for palaldin class family) if( spellInfo->SpellFamilyFlags[2] & 0x00000020 ) - return SPELL_AURA; + return SPELL_SPECIFIC_AURA; break; } case SPELLFAMILY_SHAMAN: { if (IsElementalShield(spellInfo)) - return SPELL_ELEMENTAL_SHIELD; + return SPELL_SPECIFIC_ELEMENTAL_SHIELD; break; } @@ -628,7 +633,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId) case SPELLFAMILY_DEATHKNIGHT: if (spellInfo->Id == SPELL_ID_BLOOD_PRESENCE || spellInfo->Id == SPELL_ID_FROST_PRESENCE || spellInfo->Id == SPELL_ID_UNHOLY_PRESENCE) //if (spellInfo->Category == 47) - return SPELL_PRESENCE; + return SPELL_SPECIFIC_PRESENCE; break; } @@ -642,13 +647,13 @@ SpellSpecific GetSpellSpecific(uint32 spellId) case SPELL_AURA_MOD_POSSESS_PET: case SPELL_AURA_MOD_POSSESS: case SPELL_AURA_AOE_CHARM: - return SPELL_CHARM; + return SPELL_SPECIFIC_CHARM; case SPELL_AURA_TRACK_CREATURES: case SPELL_AURA_TRACK_RESOURCES: case SPELL_AURA_TRACK_STEALTHED: - return SPELL_TRACKER; + return SPELL_SPECIFIC_TRACKER; case SPELL_AURA_PHASE: - return SPELL_PHASE; + return SPELL_SPECIFIC_PHASE; } } } @@ -656,7 +661,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if(SpellSpecific sp = spellmgr.GetSpellElixirSpecific(spellInfo->Id)) return sp; - return SPELL_NORMAL; + return SPELL_SPECIFIC_NORMAL; } // target not allow have more one spell specific from same caster @@ -664,16 +669,16 @@ bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1,SpellSpecific s { switch(spellSpec1) { - case SPELL_SEAL: - case SPELL_BLESSING: - case SPELL_HAND: - case SPELL_AURA: - case SPELL_STING: - case SPELL_CURSE: - case SPELL_ASPECT: - case SPELL_POSITIVE_SHOUT: - case SPELL_JUDGEMENT: - case SPELL_WARLOCK_CORRUPTION: + case SPELL_SPECIFIC_SEAL: + case SPELL_SPECIFIC_BLESSING: + case SPELL_SPECIFIC_HAND: + case SPELL_SPECIFIC_AURA: + case SPELL_SPECIFIC_STING: + case SPELL_SPECIFIC_CURSE: + case SPELL_SPECIFIC_ASPECT: + case SPELL_SPECIFIC_POSITIVE_SHOUT: + case SPELL_SPECIFIC_JUDGEMENT: + case SPELL_SPECIFIC_WARLOCK_CORRUPTION: return spellSpec1==spellSpec2; default: return false; @@ -684,40 +689,40 @@ bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1, SpellSpecific { switch(spellSpec1) { - case SPELL_PHASE: - case SPELL_TRACKER: - case SPELL_WARLOCK_ARMOR: - case SPELL_MAGE_ARMOR: - case SPELL_ELEMENTAL_SHIELD: - case SPELL_MAGE_POLYMORPH: - case SPELL_PRESENCE: - case SPELL_WELL_FED: - case SPELL_CHARM: - case SPELL_SCROLL: - case SPELL_WARRIOR_ENRAGE: - case SPELL_MAGE_ARCANE_BRILLANCE: - case SPELL_PRIEST_DIVINE_SPIRIT: + case SPELL_SPECIFIC_PHASE: + case SPELL_SPECIFIC_TRACKER: + case SPELL_SPECIFIC_WARLOCK_ARMOR: + case SPELL_SPECIFIC_MAGE_ARMOR: + case SPELL_SPECIFIC_ELEMENTAL_SHIELD: + case SPELL_SPECIFIC_MAGE_POLYMORPH: + case SPELL_SPECIFIC_PRESENCE: + case SPELL_SPECIFIC_WELL_FED: + case SPELL_SPECIFIC_CHARM: + case SPELL_SPECIFIC_SCROLL: + case SPELL_SPECIFIC_WARRIOR_ENRAGE: + case SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE: + case SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT: return spellSpec1==spellSpec2; - case SPELL_FOOD: - return spellSpec2==SPELL_FOOD - || spellSpec2==SPELL_FOOD_AND_DRINK; - case SPELL_DRINK: - return spellSpec2==SPELL_DRINK - || spellSpec2==SPELL_FOOD_AND_DRINK; - case SPELL_FOOD_AND_DRINK: - return spellSpec2==SPELL_FOOD - || spellSpec2==SPELL_DRINK - || spellSpec2==SPELL_FOOD_AND_DRINK; - case SPELL_BATTLE_ELIXIR: - return spellSpec2==SPELL_BATTLE_ELIXIR - || spellSpec2==SPELL_FLASK_ELIXIR; - case SPELL_GUARDIAN_ELIXIR: - return spellSpec2==SPELL_GUARDIAN_ELIXIR - || spellSpec2==SPELL_FLASK_ELIXIR; - case SPELL_FLASK_ELIXIR: - return spellSpec2==SPELL_BATTLE_ELIXIR - || spellSpec2==SPELL_GUARDIAN_ELIXIR - || spellSpec2==SPELL_FLASK_ELIXIR; + case SPELL_SPECIFIC_FOOD: + return spellSpec2==SPELL_SPECIFIC_FOOD + || spellSpec2==SPELL_SPECIFIC_FOOD_AND_DRINK; + case SPELL_SPECIFIC_DRINK: + return spellSpec2==SPELL_SPECIFIC_DRINK + || spellSpec2==SPELL_SPECIFIC_FOOD_AND_DRINK; + case SPELL_SPECIFIC_FOOD_AND_DRINK: + return spellSpec2==SPELL_SPECIFIC_FOOD + || spellSpec2==SPELL_SPECIFIC_DRINK + || spellSpec2==SPELL_SPECIFIC_FOOD_AND_DRINK; + case SPELL_SPECIFIC_BATTLE_ELIXIR: + return spellSpec2==SPELL_SPECIFIC_BATTLE_ELIXIR + || spellSpec2==SPELL_SPECIFIC_FLASK_ELIXIR; + case SPELL_SPECIFIC_GUARDIAN_ELIXIR: + return spellSpec2==SPELL_SPECIFIC_GUARDIAN_ELIXIR + || spellSpec2==SPELL_SPECIFIC_FLASK_ELIXIR; + case SPELL_SPECIFIC_FLASK_ELIXIR: + return spellSpec2==SPELL_SPECIFIC_BATTLE_ELIXIR + || spellSpec2==SPELL_SPECIFIC_GUARDIAN_ELIXIR + || spellSpec2==SPELL_SPECIFIC_FLASK_ELIXIR; default: return false; } @@ -1036,10 +1041,9 @@ bool IsSingleTargetSpell(SpellEntry const *spellInfo) if ( spellInfo->AttributesEx5 & SPELL_ATTR_EX5_SINGLE_TARGET_SPELL ) return true; - // TODO - need found Judgements rule switch(GetSpellSpecific(spellInfo->Id)) { - case SPELL_JUDGEMENT: + case SPELL_SPECIFIC_JUDGEMENT: return true; default: break; @@ -1061,8 +1065,8 @@ bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellI // spell with single target specific types switch(spec1) { - case SPELL_JUDGEMENT: - case SPELL_MAGE_POLYMORPH: + case SPELL_SPECIFIC_JUDGEMENT: + case SPELL_SPECIFIC_MAGE_POLYMORPH: if(GetSpellSpecific(spellInfo2->Id) == spec1) return true; break; @@ -1499,7 +1503,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellPr if (procEvent_procEx & PROC_EX_EX_TRIGGER_ALWAYS) return true; // PROC_EX_NOT_ACTIVE_SPELL and PROC_EX_ONLY_ACTIVE_SPELL flags handle: if passed checks before - if ((procExtra & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) && ((procEvent_procEx & (AURA_SPELL_PROC_EX_MASK | AURA_REMOVE_PROC_EX_MASK)) == 0)) + if ((procExtra & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) && ((procEvent_procEx & (AURA_SPELL_PROC_EX_MASK)) == 0)) return true; } // Check Extra Requirement like (hit/crit/miss/resist/parry/dodge/block/immune/reflect/absorb and other) @@ -2525,17 +2529,6 @@ void SpellMgr::LoadSpellAreas() continue; } - switch (spellInfo->EffectApplyAuraName[0]) - { - case SPELL_AURA_DUMMY: - case SPELL_AURA_PHASE: - case SPELL_AURA_GHOST: - break; - default: - sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase/ghost aura in effect 0", spell,abs(spellArea.auraSpell)); - continue; - } - if (abs(spellArea.auraSpell) == spellArea.spellId) { sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement for itself", spell,abs(spellArea.auraSpell)); @@ -3577,21 +3570,6 @@ void SpellMgr::LoadSpellCustomAttr() for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j) { - switch (spellInfo->EffectApplyAuraName[j]) - { - case SPELL_AURA_MOD_ROOT: - mSpellCustomAttr[i] |= SPELL_ATTR_CU_AURA_CC; - mSpellCustomAttr[i] |= SPELL_ATTR_CU_MOVEMENT_IMPAIR; - count++; - break; - case SPELL_AURA_MOD_DECREASE_SPEED: - mSpellCustomAttr[i] |= SPELL_ATTR_CU_MOVEMENT_IMPAIR; - count++; - break; - default: - break; - } - switch (spellInfo->Effect[j]) { case SPELL_EFFECT_SCHOOL_DAMAGE: @@ -3645,7 +3623,6 @@ void SpellMgr::LoadSpellCustomAttr() case SPELL_AURA_MOD_FEAR: case SPELL_AURA_MOD_STUN: mSpellCustomAttr[i] |= SPELL_ATTR_CU_AURA_CC; - mSpellCustomAttr[i] &= ~SPELL_ATTR_CU_MOVEMENT_IMPAIR; count++; break; } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 54bb649e218..a31c4c5434c 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -143,36 +143,36 @@ enum SpellFamilyFlag // Spell clasification enum SpellSpecific { - SPELL_NORMAL = 0, - SPELL_SEAL = 1, - SPELL_BLESSING = 2, - SPELL_AURA = 3, - SPELL_STING = 4, - SPELL_CURSE = 5, - SPELL_ASPECT = 6, - SPELL_TRACKER = 7, - SPELL_WARLOCK_ARMOR = 8, - SPELL_MAGE_ARMOR = 9, - SPELL_ELEMENTAL_SHIELD = 10, - SPELL_MAGE_POLYMORPH = 11, - SPELL_POSITIVE_SHOUT = 12, - SPELL_JUDGEMENT = 13, - SPELL_BATTLE_ELIXIR = 14, - SPELL_GUARDIAN_ELIXIR = 15, - SPELL_FLASK_ELIXIR = 16, - SPELL_WARLOCK_CORRUPTION= 17, - SPELL_WELL_FED = 18, - SPELL_FOOD = 19, - SPELL_DRINK = 20, - SPELL_FOOD_AND_DRINK = 21, - SPELL_PRESENCE = 22, - SPELL_CHARM = 23, - SPELL_SCROLL = 24, - SPELL_MAGE_ARCANE_BRILLANCE = 25, - SPELL_WARRIOR_ENRAGE = 26, - SPELL_PRIEST_DIVINE_SPIRIT = 27, - SPELL_HAND = 28, - SPELL_PHASE = 29, + SPELL_SPECIFIC_NORMAL = 0, + SPELL_SPECIFIC_SEAL = 1, + SPELL_SPECIFIC_BLESSING = 2, + SPELL_SPECIFIC_AURA = 3, + SPELL_SPECIFIC_STING = 4, + SPELL_SPECIFIC_CURSE = 5, + SPELL_SPECIFIC_ASPECT = 6, + SPELL_SPECIFIC_TRACKER = 7, + SPELL_SPECIFIC_WARLOCK_ARMOR = 8, + SPELL_SPECIFIC_MAGE_ARMOR = 9, + SPELL_SPECIFIC_ELEMENTAL_SHIELD = 10, + SPELL_SPECIFIC_MAGE_POLYMORPH = 11, + SPELL_SPECIFIC_POSITIVE_SHOUT = 12, + SPELL_SPECIFIC_JUDGEMENT = 13, + SPELL_SPECIFIC_BATTLE_ELIXIR = 14, + SPELL_SPECIFIC_GUARDIAN_ELIXIR = 15, + SPELL_SPECIFIC_FLASK_ELIXIR = 16, + SPELL_SPECIFIC_WARLOCK_CORRUPTION= 17, + SPELL_SPECIFIC_WELL_FED = 18, + SPELL_SPECIFIC_FOOD = 19, + SPELL_SPECIFIC_DRINK = 20, + SPELL_SPECIFIC_FOOD_AND_DRINK = 21, + SPELL_SPECIFIC_PRESENCE = 22, + SPELL_SPECIFIC_CHARM = 23, + SPELL_SPECIFIC_SCROLL = 24, + SPELL_SPECIFIC_MAGE_ARCANE_BRILLANCE = 25, + SPELL_SPECIFIC_WARRIOR_ENRAGE = 26, + SPELL_SPECIFIC_PRIEST_DIVINE_SPIRIT = 27, + SPELL_SPECIFIC_HAND = 28, + SPELL_SPECIFIC_PHASE = 29, }; #define SPELL_LINKED_MAX_SPELLS 200000 @@ -301,6 +301,7 @@ bool IsHigherHankOfSpell(uint32 spellId_1,uint32 spellId_2); bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1, SpellSpecific spellSpec2); bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1, SpellSpecific spellSpec2); bool IsPassiveSpell(uint32 spellId); +bool IsPassiveSpell(SpellEntry const * spellInfo); bool IsAutocastableSpell(uint32 spellId); uint32 CalculatePowerCost(SpellEntry const * spellInfo, Unit const * caster, SpellSchoolMask schoolMask); @@ -404,6 +405,12 @@ inline bool IsAreaAuraEffect(uint32 effect) return true; return false; } + +inline bool IsUnitOwnedAuraEffect(uint32 effect) +{ + return (IsAreaAuraEffect(effect) || effect == SPELL_EFFECT_APPLY_AURA); +} + inline bool IsDispel(SpellEntry const *spellInfo) { //spellsteal is also dispel @@ -573,8 +580,6 @@ enum ProcFlagsEx PROC_EX_ABSORB = 0x0000400, PROC_EX_REFLECT = 0x0000800, PROC_EX_INTERRUPT = 0x0001000, // Melee hit result can be Interrupt (not used) - PROC_EX_AURA_REMOVE_DESTROY = 0x0002000, // Aura absorb destroy or dispel - PROC_EX_AURA_REMOVE_EXPIRE = 0x0004000, // Aura remove by default and by cancel PROC_EX_NOT_ACTIVE_SPELL = 0x0008000, // Spell mustn't do damage/heal to proc PROC_EX_EX_TRIGGER_ALWAYS = 0x0010000, // If set trigger always no matter of hit result PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000, // If set trigger always but only one time (not implemented yet) @@ -587,8 +592,6 @@ enum ProcFlagsEx PROC_EX_INTERNAL_TRIGGERED = 0x4000000, PROC_EX_INTERNAL_REQ_FAMILY = 0x8000000 }; -#define AURA_REMOVE_PROC_EX_MASK \ - (PROC_EX_AURA_REMOVE_DESTROY | PROC_EX_AURA_REMOVE_EXPIRE) #define AURA_SPELL_PROC_EX_MASK \ (PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT | PROC_EX_MISS | \ @@ -822,7 +825,6 @@ inline bool IsProfessionSkill(uint32 skill) #define SPELL_ATTR_CU_LINK_HIT 0x00000800 #define SPELL_ATTR_CU_LINK_AURA 0x00001000 #define SPELL_ATTR_CU_LINK_REMOVE 0x00002000 -#define SPELL_ATTR_CU_MOVEMENT_IMPAIR 0x00004000 #define SPELL_ATTR_CU_EXCLUDE_SELF 0x00008000 #define SPELL_ATTR_CU_NEGATIVE_EFF0 0x00010000 #define SPELL_ATTR_CU_NEGATIVE_EFF1 0x00020000 @@ -866,15 +868,15 @@ class SpellMgr { uint32 mask = GetSpellElixirMask(spellid); if((mask & ELIXIR_FLASK_MASK)==ELIXIR_FLASK_MASK) - return SPELL_FLASK_ELIXIR; + return SPELL_SPECIFIC_FLASK_ELIXIR; else if(mask & ELIXIR_BATTLE_MASK) - return SPELL_BATTLE_ELIXIR; + return SPELL_SPECIFIC_BATTLE_ELIXIR; else if(mask & ELIXIR_GUARDIAN_MASK) - return SPELL_GUARDIAN_ELIXIR; + return SPELL_SPECIFIC_GUARDIAN_ELIXIR; else if(mask & ELIXIR_WELL_FED) - return SPELL_WELL_FED; + return SPELL_SPECIFIC_WELL_FED; else - return SPELL_NORMAL; + return SPELL_SPECIFIC_NORMAL; } uint16 GetSpellThreat(uint32 spellid) const diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 05e47ee1db3..f5d8bf636f2 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -24,6 +24,7 @@ #include "Creature.h" #include "SharedDefines.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" /*####################################### ######## ######## @@ -97,9 +98,9 @@ bool Player::UpdateStats(Stats stat) // Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat uint32 mask = 0; - AuraEffectList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); + AuraEffectList const& modRatingFromStat = GetAuraEffectsByType(SPELL_AURA_MOD_RATING_FROM_STAT); for (AuraEffectList::const_iterator i = modRatingFromStat.begin(); i != modRatingFromStat.end(); ++i) - if (Stats((*i)->GetMiscBValue()) == stat) + if (Stats((*i)->GetMiscValueB()) == stat) mask |= (*i)->GetMiscValue(); if (mask) { @@ -188,11 +189,11 @@ void Player::UpdateArmor() value += GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods - AuraEffectList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); + AuraEffectList const& mResbyIntellect = GetAuraEffectsByType(SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mResbyIntellect.begin(); i != mResbyIntellect.end(); ++i) { if((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) - value += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetAmount() / 100.0f); + value += int32(GetStat(Stats((*i)->GetMiscValueB())) * (*i)->GetAmount() / 100.0f); } value *= GetModifierValue(unitMod, TOTAL_PCT); @@ -315,7 +316,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) case FORM_DIREBEAR: case FORM_MOONKIN: { - Unit::AuraEffectList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY); + Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { // Predatory Strikes (effect 0) @@ -360,18 +361,18 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) { if ((getClassMask() & CLASSMASK_WAND_USERS)==0) { - AuraEffectList const& mRAPbyStat = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); + AuraEffectList const& mRAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mRAPbyStat.begin(); i != mRAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 100.0f); } } else { - AuraEffectList const& mAPbyStat = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); + AuraEffectList const& mAPbyStat = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mAPbyStat.begin(); i != mAPbyStat.end(); ++i) attPowerMod += int32(GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 100.0f); - AuraEffectList const& mAPbyArmor = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR); + AuraEffectList const& mAPbyArmor = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR); for (AuraEffectList::const_iterator iter = mAPbyArmor.begin(); iter != mAPbyArmor.end(); ++iter) // always: ((*i)->GetModifier()->m_miscvalue == 1 == SPELL_SCHOOL_MASK_NORMAL) attPowerMod += int32(GetArmor() / (*iter)->GetAmount()); @@ -666,7 +667,7 @@ void Player::UpdateExpertise(WeaponAttackType attack) Item *weapon = GetWeaponForAttack(attack); - AuraEffectList const& expAuras = GetAurasByType(SPELL_AURA_MOD_EXPERTISE); + AuraEffectList const& expAuras = GetAuraEffectsByType(SPELL_AURA_MOD_EXPERTISE); for (AuraEffectList::const_iterator itr = expAuras.begin(); itr != expAuras.end(); ++itr) { // item neutral spell @@ -711,7 +712,7 @@ void Player::UpdateManaRegen() float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f; // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura - AuraEffectList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); + AuraEffectList const& regenAura = GetAuraEffectsByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); for (AuraEffectList::const_iterator i = regenAura.begin(); i != regenAura.end(); ++i) { power_regen_mp5 += GetStat(Stats((*i)->GetMiscValue())) * (*i)->GetAmount() / 500.0f; @@ -730,7 +731,7 @@ void Player::_ApplyAllStatBonuses() { SetCanModifyStats(false); - _ApplyAllAuraMods(); + _ApplyAllAuraStatMods(); _ApplyAllItemMods(); SetCanModifyStats(true); @@ -743,7 +744,7 @@ void Player::_RemoveAllStatBonuses() SetCanModifyStats(false); _RemoveAllItemMods(); - _RemoveAllAuraMods(); + _RemoveAllAuraStatMods(); SetCanModifyStats(true); @@ -1239,7 +1240,7 @@ void Guardian::UpdateDamagePhysical(WeaponAttackType attType) } } - Unit::AuraEffectList const& mDummy = GetAurasByType(SPELL_AURA_MOD_ATTACKSPEED); + Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_MOD_ATTACKSPEED); for(Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) { switch ((*itr)->GetSpellProto()->Id) diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index 5788d954882..438a6cb0381 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -285,7 +285,7 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe assert(target); // if the ref has status online the target must be there ! // some units are prefered in comparison to others - if(!noPriorityTargetFound && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask()) || target->hasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE)) ) + if(!noPriorityTargetFound && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask()) || target->HasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_TAKE_DAMAGE)) ) { if(iter != lastRef) { diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 89342551cdb..b31a406e185 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -33,6 +33,7 @@ #include "Spell.h" #include "Group.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" #include "MapManager.h" #include "ObjectAccessor.h" #include "CreatureAI.h" @@ -125,12 +126,8 @@ Unit::Unit() m_SummonSlot[i] = 0; m_ObjectSlot[0] = m_ObjectSlot[1] = m_ObjectSlot[2] = m_ObjectSlot[3] = 0; - //m_Aura = NULL; - //m_AurasCheck = 2000; - //m_removeAuraTimer = 4; - //tmpAura = NULL; - m_AurasUpdateIterator = m_Auras.end(); + m_auraUpdateIterator = m_ownedAuras.end(); m_Visibility = VISIBILITY_ON; m_interruptMask = 0; @@ -200,7 +197,7 @@ Unit::~Unit() RemoveAllGameObjects(); RemoveAllDynObjects(); - _DeleteAuras(); + _DeleteRemovedAuras(); if (m_charmInfo) delete m_charmInfo; @@ -211,6 +208,9 @@ Unit::~Unit() assert(m_attackers.empty()); assert(m_sharedVision.empty()); assert(m_Controlled.empty()); + assert(m_appliedAuras.empty()); + assert(m_ownedAuras.empty()); + assert(m_removedAuras.empty()); } void Unit::Update(uint32 p_time) @@ -514,87 +514,11 @@ void Unit::GetRandomContactPoint(const Unit* obj, float &x, float &y, float &z, , GetAngle(obj) + (attacker_number ? (M_PI/2 - M_PI * rand_norm()) * float(attacker_number) / combat_reach * 0.3 : 0)); } -void Unit::RemoveMovementImpairingAuras() -{ - RemoveAurasWithMechanic((1<<MECHANIC_SNARE)|(1<<MECHANIC_ROOT)); - return; - - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) - { - if (spellmgr.GetSpellCustomAttr(iter->second->GetId()) & SPELL_ATTR_CU_MOVEMENT_IMPAIR) - RemoveAura(iter); - else - ++iter; - } -} - -void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except) -{ - if (!(m_interruptMask & flag)) - return; - - // interrupt auras - for (AuraList::iterator iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end();) - { - Aura * aur = *iter; - ++iter; - if ((aur->GetSpellProto()->AuraInterruptFlags & flag) && (!except || aur->GetId() != except)) - { - uint32 removedAuras = m_removedAurasCount; - RemoveAura(aur, AURA_REMOVE_BY_ENEMY_SPELL); - if (m_removedAurasCount > removedAuras + 1) - iter = m_interruptableAuras.begin(); - } - } - - // interrupt channeled spell - if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) - if (spell->getState() == SPELL_STATE_CASTING - && (spell->m_spellInfo->ChannelInterruptFlags & flag) - && spell->m_spellInfo->Id != except) - InterruptNonMeleeSpells(false); - - UpdateInterruptMask(); -} - -void Unit::RemoveAurasWithFamily(uint32 family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID) -{ - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) - { - if (!casterGUID || iter->second->GetCasterGUID() == casterGUID) - { - SpellEntry const *spell = iter->second->GetSpellProto(); - if (spell->SpellFamilyName == family && spell->SpellFamilyFlags.HasFlag(familyFlag1, familyFlag2, familyFlag3)) - { - RemoveAura(iter); - continue; - } - } - ++iter; - } -} - -void Unit::RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode, uint32 except) -{ - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) - { - if (!except || iter->second->GetId() != except) - { - if (GetAllSpellMechanicMask(iter->second->GetSpellProto()) & mechanic_mask) - { - RemoveAura(iter, removemode); - continue; - } - } - ++iter; - } -} - void Unit::UpdateInterruptMask() { m_interruptMask = 0; - for (AuraList::const_iterator i = m_interruptableAuras.begin(); i != m_interruptableAuras.end(); ++i) - m_interruptMask |= (*i)->GetSpellProto()->AuraInterruptFlags; + for (AuraApplicationList::const_iterator i = m_interruptableAuras.begin(); i != m_interruptableAuras.end(); ++i) + m_interruptMask |= (*i)->GetBase()->GetSpellProto()->AuraInterruptFlags; if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) if (spell->getState() == SPELL_STATE_CASTING) @@ -605,7 +529,7 @@ bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint { if (!HasAuraType(auraType)) return false; - AuraEffectList const &auras = GetAurasByType(auraType); + AuraEffectList const &auras = GetAuraEffectsByType(auraType); for (AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) if (SpellEntry const *iterSpellProto = (*itr)->GetSpellProto()) if (iterSpellProto->SpellFamilyName == familyName && iterSpellProto->SpellFamilyFlags[0] & familyFlags) @@ -925,7 +849,7 @@ void Unit::CastStop(uint32 except_spellid) InterruptSpell(CurrentSpellTypes(i),false); } -void Unit::CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster) +void Unit::CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem, AuraEffect const * triggeredByAura, uint64 originalCaster) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); @@ -938,7 +862,7 @@ void Unit::CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castIte CastSpell(Victim,spellInfo,triggered,castItem,triggeredByAura, originalCaster); } -void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster) +void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem, AuraEffect const * triggeredByAura, uint64 originalCaster) { if (!spellInfo) { @@ -996,7 +920,7 @@ void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, I spell->prepare(&targets, triggeredByAura); } -void Unit::CastCustomSpell(Unit* target, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster) +void Unit::CastCustomSpell(Unit* target, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem, AuraEffect const * triggeredByAura, uint64 originalCaster) { CustomSpellValues values; if (bp0) @@ -1008,14 +932,14 @@ void Unit::CastCustomSpell(Unit* target, uint32 spellId, int32 const* bp0, int32 CastCustomSpell(spellId, values, target, triggered, castItem, triggeredByAura, originalCaster); } -void Unit::CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* target, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster) +void Unit::CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* target, bool triggered, Item *castItem, AuraEffect const * triggeredByAura, uint64 originalCaster) { CustomSpellValues values; values.AddSpellMod(mod, value); CastCustomSpell(spellId, values, target, triggered, castItem, triggeredByAura, originalCaster); } -void Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const &value, Unit* Victim, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster) +void Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const &value, Unit* Victim, bool triggered, Item *castItem, AuraEffect const * triggeredByAura, uint64 originalCaster) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); if (!spellInfo) @@ -1072,7 +996,7 @@ void Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const &value, Unit* } // used for scripting -void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem, AuraEffect* triggeredByAura, uint64 originalCaster, Unit* OriginalVictim) +void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem, AuraEffect const * triggeredByAura, uint64 originalCaster, Unit* OriginalVictim) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); @@ -1621,7 +1545,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) // victim's damage shield std::set<AuraEffect*> alreadyDone; uint32 removedAuras = pVictim->m_removedAurasCount; - AuraEffectList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD); + AuraEffectList const& vDamageShields = pVictim->GetAuraEffectsByType(SPELL_AURA_DAMAGE_SHIELD); for (AuraEffectList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next) { ++next; @@ -1679,15 +1603,15 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEnt if (Player *modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor); - AuraEffectList const& ResIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST); + AuraEffectList const& ResIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST); for (AuraEffectList::const_iterator j = ResIgnoreAurasAb.begin(); j != ResIgnoreAurasAb.end(); ++j) { if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL - && (*j)->isAffectedOnSpell(spellInfo)) + && (*j)->IsAffectedOnSpell(spellInfo)) armor= int32(float(armor) * (float(100-(*j)->GetAmount())/100.0f)); } - AuraEffectList const& ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j) { if ((*j)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) @@ -1696,7 +1620,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEnt if (GetTypeId() == TYPEID_PLAYER) { - AuraEffectList const& ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT); + AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_ARMOR_PENETRATION_PCT); for (AuraEffectList::const_iterator itr = ResIgnoreAuras.begin(); itr != ResIgnoreAuras.end(); ++itr) { // item neutral spell @@ -1814,15 +1738,15 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff *resist += damageResisted; - AuraEffectList const &ResIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST); + AuraEffectList const &ResIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST); for (AuraEffectList::const_iterator j = ResIgnoreAurasAb.begin(); j != ResIgnoreAurasAb.end(); ++j) { if ((*j)->GetMiscValue() & schoolMask - && (*j)->isAffectedOnSpell(spellInfo)) + && (*j)->IsAffectedOnSpell(spellInfo)) *resist= int32(float(*resist) * (float(100-(*j)->GetAmount())/100.0f)); } - AuraEffectList const &ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + AuraEffectList const &ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j) { if ((*j)->GetMiscValue() & schoolMask) @@ -1843,7 +1767,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff bool existExpired = false; TriggeredSpellInfoVct triggeredSpells; // absorb without mana cost - AuraEffectList const& vSchoolAbsorb = pVictim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB); + AuraEffectList const& vSchoolAbsorb = pVictim->GetAuraEffectsByType(SPELL_AURA_SCHOOL_ABSORB); for (AuraEffectList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && RemainingDamage > 0; ++i) { if (!((*i)->GetMiscValue() & schoolMask)) @@ -1961,14 +1885,14 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff if (!caster) break; // Glyph of Power Word: Shield - if (Aura *glyph = pVictim->GetAura(55672,0)) + if (AuraEffect *glyph = pVictim->GetAuraEffect(55672, 0)) { - int32 heal = int32(glyph->GetPartAura(0)->GetAmount() * + int32 heal = int32(glyph->GetAmount() * (RemainingDamage >= currentAbsorb ? currentAbsorb : RemainingDamage) / 100); pVictim->CastCustomSpell(pVictim, 56160, &heal, NULL, NULL, true, 0, *i); } // Reflective Shield - if (AuraEffect const * aurEff = caster->GetDummyAura(SPELLFAMILY_PRIEST, 566, 0)) + if (AuraEffect const * aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 566, 0)) { switch(aurEff->GetMiscValue()) { @@ -2114,13 +2038,12 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff { for (AuraEffectList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end();) { - Aura *aura=(*i)->GetParentAura(); - AuraEffect *auraeff =(*i); + AuraEffect * auraEff =(*i); ++i; - if (auraeff->GetAmount()<=0) + if (auraEff->GetAmount()<=0) { uint32 removedAuras = pVictim->m_removedAurasCount; - pVictim->RemoveAura(aura, AURA_REMOVE_BY_ENEMY_SPELL); + auraEff->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL); if (removedAuras+1<pVictim->m_removedAurasCount) i=vSchoolAbsorb.begin(); } @@ -2128,7 +2051,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff } // absorb by mana cost - AuraEffectList const& vManaShield = pVictim->GetAurasByType(SPELL_AURA_MANA_SHIELD); + AuraEffectList const& vManaShield = pVictim->GetAuraEffectsByType(SPELL_AURA_MANA_SHIELD); for (AuraEffectList::const_iterator i = vManaShield.begin(), next; i != vManaShield.end() && RemainingDamage > 0; i = next) { next = i; ++next; @@ -2159,7 +2082,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff (*i)->SetAmount((*i)->GetAmount()-currentAbsorb); if ((*i)->GetAmount() <= 0) { - pVictim->RemoveAura((*i)->GetParentAura(), AURA_REMOVE_BY_ENEMY_SPELL); + (*i)->GetBase()->Remove(AURA_REMOVE_BY_ENEMY_SPELL); next = vManaShield.begin(); } @@ -2169,7 +2092,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff // only split damage if not damaging yourself if (pVictim != this) { - AuraEffectList const& vSplitDamageFlat = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); + AuraEffectList const& vSplitDamageFlat = pVictim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); for (AuraEffectList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next) { next = i; ++next; @@ -2201,7 +2124,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); } - AuraEffectList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); + AuraEffectList const& vSplitDamagePct = pVictim->GetAuraEffectsByType(SPELL_AURA_SPLIT_DAMAGE_PCT); for (AuraEffectList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next) { next = i; ++next; @@ -2232,11 +2155,11 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff TotalAbsorb = (TotalAbsorb - RemainingDamage > 0) ? TotalAbsorb - RemainingDamage : 0; // TODO: School should be checked for absorbing auras or for attacks? int32 auraAbsorbMod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL); - AuraEffectList const& AbsIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL); + AuraEffectList const& AbsIgnoreAurasAb = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL); for (AuraEffectList::const_iterator i = AbsIgnoreAurasAb.begin(); i != AbsIgnoreAurasAb.end(); ++i) { if ((*i)->GetAmount() > auraAbsorbMod - && (*i)->isAffectedOnSpell(spellInfo)) + && (*i)->IsAffectedOnSpell(spellInfo)) auraAbsorbMod = (*i)->GetAmount(); } @@ -2282,13 +2205,13 @@ void Unit::CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEff { // Incanter's Absorption // TODO: move this code to procflag - if (AuraEffect const * aurEff = pVictim->GetDummyAura(SPELLFAMILY_GENERIC, 2941, 0)) + if (AuraEffect const * aurEff = pVictim->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2941, 0)) { // Get total damage bonus from auras int32 current_dmg = 0; - std::pair<AuraMap::const_iterator, AuraMap::const_iterator> range = pVictim->GetAuras().equal_range(44413); + std::pair<AuraMap::const_iterator, AuraMap::const_iterator> range = pVictim->GetOwnedAuras().equal_range(44413); for (AuraMap::const_iterator iter = range.first; iter != range.second; ++iter) - if (AuraEffect const * bonusEff = iter->second->GetPartAura(0)) + if (AuraEffect const * bonusEff = iter->second->GetEffect(0)) current_dmg += bonusEff->GetAmount(); int32 new_dmg = (int32)*absorb * aurEff->GetAmount() / 100; @@ -2629,10 +2552,10 @@ bool Unit::isSpellBlocked(Unit *pVictim, SpellEntry const * /*spellProto*/, Weap { /* Currently not exist spells with ignore block // Ignore combat result aura (parry/dodge check on prepare) - AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + AuraList const& ignore = GetAuraEffectsByType(SPELL_AURA_IGNORE_COMBAT_RESULT); for (AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) { - if (!(*i)->isAffectedOnSpell(spellProto)) + if (!(*i)->IsAffectedOnSpell(spellProto)) continue; if ((*i)->GetMiscValue() == ) return false; @@ -2820,10 +2743,10 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell) canBlock = false; } // Ignore combat result aura - AuraEffectList const &ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + AuraEffectList const &ignore = GetAuraEffectsByType(SPELL_AURA_IGNORE_COMBAT_RESULT); for (AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) { - if (!(*i)->isAffectedOnSpell(spell)) + if (!(*i)->IsAffectedOnSpell(spell)) continue; switch ((*i)->GetMiscValue()) { @@ -2996,7 +2919,7 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool if (CanReflect) { int32 reflectchance = pVictim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS); - Unit::AuraEffectList const& mReflectSpellsSchool = pVictim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); + Unit::AuraEffectList const& mReflectSpellsSchool = pVictim->GetAuraEffectsByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); for (Unit::AuraEffectList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i) if((*i)->GetMiscValue() & GetSpellSchoolMask(spell)) reflectchance += (*i)->GetAmount(); @@ -3277,13 +3200,12 @@ uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target) return value; } -void Unit::_DeleteAuras() +void Unit::_DeleteRemovedAuras() { while(!m_removedAuras.empty()) { delete m_removedAuras.front(); m_removedAuras.pop_front(); -// sLog.outDebug("Aura %d is deleted from unit %d", Aur->GetId(), GetGUIDLow()); } } @@ -3302,25 +3224,29 @@ void Unit::_UpdateSpells( uint32 time ) } } - // update auras - // m_AurasUpdateIterator can be updated in inderect called code at aura remove to skip next planned to update but removed auras - for (m_AurasUpdateIterator = m_Auras.begin(); m_AurasUpdateIterator != m_Auras.end();) + // update auraBases + // m_auraBaseUpdateIterator can be updated in indirect called code at aura remove to skip next planned to update but removed auras + for (m_auraUpdateIterator = m_ownedAuras.begin(); m_auraUpdateIterator != m_ownedAuras.end();) { - Aura* i_aura = m_AurasUpdateIterator->second; - ++m_AurasUpdateIterator; // need shift to next for allow update if need into aura update - i_aura->Update(time); + Aura * i_aura = m_auraUpdateIterator->second; + ++m_auraUpdateIterator; // need shift to next for allow update if need into aura update + i_aura->UpdateOwner(time, this); } - // remove expired auras - for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end();) + // remove expired auras - do that after updates(used in scripts?) + for (AuraMap::iterator i = m_ownedAuras.begin(); i != m_ownedAuras.end();) { if(i->second->IsExpired()) - RemoveAura(i, AURA_REMOVE_BY_EXPIRE); + RemoveOwnedAura(i, AURA_REMOVE_BY_EXPIRE); else ++i; } - _DeleteAuras(); + for (VisibleAuraMap::iterator itr = m_visibleAuras.begin(); itr != m_visibleAuras.end(); ++itr) + if (itr->second->IsNeedClientUpdate()) + itr->second->ClientUpdate(); + + _DeleteRemovedAuras(); if(!m_gameObj.empty()) { @@ -3591,332 +3517,269 @@ void Unit::DeMorph() SetDisplayId(GetNativeDisplayId()); } -int32 Unit::GetTotalAuraModifier(AuraType auratype) const -{ - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - modifier += (*i)->GetAmount(); - - return modifier; -} - -float Unit::GetTotalAuraMultiplier(AuraType auratype) const +void Unit::_AddAura(Aura * aura) { - float multiplier = 1.0f; - - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - multiplier *= (100.0f + (*i)->GetAmount())/100.0f; - - return multiplier; + m_ownedAuras.insert(AuraMap::value_type(aura->GetId(), aura)); } -int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype) +AuraApplication * Unit::__ApplyAura(Aura * aura) { - int32 modifier = 0; + // auraBase musn't be removed + assert(!aura->IsRemoved()); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - { - if ((*i)->GetAmount() > modifier) - modifier = (*i)->GetAmount(); - } + SpellEntry const* aurSpellInfo = aura->GetSpellProto(); + uint32 aurId = aurSpellInfo->Id; - return modifier; -} + // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) + if( !isAlive() && !IsDeathPersistentSpell(aurSpellInfo) && + (GetTypeId() != TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) ) + return NULL; -int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const -{ - int32 modifier = 0; + Unit * caster = aura->GetCaster(); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if ((*i)->GetAmount() < modifier) - modifier = (*i)->GetAmount(); + // Add all pointers to lists here to prevent possible pointer invalidation on spellcast/auraapply/auraremove - return modifier; -} + AuraApplication * aurApp = new AuraApplication(this, caster, aura); + m_appliedAuras.insert(AuraApplicationMap::value_type(aurId, aurApp)); -int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const -{ - int32 modifier = 0; + // Register single cast aura + if (caster && aura->IsSingleTarget()) + caster->GetSingleCastAuras().push_back(aurApp); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + if(aurSpellInfo->AuraInterruptFlags) { - if ((*i)->GetMiscValue()& misc_mask) - modifier += (*i)->GetAmount(); + m_interruptableAuras.push_back(aurApp); + AddInterruptMask(aurSpellInfo->AuraInterruptFlags); } - return modifier; -} -float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const -{ - float multiplier = 1.0f; + AuraState aState = GetSpellAuraState(aura->GetSpellProto()); + if(aState) + m_auraStateAuras.insert(AuraStateAurasMap::value_type(aState, aurApp)); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - { - if ((*i)->GetMiscValue()& misc_mask) - multiplier *= (100.0f + (*i)->GetAmount())/100.0f; - } - return multiplier; -} - -int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const -{ - int32 modifier = 0; + aura->_ApplyForTarget(this, caster, aurApp); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + // passive and Incanter's Absorption and auras with different type can stack with themselves any number of times + // auras with type other than TARGET_AURA have CanAuraStack check in their target selection code, so shouldn't go here + if (!aura->IsPassive() && aura->GetType() == UNIT_AURA_TYPE && aurId != 44413) { - if ((*i)->GetMiscValue()& misc_mask && (*i)->GetAmount() > modifier) - modifier = (*i)->GetAmount(); - } - - return modifier; -} - -int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const -{ - int32 modifier = 0; + // find current aura from spell and change it's stackamount + if (AuraApplication * foundAura = GetAuraApplication(aurId, aura->GetCasterGUID(), 0, aurApp)) + { + if(aurSpellInfo->StackAmount) + aura->ModStackAmount(foundAura->GetBase()->GetStackAmount()); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - { - if ((*i)->GetMiscValue()& misc_mask && (*i)->GetAmount() < modifier) - modifier = (*i)->GetAmount(); + // Use the new one to replace the old one + // This is the only place where AURA_REMOVE_BY_STACK should be used + RemoveAura(foundAura, AURA_REMOVE_BY_STACK); + } } - return modifier; -} - -int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const -{ - int32 modifier = 0; - - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + // update single target auras list - after aura stack check to allow single target auras to stack + if (aura->IsSingleTarget()) { - if ((*i)->GetMiscValue()== misc_value) - modifier += (*i)->GetAmount(); + for (;;) + { + bool restart = false; + AuraApplicationList& scAuras = caster->GetSingleCastAuras(); + for (AuraApplicationList::iterator itr = scAuras.begin(); itr != scAuras.end(); ++itr) + { + if( (*itr)->GetBase() != aura && + IsSingleTargetSpells((*itr)->GetBase()->GetSpellProto(), aura->GetSpellProto())) + { + (*itr)->GetBase()->Remove(AURA_REMOVE_BY_DEFAULT); + restart = true; + break; + } + } + + if(!restart) + break; + } } - return modifier; -} -float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const -{ - float multiplier = 1.0f; + _RemoveNoStackAurasDueToAura(aura); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - { - if ((*i)->GetMiscValue()== misc_value) - multiplier *= (100.0f + (*i)->GetAmount())/100.0f; - } - return multiplier; -} + // Update target aura state flag + if(aState) + ModifyAuraState(aState, true); -int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const -{ - int32 modifier = 0; + // Sitdown on apply aura req seated + if (aurSpellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !IsSitState()) + SetStandState(UNIT_STAND_STATE_SIT); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - { - if ((*i)->GetMiscValue()== misc_value && (*i)->GetAmount() > modifier) - modifier = (*i)->GetAmount(); - } + aura->HandleAuraSpecificMods(aurApp, caster, true); - return modifier; + if (aurApp->GetRemoveMode()) + return NULL; + + return aurApp; } -int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +void Unit::__UnapplyAura(AuraApplicationMap::iterator &i) { - int32 modifier = 0; + AuraApplication * aurApp = i->second; + assert(aurApp->GetTarget() == this); + Aura * aura = aurApp->GetBase(); - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - { - if ((*i)->GetMiscValue()== misc_value && (*i)->GetAmount() < modifier) - modifier = (*i)->GetAmount(); - } + // dead loop is killing the server probably + assert(m_removedAurasCount < 0xFFFFFFFF); - return modifier; -} + ++m_removedAurasCount; -bool Unit::AddAura(Aura *Aur, bool handleEffects) -{ - // aura doesn't apply effects-return - if (!Aur->GetEffectMask() || Aur->IsExpired()) - { - delete Aur; - return false; - } + Unit * caster = aura->GetCaster(); - SpellEntry const* aurSpellInfo = Aur->GetSpellProto(); + // Remove all pointers from lists here to prevent possible pointer invalidation on spellcast/auraapply/auraremove + m_appliedAuras.erase(i); - // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) - if( !isAlive() && !IsDeathPersistentSpell(aurSpellInfo) && - //Aur->GetId() != 2584 && // Waiting to Resurrect (not have death persistence flag) - (GetTypeId() != TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) ) - { - delete Aur; - return false; - } + // Unregister single cast aura + if (caster && aura->IsSingleTarget()) + caster->GetSingleCastAuras().remove(aurApp); - if(Aur->GetTarget() != this) + if (aura->GetSpellProto()->AuraInterruptFlags) { - sLog.outError("Aura (spell %u) add to aura list of %s (lowguid: %u) but Aura target is %s (lowguid: %u)", - Aur->GetId(),(GetTypeId() == TYPEID_PLAYER?"player":"creature"),GetGUIDLow(), - (Aur->GetTarget()->GetTypeId() == TYPEID_PLAYER?"player":"creature"),Aur->GetTarget()->GetGUIDLow()); - delete Aur; - return false; + m_interruptableAuras.remove(aurApp); + UpdateInterruptMask(); } - uint32 aurId = aurSpellInfo->Id; - - // passive and persistent and Incanter's Absorption auras can stack with themselves any number of times - if (!Aur->IsPassive() && !Aur->IsPersistent() && aurId != 44413) + bool auraStateFound = false; + AuraState auraState; + if (auraState = GetSpellAuraState(aura->GetSpellProto())) { - // find current aura from spell and change it's stackamount - if (Aura * foundAura = GetAura(aurId, Aur->GetCasterGUID())) + bool canBreak = false; + // Get mask of all aurastates from remaining auras + for (AuraStateAurasMap::iterator itr = m_auraStateAuras.lower_bound(auraState); itr != m_auraStateAuras.upper_bound(auraState) && !(auraStateFound && canBreak);) { - if(aurSpellInfo->StackAmount) + if (itr->second == aurApp) { - uint8 stackAmount = foundAura->GetStackAmount() + 1; - if (stackAmount > aurSpellInfo->StackAmount) - stackAmount = aurSpellInfo->StackAmount; - Aur->SetStackAmount(stackAmount, false); - - // spell is triggered with only stackamount change but no amount change - switch(aurId) - { - case 28832: // Mark of Korth'azz - case 28833: // Mark of Blaumeux - case 28834: // Mark of Rivendare - case 28835: // Mark of Zeliek - if(Unit *caster = Aur->GetCaster()) // actually we can also use cast(this, originalcasterguid) - { - int32 damage; - switch(stackAmount) - { - case 1: damage = 0; break; - case 2: damage = 500; break; - case 3: damage = 1000; break; - case 4: damage = 1500; break; - case 5: damage = 4000; break; - case 6: damage = 12000; break; - default:damage = 20000 + 1000 * (stackAmount - 7); break; - } - if(damage) - caster->CastCustomSpell(28836, SPELLVALUE_BASE_POINT0, damage, this); - } - break; - case 64821: // Fuse Armor (Razorscale) - if(stackAmount == aurSpellInfo->StackAmount) - CastSpell(this, 64774, true, NULL, NULL, Aur->GetCasterGUID()); - break; - } + m_auraStateAuras.erase(itr); + itr = m_auraStateAuras.lower_bound(auraState); + canBreak = true; + continue; } - - // Use the new one to replace the old one - // This is the only place where AURA_REMOVE_BY_STACK should be used - RemoveAura(foundAura, AURA_REMOVE_BY_STACK); + auraStateFound = true; + ++itr; } } - // passive auras not stacable with other ranks - if (!RemoveNoStackAurasDueToAura(Aur)) + aurApp->_Remove(); + aura->_UnapplyForTarget(this, caster, aurApp); + + // remove effects of the spell - needs to be done after removing aura from lists + for (uint8 itr = 0 ; itr < MAX_SPELL_EFFECTS; ++itr) { - delete Aur; - return false; // couldn't remove conflicting aura with higher rank + if (aurApp->HasEffect(itr)) + aurApp->_HandleEffect(itr, false); } - // update single target auras list (before aura add to aura list, to prevent unexpected remove recently added aura) - if (Aur->IsSingleTarget()) + // all effect mustn't be applied + assert(!aurApp->GetEffectMask()); + + // Remove totem at next update if totem looses its aura + if (aurApp->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isTotem()&& ((TempSummon*)this)->GetSummonerGUID() == aura->GetCasterGUID()) { - // caster pointer can be deleted in time aura remove, find it by guid at each iteration - for (;;) - { - Unit* caster = Aur->GetCaster(); - assert(caster); + if (((Totem*)this)->GetSpell() == aura->GetId() && ((Totem*)this)->GetTotemType() == TOTEM_PASSIVE) + ((Totem*)this)->setDeathState(JUST_DIED); + } - bool restart = false; - AuraList& scAuras = caster->GetSingleCastAuras(); - for (AuraList::iterator itr = scAuras.begin(); itr != scAuras.end(); ++itr) - { - if( (*itr)->GetTarget() != Aur->GetTarget() && - IsSingleTargetSpells((*itr)->GetSpellProto(),aurSpellInfo) ) - { - (*itr)->GetTarget()->RemoveAurasDueToSpell((*itr)->GetId(), caster->GetGUID(), AURA_REMOVE_BY_DEFAULT); - restart = true; - break; - } - } + // Remove aurastates only if were not found + if (!auraStateFound) + ModifyAuraState(auraState, false); - if(!restart) - { - // done - scAuras.push_back(Aur); - break; - } - } - } + aura->HandleAuraSpecificMods(aurApp, caster, false); - // add aura, register in lists and arrays - Aur->_AddAura(); + // only way correctly remove all auras from list + //if(removedAuras != m_removedAurasCount) new aura may be added + i = m_appliedAuras.begin(); +} - //***************************************************** - // Update target aura state flag - //***************************************************** - if(AuraState aState = GetSpellAuraState(Aur->GetSpellProto())) +bool Unit::_ApplyAuraEffect(Aura * aura, uint8 effIndex) +{ + // check if aura has requested effect - should always do + assert(aura); + assert(aura->HasEffect(effIndex)); + AuraApplication * aurApp = aura->GetApplicationOfTarget(GetGUID()); + if (!aurApp) { - m_auraStateAuras.insert(AuraStateAurasMap::value_type(aState, Aur)); - ModifyAuraState(aState, true); + // real aura apply + aurApp = __ApplyAura(aura); + if (!aurApp) + return false; } + // add effect to unit + aurApp->_HandleEffect(effIndex, true); + return true; +} - m_Auras.insert(AuraMap::value_type(aurId, Aur)); +// Not implemented - afaik there should be no way to remove effects separately +void Unit::_UnapplyAuraEffect(AuraApplication * aurApp, uint8 effIndex, AuraRemoveMode removeMode) +{ + assert(aurApp); + assert(aurApp->HasEffect(effIndex)); + _UnapplyAura(aurApp, removeMode); +} - if(aurSpellInfo->AuraInterruptFlags) +void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode) +{ + AuraApplication * aurApp = i->second; + assert(aurApp); + assert(!aurApp->GetRemoveMode()); + aurApp->SetRemoveMode(removeMode); + sLog.outDebug("Aura %u now is remove mode %d", aurApp->GetBase()->GetId(), removeMode); + __UnapplyAura(i); +} + +void Unit::_UnapplyAura(AuraApplication * aurApp, AuraRemoveMode removeMode) +{ + // aura can be removed from unit only if it's applied on it, shouldn't happen + assert(aurApp->GetBase()->GetApplicationOfTarget(GetGUID()) == aurApp); + uint32 spellId = aurApp->GetBase()->GetId(); + for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);) { - m_interruptableAuras.push_back(Aur); - AddInterruptMask(aurSpellInfo->AuraInterruptFlags); + if (iter->second == aurApp) + { + _UnapplyAura(iter, removeMode); + return; + } + else + ++iter; } - - if (handleEffects) - Aur->HandleEffects(true); - - sLog.outDebug("Aura %u now is in use", aurId); - return true; } -bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) +void Unit::_RemoveNoStackAurasDueToAura(Aura * aura) { - SpellEntry const* spellProto = Aur->GetSpellProto(); + if (aura->GetType() == DYNOBJ_AURA_TYPE) + return; + + SpellEntry const* spellProto = aura->GetSpellProto(); - uint32 spellId = Aur->GetId(); + uint32 spellId = aura->GetId(); // passive spell special case (only non stackable with ranks) if(IsPassiveSpell(spellId) && IsPassiveSpellStackableWithRanks(spellProto)) - return true; + return; //bool linked = spellmgr.GetSpellCustomAttr(spellId) & SPELL_ATTR_CU_LINK_AURA? true : false; bool remove = false; - for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) + for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i) { if(remove) { remove = false; - i = m_Auras.begin(); + i = m_appliedAuras.begin(); } - SpellEntry const* i_spellProto = i->second->GetSpellProto(); + // Do not check already applied aura + if (i->second->GetBase() == aura) + continue; + + // Do not check already applied aura + if (i->second->GetBase()->GetType() != aura->GetType()) + continue; + + SpellEntry const* i_spellProto = i->second->GetBase()->GetSpellProto(); uint32 i_spellId = i_spellProto->Id; - bool sameCaster = Aur->GetCasterGUID() == (*i).second->GetCasterGUID(); + bool sameCaster = aura->GetCasterGUID() == (*i).second->GetBase()->GetCasterGUID(); if(IsPassiveSpell(i_spellId)) { @@ -3942,49 +3805,102 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) } } - // check if they can stack - - /*// Dont remove by stack with linked auras - // Not needed for now - if(sameCaster && linked) - { - if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(spellId + SPELL_LINK_AURA)) - for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) - if(*itr>0 && *itr==i_spellId) - { - is_triggered_by_spell=true; - break; - } - }*/ - if (is_triggered_by_spell) continue; if(spellmgr.CanAurasStack(spellProto, i_spellProto, sameCaster)) continue; - //some spells should be not removed by lower rank of them (totem, paladin aura) - if (!sameCaster - &&(Aur->IsAreaAura()) - &&(spellProto->DurationIndex==21) - &&(spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId)) - &&(IsHigherHankOfSpell(spellId,i_spellId))) - return false; - // Remove all auras by aura caster RemoveAura(i, AURA_REMOVE_BY_DEFAULT); - if(i == m_Auras.end()) + if(i == m_appliedAuras.end()) break; remove = true; } - return true; } -void Unit::RemoveAura(uint32 spellId, uint64 caster, AuraRemoveMode removeMode) +void Unit::_HandleAuraEffect(AuraEffect * aurEff, bool apply) { - for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) + if (apply) + m_modAuras[aurEff->GetAuraType()].push_back(aurEff); + else + m_modAuras[aurEff->GetAuraType()].remove(aurEff); +} + +// All aura base removes should go threw this function! +void Unit::RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode) +{ + Aura * aura = i->second; + assert(!aura->IsRemoved()); + + // if unit currently update aura list then make safe update iterator shift to next + if (m_auraUpdateIterator == i) + ++m_auraUpdateIterator; + + m_ownedAuras.erase(i); + + aura->_Remove(removeMode); + + i = m_ownedAuras.begin(); +} + +void Unit::RemoveOwnedAura(uint32 spellId, uint64 caster, uint8 reqEffMask, AuraRemoveMode removeMode) +{ + for (AuraMap::iterator itr = m_ownedAuras.lower_bound(spellId); itr != m_ownedAuras.upper_bound(spellId);) + if(((itr->second->GetEffectMask() & reqEffMask) == reqEffMask) && (!caster || itr->second->GetCasterGUID() == caster)) + { + RemoveOwnedAura(itr, removeMode); + itr = m_ownedAuras.lower_bound(spellId); + } + else + ++itr; +} + +void Unit::RemoveOwnedAura(Aura * aura, AuraRemoveMode removeMode) +{ + if (aura->IsRemoved()) + return; + + assert(aura->GetOwner() == this); + + uint32 spellId = aura->GetId(); + for (AuraMap::iterator itr = m_ownedAuras.lower_bound(spellId); itr != m_ownedAuras.upper_bound(spellId); ++itr) + if (itr->second == aura) + { + RemoveOwnedAura(itr, removeMode); + return; + } + assert(false); +} + +Aura * Unit::GetOwnedAura(uint32 spellId, uint64 caster, uint8 reqEffMask) const +{ + for (AuraMap::const_iterator itr = m_ownedAuras.lower_bound(spellId); itr != m_ownedAuras.upper_bound(spellId); ++itr) + if(((itr->second->GetEffectMask() & reqEffMask) == reqEffMask) && (!caster || itr->second->GetCasterGUID() == caster)) + return itr->second; + return NULL; +} + +void Unit::RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode) +{ + AuraApplication * aurApp = i->second; + // Do not remove aura which is already being removed + if (aurApp->GetRemoveMode()) + return; + Aura * aura = aurApp->GetBase(); + _UnapplyAura(i, mode); + // Remove aura - for Area and Target auras + if (aura->GetOwner() == this) + aura->Remove(mode); +} + +void Unit::RemoveAura(uint32 spellId, uint64 caster, uint8 reqEffMask, AuraRemoveMode removeMode) +{ + for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);) { - if (!caster || iter->second->GetCasterGUID() == caster) + Aura const * aura = iter->second->GetBase(); + if (((aura->GetEffectMask() & reqEffMask) == reqEffMask) + && (!caster || aura->GetCasterGUID() == caster)) { RemoveAura(iter, removeMode); return; @@ -3994,14 +3910,16 @@ void Unit::RemoveAura(uint32 spellId, uint64 caster, AuraRemoveMode removeMode) } } -void Unit::RemoveAura(Aura * aur ,AuraRemoveMode mode) +void Unit::RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode) { + assert(aurApp->GetBase()->GetApplicationOfTarget(GetGUID()) == aurApp); // no need to remove - if (!aur || aur->IsRemoved()) + if (aurApp->GetRemoveMode() || aurApp->GetBase()->IsRemoved()) return; - for (AuraMap::iterator iter = m_Auras.lower_bound(aur->GetId()); iter != m_Auras.upper_bound(aur->GetId());) + uint32 spellId = aurApp->GetBase()->GetId(); + for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);) { - if (aur == iter->second) + if (aurApp == iter->second) { RemoveAura(iter, mode); return; @@ -4011,14 +3929,26 @@ void Unit::RemoveAura(Aura * aur ,AuraRemoveMode mode) } } -void Unit::RemoveAurasDueToSpell(uint32 spellId, uint64 caster, AuraRemoveMode removeMode) +void Unit::RemoveAura(Aura * aura, AuraRemoveMode mode) { - for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) + if (aura->IsRemoved()) + return; + if (AuraApplication * aurApp = aura->GetApplicationOfTarget(GetGUID())) + RemoveAura(aurApp, mode); + else + assert(false); +} + +void Unit::RemoveAurasDueToSpell(uint32 spellId, uint64 caster, uint8 reqEffMask, AuraRemoveMode removeMode) +{ + for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);) { - if (!caster || iter->second->GetCasterGUID()==caster) + Aura const * aura = iter->second->GetBase(); + if (((aura->GetEffectMask() & reqEffMask) == reqEffMask) + && (!caster || aura->GetCasterGUID() == caster)) { RemoveAura(iter, removeMode); - iter = m_Auras.lower_bound(spellId); + iter = m_appliedAuras.lower_bound(spellId); } else ++iter; @@ -4027,9 +3957,11 @@ void Unit::RemoveAurasDueToSpell(uint32 spellId, uint64 caster, AuraRemoveMode r void Unit::RemoveAuraFromStack(uint32 spellId, uint64 caster, AuraRemoveMode removeMode) { - for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) + for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);) { - if (!caster || iter->second->GetCasterGUID()==caster) + Aura const * aura = iter->second; + if ((aura->GetType() == UNIT_AURA_TYPE) + && (!caster || aura->GetCasterGUID() == caster)) { RemoveAuraFromStack(iter, removeMode); return; @@ -4039,49 +3971,65 @@ void Unit::RemoveAuraFromStack(uint32 spellId, uint64 caster, AuraRemoveMode rem } } -inline void Unit::RemoveAuraFromStack(AuraMap::iterator &iter,AuraRemoveMode removeMode) +inline void Unit::RemoveAuraFromStack(AuraMap::iterator &iter, AuraRemoveMode removeMode) { - if (iter->second->modStackAmount(-1)) - RemoveAura(iter, removeMode); + if (iter->second->ModStackAmount(-1)) + RemoveOwnedAura(iter, removeMode); } -void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeller) +void Unit::RemoveAurasDueToSpellByDispel(Aura * aura, Unit *dispeller) { - for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) + if (aura->IsRemoved()) + return; + + uint32 spellId = aura->GetId(); + + for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);) { - Aura *aur = iter->second; - if (casterGUID == aur->GetCasterGUID()) + if (aura == iter->second) { - if (aur->GetSpellProto()->AttributesEx7 & SPELL_ATTR_EX7_DISPEL_CHARGES) - iter = aur->DropAuraCharge() ? m_Auras.begin() : iter; + if (aura->GetSpellProto()->AttributesEx7 & SPELL_ATTR_EX7_DISPEL_CHARGES) + aura->DropCharge(); else RemoveAuraFromStack(iter, AURA_REMOVE_BY_ENEMY_SPELL); // Unstable Affliction (crash if before removeaura?) - if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags[1] & 0x0100)) + if (aura->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aura->GetSpellProto()->SpellFamilyFlags[1] & 0x0100)) { - if (AuraEffect const * aurEff = aur->GetPartAura(0)) + if (AuraEffect const * aurEff = aura->GetEffect(0)) { int32 damage = aurEff->GetAmount()*9; // backfire damage and silence dispeller->CastCustomSpell(dispeller, 31117, &damage, NULL, NULL, true, NULL, NULL, GetGUID()); } } - if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (aur->GetSpellProto()->SpellFamilyFlags[0] & 0x10000000)) + // Flame Shock + if (aura->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (aura->GetSpellProto()->SpellFamilyFlags[0] & 0x10000000)) { - Unit *caster = GetUnit(*this, casterGUID); - uint32 triggered_spell_id = 0; + Unit * caster = aura->GetCaster(); if (caster) { + uint32 triggeredSpellId = 0; // Lava Flows - if (caster->HasAura(51482)) // Rank 3 - triggered_spell_id = 65264; - else if (caster->HasAura(51481)) // Rank 2 - triggered_spell_id = 65263; - else if (caster->HasAura(51480)) // Rank 1 - triggered_spell_id = 64694; - if (triggered_spell_id) - caster->CastSpell(caster, triggered_spell_id, true); + if (AuraEffect const * aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_SHAMAN, 3087, 0)) + { + switch(aurEff->GetId()) + { + case 51482: // Rank 3 + triggeredSpellId = 65264; + break; + case 51481: // Rank 2 + triggeredSpellId = 65263; + break; + case 51480: // Rank 1 + triggeredSpellId = 64694; + break; + default: + sLog.outError("Aura::HandleAuraSpecificMods: Unknown rank of Lava Flows (%d) found", aurEff->GetId()); + } + } + if (triggeredSpellId) + caster->CastSpell(caster, triggeredSpellId, true); } } return; @@ -4091,55 +4039,67 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit } } -void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer) +void Unit::RemoveAurasDueToSpellBySteal(Aura * aura, Unit *stealer) { - if (casterGUID == stealer->GetGUID()) + if (aura->IsRemoved()) return; - for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) + uint32 spellId = aura->GetId(); + + for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);) { - Aura * aur = iter->second; - if (casterGUID == aur->GetCasterGUID()) + if (aura == iter->second) { int32 damage[MAX_SPELL_EFFECTS]; - for (uint8 i=0; i<MAX_SPELL_EFFECTS; ++i) + int32 baseDamage[MAX_SPELL_EFFECTS]; + uint8 effMask = 0; + uint8 recalculateMask = 0; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (aur->GetPartAura(i)) - damage[i]=aur->GetPartAura(i)->GetAmount(); + if (aura->GetEffect(i)) + { + baseDamage[i] = aura->GetEffect(i)->GetBaseAmount(); + damage[i] = aura->GetEffect(i)->GetAmount(); + effMask |= (1<<i); + if (aura->GetEffect(i)->CanBeRecalculated()) + recalculateMask |= (1<<i); + } else - damage[i]=NULL; + { + baseDamage[i] = NULL; + damage[i] = NULL; + } } - bool steal_charge = aur->GetSpellProto()->AttributesEx7 & SPELL_ATTR_EX7_DISPEL_CHARGES; + bool stealCharge = aura->GetSpellProto()->AttributesEx7 & SPELL_ATTR_EX7_DISPEL_CHARGES; - if (Aura * new_aur = steal_charge ? stealer->GetAura(aur->GetId(), aur->GetCasterGUID()) : NULL) + if (stealCharge) + aura->DropCharge(); + else + RemoveAuraFromStack(iter, AURA_REMOVE_BY_ENEMY_SPELL); + + + if (Aura * newAura = stealCharge ? stealer->GetAura(aura->GetId(), aura->GetCasterGUID()) : NULL) { - uint8 new_charges = new_aur->GetAuraCharges() + 1; - uint8 max_charges = new_aur->GetSpellProto()->procCharges; + uint8 newCharges = newAura->GetCharges() + 1; + uint8 maxCharges = newAura->GetSpellProto()->procCharges; // We must be able to steal as much charges as original caster can have - if (Player* modOwner = aur->GetCaster()->GetSpellModOwner()) - modOwner->ApplySpellMod(aur->GetId(), SPELLMOD_CHARGES, max_charges); - // TODO: Do we need to refresh an aura? - new_aur->SetAuraCharges(max_charges < new_charges ? max_charges : new_charges); + if (Unit * caster = newAura->GetCaster()) + if (Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(aura->GetId(), SPELLMOD_CHARGES, maxCharges); + newAura->SetCharges(maxCharges < newCharges ? maxCharges : newCharges); } else { - int32 dur = 2*MINUTE*IN_MILISECONDS < aur->GetAuraDuration() ? 2*MINUTE*IN_MILISECONDS : aur->GetAuraDuration(); + int32 dur = 2*MINUTE*IN_MILISECONDS < aura->GetDuration() ? 2*MINUTE*IN_MILISECONDS : aura->GetDuration(); - new_aur = new Aura(aur->GetSpellProto(),aur->GetEffectMask(), stealer, stealer, stealer); - new_aur->SetLoadedState(aur->GetCasterGUID(), dur, dur, steal_charge ? 1 : aur->GetAuraCharges(), aur->GetStackAmount(), &damage[0]); - - // Unregister _before_ adding to stealer - aur->UnregisterSingleCastAura(); + newAura = Aura::TryCreate(aura->GetSpellProto(), effMask, stealer, NULL, &baseDamage[0], NULL, aura->GetCasterGUID()); + assert(newAura); + newAura->SetLoadedState(dur, dur, stealCharge ? 1 : aura->GetCharges(), aura->GetStackAmount(), recalculateMask, &damage[0]); // strange but intended behaviour: Stolen single target auras won't be treated as single targeted - new_aur->SetIsSingleTarget(false); - stealer->AddAura(new_aur); + newAura->SetIsSingleTarget(false); + newAura->ApplyForTargets(); } - - if (steal_charge) - iter = aur->DropAuraCharge() ? m_Auras.begin() : iter; - else - RemoveAuraFromStack(iter, AURA_REMOVE_BY_ENEMY_SPELL); return; } else @@ -4149,12 +4109,12 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId) { - for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) + for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);) { - if (!castItem || iter->second->GetCastItemGUID()==castItem->GetGUID()) + if (!castItem || iter->second->GetBase()->GetCastItemGUID() == castItem->GetGUID()) { RemoveAura(iter); - iter = m_Auras.upper_bound(spellId); // overwrite by more appropriate + iter = m_appliedAuras.upper_bound(spellId); // overwrite by more appropriate } else ++iter; @@ -4163,15 +4123,17 @@ void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId) void Unit::RemoveAurasByType(AuraType auraType, uint64 casterGUID, Aura * except, bool negative, bool positive) { - for (AuraEffectList::const_iterator iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end();) + for (AuraEffectList::iterator iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end();) { - Aura * aur = (*iter)->GetParentAura(); + Aura * aura = (*iter)->GetBase(); + AuraApplication * aurApp = aura ->GetApplicationOfTarget(GetGUID()); + ++iter; - if (aur != except && (!casterGUID || aur->GetCasterGUID()==casterGUID) - && ((negative && !aur->IsPositive()) || (positive && aur->IsPositive()))) + if (aura != except && (!casterGUID || aura->GetCasterGUID() == casterGUID) + && ((negative && !aurApp->IsPositive()) || (positive && aurApp->IsPositive()))) { uint32 removedAuras = m_removedAurasCount; - RemoveAura(aur); + RemoveAura(aurApp); if (m_removedAurasCount > removedAuras + 1) iter = m_modAuras[auraType].begin(); } @@ -4181,17 +4143,18 @@ void Unit::RemoveAurasByType(AuraType auraType, uint64 casterGUID, Aura * except void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase) { // single target auras from other casters - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) + for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();) { - if (iter->second->GetCasterGUID()!=GetGUID() && IsSingleTargetSpell(iter->second->GetSpellProto())) + Aura const * aura = iter->second; + if (aura->GetCasterGUID() !=GetGUID() && IsSingleTargetSpell(aura->GetSpellProto())) { if (!newPhase) - RemoveAura(iter); + RemoveOwnedAura(iter); else { - Unit* caster = iter->second->GetCaster(); + Unit* caster = aura->GetCaster(); if (!caster || !caster->InSamePhase(newPhase)) - RemoveAura(iter); + RemoveOwnedAura(iter); else ++iter; } @@ -4201,121 +4164,145 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase) } // single target auras at other targets - AuraList& scAuras = GetSingleCastAuras(); - for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();) + AuraApplicationList& scAuras = GetSingleCastAuras(); + for (AuraApplicationList::iterator iter = scAuras.begin(); iter != scAuras.end();) { - Aura * aura=*iter; + AuraApplication * aurApp= *iter; ++iter; - if (aura->GetTarget() != this && !aura->GetTarget()->InSamePhase(newPhase)) + if (aurApp->GetTarget() != this && !aurApp->GetTarget()->InSamePhase(newPhase)) { uint32 removedAuras = m_removedAurasCount; - aura->GetTarget()->RemoveAura(aura); + aurApp->GetBase()->Remove(); if (m_removedAurasCount > removedAuras + 1) iter = scAuras.begin(); } } } -void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) -{ - Aura* Aur = i->second; - - // if unit currently update aura list then make safe update iterator shift to next - if (m_AurasUpdateIterator == i) - ++m_AurasUpdateIterator; - - // some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura - // remove aura from list before to prevent deleting it before - m_Auras.erase(i); - - ++m_removedAurasCount; - - if(Aur->IsPersistent()) - if(DynamicObject *dynObj = ObjectAccessor::GetObjectInWorld(Aur->GetSourceGUID(), (DynamicObject*)NULL)) - dynObj->RemoveAffected(this); - Aur->UnregisterSingleCastAura(); +void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except) +{ + if (!(m_interruptMask & flag)) + return; - if(Aur->GetSpellProto()->AuraInterruptFlags) + // interrupt auras + for (AuraApplicationList::iterator iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end();) { - m_interruptableAuras.remove(Aur); - UpdateInterruptMask(); + Aura * aura = (*iter)->GetBase(); + ++iter; + if ((aura->GetSpellProto()->AuraInterruptFlags & flag) && (!except || aura->GetId() != except)) + { + uint32 removedAuras = m_removedAurasCount; + RemoveAura(aura); + if (m_removedAurasCount > removedAuras + 1) + iter = m_interruptableAuras.begin(); + } } - Aur->SetRemoveMode(mode); - - sLog.outDebug("Aura %u now is remove mode %d", Aur->GetId(), mode); - Aur->HandleEffects(false); - - // set aura to be removed during unit::_updatespells - m_removedAuras.push_back(Aur); + // interrupt channeled spell + if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) + if (spell->getState() == SPELL_STATE_CASTING + && (spell->m_spellInfo->ChannelInterruptFlags & flag) + && spell->m_spellInfo->Id != except) + InterruptNonMeleeSpells(false); - Aur->_RemoveAura(); + UpdateInterruptMask(); +} - bool auraStateFound = false; - if (AuraState auraState = GetSpellAuraState(Aur->GetSpellProto())) +void Unit::RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID) +{ + for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) { - bool canBreak = false; - // Get mask of all aurastates from remaining auras - for (AuraStateAurasMap::iterator itr = m_auraStateAuras.lower_bound(auraState); itr != m_auraStateAuras.upper_bound(auraState) && !(auraStateFound && canBreak);) + Aura const * aura = iter->second->GetBase(); + if (!casterGUID || aura->GetCasterGUID() == casterGUID) { - if (itr->second == Aur) + SpellEntry const *spell = aura->GetSpellProto(); + if (spell->SpellFamilyName == family && spell->SpellFamilyFlags.HasFlag(familyFlag1, familyFlag2, familyFlag3)) { - m_auraStateAuras.erase(itr); - itr = m_auraStateAuras.lower_bound(auraState); - canBreak = true; + RemoveAura(iter); continue; } - auraStateFound = true; - ++itr; } - // Remove only aurastates which were not found - if (!auraStateFound) - ModifyAuraState(auraState, false); - } - - // Remove totem at next update if totem looses its aura - if (Aur->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE && GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isTotem()&& ((TempSummon*)this)->GetSummonerGUID()==Aur->GetCasterGUID()) - { - if (((Totem*)this)->GetSpell()==Aur->GetId() && ((Totem*)this)->GetTotemType()==TOTEM_PASSIVE) - ((Totem*)this)->setDeathState(JUST_DIED); + ++iter; } +} - // only way correctly remove all auras from list - //if(removedAuras != m_removedAurasCount) new aura may be casted - i = m_Auras.begin(); +void Unit::RemoveMovementImpairingAuras() +{ + RemoveAurasWithMechanic((1<<MECHANIC_SNARE)|(1<<MECHANIC_ROOT)); } -void Unit::RemoveAllAuras() +void Unit::RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode, uint32 except) { - AuraMap::iterator iter = m_Auras.begin(); - while (!m_Auras.empty()) - RemoveAura(iter); + for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) + { + Aura const * aura = iter->second->GetBase(); + if (!except || aura->GetId() != except) + { + if (GetAllSpellMechanicMask(aura->GetSpellProto()) & mechanic_mask) + { + RemoveAura(iter, removemode); + continue; + } + } + ++iter; + } } -void Unit::RemoveAllAuras(uint64 casterGUID, Aura * except /*=NULL*/, bool negative /*=true*/, bool positive /*=true*/) +void Unit::RemoveAreaAurasDueToLeaveWorld() { - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) + // make sure that all area auras not applied on self are removed - prevent access to deleted pointer later + for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();) { - if (iter->second != except && (!casterGUID || iter->second->GetCasterGUID()==casterGUID) - && ((negative && !iter->second->IsPositive()) || (positive && iter->second->IsPositive()))) + Aura * aura = iter->second; + ++iter; + Aura::ApplicationMap const & appMap = aura->GetApplicationMap(); + for(Aura::ApplicationMap::const_iterator itr = appMap.begin(); itr!= appMap.end();) + { + AuraApplication * aurApp = itr->second; + ++itr; + Unit * target = aurApp->GetTarget(); + if (target == this) + continue; + target->RemoveAura(aurApp); + // things linked on aura remove may apply new area aura - so start from the beginning + iter = m_ownedAuras.begin(); + } + } + + // remove area auras owned by others + for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) + { + if (iter->second->GetBase()->GetOwner()!=this) RemoveAura(iter); else ++iter; } } +void Unit::RemoveAllAuras() +{ + AuraApplicationMap::iterator aurAppIter = m_appliedAuras.begin(); + while (!m_appliedAuras.empty()) + _UnapplyAura(aurAppIter, AURA_REMOVE_BY_DEFAULT); + + AuraMap::iterator aurIter = m_ownedAuras.begin(); + while (!m_ownedAuras.empty()) + RemoveOwnedAura(aurIter); +} + void Unit::RemoveArenaAuras(bool onleave) { // in join, remove positive buffs, on end, remove negative // used to remove positive visible auras in arenas - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) - { - if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras - && !iter->second->IsPassive() // don't remove passive auras - && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable) - && (iter->second->IsPositive() ^ onleave)) // remove positive buffs on enter, negative buffs on leave - RemoveAura(iter); + for (AuraMap::iterator iter = m_ownedAuras.begin(); iter != m_ownedAuras.end();) + { + Aura const * aura = iter->second; + if ( !(aura->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras + && !aura->IsPassive() // don't remove passive auras + && (!(aura->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(aura->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable) + && (aura->IsPositive(this) ^ onleave)) // remove positive buffs on enter, negative buffs on leave + RemoveOwnedAura(iter); else ++iter; } @@ -4325,144 +4312,199 @@ void Unit::RemoveAllAurasOnDeath() { // used just after dieing to remove all visible auras // and disable the mods for the passive ones - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) + for (AuraApplicationMap::iterator iter = m_appliedAuras.begin(); iter != m_appliedAuras.end();) { - if (!iter->second->IsPassive() && !iter->second->IsDeathPersistent()) + Aura const * aura = iter->second->GetBase(); + if (!aura->IsPassive() && !aura->IsDeathPersistent()) RemoveAura(iter, AURA_REMOVE_BY_DEATH); else ++iter; } } -void Unit::DelayAura(uint32 spellId, uint64 caster, int32 delaytime) +void Unit::DelayOwnedAuras(uint32 spellId, uint64 caster, int32 delaytime) { - if (Aura * aur = GetAura(spellId, caster)) + for (AuraMap::iterator iter = m_ownedAuras.lower_bound(spellId); iter != m_ownedAuras.upper_bound(spellId);++iter) { - if (aur->GetAuraDuration() < delaytime) - aur->SetAuraDuration(0); - else - aur->SetAuraDuration(aur->GetAuraDuration() - delaytime); - // update for out of range group members (on 1 slot use) - UpdateAuraForGroup(aur->GetAuraSlot()); - sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",aur->GetId(), GetGUIDLow(), aur->GetAuraDuration()); + Aura * aura = iter->second; + if (!caster || aura->GetCasterGUID() == caster) + { + if (aura->GetDuration() < delaytime) + aura->SetDuration(0); + else + aura->SetDuration(aura->GetDuration() - delaytime); + + // update for out of range group members (on 1 slot use) + aura->SetNeedClientUpdateForTargets(); + sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",aura->GetId() , GetGUIDLow(), aura->GetDuration()); + } } } -void Unit::_RemoveAllAuraMods() +void Unit::_RemoveAllAuraStatMods() { - for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) - (*i).second->ApplyAllModifiers(false); + for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i) + (*i).second->GetBase()->HandleAllEffects(i->second, AURA_EFFECT_HANDLE_STAT, false); } -void Unit::_ApplyAllAuraMods() +void Unit::_ApplyAllAuraStatMods() { - for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) - (*i).second->ApplyAllModifiers(true); + for (AuraApplicationMap::iterator i = m_appliedAuras.begin(); i != m_appliedAuras.end(); ++i) + (*i).second->GetBase()->HandleAllEffects(i->second, AURA_EFFECT_HANDLE_STAT, true); } -bool Unit::HasAuraTypeWithMiscvalue(AuraType auratype, uint32 miscvalue) const +AuraEffect * Unit::GetAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster) const { - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if (miscvalue == (*i)->GetMiscValue()) - return true; - return false; + for (AuraApplicationMap::const_iterator itr = m_appliedAuras.lower_bound(spellId); itr != m_appliedAuras.upper_bound(spellId); ++itr) + if(itr->second->HasEffect(effIndex) && (!caster || itr->second->GetBase()->GetCasterGUID() == caster)) + return itr->second->GetBase()->GetEffect(effIndex); + return NULL; } -bool Unit::HasAuraTypeWithValue(AuraType auratype, uint32 value) const +AuraEffect * Unit::GetAuraEffectOfRankedSpell(uint32 spellId, uint8 effIndex, uint64 caster) const { - AuraEffectList const& mTotalAuraList = GetAurasByType(auratype); - for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) - if (value == (*i)->GetAmount()) - return true; - return false; + uint32 rankSpell = spellmgr.GetFirstSpellInChain(spellId); + while(true) + { + if (AuraEffect * aurEff = GetAuraEffect(spellId, effIndex, caster)) + return aurEff; + SpellChainNode const * chainNode = spellmgr.GetSpellChainNode(rankSpell); + if (!chainNode) + break; + else + rankSpell = chainNode->next; + } + return NULL; } -bool Unit::HasAuraType(AuraType auraType) const +AuraEffect* Unit::GetAuraEffect(AuraType type, SpellFamilyNames name, uint32 iconId, uint8 effIndex) const { - return (!m_modAuras[auraType].empty()); + AuraEffectList const& auras = GetAuraEffectsByType(type); + for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + if (effIndex != (*itr)->GetEffIndex()) + continue; + SpellEntry const * spell = (*itr)->GetSpellProto(); + if (spell->SpellIconID == iconId && spell->SpellFamilyName == name && !spell->SpellFamilyFlags) + return *itr; + } + return NULL; } -bool Unit::HasAura(uint32 spellId, uint64 caster) const +AuraEffect* Unit::GetAuraEffect(AuraType type, SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID) { - //Special case for non existing spell - if (spellId==61988) - return HasAura(61987, caster) || HasAura(25771, caster); + AuraEffectList const& auras = GetAuraEffectsByType(type); + for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) + { + SpellEntry const *spell = (*i)->GetSpellProto(); + if (spell->SpellFamilyName == family && spell->SpellFamilyFlags.HasFlag(familyFlag1, familyFlag2, familyFlag3)) + { + if (casterGUID && (*i)->GetCasterGUID()!=casterGUID) + continue; + return (*i); + } + } + return NULL; +} - if (Aura * aur = GetAura(spellId, caster)) - return true; - return false; +AuraApplication * Unit::GetAuraApplication(uint32 spellId, uint64 casterGUID, uint8 reqEffMask, AuraApplication * except) const +{ + for (AuraApplicationMap::const_iterator itr = m_appliedAuras.lower_bound(spellId); itr != m_appliedAuras.upper_bound(spellId); ++itr) + { + Aura const * aura = itr->second->GetBase(); + if(((aura->GetEffectMask() & reqEffMask) == reqEffMask) && (!casterGUID || aura->GetCasterGUID() == casterGUID) && (!except || except!=itr->second)) + return itr->second; + } + return NULL; } -bool Unit::HasAura(Aura * aur) const +Aura * Unit::GetAura(uint32 spellId, uint64 casterGUID, uint8 reqEffMask) const { - // no need to find aura - if (!aur || aur->IsRemoved()) - return false; - for (AuraMap::const_iterator iter = m_Auras.lower_bound(aur->GetId()); iter != m_Auras.upper_bound(aur->GetId());) + AuraApplication * aurApp = GetAuraApplication(spellId, casterGUID, reqEffMask); + return aurApp ? aurApp->GetBase():NULL; +} + +AuraApplication * Unit::GetAuraApplicationOfRankedSpel(uint32 spellId, uint64 casterGUID, uint8 reqEffMask, AuraApplication * except) const +{ + uint32 rankSpell = spellmgr.GetFirstSpellInChain(spellId); + while(true) { - if (aur == iter->second) - return true; + if (AuraApplication * aurApp = GetAuraApplication(rankSpell, casterGUID, reqEffMask, except)) + return aurApp; + SpellChainNode const * chainNode = spellmgr.GetSpellChainNode(rankSpell); + if (!chainNode) + break; else - ++iter; + rankSpell = chainNode->next; } - return false; + return NULL; +} + +Aura * Unit::GetAuraOfRankedSpell(uint32 spellId, uint64 casterGUID, uint8 reqEffMask) const +{ + AuraApplication * aurApp = GetAuraApplicationOfRankedSpel(spellId, casterGUID, reqEffMask); + return aurApp ? aurApp->GetBase() : NULL; } bool Unit::HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster) const { - if (Aura * aur = GetAura(spellId, caster)) - return aur->HasEffect(effIndex); + for (AuraApplicationMap::const_iterator itr = m_appliedAuras.lower_bound(spellId); itr != m_appliedAuras.upper_bound(spellId); ++itr) + if(itr->second->HasEffect(effIndex) && (!caster || itr->second->GetBase()->GetCasterGUID() == caster)) + return true; return false; } -Aura * Unit::GetAura(uint32 spellId, uint64 caster) const +bool Unit::HasAura(uint32 spellId, uint64 caster, uint8 reqEffMask) const { - if (!caster) - { - AuraMap::const_iterator itr = m_Auras.find(spellId); - return itr != m_Auras.end() ? itr->second : NULL; - } - else - { - AuraMap const& auras = GetAuras(); - for (AuraMap::const_iterator itr = auras.lower_bound(spellId); itr != auras.upper_bound(spellId); ++itr) - if(itr->second->GetCasterGUID()==caster) - return itr->second; - return NULL; - } + //Special case for non existing spell + if (spellId==61988) + return HasAura(61987, caster, reqEffMask) || HasAura(25771, caster, reqEffMask); + + if (GetAuraApplication(spellId, caster, reqEffMask)) + return true; + return false; } -AuraEffect * Unit::GetAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster) const +bool Unit::HasAuraType(AuraType auraType) const +{ + return (!m_modAuras[auraType].empty()); +} + +bool Unit::HasAuraTypeWithMiscvalue(AuraType auratype, uint32 miscvalue) const { - if (Aura * aur = GetAura(spellId, caster)) - return aur->GetPartAura(effIndex); + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + if (miscvalue == (*i)->GetMiscValue()) + return true; return false; } -AuraEffect* Unit::GetAura(AuraType type, uint32 family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID) +bool Unit::HasAuraTypeWithValue(AuraType auratype, uint32 value) const { - AuraEffectList const& auras = GetAurasByType(type); - for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + if (value == (*i)->GetAmount()) + return true; + return false; +} + +bool Unit::HasNegativeAuraWithInterruptFlag(uint32 flag) +{ + for (AuraApplicationList::iterator iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end(); ++iter) { - SpellEntry const *spell = (*i)->GetSpellProto(); - if (spell->SpellFamilyName == family && spell->SpellFamilyFlags.HasFlag(familyFlag1, familyFlag2, familyFlag3)) - { - if (casterGUID && (*i)->GetCasterGUID()!=casterGUID) - continue; - return (*i); - } + if (!(*iter)->IsPositive() && (*iter)->GetBase()->GetSpellProto()->AuraInterruptFlags & flag) + return true; } - return NULL; + return false; } AuraEffect * Unit::IsScriptOverriden(SpellEntry const * spell, int32 script) const { - AuraEffectList const& auras = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) { if ((*i)->GetMiscValue() == script) - if ((*i)->isAffectedOnSpell(spell)) + if ((*i)->IsAffectedOnSpell(spell)) return (*i); } return NULL; @@ -4513,7 +4555,7 @@ uint32 Unit::GetDoTsByCaster(uint64 casterGUID) const uint32 dots=0; for (AuraType const* itr = &diseaseAuraTypes[0]; itr && itr[0] != SPELL_AURA_NONE; ++itr) { - Unit::AuraEffectList const& auras = GetAurasByType(*itr); + Unit::AuraEffectList const& auras = GetAuraEffectsByType(*itr); for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i) { // Get auras by caster @@ -4524,6 +4566,162 @@ uint32 Unit::GetDoTsByCaster(uint64 casterGUID) const return dots; } +int32 Unit::GetTotalAuraModifier(AuraType auratype) const +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + modifier += (*i)->GetAmount(); + + return modifier; +} + +float Unit::GetTotalAuraMultiplier(AuraType auratype) const +{ + float multiplier = 1.0f; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + multiplier *= (100.0f + (*i)->GetAmount())/100.0f; + + return multiplier; +} + +int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype) +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetAmount() > modifier) + modifier = (*i)->GetAmount(); + } + + return modifier; +} + +int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + if ((*i)->GetAmount() < modifier) + modifier = (*i)->GetAmount(); + + return modifier; +} + +int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetMiscValue()& misc_mask) + modifier += (*i)->GetAmount(); + } + return modifier; +} + +float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const +{ + float multiplier = 1.0f; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetMiscValue()& misc_mask) + multiplier *= (100.0f + (*i)->GetAmount())/100.0f; + } + return multiplier; +} + +int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetMiscValue()& misc_mask && (*i)->GetAmount() > modifier) + modifier = (*i)->GetAmount(); + } + + return modifier; +} + +int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetMiscValue()& misc_mask && (*i)->GetAmount() < modifier) + modifier = (*i)->GetAmount(); + } + + return modifier; +} + +int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetMiscValue()== misc_value) + modifier += (*i)->GetAmount(); + } + return modifier; +} + +float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const +{ + float multiplier = 1.0f; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetMiscValue()== misc_value) + multiplier *= (100.0f + (*i)->GetAmount())/100.0f; + } + return multiplier; +} + +int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetMiscValue()== misc_value && (*i)->GetAmount() > modifier) + modifier = (*i)->GetAmount(); + } + + return modifier; +} + +int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const +{ + int32 modifier = 0; + + AuraEffectList const& mTotalAuraList = GetAuraEffectsByType(auratype); + for (AuraEffectList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i) + { + if ((*i)->GetMiscValue()== misc_value && (*i)->GetAmount() < modifier) + modifier = (*i)->GetAmount(); + } + + return modifier; +} + void Unit::AddDynObject(DynamicObject* dynObj) { m_dynObjGUIDs.push_back(dynObj->GetGUID()); @@ -4727,15 +4925,15 @@ void Unit::ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVic void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo) { - AuraEffect *aura = pInfo->auraEff; + AuraEffect const * aura = pInfo->auraEff; WorldPacket data(SMSG_PERIODICAURALOG, 30); data.append(GetPackGUID()); data.appendPackGUID(aura->GetCasterGUID()); data << uint32(aura->GetId()); // spellId data << uint32(1); // count - data << uint32(aura->GetAuraName()); // auraId - switch(aura->GetAuraName()) + data << uint32(aura->GetAuraType()); // auraId + switch(aura->GetAuraType()) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: @@ -4763,7 +4961,7 @@ void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo) data << float(pInfo->multiplier); // gain multiplier break; default: - sLog.outError("Unit::SendPeriodicAuraLog: unknown aura %u", uint32(aura->GetAuraName())); + sLog.outError("Unit::SendPeriodicAuraLog: unknown aura %u", uint32(aura->GetAuraType())); return; } @@ -4868,8 +5066,8 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger { SpellEntry const *hasteSpell = triggeredByAura->GetSpellProto(); - Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL; + Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; uint32 triggered_spell_id = 0; Unit* target = pVictim; @@ -4931,8 +5129,8 @@ bool Unit::HandleSpellCritChanceAuraProc(Unit *pVictim, uint32 /*damage*/, AuraE { SpellEntry const *triggeredByAuraSpell = triggeredByAura->GetSpellProto(); - Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL; + Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; uint32 triggered_spell_id = 0; Unit* target = pVictim; @@ -4995,25 +5193,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger uint32 effIndex = triggeredByAura->GetEffIndex(); int32 triggerAmount = triggeredByAura->GetAmount(); - Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL; + Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; uint32 triggered_spell_id = 0; Unit* target = pVictim; int32 basepoints0 = 0; uint64 originalCaster = 0; - // Master of subtlety (checked here because ranks have different spellfamilynames) - if (dummySpell->Id == 31223 || dummySpell->Id == 31221 || dummySpell->Id == 31222) - { - if (procEx & AURA_REMOVE_PROC_EX_MASK) - triggered_spell_id = 31666; - else - { - triggered_spell_id = 31665; - basepoints0 = triggerAmount; - } - } switch(dummySpell->SpellFamilyName) { case SPELLFAMILY_GENERIC: @@ -5036,30 +5223,15 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger case 33174: case 33182: { - // Tricky thing here, we find current aura from spell by caster and change its modifier value int32 spelldmg = CalculateSpellDamage(procSpell, 0, procSpell->EffectBasePoints[0],pVictim); if (AuraEffect * Aur = pVictim->GetAuraEffect(procSpell->Id, effIndex+1, triggeredByAura->GetCasterGUID())) { // Remove aura mods - Aur->ApplyModifier(false, false, true); - Aur->SetAmount(Aur->GetAmount() + spelldmg/* * triggerAmount / 100*/); - // Apply extended aura mods - Aur->ApplyModifier(true, false, true); + Aur->ChangeAmount(Aur->GetAmount() + spelldmg); return true; } return false; } - // Overkill - case 58426: - { - if (procEx & AURA_REMOVE_PROC_EX_MASK) - triggered_spell_id = 58428; - else - { - triggered_spell_id = 58427; - } - break; - } // Eye for an Eye case 9799: case 25988: @@ -5106,7 +5278,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger return false; // find Mage Armor - if (!GetAura(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, 0x10000000)) + if (!GetAuraEffect(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT, SPELLFAMILY_MAGE, 0x10000000, 0, 0)) return false; switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) @@ -5175,7 +5347,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger case 33493: { // Cast finish spell at last charge - if (triggeredByAura->GetParentAura()->GetAuraCharges() > 1) + if (triggeredByAura->GetBase()->GetCharges() > 1) return false; target = this; @@ -5453,16 +5625,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger triggered_spell_id = 29077; break; } - // Shattered Barrier - if (dummySpell->SpellIconID == 2945) - { - // only on dispel/remove aura by destroy - target = NULL; - triggered_spell_id = 55080; - CastSpell(target, triggered_spell_id, true, 0, triggeredByAura); - return true; - } - // Arcane Potency if (dummySpell->SpellIconID == 2120) { @@ -5486,7 +5648,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger { if (effIndex!=0) return false; - AuraEffect *counter = triggeredByAura->GetParentAura()->GetPartAura(1); + AuraEffect *counter = triggeredByAura->GetBase()->GetEffect(1); if (!counter) return true; @@ -5568,7 +5730,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger return false; } - AuraEffectList const& DoTAuras = target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + AuraEffectList const& DoTAuras = target->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE); for (Unit::AuraEffectList::const_iterator i = DoTAuras.begin(); i != DoTAuras.end(); ++i) { if ((*i)->GetCasterGUID() != GetGUID() || (*i)->GetId() != 12654 || (*i)->GetEffIndex() != 0) @@ -5588,7 +5750,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger return false; //last charge and crit - if (triggeredByAura->GetParentAura()->GetAuraCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT) ) + if (triggeredByAura->GetBase()->GetCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT) ) { RemoveAurasDueToSpell(28682); //-> remove Combustion auras return true; // charge counting (will removed) @@ -5802,7 +5964,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger case 30296: { // Improved Soul Leech - AuraEffectList const& SoulLeechAuras = GetAurasByType(SPELL_AURA_DUMMY); + AuraEffectList const& SoulLeechAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (Unit::AuraEffectList::const_iterator i = SoulLeechAuras.begin(); i != SoulLeechAuras.end(); ++i) { if ((*i)->GetId()==54117 || (*i)->GetId()==54118) @@ -5818,7 +5980,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger // regen mana for caster CastCustomSpell(this,59117,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); // Get second aura of spell for replenishment effect on party - if (AuraEffect const * aurEff = (*i)->GetParentAura()->GetPartAura(1)) + if (AuraEffect const * aurEff = (*i)->GetBase()->GetEffect(1)) { // Replenishment - roll chance if (roll_chance_i(aurEff->GetAmount())) @@ -5835,22 +5997,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger triggered_spell_id = 30294; break; } - // Improved Fear - case 53754: - { - if(!pVictim || !pVictim->isAlive()) - return false; - pVictim->CastSpell(pVictim, 60946,true, castItem, triggeredByAura); - return true; - } - // Improved Fear (Rank 2) - case 53759: - { - if(!pVictim || !pVictim->isAlive()) - return false; - pVictim->CastSpell(pVictim, 60947,true, castItem, triggeredByAura); - return true; - } // Shadowflame (Voidheart Raiment set bonus) case 37377: { @@ -5940,18 +6086,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger pVictim->CastCustomSpell(pVictim,15290,&team,&self,NULL,true,castItem,triggeredByAura); return true; // no hidden cooldown } - // Shadow Affinity (Ranks 1-3) - case 15318: - case 15272: - case 15320: - { - if (!target) - return false; - - basepoints0 = triggerAmount * target->GetCreateMana() / 100; - triggered_spell_id = 64103; - break; - } // Priest Tier 6 Trinket (Ashtongue Talisman of Acumen) case 40438: { @@ -6002,43 +6136,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger RemoveMovementImpairingAuras(); break; } - // Rapture - case 47535: // Rank 1 1.5% of max mana - case 47536: // Rank 2 2% of max mana - case 47537: // Rank 3 2.5% of max mana - { - // Effect 0 - proc on self - if (effIndex == 0) - { - float multiplier = triggerAmount; - if (dummySpell->Id == 47535) - multiplier -= 0.5f; - else if (dummySpell->Id == 47537) - multiplier += 0.5f; - - basepoints0 = (multiplier * GetMaxPower(POWER_MANA) / 100); - triggered_spell_id = 47755; - target = this; - } - else - { - if (!roll_chance_i(triggerAmount)) - return false; - - switch(pVictim->getPowerType()) - { - target = pVictim; - case POWER_MANA: - triggered_spell_id = 63654; - basepoints0 = 2 * (pVictim->GetMaxPower(POWER_MANA) / 100); - break; - case POWER_RAGE: triggered_spell_id = 63653; break; - case POWER_ENERGY: triggered_spell_id = 63655; break; - case POWER_RUNIC_POWER: triggered_spell_id = 63652; break; - } - } - break; - } // Glyph of Dispel Magic case 55677: { @@ -6306,9 +6403,9 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger { // "refresh your Slice and Dice duration to its 5 combo point maximum" // lookup Slice and Dice - if (AuraEffect const* aur = GetAura(SPELL_AURA_MOD_HASTE, SPELLFAMILY_ROGUE,0x40000, 0, 0)) + if (AuraEffect const* aur = GetAuraEffect(SPELL_AURA_MOD_HASTE, SPELLFAMILY_ROGUE,0x40000, 0, 0)) { - aur->GetParentAura()->SetAuraDuration(GetSpellMaxDuration(aur->GetSpellProto()), true); + aur->GetBase()->SetDuration(GetSpellMaxDuration(aur->GetSpellProto()), true); return true; } return false; @@ -6419,20 +6516,20 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger break; } // Light's Beacon - Beacon of Light - if ( dummySpell->Id == 53651 ) + if (dummySpell->Id == 53651) { - if (Unit *source = triggeredByAura->GetParentAura()->GetUnitSource()) + // Get target of beacon of light + if (Unit * beaconTarget = triggeredByAura->GetBase()->GetCaster()) { // do not proc when target of beacon of light is healed - if (source == this) + if (beaconTarget == this) return false; - if (Unit * caster = triggeredByAura->GetCaster()) + // check if it was heal by paladin which casted this beacon of light + if (Aura const * aura = beaconTarget->GetAura(53563, pVictim->GetGUID())) { - if (caster != pVictim) - return false; basepoints0 = damage; triggered_spell_id = 53654; - target = source; + target = beaconTarget; break; } } @@ -6441,10 +6538,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger // Judgements of the Wise if (dummySpell->SpellIconID == 3017) { - //Mangos code, do not know if we need it - // triggered only at casted Judgement spells, not at additional Judgement effects - //if(!procSpell || procSpell->Category != 1210) - // return; target = this; triggered_spell_id = 31930; // replenishment @@ -6611,7 +6704,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger chance = 15.0f; } // Judgement (any) - else if (GetSpellSpecific(procSpell->Id)==SPELL_JUDGEMENT) + else if (GetSpellSpecific(procSpell->Id) == SPELL_SPECIFIC_JUDGEMENT) { triggered_spell_id = 40472; chance = 50.0f; @@ -6721,7 +6814,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger if( cooldown && ((Player*)this)->HasSpellCooldown(dummySpell->Id)) return false; - if(triggeredByAura->GetParentAura() && castItem->GetGUID() != triggeredByAura->GetParentAura()->GetCastItemGUID()) + if (triggeredByAura->GetBase() && castItem->GetGUID() != triggeredByAura->GetBase()->GetCastItemGUID()) return false; WeaponAttackType attType = WeaponAttackType(((Player*)this)->GetAttackBySlot(castItem->GetSlot())); @@ -6956,7 +7049,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger return false; // Water Shield - if (AuraEffect const * aurEff = GetAura(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0, 0x00000020)) + if (AuraEffect const * aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0, 0x00000020)) { uint32 spell = aurEff->GetSpellProto()->EffectTriggerSpell[aurEff->GetEffIndex()]; CastSpell(this, spell, true, castItem, triggeredByAura); @@ -7034,11 +7127,11 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger if(dummySpell->SpellIconID == 3059) { // Lightning Shield - if (AuraEffect const * aurEff = GetAura(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400)) + if (AuraEffect const * aurEff = GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN, 0x400, 0, 0)) { uint32 spell = spellmgr.GetSpellWithRank(26364, spellmgr.GetSpellRank(aurEff->GetId())); CastSpell(target, spell, true, castItem, triggeredByAura); - aurEff->GetParentAura()->DropAuraCharge(); + aurEff->GetBase()->DropCharge(); return true; } return false; @@ -7319,8 +7412,8 @@ bool Unit::HandleObsModEnergyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* uint32 effIndex = triggeredByAura->GetEffIndex(); int32 triggerAmount = triggeredByAura->GetAmount(); - Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL; + Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; uint32 triggered_spell_id = 0; Unit* target = pVictim; @@ -7376,8 +7469,8 @@ bool Unit::HandleModDamagePctTakenAuraProc(Unit *pVictim, uint32 damage, AuraEff uint32 effIndex = triggeredByAura->GetEffIndex(); int32 triggerAmount = triggeredByAura->GetAmount(); - Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL; + Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; uint32 triggered_spell_id = 0; Unit* target = pVictim; @@ -7432,7 +7525,7 @@ bool Unit::HandleModDamagePctTakenAuraProc(Unit *pVictim, uint32 damage, AuraEff // Used in case when access to whole aura is needed // All procs should be handled like this... -bool Unit::HandleAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool * handled) +bool Unit::HandleAuraProc(Unit *pVictim, uint32 damage, Aura * triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool * handled) { SpellEntry const *dummySpell = triggeredByAura->GetSpellProto(); @@ -7455,11 +7548,11 @@ bool Unit::HandleAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, S // can't proc from death rune use if (rune == RUNE_DEATH) return false; - AuraEffect * aurEff = triggeredByAura->GetPartAura(0); + AuraEffect * aurEff = triggeredByAura->GetEffect(0); if (!aurEff) return false; // Reset amplitude - set death rune remove timer to 30s - aurEff->ResetPeriodicTimer(); + aurEff->ResetPeriodic(); uint32 runesLeft; if (dummySpell->SpellIconID == 2622) @@ -7467,7 +7560,7 @@ bool Unit::HandleAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, S else runesLeft = 1; - for (uint8 i=0; i<MAX_RUNES && runesLeft; ++i) + for (uint8 i=0; i < MAX_RUNES && runesLeft; ++i) { if (dummySpell->SpellIconID == 2622) { @@ -7486,8 +7579,7 @@ bool Unit::HandleAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, S --runesLeft; // Mark aura as used - aurEff->SetAmount(aurEff->GetAmount() | (1<<i)); - ((Player*)this)->ConvertRune(i,RUNE_DEATH); + ((Player*)this)->AddRuneByAuraEffect(i, RUNE_DEATH, aurEff); } return true; } @@ -7524,11 +7616,11 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig Unit* target = NULL; int32 basepoints0 = 0; - if(triggeredByAura->GetAuraName() == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE) + if(triggeredByAura->GetAuraType() == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE) basepoints0 = triggerAmount; - Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL; + Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; // Try handle unknown trigger spells if (sSpellStore.LookupEntry(trigger_spell_id) == NULL) @@ -7618,7 +7710,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig if (auraSpellInfo->SpellFamilyFlags[0] & 0x4000) { // Improved Drain Soul - Unit::AuraEffectList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_DUMMY); + Unit::AuraEffectList const& mAddFlatModifier = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (Unit::AuraEffectList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i) { if ((*i)->GetMiscValue() == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113) @@ -8053,7 +8145,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig // Honor Among Thieves case 52916: { - target = triggeredByAura->GetParentAura()->GetCaster(); + target = triggeredByAura->GetBase()->GetCaster(); if(!target) return false; @@ -8128,7 +8220,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig if (isPet()) if (Unit * owner = GetOwner()) { - if (AuraEffect * aurEff = owner->GetDummyAura(SPELLFAMILY_WARLOCK, 3220, 0)) + if (AuraEffect * aurEff = owner->GetDummyAuraEffect(SPELLFAMILY_WARLOCK, 3220, 0)) { basepoints0 = int32((aurEff->GetAmount() * owner->SpellBaseDamageBonus(SpellSchoolMask(SPELL_SCHOOL_MASK_MAGIC)) + 100.0f) / 100.0f); CastCustomSpell(this,trigger_spell_id,&basepoints0,&basepoints0,NULL,true,castItem,triggeredByAura); @@ -8247,8 +8339,8 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, AuraE if(!pVictim || !pVictim->isAlive()) return false; - Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL; + Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER + ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; uint32 triggered_spell_id = 0; @@ -8869,10 +8961,10 @@ void Unit::ModifyAuraState(AuraState flag, bool apply) if (flag != AURA_STATE_ENRAGE) // enrage aura state triggering continues auras { - Unit::AuraMap& tAuras = GetAuras(); - for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) + Unit::AuraApplicationMap& tAuras = GetAppliedAuras(); + for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();) { - SpellEntry const* spellProto = (*itr).second->GetSpellProto(); + SpellEntry const* spellProto = (*itr).second->GetBase()->GetSpellProto(); if (spellProto->CasterAuraState == flag) RemoveAura(itr); else @@ -8888,7 +8980,7 @@ uint32 Unit::BuildAuraStateUpdateForTarget(Unit * target) const uint32 auraStates = GetUInt32Value(UNIT_FIELD_AURASTATE) &~(PER_CASTER_AURA_STATE_MASK); for (AuraStateAurasMap::const_iterator itr = m_auraStateAuras.begin(); itr != m_auraStateAuras.end(); ++itr) if ((1<<(itr->first-1)) & PER_CASTER_AURA_STATE_MASK) - if (itr->second->GetCasterGUID() == target->GetGUID()) + if (itr->second->GetBase()->GetCasterGUID() == target->GetGUID()) auraStates |= (1<<(itr->first-1)); return auraStates; @@ -8900,9 +8992,9 @@ bool Unit::HasAuraState(AuraState flag, SpellEntry const *spellProto, Unit const { if (spellProto) { - AuraEffectList const& stateAuras = Caster->GetAurasByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); + AuraEffectList const& stateAuras = Caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); for (AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j) - if ((*j)->isAffectedOnSpell(spellProto)) + if ((*j)->IsAffectedOnSpell(spellProto)) return true; } // Check per caster aura state @@ -8910,7 +9002,7 @@ bool Unit::HasAuraState(AuraState flag, SpellEntry const *spellProto, Unit const if ((1<<(flag-1)) & PER_CASTER_AURA_STATE_MASK) { for (AuraStateAurasMap::const_iterator itr = m_auraStateAuras.lower_bound(flag); itr != m_auraStateAuras.upper_bound(flag); ++itr) - if (itr->second->GetCasterGUID() == Caster->GetGUID()) + if (itr->second->GetBase()->GetCasterGUID() == Caster->GetGUID()) return true; return false; } @@ -9279,25 +9371,25 @@ Unit* Unit::SelectMagnetTarget(Unit *victim, SpellEntry const *spellInfo) if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE) return victim; - Unit::AuraEffectList const& magnetAuras = victim->GetAurasByType(SPELL_AURA_SPELL_MAGNET); + Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET); for (Unit::AuraEffectList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr) - if (Unit* magnet = (*itr)->GetParentAura()->GetUnitSource()) + if (Unit* magnet = (*itr)->GetBase()->GetUnitOwner()) if (magnet->isAlive()) { - (*itr)->GetParentAura()->DropAuraCharge(); + (*itr)->GetBase()->DropCharge(); return magnet; } } // Melee && ranged case else { - AuraEffectList const& hitTriggerAuras = victim->GetAurasByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER); + AuraEffectList const& hitTriggerAuras = victim->GetAuraEffectsByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER); for (AuraEffectList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i) - if (Unit* magnet = (*i)->GetParentAura()->GetUnitSource()) + if (Unit* magnet = (*i)->GetBase()->GetUnitOwner()) if (magnet->isAlive() && magnet->IsWithinLOSInMap(this)) if (roll_chance_i((*i)->GetAmount())) { - (*i)->GetParentAura()->DropAuraCharge(); + (*i)->GetBase()->DropCharge(); return magnet; } } @@ -9505,7 +9597,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 if (GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet()) DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank); - AuraEffectList const &mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + AuraEffectList const &mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) if (((*i)->GetMiscValue() & GetSpellSchoolMask(spellProto)) && (*i)->GetSpellProto()->EquippedItemClass == -1 && // -1 == any item class (not wand) @@ -9515,17 +9607,17 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); // Add flat bonus from spell damage versus DoneTotal += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask); - AuraEffectList const &mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); + AuraEffectList const &mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i) if (creatureTypeMask & uint32((*i)->GetMiscValue())) DoneTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; // done scripted mod (take it from owner) Unit *owner = GetOwner() ? GetOwner() : this; - AuraEffectList const &mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + AuraEffectList const &mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { - if (!(*i)->isAffectedOnSpell(spellProto)) + if (!(*i)->IsAffectedOnSpell(spellProto)) continue; switch ((*i)->GetMiscValue()) { @@ -9549,13 +9641,14 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 int32 stepPercent = CalculateSpellDamage((*i)->GetSpellProto(), 0, (*i)->GetSpellProto()->EffectBasePoints[0], this); // count affliction effects and calc additional damage in percentage int32 modPercent = 0; - AuraMap const &victimAuras = pVictim->GetAuras(); - for (AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) + AuraApplicationMap const &victimAuras = pVictim->GetAppliedAuras(); + for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) { - SpellEntry const *m_spell = itr->second->GetSpellProto(); + Aura const * aura = itr->second->GetBase(); + SpellEntry const *m_spell = aura->GetSpellProto(); if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK || !(m_spell->SpellFamilyFlags[1] & 0x0004071B || m_spell->SpellFamilyFlags[0] & 0x8044C402)) continue; - modPercent += stepPercent * itr->second->GetStackAmount(); + modPercent += stepPercent * aura->GetStackAmount(); if (modPercent >= maxPercent) { modPercent = maxPercent; @@ -9573,7 +9666,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 break; case 5481: // Starfire Bonus { - if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002, 0)) + if (pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002, 0, 0)) DoneTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; break; } @@ -9611,7 +9704,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 // Rage of Rivendare case 7293: { - if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0,0x02000000,0)) + if (pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0,0x02000000,0)) { if (SpellChainNode const *chain = spellmgr.GetSpellChainNode((*i)->GetId())) DoneTotalMod *= (chain->rank * 2.0f + 100.0f)/100.0f; @@ -9621,7 +9714,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 // Twisted Faith case 7377: { - if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0,0, GetGUID())) + if (pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0,0, GetGUID())) DoneTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; break; } @@ -9632,7 +9725,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 case 7601: case 7602: { - if (pVictim->GetAura(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400, 0)) + if (pVictim->GetAuraEffect(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400, 0, 0)) DoneTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; break; } @@ -9660,7 +9753,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 if (spellProto->SpellFamilyFlags[0]&0x20200021 || spellProto->SpellFamilyFlags[1]& 0x9000) if (pVictim->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED)) { - AuraEffectList const& mDumyAuras = GetAurasByType(SPELL_AURA_DUMMY); + AuraEffectList const& mDumyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (AuraEffectList::const_iterator i = mDumyAuras.begin(); i != mDumyAuras.end(); ++i) if ((*i)->GetSpellProto()->SpellIconID == 3263) { @@ -9676,7 +9769,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 // Increase Mind Flay damage if (AuraEffect * aurEff = GetAuraEffect(55687, 0)) // if Shadow Word: Pain present - if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0,0, GetGUID())) + if (pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0,0, GetGUID())) DoneTotalMod *= (aurEff->GetAmount() + 100.0f) / 100.f; } break; @@ -9687,11 +9780,11 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 { // Get stack of Holy Vengeance/Blood Corruption on the target added by caster uint32 stacks = 0; - Unit::AuraEffectList const& auras = pVictim->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + Unit::AuraEffectList const& auras = pVictim->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE); for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) if (((*itr)->GetId() == 31803 || (*itr)->GetId() == 53742) && (*itr)->GetCasterGUID()==GetGUID()) { - stacks = (*itr)->GetParentAura()->GetStackAmount(); + stacks = (*itr)->GetBase()->GetStackAmount(); break; } // + 10% for each application of Holy Vengeance/Blood Corruption on the target @@ -9704,7 +9797,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 if (spellProto->SpellFamilyFlags[1] & 0x00020040) if (pVictim->HasAuraState(AURA_STATE_CONFLAGRATE)) { - AuraEffectList const& mDumyAuras = GetAurasByType(SPELL_AURA_DUMMY); + AuraEffectList const& mDumyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY); for (AuraEffectList::const_iterator i = mDumyAuras.begin(); i != mDumyAuras.end(); ++i) if ((*i)->GetSpellProto()->SpellIconID == 3173) { @@ -9716,29 +9809,29 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 case SPELLFAMILY_DEATHKNIGHT: // Improved Icy Touch if (spellProto->SpellFamilyFlags[0] & 0x2) - if (AuraEffect * aurEff = GetDummyAura(SPELLFAMILY_DEATHKNIGHT, 2721, 0)) + if (AuraEffect * aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2721, 0)) DoneTotalMod *= (100.0f + aurEff->GetAmount()) / 100.0f; // Glacier Rot if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6) - if (AuraEffect * aurEff = GetDummyAura(SPELLFAMILY_DEATHKNIGHT, 196, 0)) + if (AuraEffect * aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0)) if (pVictim->GetDiseasesByCaster(owner->GetGUID()) > 0) DoneTotalMod *= (100.0f + aurEff->GetAmount()) / 100.0f; // This is not a typo - Impurity has SPELLFAMILY_DRUID - if (AuraEffect * aurEff = GetDummyAura(SPELLFAMILY_DRUID, 1986, 0)) + if (AuraEffect * aurEff = GetDummyAuraEffect(SPELLFAMILY_DRUID, 1986, 0)) ApCoeffMod *= (100.0f + aurEff->GetAmount()) / 100.0f; break; } // ..taken - AuraEffectList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + AuraEffectList const& mModDamagePercentTaken = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); for (AuraEffectList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) if ((*i)->GetMiscValue() & GetSpellSchoolMask(spellProto) ) TakenTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; // .. taken pct: dummy auras - AuraEffectList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + AuraEffectList const& mDummyAuras = pVictim->GetAuraEffectsByType(SPELL_AURA_DUMMY); for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) { switch((*i)->GetSpellProto()->SpellIconID) @@ -9764,15 +9857,15 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 } // From caster spells - AuraEffectList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); + AuraEffectList const& mOwnerTaken = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) - if ((*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto)) + if ((*i)->GetCasterGUID() == GetGUID() && (*i)->IsAffectedOnSpell(spellProto)) TakenTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; // Mod damage from spell mechanic if (uint32 mechanicMask = GetAllSpellMechanicMask(spellProto)) { - AuraEffectList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); + AuraEffectList const& mDamageDoneMechanic = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i) if (mechanicMask & uint32(1<<((*i)->GetMiscValue()))) TakenTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; @@ -9892,7 +9985,7 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask) int32 DoneAdvertisedBenefit = 0; // ..done - AuraEffectList const& mDamageDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE); + AuraEffectList const& mDamageDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE); for (AuraEffectList::const_iterator i = mDamageDone.begin(); i != mDamageDone.end(); ++i) if (((*i)->GetMiscValue() & schoolMask) != 0 && (*i)->GetSpellProto()->EquippedItemClass == -1 && @@ -9907,18 +10000,18 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask) DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellPowerBonus(); // Damage bonus from stats - AuraEffectList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT); + AuraEffectList const& mDamageDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mDamageDoneOfStatPercent.begin(); i != mDamageDoneOfStatPercent.end(); ++i) { if ((*i)->GetMiscValue() & schoolMask) { // stat used stored in miscValueB for this aura - Stats usedStat = Stats((*i)->GetMiscBValue()); + Stats usedStat = Stats((*i)->GetMiscValueB()); DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetAmount() / 100.0f); } } // ... and attack power - AuraEffectList const& mDamageDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER); + AuraEffectList const& mDamageDonebyAP = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER); for (AuraEffectList::const_iterator i =mDamageDonebyAP.begin(); i != mDamageDonebyAP.end(); ++i) if ((*i)->GetMiscValue() & schoolMask) DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetAmount() / 100.0f); @@ -9933,13 +10026,13 @@ int32 Unit::SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVic int32 TakenAdvertisedBenefit = 0; // ..done (for creature type by mask) in taken - AuraEffectList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); + AuraEffectList const& mDamageDoneCreature = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); for (AuraEffectList::const_iterator i = mDamageDoneCreature.begin(); i != mDamageDoneCreature.end(); ++i) if (creatureTypeMask & uint32((*i)->GetMiscValue())) TakenAdvertisedBenefit += (*i)->GetAmount(); // ..taken - AuraEffectList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN); + AuraEffectList const& mDamageTaken = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN); for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i) if (((*i)->GetMiscValue() & schoolMask) != 0) TakenAdvertisedBenefit += (*i)->GetAmount(); @@ -9984,10 +10077,10 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM crit_chance -= pVictim->GetSpellCritChanceReduction(); } // scripted (increase crit chance ... against ... target by x% - AuraEffectList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + AuraEffectList const& mOverrideClassScript = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { - if (!((*i)->isAffectedOnSpell(spellProto))) + if (!((*i)->IsAffectedOnSpell(spellProto))) continue; int32 modChance=0; switch((*i)->GetMiscValue()) @@ -10027,8 +10120,8 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM if (spellProto->SpellFamilyFlags[0] & 0x4 && spellProto->SpellIconID == 1485) { // Improved Insect Swarm - if (AuraEffect const * aurEff = GetDummyAura(SPELLFAMILY_DRUID, 1771, 0)) - if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00000002)) + if (AuraEffect const * aurEff = GetDummyAuraEffect(SPELLFAMILY_DRUID, 1771, 0)) + if (pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x00000002, 0, 0)) crit_chance+=aurEff->GetAmount(); break; } @@ -10055,7 +10148,7 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM // Lava Burst if (spellProto->SpellFamilyFlags[1] & 0x00001000) { - if (AuraEffect const* flameShock = pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0,0, GetGUID())) + if (AuraEffect const* flameShock = pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0,0, GetGUID())) return true; break; } @@ -10074,7 +10167,7 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM // Rend and Tear - bonus crit chance for bleeding targets of Ferocious Bite if (spellProto->SpellFamilyFlags[0] & 0x00800000 && pVictim->HasAuraState(AURA_STATE_BLEEDING, spellProto, this)) { - if (AuraEffect const *rendAndTear = GetDummyAura(SPELLFAMILY_DRUID, 2859, 1)) + if (AuraEffect const *rendAndTear = GetDummyAuraEffect(SPELLFAMILY_DRUID, 2859, 1)) crit_chance += rendAndTear->GetAmount(); break; } @@ -10187,16 +10280,16 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint int32 TakenTotal = 0; // Healing done percent - AuraEffectList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); + AuraEffectList const& mHealingDonePct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); for (AuraEffectList::const_iterator i = mHealingDonePct.begin(); i != mHealingDonePct.end(); ++i) DoneTotalMod *= (100.0f + (*i)->GetAmount()) / 100.0f; // done scripted mod (take it from owner) Unit *owner = GetOwner() ? GetOwner() : this; - AuraEffectList const &mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + AuraEffectList const &mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { - if (!(*i)->isAffectedOnSpell(spellProto)) + if (!(*i)->IsAffectedOnSpell(spellProto)) continue; switch((*i)->GetMiscValue()) { @@ -10218,7 +10311,7 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint break; case 7798: // Glyph of Regrowth { - if (pVictim->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0)) + if (pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0)) DoneTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; break; } @@ -10226,23 +10319,24 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint { int32 stepPercent = (*i)->GetAmount(); int32 modPercent = 0; - AuraMap const& victimAuras = pVictim->GetAuras(); - for (AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) + AuraApplicationMap const& victimAuras = pVictim->GetAppliedAuras(); + for (AuraApplicationMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) { - if (itr->second->GetCasterGUID()!=GetGUID()) + Aura const * aura = itr->second->GetBase(); + if (aura->GetCasterGUID()!=GetGUID()) continue; - SpellEntry const* m_spell = itr->second->GetSpellProto(); + SpellEntry const* m_spell = aura->GetSpellProto(); if ( m_spell->SpellFamilyName != SPELLFAMILY_DRUID || !(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50)) continue; - modPercent += stepPercent * itr->second->GetStackAmount(); + modPercent += stepPercent * aura->GetStackAmount(); } DoneTotalMod *= (modPercent+100.0f)/100.0f; break; } case 7871: // Glyph of Lesser Healing Wave { - if (pVictim->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0 , 0x00000400, 0, GetGUID())) + if (pVictim->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0 , 0x00000400, 0, GetGUID())) DoneTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; break; } @@ -10392,7 +10486,7 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint if (spellProto->SpellFamilyName == SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags[1] & 0x2000000) { // Rejuvenation, Regrowth, Lifebloom, or Wild Growth - if (pVictim->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x50, 0x4000010, 0)) + if (pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x50, 0x4000010, 0)) //increase healing by 20% TakenTotalMod *= 1.2f; } @@ -10433,9 +10527,9 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint TakenTotalMod *= (100.0f + maxval_hot) / 100.0f; } - AuraEffectList const& mHealingGet= pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED); + AuraEffectList const& mHealingGet= pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_RECEIVED); for (AuraEffectList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i) - if (GetGUID()==(*i)->GetCasterGUID() && (*i)->isAffectedOnSpell(spellProto) ) + if (GetGUID()==(*i)->GetCasterGUID() && (*i)->IsAffectedOnSpell(spellProto) ) TakenTotalMod *= ((*i)->GetAmount() + 100.0f) / 100.0f; heal = (int32(heal) + TakenTotal) * TakenTotalMod; @@ -10447,7 +10541,7 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask) { int32 AdvertisedBenefit = 0; - AuraEffectList const& mHealingDone = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE); + AuraEffectList const& mHealingDone = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE); for (AuraEffectList::const_iterator i = mHealingDone.begin(); i != mHealingDone.end(); ++i) if (((*i)->GetMiscValue() & schoolMask) != 0) AdvertisedBenefit += (*i)->GetAmount(); @@ -10459,7 +10553,7 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask) AdvertisedBenefit +=((Player*)this)->GetBaseSpellPowerBonus(); // Healing bonus from stats - AuraEffectList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT); + AuraEffectList const& mHealingDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mHealingDoneOfStatPercent.begin(); i != mHealingDoneOfStatPercent.end(); ++i) { // stat used dependent from misc value (stat index) @@ -10468,7 +10562,7 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask) } // ... and attack power - AuraEffectList const& mHealingDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER); + AuraEffectList const& mHealingDonebyAP = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER); for (AuraEffectList::const_iterator i = mHealingDonebyAP.begin(); i != mHealingDonebyAP.end(); ++i) if ((*i)->GetMiscValue() & schoolMask) AdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetAmount() / 100.0f); @@ -10479,7 +10573,7 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask) int32 Unit::SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim) { int32 AdvertisedBenefit = 0; - AuraEffectList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING); + AuraEffectList const& mDamageTaken = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_HEALING); for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i) if (((*i)->GetMiscValue() & schoolMask) != 0) AdvertisedBenefit += (*i)->GetAmount(); @@ -10590,7 +10684,7 @@ bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) con if (itr->type == aura) return true; // Check for immune to application of harmful magical effects - AuraEffectList const& immuneAuraApply = GetAurasByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL); + AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL); for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter) if (spellInfo->Dispel == DISPEL_MAGIC && // Magic debuff ((*iter)->GetMiscValue() & GetSpellSchoolMask(spellInfo)) && // Check school @@ -10640,7 +10734,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att int32 TakenFlatBenefit = 0; // ..done (for creature type by mask) in taken - AuraEffectList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); + AuraEffectList const& mDamageDoneCreature = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); for (AuraEffectList::const_iterator i = mDamageDoneCreature.begin(); i != mDamageDoneCreature.end(); ++i) if (creatureTypeMask & uint32((*i)->GetMiscValue())) DoneFlatBenefit += (*i)->GetAmount(); @@ -10655,7 +10749,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS); // ..done (base at attack power and creature type) - AuraEffectList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS); + AuraEffectList const& mCreatureAttackPower = GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS); for (AuraEffectList::const_iterator i = mCreatureAttackPower.begin(); i != mCreatureAttackPower.end(); ++i) if (creatureTypeMask & uint32((*i)->GetMiscValue())) APbonus += (*i)->GetAmount(); @@ -10665,7 +10759,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS); // ..done (base at attack power and creature type) - AuraEffectList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS); + AuraEffectList const& mCreatureAttackPower = GetAuraEffectsByType(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS); for (AuraEffectList::const_iterator i = mCreatureAttackPower.begin(); i != mCreatureAttackPower.end(); ++i) if (creatureTypeMask & uint32((*i)->GetMiscValue())) APbonus += (*i)->GetAmount(); @@ -10683,14 +10777,14 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att } // This is not a typo - Impurity has SPELLFAMILY_DRUID - if (AuraEffect const * aurEff = GetDummyAura(SPELLFAMILY_DRUID, 1986, 0)) + if (AuraEffect const * aurEff = GetDummyAuraEffect(SPELLFAMILY_DRUID, 1986, 0)) APbonus *= (100.0f + aurEff->GetAmount()) / 100.0f; DoneFlatBenefit += int32(APbonus/14.0f * GetAPMultiplier(attType,normalized)); } // ..taken - AuraEffectList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN); + AuraEffectList const& mDamageTaken = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_TAKEN); for (AuraEffectList::const_iterator i = mDamageTaken.begin(); i != mDamageTaken.end(); ++i) if ((*i)->GetMiscValue() & GetMeleeDamageSchoolMask()) TakenFlatBenefit += (*i)->GetAmount(); @@ -10712,23 +10806,23 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att if (spellProto) if (GetSpellSchoolMask(spellProto) != SPELL_SCHOOL_MASK_NORMAL) { - AuraEffectList const &mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + AuraEffectList const &mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) if (((*i)->GetMiscValue() & GetSpellSchoolMask(spellProto)) && !((*i)->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) DoneTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; } - AuraEffectList const &mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); + AuraEffectList const &mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i) if (creatureTypeMask & uint32((*i)->GetMiscValue())) DoneTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; // done scripted mod (take it from owner) Unit *owner = GetOwner() ? GetOwner() : this; - AuraEffectList const &mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + AuraEffectList const &mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { - if (!(*i)->isAffectedOnSpell(spellProto)) + if (!(*i)->IsAffectedOnSpell(spellProto)) continue; switch ((*i)->GetMiscValue()) { @@ -10754,7 +10848,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att // Rage of Rivendare case 7293: { - if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0,0x02000000,0)) + if (pVictim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0,0x02000000,0)) if (SpellChainNode const *chain = spellmgr.GetSpellChainNode((*i)->GetId())) DoneTotalMod *= (chain->rank * 2.0f + 100.0f)/100.0f; break; @@ -10769,14 +10863,14 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att case SPELLFAMILY_DEATHKNIGHT: // Glacier Rot if (spellProto->SpellFamilyFlags[0] & 0x2 || spellProto->SpellFamilyFlags[1] & 0x6) - if (AuraEffect * aurEff = GetDummyAura(SPELLFAMILY_DEATHKNIGHT, 196, 0)) + if (AuraEffect * aurEff = GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 196, 0)) if (pVictim->GetDiseasesByCaster(owner->GetGUID()) > 0) DoneTotalMod *= (100.0f + aurEff->GetAmount()) / 100.0f; break; } // ..taken - AuraEffectList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + AuraEffectList const& mModDamagePercentTaken = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); for (AuraEffectList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) if ((*i)->GetMiscValue() & GetMeleeDamageSchoolMask()) TakenTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; @@ -10793,7 +10887,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att if (mechanicMask) { - AuraEffectList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); + AuraEffectList const& mDamageDoneMechanic = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT); for (AuraEffectList::const_iterator i = mDamageDoneMechanic.begin(); i != mDamageDoneMechanic.end(); ++i) if (mechanicMask & uint32(1<<((*i)->GetMiscValue()))) TakenTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; @@ -10801,7 +10895,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att } // .. taken pct: dummy auras - AuraEffectList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + AuraEffectList const& mDummyAuras = pVictim->GetAuraEffectsByType(SPELL_AURA_DUMMY); for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) { switch((*i)->GetSpellProto()->SpellIconID) @@ -10839,7 +10933,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att } // .. taken pct: class scripts - AuraEffectList const& mclassScritAuras = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + AuraEffectList const& mclassScritAuras = GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffectList::const_iterator i = mclassScritAuras.begin(); i != mclassScritAuras.end(); ++i) { switch((*i)->GetMiscValue()) @@ -10847,7 +10941,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att case 6427: case 6428: // Dirty Deeds if (pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this)) { - AuraEffect* eff0 = (*i)->GetParentAura()->GetPartAura(0); + AuraEffect* eff0 = (*i)->GetBase()->GetEffect(0); if (!eff0 || (*i)->GetEffIndex()!=1) { sLog.outError("Spell structure of DD (%u) changed.",(*i)->GetId()); @@ -10863,13 +10957,13 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage, WeaponAttackType att if (attType != RANGED_ATTACK) { - AuraEffectList const& mModMeleeDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT); + AuraEffectList const& mModMeleeDamageTakenPercent = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT); for (AuraEffectList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i) TakenTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; } else { - AuraEffectList const& mModRangedDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT); + AuraEffectList const& mModRangedDamageTakenPercent = pVictim->GetAuraEffectsByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT); for (AuraEffectList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i) TakenTotalMod *= ((*i)->GetAmount()+100.0f)/100.0f; } @@ -10928,10 +11022,10 @@ void Unit::ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType ty // Create dispel mask by dispel type uint32 dispelMask = GetDispellMask(type); // Dispel all existing auras vs current dispel type - AuraMap& auras = GetAuras(); - for (AuraMap::iterator itr = auras.begin(); itr != auras.end();) + AuraApplicationMap& auras = GetAppliedAuras(); + for (AuraApplicationMap::iterator itr = auras.begin(); itr != auras.end();) { - SpellEntry const* spell = itr->second->GetSpellProto(); + SpellEntry const* spell = itr->second->GetBase()->GetSpellProto(); if ((1<<spell->Dispel) & dispelMask ) { // Dispel aura @@ -11302,7 +11396,7 @@ bool Unit::canDetectInvisibilityOf(Unit const* u) const { if (m_invisibilityMask & u->m_invisibilityMask) // same group return true; - AuraEffectList const& auras = u->GetAurasByType(SPELL_AURA_MOD_STALKED); // Hunter mark + AuraEffectList const& auras = u->GetAuraEffectsByType(SPELL_AURA_MOD_STALKED); // Hunter mark for (AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) if ((*iter)->GetCasterGUID()==GetGUID()) return true; @@ -11316,7 +11410,7 @@ bool Unit::canDetectInvisibilityOf(Unit const* u) const // find invisibility level uint32 invLevel = 0; - Unit::AuraEffectList const& iAuras = u->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); + Unit::AuraEffectList const& iAuras = u->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY); for (Unit::AuraEffectList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr) if (((*itr)->GetMiscValue())==i && invLevel < (*itr)->GetAmount()) invLevel = (*itr)->GetAmount(); @@ -11329,7 +11423,7 @@ bool Unit::canDetectInvisibilityOf(Unit const* u) const } else { - Unit::AuraEffectList const& dAuras = GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); + Unit::AuraEffectList const& dAuras = GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); for (Unit::AuraEffectList::const_iterator itr = dAuras.begin(); itr != dAuras.end(); ++itr) if (((*itr)->GetMiscValue())==i && detectLevel < (*itr)->GetAmount()) detectLevel = (*itr)->GetAmount(); @@ -11354,7 +11448,7 @@ bool Unit::canDetectStealthOf(Unit const* target, float distance) const if (HasAuraType(SPELL_AURA_DETECT_STEALTH)) return true; - AuraEffectList const &auras = target->GetAurasByType(SPELL_AURA_MOD_STALKED); // Hunter mark + AuraEffectList const &auras = target->GetAuraEffectsByType(SPELL_AURA_MOD_STALKED); // Hunter mark for (AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) if ((*iter)->GetCasterGUID() == GetGUID()) return true; @@ -11818,7 +11912,7 @@ Unit* Creature::SelectVictim() Unit* target = NULL; // First checking if we have some taunt on us - const AuraEffectList& tauntAuras = GetAurasByType(SPELL_AURA_MOD_TAUNT); + const AuraEffectList& tauntAuras = GetAuraEffectsByType(SPELL_AURA_MOD_TAUNT); if (!tauntAuras.empty()) { Unit* caster; @@ -11910,9 +12004,9 @@ Unit* Creature::SelectVictim() if (m_invisibilityMask) { - Unit::AuraEffectList const& iAuras = GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); + Unit::AuraEffectList const& iAuras = GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY); for (Unit::AuraEffectList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr) - if ((*itr)->GetParentAura()->IsPermanent()) + if ((*itr)->GetBase()->IsPermanent()) { AI()->EnterEvadeMode(); break; @@ -12711,6 +12805,8 @@ void Unit::RemoveFromWorld() UnsummonAllTotems(); RemoveAllControlled(); + RemoveAreaAurasDueToLeaveWorld(); + if (m_NotifyListPos >= 0) GetMap()->RemoveUnitFromNotify(this); @@ -13222,13 +13318,12 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit * pTarget, uint32 procFlag, ProcTriggeredList procTriggered; // Fill procTriggered list - for (AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr) + for (AuraApplicationMap::const_iterator itr = GetAppliedAuras().begin(); itr!= GetAppliedAuras().end(); ++itr) { // Do not allow auras to proc from effect triggered by itself if (procAura && procAura->Id == itr->first) continue; - ProcTriggeredData triggerData(itr->second); - + ProcTriggeredData triggerData(itr->second->GetBase()); // Defensive procs are active on absorbs (so absorption effects are not a hindrance) bool active = (damage > 0) || ((procExtra & PROC_EX_ABSORB) && isVictim); if (!IsTriggeredAtSpellProcEvent(pTarget, triggerData.aura, procSpell, procFlag, procExtra, attType, isVictim, active, triggerData.spellProcEvent)) @@ -13236,17 +13331,18 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit * pTarget, uint32 procFlag, for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (AuraEffect * aurEff = itr->second->GetPartAura(i)) + if (itr->second->HasEffect(i)) { + AuraEffect * aurEff = itr->second->GetBase()->GetEffect(i); // Skip this auras - if (isNonTriggerAura[aurEff->GetAuraName()]) + if (isNonTriggerAura[aurEff->GetAuraType()]) continue; // If not trigger by default and spellProcEvent==NULL - skip - if (!isTriggerAura[aurEff->GetAuraName()] && triggerData.spellProcEvent==NULL) + if (!isTriggerAura[aurEff->GetAuraType()] && triggerData.spellProcEvent==NULL) continue; uint32 triggered_spell_id = aurEff->GetSpellProto()->EffectTriggerSpell[i]; // check for positive auras that proc with charge drop - bool positive = (!triggered_spell_id && IsPositiveSpell(aurEff->GetId()) && aurEff->GetParentAura()->GetAuraCharges()) || + bool positive = (!triggered_spell_id && IsPositiveSpell(aurEff->GetId()) && aurEff->GetBase()->GetCharges()) || // check for positive auras that triggers unknown spells (Blessing Recovery, etc...) (!sSpellStore.LookupEntry(triggered_spell_id) && IsPositiveSpell(aurEff->GetId())) || // final check for positive triggered spell @@ -13271,10 +13367,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit * pTarget, uint32 procFlag, for (ProcTriggeredList::const_iterator i = procTriggered.begin(); i != procTriggered.end(); ++i) { // look for aura in auras list, it may be removed while proc event processing - if (!HasAura(i->aura)) + if (i->aura->IsRemoved()) continue; - bool useCharges= i->aura->GetAuraCharges()>0; + bool useCharges= i->aura->GetCharges()>0; bool takeCharges = false; SpellEntry const *spellInfo = i->aura->GetSpellProto(); uint32 Id = i->aura->GetId(); @@ -13301,10 +13397,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit * pTarget, uint32 procFlag, if (!(i->effMask & (1<<effIndex))) continue; - AuraEffect *triggeredByAura = i->aura->GetPartAura(effIndex); + AuraEffect *triggeredByAura = i->aura->GetEffect(effIndex); assert(triggeredByAura); - switch(triggeredByAura->GetAuraName()) + switch(triggeredByAura->GetAuraType()) { case SPELL_AURA_PROC_TRIGGER_SPELL: { @@ -13433,12 +13529,12 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit * pTarget, uint32 procFlag, { // Damage is dealt after proc system - lets ignore auras which wasn't updated yet // to make spell not remove its own aura - if (i->aura->GetAuraDuration() == i->aura->GetAuraMaxDuration()) + if (i->aura->GetDuration() == i->aura->GetMaxDuration()) break; int32 damageLeft = triggeredByAura->GetAmount(); // No damage left if (damageLeft < damage ) - RemoveAura(i->aura); + i->aura->Remove(); else triggeredByAura->SetAmount(damageLeft-damage); } @@ -13455,7 +13551,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit * pTarget, uint32 procFlag, } // Remove charge (aura can be removed by triggers) if (useCharges && takeCharges) - i->aura->DropAuraCharge(); + i->aura->DropCharge(); if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_DISABLE_PROC) SetCantProc(false); @@ -13598,7 +13694,7 @@ void Unit::SetStandState(uint8 state) bool Unit::IsPolymorphed() const { - return GetSpellSpecific(getTransForm())==SPELL_MAGE_POLYMORPH; + return GetSpellSpecific(getTransForm())==SPELL_SPECIFIC_MAGE_POLYMORPH; } void Unit::SetDisplayId(uint32 modelId) @@ -13718,16 +13814,6 @@ Unit* Unit::SelectNearbyTarget(float dist) const return *tcIter; } -bool Unit::hasNegativeAuraWithInterruptFlag(uint32 flag) -{ - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ++iter) - { - if (!iter->second->IsPositive() && iter->second->GetSpellProto()->AuraInterruptFlags & flag) - return true; - } - return false; -} - void Unit::ApplyAttackTimePercentMod( WeaponAttackType att,float val, bool apply ) { float remainingTimePct = (float)m_attackTimer[att] / (GetAttackTime(att) * m_modAttackSpeedPct[att]); @@ -13895,21 +13981,6 @@ float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) } } -AuraEffect* Unit::GetAuraEffect(AuraType type, SpellFamilyNames name, uint32 iconId, uint8 effIndex) const -{ - Unit::AuraEffectList const& mDummy = GetAurasByType(type); - for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr) - { - if (effIndex != (*itr)->GetEffIndex()) - continue; - SpellEntry const * spell = (*itr)->GetSpellProto(); - if (spell->SpellIconID == iconId && spell->SpellFamilyName == name - && !spell->SpellFamilyFlags) - return *itr; - } - return NULL; -} - bool Unit::IsUnderLastManaUseEffect() const { return getMSTimeDiff(m_lastManaUse,getMSTime()) < 5000; @@ -14101,14 +14172,21 @@ bool Unit::HandleAuraRaidProcFromChargeWithValue(AuraEffect *triggeredByAura) int32 heal = triggeredByAura->GetAmount(); uint64 caster_guid = triggeredByAura->GetCasterGUID(); + //Currently only Prayer of Mending + if (!(spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && spellProto->SpellFamilyFlags[1] & 0x20)) + { + sLog.outDebug("Unit::HandleAuraRaidProcFromChargeWithValue, received not handled spell: %u", spellProto->Id); + return false; + } + // jumps - int32 jumps = triggeredByAura->GetParentAura()->GetAuraCharges()-1; + int32 jumps = triggeredByAura->GetBase()->GetCharges()-1; // current aura expire - triggeredByAura->GetParentAura()->SetAuraCharges(1); // will removed at next charges decrease + triggeredByAura->GetBase()->SetCharges(1); // will removed at next charges decrease // next target selection - if (jumps > 0 && IS_PLAYER_GUID(caster_guid)) + if (jumps > 0) { float radius; if (spellProto->EffectRadiusIndex[effIdx]) @@ -14116,15 +14194,16 @@ bool Unit::HandleAuraRaidProcFromChargeWithValue(AuraEffect *triggeredByAura) else radius = GetSpellMaxRangeForTarget(triggeredByAura->GetCaster(), sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); - if (Player *caster = (Player*)triggeredByAura->GetCaster()) + if (Unit * caster = triggeredByAura->GetCaster()) { - caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius, NULL); + if (Player * modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius, NULL); if (Unit *target = GetNextRandomRaidMemberOrPet(radius)) { - CastCustomSpell(target, spellProto->Id, &heal, NULL, NULL, true, NULL, triggeredByAura, caster->GetGUID()); - if (Aura *aur = target->GetAura(spellProto->Id, caster->GetGUID())) - aur->SetAuraCharges(jumps); + CastCustomSpell(target, spellProto->Id, &heal, NULL, NULL, true, NULL, triggeredByAura, caster_guid); + if (Aura * aura = target->GetAura(spellProto->Id, caster->GetGUID())) + aura->SetCharges(jumps); heal = caster->SpellHealingBonus(this, spellProto, heal, HEAL); } } @@ -14158,24 +14237,17 @@ bool Unit::HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura) return false; } - //Currently only Prayer of Mending - if (!(spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && spellProto->SpellFamilyFlags[1] & 0x20)) - { - sLog.outDebug("Unit::HandleAuraRaidProcFromChargeWithValue, received not handled spell: %u", spellProto->Id); - return false; - } - uint64 caster_guid = triggeredByAura->GetCasterGUID(); uint32 effIdx = triggeredByAura->GetEffIndex(); // jumps - int32 jumps = triggeredByAura->GetParentAura()->GetAuraCharges()-1; + int32 jumps = triggeredByAura->GetBase()->GetCharges()-1; // current aura expire - triggeredByAura->GetParentAura()->SetAuraCharges(1); // will removed at next charges decrease + triggeredByAura->GetBase()->SetCharges(1); // will removed at next charges decrease // next target selection - if (jumps > 0 && IS_PLAYER_GUID(caster_guid)) + if (jumps > 0) { float radius; if (spellProto->EffectRadiusIndex[effIdx]) @@ -14183,15 +14255,16 @@ bool Unit::HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura) else radius = GetSpellMaxRangeForTarget(triggeredByAura->GetCaster() ,sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); - if (Player* caster = ((Player*)triggeredByAura->GetCaster())) + if (Unit * caster = triggeredByAura->GetCaster()) { - caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL); + if (Player * modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius, NULL); if (Unit* target= GetNextRandomRaidMemberOrPet(radius)) { CastSpell(target, spellProto, true,NULL,triggeredByAura,caster_guid); - if (Aura * aur = target->GetAura(spellProto->Id, caster->GetGUID())) - aur->SetAuraCharges(jumps); + if (Aura * aura = target->GetAura(spellProto->Id, caster->GetGUID())) + aura->SetCharges(jumps); } } } @@ -14267,7 +14340,7 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss) bool SpiritOfRedemption = false; if (pVictim->GetTypeId() == TYPEID_PLAYER && pVictim->getClass() == CLASS_PRIEST) { - AuraEffectList const& vDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + AuraEffectList const& vDummyAuras = pVictim->GetAuraEffectsByType(SPELL_AURA_DUMMY); for (AuraEffectList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr) { if ((*itr)->GetSpellProto()->SpellIconID==1654) @@ -14542,7 +14615,7 @@ void Unit::SetFeared(bool apply) SetUInt64Value(UNIT_FIELD_TARGET, 0); Unit *caster = NULL; - Unit::AuraEffectList const& fearAuras = GetAurasByType(SPELL_AURA_MOD_FEAR); + Unit::AuraEffectList const& fearAuras = GetAuraEffectsByType(SPELL_AURA_MOD_FEAR); if (!fearAuras.empty()) caster = ObjectAccessor::GetUnit(*this, fearAuras.front()->GetCasterGUID()); if (!caster) @@ -15003,124 +15076,49 @@ void Unit::GetPartyMembers(std::list<Unit*> &TagUnitMap) } } -void Unit::HandleAuraEffect(AuraEffect * aureff, bool apply) +Aura * Unit::AddAura(uint32 spellId, Unit *target) { - if (aureff->GetParentAura()->IsRemoved()) - return; - - sLog.outDebug("HandleAuraEffect: %u, apply: %u: amount: %u", aureff->GetAuraName(), apply, aureff->GetAmount()); - - if (apply) - { - if (aureff->IsApplied()) - return; - - aureff->SetApplied(true); - m_modAuras[aureff->GetAuraName()].push_back(aureff); - aureff->ApplyModifier(true, true); - } - else - { - if (!aureff->IsApplied()) - return; + if (!target || !target->isAlive()) + return NULL; - aureff->SetApplied(false); - // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) - m_modAuras[aureff->GetAuraName()].remove(aureff); - aureff->ApplyModifier(false, true); + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if (!spellInfo) + return NULL; - // Remove all triggered by aura spells vs unlimited duration - aureff->CleanupTriggeredSpells(); - } + return AddAura(spellInfo, MAX_EFFECT_MASK, target); } -void Unit::AddAura(uint32 spellId, Unit *target) +Aura * Unit::AddAura(SpellEntry const *spellInfo, uint8 effMask, Unit *target) { - if (!target || !target->isAlive()) - return; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); if (!spellInfo) - return; + return NULL; if (target->IsImmunedToSpell(spellInfo)) - return; - - uint8 eff_mask=0; - Unit * source = this; + return NULL; for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || IsAreaAuraEffect(spellInfo->Effect[i])) - { - // Area auras applied as linked should have target as source (otherwise they'll be removed after first aura update) - if (spellInfo->Effect[i] != SPELL_EFFECT_APPLY_AURA) - source = target; - - if (target->IsImmunedToSpellEffect(spellInfo, i)) - continue; - eff_mask|=1<<i; - } + if (!(effMask & (1<<i))) + continue; + if (target->IsImmunedToSpellEffect(spellInfo, i)) + effMask &= ~(1<<i); } - if (!eff_mask) - return; - - // Because source is not give, use caster as source - Aura *Aur = new Aura(spellInfo, eff_mask, target, source, this); - target->AddAura(Aur); -} - -void Unit::SetAuraStack(uint32 spellId, Unit *target, uint32 stack) -{ - Aura *aur = target->GetAura(spellId, GetGUID()); - if (!aur) + if (Aura * aura = Aura::TryCreate(spellInfo, effMask, target, this)) { - AddAura(spellId, target); - aur = target->GetAura(spellId, GetGUID()); + aura->ApplyForTargets(); + return aura; } - if (aur && stack) - aur->SetStackAmount(stack); + return NULL; } -// This function is only used for area aura and creature addon -// it should be removed in the future -Aura * Unit::AddAuraEffect(const SpellEntry * spellInfo, uint8 effIndex, WorldObject *source, Unit* caster, int32 * basePoints) +void Unit::SetAuraStack(uint32 spellId, Unit *target, uint32 stack) { - // can't do that for passive auras - they stack from same caster so there is no way to get exact aura which should get effect - //assert (!IsPassiveSpell(spellInfo)); - - sLog.outDebug("AddAuraEffect: spell id: %u, effect index: %u", spellInfo->Id, (uint32)effIndex); - - Aura *aur = GetAura(spellInfo->Id, caster->GetGUID()); - // without this it may crash when shaman refresh totem? source is NULL - if (aur && aur->GetSourceGUID() != source->GetGUID()) - { - RemoveAura(aur); - aur = NULL; - } - - if (aur) - { - if (AuraEffect *aurEffect = CreateAuraEffect(aur, effIndex, basePoints)) - if (!aur->SetPartAura(aurEffect, effIndex)) - delete aurEffect; - } - else - { - if (basePoints) - { - int32 amount[MAX_SPELL_EFFECTS]; - amount[effIndex] = *basePoints; - aur = new Aura(spellInfo, 1<<effIndex, this, source, caster, amount, NULL); - } - else - aur = new Aura(spellInfo, 1<<effIndex, this, source, caster, NULL, NULL); - - if (!AddAura(aur)) - return NULL; - } - return aur; + Aura *aura = target->GetAura(spellId, GetGUID()); + if (!aura) + aura = AddAura(spellId, target); + if (aura && stack) + aura->SetStackAmount(stack); } // Melee based spells can be miss, parry or dodge on this step @@ -15580,13 +15578,13 @@ void Unit::ExitVehicle() return; Unit *vehicleBase = m_vehicle->GetBase(); - const AuraEffectList &modAuras = vehicleBase->GetAurasByType(SPELL_AURA_CONTROL_VEHICLE); + const AuraEffectList &modAuras = vehicleBase->GetAuraEffectsByType(SPELL_AURA_CONTROL_VEHICLE); for (AuraEffectList::const_iterator itr = modAuras.begin(); itr != modAuras.end(); ++itr) { - if ((*itr)->GetParentAura()->GetSourceGUID() == GetGUID()) + if ((*itr)->GetBase()->GetOwner() == this) { - vehicleBase->RemoveAura((*itr)->GetParentAura()); - break; // there should be no case that a vehicle has two auras for one source + vehicleBase->RemoveAura((*itr)->GetBase()); + break; // there should be no case that a vehicle has two auras for one owner } } @@ -15901,7 +15899,7 @@ void Unit::OutDebugInfo() const sLog.outString(); sLog.outStringInLine("Aura List: "); - for (AuraMap::const_iterator itr = m_Auras.begin(); itr != m_Auras.end(); ++itr) + for (AuraApplicationMap::const_iterator itr = m_appliedAuras.begin(); itr != m_appliedAuras.end(); ++itr) sLog.outStringInLine("%u, ", itr->first); sLog.outString(); diff --git a/src/game/Unit.h b/src/game/Unit.h index d2a713349a1..5507335d848 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -85,6 +85,7 @@ enum SpellAuraInterruptFlags AURA_INTERRUPT_FLAG_TELEPORTED = 0x00400000, // 22 AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000, // 24 removed by any direct damage + AURA_INTERRUPT_FLAG_LANDING = 0x02000000, // 25 removed by hitting the ground AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE | AURA_INTERRUPT_FLAG_DIRECT_DAMAGE), }; @@ -317,6 +318,7 @@ struct FactionTemplateEntry; struct SpellEntry; struct SpellValue; +class AuraApplication; class Aura; class AuraEffect; class Creature; @@ -365,11 +367,12 @@ enum DamageTypeToSchool enum AuraRemoveMode { - AURA_REMOVE_BY_DEFAULT=0, // scripted remove, remove by stack with aura with different ids and sc aura remove - AURA_REMOVE_BY_STACK, // replace by aura with same id + AURA_REMOVE_NONE = 0, + AURA_REMOVE_BY_DEFAULT = 1, // scripted remove, remove by stack with aura with different ids and sc aura remove + AURA_REMOVE_BY_STACK, // replace by aura with same id AURA_REMOVE_BY_CANCEL, - AURA_REMOVE_BY_ENEMY_SPELL, // dispel and absorb aura destroy - AURA_REMOVE_BY_EXPIRE, // dispel and absorb aura destroy + AURA_REMOVE_BY_ENEMY_SPELL, // dispel and absorb aura destroy + AURA_REMOVE_BY_EXPIRE, // aura duration has ended AURA_REMOVE_BY_DEATH }; @@ -854,10 +857,10 @@ struct SpellNonMeleeDamage{ struct SpellPeriodicAuraLogInfo { - SpellPeriodicAuraLogInfo(AuraEffect *_auraEff, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier, bool _critical) + SpellPeriodicAuraLogInfo(AuraEffect const *_auraEff, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier, bool _critical) : auraEff(_auraEff), damage(_damage), overDamage(_overDamage), absorb(_absorb), resist(_resist), multiplier(_multiplier), critical(_critical){} - AuraEffect *auraEff; + AuraEffect const * auraEff; uint32 damage; uint32 overDamage; // overkill/overheal uint32 absorb; @@ -1081,13 +1084,15 @@ class TRINITY_DLL_SPEC Unit : public WorldObject typedef std::set<Unit*> ControlList; typedef std::pair<uint32, uint8> spellEffectPair; typedef std::multimap<uint32, Aura*> AuraMap; - typedef std::multimap<AuraState, Aura*> AuraStateAurasMap; + typedef std::multimap<uint32, AuraApplication*> AuraApplicationMap; + typedef std::multimap<AuraState, AuraApplication*> AuraStateAurasMap; typedef std::list<AuraEffect *> AuraEffectList; typedef std::list<Aura *> AuraList; + typedef std::list<AuraApplication *> AuraApplicationList; typedef std::list<DiminishingReturn> Diminishing; typedef std::set<uint32> ComboPointHolderSet; - typedef std::map<uint8, Aura*> VisibleAuraMap; + typedef std::map<uint8, AuraApplication*> VisibleAuraMap; virtual ~Unit ( ); @@ -1154,7 +1159,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void CombatStopWithPets(bool includingCast = false); void StopAttackFaction(uint32 faction_id); Unit* SelectNearbyTarget(float dist = NOMINAL_MELEE_RANGE) const; - bool hasNegativeAuraWithInterruptFlag(uint32 flag); void SendMeleeAttackStop(Unit* victim); void SendMeleeAttackStart(Unit* pVictim); @@ -1396,17 +1400,16 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage,Powers powertype); void EnergizeBySpell(Unit *pVictim, uint32 SpellID, uint32 Damage, Powers powertype); uint32 SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage); - void CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem = NULL, AuraEffect* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastSpell(Unit* Victim, SpellEntry const *spellInfo, bool triggered, Item *castItem= NULL, AuraEffect* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem = NULL, AuraEffect* triggeredByAura = NULL, uint64 originalCaster = 0, Unit* originalVictim = 0); - void CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem= NULL, AuraEffect* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* Victim = NULL, bool triggered = true, Item *castItem = NULL, AuraEffect* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastCustomSpell(uint32 spellId, CustomSpellValues const &value, Unit* Victim = NULL, bool triggered = true, Item *castItem = NULL, AuraEffect* triggeredByAura = NULL, uint64 originalCaster = 0); + void CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem = NULL, AuraEffect const * triggeredByAura = NULL, uint64 originalCaster = 0); + void CastSpell(Unit* Victim, SpellEntry const *spellInfo, bool triggered, Item *castItem= NULL, AuraEffect const * triggeredByAura = NULL, uint64 originalCaster = 0); + void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem = NULL, AuraEffect const * triggeredByAura = NULL, uint64 originalCaster = 0, Unit* originalVictim = 0); + void CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem= NULL, AuraEffect const * triggeredByAura = NULL, uint64 originalCaster = 0); + void CastCustomSpell(uint32 spellId, SpellValueMod mod, int32 value, Unit* Victim = NULL, bool triggered = true, Item *castItem = NULL, AuraEffect const * triggeredByAura = NULL, uint64 originalCaster = 0); + void CastCustomSpell(uint32 spellId, CustomSpellValues const &value, Unit* Victim = NULL, bool triggered = true, Item *castItem = NULL, AuraEffect const * triggeredByAura = NULL, uint64 originalCaster = 0); void CastSpell(GameObject *go, uint32 spellId, bool triggered, Item *castItem = NULL, AuraEffect* triggeredByAura = NULL, uint64 originalCaster = 0); - void AddAura(uint32 spellId, Unit *target); + Aura * AddAura(uint32 spellId, Unit *target); + Aura * AddAura(SpellEntry const *spellInfo, uint8 effMask, Unit *target); void SetAuraStack(uint32 spellId, Unit *target, uint32 stack); - void HandleAuraEffect(AuraEffect * aureff, bool apply); - Aura *AddAuraEffect(const SpellEntry *spellInfo, uint8 effIndex, WorldObject *source, Unit *caster, int32 *basePoints = NULL); bool IsDamageToThreatSpell(SpellEntry const * spellInfo) const; @@ -1526,31 +1529,99 @@ class TRINITY_DLL_SPEC Unit : public WorldObject Pet* CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id = 0); - bool AddAura(Aura *aur, bool handleEffects = true); - - void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); - void RemoveAura(uint32 spellId, uint64 caster = 0 ,AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + // aura apply/remove helpers - you should better not use these + void _AddAura(Aura * aura); + AuraApplication * __ApplyAura(Aura * aura); + void __UnapplyAura(AuraApplicationMap::iterator &i); + bool _ApplyAuraEffect(Aura * aura, uint8 effIndex); + void _UnapplyAuraEffect(AuraApplication * aurApp, uint8 effIndex, AuraRemoveMode removeMode); + void _UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode); + void _UnapplyAura(AuraApplication * aurApp, AuraRemoveMode removeMode); + void _RemoveNoStackAurasDueToAura(Aura * aura); + void _HandleAuraEffect(AuraEffect * aurEff, bool apply); + + // m_ownedAuras container management + AuraMap & GetOwnedAuras() { return m_ownedAuras; } + AuraMap const& GetOwnedAuras() const { return m_ownedAuras; } + + void RemoveOwnedAura(AuraMap::iterator &i, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void RemoveOwnedAura(uint32 spellId, uint64 caster, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void RemoveOwnedAura(Aura * aura, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + + Aura * GetOwnedAura(uint32 spellId, uint64 casterGUID = 0, uint8 reqEffMask = 0) const; + + // m_appliedAuras container management + AuraApplicationMap & GetAppliedAuras() { return m_appliedAuras; } + AuraApplicationMap const& GetAppliedAuras() const { return m_appliedAuras; } + + void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); + void RemoveAura(uint32 spellId, uint64 caster = 0, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(Aura * aur, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); - void RemoveAurasDueToSpell(uint32 spellId, uint64 caster = NULL ,AuraRemoveMode removeMode= AURA_REMOVE_BY_DEFAULT); - void RemoveAuraFromStack(uint32 spellId, uint64 caster = NULL ,AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + + void RemoveAurasDueToSpell(uint32 spellId, uint64 caster = NULL, uint8 reqEffMask = 0, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void RemoveAuraFromStack(uint32 spellId, uint64 caster = NULL, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); inline void RemoveAuraFromStack(AuraMap::iterator &iter,AuraRemoveMode removeMode); - void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeller); - void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer); + void RemoveAurasDueToSpellByDispel(Aura * aura, Unit *dispeller); + void RemoveAurasDueToSpellBySteal(Aura * aura, Unit *stealer); void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId); void RemoveAurasByType(AuraType auraType, uint64 casterGUID = 0, Aura * except = NULL, bool negative = true, bool positive = true); void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0); - - void RemoveRankAurasDueToSpell(uint32 spellId); - bool RemoveNoStackAurasDueToAura(Aura *Aur); void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = NULL); - void RemoveAurasWithFamily(uint32 family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID); - void RemoveMovementImpairingAuras(); + void RemoveAurasWithFamily(SpellFamilyNames family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID); void RemoveAurasWithMechanic(uint32 mechanic_mask, AuraRemoveMode removemode = AURA_REMOVE_BY_DEFAULT, uint32 except=0); + void RemoveMovementImpairingAuras(); + + void RemoveAreaAurasDueToLeaveWorld(); void RemoveAllAuras(); - void RemoveAllAuras(uint64 casterGUID, Aura * except = NULL, bool negative = true, bool positive = true); void RemoveArenaAuras(bool onleave = false); void RemoveAllAurasOnDeath(); - void DelayAura(uint32 spellId, uint64 caster, int32 delaytime); + void DelayOwnedAuras(uint32 spellId, uint64 caster, int32 delaytime); + + void _RemoveAllAuraStatMods(); + void _ApplyAllAuraStatMods(); + + AuraEffectList const& GetAuraEffectsByType(AuraType type) const { return m_modAuras[type]; } + AuraApplicationList & GetSingleCastAuras() { return m_scAuras; } + AuraApplicationList const& GetSingleCastAuras() const { return m_scAuras; } + + AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, uint64 casterGUID = 0) const; + AuraEffect * GetAuraEffectOfRankedSpell(uint32 spellId, uint8 effIndex, uint64 casterGUID = 0) const; + AuraEffect * GetAuraEffect(AuraType type, SpellFamilyNames name, uint32 iconId, uint8 effIndex) const; // spell mustn't have familyflags + AuraEffect * GetAuraEffect(AuraType type, SpellFamilyNames family, uint32 familyFlag1 , uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID =0 ); + inline AuraEffect* GetDummyAuraEffect(SpellFamilyNames name, uint32 iconId, uint8 effIndex) const { return GetAuraEffect(SPELL_AURA_DUMMY, name, iconId, effIndex);} + + AuraApplication * GetAuraApplication(uint32 spellId, uint64 casterGUID = 0, uint8 reqEffMask = 0, AuraApplication * except = NULL) const; + Aura * GetAura(uint32 spellId, uint64 casterGUID = 0, uint8 reqEffMask = 0) const; + + AuraApplication * GetAuraApplicationOfRankedSpel(uint32 spellId, uint64 casterGUID = 0, uint8 reqEffMask = 0, AuraApplication * except = NULL) const; + Aura * GetAuraOfRankedSpell(uint32 spellId, uint64 casterGUID = 0, uint8 reqEffMask = 0) const; + + bool HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster = 0) const; + bool HasAura(uint32 spellId, uint64 caster = 0, uint8 reqEffMask = 0) const; + bool HasAuraType(AuraType auraType) const; + bool HasAuraTypeWithMiscvalue(AuraType auratype, uint32 miscvalue) const; + bool HasAuraTypeWithValue(AuraType auratype, uint32 value) const; + bool HasNegativeAuraWithInterruptFlag(uint32 flag); + + AuraEffect * IsScriptOverriden(SpellEntry const * spell, int32 script) const; + uint32 GetDiseasesByCaster(uint64 casterGUID, bool remove = false); + uint32 GetDoTsByCaster(uint64 casterGUID) const; + + int32 GetTotalAuraModifier(AuraType auratype) const; + float GetTotalAuraMultiplier(AuraType auratype) const; + int32 GetMaxPositiveAuraModifier(AuraType auratype); + int32 GetMaxNegativeAuraModifier(AuraType auratype) const; + + int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; + float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const; + int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; + int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; + + int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; + float GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const; + int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; + int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); } void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); } @@ -1665,8 +1736,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject // function for low level grid visibility checks in player/creature cases virtual bool IsVisibleInGridForPlayer(Player const* pl) const = 0; - AuraList & GetSingleCastAuras() { return m_scAuras; } - AuraList const& GetSingleCastAuras() const { return m_scAuras; } SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; // Threat related methods @@ -1682,49 +1751,15 @@ class TRINITY_DLL_SPEC Unit : public WorldObject HostilRefManager& getHostilRefManager() { return m_HostilRefManager; } VisibleAuraMap const *GetVisibleAuras() { return &m_visibleAuras; } - Aura * GetVisibleAura(uint8 slot) + AuraApplication * GetVisibleAura(uint8 slot) { VisibleAuraMap::iterator itr = m_visibleAuras.find(slot); if(itr != m_visibleAuras.end()) return itr->second; return 0; } - void SetVisibleAura(uint8 slot, Aura * aur){ m_visibleAuras[slot]=aur; } - void RemoveVisibleAura(uint8 slot){ m_visibleAuras.erase(slot); } - - AuraMap & GetAuras() { return m_Auras; } - AuraMap const& GetAuras() const { return m_Auras; } - AuraEffectList const& GetAurasByType(AuraType type) const { return m_modAuras[type]; } - - AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, uint64 casterGUID = 0) const; - Aura * GetAura(uint32 spellId, uint64 casterGUID = 0) const; - AuraEffect * GetAura(AuraType type, uint32 family, uint32 familyFlag1 , uint32 familyFlag2=0, uint32 familyFlag3=0, uint64 casterGUID=0); - AuraEffect * IsScriptOverriden(SpellEntry const * spell, int32 script) const; - bool HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster = 0) const; - bool HasAura(uint32 spellId, uint64 caster = 0) const; - bool HasAura(Aura * aur) const; - bool HasAuraType(AuraType auraType) const; - bool HasAuraTypeWithMiscvalue(AuraType auratype, uint32 miscvalue) const; - bool HasAuraTypeWithValue(AuraType auratype, uint32 value) const; - inline AuraEffect* GetDummyAura(SpellFamilyNames name, uint32 iconId, uint8 effIndex) const { return GetAuraEffect(SPELL_AURA_DUMMY, name, iconId, effIndex);} - AuraEffect* GetAuraEffect(AuraType type, SpellFamilyNames name, uint32 iconId, uint8 effIndex) const; - uint32 GetDiseasesByCaster(uint64 casterGUID, bool remove = false); - uint32 GetDoTsByCaster(uint64 casterGUID) const; - - int32 GetTotalAuraModifier(AuraType auratype) const; - float GetTotalAuraMultiplier(AuraType auratype) const; - int32 GetMaxPositiveAuraModifier(AuraType auratype); - int32 GetMaxNegativeAuraModifier(AuraType auratype) const; - - int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; - float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const; - int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; - int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; - - int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; - float GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const; - int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; - int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; + void SetVisibleAura(uint8 slot, AuraApplication * aur){ m_visibleAuras[slot]=aur; UpdateAuraForGroup(slot);} + void RemoveVisibleAura(uint8 slot){ m_visibleAuras.erase(slot); UpdateAuraForGroup(slot);} uint32 GetInterruptMask() const { return m_interruptMask; } void AddInterruptMask(uint32 mask) { m_interruptMask |= mask; } @@ -1797,9 +1832,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void SetHover(bool on); bool isHover() const { return HasAuraType(SPELL_AURA_HOVER); } - void _RemoveAllAuraMods(); - void _ApplyAllAuraMods(); - int32 CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 basePoints, Unit const* target); int32 CalcSpellDuration(SpellEntry const* spellProto); int32 ModSpellDuration(SpellEntry const* spellProto, Unit const* target, int32 duration, bool positive); @@ -1931,7 +1963,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject Transport * m_transport; void _UpdateSpells(uint32 time); - void _DeleteAuras(); + void _DeleteRemovedAuras(); void _UpdateAutoRepeatSpell(); @@ -1946,9 +1978,6 @@ class TRINITY_DLL_SPEC Unit : public WorldObject DeathState m_deathState; - AuraMap m_Auras; - AuraMap::iterator m_AurasUpdateIterator; - uint32 m_removedAurasCount; int32 m_procDeep; typedef std::list<uint64> DynObjectGUIDs; @@ -1959,11 +1988,16 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool m_isSorted; uint32 m_transform; - AuraEffectList m_modAuras[TOTAL_AURAS]; - AuraList m_scAuras; // casted singlecast auras - AuraList m_interruptableAuras; + AuraMap m_ownedAuras; + AuraApplicationMap m_appliedAuras; AuraList m_removedAuras; - AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove + AuraMap::iterator m_auraUpdateIterator; + uint32 m_removedAurasCount; + + AuraEffectList m_modAuras[TOTAL_AURAS]; + AuraApplicationList m_scAuras; // casted singlecast auras + AuraApplicationList m_interruptableAuras; // auras which have interrupt mask applied on unit + AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove uint32 m_interruptMask; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; @@ -1992,7 +2026,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject uint32 m_unitTypeMask; private: - bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const * procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const *& spellProcEvent ); + bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura * aura, SpellEntry const * procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const *& spellProcEvent ); bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleSpellCritChanceAuraProc( Unit *pVictim, uint32 damage, AuraEffect* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); diff --git a/src/game/UnitAI.cpp b/src/game/UnitAI.cpp index bafcb04a2f3..7365619030f 100644 --- a/src/game/UnitAI.cpp +++ b/src/game/UnitAI.cpp @@ -22,6 +22,7 @@ #include "Player.h" #include "Creature.h" #include "SpellAuras.h" +#include "SpellAuraEffects.h" #include "SpellMgr.h" #include "CreatureAIImpl.h" @@ -370,9 +371,9 @@ void SimpleCharmedAI::UpdateAI(const uint32 /*diff*/) //kill self if charm aura has infinite duration if(charmer->IsInEvadeMode()) { - Unit::AuraEffectList const& auras = me->GetAurasByType(SPELL_AURA_MOD_CHARM); + Unit::AuraEffectList const& auras = me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM); for (Unit::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) - if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetParentAura()->IsPermanent()) + if((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent()) { charmer->Kill(me); return; diff --git a/src/shared/ByteBuffer.h b/src/shared/ByteBuffer.h index d5001cfc1bf..6fd0c9b883d 100644 --- a/src/shared/ByteBuffer.h +++ b/src/shared/ByteBuffer.h @@ -386,21 +386,21 @@ class ByteBuffer void appendPackGUID(uint64 guid) { - if (_storage.size() < _wpos + sizeof(guid) + 1) - _storage.resize(_wpos + sizeof(guid) + 1); - - size_t mask_position = wpos(); - *this << uint8(0); - for (uint8 i = 0; i < 8; ++i) + uint8 packGUID[8+1]; + packGUID[0] = 0; + size_t size = 1; + for(uint8 i = 0;guid != 0;++i) { if(guid & 0xFF) { - _storage[mask_position] |= uint8(1 << i); - *this << uint8(guid & 0xFF); + packGUID[0] |= uint8(1 << i); + packGUID[size] = uint8(guid & 0xFF); + ++size; } guid >>= 8; } + append(packGUID, size); } void put(size_t pos, const uint8 *src, size_t cnt) |