From ba8ae4b06f3198bd239365c2f4b963ea01395cab Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 13 Nov 2008 01:20:53 +0300 Subject: [PATCH] [6820] Cleanup spell proc event code. Avoid send same information by 2 ways to function. --- src/game/Unit.cpp | 308 +++++++++++++++++++++++------------------------ src/game/Unit.h | 10 +- src/shared/revision_nr.h | 2 +- 3 files changed, 161 insertions(+), 159 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 425e0a7b6..5c4b8434d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4547,8 +4547,10 @@ void Unit::CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchool ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, damageSchoolMask, spellCasted, isTriggeredSpell, attType); } -bool Unit::HandleHasteAuraProc(Unit *pVictim, SpellEntry const *hasteSpell, uint32 /*effIndex*/, uint32 damage, Aura* triggeredByAura, SpellEntry const * /*procSpell*/, uint32 /*procFlag*/, uint32 cooldown) +bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * /*procSpell*/, uint32 /*procFlag*/, uint32 cooldown) { + SpellEntry const *hasteSpell = triggeredByAura->GetSpellProto(); + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; @@ -4608,8 +4610,11 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, SpellEntry const *hasteSpell, uint return true; } -bool Unit::HandleDummyAuraProc(Unit *pVictim, SpellEntry const *dummySpell, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 cooldown) +bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 cooldown) { + SpellEntry const *dummySpell = triggeredByAura->GetSpellProto (); + uint32 effIndex = triggeredByAura->GetEffIndex (); + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; @@ -6423,8 +6428,10 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return true; } -bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 /*damage*/, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) +bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) { + int32 scriptId = triggeredByAura->GetModifier()->m_miscvalue; + if(!pVictim || !pVictim->isAlive()) return false; @@ -9970,17 +9977,15 @@ bool Unit::isFrozen() const struct ProcTriggeredData { - ProcTriggeredData(SpellEntry const * _spellInfo, uint32 _spellParam, Aura* _triggeredByAura, uint32 _cooldown) - : spellInfo(_spellInfo), spellParam(_spellParam), triggeredByAura(_triggeredByAura), + ProcTriggeredData(Aura* _triggeredByAura, uint32 _cooldown) + : triggeredByAura(_triggeredByAura), triggeredByAura_SpellPair(Unit::spellEffectPair(triggeredByAura->GetId(),triggeredByAura->GetEffIndex())), cooldown(_cooldown) - {} + {} - SpellEntry const * spellInfo; - uint32 spellParam; - Aura* triggeredByAura; - Unit::spellEffectPair triggeredByAura_SpellPair; - uint32 cooldown; + Aura* triggeredByAura; // triggred aura, can be invalidate at triggered aura proccessing + Unit::spellEffectPair triggeredByAura_SpellPair; // spell pair, used for re-find aura (by pointer comparison in range) + uint32 cooldown; // possible hidden cooldown }; typedef std::list< ProcTriggeredData > ProcTriggeredList; @@ -9997,87 +10002,13 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag { next = i; ++next; - SpellEntry const *spellProto = (*i)->GetSpellProto(); - if(!spellProto) - continue; - - SpellProcEventEntry const *spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id); - if(!spellProcEvent) - { - // used to prevent spam in log about same non-handled spells - static std::set nonHandledSpellProcSet; - - if(spellProto->procFlags != 0 && nonHandledSpellProcSet.find(spellProto->Id)==nonHandledSpellProcSet.end()) - { - sLog.outError("ProcDamageAndSpell: spell %u (%s aura source) not have record in `spell_proc_event`)",spellProto->Id,(isVictim?"a victim's":"an attacker's")); - nonHandledSpellProcSet.insert(spellProto->Id); - } + Aura* i_aura = *i; - // spell.dbc use totally different flags, that only can create problems if used. + uint32 cooldown; // returned at next line + if(!IsTriggeredAtSpellProcEvent(i_aura->GetSpellProto(), procSpell, procFlag,attType,isVictim,cooldown)) continue; - } - - // Check spellProcEvent data requirements - if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, procSpell,procFlag)) - continue; - - // Check if current equipment allows aura to proc - if(!isVictim && GetTypeId() == TYPEID_PLAYER ) - { - if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON) - { - Item *item = ((Player*)this)->GetWeaponForAttack(attType,true); - - if(!item || !((1<GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) - continue; - } - else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) - { - // Check if player is wearing shield - Item *item = ((Player*)this)->GetShield(true); - if(!item || !((1<GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) - continue; - } - } - - float chance = (float)spellProto->procChance; - - if(Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance); - - if(!isVictim && spellProcEvent->ppmRate != 0) - { - uint32 WeaponSpeed = GetAttackTime(attType); - chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate); - } - if(roll_chance_f(chance)) - { - uint32 cooldown = spellProcEvent->cooldown; - - uint32 i_spell_eff = (*i)->GetEffIndex(); - - int32 i_spell_param; - switch(*aur) - { - case SPELL_AURA_PROC_TRIGGER_SPELL: - i_spell_param = procFlag; - break; - case SPELL_AURA_DUMMY: - case SPELL_AURA_PRAYER_OF_MENDING: - case SPELL_AURA_MOD_HASTE: - i_spell_param = i_spell_eff; - break; - case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: - i_spell_param = (*i)->GetModifier()->m_miscvalue; - break; - default: - i_spell_param = (*i)->GetModifier()->m_amount; - break; - } - - procTriggered.push_back( ProcTriggeredData(spellProto,i_spell_param,*i, cooldown) ); - } + procTriggered.push_back( ProcTriggeredData(i_aura, cooldown) ); } // Handle effects proceed this time @@ -10110,106 +10041,66 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag } } + // this is aura triggering code call + Aura* triggeredByAura = i->triggeredByAura; + // save charges existence before processing to prevent crash at access to deleted triggered aura after - bool triggeredByAuraWithCharges = i->triggeredByAura->m_procCharges > 0; + bool triggeredByAuraWithCharges = triggeredByAura->m_procCharges > 0; bool casted = false; switch(*aur) { case SPELL_AURA_PROC_TRIGGER_SPELL: { - sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - casted = HandleProcTriggerSpell(pTarget, damage, i->triggeredByAura, procSpell,i->spellParam,attType,i->cooldown); + sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s proc aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); + casted = HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, attType, i->cooldown); break; } case SPELL_AURA_PROC_TRIGGER_DAMAGE: { - sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", i->spellParam, i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - uint32 damage = i->spellParam; - SpellNonMeleeDamageLog(pTarget, i->spellInfo->Id, damage, true, true); + uint32 triggered_damage = triggeredByAura->GetModifier()->m_amount; + sLog.outDebug("ProcDamageAndSpell: doing %u damage (triggered by %s aura of spell %u)", + triggered_damage, (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + SpellNonMeleeDamageLog(pTarget, triggeredByAura->GetId(), triggered_damage, true, true); casted = true; break; } case SPELL_AURA_DUMMY: { - sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - casted = HandleDummyAuraProc(pTarget, i->spellInfo, i->spellParam, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown); + uint32 effect = triggeredByAura->GetEffIndex(); + sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s dummy aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + casted = HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag,i->cooldown); break; } case SPELL_AURA_PRAYER_OF_MENDING: { - sLog.outDebug("ProcDamageAndSpell(mending): casting spell id %u (triggered by %s dummy aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - - // aura can be deleted at casts - int32 heal = i->triggeredByAura->GetModifier()->m_amount; - uint64 caster_guid = i->triggeredByAura->GetCasterGUID(); - - // jumps - int32 jumps = i->triggeredByAura->m_procCharges-1; - - // current aura expire - i->triggeredByAura->m_procCharges = 1; // will removed at next charges decrease - - // next target selection - if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid)) - { - Aura* aura = i->triggeredByAura; - - SpellEntry const* spellProto = aura->GetSpellProto(); - uint32 effIdx = aura->GetEffIndex(); - - float radius; - if (spellProto->EffectRadiusIndex[effIdx]) - radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx])); - else - radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); - - if(Player* caster = ((Player*)aura->GetCaster())) - { - caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL); - - if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius)) - { - // aura will applied from caster, but spell casted from current aura holder - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_CHARGES; - mod->value = jumps-5; // negative - mod->type = SPELLMOD_FLAT; - mod->spellId = spellProto->Id; - mod->effectId = effIdx; - mod->lastAffected = NULL; - mod->mask = spellProto->SpellFamilyFlags; - mod->charges = 0; - - caster->AddSpellMod(mod, true); - CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,aura,caster->GetGUID()); - caster->AddSpellMod(mod, false); - } - } - } + sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); - // heal - CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid); - casted = true; + casted = HandleMeandingAuraProc(triggeredByAura); break; } case SPELL_AURA_MOD_HASTE: { - sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - casted = HandleHasteAuraProc(pTarget, i->spellInfo, i->spellParam, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown); + sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s haste aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + casted = HandleHasteAuraProc(pTarget, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown); break; } case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: { // nothing do, just charges counter // but count only in case appropriate school damage - casted = i->triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask; + casted = triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask; break; } case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: { - sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId()); - casted = HandleOverrideClassScriptAuraProc(pTarget, i->spellParam, damage, i->triggeredByAura, procSpell,i->cooldown); + sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s class script aura of spell %u)", + (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); + casted = HandleOverrideClassScriptAuraProc(pTarget, i->triggeredByAura, procSpell,i->cooldown); break; } default: @@ -10855,3 +10746,112 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) return pet; } + +bool Unit::IsTriggeredAtSpellProcEvent(SpellEntry const* spellProto, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, bool isVictim, uint32& cooldown ) +{ + SpellProcEventEntry const * spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id); + + if(!spellProcEvent) + { + // used to prevent spam in log about same non-handled spells + static std::set nonHandledSpellProcSet; + + if(spellProto->procFlags != 0 && nonHandledSpellProcSet.find(spellProto->Id)==nonHandledSpellProcSet.end()) + { + sLog.outError("ProcDamageAndSpell: spell %u (%s aura source) not have record in `spell_proc_event`)",spellProto->Id,(isVictim?"a victim's":"an attacker's")); + nonHandledSpellProcSet.insert(spellProto->Id); + } + + // spell.dbc use totally different flags, that only can create problems if used. + return false; + } + + // Check spellProcEvent data requirements + if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, procSpell,procFlag)) + return false; + + // Check if current equipment allows aura to proc + if(!isVictim && GetTypeId() == TYPEID_PLAYER ) + { + if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON) + { + Item *item = ((Player*)this)->GetWeaponForAttack(attType,true); + + if(!item || !((1<GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) + return false; + } + else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) + { + // Check if player is wearing shield + Item *item = ((Player*)this)->GetShield(true); + if(!item || !((1<GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) + return false; + } + } + + float chance = (float)spellProto->procChance; + + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance); + + if(!isVictim && spellProcEvent && spellProcEvent->ppmRate != 0) + { + uint32 WeaponSpeed = GetAttackTime(attType); + chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate); + } + + cooldown = spellProcEvent ? spellProcEvent->cooldown : 0; + return roll_chance_f(chance); +} + +bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura ) +{ + // aura can be deleted at casts + SpellEntry const* spellProto = triggeredByAura->GetSpellProto(); + uint32 effIdx = triggeredByAura->GetEffIndex(); + int32 heal = triggeredByAura->GetModifier()->m_amount; + uint64 caster_guid = triggeredByAura->GetCasterGUID(); + + // jumps + int32 jumps = triggeredByAura->m_procCharges-1; + + // current aura expire + triggeredByAura->m_procCharges = 1; // will removed at next charges decrease + + // next target selection + if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid)) + { + float radius; + if (spellProto->EffectRadiusIndex[effIdx]) + radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx])); + else + radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); + + if(Player* caster = ((Player*)triggeredByAura->GetCaster())) + { + caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL); + + if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius)) + { + // aura will applied from caster, but spell casted from current aura holder + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_CHARGES; + mod->value = jumps-5; // negative + mod->type = SPELLMOD_FLAT; + mod->spellId = spellProto->Id; + mod->effectId = effIdx; + mod->lastAffected = NULL; + mod->mask = spellProto->SpellFamilyFlags; + mod->charges = 0; + + caster->AddSpellMod(mod, true); + CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID()); + caster->AddSpellMod(mod, false); + } + } + } + + // heal + CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid); + return true; +} \ No newline at end of file diff --git a/src/game/Unit.h b/src/game/Unit.h index 3ebab6932..9447c5d93 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1316,10 +1316,12 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*) void ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, AuraTypeSet const& procAuraTypes, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage, SpellSchoolMask damageSchoolMask ); - bool HandleDummyAuraProc(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag,uint32 cooldown); - bool HandleProcTriggerSpell(Unit *pVictim,uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags,WeaponAttackType attType,uint32 cooldown); - bool HandleHasteAuraProc(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag,uint32 cooldown); - bool HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell,uint32 cooldown); + bool IsTriggeredAtSpellProcEvent( SpellEntry const* spellProto, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, bool isVictim, uint32& cooldown ); + bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 cooldown); + bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, uint32 cooldown); + bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 cooldown); + bool HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 cooldown); + bool HandleMeandingAuraProc(Aura* triggeredByAura); uint32 m_state; // Even derived shouldn't modify uint32 m_CombatTimer; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a172f3f8e..b78e4e8dc 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6819" + #define REVISION_NR "6820" #endif // __REVISION_NR_H__ -- 2.11.4.GIT