From fcf0fdc1c15d42b228d11ae1d325df08d1bbeab2 Mon Sep 17 00:00:00 2001 From: QAston Date: Sun, 10 May 2009 18:06:22 +0200 Subject: [PATCH 1/6] *Item enchancment/proc patch - original code by Thenecromancer --HG-- branch : trunk --- sql/updates/latest.sql | 13 ++++++ src/game/Player.cpp | 104 +++++++++++++++++++++++++++-------------- src/game/Player.h | 2 +- src/game/SpellMgr.cpp | 52 +++++++++++++++++++++ src/game/SpellMgr.h | 19 ++++++++ src/game/Unit.cpp | 44 +++++++++++++++-- src/game/World.cpp | 3 ++ 7 files changed, 196 insertions(+), 41 deletions(-) create mode 100644 sql/updates/latest.sql diff --git a/sql/updates/latest.sql b/sql/updates/latest.sql new file mode 100644 index 00000000000..0a25eaefc46 --- /dev/null +++ b/sql/updates/latest.sql @@ -0,0 +1,13 @@ +CREATE TABLE `spell_enchant_proc_data` ( + `entry` INT(10) UNSIGNED NOT NULL, + `customChance` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `PPMChance` FLOAT UNSIGNED NOT NULL DEFAULT '0', + `procEx` FLOAT UNSIGNED NOT NULL DEFAULT '0' +) ENGINE=MYISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Spell enchant proc data'; + +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (2, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (12, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (524, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (1667, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (1668, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (2635, 0, 8.8,0); 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]; - - // no spell - if(!spellData.SpellId ) - continue; - - // wrong triggering type - if(spellData.SpellTrigger != ITEM_SPELLTRIGGER_CHANCE_ON_HIT) - continue; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); - if(!spellInfo) + for (int i = 0; i < 5; i++) { - sLog.outError("WORLD: unknown Item spellid %i", spellData.SpellId); - continue; + _Spell const& spellData = proto->Spells[i]; + + // no spell + if(!spellData.SpellId ) + 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; + } + + // not allow proc extra attack spell at extra attack + if( m_extraAttacks && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) + return; + + float chance = spellInfo->procChance; + + 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); } - - // not allow proc extra attack spell at extra attack - if( m_extraAttacks && IsSpellHaveEffect(spellInfo,SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) - return; - - float chance = spellInfo->procChance; - - 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); } // 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 SpellProcEventMap; +struct SpellEnchantProcEntry +{ + uint32 customChance; + float PPMChance; + uint32 procEx; +}; + +typedef UNORDERED_MAP 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 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(); From 9171455b73e5aaf685a5541e1b79e3a6c84c024b Mon Sep 17 00:00:00 2001 From: ArcticDevil Date: Sun, 10 May 2009 18:49:04 +0200 Subject: [PATCH 2/6] Send cc aura duration to party members --HG-- branch : trunk --- sql/updates/TC1_1486_world.sql | 13 +++++++++++++ src/game/SpellAuras.cpp | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 sql/updates/TC1_1486_world.sql diff --git a/sql/updates/TC1_1486_world.sql b/sql/updates/TC1_1486_world.sql new file mode 100644 index 00000000000..0a25eaefc46 --- /dev/null +++ b/sql/updates/TC1_1486_world.sql @@ -0,0 +1,13 @@ +CREATE TABLE `spell_enchant_proc_data` ( + `entry` INT(10) UNSIGNED NOT NULL, + `customChance` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `PPMChance` FLOAT UNSIGNED NOT NULL DEFAULT '0', + `procEx` FLOAT UNSIGNED NOT NULL DEFAULT '0' +) ENGINE=MYISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Spell enchant proc data'; + +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (2, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (12, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (524, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (1667, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (1668, 0, 8.8,0); +INSERT INTO spell_enchant_proc_data (`entry`, `customChance`, `PPMChance`,`procEx`) VALUES (2635, 0, 8.8,0); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c2be850370c..8c9c640c86b 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -774,12 +774,28 @@ void Aura::UpdateAuraDuration() Unit* caster = GetCaster(); - if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target) + if(caster && caster->GetTypeId() == TYPEID_PLAYER) + { SendAuraDurationForCaster((Player*)caster); + + Group* CasterGroup = ((Player*)caster)->GetGroup(); + if (CasterGroup && (spellmgr.GetSpellCustomAttr(GetId()) & SPELL_ATTR_CU_AURA_CC)) + { + for (GroupReference *itr = CasterGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* player = itr->getSource(); + if(player && player != caster) + SendAuraDurationForCaster(player); + } + } + } } void Aura::SendAuraDurationForCaster(Player* caster) { + if (caster == m_target) + return; + WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4)); data.append(m_target->GetPackGUID()); data << uint8(m_auraSlot); From 53b3c9a6dc6cf96a0ce0769a3ad431f1d6c4768c Mon Sep 17 00:00:00 2001 From: QAston Date: Sun, 10 May 2009 19:21:39 +0200 Subject: [PATCH 3/6] *Fix trap radius calculation in some cases-by krz --HG-- branch : trunk --- src/game/GameObject.cpp | 7 ++++++- src/game/Player.cpp | 4 ++-- src/game/Unit.cpp | 8 +++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index f71c08b3403..744b6679862 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -293,7 +293,12 @@ void GameObject::Update(uint32 /*p_time*/) bool IsBattleGroundTrap = false; //FIXME: this is activation radius (in different casting radius that must be selected from spell data) //TODO: move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state - float radius = goInfo->trap.radius; + float radius = 0.0f; + const SpellEntry *spellEntry = sSpellStore.LookupEntry(m_spellId); + if(spellEntry) + radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellEntry->EffectRadiusIndex[0])); + else + radius = goInfo->trap.radius; if(!radius) { if(goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 18426621300..9eb97ee295c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -7007,7 +7007,7 @@ void Player::CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo) return; // Can do effect if any damage done to target - if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE) + if (damageInfo->damage) { for (int i = 0; i < 5; i++) { @@ -7071,7 +7071,7 @@ void Player::CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo) else { // Can do effect if any damage done to target - if (!(damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE)) + if (!(damageInfo->damage)) continue; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index a4963e37d5b..7117449ae34 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1626,6 +1626,8 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) case BASE_ATTACK: slot = EQUIPMENT_SLOT_MAINHAND; break; case OFF_ATTACK: slot = EQUIPMENT_SLOT_OFFHAND; break; case RANGED_ATTACK: slot = EQUIPMENT_SLOT_RANGED; break; + default: + slot=EQUIPMENT_SLOT_END; } // offhand item cannot proc from main hand hit etc if (slot != i) @@ -1638,7 +1640,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) if (!((Player*)this)->IsUseEquipedWeapon(true)) slot=EQUIPMENT_SLOT_END; } - else + else if (damageInfo->attackType == OFF_ATTACK) { if (((Player*)this)->IsInFeralForm()) slot=EQUIPMENT_SLOT_END; @@ -1647,12 +1649,12 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) } // If usable, try to cast item spell if(slot!=EQUIPMENT_SLOT_END) - (((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i), &damageInfo); + ((Player*)this)->CastItemCombatSpell(((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) + if (damageInfo->damage) { // victim's damage shield std::set alreadyDone; From 95504364e04b33345d7c7251383eb719ab64bf8c Mon Sep 17 00:00:00 2001 From: QAston Date: Sun, 10 May 2009 20:15:35 +0200 Subject: [PATCH 4/6] Do not proc relentless strikes with slice and dice twice, fix vanish stealth apply --HG-- branch : trunk --- src/game/Spell.cpp | 5 +++-- src/game/SpellEffects.cpp | 18 +++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 2227bc4c92b..4fdd26c806f 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -978,7 +978,8 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) uint32 procEx = PROC_EX_NONE; //Spells with this flag cannot trigger if effect is casted on self - bool canEffectTrigger = (m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST ? m_caster!=unitTarget : true) + // Slice and Dice, relentless strikes, eviscerate + bool canEffectTrigger = (m_spellInfo->AttributesEx4 & (SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST | SPELL_ATTR_EX4_UNK4) ? m_caster!=unitTarget : true) && m_canTrigger; if (missInfo==SPELL_MISS_NONE) // In case spell hit target, do all effect on that target @@ -1222,7 +1223,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) ((Creature*)m_caster)->AI()->SpellHitTarget(unit, m_spellInfo); // spells with this flag can trigger only if not selfcast (eviscerate for example) - if (m_ChanceTriggerSpells.size() && (!(m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST) || unit!=m_caster)) + if (m_ChanceTriggerSpells.size() && (!(m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_CANT_PROC_FROM_SELFCAST | SPELL_ATTR_EX4_UNK4) || unit!=m_caster)) { int _duration=0; for(ChanceTriggerSpells::const_iterator i = m_ChanceTriggerSpells.begin(); i != m_ChanceTriggerSpells.end(); ++i) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 9ee2050a6ab..86c2235cdb5 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1824,7 +1824,8 @@ void Spell::EffectTriggerSpell(uint32 i) return; // get highest rank of the Stealth spell - uint32 spellId = 0; + bool found = false; + SpellEntry const *spellInfo; const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap(); for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) { @@ -1832,26 +1833,26 @@ void Spell::EffectTriggerSpell(uint32 i) if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + spellInfo = sSpellStore.LookupEntry(itr->first); if (!spellInfo) continue; if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH) { - spellId = spellInfo->Id; + found=true; break; } } // no Stealth spell found - if (!spellId) + if (!found) return; // reset cooldown on it if needed - if(((Player*)m_caster)->HasSpellCooldown(spellId)) - ((Player*)m_caster)->RemoveSpellCooldown(spellId); + if(((Player*)m_caster)->HasSpellCooldown(spellInfo->Id)) + ((Player*)m_caster)->RemoveSpellCooldown(spellInfo->Id); - m_caster->CastSpell(m_caster, spellId, true); + m_TriggerSpells.push_back(spellInfo); return; } // just skip @@ -1961,8 +1962,7 @@ void Spell::EffectTriggerSpell(uint32 i) for(uint32 j = i+1; j < 3; ++j) { if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_UNIT_CASTER - && (m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL - || m_spellInfo->Effect[j]==SPELL_EFFECT_SANCTUARY)) + && (m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL)) { instant = true; break; From 51b5f2aa640d08d547e3b6de4831f9bb02e870fd Mon Sep 17 00:00:00 2001 From: QAston Date: Mon, 11 May 2009 23:46:45 +0200 Subject: [PATCH 5/6] *Allow Hots to proc-this should fix talents like 33776 effect from hots. --HG-- branch : trunk --- src/game/Player.cpp | 9 +----- src/game/Player.h | 2 +- src/game/SpellAuras.cpp | 29 ++++++++++-------- src/game/SpellMgr.cpp | 37 ++++++++++++++++++++++- src/game/SpellMgr.h | 4 ++- src/game/Unit.cpp | 66 ++++++++++++++++++++--------------------- 6 files changed, 89 insertions(+), 58 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 9eb97ee295c..4ebd4f03684 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -6991,15 +6991,8 @@ void Player::UpdateEquipSpellsAtFormChange() } } -void Player::CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo) +void Player::CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo, ItemPrototype const * proto) { - if(!item || item->IsBroken()) - return; - - ItemPrototype const *proto = item->GetProto(); - if(!proto) - return; - Unit * Target = damageInfo->target; WeaponAttackType attType = damageInfo->attackType; diff --git a/src/game/Player.h b/src/game/Player.h index fbe365173dc..27e088f5131 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, CalcDamageInfo *damageInfo); + void CastItemCombatSpell(Item *item, CalcDamageInfo *damageInfo, ItemPrototype const * proto); void SendInitWorldStates(bool force = false, uint32 forceZoneId = 0); void SendUpdateWorldState(uint32 Field, uint32 Value); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 8c9c640c86b..96c73cf8732 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -5440,12 +5440,13 @@ void Aura::PeriodicTick() SpellEntry const* spellProto = GetSpellProto(); // Set trigger flag - uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT; - uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT; + uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; + uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; + uint32 procEx = PROC_EX_INTERNAL_DOT; pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist); if (pdamage) procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; - pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto); + pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, pdamage, BASE_ATTACK, spellProto); pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true); break; @@ -5560,12 +5561,13 @@ void Aura::PeriodicTick() float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1; // Set trigger flag - uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT; - uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT; + uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; + uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; + uint32 procEx = PROC_EX_INTERNAL_DOT; pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist); if (pdamage) procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; - pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto); + pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, pdamage, BASE_ATTACK, spellProto); int32 new_damage = pCaster->DealDamage(target, pdamage, &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false); if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false)) @@ -5670,11 +5672,12 @@ void Aura::PeriodicTick() } } - uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HEAL; - uint32 procVictim = 0;//ROC_FLAG_ON_TAKE_PERIODIC | PROC_FLAG_TAKEN_HEAL; + uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; + uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; + uint32 procEx = PROC_EX_INTERNAL_HOT; // ignore item heals -// if(procSpell && !haveCastItem) -// pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, PROC_EX_NORMAL_HIT, pdamage, BASE_ATTACK, spellProto); + if(procSpell && !haveCastItem) + pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, pdamage, BASE_ATTACK, spellProto); break; } case SPELL_AURA_PERIODIC_MANA_LEECH: @@ -5863,9 +5866,9 @@ void Aura::PeriodicTick() pCaster->SendSpellNonMeleeDamageLog(&damageInfo); // Set trigger flag - uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT; - uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;// | PROC_FLAG_TAKEN_HARMFUL_SPELL_HIT; - uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE); + uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; + uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; + uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE) | PROC_EX_INTERNAL_DOT; if (damageInfo.damage) procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 3a22efd71d6..55c45209583 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1213,6 +1213,41 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP if((procFlags & EventProcFlag) == 0) return false; + /* Check Periodic Auras + + * Both hots and dots can trigger if spell has no PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL + nor PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT + + *Only Hots can trigger if spell has PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL + + *Only dots can trigger if spell has both positivity flags or PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT + + */ + + if (EventProcFlag & PROC_FLAG_ON_DO_PERIODIC) + { + if (procFlags & PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT) + { + if (!(procExtra & PROC_EX_INTERNAL_DOT)) + return false; + } + else if (procFlags & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL + && !(procExtra & PROC_EX_INTERNAL_HOT)) + return false; + } + + if (EventProcFlag & PROC_FLAG_ON_TAKE_PERIODIC) + { + if (procFlags & PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT) + { + if (!(procExtra & PROC_EX_INTERNAL_DOT)) + return false; + } + else if (procFlags & PROC_FLAG_TAKEN_POSITIVE_SPELL + && !(procExtra & PROC_EX_INTERNAL_HOT)) + return false; + } + // Always trigger for this if (EventProcFlag & (PROC_FLAG_KILLED | PROC_FLAG_KILL_AND_GET_XP)) return true; @@ -1337,7 +1372,7 @@ void SpellMgr::LoadSpellEnchantProcData() uint32 count = 0; // 0 1 2 3 - QueryResult *result = WorldDatabase.Query("SELECT entry, customChance, PPMChance, procEx"); + QueryResult *result = WorldDatabase.Query("SELECT entry, customChance, PPMChance, procEx FROM spell_enchant_proc_data"); if( !result ) { diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 749abab0efb..aeba2deb068 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -547,7 +547,9 @@ enum ProcFlagsEx PROC_EX_RESERVED2 = 0x0004000, PROC_EX_RESERVED3 = 0x0008000, PROC_EX_EX_TRIGGER_ALWAYS = 0x0010000, // If set trigger always ( no matter another flags) used for drop charges - PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000 // If set trigger always but only one time + PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000, // If set trigger always but only one time + PROC_EX_INTERNAL_HOT = 0x1000000, // Only for internal use + PROC_EX_INTERNAL_DOT = 0x2000000 // Only for internal use }; struct SpellProcEventEntry diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 7117449ae34..d0b71d0f3a3 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1615,41 +1615,39 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) { for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) { - 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; - default: - slot=EQUIPMENT_SLOT_END; - } - // 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 (damageInfo->attackType == OFF_ATTACK) - { - if (((Player*)this)->IsInFeralForm()) - slot=EQUIPMENT_SLOT_END; - } - } - } // If usable, try to cast item spell - if(slot!=EQUIPMENT_SLOT_END) - ((Player*)this)->CastItemCombatSpell(((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i), damageInfo); + if (Item * item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i)) + if(!item->IsBroken()) + if (ItemPrototype const *proto = item->GetProto()) + { + // Additional check for weapons + if (proto->Class==ITEM_CLASS_WEAPON) + { + // offhand item cannot proc from main hand hit etc + EquipmentSlots slot; + 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; + default: slot = EQUIPMENT_SLOT_END; break; + } + if (slot != i) + continue; + // Check if item is useable (forms or disarm) + if (damageInfo->attackType == BASE_ATTACK) + { + if (!((Player*)this)->IsUseEquipedWeapon(true)) + continue; + } + else + { + if (((Player*)this)->IsInFeralForm()) + continue; + } + } + ((Player*)this)->CastItemCombatSpell(item, damageInfo, proto); + } } } From a9349e06ba77c6a8502f98765ef90119ee52aca5 Mon Sep 17 00:00:00 2001 From: QAston Date: Mon, 11 May 2009 23:52:50 +0200 Subject: [PATCH 6/6] *Fix a typo --HG-- branch : trunk --- src/game/SpellMgr.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 55c45209583..54911ff4451 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1224,26 +1224,26 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP */ - if (EventProcFlag & PROC_FLAG_ON_DO_PERIODIC) + if (procFlags & PROC_FLAG_ON_DO_PERIODIC) { - if (procFlags & PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT) + if (EventProcFlag & PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT) { if (!(procExtra & PROC_EX_INTERNAL_DOT)) return false; } - else if (procFlags & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL + else if (EventProcFlag & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL && !(procExtra & PROC_EX_INTERNAL_HOT)) return false; } - if (EventProcFlag & PROC_FLAG_ON_TAKE_PERIODIC) + if (procFlags & PROC_FLAG_ON_TAKE_PERIODIC) { - if (procFlags & PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT) + if (EventProcFlag & PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT) { if (!(procExtra & PROC_EX_INTERNAL_DOT)) return false; } - else if (procFlags & PROC_FLAG_TAKEN_POSITIVE_SPELL + else if (EventProcFlag & PROC_FLAG_TAKEN_POSITIVE_SPELL && !(procExtra & PROC_EX_INTERNAL_HOT)) return false; }