Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
UnitProcEvent.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Battlefield.h"
7#include "BattlefieldMgr.h"
8#include "Battleground.h"
9#include "CellImpl.h"
10#include "Common.h"
11#include "ConditionMgr.h"
12#include "Creature.h"
13#include "CreatureAI.h"
14#include "CreatureAIImpl.h"
15#include "CreatureGroups.h"
16#include "Formulas.h"
17#include "GridNotifiersImpl.h"
18#include "Group.h"
19#include "InstanceSaveMgr.h"
20#include "InstanceScript.h"
21#include "Log.h"
22#include "MapManager.h"
23#include "MovementStructures.h"
24#include "MoveSpline.h"
25#include "ObjectAccessor.h"
26#include "ObjectMgr.h"
27#include "Opcodes.h"
28#include "OutdoorPvP.h"
29#include "PassiveAI.h"
30#include "Pet.h"
31#include "PetAI.h"
32#include "Player.h"
33#include "QuestDef.h"
34#include "ReputationMgr.h"
35#include "Spell.h"
36#include "SpellAuraEffects.h"
37#include "SpellAuras.h"
38#include "SpellInfo.h"
39#include "SpellMgr.h"
40#include "TemporarySummon.h"
41#include "Totem.h"
42#include "Transport.h"
43#include "Unit.h"
44#include "UpdateFieldFlags.h"
45#include "Util.h"
46#include "Vehicle.h"
47#include "World.h"
48#include "WorldPacket.h"
49#include "WorldSession.h"
50
51#include <math.h>
52
53// Used for prepare can/can`t triggr aura
54static bool InitTriggerAuraData();
55// Define can trigger auras
57// Define can't trigger auras (need for disable second trigger)
59// Triggered always, even from triggered spells
61// Prepare lists
63
65{
66 // normalized proc chance for weapon attack speed
67 // (odd formula...)
69 return (GetAttackTime(WeaponAttackType::BASE_ATTACK) * 1.8f / 1000.0f);
71 return (GetAttackTime(WeaponAttackType::OFF_ATTACK) * 1.6f / 1000.0f);
72 return 0;
73}
74
75float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellInfo* spellProto) const
76{
77 // proc per minute chance calculation
78 if (PPM <= 0)
79 return 0.0f;
80
81 // Apply chance modifer aura
82 if (spellProto)
83 if (Player* modOwner = GetSpellModOwner())
84 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_PROC_PER_MINUTE, PPM);
85
86 return floor((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
87}
88
90{
92 : aura(_aura)
93 {
94 effMask = 0;
95 spellProcEvent = NULL;
96 }
100};
101
102typedef std::list< ProcTriggeredData > ProcTriggeredList;
103
104// List of auras that CAN be trigger but may not exist in spell_proc_event
105// in most case need for drop charges
106// in some types of aura need do additional check
107// for example SPELL_AURA_MECHANIC_IMMUNITY - need check for mechanic
109{
110 for (uint16 i = 0; i < TOTAL_AURAS; ++i)
111 {
112 isTriggerAura[i] = false;
113 isNonTriggerAura[i] = false;
114 isAlwaysTriggeredAura[i] = false;
115 }
120 isTriggerAura[SPELL_AURA_MOD_STUN] = true; // Aura does not have charges but needs to be removed on trigger
125 isTriggerAura[SPELL_AURA_MOD_FEAR] = true; // Aura does not have charges but needs to be removed on trigger
134 isTriggerAura[SPELL_AURA_SCHOOL_ABSORB] = true; // Savage Defense untested
156
159
169
170 return true;
171}
172
174{
175 uint32 procEx = PROC_EX_NONE;
176 // Check victim state
177 if (missCondition != SPELL_MISS_NONE)
178 switch (missCondition)
179 {
180 case SPELL_MISS_MISS: procEx |= PROC_EX_MISS; break;
181 case SPELL_MISS_RESIST: procEx |= PROC_EX_RESIST; break;
182 case SPELL_MISS_DODGE: procEx |= PROC_EX_DODGE; break;
183 case SPELL_MISS_PARRY: procEx |= PROC_EX_PARRY; break;
184 case SPELL_MISS_BLOCK: procEx |= PROC_EX_BLOCK; break;
185 case SPELL_MISS_EVADE: procEx |= PROC_EX_EVADE; break;
186 case SPELL_MISS_IMMUNE: procEx |= PROC_EX_IMMUNE; break;
187 case SPELL_MISS_IMMUNE2: procEx |= PROC_EX_IMMUNE; break;
188 case SPELL_MISS_DEFLECT: procEx |= PROC_EX_DEFLECT; break;
189 case SPELL_MISS_ABSORB: procEx |= PROC_EX_ABSORB; break;
190 case SPELL_MISS_REFLECT: procEx |= PROC_EX_REFLECT; break;
191 default:
192 break;
193 }
194 else
195 {
196 // On block
197 if (damageInfo->blocked)
198 procEx |= PROC_EX_BLOCK;
199 // On absorb
200 if (damageInfo->absorb)
201 procEx |= PROC_EX_ABSORB;
202 // On crit
203 if (damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT)
204 procEx |= PROC_EX_CRITICAL_HIT;
205 else
206 procEx |= PROC_EX_NORMAL_HIT;
207 }
208 return procEx;
209}
210
211void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const* procSpell, uint32 damage, SpellInfo const* procAura)
212{
213 // Player is loaded now - do not allow passive spell casts to proc
214 if (GetTypeId() == TypeID::TYPEID_PLAYER && ToPlayer()->GetSession()->PlayerLoading())
215 return;
216 // For melee/ranged based attack need update skills and set some Aura states if victim present
217 if (procFlag & MELEE_BASED_TRIGGER_MASK && target)
218 {
219 // If exist crit/parry/dodge/block need update aura state (for victim and attacker)
221 {
222 // for victim
223 if (isVictim)
224 {
225 // if victim and dodge attack
226 if (procExtra & PROC_EX_DODGE)
227 {
228 // Update AURA_STATE on dodge
229 if (getClass() != CLASS_ROGUE) // skip Rogue Riposte
230 {
233 }
234 }
235 // if victim and parry attack
236 if (procExtra & PROC_EX_PARRY)
237 {
238 // For Hunters only Counterattack (skip Mongoose bite)
239 if (getClass() == CLASS_HUNTER)
240 {
243 }
244 else
245 {
248 }
249 }
250 // if and victim block attack
251 if (procExtra & PROC_EX_BLOCK)
252 {
255 }
256 }
257 else // For attacker
258 {
259 // Overpower on victim dodge
261 {
262 ToPlayer()->AddComboPoints(target, 1);
264 }
265 }
266 }
267 }
268
270 {
271 if (ToPlayer()->HasAura(46953)) // Sword and Board (Passive)
272 {
273 if (procSpell && procSpell->SpellFamilyName == SPELLFAMILY_WARRIOR)
274 {
275 if (procSpell->SpellIconID == 1508 && procSpell->SpellFamilyFlags[1] == 0x00000040) // Devastate
276 {
277 if (roll_chance_f(30))
278 {
279 //Shield Slam Cooldown
280 if (ToPlayer()->HasSpellCooldown(23922))
281 ToPlayer()->RemoveSpellCooldown(23922, true);
282
283 // Sword and Board Energize Spell
284 ToPlayer()->CastSpell(this, 50227);
285 }
286 }
287 }
288 }
289 }
290
291 if (getClass() == CLASS_WARLOCK)
292 {
293 float mult = 1.0f;
294 if (procSpell && procSpell->SpellFamilyName == SPELLFAMILY_WARLOCK)
295 {
296 if (procExtra & PROC_EX_CRITICAL_HIT)
297 mult = 2.0f;
298
299 if ((procSpell->SpellIconID == 2128 && procSpell->SpellFamilyFlags[1] == 0x00000040) ||
300 (procSpell->SpellIconID == 12 && procSpell->SpellFamilyFlags[1] == 0x00800000) ||
301 (procSpell->SpellIconID == 31 && procSpell->SpellFamilyFlags[0] == 0x00000004))
302 {
304 }
305 }
306 }
307
308 Unit* actor = isVictim ? target : this;
309 Unit* actionTarget = !isVictim ? target : this;
310
311 DamageInfo damageInfo = DamageInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL, SPELL_DIRECT_DAMAGE);
312 HealInfo healInfo = HealInfo(damage);
313 ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, NULL, &damageInfo, &healInfo);
314
315 ProcTriggeredList procTriggered;
316 // Fill procTriggered list
317 for (AuraApplicationMap::const_iterator itr = GetAppliedAuras().begin(); itr != GetAppliedAuras().end(); ++itr)
318 {
319 // Do not allow auras to proc from effect triggered by itself
320 if (procAura && procAura->Id == itr->first)
321 continue;
322 ProcTriggeredData triggerData(itr->second->GetBase());
323 // Defensive procs are active on absorbs (so absorption effects are not a hindrance)
324 bool active = damage || (procExtra & PROC_EX_BLOCK && isVictim);
325 if (isVictim)
326 procExtra &= ~PROC_EX_INTERNAL_REQ_FAMILY;
327
328 SpellInfo const* spellProto = itr->second->GetBase()->GetSpellInfo();
329
330 // only auras that has triggered spell should proc from fully absorbed damage
331 if (procExtra & PROC_EX_ABSORB && isVictim)
332 if (damage || spellProto->Effects[EFFECT_0].TriggerSpell || spellProto->Effects[EFFECT_1].TriggerSpell || spellProto->Effects[EFFECT_2].TriggerSpell)
333 active = true;
334
335 if (!IsTriggeredAtSpellProcEvent(target, triggerData.aura, procSpell, procFlag, procExtra, attType, isVictim, active, triggerData.spellProcEvent))
336 continue;
337
338 // do checks using conditions table
339 ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, spellProto->Id);
340 ConditionSourceInfo condInfo = ConditionSourceInfo(eventInfo.GetActor(), eventInfo.GetActionTarget());
341 if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
342 continue;
343
344 // AuraScript Hook
345 if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo))
346 continue;
347
348 // Triggered spells not triggering additional spells
349 bool triggered = !(spellProto->AttributesEx3 & SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ?
350 (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false;
351
352 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
353 {
354 if (itr->second->HasEffect(i))
355 {
356 AuraEffect* aurEff = itr->second->GetBase()->GetEffect(i);
357 // Skip this auras
358 if (isNonTriggerAura[aurEff->GetAuraType()])
359 continue;
360 // If not trigger by default and spellProcEvent == NULL - skip
361 if (!isTriggerAura[aurEff->GetAuraType()] && triggerData.spellProcEvent == NULL)
362 continue;
363 // Some spells must always trigger
364 if (!triggered || isAlwaysTriggeredAura[aurEff->GetAuraType()])
365 triggerData.effMask |= 1 << i;
366 }
367 }
368 if (triggerData.effMask)
369 procTriggered.push_front(triggerData);
370 }
371
372 // Nothing found
373 if (procTriggered.empty())
374 return;
375
376 // Note: must SetCantProc(false) before return
378 SetCantProc(true);
379
380 // Handle effects proceed this time
381 for (ProcTriggeredList::const_iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
382 {
383 // look for aura in auras list, it may be removed while proc event processing
384 if (i->aura->IsRemoved())
385 continue;
386
387 bool useCharges = i->aura->IsUsingCharges();
388 // no more charges to use, prevent proc
389 if (useCharges && !i->aura->GetCharges())
390 continue;
391
392 bool takeCharges = false;
393 SpellInfo const* spellInfo = i->aura->GetSpellInfo();
394 uint32 Id = i->aura->GetId();
395
396 AuraApplication* aurApp = i->aura->GetApplicationOfTarget(GetGUID());
397
398 bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo);
399
400 // For players set spell cooldown if need
401 uint32 cooldown = 0;
402 if (prepare && GetTypeId() == TypeID::TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown)
403 cooldown = i->spellProcEvent->cooldown;
404
405 // Note: must SetCantProc(false) before return
407 SetCantProc(true);
408
409 bool handled = i->aura->CallScriptProcHandlers(aurApp, eventInfo);
410
411 // "handled" is needed as long as proc can be handled in multiple places
412 if (!handled && HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, cooldown, &handled))
413 {
414 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), Id);
415 takeCharges = true;
416 }
417
418 if (!handled)
419 {
420 for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
421 {
422 if (!(i->effMask & (1 << effIndex)))
423 continue;
424
425 AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex);
426 ASSERT(triggeredByAura);
427
428 bool prevented = i->aura->CallScriptEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
429 if (prevented)
430 {
431 takeCharges = true;
432 continue;
433 }
434
435 switch (triggeredByAura->GetAuraType())
436 {
439 {
440 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
441 // Don`t drop charge or add cooldown for not started trigger
442 if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
443 takeCharges = true;
444 break;
445 }
447 {
448 // target has to be valid
449 if (!eventInfo.GetProcTarget())
450 break;
451
452 triggeredByAura->HandleProcTriggerDamageAuraProc(aurApp, eventInfo); // this function is part of the new proc system
453 takeCharges = true;
454 break;
455 }
457 case SPELL_AURA_DUMMY:
458 {
459 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
460 if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
461 takeCharges = true;
462 break;
463 }
465 {
466 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
467 if (HandleAuraProcOnPowerAmount(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
468 takeCharges = true;
469 break;
470 }
477 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId());
478 takeCharges = true;
479 break;
481 {
482 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
483 if (HandleOverrideClassScriptAuraProc(target, damage, triggeredByAura, procSpell, cooldown))
484 takeCharges = true;
485 break;
486 }
488 {
489 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
490 (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
491
493 takeCharges = true;
494 break;
495 }
497 {
498 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
499 (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
500
501 HandleAuraRaidProcFromCharge(triggeredByAura);
502 takeCharges = true;
503 break;
504 }
506 {
507 SF_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId());
508
509 if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
510 takeCharges = true;
511 break;
512 }
514 // Skip melee hits or instant cast spells
515 if (procSpell && procSpell->CalcCastTime(getLevel()) > 0)
516 takeCharges = true;
517 break;
519 // Skip Melee hits and spells ws wrong school
520 if (procSpell && (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
521 takeCharges = true;
522 break;
524 // Skip Melee hits and targets with magnet aura
525 if (procSpell && (triggeredByAura->GetBase()->GetUnitOwner()->ToUnit() == ToUnit())) // Magnet
526 takeCharges = true;
527 break;
530 // Skip melee hits and spells ws wrong school or zero cost
531 if (procSpell &&
532 //(procSpell->ManaCost != 0 || procSpell->ManaCostPercentage != 0) && // Cost check
533 (triggeredByAura->GetMiscValue() & procSpell->SchoolMask)) // School check
534 takeCharges = true;
535 break;
537 // Compare mechanic
538 if (procSpell && procSpell->Mechanic == uint32(triggeredByAura->GetMiscValue()))
539 takeCharges = true;
540 break;
542 // Compare mechanic
543 if (procSpell && procSpell->Mechanic == uint32(triggeredByAura->GetMiscValue()))
544 takeCharges = true;
545 break;
547 // Compare casters
548 if (triggeredByAura->GetCasterGUID() == target->GetGUID())
549 takeCharges = true;
550 break;
551 // CC Auras which use their amount amount to drop
552 // Are there any more auras which need this?
559 {
560 // chargeable mods are breaking on hit
561 if (useCharges)
562 takeCharges = true;
563 else
564 {
565 // Spell own direct damage at apply wont break the CC
566 if (procSpell && (procSpell->Id == triggeredByAura->GetId()))
567 {
568 Aura* aura = triggeredByAura->GetBase();
569 // called from spellcast, should not have ticked yet
570 if (aura->GetDuration() == aura->GetMaxDuration())
571 break;
572 }
573 int32 damageLeft = triggeredByAura->GetAmount();
574 // No damage left
575 if (damageLeft < int32(damage))
576 i->aura->Remove();
577 else
578 triggeredByAura->SetAmount(damageLeft - damage);
579 }
580 break;
581 }
582 //case SPELL_AURA_ADD_FLAT_MODIFIER:
583 //case SPELL_AURA_ADD_PCT_MODIFIER:
584 // HandleSpellModAuraProc
585 //break;
586 default:
587 // nothing do, just charges counter
588 takeCharges = true;
589 break;
590 } // switch (triggeredByAura->GetAuraType())
591 i->aura->CallScriptAfterEffectProcHandlers(triggeredByAura, aurApp, eventInfo);
592 } // for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
593 } // if (!handled)
594
595 // Remove charge (aura can be removed by triggers)
596 if (prepare && useCharges && takeCharges)
597 i->aura->DropCharge();
598
599 i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo);
600
602 SetCantProc(false);
603 }
604
605 // Cleanup proc requirements
607 SetCantProc(false);
608}
609
610void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo)
611{
612 // use provided list of auras which can proc
613 if (procAuras)
614 {
615 for (std::list<AuraApplication*>::iterator itr = procAuras->begin(); itr != procAuras->end(); ++itr)
616 {
617 ASSERT((*itr)->GetTarget() == this);
618 if (!(*itr)->GetRemoveMode())
619 if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo))
620 {
621 (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo);
622 aurasTriggeringProc.push_back(*itr);
623 }
624 }
625 }
626 // or generate one on our own
627 else
628 {
629 for (AuraApplicationMap::iterator itr = GetAppliedAuras().begin(); itr != GetAppliedAuras().end(); ++itr)
630 {
631 if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo))
632 {
633 itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo);
634 aurasTriggeringProc.push_back(itr->second);
635 }
636 }
637 }
638}
639
641{
642 DamageInfo dmgInfo = DamageInfo(damageInfo);
643 TriggerAurasProcOnEvent(NULL, NULL, damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, 0, 0, damageInfo.procEx, NULL, &dmgInfo, NULL);
644}
645
646void Unit::TriggerAurasProcOnEvent(std::list<AuraApplication*>* myProcAuras, std::list<AuraApplication*>* targetProcAuras, Unit* actionTarget, uint32 typeMaskActor, uint32 typeMaskActionTarget, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell* spell, DamageInfo* damageInfo, HealInfo* healInfo)
647{
648 // prepare data for self trigger
649 ProcEventInfo myProcEventInfo = ProcEventInfo(this, actionTarget, actionTarget, typeMaskActor, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
650 std::list<AuraApplication*> myAurasTriggeringProc;
651 GetProcAurasTriggeredOnEvent(myAurasTriggeringProc, myProcAuras, myProcEventInfo);
652
653 // prepare data for target trigger
654 ProcEventInfo targetProcEventInfo = ProcEventInfo(this, actionTarget, this, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, spell, damageInfo, healInfo);
655 std::list<AuraApplication*> targetAurasTriggeringProc;
656 if (typeMaskActionTarget)
657 GetProcAurasTriggeredOnEvent(targetAurasTriggeringProc, targetProcAuras, targetProcEventInfo);
658
659 TriggerAurasProcOnEvent(myProcEventInfo, myAurasTriggeringProc);
660
661 if (typeMaskActionTarget)
662 TriggerAurasProcOnEvent(targetProcEventInfo, targetAurasTriggeringProc);
663}
664
665void Unit::TriggerAurasProcOnEvent(ProcEventInfo& eventInfo, std::list<AuraApplication*>& aurasTriggeringProc)
666{
667 for (std::list<AuraApplication*>::iterator itr = aurasTriggeringProc.begin(); itr != aurasTriggeringProc.end(); ++itr)
668 {
669 if (!(*itr)->GetRemoveMode())
670 (*itr)->GetBase()->TriggerProcOnEvent(*itr, eventInfo);
671 }
672}
673
674void Unit::SetCantProc(bool apply)
675{
676 if (apply)
677 ++m_procDeep;
678 else
679 {
681 --m_procDeep;
682 }
683}
684
685bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent)
686{
687 SpellInfo const* spellProto = aura->GetSpellInfo();
688
689 // let the aura be handled by new proc system if it has new entry
690 if (sSpellMgr->GetSpellProcEntry(spellProto->Id))
691 return false;
692
693 // Get proc Event Entry
694 spellProcEvent = sSpellMgr->GetSpellProcEvent(spellProto->Id);
695
696 // Get EventProcFlag
697 uint32 EventProcFlag;
698 if (spellProcEvent && spellProcEvent->procFlags) // if exist get custom spellProcEvent->procFlags
699 EventProcFlag = spellProcEvent->procFlags;
700 else
701 EventProcFlag = spellProto->ProcFlags; // else get from spell proto
702 // Continue if no trigger exist
703 if (!EventProcFlag)
704 return false;
705
706 // Additional checks for triggered spells (ignore trap casts)
707 if (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION))
708 {
710 return false;
711 }
712
713 // Check spellProcEvent data requirements
714 if (!sSpellMgr->IsSpellProcEventCanTriggeredBy(spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active))
715 return false;
716 // In most cases req get honor or XP from kill
717 if (EventProcFlag & PROC_FLAG_KILL && GetTypeId() == TypeID::TYPEID_PLAYER)
718 {
719 bool allow = false;
720
721 if (victim)
722 allow = ToPlayer()->isHonorOrXPTarget(victim);
723
724 // Shadow Word: Death - can trigger from every kill
725 if (aura->GetId() == 32409)
726 allow = true;
727 if (!allow)
728 return false;
729 }
730 // Aura added by spell can`t trigger from self (prevent drop charges/do triggers)
731 // But except periodic and kill triggers (can triggered from self)
732 if (procSpell && procSpell->Id == spellProto->Id
733 && !(spellProto->ProcFlags & (PROC_FLAG_TAKEN_PERIODIC | PROC_FLAG_KILL)))
734 return false;
735
736 // Check if current equipment allows aura to proc
737 if (!isVictim && GetTypeId() == TypeID::TYPEID_PLAYER)
738 {
739 Player* player = ToPlayer();
740 if (spellProto->EquippedItemClass == ITEM_CLASS_WEAPON)
741 {
742 Item* item = NULL;
745 else if (attType == WeaponAttackType::OFF_ATTACK)
747
748 if (player->IsInFeralForm())
749 return false;
750
751 if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_WEAPON || !((1 << item->GetTemplate()->SubClass) & spellProto->EquippedItemSubClassMask))
752 return false;
753 }
754 else if (spellProto->EquippedItemClass == ITEM_CLASS_ARMOR)
755 {
756 // Check if player is wearing shield
758 if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_ARMOR || !((1 << item->GetTemplate()->SubClass) & spellProto->EquippedItemSubClassMask))
759 return false;
760 }
761 }
762 // Get chance from spell
763 float chance = float(spellProto->ProcChance);
764 // If in spellProcEvent exist custom chance, chance = spellProcEvent->customChance;
765 if (spellProcEvent && spellProcEvent->customChance)
766 chance = spellProcEvent->customChance;
767 // If PPM exist calculate chance from PPM
768 if (spellProcEvent && spellProcEvent->ppmRate != 0)
769 {
770 if (!isVictim)
771 {
772 uint32 weaponSpeed = GetAttackTime(attType);
773 chance = GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellProto);
774 }
775 else if (victim)
776 {
777 uint32 weaponSpeed = victim->GetAttackTime(attType);
778 chance = victim->GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellProto);
779 }
780 }
781 // Apply chance modifer aura
782 if (Player* modOwner = GetSpellModOwner())
783 {
784 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance);
785 }
786 return roll_chance_f(chance);
787}
788
790{
791 // aura can be deleted at casts
792 SpellInfo const* spellProto = triggeredByAura->GetSpellInfo();
793 int32 heal = triggeredByAura->GetAmount();
794 uint64 caster_guid = triggeredByAura->GetCasterGUID();
795
796 // Currently only Prayer of Mending
797 if (!(spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && spellProto->SpellFamilyFlags[1] & 0x20))
798 {
799 SF_LOG_DEBUG("spells", "Unit::HandleAuraRaidProcFromChargeWithValue, received not handled spell: %u", spellProto->Id);
800 return false;
801 }
802
803 // jumps
804 int32 jumps = triggeredByAura->GetBase()->GetCharges() - 1;
805
806 // current aura expire
807 triggeredByAura->GetBase()->SetCharges(1); // will removed at next charges decrease
808
809 // next target selection
810 if (jumps > 0)
811 {
812 if (Unit* caster = triggeredByAura->GetCaster())
813 {
814 float radius = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcRadius(caster);
815
816 if (Unit* target = GetNextRandomRaidMemberOrPet(radius))
817 {
818 CastCustomSpell(target, spellProto->Id, &heal, NULL, NULL, true, NULL, triggeredByAura, caster_guid);
819 if (Aura* aura = target->GetAura(spellProto->Id, caster->GetGUID()))
820 aura->SetCharges(jumps);
821 }
822 }
823 }
824
825 // heal
826 CastCustomSpell(this, 33110, &heal, NULL, NULL, true, NULL, NULL, caster_guid);
827 return true;
828}
830{
831 // aura can be deleted at casts
832 SpellInfo const* spellProto = triggeredByAura->GetSpellInfo();
833
834 uint32 damageSpellId;
835 switch (spellProto->Id)
836 {
837 case 57949: // shiver
838 damageSpellId = 57952;
839 //animationSpellId = 57951; dummy effects for jump spell have unknown use (see also 41637)
840 break;
841 case 59978: // shiver
842 damageSpellId = 59979;
843 break;
844 case 43593: // Cold Stare
845 damageSpellId = 43594;
846 break;
847 default:
848 SF_LOG_ERROR("entities.unit", "Unit::HandleAuraRaidProcFromCharge, received unhandled spell: %u", spellProto->Id);
849 return false;
850 }
851
852 uint64 caster_guid = triggeredByAura->GetCasterGUID();
853
854 // jumps
855 int32 jumps = triggeredByAura->GetBase()->GetCharges() - 1;
856
857 // current aura expire
858 triggeredByAura->GetBase()->SetCharges(1); // will removed at next charges decrease
859
860 // next target selection
861 if (jumps > 0)
862 {
863 if (Unit* caster = triggeredByAura->GetCaster())
864 {
865 float radius = triggeredByAura->GetSpellInfo()->Effects[triggeredByAura->GetEffIndex()].CalcRadius(caster);
866 if (Unit* target = GetNextRandomRaidMemberOrPet(radius))
867 {
868 CastSpell(target, spellProto, true, NULL, triggeredByAura, caster_guid);
869 if (Aura* aura = target->GetAura(spellProto->Id, caster->GetGUID()))
870 aura->SetCharges(jumps);
871 }
872 }
873 }
874
875 CastSpell(this, damageSpellId, true, NULL, triggeredByAura, caster_guid);
876
877 return true;
878}
#define sConditionMgr
@ CONDITION_SOURCE_TYPE_SPELL_PROC
std::list< Condition * > ConditionList
#define MAX_SPELL_EFFECTS
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
std::uint16_t uint16
Definition Define.h:78
#define ASSERT
Definition Errors.h:29
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_WEAPON
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ TYPEID_PLAYER
Definition Object.h:55
@ EQUIPMENT_SLOT_MAINHAND
Definition Player.h:704
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:705
#define INVENTORY_SLOT_BAG_0
Definition Player.h:684
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
@ POWER_BURNING_EMBERS
@ CLASS_HUNTER
@ CLASS_WARRIOR
@ CLASS_WARLOCK
@ CLASS_ROGUE
@ SPELL_ATTR3_DISABLE_PROC
@ SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED
@ SPELLFAMILY_PRIEST
@ SPELLFAMILY_WARLOCK
@ SPELLFAMILY_WARRIOR
@ SPELL_HIT_TYPE_CRIT
SpellMissInfo
@ SPELL_MISS_PARRY
@ SPELL_MISS_IMMUNE
@ SPELL_MISS_ABSORB
@ SPELL_MISS_DODGE
@ SPELL_MISS_IMMUNE2
@ SPELL_MISS_NONE
@ SPELL_MISS_RESIST
@ SPELL_MISS_MISS
@ SPELL_MISS_EVADE
@ SPELL_MISS_REFLECT
@ SPELL_MISS_BLOCK
@ SPELL_MISS_DEFLECT
@ AURA_STATE_DEFENSE
@ AURA_STATE_HUNTER_PARRY
SpellSchoolMask
@ SPELL_SCHOOL_MASK_NORMAL
@ SPELL_AURA_MANA_SHIELD
@ SPELL_AURA_MOD_ATTACK_POWER
@ SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE
@ SPELL_AURA_ABILITY_IGNORE_AURASTATE
@ SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE
@ SPELL_AURA_MOD_THREAT
@ TOTAL_AURAS
@ SPELL_AURA_MOD_RESISTANCE
@ SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS
@ SPELL_AURA_PROC_TRIGGER_SPELL
@ SPELL_AURA_MOD_FEAR
@ SPELL_AURA_PROC_ON_POWER_AMOUNT
@ SPELL_AURA_MOD_POWER_REGEN
@ SPELL_AURA_OBS_MOD_POWER
@ SPELL_AURA_ADD_CASTER_HIT_TRIGGER
@ SPELL_AURA_REFLECT_SPELLS
@ SPELL_AURA_MOD_MELEE_HASTE
@ SPELL_AURA_MOD_SPELL_CRIT_CHANCE
@ SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
@ SPELL_AURA_DUMMY
@ SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
@ SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
@ SPELL_AURA_PROC_TRIGGER_SPELL_2
@ SPELL_AURA_MOD_FEAR_2
@ SPELL_AURA_MOD_ROOT
@ SPELL_AURA_MOD_POWER_COST_SCHOOL
@ SPELL_AURA_MECHANIC_IMMUNITY
@ SPELL_AURA_RAID_PROC_FROM_CHARGE
@ SPELL_AURA_MOD_DAMAGE_TAKEN
@ SPELL_AURA_TRANSFORM
@ SPELL_AURA_SCHOOL_ABSORB
@ SPELL_AURA_REDUCE_PUSHBACK
@ SPELL_AURA_SPELL_MAGNET
@ SPELL_AURA_PROC_TRIGGER_DAMAGE
@ SPELL_AURA_MOD_POWER_REGEN_PERCENT
@ SPELL_AURA_MOD_DAMAGE_FROM_CASTER
@ SPELL_AURA_DAMAGE_IMMUNITY
@ SPELL_AURA_MOD_DAMAGE_DONE
@ SPELL_AURA_MOD_CONFUSE
@ SPELL_AURA_REFLECT_SPELLS_SCHOOL
@ SPELL_AURA_MOD_MECHANIC_RESISTANCE
@ SPELL_AURA_MOD_MELEE_HASTE_3
@ SPELL_AURA_MOD_STEALTH
@ SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
@ SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
@ SPELL_AURA_MOD_STUN
#define MELEE_BASED_TRIGGER_MASK
Definition SpellMgr.h:173
#define sSpellMgr
Definition SpellMgr.h:744
@ PROC_EX_NONE
Definition SpellMgr.h:184
@ PROC_EX_DODGE
Definition SpellMgr.h:189
@ PROC_EX_DEFLECT
Definition SpellMgr.h:194
@ PROC_EX_BLOCK
Definition SpellMgr.h:191
@ PROC_EX_INTERNAL_CANT_PROC
Definition SpellMgr.h:206
@ PROC_EX_CRITICAL_HIT
Definition SpellMgr.h:186
@ PROC_EX_NORMAL_HIT
Definition SpellMgr.h:185
@ PROC_EX_IMMUNE
Definition SpellMgr.h:193
@ PROC_EX_MISS
Definition SpellMgr.h:187
@ PROC_EX_RESIST
Definition SpellMgr.h:188
@ PROC_EX_REFLECT
Definition SpellMgr.h:196
@ PROC_EX_ABSORB
Definition SpellMgr.h:195
@ PROC_EX_PARRY
Definition SpellMgr.h:190
@ PROC_EX_INTERNAL_TRIGGERED
Definition SpellMgr.h:209
@ PROC_EX_EVADE
Definition SpellMgr.h:192
@ PROC_EX_INTERNAL_REQ_FAMILY
Definition SpellMgr.h:210
@ PROC_FLAG_TAKEN_PERIODIC
Definition SpellMgr.h:126
@ PROC_FLAG_KILL
Definition SpellMgr.h:99
@ PROC_FLAG_DONE_TRAP_ACTIVATION
Definition SpellMgr.h:129
WeaponAttackType
Definition Unit.h:572
@ SPELLMOD_CHANCE_OF_SUCCESS
Definition Unit.h:91
@ SPELLMOD_PROC_PER_MINUTE
Definition Unit.h:99
@ REACTIVE_OVERPOWER
Definition Unit.h:1335
@ REACTIVE_DEFENSE
Definition Unit.h:1333
@ REACTIVE_HUNTER_PARRY
Definition Unit.h:1334
@ SPELL_DIRECT_DAMAGE
Definition Unit.h:615
static bool procPrepared
static bool isAlwaysTriggeredAura[TOTAL_AURAS]
static bool InitTriggerAuraData()
static bool isNonTriggerAura[TOTAL_AURAS]
static bool isTriggerAura[TOTAL_AURAS]
std::list< ProcTriggeredData > ProcTriggeredList
uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition)
bool roll_chance_f(float chance)
Definition Util.h:83
SpellInfo const * GetSpellInfo() const
AuraType GetAuraType() const
uint32 GetId() const
void SetAmount(int32 amount)
Unit * GetCaster() const
int32 GetMiscValue() const
Aura * GetBase() const
uint32 GetEffIndex() const
void HandleProcTriggerDamageAuraProc(AuraApplication *aurApp, ProcEventInfo &eventInfo)
uint64 GetCasterGUID() const
int32 GetAmount() const
int32 GetMaxDuration() const
Definition SpellAuras.h:115
Unit * GetUnitOwner() const
Definition SpellAuras.h:94
uint32 GetId() const
Definition SpellAuras.h:88
int32 GetDuration() const
Definition SpellAuras.h:119
AuraEffect * GetEffect(uint8 effIndex) const
Definition SpellAuras.h:168
void SetCharges(uint8 charges)
bool CallScriptCheckProcHandlers(AuraApplication const *aurApp, ProcEventInfo &eventInfo)
uint8 GetCharges() const
Definition SpellAuras.h:126
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:87
Definition Item.h:202
ItemTemplate const * GetTemplate() const
Definition Item.cpp:528
bool IsBroken() const
Definition Item.h:247
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
TypeID GetTypeId() const
Definition Object.h:131
Unit * ToUnit()
Definition Object.h:210
void AddComboPoints(Unit *target, int8 count, Spell *spell=NULL)
Definition Player.cpp:18439
Item * GetUseableItemByPos(uint8 bag, uint8 slot) const
bool isHonorOrXPTarget(Unit const *victim)
Definition Player.cpp:19697
void RemoveSpellCooldown(uint32 spell_id, bool update=false)
Definition Player.cpp:4284
Unit * GetActionTarget() const
Definition Unit.h:973
Unit * GetProcTarget() const
Definition Unit.h:974
Unit * GetActor() const
Definition Unit.h:972
uint32 TriggerSpell
Definition SpellInfo.h:108
float CalcRadius(Unit *caster=NULL, Spell *=NULL) const
Definition Spell.h:289
SpellEffectInfo Effects[MAX_SPELL_EFFECTS]
Definition SpellInfo.h:255
uint32 CalcCastTime(uint8 level=0, Spell *spell=NULL) const
uint32 Mechanic
Definition SpellInfo.h:163
uint32 Id
Definition SpellInfo.h:160
int32 EquippedItemClass
Definition SpellInfo.h:215
uint32 SchoolMask
Definition SpellInfo.h:231
uint32 ProcFlags
Definition SpellInfo.h:201
flag128 SpellFamilyFlags
Definition SpellInfo.h:227
uint32 AttributesEx3
Definition SpellInfo.h:167
int32 EquippedItemSubClassMask
Definition SpellInfo.h:216
uint32 SpellIconID
Definition SpellInfo.h:220
uint32 ProcChance
Definition SpellInfo.h:202
uint32 SpellFamilyName
Definition SpellInfo.h:226
bool HandleAuraRaidProcFromChargeWithValue(AuraEffect *triggeredByAura)
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void SetPower(Powers power, int32 val)
Definition Unit.cpp:5255
Player * GetSpellModOwner() const
Definition Unit.cpp:5818
bool HandleDummyAuraProc(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
Definition UnitProc.cpp:193
bool HandleAuraProc(Unit *victim, uint32 damage, Aura *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool *handled)
void SetCantProc(bool apply)
void GetProcAurasTriggeredOnEvent(AuraApplicationList &aurasTriggeringProc, AuraApplicationList *procAuras, ProcEventInfo eventInfo)
bool haveOffhandWeapon() const
Definition Unit.cpp:350
void StartReactiveTimer(ReactiveType reactive)
Definition Unit.h:2690
uint8 getClass() const
Definition Unit.h:1543
bool HandleOverrideClassScriptAuraProc(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 cooldown)
bool HandleProcTriggerSpell(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
void ProcDamageAndSpellFor(bool isVictim, Unit *target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const *procSpell, uint32 damage, SpellInfo const *procAura=NULL)
bool IsTriggeredAtSpellProcEvent(Unit *victim, Aura *aura, SpellInfo const *procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const *&spellProcEvent)
bool HandleAuraRaidProcFromCharge(AuraEffect *triggeredByAura)
Unit * GetNextRandomRaidMemberOrPet(float radius)
Definition Unit.cpp:2826
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
bool isAttackReady(WeaponAttackType type=WeaponAttackType::BASE_ATTACK) const
Definition Unit.h:1432
void ModifyAuraState(AuraStateType flag, bool apply)
uint32 GetAttackTime(WeaponAttackType att) const
Definition Unit.cpp:4122
int32 GetPower(Powers power) const
Definition Unit.cpp:5237
void CastCustomSpell(Unit *victim, uint32 spellId, int32 const *bp0, int32 const *bp1, int32 const *bp2, bool triggered, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
Unit(bool isWorldObject)
Definition Unit.cpp:142
bool IsInFeralForm() const
Definition Unit.cpp:4936
uint8 getLevel() const
Definition Unit.h:1528
AuraApplicationMap & GetAppliedAuras()
Definition Unit.h:2204
int32 m_procDeep
Definition Unit.h:2885
void TriggerAurasProcOnEvent(CalcDamageInfo &damageInfo)
bool HandleAuraProcOnPowerAmount(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
Definition UnitProc.cpp:64
float GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellInfo *spellProto) const
float GetWeaponProcChance() const
uint32 procAttacker
Definition Unit.h:1020
uint32 procVictim
Definition Unit.h:1021
uint32 procEx
Definition Unit.h:1022
Unit * target
Definition Unit.h:1010
ProcTriggeredData(Aura *_aura)
SpellProcEventEntry const * spellProcEvent
Definition SpellMgr.h:263
float ppmRate
Definition SpellMgr.h:269
float customChance
Definition SpellMgr.h:270
uint32 procFlags
Definition SpellMgr.h:267