Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
UnitProc.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
53void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellInfo const* procSpell, SpellInfo const* procAura)
54{
55 // Not much to do if no flags are set.
56 if (procAttacker)
57 ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpell, amount, procAura);
58 // Now go on with a victim's events'n'auras
59 // Not much to do if no flags are set or there is no victim
60 if (victim && victim->IsAlive() && procVictim)
61 victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpell, amount, procAura);
62}
63
64bool Unit::HandleAuraProcOnPowerAmount(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 /*procEx*/, uint32 cooldown)
65{
66 // Get triggered aura spell info
67 SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo();
68
69 // Get effect index used for the proc
70 uint32 effIndex = triggeredByAura->GetEffIndex();
71
72 // Power amount required to proc the spell
73 int32 powerAmountRequired = triggeredByAura->GetAmount();
74 // Power type required to proc
75 Powers powerRequired = Powers(auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].MiscValue);
76
77 // Set trigger spell id, target, custom basepoints
78 uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
79
80 Unit* target = NULL;
81 int32 basepoints0 = 0;
82
83 Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TypeID::TYPEID_PLAYER
84 ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
85
86 /* Try handle unknown trigger spells or with invalid power amount or misc value
87 if (sSpellMgr->GetSpellInfo(trigger_spell_id) == NULL || powerAmountRequired == NULL || powerRequired >= MAX_POWER)
88 {
89 switch (auraSpellInfo->SpellFamilyName)
90 {
91 case SPELLFAMILY_GENERIC:
92 {
93 break;
94 }
95 }
96 }*/
97
98 // All ok. Check current trigger spell
99 SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(trigger_spell_id);
100 if (triggerEntry == NULL)
101 {
102 // Not cast unknown spell
103 // SF_LOG_ERROR("Unit::HandleAuraProcOnPowerAmount: Spell %u have 0 in EffectTriggered[%d], not handled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex());
104 return false;
105 }
106
107 // not allow proc extra attack spell at extra attack
109 return false;
110
111 if (!powerRequired || !powerAmountRequired)
112 {
113 SF_LOG_ERROR("spells", "Unit::HandleAuraProcOnPowerAmount: Spell %u have 0 powerAmountRequired in EffectAmount[%d] or 0 powerRequired in EffectMiscValue, not handled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex());
114 return false;
115 }
116
117 if (GetPower(powerRequired) != powerAmountRequired)
118 return false;
119
120 // Custom requirements (not listed in procEx) Warning! damage dealing after this
121 // Custom triggered spells
122 switch (auraSpellInfo->SpellFamilyName)
123 {
125 {
126 // Eclipse Mastery Driver Passive
127 if (auraSpellInfo->Id == 79577)
128 {
129 uint32 solarEclipseMarker = 67483;
130 uint32 lunarEclipseMarker = 67484;
131
132 switch (effIndex)
133 {
134 case 0:
135 {
136 if (HasAura(trigger_spell_id))
137 return false;
138
139 // Do not proc if proc spell isnt starfire and starsurge
140 if (procSpell->Id != 2912 && procSpell->Id != 78674)
141 return false;
142
143 if (HasAura(solarEclipseMarker))
144 {
145 RemoveAurasDueToSpell(solarEclipseMarker);
146 CastSpell(this, lunarEclipseMarker, true);
147 }
148 break;
149 }
150 case 1:
151 {
152 if (HasAura(trigger_spell_id))
153 return false;
154
155 // Do not proc if proc spell isnt wrath and starsurge
156 if (procSpell->Id != 5176 && procSpell->Id != 78674)
157 return false;
158
159 if (HasAura(lunarEclipseMarker))
160 {
161 RemoveAurasDueToSpell(lunarEclipseMarker);
162 CastSpell(this, solarEclipseMarker, true);
163 }
164
165 break;
166 }
167 }
168 }
169 break;
170 }
171 }
172
173 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(trigger_spell_id))
174 return false;
175
176 // try detect target manually if not set
177 if (target == NULL)
178 target = !(procFlag & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry && triggerEntry->IsPositive() ? this : victim;
179
180 if (basepoints0)
181 CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
182 else
183 CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
184
185 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER)
186 ToPlayer()->AddSpellCooldown(trigger_spell_id, 0, time(NULL) + cooldown);
187
188 return true;
189}
190
191//victim may be NULL
192
193bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
194{
195 SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
196 uint32 effIndex = triggeredByAura->GetEffIndex();
197 int32 triggerAmount = triggeredByAura->GetAmount();
198
199 Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TypeID::TYPEID_PLAYER
200 ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
201
202 uint32 triggered_spell_id = 0;
203 uint32 cooldown_spell_id = 0; // for random trigger, will be one of the triggered spell to avoid repeatable triggers
204 // otherwise, it's the triggered_spell_id by default
205 Unit* target = victim;
206 int32 basepoints0 = 0;
207 uint64 originalCaster = 0;
208
209 switch (dummySpell->SpellFamilyName)
210 {
212 {
213 switch (dummySpell->Id)
214 {
215 // Unstable Power
216 case 24658:
217 {
218 if (!procSpell || procSpell->Id == 24659)
219 return false;
220 // Need remove one 24659 aura
221 RemoveAuraFromStack(24659);
222 return true;
223 }
224 // Restless Strength
225 case 24661:
226 {
227 // Need remove one 24662 aura
228 RemoveAuraFromStack(24662);
229 return true;
230 }
231 // Mark of Malice
232 case 33493:
233 {
234 // Cast finish spell at last charge
235 if (triggeredByAura->GetBase()->GetCharges() > 1)
236 return false;
237
238 target = this;
239 triggered_spell_id = 33494;
240 break;
241 }
242 // Twisted Reflection (boss spell)
243 case 21063:
244 {
245 triggered_spell_id = 21064;
246 break;
247 }
248 // Vampiric Aura (boss spell)
249 case 38196:
250 {
251 basepoints0 = 3 * damage; // 300%
252 if (basepoints0 < 0)
253 return false;
254
255 triggered_spell_id = 31285;
256 target = this;
257 break;
258 }
259 // Aura of Madness (Darkmoon Card: Madness trinket)
260 //=====================================================
261 // 39511 Sociopath: +35 strength (Paladin, Rogue, Druid, Warrior)
262 // 40997 Delusional: +70 attack power (Rogue, Hunter, Paladin, Warrior, Druid)
263 // 40998 Kleptomania: +35 agility (Warrior, Rogue, Paladin, Hunter, Druid)
264 // 40999 Megalomania: +41 damage/healing (Druid, Shaman, Priest, Warlock, Mage, Paladin)
265 // 41002 Paranoia: +35 spell/melee/ranged crit strike rating (All classes)
266 // 41005 Manic: +35 haste (spell, melee and ranged) (All classes)
267 // 41009 Narcissism: +35 intellect (Druid, Shaman, Priest, Warlock, Mage, Paladin, Hunter)
268 // 41011 Martyr Complex: +35 stamina (All classes)
269 // 41406 Dementia: Every 5 seconds either gives you +5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin)
270 // 41409 Dementia: Every 5 seconds either gives you -5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin)
271 case 39446:
272 {
274 return false;
275
276 // Select class defined buff
277 switch (getClass())
278 {
279 case CLASS_PALADIN: // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409
280 case CLASS_DRUID: // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409
281 triggered_spell_id = RAND(39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409);
282 cooldown_spell_id = 39511;
283 break;
284 case CLASS_ROGUE: // 39511, 40997, 40998, 41002, 41005, 41011
285 case CLASS_WARRIOR: // 39511, 40997, 40998, 41002, 41005, 41011
287 triggered_spell_id = RAND(39511, 40997, 40998, 41002, 41005, 41011);
288 cooldown_spell_id = 39511;
289 break;
290 case CLASS_PRIEST: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
291 case CLASS_SHAMAN: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
292 case CLASS_MAGE: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
293 case CLASS_WARLOCK: // 40999, 41002, 41005, 41009, 41011, 41406, 41409
294 triggered_spell_id = RAND(40999, 41002, 41005, 41009, 41011, 41406, 41409);
295 cooldown_spell_id = 40999;
296 break;
297 case CLASS_HUNTER: // 40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409
298 triggered_spell_id = RAND(40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409);
299 cooldown_spell_id = 40997;
300 break;
301 default:
302 return false;
303 }
304
305 target = this;
306 if (roll_chance_i(10))
307 ToPlayer()->Say("This is Madness!", Language::LANG_UNIVERSAL);
308 break;
309 }
310 // Sunwell Exalted Caster Neck (??? neck)
311 // cast ??? Light's Wrath if Exalted by Aldor
312 // cast ??? Arcane Bolt if Exalted by Scryers
313 case 46569:
314 return false; // old unused version
315 // Sunwell Exalted Caster Neck (Shattered Sun Pendant of Acumen neck)
316 // cast 45479 Light's Wrath if Exalted by Aldor
317 // cast 45429 Arcane Bolt if Exalted by Scryers
318 case 45481:
319 {
320 Player* player = ToPlayer();
321 if (!player)
322 return false;
323
324 // Get Aldor reputation rank
325 if (player->GetReputationRank(932) == REP_EXALTED)
326 {
327 target = this;
328 triggered_spell_id = 45479;
329 break;
330 }
331 // Get Scryers reputation rank
332 if (player->GetReputationRank(934) == REP_EXALTED)
333 {
334 // triggered at positive/self casts also, current attack target used then
335 if (target && IsFriendlyTo(target))
336 {
337 target = GetVictim();
338 if (!target)
339 {
340 target = player->GetSelectedUnit();
341 if (!target)
342 return false;
343 }
344 if (IsFriendlyTo(target))
345 return false;
346 }
347
348 triggered_spell_id = 45429;
349 break;
350 }
351 return false;
352 }
353 // Sunwell Exalted Melee Neck (Shattered Sun Pendant of Might neck)
354 // cast 45480 Light's Strength if Exalted by Aldor
355 // cast 45428 Arcane Strike if Exalted by Scryers
356 case 45482:
357 {
359 return false;
360
361 // Get Aldor reputation rank
362 if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
363 {
364 target = this;
365 triggered_spell_id = 45480;
366 break;
367 }
368 // Get Scryers reputation rank
369 if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
370 {
371 triggered_spell_id = 45428;
372 break;
373 }
374 return false;
375 }
376 // Sunwell Exalted Tank Neck (Shattered Sun Pendant of Resolve neck)
377 // cast 45431 Arcane Insight if Exalted by Aldor
378 // cast 45432 Light's Ward if Exalted by Scryers
379 case 45483:
380 {
382 return false;
383
384 // Get Aldor reputation rank
385 if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
386 {
387 target = this;
388 triggered_spell_id = 45432;
389 break;
390 }
391 // Get Scryers reputation rank
392 if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
393 {
394 target = this;
395 triggered_spell_id = 45431;
396 break;
397 }
398 return false;
399 }
400 // Sunwell Exalted Healer Neck (Shattered Sun Pendant of Restoration neck)
401 // cast 45478 Light's Salvation if Exalted by Aldor
402 // cast 45430 Arcane Surge if Exalted by Scryers
403 case 45484:
404 {
406 return false;
407
408 // Get Aldor reputation rank
409 if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
410 {
411 target = this;
412 triggered_spell_id = 45478;
413 break;
414 }
415 // Get Scryers reputation rank
416 if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
417 {
418 triggered_spell_id = 45430;
419 break;
420 }
421 return false;
422 }
423 // Vampiric Touch (generic, used by some boss)
424 case 52723:
425 case 60501:
426 {
427 triggered_spell_id = 52724;
428 basepoints0 = damage / 2;
429 target = this;
430 break;
431 }
432 // Shadowfiend Death (Gain mana if pet dies with Glyph of Shadowfiend)
433 case 57989:
434 {
435 Unit* owner = GetOwner();
436 if (!owner || owner->GetTypeId() != TypeID::TYPEID_PLAYER)
437 return false;
438 // Glyph of Shadowfiend (need cast as self cast for owner, no hidden cooldown)
439 owner->CastSpell(owner, 58227, true, castItem, triggeredByAura);
440 return true;
441 }
442 // Purified Shard of the Scale - Onyxia 10 Caster Trinket
443 case 69755:
444 {
445 triggered_spell_id = (procFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS) ? 69733 : 69729;
446 break;
447 }
448 // Shiny Shard of the Scale - Onyxia 25 Caster Trinket
449 case 69739:
450 {
451 triggered_spell_id = (procFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS) ? 69734 : 69730;
452 break;
453 }
454 case 71519: // Deathbringer's Will Normal
455 {
457 return false;
458
459 std::vector<uint32> RandomSpells;
460 switch (getClass())
461 {
462 case CLASS_WARRIOR:
463 case CLASS_PALADIN:
465 RandomSpells.push_back(71484);
466 RandomSpells.push_back(71491);
467 RandomSpells.push_back(71492);
468 break;
469 case CLASS_SHAMAN:
470 case CLASS_ROGUE:
471 RandomSpells.push_back(71486);
472 RandomSpells.push_back(71485);
473 RandomSpells.push_back(71492);
474 break;
475 case CLASS_DRUID:
476 RandomSpells.push_back(71484);
477 RandomSpells.push_back(71485);
478 RandomSpells.push_back(71492);
479 break;
480 case CLASS_HUNTER:
481 RandomSpells.push_back(71486);
482 RandomSpells.push_back(71491);
483 RandomSpells.push_back(71485);
484 break;
485 default:
486 return false;
487 }
488 if (RandomSpells.empty()) // shouldn't happen
489 return false;
490
491 uint8 rand_spell = std::rand() % RandomSpells.size();
492 CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster);
493 for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr)
494 {
495 if (!ToPlayer()->HasSpellCooldown(*itr))
496 ToPlayer()->AddSpellCooldown(*itr, 0, time(NULL) + cooldown);
497 }
498 break;
499 }
500 case 71562: // Deathbringer's Will Heroic
501 {
503 return false;
504
505 std::vector<uint32> RandomSpells;
506 switch (getClass())
507 {
508 case CLASS_WARRIOR:
509 case CLASS_PALADIN:
511 RandomSpells.push_back(71561);
512 RandomSpells.push_back(71559);
513 RandomSpells.push_back(71560);
514 break;
515 case CLASS_SHAMAN:
516 case CLASS_ROGUE:
517 RandomSpells.push_back(71558);
518 RandomSpells.push_back(71556);
519 RandomSpells.push_back(71560);
520 break;
521 case CLASS_DRUID:
522 RandomSpells.push_back(71561);
523 RandomSpells.push_back(71556);
524 RandomSpells.push_back(71560);
525 break;
526 case CLASS_HUNTER:
527 RandomSpells.push_back(71558);
528 RandomSpells.push_back(71559);
529 RandomSpells.push_back(71556);
530 break;
531 default:
532 return false;
533 }
534 if (RandomSpells.empty()) // shouldn't happen
535 return false;
536
537 uint8 rand_spell = std::rand() % RandomSpells.size();
538 CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster);
539 for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr)
540 {
541 if (!ToPlayer()->HasSpellCooldown(*itr))
542 ToPlayer()->AddSpellCooldown(*itr, 0, time(NULL) + cooldown);
543 }
544 break;
545 }
546 case 65032: // Boom aura (321 Boombot)
547 {
548 if (victim->GetEntry() != 33343) // Scrapbot
549 return false;
550
551 InstanceScript* instance = GetInstanceScript();
552 if (!instance)
553 return false;
554
555 instance->DoCastSpellOnPlayers(65037); // Achievement criteria marker
556 break;
557 }
558 case 47020: // Enter vehicle XT-002 (Scrapbot)
559 {
561 return false;
562
563 Unit* vehicleBase = GetVehicleBase();
564 if (!vehicleBase)
565 return false;
566
567 // Todo: Check if this amount is blizzlike
568 vehicleBase->ModifyHealth(int32(vehicleBase->CountPctFromMaxHealth(1)));
569 break;
570 }
571 }
572 break;
573 }
574 case SPELLFAMILY_MAGE:
575 {
576 // Heating Up & Pyroblast!
577 if (dummySpell->SpellIconID == 2999)
578 {
579 if (effIndex != 0)
580 return false;
581 AuraEffect* counter = triggeredByAura->GetBase()->GetEffect(EFFECT_0);
582 if (!counter)
583 return true;
584
585 // Count spell criticals in a row in second aura
586 if (procEx & PROC_EX_CRITICAL_HIT)
587 {
588 counter->SetAmount(counter->GetAmount() * 2);
589 if (counter->GetAmount() < 100) // not enough
590 {
591 CastSpell(this, 48107, true, castItem, triggeredByAura); // Heating Up
592 return true;
593 }
594 // Critical counted -> roll chance
595 if (roll_chance_i(triggerAmount))
596 {
597 CastSpell(this, 48108, true, castItem, triggeredByAura); // Pyroblast!
598 }
599 }
600 counter->SetAmount(25);
601 return true;
602 }
603 // Incanter's Regalia set (add trigger chance to Mana Shield)
604 if (dummySpell->SpellFamilyFlags[0] & 0x8000)
605 {
607 return false;
608
609 target = this;
610 triggered_spell_id = 37436;
611 break;
612 }
613 break;
614 }
616 {
617 // Seed of Corruption
618 if (dummySpell->SpellFamilyFlags[1] & 0x00000010)
619 {
620 if (procSpell && procSpell->SpellFamilyFlags[1] & 0x8000)
621 return false;
622 // if damage is more than need or target die from damage deal finish spell
623 if (triggeredByAura->GetAmount() <= int32(damage) || GetHealth() <= damage)
624 {
625 // remember caster before aura delete
626 Unit* caster = triggeredByAura->GetCaster();
627
628 // Remove aura (before cast for prevent infinite loop handlers)
629 RemoveAurasDueToSpell(triggeredByAura->GetId());
630
631 uint32 spell = sSpellMgr->GetSpellWithRank(27285, dummySpell->GetRank());
632
633 // Cast finish spell (triggeredByAura already not exist!)
634 if (caster)
635 caster->CastSpell(this, spell, true, castItem);
636 return true; // no hidden cooldown
637 }
638
639 // Damage counting
640 triggeredByAura->SetAmount(triggeredByAura->GetAmount() - damage);
641 return true;
642 }
643 // Seed of Corruption (Mobs cast) - no die req
644 if (dummySpell->SpellFamilyFlags.IsEqual(0, 0, 0) && dummySpell->SpellIconID == 1932)
645 {
646 // if damage is more than need deal finish spell
647 if (triggeredByAura->GetAmount() <= int32(damage))
648 {
649 // remember caster before aura delete
650 Unit* caster = triggeredByAura->GetCaster();
651
652 // Remove aura (before cast for prevent infinite loop handlers)
653 RemoveAurasDueToSpell(triggeredByAura->GetId());
654
655 // Cast finish spell (triggeredByAura already not exist!)
656 if (caster)
657 caster->CastSpell(this, 32865, true, castItem);
658 return true; // no hidden cooldown
659 }
660 // Damage counting
661 triggeredByAura->SetAmount(triggeredByAura->GetAmount() - damage);
662 return true;
663 }
664 switch (dummySpell->Id)
665 {
666 // Shadowflame (Voidheart Raiment set bonus)
667 case 37377:
668 {
669 triggered_spell_id = 37379;
670 break;
671 }
672 // Pet Healing (Corruptor Raiment or Rift Stalker Armor)
673 case 37381:
674 {
675 target = GetGuardianPet();
676 if (!target)
677 return false;
678
679 // heal amount
680 basepoints0 = CalculatePct(int32(damage), triggerAmount);
681 triggered_spell_id = 37382;
682 break;
683 }
684 // Shadowflame Hellfire (Voidheart Raiment set bonus)
685 case 39437:
686 {
687 triggered_spell_id = 37378;
688 break;
689 }
690 }
691 break;
692 }
694 {
695 switch (dummySpell->Id)
696 {
697 // Priest Tier 6 Trinket (Ashtongue Talisman of Acumen)
698 case 40438:
699 {
700 // Shadow Word: Pain
701 if (procSpell->SpellFamilyFlags[0] & 0x8000)
702 triggered_spell_id = 40441;
703 // Renew
704 else if (procSpell->SpellFamilyFlags[0] & 0x40)
705 triggered_spell_id = 40440;
706 else
707 return false;
708
709 target = this;
710 break;
711 }
712 // Oracle Healing Bonus ("Garments of the Oracle" set)
713 case 26169:
714 {
715 // heal amount
716 basepoints0 = int32(CalculatePct(damage, 10));
717 target = this;
718 triggered_spell_id = 26170;
719 break;
720 }
721 // Frozen Shadoweave (Shadow's Embrace set) warning! its not only priest set
722 case 39372:
723 {
724 if (!procSpell || (procSpell->GetSchoolMask() & (SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW)) == 0)
725 return false;
726
727 // heal amount
728 basepoints0 = CalculatePct(int32(damage), triggerAmount);
729 target = this;
730 triggered_spell_id = 39373;
731 break;
732 }
733 // Greater Heal (Vestments of Faith (Priest Tier 3) - 4 pieces bonus)
734 case 28809:
735 {
736 triggered_spell_id = 28810;
737 break;
738 }
739 // Priest T10 Healer 2P Bonus
740 case 70770:
741 // Flash Heal
742 if (procSpell->SpellFamilyFlags[0] & 0x800)
743 {
744 triggered_spell_id = 70772;
745 SpellInfo const* blessHealing = sSpellMgr->GetSpellInfo(triggered_spell_id);
746 if (!blessHealing)
747 return false;
748 basepoints0 = int32(CalculatePct(damage, triggerAmount) / (blessHealing->GetMaxDuration() / blessHealing->Effects[0].ApplyAuraTickCount));
749 }
750 break;
751 }
752 break;
753 }
755 {
756 switch (dummySpell->Id)
757 {
758 // Leader of the Pack
759 case 24932:
760 {
761 if (triggerAmount <= 0)
762 return false;
763 basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
764 target = this;
765 triggered_spell_id = 34299;
766 // Regenerate 4% mana
767 int32 mana = CalculatePct(GetCreateMana(), triggerAmount);
768 CastCustomSpell(this, 68285, &mana, NULL, NULL, true, castItem, triggeredByAura);
769 break;
770 }
771 // Healing Touch (Dreamwalker Raiment set)
772 /*
773 case 28719:
774 {
775 // mana back
776 basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30));
777 target = this;
778 triggered_spell_id = 28742;
779 break;
780 }*/
781 // Mana Restore (Malorne Raiment set / Malorne Regalia set)
782 case 37288:
783 case 37295:
784 {
785 target = this;
786 triggered_spell_id = 37238;
787 break;
788 }
789 // Druid Tier 6 Trinket
790 case 40442:
791 {
792 float chance;
793
794 // Starfire
795 if (procSpell->SpellFamilyFlags[0] & 0x4)
796 {
797 triggered_spell_id = 40445;
798 chance = 25.0f;
799 }
800 // Rejuvenation
801 else if (procSpell->SpellFamilyFlags[0] & 0x10)
802 {
803 triggered_spell_id = 40446;
804 chance = 25.0f;
805 }
806 // Mangle (Bear) and Mangle (Cat)
807 else if (procSpell->SpellFamilyFlags[1] & 0x00000440)
808 {
809 triggered_spell_id = 40452;
810 chance = 40.0f;
811 }
812 else
813 return false;
814
815 if (!roll_chance_f(chance))
816 return false;
817
818 target = this;
819 break;
820 }
821 // Item - Druid T10 Balance 4P Bonus
822 case 70723:
823 {
824 // Wrath & Starfire
825 if ((procSpell->SpellFamilyFlags[0] & 0x5) && (procEx & PROC_EX_CRITICAL_HIT))
826 {
827 triggered_spell_id = 71023;
828 SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
829 if (!triggeredSpell)
830 return false;
831 basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraTickCount);
832 // Add remaining ticks to damage done
833 basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
834 }
835 break;
836 }
837 // Item - Druid T10 Restoration 4P Bonus (Rejuvenation)
838 case 70664:
839 {
840 // Proc only from normal Rejuvenation
841 if (procSpell->SpellVisual[0] != 32)
842 return false;
843
844 Player* caster = ToPlayer();
845 if (!caster)
846 return false;
847 if (!caster->GetGroup() && victim == this)
848 return false;
849
850 CastCustomSpell(70691, SPELLVALUE_BASE_POINT0, damage, victim, true);
851 return true;
852 }
853 }
854 break;
855 }
857 {
858 // Judgements of the Wise
859 if (dummySpell->SpellIconID == 3017)
860 {
861 target = this;
862 triggered_spell_id = 31930;
863 break;
864 }
865 switch (dummySpell->Id)
866 {
867 // Holy Power (Redemption Armor set)
868 case 28789:
869 {
870 if (!victim)
871 return false;
872
873 // Set class defined buff
874 switch (victim->getClass())
875 {
876 case CLASS_PALADIN:
877 case CLASS_PRIEST:
878 case CLASS_SHAMAN:
879 case CLASS_DRUID:
880 triggered_spell_id = 28795; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d.
881 break;
882 case CLASS_MAGE:
883 case CLASS_WARLOCK:
884 triggered_spell_id = 28793; // Increases the friendly target's spell damage and healing by up to $s1 for $d.
885 break;
886 case CLASS_HUNTER:
887 case CLASS_ROGUE:
888 triggered_spell_id = 28791; // Increases the friendly target's attack power by $s1 for $d.
889 break;
890 case CLASS_WARRIOR:
891 triggered_spell_id = 28790; // Increases the friendly target's armor
892 break;
893 default:
894 return false;
895 }
896 break;
897 }
898 case 31801:
899 {
900 if (effIndex != 0) // effect 2 used by seal unleashing code
901 return false;
902
903 // At melee attack or Hammer of the Righteous spell damage considered as melee attack
904 bool stacker = !procSpell || procSpell->Id == 53595;
905 // spells with SPELL_DAMAGE_CLASS_MELEE excluding Judgements
906 bool damager = procSpell && (procSpell->EquippedItemClass != -1 || (procSpell->SpellIconID == 243 && procSpell->SpellVisual[0] == 39));
907
908 if (!stacker && !damager)
909 return false;
910
911 triggered_spell_id = 31803;
912
913 // On target with 5 stacks of Censure direct damage is done
914 if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
915 {
916 if (aur->GetStackAmount() == 5)
917 {
918 if (stacker)
919 aur->RefreshDuration();
920 CastSpell(victim, 42463, true);
921 return true;
922 }
923 }
924
925 if (!stacker)
926 return false;
927 break;
928 }
929 // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
930 case 40470:
931 {
932 if (!procSpell)
933 return false;
934
935 float chance;
936
937 // Flash of light/Holy light
938 if (procSpell->SpellFamilyFlags[0] & 0xC0000000)
939 {
940 triggered_spell_id = 40471;
941 chance = 15.0f;
942 }
943 // Judgement (any)
944 else if (procSpell->GetSpellSpecific() == SPELL_SPECIFIC_JUDGEMENT)
945 {
946 triggered_spell_id = 40472;
947 chance = 50.0f;
948 }
949 else
950 return false;
951
952 if (!roll_chance_f(chance))
953 return false;
954
955 break;
956 }
957 // Item - Paladin T8 Holy 2P Bonus
958 case 64890:
959 {
960 triggered_spell_id = 64891;
961 basepoints0 = triggerAmount * damage / 300;
962 break;
963 }
964 case 71406: // Tiny Abomination in a Jar
965 case 71545: // Tiny Abomination in a Jar (Heroic)
966 {
967 if (!victim || !victim->IsAlive())
968 return false;
969
970 CastSpell(this, 71432, true, NULL, triggeredByAura);
971
972 Aura const* dummy = GetAura(71432);
973 if (!dummy || dummy->GetStackAmount() < (dummySpell->Id == 71406 ? 8 : 7))
974 return false;
975
977 triggered_spell_id = 71433; // default main hand attack
978 // roll if offhand
979 if (Player const* player = ToPlayer())
980 if (player->GetWeaponForAttack(WeaponAttackType::OFF_ATTACK, true) && std::rand() % 1)
981 triggered_spell_id = 71434;
982 target = victim;
983 break;
984 }
985 // Item - Icecrown 25 Normal Dagger Proc
986 case 71880:
987 {
988 switch (getPowerType())
989 {
990 case POWER_MANA:
991 triggered_spell_id = 71881;
992 break;
993 case POWER_RAGE:
994 triggered_spell_id = 71883;
995 break;
996 case POWER_ENERGY:
997 triggered_spell_id = 71882;
998 break;
1000 triggered_spell_id = 71884;
1001 break;
1002 default:
1003 return false;
1004 }
1005 break;
1006 }
1007 // Item - Icecrown 25 Heroic Dagger Proc
1008 case 71892:
1009 {
1010 switch (getPowerType())
1011 {
1012 case POWER_MANA:
1013 triggered_spell_id = 71888;
1014 break;
1015 case POWER_RAGE:
1016 triggered_spell_id = 71886;
1017 break;
1018 case POWER_ENERGY:
1019 triggered_spell_id = 71887;
1020 break;
1021 case POWER_RUNIC_POWER:
1022 triggered_spell_id = 71885;
1023 break;
1024 default:
1025 return false;
1026 }
1027 break;
1028 }
1029 }
1030 break;
1031 }
1032 case SPELLFAMILY_SHAMAN:
1033 {
1034 switch (dummySpell->Id)
1035 {
1036 // Totemic Power (The Earthshatterer set)
1037 case 28823:
1038 {
1039 if (!victim)
1040 return false;
1041
1042 // Set class defined buff
1043 switch (victim->getClass())
1044 {
1045 case CLASS_PALADIN:
1046 case CLASS_PRIEST:
1047 case CLASS_SHAMAN:
1048 case CLASS_DRUID:
1049 triggered_spell_id = 28824; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d.
1050 break;
1051 case CLASS_MAGE:
1052 case CLASS_WARLOCK:
1053 triggered_spell_id = 28825; // Increases the friendly target's spell damage and healing by up to $s1 for $d.
1054 break;
1055 case CLASS_HUNTER:
1056 case CLASS_ROGUE:
1057 triggered_spell_id = 28826; // Increases the friendly target's attack power by $s1 for $d.
1058 break;
1059 case CLASS_WARRIOR:
1060 triggered_spell_id = 28827; // Increases the friendly target's armor
1061 break;
1062 default:
1063 return false;
1064 }
1065 break;
1066 }
1067 // Windfury Weapon (Passive) 1-8 Ranks
1068 case 33757:
1069 {
1070 Player* player = ToPlayer();
1071 if (!player || !castItem || !castItem->IsEquipped() || !victim || !victim->IsAlive())
1072 return false;
1073
1074 // custom cooldown processing case
1075 if (cooldown && player->HasSpellCooldown(dummySpell->Id))
1076 return false;
1077
1078 if (triggeredByAura->GetBase() && castItem->GetGUID() != triggeredByAura->GetBase()->GetCastItemGUID())
1079 return false;
1080
1081 WeaponAttackType attType = WeaponAttackType(player->GetAttackBySlot(castItem->GetSlot()));
1082 if ((attType != WeaponAttackType::BASE_ATTACK && attType != WeaponAttackType::OFF_ATTACK)
1085 return false;
1086
1087 // Now compute real proc chance...
1088 uint32 chance = 20;
1089 player->ApplySpellMod(dummySpell->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance);
1090
1092 uint32 enchant_id_add = addWeapon ? addWeapon->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)) : 0;
1093 SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id_add);
1094 if (pEnchant && pEnchant->spellid[0] == dummySpell->Id)
1095 chance += 14;
1096
1097 if (!roll_chance_i(chance))
1098 return false;
1099
1100 // Now amount of extra power stored in 1 effect of Enchant spell
1101 uint32 spellId = 8232;
1102 SpellInfo const* windfurySpellInfo = sSpellMgr->GetSpellInfo(spellId);
1103 if (!windfurySpellInfo)
1104 {
1105 SF_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: non-existing spell id: %u (Windfury)", spellId);
1106 return false;
1107 }
1108
1109 int32 extra_attack_power = CalculateSpellDamage(victim, windfurySpellInfo, 1);
1110
1111 // Value gained from additional AP
1112 basepoints0 = int32(extra_attack_power / 14.0f * GetAttackTime(attType) / 1000);
1113
1114 if (procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)
1115 triggered_spell_id = 25504;
1116
1117 if (procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
1118 triggered_spell_id = 33750;
1119
1120 // apply cooldown before cast to prevent processing itself
1121 if (cooldown)
1122 player->AddSpellCooldown(dummySpell->Id, 0, time(NULL) + cooldown);
1123
1124 // Attack Twice
1125 for (uint32 i = 0; i < 2; ++i)
1126 CastCustomSpell(victim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
1127
1128 return true;
1129 }
1130 // Shaman Tier 6 Trinket
1131 case 40463:
1132 {
1133 if (!procSpell)
1134 return false;
1135
1136 float chance;
1137 if (procSpell->SpellFamilyFlags[0] & 0x1)
1138 {
1139 triggered_spell_id = 40465; // Lightning Bolt
1140 chance = 15.0f;
1141 }
1142 else if (procSpell->SpellFamilyFlags[0] & 0x80)
1143 {
1144 triggered_spell_id = 40465; // Lesser Healing Wave
1145 chance = 10.0f;
1146 }
1147 else if (procSpell->SpellFamilyFlags[1] & 0x00000010)
1148 {
1149 triggered_spell_id = 40466; // Stormstrike
1150 chance = 50.0f;
1151 }
1152 else
1153 return false;
1154
1155 if (!roll_chance_f(chance))
1156 return false;
1157
1158 target = this;
1159 break;
1160 }
1161 // Spirit Hunt
1162 case 58877:
1163 {
1164 // Cast on owner
1165 target = GetOwner();
1166 if (!target)
1167 return false;
1168 basepoints0 = CalculatePct(int32(damage), triggerAmount);
1169 triggered_spell_id = 58879;
1170 // Cast on spirit wolf
1171 CastCustomSpell(this, triggered_spell_id, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
1172 break;
1173 }
1174 // Shaman T8 Elemental 4P Bonus
1175 case 64928:
1176 {
1177 basepoints0 = CalculatePct(int32(damage), triggerAmount);
1178 triggered_spell_id = 64930; // Electrified
1179 break;
1180 }
1181 // Shaman T9 Elemental 4P Bonus
1182 case 67228:
1183 {
1184 // Lava Burst
1185 if (procSpell->SpellFamilyFlags[1] & 0x1000)
1186 {
1187 triggered_spell_id = 71824;
1188 SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
1189 if (!triggeredSpell)
1190 return false;
1191 basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraTickCount);
1192 }
1193 break;
1194 }
1195 // Item - Shaman T10 Restoration 4P Bonus
1196 case 70808:
1197 {
1198 // Chain Heal
1199 if ((procSpell->SpellFamilyFlags[0] & 0x100) && (procEx & PROC_EX_CRITICAL_HIT))
1200 {
1201 triggered_spell_id = 70809;
1202 SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id);
1203 if (!triggeredSpell)
1204 return false;
1205 basepoints0 = CalculatePct(int32(damage), triggerAmount) / (triggeredSpell->GetMaxDuration() / triggeredSpell->Effects[0].ApplyAuraTickCount);
1206 // Add remaining ticks to healing done
1207 basepoints0 += GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_HEAL);
1208 }
1209 break;
1210 }
1211 // Item - Shaman T10 Elemental 2P Bonus
1212 case 70811:
1213 {
1214 // Lightning Bolt & Chain Lightning
1215 if (procSpell->SpellFamilyFlags[0] & 0x3)
1216 {
1217 if (ToPlayer()->HasSpellCooldown(16166))
1218 {
1219 uint32 newCooldownDelay = ToPlayer()->GetSpellCooldownDelay(16166);
1220 if (newCooldownDelay < 3)
1221 newCooldownDelay = 0;
1222 else
1223 newCooldownDelay -= 2;
1224
1225 ToPlayer()->AddSpellCooldown(16166, 0, uint32(time(NULL) + newCooldownDelay));
1226 ToPlayer()->GetSession()->SendModifyCooldown(GetObjectGUID(), -2000, 16166);
1227 return true;
1228 }
1229 }
1230 return false;
1231 }
1232 // Item - Shaman T10 Elemental 4P Bonus
1233 case 70817:
1234 {
1235 if (!target)
1236 return false;
1237 // try to find spell Flame Shock on the target
1238 if (AuraEffect const* aurEff = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 0x10000000, 0x0, 0x0, GetGUID()))
1239 {
1240 Aura* flameShock = aurEff->GetBase();
1241 int32 maxDuration = flameShock->GetMaxDuration();
1242 int32 newDuration = flameShock->GetDuration() + 2 * aurEff->GetAmplitude();
1243
1244 flameShock->SetDuration(newDuration);
1245 // is it blizzlike to change max duration for FS?
1246 if (newDuration > maxDuration)
1247 flameShock->SetMaxDuration(newDuration);
1248
1249 return true;
1250 }
1251 // if not found Flame Shock
1252 return false;
1253 }
1254 break;
1255 }
1256 // Frozen Power
1257 if (dummySpell->SpellIconID == 3780)
1258 {
1259 if (!target)
1260 return false;
1261 if (GetDistance(target) < 15.0f)
1262 return false;
1263 float chance = (float)triggerAmount;
1264 if (!roll_chance_f(chance))
1265 return false;
1266
1267 triggered_spell_id = 63685;
1268 break;
1269 }
1270 // Flametongue Weapon (Passive)
1271 if (dummySpell->SpellFamilyFlags[0] & 0x200000)
1272 {
1273 if (GetTypeId() != TypeID::TYPEID_PLAYER || !victim || !victim->IsAlive() || !castItem || !castItem->IsEquipped())
1274 return false;
1275
1277 if ((attType != WeaponAttackType::BASE_ATTACK && attType != WeaponAttackType::OFF_ATTACK)
1280 return false;
1281
1282 float fire_onhit = float(CalculatePct(dummySpell->Effects[EFFECT_0].CalcValue(), 1.0f));
1283
1284 float add_spellpower = (float)(SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_FIRE)
1286
1287 // 1.3speed = 5%, 2.6speed = 10%, 4.0 speed = 15%, so, 1.0speed = 3.84%
1288 ApplyPct(add_spellpower, 3.84f);
1289
1290 // Enchant on Off-Hand and ready?
1291 if (castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND && procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK)
1292 {
1293 float BaseWeaponSpeed = GetAttackTime(WeaponAttackType::OFF_ATTACK) / 1000.0f;
1294
1295 // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed
1296 basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed));
1297 triggered_spell_id = 10444;
1298 }
1299
1300 // Enchant on Main-Hand and ready?
1301 else if (castItem->GetSlot() == EQUIPMENT_SLOT_MAINHAND && procFlag & PROC_FLAG_DONE_MAINHAND_ATTACK)
1302 {
1303 float BaseWeaponSpeed = GetAttackTime(WeaponAttackType::BASE_ATTACK) / 1000.0f;
1304
1305 // Value1: add the tooltip damage by swingspeed + Value2: add spelldmg by swingspeed
1306 basepoints0 = int32((fire_onhit * BaseWeaponSpeed) + (add_spellpower * BaseWeaponSpeed));
1307 triggered_spell_id = 10444;
1308 }
1309
1310 // If not ready, we should return, shouldn't we?!
1311 else
1312 return false;
1313
1314 CastCustomSpell(victim, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
1315 return true;
1316 }
1317 // Static Shock
1318 if (dummySpell->SpellIconID == 3059)
1319 {
1320 // Lightning Shield
1322 {
1323 uint32 spell = 26364;
1324
1325 // custom cooldown processing case
1326 if (GetTypeId() == TypeID::TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(spell))
1327 ToPlayer()->RemoveSpellCooldown(spell);
1328
1329 CastSpell(target, spell, true, castItem, triggeredByAura);
1330 return true;
1331 }
1332 return false;
1333 }
1334 break;
1335 }
1337 {
1338 // Blood-Caked Blade
1339 if (dummySpell->SpellIconID == 138)
1340 {
1341 if (!target || !target->IsAlive())
1342 return false;
1343
1344 triggered_spell_id = dummySpell->Effects[effIndex].TriggerSpell;
1345 break;
1346 }
1347 // Dancing Rune Weapon
1348 if (dummySpell->Id == 49028)
1349 {
1350 // 1 dummy aura for dismiss rune blade
1351 if (effIndex != 1)
1352 return false;
1353
1354 Unit* pPet = NULL;
1355 for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) // Find Rune Weapon
1356 if ((*itr)->GetEntry() == 27893)
1357 {
1358 pPet = *itr;
1359 break;
1360 }
1361
1362 if (pPet && pPet->GetVictim() && damage && procSpell)
1363 {
1364 uint32 procDmg = damage / 2;
1365 pPet->SendSpellNonMeleeDamageLog(pPet->GetVictim(), procSpell->Id, procDmg, procSpell->GetSchoolMask(), 0, 0, false, 0, false);
1366 pPet->DealDamage(pPet->GetVictim(), procDmg, NULL, SPELL_DIRECT_DAMAGE, procSpell->GetSchoolMask(), procSpell, true);
1367 break;
1368 }
1369 else
1370 return false;
1371 }
1372 // Unholy Blight
1373 if (dummySpell->Id == 49194)
1374 {
1375 triggered_spell_id = 50536;
1376 SpellInfo const* unholyBlight = sSpellMgr->GetSpellInfo(triggered_spell_id);
1377 if (!unholyBlight)
1378 return false;
1379
1380 basepoints0 = CalculatePct(int32(damage), triggerAmount);
1381
1382 //Glyph of Unholy Blight
1383 if (AuraEffect* glyph = GetAuraEffect(63332, 0))
1384 AddPct(basepoints0, glyph->GetAmount());
1385
1386 basepoints0 = basepoints0 / (unholyBlight->GetMaxDuration() / unholyBlight->Effects[0].ApplyAuraTickCount);
1387 basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), triggered_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
1388 break;
1389 }
1390 // Threat of Thassarian
1391 if (dummySpell->SpellIconID == 2023)
1392 {
1393 // Must Dual Wield
1394 if (!procSpell || !haveOffhandWeapon())
1395 return false;
1396 // Chance as basepoints for dummy aura
1397 if (!roll_chance_i(triggerAmount))
1398 return false;
1399
1400 switch (procSpell->Id)
1401 {
1402 case 49020: triggered_spell_id = 66198; break; // Obliterate
1403 case 49143: triggered_spell_id = 66196; break; // Frost Strike
1404 case 45462: triggered_spell_id = 66216; break; // Plague Strike
1405 case 49998: triggered_spell_id = 66188; break; // Death Strike
1406 case 56815: triggered_spell_id = 66217; break; // Rune Strike
1407 case 45902: triggered_spell_id = 66215; break; // Blood Strike
1408 default:
1409 return false;
1410 }
1411 break;
1412 }
1413 // Runic Power Back on Snare/Root
1414 if (dummySpell->Id == 61257)
1415 {
1416 // only for spells and hit/crit (trigger start always) and not start from self casted spells
1417 if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT)) || this == victim)
1418 return false;
1419 // Need snare or root mechanic
1420 if (!(procSpell->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_SNARE))))
1421 return false;
1422 triggered_spell_id = 61258;
1423 target = this;
1424 break;
1425 }
1426 break;
1427 }
1428 default:
1429 break;
1430 }
1431
1432 // if not handled by custom case, get triggered spell from dummySpell proto
1433 if (!triggered_spell_id)
1434 triggered_spell_id = dummySpell->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
1435
1436 // processed charge only counting case
1437 if (!triggered_spell_id)
1438 return true;
1439
1440 SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id);
1441 if (!triggerEntry)
1442 {
1443 SF_LOG_ERROR("entities.unit", "Unit::HandleDummyAuraProc: Spell %u has non-existing triggered spell %u", dummySpell->Id, triggered_spell_id);
1444 return false;
1445 }
1446
1447 if (cooldown_spell_id == 0)
1448 cooldown_spell_id = triggered_spell_id;
1449
1450 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(cooldown_spell_id))
1451 return false;
1452
1453 if (basepoints0)
1454 CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura, originalCaster);
1455 else
1456 CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura, originalCaster);
1457
1458 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER)
1459 ToPlayer()->AddSpellCooldown(cooldown_spell_id, 0, time(NULL) + cooldown);
1460
1461 return true;
1462}
1463
1464/*
1465*/
1466
1467
1468// Used in case when access to whole aura is needed
1469// All procs should be handled like this...
1470
1471bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown, bool* handled)
1472{
1473 SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo();
1474
1475 switch (dummySpell->SpellFamilyName)
1476 {
1478 {
1479 switch (dummySpell->Id)
1480 {
1481 // Nevermelting Ice Crystal
1482 case 71564:
1483 {
1484 RemoveAuraFromStack(71564);
1485 *handled = true;
1486 break;
1487 }
1488 // Gaseous Bloat
1489 case 70672:
1490 {
1491 *handled = true;
1492 uint32 stack = triggeredByAura->GetStackAmount();
1493 int32 const mod = (GetMap()->GetSpawnMode() & 1) ? 1500 : 1250;
1494 int32 dmg = 0;
1495 for (uint8 i = 1; i < stack; ++i)
1496 dmg += mod * stack;
1497 if (Unit* caster = triggeredByAura->GetCaster())
1498 caster->CastCustomSpell(70701, SPELLVALUE_BASE_POINT0, dmg);
1499 break;
1500 }
1501 // Ball of Flames Proc
1502 case 71756:
1503 {
1504 RemoveAuraFromStack(dummySpell->Id);
1505 *handled = true;
1506 break;
1507 }
1508 // Discerning Eye of the Beast
1509 case 59915:
1510 {
1511 CastSpell(this, 59914, true); // 59914 already has correct basepoints in DBC, no need for custom bp
1512 *handled = true;
1513 break;
1514 }
1515 // Swift Hand of Justice
1516 case 59906:
1517 {
1518 int32 bp0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_0].CalcValue());
1519 CastCustomSpell(this, 59913, &bp0, NULL, NULL, true);
1520 *handled = true;
1521 break;
1522 }
1523 }
1524 break;
1525 }
1527 {
1528 // Judgements of the Just
1529 if (dummySpell->SpellIconID == 3015)
1530 {
1531 *handled = true;
1532 CastSpell(victim, 68055, true);
1533 return true;
1534 }
1535 // Glyph of Divinity
1536 else if (dummySpell->Id == 54939)
1537 {
1538 if (!procSpell)
1539 return false;
1540 *handled = true;
1541 // Check if we are the target and prevent mana gain
1542 if (victim && triggeredByAura->GetCasterGUID() == victim->GetGUID())
1543 return false;
1544 // Lookup base amount mana restore
1545 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
1546 {
1547 if (procSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE)
1548 {
1549 // value multiplied by 2 because you should get twice amount
1550 int32 mana = procSpell->Effects[i].CalcValue() * 2;
1551 CastCustomSpell(this, 54986, 0, &mana, NULL, true);
1552 }
1553 }
1554 return true;
1555 }
1556 break;
1557 }
1559 {
1560 // Blood of the North
1561 // Reaping
1562 // Death Rune Mastery
1564 if (dummySpell->SpellIconID == 3041 || (dummySpell->SpellIconID == 22 && dummySpell->Id != 62459) || dummySpell->SpellIconID == 2622)
1565 {
1566 *handled = true;
1567 // Convert recently used Blood Rune to Death Rune
1568 if (Player* player = ToPlayer())
1569 {
1570 if (player->getClass() != CLASS_DEATH_KNIGHT)
1571 return false;
1572
1573 RuneType rune = ToPlayer()->GetLastUsedRune();
1574 // can't proc from death rune use
1575 if (rune == RuneType::RUNE_DEATH)
1576 return false;
1577 AuraEffect* aurEff = triggeredByAura->GetEffect(EFFECT_0);
1578 if (!aurEff)
1579 return false;
1580
1581 // Reset amplitude - set death rune remove timer to 30s
1582 aurEff->ResetPeriodic(true);
1583 uint32 runesLeft;
1584
1585 if (dummySpell->SpellIconID == 2622)
1586 runesLeft = 2;
1587 else
1588 runesLeft = 1;
1589
1590 for (uint8 i = 0; i < MAX_RUNES && runesLeft; ++i)
1591 {
1592 if (dummySpell->SpellIconID == 2622)
1593 {
1594 if (player->GetCurrentRune(i) == RuneType::RUNE_DEATH ||
1595 player->GetBaseRune(i) == RuneType::RUNE_BLOOD)
1596 continue;
1597 }
1598 else
1599 {
1600 if (player->GetCurrentRune(i) == RuneType::RUNE_DEATH ||
1601 player->GetBaseRune(i) != RuneType::RUNE_BLOOD)
1602 continue;
1603 }
1604 if (player->GetRuneCooldown(i) != player->GetRuneBaseCooldown(i))
1605 continue;
1606
1607 --runesLeft;
1608 // Mark aura as used
1609 player->AddRuneByAuraEffect(i, RuneType::RUNE_DEATH, aurEff);
1610 }
1611 return true;
1612 }
1613 return false;
1614 }
1615
1616 switch (dummySpell->Id)
1617 {
1618 // Bone Shield cooldown
1619 case 49222:
1620 {
1621 *handled = true;
1622 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER)
1623 {
1624 if (ToPlayer()->HasSpellCooldown(100000))
1625 return false;
1626 ToPlayer()->AddSpellCooldown(100000, 0, time(NULL) + cooldown);
1627 }
1628 return true;
1629 }
1630 }
1631 break;
1632 }
1634 {
1635 switch (dummySpell->Id)
1636 {
1637 // Item - Warrior T10 Protection 4P Bonus
1638 case 70844:
1639 {
1640 int32 basepoints0 = CalculatePct(GetMaxHealth(), dummySpell->Effects[EFFECT_1].CalcValue());
1641 CastCustomSpell(this, 70845, &basepoints0, NULL, NULL, true);
1642 break;
1643 }
1644 // Recklessness
1645 case 1719:
1646 {
1651 *handled = true;
1652 break;
1653 }
1654 default:
1655 break;
1656 }
1657 break;
1658 }
1659 }
1660 return false;
1661}
1662
1663bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown)
1664{
1665 // Get triggered aura spell info
1666 SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo();
1667
1668 // Basepoints of trigger aura
1669 int32 triggerAmount = triggeredByAura->GetAmount();
1670
1671 // Set trigger spell id, target, custom basepoints
1672 uint32 trigger_spell_id = auraSpellInfo->Effects[triggeredByAura->GetEffIndex()].TriggerSpell;
1673
1674 Unit* target = NULL;
1675 int32 basepoints0 = 0;
1676
1677 if (triggeredByAura->GetAuraType() == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE)
1678 basepoints0 = triggerAmount;
1679
1680 Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TypeID::TYPEID_PLAYER
1681 ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
1682
1683 // Try handle unknown trigger spells
1684 if (sSpellMgr->GetSpellInfo(trigger_spell_id) == NULL)
1685 {
1686 switch (auraSpellInfo->SpellFamilyName)
1687 {
1689 switch (auraSpellInfo->Id)
1690 {
1691 case 43820: // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket)
1692 // Pct value stored in dummy
1693 basepoints0 = victim->GetCreateHealth() * auraSpellInfo->Effects[1].CalcValue() / 100;
1694 target = victim;
1695 break;
1696 case 57345: // Darkmoon Card: Greatness
1697 {
1698 float stat = 0.0f;
1699 // strength
1700 if (GetStat(STAT_STRENGTH) > stat)
1701 {
1702 trigger_spell_id = 60229; stat = GetStat(STAT_STRENGTH);
1703 }
1704 // agility
1705 if (GetStat(STAT_AGILITY) > stat)
1706 {
1707 trigger_spell_id = 60233; stat = GetStat(STAT_AGILITY);
1708 }
1709 // intellect
1710 if (GetStat(STAT_INTELLECT) > stat)
1711 {
1712 trigger_spell_id = 60234; stat = GetStat(STAT_INTELLECT);
1713 }
1714 // spirit
1715 if (GetStat(STAT_SPIRIT) > stat)
1716 {
1717 trigger_spell_id = 60235;
1718 }
1719 break;
1720 }
1721 case 64568: // Blood Reserve
1722 {
1723 if (HealthBelowPctDamaged(35, damage))
1724 {
1725 CastCustomSpell(this, 64569, &triggerAmount, NULL, NULL, true);
1726 RemoveAura(64568);
1727 }
1728 return false;
1729 }
1730 case 67702: // Death's Choice, Item - Coliseum 25 Normal Melee Trinket
1731 {
1732 float stat = 0.0f;
1733 // strength
1734 if (GetStat(STAT_STRENGTH) > stat)
1735 {
1736 trigger_spell_id = 67708; stat = GetStat(STAT_STRENGTH);
1737 }
1738 // agility
1739 if (GetStat(STAT_AGILITY) > stat)
1740 {
1741 trigger_spell_id = 67703;
1742 }
1743 break;
1744 }
1745 case 67771: // Death's Choice (heroic), Item - Coliseum 25 Heroic Melee Trinket
1746 {
1747 float stat = 0.0f;
1748 // strength
1749 if (GetStat(STAT_STRENGTH) > stat)
1750 {
1751 trigger_spell_id = 67773; stat = GetStat(STAT_STRENGTH);
1752 }
1753 // agility
1754 if (GetStat(STAT_AGILITY) > stat)
1755 {
1756 trigger_spell_id = 67772;
1757 }
1758 break;
1759 }
1760 // Mana Drain Trigger
1761 case 27522:
1762 case 40336:
1763 {
1764 // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target.
1765 if (IsAlive())
1766 CastSpell(this, 29471, true, castItem, triggeredByAura);
1767 if (victim && victim->IsAlive())
1768 CastSpell(victim, 27526, true, castItem, triggeredByAura);
1769 return true;
1770 }
1771 // Evasive Maneuvers
1772 case 50240:
1773 {
1774 // Remove a Evasive Charge
1775 Aura* charge = GetAura(50241);
1776 if (charge && charge->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL))
1777 RemoveAurasDueToSpell(50240);
1778 break;
1779 }
1780 }
1781 break;
1782 case SPELLFAMILY_DRUID:
1783 {
1784 switch (auraSpellInfo->Id)
1785 {
1786 // Druid Forms Trinket
1787 case 37336:
1788 {
1789 switch (GetShapeshiftForm())
1790 {
1791 case FORM_NONE: trigger_spell_id = 37344; break;
1792 case FORM_CAT: trigger_spell_id = 37341; break;
1793 case FORM_BEAR: trigger_spell_id = 37340; break;
1794 case FORM_TREE: trigger_spell_id = 37342; break;
1795 case FORM_MOONKIN: trigger_spell_id = 37343; break;
1796 default:
1797 return false;
1798 }
1799 break;
1800 }
1801 default:
1802 break;
1803 }
1804 break;
1805 }
1806 case SPELLFAMILY_HUNTER:
1807 {
1808 if (auraSpellInfo->SpellIconID == 3247) // Piercing Shots
1809 {
1810 switch (auraSpellInfo->Id)
1811 {
1812 case 53234: // Rank 1
1813 case 53238: // Rank 3
1814 trigger_spell_id = 63468;
1815 break;
1816 default:
1817 SF_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Piercing Shots", auraSpellInfo->Id);
1818 return false;
1819 }
1820 SpellInfo const* TriggerPS = sSpellMgr->GetSpellInfo(trigger_spell_id);
1821 if (!TriggerPS)
1822 return false;
1823
1824 basepoints0 = CalculatePct(int32(damage), triggerAmount) / (TriggerPS->GetMaxDuration() / TriggerPS->Effects[0].ApplyAuraTickCount);
1825 basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_DAMAGE);
1826 break;
1827 }
1828 // Item - Hunter T9 4P Bonus
1829 if (auraSpellInfo->Id == 67151)
1830 {
1831 trigger_spell_id = 68130;
1832 target = this;
1833 break;
1834 }
1835 break;
1836 }
1838 {
1839 switch (auraSpellInfo->Id)
1840 {
1841 // Soul Preserver
1842 case 60510:
1843 {
1844 switch (getClass())
1845 {
1846 case CLASS_DRUID:
1847 trigger_spell_id = 60512;
1848 break;
1849 case CLASS_PALADIN:
1850 trigger_spell_id = 60513;
1851 break;
1852 case CLASS_PRIEST:
1853 trigger_spell_id = 60514;
1854 break;
1855 case CLASS_SHAMAN:
1856 trigger_spell_id = 60515;
1857 break;
1858 }
1859
1860 target = this;
1861 break;
1862 }
1863 case 37657: // Lightning Capacitor
1864 case 54841: // Thunder Capacitor
1865 case 67712: // Item - Coliseum 25 Normal Caster Trinket
1866 case 67758: // Item - Coliseum 25 Heroic Caster Trinket
1867 {
1868 if (!victim || !victim->IsAlive() || GetTypeId() != TypeID::TYPEID_PLAYER)
1869 return false;
1870
1871 uint32 stack_spell_id = 0;
1872 switch (auraSpellInfo->Id)
1873 {
1874 case 37657:
1875 stack_spell_id = 37658;
1876 trigger_spell_id = 37661;
1877 break;
1878 case 54841:
1879 stack_spell_id = 54842;
1880 trigger_spell_id = 54843;
1881 break;
1882 case 67712:
1883 stack_spell_id = 67713;
1884 trigger_spell_id = 67714;
1885 break;
1886 case 67758:
1887 stack_spell_id = 67759;
1888 trigger_spell_id = 67760;
1889 break;
1890 }
1891
1892 CastSpell(this, stack_spell_id, true, NULL, triggeredByAura);
1893
1894 Aura* dummy = GetAura(stack_spell_id);
1895 if (!dummy || dummy->GetStackAmount() < triggerAmount)
1896 return false;
1897
1898 RemoveAurasDueToSpell(stack_spell_id);
1899 target = victim;
1900 break;
1901 }
1902 default:
1903 break;
1904 }
1905 break;
1906 }
1908 {
1909 // Item - Death Knight T10 Melee 4P Bonus
1910 if (auraSpellInfo->Id == 70656)
1911 {
1913 return false;
1914
1915 for (uint8 i = 0; i < MAX_RUNES; ++i)
1916 if (ToPlayer()->GetRuneCooldown(i) == 0)
1917 return false;
1918 }
1919 break;
1920 }
1921 case SPELLFAMILY_ROGUE:
1922 {
1923 switch (auraSpellInfo->Id)
1924 {
1925 // Rogue T10 2P bonus, should only proc on caster
1926 case 70805:
1927 {
1928 if (victim != this)
1929 return false;
1930 break;
1931 }
1932 }
1933 break;
1934 }
1935 default:
1936 break;
1937 }
1938 }
1939
1940 // All ok. Check current trigger spell
1941 SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(trigger_spell_id);
1942 if (triggerEntry == NULL)
1943 {
1944 // Don't cast unknown spell
1945 // SF_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u has 0 in EffectTriggered[%d]. Unhandled custom case?", auraSpellInfo->Id, triggeredByAura->GetEffIndex());
1946 return false;
1947 }
1948
1949 // not allow proc extra attack spell at extra attack
1951 return false;
1952
1953 // Custom requirements (not listed in procEx) Warning! damage dealing after this
1954 // Custom triggered spells
1955 switch (auraSpellInfo->Id)
1956 {
1957 // Concussive Barrage
1958 case 35102:
1959 {
1960 if (!victim)
1961 return false;
1962
1963 // Proc only with Chimera Shot or Multi-Shot
1964 if (!(((procSpell->SpellIconID == 3412) && (procSpell->SpellFamilyFlags[2] & 0x00000001)) ||
1965 ((procSpell->SpellIconID == 85) && (procSpell->SpellFamilyFlags[0] & 0x00001000))))
1966 return false;
1967
1968 target = victim;
1969 trigger_spell_id = 35101;
1970 break;
1971 }
1972 // Persistent Shield (Scarab Brooch trinket)
1973 // This spell originally trigger 13567 - Dummy Trigger (vs dummy efect)
1974 case 26467:
1975 {
1976 basepoints0 = int32(CalculatePct(damage, 15));
1977 target = victim;
1978 trigger_spell_id = 26470;
1979 break;
1980 }
1981 // Unyielding Knights (item exploit 29108\29109)
1982 case 38164:
1983 {
1984 if (!victim || victim->GetEntry() != 19457) // Proc only if your target is Grillok
1985 return false;
1986 break;
1987 }
1988 // Deflection
1989 case 52420:
1990 {
1991 if (!HealthBelowPctDamaged(35, damage))
1992 return false;
1993 break;
1994 }
1995
1996 // Cheat Death
1997 case 28845:
1998 {
1999 // When your health drops below 20%
2000 if (HealthBelowPctDamaged(20, damage) || HealthBelowPct(20))
2001 return false;
2002 break;
2003 }
2004 // Greater Heal Refund (Avatar Raiment set)
2005 case 37594:
2006 {
2007 if (!victim || !victim->IsAlive())
2008 return false;
2009
2010 // Doesn't proc if target already has full health
2011 if (victim->IsFullHealth())
2012 return false;
2013 // If your Greater Heal brings the target to full health, you gain $37595s1 mana.
2014 if (victim->GetHealth() + damage < victim->GetMaxHealth())
2015 return false;
2016 break;
2017 }
2018 // Bonus Healing (Crystal Spire of Karabor mace)
2019 case 40971:
2020 {
2021 // If your target is below $s1% health
2022 if (!victim || !victim->IsAlive() || victim->HealthAbovePct(triggerAmount))
2023 return false;
2024 break;
2025 }
2026
2027 // Deathbringer Saurfang - Blood Beast's Blood Link
2028 case 72176:
2029 basepoints0 = 3;
2030 break;
2031 // Professor Putricide - Ooze Spell Tank Protection
2032 case 71770:
2033 if (victim)
2034 victim->CastSpell(victim, trigger_spell_id, true); // EffectImplicitTarget is self
2035 return true;
2036 case 45057: // Evasive Maneuvers (Commendation of Kael`thas trinket)
2037 case 71634: // Item - Icecrown 25 Normal Tank Trinket 1
2038 case 71640: // Item - Icecrown 25 Heroic Tank Trinket 1
2039 case 75475: // Item - Chamber of Aspects 25 Normal Tank Trinket
2040 case 75481: // Item - Chamber of Aspects 25 Heroic Tank Trinket
2041 {
2042 // Procs only if damage takes health below $s1%
2043 if (!HealthBelowPctDamaged(triggerAmount, damage))
2044 return false;
2045 break;
2046 }
2047 default:
2048 break;
2049 }
2050
2051 // Custom basepoints/target for exist spell
2052 // dummy basepoints or other customs
2053 switch (trigger_spell_id)
2054 {
2055 // Auras which should proc on area aura source (caster in this case):
2056 // Cast positive spell on enemy target
2057 case 7099: // Curse of Mending
2058 case 39703: // Curse of Mending
2059 case 29494: // Temptation
2060 {
2061 target = victim;
2062 break;
2063 }
2064 // Finish movies that add combo
2065 case 14189: // Seal Fate (Netherblade set)
2066 {
2067 if (!victim || victim == this)
2068 return false;
2069 // Need add combopoint AFTER finish movie (or they dropped in finish phase)
2070 break;
2071 }
2072 // Item - Druid T10 Balance 2P Bonus
2073 case 16870:
2074 {
2075 if (HasAura(70718))
2076 CastSpell(this, 70721, true);
2077 break;
2078 }
2079 // Enlightenment (trigger only from mana cost spells)
2080 case 35095:
2081 {
2082 if (!procSpell /*|| procSpell->PowerType != POWER_MANA || (procSpell->ManaCost == 0 && procSpell->ManaCostPercentage == 0 && procSpell->ManaCostPerlevel == 0)*/)
2083 return false;
2084 break;
2085 }
2086 case 46916: // Slam! (Bloodsurge proc)
2087 case 52437: // Sudden Death
2088 {
2089 // Item - Warrior T10 Melee 4P Bonus
2090 if (AuraEffect const* aurEff = GetAuraEffect(70847, 0))
2091 {
2092 if (!roll_chance_i(aurEff->GetAmount()))
2093 break;
2094 CastSpell(this, 70849, true, castItem, triggeredByAura); // Extra Charge!
2095 CastSpell(this, 71072, true, castItem, triggeredByAura); // Slam GCD Reduced
2096 CastSpell(this, 71069, true, castItem, triggeredByAura); // Execute GCD Reduced
2097 }
2098 break;
2099 }
2100 // Maelstrom Weapon
2101 case 53817:
2102 {
2103 // has rank dependant proc chance, ignore too often cases
2104 // PPM = 2.5 * (rank of talent),
2105 uint32 rank = auraSpellInfo->GetRank();
2106 // 5 rank -> 100% 4 rank -> 80% and etc from full rate
2107 if (!roll_chance_i(20 * rank))
2108 return false;
2109 // Item - Shaman T10 Enhancement 4P Bonus
2110 if (AuraEffect const* aurEff = GetAuraEffect(70832, 0))
2111 if (Aura const* maelstrom = GetAura(53817))
2112 if ((maelstrom->GetStackAmount() == maelstrom->GetSpellInfo()->StackAmount - 1) && roll_chance_i(aurEff->GetAmount()))
2113 CastSpell(this, 70831, true, castItem, triggeredByAura);
2114 break;
2115 }
2116 // Glyph of Death's Embrace
2117 case 58679:
2118 {
2119 // Proc only from healing part of Death Coil. Check is essential as all Death Coil spells have 0x2000 mask in SpellFamilyFlags
2120 if (!procSpell || !(procSpell->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && procSpell->SpellFamilyFlags[0] == 0x80002000))
2121 return false;
2122 break;
2123 }
2124 // Savage Defense
2125 case 62606:
2126 {
2128 break;
2129 }
2130 // Body and Soul
2131 case 65081:
2132 {
2133 // Proc only from PW:S cast
2134 if (!(procSpell->SpellFamilyFlags[0] & 0x00000001))
2135 return false;
2136 break;
2137 }
2138 // Culling the Herd
2139 case 70893:
2140 {
2141 // check if we're doing a critical hit
2142 if (!(procSpell->SpellFamilyFlags[1] & 0x10000000) && (procEx != PROC_EX_CRITICAL_HIT))
2143 return false;
2144 // check if we're procced by Claw, Bite or Smack (need to use the spell icon ID to detect it)
2145 if (!(procSpell->SpellIconID == 262 || procSpell->SpellIconID == 1680 || procSpell->SpellIconID == 473))
2146 return false;
2147 break;
2148 }
2149 case 91021:
2150 {
2151 if (!(procSpell->SpellFamilyName == SPELLFAMILY_ROGUE))
2152 return false;
2153 if (!(procSpell->SpellIconID == 856 || procSpell->SpellIconID == 498 || procSpell->SpellIconID == 244))
2154 return false;
2155 break;
2156 }
2157 case 55021:
2158 {
2159 if (!(procSpell->SpellFamilyName == SPELLFAMILY_MAGE))
2160 return false;
2161 if (!(procSpell->SpellIconID == 17))
2162 return false;
2163 break;
2164 }
2165 case 12880: // Enrage
2166 {
2167 if (!(procSpell->SpellFamilyName == SPELLFAMILY_WARRIOR))
2168 return false;
2169
2170 // check if we're doing a critical hit
2171 if (procEx != PROC_EX_CRITICAL_HIT)
2172 return false;
2173
2174 if (!(procSpell->SpellFamilyFlags[0] & 0x20000000 ||
2175 procSpell->SpellFamilyFlags[1] & 0x00000400 ||
2176 procSpell->SpellFamilyFlags[1] & 0x40000000 ||
2177 procSpell->SpellFamilyFlags[1] & 0x00000040 ||
2178 procSpell->SpellFamilyFlags[1] & 0x00000200))
2179 return false;
2180
2181 if (!(procSpell->SpellIconID == 564 ||
2182 procSpell->SpellIconID == 38 ||
2183 procSpell->SpellIconID == 5288 ||
2184 procSpell->SpellIconID == 1508 ||
2185 procSpell->SpellIconID == 413))
2186 return false;
2187
2188 CastSpell(this, 131116, true);
2189 break;
2190 }
2191 }
2192
2193 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(trigger_spell_id))
2194 return false;
2195
2196 // try detect target manually if not set
2197 if (target == NULL)
2198 target = !(procFlags & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry && triggerEntry->IsPositive() ? this : victim;
2199
2200 if (basepoints0)
2201 CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
2202 else
2203 CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
2204
2205 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER)
2206 ToPlayer()->AddSpellCooldown(trigger_spell_id, 0, time(NULL) + cooldown);
2207
2208 return true;
2209}
2210
2211bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* /*procSpell*/, uint32 cooldown)
2212{
2213 int32 scriptId = triggeredByAura->GetMiscValue();
2214
2215 if (!victim || !victim->IsAlive())
2216 return false;
2217
2218 Item* castItem = triggeredByAura->GetBase()->GetCastItemGUID() && GetTypeId() == TypeID::TYPEID_PLAYER
2219 ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL;
2220
2221 uint32 triggered_spell_id = 0;
2222
2223 switch (scriptId)
2224 {
2225 case 4533: // Dreamwalker Raiment 2 pieces bonus
2226 {
2227 // Chance 50%
2228 if (!roll_chance_i(50))
2229 return false;
2230
2231 switch (victim->getPowerType())
2232 {
2233 case POWER_MANA: triggered_spell_id = 28722; break;
2234 case POWER_RAGE: triggered_spell_id = 28723; break;
2235 case POWER_ENERGY: triggered_spell_id = 28724; break;
2236 default:
2237 return false;
2238 }
2239 break;
2240 }
2241 case 4537: // Dreamwalker Raiment 6 pieces bonus
2242 triggered_spell_id = 28750; // Blessing of the Claw
2243 break;
2244 default:
2245 break;
2246 }
2247
2248 // not processed
2249 if (!triggered_spell_id)
2250 return false;
2251
2252 // standard non-dummy case
2253 SpellInfo const* triggerEntry = sSpellMgr->GetSpellInfo(triggered_spell_id);
2254
2255 if (!triggerEntry)
2256 {
2257 SF_LOG_ERROR("entities.unit", "Unit::HandleOverrideClassScriptAuraProc: Spell %u triggering for class script id %u", triggered_spell_id, scriptId);
2258 return false;
2259 }
2260
2261 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(triggered_spell_id))
2262 return false;
2263
2264 CastSpell(victim, triggered_spell_id, true, castItem, triggeredByAura);
2265
2266 if (cooldown && GetTypeId() == TypeID::TYPEID_PLAYER)
2267 ToPlayer()->AddSpellCooldown(triggered_spell_id, 0, time(NULL) + cooldown);
2268
2269 return true;
2270}
const T & RAND(const T &v1, const T &v2)
DBCStorage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore(SpellItemEnchantmentfmt)
#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
EnchantmentSlot
Definition Item.h:149
@ TEMP_ENCHANTMENT_SLOT
Definition Item.h:151
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
RuneType
Definition Player.h:485
@ RUNE_DEATH
Definition Player.h:489
@ RUNE_BLOOD
Definition Player.h:486
#define MAX_RUNES
Definition Player.h:476
@ EQUIPMENT_SLOT_MAINHAND
Definition Player.h:704
@ EQUIPMENT_SLOT_OFFHAND
Definition Player.h:705
@ EFFECT_1
@ EFFECT_0
Powers
@ POWER_RAGE
@ POWER_RUNIC_POWER
@ POWER_ENERGY
@ POWER_MANA
@ SPELL_EFFECT_ADD_EXTRA_ATTACKS
@ SPELL_EFFECT_ENERGIZE
@ CLASS_HUNTER
@ CLASS_DRUID
@ CLASS_SHAMAN
@ CLASS_PRIEST
@ CLASS_WARRIOR
@ CLASS_WARLOCK
@ CLASS_MAGE
@ CLASS_DEATH_KNIGHT
@ CLASS_PALADIN
@ CLASS_ROGUE
@ SPELLFAMILY_PRIEST
@ SPELLFAMILY_WARLOCK
@ SPELLFAMILY_MAGE
@ SPELLFAMILY_GENERIC
@ SPELLFAMILY_WARRIOR
@ SPELLFAMILY_PALADIN
@ SPELLFAMILY_HUNTER
@ SPELLFAMILY_ROGUE
@ SPELLFAMILY_SHAMAN
@ SPELLFAMILY_DRUID
@ SPELLFAMILY_DEATHKNIGHT
@ REP_EXALTED
@ STAT_SPIRIT
@ STAT_INTELLECT
@ STAT_AGILITY
@ STAT_STRENGTH
@ MECHANIC_ROOT
@ MECHANIC_SNARE
@ SPELL_SCHOOL_MASK_SHADOW
@ SPELL_SCHOOL_MASK_FIRE
@ SPELL_SCHOOL_MASK_FROST
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_PROC_TRIGGER_SPELL
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
@ SPELL_SPECIFIC_JUDGEMENT
Definition SpellInfo.h:47
#define sSpellMgr
Definition SpellMgr.h:744
@ PROC_EX_CRITICAL_HIT
Definition SpellMgr.h:186
@ PROC_EX_NORMAL_HIT
Definition SpellMgr.h:185
@ PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS
Definition SpellMgr.h:119
@ PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS
Definition SpellMgr.h:113
@ PROC_FLAG_DONE_MAINHAND_ATTACK
Definition SpellMgr.h:131
@ PROC_FLAG_DONE_OFFHAND_ATTACK
Definition SpellMgr.h:132
WeaponAttackType
Definition Unit.h:572
@ SPELLMOD_CHANCE_OF_SUCCESS
Definition Unit.h:91
@ SPELLVALUE_BASE_POINT0
Definition Unit.h:114
@ AURA_REMOVE_BY_ENEMY_SPELL
Definition Unit.h:409
@ FORM_MOONKIN
Definition Unit.h:238
@ FORM_NONE
Definition Unit.h:207
@ FORM_CAT
Definition Unit.h:208
@ FORM_TREE
Definition Unit.h:209
@ FORM_BEAR
Definition Unit.h:212
@ SPELL_DIRECT_DAMAGE
Definition Unit.h:615
bool roll_chance_f(float chance)
Definition Util.h:83
bool roll_chance_i(int chance)
Definition Util.h:89
T AddPct(T &base, U pct)
Definition Util.h:109
T ApplyPct(T &base, U pct)
Definition Util.h:115
T CalculatePct(T base, U pct)
Definition Util.h:103
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 ResetPeriodic(bool resetPeriodicTimer=false)
int32 GetAmount() const
uint64 GetCasterGUID() const
Definition SpellAuras.h:91
int32 GetMaxDuration() const
Definition SpellAuras.h:115
uint64 GetCastItemGUID() const
Definition SpellAuras.h:90
bool ModStackAmount(int32 num, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
int32 GetDuration() const
Definition SpellAuras.h:119
AuraEffect * GetEffect(uint8 effIndex) const
Definition SpellAuras.h:168
Unit * GetCaster() const
void SetDuration(int32 duration, bool withMods=false)
uint8 GetStackAmount() const
Definition SpellAuras.h:133
uint8 GetCharges() const
Definition SpellAuras.h:126
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:87
void SetMaxDuration(int32 duration)
Definition SpellAuras.h:116
void DoCastSpellOnPlayers(uint32 spell)
Definition Item.h:202
uint8 GetSlot() const
Definition Item.h:265
uint32 GetEnchantmentId(EnchantmentSlot slot) const
Definition Item.h:287
bool IsEquipped() const
Definition Item.cpp:739
uint8 GetSpawnMode() const
Definition Map.h:358
ObjectGuid GetObjectGUID() const
Definition Object.h:123
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
TypeID GetTypeId() const
Definition Object.h:131
uint32 GetEntry() const
Definition Object.h:125
bool HasSpellCooldown(uint32 spell_id) const
Definition Player.cpp:17498
WorldSession * GetSession() const
Definition Player.h:2417
Item * GetItemByGuid(uint64 guid) const
void Say(std::string const &text, const Language language)
Handles said message in regular chat based on declared language and in config pre-defined Range.
Definition Player.cpp:15797
T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell *spell=NULL)
Definition Player.h:3623
Group * GetGroup()
Definition Player.h:2972
void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time)
Definition Player.cpp:17633
uint32 GetSpellCooldownDelay(uint32 spell_id) const
Definition Player.cpp:17504
ReputationRank GetReputationRank(uint32 faction_id) const
Definition Player.cpp:7098
Unit * GetSelectedUnit() const
Definition Player.cpp:18385
Item * GetWeaponForAttack(WeaponAttackType attackType, bool useable=false) const
void RemoveSpellCooldown(uint32 spell_id, bool update=false)
Definition Player.cpp:4284
RuneType GetLastUsedRune()
Definition Player.h:3075
static WeaponAttackType GetAttackBySlot(uint8 slot)
uint32 TriggerSpell
Definition SpellInfo.h:108
uint32 ApplyAuraTickCount
Definition SpellInfo.h:91
int32 CalcValue(Unit const *caster=NULL, int32 const *basePoints=NULL, Unit const *target=NULL) const
SpellEffectInfo Effects[MAX_SPELL_EFFECTS]
Definition SpellInfo.h:255
uint32 SpellVisual[2]
Definition SpellInfo.h:219
uint32 Id
Definition SpellInfo.h:160
uint8 GetRank() const
SpellSpecificType GetSpellSpecific() const
int32 GetMaxDuration() const
int32 EquippedItemClass
Definition SpellInfo.h:215
flag128 SpellFamilyFlags
Definition SpellInfo.h:227
SpellSchoolMask GetSchoolMask() const
uint32 GetAllEffectsMechanicMask() const
uint32 SpellIconID
Definition SpellInfo.h:220
bool HasEffect(SpellEffects effect) const
bool IsPositive() const
uint32 SpellFamilyName
Definition SpellInfo.h:226
int32 ModifyHealth(int32 val)
Definition Unit.cpp:4023
bool HealthAbovePct(int32 pct) const
Definition Unit.h:1621
int32 CalculateSpellDamage(Unit const *target, SpellInfo const *spellProto, uint8 effect_index, int32 const *basePoints=NULL) const
Definition Unit.cpp:4709
Unit * GetOwner() const
Definition Unit.cpp:2339
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
uint32 GetRemainingPeriodicAmount(uint64 caster, uint32 spellId, AuraType auraType, uint8 effectIndex=0) const
Definition Unit.cpp:9031
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 RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
bool HandleDummyAuraProc(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
Definition UnitProc.cpp:193
ShapeshiftForm GetShapeshiftForm() const
Definition Unit.h:2377
bool HandleAuraProc(Unit *victim, uint32 damage, Aura *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool *handled)
Aura * GetAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
Unit * GetVehicleBase() const
Definition Unit.cpp:7203
bool haveOffhandWeapon() const
Definition Unit.cpp:350
uint32 GetMaxHealth() const
Definition Unit.h:1604
void RemoveAuraFromStack(uint32 spellId, uint64 casterGUID=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
bool IsFullHealth() const
Definition Unit.h:1609
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)
bool IsAlive() const
Definition Unit.h:2032
void ProcDamageAndSpellFor(bool isVictim, Unit *target, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellInfo const *procSpell, uint32 damage, SpellInfo const *procAura=NULL)
ControlList m_Controlled
Definition Unit.h:2132
uint32 m_extraAttacks
Definition Unit.h:1453
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
uint32 DealDamage(Unit *victim, uint32 damage, CleanDamage const *cleanDamage=NULL, DamageEffectType damagetype=DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *spellProto=NULL, bool durabilityLoss=true)
bool HealthBelowPct(int32 pct) const
Definition Unit.h:1613
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask) const
Definition Unit.cpp:3099
uint32 GetHealth() const
Definition Unit.h:1600
uint32 GetCreateHealth() const
Definition Unit.h:2321
uint32 GetAttackTime(WeaponAttackType att) const
Definition Unit.cpp:4122
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, uint64 casterGUID=0) const
Unit * GetVictim() const
Definition Unit.h:1468
int32 GetPower(Powers power) const
Definition Unit.cpp:5237
void SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log)
Definition Unit.cpp:1766
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 IsFriendlyTo(Unit const *unit) const
Definition Unit.cpp:2283
uint32 CountPctFromMaxHealth(int32 pct) const
Definition Unit.h:1633
float GetStat(Stats stat) const
Definition Unit.h:1573
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition Unit.h:1617
Powers getPowerType() const
Definition Unit.h:1651
uint32 GetCreateMana() const
Definition Unit.h:2329
Guardian * GetGuardianPet() const
Definition Unit.cpp:2390
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) const
Definition Unit.cpp:3055
bool HandleAuraProcOnPowerAmount(Unit *victim, uint32 damage, AuraEffect *triggeredByAura, SpellInfo const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
Definition UnitProc.cpp:64
void ProcDamageAndSpell(Unit *victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType=WeaponAttackType::BASE_ATTACK, SpellInfo const *procSpell=NULL, SpellInfo const *procAura=NULL)
Definition UnitProc.cpp:53
float GetTotalAttackPowerValue(WeaponAttackType attType) const
Definition Unit.cpp:5118
Map * GetMap() const
Definition Object.h:740
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:1666
void SendModifyCooldown(ObjectGuid UnitGUID, int32 DeltaTime, int32 SpellID)
bool IsEqual(uint32 p1=0, uint32 p2=0, uint32 p3=0, uint32 p4=0) const
Definition Util.h:421
uint32 spellid[MAX_ITEM_ENCHANTMENT_EFFECTS]