void AuraInterface::AddAura(Aura* aur) { uint32 x,delslot = 0; Unit* pCaster = NULLUNIT; if(aur->GetUnitTarget() != NULL) pCaster = aur->GetUnitCaster(); else if( aur->GetCasterGUID() == m_Unit->GetGUID() ) pCaster = m_Unit; else if( m_Unit->GetMapMgr() && aur->GetCasterGUID()) pCaster = m_Unit->GetMapMgr()->GetUnit( aur->GetCasterGUID()); if(pCaster == NULL) return; if( !aur->IsPassive() ) { uint32 maxStack = aur->GetSpellProto()->maxstack; if( m_Unit->IsPlayer() && TO_PLAYER(m_Unit)->stack_cheat ) maxStack = 255; SpellEntry * info = aur->GetSpellProto(); bool deleteAur = false; Aura* curAura = NULLAURA; //check if we already have this aura by this caster -> update duration // Nasty check for Blood Fury debuff (spell system based on namehashes is bs anyways) if( !info->always_apply ) { for( x = 0; x < MAX_AURAS; x++ ) { if(m_auras.find(x) == m_auras.end()) continue; curAura = m_auras.at(x); if( curAura != NULL && !curAura->m_deleted ) { if( curAura->GetSpellProto()->Id != aur->GetSpellId() && ( aur->pSpellId != curAura->GetSpellProto()->Id )) //if this is a proc spell then it should not remove it's mother : test with combustion later { if( info->buffType > 0 && m_auras.at(x)->GetSpellProto()->buffType > 0 && (info->buffType & m_auras.at(x)->GetSpellProto()->buffType) ) { if( m_auras.at(x)->GetSpellProto()->buffType & SPELL_TYPE_BLESSING ) { // stupid blessings // if you have better idea correct bool ispair = false; switch( info->NameHash ) { case SPELL_HASH_BLESSING_OF_MIGHT: case SPELL_HASH_GREATER_BLESSING_OF_MIGHT: { if( m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_BLESSING_OF_MIGHT || m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_GREATER_BLESSING_OF_MIGHT ) ispair = true; }break; case SPELL_HASH_BLESSING_OF_WISDOM: case SPELL_HASH_GREATER_BLESSING_OF_WISDOM: { if( m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_BLESSING_OF_WISDOM || m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_GREATER_BLESSING_OF_WISDOM ) ispair = true; }break; case SPELL_HASH_BLESSING_OF_KINGS: case SPELL_HASH_GREATER_BLESSING_OF_KINGS: { if( m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_BLESSING_OF_KINGS || m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_GREATER_BLESSING_OF_KINGS ) ispair = true; }break; case SPELL_HASH_BLESSING_OF_SANCTUARY: case SPELL_HASH_GREATER_BLESSING_OF_SANCTUARY: { if( m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_BLESSING_OF_SANCTUARY || m_auras.at(x)->GetSpellProto()->NameHash == SPELL_HASH_GREATER_BLESSING_OF_SANCTUARY ) ispair = true; }break; } if( m_auras.at(x)->GetUnitCaster() == aur->GetUnitCaster() || ispair ) { RemoveAuraBySlot(x); continue; } } else if( m_auras.at(x)->GetSpellProto()->buffType & SPELL_TYPE_AURA ) { if( m_auras.at(x)->GetUnitCaster() == aur->GetUnitCaster() || m_auras.at(x)->GetSpellProto()->NameHash == info->NameHash ) { RemoveAuraBySlot(x); continue; } } else { RemoveAuraBySlot(x); continue; } } else if( info->poison_type > 0 && m_auras.at(x)->GetSpellProto()->poison_type == info->poison_type ) { if( m_auras.at(x)->GetSpellProto()->RankNumber < info->RankNumber || maxStack == 0) { RemoveAuraBySlot(x); continue; } else if( m_auras.at(x)->GetSpellProto()->RankNumber > info->RankNumber ) { RemoveAuraBySlot(x); break; } } else if( m_auras.at(x)->GetSpellProto()->NameHash == info->NameHash ) { if( m_auras.at(x)->GetUnitCaster() == aur->GetUnitCaster() ) { RemoveAuraBySlot(x); continue; } else if( m_auras.at(x)->GetSpellProto()->Unique ) { if( m_auras.at(x)->GetSpellProto()->RankNumber < info->RankNumber ) { RemoveAuraBySlot(x); continue; } else { delslot = x; deleteAur = true; break; } } } } else if( curAura->GetSpellId() == aur->GetSpellId() ) { if( !aur->IsPositive() && curAura->GetCasterGUID() != aur->GetCasterGUID() && maxStack == 0 && !info->Unique ) continue; // target already has this aura. Update duration, time left, procCharges curAura->SetDuration(aur->GetDuration()); curAura->SetTimeLeft(aur->GetDuration()); curAura->procCharges = curAura->GetMaxProcCharges(pCaster); curAura->UpdateModifiers(); curAura->ModStackSize(1); // increment stack size return; } } } } if(deleteAur) { sEventMgr.RemoveEvents(aur); RemoveAuraBySlot(delslot); return; } } //////////////////////////////////////////////////////// if( aur->m_auraSlot != 255 && aur->m_auraSlot < TOTAL_AURAS) { if( m_auras.find(aur->m_auraSlot) != m_auras.end() ) RemoveAuraBySlot(aur->m_auraSlot); } aur->m_auraSlot = 255; Unit* target = aur->GetUnitTarget(); if(target == NULL) return; // Should never happen. aur->SetAuraFlags(AFLAG_VISIBLE | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2 | AFLAG_NOT_GUID | (aur->GetDuration() ? AFLAG_HAS_DURATION : AFLAG_NONE) | (aur->IsPositive() ? (AFLAG_POSITIVE) : (AFLAG_NEGATIVE))); aur->SetAuraLevel(aur->GetUnitCaster() != NULL ? aur->GetUnitCaster()->getLevel() : MAXIMUM_ATTAINABLE_LEVEL); if(!aur->IsPassive()) { aur->AddAuraVisual(); if(aur->m_auraSlot == 255) { //add to invisible slot for(x = MAX_AURAS; x < TOTAL_AURAS; x++) { if(m_auras.find(x) == m_auras.end()) { m_auras.insert(make_pair(x, aur)); aur->m_auraSlot = x; break; } } if(aur->m_auraSlot == 255) { DEBUG_LOG("Unit","AddAura error in active aura. removing. SpellId: %u", aur->GetSpellProto()->Id); RemoveAura(aur); return; } } else { m_auras.insert(make_pair(aur->m_auraSlot, aur)); } } else { if(aur->m_spellProto->AttributesEx & 1024) aur->AddAuraVisual(); for(x = MAX_AURAS; x < TOTAL_AURAS; x++) { if(m_auras.find(x) == m_auras.end()) { m_auras.insert(make_pair(x, aur)); aur->m_auraSlot = x; break; } } if(aur->m_auraSlot == 255) { DEBUG_LOG("Unit","AddAura error in passive aura. removing. SpellId: %u", aur->GetSpellProto()->Id); RemoveAura(aur); return; } } if(aur->GetSpellId() == 15007) //Resurrection sickness { aur->SetNegative(100); //we're negative aur->SetDuration(target->getLevel() > 19 ? 600000 : 60000); } aur->ApplyModifiers(true); // We add 500ms here to allow for the last tick in DoT spells. This is a dirty hack, but at least it doesn't crash like my other method. // - Burlex, Crow: Changed to 400ms if(aur->GetDuration() > 0) { uint32 addTime = 400; for(uint32 spx = 0; spx < 3; spx++) { if( aur->GetSpellProto()->EffectApplyAuraName[spx] == SPELL_AURA_MOD_STUN || aur->GetSpellProto()->EffectApplyAuraName[spx] == SPELL_AURA_MOD_FEAR || aur->GetSpellProto()->EffectApplyAuraName[spx] == SPELL_AURA_MOD_ROOT || aur->GetSpellProto()->EffectApplyAuraName[spx] == SPELL_AURA_MOD_CHARM ) addTime = 50; } sEventMgr.AddAuraEvent(m_Unit, &Unit::RemoveAuraBySlot, uint8(aur->m_auraSlot), aur->GetDuration() + addTime, 1, EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT | EVENT_FLAG_DELETES_OBJECT, aur->GetSpellId()); } aur->RelocateEvents(); // Send log to client if (target != NULL) { //send the aura log WorldPacket data(SMSG_AURACASTLOG, 28); data << aur->GetCasterGUID(); data << aur->GetTargetGUID(); data << aur->m_spellProto->Id; data << uint64(0); target->SendMessageToSet(&data, true); } m_Unit->m_chargeSpellsInUse = true; if( aur->procCharges > 0 && !(aur->GetSpellProto()->procflags2 & PROC_REMOVEONUSE)) m_Unit->m_chargeSpells.push_back(aur); m_Unit->m_chargeSpellsInUse = false; aur->m_added = true; // Reaction from enemy AI if( !aur->IsPositive() && CanAgroHash( aur->GetSpellProto()->NameHash ) ) { if(pCaster != NULL && m_Unit->isAlive()) { pCaster->CombatStatus.OnDamageDealt(TO_UNIT(this), 1); if(m_Unit->IsCreature()) m_Unit->GetAIInterface()->AttackReaction(pCaster, 1, aur->GetSpellId()); } } if (aur->GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_ON_INVINCIBLE) { if( pCaster != NULL ) { pCaster->RemoveStealth(); pCaster->RemoveInvisibility(); pCaster->m_AuraInterface.RemoveAllAurasByNameHash(SPELL_HASH_ICE_BLOCK, false); pCaster->m_AuraInterface.RemoveAllAurasByNameHash(SPELL_HASH_DIVINE_SHIELD, false); pCaster->m_AuraInterface.RemoveAllAurasByNameHash(SPELL_HASH_BLESSING_OF_PROTECTION, false); } } }