예제 #1
0
        void HandleScriptEffect(SpellEffIndex effIndex)
        {
            Unit* caster = GetCaster();
            Unit* unitTarget = GetHitUnit();
            if (!unitTarget)
                return;

            uint32 spellId = 0;
            int32 basePoint = 0;
            Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
            for (Unit::AuraApplicationMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
            {
                Aura* aura = i->second->GetBase();
                if (aura->GetCasterGUID() != 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 (AuraEffect const * aurEff = aura->GetEffect(0))
                {
                    // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
                    if (familyFlag[0] & 0x4000)
                    {
                        int32 TickCount = aurEff->GetTotalTicks();
                        spellId = HUNTER_SPELL_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 = HUNTER_SPELL_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 = HUNTER_SPELL_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();
                }
                break;
            }
            if (spellId)
                caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false);
        }
예제 #2
0
bool AuraInterface::BuildAuraUpdateAllPacket(WorldPacket* data)
{
	if(!m_auras.size())
		return false;

	bool res = false;
	Aura* aur = NULL;
	for (uint32 i=0; i<MAX_AURAS; i++)
	{
		if(m_auras.find(i) != m_auras.end())
		{
			res = true;
			aur = m_auras.at(i);
			aur->BuildAuraUpdate();
			uint8 flags = aur->GetAuraFlags();

			*data << uint8(aur->m_auraSlot);
			int32 stack = aur->stackSize;
			if(aur->procCharges > stack && stack != 0)
				stack = aur->procCharges;
			if(stack < 0)
			{
				*data << uint32(0);
				continue;
			}

			*data << uint32(aur->GetSpellId());
			*data << uint8(flags);
			*data << uint8(aur->GetUnitCaster() ? aur->GetUnitCaster()->getLevel() : 0);
			*data << uint8(stack);

			if(!(flags & AFLAG_NOT_GUID))
				FastGUIDPack(*data, aur->GetCasterGUID());

			if(flags & AFLAG_HAS_DURATION)
			{
				*data << aur->GetDuration();
				*data << aur->GetTimeLeft();
			}
		}
	}
	return res;
}
예제 #3
0
            void HandleScriptEffect(SpellEffIndex /*effIndex*/)
            {
                Unit* caster = GetCaster();
                if (Unit* unitTarget = GetHitUnit())
                {
                    uint32 spellId = 0;
                    int32 basePoint = 0;
                    Unit::AuraApplicationMap& Auras = unitTarget->GetAppliedAuras();
                    for (Unit::AuraApplicationMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
                    {
                        Aura* aura = i->second->GetBase();
                        if (aura->GetCasterGUID() != caster->GetGUID())
                            continue;

                        // Search only Serpent Sting, Viper Sting, Scorpid Sting auras
                        flag96 familyFlag = aura->GetSpellInfo()->SpellFamilyFlags;
                        if (!(familyFlag[1] & 0x00000080 || familyFlag[0] & 0x0000C000))
                            continue;
                        if (AuraEffect* aurEff = aura->GetEffect(0))
                        {
                            // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
                            if (familyFlag[0] & 0x4000)
                            {
                                int32 TickCount = aurEff->GetTotalTicks();
                                spellId = SPELL_HUNTER_CHIMERA_SHOT_SERPENT;
                                basePoint = (aurEff->GetAmount() + aurEff->GetBonusAmount()) * aurEff->GetDonePct();
                                ApplyPct(basePoint, TickCount * 40);
                                basePoint = unitTarget->SpellDamageBonusTaken(caster, aura->GetSpellInfo(), basePoint, DOT, aura->GetStackAmount());
                                if (Player* modOwner = caster->GetSpellModOwner())
                                    modOwner->ApplySpellMod(aura->GetSpellInfo()->Id, SPELLMOD_DOT, basePoint);

                                aurEff->SetBonusAmount(caster->SpellDamageBonusDone(unitTarget, aurEff->GetSpellInfo(), 0, DOT));
                            }
                            // 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 = SPELL_HUNTER_CHIMERA_SHOT_VIPER;

                                // Amount of one aura tick
                                basePoint = int32(CalculatePct(unitTarget->GetMaxPower(POWER_MANA), aurEff->GetAmount()));
                                int32 casterBasePoint = aurEff->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 50; /// @todo WTF? caster uses unitTarget?
                                if (basePoint > casterBasePoint)
                                    basePoint = casterBasePoint;
                                ApplyPct(basePoint, TickCount * 60);
                            }
                            // 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 = SPELL_HUNTER_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();
                        }
                        break;
                    }
                    if (spellId)
                        caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, true);
                    if (spellId == SPELL_HUNTER_CHIMERA_SHOT_SCORPID && caster->ToPlayer()) // Scorpid Sting - Add 1 minute cooldown
                        caster->GetSpellHistory()->AddCooldown(spellId, 0, std::chrono::minutes(1));
                }
            }
예제 #4
0
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);
		}
	}
}
예제 #5
0
void AuraInterface::SaveAuras(stringstream& ss)
{
	for(uint32 x = 0; x < MAX_AURAS; x++) // Crow: Changed to max auras in r1432, since we skip passive auras.
	{
		if(m_auras.find(x) != m_auras.end())
		{
			Aura* aur = m_auras.at(x);

			// skipped spells due to bugs
			switch(aur->m_spellProto->Id)
			{
			case 642:
			case 1020:				// Divine Shield
			case 11129:				// Combustion
			case 12043:				// Presence of mind
			case 16188:				// Natures Swiftness
			case 17116:				// Natures Swiftness
			case 23333:				// WSG
			case 23335:				// WSG
			case 28682:				// Combustion proc
			case 31665:				// Master of Subtlety (buff)
			case 32724:				// Gold Team
			case 32725:				// Green Team
			case 32727:				// Arena Preparation
			case 32728:				// Arena Preparation
			case 32071:				// Hellfire Superority
			case 32049:				// Hellfire Superority
			case 34936:				// Backlash
			case 35076:				// Blessing of A'dal
			case 35774:				// Gold Team
			case 35775:				// Green Team
			case 44521:				// Preparation?
			case 44683:				// Team A
			case 44684:				// Team B
			case 45438:				// Ice Block
			case 48418:				// Master Shapeshifter Damage (buff)
			case 48420:				// Master Shapeshifter Critical Strike (buff)
			case 48421:				// Master Shapeshifter Spell Damage (buff)
			case 48422:				// Master Shapeshifter Healing (buff)
				continue;
				break;
			}

			bool stop = false;
			for(uint32 i = 0; i < 3; i++)
			{
				if(!stop)
				{
					if((aur->m_spellProto->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA && aur->GetCasterGUID() != m_Unit->GetGUID()) ||
						aur->m_spellProto->Effect[i] == SPELL_EFFECT_APPLY_AURA_128 ||
						aur->m_spellProto->Effect[i] == SPELL_EFFECT_ADD_FARSIGHT)
					{
						stop = true;
						break;
					}
				}
			}
			if(stop)
				continue;

			// We are going to cast passive spells anyway on login so no need to save auras for them
			if( aur->IsPassive() || aur->m_spellProto->c_is_flags & SPELL_FLAG_IS_EXPIREING_WITH_PET || aur->m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_ON_STAND_UP )
				continue; // To prevent food/drink bug

			ss << aur->GetSpellId() << "," << aur->GetTimeLeft() << ",";
		}
	}
}