Ejemplo n.º 1
0
void Item::ModifyEnchantmentTime( uint32 Slot, uint32 Duration )
{
	EnchantmentMap::iterator itr = Enchantments.find( Slot );
	if( itr == Enchantments.end() )
		return;

	// Reset the apply time.
	itr->second.ApplyTime = UNIXTIME;
	itr->second.Duration = Duration;

	// Change the event timer.
	event_ModifyTimeAndTimeLeft( EVENT_REMOVE_ENCHANTMENT1 + Slot, Duration * 1000 );

	// Send update packet
	SendEnchantTimeUpdate( itr->second.Slot, Duration );
}
Ejemplo n.º 2
0
void Item::ApplyEnchantmentBonus( uint32 Slot, bool Apply )
{
	if( m_owner == NULL )
		return;

	EnchantmentMap::iterator itr = Enchantments.find( Slot );
	if( itr == Enchantments.end() )
		return;

	EnchantEntry* Entry = itr->second.Enchantment;
	uint32 RandomSuffixAmount = itr->second.RandomSuffix;

	if( itr->second.BonusApplied == Apply )
		return;

	itr->second.BonusApplied = Apply;

	if( Apply )
	{
		// Send the enchantment time update packet.
		SendEnchantTimeUpdate( itr->second.Slot, itr->second.Duration );
	}

	// Apply the visual on the player.
	uint32 ItemSlot = m_owner->GetItemInterface()->GetInventorySlotByGuid( GetGUID() ) * 16;
	uint32 VisibleBase = PLAYER_VISIBLE_ITEM_1_0 + ItemSlot;
	m_owner->SetUInt32Value( VisibleBase + 1 + Slot, Apply ? Entry->Id : 0 );

	// Another one of those for loop that where not indented properly god knows what will break
	// but i made it actually affect the code below it
	for( uint32 c = 0; c < 3; c++ )
	{
		if( Entry->type[c] )
		{
			// Depending on the enchantment type, take the appropriate course of action.
			switch( Entry->type[c] )
			{
			case 1:		 // Trigger spell on melee attack.
				{
					if( Apply && Entry->spell[c] != 0 )
					{
						// Create a proc trigger spell

						ProcTriggerSpell TS;
						TS.caster = m_owner->GetGUID();
						TS.origId = 0;
						TS.procFlags = PROC_ON_MELEE_ATTACK;
						TS.procCharges = 0;
						/* This needs to be modified based on the attack speed of the weapon.
						 * Secondly, need to assign some static chance for instant attacks (ss,
						 * gouge, etc.) */
						if( !Entry->min[c] && GetProto()->Class == 2 )
						{
							float speed = (float)GetProto()->Delay;
							/////// procChance calc ///////
							float ppm = 0;
							SpellEntry* sp = dbcSpell.LookupEntry( Entry->spell[c] );
							if( sp )
							{
								switch( sp->NameHash )
								{
								case SPELL_HASH_FROSTBRAND_ATTACK:
									ppm = 9;
									break;
								}
							}
							if( ppm != 0 )
							{
								float pcount = 60/ppm;
								float chance = (speed/10) / pcount;
								TS.procChance = (uint32)chance;
							}
							else
								TS.procChance = (uint32)( speed / 600.0f );
							///////////////////////////////
						}
						else
							TS.procChance = Entry->min[c];
						Log.Debug( "Enchant", "Setting procChance to %u%%.", TS.procChance );
						TS.deleted = false;
						TS.spellId = Entry->spell[c];
						TS.groupRelation = 0;
						TS.ProcType = 0;
						TS.LastTrigger = 0;
						m_owner->m_procSpells.push_back( TS );
					}
					else
					{
						// Remove the proctriggerspell
						uint32 SpellId;
						list< struct ProcTriggerSpell >::iterator itr/*, itr2*/;
						for( itr = m_owner->m_procSpells.begin(); itr != m_owner->m_procSpells.end(); )
						{
							SpellId = itr->spellId;
							/*itr2 = itr++;*/
							
							if( SpellId == Entry->spell[c] )
							{
								//m_owner->m_procSpells.erase(itr2);
								itr->deleted = true;
							}
							itr++;
						}
					}
				}break;

			case 2:		 // Mod damage done.
				{
					int32 val = Entry->min[c];
					if( RandomSuffixAmount )
						val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

					if( Apply )
						m_owner->ModUnsigned32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS, val );
					else
						m_owner->ModUnsigned32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS, -val );
					m_owner->CalcDamage();
				}break;

			case 3:		 // Cast spell (usually means apply aura)
				{
					if( Apply )
					{
						SpellCastTargets targets( m_owner->GetGUID() );
						SpellEntry* sp;
						Spell* spell;
						
						if( Entry->spell[c] != 0 )
						{
							sp = dbcSpell.LookupEntry( Entry->spell[c] );
							if( sp == NULL )
								continue;

							spell = SpellPool.PooledNew();
							spell->Init( m_owner, sp, true, 0 );
							spell->i_caster = this;
							spell->prepare( &targets );
						}
					}
					else
					{
						if( Entry->spell[c] != 0 )
								m_owner->RemoveAura( Entry->spell[c] );
					}

				}break;

			case 4:		 // Modify physical resistance
				{
					int32 val = Entry->min[c];
					if( RandomSuffixAmount )
						val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

					if( Apply )
					{
						m_owner->FlatResistanceModifierPos[Entry->spell[c]] += val;
					}
					else
					{
						m_owner->FlatResistanceModifierPos[Entry->spell[c]] -= val;
					}
					m_owner->CalcResistance( Entry->spell[c] );
				}break;

			case 5:	 //Modify rating ...order is PLAYER_FIELD_COMBAT_RATING_1 and above
				{
					//spellid is enum ITEM_STAT_TYPE
					//min=max is amount
					int32 val = Entry->min[c];
					if( RandomSuffixAmount )
						val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

					m_owner->ModifyBonuses( Entry->spell[c], val, Apply );
					m_owner->UpdateStats();
				}break;

			case 6:	 // Rockbiter weapon (increase damage per second... how the hell do you calc that)
				{
					if( Apply )
					{
						//m_owner->ModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, Entry->min[c]);
						//if i'm not wrong then we should apply DMPS formula for this. This will have somewhat a larger value 28->34
						int32 val = Entry->min[c];
						if( RandomSuffixAmount )
							val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

						int32 value = GetProto()->Delay * val / 1000;
						m_owner->ModUnsigned32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS, value );
					}
					else
					{
						int32 val = Entry->min[c];
						if( RandomSuffixAmount )
							val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

						int32 value =- (int32)(GetProto()->Delay * val / 1000 );
						m_owner->ModUnsigned32Value( PLAYER_FIELD_MOD_DAMAGE_DONE_POS, value );
					}
					m_owner->CalcDamage();
				}break;

			default:
				{
					sLog.outError( "Unknown enchantment type: %u (%u)", Entry->type[c], Entry->Id );
				}break;
			}
		}
	}
}
Ejemplo n.º 3
0
void Item::ApplyEnchantmentBonus( uint32 Slot, bool Apply )
{
    if( m_owner == NULL )
        return;

    EnchantmentMap::iterator itr = Enchantments.find( Slot );
    if( itr == Enchantments.end() )
        return;

    EnchantEntry* Entry = itr->second.Enchantment;
    uint32 RandomSuffixAmount = itr->second.RandomSuffix;

    if( itr->second.Dummy )
        return;

    if( itr->second.BonusApplied == Apply )
        return;

    itr->second.BonusApplied = Apply;

    // Apply the visual on the player.
    uint32 ItemSlot = m_owner->GetItemInterface()->GetInventorySlotByGuid( GetGUID() );
    if(ItemSlot < EQUIPMENT_SLOT_END && Slot < 1)
    {
        uint32 VisibleBase = PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + ItemSlot * PLAYER_VISIBLE_ITEM_LENGTH;
        m_owner->SetUInt16Value( VisibleBase, Slot, Apply ? Entry->Id : 0 );
    }

    if( Apply )
    {
        // Send the enchantment time update packet.
        SendEnchantTimeUpdate( itr->second.Slot, itr->second.Duration );
    }

    // Another one of those for loop that where not indented properly god knows what will break
    // but i made it actually affect the code below it
    for( uint32 c = 0; c < 3; c++ )
    {
        if( Entry->type[c] )
        {
            // Depending on the enchantment type, take the appropriate course of action.
            switch( Entry->type[c] )
            {
            case 1:      // Trigger spell on melee attack.
                {
                    if( Apply && Entry->spell[c] != 0 )
                    {
                        // Create a proc trigger spell
                        ProcTriggerSpell TS;
                        memset(&TS, 0, sizeof(ProcTriggerSpell));
                        TS.caster = m_owner->GetGUID();
                        TS.procFlags = PROC_ON_MELEE_ATTACK;
                        TS.origId = 0;
                        TS.procflags2 = 0;
                        TS.SpellClassMask[0] = 0;
                        TS.SpellClassMask[1] = 0;
                        TS.SpellClassMask[2] = 0;
                        TS.ProcType = 0;
                        TS.LastTrigger = 0;
                        TS.procValue = 0;
                        TS.procCharges = 0;
                        TS.procChance = 10;

                        if(ItemSlot == EQUIPMENT_SLOT_MAINHAND)
                            TS.weapon_damage_type = 1; // Proc only on main hand attacks
                        else if(ItemSlot == EQUIPMENT_SLOT_OFFHAND)
                            TS.weapon_damage_type = 2; // Proc only on off hand attacks
                        else
                            TS.weapon_damage_type = 0; // Doesn't depend on weapon

                        /* This needs to be modified based on the attack speed of the weapon.
                         * Secondly, need to assign some static chance for instant attacks (ss,
                         * gouge, etc.) */
                        if( GetProto()->Class == ITEM_CLASS_WEAPON )
                        {
                            if( !Entry->min[c] )
                            {
                                float speed = (float)GetProto()->Delay;

                                /////// procChance calc ///////
                                float ppm = 0;
                                SpellEntry* sp = dbcSpell.LookupEntry( Entry->spell[c] );
                                if( sp )
                                {
                                    switch( sp->NameHash )
                                    {
                                    case SPELL_HASH_FROSTBRAND_ATTACK:
                                        ppm = 9;
                                        break;
                                    }
                                }
                                if( ppm != 0 )
                                {
                                    float pcount = 60/ppm;
                                    float chance = (speed/10) / pcount;
                                    TS.procChance = (uint32)chance;
                                }
                                else
                                    TS.procChance = (uint32)( speed / 600.0f );
                                ///////////////////////////////
                            }
                            else
                                TS.procChance = Entry->min[c];
                        }

                        sLog.Debug( "Enchant", "Setting procChance to %u%%.", TS.procChance );
                        TS.deleted = false;
                        TS.spellId = Entry->spell[c];
                        m_owner->m_procSpells.push_back( TS );
                    }
                    else
                    {
                        // Remove the proctriggerspell
                        uint32 SpellId;
                        list< struct ProcTriggerSpell >::iterator itr/*, itr2*/;
                        for( itr = m_owner->m_procSpells.begin(); itr != m_owner->m_procSpells.end(); )
                        {
                            SpellId = itr->spellId;
                            /*itr2 = itr;*/
                            /*++itr;*/

                            if( SpellId == Entry->spell[c] )
                            {
                                //m_owner->m_procSpells.erase(itr2);
                                itr->deleted = true;
                            }
                            ++itr;
                        }
                    }
                }break;

            case 2:      // Mod damage done.
                {
                    int32 val = Entry->min[c];
                    if( RandomSuffixAmount )
                        val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

                    if( Apply )
                        m_owner->DamageDonePosMod[0] += val;
                    else
                        m_owner->DamageDonePosMod[0] -= val;
                    m_owner->UpdateStats();
                }break;

            case 3:      // Cast spell (usually means apply aura)
                {
                    if( Apply )
                    {
                        SpellCastTargets targets( m_owner->GetGUID() );
                        SpellEntry* sp;

                        if( Entry->spell[c] != 0 )
                        {
                            sp = dbcSpell.LookupEntry( Entry->spell[c] );
                            if( sp == NULL )
                                continue;

                            Spell* spell = NULLSPELL;
                            //Never found out why,
                            //but this Blade of Life's Inevitability spell must be casted by the item, not owner.
                            if( m_itemProto->ItemId != 34349  )
                                spell = (new Spell( m_owner, sp, true, NULLAURA ));
                            else
                                spell = (new Spell( TO_ITEM(this), sp, true, NULLAURA ));

                            spell->i_caster = TO_ITEM(this);
                            spell->prepare( &targets );
                        }
                    }
                    else
                    {
                        if( Entry->spell[c] != 0 )
                            m_owner->RemoveAura( Entry->spell[c] );
                    }
                }break;

            case 4:      // Modify physical resistance
                {
                    int32 val = Entry->min[c];
                    if( RandomSuffixAmount )
                        val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

                    if( Apply )
                        m_owner->FlatResistanceModifierPos[Entry->spell[c]] += val;
                    else
                        m_owner->FlatResistanceModifierPos[Entry->spell[c]] -= val;
                    m_owner->CalcResistance( Entry->spell[c] );
                }break;

            case 5:  //Modify rating ...order is PLAYER_FIELD_COMBAT_RATING_1 and above
                {
                    //spellid is enum ITEM_STAT_TYPE
                    //min=max is amount
                    int32 val = Entry->min[c];
                    if( RandomSuffixAmount )
                        val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

                    m_owner->ModifyBonuses( Entry->spell[c], Apply ? val : -val );
                }break;

            case 6:  // Rockbiter weapon (increase damage per second... how the hell do you calc that)
                {
                    if( Apply )
                    {
                        //if i'm not wrong then we should apply DMPS formula for this. This will have somewhat a larger value 28->34
                        int32 val = Entry->min[c];
                        if( RandomSuffixAmount )
                            val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

                        //int32 value = GetProto()->Delay * val / 1000;
                        m_owner->DamageDonePosMod[0] += val;
                    }
                    else
                    {
                        int32 val = Entry->min[c];
                        if( RandomSuffixAmount )
                            val = RANDOM_SUFFIX_MAGIC_CALCULATION( RandomSuffixAmount, GetItemRandomSuffixFactor() );

                        //int32 value =- (int32)(GetProto()->Delay * val / 1000 );
                        m_owner->DamageDonePosMod[0] += val;
                    }
                    m_owner->UpdateStats();
                }break;

            case 7:
                {
                    if( Apply )
                    {
                        for( uint32 i = 0; i < 3; ++i )
                            OnUseSpells[ i ] = Entry->spell[ i ];
                    }
                    else
                    {
                        for( uint32 i = 0; i < 3; ++i )
                            OnUseSpells[ i ] = 0;
                    }
                }break;

            case 8:{}break;

            default:
                {
                    sLog.Debug( "Enchant","Unknown enchantment type: %u (%u)", Entry->type[c], Entry->Id );
                }break;
            }
        }
    }
}
Ejemplo n.º 4
0
void Item::ApplyEnchantmentBonus(uint32 Slot, bool Apply)
{
    if (m_owner == NULL)
        return;

    EnchantmentMap::iterator itr = Enchantments.find(Slot);
    if (itr == Enchantments.end())
        return;

    EnchantEntry* Entry = itr->second.Enchantment;
    uint32 RandomSuffixAmount = itr->second.RandomSuffix;

    if (itr->second.BonusApplied == Apply)
        return;

    itr->second.BonusApplied = Apply;

    if (Apply)
    {
        // Send the enchantment time update packet.
        SendEnchantTimeUpdate(itr->second.Slot, itr->second.Duration);
    }

    // Apply the visual on the player.
    uint32 ItemSlot = m_owner->GetItemInterface()->GetInventorySlotByGuid(GetGUID()) * PLAYER_VISIBLE_ITEM_LENGTH;   //VLack: for 3.1.1 "* 18" is a bad idea, now it's "* 2"; but this could have been calculated based on UpdateFields.h! This is PLAYER_VISIBLE_ITEM_LENGTH
    uint32 VisibleBase = PLAYER_VISIBLE_ITEM_1_ENCHANTMENT + ItemSlot;
    if (VisibleBase <= PLAYER_VISIBLE_ITEM_19_ENCHANTMENT)
        m_owner->SetUInt32Value(VisibleBase, Apply ? Entry->Id : 0);   //On 3.1 we can't add a Slot to the base now, as we no longer have multiple fields for storing them. This in some cases will try to write for example 3 visuals into one place, but now every item has only one field for this, and as we can't choose which visual to have, we'll accept the last one.
    else
        LOG_ERROR("Item::ApplyEnchantmentBonus visual out of range! Tried to address UInt32 field %i !!!", VisibleBase);

    // Another one of those for loop that where not indented properly god knows what will break
    // but i made it actually affect the code below it
    for (uint32 c = 0; c < 3; c++)
    {
        if (Entry->type[c])
        {
            // Depending on the enchantment type, take the appropriate course of action.
            switch (Entry->type[c])
            {
            case 1:         // Trigger spell on melee attack.
            {
                if (Apply)
                {
                    if (Entry->spell[c] != 0)
                        m_owner->AddProcTriggerSpell(Entry->spell[c], 0, m_owner->GetGUID(), Entry->min[c], PROC_ON_MELEE_ATTACK, 0, NULL, NULL, this);
                }
                else
                {
                    m_owner->RemoveProcTriggerSpell(Entry->spell[c], m_owner->GetGUID(), GetGUID());
                }
            }
                break;

            case 2:         // Mod damage done.
            {
                int32 val = Entry->min[c];
                if (RandomSuffixAmount)
                    val = RANDOM_SUFFIX_MAGIC_CALCULATION(RandomSuffixAmount, GetItemRandomSuffixFactor());

                if (Apply)
                    m_owner->ModPosDamageDoneMod(SCHOOL_NORMAL, val);
                else
                    m_owner->ModPosDamageDoneMod(SCHOOL_NORMAL, -val);
                m_owner->CalcDamage();
            }
                break;

            case 3:         // Cast spell (usually means apply aura)
            {
                if (Apply)
                {
                    SpellCastTargets targets(m_owner->GetGUID());
                    SpellEntry* sp;
                    Spell* spell;

                    if (Entry->spell[c] != 0)
                    {
                        sp = dbcSpell.LookupEntryForced(Entry->spell[c]);
                        if (sp == NULL)
                            continue;

                        spell = sSpellFactoryMgr.NewSpell(m_owner, sp, true, 0);
                        spell->i_caster = this;
                        spell->prepare(&targets);
                    }
                }
                else
                {
                    if (Entry->spell[c] != 0)
                        m_owner->RemoveAuraByItemGUID(Entry->spell[c], GetGUID());
                }
            }
                break;

            case 4:         // Modify physical resistance
            {
                int32 val = Entry->min[c];
                if (RandomSuffixAmount)
                    val = RANDOM_SUFFIX_MAGIC_CALCULATION(RandomSuffixAmount, GetItemRandomSuffixFactor());

                if (Apply)
                {
                    m_owner->FlatResistanceModifierPos[Entry->spell[c]] += val;
                }
                else
                {
                    m_owner->FlatResistanceModifierPos[Entry->spell[c]] -= val;
                }
                m_owner->CalcResistance(Entry->spell[c]);
            }
                break;

            case 5:     //Modify rating ...order is PLAYER_FIELD_COMBAT_RATING_1 and above
            {
                //spellid is enum ITEM_STAT_TYPE
                //min=max is amount
                int32 val = Entry->min[c];
                if (RandomSuffixAmount)
                    val = RANDOM_SUFFIX_MAGIC_CALCULATION(RandomSuffixAmount, GetItemRandomSuffixFactor());

                m_owner->ModifyBonuses(Entry->spell[c], val, Apply);
                m_owner->UpdateStats();
            }
                break;

            case 6:     // Rockbiter weapon (increase damage per second... how the hell do you calc that)
            {
                if (Apply)
                {
                    //m_owner->ModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS, Entry->min[c]);
                    //if I'm not wrong then we should apply DMPS formula for this. This will have somewhat a larger value 28->34
                    int32 val = Entry->min[c];
                    if (RandomSuffixAmount)
                        val = RANDOM_SUFFIX_MAGIC_CALCULATION(RandomSuffixAmount, GetItemRandomSuffixFactor());

                    int32 value = GetProto()->Delay * val / 1000;
                    m_owner->ModPosDamageDoneMod(SCHOOL_NORMAL, value);
                }
                else
                {
                    int32 val = Entry->min[c];
                    if (RandomSuffixAmount)
                        val = RANDOM_SUFFIX_MAGIC_CALCULATION(RandomSuffixAmount, GetItemRandomSuffixFactor());

                    int32 value = -(int32)(GetProto()->Delay * val / 1000);
                    m_owner->ModPosDamageDoneMod(SCHOOL_NORMAL, value);
                }
                m_owner->CalcDamage();
            }
                break;

            case 7:
            {
                if (Apply)
                {
                    for (uint32 i = 0; i < 3; ++i)
                        OnUseSpellIDs[i] = Entry->spell[i];
                }
                else
                {
                    for (uint32 i = 0; i < 3; ++i)
                        OnUseSpellIDs[i] = 0;
                }
                break;
            }

            case 8:
            {
                // Adding a prismatic socket to belt, hands, etc is type 8, it has no bonus to apply HERE
                break;
            }

            default:
            {
                LOG_ERROR("Unknown enchantment type: %u (%u)", Entry->type[c], Entry->Id);
            }
                break;
            }
        }
    }
}