diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/game/Player.cpp | 94 | ||||
| -rw-r--r-- | src/game/Player.h | 2 | ||||
| -rw-r--r-- | src/game/SpellMgr.cpp | 52 | ||||
| -rw-r--r-- | src/game/SpellMgr.h | 19 | ||||
| -rw-r--r-- | src/game/Unit.cpp | 44 | ||||
| -rw-r--r-- | src/game/World.cpp | 3 |
6 files changed, 178 insertions, 36 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 341742dd3b1..18426621300 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -6991,7 +6991,7 @@ void Player::UpdateEquipSpellsAtFormChange() } } -void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType) +void Player::CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo) { if(!item || item->IsBroken()) return; @@ -7000,46 +7000,53 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy if(!proto) return; + Unit * Target = damageInfo->target; + WeaponAttackType attType = damageInfo->attackType; + if (!Target || Target == this ) return; - for (int i = 0; i < 5; i++) + // Can do effect if any damage done to target + if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE) { - _Spell const& spellData = proto->Spells[i]; + for (int i = 0; i < 5; i++) + { + _Spell const& spellData = proto->Spells[i]; - // no spell - if(!spellData.SpellId ) - continue; + // no spell + if(!spellData.SpellId ) + continue; - // wrong triggering type - if(spellData.SpellTrigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT) - continue; + // wrong triggering type + if(spellData.SpellTrigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT) + continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); - if(!spellInfo) - { - sLog.outError("WORLD: unknown Item spellid %i", spellData.SpellId); - continue; - } + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); + if(!spellInfo) + { + sLog.outError("WORLD: unknown Item spellid %i", spellData.SpellId); + continue; + } - // not allow proc extra attack spell at extra attack - if( m_extraAttacks && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) - return; + // not allow proc extra attack spell at extra attack + if( m_extraAttacks && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) + return; - float chance = spellInfo->procChance; + float chance = spellInfo->procChance; - if(spellData.SpellPPMRate) - { - uint32 WeaponSpeed = GetAttackTime(attType); - chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate); - } - else if(chance > 100.0f) - { - chance = GetWeaponProcChance(); - } + if(spellData.SpellPPMRate) + { + uint32 WeaponSpeed = GetAttackTime(attType); + chance = GetPPMProcChance(WeaponSpeed, spellData.SpellPPMRate); + } + else if(chance > 100.0f) + { + chance = GetWeaponProcChance(); + } - if (roll_chance_f(chance)) - CastSpell(Target, spellInfo->Id, true, item); + if (roll_chance_f(chance)) + CastSpell(Target, spellInfo->Id, true, item); + } } // item combat enchantments @@ -7053,6 +7060,21 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL) continue; + SpellEnchantProcEntry const* entry = spellmgr.GetSpellEnchantProcEvent(enchant_id); + + if (entry && entry->procEx) + { + // Check hit/crit/dodge/parry requirement + if((entry->procEx & damageInfo->procEx) == 0) + continue; + } + else + { + // Can do effect if any damage done to target + if (!(damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE)) + continue; + } + SpellEntry const *spellInfo = sSpellStore.LookupEntry(pEnchant->spellid[s]); if (!spellInfo) { @@ -7061,6 +7083,18 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy } float chance = pEnchant->amount[s] != 0 ? float(pEnchant->amount[s]) : GetWeaponProcChance(); + + if (entry && entry->PPMChance) + { + uint32 WeaponSpeed = GetAttackTime(attType); + chance = GetPPMProcChance(WeaponSpeed, entry->PPMChance); + } + else if (entry && entry->customChance) + chance = entry->customChance; + + // Apply spell mods + ApplySpellMod(pEnchant->spellid[s],SPELLMOD_CHANCE_OF_SUCCESS,chance); + if (roll_chance_f(chance)) { if(IsPositiveSpell(pEnchant->spellid[s])) diff --git a/src/game/Player.h b/src/game/Player.h index 7d530a57228..fbe365173dc 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1797,7 +1797,7 @@ class TRINITY_DLL_SPEC Player : public Unit void ApplyItemEquipSpell(Item *item, bool apply, bool form_change = false); void ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change = false); void UpdateEquipSpellsAtFormChange(); - void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType); + void CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo); void SendInitWorldStates(bool force = false, uint32 forceZoneId = 0); void SendUpdateWorldState(uint32 Field, uint32 Value); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 8e01742587c..3a22efd71d6 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1330,6 +1330,58 @@ void SpellMgr::LoadSpellThreats() sLog.outString(); } +void SpellMgr::LoadSpellEnchantProcData() +{ + mSpellEnchantProcEventMap.clear(); // need for reload case + + uint32 count = 0; + + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT entry, customChance, PPMChance, procEx"); + if( !result ) + { + + barGoLink bar( 1 ); + + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded %u spell enchant proc event conditions", count ); + return; + } + + barGoLink bar( result->GetRowCount() ); + do + { + Field *fields = result->Fetch(); + + bar.step(); + + uint32 enchantId = fields[0].GetUInt32(); + + SpellItemEnchantmentEntry const *ench = sSpellItemEnchantmentStore.LookupEntry(enchantId); + if (!ench) + { + sLog.outErrorDb("Enchancment %u listed in `spell_enchant_proc_data` does not exist", enchantId); + continue; + } + + SpellEnchantProcEntry spe; + + spe.customChance = fields[1].GetUInt32(); + spe.PPMChance = fields[2].GetFloat(); + spe.procEx = fields[3].GetUInt32(); + + mSpellEnchantProcEventMap[enchantId] = spe; + + ++count; + } while( result->NextRow() ); + + delete result; + + sLog.outString( ">> Loaded %u enchant proc data definitions", count); +} + bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const { SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 70b81403a52..749abab0efb 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -564,6 +564,15 @@ struct SpellProcEventEntry typedef UNORDERED_MAP<uint32, SpellProcEventEntry> SpellProcEventMap; +struct SpellEnchantProcEntry +{ + uint32 customChance; + float PPMChance; + uint32 procEx; +}; + +typedef UNORDERED_MAP<uint32, SpellEnchantProcEntry> SpellEnchantProcEventMap; + #define ELIXIR_BATTLE_MASK 0x1 #define ELIXIR_GUARDIAN_MASK 0x2 #define ELIXIR_FLASK_MASK (ELIXIR_BATTLE_MASK|ELIXIR_GUARDIAN_MASK) @@ -785,6 +794,14 @@ class SpellMgr static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active); + SpellEnchantProcEntry const* GetSpellEnchantProcEvent(uint32 enchId) const + { + SpellEnchantProcEventMap::const_iterator itr = mSpellEnchantProcEventMap.find(enchId); + if( itr != mSpellEnchantProcEventMap.end( ) ) + return &itr->second; + return NULL; + } + // Spell target coordinates SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id) const { @@ -986,6 +1003,7 @@ class SpellMgr void LoadSpellPetAuras(); void LoadSpellCustomAttr(); void LoadSpellLinked(); + void LoadSpellEnchantProcData(); private: SpellScriptTarget mSpellScriptTarget; @@ -1002,6 +1020,7 @@ class SpellMgr SpellPetAuraMap mSpellPetAuraMap; SpellCustomAttribute mSpellCustomAttr; SpellLinkedMap mSpellLinkedMap; + SpellEnchantProcEventMap mSpellEnchantProcEventMap; }; #define spellmgr SpellMgr::Instance() diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index cac26755d3f..a4963e37d5b 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1611,15 +1611,49 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) } } - // If not miss - if (!(damageInfo->HitInfo & HITINFO_MISS)) + if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive()) { - if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive()) + for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) { - for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) - ((Player*)this)->CastItemCombatSpell(((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i), pVictim, damageInfo->attackType); + EquipmentSlots slot = (EquipmentSlots)i; + // For weapon slots check if valid attack type and if weapon useable + if (i == EQUIPMENT_SLOT_MAINHAND + || i == EQUIPMENT_SLOT_OFFHAND + || i == EQUIPMENT_SLOT_RANGED) + { + switch (damageInfo->attackType) + { + case BASE_ATTACK: slot = EQUIPMENT_SLOT_MAINHAND; break; + case OFF_ATTACK: slot = EQUIPMENT_SLOT_OFFHAND; break; + case RANGED_ATTACK: slot = EQUIPMENT_SLOT_RANGED; break; + } + // offhand item cannot proc from main hand hit etc + if (slot != i) + slot=EQUIPMENT_SLOT_END; + else + { + // Check if item is useable (forms or disarm) + if (damageInfo->attackType == BASE_ATTACK) + { + if (!((Player*)this)->IsUseEquipedWeapon(true)) + slot=EQUIPMENT_SLOT_END; + } + else + { + if (((Player*)this)->IsInFeralForm()) + slot=EQUIPMENT_SLOT_END; + } + } + } + // If usable, try to cast item spell + if(slot!=EQUIPMENT_SLOT_END) + (((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i), &damageInfo); } + } + // Do effect if any damage done to target + if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE) + { // victim's damage shield std::set<Aura*> alreadyDone; uint32 removedAuras = pVictim->m_removedAuras; diff --git a/src/game/World.cpp b/src/game/World.cpp index 5edd15fa472..a58103ef437 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1150,6 +1150,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading NPC Texts..." ); objmgr.LoadGossipText(); + sLog.outString( "Loading Enchant Spells Proc datas..."); + spellmgr.LoadSpellEnchantProcData(); + sLog.outString( "Loading Item Random Enchantments Table..." ); LoadRandomEnchantmentsTable(); |
