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; } } } }
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; } } } }
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; } } } }