OregonCore  revision 71a6c59-git
Your Favourite TBC server
Unit.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "Log.h"
20 #include "Opcodes.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "World.h"
24 #include "ObjectMgr.h"
25 #include "SpellMgr.h"
26 #include "Unit.h"
27 #include "QuestDef.h"
28 #include "Player.h"
29 #include "Creature.h"
30 #include "Spell.h"
31 #include "Group.h"
32 #include "SpellAuras.h"
33 #include "ObjectAccessor.h"
34 #include "CreatureAI.h"
35 #include "Formulas.h"
36 #include "Pet.h"
37 #include "Utilities/Util.h"
38 #include "Totem.h"
39 #include "Battleground.h"
40 #include "OutdoorPvP.h"
41 #include "InstanceSaveMgr.h"
42 #include "GridNotifiersImpl.h"
43 #include "CellImpl.h"
44 #include "CreatureGroups.h"
45 #include "PetAI.h"
46 #include "PassiveAI.h"
47 #include "TemporarySummon.h"
48 #include "PathFinder.h"
49 #include "ScriptMgr.h"
50 #include "Object.h"
51 #include "MovementGenerator.h"
52 #include "MoveSplineInit.h"
53 #include "MoveSpline.h"
54 
55 #include <math.h>
56 #include <array>
57 
59 {
60  2.5f, // MOVE_WALK
61  7.0f, // MOVE_RUN
62  4.5f, // MOVE_RUN_BACK
63  4.722222f, // MOVE_SWIM
64  2.5f, // MOVE_SWIM_BACK
65  3.141594f, // MOVE_TURN_RATE
66  7.0f, // MOVE_FLIGHT
67  4.5f, // MOVE_FLIGHT_BACK
68 };
69 
70 // Used for preapre can/can't trigger aura
71 void InitTriggerAuraData();
72 
73 // auraTypes contains attacker auras capable of proc'ing cast auras
74 static Unit::AuraTypeSet GenerateAttakerProcCastAuraTypes()
75 {
76  static Unit::AuraTypeSet auraTypes;
77  auraTypes.insert(SPELL_AURA_DUMMY);
78  auraTypes.insert(SPELL_AURA_PROC_TRIGGER_SPELL);
79  auraTypes.insert(SPELL_AURA_MOD_HASTE);
80  auraTypes.insert(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
81  return auraTypes;
82 }
83 
84 // auraTypes contains victim auras capable of proc'ing cast auras
85 static Unit::AuraTypeSet GenerateVictimProcCastAuraTypes()
86 {
87  static Unit::AuraTypeSet auraTypes;
88  auraTypes.insert(SPELL_AURA_DUMMY);
89  auraTypes.insert(SPELL_AURA_PRAYER_OF_MENDING);
90  auraTypes.insert(SPELL_AURA_PROC_TRIGGER_SPELL);
91  return auraTypes;
92 }
93 
94 // auraTypes contains auras capable of proc effect/damage (but not cast) for attacker
95 static Unit::AuraTypeSet GenerateAttakerProcEffectAuraTypes()
96 {
97  static Unit::AuraTypeSet auraTypes;
98  auraTypes.insert(SPELL_AURA_MOD_DAMAGE_DONE);
99  auraTypes.insert(SPELL_AURA_PROC_TRIGGER_DAMAGE);
100  auraTypes.insert(SPELL_AURA_MOD_CASTING_SPEED);
101  auraTypes.insert(SPELL_AURA_MOD_RATING);
102  return auraTypes;
103 }
104 
105 // auraTypes contains auras capable of proc effect/damage (but not cast) for victim
106 static Unit::AuraTypeSet GenerateVictimProcEffectAuraTypes()
107 {
108  static Unit::AuraTypeSet auraTypes;
109  auraTypes.insert(SPELL_AURA_MOD_RESISTANCE);
110  auraTypes.insert(SPELL_AURA_PROC_TRIGGER_DAMAGE);
111  auraTypes.insert(SPELL_AURA_MOD_PARRY_PERCENT);
112  auraTypes.insert(SPELL_AURA_MOD_BLOCK_PERCENT);
113  auraTypes.insert(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
114  return auraTypes;
115 }
116 
117 static Unit::AuraTypeSet attackerProcCastAuraTypes = GenerateAttakerProcCastAuraTypes();
118 static Unit::AuraTypeSet attackerProcEffectAuraTypes = GenerateAttakerProcEffectAuraTypes();
119 
120 static Unit::AuraTypeSet victimProcCastAuraTypes = GenerateVictimProcCastAuraTypes();
121 static Unit::AuraTypeSet victimProcEffectAuraTypes = GenerateVictimProcEffectAuraTypes();
122 
123 // auraTypes contains auras capable of proc'ing for attacker and victim
124 static Unit::AuraTypeSet GenerateProcAuraTypes()
125 {
127 
128  Unit::AuraTypeSet auraTypes;
129  auraTypes.insert(attackerProcCastAuraTypes.begin(), attackerProcCastAuraTypes.end());
130  auraTypes.insert(attackerProcEffectAuraTypes.begin(), attackerProcEffectAuraTypes.end());
131  auraTypes.insert(victimProcCastAuraTypes.begin(), victimProcCastAuraTypes.end());
132  auraTypes.insert(victimProcEffectAuraTypes.begin(), victimProcEffectAuraTypes.end());
133  return auraTypes;
134 }
135 
136 static Unit::AuraTypeSet procAuraTypes = GenerateProcAuraTypes();
137 
139 {
140  if (!IsPassiveSpell(spellId))
141  return false;
142 
143  SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId);
144  if (!spellProto)
145  return false;
146 
147  for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
148  {
149  if (std::find(procAuraTypes.begin(), procAuraTypes.end(), spellProto->EffectApplyAuraName[j]) != procAuraTypes.end())
150  return false;
151  }
152 
153  return true;
154 }
155 
156 typedef std::array<uint32, NUM_SPELL_PARTIAL_RESISTS> SpellPartialResistChanceEntry;
157 typedef std::vector<SpellPartialResistChanceEntry> SpellPartialResistDistribution;
158 static inline SpellPartialResistDistribution InitSpellPartialResistDistribution()
159 {
160  // Precalculated chances for 0-100% mitigation
161  // We use integer random instead of floats, so each chance is premultiplied by 100 (100.00 becomes 10000)
162  const SpellPartialResistDistribution precalculated = {
163  {{10000,0,0,0,0}},
164  {{9700,200,100,0,0}},
165  {{9400,400,200,0,0}},
166  {{9000,800,200,0,0}},
167  {{8700,1000,300,0,0}},
168  {{8400,1200,400,0,0}},
169  {{8200,1300,400,100,0}},
170  {{7900,1500,500,100,0}},
171  {{7600,1700,600,100,0}},
172  {{7300,1900,700,100,0}},
173  {{6900,2300,700,100,0}},
174  {{6600,2500,800,100,0}},
175  {{6300,2700,900,100,0}},
176  {{6000,2900,1000,100,0}},
177  {{5800,3000,1000,200,0}},
178  {{5400,3300,1100,200,0}},
179  {{5100,3600,1100,200,0}},
180  {{4800,3800,1200,200,0}},
181  {{4400,4200,1200,200,0}},
182  {{4100,4400,1300,200,0}},
183  {{3700,4800,1300,200,0}},
184  {{3400,5000,1400,200,0}},
185  {{3100,5200,1500,200,0}},
186  {{3000,5200,1500,200,100}},
187  {{2800,5300,1500,300,100}},
188  {{2500,5500,1600,300,100}},
189  {{2400,5400,1700,400,100}},
190  {{2300,5300,1800,500,100}},
191  {{2200,5100,2100,500,100}},
192  {{2100,5000,2200,600,100}},
193  {{2000,4900,2400,600,100}},
194  {{1900,4700,2600,700,100}},
195  {{1800,4600,2700,800,100}},
196  {{1700,4400,3000,800,100}},
197  {{1600,4300,3100,900,100}},
198  {{1500,4200,3200,1000,100}},
199  {{1400,4100,3300,1100,100}},
200  {{1300,3900,3600,1100,100}},
201  {{1300,3600,3800,1200,100}},
202  {{1200,3500,3900,1300,100}},
203  {{1100,3400,4000,1400,100}},
204  {{1000,3300,4100,1500,100}},
205  {{900,3100,4400,1500,100}},
206  {{800,3000,4500,1600,100}},
207  {{800,2700,4700,1700,100}},
208  {{700,2600,4800,1800,100}},
209  {{600,2500,4900,1900,100}},
210  {{600,2300,5000,1900,200}},
211  {{500,2200,5100,2000,200}},
212  {{300,2200,5300,2000,200}},
213  {{200,2100,5400,2100,200}},
214  {{200,2000,5300,2200,300}},
215  {{200,2000,5100,2200,500}},
216  {{200,1900,5000,2300,600}},
217  {{100,1900,4900,2500,600}},
218  {{100,1800,4800,2600,700}},
219  {{100,1700,4700,2700,800}},
220  {{100,1600,4500,3000,800}},
221  {{100,1500,4400,3100,900}},
222  {{100,1500,4100,3300,1000}},
223  {{100,1400,4000,3400,1100}},
224  {{100,1300,3900,3500,1200}},
225  {{100,1200,3800,3600,1300}},
226  {{100,1100,3600,3900,1300}},
227  {{100,1100,3300,4100,1400}},
228  {{100,1000,3200,4200,1500}},
229  {{100,900,3100,4300,1600}},
230  {{100,800,3000,4400,1700}},
231  {{100,800,2700,4600,1800}},
232  {{100,700,2600,4700,1900}},
233  {{100,600,2400,4900,2000}},
234  {{100,600,2200,5000,2100}},
235  {{100,500,2100,5100,2200}},
236  {{100,500,1800,5300,2300}},
237  {{100,400,1700,5400,2400}},
238  {{100,300,1600,5500,2500}},
239  {{100,300,1500,5300,2800}},
240  {{100,200,1500,5200,3000}},
241  {{0,200,1500,5200,3100}},
242  {{0,200,1400,5000,3400}},
243  {{0,200,1300,4800,3700}},
244  {{0,200,1300,4400,4100}},
245  {{0,200,1200,4200,4400}},
246  {{0,200,1200,3800,4800}},
247  {{0,200,1100,3600,5100}},
248  {{0,200,1100,3300,5400}},
249  {{0,200,1000,3000,5800}},
250  {{0,100,1000,2900,6000}},
251  {{0,100,900,2700,6300}},
252  {{0,100,800,2500,6600}},
253  {{0,100,700,2300,6900}},
254  {{0,100,700,1900,7300}},
255  {{0,100,600,1700,7600}},
256  {{0,100,500,1500,7900}},
257  {{0,100,400,1300,8200}},
258  {{0,0,400,1200,8400}},
259  {{0,0,300,1000,8700}},
260  {{0,0,200,800,9000}},
261  {{0,0,200,400,9400}},
262  {{0,0,100,200,9700}},
263  {{0,0,0,0,10000}},
264  };
265  // Inflate up to two decimal places of chance %: add intermediate values
267  for (size_t index = 0; index < precalculated.size(); ++index)
268  {
269  for (uint8 intermediate = 0; intermediate < 100; ++intermediate)
270  {
271  // Check if this is the last one first
272  if ((index + 1) == precalculated.size())
273  {
274  inflated.push_back(precalculated[index]);
275  break;
276  }
278  for (uint8 column = SPELL_PARTIAL_RESIST_NONE; column < NUM_SPELL_PARTIAL_RESISTS; ++column)
279  {
280  const uint32 base = precalculated.at(index).at(column);
281  const uint32 next = precalculated.at(index + 1).at(column);
282  values[column] = base + ((next - base) * intermediate / 100);
283  }
284  inflated.push_back(values);
285  }
286  }
287  return inflated;
288 }
289 
290 static const SpellPartialResistDistribution SPELL_PARTIAL_RESIST_DISTRIBUTION = InitSpellPartialResistDistribution();
291 
293 {
294  data >> moveFlags;
295  data >> moveFlags2;
296  data >> time;
297  data >> pos.m_positionX;
298  data >> pos.m_positionY;
299  data >> pos.m_positionZ;
300  pos.SetOrientation(data.read<float>());
301 
303  {
304  data >> t_guid;
305  data >> t_pos.m_positionX;
306  data >> t_pos.m_positionY;
307  data >> t_pos.m_positionZ;
308  t_pos.SetOrientation(data.read<float>());
309  data >> t_time;
310  }
312  data >> s_pitch;
313 
314  data >> fallTime;
315 
317  {
318  data >> j_velocity;
319  data >> j_sinAngle;
320  data >> j_cosAngle;
321  data >> j_xyspeed;
322  }
323 
325  data >> u_unk1;
326 }
327 
329 {
330  data << moveFlags;
331  data << moveFlags2;
332  data << time;
333  data << pos.GetPositionX();
334  data << pos.GetPositionY();
335  data << pos.GetPositionZ();
336  data << pos.GetOrientation();
337 
339  {
340  data << t_guid;
341  data << t_pos.GetPositionX();
342  data << t_pos.GetPositionY();
343  data << t_pos.GetPositionZ();
344  data << t_pos.GetOrientation();
345  data << t_time;
346  }
348  data << s_pitch;
349 
350  data << fallTime;
351 
353  {
354  data << j_velocity;
355  data << j_sinAngle;
356  data << j_cosAngle;
357  data << j_xyspeed;
358  }
359 
361  data << u_unk1;
362 }
363 
364 Unit::Unit(bool isWorldObject):
365  WorldObject(isWorldObject), IsAIEnabled(false),
366  NeedChangeAI(false),
367  LastCharmerGUID(0),
368  m_ControlledByPlayer(false),
369  i_AI(NULL),
370  i_disabledAI(NULL),
371  m_removedAurasCount(0),
372  i_motionMaster(this),
373  m_ThreatManager(this),
374  m_HostileRefManager(this),
375  m_lastSanctuaryTime(0),
376  m_procDeep(0),
377  movespline(new Movement::MoveSpline()),
378  m_movesplineTimer(POSITION_UPDATE_DELAY),
379  _lastDamagedTime(0)
380 {
383 
385 
392 
393  m_extraAttacks = 0;
394  m_canDualWield = false;
395 
396  m_state = 0;
397  m_form = FORM_NONE;
399 
400  for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i)
401  m_currentSpells[i] = NULL;
402 
403  for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i)
404  m_SummonSlot[i] = 0;
405 
406  m_ObjectSlot[0] = m_ObjectSlot[1] = m_ObjectSlot[2] = m_ObjectSlot[3] = 0;
407 
409  m_AuraFlags = 0;
410 
411  m_interruptMask = 0;
412  m_transform = 0;
414  m_canModifyStats = false;
415 
416  for (uint8 i = 0; i < MAX_SPELL_IMMUNITY; ++i)
417  m_spellImmune[i].clear();
418 
419  for (uint8 i = 0; i < UNIT_MOD_END; ++i)
420  {
421  m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
422  m_auraModifiersGroup[i][BASE_PCT] = 1.0f;
424  m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
425  }
426  // implement 50% base damage from offhand
428 
429  for (uint8 i = 0; i < MAX_ATTACK; ++i)
430  {
433  }
434 
435  for (uint8 i = 0; i < MAX_STATS; ++i)
436  m_createStats[i] = 0.0f;
437 
438  m_attacking = NULL;
439  m_modMeleeHitChance = 0.0f;
440  m_modRangedHitChance = 0.0f;
441  m_modSpellHitChance = 0.0f;
443 
444  m_initiatingCombat = false;
445 
447  m_lastManaUse = 0;
448 
449  for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
450  m_threatModifier[i] = 1.0f;
451 
452  m_isSorted = true;
453 
454  for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
455  m_speed_rate[i] = 1.0f;
456 
458 
459  m_charmInfo = NULL;
462 
463  // remove aurastates allowing special moves
464  for (uint8 i = 0; i < MAX_REACTIVE; ++i)
465  m_reactiveTimer[i] = 0;
466 
467  m_duringRemoveFromWorld = false;
468 
469  _oldFactionId = 0;
470 
472 }
473 
475 {
476  // set current spells as deletable
477  for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i)
478  if (m_currentSpells[i])
479  {
481  m_currentSpells[i] = NULL;
482  }
483 
486  _DeleteAuras();
487 
488  delete m_charmInfo;
489  delete movespline;
490 
493  ASSERT(m_attackers.empty());
494  ASSERT(m_sharedVision.empty());
495 }
496 
497 // Check if unit in combat with specific unit
498 bool Unit::IsInCombatWith(Unit const* who) const
499 {
500  // Check target exists
501  if (!who)
502  return false;
503 
504  // Search in threat list
505  uint64 guid = who->GetGUID();
507  for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
508  {
509  HostileReference* ref = (*i);
510 
511  // Return true if the unit matches
512  if (ref && ref->getUnitGuid() == guid)
513  return true;
514  }
515 
516  // Nothing found, false.
517  return false;
518 }
519 
520 void Unit::Update(uint32 p_time)
521 {
522  // WARNING! Order of execution here is important, do not change.
523  // Spells must be processed with event system BEFORE they go to _UpdateSpells.
524  // Or else we may have some SPELL_STATE_FINISHED spells stalled in pointers, that is bad.
525  m_Events.Update(p_time);
526 
527  if (!IsInWorld())
528  return;
529 
530  _UpdateSpells(p_time);
531 
532  if (uint32 base_att = getAttackTimer(BASE_ATTACK))
533  setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time));
534 
535  if (uint32 base_att = getAttackTimer(OFF_ATTACK))
536  setAttackTimer(OFF_ATTACK, (p_time >= base_att ? 0 : base_att - p_time));
537 
538  if (uint32 ranged_att = getAttackTimer(RANGED_ATTACK))
539  setAttackTimer(RANGED_ATTACK, (p_time >= ranged_att ? 0 : ranged_att - p_time));
540 
541  // update abilities available only for fraction of time
542  UpdateReactives(p_time);
543 
544  if (IsAlive())
545  {
548  }
549 
550  UpdateSplineMovement(p_time);
552 
553 }
554 
556 {
557  Unit *victim = GetVictim();
558  if (!victim || IsNonMeleeSpellCast(false))
559  return false;
560 
562  return false;
563 
564  uint8 swingError = 0;
565  if (!IsWithinMeleeRange(victim))
566  {
569  swingError = 1;
570  }
571  //120 degrees of radiant range
572  else if (!HasInArc(2 * M_PI / 3, victim))
573  {
576  swingError = 2;
577  }
578  else
579  {
581  {
582  // prevent base and off attack in same time, delay attack at 0.2 sec
583  if (haveOffhandWeapon())
584  {
587  }
590  }
592  {
593  // prevent base and off attack in same time, delay attack at 0.2 sec
594  uint32 base_att = getAttackTimer(BASE_ATTACK);
595  if (base_att < ATTACK_DISPLAY_DELAY)
597  // do attack
600  }
601  }
602 
603  Player* player = (GetTypeId() == TYPEID_PLAYER ? (Player*)this : NULL);
604  if (player && swingError != player->LastSwingErrorMsg())
605  {
606  if (swingError == 1)
607  player->SendAttackSwingNotInRange();
608  else if (swingError == 2)
610  player->SwingErrorMsg(swingError);
611  }
612 
613  return swingError == 0;
614 }
615 
617 {
618  if (GetTypeId() == TYPEID_PLAYER)
619  return ((Player*)this)->GetWeaponForAttack(OFF_ATTACK, true);
620  else
621  {
623  if (itemClass == ITEM_CLASS_WEAPON)
624  return true;
625 
626  return false;
627  }
628 
629  return CanDualWield();
630 }
631 
633 {
634  m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]);
635 }
636 
637 bool Unit::IsWithinCombatRange(const Unit* obj, float dist2compare) const
638 {
639  if (!obj || !IsInMap(obj) || !InSamePhase(obj))
640  return false;
641 
642  float dx = GetPositionX() - obj->GetPositionX();
643  float dy = GetPositionY() - obj->GetPositionY();
644  float dz = GetPositionZ() - obj->GetPositionZ();
645  float distsq = dx * dx + dy * dy + dz * dz;
646 
647  float sizefactor = GetCombatReach() + obj->GetCombatReach();
648  float maxdist = dist2compare + sizefactor;
649 
650  return distsq < maxdist * maxdist;
651 }
652 
653 bool Unit::IsWithinMeleeRange(Unit* obj, float dist) const
654 {
655  if (!obj || !IsInMap(obj) || !InSamePhase(obj))
656  return false;
657 
658  float dx = GetPositionX() - obj->GetPositionX();
659  float dy = GetPositionY() - obj->GetPositionY();
660  float dz = GetPositionZ() - obj->GetPositionZ();
661  float distsq = dx * dx + dy * dy + dz * dz;
662 
663  float sizefactor = GetMeleeReach() + obj->GetMeleeReach();
664  float maxdist = dist + sizefactor;
665 
666  return distsq < maxdist * maxdist;
667 }
668 
669 void Unit::GetRandomContactPoint(const Unit* obj, float& x, float& y, float& z, float distance2dMin, float distance2dMax) const
670 {
671  float combat_reach = GetCombatReach();
672  if (combat_reach < 0.1) // sometimes bugged for players
673  {
674  //sLog.outError("Unit %u (Type: %u) has invalid combat_reach %f",GetGUIDLow(),GetTypeId(),combat_reach);
675  //if (GetTypeId() == TYPEID_UNIT)
676  // sLog.outError("Creature entry %u has invalid combat_reach", ToCreature()->GetEntry());
677  combat_reach = DEFAULT_COMBAT_REACH;
678  }
679  uint32 attacker_number = getAttackers().size();
680  if (attacker_number > 0)
681  --attacker_number;
682  GetNearPoint(obj, x, y, z, obj->GetCombatReach(), distance2dMin + (distance2dMax - distance2dMin) * (float)rand_norm()
683  , GetAngle(obj) + (attacker_number ? (static_cast<float>(M_PI/2) - static_cast<float>(M_PI) * (float)rand_norm()) * float(attacker_number) / combat_reach * 0.3f : 0));
684 }
685 
687 {
688  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
689  {
690  if (sSpellMgr.GetSpellCustomAttr(iter->second->GetId()) & SPELL_ATTR_CU_MOVEMENT_IMPAIR)
691  RemoveAura(iter);
692  else
693  ++iter;
694  }
695 }
696 
698 {
699  if (auraType >= TOTAL_AURAS) return;
700  AuraList::iterator iter, next;
701  for (iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end(); iter = next)
702  {
703  next = iter;
704  ++next;
705 
706  if (*iter)
707  {
708  RemoveAurasDueToSpell((*iter)->GetId());
709  if (!m_modAuras[auraType].empty())
710  next = m_modAuras[auraType].begin();
711  else
712  return;
713  }
714  }
715 }
716 
717 void Unit::RemoveAuraTypeByCaster(AuraType auraType, uint64 casterGUID)
718 {
719  if (auraType >= TOTAL_AURAS) return;
720 
721  for (AuraList::iterator iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end();)
722  {
723  Aura* aur = *iter;
724  ++iter;
725 
726  if (aur)
727  {
728  uint32 removedAuras = m_removedAurasCount;
729  RemoveAurasByCasterSpell(aur->GetId(), casterGUID);
730  if (m_removedAurasCount > removedAuras + 1)
731  iter = m_modAuras[auraType].begin();
732  }
733  }
734 }
735 
737 {
738  if (!(m_interruptMask & flag))
739  return;
740 
741  // interrupt auras
742  AuraList::iterator iter;
743  for (iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end();)
744  {
745  Aura* aur = *iter;
746  ++iter;
747 
748  //sLog.outDetail("auraflag:%u flag:%u = %u", aur->GetSpellProto()->AuraInterruptFlags,flag, aur->GetSpellProto()->AuraInterruptFlags & flag);
749 
750  if (aur && (aur->GetSpellProto()->AuraInterruptFlags & flag))
751  {
752  if (aur->IsInUse())
753  sLog.outError("Aura %u is trying to remove itself! Flag %u. May cause crash!", aur->GetId(), flag);
754 
755  else if (!except || aur->GetId() != except)
756  {
757  uint32 removedAuras = m_removedAurasCount;
758 
760  if (m_removedAurasCount > removedAuras + 1)
761  iter = m_interruptableAuras.begin();
762 
763  }
764  }
765  }
766 
767  // interrupt channeled spell
769  if (spell->getState() == SPELL_STATE_CASTING
770  && (spell->m_spellInfo->ChannelInterruptFlags & flag)
771  && spell->m_spellInfo->Id != except)
773 
775 }
776 
778 {
779  m_interruptMask = 0;
780  for (AuraList::iterator i = m_interruptableAuras.begin(); i != m_interruptableAuras.end(); ++i)
781  {
782  if (*i)
783  m_interruptMask |= (*i)->GetSpellProto()->AuraInterruptFlags;
784  }
786  if (spell->getState() == SPELL_STATE_CASTING)
787  m_interruptMask |= spell->m_spellInfo->ChannelInterruptFlags;
788 }
789 
791 {
792  uint32 count = 0;
793  for (AuraMap::const_iterator itr = m_Auras.lower_bound(spellEffectPair(spellId, 0)); itr != m_Auras.upper_bound(spellEffectPair(spellId, 0)); ++itr)
794  {
795  if (!itr->second->GetStackAmount())
796  count++;
797  else
798  count += (uint32)itr->second->GetStackAmount();
799  }
800 
801  return count;
802 }
803 
810 bool Unit::HasHigherRankOfAura(uint32 spellid, uint8 effIndex) const
811 {
812  if (SpellChainNode const* curr = sSpellMgr.GetSpellChainNode(spellid))
813  {
814  SpellChainNode const* node = sSpellMgr.GetSpellChainNode(curr->first);
815  uint32 spell = curr->first;
816 
817  while (spell)
818  {
819  AuraMap::const_iterator aura = m_Auras.find(spellEffectPair(spell, effIndex));
820  if (aura != m_Auras.end())
821  if (node->rank > curr->rank)
822  return true;
823 
824  spell = node->next;
825  node = sSpellMgr.GetSpellChainNode(node->next);
826  }
827  }
828 
829  return false;
830 }
831 
832 bool Unit::HasAuraType(AuraType auraType) const
833 {
834  return (!m_modAuras[auraType].empty());
835 }
836 
837 bool Unit::HasAuraTypeWithCaster(AuraType auratype, uint64 caster) const
838 {
839  Unit::AuraList const& mTotalAuraList = GetAurasByType(auratype);
840  for (Unit::AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
841  if (caster == (*i)->GetCasterGUID())
842  return true;
843  return false;
844 }
845 
846 bool Unit::HasAuraTypeWithMiscvalue(AuraType auratype, int32 miscvalue) const
847 {
848  Unit::AuraList const& mTotalAuraList = GetAurasByType(auratype);
849  for (Unit::AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
850  if (miscvalue == (*i)->GetMiscValue())
851  return true;
852  return false;
853 }
854 
855 bool Unit::HasAuraTypeWithFamilyFlags(AuraType auraType, uint32 familyName, uint64 familyFlags) const
856 {
857  if (!HasAuraType(auraType))
858  return false;
859  AuraList const& auras = GetAurasByType(auraType);
860  for (AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
861  if (SpellEntry const* iterSpellProto = (*itr)->GetSpellProto())
862  if (iterSpellProto->SpellFamilyName == familyName && iterSpellProto->SpellFamilyFlags & familyFlags)
863  return true;
864  return false;
865 }
866 
868 {
869  if (!(m_interruptMask & flag))
870  return false;
871 
872  // interrupt auras
873  AuraList::iterator iter;
874  for (iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end();)
875  {
876  Aura* aur = *iter;
877  ++iter;
878  if (!aur->IsPositive() && aur->GetSpellProto()->AuraInterruptFlags & flag)
879  return true;
880  }
881 
882  return false;
883 }
884 
885 
886 /* Called by DealDamage for auras that have a chance to be dispelled on damage taken. */
888 {
889  // The chance to dispel an aura depends on the damage taken with respect to the casters level.
890  uint32 max_dmg = getLevel() > 8 ? 30 * getLevel() - 100 : 50;
891  float chance = float(damage) / max_dmg * 100.0f;
892 
893  AuraList::iterator i, next;
894  for (i = m_ccAuras.begin(); i != m_ccAuras.end(); i = next)
895  {
896  next = i;
897  ++next;
898 
899  if (*i && (!spell || (*i)->GetId() != spell) && roll_chance_f(chance))
900  {
901  RemoveAurasDueToSpell((*i)->GetId());
902  if (!m_ccAuras.empty())
903  next = m_ccAuras.begin();
904  else
905  return;
906  }
907  }
908 }
909 
910 uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const* spellProto, bool durabilityLoss)
911 {
912  if ((!victim->IsAlive() || victim->IsInFlight()) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()))
913  return 0;
914 
915  //You don't lose health from damage taken from another player while in a sanctuary
916  //You still see it in the combat log though
917  if (victim != this && GetTypeId() == TYPEID_PLAYER && victim->GetTypeId() == TYPEID_PLAYER)
918  {
919  const AreaTableEntry* area = GetAreaEntryByAreaID(victim->GetAreaId());
920  if (area && area->flags & AREA_FLAG_SANCTUARY) //sanctuary
921  return 0;
922  }
923 
924  //Script Event damage taken
925  if (victim->IsAIEnabled)
926  victim->ToCreature()->AI()->DamageTaken(this, damage);
927 
928  // Signal to pet that it dealt damage
929  if (IsPet() && this != victim && victim->IsAlive())
930  ToPet()->AI()->DamageDealt(victim, damage, damagetype);
931  else if (IsAIEnabled)
932  ToCreature()->AI()->DamageDealt(victim, damage, damagetype);
933 
934  if (victim->GetTypeId() == TYPEID_PLAYER && this != victim)
935  {
936  // Signal to pets that their owner was attacked - except when DOT.
937  if (damagetype != DOT)
938  {
939  Pet* pet = victim->ToPlayer()->GetPet();
940 
941  if (pet && pet->IsAlive())
942  pet->AI()->OwnerAttackedBy(this);
943  }
944 
945  if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD))
946  return 0;
947  }
948 
949  // Signal the pet it was attacked so the AI can respond if needed
950  if (victim->GetTypeId() == TYPEID_UNIT && this != victim && victim->IsPet() && victim->IsAlive())
951  victim->ToPet()->AI()->AttackedBy(this);
952 
953  if (victim->GetTypeId() == TYPEID_UNIT && (victim->ToCreature())->IsAIEnabled)
954  {
955  // Set tagging
956  if (!victim->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_OTHER_TAGGER) && !victim->IsPet())
957  {
958  //Set Loot
959  switch (GetTypeId())
960  {
961  case TYPEID_PLAYER:
962  {
963  victim->ToCreature()->SetLootRecipient(this);
964  //Set tagged
966  break;
967  }
968  case TYPEID_UNIT:
969  {
970  if (IsPet())
971  {
972  victim->ToCreature()->SetLootRecipient(this->GetOwner());
974  }
975  break;
976  }
977  }
978  }
979  }
980 
981  if (damage || (cleanDamage && cleanDamage->damage))
982  {
983  if (spellProto)
984  {
987  }
988  else
990 
991  victim->RemoveSpellbyDamageTaken(damage, spellProto ? spellProto->Id : 0);
992  // Rage from physical damage received
993  if (!damage)
994  {
995  if ((damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) && victim->GetTypeId() == TYPEID_PLAYER && (victim->getPowerType() == POWER_RAGE))
996  victim->ToPlayer()->RewardRage(cleanDamage->damage, 0, false);
997  return 0;
998  }
999  }
1000 
1001  DEBUG_LOG("DealDamageStart");
1002 
1003  uint32 health = victim->GetHealth();
1004  sLog.outDetail("deal dmg:%d to health:%d ", damage, health);
1005 
1006  // duel ends when player has 1 or less hp
1007  bool duel_hasEnded = false;
1008  if (victim->GetTypeId() == TYPEID_PLAYER && victim->ToPlayer()->duel && damage >= (health - 1))
1009  {
1010  // prevent kill only if killed in duel and killed by opponent or opponent controlled creature
1011  if (victim->ToPlayer()->duel->opponent == this || victim->ToPlayer()->duel->opponent->GetGUID() == GetOwnerGUID())
1012  damage = health - 1;
1013 
1014  duel_hasEnded = true;
1015  }
1016 
1017  // Rage from Damage made (only from direct weapon damage)
1018  if (cleanDamage && damagetype == DIRECT_DAMAGE && this != victim && GetTypeId() == TYPEID_PLAYER && (getPowerType() == POWER_RAGE))
1019  {
1020  uint32 weaponSpeedHitFactor;
1021 
1022  switch (cleanDamage->attackType)
1023  {
1024  case BASE_ATTACK:
1025  {
1026  if (cleanDamage->hitOutCome == MELEE_HIT_CRIT)
1027  weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * 7);
1028  else
1029  weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * 3.5f);
1030 
1031  // If attack is evaded/parried/dodged DON'T add rage
1032  if (cleanDamage->hitOutCome != MELEE_HIT_EVADE && cleanDamage->hitOutCome != MELEE_HIT_PARRY && cleanDamage->hitOutCome != MELEE_HIT_DODGE)
1033  ToPlayer()->RewardRage(damage, weaponSpeedHitFactor, true);
1034 
1035  break;
1036  }
1037  case OFF_ATTACK:
1038  {
1039  if (cleanDamage->hitOutCome == MELEE_HIT_CRIT)
1040  weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * 3.5f);
1041  else
1042  weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType) / 1000.0f * 1.75f);
1043 
1044  ToPlayer()->RewardRage(damage, weaponSpeedHitFactor, true);
1045 
1046  break;
1047  }
1048  case RANGED_ATTACK:
1049  break;
1050  }
1051  }
1052 
1053  if (victim->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER)
1054  {
1055  if (victim->ToPlayer()->InBattleground())
1056  {
1057  Player* killer = ToPlayer();
1058  if (killer != victim->ToPlayer())
1059  if (Battleground* bg = killer->GetBattleground())
1060  bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage);
1061  }
1062  }
1063 
1064  if (victim->GetTypeId() == TYPEID_UNIT && !victim->IsPet())
1065  {
1066  if (!victim->ToCreature()->hasLootRecipient())
1067  victim->ToCreature()->SetLootRecipient(this);
1068 
1070  victim->ToCreature()->SetPlayerDamaged(true);
1071  }
1072 
1073  if (health <= damage)
1074  {
1075  DEBUG_LOG("DealDamage: victim just died");
1076  Kill(victim, durabilityLoss);
1077 
1078  //Hook for OnPVPKill Event
1079  if (this->GetTypeId() == TYPEID_PLAYER)
1080  {
1081  if (victim->GetTypeId() == TYPEID_PLAYER)
1082  {
1083  Player *killer = this->ToPlayer();
1084  Player *killed = victim->ToPlayer();
1085  sScriptMgr.OnPVPKill(killer, killed);
1086  }
1087  else if (victim->GetTypeId() == TYPEID_UNIT)
1088  {
1089  Player *killer = this->ToPlayer();
1090  Creature *killed = victim->ToCreature();
1091  sScriptMgr.OnCreatureKill(killer, killed);
1092  }
1093  }
1094  else if (this->GetTypeId() == TYPEID_UNIT)
1095  {
1096  if (victim->GetTypeId() == TYPEID_PLAYER)
1097  {
1098  Creature *killer = this->ToCreature();
1099  Player *killed = victim->ToPlayer();
1100  sScriptMgr.OnPlayerKilledByCreature(killer, killed);
1101  }
1102  }
1103  }
1104  else // if (health <= damage)
1105  {
1106  DEBUG_LOG("DealDamageAlive");
1107 
1108  victim->ModifyHealth(-(int32)damage);
1109 
1110  if (damagetype != DOT)
1111  {
1112  if (!GetVictim())
1113  /*{
1114  // if have target and damage victim just call AI reaction
1115  if (victim != GetVictim() && victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsAIEnabled)
1116  victim->ToCreature()->AI()->AttackedBy(this);
1117  }
1118  else*/
1119  {
1120  // if not have main target then attack state with target (including AI call)
1121  //start melee attacks only after melee hit
1122  Attack(victim, (damagetype == DIRECT_DAMAGE));
1123  }
1124  }
1125 
1126  if (damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE)
1127  {
1128  victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0);
1129  if (victim->GetTypeId() == TYPEID_UNIT && !victim->IsPet())
1130  victim->SetLastDamagedTime(time(NULL));
1131  }
1132 
1133  if (victim->GetTypeId() != TYPEID_PLAYER)
1134  victim->AddThreat(this, (float)damage, damageSchoolMask, spellProto);
1135  else // victim is a player
1136  {
1137  // Rage from damage received
1138  if (this != victim && victim->getPowerType() == POWER_RAGE)
1139  {
1140  uint32 rage_damage = damage + (cleanDamage ? cleanDamage->damage : 0);
1141  victim->ToPlayer()->RewardRage(rage_damage, 0, false);
1142  }
1143 
1144  // random durability for items (HIT TAKEN)
1146  {
1148  victim->ToPlayer()->DurabilityPointLossForEquipSlot(slot);
1149  }
1150  }
1151 
1152  if (GetTypeId() == TYPEID_PLAYER)
1153  {
1154  // random durability for items (HIT DONE)
1156  {
1159  }
1160  }
1161 
1162  if (damagetype != NODAMAGE && damage)
1163  {
1164  if (victim != this && victim->GetTypeId() == TYPEID_PLAYER) // does not support creature push_back
1165  {
1166  if (damagetype != DOT)
1167  {
1168  if (Spell* spell = victim->m_currentSpells[CURRENT_GENERIC_SPELL])
1169  {
1170  if (spell->getState() == SPELL_STATE_PREPARING)
1171  {
1172  uint32 interruptFlags = spell->m_spellInfo->InterruptFlags;
1173  if (interruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE)
1174  victim->InterruptNonMeleeSpells(false);
1175  else if (interruptFlags & SPELL_INTERRUPT_FLAG_PUSH_BACK)
1176  spell->Delayed();
1177  }
1178  }
1179  }
1180 
1181  if (Spell* spell = victim->m_currentSpells[CURRENT_CHANNELED_SPELL])
1182  {
1183  if (spell->getState() == SPELL_STATE_CASTING)
1184  {
1185  uint32 channelInterruptFlags = spell->m_spellInfo->ChannelInterruptFlags;
1186  if (((channelInterruptFlags & CHANNEL_FLAG_DELAY) != 0) && (damagetype != DOT))
1187  spell->DelayedChannel();
1188  }
1189  }
1190  }
1191  }
1192 
1193  // last damage from duel opponent
1194  if (duel_hasEnded)
1195  {
1196  ASSERT(victim->GetTypeId() == TYPEID_PLAYER);
1197  Player* he = victim->ToPlayer();
1198 
1199  ASSERT(he->duel);
1200 
1201  he->SetHealth(1);
1202 
1203  he->duel->opponent->CombatStopWithPets(true);
1204  he->CombatStopWithPets(true);
1205 
1206  he->CastSpell(he, 7267, true); // beg
1207  he->DuelComplete(DUEL_WON);
1208  }
1209  }
1210 
1211  DEBUG_LOG("DealDamageEnd returned %d damage", damage);
1212 
1213  return damage;
1214 }
1215 
1216 void Unit::CastStop(uint32 except_spellid)
1217 {
1219  if (m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id != except_spellid)
1220  InterruptSpell(CurrentSpellTypes(i), false, false);
1221 }
1222 
1223 void Unit::CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item* castItem, Aura* triggeredByAura, uint64 originalCaster)
1224 {
1225  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
1226 
1227  if (!spellInfo)
1228  {
1229  sLog.outError("CastSpell: unknown spell id %i by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1230  return;
1231  }
1232 
1233  CastSpell(Victim, spellInfo, triggered, castItem, triggeredByAura, originalCaster);
1234 }
1235 
1236 void Unit::CastSpell(Unit* Victim, SpellEntry const* spellInfo, bool triggered, Item* castItem, Aura* triggeredByAura, uint64 originalCaster)
1237 {
1238  if (!spellInfo)
1239  {
1240  sLog.outError("CastSpell: unknown spell by caster: %s %u)", (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1241  return;
1242  }
1243 
1244  SpellCastTargets targets;
1245  uint32 targetMask = spellInfo->Targets;
1246  //if (targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2))
1247  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
1248  {
1249  if (sSpellMgr.SpellTargetType[spellInfo->EffectImplicitTargetA[i]] == TARGET_TYPE_UNIT_TARGET)
1250  {
1251  /*SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex);
1252  if (srange && GetSpellMaxRange(srange) == 0.0f)
1253  {
1254  Victim = this;
1255  break;
1256  }
1257  else */if (!Victim)
1258  {
1259  sLog.outError("CastSpell: spell id %i by caster: %s %u) does not have unit target", spellInfo->Id, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1260  return;
1261  }
1262  else
1263  break;
1264  }
1265  }
1266  targets.setUnitTarget(Victim);
1267 
1269  {
1270  if (!Victim)
1271  {
1272  sLog.outError("CastSpell: spell id %i by caster: %s %u) does not have destination", spellInfo->Id, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1273  return;
1274  }
1275  targets.setDst(Victim);
1276  }
1277 
1278  #ifdef OREGON_DEBUG
1279  if (castItem)
1280  DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1281  #endif
1282 
1283  if (!originalCaster && triggeredByAura)
1284  originalCaster = triggeredByAura->GetCasterGUID();
1285 
1286  Spell* spell = new Spell(this, spellInfo, triggered, originalCaster);
1287 
1288  // When casting a combat spell the unit has to be flagged as initiating combat
1289  // Check for self-cast case here for this may have been called by a command
1290  if (Victim && spell->GetCaster() != Victim && !IsNonCombatSpell(spellInfo))
1291  spell->GetCaster()->SetInitiatingCombat(true);
1292 
1293  spell->m_CastItem = castItem;
1294  spell->prepare(&targets, triggeredByAura);
1295 }
1296 
1297 void Unit::CastCustomSpell(Unit* target, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item* castItem, Aura* triggeredByAura, uint64 originalCaster)
1298 {
1299  CustomSpellValues values;
1300  if (bp0)
1301  values.AddSpellMod(SPELLVALUE_BASE_POINT0, *bp0);
1302  if (bp1)
1303  values.AddSpellMod(SPELLVALUE_BASE_POINT1, *bp1);
1304  if (bp2)
1305  values.AddSpellMod(SPELLVALUE_BASE_POINT2, *bp2);
1306  CastCustomSpell(spellId, values, target, triggered, castItem, triggeredByAura, originalCaster);
1307 }
1308 
1309 void Unit::CastCustomSpell(uint32 spellId, SpellValueMod mod, uint32 value, Unit* target, bool triggered, Item* castItem, Aura* triggeredByAura, uint64 originalCaster)
1310 {
1311  CustomSpellValues values;
1312  values.AddSpellMod(mod, value);
1313  CastCustomSpell(spellId, values, target, triggered, castItem, triggeredByAura, originalCaster);
1314 }
1315 
1316 void Unit::CastCustomSpell(uint32 spellId, CustomSpellValues const& value, Unit* Victim, bool triggered, Item* castItem, Aura* triggeredByAura, uint64 originalCaster)
1317 {
1318  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
1319  if (!spellInfo)
1320  {
1321  sLog.outError("CastSpell: unknown spell id %i by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1322  return;
1323  }
1324 
1325  SpellCastTargets targets;
1326  uint32 targetMask = spellInfo->Targets;
1327 
1328  //check unit target
1329  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
1330  {
1331  if (sSpellMgr.SpellTargetType[spellInfo->EffectImplicitTargetA[i]] == TARGET_TYPE_UNIT_TARGET)
1332  {
1333  if (!Victim)
1334  {
1335  sLog.outError("CastSpell: spell id %i by caster: %s %u) does not have unit target", spellInfo->Id, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1336  return;
1337  }
1338  else
1339  break;
1340  }
1341  }
1342  targets.setUnitTarget(Victim);
1343 
1344  //check destination
1346  {
1347  if (!Victim)
1348  {
1349  sLog.outError("CastSpell: spell id %i by caster: %s %u) does not have destination", spellInfo->Id, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1350  return;
1351  }
1352  targets.setDst(Victim);
1353  }
1354 
1355  if (!originalCaster && triggeredByAura)
1356  originalCaster = triggeredByAura->GetCasterGUID();
1357 
1358  Spell* spell = new Spell(this, spellInfo, triggered, originalCaster);
1359 
1360  if (castItem)
1361  {
1362  DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1363  spell->m_CastItem = castItem;
1364  }
1365 
1366  for (CustomSpellValues::const_iterator itr = value.begin(); itr != value.end(); ++itr)
1367  spell->SetSpellValue(itr->first, itr->second);
1368 
1369  spell->prepare(&targets, triggeredByAura);
1370 }
1371 
1372 // used for scripting
1373 void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item* castItem, Aura* triggeredByAura, uint64 originalCaster)
1374 {
1375  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
1376  if (!spellInfo)
1377  {
1378  sLog.outError("CastSpell(x,y,z): unknown spell id %i by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1379  return;
1380  }
1381 
1382  #ifdef OREGON_DEBUG
1383  if (castItem)
1384  DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1385  #endif
1386 
1387  if (!originalCaster && triggeredByAura)
1388  originalCaster = triggeredByAura->GetCasterGUID();
1389 
1390  Spell* spell = new Spell(this, spellInfo, triggered, originalCaster);
1391 
1392  SpellCastTargets targets;
1393  targets.setDst(x, y, z, GetOrientation());
1394  spell->m_CastItem = castItem;
1395  spell->prepare(&targets, triggeredByAura);
1396 }
1397 
1398 // used for scripting
1399 void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castItem, Aura* triggeredByAura, uint64 originalCaster)
1400 {
1401  if (!go)
1402  return;
1403 
1404  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
1405 
1406  if (!spellInfo)
1407  {
1408  sLog.outError("CastSpell(x,y,z): unknown spell id %i by caster: %s %u)", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1409  return;
1410  }
1411 
1412  if (!(spellInfo->Targets & (TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK)))
1413  {
1414  sLog.outError("CastSpell: spell id %i by caster: %s %u) is not gameobject spell", spellId, (GetTypeId() == TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"), (GetTypeId() == TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
1415  return;
1416  }
1417 
1418  #ifdef OREGON_DEBUG
1419  if (castItem)
1420  DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1421  #endif
1422 
1423  if (!originalCaster && triggeredByAura)
1424  originalCaster = triggeredByAura->GetCasterGUID();
1425 
1426  Spell* spell = new Spell(this, spellInfo, triggered, originalCaster);
1427 
1428  SpellCastTargets targets;
1429  targets.setGOTarget(go);
1430  spell->m_CastItem = castItem;
1431  spell->prepare(&targets, triggeredByAura);
1432 }
1433 
1434 // Obsolete func need remove, here only for comotability vs another patches
1435 uint32 Unit::SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage, bool /*isTriggeredSpell*/, bool /*useSpellDamage*/)
1436 {
1437  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellID);
1438  SpellNonMeleeDamage damageInfo(this, victim, spellInfo->Id, spellInfo->SchoolMask);
1439  damage = SpellDamageBonus(victim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
1440  CalculateSpellDamageTaken(&damageInfo, damage, spellInfo);
1441  SendSpellNonMeleeDamageLog(&damageInfo);
1442  DealSpellDamage(&damageInfo, true);
1443  return damageInfo.damage;
1444 }
1445 
1446 void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 damage, SpellEntry const* spellInfo, WeaponAttackType attackType, bool crit)
1447 {
1448  if (damage < 0)
1449  return;
1450 
1451  Unit* victim = damageInfo->target;
1452  if (!victim || !victim->IsAlive())
1453  return;
1454 
1455  SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
1456  uint32 crTypeMask = victim->GetCreatureTypeMask();
1457 
1458  bool blocked = false;
1459  // Per-school calc
1460  switch (spellInfo->DmgClass)
1461  {
1462  // Melee and Ranged Spells
1465  {
1466  // Physical Damage
1467  if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL)
1468  {
1469  // Get blocked status
1470  blocked = isSpellBlocked(victim, spellInfo, attackType);
1471  }
1472 
1473  if (crit)
1474  {
1475  damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
1476 
1477  // Calculate crit bonus
1478  uint32 crit_bonus = damage;
1479  // Apply crit_damage bonus for melee spells
1480  if (Player* modOwner = GetSpellModOwner())
1481  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
1482  damage += crit_bonus;
1483 
1484  // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
1485  int32 critPctDamageMod = 0;
1486  if (attackType == RANGED_ATTACK)
1488  else
1489  {
1492  }
1493 
1494  // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
1495  critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
1496 
1497  if (critPctDamageMod != 0)
1498  AddPct(damage, critPctDamageMod);
1499 
1500  // Resilience - reduce crit damage
1501  if (victim->GetTypeId() == TYPEID_PLAYER)
1502  damage -= victim->ToPlayer()->GetMeleeCritDamageReduction(damage);
1503  }
1504 
1505  // Spell weapon based damage CAN BE crit & blocked at same time
1506  if (blocked)
1507  {
1508  damageInfo->blocked = uint32(victim->GetShieldBlockValue());
1509  if (damage < int32(damageInfo->blocked))
1510  damageInfo->blocked = uint32(damage);
1511  damage -= damageInfo->blocked;
1512  }
1513  }
1514  break;
1515  // Magical Attacks
1518  {
1519  // If crit add critical bonus
1520  if (crit)
1521  {
1522  damageInfo->HitInfo |= SPELL_HIT_TYPE_CRIT;
1523  damage = SpellCriticalBonus(spellInfo, damage, victim);
1524 
1525  // Resilience - reduce crit damage
1526  if (victim->GetTypeId() == TYPEID_PLAYER)
1527  damage -= victim->ToPlayer()->GetSpellCritDamageReduction(damage);
1528  }
1529  }
1530  break;
1531  default:
1532  break;
1533  }
1534 
1535  // damage before absorb/resist calculation
1536  damageInfo->cleanDamage = damage;
1537  if (IsDamageReducedByArmor(damageSchoolMask, spellInfo))
1538  damage = CalcArmorReducedDamage(victim, damage);
1539 
1540  // Calculate absorb resist
1541  if (damage > 0)
1542  {
1543  CalcAbsorbResist(victim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo, IsBinarySpell(spellInfo));
1544  damage -= damageInfo->absorb + damageInfo->resist;
1545  }
1546  else
1547  damage = 0;
1548 
1549  damageInfo->damage = damage;
1550 }
1551 
1552 void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
1553 {
1554  if (damageInfo == 0)
1555  return;
1556 
1557  Unit* victim = damageInfo->target;
1558 
1559  if (!victim)
1560  return;
1561 
1562  if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()))
1563  return;
1564 
1565  SpellEntry const* spellProto = sSpellStore.LookupEntry(damageInfo->SpellID);
1566  if (spellProto == NULL)
1567  {
1568  DEBUG_LOG("Unit::DealSpellDamage has invalid damageInfo->SpellID: %u", damageInfo->SpellID);
1569  return;
1570  }
1571 
1572  //You don't lose health from damage taken from another player while in a sanctuary
1573  //You still see it in the combat log though
1574  if (victim != this && GetTypeId() == TYPEID_PLAYER && victim->GetTypeId() == TYPEID_PLAYER)
1575  {
1576  const AreaTableEntry* area = GetAreaEntryByAreaID(victim->GetAreaId());
1577  if (area && area->flags & 0x800) //sanctuary
1578  return;
1579  }
1580 
1581  // update at damage Judgement aura duration that applied by attacker at victim
1582  if (damageInfo->damage && spellProto->Id == 35395)
1583  {
1584  AuraMap& vAuras = victim->GetAuras();
1585  for (AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr)
1586  {
1587  SpellEntry const* spellInfo = (*itr).second->GetSpellProto();
1588  if (spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && spellInfo->AttributesEx3 & 0x40000)
1589  {
1590  (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
1591  (*itr).second->UpdateAuraDuration();
1592  }
1593  }
1594  }
1595  // Call default DealDamage
1596  CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL);
1597  DealDamage(victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
1598 }
1599 
1601 void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType)
1602 {
1603  damageInfo->attacker = this;
1604  damageInfo->target = victim;
1606  damageInfo->attackType = attackType;
1607  damageInfo->damage = 0;
1608  damageInfo->cleanDamage = 0;
1609  damageInfo->absorb = 0;
1610  damageInfo->resist = 0;
1611  damageInfo->blocked_amount = 0;
1612 
1613  damageInfo->TargetState = 0;
1614  damageInfo->HitInfo = 0;
1615  damageInfo->procAttacker = PROC_FLAG_NONE;
1616  damageInfo->procVictim = PROC_FLAG_NONE;
1617  damageInfo->procEx = PROC_EX_NONE;
1618  damageInfo->hitOutCome = MELEE_HIT_EVADE;
1619 
1620  if (!victim)
1621  return;
1622 
1623  if (!IsAlive() || !victim->IsAlive())
1624  return;
1625 
1626  // Select HitInfo/procAttacker/procVictim flag based on attack type
1627  switch (attackType)
1628  {
1629  case BASE_ATTACK:
1632  damageInfo->HitInfo = HITINFO_NORMALSWING2;
1633  break;
1634  case OFF_ATTACK:
1637  damageInfo->HitInfo = HITINFO_LEFTSWING;
1638  break;
1639  case RANGED_ATTACK:
1642  damageInfo->HitInfo = HITINFO_UNK3; // HitInfo flag not confirmed.
1643  break;
1644  default:
1645  break;
1646  }
1647 
1648  // Physical Immune check
1649  if (damageInfo->target->IsImmunedToDamage(SpellSchoolMask(damageInfo->damageSchoolMask), true))
1650  {
1651  damageInfo->HitInfo |= HITINFO_NORMALSWING;
1652  damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE;
1653 
1654  damageInfo->procEx |= PROC_EX_IMMUNE;
1655  damageInfo->damage = 0;
1656  damageInfo->cleanDamage = 0;
1657  return;
1658  }
1659 
1660  damage += CalculateDamage(damageInfo->attackType, false, true);
1661  // Add melee damage bonus
1662  MeleeDamageBonus(damageInfo->target, &damage, damageInfo->attackType);
1663 
1664  // Calculate armor reduction
1666  {
1667  damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage);
1668  damageInfo->cleanDamage += damage - damageInfo->damage;
1669  }
1670  else
1671  damageInfo->damage = damage;
1672 
1673  damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType);
1674 
1675  // Disable parry or dodge for ranged attack
1676  if (damageInfo->attackType == RANGED_ATTACK)
1677  {
1678  if (damageInfo->hitOutCome == MELEE_HIT_PARRY) damageInfo->hitOutCome = MELEE_HIT_NORMAL;
1679  if (damageInfo->hitOutCome == MELEE_HIT_DODGE) damageInfo->hitOutCome = MELEE_HIT_MISS;
1680  }
1681 
1682  switch (damageInfo->hitOutCome)
1683  {
1684  case MELEE_HIT_EVADE:
1685  damageInfo->HitInfo |= HITINFO_MISS | HITINFO_SWINGNOHITSOUND;
1686  damageInfo->TargetState = VICTIMSTATE_EVADES;
1687  damageInfo->procEx |= PROC_EX_EVADE;
1688  damageInfo->damage = 0;
1689  damageInfo->cleanDamage = 0;
1690  return;
1691  case MELEE_HIT_MISS:
1692  damageInfo->HitInfo |= HITINFO_MISS;
1693  damageInfo->TargetState = VICTIMSTATE_NORMAL;
1694  damageInfo->procEx |= PROC_EX_MISS;
1695  damageInfo->damage = 0;
1696  damageInfo->cleanDamage = 0;
1697  break;
1698  case MELEE_HIT_NORMAL:
1699  damageInfo->TargetState = VICTIMSTATE_NORMAL;
1700  damageInfo->procEx |= PROC_EX_NORMAL_HIT;
1701  break;
1702  case MELEE_HIT_CRIT:
1703  {
1704  damageInfo->HitInfo |= HITINFO_CRITICALHIT;
1705  damageInfo->TargetState = VICTIMSTATE_NORMAL;
1706 
1707  damageInfo->procEx |= PROC_EX_CRITICAL_HIT;
1708  // Crit bonus calc
1709  damageInfo->damage += damageInfo->damage;
1710  int32 mod = 0;
1711  // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
1712  if (damageInfo->attackType == RANGED_ATTACK)
1714  else
1715  {
1718  }
1719 
1720  uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask();
1721 
1722  // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
1724  if (mod != 0)
1725  AddPct(damageInfo->damage, mod);
1726 
1727  // Resilience - reduce crit damage
1728  if (victim->GetTypeId() == TYPEID_PLAYER)
1729  {
1730  uint32 resilienceReduction = victim->ToPlayer()->GetMeleeCritDamageReduction(damageInfo->damage);
1731  damageInfo->damage -= resilienceReduction;
1732  damageInfo->cleanDamage += resilienceReduction;
1733  }
1734  break;
1735  }
1736  case MELEE_HIT_PARRY:
1737  damageInfo->TargetState = VICTIMSTATE_PARRY;
1738  damageInfo->procEx |= PROC_EX_PARRY;
1739  damageInfo->cleanDamage += damageInfo->damage;
1740  damageInfo->damage = 0;
1741  break;
1742 
1743  case MELEE_HIT_DODGE:
1744  damageInfo->TargetState = VICTIMSTATE_DODGE;
1745  damageInfo->procEx |= PROC_EX_DODGE;
1746  damageInfo->cleanDamage += damageInfo->damage;
1747  damageInfo->damage = 0;
1748  break;
1749  case MELEE_HIT_BLOCK:
1750  damageInfo->TargetState = VICTIMSTATE_NORMAL;
1751  damageInfo->procEx |= PROC_EX_BLOCK;
1752  damageInfo->blocked_amount = damageInfo->target->GetShieldBlockValue();
1753  if (damageInfo->blocked_amount >= damageInfo->damage)
1754  {
1755  damageInfo->TargetState = VICTIMSTATE_BLOCKS;
1756  damageInfo->blocked_amount = damageInfo->damage;
1757  }
1758  else
1759  damageInfo->procEx |= PROC_EX_NORMAL_HIT;
1760  damageInfo->damage -= damageInfo->blocked_amount;
1761  damageInfo->cleanDamage += damageInfo->blocked_amount;
1762  break;
1763  case MELEE_HIT_GLANCING:
1764  {
1765  damageInfo->HitInfo |= HITINFO_GLANCING;
1766  damageInfo->TargetState = VICTIMSTATE_NORMAL;
1767  damageInfo->procEx |= PROC_EX_NORMAL_HIT;
1768  int32 leveldif = int32(victim->getLevel()) - int32(getLevel());
1769  if (leveldif > 3)
1770  leveldif = 3;
1771  float reducePercent = 1 - leveldif * 0.1f;
1772  damageInfo->cleanDamage += damageInfo->damage - uint32(reducePercent * damageInfo->damage);
1773  damageInfo->damage = uint32(reducePercent * damageInfo->damage);
1774  break;
1775  }
1776  case MELEE_HIT_CRUSHING:
1777  damageInfo->HitInfo |= HITINFO_CRUSHING;
1778  damageInfo->TargetState = VICTIMSTATE_NORMAL;
1779  damageInfo->procEx |= PROC_EX_NORMAL_HIT;
1780  // 150% normal damage
1781  damageInfo->damage += (damageInfo->damage / 2);
1782  break;
1783  default:
1784  break;
1785  }
1786 
1787  // Calculate absorb resist
1788  if (int32(damageInfo->damage) > 0)
1789  {
1790  damageInfo->procVictim |= PROC_FLAG_TAKEN_DAMAGE;
1791  // Calculate absorb & resists
1792  CalcAbsorbResist(damageInfo->target, SpellSchoolMask(damageInfo->damageSchoolMask), DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist);
1793 
1794 
1795  if (damageInfo->absorb)
1796  {
1797  damageInfo->HitInfo |= HITINFO_ABSORB;
1798  damageInfo->procEx |= PROC_EX_ABSORB;
1799  }
1800 
1801  if (damageInfo->resist)
1802  damageInfo->HitInfo |= HITINFO_RESIST;
1803 
1804  damageInfo->damage -= damageInfo->absorb + damageInfo->resist;
1805  }
1806  else // Impossible get negative result but....
1807  damageInfo->damage = 0;
1808 }
1809 
1810 void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
1811 {
1812  Unit* victim = damageInfo->target;
1813 
1814  if (!victim)
1815  return;
1816 
1817  if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()))
1818  return;
1819 
1820  //You don't lose health from damage taken from another player while in a sanctuary
1821  //You still see it in the combat log though
1822  if (victim != this && GetTypeId() == TYPEID_PLAYER && victim->GetTypeId() == TYPEID_PLAYER)
1823  {
1824  const AreaTableEntry* area = GetAreaEntryByAreaID(victim->GetAreaId());
1825  if (area && area->flags & 0x800) //sanctuary
1826  return;
1827  }
1828 
1829  // Hmmmm dont like this emotes client must by self do all animations
1830  if (damageInfo->HitInfo & HITINFO_CRITICALHIT)
1832  if (damageInfo->blocked_amount && damageInfo->TargetState != VICTIMSTATE_BLOCKS)
1834 
1835  if (damageInfo->TargetState == VICTIMSTATE_PARRY)
1836  {
1837  // Get attack timers
1838  float offtime = float(victim->getAttackTimer(OFF_ATTACK));
1839  float basetime = float(victim->getAttackTimer(BASE_ATTACK));
1840  // Reduce attack time
1841  if (victim->haveOffhandWeapon() && offtime < basetime)
1842  {
1843  float percent20 = victim->GetAttackTime(OFF_ATTACK) * 0.20f;
1844  float percent60 = 3.0f * percent20;
1845  if (offtime > percent20 && offtime <= percent60)
1846  victim->setAttackTimer(OFF_ATTACK, uint32(percent20));
1847  else if (offtime > percent60)
1848  {
1849  offtime -= 2.0f * percent20;
1850  victim->setAttackTimer(OFF_ATTACK, uint32(offtime));
1851  }
1852  }
1853  else
1854  {
1855  float percent20 = victim->GetAttackTime(BASE_ATTACK) * 0.20;
1856  float percent60 = 3.0f * percent20;
1857  if (basetime > percent20 && basetime <= percent60)
1858  victim->setAttackTimer(BASE_ATTACK, uint32(percent20));
1859  else if (basetime > percent60)
1860  {
1861  basetime -= 2.0f * percent20;
1862  victim->setAttackTimer(BASE_ATTACK, uint32(basetime));
1863  }
1864  }
1865  }
1866 
1867  // Call default DealDamage
1868  CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->attackType, damageInfo->hitOutCome);
1869  DealDamage(victim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), NULL, durabilityLoss);
1870 
1871  // If this is a creature and it attacks from behind it has a probability to daze it's victim
1872  if ((damageInfo->hitOutCome == MELEE_HIT_CRIT || damageInfo->hitOutCome == MELEE_HIT_CRUSHING || damageInfo->hitOutCome == MELEE_HIT_NORMAL || damageInfo->hitOutCome == MELEE_HIT_GLANCING) &&
1873  GetTypeId() != TYPEID_PLAYER && !ToCreature()->IsControlledByPlayer() && !victim->HasInArc(float(M_PI), this) && damageInfo->damage
1874  && (victim->GetTypeId() == TYPEID_PLAYER || !victim->ToCreature()->isWorldBoss()))
1875  {
1876  // -probability is between 0% and 40%
1877  // 20% base chance
1878  float Probability = 20.0f;
1879 
1880  //there is a newbie protection, at level 10 just 7% base chance; assuming linear function
1881  if (victim->getLevel() < 30)
1882  Probability = 0.65f * victim->getLevel() + 0.5f;
1883 
1884  uint32 VictimDefense = victim->GetDefenseSkillValue();
1885  uint32 AttackerMeleeSkill = GetUnitMeleeSkill();
1886 
1887  Probability *= AttackerMeleeSkill / (float)VictimDefense*0.16f;
1888 
1889  if (Probability < 0)
1890  Probability = 0;
1891 
1892  if (Probability > 40.0f)
1893  Probability = 40.0f;
1894 
1895  if (roll_chance_f(Probability))
1896  CastSpell(victim, 1604, true);
1897  }
1898 
1899  // update at damage Judgement aura duration that applied by attacker at victim
1900  if (damageInfo->damage)
1901  {
1902  AuraMap& vAuras = victim->GetAuras();
1903  for (AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr)
1904  {
1905  SpellEntry const* spellInfo = (*itr).second->GetSpellProto();
1906  if (spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID()))
1907  {
1908  (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration());
1909  (*itr).second->UpdateAuraDuration();
1910  }
1911  }
1912  }
1913 
1914  if (GetTypeId() == TYPEID_PLAYER)
1915  ToPlayer()->CastItemCombatSpell(victim, damageInfo->attackType, damageInfo->procVictim, damageInfo->procEx);
1916 
1917  // Do effect if any damage done to target
1918  if (damageInfo->procVictim & PROC_FLAG_TAKEN_DAMAGE)
1919  {
1920  // victim's damage shield
1921  std::set<Aura*> alreadyDone;
1922  uint32 removedAuras = victim->m_removedAurasCount;
1923  AuraList const& vDamageShields = victim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD);
1924  for (AuraList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next)
1925  {
1926  ++next;
1927  if (alreadyDone.find(*i) == alreadyDone.end())
1928  {
1929  SpellEntry const* spellProto = sSpellStore.LookupEntry((*i)->GetId());
1930  if (!spellProto)
1931  continue;
1932 
1933  // Damage shield can be resisted...
1934  if (SpellMissInfo missInfo = victim->SpellHitResult(this, spellProto, false))
1935  {
1936  victim->SendSpellMiss(this, spellProto->Id, missInfo);
1937  continue;
1938  }
1939 
1940  // ...or immuned
1941  if (IsImmunedToDamage(spellProto))
1942  {
1943  victim->SendSpellDamageImmune(this, spellProto->Id);
1944  continue;
1945  }
1946 
1947  alreadyDone.insert(*i);
1948  uint32 damage = (*i)->GetModifier()->m_amount;
1949 
1950  WorldPacket data(SMSG_SPELLDAMAGESHIELD, (8 + 8 + 4 + 4 + 4));
1951  data << uint64(victim->GetGUID());
1952  data << uint64(GetGUID());
1953  data << uint32(spellProto->Id);
1954  data << uint32(damage); // Damage
1955  data << uint32(spellProto->SchoolMask);
1956  victim->SendMessageToSet(&data, true);
1957 
1958  victim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true);
1959 
1960  if (victim->m_removedAurasCount > removedAuras)
1961  {
1962  removedAuras = victim->m_removedAurasCount;
1963  next = vDamageShields.begin();
1964  }
1965  }
1966  }
1967  }
1968 }
1969 
1971 {
1972  WorldPacket data(SMSG_EMOTE, 4 + 8);
1973  data << uint32(anim_id);
1974  data << uint64(GetGUID());
1975  SendMessageToSet(&data, true);
1976 }
1977 
1978 bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellEntry const* spellInfo, uint8 effIndex)
1979 {
1980  // only physical spells damage gets reduced by armor
1981  if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
1982  return false;
1983  if (spellInfo)
1984  {
1985  // there are spells with no specific attribute but they have "ignores armor" in tooltip
1986 
1987  if (sSpellMgr.GetSpellCustomAttr(spellInfo->Id) & SPELL_ATTR_CU_IGNORE_ARMOR)
1988  return false;
1989 
1990  // bleeding effects are not reduced by armor
1991  // @todo Get this to work with Rake.
1992  if (effIndex != MAX_SPELL_EFFECTS)
1993  {
1994  if (spellInfo->EffectApplyAuraName[effIndex] == SPELL_AURA_PERIODIC_DAMAGE ||
1995  spellInfo->Effect[effIndex] == SPELL_EFFECT_SCHOOL_DAMAGE)
1996  if (spellInfo->GetEffectMechanicMask(effIndex) & (1<<MECHANIC_BLEED))
1997  return false;
1998  }
1999  }
2000  return true;
2001 }
2002 
2004 {
2005  if (!(schoolMask & SPELL_SCHOOL_MASK_MAGIC))
2006  return 0;
2007 
2008  uint32 resistance = 0;
2009  // Select a resistance value matching spell school mask, prefer mininal for multischool spells
2010  uint32 schools = uint32(schoolMask);
2011  for (uint32 school = 0; schools; ++school)
2012  {
2013  if ((schools & 1) && school != SPELL_SCHOOL_NORMAL && school != SPELL_SCHOOL_HOLY)
2014  {
2015  // Base victim resistance
2016  uint32 amount = GetResistance(SpellSchools(school));
2017  // Add SPELL_AURA_MOD_TARGET_RESISTANCE aura value at caster
2018  // Negative value is spell penetration, but effective resistance can't be negative since betas
2019  if (const int32 casterMod = attacker->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, (1 << school)))
2020  amount = uint32(std::max((int32(amount) + casterMod), 0));
2021  if (!amount)
2022  {
2023  resistance = 0; // No resistance for this school: use it!
2024  break;
2025  }
2026  else if (!resistance || amount < resistance)
2027  resistance = amount; // First school encountered or more vulnerable: memorize and continue
2028  }
2029  schools >>= 1;
2030  }
2031 
2032  return resistance;
2033 }
2034 
2035 float Unit::CalculateMagicResistanceMitigation(Unit* attacker, uint32 resistance, bool binary) const
2036 {
2037  // Total resistance mitigation: final ratio of resistance effectiveness
2038  float ratio = float(float(resistance) / (attacker->getLevelForTarget(this) * 5)) * 0.75f;
2039  // Add bonus resistance mitigation to victim based on level difference for non-binary spells
2040  if (!binary)
2041  ratio += std::max(int32(getLevelForTarget(attacker) - attacker->getLevelForTarget(this)), 0) * 0.02f;
2042  // Magic resistance mitigation is capped at 0.75
2043  return std::min(ratio, 0.75f);
2044 }
2045 
2047 {
2048  uint32 newdamage = 0;
2049  float armor = victim->GetArmor();
2050 
2051  // Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
2053 
2054  if (armor < 0.0f) armor = 0.0f;
2055 
2056  float tmpvalue = 0.0f;
2057  if (getLevel() <= 59) //Level 1-59
2058  tmpvalue = armor / (armor + 400.0f + 85.0f * getLevel());
2059  else if (getLevel() < 70) //Level 60-69
2060  tmpvalue = armor / (armor - 22167.5f + 467.5f * getLevel());
2061  else //Level 70+
2062  tmpvalue = armor / (armor + 10557.5f);
2063 
2064  if (tmpvalue < 0.0f)
2065  tmpvalue = 0.0f;
2066  if (tmpvalue > 0.75f)
2067  tmpvalue = 0.75f;
2068 
2069  newdamage = uint32(damage - (damage * tmpvalue));
2070 
2071  return (newdamage > 1) ? newdamage : 1;
2072 }
2073 
2074 void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32* absorb, uint32* resist, SpellEntry const* spellInfo /*= NULL*/, bool binary)
2075 {
2076  if (!victim || !victim->IsAlive() || !damage)
2077  return;
2078 
2079  // Magic damage, check for resists
2080  if (!spellInfo || (spellInfo->AttributesEx4 & SPELL_ATTR4_IGNORE_RESISTANCES) == 0 && (schoolMask & SPELL_SCHOOL_MASK_MAGIC) && (!binary || damagetype == DOT))
2081  {
2082  const float mitigation = victim->CalculateMagicResistanceMitigation(victim, victim->CalculateEffectiveMagicResistance(victim, schoolMask), false);
2083  const SpellPartialResistChanceEntry &chances = SPELL_PARTIAL_RESIST_DISTRIBUTION.at(uint32(mitigation * 10000));
2084  // We choose which portion of damage is resisted below, none by default
2085  uint8 portion = SPELL_PARTIAL_RESIST_NONE;
2086  // If we got to this point, we already rolled for full resist on hit
2087  // We do a roll between remaining chances
2088  const uint8 outcomes = (NUM_SPELL_PARTIAL_RESISTS - 1);
2089  const uint32 roll = urand(1, (10000 - chances.at(SPELL_PARTIAL_RESIST_PCT_100)));
2090  uint32 sum = 0;
2091  for (uint8 outcome = SPELL_PARTIAL_RESIST_NONE; outcome < outcomes; ++outcome)
2092  {
2093  if (const uint32 chance = chances.at(outcome))
2094  {
2095  sum += chance;
2096  if (roll <= sum)
2097  {
2098  portion = outcome;
2099  break;
2100  }
2101  }
2102  }
2103  const uint32 amount = uint32(damage * (portion * (1.0f / float(outcomes))));
2104  // We already rolled for full resist on hit, so we need to deal at least *some* amount of damage...
2105  *resist = (amount >= damage) ? (damage - 1) : amount;
2106  }
2107  else
2108  *resist = 0;
2109 
2110  int32 RemainingDamage = damage - *resist;
2111 
2112  // Paladin Blessed Life 4/7/10% chance to cause 50% dmg
2113  AuraList const& blessedLife = victim->GetAurasByType(SPELL_AURA_REUSED_BLESSED_LIFE);
2114  AuraList::const_iterator blessedAura = blessedLife.begin();
2115  if (blessedAura != blessedLife.end() && *blessedAura)
2116  {
2117  if (urand(0, 100) <= (*blessedAura)->GetSpellProto()->procChance)
2118  RemainingDamage /= 2;
2119  }
2120 
2121  // Need to remove expired auras after
2122  bool expiredExists = false;
2123 
2124  // absorb without mana cost
2125  int32 reflectDamage = 0;
2126  Aura* reflectAura = NULL;
2127  AuraList const& vSchoolAbsorb = victim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB);
2128  for (AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && RemainingDamage > 0; ++i)
2129  {
2130  int32* p_absorbAmount = &(*i)->GetModifier()->m_amount;
2131 
2132  // should not happen....
2133  if (*p_absorbAmount <= 0)
2134  {
2135  expiredExists = true;
2136  continue;
2137  }
2138 
2139  if (((*i)->GetModifier()->m_miscvalue & schoolMask) == 0)
2140  continue;
2141 
2142  // Cheat Death
2143  if ((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && (*i)->GetSpellProto()->SpellIconID == 2109)
2144  {
2145  if (victim->ToPlayer()->HasSpellCooldown(31231))
2146  continue;
2147  if (int32(victim->GetHealth()) <= RemainingDamage)
2148  {
2149  int32 chance = *p_absorbAmount;
2150  if (roll_chance_i(chance))
2151  {
2152  victim->CastSpell(victim, 31231, true);
2153  victim->ToPlayer()->AddSpellCooldown(31231, 0, time(NULL) + 60);
2154 
2155  // with health > 10% lost health until health == 10%, in other case no losses
2156  uint32 health10 = victim->CountPctFromMaxHealth(10);
2157  RemainingDamage = victim->GetHealth() > health10 ? victim->GetHealth() - health10 : 0;
2158  }
2159  }
2160  continue;
2161  }
2162 
2163  int32 currentAbsorb;
2164 
2165  //Reflective Shield
2166  if ((victim != this) && (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && (*i)->GetSpellProto()->SpellFamilyFlags == 0x1)
2167  {
2168  if (Unit* caster = (*i)->GetCaster())
2169  {
2170  AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
2171  for (AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k)
2172  {
2173  switch ((*k)->GetModifier()->m_miscvalue)
2174  {
2175  case 5065: // Rank 1
2176  case 5064: // Rank 2
2177  case 5063: // Rank 3
2178  case 5062: // Rank 4
2179  case 5061: // Rank 5
2180  {
2181  if (RemainingDamage >= *p_absorbAmount)
2182  reflectDamage = *p_absorbAmount * (*k)->GetModifier()->m_amount / 100;
2183  else
2184  reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage / 100;
2185  reflectAura = *i;
2186 
2187  }
2188  break;
2189  default:
2190  break;
2191  }
2192 
2193  if (reflectDamage)
2194  break;
2195  }
2196  }
2197  }
2198 
2199  if (RemainingDamage >= *p_absorbAmount)
2200  {
2201  currentAbsorb = *p_absorbAmount;
2202  expiredExists = true;
2203  }
2204  else
2205  currentAbsorb = RemainingDamage;
2206 
2207  *p_absorbAmount -= currentAbsorb;
2208  RemainingDamage -= currentAbsorb;
2209  }
2210  // do not cast spells while looping auras; auras can get invalid otherwise
2211  if (reflectDamage)
2212  victim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, reflectAura);
2213 
2214  // Remove all expired absorb auras
2215  if (expiredExists)
2216  {
2217  for (AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end();)
2218  {
2219  Aura* aur = (*i);
2220  ++i;
2221  if (aur->GetModifier()->m_amount <= 0)
2222  {
2223  uint32 removedAuras = victim->m_removedAurasCount;
2224  victim->RemoveAurasDueToSpell(aur->GetId());
2225  if (removedAuras + 1 < victim->m_removedAurasCount)
2226  i = vSchoolAbsorb.begin();
2227  }
2228  }
2229  }
2230 
2231  // absorb by mana cost
2232  AuraList const& vManaShield = victim->GetAurasByType(SPELL_AURA_MANA_SHIELD);
2233  for (AuraList::const_iterator i = vManaShield.begin(), next; i != vManaShield.end() && RemainingDamage > 0; i = next)
2234  {
2235  next = i;
2236  ++next;
2237  int32* p_absorbAmount = &(*i)->GetModifier()->m_amount;
2238 
2239  // check damage school mask
2240  if (((*i)->GetModifier()->m_miscvalue & schoolMask) == 0)
2241  continue;
2242 
2243  int32 currentAbsorb;
2244  if (RemainingDamage >= *p_absorbAmount)
2245  currentAbsorb = *p_absorbAmount;
2246  else
2247  currentAbsorb = RemainingDamage;
2248 
2249  float manaMultiplier = (*i)->GetSpellProto()->EffectMultipleValue[(*i)->GetEffIndex()];
2250  if (Player* modOwner = GetSpellModOwner())
2251  modOwner->ApplySpellMod((*i)->GetId(), SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2252 
2253  if (manaMultiplier)
2254  {
2255  int32 maxAbsorb = int32(victim->GetPower(POWER_MANA) / manaMultiplier);
2256  if (currentAbsorb > maxAbsorb)
2257  currentAbsorb = maxAbsorb;
2258  }
2259 
2260  *p_absorbAmount -= currentAbsorb;
2261  if (*p_absorbAmount <= 0)
2262  {
2263  victim->RemoveAurasDueToSpell((*i)->GetId());
2264  next = vManaShield.begin();
2265  }
2266 
2267  int32 manaReduction = int32(currentAbsorb * manaMultiplier);
2268  victim->ApplyPowerMod(POWER_MANA, manaReduction, false);
2269 
2270  RemainingDamage -= currentAbsorb;
2271  }
2272 
2273  // only split damage if not damaging yourself
2274  if (victim != this)
2275  {
2276  AuraList const& vSplitDamageFlat = victim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT);
2277  for (AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next)
2278  {
2279  next = i;
2280  ++next;
2281 
2282  // check damage school mask
2283  if (((*i)->GetModifier()->m_miscvalue & schoolMask) == 0)
2284  continue;
2285 
2286  // Damage can be splitted only if aura has an alive caster
2287  Unit* caster = (*i)->GetCaster();
2288  if (!caster || caster == victim || !caster->IsInWorld() || !caster->IsAlive() || caster->IsImmunedToDamage((SpellSchoolMask)(*i)->GetSpellProto()->SchoolMask))
2289  continue;
2290 
2291  int32 currentAbsorb;
2292  if (RemainingDamage >= (*i)->GetModifier()->m_amount)
2293  currentAbsorb = (*i)->GetModifier()->m_amount;
2294  else
2295  currentAbsorb = RemainingDamage;
2296 
2297  RemainingDamage -= currentAbsorb;
2298 
2299  SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false);
2300 
2301  CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL);
2302  DealDamage(caster, currentAbsorb, &cleanDamage, DOT, schoolMask, (*i)->GetSpellProto(), false);
2303  }
2304 
2305  AuraList const& vSplitDamagePct = victim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT);
2306  for (AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next)
2307  {
2308  next = i;
2309  ++next;
2310 
2311  // check damage school mask
2312  if (!((*i)->GetModifier()->m_miscvalue & schoolMask))
2313  continue;
2314 
2315  // Damage can only be split if the aura has an alive caster linked
2316  Unit* caster = (*i)->GetCaster();
2317  if (!caster || caster == victim || !caster->IsInWorld() || !caster->IsAlive() || caster->IsImmunedToDamage((SpellSchoolMask)(*i)->GetSpellProto()->SchoolMask))
2318  continue;
2319 
2320  uint32 splitted = CalculatePct(RemainingDamage, (*i)->GetModifier()->m_amount);
2321 
2322  RemainingDamage -= int32(splitted);
2323 
2324  SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false);
2325 
2326  CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL);
2327  DealDamage(caster, splitted, &cleanDamage, DOT, schoolMask, (*i)->GetSpellProto(), false);
2328  // break 'Fear' and similar auras
2329  caster->ProcDamageAndSpellFor(true, this, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_NORMAL_HIT, BASE_ATTACK, (*i)->GetSpellProto(), splitted);
2330  }
2331  }
2332 
2333  *absorb = damage - RemainingDamage - *resist;
2334 }
2335 
2336 void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool extra)
2337 {
2339  return;
2340 
2341  if (!victim->IsAlive())
2342  return;
2343 
2344  if ((attType == BASE_ATTACK || attType == OFF_ATTACK) && !IsWithinLOSInMap(victim))
2345  return;
2346 
2348 
2349  if (attType != BASE_ATTACK && attType != OFF_ATTACK)
2350  return; // ignore ranged case
2351 
2352  // melee attack spell casted at main hand attack only
2353  if (attType == BASE_ATTACK && m_currentSpells[CURRENT_MELEE_SPELL] && !extra)
2354  {
2356  return;
2357  }
2358 
2359  CalcDamageInfo damageInfo;
2360  CalculateMeleeDamage(victim, 0, &damageInfo, attType);
2361  // Send log damage message to client
2362  SendAttackStateUpdate(&damageInfo);
2363 
2364  ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType);
2365 
2366  DealMeleeDamage(&damageInfo, true);
2367 
2368  // We call this last because DealMeleeDamage has to check for sit state to
2369  // allow critical hits, but we set STANDING in CombatStart, therefore always
2370  // nullifying the check.
2371  CombatStart(victim);
2372 
2373  #ifdef OREGON_DEBUG
2374  if (GetTypeId() == TYPEID_PLAYER)
2375  DEBUG_LOG("AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
2376  GetGUIDLow(), victim->GetGUIDLow(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
2377  else
2378  DEBUG_LOG("AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
2379  GetGUIDLow(), victim->GetGUIDLow(), victim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
2380  #endif
2381 
2382 }
2383 
2385 {
2386  // This is only wrapper
2387 
2388  // Miss chance based on melee
2389  //float miss_chance = MeleeMissChanceCalc(victim, attType);
2390  float miss_chance = MeleeSpellMissChance(victim, attType, int32(GetWeaponSkillValue(attType, victim)) - int32(victim->GetDefenseSkillValue(this)), 0);
2391 
2392  // Critical hit chance
2393  float crit_chance = GetUnitCriticalChance(attType, victim);
2394 
2395  // stunned target cannot dodge and this is check in GetUnitDodgeChance() (returned 0 in this case)
2396  float dodge_chance = victim->GetUnitDodgeChance();
2397  float block_chance = victim->GetUnitBlockChance();
2398  float parry_chance = victim->GetUnitParryChance();
2399 
2400  // Useful if want to specify crit & miss chances for melee, else it could be removed
2401  DEBUG_LOG("MELEE OUTCOME: miss %f crit %f dodge %f parry %f block %f", miss_chance, crit_chance, dodge_chance, parry_chance, block_chance);
2402 
2403  return RollMeleeOutcomeAgainst(victim, attType, int32(crit_chance * 100), int32(miss_chance * 100), int32(dodge_chance * 100), int32(parry_chance * 100), int32(block_chance * 100), false);
2404 }
2405 
2406 MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted) const
2407 {
2408  if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())
2409  return MELEE_HIT_EVADE;
2410 
2411  int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim);
2412  int32 victimMaxSkillValueForLevel = victim->GetMaxSkillValueForLevel(this);
2413 
2414  int32 attackerWeaponSkill = GetWeaponSkillValue(attType, victim);
2415  int32 victimDefenseSkill = victim->GetDefenseSkillValue(this);
2416 
2417  // bonus from skills is 0.04%
2418  int32 skillBonus = 4 * (attackerWeaponSkill - victimMaxSkillValueForLevel);
2419  int32 skillBonus2 = 4 * (attackerMaxSkillValueForLevel - victimDefenseSkill);
2420  int32 sum = 0, tmp = 0;
2421  int32 roll = urand (0, 10000);
2422 
2423  DEBUG_LOG ("RollMeleeOutcomeAgainst: skill bonus of %d for attacker", skillBonus);
2424  DEBUG_LOG ("RollMeleeOutcomeAgainst: rolled %d, miss %d, dodge %d, parry %d, block %d, crit %d",
2425  roll, miss_chance, dodge_chance, parry_chance, block_chance, crit_chance);
2426 
2427  tmp = miss_chance;
2428 
2429  if (tmp > 0 && roll < (sum += tmp))
2430  {
2431  DEBUG_LOG ("RollMeleeOutcomeAgainst: MISS");
2432  return MELEE_HIT_MISS;
2433  }
2434 
2435  // always crit against a sitting target (except 0 crit chance)
2436  if (victim->GetTypeId() == TYPEID_PLAYER && crit_chance > 0 && !victim->IsStandState())
2437  {
2438  DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT (sitting victim)");
2439  return MELEE_HIT_CRIT;
2440  }
2441 
2442  // Dodge chance
2443 
2444  // only players can't dodge if attacker is behind
2445  if (victim->GetTypeId() == TYPEID_PLAYER && !victim->HasInArc(float(M_PI), this))
2446  DEBUG_LOG ("RollMeleeOutcomeAgainst: attack came from behind and victim was a player.");
2447  else
2448  {
2449  // Reduce dodge chance by attacker expertise rating
2450  if (GetTypeId() == TYPEID_PLAYER)
2451  dodge_chance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100);
2452  else
2453  dodge_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
2454 
2455  // Modify dodge chance by attacker SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
2457  dodge_chance = int32 (float (dodge_chance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
2458 
2459  tmp = dodge_chance;
2460  if ((tmp > 0) // check if unit _can_ dodge
2461  && ((tmp -= skillBonus) > 0)
2462  && roll < (sum += tmp))
2463  {
2464  DEBUG_LOG ("RollMeleeOutcomeAgainst: DODGE <%d, %d)", sum - tmp, sum);
2465  return MELEE_HIT_DODGE;
2466  }
2467  }
2468 
2469  // parry & block chances
2470 
2471  // check if attack comes from behind, nobody can parry or block if attacker is behind
2472  if (!victim->HasInArc(float(M_PI), this))
2473  DEBUG_LOG ("RollMeleeOutcomeAgainst: attack came from behind.");
2474  else
2475  {
2476  // Reduce parry chance by attacker expertise rating
2477  if (GetTypeId() == TYPEID_PLAYER)
2478  parry_chance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100);
2479  else
2480  parry_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
2481 
2483  {
2484  int32 tmp2 = int32(parry_chance);
2485  if (tmp2 > 0 // check if unit _can_ parry
2486  && (tmp2 -= skillBonus) > 0
2487  && roll < (sum += tmp2))
2488  {
2489  DEBUG_LOG ("RollMeleeOutcomeAgainst: PARRY <%d, %d)", sum - tmp2, sum);
2490  return MELEE_HIT_PARRY;
2491  }
2492  }
2493 
2495  {
2496  tmp = block_chance;
2497  if (tmp > 0 // check if unit _can_ block
2498  && (tmp -= skillBonus) > 0
2499  && roll < (sum += tmp))
2500  {
2501  // Critical chance
2502  tmp = crit_chance + skillBonus2;
2503  if (GetTypeId() == TYPEID_PLAYER && SpellCasted && tmp > 0)
2504  {
2505  if (roll_chance_i(tmp / 100))
2506  {
2507  DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCKED CRIT");
2508  return MELEE_HIT_BLOCK_CRIT;
2509  }
2510  }
2511  DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCK <%d, %d)", sum - tmp, sum);
2512  return MELEE_HIT_BLOCK;
2513  }
2514  }
2515  }
2516 
2517  // Critical chance
2518  tmp = crit_chance + skillBonus2;
2519 
2520  if (tmp > 0 && roll < (sum += tmp))
2521  {
2522  DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT <%d, %d)", sum - tmp, sum);
2524  DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT DISABLED)");
2525  else
2526  return MELEE_HIT_CRIT;
2527  }
2528 
2529  // Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon)
2530  if (attType != RANGED_ATTACK && !SpellCasted &&
2531  (GetTypeId() == TYPEID_PLAYER || IsPet()) &&
2532  victim->GetTypeId() != TYPEID_PLAYER && !victim->IsPet() &&
2533  getLevel() < victim->getLevelForTarget(this))
2534  {
2535  // cap possible value (with bonuses > max skill)
2536  int32 skill = attackerWeaponSkill;
2537  int32 maxskill = attackerMaxSkillValueForLevel;
2538  skill = (skill > maxskill) ? maxskill : skill;
2539 
2540  tmp = (10 + (victimDefenseSkill - skill)) * 100;
2541  tmp = tmp > 4000 ? 4000 : tmp;
2542  if (roll < (sum += tmp))
2543  {
2544  DEBUG_LOG ("RollMeleeOutcomeAgainst: GLANCING <%d, %d)", sum - 4000, sum);
2545  return MELEE_HIT_GLANCING;
2546  }
2547  }
2548 
2549  // mobs can only score crushing blows with autoattack
2550  if (!SpellCasted && !IsControlledByPlayer() &&
2552  {
2553  // when their weapon skill is 15 or more above victim's defense skill
2554  tmp = victimDefenseSkill;
2555  int32 tmpmax = victimMaxSkillValueForLevel;
2556  // having defense above your maximum (from items, talents etc.) has no effect
2557  tmp = tmp > tmpmax ? tmpmax : tmp;
2558  // tmp = mob's level * 5 - player's current defense skill
2559  tmp = attackerMaxSkillValueForLevel - tmp;
2560  if (tmp >= 15)
2561  {
2562  // add 2% chance per lacking skill point, min. is 15%
2563  tmp = tmp * 200 - 1500;
2564  if (roll < (sum += tmp))
2565  {
2566  DEBUG_LOG ("RollMeleeOutcomeAgainst: CRUSHING <%d, %d)", sum - tmp, sum);
2567  return MELEE_HIT_CRUSHING;
2568  }
2569  }
2570  }
2571 
2572  DEBUG_LOG ("RollMeleeOutcomeAgainst: NORMAL");
2573  return MELEE_HIT_NORMAL;
2574 }
2575 
2576 uint32 Unit::CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct)
2577 {
2578  float minDamage = 0.0f;
2579  float maxDamage = 0.0f;
2580 
2581  if (normalized && GetTypeId() == TYPEID_PLAYER)
2582  ToPlayer()->CalculateMinMaxDamage(attType, normalized, addTotalPct, minDamage, maxDamage);
2583  else
2584  {
2585  switch (attType)
2586  {
2587  case RANGED_ATTACK:
2590  break;
2591  case BASE_ATTACK:
2592  minDamage = GetFloatValue(UNIT_FIELD_MINDAMAGE);
2593  maxDamage = GetFloatValue(UNIT_FIELD_MAXDAMAGE);
2594  break;
2595  case OFF_ATTACK:
2598  break;
2599  default:
2600  break;
2601  }
2602  }
2603 
2604  minDamage = std::max(0.f, minDamage);
2605  maxDamage = std::max(0.f, maxDamage);
2606 
2607  if (minDamage > maxDamage)
2608  std::swap(minDamage, maxDamage);
2609 
2610  if (maxDamage == 0.0f)
2611  maxDamage = 5.0f;
2612 
2613  return urand(uint32(minDamage), uint32(maxDamage));
2614 }
2615 
2616 float Unit::CalculateLevelPenalty(SpellEntry const* spellProto) const
2617 {
2618  if (spellProto->spellLevel <= 0 || spellProto->spellLevel >= spellProto->maxLevel)
2619  return 1.0f;
2620 
2621  float LvlPenalty = 0.0f;
2622 
2623  if (spellProto->spellLevel < 20)
2624  LvlPenalty = (20.0f - spellProto->spellLevel) * 3.75f;
2625 
2626  float LvlFactor = (float(spellProto->spellLevel) + 6.0f) / float(getLevel());
2627  if (LvlFactor > 1.0f)
2628  LvlFactor = 1.0f;
2629 
2630  return (100.0f - LvlPenalty) * LvlFactor / 100.0f;
2631 }
2632 
2634 {
2635  WorldPacket data(SMSG_ATTACKSTART, 8 + 8);
2636  data << uint64(GetGUID());
2637  data << uint64(victim->GetGUID());
2638  SendMessageToSet(&data, true);
2639  DEBUG_LOG("WORLD: Sent SMSG_ATTACKSTART");
2640 }
2641 
2643 {
2644  WorldPacket data(SMSG_ATTACKSTOP, (8+8+4));
2645  data << GetPackGUID();
2646  if (victim)
2647  data << victim->GetPackGUID();
2648  else
2649  data << uint8(0);
2650 
2651  data << uint32(0);
2652  SendMessageToSet(&data, true);
2653  sLog.outDebug("WORLD: Sent SMSG_ATTACKSTOP");
2654 
2655  if (victim)
2656  sLog.outDetail("%s %u stopped attacking %s %u", (GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), GetGUIDLow(), (victim->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), victim->GetGUIDLow());
2657  else
2658  sLog.outDetail("%s %u stopped attacking", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow());
2659 }
2660 
2661 bool Unit::isSpellBlocked(Unit* victim, SpellEntry const* spellProto, WeaponAttackType attackType)
2662 {
2663  // These spells can't be blocked
2664  if (spellProto && spellProto->Attributes & SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK)
2665  return false;
2666 
2667  if (victim->HasInArc(float(M_PI), this))
2668  {
2669  // Check creatures flags_extra for disable block
2670  if (victim->GetTypeId() == TYPEID_UNIT &&
2672  return false;
2673 
2674  float blockChance = victim->GetUnitBlockChance();
2675 
2676  float fAttackerSkill = GetWeaponSkillValue(attackType, victim) * 0.04f;
2677  float fDefenserSkill = victim->GetDefenseSkillValue(this) * 0.04f;
2678 
2679  blockChance += (fDefenserSkill - fAttackerSkill);
2680  if (blockChance < 0.0)
2681  blockChance = 0.0;
2682 
2683  if (roll_chance_f(blockChance))
2684  return true;
2685  }
2686  return false;
2687 }
2688 
2689 // Melee based spells can be miss, parry or dodge on this step
2690 // Crit or block - determined on damage calculation phase! (and can be both in some time)
2691 float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
2692 {
2693  // Calculate hit chance (more correct for chance mod)
2694  float HitChance = 0.0f;
2695 
2696  // PvP - PvE melee chances
2697  if (victim->GetTypeId() == TYPEID_PLAYER)
2698  HitChance = 95.0f + skillDiff * 0.04f;
2699  else if (skillDiff < -10)
2700  HitChance = 93.0f + (skillDiff + 10) * 0.4f; // 7% base chance to miss for big skill diff (%6 in 3.x)
2701  else
2702  HitChance = 95.0f + skillDiff * 0.1f;
2703 
2704  // Hit chance depends from victim auras
2705  if (attType == RANGED_ATTACK)
2707  else
2709 
2710  // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
2711  if (spellId)
2712  {
2713  if (Player* modOwner = GetSpellModOwner())
2714  modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, HitChance);
2715  }
2716 
2717  // Miss = 100 - hit
2718  float miss_chance = 100.0f - HitChance;
2719 
2720  // Bonuses from attacker aura and ratings
2721  if (attType == RANGED_ATTACK)
2722  miss_chance -= m_modRangedHitChance;
2723  else
2724  miss_chance -= m_modMeleeHitChance;
2725 
2726  // bonus from skills is 0.04%
2727  //miss_chance -= skillDiff * 0.04f;
2728  int32 diff = -skillDiff;
2729  if (victim->GetTypeId() == TYPEID_PLAYER)
2730  miss_chance += diff > 0 ? diff * 0.04 : diff * 0.02;
2731  else
2732  miss_chance += diff > 10 ? 2 + (diff - 10) * 0.4 : diff * 0.1;
2733 
2734  // Limit miss chance from 0 to 60%
2735  if (miss_chance < 0.0f)
2736  return 0.0f;
2737  if (miss_chance > 60.0f)
2738  return 60.0f;
2739  return miss_chance;
2740 }
2741 
2743 {
2744  if (!spellInfo)
2745  return 0;
2746 
2747  int32 resistMech = 0;
2748  for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff)
2749  {
2750  if (spellInfo->Effect[eff] == 0)
2751  break;
2752 
2753  int32 effectMech = GetEffectMechanic(spellInfo, eff);
2754  if (effectMech)
2755  {
2757  if (resistMech < temp)
2758  resistMech = temp;
2759  }
2760  }
2761  return resistMech;
2762 }
2763 
2764 bool Unit::CanUseAttackType(uint8 attacktype) const
2765 {
2766  switch (attacktype)
2767  {
2768  case BASE_ATTACK:
2770  /* @todo Implement unit flags 2 properly
2771  case OFF_ATTACK:
2772  return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_OFFHAND);
2773  case RANGED_ATTACK:
2774  return !HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_DISARM_RANGED);*/
2775  default:
2776  return true;
2777  }
2778 }
2779 
2780 // Melee based spells hit result calculations
2781 SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellEntry const* spellInfo, bool cMiss)
2782 {
2783  // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will additionally fully ignore
2784  // resist and deflect chances
2785  if (spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_MISS)
2786  return SPELL_MISS_NONE;
2787 
2788  WeaponAttackType attType = BASE_ATTACK;
2789 
2790  // Check damage class instead of attack type to correctly handle judgements
2791  // - they are meele, but can't be dodged/parried/deflected because of ranged dmg class
2792  if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
2793  attType = RANGED_ATTACK;
2794 
2795  int32 attackerWeaponSkill;
2796  // skill value for these spells (for example judgements) is 5* level
2797  if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED && !(spellInfo->Attributes & SPELL_ATTR0_RANGED))
2798  attackerWeaponSkill = getLevel() * 5;
2799  // bonus from skills is 0.04% per skill Diff
2800  else
2801  attackerWeaponSkill = int32(GetWeaponSkillValue(attType, victim));
2802 
2803  int32 skillDiff = attackerWeaponSkill - int32(victim->GetMaxSkillValueForLevel(this));
2804  int32 fullSkillDiff = attackerWeaponSkill - int32(victim->GetDefenseSkillValue(this));
2805 
2806  uint32 roll = urand (0, 10000);
2807  uint32 tmp = 0;
2808 
2809  bool canDodge = true;
2810  bool canParry = true;
2811  bool canBlock = (spellInfo->AttributesEx3 & SPELL_ATTR3_CAN_BE_BLOCKED) != 0;
2812  bool canMiss = !(spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_MISS) && cMiss;
2813 
2814  if (canMiss)
2815  {
2816  uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, fullSkillDiff, spellInfo->Id) * 100.0f);
2817  // Roll miss
2818  tmp += missChance;
2819  if (roll < tmp)
2820  return SPELL_MISS_MISS;
2821  }
2822 
2823  // Chance resist mechanic
2824  int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100;
2825  tmp += resist_chance;
2826  if (roll < tmp)
2827  return SPELL_MISS_RESIST;
2828 
2829  // @XXX: Tidal Charm: Increased chance to be resisted when used against targets over level 60.
2830  if (spellInfo->Id == 835)
2831  {
2832  if (victim->getLevel() > 60)
2833  {
2834  uint32 tmp = victim->getLevel();
2835  uint32 rand = urand(60, 160);
2836 
2837  if (rand > tmp)
2838  return SPELL_MISS_RESIST;
2839  }
2840  }
2841 
2842  // Ranged attack can`t miss too
2843  if (attType == RANGED_ATTACK)
2844  return SPELL_MISS_NONE;
2845 
2846  // Some spells cannot be parry/dodge
2848  return SPELL_MISS_NONE;
2849 
2850  // Check for attack from behind
2851  // This is the only Dodge/Block check that can't be done from behind
2852  // based on unit type.
2853  if (!victim->HasInArc(float(M_PI), this))
2854  {
2855  // Can`t dodge from behind in PvP (but its possible in PvE)
2856  if (victim->GetTypeId() == TYPEID_PLAYER)
2857  canDodge = false;
2858  // Can`t parry
2859  canParry = false;
2860  // Can't block from behind in PvE (but its possible in PvP)
2861  if (victim->GetTypeId() == TYPEID_UNIT)
2862  canBlock = false;
2863  }
2864 
2865  // Check creatures flags_extra for disable parry
2866  if (victim->GetTypeId() == TYPEID_UNIT)
2867  {
2868  uint32 flagEx = victim->ToCreature()->GetCreatureTemplate()->flags_extra;
2869  if (flagEx & CREATURE_FLAG_EXTRA_NO_PARRY)
2870  canParry = false;
2871  // Check creatures flags_extra for disable block
2872  if (flagEx & CREATURE_FLAG_EXTRA_NO_BLOCK)
2873  canBlock = false;
2874  }
2875 
2876  // Ignore combat result aura
2877  AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
2878  for (AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i)
2879  {
2880  switch ((*i)->GetMiscValue())
2881  {
2882  case MELEE_HIT_DODGE:
2883  canDodge = false;
2884  break;
2885  case MELEE_HIT_BLOCK:
2886  canBlock = false;
2887  break;
2888  case MELEE_HIT_PARRY:
2889  canParry = false;
2890  break;
2891  default:
2892  DEBUG_LOG("Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT has unhandled state %d", (*i)->GetId(), (*i)->GetMiscValue());
2893  break;
2894  }
2895  }
2896 
2897  if (canDodge)
2898  {
2899  // Roll dodge
2900  int32 dodgeChance = int32(victim->GetUnitDodgeChance() * 100.0f) - skillDiff * 4;
2901  // Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
2903  dodgeChance = int32(float(dodgeChance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE));
2904  // Reduce dodge chance by attacker expertise rating
2905  if (GetTypeId() == TYPEID_PLAYER)
2906  dodgeChance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
2907  else
2908  dodgeChance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
2909  if (dodgeChance < 0)
2910  dodgeChance = 0;
2911 
2912  if (roll < (tmp += dodgeChance))
2913  return SPELL_MISS_DODGE;
2914  }
2915 
2916  if (canParry)
2917  {
2918  // Roll parry
2919  int32 parryChance = int32(victim->GetUnitParryChance() * 100.0f) - skillDiff * 4;
2920  // Reduce parry chance by attacker expertise rating
2921  if (GetTypeId() == TYPEID_PLAYER)
2922  parryChance -= int32(ToPlayer()->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
2923  else
2924  parryChance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE) * 25;
2925  if (parryChance < 0)
2926  parryChance = 0;
2927 
2928  tmp += parryChance;
2929  if (roll < tmp)
2930  return SPELL_MISS_PARRY;
2931  }
2932 
2933  if (canBlock)
2934  {
2935  int32 blockChance = int32(victim->GetUnitBlockChance() * 100.0f) - skillDiff * 4;
2936  if (blockChance < 0)
2937  blockChance = 0;
2938  tmp += blockChance;
2939 
2940  if (roll < tmp)
2941  return SPELL_MISS_BLOCK;
2942  }
2943 
2944  return SPELL_MISS_NONE;
2945 }
2946 
2949 {
2950  // Can`t miss on dead target (on skinning for example)
2951  if ((!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER) || spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_MISS)
2952  return SPELL_MISS_NONE;
2953 
2954  SpellSchoolMask schoolMask = GetSpellSchoolMask(spellInfo);
2955  // PvP - PvE spell misschances per leveldif > 2
2956  int32 lchance = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
2957  int32 thisLevel = getLevelForTarget(victim);
2958  if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger())
2959  thisLevel = std::max<int32>(thisLevel, spellInfo->spellLevel);
2960  int32 leveldif = int32(victim->getLevelForTarget(this)) - thisLevel;
2961 
2962  // Base hit chance from attacker and victim levels
2963  int32 modHitChance;
2964  if (leveldif < 3)
2965  modHitChance = 96 - leveldif;
2966  else
2967  modHitChance = 94 - (leveldif - 2) * lchance;
2968 
2969  // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
2970  if (Player* modOwner = GetSpellModOwner())
2971  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
2972 
2973  // Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras
2975 
2976  // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
2977  modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
2978  // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura
2979  if (IsAreaOfEffectSpell(spellInfo))
2980  modHitChance -= victim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE);
2981 
2982  // Decrease hit chance from victim rating bonus
2983  if (victim->GetTypeId() == TYPEID_PLAYER)
2984  modHitChance -= int32(victim->ToPlayer()->GetRatingBonusValue(CR_HIT_TAKEN_SPELL));
2985 
2986  // Reduce spell hit chance for dispel mechanic spells from victim SPELL_AURA_MOD_DISPEL_RESIST
2987  if (IsDispelSpell(spellInfo))
2988  modHitChance -= victim->GetTotalAuraModifier(SPELL_AURA_MOD_DISPEL_RESIST);
2989 
2990  // Chance resist mechanic (select max value from every mechanic spell effect)
2991  int32 resist_chance = victim->GetMechanicResistChance(spellInfo);
2992  // Apply mod
2993  modHitChance -= resist_chance;
2994 
2995  // Chance resist debuff
2996  modHitChance -= victim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spellInfo->Dispel));
2997 
2998  int32 HitChance = modHitChance * 100;
2999  // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
3000  HitChance += int32(m_modSpellHitChance * 100.0f);
3001 
3002  if (HitChance < 100) HitChance = 100;
3003  if (HitChance > 9900) HitChance = 9900;
3004 
3005  int32 rand = irand(0, 10000);
3006  if (rand > HitChance)
3007  return SPELL_MISS_RESIST;
3008 
3010  {
3011  const bool binary = IsBinarySpell(spellInfo);
3012  const float mitigation = victim->CalculateMagicResistanceMitigation(this, victim->CalculateEffectiveMagicResistance(this, schoolMask), binary);
3013  // Calculate full resist chance
3014  const uint32 chance = binary ? uint32(mitigation * 10000) : SPELL_PARTIAL_RESIST_DISTRIBUTION.at(uint32(mitigation * 10000)).at(SPELL_PARTIAL_RESIST_PCT_100);
3015  // Do a roll for full resist chance
3016  if (urand(0,9999) < chance)
3017  return SPELL_MISS_RESIST;
3018  }
3019 
3020  return SPELL_MISS_NONE;
3021 }
3022 
3023 // Calculate spell hit result can be:
3024 // Every spell can: Evade/Immune/Reflect/Sucesful hit
3025 // For melee based spells:
3026 // Miss
3027 // Dodge
3028 // Parry
3029 // For spells
3030 // Resist
3031 SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellEntry const* spell, bool CanReflect, bool canMiss)
3032 {
3033  // Check for immune (use charges)
3034  if (victim->IsImmuneToSpell(spell, true))
3035  return SPELL_MISS_IMMUNE;
3036 
3037  // All positive spells can`t miss
3038  // @todo client not show miss log for this spells - so need find info for this in dbc and use it!
3039  if (IsPositiveSpell(spell->Id) && !IsHostileTo(victim)) //prevent from affecting enemy by "positive" spell
3040  return SPELL_MISS_NONE;
3041 
3042  // Check for immune
3043  if (victim->IsImmunedToDamage(spell))
3044  return SPELL_MISS_IMMUNE;
3045 
3046  if (this == victim)
3047  return SPELL_MISS_NONE;
3048 
3049  // Return evade for units in evade mode
3050  if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode() && this != victim)
3051  return SPELL_MISS_EVADE;
3052 
3053  // Try victim reflect spell
3054  if (CanReflect)
3055  {
3056  int32 reflectchance = victim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS);
3057  Unit::AuraList const& mReflectSpellsSchool = victim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL);
3058  for (Unit::AuraList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i)
3059  if ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spell))
3060  reflectchance = (*i)->GetModifierValue();
3061  if (reflectchance > 0 && roll_chance_i(reflectchance))
3062  {
3063  // Start triggers for remove charges if need (trigger only for victim, and mark as active spell)
3065  return SPELL_MISS_REFLECT;
3066  }
3067  }
3068 
3069  switch (spell->DmgClass)
3070  {
3073  return MeleeSpellHitResult(victim, spell, canMiss);
3075  return SPELL_MISS_NONE;
3077  return MagicSpellHitResult(victim, spell);
3078  }
3079  return SPELL_MISS_NONE;
3080 }
3081 
3082 float Unit::MeleeMissChanceCalc(const Unit* victim, WeaponAttackType attType) const
3083 {
3084  if (!victim)
3085  return 0.0f;
3086 
3087  // Base misschance 5%
3088  float missChance = 5.0f;
3089 
3090  // DualWield - white damage has additional 19% miss penalty
3091  if (haveOffhandWeapon() && attType != RANGED_ATTACK)
3092  {
3093  bool isNormal = false;
3095  {
3097  {
3098  isNormal = true;
3099  break;
3100  }
3101  }
3102  if (!isNormal && !m_currentSpells[CURRENT_MELEE_SPELL])
3103  missChance += 19.0f;
3104  }
3105 
3106  int32 skillDiff = int32(GetWeaponSkillValue(attType, victim)) - int32(victim->GetDefenseSkillValue(this));
3107 
3108  // PvP - PvE melee chances
3109  if ( victim->GetTypeId() == TYPEID_PLAYER )
3110  missChance -= skillDiff * 0.04f;
3111  else if ( skillDiff < -10 )
3112  missChance -= (skillDiff + 10) * 0.4f - 2.0f; // 7% base chance to miss for big skill diff (%6 in 3.x)
3113  else
3114  missChance -= skillDiff * 0.1f;
3115 
3116  // Hit chance bonus from attacker based on ratings and auras
3117  if (attType == RANGED_ATTACK)
3118  missChance -= m_modRangedHitChance;
3119  else
3120  missChance -= m_modMeleeHitChance;
3121 
3122  // Hit chance for victim based on ratings
3123  if (victim->GetTypeId() == TYPEID_PLAYER)
3124  {
3125  if (attType == RANGED_ATTACK)
3126  missChance += ((Player*)victim)->GetRatingBonusValue(CR_HIT_TAKEN_RANGED);
3127  else
3128  missChance += ((Player*)victim)->GetRatingBonusValue(CR_HIT_TAKEN_MELEE);
3129  }
3130 
3131  // Modify miss chance by victim auras
3132  if (attType == RANGED_ATTACK)
3134  else
3136 
3137  // Limit miss chance from 0 to 60%
3138  if (missChance < 0.0f)
3139  return 0.0f;
3140  if (missChance > 60.0f)
3141  return 60.0f;
3142 
3143  return missChance;
3144 }
3145 
3147 {
3148  if (GetTypeId() == TYPEID_PLAYER)
3149  {
3150  // in PvP use full skill instead current skill value
3151  uint32 value = (target && target->GetTypeId() == TYPEID_PLAYER)
3154  value += uint32(ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL));
3155  return value;
3156  }
3157  else
3158  return GetUnitMeleeSkill(target);
3159 }
3160 
3162 {
3164  return 0.0f;
3165 
3166  if (GetTypeId() == TYPEID_PLAYER)
3168  else
3169  {
3170  if (IsTotem())
3171  return 0.0f;
3172  else
3173  {
3174  float dodge = 5.0f;
3176  return dodge > 0.0f ? dodge : 0.0f;
3177  }
3178  }
3179 }
3180 
3182 {
3184  return 0.0f;
3185 
3186  float chance = 0.0f;
3187 
3188  if (GetTypeId() == TYPEID_PLAYER)
3189  {
3190  Player const* player = (Player const*)this;
3191  if (player->CanParry())
3192  {
3193  Item* tmpitem = player->GetWeaponForAttack(BASE_ATTACK, true);
3194  if (!tmpitem)
3195  tmpitem = player->GetWeaponForAttack(OFF_ATTACK, true);
3196 
3197  if (tmpitem)
3199  }
3200  }
3201  else if (GetTypeId() == TYPEID_UNIT)
3202  {
3204  {
3205  chance = 5.0f;
3207  }
3208  }
3209 
3210  return chance > 0.0f ? chance : 0.0f;
3211 }
3212 
3214 {
3216  return 0.0f;
3217 
3218  if (GetTypeId() == TYPEID_PLAYER)
3219  {
3220  Player const* player = (Player const*)this;
3221  if (player->CanBlock())
3222  {
3224  if (tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block)
3226  }
3227  // is player but has no block ability or no not broken shield equipped
3228  return 0.0f;
3229  }
3230  else
3231  {
3232  if (IsTotem())
3233  return 0.0f;
3234  else
3235  {
3236  float block = 5.0f;
3238  return block > 0.0f ? block : 0.0f;
3239  }
3240  }
3241 }
3242 
3243 float Unit::GetUnitCriticalChance(WeaponAttackType attackType, const Unit* victim) const
3244 {
3245  float crit;
3246 
3247  if (GetTypeId() == TYPEID_PLAYER)
3248  {
3249  switch (attackType)
3250  {
3251  case BASE_ATTACK:
3253  break;
3254  case OFF_ATTACK:
3256  break;
3257  case RANGED_ATTACK:
3259  break;
3260  // Just for good manner
3261  default:
3262  crit = 0.0f;
3263  break;
3264  }
3265  }
3266  else
3267  {
3268  crit = 5.0f;
3270  }
3271 
3272  // flat aura mods
3273  if (attackType == RANGED_ATTACK)
3275  else
3277 
3279 
3280  // reduce crit chance from Rating for players
3281  if (victim->GetTypeId() == TYPEID_PLAYER)
3282  {
3283  if (attackType == RANGED_ATTACK)
3285  else
3286  crit -= victim->ToPlayer()->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE);
3287  }
3288 
3289  if (crit < 0.0f)
3290  crit = 0.0f;
3291  return crit;
3292 }
3293 
3295 {
3296  uint32 value = 0;
3297  if (GetTypeId() == TYPEID_PLAYER)
3298  {
3299  Item* item = ToPlayer()->GetWeaponForAttack(attType, true);
3300 
3301  // feral or unarmed skill only for base attack
3302  if (attType != BASE_ATTACK && !item)
3303  {
3304  if (attType == RANGED_ATTACK && getClass() == CLASS_PALADIN) //hammer
3305  return GetMaxSkillValueForLevel();
3306  return 0;
3307  }
3308 
3309  if (IsInFeralForm())
3310  return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact
3311 
3312  // weapon skill or (unarmed for base attack and fist weapons)
3313  uint32 skill = item && item->GetSkill() != SKILL_FIST_WEAPONS ? item->GetSkill() : uint32(SKILL_UNARMED);
3314 
3315  // in PvP use full skill instead current skill value
3316  value = (target && target->IsCharmedOwnedByPlayerOrPlayer())
3317  ? ToPlayer()->GetMaxSkillValue(skill)
3318  : ToPlayer()->GetSkillValue(skill);
3319  // Modify value from ratings
3320  value += uint32(ToPlayer()->GetRatingBonusValue(CR_WEAPON_SKILL));
3321  switch (attType)
3322  {
3323  case BASE_ATTACK: value += uint32(ToPlayer()->GetRatingBonusValue(CR_WEAPON_SKILL_MAINHAND)); break;
3324  case OFF_ATTACK: value += uint32(ToPlayer()->GetRatingBonusValue(CR_WEAPON_SKILL_OFFHAND)); break;
3325  case RANGED_ATTACK: value += uint32(ToPlayer()->GetRatingBonusValue(CR_WEAPON_SKILL_RANGED)); break;
3326  default: break;
3327  }
3328  }
3329  else
3330  value = GetUnitMeleeSkill(target);
3331  return value;
3332 }
3333 
3335 {
3336  while (!m_removedAuras.empty())
3337  {
3338  delete m_removedAuras.front();
3339  m_removedAuras.pop_front();
3340  }
3341 }
3342 
3344 {
3347 
3348  // remove finished spells from current pointers
3349  for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
3350  {
3351  if (m_currentSpells[i] && m_currentSpells[i]->getState() == SPELL_STATE_FINISHED)
3352  {
3354  m_currentSpells[i] = NULL; // remove pointer
3355  }
3356  }
3357 
3358  // m_AurasUpdateIterator can be updated in inderect called code at aura remove to skip next planned to update but removed auras
3359  for (m_AurasUpdateIterator = m_Auras.begin(); m_AurasUpdateIterator != m_Auras.end();)
3360  {
3361  Aura* i_aura = m_AurasUpdateIterator->second;
3362  ++m_AurasUpdateIterator; // need shift to next for allow update if need into aura update
3363  i_aura->Update(time);
3364  }
3365 
3366  // remove expired auras
3367  for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end();)
3368  {
3369  if (i->second->IsExpired())
3371  else
3372  ++i;
3373  }
3374 
3375  _DeleteAuras();
3376 
3377  if (!m_gameObj.empty())
3378  {
3379  std::list<GameObject*>::iterator itr;
3380  for (itr = m_gameObj.begin(); itr != m_gameObj.end();)
3381  {
3382  if (!(*itr)->isSpawned())
3383  {
3384  (*itr)->SetOwnerGUID(0);
3385  (*itr)->SetRespawnTime(0);
3386  (*itr)->Delete();
3387  m_gameObj.erase(itr++);
3388  }
3389  else
3390  ++itr;
3391  }
3392  }
3393 }
3394 
3396 {
3397  //check "realtime" interrupts
3398  if ((GetTypeId() == TYPEID_PLAYER && isMoving()) || IsNonMeleeSpellCast(false, false, true))
3399  {
3400  // cancel wand shoot
3401  if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351)
3403  m_AutoRepeatFirstCast = true;
3404  return;
3405  }
3406 
3407  // apply delay (Auto Shot (spellID 75) not affected)
3410  m_AutoRepeatFirstCast = false;
3411 
3412  //castroutine
3414  {
3415  // Check if able to cast
3416  if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CheckCast(true) != SPELL_CAST_OK)
3417  {
3419  return;
3420  }
3421 
3422  // we want to shoot
3423  Spell* spell = new Spell(this, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo, true, 0);
3424  spell->prepare(&(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets));
3425 
3426  // all went good, reset attack
3428  }
3429 }
3430 
3432 {
3433  ASSERT(pSpell); // NULL may be never passed here, use InterruptSpell or InterruptNonMeleeSpells
3434 
3435  CurrentSpellTypes CSpellType = pSpell->GetCurrentContainer();
3436 
3437  if (pSpell == m_currentSpells[CSpellType]) // avoid breaking self
3438  return;
3439 
3440  // break same type spell if it is not delayed
3441  InterruptSpell(CSpellType, false);
3442 
3443  // special breakage effects:
3444  switch (CSpellType)
3445  {
3446  case CURRENT_GENERIC_SPELL:
3447  {
3448  // generic spells always break channeled not delayed spells
3450 
3451  // autorepeat breaking
3453  {
3454  // break autorepeat if not Auto Shot
3455  if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351)
3456  InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
3457  m_AutoRepeatFirstCast = true;
3458  }
3459  if (pSpell->GetCastTime() > 0)
3461 
3462  break;
3463  }
3465  {
3466  // channel spells always break generic non-delayed and any channeled spells
3469 
3470  // it also does break autorepeat if not Auto Shot
3472  m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351)
3475 
3476  break;
3477  }
3479  {
3480  // only Auto Shoot does not break anything
3481  if (pSpell->m_spellInfo->Category == 351)
3482  {
3483  // generic autorepeats break generic non-delayed and channeled non-delayed spells
3486  }
3487  // special action: set first cast flag
3488  m_AutoRepeatFirstCast = true;
3489 
3490  break;
3491  }
3492  default:
3493  break; // other spell types don't break anything now
3494  }
3495 
3496  // current spell (if it is still here) may be safely deleted now
3497  if (m_currentSpells[CSpellType])
3498  m_currentSpells[CSpellType]->SetReferencedFromCurrent(false);
3499 
3500  // set new current spell
3501  m_currentSpells[CSpellType] = pSpell;
3502  pSpell->SetReferencedFromCurrent(true);
3503 
3504  pSpell->m_selfContainer = &(m_currentSpells[pSpell->GetCurrentContainer()]);
3505 }
3506 
3507 void Unit::InterruptSpell(CurrentSpellTypes spellType, bool withDelayed, bool withInstant)
3508 {
3509  Spell* spell = m_currentSpells[spellType];
3510  if (spell
3511  && (withDelayed || spell->getState() != SPELL_STATE_DELAYED)
3512  && (withInstant || spell->GetCastTime() > 0 || spell->getState() == SPELL_STATE_CASTING))
3513  {
3514  // for example, do not let self-stun aura interrupt itself
3515  if (!spell->IsInterruptable())
3516  return;
3517 
3518  m_currentSpells[spellType] = NULL;
3519 
3520  // send autorepeat cancel message for autorepeat spells
3521  if (spellType == CURRENT_AUTOREPEAT_SPELL)
3522  if (GetTypeId() == TYPEID_PLAYER)
3524 
3525  if (spell->getState() != SPELL_STATE_FINISHED)
3526  spell->cancel(true);
3527  else
3528  {
3529  m_currentSpells[spellType] = nullptr;
3530  spell->SetReferencedFromCurrent(false);
3531  }
3532  }
3533 }
3534 
3535 void Unit::FinishSpell(CurrentSpellTypes spellType, bool ok /*= true*/)
3536 {
3537  Spell* spell = m_currentSpells[spellType];
3538  if (!spell)
3539  return;
3540 
3541  if (spellType == CURRENT_CHANNELED_SPELL)
3542  spell->SendChannelUpdate(0);
3543 
3544  spell->finish(ok);
3545 }
3546 
3547 bool Unit::IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled, bool skipAutorepeat) const
3548 {
3549  // We don't do loop here to explicitly show that melee spell is excluded.
3550  // Maybe later some special spells will be excluded too.
3551 
3552  // generic spells are casted when they are not finished and not delayed
3555  (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED))
3556  {
3557  if (!(m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS))
3558  return (true);
3559  }
3560 
3561  // channeled spells may be delayed, but they are still considered casted
3562  else if (!skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] &&
3564  {
3565  if (!(m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS))
3566  return (true);
3567  }
3568 
3569  // autorepeat spells may be finished or delayed, but they are still considered casted
3570  else if (!skipAutorepeat && m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
3571  return (true);
3572 
3573  return (false);
3574 }
3575 
3576 void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id, bool withInstant)
3577 {
3578  // generic spells are interrupted if they are not finished or delayed
3579  if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id == spell_id))
3580  InterruptSpell(CURRENT_GENERIC_SPELL, withDelayed, withInstant);
3581 
3582  // autorepeat spells are interrupted if they are not finished or delayed
3583  if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == spell_id))
3584  InterruptSpell(CURRENT_AUTOREPEAT_SPELL, withDelayed, withInstant);
3585 
3586  // channeled spells are interrupted if they are not finished, even if they are delayed
3587  if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id == spell_id))
3589 }
3590 
3592 {
3593  for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
3594  if (m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id == spell_id)
3595  return m_currentSpells[i];
3596  return NULL;
3597 }
3598 
3600 {
3601  if (Spell const* spell = FindCurrentSpellBySpellId(spell_id))
3602  return spell->GetCastTime();
3603  return 0;
3604 }
3605 
3607 {
3609  if (spell->getState() != SPELL_STATE_FINISHED)
3610  return spell->m_spellInfo->AttributesEx5 & SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING && spell->IsChannelActive();
3611 
3612  return false;
3613 }
3614 
3615 bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
3616 {
3617  return IsWithinDistInMap(target, distance) && HasInArc(arc, target);
3618 }
3619 
3620 bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const
3621 {
3622  return IsWithinDistInMap(target, distance) && !HasInArc(2 * M_PI - arc, target);
3623 }
3624 
3625 void Unit::SetFacingTo(float ori)
3626 {
3627  Movement::MoveSplineInit init(*this);
3628  init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZ(), false);
3629  init.SetFacing(ori);
3630  init.Launch();
3631 }
3632 
3634 {
3635  // never face when already moving
3636  if (!IsStopped())
3637  return;
3638 
3640  Movement::MoveSplineInit init(*this);
3642  init.SetFacing(GetAngle(pObject)); // when on transport, GetAngle will still return global coordinates (and angle) that needs transforming
3643  init.Launch();
3644 }
3645 
3647 {
3648  if (IsInWater())
3649  return c->CanSwim();
3650  else
3651  return c->CanWalk() || c->CanFly();
3652 }
3653 
3654 bool Unit::IsInWater() const
3655 {
3657 }
3658 
3660 {
3662 }
3663 
3665 {
3667 }
3668 
3670 {
3671  int32 modifier = 0;
3672 
3673  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3674  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3675  modifier += (*i)->GetModifierValue();
3676 
3677  return modifier;
3678 }
3679 
3681 {
3682  float multiplier = 1.0f;
3683 
3684  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3685  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3686  multiplier *= (100.0f + (*i)->GetModifierValue()) / 100.0f;
3687 
3688  return multiplier;
3689 }
3690 
3692 {
3693  int32 modifier = 0;
3694 
3695  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3696  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3697  {
3698  int32 amount = (*i)->GetModifierValue();
3699  if (amount > modifier)
3700  modifier = amount;
3701  }
3702 
3703  return modifier;
3704 }
3705 
3707 {
3708  int32 modifier = 0;
3709 
3710  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3711  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3712  {
3713  int32 amount = (*i)->GetModifierValue();
3714  if (amount < modifier)
3715  modifier = amount;
3716  }
3717 
3718  return modifier;
3719 }
3720 
3722 {
3723  int32 modifier = 0;
3724 
3725  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3726  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3727  {
3728  Modifier* mod = (*i)->GetModifier();
3729  if ((mod->m_miscvalue & misc_mask) != 0)
3730  modifier += (*i)->GetModifierValue();
3731  }
3732  return modifier;
3733 }
3734 
3736 {
3737  float multiplier = 1.0f;
3738 
3739  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3740  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3741  {
3742  Modifier* mod = (*i)->GetModifier();
3743  if (mod->m_miscvalue & misc_mask)
3744  multiplier *= (100.0f + (*i)->GetModifierValue()) / 100.0f;
3745  }
3746  return multiplier;
3747 }
3748 
3750 {
3751  int32 modifier = 0;
3752 
3753  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3754  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3755  {
3756  Modifier* mod = (*i)->GetModifier();
3757  int32 amount = (*i)->GetModifierValue();
3758  if (mod->m_miscvalue & misc_mask && amount > modifier)
3759  modifier = amount;
3760  }
3761 
3762  return modifier;
3763 }
3764 
3766 {
3767  int32 modifier = 0;
3768 
3769  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3770  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3771  {
3772  Modifier* mod = (*i)->GetModifier();
3773  int32 amount = (*i)->GetModifierValue();
3774  if (mod->m_miscvalue & misc_mask && amount < modifier)
3775  modifier = amount;
3776  }
3777 
3778  return modifier;
3779 }
3780 
3782 {
3783  int32 modifier = 0;
3784 
3785  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3786  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3787  {
3788  Modifier* mod = (*i)->GetModifier();
3789  if (mod->m_miscvalue == misc_value)
3790  modifier += (*i)->GetModifierValue();
3791  }
3792  return modifier;
3793 }
3794 
3795 float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const
3796 {
3797  float multiplier = 1.0f;
3798 
3799  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3800  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3801  {
3802  Modifier* mod = (*i)->GetModifier();
3803  if (mod->m_miscvalue == misc_value)
3804  multiplier *= (100.0f + (*i)->GetModifierValue()) / 100.0f;
3805  }
3806  return multiplier;
3807 }
3808 
3810 {
3811  int32 modifier = 0;
3812 
3813  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3814  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3815  {
3816  Modifier* mod = (*i)->GetModifier();
3817  int32 amount = (*i)->GetModifierValue();
3818  if (mod->m_miscvalue == misc_value && amount > modifier)
3819  modifier = amount;
3820  }
3821 
3822  return modifier;
3823 }
3824 
3826 {
3827  int32 modifier = 0;
3828 
3829  AuraList const& mTotalAuraList = GetAurasByType(auratype);
3830  for (AuraList::const_iterator i = mTotalAuraList.begin(); i != mTotalAuraList.end(); ++i)
3831  {
3832  Modifier* mod = (*i)->GetModifier();
3833  int32 amount = (*i)->GetModifierValue();
3834  if (mod->m_miscvalue == misc_value && amount < modifier)
3835  modifier = amount;
3836  }
3837 
3838  return modifier;
3839 }
3840 
3842 {
3843  // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
3844  if (!IsAlive() && Aur->GetId() != 20584 && Aur->GetId() != 8326 && Aur->GetId() != 2584 &&
3846  {
3847  delete Aur;
3848  return false;
3849  }
3850 
3851  if (Aur->GetTarget() != this)
3852  {
3853  sLog.outError("Aura (spell %u eff %u) add to aura list of %s (lowguid: %u) but Aura target is %s (lowguid: %u)",
3854  Aur->GetId(), Aur->GetEffIndex(), (GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), GetGUIDLow(),
3855  (Aur->GetTarget()->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), Aur->GetTarget()->GetGUIDLow());
3856  delete Aur;
3857  return false;
3858  }
3859 
3860  SpellEntry const* aurSpellInfo = Aur->GetSpellProto();
3861 
3862  spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex());
3863  bool stackModified = false;
3864 
3865  // Handle aura stacking down below...
3866  if (!Aur->IsPassive() && !Aur->IsPersistent())
3867  {
3868  for (AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair);)
3869  {
3870  Aura* aur2 = i2->second;
3871 
3872  if (aur2 && !stackModified)
3873  {
3874  ASSERT(aur2->GetId() == Aur->GetId());
3875 
3876  // @todo: fix this hack
3877  // Allow mongoose proc from different weapons... this should be corrected to allow multiple
3878  // auras triggered by different enchanted items this is not possible currently since we only have
3879  // GUID and not even information if the Aura was "triggered" see m_IsTriggeredSpell in Spell.h
3880  if (Aur->GetCastItemGUID() && Aur->GetId() == 28093)
3881  {
3882  bool allow = true;
3883 
3884  for (AuraMap::const_iterator i3 = m_Auras.lower_bound(spair); i3 != m_Auras.upper_bound(spair); i3++)
3885  if (i3->second->GetCastItemGUID() == Aur->GetCastItemGUID())
3886  allow = false;
3887 
3888  if (allow)
3889  break;
3890  }
3891 
3892  if (sSpellMgr.IsNoStackSpellDueToSpell(Aur->GetId(), aur2->GetId(), Aur->GetCasterGUID() == aur2->GetCasterGUID()))
3893  {
3894  // Non stackable and capped auras do not allow stacking
3895  if (!(aurSpellInfo->StackAmount && uint32(aur2->GetStackAmount()) < aurSpellInfo->StackAmount))
3896  {
3897  // Do not let the stack size exceed the maximum stack limit
3898  // Instead of adding a new stack, just set the duration time
3899  // we need to use time from Aur because of diminishing effects
3900  aur2->SetAuraDuration(Aur->GetAuraMaxDuration());
3901  aur2->SetAuraProcCharges(Aur->m_procCharges);
3902  aur2->UpdateAuraDuration();
3903  aur2->UpdateAuraCharges();
3904  *aur2->GetModifier() = *Aur->GetModifier();
3905  delete Aur;
3906  return true;
3907  }
3908 
3909  // Increment aura's stack, one stack per one call
3910  Aur->SetStackAmount(aur2->GetStackAmount() + 1);
3911  stackModified = true;
3912 
3913  // Existing aura will be replaced with the newly created one
3915  i2 = m_Auras.lower_bound(spair);
3916  continue;
3917  }
3918  }
3919 
3920  ++i2;
3921  }
3922  }
3923 
3924  // passive auras stack with all (except passive spell proc auras)
3925  if ((!Aur->IsPassive() || !IsPassiveStackableSpell(Aur->GetId())) &&
3926  !(Aur->GetId() == 20584 || Aur->GetId() == 8326))
3927  {
3928  if (!RemoveNoStackAurasDueToAura(Aur))
3929  {
3930  delete Aur;
3931  return false; // couldn't remove conflicting aura with higher rank
3932  }
3933  }
3934 
3935  // update single target auras list (before aura add to aura list, to prevent unexpected remove recently added aura)
3936  if (Aur->IsSingleTarget() && Aur->GetTarget())
3937  {
3938  // caster pointer can be deleted in time aura remove, find it by guid at each iteration
3939  for (;;)
3940  {
3941  Unit* caster = Aur->GetCaster();
3942  if (!caster) // caster deleted and not required adding scAura
3943  break;
3944 
3945  bool restart = false;
3946  AuraList& scAuras = caster->GetSingleCastAuras();
3947  for (AuraList::iterator itr = scAuras.begin(); itr != scAuras.end(); ++itr)
3948  {
3949  if ((*itr)->GetTarget() != Aur->GetTarget() &&
3950  IsSingleTargetSpells((*itr)->GetSpellProto(), aurSpellInfo))
3951  {
3952  if ((*itr)->IsInUse())
3953  {
3954  sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for IsSingleTargetSpell", (*itr)->GetId(), (*itr)->GetEffIndex(), Aur->GetId(), Aur->GetEffIndex());
3955  continue;
3956  }
3957  (*itr)->GetTarget()->RemoveAura((*itr)->GetId(), (*itr)->GetEffIndex());
3958  restart = true;
3959  break;
3960  }
3961  }
3962 
3963  if (!restart)
3964  {
3965  // done
3966  scAuras.push_back(Aur);
3967  break;
3968  }
3969  }
3970  }
3971 
3972  // add aura, register in lists and arrays
3973  Aur->_AddAura();
3974  m_Auras.insert(AuraMap::value_type(spellEffectPair(Aur->GetId(), Aur->GetEffIndex()), Aur));
3975  if (Aur->GetModifier()->m_auraname < TOTAL_AURAS)
3976  {
3977  m_modAuras[Aur->GetModifier()->m_auraname].push_back(Aur);
3978  if (Aur->GetSpellProto()->AuraInterruptFlags)
3979  {
3980  m_interruptableAuras.push_back(Aur);
3982  }
3984  && (Aur->GetModifier()->m_auraname != SPELL_AURA_MOD_POSSESS)) //only dummy aura is breakable
3985  m_ccAuras.push_back(Aur);
3986  }
3987 
3988  Aur->ApplyModifier(true, true);
3989 
3990  uint32 id = Aur->GetId();
3991  if (sSpellMgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA)
3992  {
3993  if (const std::vector<int32>* spell_triggered = sSpellMgr.GetSpellLinked(id + SPELL_LINK_AURA))
3994  {
3995  for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
3996  if (*itr < 0)
3997  ApplySpellImmune(id, IMMUNITY_ID, -(*itr), true);
3998  else if (Unit* caster = Aur->GetCaster())
3999  caster->AddAura(*itr, this);
4000  }
4001  }
4002 
4003  DEBUG_LOG("Aura %u now is in use", Aur->GetModifier()->m_auraname);
4004  return true;
4005 }
4006 
4008 {
4009  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
4010  if (!spellInfo)
4011  return;
4012  AuraMap::iterator i, next;
4013  for (i = m_Auras.begin(); i != m_Auras.end(); i = next)
4014  {
4015  next = i;
4016  ++next;
4017  uint32 i_spellId = (*i).second->GetId();
4018  if ((*i).second && i_spellId && i_spellId != spellId)
4019  {
4020  if (sSpellMgr.IsRankSpellDueToSpell(spellInfo, i_spellId))
4021  {
4022  RemoveAurasDueToSpell(i_spellId);
4023 
4024  if (m_Auras.empty())
4025  break;
4026  else
4027  next = m_Auras.begin();
4028  }
4029  }
4030  }
4031 }
4032 
4034 {
4035  if (!Aur) return false;
4036 
4037  SpellEntry const* spellProto = Aur->GetSpellProto();
4038  if (!spellProto) return false;
4039 
4040  uint32 spellId = Aur->GetId();
4041  uint32 effIndex = Aur->GetEffIndex();
4042 
4043  AuraMap::iterator i, next;
4044  for (i = m_Auras.begin(); i != m_Auras.end(); i = next)
4045  {
4046  next = i;
4047  ++next;
4048  if (!(*i).second) continue;
4049 
4050  SpellEntry const* i_spellProto = (*i).second->GetSpellProto();
4051  if (!i_spellProto) continue;
4052 
4053  uint32 i_spellId = i_spellProto->Id;
4054 
4055  if (spellId == i_spellId)
4056  continue;
4057 
4058  if (IsPassiveSpell(i_spellId))
4059  {
4060  // passive non-stackable spells not stackable only with another rank of same spell
4061  if (IsPassiveStackableSpell(i_spellId) || !sSpellMgr.IsRankSpellDueToSpell(spellProto, i_spellId))
4062  continue;
4063  }
4064  uint32 i_effIndex = (*i).second->GetEffIndex();
4065 
4066  bool is_triggered_by_spell = false;
4067  // prevent triggered aura of removing aura that triggered it
4068  for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
4069  {
4070  if (i_spellProto->EffectTriggerSpell[j] == spellProto->Id)
4071  {
4072  is_triggered_by_spell = true;
4073  break;
4074  }
4075  }
4076  if (is_triggered_by_spell) continue;
4077 
4078  for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
4079  {
4080  // prevent remove dummy triggered spells at next effect aura add
4081  if (spellProto->Effect[j] == SPELL_EFFECT_DUMMY && spellId == 5420 && i_spellId == 34123)
4082  is_triggered_by_spell = true;
4083 
4084  // main aura added before triggered spell
4085  // prevent remove form main spell by triggered passive spells
4086  else if (i_spellProto->EffectApplyAuraName[j] == SPELL_AURA_MOD_SHAPESHIFT)
4087  {
4088  if ((i_spellId == 24858 && spellId == 24905) || (i_spellId == 34551 && spellId == 22688))
4089  is_triggered_by_spell = true;
4090 
4091  else if (i_spellId == 33891 && (spellId == 5420 || spellId == 34123))
4092  is_triggered_by_spell = true;
4093  }
4094  else continue;
4095  break;
4096  }
4097 
4098  if (!is_triggered_by_spell)
4099  {
4100  bool sameCaster = Aur->GetCasterGUID() == (*i).second->GetCasterGUID();
4101 
4102  if (!sSpellMgr.IsNoStackSpellDueToSpell(spellId, i_spellId, sameCaster))
4103  continue;
4104 
4105  int32 aur1Rank = Aur->GetModifierValue();
4106  int32 aur2Rank = (*i).second->GetModifierValue();
4107  // Check if effect is "better"
4108  if (!sameCaster && (abs(aur1Rank)-abs(aur2Rank)) < 0)
4109  return false;
4110  // Some spells should be not removed by lower rank of them (totem, paladin aura)
4111  if (!sameCaster && spellProto->DurationIndex == 21 && sSpellMgr.IsRankSpellDueToSpell(spellProto, i_spellId))
4112  if (spellProto->Effect[effIndex] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
4113  if (CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
4114  return false;
4115 
4116  // Its a parent aura (create this aura in ApplyModifier)
4117  if ((*i).second->IsInUse())
4118  {
4119  sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(), Aur->GetId(), Aur->GetEffIndex());
4120  continue;
4121  }
4122  uint64 caster = (*i).second->GetCasterGUID();
4123  // Remove all auras by aura caster
4124  for (uint8 a = 0; a < MAX_SPELL_EFFECTS; ++a)
4125  {
4126  spellEffectPair spair = spellEffectPair(i_spellId, a);
4127  for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);)
4128  {
4129  if (iter->second->GetCasterGUID() == caster)
4130  {
4132  iter = m_Auras.lower_bound(spair);
4133  }
4134  else ++iter;
4135  }
4136  }
4137  if (m_Auras.empty()) break;
4138  else next = m_Auras.begin();
4139  }
4140  }
4141  return true;
4142 }
4143 
4144 void Unit::RemoveAura(uint32 spellId, uint32 effindex, Aura* except)
4145 {
4146  spellEffectPair spair = spellEffectPair(spellId, effindex);
4147  for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);)
4148  {
4149  if (iter->second != except)
4150  {
4151  RemoveAura(iter);
4152  iter = m_Auras.lower_bound(spair);
4153  }
4154  else
4155  ++iter;
4156  }
4157 }
4158 
4160 {
4161  for (int k = 0; k < MAX_SPELL_EFFECTS; ++k)
4162  {
4163  spellEffectPair spair = spellEffectPair(spellId, k);
4164  for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);)
4165  {
4166  if (iter->second->GetCasterGUID() == casterGUID)
4167  {
4168  RemoveAura(iter);
4169  iter = m_Auras.upper_bound(spair); // overwrite by more appropriate
4170  }
4171  else
4172  ++iter;
4173  }
4174  }
4175 }
4176 
4177 void Unit::SetAurasDurationByCasterSpell(uint32 spellId, uint64 casterGUID, int32 duration)
4178 {
4179  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
4180  {
4181  spellEffectPair spair = spellEffectPair(spellId, i);
4182  for (AuraMap::const_iterator itr = GetAuras().lower_bound(spair); itr != GetAuras().upper_bound(spair); ++itr)
4183  {
4184  if (itr->second->GetCasterGUID() == casterGUID)
4185  {
4186  itr->second->SetAuraDuration(duration);
4187  break;
4188  }
4189  }
4190  }
4191 }
4192 
4194 {
4195  // Returns first found aura from spell-use only in cases where effindex of spell doesn't matter!
4196  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
4197  {
4198  spellEffectPair spair = spellEffectPair(spellId, i);
4199  for (AuraMap::const_iterator itr = GetAuras().lower_bound(spair); itr != GetAuras().upper_bound(spair); ++itr)
4200  {
4201  if (itr->second->GetCasterGUID() == casterGUID)
4202  return itr->second;
4203  }
4204  }
4205  return NULL;
4206 }
4207 
4208 void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit* dispeler)
4209 {
4210  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
4211  {
4212  Aura* aur = iter->second;
4213  if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
4214  {
4215  // Custom dispel case
4216  // Unstable Affliction
4217  if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags & 0x010000000000LL))
4218  {
4219  int32 damage = aur->GetModifier()->m_amount * 9;
4220  uint64 caster_guid = aur->GetCasterGUID();
4221 
4222  // Remove aura
4224 
4225  // backfire damage and silence
4226  dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL, caster_guid);
4227 
4228  iter = m_Auras.begin(); // iterator can be invalidate at cast if self-dispel
4229  }
4230  else
4232  }
4233  else
4234  ++iter;
4235  }
4236 }
4237 
4238 void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit* stealer)
4239 {
4240  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
4241  {
4242  Aura* aur = iter->second;
4243  if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
4244  {
4245  //int32 basePoints = aur->GetBasePoints();
4246  // construct the new aura for the attacker
4247  Aura* new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), NULL/*&basePoints*/, stealer);
4248  if (!new_aur)
4249  continue;
4250 
4251  // set its duration and maximum duration
4252  // max duration 2 minutes (in msecs)
4253  int32 dur = aur->GetAuraDuration();
4254  const int32 max_dur = 2 * MINUTE * IN_MILLISECONDS;
4255  new_aur->SetAuraMaxDuration(max_dur > dur ? dur : max_dur);
4256  new_aur->SetAuraDuration(max_dur > dur ? dur : max_dur);
4257  new_aur->SetAuraProcCharges(aur->m_procCharges);
4258 
4259  // Unregister _before_ adding to stealer
4260  aur->UnregisterSingleCastAura();
4261  // strange but intended behaviour: Stolen single target auras won't be treated as single targeted
4262  new_aur->SetIsSingleTarget(false);
4263  // add the new aura to stealer
4264  stealer->AddAura(new_aur);
4265  // Remove aura as dispel
4266  if (aur->GetStackAmount() > 1)
4267  {
4268  // reapply modifier with reduced stack amount
4269  aur->ApplyModifier(false, true);
4270  aur->SetStackAmount(aur->GetStackAmount() - 1);
4271  aur->ApplyModifier(true, true);
4272 
4274  ++iter;
4275  }
4276  else
4278  }
4279  else
4280  ++iter;
4281  }
4282 }
4283 
4285 {
4286  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
4287  {
4288  if (iter->second->GetId() == spellId)
4290  else
4291  ++iter;
4292  }
4293 }
4294 
4296 {
4297  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
4298  {
4299  SpellEntry const* spell = iter->second->GetSpellProto();
4300  if (spell->Attributes & flags)
4301  RemoveAura(iter);
4302  else
4303  ++iter;
4304  }
4305 }
4306 
4308 {
4309  // Create dispel mask by dispel type
4310  uint32 dispelMask = GetDispelMask(type);
4311  // Dispel all existing auras vs current dispel type
4312  AuraMap& auras = GetAuras();
4313  for (AuraMap::iterator itr = auras.begin(); itr != auras.end();)
4314  {
4315  SpellEntry const* spell = itr->second->GetSpellProto();
4316  if ((1 << spell->Dispel) & dispelMask && !itr->second->IsInUse())
4317  {
4318  // Dispel aura
4319  RemoveAurasDueToSpell(spell->Id);
4320  itr = auras.begin();
4321  }
4322  else
4323  ++itr;
4324  }
4325 }
4326 
4328 {
4329  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
4330  {
4331  Aura* aur = iter->second;
4332  if (aur->GetId() == spellId)
4333  {
4334  if (iter->second->GetStackAmount() > 1)
4335  {
4336  // reapply modifier with reduced stack amount
4337  iter->second->ApplyModifier(false, true);
4338  iter->second->SetStackAmount(iter->second->GetStackAmount() - 1);
4339  iter->second->ApplyModifier(true, true);
4340 
4341  iter->second->UpdateSlotCounterAndDuration();
4342  return; // not remove aura if stack amount > 1
4343  }
4344  else
4346  }
4347  else
4348  ++iter;
4349  }
4350 }
4351 
4353 {
4354  AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
4355  if (iter != m_Auras.end())
4356  {
4357  if (iter->second->GetStackAmount() > 1)
4358  {
4359  // reapply modifier with reduced stack amount
4360  iter->second->ApplyModifier(false, true);
4361  iter->second->SetStackAmount(iter->second->GetStackAmount() - 1);
4362  iter->second->ApplyModifier(true, true);
4363 
4364  iter->second->UpdateSlotCounterAndDuration();
4365  return; // not remove aura if stack amount > 1
4366  }
4367  RemoveAura(iter);
4368  }
4369 }
4370 
4372 {
4373  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
4374  RemoveAura(spellId, i, except);
4375 }
4376 
4378 {
4379  for (int k = 0; k < MAX_SPELL_EFFECTS; ++k)
4380  {
4381  spellEffectPair spair = spellEffectPair(spellId, k);
4382  for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);)
4383  {
4384  if (iter->second->GetCastItemGUID() == castItem->GetGUID())
4385  {
4386  RemoveAura(iter);
4387  iter = m_Auras.upper_bound(spair); // overwrite by more appropriate
4388  }
4389  else
4390  ++iter;
4391  }
4392  }
4393 }
4394 
4395 void Unit::RemoveAurasByType(AuraType auraType, uint64 casterGUID, Aura* except, bool negative, bool positive)
4396 {
4397  if (auraType >= TOTAL_AURAS)
4398  return;
4399 
4400  for (AuraList::iterator iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end();)
4401  {
4402  Aura* aura = *iter;
4403 
4404  ++iter;
4405  if (aura != except && (!casterGUID || aura->GetCasterGUID() == casterGUID)
4406  && ((negative && !aura->IsPositive()) || (positive && aura->IsPositive())))
4407  {
4408  uint32 removedAuras = m_removedAurasCount;
4409  RemoveAurasDueToSpell(aura->GetId());
4410  if (m_removedAurasCount > removedAuras + 1)
4411  iter = m_modAuras[auraType].begin();
4412  }
4413  }
4414 }
4415 
4417 {
4418  // single target auras from other casters
4419  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
4420  {
4421  if (iter->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(iter->second->GetSpellProto()))
4422  RemoveAura(iter);
4423  else
4424  ++iter;
4425  }
4426 
4427  // single target auras at other targets
4428  AuraList& scAuras = GetSingleCastAuras();
4429  for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();)
4430  {
4431  Aura* aur = *iter;
4432  ++iter;
4433  if (aur->GetTarget() != this)
4434  {
4435  uint32 removedAuras = m_removedAurasCount;
4436  aur->GetTarget()->RemoveAura(aur->GetId(), aur->GetEffIndex());
4437  if (m_removedAurasCount > removedAuras + 1)
4438  iter = scAuras.begin();
4439  }
4440  }
4441 
4442 }
4443 
4444 void Unit::RemoveAura(AuraMap::iterator& i, AuraRemoveMode mode)
4445 {
4446  Aura* Aur = i->second;
4447 
4448  // if unit currently update aura list then make safe update iterator shift to next
4449  if (m_AurasUpdateIterator == i)
4451 
4452  // some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura
4453  // remove aura from list before to prevent deleting it before
4454  m_Auras.erase(i);
4456 
4457  SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
4458  Unit* caster = NULL;
4459  Aur->UnregisterSingleCastAura();
4460 
4461  // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order)
4462  if (Aur->GetModifier()->m_auraname < TOTAL_AURAS)
4463  {
4464  m_modAuras[Aur->GetModifier()->m_auraname].remove(Aur);
4465 
4466  if (Aur->GetSpellProto()->AuraInterruptFlags)
4467  {
4468  m_interruptableAuras.remove(Aur);
4470  }
4471 
4473  && (Aur->GetModifier()->m_auraname != SPELL_AURA_MOD_POSSESS)) //only dummy aura is breakable
4474  m_ccAuras.remove(Aur);
4475  }
4476 
4477  // Set remove mode
4478  Aur->SetRemoveMode(mode);
4479 
4480  // Statue unsummoned at aura remove
4481  //Totem* statue = NULL;
4482  if (Aur->GetAuraDuration() && !Aur->IsPersistent() && IsChanneledSpell(AurSpellInfo))
4483  {
4484  if (!caster) // can be already located for IsSingleTargetSpell case
4485  caster = Aur->GetCaster();
4486 
4487  if (caster && caster->IsAlive())
4488  {
4489  // stop caster chanelling state
4491  //prevent recurential call
4493  {
4494  if (caster == this || !IsAreaOfEffectSpell(AurSpellInfo))
4495  {
4496  // remove auras only for non-aoe spells or when chanelled aura is removed
4497  // because aoe spells don't require aura on target to continue
4498  if (AurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()] != SPELL_AURA_PERIODIC_DUMMY
4499  && AurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()] != SPELL_AURA_DUMMY)
4500  //don't stop channeling of scripted spells (this is actually a hack)
4501  {
4503  caster->m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL;
4504 
4505  }
4506  }
4507 
4508  //if (caster->GetTypeId() == TYPEID_UNIT && caster->IsTotem() && ((Totem*)caster)->GetTotemType() == TOTEM_STATUE)
4509  // statue = ((Totem*)caster);
4510  }
4511 
4512  // Unsummon summon as possessed creatures on spell cancel
4513  if (caster->GetTypeId() == TYPEID_PLAYER)
4514  if (Unit* charm = caster->GetCharm())
4515  if (charm->GetTypeId() == TYPEID_UNIT
4516  && charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_PUPPET)
4517  && charm->GetUInt32Value(UNIT_CREATED_BY_SPELL) == AurSpellInfo->Id)
4518  ((Puppet*)charm)->UnSummon();
4519  }
4520  }
4521 
4522  DEBUG_LOG("Aura %u (%u) now is remove mode %d", Aur->GetId(), Aur->GetModifier()->m_auraname, mode);
4523  ASSERT(!Aur->IsInUse());
4524  Aur->ApplyModifier(false, true);
4525 
4526  Aur->SetStackAmount(0);
4527 
4528  // set aura to be removed during unit::_updatespells
4529  m_removedAuras.push_back(Aur);
4530 
4531  Aur->_RemoveAura();
4532 
4533  bool stack = false;
4534  spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex());
4535  for (AuraMap::const_iterator itr = GetAuras().lower_bound(spair); itr != GetAuras().upper_bound(spair); ++itr)
4536  {
4537  if (itr->second->GetCasterGUID() == GetGUID())
4538  stack = true;
4539  }
4540  if (!stack)
4541  {
4542  // Remove all triggered by aura spells vs unlimited duration
4543  Aur->CleanupTriggeredSpells();
4544 
4545  // Remove Linked Auras
4546  uint32 id = Aur->GetId();
4547  if (sSpellMgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_REMOVE)
4548  {
4549  if (const std::vector<int32>* spell_triggered = sSpellMgr.GetSpellLinked(-(int32)id))
4550  {
4551  for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
4552  if (*itr < 0)
4553  RemoveAurasDueToSpell(-(*itr));
4554  else if (Unit* caster = Aur->GetCaster())
4555  CastSpell(this, *itr, true, 0, 0, caster->GetGUID());
4556  }
4557  }
4558  if (sSpellMgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA)
4559  {
4560  if (const std::vector<int32>* spell_triggered = sSpellMgr.GetSpellLinked(id + SPELL_LINK_AURA))
4561  {
4562  for (std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr)
4563  if (*itr < 0)
4564  ApplySpellImmune(id, IMMUNITY_ID, -(*itr), false);
4565  else
4566  RemoveAurasDueToSpell(*itr);
4567  }
4568  }
4569  }
4570 
4571  //if (statue)
4572  // statue->UnSummon();
4573 
4574  i = m_Auras.begin();
4575 }
4576 
4578 {
4579  while (!m_Auras.empty())
4580  {
4581  AuraMap::iterator iter = m_Auras.begin();
4582  RemoveAura(iter);
4583  }
4584 }
4585 
4587 {
4588  // in join, remove positive buffs, on end, remove negative
4589  // used to remove positive visible auras in arenas
4590  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
4591  {
4592  Aura* aura = iter->second;
4593  if (!(aura->GetSpellProto()->AttributesEx4 & SPELL_ATTR4_STANCES) // don't remove stances, shadowform, pally/hunter auras
4594  && !aura->IsPassive() // don't remove passive auras
4595  && (aura->IsPositive() || !(aura->GetSpellProto()->AttributesEx3 & SPELL_ATTR3_DEATH_PERSISTENT))) // not negative death persistent auras
4596  RemoveAura(iter);
4597  else
4598  ++iter;
4599  }
4600 }
4601 
4603 {
4604  // used just after dieing to remove all visible auras
4605  // and disable the mods for the passive ones
4606  for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
4607  {
4608  if (!iter->second->IsPassive() && !iter->second->IsDeathPersistent())
4610  else
4611  ++iter;
4612  }
4613 }
4614 
4615 void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime)
4616 {
4617  AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
4618  if (iter != m_Auras.end())
4619  {
4620  if (iter->second->GetAuraDuration() < delaytime)
4621  iter->second->SetAuraDuration(0);
4622  else
4623  iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime);
4624  iter->second->UpdateAuraDuration();
4625  DEBUG_LOG("Aura %u partially interrupted on unit %u, new duration: %u ms", iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration());
4626  }
4627 }
4628 
4630 {
4631  for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i)
4632  (*i).second->ApplyModifier(false);
4633 }
4634 
4636 {
4637  for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i)
4638  (*i).second->ApplyModifier(true);
4639 }
4640 
4641 Aura* Unit::GetAura(uint32 spellId, uint32 effindex)
4642 {
4643  AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
4644  if (iter != m_Auras.end())
4645  return iter->second;
4646  return NULL;
4647 }
4648 
4650 {
4651  m_dynObjGUIDs.push_back(dynObj->GetGUID());
4652 }
4653 
4655 {
4656  if (m_dynObjGUIDs.empty())
4657  return;
4658  for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();)
4659  {
4660  DynamicObject* dynObj = GetMap()->GetDynamicObject(*i);
4661  if (!dynObj) // may happen if a dynobj is removed when grid unload
4662  i = m_dynObjGUIDs.erase(i);
4663  else if (spellid == 0 || dynObj->GetSpellId() == spellid)
4664  {
4665  dynObj->Remove();
4666  i = m_dynObjGUIDs.erase(i);
4667  }
4668  else
4669  ++i;
4670  }
4671 }
4672 
4674 {
4675  while (!m_dynObjGUIDs.empty())
4676  {
4677  DynamicObject* dynObj = GetMap()->GetDynamicObject(*m_dynObjGUIDs.begin());
4678  if (dynObj)
4679  dynObj->Remove();
4680  m_dynObjGUIDs.erase(m_dynObjGUIDs.begin());
4681  }
4682 }
4683 
4685 {
4686  for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();)
4687  {
4688  DynamicObject* dynObj = GetMap()->GetDynamicObject(*i);
4689  if (!dynObj)
4690  {
4691  i = m_dynObjGUIDs.erase(i);
4692  continue;
4693  }
4694 
4695  if (dynObj->GetSpellId() == spellId && dynObj->GetEffIndex() == effIndex)
4696  return dynObj;
4697  ++i;
4698  }
4699  return NULL;
4700 }
4701 
4703 {
4704  for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();)
4705  {
4706  DynamicObject* dynObj = GetMap()->GetDynamicObject(*i);
4707  if (!dynObj)
4708  {
4709  i = m_dynObjGUIDs.erase(i);
4710  continue;
4711  }
4712 
4713  if (dynObj->GetSpellId() == spellId)
4714  return dynObj;
4715  ++i;
4716  }
4717  return NULL;
4718 }
4719 
4721 {
4722  if (!gameObj || gameObj->GetOwnerGUID() != 0)
4723  return;
4724 
4725  m_gameObj.push_back(gameObj);
4726  gameObj->SetOwnerGUID(GetGUID());
4727 }
4728 
4729 void Unit::RemoveGameObject(GameObject* gameObj, bool del)
4730 {
4731  if (!gameObj || gameObj->GetOwnerGUID() != GetGUID())
4732  return;
4733 
4734  gameObj->SetOwnerGUID(0);
4735 
4736  for (uint8 i = 0; i < 3; ++i)
4737  {
4738  if (m_ObjectSlot[i] == gameObj->GetGUID())
4739  {
4740  m_ObjectSlot[i] = 0;
4741  break;
4742  }
4743  }
4744 
4745  // GO created by some spell
4746  if (uint32 spellid = gameObj->GetSpellId())
4747  {
4748  RemoveAurasDueToSpell(spellid);
4749 
4750  if (GetTypeId() == TYPEID_PLAYER)
4751  {
4752  SpellEntry const* createBySpell = sSpellStore.LookupEntry(spellid);
4753  // Need activate spell use for owner
4754  if (createBySpell && createBySpell->Attributes & SPELL_ATTR0_DISABLED_WHILE_ACTIVE)
4755  // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
4756  ToPlayer()->SendCooldownEvent(createBySpell);
4757  }
4758  }
4759 
4760  m_gameObj.remove(gameObj);
4761 
4762  if (del)
4763  {
4764  gameObj->SetRespawnTime(0);
4765  gameObj->Delete();
4766  }
4767 }
4768 
4769 void Unit::RemoveGameObject(uint32 spellid, bool del)
4770 {
4771  if (m_gameObj.empty())
4772  return;
4773  std::list<GameObject*>::iterator i, next;
4774  for (i = m_gameObj.begin(); i != m_gameObj.end(); i = next)
4775  {
4776  next = i;
4777  if (spellid == 0 || (*i)->GetSpellId() == spellid)
4778  {
4779  (*i)->SetOwnerGUID(0);
4780  if (del)
4781  {
4782  (*i)->SetRespawnTime(0);
4783  (*i)->Delete();
4784  }
4785 
4786  next = m_gameObj.erase(i);
4787  }
4788  else
4789  ++next;
4790  }
4791 }
4792 
4794 {
4795  // remove references to unit
4796  for (std::list<GameObject*>::iterator i = m_gameObj.begin(); i != m_gameObj.end();)
4797  {
4798  (*i)->SetOwnerGUID(0);
4799  (*i)->SetRespawnTime(0);
4800  (*i)->Delete();
4801  i = m_gameObj.erase(i);
4802  }
4803 }
4804 
4806 {
4807  WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16 + 4 + 4 + 1 + 4 + 4 + 1 + 1 + 4 + 4 + 1)); // we guess size
4808  data << log->target->GetPackGUID();
4809  data << log->attacker->GetPackGUID();
4810  data << uint32(log->SpellID);
4811  data << uint32(log->damage); // damage amount
4812  data << uint8 (log->schoolMask); // damage school
4813  data << uint32(log->absorb); // AbsorbedDamage
4814  data << uint32(log->resist); // resist
4815  data << uint8 (log->physicalLog); // damsge type? flag
4816  data << uint8 (log->unused); // unused
4817  data << uint32(log->blocked); // blocked
4818  data << uint32(log->HitInfo);
4819  data << uint8 (0); // flag to use extend data
4820  SendMessageToSet(&data, true);
4821 }
4822 
4823 void Unit::SendSpellNonMeleeDamageLog(Unit* target, uint32 SpellID, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit)
4824 {
4825  DEBUG_LOG("Sending: SMSG_SPELLNONMELEEDAMAGELOG");
4826  WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16 + 4 + 4 + 1 + 4 + 4 + 1 + 1 + 4 + 4 + 1)); // we guess size
4827  data << target->GetPackGUID();
4828  data << GetPackGUID();
4829  data << uint32(SpellID);
4830  data << uint32(Damage - AbsorbedDamage - Resist - Blocked);
4831  data << uint8(damageSchoolMask); // spell school
4832  data << uint32(AbsorbedDamage); // AbsorbedDamage
4833  data << uint32(Resist); // resist
4834  data << uint8(PhysicalDamage); // if 1, then client show spell name (example: %s's ranged shot hit %s for %u school or %s suffers %u school damage from %s's spell_name
4835  data << uint8(0); // unk isFromAura
4836  data << uint32(Blocked); // blocked
4837  data << uint32(CriticalHit ? 0x27 : 0x25); // hitType, flags: 0x2 - SPELL_HIT_TYPE_CRIT, 0x10 - replace caster?
4838  data << uint8(0); // isDebug?
4839  SendMessageToSet(&data, true);
4840 }
4841 
4842 void Unit::ProcDamageAndSpell(Unit* victim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellEntry const* procSpell, bool canTrigger)
4843 {
4844  // Proc all effects (auras/talents/whatever) on on victim first, then on caster
4845 
4846  // Now go on with a victim's events'n'auras
4847  // Not much to do if no flags are set or there is no victim
4848  if (victim && victim->IsAlive() && procVictim)
4849  victim->ProcDamageAndSpellFor(true, this, procVictim, procExtra, attType, procSpell, amount);
4850 
4851  // Not much to do if no flags are set.
4852  if (procAttacker && canTrigger)
4853  ProcDamageAndSpellFor(false, victim, procAttacker, procExtra, attType, procSpell, amount);
4854 }
4855 
4856 void Unit::SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo)
4857 {
4858  WorldPacket data(SMSG_SPELLLOGMISS, (4+8+1+4+8+1));
4859  data << uint32(spellID);
4860  data << uint64(GetGUID());
4861  data << uint8(0); // can be 0 or 1
4862  data << uint32(1); // target count
4863  // for (i = 0; i < target count; ++i)
4864  data << uint64(target->GetGUID()); // target GUID
4865  data << uint8(missInfo);
4866  // end loop
4867  SendMessageToSet(&data, true);
4868 }
4869 
4871 {
4872  WorldPacket data(SMSG_SPELLORDAMAGE_IMMUNE, 8 + 8 + 4 + 1);
4873  data << uint64(GetGUID());
4874  data << uint64(target->GetGUID());
4875  data << uint32(spellId);
4876  data << uint8(0); // bool - log format: 0-default, 1-debug
4877  SendMessageToSet(&data, true);
4878 }
4879 
4881 {
4882  WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16 + 84)); // we guess size
4883  data << (uint32)damageInfo->HitInfo;
4884  data << GetPackGUID();
4885  data << damageInfo->target->GetPackGUID();
4886  data << (uint32)(damageInfo->damage); // Full damage
4887 
4888  data << (uint8)1; // Sub damage count
4889  //=== Sub damage description
4890  data << (uint32)(damageInfo->damageSchoolMask); // School of sub damage
4891  data << (float)damageInfo->damage; // sub damage
4892  data << (uint32)damageInfo->damage; // Sub Damage
4893  data << (uint32)damageInfo->absorb; // Absorb
4894  data << (uint32)damageInfo->resist; // Resist
4895  //=================================================
4896  data << (uint32)damageInfo->TargetState;
4897  data << (uint32)0;
4898  data << (uint32)0;
4899  data << (uint32)damageInfo->blocked_amount;
4900  SendMessageToSet(&data, true);
4901 }
4902 
4903 void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount)
4904 {
4905  DEBUG_LOG("WORLD: Sending SMSG_ATTACKERSTATEUPDATE");
4906 
4907  WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16 + 45)); // we guess size
4908  data << (uint32)HitInfo;
4909  data << GetPackGUID();
4910  data << target->GetPackGUID();
4911  data << (uint32)(Damage - AbsorbDamage - Resist - BlockedAmount);
4912 
4913  data << (uint8)SwingType; // count?
4914 
4915  // for (i = 0; i < SwingType; ++i)
4916  data << (uint32)damageSchoolMask;
4917  data << (float)(Damage - AbsorbDamage - Resist - BlockedAmount);
4918  // still need to double check damage
4919  data << (uint32)(Damage - AbsorbDamage - Resist - BlockedAmount);
4920  data << (uint32)AbsorbDamage;
4921  data << (uint32)Resist;
4922  // end loop
4923 
4924  data << (uint32)TargetState;
4925 
4926  if (AbsorbDamage == 0) //also 0x3E8 = 0x3E8, check when that happens
4927  data << (uint32)0;
4928  else
4929  data << (uint32) - 1;
4930 
4931  data << (uint32)0;
4932  data << (uint32)BlockedAmount;
4933 
4934  SendMessageToSet(&data, true);
4935 }
4936 
4937 bool Unit::HandleHasteAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellEntry const* /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown)
4938 {
4939  SpellEntry const* hasteSpell = triggeredByAura->GetSpellProto();
4940 
4941  Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
4942  ? ToPlayer()->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
4943 
4944  uint32 triggered_spell_id = 0;
4945  Unit* target = victim;
4946  int32 basepoints0 = 0;
4947 
4948  switch (hasteSpell->SpellFamilyName)
4949  {
4950  case SPELLFAMILY_ROGUE:
4951  {
4952  switch (hasteSpell->Id)
4953  {
4954  // Blade Flurry
4955  case 13877:
4956  case 33735:
4957  {
4958  target = SelectNearbyTarget(victim);
4959  if (!target)
4960  return false;
4961  basepoints0 = damage;
4962  triggered_spell_id = 22482;
4963  break;
4964  }
4965  }
4966  break;
4967  }
4968  }
4969 
4970  // processed charge only counting case
4971  if (!triggered_spell_id)
4972  return true;
4973 
4974  SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id);
4975 
4976  if (!triggerEntry)
4977  {
4978  sLog.outError("Unit::HandleHasteAuraProc: Spell %u has invalid triggered spell %u", hasteSpell->Id, triggered_spell_id);
4979  return false;
4980  }
4981 
4982  // default case
4983  if (!target || (target != this && !target->IsAlive()))
4984  return false;
4985 
4986  if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(triggered_spell_id))
4987  return false;
4988 
4989  if (basepoints0)
4990  CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
4991  else
4992  CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura);
4993 
4994  if (cooldown && GetTypeId() == TYPEID_PLAYER)
4995  ToPlayer()->AddSpellCooldown(triggered_spell_id, 0, time(NULL) + cooldown);
4996 
4997  return true;
4998 }
4999 
5000 bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 /*procFlag*/, uint32 procEx, uint32 cooldown)
5001 {
5002  SpellEntry const* dummySpell = triggeredByAura->GetSpellProto();
5003  uint32 effIndex = triggeredByAura->GetEffIndex();
5004 
5005  Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId() == TYPEID_PLAYER
5006  ? ToPlayer()->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
5007 
5008  uint32 triggered_spell_id = 0;