Example #1
0
void TempSummon::InitStats(uint32 duration)
{
    ASSERT(!isPet());

    m_timer = duration;
    m_lifetime = duration;

    if (m_type == TEMPSUMMON_MANUAL_DESPAWN)
        m_type = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;

    Unit* owner = GetSummoner();

    if (owner && isTrigger() && m_spells[0])
    {
        setFaction(owner->getFaction());
        SetLevel(owner->getLevel());
        if (owner->GetTypeId() == TYPEID_PLAYER)
            m_ControlledByPlayer = true;
    }

    if (!m_Properties)
        return;

    // Fix Force of Nature treants stats
    if (owner && owner->getClass() == CLASS_DRUID && owner->HasSpell(106737))
    {
        float damage = 0.0f;

        switch (GetEntry())
        {
        case ENTRY_TREANT_RESTO:
        case ENTRY_TREANT_BALANCE:
            SetMaxHealth(owner->CountPctFromMaxHealth(40));
            break;
        case ENTRY_TREANT_GUARDIAN:
            SetMaxHealth(owner->CountPctFromMaxHealth(40));
            // (Attack power / 14 * 2 * 0.75) * 0.2f
            damage = ((owner->GetTotalAttackPowerValue(BASE_ATTACK) / 14.0f) * 2.0f * 0.75f) * 0.2f;
            SetStatFloatValue(UNIT_FIELD_MINDAMAGE, damage);
            SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, damage);
        case ENTRY_TREANT_FERAL:
            SetMaxHealth(owner->CountPctFromMaxHealth(40));
            // Attack power / 14 * 2 * 0.75
            damage = (owner->GetTotalAttackPowerValue(BASE_ATTACK) / 14.0f) * 2.0f * 0.75f;
            SetStatFloatValue(UNIT_FIELD_MINDAMAGE, damage);
            SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, damage);
        default:
            break;
        }
    }

    if (owner)
    {
        if (uint32 slot = m_Properties->Slot)
        {
            if (owner->m_SummonSlot[slot] && owner->m_SummonSlot[slot] != GetGUID())
            {
                Creature* oldSummon = GetMap()->GetCreature(owner->m_SummonSlot[slot]);
                if (oldSummon && oldSummon->IsSummon())
                    oldSummon->ToTempSummon()->UnSummon();
            }
            owner->m_SummonSlot[slot] = GetGUID();
        }
    }

    if (m_Properties->Faction)
        setFaction(m_Properties->Faction);
    else if (IsVehicle() && owner) // properties should be vehicle
        setFaction(owner->getFaction());
}
Example #2
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);
		}
	}
}
Example #3
0
        void Absorb(AuraEffect* aurEff, DamageInfo & dmgInfo, uint32 & absorbAmount)
        {
            Unit* victim = GetTarget();
            int32 remainingHealth = victim->GetHealth() - dmgInfo.GetDamage();
            uint32 allowedHealth = victim->CountPctFromMaxHealth(35);

            //npcbot - calc for bots
            if (victim->GetTypeId() == TYPEID_UNIT/* && victim->ToCreature()->IsNPCBot()*/)
            {
                if (remainingHealth <= 0 && !victim->ToCreature()->GetSpellHistory()->HasCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL))
                {
                    // Cast healing spell, completely avoid damage
                    absorbAmount = dmgInfo.GetDamage();

                    uint32 defenseSkillValue = victim->GetDefenseSkillValue();
                    // Max heal when defense skill denies critical hits from raid bosses
                    // Formula: max defense at level + 140 (raiting from gear)
                    uint32 reqDefForMaxHeal  = victim->getLevel() * 5 + 140;
                    float pctFromDefense = (defenseSkillValue >= reqDefForMaxHeal)
                                           ? 1.0f
                                           : float(defenseSkillValue) / float(reqDefForMaxHeal);

                    int32 healAmount = int32(victim->CountPctFromMaxHealth(int32(healPct * pctFromDefense)));
                    victim->CastCustomSpell(victim, PAL_SPELL_ARDENT_DEFENDER_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff);
                    victim->ToCreature()->AddBotSpellCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL, 120 * IN_MILLISECONDS);
                }
                else if (remainingHealth < int32(allowedHealth))
                {
                    // Reduce damage that brings us under 35% (or full damage if we are already under 35%) by x%
                    uint32 damageToReduce = (victim->GetHealth() < allowedHealth)
                                            ? dmgInfo.GetDamage()
                                            : allowedHealth - remainingHealth;
                    absorbAmount = CalculatePct(damageToReduce, absorbPct);
                }

                return;
            }
            //end npcbot

            // If damage kills us
            if (remainingHealth <= 0 && !victim->GetSpellHistory()->HasCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL))
            {
                // Cast healing spell, completely avoid damage
                absorbAmount = dmgInfo.GetDamage();

                uint32 defenseSkillValue = victim->GetDefenseSkillValue();
                // Max heal when defense skill denies critical hits from raid bosses
                // Formula: max defense at level + 140 (raiting from gear)
                uint32 reqDefForMaxHeal  = victim->getLevel() * 5 + 140;
                float pctFromDefense = (defenseSkillValue >= reqDefForMaxHeal)
                                       ? 1.0f
                                       : float(defenseSkillValue) / float(reqDefForMaxHeal);

                int32 healAmount = int32(victim->CountPctFromMaxHealth(uint32(healPct * pctFromDefense)));
                victim->CastCustomSpell(victim, PAL_SPELL_ARDENT_DEFENDER_HEAL, &healAmount, NULL, NULL, true, NULL, aurEff);
                victim->GetSpellHistory()->AddCooldown(PAL_SPELL_ARDENT_DEFENDER_HEAL, 0, std::chrono::minutes(2));
            }
            else if (remainingHealth < int32(allowedHealth))
            {
                // Reduce damage that brings us under 35% (or full damage if we are already under 35%) by x%
                uint32 damageToReduce = (victim->GetHealth() < allowedHealth)
                                        ? dmgInfo.GetDamage()
                                        : allowedHealth - remainingHealth;
                absorbAmount = CalculatePct(damageToReduce, absorbPct);
            }
        }
Example #4
0
void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
{
    uint32 spellId;
    uint8  cast_count;
    recvPacket >> spellId;
    recvPacket >> cast_count;

    DEBUG_LOG("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i",
              spellId, cast_count, recvPacket.size());

    SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);

    if (!spellInfo)
    {
        sLog.outError("WORLD: unknown spell id %u", spellId);
        return;
    }

    // not have spell or spell passive and not casted by client
    if (!_player->HasSpell (spellId) || IsPassiveSpell(spellId))
    {
        //cheater? kick? ban?
        return;
    }

    // can't use our own spells when we're in possession of another unit,
    if (_player->isPossessing())
        return;

    // client provided targets
    SpellCastTargets targets;

    recvPacket >> targets.ReadForCaster(_player);

    Unit* target = targets.getUnitTarget();
    if (target) // auto-selection buff level base at target level (in spellInfo)
    {
        // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message
        if (SpellEntry const* actualSpellInfo = sSpellMgr.SelectAuraRankForPlayerLevel(spellInfo, target->getLevel()))
            spellInfo = actualSpellInfo;
    }

    if (spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)
    {
        if (_player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && _player->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo->Id == spellInfo->Id)
            return;
    }

    // When casting a combat spell the unit has to be flagged as initiating combat
    // No need to check if spell is self-cast because combat spells can only be cast on self with commands
    if (target && !IsNonCombatSpell(spellInfo))
        _player->setInitiatingCombat(true);

    Spell* spell = new Spell(_player, spellInfo, false);
    spell->m_cast_count = cast_count;                       // set count of casts
    spell->prepare(&targets);
}