[8023] Move guardian list at Unit level and unsummon guardians at owner-creature...
[getmangos.git] / src / game / Unit.cpp
blob1a9a38748d4416761d90fe1494b629bc67eb8274
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Log.h"
21 #include "Opcodes.h"
22 #include "WorldPacket.h"
23 #include "WorldSession.h"
24 #include "World.h"
25 #include "ObjectMgr.h"
26 #include "SpellMgr.h"
27 #include "Unit.h"
28 #include "QuestDef.h"
29 #include "Player.h"
30 #include "Creature.h"
31 #include "Spell.h"
32 #include "Group.h"
33 #include "SpellAuras.h"
34 #include "MapManager.h"
35 #include "ObjectAccessor.h"
36 #include "CreatureAI.h"
37 #include "Formulas.h"
38 #include "Pet.h"
39 #include "Util.h"
40 #include "Totem.h"
41 #include "BattleGround.h"
42 #include "InstanceSaveMgr.h"
43 #include "GridNotifiersImpl.h"
44 #include "CellImpl.h"
45 #include "Path.h"
46 #include "Traveller.h"
48 #include <math.h>
50 float baseMoveSpeed[MAX_MOVE_TYPE] =
52 2.5f, // MOVE_WALK
53 7.0f, // MOVE_RUN
54 1.25f, // MOVE_RUN_BACK
55 4.722222f, // MOVE_SWIM
56 4.5f, // MOVE_SWIM_BACK
57 3.141594f, // MOVE_TURN_RATE
58 7.0f, // MOVE_FLIGHT
59 4.5f, // MOVE_FLIGHT_BACK
60 3.14f // MOVE_PITCH_RATE
63 // Used for prepare can/can`t triggr aura
64 static bool InitTriggerAuraData();
65 // Define can trigger auras
66 static bool isTriggerAura[TOTAL_AURAS];
67 // Define can`t trigger auras (need for disable second trigger)
68 static bool isNonTriggerAura[TOTAL_AURAS];
69 // Prepare lists
70 static bool procPrepared = InitTriggerAuraData();
72 Unit::Unit()
73 : WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this)
75 m_objectType |= TYPEMASK_UNIT;
76 m_objectTypeId = TYPEID_UNIT;
78 m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION);
80 m_attackTimer[BASE_ATTACK] = 0;
81 m_attackTimer[OFF_ATTACK] = 0;
82 m_attackTimer[RANGED_ATTACK] = 0;
83 m_modAttackSpeedPct[BASE_ATTACK] = 1.0f;
84 m_modAttackSpeedPct[OFF_ATTACK] = 1.0f;
85 m_modAttackSpeedPct[RANGED_ATTACK] = 1.0f;
87 m_extraAttacks = 0;
89 m_state = 0;
90 m_form = FORM_NONE;
91 m_deathState = ALIVE;
93 for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
94 m_currentSpells[i] = NULL;
96 m_addDmgOnce = 0;
98 for(int i = 0; i < MAX_TOTEM; ++i)
99 m_TotemSlot[i] = 0;
101 m_ObjectSlot[0] = m_ObjectSlot[1] = m_ObjectSlot[2] = m_ObjectSlot[3] = 0;
102 //m_Aura = NULL;
103 //m_AurasCheck = 2000;
104 //m_removeAuraTimer = 4;
105 //tmpAura = NULL;
107 m_Visibility = VISIBILITY_ON;
109 m_detectInvisibilityMask = 0;
110 m_invisibilityMask = 0;
111 m_transform = 0;
112 m_ShapeShiftFormSpellId = 0;
113 m_canModifyStats = false;
115 for (int i = 0; i < MAX_SPELL_IMMUNITY; ++i)
116 m_spellImmune[i].clear();
117 for (int i = 0; i < UNIT_MOD_END; ++i)
119 m_auraModifiersGroup[i][BASE_VALUE] = 0.0f;
120 m_auraModifiersGroup[i][BASE_PCT] = 1.0f;
121 m_auraModifiersGroup[i][TOTAL_VALUE] = 0.0f;
122 m_auraModifiersGroup[i][TOTAL_PCT] = 1.0f;
124 // implement 50% base damage from offhand
125 m_auraModifiersGroup[UNIT_MOD_DAMAGE_OFFHAND][TOTAL_PCT] = 0.5f;
127 for (int i = 0; i < MAX_ATTACK; ++i)
129 m_weaponDamage[i][MINDAMAGE] = BASE_MINDAMAGE;
130 m_weaponDamage[i][MAXDAMAGE] = BASE_MAXDAMAGE;
132 for (int i = 0; i < MAX_STATS; ++i)
133 m_createStats[i] = 0.0f;
135 m_attacking = NULL;
136 m_modMeleeHitChance = 0.0f;
137 m_modRangedHitChance = 0.0f;
138 m_modSpellHitChance = 0.0f;
139 m_baseSpellCritChance = 5;
141 m_CombatTimer = 0;
142 m_lastManaUse = 0;
144 //m_victimThreat = 0.0f;
145 for (int i = 0; i < MAX_SPELL_SCHOOL; ++i)
146 m_threatModifier[i] = 1.0f;
147 m_isSorted = true;
148 for (int i = 0; i < MAX_MOVE_TYPE; ++i)
149 m_speed_rate[i] = 1.0f;
151 m_removedAuras = 0;
152 m_charmInfo = NULL;
153 m_unit_movement_flags = 0;
155 // remove aurastates allowing special moves
156 for(int i=0; i < MAX_REACTIVE; ++i)
157 m_reactiveTimer[i] = 0;
160 Unit::~Unit()
162 // set current spells as deletable
163 for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
165 if (m_currentSpells[i])
167 m_currentSpells[i]->SetReferencedFromCurrent(false);
168 m_currentSpells[i] = NULL;
172 RemoveAllGameObjects();
173 RemoveAllDynObjects();
175 if(m_charmInfo) delete m_charmInfo;
178 void Unit::Update( uint32 p_time )
180 /*if(p_time > m_AurasCheck)
182 m_AurasCheck = 2000;
183 _UpdateAura();
184 }else
185 m_AurasCheck -= p_time;*/
187 // WARNING! Order of execution here is important, do not change.
188 // Spells must be processed with event system BEFORE they go to _UpdateSpells.
189 // Or else we may have some SPELL_STATE_FINISHED spells stalled in pointers, that is bad.
190 m_Events.Update( p_time );
191 _UpdateSpells( p_time );
193 // update combat timer only for players and pets
194 if (isInCombat() && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet() || ((Creature*)this)->isCharmed()))
196 // Check UNIT_STAT_MELEE_ATTACKING or UNIT_STAT_CHASE (without UNIT_STAT_FOLLOW in this case) so pets can reach far away
197 // targets without stopping half way there and running off.
198 // These flags are reset after target dies or another command is given.
199 if( m_HostilRefManager.isEmpty() )
201 // m_CombatTimer set at aura start and it will be freeze until aura removing
202 if ( m_CombatTimer <= p_time )
203 ClearInCombat();
204 else
205 m_CombatTimer -= p_time;
209 if(uint32 base_att = getAttackTimer(BASE_ATTACK))
211 setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time) );
214 // update abilities available only for fraction of time
215 UpdateReactives( p_time );
217 ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth()*0.20f);
218 ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f);
219 ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth()*0.75f);
221 i_motionMaster.UpdateMotion(p_time);
224 bool Unit::haveOffhandWeapon() const
226 if(GetTypeId() == TYPEID_PLAYER)
227 return ((Player*)this)->GetWeaponForAttack(OFF_ATTACK,true);
228 else
229 return false;
232 void Unit::SendMonsterMoveWithSpeedToCurrentDestination(Player* player)
234 float x, y, z;
235 if(GetMotionMaster()->GetDestination(x, y, z))
236 SendMonsterMoveWithSpeed(x, y, z, 0, player);
239 void Unit::SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime, Player* player)
241 if (!transitTime)
243 if(GetTypeId()==TYPEID_PLAYER)
245 Traveller<Player> traveller(*(Player*)this);
246 transitTime = traveller.GetTotalTrevelTimeTo(x,y,z);
248 else
250 Traveller<Creature> traveller(*(Creature*)this);
251 transitTime = traveller.GetTotalTrevelTimeTo(x,y,z);
254 //float orientation = (float)atan2((double)dy, (double)dx);
255 SendMonsterMove(x, y, z, 0, GetUnitMovementFlags(), transitTime, player);
258 void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player)
260 float moveTime = Time;
262 WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) );
263 data.append(GetPackGUID());
264 data << uint8(0); // new in 3.1
265 data << GetPositionX() << GetPositionY() << GetPositionZ();
266 data << uint32(getMSTime());
268 data << uint8(type); // unknown
269 switch(type)
271 case 0: // normal packet
272 break;
273 case 1: // stop packet (raw pos?)
274 SendMessageToSet( &data, true );
275 return;
276 case 2: // facing spot, not used currently
277 data << float(0);
278 data << float(0);
279 data << float(0);
280 break;
281 case 3: // not used currently
282 data << uint64(0); // probably target guid (facing target?)
283 break;
284 case 4: // not used currently
285 data << float(0); // facing angle
286 break;
289 data << uint32(MovementFlags);
291 if(MovementFlags & MONSTER_MOVE_WALK)
292 moveTime *= 1.05f;
294 data << uint32(moveTime); // Time in between points
295 data << uint32(1); // 1 single waypoint
296 data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B
298 if(player)
299 player->GetSession()->SendPacket(&data);
300 else
301 SendMessageToSet( &data, true );
304 void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags)
306 uint32 traveltime = uint32(path.GetTotalLength(start, end) * 32);
308 uint32 pathSize = end - start;
310 WorldPacket data( SMSG_MONSTER_MOVE, (GetPackGUID().size()+1+4+4+4+4+1+4+4+4+pathSize*4*3) );
311 data.append(GetPackGUID());
312 data << uint8(0);
313 data << GetPositionX();
314 data << GetPositionY();
315 data << GetPositionZ();
316 data << uint32(getMSTime());
317 data << uint8( 0 );
318 data << uint32( MovementFlags );
319 data << uint32( traveltime );
320 data << uint32( pathSize );
321 data.append( (char*)path.GetNodes(start), pathSize * 4 * 3 );
322 SendMessageToSet(&data, true);
325 void Unit::resetAttackTimer(WeaponAttackType type)
327 m_attackTimer[type] = uint32(GetAttackTime(type) * m_modAttackSpeedPct[type]);
330 bool Unit::canReachWithAttack(Unit *pVictim) const
332 assert(pVictim);
333 float reach = GetFloatValue(UNIT_FIELD_COMBATREACH);
334 if( reach <= 0.0f )
335 reach = 1.0f;
336 return IsWithinDistInMap(pVictim, reach);
339 void Unit::RemoveSpellsCausingAura(AuraType auraType)
341 if (auraType >= TOTAL_AURAS) return;
342 AuraList::const_iterator iter, next;
343 for (iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end(); iter = next)
345 next = iter;
346 ++next;
348 if (*iter)
350 RemoveAurasDueToSpell((*iter)->GetId());
351 if (!m_modAuras[auraType].empty())
352 next = m_modAuras[auraType].begin();
353 else
354 return;
359 bool Unit::HasAuraType(AuraType auraType) const
361 return (!m_modAuras[auraType].empty());
364 /* Called by DealDamage for auras that have a chance to be dispelled on damage taken. */
365 void Unit::RemoveSpellbyDamageTaken(AuraType auraType, uint32 damage)
367 if(!HasAuraType(auraType))
368 return;
370 // The chance to dispel an aura depends on the damage taken with respect to the casters level.
371 uint32 max_dmg = getLevel() > 8 ? 25 * getLevel() - 150 : 50;
372 float chance = float(damage) / max_dmg * 100.0f;
373 if (roll_chance_f(chance))
374 RemoveSpellsCausingAura(auraType);
377 void Unit::DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb)
379 if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
381 if(absorb)
382 absorb += damage;
383 damage = 0;
384 return;
387 //You don't lose health from damage taken from another player while in a sanctuary
388 //You still see it in the combat log though
389 if(pVictim != this && GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
391 const AreaTableEntry *area = GetAreaEntryByAreaID(pVictim->GetAreaId());
392 if(area && area->flags & AREA_FLAG_SANCTUARY) //sanctuary
394 if(absorb)
395 absorb += damage;
396 damage = 0;
400 uint32 originalDamage = damage;
402 //Script Event damage Deal
403 if( GetTypeId()== TYPEID_UNIT && ((Creature *)this)->AI())
404 ((Creature *)this)->AI()->DamageDeal(pVictim, damage);
405 //Script Event damage taken
406 if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() )
407 ((Creature *)pVictim)->AI()->DamageTaken(this, damage);
409 if(absorb && originalDamage > damage)
410 absorb += (originalDamage - damage);
413 uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss)
415 // remove affects from victim (including from 0 damage and DoTs)
416 if(pVictim != this)
417 pVictim->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
419 // remove affects from attacker at any non-DoT damage (including 0 damage)
420 if( damagetype != DOT)
422 RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
423 RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
425 if(pVictim != this)
426 RemoveSpellsCausingAura(SPELL_AURA_MOD_INVISIBILITY);
428 if(pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->IsStandState() && !pVictim->hasUnitState(UNIT_STAT_STUNNED))
429 pVictim->SetStandState(UNIT_STAND_STATE_STAND);
432 if(!damage)
434 // Rage from physical damage received .
435 if(cleanDamage && cleanDamage->damage && (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) && pVictim->GetTypeId() == TYPEID_PLAYER && (pVictim->getPowerType() == POWER_RAGE))
436 ((Player*)pVictim)->RewardRage(cleanDamage->damage, 0, false);
438 return 0;
440 if (!spellProto || !IsAuraAddedBySpell(SPELL_AURA_MOD_FEAR, spellProto->Id))
441 pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_FEAR, damage);
442 // root type spells do not dispel the root effect
443 if (!spellProto || !(spellProto->Mechanic == MECHANIC_ROOT || IsAuraAddedBySpell(SPELL_AURA_MOD_ROOT, spellProto->Id)))
444 pVictim->RemoveSpellbyDamageTaken(SPELL_AURA_MOD_ROOT, damage);
446 // no xp,health if type 8 /critters/
447 if(pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() == CREATURE_TYPE_CRITTER)
449 pVictim->setDeathState(JUST_DIED);
450 pVictim->SetHealth(0);
452 // allow loot only if has loot_id in creature_template
453 CreatureInfo const* cInfo = ((Creature*)pVictim)->GetCreatureInfo();
454 if(cInfo && cInfo->lootid)
455 pVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
457 // some critters required for quests
458 if(GetTypeId() == TYPEID_PLAYER)
459 ((Player*)this)->KilledMonster(pVictim->GetEntry(),pVictim->GetGUID());
461 return damage;
464 DEBUG_LOG("DealDamageStart");
466 uint32 health = pVictim->GetHealth();
467 sLog.outDetail("deal dmg:%d to health:%d ",damage,health);
469 // duel ends when player has 1 or less hp
470 bool duel_hasEnded = false;
471 if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->duel && damage >= (health-1))
473 // prevent kill only if killed in duel and killed by opponent or opponent controlled creature
474 if(((Player*)pVictim)->duel->opponent==this || ((Player*)pVictim)->duel->opponent->GetGUID() == GetOwnerGUID())
475 damage = health-1;
477 duel_hasEnded = true;
479 //Get in CombatState
480 if(pVictim != this && damagetype != DOT)
482 SetInCombatWith(pVictim);
483 pVictim->SetInCombatWith(this);
485 if(Player* attackedPlayer = pVictim->GetCharmerOrOwnerPlayerOrPlayerItself())
486 SetContestedPvP(attackedPlayer);
489 // Rage from Damage made (only from direct weapon damage)
490 if( cleanDamage && damagetype==DIRECT_DAMAGE && this != pVictim && GetTypeId() == TYPEID_PLAYER && (getPowerType() == POWER_RAGE))
492 uint32 weaponSpeedHitFactor;
494 switch(cleanDamage->attackType)
496 case BASE_ATTACK:
498 if(cleanDamage->hitOutCome == MELEE_HIT_CRIT)
499 weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 7);
500 else
501 weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 3.5f);
503 ((Player*)this)->RewardRage(damage, weaponSpeedHitFactor, true);
505 break;
507 case OFF_ATTACK:
509 if(cleanDamage->hitOutCome == MELEE_HIT_CRIT)
510 weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 3.5f);
511 else
512 weaponSpeedHitFactor = uint32(GetAttackTime(cleanDamage->attackType)/1000.0f * 1.75f);
514 ((Player*)this)->RewardRage(damage, weaponSpeedHitFactor, true);
516 break;
518 case RANGED_ATTACK:
519 break;
523 if (GetTypeId() == TYPEID_PLAYER && this != pVictim)
525 Player *killer = ((Player*)this);
527 // in bg, count dmg if victim is also a player
528 if (pVictim->GetTypeId()==TYPEID_PLAYER)
530 if (BattleGround *bg = killer->GetBattleGround())
532 // FIXME: kept by compatibility. don't know in BG if the restriction apply.
533 bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage);
537 killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, damage, 0, pVictim);
538 killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage);
541 if (pVictim->GetTypeId() == TYPEID_PLAYER)
542 ((Player*)pVictim)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED, damage);
544 if (pVictim->GetTypeId() == TYPEID_UNIT && !((Creature*)pVictim)->isPet() && !((Creature*)pVictim)->hasLootRecipient())
545 ((Creature*)pVictim)->SetLootRecipient(this);
547 if (health <= damage)
549 DEBUG_LOG("DealDamage: victim just died");
551 if (pVictim->GetTypeId() == TYPEID_PLAYER)
552 ((Player*)pVictim)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health);
554 // find player: owner of controlled `this` or `this` itself maybe
555 Player *player = GetCharmerOrOwnerPlayerOrPlayerItself();
557 if(pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->GetLootRecipient())
558 player = ((Creature*)pVictim)->GetLootRecipient();
559 // Reward player, his pets, and group/raid members
560 // call kill spell proc event (before real die and combat stop to triggering auras removed at death/combat stop)
561 if(player && player!=pVictim)
563 player->RewardPlayerAndGroupAtKill(pVictim);
564 player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0);
567 DEBUG_LOG("DealDamageAttackStop");
569 // stop combat
570 pVictim->CombatStop();
571 pVictim->getHostilRefManager().deleteReferences();
573 bool damageFromSpiritOfRedemtionTalent = spellProto && spellProto->Id == 27795;
575 // if talent known but not triggered (check priest class for speedup check)
576 Aura* spiritOfRedemtionTalentReady = NULL;
577 if( !damageFromSpiritOfRedemtionTalent && // not called from SPELL_AURA_SPIRIT_OF_REDEMPTION
578 pVictim->GetTypeId()==TYPEID_PLAYER && pVictim->getClass()==CLASS_PRIEST )
580 AuraList const& vDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
581 for(AuraList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr)
583 if((*itr)->GetSpellProto()->SpellIconID==1654)
585 spiritOfRedemtionTalentReady = *itr;
586 break;
591 DEBUG_LOG("SET JUST_DIED");
592 if(!spiritOfRedemtionTalentReady)
593 pVictim->setDeathState(JUST_DIED);
595 DEBUG_LOG("DealDamageHealth1");
597 if(spiritOfRedemtionTalentReady)
599 // save value before aura remove
600 uint32 ressSpellId = pVictim->GetUInt32Value(PLAYER_SELF_RES_SPELL);
601 if(!ressSpellId)
602 ressSpellId = ((Player*)pVictim)->GetResurrectionSpellId();
604 //Remove all expected to remove at death auras (most important negative case like DoT or periodic triggers)
605 pVictim->RemoveAllAurasOnDeath();
607 // restore for use at real death
608 pVictim->SetUInt32Value(PLAYER_SELF_RES_SPELL,ressSpellId);
610 // FORM_SPIRITOFREDEMPTION and related auras
611 pVictim->CastSpell(pVictim,27827,true,NULL,spiritOfRedemtionTalentReady);
613 else
614 pVictim->SetHealth(0);
616 // remember victim PvP death for corpse type and corpse reclaim delay
617 // at original death (not at SpiritOfRedemtionTalent timeout)
618 if( pVictim->GetTypeId()==TYPEID_PLAYER && !damageFromSpiritOfRedemtionTalent )
619 ((Player*)pVictim)->SetPvPDeath(player!=NULL);
621 // Call KilledUnit for creatures
622 if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI())
623 ((Creature*)this)->AI()->KilledUnit(pVictim);
625 // achievement stuff
626 if (pVictim->GetTypeId() == TYPEID_PLAYER)
628 if (GetTypeId() == TYPEID_UNIT)
629 ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
630 else if(GetTypeId() == TYPEID_PLAYER && pVictim != this)
631 ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ((Player*)this)->GetTeam());
634 // 10% durability loss on death
635 // clean InHateListOf
636 if (pVictim->GetTypeId() == TYPEID_PLAYER)
638 // only if not player and not controlled by player pet. And not at BG
639 if (durabilityLoss && !player && !((Player*)pVictim)->InBattleGround())
641 DEBUG_LOG("We are dead, loosing 10 percents durability");
642 ((Player*)pVictim)->DurabilityLossAll(0.10f,false);
643 // durability lost message
644 WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0);
645 ((Player*)pVictim)->GetSession()->SendPacket(&data);
648 else // creature died
650 DEBUG_LOG("DealDamageNotPlayer");
651 Creature *cVictim = (Creature*)pVictim;
653 if(!cVictim->isPet())
655 cVictim->DeleteThreatList();
656 cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
658 // Call creature just died function
659 if (cVictim->AI())
660 cVictim->AI()->JustDied(this);
662 // Dungeon specific stuff, only applies to players killing creatures
663 if(cVictim->GetInstanceId())
665 Map *m = cVictim->GetMap();
666 Player *creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself();
667 // TODO: do instance binding anyway if the charmer/owner is offline
669 if(m->IsDungeon() && creditedPlayer)
671 if(m->IsRaid() || m->IsHeroic())
673 if(cVictim->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
674 ((InstanceMap *)m)->PermBindAllPlayers(creditedPlayer);
676 else
678 // the reset time is set but not added to the scheduler
679 // until the players leave the instance
680 time_t resettime = cVictim->GetRespawnTimeEx() + 2 * HOUR;
681 if(InstanceSave *save = sInstanceSaveManager.GetInstanceSave(cVictim->GetInstanceId()))
682 if(save->GetResetTime() < resettime) save->SetResetTime(resettime);
688 // last damage from non duel opponent or opponent controlled creature
689 if(duel_hasEnded)
691 assert(pVictim->GetTypeId()==TYPEID_PLAYER);
692 Player *he = (Player*)pVictim;
694 assert(he->duel);
696 he->duel->opponent->CombatStopWithPets(true);
697 he->CombatStopWithPets(true);
699 he->DuelComplete(DUEL_INTERUPTED);
702 // battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill)
703 if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->InBattleGround())
705 Player *killed = ((Player*)pVictim);
706 if(BattleGround *bg = killed->GetBattleGround())
707 if(player)
708 bg->HandleKillPlayer(killed, player);
709 //later we can add support for creature->player kills here i'm
710 //not sure, but i guess those kills also get counted in av
711 //else if(GetTypeId() == TYPEID_UNIT)
712 // bg->HandleKillPlayer(killed,(Creature*)this);
715 else // if (health <= damage)
717 DEBUG_LOG("DealDamageAlive");
719 if (pVictim->GetTypeId() == TYPEID_PLAYER)
720 ((Player*)pVictim)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, damage);
722 pVictim->ModifyHealth(- (int32)damage);
724 if(damagetype != DOT)
726 if(!getVictim())
728 // if not have main target then attack state with target (including AI call)
729 //start melee attacks only after melee hit
730 Attack(pVictim,(damagetype == DIRECT_DAMAGE));
733 // if damage pVictim call AI reaction
734 if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI())
735 ((Creature*)pVictim)->AI()->AttackedBy(this);
738 // polymorphed and other negative transformed cases
739 if(pVictim->getTransForm() && pVictim->hasUnitState(UNIT_STAT_CONFUSED))
740 pVictim->RemoveAurasDueToSpell(pVictim->getTransForm());
742 if(damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE)
744 if (!spellProto || !(spellProto->AuraInterruptFlags&AURA_INTERRUPT_FLAG_DIRECT_DAMAGE))
745 pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE);
747 if (pVictim->GetTypeId() != TYPEID_PLAYER)
749 if(spellProto && IsDamageToThreatSpell(spellProto))
750 pVictim->AddThreat(this, damage*2, damageSchoolMask, spellProto);
751 else
752 pVictim->AddThreat(this, damage, damageSchoolMask, spellProto);
754 else // victim is a player
756 // Rage from damage received
757 if(this != pVictim && pVictim->getPowerType() == POWER_RAGE)
759 uint32 rage_damage = damage + (cleanDamage ? cleanDamage->damage : 0);
760 ((Player*)pVictim)->RewardRage(rage_damage, 0, false);
763 // random durability for items (HIT TAKEN)
764 if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_DAMAGE)))
766 EquipmentSlots slot = EquipmentSlots(urand(0,EQUIPMENT_SLOT_END-1));
767 ((Player*)pVictim)->DurabilityPointLossForEquipSlot(slot);
771 if(GetTypeId()==TYPEID_PLAYER)
773 // random durability for items (HIT DONE)
774 if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_DAMAGE)))
776 EquipmentSlots slot = EquipmentSlots(urand(0,EQUIPMENT_SLOT_END-1));
777 ((Player*)this)->DurabilityPointLossForEquipSlot(slot);
781 // TODO: Store auras by interrupt flag to speed this up.
782 AuraMap& vAuras = pVictim->GetAuras();
783 for (AuraMap::const_iterator i = vAuras.begin(), next; i != vAuras.end(); i = next)
785 const SpellEntry *se = i->second->GetSpellProto();
786 next = i; ++next;
787 if (spellProto && spellProto->Id == se->Id) // Not drop auras added by self
788 continue;
789 if( se->AuraInterruptFlags & AURA_INTERRUPT_FLAG_DAMAGE )
791 bool remove = true;
792 if (se->procFlags & (1<<3))
794 if (!roll_chance_i(se->procChance))
795 remove = false;
797 if (remove)
799 pVictim->RemoveAurasDueToSpell(i->second->GetId());
800 // FIXME: this may cause the auras with proc chance to be rerolled several times
801 next = vAuras.begin();
806 if (damagetype != NODAMAGE && damage && pVictim->GetTypeId() == TYPEID_PLAYER)
808 if( damagetype != DOT )
810 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
812 // skip channeled spell (processed differently below)
813 if (i == CURRENT_CHANNELED_SPELL)
814 continue;
816 if(Spell* spell = pVictim->m_currentSpells[i])
817 if(spell->getState() == SPELL_STATE_PREPARING)
819 if(spell->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_ABORT_ON_DMG)
820 pVictim->InterruptSpell(i);
821 else
822 spell->Delayed();
827 if(Spell* spell = pVictim->m_currentSpells[CURRENT_CHANNELED_SPELL])
829 if (spell->getState() == SPELL_STATE_CASTING)
831 uint32 channelInterruptFlags = spell->m_spellInfo->ChannelInterruptFlags;
832 if( channelInterruptFlags & CHANNEL_FLAG_DELAY )
834 if(pVictim!=this) //don't shorten the duration of channeling if you damage yourself
835 spell->DelayedChannel();
837 else if( (channelInterruptFlags & (CHANNEL_FLAG_DAMAGE | CHANNEL_FLAG_DAMAGE2)) )
839 sLog.outDetail("Spell %u canceled at damage!",spell->m_spellInfo->Id);
840 pVictim->InterruptSpell(CURRENT_CHANNELED_SPELL);
843 else if (spell->getState() == SPELL_STATE_DELAYED)
844 // break channeled spell in delayed state on damage
846 sLog.outDetail("Spell %u canceled at damage!",spell->m_spellInfo->Id);
847 pVictim->InterruptSpell(CURRENT_CHANNELED_SPELL);
852 // last damage from duel opponent
853 if(duel_hasEnded)
855 assert(pVictim->GetTypeId()==TYPEID_PLAYER);
856 Player *he = (Player*)pVictim;
858 assert(he->duel);
860 he->SetHealth(1);
862 he->duel->opponent->CombatStopWithPets(true);
863 he->CombatStopWithPets(true);
865 he->CastSpell(he, 7267, true); // beg
866 he->DuelComplete(DUEL_WON);
870 DEBUG_LOG("DealDamageEnd returned %d damage", damage);
872 return damage;
875 void Unit::CastStop(uint32 except_spellid)
877 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
878 if (m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id!=except_spellid)
879 InterruptSpell(i,false);
882 void Unit::CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem, Aura* triggeredByAura, uint64 originalCaster)
884 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
886 if(!spellInfo)
888 sLog.outError("CastSpell: unknown spell id %i by caster: %s %u)", spellId,(GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
889 return;
892 CastSpell(Victim,spellInfo,triggered,castItem,triggeredByAura, originalCaster);
895 void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem, Aura* triggeredByAura, uint64 originalCaster)
897 if(!spellInfo)
899 sLog.outError("CastSpell: unknown spell by caster: %s %u)", (GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
900 return;
903 if (castItem)
904 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
906 if(!originalCaster && triggeredByAura)
907 originalCaster = triggeredByAura->GetCasterGUID();
909 Spell *spell = new Spell(this, spellInfo, triggered, originalCaster );
911 SpellCastTargets targets;
912 targets.setUnitTarget( Victim );
913 spell->m_CastItem = castItem;
914 spell->prepare(&targets, triggeredByAura);
917 void Unit::CastCustomSpell(Unit* Victim,uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem, Aura* triggeredByAura, uint64 originalCaster)
919 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
921 if(!spellInfo)
923 sLog.outError("CastCustomSpell: unknown spell id %i", spellId);
924 return;
927 CastCustomSpell(Victim,spellInfo,bp0,bp1,bp2,triggered,castItem,triggeredByAura, originalCaster);
930 void Unit::CastCustomSpell(Unit* Victim,SpellEntry const *spellInfo, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem, Aura* triggeredByAura, uint64 originalCaster)
932 if(!spellInfo)
934 sLog.outError("CastCustomSpell: unknown spell");
935 return;
938 if (castItem)
939 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
941 if(!originalCaster && triggeredByAura)
942 originalCaster = triggeredByAura->GetCasterGUID();
944 Spell *spell = new Spell(this, spellInfo, triggered, originalCaster);
946 if(bp0)
947 spell->m_currentBasePoints[0] = *bp0-int32(spellInfo->EffectBaseDice[0]);
949 if(bp1)
950 spell->m_currentBasePoints[1] = *bp1-int32(spellInfo->EffectBaseDice[1]);
952 if(bp2)
953 spell->m_currentBasePoints[2] = *bp2-int32(spellInfo->EffectBaseDice[2]);
955 SpellCastTargets targets;
956 targets.setUnitTarget( Victim );
957 spell->m_CastItem = castItem;
958 spell->prepare(&targets, triggeredByAura);
961 // used for scripting
962 void Unit::CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem, Aura* triggeredByAura, uint64 originalCaster)
964 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
966 if(!spellInfo)
968 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()));
969 return;
972 CastSpell(x, y, z,spellInfo,triggered,castItem,triggeredByAura, originalCaster);
975 // used for scripting
976 void Unit::CastSpell(float x, float y, float z, SpellEntry const *spellInfo, bool triggered, Item *castItem, Aura* triggeredByAura, uint64 originalCaster)
978 if(!spellInfo)
980 sLog.outError("CastSpell(x,y,z): unknown spell by caster: %s %u)", (GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
981 return;
984 if (castItem)
985 DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
987 if(!originalCaster && triggeredByAura)
988 originalCaster = triggeredByAura->GetCasterGUID();
990 Spell *spell = new Spell(this, spellInfo, triggered, originalCaster );
992 SpellCastTargets targets;
993 targets.setDestination(x, y, z);
994 spell->m_CastItem = castItem;
995 spell->prepare(&targets, triggeredByAura);
998 // Obsolete func need remove, here only for comotability vs another patches
999 uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage)
1001 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID);
1002 SpellNonMeleeDamage damageInfo(this, pVictim, spellInfo->Id, spellInfo->SchoolMask);
1003 CalculateSpellDamage(&damageInfo, damage, spellInfo);
1004 DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
1005 SendSpellNonMeleeDamageLog(&damageInfo);
1006 DealSpellDamage(&damageInfo, true);
1007 return damageInfo.damage;
1010 void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType)
1012 SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask);
1013 Unit *pVictim = damageInfo->target;
1015 if (damage < 0)
1016 return;
1018 if(!this || !pVictim)
1019 return;
1020 if(!this->isAlive() || !pVictim->isAlive())
1021 return;
1023 uint32 crTypeMask = pVictim->GetCreatureTypeMask();
1024 // Check spell crit chance
1025 bool crit = isSpellCrit(pVictim, spellInfo, damageSchoolMask, attackType);
1026 bool blocked = false;
1027 // Per-school calc
1028 switch (spellInfo->DmgClass)
1030 // Melee and Ranged Spells
1031 case SPELL_DAMAGE_CLASS_RANGED:
1032 case SPELL_DAMAGE_CLASS_MELEE:
1034 // Physical Damage
1035 if ( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL )
1037 //Calculate armor mitigation
1038 damage = CalcArmorReducedDamage(pVictim, damage);
1039 // Get blocked status
1040 blocked = isSpellBlocked(pVictim, spellInfo, attackType);
1042 // Magical Damage
1043 else
1045 // Calculate damage bonus
1046 damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
1048 if (crit)
1050 damageInfo->HitInfo|= SPELL_HIT_TYPE_CRIT;
1052 // Calculate crit bonus
1053 uint32 crit_bonus = damage;
1054 // Apply crit_damage bonus for melee spells
1055 if(Player* modOwner = GetSpellModOwner())
1056 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
1057 damage += crit_bonus;
1059 // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
1060 int32 critPctDamageMod=0;
1061 if(attackType == RANGED_ATTACK)
1062 critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
1063 else
1065 critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
1066 critPctDamageMod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE);
1068 // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
1069 critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
1071 if (critPctDamageMod!=0)
1072 damage = int32((damage) * float((100.0f + critPctDamageMod)/100.0f));
1074 // Resilience - reduce crit damage
1075 if (pVictim->GetTypeId()==TYPEID_PLAYER)
1076 damage -= ((Player*)pVictim)->GetMeleeCritDamageReduction(damage);
1078 // Spell weapon based damage CAN BE crit & blocked at same time
1079 if (blocked)
1081 damageInfo->blocked = uint32(pVictim->GetShieldBlockValue());
1082 if (damage < damageInfo->blocked)
1083 damageInfo->blocked = damage;
1084 damage-=damageInfo->blocked;
1087 break;
1088 // Magical Attacks
1089 case SPELL_DAMAGE_CLASS_NONE:
1090 case SPELL_DAMAGE_CLASS_MAGIC:
1092 // Calculate damage bonus
1093 damage = SpellDamageBonus(pVictim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
1094 // If crit add critical bonus
1095 if (crit)
1097 damageInfo->HitInfo|= SPELL_HIT_TYPE_CRIT;
1098 damage = SpellCriticalDamageBonus(spellInfo, damage, pVictim);
1099 // Resilience - reduce crit damage
1100 if (pVictim->GetTypeId()==TYPEID_PLAYER)
1101 damage -= ((Player*)pVictim)->GetSpellCritDamageReduction(damage);
1104 break;
1107 // Calculate absorb resist
1108 if(damage > 0)
1110 // lookup absorb/resist ignore auras on caster for spell
1111 bool ignore = false;
1112 Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL);
1113 for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i)
1114 if ((*i)->isAffectedOnSpell(spellInfo))
1116 ignore = true;
1117 break;
1120 if (!ignore)
1122 CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist);
1123 damage-= damageInfo->absorb + damageInfo->resist;
1126 else
1127 damage = 0;
1128 damageInfo->damage = damage;
1131 void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
1133 if (damageInfo==0)
1134 return;
1136 Unit *pVictim = damageInfo->target;
1138 if(!this || !pVictim)
1139 return;
1141 if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
1142 return;
1144 SpellEntry const *spellProto = sSpellStore.LookupEntry(damageInfo->SpellID);
1145 if (spellProto == NULL)
1147 sLog.outDebug("Unit::DealSpellDamage have wrong damageInfo->SpellID: %u", damageInfo->SpellID);
1148 return;
1151 //You don't lose health from damage taken from another player while in a sanctuary
1152 //You still see it in the combat log though
1153 if(pVictim != this && GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
1155 const AreaTableEntry *area = GetAreaEntryByAreaID(pVictim->GetAreaId());
1156 if(area && area->flags & AREA_FLAG_SANCTUARY) // sanctuary
1157 return;
1160 // Call default DealDamage
1161 CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL);
1162 DealDamage(pVictim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
1165 //TODO for melee need create structure as in
1166 void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *damageInfo, WeaponAttackType attackType)
1168 damageInfo->attacker = this;
1169 damageInfo->target = pVictim;
1170 damageInfo->damageSchoolMask = GetMeleeDamageSchoolMask();
1171 damageInfo->attackType = attackType;
1172 damageInfo->damage = 0;
1173 damageInfo->cleanDamage = 0;
1174 damageInfo->absorb = 0;
1175 damageInfo->resist = 0;
1176 damageInfo->blocked_amount = 0;
1178 damageInfo->TargetState = 0;
1179 damageInfo->HitInfo = 0;
1180 damageInfo->procAttacker = PROC_FLAG_NONE;
1181 damageInfo->procVictim = PROC_FLAG_NONE;
1182 damageInfo->procEx = PROC_EX_NONE;
1183 damageInfo->hitOutCome = MELEE_HIT_EVADE;
1185 if(!this || !pVictim)
1186 return;
1187 if(!this->isAlive() || !pVictim->isAlive())
1188 return;
1190 // Select HitInfo/procAttacker/procVictim flag based on attack type
1191 switch (attackType)
1193 case BASE_ATTACK:
1194 damageInfo->procAttacker = PROC_FLAG_SUCCESSFUL_MILEE_HIT;
1195 damageInfo->procVictim = PROC_FLAG_TAKEN_MELEE_HIT;
1196 damageInfo->HitInfo = HITINFO_NORMALSWING2;
1197 break;
1198 case OFF_ATTACK:
1199 damageInfo->procAttacker = PROC_FLAG_SUCCESSFUL_MILEE_HIT | PROC_FLAG_SUCCESSFUL_OFFHAND_HIT;
1200 damageInfo->procVictim = PROC_FLAG_TAKEN_MELEE_HIT;//|PROC_FLAG_TAKEN_OFFHAND_HIT // not used
1201 damageInfo->HitInfo = HITINFO_LEFTSWING;
1202 break;
1203 case RANGED_ATTACK:
1204 damageInfo->procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_HIT;
1205 damageInfo->procVictim = PROC_FLAG_TAKEN_RANGED_HIT;
1206 damageInfo->HitInfo = 0x08;// test
1207 break;
1208 default:
1209 break;
1212 // Physical Immune check
1213 if(damageInfo->target->IsImmunedToDamage(SpellSchoolMask(damageInfo->damageSchoolMask)))
1215 damageInfo->HitInfo |= HITINFO_NORMALSWING;
1216 damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE;
1218 damageInfo->procEx |=PROC_EX_IMMUNE;
1219 damageInfo->damage = 0;
1220 damageInfo->cleanDamage = 0;
1221 return;
1223 damage += CalculateDamage (damageInfo->attackType, false);
1224 // Add melee damage bonus
1225 MeleeDamageBonus(damageInfo->target, &damage, damageInfo->attackType);
1226 // Calculate armor reduction
1227 damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage);
1228 damageInfo->cleanDamage += damage - damageInfo->damage;
1230 damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType);
1232 // Disable parry or dodge for ranged attack
1233 if(damageInfo->attackType == RANGED_ATTACK)
1235 if (damageInfo->hitOutCome == MELEE_HIT_PARRY) damageInfo->hitOutCome = MELEE_HIT_NORMAL;
1236 if (damageInfo->hitOutCome == MELEE_HIT_DODGE) damageInfo->hitOutCome = MELEE_HIT_MISS;
1239 switch(damageInfo->hitOutCome)
1241 case MELEE_HIT_EVADE:
1243 damageInfo->HitInfo |= HITINFO_MISS|HITINFO_SWINGNOHITSOUND;
1244 damageInfo->TargetState = VICTIMSTATE_EVADES;
1246 damageInfo->procEx|=PROC_EX_EVADE;
1247 damageInfo->damage = 0;
1248 damageInfo->cleanDamage = 0;
1249 return;
1251 case MELEE_HIT_MISS:
1253 damageInfo->HitInfo |= HITINFO_MISS;
1254 damageInfo->TargetState = VICTIMSTATE_NORMAL;
1256 damageInfo->procEx|=PROC_EX_MISS;
1257 damageInfo->damage = 0;
1258 damageInfo->cleanDamage = 0;
1259 break;
1261 case MELEE_HIT_NORMAL:
1262 damageInfo->TargetState = VICTIMSTATE_NORMAL;
1263 damageInfo->procEx|=PROC_EX_NORMAL_HIT;
1264 break;
1265 case MELEE_HIT_CRIT:
1267 damageInfo->HitInfo |= HITINFO_CRITICALHIT;
1268 damageInfo->TargetState = VICTIMSTATE_NORMAL;
1270 damageInfo->procEx|=PROC_EX_CRITICAL_HIT;
1271 // Crit bonus calc
1272 damageInfo->damage += damageInfo->damage;
1273 int32 mod=0;
1274 // Apply SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE or SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE
1275 if(damageInfo->attackType == RANGED_ATTACK)
1276 mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE);
1277 else
1279 mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE);
1280 mod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE);
1283 uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask();
1285 // Increase crit damage from SPELL_AURA_MOD_CRIT_PERCENT_VERSUS
1286 mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, crTypeMask);
1287 if (mod!=0)
1288 damageInfo->damage = int32((damageInfo->damage) * float((100.0f + mod)/100.0f));
1290 // Resilience - reduce crit damage
1291 if (pVictim->GetTypeId()==TYPEID_PLAYER)
1293 uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(damageInfo->damage);
1294 damageInfo->damage -= resilienceReduction;
1295 damageInfo->cleanDamage += resilienceReduction;
1297 break;
1299 case MELEE_HIT_PARRY:
1300 damageInfo->TargetState = VICTIMSTATE_PARRY;
1301 damageInfo->procEx|=PROC_EX_PARRY;
1302 damageInfo->cleanDamage += damageInfo->damage;
1303 damageInfo->damage = 0;
1304 break;
1306 case MELEE_HIT_DODGE:
1307 damageInfo->TargetState = VICTIMSTATE_DODGE;
1308 damageInfo->procEx|=PROC_EX_DODGE;
1309 damageInfo->cleanDamage += damageInfo->damage;
1310 damageInfo->damage = 0;
1311 break;
1312 case MELEE_HIT_BLOCK:
1314 damageInfo->TargetState = VICTIMSTATE_NORMAL;
1315 damageInfo->HitInfo |= HITINFO_BLOCK;
1316 damageInfo->procEx|=PROC_EX_BLOCK;
1317 damageInfo->blocked_amount = damageInfo->target->GetShieldBlockValue();
1318 if (damageInfo->blocked_amount >= damageInfo->damage)
1320 damageInfo->TargetState = VICTIMSTATE_BLOCKS;
1321 damageInfo->blocked_amount = damageInfo->damage;
1323 damageInfo->damage -= damageInfo->blocked_amount;
1324 damageInfo->cleanDamage += damageInfo->blocked_amount;
1325 break;
1327 case MELEE_HIT_GLANCING:
1329 damageInfo->HitInfo |= HITINFO_GLANCING;
1330 damageInfo->TargetState = VICTIMSTATE_NORMAL;
1331 damageInfo->procEx|=PROC_EX_NORMAL_HIT;
1332 float reducePercent = 1.0f; //damage factor
1333 // calculate base values and mods
1334 float baseLowEnd = 1.3f;
1335 float baseHighEnd = 1.2f;
1336 switch(getClass()) // lowering base values for casters
1338 case CLASS_SHAMAN:
1339 case CLASS_PRIEST:
1340 case CLASS_MAGE:
1341 case CLASS_WARLOCK:
1342 case CLASS_DRUID:
1343 baseLowEnd -= 0.7f;
1344 baseHighEnd -= 0.3f;
1345 break;
1348 float maxLowEnd = 0.6f;
1349 switch(getClass()) // upper for melee classes
1351 case CLASS_WARRIOR:
1352 case CLASS_ROGUE:
1353 maxLowEnd = 0.91f; //If the attacker is a melee class then instead the lower value of 0.91
1356 // calculate values
1357 int32 diff = damageInfo->target->GetDefenseSkillValue() - GetWeaponSkillValue(damageInfo->attackType);
1358 float lowEnd = baseLowEnd - ( 0.05f * diff );
1359 float highEnd = baseHighEnd - ( 0.03f * diff );
1361 // apply max/min bounds
1362 if ( lowEnd < 0.01f ) //the low end must not go bellow 0.01f
1363 lowEnd = 0.01f;
1364 else if ( lowEnd > maxLowEnd ) //the smaller value of this and 0.6 is kept as the low end
1365 lowEnd = maxLowEnd;
1367 if ( highEnd < 0.2f ) //high end limits
1368 highEnd = 0.2f;
1369 if ( highEnd > 0.99f )
1370 highEnd = 0.99f;
1372 if(lowEnd > highEnd) // prevent negative range size
1373 lowEnd = highEnd;
1375 reducePercent = lowEnd + rand_norm() * ( highEnd - lowEnd );
1377 damageInfo->cleanDamage += damageInfo->damage-uint32(reducePercent * damageInfo->damage);
1378 damageInfo->damage = uint32(reducePercent * damageInfo->damage);
1379 break;
1381 case MELEE_HIT_CRUSHING:
1383 damageInfo->HitInfo |= HITINFO_CRUSHING;
1384 damageInfo->TargetState = VICTIMSTATE_NORMAL;
1385 damageInfo->procEx|=PROC_EX_NORMAL_HIT;
1386 // 150% normal damage
1387 damageInfo->damage += (damageInfo->damage / 2);
1388 break;
1390 default:
1392 break;
1395 // Calculate absorb resist
1396 if(int32(damageInfo->damage) > 0)
1398 damageInfo->procVictim |= PROC_FLAG_TAKEN_ANY_DAMAGE;
1399 // Calculate absorb & resists
1400 CalcAbsorbResist(damageInfo->target, SpellSchoolMask(damageInfo->damageSchoolMask), DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist);
1401 damageInfo->damage-=damageInfo->absorb + damageInfo->resist;
1402 if (damageInfo->absorb)
1404 damageInfo->HitInfo|=HITINFO_ABSORB;
1405 damageInfo->procEx|=PROC_EX_ABSORB;
1407 if (damageInfo->resist)
1408 damageInfo->HitInfo|=HITINFO_RESIST;
1411 else // Umpossible get negative result but....
1412 damageInfo->damage = 0;
1415 void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss)
1417 if (damageInfo==0) return;
1418 Unit *pVictim = damageInfo->target;
1420 if(!this || !pVictim)
1421 return;
1423 if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
1424 return;
1426 //You don't lose health from damage taken from another player while in a sanctuary
1427 //You still see it in the combat log though
1428 if(pVictim != this && GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
1430 const AreaTableEntry *area = GetAreaEntryByAreaID(pVictim->GetAreaId());
1431 if(area && area->flags & AREA_FLAG_SANCTUARY) // sanctuary
1432 return;
1435 // Hmmmm dont like this emotes client must by self do all animations
1436 if (damageInfo->HitInfo&HITINFO_CRITICALHIT)
1437 pVictim->HandleEmoteCommand(EMOTE_ONESHOT_WOUNDCRITICAL);
1438 if(damageInfo->blocked_amount && damageInfo->TargetState!=VICTIMSTATE_BLOCKS)
1439 pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD);
1441 if(damageInfo->TargetState == VICTIMSTATE_PARRY)
1443 // Get attack timers
1444 float offtime = float(pVictim->getAttackTimer(OFF_ATTACK));
1445 float basetime = float(pVictim->getAttackTimer(BASE_ATTACK));
1446 // Reduce attack time
1447 if (pVictim->haveOffhandWeapon() && offtime < basetime)
1449 float percent20 = pVictim->GetAttackTime(OFF_ATTACK) * 0.20f;
1450 float percent60 = 3.0f * percent20;
1451 if(offtime > percent20 && offtime <= percent60)
1453 pVictim->setAttackTimer(OFF_ATTACK, uint32(percent20));
1455 else if(offtime > percent60)
1457 offtime -= 2.0f * percent20;
1458 pVictim->setAttackTimer(OFF_ATTACK, uint32(offtime));
1461 else
1463 float percent20 = pVictim->GetAttackTime(BASE_ATTACK) * 0.20;
1464 float percent60 = 3.0f * percent20;
1465 if(basetime > percent20 && basetime <= percent60)
1467 pVictim->setAttackTimer(BASE_ATTACK, uint32(percent20));
1469 else if(basetime > percent60)
1471 basetime -= 2.0f * percent20;
1472 pVictim->setAttackTimer(BASE_ATTACK, uint32(basetime));
1477 // Call default DealDamage
1478 CleanDamage cleanDamage(damageInfo->cleanDamage,damageInfo->attackType,damageInfo->hitOutCome);
1479 DealDamage(pVictim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), NULL, durabilityLoss);
1481 // If this is a creature and it attacks from behind it has a probability to daze it's victim
1482 if( (damageInfo->hitOutCome==MELEE_HIT_CRIT || damageInfo->hitOutCome==MELEE_HIT_CRUSHING || damageInfo->hitOutCome==MELEE_HIT_NORMAL || damageInfo->hitOutCome==MELEE_HIT_GLANCING) &&
1483 GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this) )
1485 // -probability is between 0% and 40%
1486 // 20% base chance
1487 float Probability = 20.0f;
1489 //there is a newbie protection, at level 10 just 7% base chance; assuming linear function
1490 if( pVictim->getLevel() < 30 )
1491 Probability = 0.65f*pVictim->getLevel()+0.5f;
1493 uint32 VictimDefense=pVictim->GetDefenseSkillValue();
1494 uint32 AttackerMeleeSkill=GetUnitMeleeSkill();
1496 Probability *= AttackerMeleeSkill/(float)VictimDefense;
1498 if(Probability > 40.0f)
1499 Probability = 40.0f;
1501 if(roll_chance_f(Probability))
1502 CastSpell(pVictim, 1604, true);
1505 // If not miss
1506 if (!(damageInfo->HitInfo & HITINFO_MISS))
1508 // on weapon hit casts
1509 if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive())
1510 ((Player*)this)->CastItemCombatSpell(pVictim, damageInfo->attackType);
1512 // victim's damage shield
1513 std::set<Aura*> alreadyDone;
1514 uint32 removedAuras = pVictim->m_removedAuras;
1515 AuraList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD);
1516 for(AuraList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next)
1518 next++;
1519 if (alreadyDone.find(*i) == alreadyDone.end())
1521 alreadyDone.insert(*i);
1522 uint32 damage=(*i)->GetModifier()->m_amount;
1523 SpellEntry const *spellProto = sSpellStore.LookupEntry((*i)->GetId());
1524 if(!spellProto)
1525 continue;
1526 //Calculate absorb resist ??? no data in opcode for this possibly unable to absorb or resist?
1527 //uint32 absorb;
1528 //uint32 resist;
1529 //CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
1530 //damage-=absorb + resist;
1532 pVictim->DealDamageMods(this,damage,NULL);
1534 WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4+4+4));
1535 data << uint64(pVictim->GetGUID());
1536 data << uint64(GetGUID());
1537 data << uint32(spellProto->Id);
1538 data << uint32(damage); // Damage
1539 data << uint32(0); // Overkill
1540 data << uint32(spellProto->SchoolMask);
1541 pVictim->SendMessageToSet(&data, true );
1543 pVictim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true);
1545 if (pVictim->m_removedAuras > removedAuras)
1547 removedAuras = pVictim->m_removedAuras;
1548 next = vDamageShields.begin();
1556 void Unit::HandleEmoteCommand(uint32 anim_id)
1558 WorldPacket data( SMSG_EMOTE, 4 + 8 );
1559 data << uint32(anim_id);
1560 data << uint64(GetGUID());
1561 SendMessageToSet(&data, true);
1564 uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage)
1566 uint32 newdamage = 0;
1567 float armor = pVictim->GetArmor();
1568 // Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura
1569 armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL);
1571 // Apply Player CR_ARMOR_PENETRATION rating
1572 if (GetTypeId()==TYPEID_PLAYER)
1573 armor *= 1.0f - ((Player*)this)->GetRatingBonusValue(CR_ARMOR_PENETRATION) / 100.0f;
1575 if (armor < 0.0f) armor=0.0f;
1577 float levelModifier = getLevel();
1578 if ( levelModifier > 59 )
1579 levelModifier = levelModifier + (4.5f * (levelModifier-59));
1581 float tmpvalue = 0.1f * armor / (8.5f * levelModifier + 40);
1582 tmpvalue = tmpvalue/(1.0f + tmpvalue);
1584 if(tmpvalue < 0.0f)
1585 tmpvalue = 0.0f;
1586 if(tmpvalue > 0.75f)
1587 tmpvalue = 0.75f;
1588 newdamage = uint32(damage - (damage * tmpvalue));
1590 return (newdamage > 1) ? newdamage : 1;
1593 void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist)
1595 if(!pVictim || !pVictim->isAlive() || !damage)
1596 return;
1598 // Magic damage, check for resists
1599 if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL)==0)
1601 // Get base victim resistance for school
1602 float tmpvalue2 = (float)pVictim->GetResistance(GetFirstSchoolInMask(schoolMask));
1603 // Ignore resistance by self SPELL_AURA_MOD_TARGET_RESISTANCE aura
1604 tmpvalue2 += (float)GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask);
1606 tmpvalue2 *= (float)(0.15f / getLevel());
1607 if (tmpvalue2 < 0.0f)
1608 tmpvalue2 = 0.0f;
1609 if (tmpvalue2 > 0.75f)
1610 tmpvalue2 = 0.75f;
1611 uint32 ran = urand(0, 100);
1612 uint32 faq[4] = {24,6,4,6};
1613 uint8 m = 0;
1614 float Binom = 0.0f;
1615 for (uint8 i = 0; i < 4; ++i)
1617 Binom += 2400 *( powf(tmpvalue2, i) * powf( (1-tmpvalue2), (4-i)))/faq[i];
1618 if (ran > Binom )
1619 ++m;
1620 else
1621 break;
1623 if (damagetype == DOT && m == 4)
1624 *resist += uint32(damage - 1);
1625 else
1626 *resist += uint32(damage * m / 4);
1627 if(*resist > damage)
1628 *resist = damage;
1630 else
1631 *resist = 0;
1633 int32 RemainingDamage = damage - *resist;
1635 // Get unit state (need for some absorb check)
1636 uint32 unitflag = pVictim->GetUInt32Value(UNIT_FIELD_FLAGS);
1637 // Reflect damage spells (not cast any damage spell in aura lookup)
1638 uint32 reflectSpell = 0;
1639 int32 reflectDamage = 0;
1640 // Death Prevention Aura
1641 SpellEntry const* preventDeathSpell = NULL;
1642 int32 preventDeathAmount = 0;
1643 // Need remove expired auras after
1644 bool existExpired = false;
1645 // absorb without mana cost
1646 AuraList const& vSchoolAbsorb = pVictim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB);
1647 for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && RemainingDamage > 0; ++i)
1649 Modifier* mod = (*i)->GetModifier();
1650 if (!(mod->m_miscvalue & schoolMask))
1651 continue;
1653 SpellEntry const* spellProto = (*i)->GetSpellProto();
1655 // Max Amount can be absorbed by this aura
1656 int32 currentAbsorb = mod->m_amount;
1658 // Found empty aura (impossible but..)
1659 if (currentAbsorb <=0)
1661 existExpired = true;
1662 continue;
1664 // Handle custom absorb auras
1665 // TODO: try find better way
1666 switch(spellProto->SpellFamilyName)
1668 case SPELLFAMILY_GENERIC:
1670 // Astral Shift
1671 if (spellProto->SpellIconID == 3066)
1673 //reduces all damage taken while stun, fear or silence
1674 if (unitflag & (UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))
1675 RemainingDamage -= RemainingDamage * currentAbsorb / 100;
1676 continue;
1678 // Nerves of Steel
1679 if (spellProto->SpellIconID == 2115)
1681 // while affected by Stun and Fear
1682 if (unitflag&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING))
1683 RemainingDamage -= RemainingDamage * currentAbsorb / 100;
1684 continue;
1686 // Spell Deflection
1687 if (spellProto->SpellIconID == 3006)
1689 // You have a chance equal to your Parry chance
1690 if (damagetype == DIRECT_DAMAGE && // Only for direct damage
1691 roll_chance_f(pVictim->GetUnitParryChance())) // Roll chance
1692 RemainingDamage -= RemainingDamage * currentAbsorb / 100;
1693 continue;
1695 // Reflective Shield (Lady Malande boss)
1696 if (spellProto->Id == 41475)
1698 if(RemainingDamage < currentAbsorb)
1699 reflectDamage = RemainingDamage / 2;
1700 else
1701 reflectDamage = currentAbsorb / 2;
1702 reflectSpell = 33619;
1703 break;
1705 if (spellProto->Id == 39228 || // Argussian Compass
1706 spellProto->Id == 60218) // Essence of Gossamer
1708 // Max absorb stored in 1 dummy effect
1709 if (spellProto->EffectBasePoints[1] < currentAbsorb)
1710 currentAbsorb = spellProto->EffectBasePoints[1];
1711 break;
1713 break;
1715 case SPELLFAMILY_DRUID:
1717 // Primal Tenacity
1718 if (spellProto->SpellIconID == 2253)
1720 //reduces all damage taken while Stunned
1721 if (unitflag & UNIT_FLAG_STUNNED)
1722 RemainingDamage -= RemainingDamage * currentAbsorb / 100;
1723 continue;
1725 break;
1727 case SPELLFAMILY_ROGUE:
1729 // Cheat Death (make less prio with Guardian Spirit case)
1730 if (!preventDeathSpell && spellProto->SpellIconID == 2109 &&
1731 pVictim->GetTypeId()==TYPEID_PLAYER && // Only players
1732 !((Player*)pVictim)->HasSpellCooldown(31231) &&
1733 // Only if no cooldown
1734 roll_chance_i((*i)->GetModifier()->m_amount))
1735 // Only if roll
1737 preventDeathSpell = (*i)->GetSpellProto();
1738 continue;
1740 break;
1742 case SPELLFAMILY_PRIEST:
1744 // Guardian Spirit
1745 if (spellProto->SpellIconID == 2873)
1747 preventDeathSpell = (*i)->GetSpellProto();
1748 preventDeathAmount = (*i)->GetModifier()->m_amount;
1749 continue;
1752 // Reflective Shield
1753 if (spellProto->SpellFamilyFlags == 0x1)
1755 if (pVictim == this)
1756 break;
1757 Unit* caster = (*i)->GetCaster();
1758 if (!caster)
1759 break;
1760 AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_DUMMY);
1761 for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k)
1763 switch((*k)->GetModifier()->m_miscvalue)
1765 case 5065: // Rank 1
1766 case 5064: // Rank 2
1767 case 5063: // Rank 3
1769 if(RemainingDamage >= currentAbsorb)
1770 reflectDamage = (*k)->GetModifier()->m_amount * currentAbsorb/100;
1771 else
1772 reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100;
1773 reflectSpell = 33619;
1774 } break;
1775 default: break;
1778 break;
1780 break;
1782 case SPELLFAMILY_SHAMAN:
1784 // Astral Shift
1785 if (spellProto->SpellIconID == 3066)
1787 //reduces all damage taken while stun, fear or silence
1788 if (unitflag & (UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))
1789 RemainingDamage -= RemainingDamage * currentAbsorb / 100;
1790 continue;
1792 break;
1794 case SPELLFAMILY_DEATHKNIGHT:
1796 // Shadow of Death
1797 if (spellProto->SpellIconID == 1958)
1799 // TODO: absorb only while transform
1800 continue;
1802 // Anti-Magic Shell (on self)
1803 if (spellProto->Id == 48707)
1805 // damage absorbed by Anti-Magic Shell energizes the DK with additional runic power.
1806 // This, if I'm not mistaken, shows that we get back ~2% of the absorbed damage as runic power.
1807 int32 absorbed = RemainingDamage * currentAbsorb / 100;
1808 int32 regen = absorbed * 2 / 10;
1809 pVictim->CastCustomSpell(pVictim, 49088, &regen, NULL, NULL, true, NULL, *i);
1810 RemainingDamage -= absorbed;
1811 continue;
1813 // Anti-Magic Shell (on single party/raid member)
1814 if (spellProto->Id == 50462)
1816 RemainingDamage -= RemainingDamage * currentAbsorb / 100;
1817 continue;
1819 // Anti-Magic Zone
1820 if (spellProto->Id == 50461)
1822 Unit* caster = (*i)->GetCaster();
1823 if (!caster)
1824 continue;
1825 int32 absorbed = RemainingDamage * currentAbsorb / 100;
1826 int32 canabsorb = caster->GetHealth();
1827 if (canabsorb < absorbed)
1828 absorbed = canabsorb;
1830 RemainingDamage -= absorbed;
1832 uint32 ab_damage = absorbed;
1833 DealDamageMods(caster,ab_damage,NULL);
1834 DealDamage(caster, ab_damage, NULL, damagetype, schoolMask, 0, false);
1835 continue;
1837 break;
1839 default:
1840 break;
1843 // currentAbsorb - damage can be absorbed by shield
1844 // If need absorb less damage
1845 if (RemainingDamage < currentAbsorb)
1846 currentAbsorb = RemainingDamage;
1848 RemainingDamage -= currentAbsorb;
1850 // Reduce shield amount
1851 mod->m_amount-=currentAbsorb;
1852 // Need remove it later
1853 if (mod->m_amount<=0)
1854 existExpired = true;
1857 // Remove all expired absorb auras
1858 if (existExpired)
1860 for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end();)
1862 if ((*i)->GetModifier()->m_amount<=0)
1864 pVictim->RemoveAurasDueToSpell((*i)->GetId());
1865 i = vSchoolAbsorb.begin();
1867 else
1868 ++i;
1872 // Cast back reflect damage spell
1873 if (reflectSpell)
1874 pVictim->CastCustomSpell(this, reflectSpell, &reflectDamage, NULL, NULL, true);
1876 // absorb by mana cost
1877 AuraList const& vManaShield = pVictim->GetAurasByType(SPELL_AURA_MANA_SHIELD);
1878 for(AuraList::const_iterator i = vManaShield.begin(), next; i != vManaShield.end() && RemainingDamage > 0; i = next)
1880 next = i; ++next;
1882 // check damage school mask
1883 if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0)
1884 continue;
1886 int32 currentAbsorb;
1887 if (RemainingDamage >= (*i)->GetModifier()->m_amount)
1888 currentAbsorb = (*i)->GetModifier()->m_amount;
1889 else
1890 currentAbsorb = RemainingDamage;
1892 float manaMultiplier = (*i)->GetSpellProto()->EffectMultipleValue[(*i)->GetEffIndex()];
1893 if(Player *modOwner = pVictim->GetSpellModOwner())
1894 modOwner->ApplySpellMod((*i)->GetId(), SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
1896 int32 maxAbsorb = int32(pVictim->GetPower(POWER_MANA) / manaMultiplier);
1897 if (currentAbsorb > maxAbsorb)
1898 currentAbsorb = maxAbsorb;
1900 (*i)->GetModifier()->m_amount -= currentAbsorb;
1901 if((*i)->GetModifier()->m_amount <= 0)
1903 pVictim->RemoveAurasDueToSpell((*i)->GetId());
1904 next = vManaShield.begin();
1907 int32 manaReduction = int32(currentAbsorb * manaMultiplier);
1908 pVictim->ApplyPowerMod(POWER_MANA, manaReduction, false);
1910 RemainingDamage -= currentAbsorb;
1913 // only split damage if not damaging yourself
1914 if(pVictim != this)
1916 AuraList const& vSplitDamageFlat = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT);
1917 for(AuraList::const_iterator i = vSplitDamageFlat.begin(), next; i != vSplitDamageFlat.end() && RemainingDamage >= 0; i = next)
1919 next = i; ++next;
1921 // check damage school mask
1922 if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0)
1923 continue;
1925 // Damage can be splitted only if aura has an alive caster
1926 Unit *caster = (*i)->GetCaster();
1927 if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive())
1928 continue;
1930 int32 currentAbsorb;
1931 if (RemainingDamage >= (*i)->GetModifier()->m_amount)
1932 currentAbsorb = (*i)->GetModifier()->m_amount;
1933 else
1934 currentAbsorb = RemainingDamage;
1936 RemainingDamage -= currentAbsorb;
1939 uint32 splitted = currentAbsorb;
1940 uint32 splitted_absorb = 0;
1941 DealDamageMods(caster,splitted,&splitted_absorb);
1943 SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false);
1945 CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL);
1946 DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false);
1949 AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT);
1950 for(AuraList::const_iterator i = vSplitDamagePct.begin(), next; i != vSplitDamagePct.end() && RemainingDamage >= 0; i = next)
1952 next = i; ++next;
1954 // check damage school mask
1955 if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0)
1956 continue;
1958 // Damage can be splitted only if aura has an alive caster
1959 Unit *caster = (*i)->GetCaster();
1960 if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive())
1961 continue;
1963 uint32 splitted = uint32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f);
1965 RemainingDamage -= int32(splitted);
1967 uint32 split_absorb = 0;
1968 DealDamageMods(caster,splitted,&split_absorb);
1970 SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, split_absorb, 0, false, 0, false);
1972 CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL);
1973 DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false);
1977 // Apply death prevention spells effects
1978 if (preventDeathSpell && RemainingDamage >= pVictim->GetHealth())
1980 switch(preventDeathSpell->SpellFamilyName)
1982 // Cheat Death
1983 case SPELLFAMILY_ROGUE:
1985 // Cheat Death
1986 if (preventDeathSpell->SpellIconID == 2109)
1988 pVictim->CastSpell(pVictim,31231,true);
1989 ((Player*)pVictim)->AddSpellCooldown(31231,0,time(NULL)+60);
1990 // with health > 10% lost health until health==10%, in other case no losses
1991 uint32 health10 = pVictim->GetMaxHealth()/10;
1992 RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0;
1994 break;
1996 // Guardian Spirit
1997 case SPELLFAMILY_PRIEST:
1999 // Guardian Spirit
2000 if (preventDeathSpell->SpellIconID == 2873)
2002 int32 healAmount = pVictim->GetMaxHealth() * preventDeathAmount / 100;
2003 pVictim->CastCustomSpell(pVictim, 48153, &healAmount, NULL, NULL, true);
2004 pVictim->RemoveAurasDueToSpell(preventDeathSpell->Id);
2005 RemainingDamage = 0;
2007 break;
2012 *absorb = damage - RemainingDamage - *resist;
2015 void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool extra )
2017 if(hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) )
2018 return;
2020 if (!pVictim->isAlive())
2021 return;
2023 if(IsNonMeleeSpellCasted(false))
2024 return;
2026 uint32 hitInfo;
2027 if (attType == BASE_ATTACK)
2028 hitInfo = HITINFO_NORMALSWING2;
2029 else if (attType == OFF_ATTACK)
2030 hitInfo = HITINFO_LEFTSWING;
2031 else
2032 return; // ignore ranged case
2034 uint32 extraAttacks = m_extraAttacks;
2036 // melee attack spell casted at main hand attack only
2037 if (attType == BASE_ATTACK && m_currentSpells[CURRENT_MELEE_SPELL])
2039 m_currentSpells[CURRENT_MELEE_SPELL]->cast();
2041 // not recent extra attack only at any non extra attack (melee spell case)
2042 if(!extra && extraAttacks)
2044 while(m_extraAttacks)
2046 AttackerStateUpdate(pVictim, BASE_ATTACK, true);
2047 if(m_extraAttacks > 0)
2048 --m_extraAttacks;
2051 return;
2054 // attack can be redirected to another target
2055 pVictim = SelectMagnetTarget(pVictim);
2057 CalcDamageInfo damageInfo;
2058 CalculateMeleeDamage(pVictim, 0, &damageInfo, attType);
2059 // Send log damage message to client
2060 DealDamageMods(pVictim,damageInfo.damage,&damageInfo.absorb);
2061 SendAttackStateUpdate(&damageInfo);
2062 ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType);
2063 DealMeleeDamage(&damageInfo,true);
2065 if (GetTypeId() == TYPEID_PLAYER)
2066 DEBUG_LOG("AttackerStateUpdate: (Player) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
2067 GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
2068 else
2069 DEBUG_LOG("AttackerStateUpdate: (NPC) %u attacked %u (TypeId: %u) for %u dmg, absorbed %u, blocked %u, resisted %u.",
2070 GetGUIDLow(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damageInfo.damage, damageInfo.absorb, damageInfo.blocked_amount, damageInfo.resist);
2072 // if damage pVictim call AI reaction
2073 if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->AI())
2074 ((Creature*)pVictim)->AI()->AttackedBy(this);
2076 // extra attack only at any non extra attack (normal case)
2077 if(!extra && extraAttacks)
2079 while(m_extraAttacks)
2081 AttackerStateUpdate(pVictim, BASE_ATTACK, true);
2082 if(m_extraAttacks > 0)
2083 --m_extraAttacks;
2088 MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const
2090 // This is only wrapper
2092 // Miss chance based on melee
2093 float miss_chance = MeleeMissChanceCalc(pVictim, attType);
2095 // Critical hit chance
2096 float crit_chance = GetUnitCriticalChance(attType, pVictim);
2098 // stunned target cannot dodge and this is check in GetUnitDodgeChance() (returned 0 in this case)
2099 float dodge_chance = pVictim->GetUnitDodgeChance();
2100 float block_chance = pVictim->GetUnitBlockChance();
2101 float parry_chance = pVictim->GetUnitParryChance();
2103 // Useful if want to specify crit & miss chances for melee, else it could be removed
2104 DEBUG_LOG("MELEE OUTCOME: miss %f crit %f dodge %f parry %f block %f", miss_chance,crit_chance,dodge_chance,parry_chance,block_chance);
2106 return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100));
2109 MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const
2111 if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
2112 return MELEE_HIT_EVADE;
2114 int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(pVictim);
2115 int32 victimMaxSkillValueForLevel = pVictim->GetMaxSkillValueForLevel(this);
2117 int32 attackerWeaponSkill = GetWeaponSkillValue(attType,pVictim);
2118 int32 victimDefenseSkill = pVictim->GetDefenseSkillValue(this);
2120 // bonus from skills is 0.04%
2121 int32 skillBonus = 4 * ( attackerWeaponSkill - victimMaxSkillValueForLevel );
2122 int32 sum = 0, tmp = 0;
2123 int32 roll = urand (0, 10000);
2125 DEBUG_LOG ("RollMeleeOutcomeAgainst: skill bonus of %d for attacker", skillBonus);
2126 DEBUG_LOG ("RollMeleeOutcomeAgainst: rolled %d, miss %d, dodge %d, parry %d, block %d, crit %d",
2127 roll, miss_chance, dodge_chance, parry_chance, block_chance, crit_chance);
2129 tmp = miss_chance;
2131 if (tmp > 0 && roll < (sum += tmp ))
2133 DEBUG_LOG ("RollMeleeOutcomeAgainst: MISS");
2134 return MELEE_HIT_MISS;
2137 // always crit against a sitting target (except 0 crit chance)
2138 if( pVictim->GetTypeId() == TYPEID_PLAYER && crit_chance > 0 && !pVictim->IsStandState() )
2140 DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT (sitting victim)");
2141 return MELEE_HIT_CRIT;
2144 // Dodge chance
2146 // only players can't dodge if attacker is behind
2147 if (pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->HasInArc(M_PI,this))
2149 DEBUG_LOG ("RollMeleeOutcomeAgainst: attack came from behind and victim was a player.");
2151 else
2153 // Reduce dodge chance by attacker expertise rating
2154 if (GetTypeId() == TYPEID_PLAYER)
2155 dodge_chance -= int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType)*100);
2157 // Modify dodge chance by attacker SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
2158 dodge_chance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE);
2160 tmp = dodge_chance;
2161 if ( (tmp > 0) // check if unit _can_ dodge
2162 && ((tmp -= skillBonus) > 0)
2163 && roll < (sum += tmp))
2165 DEBUG_LOG ("RollMeleeOutcomeAgainst: DODGE <%d, %d)", sum-tmp, sum);
2166 return MELEE_HIT_DODGE;
2170 // parry & block chances
2172 // check if attack comes from behind, nobody can parry or block if attacker is behind
2173 if (!pVictim->HasInArc(M_PI,this))
2175 DEBUG_LOG ("RollMeleeOutcomeAgainst: attack came from behind.");
2177 else
2179 // Reduce parry chance by attacker expertise rating
2180 if (GetTypeId() == TYPEID_PLAYER)
2181 parry_chance-= int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType)*100);
2183 if(pVictim->GetTypeId()==TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_PARRY) )
2185 int32 tmp2 = int32(parry_chance);
2186 if ( (tmp2 > 0) // check if unit _can_ parry
2187 && ((tmp2 -= skillBonus) > 0)
2188 && (roll < (sum += tmp2)))
2190 DEBUG_LOG ("RollMeleeOutcomeAgainst: PARRY <%d, %d)", sum-tmp2, sum);
2191 return MELEE_HIT_PARRY;
2195 if(pVictim->GetTypeId()==TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_BLOCK) )
2197 tmp = block_chance;
2198 if ( (tmp > 0) // check if unit _can_ block
2199 && ((tmp -= skillBonus) > 0)
2200 && (roll < (sum += tmp)))
2202 DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCK <%d, %d)", sum-tmp, sum);
2203 return MELEE_HIT_BLOCK;
2208 // Critical chance
2209 tmp = crit_chance;
2211 if (tmp > 0 && roll < (sum += tmp))
2213 DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT <%d, %d)", sum-tmp, sum);
2214 return MELEE_HIT_CRIT;
2217 // 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)
2218 if( attType != RANGED_ATTACK &&
2219 (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet()) &&
2220 pVictim->GetTypeId() != TYPEID_PLAYER && !((Creature*)pVictim)->isPet() &&
2221 getLevel() < pVictim->getLevelForTarget(this) )
2223 // cap possible value (with bonuses > max skill)
2224 int32 skill = attackerWeaponSkill;
2225 int32 maxskill = attackerMaxSkillValueForLevel;
2226 skill = (skill > maxskill) ? maxskill : skill;
2228 tmp = (10 + (victimDefenseSkill - skill)) * 100;
2229 tmp = tmp > 4000 ? 4000 : tmp;
2230 if (roll < (sum += tmp))
2232 DEBUG_LOG ("RollMeleeOutcomeAgainst: GLANCING <%d, %d)", sum-4000, sum);
2233 return MELEE_HIT_GLANCING;
2237 // mobs can score crushing blows if they're 4 or more levels above victim
2238 if (getLevelForTarget(pVictim) >= pVictim->getLevelForTarget(this) + 4 &&
2239 // can be from by creature (if can) or from controlled player that considered as creature
2240 (GetTypeId()!=TYPEID_PLAYER && !((Creature*)this)->isPet() &&
2241 !(((Creature*)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH) ||
2242 GetTypeId()==TYPEID_PLAYER && GetCharmerOrOwnerGUID()))
2244 // when their weapon skill is 15 or more above victim's defense skill
2245 tmp = victimDefenseSkill;
2246 int32 tmpmax = victimMaxSkillValueForLevel;
2247 // having defense above your maximum (from items, talents etc.) has no effect
2248 tmp = tmp > tmpmax ? tmpmax : tmp;
2249 // tmp = mob's level * 5 - player's current defense skill
2250 tmp = attackerMaxSkillValueForLevel - tmp;
2251 if(tmp >= 15)
2253 // add 2% chance per lacking skill point, min. is 15%
2254 tmp = tmp * 200 - 1500;
2255 if (roll < (sum += tmp))
2257 DEBUG_LOG ("RollMeleeOutcomeAgainst: CRUSHING <%d, %d)", sum-tmp, sum);
2258 return MELEE_HIT_CRUSHING;
2263 DEBUG_LOG ("RollMeleeOutcomeAgainst: NORMAL");
2264 return MELEE_HIT_NORMAL;
2267 uint32 Unit::CalculateDamage (WeaponAttackType attType, bool normalized)
2269 float min_damage, max_damage;
2271 if (normalized && GetTypeId()==TYPEID_PLAYER)
2272 ((Player*)this)->CalculateMinMaxDamage(attType,normalized,min_damage, max_damage);
2273 else
2275 switch (attType)
2277 case RANGED_ATTACK:
2278 min_damage = GetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE);
2279 max_damage = GetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE);
2280 break;
2281 case BASE_ATTACK:
2282 min_damage = GetFloatValue(UNIT_FIELD_MINDAMAGE);
2283 max_damage = GetFloatValue(UNIT_FIELD_MAXDAMAGE);
2284 break;
2285 case OFF_ATTACK:
2286 min_damage = GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE);
2287 max_damage = GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE);
2288 break;
2289 // Just for good manner
2290 default:
2291 min_damage = 0.0f;
2292 max_damage = 0.0f;
2293 break;
2297 if (min_damage > max_damage)
2299 std::swap(min_damage,max_damage);
2302 if(max_damage == 0.0f)
2303 max_damage = 5.0f;
2305 return urand((uint32)min_damage, (uint32)max_damage);
2308 float Unit::CalculateLevelPenalty(SpellEntry const* spellProto) const
2310 if(spellProto->spellLevel <= 0)
2311 return 1.0f;
2313 float LvlPenalty = 0.0f;
2315 if(spellProto->spellLevel < 20)
2316 LvlPenalty = 20.0f - spellProto->spellLevel * 3.75f;
2317 float LvlFactor = (float(spellProto->spellLevel) + 6.0f) / float(getLevel());
2318 if(LvlFactor > 1.0f)
2319 LvlFactor = 1.0f;
2321 return (100.0f - LvlPenalty) * LvlFactor / 100.0f;
2324 void Unit::SendMeleeAttackStart(Unit* pVictim)
2326 WorldPacket data( SMSG_ATTACKSTART, 8 + 8 );
2327 data << uint64(GetGUID());
2328 data << uint64(pVictim->GetGUID());
2330 SendMessageToSet(&data, true);
2331 DEBUG_LOG( "WORLD: Sent SMSG_ATTACKSTART" );
2334 void Unit::SendMeleeAttackStop(Unit* victim)
2336 if(!victim)
2337 return;
2339 WorldPacket data( SMSG_ATTACKSTOP, (4+16) ); // we guess size
2340 data.append(GetPackGUID());
2341 data.append(victim->GetPackGUID()); // can be 0x00...
2342 data << uint32(0); // can be 0x1
2343 SendMessageToSet(&data, true);
2344 sLog.outDetail("%s %u stopped attacking %s %u", (GetTypeId()==TYPEID_PLAYER ? "player" : "creature"), GetGUIDLow(), (victim->GetTypeId()==TYPEID_PLAYER ? "player" : "creature"),victim->GetGUIDLow());
2346 /*if(victim->GetTypeId() == TYPEID_UNIT)
2347 ((Creature*)victim)->AI().EnterEvadeMode(this);*/
2350 bool Unit::isSpellBlocked(Unit *pVictim, SpellEntry const * /*spellProto*/, WeaponAttackType attackType)
2352 if (pVictim->HasInArc(M_PI,this))
2354 /* Currently not exist spells with ignore block
2355 // Ignore combat result aura (parry/dodge check on prepare)
2356 AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
2357 for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
2359 if (!(*i)->isAffectedOnSpell(spellProto))
2360 continue;
2361 if ((*i)->GetModifier()->m_miscvalue == )
2362 return false;
2366 // Check creatures flags_extra for disable block
2367 if(pVictim->GetTypeId()==TYPEID_UNIT &&
2368 ((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_BLOCK )
2369 return false;
2371 float blockChance = pVictim->GetUnitBlockChance();
2372 blockChance += (int32(GetWeaponSkillValue(attackType)) - int32(pVictim->GetMaxSkillValueForLevel()))*0.04f;
2373 if (roll_chance_f(blockChance))
2374 return true;
2376 return false;
2379 // Melee based spells can be miss, parry or dodge on this step
2380 // Crit or block - determined on damage calculation phase! (and can be both in some time)
2381 float Unit::MeleeSpellMissChance(Unit *pVictim, WeaponAttackType attType, int32 skillDiff, SpellEntry const *spell)
2383 // Calculate hit chance (more correct for chance mod)
2384 int32 HitChance;
2386 // PvP - PvE melee chances
2387 int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7;
2388 int32 leveldif = pVictim->getLevelForTarget(this) - getLevelForTarget(pVictim);
2389 if(leveldif < 3)
2390 HitChance = 95 - leveldif;
2391 else
2392 HitChance = 93 - (leveldif - 2) * lchance;
2394 // Hit chance depends from victim auras
2395 if(attType == RANGED_ATTACK)
2396 HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE);
2397 else
2398 HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE);
2400 // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
2401 if(Player *modOwner = GetSpellModOwner())
2402 modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, HitChance);
2404 // Miss = 100 - hit
2405 float miss_chance= 100.0f - HitChance;
2407 // Bonuses from attacker aura and ratings
2408 if (attType == RANGED_ATTACK)
2409 miss_chance -= m_modRangedHitChance;
2410 else
2411 miss_chance -= m_modMeleeHitChance;
2413 // bonus from skills is 0.04%
2414 miss_chance -= skillDiff * 0.04f;
2416 // Limit miss chance from 0 to 60%
2417 if (miss_chance < 0.0f)
2418 return 0.0f;
2419 if (miss_chance > 60.0f)
2420 return 60.0f;
2421 return miss_chance;
2424 // Melee based spells hit result calculations
2425 SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell)
2427 WeaponAttackType attType = BASE_ATTACK;
2429 if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED)
2430 attType = RANGED_ATTACK;
2432 // bonus from skills is 0.04% per skill Diff
2433 int32 attackerWeaponSkill = int32(GetWeaponSkillValue(attType,pVictim));
2434 int32 skillDiff = attackerWeaponSkill - int32(pVictim->GetMaxSkillValueForLevel(this));
2435 int32 fullSkillDiff = attackerWeaponSkill - int32(pVictim->GetDefenseSkillValue(this));
2437 uint32 roll = urand (0, 10000);
2439 uint32 missChance = uint32(MeleeSpellMissChance(pVictim, attType, fullSkillDiff, spell)*100.0f);
2440 // Roll miss
2441 uint32 tmp = missChance;
2442 if (roll < tmp)
2443 return SPELL_MISS_MISS;
2445 // Chance resist mechanic (select max value from every mechanic spell effect)
2446 int32 resist_mech = 0;
2447 // Get effects mechanic and chance
2448 for(int eff = 0; eff < 3; ++eff)
2450 int32 effect_mech = GetEffectMechanic(spell, eff);
2451 if (effect_mech)
2453 int32 temp = pVictim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech);
2454 if (resist_mech < temp*100)
2455 resist_mech = temp*100;
2458 // Roll chance
2459 tmp += resist_mech;
2460 if (roll < tmp)
2461 return SPELL_MISS_RESIST;
2463 bool canDodge = true;
2464 bool canParry = true;
2466 // Same spells cannot be parry/dodge
2467 if (spell->Attributes & SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK)
2468 return SPELL_MISS_NONE;
2470 // Ranged attack cannot be parry/dodge only deflect
2471 if (attType == RANGED_ATTACK)
2473 // only if in front
2474 if (pVictim->HasInArc(M_PI,this))
2476 int32 deflect_chance = pVictim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS)*100;
2477 tmp+=deflect_chance;
2478 if (roll < tmp)
2479 return SPELL_MISS_DEFLECT;
2481 return SPELL_MISS_NONE;
2484 // Check for attack from behind
2485 if (!pVictim->HasInArc(M_PI,this))
2487 // Can`t dodge from behind in PvP (but its possible in PvE)
2488 if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER)
2489 canDodge = false;
2490 // Can`t parry
2491 canParry = false;
2493 // Check creatures flags_extra for disable parry
2494 if(pVictim->GetTypeId()==TYPEID_UNIT)
2496 uint32 flagEx = ((Creature*)pVictim)->GetCreatureInfo()->flags_extra;
2497 if( flagEx & CREATURE_FLAG_EXTRA_NO_PARRY )
2498 canParry = false;
2500 // Ignore combat result aura
2501 AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT);
2502 for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
2504 if (!(*i)->isAffectedOnSpell(spell))
2505 continue;
2506 switch((*i)->GetModifier()->m_miscvalue)
2508 case MELEE_HIT_DODGE: canDodge = false; break;
2509 case MELEE_HIT_BLOCK: break; // Block check in hit step
2510 case MELEE_HIT_PARRY: canParry = false; break;
2511 default:
2512 DEBUG_LOG("Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT have unhandled state %d", (*i)->GetId(), (*i)->GetModifier()->m_miscvalue);
2513 break;
2517 if (canDodge)
2519 // Roll dodge
2520 int32 dodgeChance = int32(pVictim->GetUnitDodgeChance()*100.0f) - skillDiff * 4;
2521 // Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE
2522 dodgeChance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE)*100;
2523 // Reduce dodge chance by attacker expertise rating
2524 if (GetTypeId() == TYPEID_PLAYER)
2525 dodgeChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
2526 if (dodgeChance < 0)
2527 dodgeChance = 0;
2529 tmp += dodgeChance;
2530 if (roll < tmp)
2531 return SPELL_MISS_DODGE;
2534 if (canParry)
2536 // Roll parry
2537 int32 parryChance = int32(pVictim->GetUnitParryChance()*100.0f) - skillDiff * 4;
2538 // Reduce parry chance by attacker expertise rating
2539 if (GetTypeId() == TYPEID_PLAYER)
2540 parryChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f);
2541 if (parryChance < 0)
2542 parryChance = 0;
2544 tmp += parryChance;
2545 if (roll < tmp)
2546 return SPELL_MISS_PARRY;
2549 return SPELL_MISS_NONE;
2552 // TODO need use unit spell resistances in calculations
2553 SpellMissInfo Unit::MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell)
2555 // Can`t miss on dead target (on skinning for example)
2556 if (!pVictim->isAlive())
2557 return SPELL_MISS_NONE;
2559 SpellSchoolMask schoolMask = GetSpellSchoolMask(spell);
2560 // PvP - PvE spell misschances per leveldif > 2
2561 int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
2562 int32 leveldif = int32(pVictim->getLevelForTarget(this)) - int32(getLevelForTarget(pVictim));
2564 // Base hit chance from attacker and victim levels
2565 int32 modHitChance;
2566 if(leveldif < 3)
2567 modHitChance = 96 - leveldif;
2568 else
2569 modHitChance = 94 - (leveldif - 2) * lchance;
2571 // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
2572 if(Player *modOwner = GetSpellModOwner())
2573 modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
2574 // Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras
2575 modHitChance+=GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT, schoolMask);
2576 // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
2577 modHitChance+= pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask);
2578 // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura
2579 if (IsAreaOfEffectSpell(spell))
2580 modHitChance-=pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE);
2581 // Reduce spell hit chance for dispel mechanic spells from victim SPELL_AURA_MOD_DISPEL_RESIST
2582 if (IsDispelSpell(spell))
2583 modHitChance-=pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_DISPEL_RESIST);
2584 // Chance resist mechanic (select max value from every mechanic spell effect)
2585 int32 resist_mech = 0;
2586 // Get effects mechanic and chance
2587 for(int eff = 0; eff < 3; ++eff)
2589 int32 effect_mech = GetEffectMechanic(spell, eff);
2590 if (effect_mech)
2592 int32 temp = pVictim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech);
2593 if (resist_mech < temp)
2594 resist_mech = temp;
2597 // Apply mod
2598 modHitChance-=resist_mech;
2600 // Chance resist debuff
2601 modHitChance-=pVictim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, int32(spell->Dispel));
2603 int32 HitChance = modHitChance * 100;
2604 // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
2605 HitChance += int32(m_modSpellHitChance*100.0f);
2607 // Decrease hit chance from victim rating bonus
2608 if (pVictim->GetTypeId()==TYPEID_PLAYER)
2609 HitChance -= int32(((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_SPELL)*100.0f);
2611 if (HitChance < 100) HitChance = 100;
2612 if (HitChance > 10000) HitChance = 10000;
2614 int32 tmp = 10000 - HitChance;
2616 uint32 rand = urand(0,10000);
2618 if (rand < tmp)
2619 return SPELL_MISS_RESIST;
2621 // cast by caster in front of victim
2622 if (pVictim->HasInArc(M_PI,this))
2624 int32 deflect_chance = pVictim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS)*100;
2625 tmp+=deflect_chance;
2626 if (rand < tmp)
2627 return SPELL_MISS_DEFLECT;
2630 return SPELL_MISS_NONE;
2633 // Calculate spell hit result can be:
2634 // Every spell can: Evade/Immune/Reflect/Sucesful hit
2635 // For melee based spells:
2636 // Miss
2637 // Dodge
2638 // Parry
2639 // For spells
2640 // Resist
2641 SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool CanReflect)
2643 // Return evade for units in evade mode
2644 if (pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
2645 return SPELL_MISS_EVADE;
2647 // Check for immune
2648 if (pVictim->IsImmunedToSpell(spell))
2649 return SPELL_MISS_IMMUNE;
2651 // All positive spells can`t miss
2652 // TODO: client not show miss log for this spells - so need find info for this in dbc and use it!
2653 if (IsPositiveSpell(spell->Id))
2654 return SPELL_MISS_NONE;
2656 // Check for immune
2657 if (pVictim->IsImmunedToDamage(GetSpellSchoolMask(spell)))
2658 return SPELL_MISS_IMMUNE;
2660 // Try victim reflect spell
2661 if (CanReflect)
2663 int32 reflectchance = pVictim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS);
2664 Unit::AuraList const& mReflectSpellsSchool = pVictim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL);
2665 for(Unit::AuraList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i)
2666 if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spell))
2667 reflectchance += (*i)->GetModifier()->m_amount;
2668 if (reflectchance > 0 && roll_chance_i(reflectchance))
2670 // Start triggers for remove charges if need (trigger only for victim, and mark as active spell)
2671 ProcDamageAndSpell(pVictim, PROC_FLAG_NONE, PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT, PROC_EX_REFLECT, 1, BASE_ATTACK, spell);
2672 return SPELL_MISS_REFLECT;
2676 switch (spell->DmgClass)
2678 case SPELL_DAMAGE_CLASS_RANGED:
2679 case SPELL_DAMAGE_CLASS_MELEE:
2680 return MeleeSpellHitResult(pVictim, spell);
2681 case SPELL_DAMAGE_CLASS_NONE:
2682 case SPELL_DAMAGE_CLASS_MAGIC:
2683 return MagicSpellHitResult(pVictim, spell);
2685 return SPELL_MISS_NONE;
2688 float Unit::MeleeMissChanceCalc(const Unit *pVictim, WeaponAttackType attType) const
2690 if(!pVictim)
2691 return 0.0f;
2693 // Base misschance 5%
2694 float misschance = 5.0f;
2696 // DualWield - Melee spells and physical dmg spells - 5% , white damage 24%
2697 if (haveOffhandWeapon() && attType != RANGED_ATTACK)
2699 bool isNormal = false;
2700 for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
2702 if( m_currentSpells[i] && (GetSpellSchoolMask(m_currentSpells[i]->m_spellInfo) & SPELL_SCHOOL_MASK_NORMAL) )
2704 isNormal = true;
2705 break;
2708 if (isNormal || m_currentSpells[CURRENT_MELEE_SPELL])
2710 misschance = 5.0f;
2712 else
2714 misschance = 24.0f;
2718 // PvP : PvE melee misschances per leveldif > 2
2719 int32 chance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7;
2721 int32 leveldif = int32(pVictim->getLevelForTarget(this)) - int32(getLevelForTarget(pVictim));
2722 if(leveldif < 0)
2723 leveldif = 0;
2725 // Hit chance from attacker based on ratings and auras
2726 float m_modHitChance;
2727 if (attType == RANGED_ATTACK)
2728 m_modHitChance = m_modRangedHitChance;
2729 else
2730 m_modHitChance = m_modMeleeHitChance;
2732 if(leveldif < 3)
2733 misschance += (leveldif - m_modHitChance);
2734 else
2735 misschance += ((leveldif - 2) * chance - m_modHitChance);
2737 // Hit chance for victim based on ratings
2738 if (pVictim->GetTypeId()==TYPEID_PLAYER)
2740 if (attType == RANGED_ATTACK)
2741 misschance += ((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_RANGED);
2742 else
2743 misschance += ((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_MELEE);
2746 // Modify miss chance by victim auras
2747 if(attType == RANGED_ATTACK)
2748 misschance -= pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE);
2749 else
2750 misschance -= pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE);
2752 // Modify miss chance from skill difference ( bonus from skills is 0.04% )
2753 int32 skillBonus = int32(GetWeaponSkillValue(attType,pVictim)) - int32(pVictim->GetDefenseSkillValue(this));
2754 misschance -= skillBonus * 0.04f;
2756 // Limit miss chance from 0 to 60%
2757 if ( misschance < 0.0f)
2758 return 0.0f;
2759 if ( misschance > 60.0f)
2760 return 60.0f;
2762 return misschance;
2765 uint32 Unit::GetDefenseSkillValue(Unit const* target) const
2767 if(GetTypeId() == TYPEID_PLAYER)
2769 // in PvP use full skill instead current skill value
2770 uint32 value = (target && target->GetTypeId() == TYPEID_PLAYER)
2771 ? ((Player*)this)->GetMaxSkillValue(SKILL_DEFENSE)
2772 : ((Player*)this)->GetSkillValue(SKILL_DEFENSE);
2773 value += uint32(((Player*)this)->GetRatingBonusValue(CR_DEFENSE_SKILL));
2774 return value;
2776 else
2777 return GetUnitMeleeSkill(target);
2780 float Unit::GetUnitDodgeChance() const
2782 if(hasUnitState(UNIT_STAT_STUNNED))
2783 return 0.0f;
2784 if( GetTypeId() == TYPEID_PLAYER )
2785 return GetFloatValue(PLAYER_DODGE_PERCENTAGE);
2786 else
2788 if(((Creature const*)this)->isTotem())
2789 return 0.0f;
2790 else
2792 float dodge = 5.0f;
2793 dodge += GetTotalAuraModifier(SPELL_AURA_MOD_DODGE_PERCENT);
2794 return dodge > 0.0f ? dodge : 0.0f;
2799 float Unit::GetUnitParryChance() const
2801 if ( IsNonMeleeSpellCasted(false) || hasUnitState(UNIT_STAT_STUNNED))
2802 return 0.0f;
2804 float chance = 0.0f;
2806 if(GetTypeId() == TYPEID_PLAYER)
2808 Player const* player = (Player const*)this;
2809 if(player->CanParry() )
2811 Item *tmpitem = player->GetWeaponForAttack(BASE_ATTACK,true);
2812 if(!tmpitem)
2813 tmpitem = player->GetWeaponForAttack(OFF_ATTACK,true);
2815 if(tmpitem)
2816 chance = GetFloatValue(PLAYER_PARRY_PERCENTAGE);
2819 else if(GetTypeId() == TYPEID_UNIT)
2821 if(GetCreatureType() == CREATURE_TYPE_HUMANOID)
2823 chance = 5.0f;
2824 chance += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT);
2828 return chance > 0.0f ? chance : 0.0f;
2831 float Unit::GetUnitBlockChance() const
2833 if ( IsNonMeleeSpellCasted(false) || hasUnitState(UNIT_STAT_STUNNED))
2834 return 0.0f;
2836 if(GetTypeId() == TYPEID_PLAYER)
2838 Player const* player = (Player const*)this;
2839 if(player->CanBlock() )
2841 Item *tmpitem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
2842 if(tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block)
2843 return GetFloatValue(PLAYER_BLOCK_PERCENTAGE);
2845 // is player but has no block ability or no not broken shield equipped
2846 return 0.0f;
2848 else
2850 if(((Creature const*)this)->isTotem())
2851 return 0.0f;
2852 else
2854 float block = 5.0f;
2855 block += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT);
2856 return block > 0.0f ? block : 0.0f;
2861 float Unit::GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const
2863 float crit;
2865 if(GetTypeId() == TYPEID_PLAYER)
2867 switch(attackType)
2869 case BASE_ATTACK:
2870 crit = GetFloatValue( PLAYER_CRIT_PERCENTAGE );
2871 break;
2872 case OFF_ATTACK:
2873 crit = GetFloatValue( PLAYER_OFFHAND_CRIT_PERCENTAGE );
2874 break;
2875 case RANGED_ATTACK:
2876 crit = GetFloatValue( PLAYER_RANGED_CRIT_PERCENTAGE );
2877 break;
2878 // Just for good manner
2879 default:
2880 crit = 0.0f;
2881 break;
2884 else
2886 crit = 5.0f;
2887 crit += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_PERCENT);
2890 // flat aura mods
2891 if(attackType == RANGED_ATTACK)
2892 crit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE);
2893 else
2894 crit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE);
2896 crit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
2898 // reduce crit chance from Rating for players
2899 if (pVictim->GetTypeId()==TYPEID_PLAYER)
2901 if (attackType==RANGED_ATTACK)
2902 crit -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_RANGED);
2903 else
2904 crit -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE);
2907 // Apply crit chance from defence skill
2908 crit += (int32(GetMaxSkillValueForLevel(pVictim)) - int32(pVictim->GetDefenseSkillValue(this))) * 0.04f;
2910 if (crit < 0.0f)
2911 crit = 0.0f;
2912 return crit;
2915 uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target) const
2917 uint32 value = 0;
2918 if(GetTypeId() == TYPEID_PLAYER)
2920 Item* item = ((Player*)this)->GetWeaponForAttack(attType,true);
2922 // feral or unarmed skill only for base attack
2923 if(attType != BASE_ATTACK && !item )
2924 return 0;
2926 if(IsInFeralForm())
2927 return GetMaxSkillValueForLevel(); // always maximized SKILL_FERAL_COMBAT in fact
2929 // weapon skill or (unarmed for base attack)
2930 uint32 skill = item ? item->GetSkill() : SKILL_UNARMED;
2932 // in PvP use full skill instead current skill value
2933 value = (target && target->GetTypeId() == TYPEID_PLAYER)
2934 ? ((Player*)this)->GetMaxSkillValue(skill)
2935 : ((Player*)this)->GetSkillValue(skill);
2936 // Modify value from ratings
2937 value += uint32(((Player*)this)->GetRatingBonusValue(CR_WEAPON_SKILL));
2938 switch (attType)
2940 case BASE_ATTACK: value+=uint32(((Player*)this)->GetRatingBonusValue(CR_WEAPON_SKILL_MAINHAND));break;
2941 case OFF_ATTACK: value+=uint32(((Player*)this)->GetRatingBonusValue(CR_WEAPON_SKILL_OFFHAND));break;
2942 case RANGED_ATTACK: value+=uint32(((Player*)this)->GetRatingBonusValue(CR_WEAPON_SKILL_RANGED));break;
2945 else
2946 value = GetUnitMeleeSkill(target);
2947 return value;
2950 void Unit::_UpdateSpells( uint32 time )
2952 if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
2953 _UpdateAutoRepeatSpell();
2955 // remove finished spells from current pointers
2956 for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
2958 if (m_currentSpells[i] && m_currentSpells[i]->getState() == SPELL_STATE_FINISHED)
2960 m_currentSpells[i]->SetReferencedFromCurrent(false);
2961 m_currentSpells[i] = NULL; // remove pointer
2965 // TODO: Find a better way to prevent crash when multiple auras are removed.
2966 m_removedAuras = 0;
2967 for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i)
2968 if ((*i).second)
2969 (*i).second->SetUpdated(false);
2971 for (AuraMap::iterator i = m_Auras.begin(), next; i != m_Auras.end(); i = next)
2973 next = i;
2974 ++next;
2975 if ((*i).second)
2977 // prevent double update
2978 if ((*i).second->IsUpdated())
2979 continue;
2980 (*i).second->SetUpdated(true);
2981 (*i).second->Update( time );
2982 // several auras can be deleted due to update
2983 if (m_removedAuras)
2985 if (m_Auras.empty()) break;
2986 next = m_Auras.begin();
2987 m_removedAuras = 0;
2992 for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end();)
2994 if ((*i).second)
2996 if ( !(*i).second->GetAuraDuration() && !((*i).second->IsPermanent() || ((*i).second->IsPassive())) )
2998 RemoveAura(i);
3000 else
3002 ++i;
3005 else
3007 ++i;
3011 if(!m_gameObj.empty())
3013 GameObjectList::iterator ite1, dnext1;
3014 for (ite1 = m_gameObj.begin(); ite1 != m_gameObj.end(); ite1 = dnext1)
3016 dnext1 = ite1;
3017 //(*i)->Update( difftime );
3018 if( !(*ite1)->isSpawned() )
3020 (*ite1)->SetOwnerGUID(0);
3021 (*ite1)->SetRespawnTime(0);
3022 (*ite1)->Delete();
3023 dnext1 = m_gameObj.erase(ite1);
3025 else
3026 ++dnext1;
3031 void Unit::_UpdateAutoRepeatSpell()
3033 //check "realtime" interrupts
3034 if ( (GetTypeId() == TYPEID_PLAYER && ((Player*)this)->isMoving()) || IsNonMeleeSpellCasted(false,false,true) )
3036 // cancel wand shoot
3037 if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT)
3038 InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
3039 m_AutoRepeatFirstCast = true;
3040 return;
3043 //apply delay
3044 if ( m_AutoRepeatFirstCast && getAttackTimer(RANGED_ATTACK) < 500 )
3045 setAttackTimer(RANGED_ATTACK,500);
3046 m_AutoRepeatFirstCast = false;
3048 //castroutine
3049 if (isAttackReady(RANGED_ATTACK))
3051 // Check if able to cast
3052 if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CheckCast(true) != SPELL_CAST_OK)
3054 InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
3055 return;
3058 // we want to shoot
3059 Spell* spell = new Spell(this, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo, true, 0);
3060 spell->prepare(&(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets));
3062 // all went good, reset attack
3063 resetAttackTimer(RANGED_ATTACK);
3067 void Unit::SetCurrentCastedSpell( Spell * pSpell )
3069 assert(pSpell); // NULL may be never passed here, use InterruptSpell or InterruptNonMeleeSpells
3071 CurrentSpellTypes CSpellType = pSpell->GetCurrentContainer();
3073 if (pSpell == m_currentSpells[CSpellType]) return; // avoid breaking self
3075 // break same type spell if it is not delayed
3076 InterruptSpell(CSpellType,false);
3078 // special breakage effects:
3079 switch (CSpellType)
3081 case CURRENT_GENERIC_SPELL:
3083 // generic spells always break channeled not delayed spells
3084 InterruptSpell(CURRENT_CHANNELED_SPELL,false);
3086 // autorepeat breaking
3087 if ( m_currentSpells[CURRENT_AUTOREPEAT_SPELL] )
3089 // break autorepeat if not Auto Shot
3090 if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT)
3091 InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
3092 m_AutoRepeatFirstCast = true;
3094 } break;
3096 case CURRENT_CHANNELED_SPELL:
3098 // channel spells always break generic non-delayed and any channeled spells
3099 InterruptSpell(CURRENT_GENERIC_SPELL,false);
3100 InterruptSpell(CURRENT_CHANNELED_SPELL);
3102 // it also does break autorepeat if not Auto Shot
3103 if ( m_currentSpells[CURRENT_AUTOREPEAT_SPELL] &&
3104 m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT )
3105 InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
3106 } break;
3108 case CURRENT_AUTOREPEAT_SPELL:
3110 // only Auto Shoot does not break anything
3111 if (pSpell->m_spellInfo->Id != SPELL_ID_AUTOSHOT)
3113 // generic autorepeats break generic non-delayed and channeled non-delayed spells
3114 InterruptSpell(CURRENT_GENERIC_SPELL,false);
3115 InterruptSpell(CURRENT_CHANNELED_SPELL,false);
3117 // special action: set first cast flag
3118 m_AutoRepeatFirstCast = true;
3119 } break;
3121 default:
3123 // other spell types don't break anything now
3124 } break;
3127 // current spell (if it is still here) may be safely deleted now
3128 if (m_currentSpells[CSpellType])
3129 m_currentSpells[CSpellType]->SetReferencedFromCurrent(false);
3131 // set new current spell
3132 m_currentSpells[CSpellType] = pSpell;
3133 pSpell->SetReferencedFromCurrent(true);
3136 void Unit::InterruptSpell(uint32 spellType, bool withDelayed)
3138 assert(spellType < CURRENT_MAX_SPELL);
3140 if (m_currentSpells[spellType] && (withDelayed || m_currentSpells[spellType]->getState() != SPELL_STATE_DELAYED) )
3142 // send autorepeat cancel message for autorepeat spells
3143 if (spellType == CURRENT_AUTOREPEAT_SPELL)
3145 if(GetTypeId()==TYPEID_PLAYER)
3146 ((Player*)this)->SendAutoRepeatCancel();
3149 if (m_currentSpells[spellType]->getState() != SPELL_STATE_FINISHED)
3150 m_currentSpells[spellType]->cancel();
3152 // cancel can interrupt spell already (caster cancel ->target aura remove -> caster iterrupt)
3153 if (m_currentSpells[spellType])
3155 m_currentSpells[spellType]->SetReferencedFromCurrent(false);
3156 m_currentSpells[spellType] = NULL;
3161 bool Unit::IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled, bool skipAutorepeat) const
3163 // We don't do loop here to explicitly show that melee spell is excluded.
3164 // Maybe later some special spells will be excluded too.
3166 // generic spells are casted when they are not finished and not delayed
3167 if ( m_currentSpells[CURRENT_GENERIC_SPELL] &&
3168 (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) &&
3169 (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED) )
3170 return(true);
3172 // channeled spells may be delayed, but they are still considered casted
3173 else if ( !skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] &&
3174 (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED) )
3175 return(true);
3177 // autorepeat spells may be finished or delayed, but they are still considered casted
3178 else if ( !skipAutorepeat && m_currentSpells[CURRENT_AUTOREPEAT_SPELL] )
3179 return(true);
3181 return(false);
3184 void Unit::InterruptNonMeleeSpells(bool withDelayed, uint32 spell_id)
3186 // generic spells are interrupted if they are not finished or delayed
3187 if (m_currentSpells[CURRENT_GENERIC_SPELL] && (!spell_id || m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->Id==spell_id))
3188 InterruptSpell(CURRENT_GENERIC_SPELL,withDelayed);
3190 // autorepeat spells are interrupted if they are not finished or delayed
3191 if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && (!spell_id || m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id==spell_id))
3192 InterruptSpell(CURRENT_AUTOREPEAT_SPELL,withDelayed);
3194 // channeled spells are interrupted if they are not finished, even if they are delayed
3195 if (m_currentSpells[CURRENT_CHANNELED_SPELL] && (!spell_id || m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->Id==spell_id))
3196 InterruptSpell(CURRENT_CHANNELED_SPELL,true);
3199 Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const
3201 for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i)
3202 if(m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->Id==spell_id)
3203 return m_currentSpells[i];
3204 return NULL;
3207 bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
3209 return IsWithinDistInMap(target, distance) && HasInArc( arc, target );
3212 void Unit::SetInFront(Unit const* target)
3214 SetOrientation(GetAngle(target));
3217 bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const
3219 return IsWithinDistInMap(target, distance) && !HasInArc( 2 * M_PI - arc, target );
3222 bool Unit::isInAccessablePlaceFor(Creature const* c) const
3224 if(IsInWater())
3225 return c->canSwim();
3226 else
3227 return c->canWalk() || c->canFly();
3230 bool Unit::IsInWater() const
3232 return MapManager::Instance().GetBaseMap(GetMapId())->IsInWater(GetPositionX(),GetPositionY(), GetPositionZ());
3235 bool Unit::IsUnderWater() const
3237 return MapManager::Instance().GetBaseMap(GetMapId())->IsUnderWater(GetPositionX(),GetPositionY(),GetPositionZ());
3240 void Unit::DeMorph()
3242 SetDisplayId(GetNativeDisplayId());
3245 int32 Unit::GetTotalAuraModifier(AuraType auratype) const
3247 int32 modifier = 0;
3249 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3250 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3251 modifier += (*i)->GetModifier()->m_amount;
3253 return modifier;
3256 float Unit::GetTotalAuraMultiplier(AuraType auratype) const
3258 float multiplier = 1.0f;
3260 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3261 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3262 multiplier *= (100.0f + (*i)->GetModifier()->m_amount)/100.0f;
3264 return multiplier;
3267 int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype) const
3269 int32 modifier = 0;
3271 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3272 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3273 if ((*i)->GetModifier()->m_amount > modifier)
3274 modifier = (*i)->GetModifier()->m_amount;
3276 return modifier;
3279 int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const
3281 int32 modifier = 0;
3283 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3284 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3285 if ((*i)->GetModifier()->m_amount < modifier)
3286 modifier = (*i)->GetModifier()->m_amount;
3288 return modifier;
3291 int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
3293 int32 modifier = 0;
3295 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3296 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3298 Modifier* mod = (*i)->GetModifier();
3299 if (mod->m_miscvalue & misc_mask)
3300 modifier += mod->m_amount;
3302 return modifier;
3305 float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
3307 float multiplier = 1.0f;
3309 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3310 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3312 Modifier* mod = (*i)->GetModifier();
3313 if (mod->m_miscvalue & misc_mask)
3314 multiplier *= (100.0f + mod->m_amount)/100.0f;
3316 return multiplier;
3319 int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
3321 int32 modifier = 0;
3323 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3324 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3326 Modifier* mod = (*i)->GetModifier();
3327 if (mod->m_miscvalue & misc_mask && mod->m_amount > modifier)
3328 modifier = mod->m_amount;
3331 return modifier;
3334 int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const
3336 int32 modifier = 0;
3338 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3339 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3341 Modifier* mod = (*i)->GetModifier();
3342 if (mod->m_miscvalue & misc_mask && mod->m_amount < modifier)
3343 modifier = mod->m_amount;
3346 return modifier;
3349 int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
3351 int32 modifier = 0;
3353 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3354 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3356 Modifier* mod = (*i)->GetModifier();
3357 if (mod->m_miscvalue == misc_value)
3358 modifier += mod->m_amount;
3360 return modifier;
3363 float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const
3365 float multiplier = 1.0f;
3367 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3368 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3370 Modifier* mod = (*i)->GetModifier();
3371 if (mod->m_miscvalue == misc_value)
3372 multiplier *= (100.0f + mod->m_amount)/100.0f;
3374 return multiplier;
3377 int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
3379 int32 modifier = 0;
3381 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3382 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3384 Modifier* mod = (*i)->GetModifier();
3385 if (mod->m_miscvalue == misc_value && mod->m_amount > modifier)
3386 modifier = mod->m_amount;
3389 return modifier;
3392 int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const
3394 int32 modifier = 0;
3396 AuraList const& mTotalAuraList = GetAurasByType(auratype);
3397 for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i)
3399 Modifier* mod = (*i)->GetModifier();
3400 if (mod->m_miscvalue == misc_value && mod->m_amount < modifier)
3401 modifier = mod->m_amount;
3404 return modifier;
3407 bool Unit::AddAura(Aura *Aur)
3409 // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
3410 if( !isAlive() && Aur->GetId() != 20584 && Aur->GetId() != 8326 && Aur->GetId() != 2584 &&
3411 (GetTypeId()!=TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) )
3413 delete Aur;
3414 return false;
3417 if(Aur->GetTarget() != this)
3419 sLog.outError("Aura (spell %u eff %u) add to aura list of %s (lowguid: %u) but Aura target is %s (lowguid: %u)",
3420 Aur->GetId(),Aur->GetEffIndex(),(GetTypeId()==TYPEID_PLAYER?"player":"creature"),GetGUIDLow(),
3421 (Aur->GetTarget()->GetTypeId()==TYPEID_PLAYER?"player":"creature"),Aur->GetTarget()->GetGUIDLow());
3422 delete Aur;
3423 return false;
3426 SpellEntry const* aurSpellInfo = Aur->GetSpellProto();
3427 AuraType aurName = Aur->GetModifier()->m_auraname;
3429 spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex());
3430 AuraMap::iterator i = m_Auras.find( spair );
3432 // take out same spell
3433 if (i != m_Auras.end())
3435 // passive and persistent auras can stack with themselves any number of times
3436 if (!Aur->IsPassive() && !Aur->IsPersistent())
3438 for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2)
3440 if(i2->second->GetCasterGUID()==Aur->GetCasterGUID())
3442 // Aura can stack on self -> Stack it;
3443 if(aurSpellInfo->StackAmount)
3445 i2->second->modStackAmount(1);
3446 delete Aur;
3447 return false;
3449 // can be only single (this check done at _each_ aura add
3450 RemoveAura(i2,AURA_REMOVE_BY_STACK);
3451 break;
3454 bool stop = false;
3455 switch(aurName)
3457 // DoT/HoT/etc
3458 case SPELL_AURA_PERIODIC_DAMAGE: // allow stack
3459 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
3460 case SPELL_AURA_PERIODIC_LEECH:
3461 case SPELL_AURA_PERIODIC_HEAL:
3462 case SPELL_AURA_OBS_MOD_HEALTH:
3463 case SPELL_AURA_PERIODIC_MANA_LEECH:
3464 case SPELL_AURA_PERIODIC_ENERGIZE:
3465 case SPELL_AURA_OBS_MOD_MANA:
3466 case SPELL_AURA_POWER_BURN_MANA:
3467 break;
3468 default: // not allow
3469 // can be only single (this check done at _each_ aura add
3470 RemoveAura(i2,AURA_REMOVE_BY_STACK);
3471 stop = true;
3472 break;
3475 if(stop)
3476 break;
3481 // passive auras not stacable with other ranks
3482 if (!IsPassiveSpellStackableWithRanks(aurSpellInfo))
3484 if (!RemoveNoStackAurasDueToAura(Aur))
3486 delete Aur;
3487 return false; // couldn't remove conflicting aura with higher rank
3491 // update single target auras list (before aura add to aura list, to prevent unexpected remove recently added aura)
3492 if (Aur->IsSingleTarget() && Aur->GetTarget())
3494 // caster pointer can be deleted in time aura remove, find it by guid at each iteration
3495 for(;;)
3497 Unit* caster = Aur->GetCaster();
3498 if(!caster) // caster deleted and not required adding scAura
3499 break;
3501 bool restart = false;
3502 AuraList& scAuras = caster->GetSingleCastAuras();
3503 for(AuraList::const_iterator itr = scAuras.begin(); itr != scAuras.end(); ++itr)
3505 if( (*itr)->GetTarget() != Aur->GetTarget() &&
3506 IsSingleTargetSpells((*itr)->GetSpellProto(),aurSpellInfo) )
3508 if ((*itr)->IsInUse())
3510 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());
3511 continue;
3513 (*itr)->GetTarget()->RemoveAura((*itr)->GetId(), (*itr)->GetEffIndex());
3514 restart = true;
3515 break;
3519 if(!restart)
3521 // done
3522 scAuras.push_back(Aur);
3523 break;
3528 // add aura, register in lists and arrays
3529 Aur->_AddAura();
3530 m_Auras.insert(AuraMap::value_type(spellEffectPair(Aur->GetId(), Aur->GetEffIndex()), Aur));
3531 if (aurName < TOTAL_AURAS)
3533 m_modAuras[aurName].push_back(Aur);
3536 Aur->ApplyModifier(true,true);
3537 sLog.outDebug("Aura %u now is in use", aurName);
3538 return true;
3541 void Unit::RemoveRankAurasDueToSpell(uint32 spellId)
3543 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
3544 if(!spellInfo)
3545 return;
3546 AuraMap::const_iterator i,next;
3547 for (i = m_Auras.begin(); i != m_Auras.end(); i = next)
3549 next = i;
3550 ++next;
3551 uint32 i_spellId = (*i).second->GetId();
3552 if((*i).second && i_spellId && i_spellId != spellId)
3554 if(spellmgr.IsRankSpellDueToSpell(spellInfo,i_spellId))
3556 RemoveAurasDueToSpell(i_spellId);
3558 if( m_Auras.empty() )
3559 break;
3560 else
3561 next = m_Auras.begin();
3567 bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
3569 if (!Aur)
3570 return false;
3572 SpellEntry const* spellProto = Aur->GetSpellProto();
3573 if (!spellProto)
3574 return false;
3576 uint32 spellId = Aur->GetId();
3577 uint32 effIndex = Aur->GetEffIndex();
3579 // passive spell special case (only non stackable with ranks)
3580 if(IsPassiveSpell(spellId))
3582 if(IsPassiveSpellStackableWithRanks(spellProto))
3583 return true;
3586 SpellSpecific spellId_spec = GetSpellSpecific(spellId);
3588 AuraMap::iterator i,next;
3589 for (i = m_Auras.begin(); i != m_Auras.end(); i = next)
3591 next = i;
3592 ++next;
3593 if (!(*i).second) continue;
3595 SpellEntry const* i_spellProto = (*i).second->GetSpellProto();
3597 if (!i_spellProto)
3598 continue;
3600 uint32 i_spellId = i_spellProto->Id;
3602 // early checks that spellId is passive non stackable spell
3603 if(IsPassiveSpell(i_spellId))
3605 // passive non-stackable spells not stackable only for same caster
3606 if(Aur->GetCasterGUID()!=i->second->GetCasterGUID())
3607 continue;
3609 // passive non-stackable spells not stackable only with another rank of same spell
3610 if (!spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
3611 continue;
3614 uint32 i_effIndex = (*i).second->GetEffIndex();
3616 if(i_spellId == spellId) continue;
3618 bool is_triggered_by_spell = false;
3619 // prevent triggered aura of removing aura that triggered it
3620 for(int j = 0; j < 3; ++j)
3621 if (i_spellProto->EffectTriggerSpell[j] == spellProto->Id)
3622 is_triggered_by_spell = true;
3624 if (is_triggered_by_spell)
3625 continue;
3627 SpellSpecific i_spellId_spec = GetSpellSpecific(i_spellId);
3629 bool is_sspc = IsSingleFromSpellSpecificPerCaster(spellId_spec,i_spellId_spec);
3630 bool is_sspt = IsSingleFromSpellSpecificRanksPerTarget(spellId_spec,i_spellId_spec);
3632 if( is_sspc && Aur->GetCasterGUID() == (*i).second->GetCasterGUID() )
3634 // cannot remove higher rank
3635 if (spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId))
3636 if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
3637 return false;
3639 // Its a parent aura (create this aura in ApplyModifier)
3640 if ((*i).second->IsInUse())
3642 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());
3643 continue;
3645 RemoveAurasDueToSpell(i_spellId);
3647 if( m_Auras.empty() )
3648 break;
3649 else
3650 next = m_Auras.begin();
3652 else if( is_sspt && Aur->GetCasterGUID() != (*i).second->GetCasterGUID() && spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId) )
3654 // cannot remove higher rank
3655 if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
3656 return false;
3658 // Its a parent aura (create this aura in ApplyModifier)
3659 if ((*i).second->IsInUse())
3661 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());
3662 continue;
3664 RemoveAurasDueToSpell(i_spellId);
3666 if( m_Auras.empty() )
3667 break;
3668 else
3669 next = m_Auras.begin();
3671 else if( !is_sspc && spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId) )
3673 // Its a parent aura (create this aura in ApplyModifier)
3674 if ((*i).second->IsInUse())
3676 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());
3677 continue;
3679 RemoveAurasDueToSpell(i_spellId);
3681 if( m_Auras.empty() )
3682 break;
3683 else
3684 next = m_Auras.begin();
3686 // Potions stack aura by aura (elixirs/flask already checked)
3687 else if( spellProto->SpellFamilyName == SPELLFAMILY_POTION && i_spellProto->SpellFamilyName == SPELLFAMILY_POTION )
3689 if (IsNoStackAuraDueToAura(spellId, effIndex, i_spellId, i_effIndex))
3691 if(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)
3692 return false; // cannot remove higher rank
3694 // Its a parent aura (create this aura in ApplyModifier)
3695 if ((*i).second->IsInUse())
3697 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());
3698 continue;
3700 RemoveAura(i);
3701 next = i;
3705 return true;
3708 void Unit::RemoveAura(uint32 spellId, uint32 effindex, Aura* except)
3710 spellEffectPair spair = spellEffectPair(spellId, effindex);
3711 for(AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);)
3713 if(iter->second!=except)
3715 RemoveAura(iter);
3716 iter = m_Auras.lower_bound(spair);
3718 else
3719 ++iter;
3723 void Unit::RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID)
3725 for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
3727 Aura *aur = iter->second;
3728 if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
3729 RemoveAura(iter);
3730 else
3731 ++iter;
3735 void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler)
3737 for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
3739 Aura *aur = iter->second;
3740 if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
3742 // Custom dispel case
3743 // Unstable Affliction
3744 if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x010000000000)))
3746 int32 damage = aur->GetModifier()->m_amount*9;
3747 uint64 caster_guid = aur->GetCasterGUID();
3749 // Remove aura
3750 RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
3752 // backfire damage and silence
3753 dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,caster_guid);
3755 iter = m_Auras.begin(); // iterator can be invalidate at cast if self-dispel
3757 else
3758 RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
3760 else
3761 ++iter;
3765 void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer)
3767 for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
3769 Aura *aur = iter->second;
3770 if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID)
3772 int32 basePoints = aur->GetBasePoints();
3773 // construct the new aura for the attacker - will never return NULL, it's just a wrapper for
3774 // some different constructors
3775 Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), &basePoints, stealer, this);
3777 // set its duration and maximum duration
3778 // max duration 2 minutes (in msecs)
3779 int32 dur = aur->GetAuraDuration();
3780 const int32 max_dur = 2*MINUTE*IN_MILISECONDS;
3781 new_aur->SetAuraMaxDuration( max_dur > dur ? dur : max_dur );
3782 new_aur->SetAuraDuration( max_dur > dur ? dur : max_dur );
3784 // Unregister _before_ adding to stealer
3785 aur->UnregisterSingleCastAura();
3787 // strange but intended behaviour: Stolen single target auras won't be treated as single targeted
3788 new_aur->SetIsSingleTarget(false);
3790 // add the new aura to stealer
3791 stealer->AddAura(new_aur);
3793 // Remove aura as dispel
3794 RemoveAura(iter, AURA_REMOVE_BY_DISPEL);
3796 else
3797 ++iter;
3801 void Unit::RemoveAurasDueToSpellByCancel(uint32 spellId)
3803 for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
3805 if (iter->second->GetId() == spellId)
3806 RemoveAura(iter, AURA_REMOVE_BY_CANCEL);
3807 else
3808 ++iter;
3812 void Unit::RemoveAurasWithDispelType( DispelType type )
3814 // Create dispel mask by dispel type
3815 uint32 dispelMask = GetDispellMask(type);
3816 // Dispel all existing auras vs current dispel type
3817 AuraMap& auras = GetAuras();
3818 for(AuraMap::iterator itr = auras.begin(); itr != auras.end(); )
3820 SpellEntry const* spell = itr->second->GetSpellProto();
3821 if( (1<<spell->Dispel) & dispelMask )
3823 // Dispel aura
3824 RemoveAurasDueToSpell(spell->Id);
3825 itr = auras.begin();
3827 else
3828 ++itr;
3832 void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex)
3834 AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
3835 if(iter != m_Auras.end())
3837 if (iter->second->modStackAmount(-1))
3838 RemoveAura(iter);
3842 void Unit::RemoveSingleSpellAurasFromStack(uint32 spellId)
3844 for (int i=0; i<3; ++i)
3845 RemoveSingleAuraFromStack(spellId, i);
3848 void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except)
3850 for (int i = 0; i < 3; ++i)
3851 RemoveAura(spellId,i,except);
3854 void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId)
3856 for (int k=0; k < 3; ++k)
3858 spellEffectPair spair = spellEffectPair(spellId, k);
3859 for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);)
3861 if (iter->second->GetCastItemGUID() == castItem->GetGUID())
3863 RemoveAura(iter);
3864 iter = m_Auras.upper_bound(spair); // overwrite by more appropriate
3866 else
3867 ++iter;
3872 void Unit::RemoveAurasWithInterruptFlags(uint32 flags)
3874 for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
3876 if (iter->second->GetSpellProto()->AuraInterruptFlags & flags)
3877 RemoveAura(iter);
3878 else
3879 ++iter;
3883 void Unit::RemoveNotOwnSingleTargetAuras()
3885 // single target auras from other casters
3886 for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
3888 if (iter->second->GetCasterGUID()!=GetGUID() && IsSingleTargetSpell(iter->second->GetSpellProto()))
3889 RemoveAura(iter);
3890 else
3891 ++iter;
3894 // single target auras at other targets
3895 AuraList& scAuras = GetSingleCastAuras();
3896 for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end(); )
3898 Aura* aura = *iter;
3899 if (aura->GetTarget()!=this)
3901 scAuras.erase(iter); // explicitly remove, instead waiting remove in RemoveAura
3902 aura->GetTarget()->RemoveAura(aura->GetId(),aura->GetEffIndex());
3903 iter = scAuras.begin();
3905 else
3906 ++iter;
3911 void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
3913 Aura* Aur = i->second;
3914 SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
3916 Aur->UnregisterSingleCastAura();
3918 // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order)
3919 if (Aur->GetModifier()->m_auraname < TOTAL_AURAS)
3921 m_modAuras[Aur->GetModifier()->m_auraname].remove(Aur);
3924 // Set remove mode
3925 Aur->SetRemoveMode(mode);
3926 // some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura
3927 // remove aura from list before to prevent deleting it before
3928 m_Auras.erase(i);
3929 ++m_removedAuras; // internal count used by unit update
3931 // Statue unsummoned at aura remove
3932 Totem* statue = NULL;
3933 bool caster_channeled = false;
3934 if(IsChanneledSpell(AurSpellInfo))
3936 Unit* caster = Aur->GetCaster();
3938 if(caster)
3940 if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE)
3941 statue = ((Totem*)caster);
3942 else
3943 caster_channeled = caster==this;
3947 sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode);
3948 Aur->ApplyModifier(false,true);
3949 Aur->_RemoveAura();
3950 delete Aur;
3952 if(caster_channeled)
3953 RemoveAurasAtChanneledTarget (AurSpellInfo);
3955 if(statue)
3956 statue->UnSummon();
3958 // only way correctly remove all auras from list
3959 if( m_Auras.empty() )
3960 i = m_Auras.end();
3961 else
3962 i = m_Auras.begin();
3965 void Unit::RemoveAllAuras()
3967 while (!m_Auras.empty())
3969 AuraMap::iterator iter = m_Auras.begin();
3970 RemoveAura(iter);
3974 void Unit::RemoveArenaAuras(bool onleave)
3976 // in join, remove positive buffs, on end, remove negative
3977 // used to remove positive visible auras in arenas
3978 for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
3980 if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras
3981 && !iter->second->IsPassive() // don't remove passive auras
3982 && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable)
3983 && (iter->second->IsPositive() ^ onleave)) // remove positive buffs on enter, negative buffs on leave
3984 RemoveAura(iter);
3985 else
3986 ++iter;
3990 void Unit::RemoveAllAurasOnDeath()
3992 // used just after dieing to remove all visible auras
3993 // and disable the mods for the passive ones
3994 for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
3996 if (!iter->second->IsPassive() && !iter->second->IsDeathPersistent())
3997 RemoveAura(iter, AURA_REMOVE_BY_DEATH);
3998 else
3999 ++iter;
4003 void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime)
4005 AuraMap::const_iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
4006 if (iter != m_Auras.end())
4008 if (iter->second->GetAuraDuration() < delaytime)
4009 iter->second->SetAuraDuration(0);
4010 else
4011 iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime);
4012 iter->second->SendAuraUpdate(false);
4013 sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration());
4017 void Unit::_RemoveAllAuraMods()
4019 for (AuraMap::const_iterator i = m_Auras.begin(); i != m_Auras.end(); ++i)
4021 (*i).second->ApplyModifier(false);
4025 void Unit::_ApplyAllAuraMods()
4027 for (AuraMap::const_iterator i = m_Auras.begin(); i != m_Auras.end(); ++i)
4029 (*i).second->ApplyModifier(true);
4033 Aura* Unit::GetAura(uint32 spellId, uint32 effindex)
4035 AuraMap::const_iterator iter = m_Auras.find(spellEffectPair(spellId, effindex));
4036 if (iter != m_Auras.end())
4037 return iter->second;
4038 return NULL;
4041 Aura* Unit::GetAura(AuraType type, uint32 family, uint64 familyFlag, uint32 familyFlag2, uint64 casterGUID)
4043 AuraList const& auras = GetAurasByType(type);
4044 for(AuraList::const_iterator i = auras.begin();i != auras.end(); ++i)
4046 SpellEntry const *spell = (*i)->GetSpellProto();
4047 if (spell->SpellFamilyName == family && (spell->SpellFamilyFlags & familyFlag || spell->SpellFamilyFlags2 & familyFlag2))
4049 if (casterGUID && (*i)->GetCasterGUID()!=casterGUID)
4050 continue;
4051 return (*i);
4054 return NULL;
4057 bool Unit::HasAura(uint32 spellId) const
4059 for (int i = 0; i < 3 ; ++i)
4061 AuraMap::const_iterator iter = m_Auras.find(spellEffectPair(spellId, i));
4062 if (iter != m_Auras.end())
4063 return true;
4065 return false;
4068 void Unit::AddDynObject(DynamicObject* dynObj)
4070 m_dynObjGUIDs.push_back(dynObj->GetGUID());
4073 void Unit::RemoveDynObject(uint32 spellid)
4075 if(m_dynObjGUIDs.empty())
4076 return;
4077 for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();)
4079 DynamicObject* dynObj = GetMap()->GetDynamicObject(*i);
4080 if(!dynObj)
4082 i = m_dynObjGUIDs.erase(i);
4084 else if(spellid == 0 || dynObj->GetSpellId() == spellid)
4086 dynObj->Delete();
4087 i = m_dynObjGUIDs.erase(i);
4089 else
4090 ++i;
4094 void Unit::RemoveAllDynObjects()
4096 while(!m_dynObjGUIDs.empty())
4098 DynamicObject* dynObj = GetMap()->GetDynamicObject(*m_dynObjGUIDs.begin());
4099 if(dynObj)
4100 dynObj->Delete();
4101 m_dynObjGUIDs.erase(m_dynObjGUIDs.begin());
4105 DynamicObject * Unit::GetDynObject(uint32 spellId, uint32 effIndex)
4107 for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();)
4109 DynamicObject* dynObj = GetMap()->GetDynamicObject(*i);
4110 if(!dynObj)
4112 i = m_dynObjGUIDs.erase(i);
4113 continue;
4116 if (dynObj->GetSpellId() == spellId && dynObj->GetEffIndex() == effIndex)
4117 return dynObj;
4118 ++i;
4120 return NULL;
4123 DynamicObject * Unit::GetDynObject(uint32 spellId)
4125 for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();)
4127 DynamicObject* dynObj = GetMap()->GetDynamicObject(*i);
4128 if(!dynObj)
4130 i = m_dynObjGUIDs.erase(i);
4131 continue;
4134 if (dynObj->GetSpellId() == spellId)
4135 return dynObj;
4136 ++i;
4138 return NULL;
4141 GameObject* Unit::GetGameObject(uint32 spellId) const
4143 for (GameObjectList::const_iterator i = m_gameObj.begin(); i != m_gameObj.end(); ++i)
4144 if ((*i)->GetSpellId() == spellId)
4145 return *i;
4147 return NULL;
4150 void Unit::AddGameObject(GameObject* gameObj)
4152 assert(gameObj && gameObj->GetOwnerGUID()==0);
4153 m_gameObj.push_back(gameObj);
4154 gameObj->SetOwnerGUID(GetGUID());
4156 if ( GetTypeId()==TYPEID_PLAYER && gameObj->GetSpellId() )
4158 SpellEntry const* createBySpell = sSpellStore.LookupEntry(gameObj->GetSpellId());
4159 // Need disable spell use for owner
4160 if (createBySpell && createBySpell->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
4161 // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
4162 ((Player*)this)->AddSpellAndCategoryCooldowns(createBySpell,0,NULL,true);
4166 void Unit::RemoveGameObject(GameObject* gameObj, bool del)
4168 assert(gameObj && gameObj->GetOwnerGUID()==GetGUID());
4170 gameObj->SetOwnerGUID(0);
4172 // GO created by some spell
4173 if (uint32 spellid = gameObj->GetSpellId())
4175 RemoveAurasDueToSpell(spellid);
4177 if (GetTypeId()==TYPEID_PLAYER)
4179 SpellEntry const* createBySpell = sSpellStore.LookupEntry(spellid );
4180 // Need activate spell use for owner
4181 if (createBySpell && createBySpell->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
4182 // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
4183 ((Player*)this)->SendCooldownEvent(createBySpell);
4187 m_gameObj.remove(gameObj);
4189 if(del)
4191 gameObj->SetRespawnTime(0);
4192 gameObj->Delete();
4196 void Unit::RemoveGameObject(uint32 spellid, bool del)
4198 if(m_gameObj.empty())
4199 return;
4200 GameObjectList::iterator i, next;
4201 for (i = m_gameObj.begin(); i != m_gameObj.end(); i = next)
4203 next = i;
4204 if(spellid == 0 || (*i)->GetSpellId() == spellid)
4206 (*i)->SetOwnerGUID(0);
4207 if(del)
4209 (*i)->SetRespawnTime(0);
4210 (*i)->Delete();
4213 next = m_gameObj.erase(i);
4215 else
4216 ++next;
4220 void Unit::RemoveAllGameObjects()
4222 // remove references to unit
4223 for(GameObjectList::iterator i = m_gameObj.begin(); i != m_gameObj.end();)
4225 (*i)->SetOwnerGUID(0);
4226 (*i)->SetRespawnTime(0);
4227 (*i)->Delete();
4228 i = m_gameObj.erase(i);
4232 void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log)
4234 WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16+4+4+4+1+4+4+1+1+4+4+1)); // we guess size
4235 data.append(log->target->GetPackGUID());
4236 data.append(log->attacker->GetPackGUID());
4237 data << uint32(log->SpellID);
4238 data << uint32(log->damage); // damage amount
4239 data << uint32(log->overkill); // overkill
4240 data << uint8 (log->schoolMask); // damage school
4241 data << uint32(log->absorb); // AbsorbedDamage
4242 data << uint32(log->resist); // resist
4243 data << uint8 (log->physicalLog); // 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
4244 data << uint8 (log->unused); // unused
4245 data << uint32(log->blocked); // blocked
4246 data << uint32(log->HitInfo);
4247 data << uint8 (0); // flag to use extend data
4248 SendMessageToSet( &data, true );
4251 void Unit::SendSpellNonMeleeDamageLog(Unit *target, uint32 SpellID, uint32 Damage, SpellSchoolMask damageSchoolMask, uint32 AbsorbedDamage, uint32 Resist, bool PhysicalDamage, uint32 Blocked, bool CriticalHit)
4253 SpellNonMeleeDamage log(this, target, SpellID, damageSchoolMask);
4254 log.damage = Damage - AbsorbedDamage - Resist - Blocked;
4255 log.absorb = AbsorbedDamage;
4256 log.resist = Resist;
4257 log.physicalLog = PhysicalDamage;
4258 log.blocked = Blocked;
4259 log.HitInfo = SPELL_HIT_TYPE_UNK1 | SPELL_HIT_TYPE_UNK3 | SPELL_HIT_TYPE_UNK6;
4260 if(CriticalHit)
4261 log.HitInfo |= SPELL_HIT_TYPE_CRIT;
4262 SendSpellNonMeleeDamageLog(&log);
4265 void Unit::SendPeriodicAuraLog(SpellPeriodicAuraLogInfo *pInfo)
4267 Aura *aura = pInfo->aura;
4268 Modifier *mod = aura->GetModifier();
4270 WorldPacket data(SMSG_PERIODICAURALOG, 30);
4271 data.append(aura->GetTarget()->GetPackGUID());
4272 data.appendPackGUID(aura->GetCasterGUID());
4273 data << uint32(aura->GetId()); // spellId
4274 data << uint32(1); // count
4275 data << uint32(mod->m_auraname); // auraId
4276 switch(mod->m_auraname)
4278 case SPELL_AURA_PERIODIC_DAMAGE:
4279 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
4280 data << uint32(pInfo->damage); // damage
4281 data << uint32(pInfo->overDamage); // overkill?
4282 data << uint32(GetSpellSchoolMask(aura->GetSpellProto()));
4283 data << uint32(pInfo->absorb); // absorb
4284 data << uint32(pInfo->resist); // resist
4285 data << uint8(0); // new 3.1.2
4286 break;
4287 case SPELL_AURA_PERIODIC_HEAL:
4288 case SPELL_AURA_OBS_MOD_HEALTH:
4289 data << uint32(pInfo->damage); // damage
4290 data << uint32(pInfo->overDamage); // overheal?
4291 data << uint8(0); // new 3.1.2
4292 break;
4293 case SPELL_AURA_OBS_MOD_MANA:
4294 case SPELL_AURA_PERIODIC_ENERGIZE:
4295 data << uint32(mod->m_miscvalue); // power type
4296 data << uint32(pInfo->damage); // damage
4297 break;
4298 case SPELL_AURA_PERIODIC_MANA_LEECH:
4299 data << uint32(mod->m_miscvalue); // power type
4300 data << uint32(pInfo->damage); // amount
4301 data << float(pInfo->multiplier); // gain multiplier
4302 break;
4303 default:
4304 sLog.outError("Unit::SendPeriodicAuraLog: unknown aura %u", uint32(mod->m_auraname));
4305 return;
4308 aura->GetTarget()->SendMessageToSet(&data, true);
4311 void Unit::ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 procExtra, uint32 amount, WeaponAttackType attType, SpellEntry const *procSpell)
4313 // Not much to do if no flags are set.
4314 if (procAttacker)
4315 ProcDamageAndSpellFor(false,pVictim,procAttacker, procExtra,attType, procSpell, amount);
4316 // Now go on with a victim's events'n'auras
4317 // Not much to do if no flags are set or there is no victim
4318 if(pVictim && pVictim->isAlive() && procVictim)
4319 pVictim->ProcDamageAndSpellFor(true,this,procVictim, procExtra, attType, procSpell, amount);
4322 void Unit::SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo)
4324 WorldPacket data(SMSG_SPELLLOGMISS, (4+8+1+4+8+1));
4325 data << uint32(spellID);
4326 data << uint64(GetGUID());
4327 data << uint8(0); // can be 0 or 1
4328 data << uint32(1); // target count
4329 // for(i = 0; i < target count; ++i)
4330 data << uint64(target->GetGUID()); // target GUID
4331 data << uint8(missInfo);
4332 // end loop
4333 SendMessageToSet(&data, true);
4336 void Unit::SendAttackStateUpdate(CalcDamageInfo *damageInfo)
4338 sLog.outDebug("WORLD: Sending SMSG_ATTACKERSTATEUPDATE");
4340 uint32 count = 1;
4341 WorldPacket data(SMSG_ATTACKERSTATEUPDATE, 16 + 45); // we guess size
4342 data << uint32(damageInfo->HitInfo);
4343 data.append(damageInfo->attacker->GetPackGUID());
4344 data.append(damageInfo->target->GetPackGUID());
4345 data << uint32(damageInfo->damage); // Full damage
4346 data << uint32(0); // overkill value
4347 data << uint8(count); // Sub damage count
4349 for(int i = 0; i < count; ++i)
4351 data << uint32(damageInfo->damageSchoolMask); // School of sub damage
4352 data << float(damageInfo->damage); // sub damage
4353 data << uint32(damageInfo->damage); // Sub Damage
4356 if(damageInfo->HitInfo & (HITINFO_ABSORB | HITINFO_ABSORB2))
4358 for(int i = 0; i < count; ++i)
4359 data << uint32(damageInfo->absorb); // Absorb
4362 if(damageInfo->HitInfo & (HITINFO_RESIST | HITINFO_RESIST2))
4364 for(int i = 0; i < count; ++i)
4365 data << uint32(damageInfo->resist); // Resist
4368 data << uint8(damageInfo->TargetState);
4369 data << uint32(0);
4370 data << uint32(0);
4372 if(damageInfo->HitInfo & HITINFO_BLOCK)
4373 data << uint32(damageInfo->blocked_amount);
4375 if(damageInfo->HitInfo & HITINFO_UNK3)
4376 data << uint32(0);
4378 if(damageInfo->HitInfo & HITINFO_UNK1)
4380 data << uint32(0);
4381 data << float(0);
4382 data << float(0);
4383 data << float(0);
4384 data << float(0);
4385 data << float(0);
4386 data << float(0);
4387 data << float(0);
4388 data << float(0);
4389 for(uint8 i = 0; i < 5; ++i)
4391 data << float(0);
4392 data << float(0);
4394 data << uint32(0);
4397 SendMessageToSet( &data, true );
4400 void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount)
4402 CalcDamageInfo dmgInfo;
4403 dmgInfo.HitInfo = HitInfo;
4404 dmgInfo.attacker = this;
4405 dmgInfo.target = target;
4406 dmgInfo.damage = Damage - AbsorbDamage - Resist - BlockedAmount;
4407 dmgInfo.damageSchoolMask = damageSchoolMask;
4408 dmgInfo.absorb = AbsorbDamage;
4409 dmgInfo.resist = Resist;
4410 dmgInfo.TargetState = TargetState;
4411 dmgInfo.blocked_amount = BlockedAmount;
4412 SendAttackStateUpdate(&dmgInfo);
4415 bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * /*procSpell*/, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown)
4417 SpellEntry const *hasteSpell = triggeredByAura->GetSpellProto();
4419 Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
4420 ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
4422 uint32 triggered_spell_id = 0;
4423 Unit* target = pVictim;
4424 int32 basepoints0 = 0;
4426 switch(hasteSpell->SpellFamilyName)
4428 case SPELLFAMILY_ROGUE:
4430 switch(hasteSpell->Id)
4432 // Blade Flurry
4433 case 13877:
4434 case 33735:
4436 target = SelectNearbyTarget();
4437 if(!target)
4438 return false;
4439 basepoints0 = damage;
4440 triggered_spell_id = 22482;
4441 break;
4444 break;
4448 // processed charge only counting case
4449 if(!triggered_spell_id)
4450 return true;
4452 SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id);
4454 if(!triggerEntry)
4456 sLog.outError("Unit::HandleHasteAuraProc: Spell %u have not existed triggered spell %u",hasteSpell->Id,triggered_spell_id);
4457 return false;
4460 // default case
4461 if(!target || target!=this && !target->isAlive())
4462 return false;
4464 if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id))
4465 return false;
4467 if(basepoints0)
4468 CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
4469 else
4470 CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura);
4472 if( cooldown && GetTypeId()==TYPEID_PLAYER )
4473 ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown);
4475 return true;
4478 bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
4480 SpellEntry const *dummySpell = triggeredByAura->GetSpellProto ();
4481 uint32 effIndex = triggeredByAura->GetEffIndex();
4482 int32 triggerAmount = triggeredByAura->GetModifier()->m_amount;
4484 Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
4485 ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
4487 uint32 triggered_spell_id = 0;
4488 Unit* target = pVictim;
4489 int32 basepoints0 = 0;
4491 switch(dummySpell->SpellFamilyName)
4493 case SPELLFAMILY_GENERIC:
4495 switch (dummySpell->Id)
4497 // Eye for an Eye
4498 case 9799:
4499 case 25988:
4501 // return damage % to attacker but < 50% own total health
4502 basepoints0 = triggerAmount*int32(damage)/100;
4503 if(basepoints0 > GetMaxHealth()/2)
4504 basepoints0 = GetMaxHealth()/2;
4506 triggered_spell_id = 25997;
4507 break;
4509 // Sweeping Strikes
4510 case 12328:
4511 case 18765:
4512 case 35429:
4514 // prevent chain of triggered spell from same triggered spell
4515 if(procSpell && procSpell->Id==26654)
4516 return false;
4518 target = SelectNearbyTarget();
4519 if(!target)
4520 return false;
4522 triggered_spell_id = 26654;
4523 break;
4525 // Unstable Power
4526 case 24658:
4528 if (!procSpell || procSpell->Id == 24659)
4529 return false;
4530 // Need remove one 24659 aura
4531 RemoveSingleSpellAurasFromStack(24659);
4532 return true;
4534 // Restless Strength
4535 case 24661:
4537 // Need remove one 24662 aura
4538 RemoveSingleSpellAurasFromStack(24662);
4539 return true;
4541 // Adaptive Warding (Frostfire Regalia set)
4542 case 28764:
4544 if(!procSpell)
4545 return false;
4547 // find Mage Armor
4548 bool found = false;
4549 AuraList const& mRegenInterupt = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT);
4550 for(AuraList::const_iterator iter = mRegenInterupt.begin(); iter != mRegenInterupt.end(); ++iter)
4552 if(SpellEntry const* iterSpellProto = (*iter)->GetSpellProto())
4554 if(iterSpellProto->SpellFamilyName==SPELLFAMILY_MAGE && (iterSpellProto->SpellFamilyFlags & UI64LIT(0x10000000)))
4556 found=true;
4557 break;
4561 if(!found)
4562 return false;
4564 switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell)))
4566 case SPELL_SCHOOL_NORMAL:
4567 case SPELL_SCHOOL_HOLY:
4568 return false; // ignored
4569 case SPELL_SCHOOL_FIRE: triggered_spell_id = 28765; break;
4570 case SPELL_SCHOOL_NATURE: triggered_spell_id = 28768; break;
4571 case SPELL_SCHOOL_FROST: triggered_spell_id = 28766; break;
4572 case SPELL_SCHOOL_SHADOW: triggered_spell_id = 28769; break;
4573 case SPELL_SCHOOL_ARCANE: triggered_spell_id = 28770; break;
4574 default:
4575 return false;
4578 target = this;
4579 break;
4581 // Obsidian Armor (Justice Bearer`s Pauldrons shoulder)
4582 case 27539:
4584 if(!procSpell)
4585 return false;
4587 switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell)))
4589 case SPELL_SCHOOL_NORMAL:
4590 return false; // ignore
4591 case SPELL_SCHOOL_HOLY: triggered_spell_id = 27536; break;
4592 case SPELL_SCHOOL_FIRE: triggered_spell_id = 27533; break;
4593 case SPELL_SCHOOL_NATURE: triggered_spell_id = 27538; break;
4594 case SPELL_SCHOOL_FROST: triggered_spell_id = 27534; break;
4595 case SPELL_SCHOOL_SHADOW: triggered_spell_id = 27535; break;
4596 case SPELL_SCHOOL_ARCANE: triggered_spell_id = 27540; break;
4597 default:
4598 return false;
4601 target = this;
4602 break;
4604 // Mana Leech (Passive) (Priest Pet Aura)
4605 case 28305:
4607 // Cast on owner
4608 target = GetOwner();
4609 if(!target)
4610 return false;
4612 triggered_spell_id = 34650;
4613 break;
4615 // Mark of Malice
4616 case 33493:
4618 // Cast finish spell at last charge
4619 if (triggeredByAura->GetAuraCharges() > 1)
4620 return false;
4622 target = this;
4623 triggered_spell_id = 33494;
4624 break;
4626 // Twisted Reflection (boss spell)
4627 case 21063:
4628 triggered_spell_id = 21064;
4629 break;
4630 // Vampiric Aura (boss spell)
4631 case 38196:
4633 basepoints0 = 3 * damage; // 300%
4634 if (basepoints0 < 0)
4635 return false;
4637 triggered_spell_id = 31285;
4638 target = this;
4639 break;
4641 // Aura of Madness (Darkmoon Card: Madness trinket)
4642 //=====================================================
4643 // 39511 Sociopath: +35 strength (Paladin, Rogue, Druid, Warrior)
4644 // 40997 Delusional: +70 attack power (Rogue, Hunter, Paladin, Warrior, Druid)
4645 // 40998 Kleptomania: +35 agility (Warrior, Rogue, Paladin, Hunter, Druid)
4646 // 40999 Megalomania: +41 damage/healing (Druid, Shaman, Priest, Warlock, Mage, Paladin)
4647 // 41002 Paranoia: +35 spell/melee/ranged crit strike rating (All classes)
4648 // 41005 Manic: +35 haste (spell, melee and ranged) (All classes)
4649 // 41009 Narcissism: +35 intellect (Druid, Shaman, Priest, Warlock, Mage, Paladin, Hunter)
4650 // 41011 Martyr Complex: +35 stamina (All classes)
4651 // 41406 Dementia: Every 5 seconds either gives you +5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin)
4652 // 41409 Dementia: Every 5 seconds either gives you -5% damage/healing. (Druid, Shaman, Priest, Warlock, Mage, Paladin)
4653 case 39446:
4655 if(GetTypeId() != TYPEID_PLAYER)
4656 return false;
4658 // Select class defined buff
4659 switch (getClass())
4661 case CLASS_PALADIN: // 39511,40997,40998,40999,41002,41005,41009,41011,41409
4662 case CLASS_DRUID: // 39511,40997,40998,40999,41002,41005,41009,41011,41409
4664 uint32 RandomSpell[]={39511,40997,40998,40999,41002,41005,41009,41011,41409};
4665 triggered_spell_id = RandomSpell[ irand(0, sizeof(RandomSpell)/sizeof(uint32) - 1) ];
4666 break;
4668 case CLASS_ROGUE: // 39511,40997,40998,41002,41005,41011
4669 case CLASS_WARRIOR: // 39511,40997,40998,41002,41005,41011
4671 uint32 RandomSpell[]={39511,40997,40998,41002,41005,41011};
4672 triggered_spell_id = RandomSpell[ irand(0, sizeof(RandomSpell)/sizeof(uint32) - 1) ];
4673 break;
4675 case CLASS_PRIEST: // 40999,41002,41005,41009,41011,41406,41409
4676 case CLASS_SHAMAN: // 40999,41002,41005,41009,41011,41406,41409
4677 case CLASS_MAGE: // 40999,41002,41005,41009,41011,41406,41409
4678 case CLASS_WARLOCK: // 40999,41002,41005,41009,41011,41406,41409
4680 uint32 RandomSpell[]={40999,41002,41005,41009,41011,41406,41409};
4681 triggered_spell_id = RandomSpell[ irand(0, sizeof(RandomSpell)/sizeof(uint32) - 1) ];
4682 break;
4684 case CLASS_HUNTER: // 40997,40999,41002,41005,41009,41011,41406,41409
4686 uint32 RandomSpell[]={40997,40999,41002,41005,41009,41011,41406,41409};
4687 triggered_spell_id = RandomSpell[ irand(0, sizeof(RandomSpell)/sizeof(uint32) - 1) ];
4688 break;
4690 default:
4691 return false;
4694 target = this;
4695 if (roll_chance_i(10))
4696 ((Player*)this)->Say("This is Madness!", LANG_UNIVERSAL);
4697 break;
4700 // TODO: need find item for aura and triggered spells
4701 // Sunwell Exalted Caster Neck (??? neck)
4702 // cast ??? Light's Wrath if Exalted by Aldor
4703 // cast ??? Arcane Bolt if Exalted by Scryers*/
4704 case 46569:
4705 return false; // disable for while
4708 if(GetTypeId() != TYPEID_PLAYER)
4709 return false;
4711 // Get Aldor reputation rank
4712 if (((Player *)this)->GetReputationRank(932) == REP_EXALTED)
4714 target = this;
4715 triggered_spell_id = ???
4716 break;
4718 // Get Scryers reputation rank
4719 if (((Player *)this)->GetReputationRank(934) == REP_EXALTED)
4721 triggered_spell_id = ???
4722 break;
4724 return false;
4726 // Sunwell Exalted Caster Neck (Shattered Sun Pendant of Acumen neck)
4727 // cast 45479 Light's Wrath if Exalted by Aldor
4728 // cast 45429 Arcane Bolt if Exalted by Scryers
4729 case 45481:
4731 if(GetTypeId() != TYPEID_PLAYER)
4732 return false;
4734 // Get Aldor reputation rank
4735 if (((Player *)this)->GetReputationRank(932) == REP_EXALTED)
4737 target = this;
4738 triggered_spell_id = 45479;
4739 break;
4741 // Get Scryers reputation rank
4742 if (((Player *)this)->GetReputationRank(934) == REP_EXALTED)
4744 triggered_spell_id = 45429;
4745 break;
4747 return false;
4749 // Sunwell Exalted Melee Neck (Shattered Sun Pendant of Might neck)
4750 // cast 45480 Light's Strength if Exalted by Aldor
4751 // cast 45428 Arcane Strike if Exalted by Scryers
4752 case 45482:
4754 if(GetTypeId() != TYPEID_PLAYER)
4755 return false;
4757 // Get Aldor reputation rank
4758 if (((Player *)this)->GetReputationRank(932) == REP_EXALTED)
4760 target = this;
4761 triggered_spell_id = 45480;
4762 break;
4764 // Get Scryers reputation rank
4765 if (((Player *)this)->GetReputationRank(934) == REP_EXALTED)
4767 triggered_spell_id = 45428;
4768 break;
4770 return false;
4772 // Sunwell Exalted Tank Neck (Shattered Sun Pendant of Resolve neck)
4773 // cast 45431 Arcane Insight if Exalted by Aldor
4774 // cast 45432 Light's Ward if Exalted by Scryers
4775 case 45483:
4777 if(GetTypeId() != TYPEID_PLAYER)
4778 return false;
4780 // Get Aldor reputation rank
4781 if (((Player *)this)->GetReputationRank(932) == REP_EXALTED)
4783 target = this;
4784 triggered_spell_id = 45432;
4785 break;
4787 // Get Scryers reputation rank
4788 if (((Player *)this)->GetReputationRank(934) == REP_EXALTED)
4790 target = this;
4791 triggered_spell_id = 45431;
4792 break;
4794 return false;
4796 // Sunwell Exalted Healer Neck (Shattered Sun Pendant of Restoration neck)
4797 // cast 45478 Light's Salvation if Exalted by Aldor
4798 // cast 45430 Arcane Surge if Exalted by Scryers
4799 case 45484:
4801 if(GetTypeId() != TYPEID_PLAYER)
4802 return false;
4804 // Get Aldor reputation rank
4805 if (((Player *)this)->GetReputationRank(932) == REP_EXALTED)
4807 target = this;
4808 triggered_spell_id = 45478;
4809 break;
4811 // Get Scryers reputation rank
4812 if (((Player *)this)->GetReputationRank(934) == REP_EXALTED)
4814 triggered_spell_id = 45430;
4815 break;
4817 return false;
4819 // Living Seed
4820 case 48504:
4822 triggered_spell_id = 48503;
4823 basepoints0 = triggerAmount;
4824 target = this;
4825 break;
4827 // Vampiric Touch (generic, used by some boss)
4828 case 52723:
4829 case 60501:
4831 triggered_spell_id = 52724;
4832 basepoints0 = damage / 2;
4833 target = this;
4834 break;
4836 // Divine purpose
4837 case 31871:
4838 case 31872:
4840 // Roll chane
4841 if (!roll_chance_i(triggerAmount))
4842 return false;
4844 // Remove any stun effect on target
4845 AuraMap& Auras = pVictim->GetAuras();
4846 for(AuraMap::const_iterator iter = Auras.begin(); iter != Auras.end();)
4848 SpellEntry const *spell = iter->second->GetSpellProto();
4849 if( spell->Mechanic == MECHANIC_STUN ||
4850 spell->EffectMechanic[iter->second->GetEffIndex()] == MECHANIC_STUN)
4852 pVictim->RemoveAurasDueToSpell(spell->Id);
4853 iter = Auras.begin();
4855 else
4856 ++iter;
4858 return true;
4861 break;
4863 case SPELLFAMILY_MAGE:
4865 // Magic Absorption
4866 if (dummySpell->SpellIconID == 459) // only this spell have SpellIconID == 459 and dummy aura
4868 if (getPowerType() != POWER_MANA)
4869 return false;
4871 // mana reward
4872 basepoints0 = (triggerAmount * GetMaxPower(POWER_MANA) / 100);
4873 target = this;
4874 triggered_spell_id = 29442;
4875 break;
4877 // Master of Elements
4878 if (dummySpell->SpellIconID == 1920)
4880 if(!procSpell)
4881 return false;
4883 // mana cost save
4884 int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
4885 basepoints0 = cost * triggerAmount/100;
4886 if( basepoints0 <=0 )
4887 return false;
4889 target = this;
4890 triggered_spell_id = 29077;
4891 break;
4894 //Arcane Potency
4895 if (dummySpell->SpellIconID == 2120)
4897 if(!procSpell)
4898 return false;
4900 target = this;
4901 switch (dummySpell->Id)
4903 case 31571: triggered_spell_id = 57529; break;
4904 case 31572: triggered_spell_id = 57531; break;
4905 default:
4906 sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u",dummySpell->Id);
4907 return false;
4909 break;
4912 // Hot Streak
4913 if (dummySpell->SpellIconID == 2999)
4915 if (effIndex!=0)
4916 return true;
4917 Aura *counter = GetAura(triggeredByAura->GetId(), 1);
4918 if (!counter)
4919 return true;
4921 // Count spell criticals in a row in second aura
4922 Modifier *mod = counter->GetModifier();
4923 if (procEx & PROC_EX_CRITICAL_HIT)
4925 mod->m_amount *=2;
4926 if (mod->m_amount < 100) // not enough
4927 return true;
4928 // Crititcal counted -> roll chance
4929 if (roll_chance_i(triggerAmount))
4930 CastSpell(this, 48108, true, castItem, triggeredByAura);
4932 mod->m_amount = 25;
4933 return true;
4935 // Burnout
4936 if (dummySpell->SpellIconID == 2998)
4938 if(!procSpell)
4939 return false;
4941 int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
4942 basepoints0 = cost * triggerAmount/100;
4943 if( basepoints0 <=0 )
4944 return false;
4945 triggered_spell_id = 44450;
4946 target = this;
4947 break;
4949 // Incanter's Regalia set (add trigger chance to Mana Shield)
4950 if (dummySpell->SpellFamilyFlags & UI64LIT(0x0000000000008000))
4952 if(GetTypeId() != TYPEID_PLAYER)
4953 return false;
4955 target = this;
4956 triggered_spell_id = 37436;
4957 break;
4959 switch(dummySpell->Id)
4961 // Ignite
4962 case 11119:
4963 case 11120:
4964 case 12846:
4965 case 12847:
4966 case 12848:
4968 switch (dummySpell->Id)
4970 case 11119: basepoints0 = int32(0.04f*damage); break;
4971 case 11120: basepoints0 = int32(0.08f*damage); break;
4972 case 12846: basepoints0 = int32(0.12f*damage); break;
4973 case 12847: basepoints0 = int32(0.16f*damage); break;
4974 case 12848: basepoints0 = int32(0.20f*damage); break;
4975 default:
4976 sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (IG)",dummySpell->Id);
4977 return false;
4980 triggered_spell_id = 12654;
4981 break;
4983 // Combustion
4984 case 11129:
4986 //last charge and crit
4987 if (triggeredByAura->GetAuraCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT) )
4989 RemoveAurasDueToSpell(28682); //-> remove Combustion auras
4990 return true; // charge counting (will removed)
4993 CastSpell(this, 28682, true, castItem, triggeredByAura);
4994 return (procEx & PROC_EX_CRITICAL_HIT);// charge update only at crit hits, no hidden cooldowns
4997 break;
4999 case SPELLFAMILY_WARRIOR:
5001 // Retaliation
5002 if (dummySpell->SpellFamilyFlags == UI64LIT(0x0000000800000000))
5004 // check attack comes not from behind
5005 if (!HasInArc(M_PI, pVictim))
5006 return false;
5008 triggered_spell_id = 22858;
5009 break;
5011 // Second Wind
5012 if (dummySpell->SpellIconID == 1697)
5014 // only for spells and hit/crit (trigger start always) and not start from self casted spells (5530 Mace Stun Effect for example)
5015 if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
5016 return false;
5017 // Need stun or root mechanic
5018 if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_STUN))))
5019 return false;
5021 switch (dummySpell->Id)
5023 case 29838: triggered_spell_id=29842; break;
5024 case 29834: triggered_spell_id=29841; break;
5025 case 42770: triggered_spell_id=42771; break;
5026 default:
5027 sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (SW)",dummySpell->Id);
5028 return false;
5031 target = this;
5032 break;
5034 // Damage Shield
5035 if (dummySpell->SpellIconID == 3214)
5037 triggered_spell_id = 59653;
5038 basepoints0 = GetShieldBlockValue() * triggerAmount / 100;
5039 break;
5041 break;
5043 case SPELLFAMILY_WARLOCK:
5045 // Seed of Corruption
5046 if (dummySpell->SpellFamilyFlags & UI64LIT(0x0000001000000000))
5048 Modifier* mod = triggeredByAura->GetModifier();
5049 // if damage is more than need or target die from damage deal finish spell
5050 if( mod->m_amount <= damage || GetHealth() <= damage )
5052 // remember guid before aura delete
5053 uint64 casterGuid = triggeredByAura->GetCasterGUID();
5055 // Remove aura (before cast for prevent infinite loop handlers)
5056 RemoveAurasDueToSpell(triggeredByAura->GetId());
5058 // Cast finish spell (triggeredByAura already not exist!)
5059 CastSpell(this, 27285, true, castItem, NULL, casterGuid);
5060 return true; // no hidden cooldown
5063 // Damage counting
5064 mod->m_amount-=damage;
5065 return true;
5067 // Seed of Corruption (Mobs cast) - no die req
5068 if (dummySpell->SpellFamilyFlags == UI64LIT(0x0) && dummySpell->SpellIconID == 1932)
5070 Modifier* mod = triggeredByAura->GetModifier();
5071 // if damage is more than need deal finish spell
5072 if( mod->m_amount <= damage )
5074 // remember guid before aura delete
5075 uint64 casterGuid = triggeredByAura->GetCasterGUID();
5077 // Remove aura (before cast for prevent infinite loop handlers)
5078 RemoveAurasDueToSpell(triggeredByAura->GetId());
5080 // Cast finish spell (triggeredByAura already not exist!)
5081 CastSpell(this, 32865, true, castItem, NULL, casterGuid);
5082 return true; // no hidden cooldown
5084 // Damage counting
5085 mod->m_amount-=damage;
5086 return true;
5088 // Fel Synergy
5089 if (dummySpell->SpellIconID == 3222)
5091 target = GetPet();
5092 if (!target)
5093 return false;
5094 basepoints0 = damage * triggerAmount / 100;
5095 triggered_spell_id = 54181;
5096 break;
5098 switch(dummySpell->Id)
5100 // Nightfall
5101 case 18094:
5102 case 18095:
5104 target = this;
5105 triggered_spell_id = 17941;
5106 break;
5108 //Soul Leech
5109 case 30293:
5110 case 30295:
5111 case 30296:
5113 // health
5114 basepoints0 = int32(damage*triggerAmount/100);
5115 target = this;
5116 triggered_spell_id = 30294;
5117 break;
5119 // Shadowflame (Voidheart Raiment set bonus)
5120 case 37377:
5122 triggered_spell_id = 37379;
5123 break;
5125 // Pet Healing (Corruptor Raiment or Rift Stalker Armor)
5126 case 37381:
5128 target = GetPet();
5129 if(!target)
5130 return false;
5132 // heal amount
5133 basepoints0 = damage * triggerAmount/100;
5134 triggered_spell_id = 37382;
5135 break;
5137 // Shadowflame Hellfire (Voidheart Raiment set bonus)
5138 case 39437:
5140 triggered_spell_id = 37378;
5141 break;
5144 break;
5146 case SPELLFAMILY_PRIEST:
5148 // Vampiric Touch
5149 if (dummySpell->SpellFamilyFlags & UI64LIT(0x0000040000000000))
5151 if(!pVictim || !pVictim->isAlive())
5152 return false;
5154 // pVictim is caster of aura
5155 if(triggeredByAura->GetCasterGUID() != pVictim->GetGUID())
5156 return false;
5158 // Energize 0.25% of max. mana
5159 pVictim->CastSpell(pVictim,57669,true,castItem,triggeredByAura);
5160 return true; // no hidden cooldown
5162 // Divine Aegis
5163 if (dummySpell->SpellIconID == 2820)
5165 basepoints0 = damage * triggerAmount/100;
5166 triggered_spell_id = 47753;
5167 break;
5169 switch(dummySpell->Id)
5171 // Vampiric Embrace
5172 case 15286:
5174 if(!pVictim || !pVictim->isAlive())
5175 return false;
5177 // pVictim is caster of aura
5178 if(triggeredByAura->GetCasterGUID() != pVictim->GetGUID())
5179 return false;
5181 // heal amount
5182 int32 team = triggerAmount*damage/500;
5183 int32 self = triggerAmount*damage/100 - team;
5184 pVictim->CastCustomSpell(pVictim,15290,&team,&self,NULL,true,castItem,triggeredByAura);
5185 return true; // no hidden cooldown
5187 // Priest Tier 6 Trinket (Ashtongue Talisman of Acumen)
5188 case 40438:
5190 // Shadow Word: Pain
5191 if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000008000))
5192 triggered_spell_id = 40441;
5193 // Renew
5194 else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000010))
5195 triggered_spell_id = 40440;
5196 else
5197 return false;
5199 target = this;
5200 break;
5202 // Oracle Healing Bonus ("Garments of the Oracle" set)
5203 case 26169:
5205 // heal amount
5206 basepoints0 = int32(damage * 10/100);
5207 target = this;
5208 triggered_spell_id = 26170;
5209 break;
5211 // Frozen Shadoweave (Shadow's Embrace set) warning! its not only priest set
5212 case 39372:
5214 if(!procSpell || (GetSpellSchoolMask(procSpell) & (SPELL_SCHOOL_MASK_FROST | SPELL_SCHOOL_MASK_SHADOW))==0 )
5215 return false;
5217 // heal amount
5218 basepoints0 = damage * triggerAmount/100;
5219 target = this;
5220 triggered_spell_id = 39373;
5221 break;
5223 // Greater Heal (Vestments of Faith (Priest Tier 3) - 4 pieces bonus)
5224 case 28809:
5226 triggered_spell_id = 28810;
5227 break;
5229 // Glyph of Dispel Magic
5230 case 55677:
5232 if(!target->IsFriendlyTo(this))
5233 return false;
5235 basepoints0 = int32(target->GetMaxHealth() * triggerAmount / 100);
5236 triggered_spell_id = 56131;
5237 break;
5240 break;
5242 case SPELLFAMILY_DRUID:
5244 switch(dummySpell->Id)
5246 // Healing Touch (Dreamwalker Raiment set)
5247 case 28719:
5249 // mana back
5250 basepoints0 = int32(procSpell->manaCost * 30 / 100);
5251 target = this;
5252 triggered_spell_id = 28742;
5253 break;
5255 // Healing Touch Refund (Idol of Longevity trinket)
5256 case 28847:
5258 target = this;
5259 triggered_spell_id = 28848;
5260 break;
5262 // Mana Restore (Malorne Raiment set / Malorne Regalia set)
5263 case 37288:
5264 case 37295:
5266 target = this;
5267 triggered_spell_id = 37238;
5268 break;
5270 // Druid Tier 6 Trinket
5271 case 40442:
5273 float chance;
5275 // Starfire
5276 if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000004))
5278 triggered_spell_id = 40445;
5279 chance = 25.0f;
5281 // Rejuvenation
5282 else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000010))
5284 triggered_spell_id = 40446;
5285 chance = 25.0f;
5287 // Mangle (cat/bear)
5288 else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000044000000000))
5290 triggered_spell_id = 40452;
5291 chance = 40.0f;
5293 else
5294 return false;
5296 if (!roll_chance_f(chance))
5297 return false;
5299 target = this;
5300 break;
5302 // Maim Interrupt
5303 case 44835:
5305 // Deadly Interrupt Effect
5306 triggered_spell_id = 32747;
5307 break;
5310 // Eclipse
5311 if (dummySpell->SpellIconID == 2856)
5313 if (!procSpell)
5314 return false;
5315 // Only 0 aura can proc
5316 if (effIndex!=0)
5317 return true;
5318 // Wrath crit
5319 if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000001))
5321 if (!roll_chance_i(60))
5322 return false;
5323 triggered_spell_id = 48518;
5324 target = this;
5325 break;
5327 // Starfire crit
5328 if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000004))
5330 triggered_spell_id = 48517;
5331 target = this;
5332 break;
5334 return false;
5336 // Living Seed
5337 else if (dummySpell->SpellIconID == 2860)
5339 triggered_spell_id = 48504;
5340 basepoints0 = triggerAmount * damage / 100;
5341 break;
5343 break;
5345 case SPELLFAMILY_ROGUE:
5347 switch(dummySpell->Id)
5349 // Deadly Throw Interrupt
5350 case 32748:
5352 // Prevent cast Deadly Throw Interrupt on self from last effect (apply dummy) of Deadly Throw
5353 if(this == pVictim)
5354 return false;
5356 triggered_spell_id = 32747;
5357 break;
5360 // Cut to the Chase
5361 if( dummySpell->SpellIconID == 2909 )
5363 // "refresh your Slice and Dice duration to its 5 combo point maximum"
5364 // lookup Slice and Dice
5365 AuraList const& sd = GetAurasByType(SPELL_AURA_MOD_HASTE);
5366 for(AuraList::const_iterator itr = sd.begin(); itr != sd.end(); ++itr)
5368 SpellEntry const *spellProto = (*itr)->GetSpellProto();
5369 if (spellProto->SpellFamilyName == SPELLFAMILY_ROGUE &&
5370 (spellProto->SpellFamilyFlags & UI64LIT(0x0000000000040000)))
5372 (*itr)->SetAuraMaxDuration(GetSpellMaxDuration(spellProto));
5373 (*itr)->RefreshAura();
5374 return true;
5377 return false;
5379 // Deadly Brew
5380 if( dummySpell->SpellIconID == 2963 )
5382 triggered_spell_id = 25809;
5383 break;
5385 // Quick Recovery
5386 if( dummySpell->SpellIconID == 2116 )
5388 if(!procSpell)
5389 return false;
5391 // energy cost save
5392 basepoints0 = procSpell->manaCost * triggerAmount/100;
5393 if(basepoints0 <= 0)
5394 return false;
5396 target = this;
5397 triggered_spell_id = 31663;
5398 break;
5400 break;
5402 case SPELLFAMILY_HUNTER:
5404 // Aspect of the Viper
5405 if (dummySpell->SpellFamilyFlags & UI64LIT(0x4000000000000))
5407 uint32 maxmana = GetMaxPower(POWER_MANA);
5408 basepoints0 = maxmana* GetAttackTime(RANGED_ATTACK)/1000.0f/100.0f;
5410 target = this;
5411 triggered_spell_id = 34075;
5412 break;
5414 // Thrill of the Hunt
5415 if (dummySpell->SpellIconID == 2236)
5417 if(!procSpell)
5418 return false;
5420 // mana cost save
5421 int32 mana = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
5422 basepoints0 = mana * 40/100;
5423 if(basepoints0 <= 0)
5424 return false;
5426 target = this;
5427 triggered_spell_id = 34720;
5428 break;
5430 // Hunting Party
5431 if ( dummySpell->SpellIconID == 3406 )
5433 triggered_spell_id = 57669;
5434 target = this;
5435 break;
5437 // Lock and Load
5438 if ( dummySpell->SpellIconID == 3579 )
5440 // Proc only from periodic (from trap activation proc another aura of this spell)
5441 if (!(procFlag & PROC_FLAG_ON_DO_PERIODIC) || !roll_chance_i(triggerAmount))
5442 return false;
5443 triggered_spell_id = 56453;
5444 target = this;
5445 break;
5447 // Rapid Recuperation
5448 if ( dummySpell->SpellIconID == 3560 )
5450 // This effect only from Rapid Killing (mana regen)
5451 if (!(procSpell->SpellFamilyFlags & UI64LIT(0x0100000000000000)))
5452 return false;
5453 triggered_spell_id = 56654;
5454 target = this;
5455 break;
5457 break;
5459 case SPELLFAMILY_PALADIN:
5461 // Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage)
5462 if ((dummySpell->SpellFamilyFlags & UI64LIT(0x000000008000000)) && effIndex==0)
5464 triggered_spell_id = 25742;
5465 float ap = GetTotalAttackPowerValue(BASE_ATTACK);
5466 int32 holy = SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) +
5467 SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, pVictim);
5468 basepoints0 = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000;
5469 break;
5471 // Sacred Shield
5472 if (dummySpell->SpellFamilyFlags & UI64LIT(0x0008000000000000))
5474 triggered_spell_id = 58597;
5475 target = this;
5476 break;
5478 // Righteous Vengeance
5479 if (dummySpell->SpellIconID == 3025)
5481 // 4 damage tick
5482 basepoints0 = triggerAmount*damage/400;
5483 triggered_spell_id = 61840;
5484 break;
5486 // Sheath of Light
5487 if (dummySpell->SpellIconID == 3030)
5489 // 4 healing tick
5490 basepoints0 = triggerAmount*damage/400;
5491 triggered_spell_id = 54203;
5492 break;
5494 switch(dummySpell->Id)
5496 // Judgement of Light
5497 case 20185:
5499 // Get judgement caster
5500 Unit *caster = triggeredByAura->GetCaster();
5501 if (!caster)
5502 return false;
5503 float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
5504 int32 holy = caster->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) +
5505 caster->SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, this);
5506 basepoints0 = int32(ap*0.10f + 0.10f*holy);
5507 pVictim->CastCustomSpell(pVictim, 20267, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
5508 return true;
5510 // Judgement of Wisdom
5511 case 20186:
5513 if (pVictim->getPowerType() == POWER_MANA)
5515 // 2% of maximum base mana
5516 basepoints0 = int32(pVictim->GetCreateMana() * 2 / 100);
5517 pVictim->CastCustomSpell(pVictim, 20268, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
5519 return true;
5521 // Holy Power (Redemption Armor set)
5522 case 28789:
5524 if(!pVictim)
5525 return false;
5527 // Set class defined buff
5528 switch (pVictim->getClass())
5530 case CLASS_PALADIN:
5531 case CLASS_PRIEST:
5532 case CLASS_SHAMAN:
5533 case CLASS_DRUID:
5534 triggered_spell_id = 28795; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d.
5535 break;
5536 case CLASS_MAGE:
5537 case CLASS_WARLOCK:
5538 triggered_spell_id = 28793; // Increases the friendly target's spell damage and healing by up to $s1 for $d.
5539 break;
5540 case CLASS_HUNTER:
5541 case CLASS_ROGUE:
5542 triggered_spell_id = 28791; // Increases the friendly target's attack power by $s1 for $d.
5543 break;
5544 case CLASS_WARRIOR:
5545 triggered_spell_id = 28790; // Increases the friendly target's armor
5546 break;
5547 default:
5548 return false;
5550 break;
5552 case 25899: // Greater Blessing of Sanctuary
5553 case 20911: // Blessing of Sanctuary
5555 if (target->GetTypeId() != TYPEID_PLAYER)
5556 return false;
5558 target = this;
5559 switch (target->getPowerType())
5561 case POWER_MANA:
5562 triggered_spell_id = 57319;
5563 break;
5564 case POWER_RAGE:
5565 triggered_spell_id = 57320;
5566 break;
5567 case POWER_RUNIC_POWER:
5568 triggered_spell_id = 57321;
5569 break;
5570 default:
5571 return false;
5573 break;
5575 // Seal of Vengeance (damage calc on apply aura)
5576 case 31801:
5578 if(effIndex != 0) // effect 1,2 used by seal unleashing code
5579 return false;
5581 triggered_spell_id = 31803;
5582 break;
5584 // Spiritual Attunement
5585 case 31785:
5586 case 33776:
5588 // if healed by another unit (pVictim)
5589 if(this == pVictim)
5590 return false;
5592 // heal amount
5593 basepoints0 = triggerAmount*damage/100;
5594 target = this;
5595 triggered_spell_id = 31786;
5596 break;
5598 // Seal of Blood do damage trigger
5599 case 31892:
5601 if (effIndex == 0) // 0 effect - is proc on enemy
5602 triggered_spell_id = 31893;
5603 else if (effIndex == 1) // 1 effect - is proc on self
5605 // add spell damage from prev effect (27%)
5606 damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100;
5607 basepoints0 = triggerAmount * damage / 100;
5608 target = this;
5609 triggered_spell_id = 32221;
5611 else
5612 return true;
5613 break;
5615 // Seal of the Martyr do damage trigger
5616 case 53720:
5618 if (effIndex == 0) // 0 effect - is proc on enemy
5619 triggered_spell_id = 53719;
5620 else if (effIndex == 1) // 1 effect - is proc on self
5622 // add spell damage from prev effect (27%)
5623 damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100;
5624 basepoints0 = triggerAmount * damage / 100;
5625 target = this;
5626 triggered_spell_id = 53718;
5628 else
5629 return true;
5630 break;
5632 // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal)
5633 case 40470:
5635 if (!procSpell)
5636 return false;
5638 float chance;
5640 // Flash of light/Holy light
5641 if (procSpell->SpellFamilyFlags & UI64LIT(0x00000000C0000000))
5643 triggered_spell_id = 40471;
5644 chance = 15.0f;
5646 // Judgement
5647 else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000800000))
5649 triggered_spell_id = 40472;
5650 chance = 50.0f;
5652 else
5653 return false;
5655 if (!roll_chance_f(chance))
5656 return false;
5658 break;
5660 // Glyph of Divinity
5661 case 54939:
5663 // Lookup base amount mana restore
5664 for (int i=0; i<3;++i)
5665 if (procSpell->Effect[i] == SPELL_EFFECT_ENERGIZE)
5667 int32 mana = procSpell->EffectBasePoints[i];
5668 CastCustomSpell(this, 54986, NULL, &mana, NULL, true, castItem, triggeredByAura);
5669 break;
5671 return true;
5673 // Glyph of Flash of Light
5674 case 54936:
5676 triggered_spell_id = 54957;
5677 basepoints0 = triggerAmount*damage/100;
5678 break;
5680 // Glyph of Holy Light
5681 case 54937:
5683 triggered_spell_id = 54968;
5684 basepoints0 = triggerAmount*damage/100;
5685 break;
5688 break;
5690 case SPELLFAMILY_SHAMAN:
5692 switch(dummySpell->Id)
5694 // Totemic Power (The Earthshatterer set)
5695 case 28823:
5697 if( !pVictim )
5698 return false;
5700 // Set class defined buff
5701 switch (pVictim->getClass())
5703 case CLASS_PALADIN:
5704 case CLASS_PRIEST:
5705 case CLASS_SHAMAN:
5706 case CLASS_DRUID:
5707 triggered_spell_id = 28824; // Increases the friendly target's mana regeneration by $s1 per 5 sec. for $d.
5708 break;
5709 case CLASS_MAGE:
5710 case CLASS_WARLOCK:
5711 triggered_spell_id = 28825; // Increases the friendly target's spell damage and healing by up to $s1 for $d.
5712 break;
5713 case CLASS_HUNTER:
5714 case CLASS_ROGUE:
5715 triggered_spell_id = 28826; // Increases the friendly target's attack power by $s1 for $d.
5716 break;
5717 case CLASS_WARRIOR:
5718 triggered_spell_id = 28827; // Increases the friendly target's armor
5719 break;
5720 default:
5721 return false;
5723 break;
5725 // Lesser Healing Wave (Totem of Flowing Water Relic)
5726 case 28849:
5728 target = this;
5729 triggered_spell_id = 28850;
5730 break;
5732 // Windfury Weapon (Passive) 1-5 Ranks
5733 case 33757:
5735 if(GetTypeId()!=TYPEID_PLAYER)
5736 return false;
5738 if(!castItem || !castItem->IsEquipped())
5739 return false;
5741 // custom cooldown processing case
5742 if( cooldown && ((Player*)this)->HasSpellCooldown(dummySpell->Id))
5743 return false;
5745 // Now amount of extra power stored in 1 effect of Enchant spell
5746 // Get it by item enchant id
5747 uint32 spellId;
5748 switch (castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)))
5750 case 283: spellId = 8232; break; // 1 Rank
5751 case 284: spellId = 8235; break; // 2 Rank
5752 case 525: spellId = 10486; break; // 3 Rank
5753 case 1669:spellId = 16362; break; // 4 Rank
5754 case 2636:spellId = 25505; break; // 5 Rank
5755 case 3785:spellId = 58801; break; // 6 Rank
5756 case 3786:spellId = 58803; break; // 7 Rank
5757 case 3787:spellId = 58804; break; // 8 Rank
5758 default:
5760 sLog.outError("Unit::HandleDummyAuraProc: non handled item enchantment (rank?) %u for spell id: %u (Windfury)",
5761 castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT)),dummySpell->Id);
5762 return false;
5766 SpellEntry const* windfurySpellEntry = sSpellStore.LookupEntry(spellId);
5767 if(!windfurySpellEntry)
5769 sLog.outError("Unit::HandleDummyAuraProc: non existed spell id: %u (Windfury)",spellId);
5770 return false;
5773 int32 extra_attack_power = CalculateSpellDamage(windfurySpellEntry, 1, windfurySpellEntry->EffectBasePoints[1], pVictim);
5775 // Off-Hand case
5776 if ( castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND )
5778 // Value gained from additional AP
5779 basepoints0 = int32(extra_attack_power/14.0f * GetAttackTime(OFF_ATTACK)/1000/2);
5780 triggered_spell_id = 33750;
5782 // Main-Hand case
5783 else
5785 // Value gained from additional AP
5786 basepoints0 = int32(extra_attack_power/14.0f * GetAttackTime(BASE_ATTACK)/1000);
5787 triggered_spell_id = 25504;
5790 // apply cooldown before cast to prevent processing itself
5791 if( cooldown )
5792 ((Player*)this)->AddSpellCooldown(dummySpell->Id,0,time(NULL) + cooldown);
5794 // Attack Twice
5795 for ( uint32 i = 0; i<2; ++i )
5796 CastCustomSpell(pVictim,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
5798 return true;
5800 // Shaman Tier 6 Trinket
5801 case 40463:
5803 if( !procSpell )
5804 return false;
5806 float chance;
5807 if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000001))
5809 triggered_spell_id = 40465; // Lightning Bolt
5810 chance = 15.0f;
5812 else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000080))
5814 triggered_spell_id = 40465; // Lesser Healing Wave
5815 chance = 10.0f;
5817 else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000001000000000))
5819 triggered_spell_id = 40466; // Stormstrike
5820 chance = 50.0f;
5822 else
5823 return false;
5825 if (!roll_chance_f(chance))
5826 return false;
5828 target = this;
5829 break;
5831 // Glyph of Healing Wave
5832 case 55440:
5834 // Not proc from self heals
5835 if (this==pVictim)
5836 return false;
5837 basepoints0 = triggerAmount * damage / 100;
5838 target = this;
5839 triggered_spell_id = 55533;
5840 break;
5842 // Spirit Hunt
5843 case 58877:
5845 // Cast on owner
5846 target = GetOwner();
5847 if(!target)
5848 return false;
5849 basepoints0 = triggerAmount * damage / 100;
5850 triggered_spell_id = 58879;
5851 break;
5854 // Storm, Earth and Fire
5855 if (dummySpell->SpellIconID == 3063)
5857 // Earthbind Totem summon only
5858 if(procSpell->Id != 2484)
5859 return false;
5861 float chance = triggerAmount;
5862 if (!roll_chance_f(chance))
5863 return false;
5865 triggered_spell_id = 64695;
5866 break;
5868 // Ancestral Awakening
5869 if (dummySpell->SpellIconID == 3065)
5871 triggered_spell_id = 52759;
5872 basepoints0 = triggerAmount * damage / 100;
5873 target = this;
5874 break;
5876 // Earth Shield
5877 if (dummySpell->SpellFamilyFlags & UI64LIT(0x0000040000000000))
5879 basepoints0 = triggerAmount;
5880 target = this;
5881 triggered_spell_id = 379;
5882 break;
5884 // Improved Water Shield
5885 if (dummySpell->SpellIconID == 2287)
5887 // Lesser Healing Wave need aditional 60% roll
5888 if ((procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000080)) && !roll_chance_i(60))
5889 return false;
5890 // lookup water shield
5891 AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
5892 for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr)
5894 if ((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN &&
5895 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000002000000000)))
5897 uint32 spell = (*itr)->GetSpellProto()->EffectTriggerSpell[(*itr)->GetEffIndex()];
5898 CastSpell(this, spell, true, castItem, triggeredByAura);
5899 if ((*itr)->DropAuraCharge())
5900 RemoveAurasDueToSpell((*itr)->GetId());
5901 return true;
5904 return false;
5905 break;
5907 // Lightning Overload
5908 if (dummySpell->SpellIconID == 2018) // only this spell have SpellFamily Shaman SpellIconID == 2018 and dummy aura
5910 if(!procSpell || GetTypeId() != TYPEID_PLAYER || !pVictim )
5911 return false;
5913 // custom cooldown processing case
5914 if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(dummySpell->Id))
5915 return false;
5917 uint32 spellId = 0;
5918 // Every Lightning Bolt and Chain Lightning spell have duplicate vs half damage and zero cost
5919 switch (procSpell->Id)
5921 // Lightning Bolt
5922 case 403: spellId = 45284; break; // Rank 1
5923 case 529: spellId = 45286; break; // Rank 2
5924 case 548: spellId = 45287; break; // Rank 3
5925 case 915: spellId = 45288; break; // Rank 4
5926 case 943: spellId = 45289; break; // Rank 5
5927 case 6041: spellId = 45290; break; // Rank 6
5928 case 10391: spellId = 45291; break; // Rank 7
5929 case 10392: spellId = 45292; break; // Rank 8
5930 case 15207: spellId = 45293; break; // Rank 9
5931 case 15208: spellId = 45294; break; // Rank 10
5932 case 25448: spellId = 45295; break; // Rank 11
5933 case 25449: spellId = 45296; break; // Rank 12
5934 case 49237: spellId = 49239; break; // Rank 13
5935 case 49238: spellId = 49240; break; // Rank 14
5936 // Chain Lightning
5937 case 421: spellId = 45297; break; // Rank 1
5938 case 930: spellId = 45298; break; // Rank 2
5939 case 2860: spellId = 45299; break; // Rank 3
5940 case 10605: spellId = 45300; break; // Rank 4
5941 case 25439: spellId = 45301; break; // Rank 5
5942 case 25442: spellId = 45302; break; // Rank 6
5943 case 49268: spellId = 49270; break; // Rank 7
5944 case 49269: spellId = 49271; break; // Rank 8
5945 default:
5946 sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id);
5947 return false;
5949 // No thread generated mod
5950 // TODO: exist special flag in spell attributes for this, need found and use!
5951 SpellModifier *mod = new SpellModifier;
5952 mod->op = SPELLMOD_THREAT;
5953 mod->value = -100;
5954 mod->type = SPELLMOD_PCT;
5955 mod->spellId = dummySpell->Id;
5956 mod->mask = UI64LIT(0x0000000000000003);
5957 mod->mask2= UI64LIT(0x0);
5958 ((Player*)this)->AddSpellMod(mod, true);
5960 // Remove cooldown (Chain Lightning - have Category Recovery time)
5961 if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000002))
5962 ((Player*)this)->RemoveSpellCooldown(spellId);
5964 CastSpell(pVictim, spellId, true, castItem, triggeredByAura);
5966 ((Player*)this)->AddSpellMod(mod, false);
5968 if( cooldown && GetTypeId()==TYPEID_PLAYER )
5969 ((Player*)this)->AddSpellCooldown(dummySpell->Id,0,time(NULL) + cooldown);
5971 return true;
5973 // Static Shock
5974 if(dummySpell->SpellIconID == 3059)
5976 // lookup Lightning Shield
5977 AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL);
5978 for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr)
5980 if ((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN &&
5981 ((*itr)->GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000000400)))
5983 uint32 spell = 0;
5984 switch ((*itr)->GetId())
5986 case 324: spell = 26364; break;
5987 case 325: spell = 26365; break;
5988 case 905: spell = 26366; break;
5989 case 945: spell = 26367; break;
5990 case 8134: spell = 26369; break;
5991 case 10431: spell = 26370; break;
5992 case 10432: spell = 26363; break;
5993 case 25469: spell = 26371; break;
5994 case 25472: spell = 26372; break;
5995 case 49280: spell = 49278; break;
5996 case 49281: spell = 49279; break;
5997 default:
5998 return false;
6000 CastSpell(target, spell, true, castItem, triggeredByAura);
6001 if ((*itr)->DropAuraCharge())
6002 RemoveAurasDueToSpell((*itr)->GetId());
6003 return true;
6006 return false;
6007 break;
6009 break;
6011 case SPELLFAMILY_DEATHKNIGHT:
6013 // Blood Aura
6014 if (dummySpell->SpellIconID == 2636)
6016 if (GetTypeId() != TYPEID_PLAYER || !((Player*)this)->isHonorOrXPTarget(pVictim))
6017 return false;
6018 basepoints0 = triggerAmount * damage / 100;
6019 triggered_spell_id = 53168;
6020 break;
6022 // Butchery
6023 if (dummySpell->SpellIconID == 2664)
6025 basepoints0 = triggerAmount;
6026 triggered_spell_id = 50163;
6027 target = this;
6028 break;
6030 // Dancing Rune Weapon
6031 if (dummySpell->Id == 49028)
6033 // 1 dummy aura for dismiss rune blade
6034 if (effIndex!=2)
6035 return false;
6036 // TODO: wite script for this "fights on its own, doing the same attacks"
6037 // NOTE: Trigger here on every attack and spell cast
6038 return false;
6040 // Mark of Blood
6041 if (dummySpell->Id == 49005)
6043 // TODO: need more info (cooldowns/PPM)
6044 triggered_spell_id = 61607;
6045 break;
6047 // Vendetta
6048 if (dummySpell->SpellFamilyFlags & UI64LIT(0x0000000000010000))
6050 basepoints0 = triggerAmount * GetMaxHealth() / 100;
6051 triggered_spell_id = 50181;
6052 target = this;
6053 break;
6055 // Necrosis
6056 if (dummySpell->SpellIconID == 2709)
6058 basepoints0 = triggerAmount * damage / 100;
6059 triggered_spell_id = 51460;
6060 break;
6062 // Runic Power Back on Snare/Root
6063 if (dummySpell->Id == 61257)
6065 // only for spells and hit/crit (trigger start always) and not start from self casted spells
6066 if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
6067 return false;
6068 // Need snare or root mechanic
6069 if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_SNARE))))
6070 return false;
6071 triggered_spell_id = 61258;
6072 target = this;
6073 break;
6075 // Wandering Plague
6076 if (dummySpell->SpellIconID == 1614)
6078 if (!roll_chance_f(GetUnitCriticalChance(BASE_ATTACK, pVictim)))
6079 return false;
6080 basepoints0 = triggerAmount * damage / 100;
6081 triggered_spell_id = 50526;
6082 break;
6084 break;
6086 default:
6087 break;
6090 // processed charge only counting case
6091 if(!triggered_spell_id)
6092 return true;
6094 SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id);
6096 if(!triggerEntry)
6098 sLog.outError("Unit::HandleDummyAuraProc: Spell %u have not existed triggered spell %u",dummySpell->Id,triggered_spell_id);
6099 return false;
6102 // default case
6103 if(!target || target!=this && !target->isAlive())
6104 return false;
6106 if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id))
6107 return false;
6109 if(basepoints0)
6110 CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
6111 else
6112 CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura);
6114 if( cooldown && GetTypeId()==TYPEID_PLAYER )
6115 ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown);
6117 return true;
6120 bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown)
6122 // Get triggered aura spell info
6123 SpellEntry const* auraSpellInfo = triggeredByAura->GetSpellProto();
6125 // Basepoints of trigger aura
6126 int32 triggerAmount = triggeredByAura->GetModifier()->m_amount;
6128 // Set trigger spell id, target, custom basepoints
6129 uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()];
6130 Unit* target = NULL;
6131 int32 basepoints0 = 0;
6133 if(triggeredByAura->GetModifier()->m_auraname == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE)
6134 basepoints0 = triggerAmount;
6136 Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
6137 ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
6139 // Try handle uncnown trigger spells
6140 if (sSpellStore.LookupEntry(trigger_spell_id)==NULL)
6142 switch (auraSpellInfo->SpellFamilyName)
6144 case SPELLFAMILY_GENERIC:
6145 //if (auraSpellInfo->Id==59532) // Abandon Passengers on Poly
6146 //if (auraSpellInfo->Id==54775) // Abandon Vehicle on Poly
6147 //if (auraSpellInfo->Id==34082) // Advantaged State (DND)
6148 if (auraSpellInfo->Id == 23780) // Aegis of Preservation (Aegis of Preservation trinket)
6149 trigger_spell_id = 23781;
6150 //else if (auraSpellInfo->Id==43504) // Alterac Valley OnKill Proc Aura
6151 //else if (auraSpellInfo->Id == 48876) // Beast's Mark
6153 // trigger_spell_id = 48877;
6155 //else if (auraSpellInfo->Id == 59237) // Beast's Mark
6157 // trigger_spell_id = 59233;
6159 //else if (auraSpellInfo->Id==46939) // Black Bow of the Betrayer
6161 // trigger_spell_id = 29471; // gain mana
6162 // 27526; // drain mana if possible
6164 //else if (auraSpellInfo->Id==50844) // Blood Mirror
6165 //else if (auraSpellInfo->Id==54476) // Blood Presence
6166 //else if (auraSpellInfo->Id==50689) // Blood Presence (Rank 1)
6167 //else if (auraSpellInfo->Id==37030) // Chaotic Temperament
6168 //else if (auraSpellInfo->Id==52856) // Charge
6169 else if (auraSpellInfo->Id==43820) // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket)
6171 // Pct value stored in dummy
6172 basepoints0 = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100;
6173 target = pVictim;
6174 break;
6176 //else if (auraSpellInfo->Id==41248) // Consuming Strikes
6177 // trigger_spell_id = 41249;
6178 //else if (auraSpellInfo->Id==45205) // Copy Offhand Weapon
6179 //else if (auraSpellInfo->Id==57594) // Copy Ranged Weapon
6180 //else if (auraSpellInfo->Id==41054) // Copy Weapon
6181 // trigger_spell_id = 41055;
6182 //else if (auraSpellInfo->Id==45343) // Dark Flame Aura
6183 //else if (auraSpellInfo->Id==47300) // Dark Flame Aura
6184 else if (auraSpellInfo->Id==57345) // Darkmoon Card: Greatness
6186 float stat = 0.0f;
6187 // strength
6188 if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 60229;stat = GetStat(STAT_STRENGTH); }
6189 // agility
6190 if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 60233;stat = GetStat(STAT_AGILITY); }
6191 // intellect
6192 if (GetStat(STAT_INTELLECT)> stat) { trigger_spell_id = 60234;stat = GetStat(STAT_INTELLECT);}
6193 // spirit
6194 if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235;stat = GetStat(STAT_SPIRIT); }
6196 //else if (auraSpellInfo->Id==31255) // Deadly Swiftness (Rank 1)
6197 //else if (auraSpellInfo->Id==5301) // Defensive State (DND)
6198 //else if (auraSpellInfo->Id==13358) // Defensive State (DND)
6199 //else if (auraSpellInfo->Id==16092) // Defensive State (DND)
6200 //else if (auraSpellInfo->Id==24949) // Defensive State 2 (DND)
6201 //else if (auraSpellInfo->Id==40329) // Demo Shout Sensor
6202 else if (auraSpellInfo->Id == 33896) // Desperate Defense (Stonescythe Whelp, Stonescythe Alpha, Stonescythe Ambusher)
6203 trigger_spell_id = 33898;
6204 //else if (auraSpellInfo->Id==18943) // Double Attack
6205 //else if (auraSpellInfo->Id==19194) // Double Attack
6206 //else if (auraSpellInfo->Id==19817) // Double Attack
6207 //else if (auraSpellInfo->Id==19818) // Double Attack
6208 //else if (auraSpellInfo->Id==22835) // Drunken Rage
6209 // trigger_spell_id = 14822;
6211 else if (auraSpellInfo->SpellIconID==191) // Elemental Response
6213 switch (auraSpellInfo->Id && auraSpellInfo->AttributesEx==0)
6215 case 34191:
6216 case 34329:
6217 case 34524:
6218 case 34582:
6219 case 36733:
6220 break;
6221 default:
6222 sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Elemental Response",auraSpellInfo->Id);
6223 return false;
6225 //This generic aura self-triggers a different spell for each school of magic that lands on the wearer:
6226 switch (procSpell->School)
6228 case SPELL_SCHOOL_FIRE: trigger_spell_id = 34192; break;
6229 case SPELL_SCHOOL_FROST: trigger_spell_id = 34193; break;
6230 case SPELL_SCHOOL_ARCANE:trigger_spell_id = 34194; break;
6231 case SPELL_SCHOOL_NATURE:trigger_spell_id = 34195; break;
6232 case SPELL_SCHOOL_SHADOW:trigger_spell_id = 34196; break;
6233 case SPELL_SCHOOL_HOLY: trigger_spell_id = 34197; break;
6234 case SPELL_SCHOOL_NORMAL:trigger_spell_id = 34198; break;
6235 default:
6236 sLog.outError("Unit::HandleProcTriggerSpell: Spell %u Elemental Response wrong school",auraSpellInfo->Id);
6237 return false;
6241 //else if (auraSpellInfo->Id==40364) // Entangling Roots Sensor
6242 //else if (auraSpellInfo->Id==33207) // Gossip NPC Periodic - Fidget
6243 //else if (auraSpellInfo->Id==50051) // Ethereal Pet Aura
6244 //else if (auraSpellInfo->Id==35321) // Gushing Wound
6245 //else if (auraSpellInfo->Id==38363) // Gushing Wound
6246 //else if (auraSpellInfo->Id==39215) // Gushing Wound
6247 //else if (auraSpellInfo->Id==44527) // Hate Monster (Spar Buddy) (30 sec)
6248 //else if (auraSpellInfo->Id==44819) // Hate Monster (Spar Buddy) (>30% Health)
6249 //else if (auraSpellInfo->Id==44526) // Hate Monster (Spar) (30 sec)
6250 //else if (auraSpellInfo->Id==44820) // Hate Monster (Spar) (<30%)
6251 //else if (auraSpellInfo->Id==49059) // Horde, Hate Monster (Spar Buddy) (>30% Health)
6252 //else if (auraSpellInfo->Id==40250) // Improved Duration
6253 //else if (auraSpellInfo->Id==59288) // Infra-Green Shield
6254 //else if (auraSpellInfo->Id==54072) // Knockback Ball Passive
6255 else if (auraSpellInfo->Id==27522 || auraSpellInfo->Id==40336)
6256 // Mana Drain Trigger
6258 // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target.
6259 if (this && this->isAlive())
6260 CastSpell(this, 29471, true, castItem, triggeredByAura);
6261 if (pVictim && pVictim->isAlive())
6262 CastSpell(pVictim, 27526, true, castItem, triggeredByAura);
6263 return true;
6265 //else if (auraSpellInfo->Id==55580) // Mana Link
6266 //else if (auraSpellInfo->Id==45903) // Offensive State
6267 //else if (auraSpellInfo->Id==44326) // Pure Energy Passive
6268 //else if (auraSpellInfo->Id==43453) // Rune Ward
6269 //else if (auraSpellInfo->Id== 7137) // Shadow Charge (Rank 1)
6270 //else if (auraSpellInfo->Id==36576) // Shaleskin (Shaleskin Flayer, Shaleskin Ripper) 30023 trigger
6271 //else if (auraSpellInfo->Id==34783) // Spell Reflection
6272 //else if (auraSpellInfo->Id==36096) // Spell Reflection
6273 //else if (auraSpellInfo->Id==57587) // Steal Ranged ()
6274 //else if (auraSpellInfo->Id==36207) // Steal Weapon
6275 //else if (auraSpellInfo->Id== 7377) // Take Immune Periodic Damage <Not Working>
6276 //else if (auraSpellInfo->Id==35205) // Vanish
6277 //else if (auraSpellInfo->Id==42730) // Woe Strike
6278 //else if (auraSpellInfo->Id==59735) // Woe Strike
6279 //else if (auraSpellInfo->Id==46146) // [PH] Ahune Spanky Hands
6280 break;
6281 case SPELLFAMILY_MAGE:
6282 if (auraSpellInfo->SpellIconID == 2127) // Blazing Speed
6284 switch (auraSpellInfo->Id)
6286 case 31641: // Rank 1
6287 case 31642: // Rank 2
6288 trigger_spell_id = 31643;
6289 break;
6290 default:
6291 sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed",auraSpellInfo->Id);
6292 return false;
6295 break;
6296 case SPELLFAMILY_WARRIOR:
6297 if (auraSpellInfo->Id == 50421) // Scent of Blood
6298 trigger_spell_id = 50422;
6299 break;
6300 case SPELLFAMILY_WARLOCK:
6302 // Pyroclasm
6303 if (auraSpellInfo->SpellIconID == 1137)
6305 if(!pVictim || !pVictim->isAlive() || pVictim == this || procSpell == NULL)
6306 return false;
6307 // Calculate spell tick count for spells
6308 uint32 tick = 1; // Default tick = 1
6310 // Hellfire have 15 tick
6311 if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000040))
6312 tick = 15;
6313 // Rain of Fire have 4 tick
6314 else if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000020))
6315 tick = 4;
6316 else
6317 return false;
6319 // Calculate chance = baseChance / tick
6320 float chance = 0;
6321 switch (auraSpellInfo->Id)
6323 case 18096: chance = 13.0f / tick; break;
6324 case 18073: chance = 26.0f / tick; break;
6326 // Roll chance
6327 if (!roll_chance_f(chance))
6328 return false;
6330 trigger_spell_id = 18093;
6332 // Drain Soul
6333 else if (auraSpellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000))
6335 Unit::AuraList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER);
6336 for(Unit::AuraList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i)
6338 if ((*i)->GetModifier()->m_miscvalue == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113)
6340 int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this);
6341 // Drain Soul
6342 CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura);
6343 break;
6346 // Not remove charge (aura removed on death in any cases)
6347 // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura
6348 return false;
6350 // Nether Protection
6351 else if (auraSpellInfo->SpellIconID == 1985)
6353 if (!procSpell)
6354 return false;
6355 switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell)))
6357 case SPELL_SCHOOL_NORMAL:
6358 return false; // ignore
6359 case SPELL_SCHOOL_HOLY: trigger_spell_id = 54370; break;
6360 case SPELL_SCHOOL_FIRE: trigger_spell_id = 54371; break;
6361 case SPELL_SCHOOL_NATURE: trigger_spell_id = 54375; break;
6362 case SPELL_SCHOOL_FROST: trigger_spell_id = 54372; break;
6363 case SPELL_SCHOOL_SHADOW: trigger_spell_id = 54374; break;
6364 case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break;
6365 default:
6366 return false;
6369 break;
6371 case SPELLFAMILY_PRIEST:
6373 // Greater Heal Refund
6374 if (auraSpellInfo->Id==37594)
6375 trigger_spell_id = 37595;
6376 // Blessed Recovery
6377 else if (auraSpellInfo->SpellIconID == 1875)
6379 switch (auraSpellInfo->Id)
6381 case 27811: trigger_spell_id = 27813; break;
6382 case 27815: trigger_spell_id = 27817; break;
6383 case 27816: trigger_spell_id = 27818; break;
6384 default:
6385 sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id);
6386 return false;
6388 basepoints0 = damage * triggerAmount / 100 / 3;
6389 target = this;
6391 break;
6393 case SPELLFAMILY_DRUID:
6395 // Druid Forms Trinket
6396 if (auraSpellInfo->Id==37336)
6398 switch(m_form)
6400 case FORM_NONE: trigger_spell_id = 37344;break;
6401 case FORM_CAT: trigger_spell_id = 37341;break;
6402 case FORM_BEAR:
6403 case FORM_DIREBEAR: trigger_spell_id = 37340;break;
6404 case FORM_TREE: trigger_spell_id = 37342;break;
6405 case FORM_MOONKIN: trigger_spell_id = 37343;break;
6406 default:
6407 return false;
6410 //else if (auraSpellInfo->Id==40363)// Entangling Roots ()
6411 // trigger_spell_id = ????;
6412 // Leader of the Pack
6413 else if (auraSpellInfo->Id == 24932)
6415 if (triggerAmount == 0)
6416 return false;
6417 basepoints0 = triggerAmount * GetMaxHealth() / 100;
6418 trigger_spell_id = 34299;
6420 break;
6422 case SPELLFAMILY_HUNTER:
6423 break;
6424 case SPELLFAMILY_PALADIN:
6427 // Blessed Life
6428 if (auraSpellInfo->SpellIconID == 2137)
6430 switch (auraSpellInfo->Id)
6432 case 31828: // Rank 1
6433 case 31829: // Rank 2
6434 case 31830: // Rank 3
6435 break;
6436 default:
6437 sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blessed Life", auraSpellInfo->Id);
6438 return false;
6442 // Healing Discount
6443 if (auraSpellInfo->Id==37705)
6445 trigger_spell_id = 37706;
6446 target = this;
6448 // Soul Preserver
6449 if (auraSpellInfo->Id==60510)
6451 trigger_spell_id = 60515;
6452 target = this;
6454 // Illumination
6455 else if (auraSpellInfo->SpellIconID==241)
6457 if(!procSpell)
6458 return false;
6459 // procspell is triggered spell but we need mana cost of original casted spell
6460 uint32 originalSpellId = procSpell->Id;
6461 // Holy Shock heal
6462 if (procSpell->SpellFamilyFlags & UI64LIT(0x0001000000000000))
6464 switch(procSpell->Id)
6466 case 25914: originalSpellId = 20473; break;
6467 case 25913: originalSpellId = 20929; break;
6468 case 25903: originalSpellId = 20930; break;
6469 case 27175: originalSpellId = 27174; break;
6470 case 33074: originalSpellId = 33072; break;
6471 case 48820: originalSpellId = 48824; break;
6472 case 48821: originalSpellId = 48825; break;
6473 default:
6474 sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in HShock",procSpell->Id);
6475 return false;
6478 SpellEntry const *originalSpell = sSpellStore.LookupEntry(originalSpellId);
6479 if(!originalSpell)
6481 sLog.outError("Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu",originalSpellId);
6482 return false;
6484 // percent stored in effect 1 (class scripts) base points
6485 int32 cost = originalSpell->manaCost + originalSpell->ManaCostPercentage * GetCreateMana() / 100;
6486 basepoints0 = cost*auraSpellInfo->CalculateSimpleValue(1)/100;
6487 trigger_spell_id = 20272;
6488 target = this;
6490 // Lightning Capacitor
6491 else if (auraSpellInfo->Id==37657)
6493 if(!pVictim || !pVictim->isAlive())
6494 return false;
6495 // stacking
6496 CastSpell(this, 37658, true, NULL, triggeredByAura);
6498 Aura * dummy = GetDummyAura(37658);
6499 // release at 3 aura in stack (cont contain in basepoint of trigger aura)
6500 if(!dummy || dummy->GetStackAmount() < triggerAmount)
6501 return false;
6503 RemoveAurasDueToSpell(37658);
6504 trigger_spell_id = 37661;
6505 target = pVictim;
6507 // Thunder Capacitor
6508 else if (auraSpellInfo->Id == 54841)
6510 if(!pVictim || !pVictim->isAlive())
6511 return false;
6512 // stacking
6513 CastSpell(this, 54842, true, NULL, triggeredByAura);
6515 // counting
6516 Aura * dummy = GetDummyAura(54842);
6517 // release at 3 aura in stack (cont contain in basepoint of trigger aura)
6518 if(!dummy || dummy->GetStackAmount() < triggerAmount)
6519 return false;
6521 RemoveAurasDueToSpell(54842);
6522 trigger_spell_id = 54843;
6523 target = pVictim;
6525 break;
6527 case SPELLFAMILY_SHAMAN:
6529 // Lightning Shield (overwrite non existing triggered spell call in spell.dbc
6530 if (auraSpellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000400))
6532 switch(auraSpellInfo->Id)
6534 case 324: // Rank 1
6535 trigger_spell_id = 26364; break;
6536 case 325: // Rank 2
6537 trigger_spell_id = 26365; break;
6538 case 905: // Rank 3
6539 trigger_spell_id = 26366; break;
6540 case 945: // Rank 4
6541 trigger_spell_id = 26367; break;
6542 case 8134: // Rank 5
6543 trigger_spell_id = 26369; break;
6544 case 10431: // Rank 6
6545 trigger_spell_id = 26370; break;
6546 case 10432: // Rank 7
6547 trigger_spell_id = 26363; break;
6548 case 25469: // Rank 8
6549 trigger_spell_id = 26371; break;
6550 case 25472: // Rank 9
6551 trigger_spell_id = 26372; break;
6552 case 49280: // Rank 10
6553 trigger_spell_id = 49278; break;
6554 case 49281: // Rank 11
6555 trigger_spell_id = 49279; break;
6556 default:
6557 sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield", auraSpellInfo->Id);
6558 return false;
6561 // Lightning Shield (The Ten Storms set)
6562 else if (auraSpellInfo->Id == 23551)
6564 trigger_spell_id = 23552;
6565 target = pVictim;
6567 // Damage from Lightning Shield (The Ten Storms set)
6568 else if (auraSpellInfo->Id == 23552)
6569 trigger_spell_id = 27635;
6570 // Mana Surge (The Earthfury set)
6571 else if (auraSpellInfo->Id == 23572)
6573 if(!procSpell)
6574 return false;
6575 basepoints0 = procSpell->manaCost * 35 / 100;
6576 trigger_spell_id = 23571;
6577 target = this;
6579 // Nature's Guardian
6580 else if (auraSpellInfo->SpellIconID == 2013)
6582 // Check health condition - should drop to less 30% (damage deal after this!)
6583 if (!(10*(int32(GetHealth() - damage)) < 3 * GetMaxHealth()))
6584 return false;
6586 if(pVictim && pVictim->isAlive())
6587 pVictim->getThreatManager().modifyThreatPercent(this,-10);
6589 basepoints0 = triggerAmount * GetMaxHealth() / 100;
6590 trigger_spell_id = 31616;
6591 target = this;
6593 break;
6595 case SPELLFAMILY_DEATHKNIGHT:
6597 // Acclimation
6598 if (auraSpellInfo->SpellIconID == 1930)
6600 if (!procSpell)
6601 return false;
6602 switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell)))
6604 case SPELL_SCHOOL_NORMAL:
6605 return false; // ignore
6606 case SPELL_SCHOOL_HOLY: trigger_spell_id = 50490; break;
6607 case SPELL_SCHOOL_FIRE: trigger_spell_id = 50362; break;
6608 case SPELL_SCHOOL_NATURE: trigger_spell_id = 50488; break;
6609 case SPELL_SCHOOL_FROST: trigger_spell_id = 50485; break;
6610 case SPELL_SCHOOL_SHADOW: trigger_spell_id = 50489; break;
6611 case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break;
6612 default:
6613 return false;
6616 // Blood Presence
6617 else if (auraSpellInfo->Id == 48266)
6619 if (GetTypeId() != TYPEID_PLAYER)
6620 return false;
6621 if (!((Player*)this)->isHonorOrXPTarget(pVictim))
6622 return false;
6623 trigger_spell_id = 50475;
6624 basepoints0 = damage * triggerAmount / 100;
6626 break;
6628 default:
6629 break;
6633 // All ok. Check current trigger spell
6634 SpellEntry const* triggerEntry = sSpellStore.LookupEntry(trigger_spell_id);
6635 if ( triggerEntry == NULL )
6637 // Not cast unknown spell
6638 // sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",auraSpellInfo->Id,triggeredByAura->GetEffIndex());
6639 return false;
6642 // not allow proc extra attack spell at extra attack
6643 if( m_extraAttacks && IsSpellHaveEffect(triggerEntry, SPELL_EFFECT_ADD_EXTRA_ATTACKS) )
6644 return false;
6646 // Custom requirements (not listed in procEx) Warning! damage dealing after this
6647 // Custom triggered spells
6648 switch (auraSpellInfo->Id)
6650 // Persistent Shield (Scarab Brooch trinket)
6651 // This spell originally trigger 13567 - Dummy Trigger (vs dummy efect)
6652 case 26467:
6654 basepoints0 = damage * 15 / 100;
6655 target = pVictim;
6656 trigger_spell_id = 26470;
6657 break;
6659 // Cheat Death
6660 case 28845:
6662 // When your health drops below 20% ....
6663 if (GetHealth() - damage > GetMaxHealth() / 5 || GetHealth() < GetMaxHealth() / 5)
6664 return false;
6665 break;
6667 // Deadly Swiftness (Rank 1)
6668 case 31255:
6670 // whenever you deal damage to a target who is below 20% health.
6671 if (pVictim->GetHealth() > pVictim->GetMaxHealth() / 5)
6672 return false;
6674 target = this;
6675 trigger_spell_id = 22588;
6677 // Greater Heal Refund (Avatar Raiment set)
6678 case 37594:
6680 // Not give if target already have full health
6681 if (pVictim->GetHealth() == pVictim->GetMaxHealth())
6682 return false;
6683 // If your Greater Heal brings the target to full health, you gain $37595s1 mana.
6684 if (pVictim->GetHealth() + damage < pVictim->GetMaxHealth())
6685 return false;
6686 break;
6688 // Bonus Healing (Crystal Spire of Karabor mace)
6689 case 40971:
6691 // If your target is below $s1% health
6692 if (pVictim->GetHealth() > pVictim->GetMaxHealth() * triggerAmount / 100)
6693 return false;
6694 break;
6696 // Evasive Maneuvers (Commendation of Kael`thas trinket)
6697 case 45057:
6699 // reduce you below $s1% health
6700 if (GetHealth() - damage > GetMaxHealth() * triggerAmount / 100)
6701 return false;
6702 break;
6704 // Rapid Recuperation
6705 case 53228:
6706 case 53232:
6708 // This effect only from Rapid Fire (ability cast)
6709 if (!(procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000020)))
6710 return false;
6711 break;
6715 // Custom basepoints/target for exist spell
6716 // dummy basepoints or other customs
6717 switch(trigger_spell_id)
6719 // Cast positive spell on enemy target
6720 case 7099: // Curse of Mending
6721 case 39647: // Curse of Mending
6722 case 29494: // Temptation
6723 case 20233: // Improved Lay on Hands (cast on target)
6725 target = pVictim;
6726 break;
6728 // Combo points add triggers (need add combopoint only for main target, and after possible combopoints reset)
6729 case 15250: // Rogue Setup
6731 if(!pVictim || pVictim != getVictim()) // applied only for main target
6732 return false;
6733 break; // continue normal case
6735 // Finish movies that add combo
6736 case 14189: // Seal Fate (Netherblade set)
6737 case 14157: // Ruthlessness
6739 // Need add combopoint AFTER finish movie (or they dropped in finish phase)
6740 break;
6742 // Bloodthirst (($m/100)% of max health)
6743 case 23880:
6745 basepoints0 = int32(GetMaxHealth() * triggerAmount / 100);
6746 break;
6748 // Shamanistic Rage triggered spell
6749 case 30824:
6751 basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100);
6752 break;
6754 // Enlightenment (trigger only from mana cost spells)
6755 case 35095:
6757 if(!procSpell || procSpell->powerType!=POWER_MANA || procSpell->manaCost==0 && procSpell->ManaCostPercentage==0 && procSpell->manaCostPerlevel==0)
6758 return false;
6759 break;
6761 // Brain Freeze
6762 case 57761:
6764 if(!procSpell)
6765 return false;
6766 // For trigger from Blizzard need exist Improved Blizzard
6767 if (procSpell->SpellFamilyName==SPELLFAMILY_MAGE && (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000080)))
6769 bool found = false;
6770 AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
6771 for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
6773 int32 script = (*i)->GetModifier()->m_miscvalue;
6774 if(script==836 || script==988 || script==989)
6776 found=true;
6777 break;
6780 if(!found)
6781 return false;
6783 break;
6785 // Astral Shift
6786 case 52179:
6788 if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim)
6789 return false;
6791 // Need stun, fear or silence mechanic
6792 if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_SILENCE)|(1<<MECHANIC_STUN)|(1<<MECHANIC_FEAR))))
6793 return false;
6794 break;
6796 // Burning Determination
6797 case 54748:
6799 if(!procSpell)
6800 return false;
6801 // Need Interrupt or Silenced mechanic
6802 if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_INTERRUPT)|(1<<MECHANIC_SILENCE))))
6803 return false;
6804 break;
6806 // Lock and Load
6807 case 56453:
6809 // Proc only from trap activation (from periodic proc another aura of this spell)
6810 if (!(procFlags & PROC_FLAG_ON_TRAP_ACTIVATION) || !roll_chance_i(triggerAmount))
6811 return false;
6812 break;
6816 if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(trigger_spell_id))
6817 return false;
6819 // try detect target manually if not set
6820 if ( target == NULL )
6821 target = !(procFlags & PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL) && IsPositiveSpell(trigger_spell_id) ? this : pVictim;
6823 // default case
6824 if(!target || target!=this && !target->isAlive())
6825 return false;
6827 if(basepoints0)
6828 CastCustomSpell(target,trigger_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura);
6829 else
6830 CastSpell(target,trigger_spell_id,true,castItem,triggeredByAura);
6832 if( cooldown && GetTypeId()==TYPEID_PLAYER )
6833 ((Player*)this)->AddSpellCooldown(trigger_spell_id,0,time(NULL) + cooldown);
6835 return true;
6838 bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown)
6840 int32 scriptId = triggeredByAura->GetModifier()->m_miscvalue;
6842 if(!pVictim || !pVictim->isAlive())
6843 return false;
6845 Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
6846 ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
6848 uint32 triggered_spell_id = 0;
6850 switch(scriptId)
6852 case 836: // Improved Blizzard (Rank 1)
6854 if (!procSpell || procSpell->SpellVisual[0]!=9487)
6855 return false;
6856 triggered_spell_id = 12484;
6857 break;
6859 case 988: // Improved Blizzard (Rank 2)
6861 if (!procSpell || procSpell->SpellVisual[0]!=9487)
6862 return false;
6863 triggered_spell_id = 12485;
6864 break;
6866 case 989: // Improved Blizzard (Rank 3)
6868 if (!procSpell || procSpell->SpellVisual[0]!=9487)
6869 return false;
6870 triggered_spell_id = 12486;
6871 break;
6873 case 4086: // Improved Mend Pet (Rank 1)
6874 case 4087: // Improved Mend Pet (Rank 2)
6876 int32 chance = triggeredByAura->GetSpellProto()->EffectBasePoints[triggeredByAura->GetEffIndex()];
6877 if(!roll_chance_i(chance))
6878 return false;
6880 triggered_spell_id = 24406;
6881 break;
6883 case 4533: // Dreamwalker Raiment 2 pieces bonus
6885 // Chance 50%
6886 if (!roll_chance_i(50))
6887 return false;
6889 switch (pVictim->getPowerType())
6891 case POWER_MANA: triggered_spell_id = 28722; break;
6892 case POWER_RAGE: triggered_spell_id = 28723; break;
6893 case POWER_ENERGY: triggered_spell_id = 28724; break;
6894 default:
6895 return false;
6897 break;
6899 case 4537: // Dreamwalker Raiment 6 pieces bonus
6900 triggered_spell_id = 28750; // Blessing of the Claw
6901 break;
6902 case 5497: // Improved Mana Gems (Serpent-Coil Braid)
6903 triggered_spell_id = 37445; // Mana Surge
6904 break;
6905 case 8152: // Serendipity
6907 // if heal your target over maximum health
6908 if (pVictim->GetHealth() + damage < pVictim->GetMaxHealth())
6909 return false;
6910 int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100;
6911 int32 basepoints0 = cost * triggeredByAura->GetModifier()->m_amount/100;
6912 CastCustomSpell(this, 47762, &basepoints0, NULL, NULL, true, NULL, triggeredByAura);
6913 return true;
6917 // not processed
6918 if(!triggered_spell_id)
6919 return false;
6921 // standard non-dummy case
6922 SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id);
6924 if(!triggerEntry)
6926 sLog.outError("Unit::HandleOverrideClassScriptAuraProc: Spell %u triggering for class script id %u",triggered_spell_id,scriptId);
6927 return false;
6930 if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id))
6931 return false;
6933 CastSpell(pVictim, triggered_spell_id, true, castItem, triggeredByAura);
6935 if( cooldown && GetTypeId()==TYPEID_PLAYER )
6936 ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown);
6938 return true;
6941 void Unit::setPowerType(Powers new_powertype)
6943 SetByteValue(UNIT_FIELD_BYTES_0, 3, new_powertype);
6945 if(GetTypeId() == TYPEID_PLAYER)
6947 if(((Player*)this)->GetGroup())
6948 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_POWER_TYPE);
6950 else if(((Creature*)this)->isPet())
6952 Pet *pet = ((Pet*)this);
6953 if(pet->isControlled())
6955 Unit *owner = GetOwner();
6956 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
6957 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE);
6961 switch(new_powertype)
6963 default:
6964 case POWER_MANA:
6965 break;
6966 case POWER_RAGE:
6967 SetMaxPower(POWER_RAGE,GetCreatePowers(POWER_RAGE));
6968 SetPower( POWER_RAGE,0);
6969 break;
6970 case POWER_FOCUS:
6971 SetMaxPower(POWER_FOCUS,GetCreatePowers(POWER_FOCUS));
6972 SetPower( POWER_FOCUS,GetCreatePowers(POWER_FOCUS));
6973 break;
6974 case POWER_ENERGY:
6975 SetMaxPower(POWER_ENERGY,GetCreatePowers(POWER_ENERGY));
6976 SetPower( POWER_ENERGY,0);
6977 break;
6978 case POWER_HAPPINESS:
6979 SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
6980 SetPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS));
6981 break;
6985 FactionTemplateEntry const* Unit::getFactionTemplateEntry() const
6987 FactionTemplateEntry const* entry = sFactionTemplateStore.LookupEntry(getFaction());
6988 if(!entry)
6990 static uint64 guid = 0; // prevent repeating spam same faction problem
6992 if(GetGUID() != guid)
6994 if(GetTypeId() == TYPEID_PLAYER)
6995 sLog.outError("Player %s have invalid faction (faction template id) #%u", ((Player*)this)->GetName(), getFaction());
6996 else
6997 sLog.outError("Creature (template id: %u) have invalid faction (faction template id) #%u", ((Creature*)this)->GetCreatureInfo()->Entry, getFaction());
6998 guid = GetGUID();
7001 return entry;
7004 bool Unit::IsHostileTo(Unit const* unit) const
7006 // always non-hostile to self
7007 if(unit==this)
7008 return false;
7010 // always non-hostile to GM in GM mode
7011 if(unit->GetTypeId()==TYPEID_PLAYER && ((Player const*)unit)->isGameMaster())
7012 return false;
7014 // always hostile to enemy
7015 if(getVictim()==unit || unit->getVictim()==this)
7016 return true;
7018 // test pet/charm masters instead pers/charmeds
7019 Unit const* testerOwner = GetCharmerOrOwner();
7020 Unit const* targetOwner = unit->GetCharmerOrOwner();
7022 // always hostile to owner's enemy
7023 if(testerOwner && (testerOwner->getVictim()==unit || unit->getVictim()==testerOwner))
7024 return true;
7026 // always hostile to enemy owner
7027 if(targetOwner && (getVictim()==targetOwner || targetOwner->getVictim()==this))
7028 return true;
7030 // always hostile to owner of owner's enemy
7031 if(testerOwner && targetOwner && (testerOwner->getVictim()==targetOwner || targetOwner->getVictim()==testerOwner))
7032 return true;
7034 Unit const* tester = testerOwner ? testerOwner : this;
7035 Unit const* target = targetOwner ? targetOwner : unit;
7037 // always non-hostile to target with common owner, or to owner/pet
7038 if(tester==target)
7039 return false;
7041 // special cases (Duel, etc)
7042 if(tester->GetTypeId()==TYPEID_PLAYER && target->GetTypeId()==TYPEID_PLAYER)
7044 Player const* pTester = (Player const*)tester;
7045 Player const* pTarget = (Player const*)target;
7047 // Duel
7048 if(pTester->duel && pTester->duel->opponent == pTarget && pTester->duel->startTime != 0)
7049 return true;
7051 // Group
7052 if(pTester->GetGroup() && pTester->GetGroup()==pTarget->GetGroup())
7053 return false;
7055 // Sanctuary
7056 if(pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY))
7057 return false;
7059 // PvP FFA state
7060 if(pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
7061 return true;
7063 //= PvP states
7064 // Green/Blue (can't attack)
7065 if(pTester->GetTeam()==pTarget->GetTeam())
7066 return false;
7068 // Red (can attack) if true, Blue/Yellow (can't attack) in another case
7069 return pTester->IsPvP() && pTarget->IsPvP();
7072 // faction base cases
7073 FactionTemplateEntry const*tester_faction = tester->getFactionTemplateEntry();
7074 FactionTemplateEntry const*target_faction = target->getFactionTemplateEntry();
7075 if(!tester_faction || !target_faction)
7076 return false;
7078 if(target->isAttackingPlayer() && tester->IsContestedGuard())
7079 return true;
7081 // PvC forced reaction and reputation case
7082 if(tester->GetTypeId()==TYPEID_PLAYER)
7084 // forced reaction
7085 if(target_faction->faction)
7087 if(ReputationRank const* force =((Player*)tester)->GetReputationMgr().GetForcedRankIfAny(target_faction))
7088 return *force <= REP_HOSTILE;
7090 // if faction have reputation then hostile state for tester at 100% dependent from at_war state
7091 if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction))
7092 if(FactionState const* factionState = ((Player*)tester)->GetReputationMgr().GetState(raw_target_faction))
7093 return (factionState->Flags & FACTION_FLAG_AT_WAR);
7096 // CvP forced reaction and reputation case
7097 else if(target->GetTypeId()==TYPEID_PLAYER)
7099 // forced reaction
7100 if(tester_faction->faction)
7102 if(ReputationRank const* force = ((Player*)target)->GetReputationMgr().GetForcedRankIfAny(tester_faction))
7103 return *force <= REP_HOSTILE;
7105 // apply reputation state
7106 FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction);
7107 if(raw_tester_faction && raw_tester_faction->reputationListID >=0 )
7108 return ((Player const*)target)->GetReputationMgr().GetRank(raw_tester_faction) <= REP_HOSTILE;
7112 // common faction based case (CvC,PvC,CvP)
7113 return tester_faction->IsHostileTo(*target_faction);
7116 bool Unit::IsFriendlyTo(Unit const* unit) const
7118 // always friendly to self
7119 if(unit==this)
7120 return true;
7122 // always friendly to GM in GM mode
7123 if(unit->GetTypeId()==TYPEID_PLAYER && ((Player const*)unit)->isGameMaster())
7124 return true;
7126 // always non-friendly to enemy
7127 if(getVictim()==unit || unit->getVictim()==this)
7128 return false;
7130 // test pet/charm masters instead pers/charmeds
7131 Unit const* testerOwner = GetCharmerOrOwner();
7132 Unit const* targetOwner = unit->GetCharmerOrOwner();
7134 // always non-friendly to owner's enemy
7135 if(testerOwner && (testerOwner->getVictim()==unit || unit->getVictim()==testerOwner))
7136 return false;
7138 // always non-friendly to enemy owner
7139 if(targetOwner && (getVictim()==targetOwner || targetOwner->getVictim()==this))
7140 return false;
7142 // always non-friendly to owner of owner's enemy
7143 if(testerOwner && targetOwner && (testerOwner->getVictim()==targetOwner || targetOwner->getVictim()==testerOwner))
7144 return false;
7146 Unit const* tester = testerOwner ? testerOwner : this;
7147 Unit const* target = targetOwner ? targetOwner : unit;
7149 // always friendly to target with common owner, or to owner/pet
7150 if(tester==target)
7151 return true;
7153 // special cases (Duel)
7154 if(tester->GetTypeId()==TYPEID_PLAYER && target->GetTypeId()==TYPEID_PLAYER)
7156 Player const* pTester = (Player const*)tester;
7157 Player const* pTarget = (Player const*)target;
7159 // Duel
7160 if(pTester->duel && pTester->duel->opponent == target && pTester->duel->startTime != 0)
7161 return false;
7163 // Group
7164 if(pTester->GetGroup() && pTester->GetGroup()==pTarget->GetGroup())
7165 return true;
7167 // Sanctuary
7168 if(pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY))
7169 return true;
7171 // PvP FFA state
7172 if(pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP))
7173 return false;
7175 //= PvP states
7176 // Green/Blue (non-attackable)
7177 if(pTester->GetTeam()==pTarget->GetTeam())
7178 return true;
7180 // Blue (friendly/non-attackable) if not PVP, or Yellow/Red in another case (attackable)
7181 return !pTarget->IsPvP();
7184 // faction base cases
7185 FactionTemplateEntry const*tester_faction = tester->getFactionTemplateEntry();
7186 FactionTemplateEntry const*target_faction = target->getFactionTemplateEntry();
7187 if(!tester_faction || !target_faction)
7188 return false;
7190 if(target->isAttackingPlayer() && tester->IsContestedGuard())
7191 return false;
7193 // PvC forced reaction and reputation case
7194 if(tester->GetTypeId()==TYPEID_PLAYER)
7196 // forced reaction
7197 if(target_faction->faction)
7199 if(ReputationRank const* force =((Player*)tester)->GetReputationMgr().GetForcedRankIfAny(target_faction))
7200 return *force >= REP_FRIENDLY;
7202 // if faction have reputation then friendly state for tester at 100% dependent from at_war state
7203 if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction))
7204 if(FactionState const* factionState = ((Player*)tester)->GetReputationMgr().GetState(raw_target_faction))
7205 return !(factionState->Flags & FACTION_FLAG_AT_WAR);
7208 // CvP forced reaction and reputation case
7209 else if(target->GetTypeId()==TYPEID_PLAYER)
7211 // forced reaction
7212 if(tester_faction->faction)
7214 if(ReputationRank const* force =((Player*)target)->GetReputationMgr().GetForcedRankIfAny(tester_faction))
7215 return *force >= REP_FRIENDLY;
7217 // apply reputation state
7218 if(FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction))
7219 if(raw_tester_faction->reputationListID >=0 )
7220 return ((Player const*)target)->GetReputationMgr().GetRank(raw_tester_faction) >= REP_FRIENDLY;
7224 // common faction based case (CvC,PvC,CvP)
7225 return tester_faction->IsFriendlyTo(*target_faction);
7228 bool Unit::IsHostileToPlayers() const
7230 FactionTemplateEntry const* my_faction = getFactionTemplateEntry();
7231 if(!my_faction || !my_faction->faction)
7232 return false;
7234 FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction);
7235 if(raw_faction && raw_faction->reputationListID >=0 )
7236 return false;
7238 return my_faction->IsHostileToPlayers();
7241 bool Unit::IsNeutralToAll() const
7243 FactionTemplateEntry const* my_faction = getFactionTemplateEntry();
7244 if(!my_faction || !my_faction->faction)
7245 return true;
7247 FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction);
7248 if(raw_faction && raw_faction->reputationListID >=0 )
7249 return false;
7251 return my_faction->IsNeutralToAll();
7254 bool Unit::Attack(Unit *victim, bool meleeAttack)
7256 if(!victim || victim == this)
7257 return false;
7259 // dead units can neither attack nor be attacked
7260 if(!isAlive() || !victim->isAlive())
7261 return false;
7263 // player cannot attack in mount state
7264 if(GetTypeId()==TYPEID_PLAYER && IsMounted())
7265 return false;
7267 // nobody can attack GM in GM-mode
7268 if(victim->GetTypeId()==TYPEID_PLAYER)
7270 if(((Player*)victim)->isGameMaster())
7271 return false;
7273 else
7275 if(((Creature*)victim)->IsInEvadeMode())
7276 return false;
7279 // remove SPELL_AURA_MOD_UNATTACKABLE at attack (in case non-interruptible spells stun aura applied also that not let attack)
7280 if(HasAuraType(SPELL_AURA_MOD_UNATTACKABLE))
7281 RemoveSpellsCausingAura(SPELL_AURA_MOD_UNATTACKABLE);
7283 // in fighting already
7284 if (m_attacking)
7286 if (m_attacking == victim)
7288 // switch to melee attack from ranged/magic
7289 if( meleeAttack && !hasUnitState(UNIT_STAT_MELEE_ATTACKING) )
7291 addUnitState(UNIT_STAT_MELEE_ATTACKING);
7292 SendMeleeAttackStart(victim);
7293 return true;
7295 return false;
7298 // remove old target data
7299 AttackStop(true);
7301 // new battle
7302 else
7304 // set position before any AI calls/assistance
7305 if(GetTypeId()==TYPEID_UNIT)
7306 ((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
7309 //Set our target
7310 SetUInt64Value(UNIT_FIELD_TARGET, victim->GetGUID());
7312 if(meleeAttack)
7313 addUnitState(UNIT_STAT_MELEE_ATTACKING);
7315 m_attacking = victim;
7316 m_attacking->_addAttacker(this);
7318 if(GetTypeId()==TYPEID_UNIT)
7320 WorldPacket data(SMSG_AI_REACTION, 12);
7321 data << uint64(GetGUID());
7322 data << uint32(AI_REACTION_AGGRO); // Aggro sound
7323 ((WorldObject*)this)->SendMessageToSet(&data, true);
7325 ((Creature*)this)->CallAssistance();
7328 // delay offhand weapon attack to next attack time
7329 if(haveOffhandWeapon())
7330 resetAttackTimer(OFF_ATTACK);
7332 if(meleeAttack)
7333 SendMeleeAttackStart(victim);
7335 return true;
7338 bool Unit::AttackStop(bool targetSwitch /*=false*/)
7340 if (!m_attacking)
7341 return false;
7343 Unit* victim = m_attacking;
7345 m_attacking->_removeAttacker(this);
7346 m_attacking = NULL;
7348 //Clear our target
7349 SetUInt64Value(UNIT_FIELD_TARGET, 0);
7351 clearUnitState(UNIT_STAT_MELEE_ATTACKING);
7353 InterruptSpell(CURRENT_MELEE_SPELL);
7355 // reset only at real combat stop
7356 if(!targetSwitch && GetTypeId()==TYPEID_UNIT )
7358 ((Creature*)this)->SetNoCallAssistance(false);
7359 ((Creature*)this)->SetNoSearchAssistance(false);
7362 SendMeleeAttackStop(victim);
7364 return true;
7367 void Unit::CombatStop(bool includingCast)
7369 if (includingCast && IsNonMeleeSpellCasted(false))
7370 InterruptNonMeleeSpells(false);
7372 AttackStop();
7373 RemoveAllAttackers();
7374 if( GetTypeId()==TYPEID_PLAYER )
7375 ((Player*)this)->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
7376 ClearInCombat();
7379 void Unit::CombatStopWithPets(bool includingCast)
7381 CombatStop(includingCast);
7382 if(Pet* pet = GetPet())
7383 pet->CombatStop(includingCast);
7384 if(Unit* charm = GetCharm())
7385 charm->CombatStop(includingCast);
7387 for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
7388 if(Unit* guardian = Unit::GetUnit(*this,*itr))
7389 guardian->CombatStop(includingCast);
7392 bool Unit::isAttackingPlayer() const
7394 if(hasUnitState(UNIT_STAT_ATTACK_PLAYER))
7395 return true;
7397 Pet* pet = GetPet();
7398 if(pet && pet->isAttackingPlayer())
7399 return true;
7401 Unit* charmed = GetCharm();
7402 if(charmed && charmed->isAttackingPlayer())
7403 return true;
7405 for (int8 i = 0; i < MAX_TOTEM; ++i)
7407 if(m_TotemSlot[i])
7409 Creature *totem = GetMap()->GetCreature(m_TotemSlot[i]);
7410 if(totem && totem->isAttackingPlayer())
7411 return true;
7415 return false;
7418 void Unit::RemoveAllAttackers()
7420 while (!m_attackers.empty())
7422 AttackerSet::iterator iter = m_attackers.begin();
7423 if(!(*iter)->AttackStop())
7425 sLog.outError("WORLD: Unit has an attacker that isn't attacking it!");
7426 m_attackers.erase(iter);
7431 void Unit::ModifyAuraState(AuraState flag, bool apply)
7433 if (apply)
7435 if (!HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)))
7437 SetFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1));
7438 if(GetTypeId() == TYPEID_PLAYER)
7440 const PlayerSpellMap& sp_list = ((Player*)this)->GetSpellMap();
7441 for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
7443 if(itr->second->state == PLAYERSPELL_REMOVED) continue;
7444 SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
7445 if (!spellInfo || !IsPassiveSpell(itr->first)) continue;
7446 if (spellInfo->CasterAuraState == flag)
7447 CastSpell(this, itr->first, true, NULL);
7452 else
7454 if (HasFlag(UNIT_FIELD_AURASTATE,1<<(flag-1)))
7456 RemoveFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1));
7458 if (flag != AURA_STATE_ENRAGE) // enrage aura state triggering continues auras
7460 Unit::AuraMap& tAuras = GetAuras();
7461 for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
7463 SpellEntry const* spellProto = (*itr).second->GetSpellProto();
7464 if (spellProto->CasterAuraState == flag)
7466 // exceptions (applied at state but not removed at state change)
7467 // Rampage
7468 if(spellProto->SpellIconID==2006 && spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && spellProto->SpellFamilyFlags==0x100000)
7470 ++itr;
7471 continue;
7474 RemoveAura(itr);
7476 else
7477 ++itr;
7484 Unit *Unit::GetOwner() const
7486 if(uint64 ownerid = GetOwnerGUID())
7487 return ObjectAccessor::GetUnit(*this, ownerid);
7488 return NULL;
7491 Unit *Unit::GetCharmer() const
7493 if(uint64 charmerid = GetCharmerGUID())
7494 return ObjectAccessor::GetUnit(*this, charmerid);
7495 return NULL;
7498 Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself()
7500 uint64 guid = GetCharmerOrOwnerGUID();
7501 if(IS_PLAYER_GUID(guid))
7502 return ObjectAccessor::GetPlayer(*this, guid);
7504 return GetTypeId()==TYPEID_PLAYER ? (Player*)this : NULL;
7507 Pet* Unit::GetPet() const
7509 if(uint64 pet_guid = GetPetGUID())
7511 if(Pet* pet = ObjectAccessor::GetPet(pet_guid))
7512 return pet;
7514 sLog.outError("Unit::GetPet: Pet %u not exist.",GUID_LOPART(pet_guid));
7515 const_cast<Unit*>(this)->SetPet(0);
7518 return NULL;
7521 Unit* Unit::GetCharm() const
7523 if(uint64 charm_guid = GetCharmGUID())
7525 if(Unit* pet = ObjectAccessor::GetUnit(*this, charm_guid))
7526 return pet;
7528 sLog.outError("Unit::GetCharm: Charmed creature %u not exist.",GUID_LOPART(charm_guid));
7529 const_cast<Unit*>(this)->SetCharm(NULL);
7532 return NULL;
7535 float Unit::GetCombatDistance( const Unit* target ) const
7537 float radius = target->GetFloatValue(UNIT_FIELD_COMBATREACH) + GetFloatValue(UNIT_FIELD_COMBATREACH);
7538 float dx = GetPositionX() - target->GetPositionX();
7539 float dy = GetPositionY() - target->GetPositionY();
7540 float dz = GetPositionZ() - target->GetPositionZ();
7541 float dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)) - radius;
7542 return ( dist > 0 ? dist : 0);
7545 void Unit::SetPet(Pet* pet)
7547 SetUInt64Value(UNIT_FIELD_SUMMON, pet ? pet->GetGUID() : 0);
7549 // FIXME: hack, speed must be set only at follow
7550 if(pet && GetTypeId()==TYPEID_PLAYER)
7551 for(int i = 0; i < MAX_MOVE_TYPE; ++i)
7552 pet->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
7555 void Unit::SetCharm(Unit* pet)
7557 SetUInt64Value(UNIT_FIELD_CHARM, pet ? pet->GetGUID() : 0);
7559 if(GetTypeId() == TYPEID_PLAYER)
7560 ((Player*)this)->m_mover = pet ? pet : this;
7564 void Unit::AddGuardian( Pet* pet )
7566 m_guardianPets.insert(pet->GetGUID());
7570 void Unit::RemoveGuardian( Pet* pet )
7572 m_guardianPets.erase(pet->GetGUID());
7575 void Unit::RemoveGuardians()
7577 while(!m_guardianPets.empty())
7579 uint64 guid = *m_guardianPets.begin();
7580 if(Pet* pet = ObjectAccessor::GetPet(guid))
7581 pet->Remove(PET_SAVE_AS_DELETED);
7583 m_guardianPets.erase(guid);
7587 bool Unit::HasGuardianWithEntry(uint32 entry)
7589 // pet guid middle part is entry (and creature also)
7590 // and in guardian list must be guardians with same entry _always_
7591 for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
7593 if(Pet* pet = ObjectAccessor::GetPet(*itr))
7594 if (pet->GetEntry() == entry)
7595 return true;
7598 return false;
7601 void Unit::UnsummonAllTotems()
7603 for (int8 i = 0; i < MAX_TOTEM; ++i)
7605 if(!m_TotemSlot[i])
7606 continue;
7608 Creature *OldTotem = GetMap()->GetCreature(m_TotemSlot[i]);
7609 if (OldTotem && OldTotem->isTotem())
7610 ((Totem*)OldTotem)->UnSummon();
7614 int32 Unit::DealHeal(Unit *pVictim, uint32 addhealth, SpellEntry const *spellProto, bool critical)
7616 int32 gain = pVictim->ModifyHealth(int32(addhealth));
7618 if (GetTypeId()==TYPEID_PLAYER)
7620 // overheal = addhealth - gain
7621 SendHealSpellLog(pVictim, spellProto->Id, addhealth, addhealth - gain, critical);
7623 if (BattleGround *bg = ((Player*)this)->GetBattleGround())
7624 bg->UpdatePlayerScore((Player*)this, SCORE_HEALING_DONE, gain);
7626 // use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
7627 if (gain)
7628 ((Player*)this)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, pVictim);
7630 ((Player*)this)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED, addhealth);
7633 if (pVictim->GetTypeId()==TYPEID_PLAYER)
7635 ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED, gain);
7636 ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED, addhealth);
7639 return gain;
7642 Unit* Unit::SelectMagnetTarget(Unit *victim, SpellEntry const *spellInfo)
7644 if(!victim)
7645 return NULL;
7647 // Magic case
7648 if(spellInfo && (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE || spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC))
7650 Unit::AuraList const& magnetAuras = victim->GetAurasByType(SPELL_AURA_SPELL_MAGNET);
7651 for(Unit::AuraList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr)
7652 if(Unit* magnet = (*itr)->GetCaster())
7653 if(magnet->IsWithinLOSInMap(this) && magnet->isAlive())
7654 return magnet;
7656 // Melee && ranged case
7657 else
7659 AuraList const& hitTriggerAuras = victim->GetAurasByType(SPELL_AURA_ADD_CASTER_HIT_TRIGGER);
7660 for(AuraList::const_iterator i = hitTriggerAuras.begin(); i != hitTriggerAuras.end(); ++i)
7661 if(Unit* magnet = (*i)->GetCaster())
7662 if(magnet->isAlive() && magnet->IsWithinLOSInMap(this))
7663 if(roll_chance_i((*i)->GetModifier()->m_amount))
7664 return magnet;
7667 return victim;
7670 void Unit::SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, uint32 OverHeal, bool critical)
7672 // we guess size
7673 WorldPacket data(SMSG_SPELLHEALLOG, (8+8+4+4+1));
7674 data.append(pVictim->GetPackGUID());
7675 data.append(GetPackGUID());
7676 data << uint32(SpellID);
7677 data << uint32(Damage);
7678 data << uint32(OverHeal);
7679 data << uint8(critical ? 1 : 0);
7680 data << uint8(0); // unused in client?
7681 SendMessageToSet(&data, true);
7684 void Unit::SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, Powers powertype)
7686 WorldPacket data(SMSG_SPELLENERGIZELOG, (8+8+4+4+4+1));
7687 data.append(pVictim->GetPackGUID());
7688 data.append(GetPackGUID());
7689 data << uint32(SpellID);
7690 data << uint32(powertype);
7691 data << uint32(Damage);
7692 SendMessageToSet(&data, true);
7695 void Unit::EnergizeBySpell(Unit *pVictim, uint32 SpellID, uint32 Damage, Powers powertype)
7697 SendEnergizeSpellLog(pVictim, SpellID, Damage, powertype);
7698 // needs to be called after sending spell log
7699 ModifyPower(powertype, Damage);
7702 uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
7704 if(!spellProto || !pVictim || damagetype==DIRECT_DAMAGE )
7705 return pdamage;
7707 // For totems get damage bonus from owner (statue isn't totem in fact)
7708 if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE)
7710 if(Unit* owner = GetOwner())
7711 return owner->SpellDamageBonus(pVictim, spellProto, pdamage, damagetype);
7714 // Taken/Done total percent damage auras
7715 float DoneTotalMod = 1.0f;
7716 float TakenTotalMod = 1.0f;
7717 int32 DoneTotal = 0;
7718 int32 TakenTotal = 0;
7720 // ..done
7721 // Pet damage
7722 if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() )
7723 DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank);
7725 AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
7726 for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
7728 if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) &&
7729 (*i)->GetSpellProto()->EquippedItemClass == -1 &&
7730 // -1 == any item class (not wand then)
7731 (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 )
7732 // 0 == any inventory type (not wand then)
7734 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7738 uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
7739 // Add flat bonus from spell damage versus
7740 DoneTotal += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask);
7741 AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
7742 for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i)
7743 if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
7744 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7746 // done scripted mod (take it from owner)
7747 Unit *owner = GetOwner();
7748 if (!owner) owner = this;
7749 AuraList const& mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
7750 for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
7752 if (!(*i)->isAffectedOnSpell(spellProto))
7753 continue;
7754 switch((*i)->GetModifier()->m_miscvalue)
7756 case 4920: // Molten Fury
7757 case 4919:
7758 case 6917: // Death's Embrace
7759 case 6926:
7760 case 6928:
7762 if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
7763 DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
7764 break;
7766 // Soul Siphon
7767 case 4992:
7768 case 4993:
7770 // effect 1 m_amount
7771 int32 maxPercent = (*i)->GetModifier()->m_amount;
7772 // effect 0 m_amount
7773 int32 stepPercent = CalculateSpellDamage((*i)->GetSpellProto(), 0, (*i)->GetSpellProto()->EffectBasePoints[0], this);
7774 // count affliction effects and calc additional damage in percentage
7775 int32 modPercent = 0;
7776 AuraMap const& victimAuras = pVictim->GetAuras();
7777 for (AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
7779 SpellEntry const* m_spell = itr->second->GetSpellProto();
7780 if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK || !(m_spell->SpellFamilyFlags & UI64LIT(0x0004071B8044C402)))
7781 continue;
7782 modPercent += stepPercent * itr->second->GetStackAmount();
7783 if (modPercent >= maxPercent)
7785 modPercent = maxPercent;
7786 break;
7789 DoneTotalMod *= (modPercent+100.0f)/100.0f;
7790 break;
7792 case 6916: // Death's Embrace
7793 case 6925:
7794 case 6927:
7795 if (HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT))
7796 DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
7797 break;
7798 case 5481: // Starfire Bonus
7800 if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, UI64LIT(0x0000000000200002)))
7801 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7802 break;
7804 case 4418: // Increased Shock Damage
7805 case 4554: // Increased Lightning Damage
7806 case 4555: // Improved Moonfire
7807 case 5142: // Increased Lightning Damage
7808 case 5147: // Improved Consecration / Libram of Resurgence
7809 case 5148: // Idol of the Shooting Star
7810 case 6008: // Increased Lightning Damage / Totem of Hex
7812 DoneTotal+=(*i)->GetModifier()->m_amount;
7813 break;
7815 // Tundra Stalker
7816 // Merciless Combat
7817 case 7277:
7819 // Merciless Combat
7820 if ((*i)->GetSpellProto()->SpellIconID == 2656)
7822 if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
7823 DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
7825 else // Tundra Stalker
7827 if (pVictim->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_DEATHKNIGHT, UI64LIT(0x0400000000000000)))
7828 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7829 break;
7831 break;
7833 case 7293: // Rage of Rivendare
7835 if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, UI64LIT(0x0200000000000000)))
7836 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7837 break;
7839 // Twisted Faith
7840 case 7377:
7842 if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, UI64LIT(0x0000000000008000), 0, GetGUID()))
7843 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7844 break;
7846 // Marked for Death
7847 case 7598:
7848 case 7599:
7849 case 7600:
7850 case 7601:
7851 case 7602:
7853 if (pVictim->GetAura(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, UI64LIT(0x0000000000000400)))
7854 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7855 break;
7860 // Custom scripted damage
7861 // Ice Lance
7862 if (spellProto->SpellFamilyName == SPELLFAMILY_MAGE && spellProto->SpellIconID == 186)
7864 if (pVictim->isFrozen())
7865 DoneTotalMod *= 3.0f;
7868 // ..taken
7869 AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
7870 for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i)
7871 if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) )
7872 TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7874 // .. taken pct: dummy auras
7875 if (pVictim->GetTypeId() == TYPEID_PLAYER)
7877 //Cheat Death
7878 if (Aura *dummy = pVictim->GetDummyAura(45182))
7880 float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4;
7881 if (mod < dummy->GetModifier()->m_amount)
7882 mod = dummy->GetModifier()->m_amount;
7883 TakenTotalMod *= (mod+100.0f)/100.0f;
7887 // From caster spells
7888 AuraList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
7889 for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
7890 if( (*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto))
7891 TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7893 // Mod damage from spell mechanic
7894 uint32 mechanicMask = GetAllSpellMechanicMask(spellProto);
7895 if (mechanicMask)
7897 AuraList const& mDamageDoneMechanic = pVictim->GetAurasByType(SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT);
7898 for(AuraList::const_iterator i = mDamageDoneMechanic.begin();i != mDamageDoneMechanic.end(); ++i)
7899 if(mechanicMask & uint32(1<<((*i)->GetModifier()->m_miscvalue)))
7900 TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
7903 // Taken/Done fixed damage bonus auras
7904 int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto));
7905 int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim);
7907 // Pets just add their bonus damage to their spell damage
7908 // note that their spell damage is just gain of their own auras
7909 if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
7910 DoneAdvertisedBenefit += ((Pet*)this)->GetBonusDamage();
7912 float LvlPenalty = CalculateLevelPenalty(spellProto);
7913 // Spellmod SpellDamage
7914 float SpellModSpellDamage = 100.0f;
7915 if(Player* modOwner = GetSpellModOwner())
7916 modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage);
7917 SpellModSpellDamage /= 100.0f;
7919 // Check for table values
7920 SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id);
7921 if (bonus)
7923 float coeff;
7924 if (damagetype == DOT)
7925 coeff = bonus->dot_damage * LvlPenalty * stack;
7926 else
7927 coeff = bonus->direct_damage * LvlPenalty * stack;
7929 if (bonus->ap_bonus)
7930 DoneTotal += int32(bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack);
7932 DoneTotal += int32(DoneAdvertisedBenefit * coeff * SpellModSpellDamage);
7933 TakenTotal += int32(TakenAdvertisedBenefit * coeff);
7935 // Default calculation
7936 else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
7938 // Damage Done from spell damage bonus
7939 uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
7940 // Damage over Time spells bonus calculation
7941 float DotFactor = 1.0f;
7942 if(damagetype == DOT)
7944 int32 DotDuration = GetSpellDuration(spellProto);
7945 // 200% limit
7946 if(DotDuration > 0)
7948 if(DotDuration > 30000) DotDuration = 30000;
7949 if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
7950 int x = 0;
7951 for(int j = 0; j < 3; j++)
7953 if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
7954 spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
7955 spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
7957 x = j;
7958 break;
7961 int32 DotTicks = 6;
7962 if(spellProto->EffectAmplitude[x] != 0)
7963 DotTicks = DotDuration / spellProto->EffectAmplitude[x];
7964 if(DotTicks)
7966 DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
7967 TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
7971 // Distribute Damage over multiple effects, reduce by AoE
7972 CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
7973 // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
7974 for(int j = 0; j < 3; ++j)
7976 if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
7977 spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
7979 CastingTime /= 2;
7980 break;
7983 DoneTotal += int32(DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage);
7984 TakenTotal+= int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty);
7987 float tmpDamage = (pdamage + DoneTotal) * DoneTotalMod;
7988 // apply spellmod to Done damage (flat and pct)
7989 if(Player* modOwner = GetSpellModOwner())
7990 modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
7992 tmpDamage = (tmpDamage + TakenTotal) * TakenTotalMod;
7994 return tmpDamage > 0 ? uint32(tmpDamage) : 0;
7997 int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask)
7999 int32 DoneAdvertisedBenefit = 0;
8001 // ..done
8002 AuraList const& mDamageDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE);
8003 for(AuraList::const_iterator i = mDamageDone.begin();i != mDamageDone.end(); ++i)
8004 if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0 &&
8005 (*i)->GetSpellProto()->EquippedItemClass == -1 &&
8006 // -1 == any item class (not wand then)
8007 (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 )
8008 // 0 == any inventory type (not wand then)
8009 DoneAdvertisedBenefit += (*i)->GetModifier()->m_amount;
8011 if (GetTypeId() == TYPEID_PLAYER)
8013 // Base value
8014 DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellDamageBonus();
8016 // Damage bonus from stats
8017 AuraList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT);
8018 for(AuraList::const_iterator i = mDamageDoneOfStatPercent.begin();i != mDamageDoneOfStatPercent.end(); ++i)
8020 if((*i)->GetModifier()->m_miscvalue & schoolMask)
8022 // stat used stored in miscValueB for this aura
8023 Stats usedStat = Stats((*i)->GetMiscBValue());
8024 DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f);
8027 // ... and attack power
8028 AuraList const& mDamageDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER);
8029 for(AuraList::const_iterator i =mDamageDonebyAP.begin();i != mDamageDonebyAP.end(); ++i)
8030 if ((*i)->GetModifier()->m_miscvalue & schoolMask)
8031 DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f);
8034 return DoneAdvertisedBenefit;
8037 int32 Unit::SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim)
8039 uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
8041 int32 TakenAdvertisedBenefit = 0;
8042 // ..done (for creature type by mask) in taken
8043 AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE);
8044 for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i)
8045 if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
8046 TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
8048 // ..taken
8049 AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
8050 for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
8051 if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
8052 TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount;
8054 return TakenAdvertisedBenefit;
8057 bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType)
8059 // not critting spell
8060 if((spellProto->AttributesEx2 & SPELL_ATTR_EX2_CANT_CRIT))
8061 return false;
8063 float crit_chance = 0.0f;
8064 switch(spellProto->DmgClass)
8066 case SPELL_DAMAGE_CLASS_NONE:
8067 return false;
8068 case SPELL_DAMAGE_CLASS_MAGIC:
8070 if (schoolMask & SPELL_SCHOOL_MASK_NORMAL)
8071 crit_chance = 0.0f;
8072 // For other schools
8073 else if (GetTypeId() == TYPEID_PLAYER)
8074 crit_chance = GetFloatValue( PLAYER_SPELL_CRIT_PERCENTAGE1 + GetFirstSchoolInMask(schoolMask));
8075 else
8077 crit_chance = m_baseSpellCritChance;
8078 crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask);
8080 // taken
8081 if (pVictim)
8083 if (!IsPositiveSpell(spellProto->Id))
8085 // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE
8086 crit_chance += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask);
8087 // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE
8088 crit_chance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE);
8089 // Modify by player victim resilience
8090 if (pVictim->GetTypeId() == TYPEID_PLAYER)
8091 crit_chance -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL);
8094 // scripted (increase crit chance ... against ... target by x%
8095 AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
8096 for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
8098 if (!((*i)->isAffectedOnSpell(spellProto)))
8099 continue;
8100 switch((*i)->GetModifier()->m_miscvalue)
8102 case 849: if (pVictim->isFrozen()) crit_chance+= 17.0f; break; //Shatter Rank 1
8103 case 910: if (pVictim->isFrozen()) crit_chance+= 34.0f; break; //Shatter Rank 2
8104 case 911: if (pVictim->isFrozen()) crit_chance+= 50.0f; break; //Shatter Rank 3
8105 case 7917: // Glyph of Shadowburn
8106 if (pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
8107 crit_chance+=(*i)->GetModifier()->m_amount;
8108 break;
8109 case 7997: // Renewed Hope
8110 case 7998:
8111 if (pVictim->HasAura(6788))
8112 crit_chance+=(*i)->GetModifier()->m_amount;
8113 break;
8114 case 21: // Test of Faith
8115 case 6935:
8116 case 6918:
8117 if (pVictim->GetHealth() < pVictim->GetMaxHealth()/2)
8118 crit_chance+=(*i)->GetModifier()->m_amount;
8119 break;
8120 default:
8121 break;
8124 // Custom crit by class
8125 switch(spellProto->SpellFamilyName)
8127 case SPELLFAMILY_PALADIN:
8128 // Sacred Shield
8129 if (spellProto->SpellFamilyFlags & UI64LIT(0x0000000040000000))
8131 Aura *aura = pVictim->GetDummyAura(58597);
8132 if (aura && aura->GetCasterGUID() == GetGUID())
8133 crit_chance+=aura->GetModifier()->m_amount;
8134 break;
8136 break;
8137 case SPELLFAMILY_SHAMAN:
8138 // Lava Burst
8139 if (spellProto->SpellFamilyFlags & UI64LIT(0x0000100000000000))
8141 if (Aura *flameShock = pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, UI64LIT(0x0000000010000000), 0, GetGUID()))
8143 // Consume shock aura if not have Glyph of Flame Shock
8144 if (!GetAura(55447, 0))
8145 pVictim->RemoveAurasByCasterSpell(flameShock->GetId(), GetGUID());
8146 return true;
8148 break;
8150 break;
8154 break;
8156 case SPELL_DAMAGE_CLASS_MELEE:
8157 case SPELL_DAMAGE_CLASS_RANGED:
8159 if (pVictim)
8161 crit_chance = GetUnitCriticalChance(attackType, pVictim);
8162 crit_chance+= GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask);
8164 break;
8166 default:
8167 return false;
8169 // percent done
8170 // only players use intelligence for critical chance computations
8171 if(Player* modOwner = GetSpellModOwner())
8172 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
8174 crit_chance = crit_chance > 0.0f ? crit_chance : 0.0f;
8175 if (roll_chance_f(crit_chance))
8176 return true;
8177 return false;
8180 uint32 Unit::SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim)
8182 // Calculate critical bonus
8183 int32 crit_bonus;
8184 switch(spellProto->DmgClass)
8186 case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100%
8187 case SPELL_DAMAGE_CLASS_RANGED:
8188 // TODO: write here full calculation for melee/ranged spells
8189 crit_bonus = damage;
8190 break;
8191 default:
8192 crit_bonus = damage / 2; // for spells is 50%
8193 break;
8196 // adds additional damage to crit_bonus (from talents)
8197 if(Player* modOwner = GetSpellModOwner())
8198 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus);
8200 if(pVictim)
8202 uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
8203 crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
8206 if(crit_bonus > 0)
8207 damage += crit_bonus;
8209 return damage;
8212 uint32 Unit::SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim)
8214 // Calculate critical bonus
8215 int32 crit_bonus;
8216 switch(spellProto->DmgClass)
8218 case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100%
8219 case SPELL_DAMAGE_CLASS_RANGED:
8220 // TODO: write here full calculation for melee/ranged spells
8221 crit_bonus = damage;
8222 break;
8223 default:
8224 crit_bonus = damage / 2; // for spells is 50%
8225 break;
8228 if(pVictim)
8230 uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
8231 crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask));
8234 if(crit_bonus > 0)
8235 damage += crit_bonus;
8237 damage = int32(damage * GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT));
8239 return damage;
8242 uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack)
8244 // No heal amount for this class spells
8245 if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
8246 return healamount;
8248 // For totems get healing bonus from owner (statue isn't totem in fact)
8249 if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE)
8250 if(Unit* owner = GetOwner())
8251 return owner->SpellHealingBonus(pVictim, spellProto, healamount, damagetype, stack);
8253 // Healing Done
8254 // Taken/Done total percent damage auras
8255 float DoneTotalMod = 1.0f;
8256 float TakenTotalMod = 1.0f;
8257 int32 DoneTotal = 0;
8258 int32 TakenTotal = 0;
8260 // Healing done percent
8261 AuraList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
8262 for(AuraList::const_iterator i = mHealingDonePct.begin();i != mHealingDonePct.end(); ++i)
8263 DoneTotalMod *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f;
8265 // done scripted mod (take it from owner)
8266 Unit *owner = GetOwner();
8267 if (!owner) owner = this;
8268 AuraList const& mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
8269 for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
8271 if (!(*i)->isAffectedOnSpell(spellProto))
8272 continue;
8273 switch((*i)->GetModifier()->m_miscvalue)
8275 case 4415: // Increased Rejuvenation Healing
8276 case 4953:
8277 case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind
8278 DoneTotal+=(*i)->GetModifier()->m_amount;
8279 break;
8280 case 7997: // Renewed Hope
8281 case 7998:
8282 if (pVictim->HasAura(6788))
8283 DoneTotalMod *=((*i)->GetModifier()->m_amount + 100.0f)/100.0f;
8284 break;
8285 case 21: // Test of Faith
8286 case 6935:
8287 case 6918:
8288 if (pVictim->GetHealth() < pVictim->GetMaxHealth()/2)
8289 DoneTotalMod *=((*i)->GetModifier()->m_amount + 100.0f)/100.0f;
8290 break;
8291 case 7798: // Glyph of Regrowth
8293 if (pVictim->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, UI64LIT(0x0000000000000040)))
8294 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
8295 break;
8297 case 8477: // Nourish Heal Boost
8299 int32 stepPercent = (*i)->GetModifier()->m_amount;
8300 int32 modPercent = 0;
8301 AuraMap const& victimAuras = pVictim->GetAuras();
8302 for (AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
8304 if (itr->second->GetCasterGUID()!=GetGUID())
8305 continue;
8306 SpellEntry const* m_spell = itr->second->GetSpellProto();
8307 if (m_spell->SpellFamilyName != SPELLFAMILY_DRUID ||
8308 !(m_spell->SpellFamilyFlags & UI64LIT(0x0000001000000050)))
8309 continue;
8310 modPercent += stepPercent * itr->second->GetStackAmount();
8312 DoneTotalMod *= (modPercent+100.0f)/100.0f;
8313 break;
8315 case 7871: // Glyph of Lesser Healing Wave
8317 if (pVictim->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, UI64LIT(0x0000040000000000), 0, GetGUID()))
8318 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
8319 break;
8321 default:
8322 break;
8326 // Taken/Done fixed damage bonus auras
8327 int32 DoneAdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto));
8328 int32 TakenAdvertisedBenefit = SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim);
8330 float LvlPenalty = CalculateLevelPenalty(spellProto);
8331 // Spellmod SpellDamage
8332 float SpellModSpellDamage = 100.0f;
8333 if(Player* modOwner = GetSpellModOwner())
8334 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_SPELL_BONUS_DAMAGE, SpellModSpellDamage);
8335 SpellModSpellDamage /= 100.0f;
8337 // Check for table values
8338 SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id);
8339 if (bonus)
8341 float coeff;
8342 if (damagetype == DOT)
8343 coeff = bonus->dot_damage * LvlPenalty * stack;
8344 else
8345 coeff = bonus->direct_damage * LvlPenalty * stack;
8347 if (bonus->ap_bonus)
8348 DoneTotal += int32(bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack);
8350 DoneTotal += int32(DoneAdvertisedBenefit * coeff * SpellModSpellDamage);
8351 TakenTotal += int32(TakenAdvertisedBenefit * coeff);
8353 // Default calculation
8354 else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit)
8356 // Damage Done from spell damage bonus
8357 uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto);
8358 // Damage over Time spells bonus calculation
8359 float DotFactor = 1.0f;
8360 if(damagetype == DOT)
8362 int32 DotDuration = GetSpellDuration(spellProto);
8363 // 200% limit
8364 if(DotDuration > 0)
8366 if(DotDuration > 30000) DotDuration = 30000;
8367 if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f;
8368 int x = 0;
8369 for(int j = 0; j < 3; j++)
8371 if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && (
8372 spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE ||
8373 spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) )
8375 x = j;
8376 break;
8379 int32 DotTicks = 6;
8380 if(spellProto->EffectAmplitude[x] != 0)
8381 DotTicks = DotDuration / spellProto->EffectAmplitude[x];
8382 if(DotTicks)
8384 DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks;
8385 TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks;
8389 // Distribute Damage over multiple effects, reduce by AoE
8390 CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime );
8391 // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing
8392 for(int j = 0; j < 3; ++j)
8394 if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH ||
8395 spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH )
8397 CastingTime /= 2;
8398 break;
8401 DoneTotal += int32(DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * SpellModSpellDamage * 1.88f);
8402 TakenTotal += int32(TakenAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * LvlPenalty * 1.88f);
8405 // use float as more appropriate for negative values and percent applying
8406 float heal = (healamount + DoneTotal)*DoneTotalMod;
8407 // apply spellmod to Done amount
8408 if(Player* modOwner = GetSpellModOwner())
8409 modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
8411 // Taken mods
8412 // Healing Wave cast
8413 if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && (spellProto->SpellFamilyFlags & UI64LIT(0x0000000000000040)))
8415 // Search for Healing Way on Victim
8416 Unit::AuraList const& auraDummy = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
8417 for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr!=auraDummy.end(); ++itr)
8418 if((*itr)->GetId() == 29203)
8419 TakenTotalMod *= ((*itr)->GetModifier()->m_amount+100.0f) / 100.0f;
8422 // Healing taken percent
8423 float minval = pVictim->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
8424 if(minval)
8425 TakenTotalMod *= (100.0f + minval) / 100.0f;
8427 float maxval = pVictim->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
8428 if(maxval)
8429 TakenTotalMod *= (100.0f + maxval) / 100.0f;
8431 AuraList const& mHealingGet= pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED);
8432 for(AuraList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
8433 if ((*i)->isAffectedOnSpell(spellProto))
8434 TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f;
8436 heal = (heal + TakenTotal) * TakenTotalMod;
8438 return heal < 0 ? 0 : uint32(heal);
8441 int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask)
8443 int32 AdvertisedBenefit = 0;
8445 AuraList const& mHealingDone = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE);
8446 for(AuraList::const_iterator i = mHealingDone.begin();i != mHealingDone.end(); ++i)
8447 if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
8448 AdvertisedBenefit += (*i)->GetModifier()->m_amount;
8450 // Healing bonus of spirit, intellect and strength
8451 if (GetTypeId() == TYPEID_PLAYER)
8453 // Base value
8454 AdvertisedBenefit +=((Player*)this)->GetBaseSpellHealingBonus();
8456 // Healing bonus from stats
8457 AuraList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT);
8458 for(AuraList::const_iterator i = mHealingDoneOfStatPercent.begin();i != mHealingDoneOfStatPercent.end(); ++i)
8460 // stat used dependent from misc value (stat index)
8461 Stats usedStat = Stats((*i)->GetSpellProto()->EffectMiscValue[(*i)->GetEffIndex()]);
8462 AdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f);
8465 // ... and attack power
8466 AuraList const& mHealingDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER);
8467 for(AuraList::const_iterator i = mHealingDonebyAP.begin();i != mHealingDonebyAP.end(); ++i)
8468 if ((*i)->GetModifier()->m_miscvalue & schoolMask)
8469 AdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f);
8471 return AdvertisedBenefit;
8474 int32 Unit::SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim)
8476 int32 AdvertisedBenefit = 0;
8477 AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING);
8478 for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
8479 if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0)
8480 AdvertisedBenefit += (*i)->GetModifier()->m_amount;
8481 return AdvertisedBenefit;
8484 bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask)
8486 //If m_immuneToSchool type contain this school type, IMMUNE damage.
8487 SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
8488 for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
8489 if(itr->type & shoolMask)
8490 return true;
8492 //If m_immuneToDamage type contain magic, IMMUNE damage.
8493 SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE];
8494 for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr)
8495 if(itr->type & shoolMask)
8496 return true;
8498 return false;
8501 bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo)
8503 if (!spellInfo)
8504 return false;
8506 //TODO add spellEffect immunity checks!, player with flag in bg is imune to imunity buffs from other friendly players!
8507 //SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_EFFECT];
8509 SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
8510 for(SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr)
8511 if(itr->type == spellInfo->Dispel)
8512 return true;
8514 if( !(spellInfo->AttributesEx & SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE) && // unaffected by school immunity
8515 !(spellInfo->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)) // can remove immune (by dispell or immune it)
8517 SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
8518 for(SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
8519 if( !(IsPositiveSpell(itr->spellId) && IsPositiveSpell(spellInfo->Id)) &&
8520 (itr->type & GetSpellSchoolMask(spellInfo)) )
8521 return true;
8524 SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
8525 for(SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
8527 if(itr->type == spellInfo->Mechanic)
8529 return true;
8533 return false;
8536 bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const
8538 //If m_immuneToEffect type contain this effect type, IMMUNE effect.
8539 uint32 effect = spellInfo->Effect[index];
8540 SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT];
8541 for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr)
8542 if(itr->type == effect)
8543 return true;
8545 if(uint32 mechanic = spellInfo->EffectMechanic[index])
8547 SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
8548 for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
8549 if(itr->type == mechanic)
8550 return true;
8553 if(uint32 aura = spellInfo->EffectApplyAuraName[index])
8555 SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE];
8556 for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
8557 if(itr->type == aura)
8558 return true;
8559 // Check for immune to application of harmful magical effects
8560 AuraList const& immuneAuraApply = GetAurasByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL);
8561 for(AuraList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter)
8562 if (spellInfo->Dispel == DISPEL_MAGIC && // Magic debuff
8563 ((*iter)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellInfo)) && // Check school
8564 !IsPositiveEffect(spellInfo->Id, index)) // Harmful
8565 return true;
8568 return false;
8571 bool Unit::IsDamageToThreatSpell(SpellEntry const * spellInfo) const
8573 if(!spellInfo)
8574 return false;
8576 uint32 family = spellInfo->SpellFamilyName;
8577 uint64 flags = spellInfo->SpellFamilyFlags;
8579 if((family == 5 && flags == 256) || //Searing Pain
8580 (family == 6 && flags == 8192) || //Mind Blast
8581 (family == 11 && flags == 1048576)) //Earth Shock
8582 return true;
8584 return false;
8587 void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attType, SpellEntry const *spellProto)
8589 if(!pVictim)
8590 return;
8592 if(*pdamage == 0)
8593 return;
8595 uint32 creatureTypeMask = pVictim->GetCreatureTypeMask();
8597 // Taken/Done fixed damage bonus auras
8598 int32 DoneFlatBenefit = 0;
8599 int32 TakenFlatBenefit = 0;
8601 // ..done (for creature type by mask) in taken
8602 AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE);
8603 for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i)
8604 if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
8605 DoneFlatBenefit += (*i)->GetModifier()->m_amount;
8607 // ..done
8608 // SPELL_AURA_MOD_DAMAGE_DONE included in weapon damage
8610 // ..done (base at attack power for marked target and base at attack power for creature type)
8611 int32 APbonus = 0;
8612 if(attType == RANGED_ATTACK)
8614 APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS);
8616 // ..done (base at attack power and creature type)
8617 AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS);
8618 for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i)
8619 if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
8620 APbonus += (*i)->GetModifier()->m_amount;
8622 else
8624 APbonus += pVictim->GetTotalAuraModifier(SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS);
8626 // ..done (base at attack power and creature type)
8627 AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS);
8628 for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i)
8629 if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
8630 APbonus += (*i)->GetModifier()->m_amount;
8633 if (APbonus!=0) // Can be negative
8635 bool normalized = false;
8636 if(spellProto)
8638 for (uint8 i = 0; i<3;++i)
8640 if (spellProto->Effect[i] == SPELL_EFFECT_NORMALIZED_WEAPON_DMG)
8642 normalized = true;
8643 break;
8648 DoneFlatBenefit += int32(APbonus/14.0f * GetAPMultiplier(attType,normalized));
8651 // ..taken
8652 AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN);
8653 for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i)
8654 if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask())
8655 TakenFlatBenefit += (*i)->GetModifier()->m_amount;
8657 if(attType!=RANGED_ATTACK)
8658 TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN);
8659 else
8660 TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN);
8662 // Done/Taken total percent damage auras
8663 float DoneTotalMod = 1.0f;
8664 float TakenTotalMod = 1.0f;
8666 // ..done
8667 // SPELL_AURA_MOD_DAMAGE_PERCENT_DONE included in weapon damage
8668 // SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT included in weapon damage
8670 AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
8671 for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i)
8672 if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue))
8673 DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
8675 // ..taken
8676 AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN);
8677 for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i)
8678 if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask())
8679 TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
8681 // .. taken pct: dummy auras
8682 AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY);
8683 for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
8685 switch((*i)->GetSpellProto()->SpellIconID)
8687 //Cheat Death
8688 case 2109:
8689 if((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)
8691 if(pVictim->GetTypeId() != TYPEID_PLAYER)
8692 continue;
8693 float mod = ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE)*(-8.0f);
8694 if (mod < (*i)->GetModifier()->m_amount)
8695 mod = (*i)->GetModifier()->m_amount;
8696 TakenTotalMod *= (mod+100.0f)/100.0f;
8698 break;
8699 //Mangle
8700 case 2312:
8701 if(spellProto==NULL)
8702 break;
8703 // Should increase Shred (initial Damage of Lacerate and Rake handled in Spell::EffectSchoolDMG)
8704 if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags == UI64LIT(0x00008000)))
8705 TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f;
8706 break;
8710 // .. taken pct: class scripts
8711 AuraList const& mclassScritAuras = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
8712 for(AuraList::const_iterator i = mclassScritAuras.begin(); i != mclassScritAuras.end(); ++i)
8714 switch((*i)->GetMiscValue())
8716 case 6427: case 6428: // Dirty Deeds
8717 if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
8719 Aura* eff0 = GetAura((*i)->GetId(),0);
8720 if(!eff0 || (*i)->GetEffIndex()!=1)
8722 sLog.outError("Spell structure of DD (%u) changed.",(*i)->GetId());
8723 continue;
8726 // effect 0 have expected value but in negative state
8727 TakenTotalMod *= (-eff0->GetModifier()->m_amount+100.0f)/100.0f;
8729 break;
8733 if(attType != RANGED_ATTACK)
8735 AuraList const& mModMeleeDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT);
8736 for(AuraList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i)
8737 TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
8739 else
8741 AuraList const& mModRangedDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT);
8742 for(AuraList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i)
8743 TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f;
8746 float tmpDamage = float(int32(*pdamage) + DoneFlatBenefit) * DoneTotalMod;
8748 // apply spellmod to Done damage
8749 if(spellProto)
8751 if(Player* modOwner = GetSpellModOwner())
8752 modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
8755 tmpDamage = (tmpDamage + TakenFlatBenefit)*TakenTotalMod;
8757 // bonus result can be negative
8758 *pdamage = tmpDamage > 0 ? uint32(tmpDamage) : 0;
8761 void Unit::ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply)
8763 if (apply)
8765 for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(), next; itr != m_spellImmune[op].end(); itr = next)
8767 next = itr; ++next;
8768 if(itr->type == type)
8770 m_spellImmune[op].erase(itr);
8771 next = m_spellImmune[op].begin();
8774 SpellImmune Immune;
8775 Immune.spellId = spellId;
8776 Immune.type = type;
8777 m_spellImmune[op].push_back(Immune);
8779 else
8781 for (SpellImmuneList::iterator itr = m_spellImmune[op].begin(); itr != m_spellImmune[op].end(); ++itr)
8783 if(itr->spellId == spellId)
8785 m_spellImmune[op].erase(itr);
8786 break;
8793 void Unit::ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType type, bool apply)
8795 ApplySpellImmune(spellProto->Id,IMMUNITY_DISPEL, type, apply);
8797 if (apply && spellProto->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
8798 RemoveAurasWithDispelType(type);
8801 float Unit::GetWeaponProcChance() const
8803 // normalized proc chance for weapon attack speed
8804 // (odd formula...)
8805 if(isAttackReady(BASE_ATTACK))
8806 return (GetAttackTime(BASE_ATTACK) * 1.8f / 1000.0f);
8807 else if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
8808 return (GetAttackTime(OFF_ATTACK) * 1.6f / 1000.0f);
8809 return 0;
8812 float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const
8814 // proc per minute chance calculation
8815 if (PPM <= 0) return 0.0f;
8816 uint32 result = uint32((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60))
8817 return result;
8820 void Unit::Mount(uint32 mount)
8822 if(!mount)
8823 return;
8825 RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING);
8827 SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, mount);
8829 SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT );
8831 // unsummon pet
8832 if(GetTypeId() == TYPEID_PLAYER)
8833 ((Player*)this)->UnsummonPetTemporaryIfAny();
8836 void Unit::Unmount()
8838 if(!IsMounted())
8839 return;
8841 RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_MOUNTED);
8843 SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
8844 RemoveFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT );
8846 // only resummon old pet if the player is already added to a map
8847 // this prevents adding a pet to a not created map which would otherwise cause a crash
8848 // (it could probably happen when logging in after a previous crash)
8849 if(GetTypeId() == TYPEID_PLAYER)
8850 ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny();
8853 void Unit::SetInCombatWith(Unit* enemy)
8855 Unit* eOwner = enemy->GetCharmerOrOwnerOrSelf();
8856 if(eOwner->IsPvP())
8858 SetInCombatState(true,enemy);
8859 return;
8862 //check for duel
8863 if(eOwner->GetTypeId() == TYPEID_PLAYER && ((Player*)eOwner)->duel)
8865 Unit const* myOwner = GetCharmerOrOwnerOrSelf();
8866 if(((Player const*)eOwner)->duel->opponent == myOwner)
8868 SetInCombatState(true,enemy);
8869 return;
8872 SetInCombatState(false,enemy);
8875 void Unit::SetInCombatState(bool PvP, Unit* enemy)
8877 // only alive units can be in combat
8878 if(!isAlive())
8879 return;
8881 if(PvP)
8882 m_CombatTimer = 5000;
8884 bool creatureNotInCombat = GetTypeId()==TYPEID_UNIT && !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
8886 SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
8888 if(isCharmed() || (GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet()))
8889 SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
8891 if(creatureNotInCombat && ((Creature*)this)->AI())
8892 ((Creature*)this)->AI()->EnterCombat(enemy);
8895 void Unit::ClearInCombat()
8897 m_CombatTimer = 0;
8898 RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
8900 if(isCharmed() || (GetTypeId()!=TYPEID_PLAYER && ((Creature*)this)->isPet()))
8901 RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT);
8903 // Player's state will be cleared in Player::UpdateContestedPvP
8904 if(GetTypeId()!=TYPEID_PLAYER)
8905 clearUnitState(UNIT_STAT_ATTACK_PLAYER);
8906 else
8907 ((Player*)this)->UpdatePotionCooldown();
8910 bool Unit::isTargetableForAttack() const
8912 if (GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster())
8913 return false;
8915 if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
8916 return false;
8918 return isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;
8921 int32 Unit::ModifyHealth(int32 dVal)
8923 int32 gain = 0;
8925 if(dVal==0)
8926 return 0;
8928 int32 curHealth = (int32)GetHealth();
8930 int32 val = dVal + curHealth;
8931 if(val <= 0)
8933 SetHealth(0);
8934 return -curHealth;
8937 int32 maxHealth = (int32)GetMaxHealth();
8939 if(val < maxHealth)
8941 SetHealth(val);
8942 gain = val - curHealth;
8944 else if(curHealth != maxHealth)
8946 SetHealth(maxHealth);
8947 gain = maxHealth - curHealth;
8950 return gain;
8953 int32 Unit::ModifyPower(Powers power, int32 dVal)
8955 int32 gain = 0;
8957 if(dVal==0)
8958 return 0;
8960 int32 curPower = (int32)GetPower(power);
8962 int32 val = dVal + curPower;
8963 if(val <= 0)
8965 SetPower(power,0);
8966 return -curPower;
8969 int32 maxPower = (int32)GetMaxPower(power);
8971 if(val < maxPower)
8973 SetPower(power,val);
8974 gain = val - curPower;
8976 else if(curPower != maxPower)
8978 SetPower(power,maxPower);
8979 gain = maxPower - curPower;
8982 return gain;
8985 bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, bool is3dDistance) const
8987 if(!u)
8988 return false;
8990 // Always can see self
8991 if (u==this)
8992 return true;
8994 // player visible for other player if not logout and at same transport
8995 // including case when player is out of world
8996 bool at_same_transport =
8997 GetTypeId() == TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER &&
8998 !((Player*)this)->GetSession()->PlayerLogout() && !((Player*)u)->GetSession()->PlayerLogout() &&
8999 !((Player*)this)->GetSession()->PlayerLoading() && !((Player*)u)->GetSession()->PlayerLoading() &&
9000 ((Player*)this)->GetTransport() && ((Player*)this)->GetTransport() == ((Player*)u)->GetTransport();
9002 // not in world
9003 if(!at_same_transport && (!IsInWorld() || !u->IsInWorld()))
9004 return false;
9006 // forbidden to seen (at GM respawn command)
9007 if(m_Visibility==VISIBILITY_RESPAWN)
9008 return false;
9010 // Grid dead/alive checks
9011 if( u->GetTypeId()==TYPEID_PLAYER)
9013 // non visible at grid for any stealth state
9014 if(!IsVisibleInGridForPlayer((Player *)u))
9015 return false;
9017 // if player is dead then he can't detect anyone in any cases
9018 if(!u->isAlive())
9019 detect = false;
9021 else
9023 // all dead creatures/players not visible for any creatures
9024 if(!u->isAlive() || !isAlive())
9025 return false;
9028 // always seen by owner
9029 if(GetCharmerOrOwnerGUID()==u->GetGUID())
9030 return true;
9032 // different visible distance checks
9033 if(u->isInFlight()) // what see player in flight
9035 // use object grey distance for all (only see objects any way)
9036 if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance))
9037 return false;
9039 else if(!isAlive()) // distance for show body
9041 if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance))
9042 return false;
9044 else if(GetTypeId()==TYPEID_PLAYER) // distance for show player
9046 if(u->GetTypeId()==TYPEID_PLAYER)
9048 // Players far than max visible distance for player or not in our map are not visible too
9049 if (!at_same_transport && !IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
9050 return false;
9052 else
9054 // Units far than max visible distance for creature or not in our map are not visible too
9055 if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
9056 return false;
9059 else if(GetCharmerOrOwnerGUID()) // distance for show pet/charmed
9061 // Pet/charmed far than max visible distance for player or not in our map are not visible too
9062 if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
9063 return false;
9065 else // distance for show creature
9067 // Units far than max visible distance for creature or not in our map are not visible too
9068 if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance))
9069 return false;
9072 // Visible units, always are visible for all units, except for units under invisibility and phases
9073 if (m_Visibility == VISIBILITY_ON && u->m_invisibilityMask==0 && InSamePhase(u))
9074 return true;
9076 // GMs see any players, not higher GMs and all units in any phase
9077 if (u->GetTypeId() == TYPEID_PLAYER && ((Player *)u)->isGameMaster())
9079 if(GetTypeId() == TYPEID_PLAYER)
9080 return ((Player *)this)->GetSession()->GetSecurity() <= ((Player *)u)->GetSession()->GetSecurity();
9081 else
9082 return true;
9085 // non faction visibility non-breakable for non-GMs
9086 if (m_Visibility == VISIBILITY_OFF)
9087 return false;
9089 // phased visibility (both must phased in same way)
9090 if(!InSamePhase(u))
9091 return false;
9093 // raw invisibility
9094 bool invisible = (m_invisibilityMask != 0 || u->m_invisibilityMask !=0);
9096 // detectable invisibility case
9097 if( invisible && (
9098 // Invisible units, always are visible for units under same invisibility type
9099 (m_invisibilityMask & u->m_invisibilityMask)!=0 ||
9100 // Invisible units, always are visible for unit that can detect this invisibility (have appropriate level for detect)
9101 u->canDetectInvisibilityOf(this) ||
9102 // Units that can detect invisibility always are visible for units that can be detected
9103 canDetectInvisibilityOf(u) ))
9105 invisible = false;
9108 // special cases for always overwrite invisibility/stealth
9109 if(invisible || m_Visibility == VISIBILITY_GROUP_STEALTH)
9111 // non-hostile case
9112 if (!u->IsHostileTo(this))
9114 // player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting)
9115 if(GetTypeId()==TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER)
9117 if(((Player*)this)->IsGroupVisibleFor(((Player*)u)))
9118 return true;
9120 // else apply same rules as for hostile case (detecting check for stealth)
9123 // hostile case
9124 else
9126 // Hunter mark functionality
9127 AuraList const& auras = GetAurasByType(SPELL_AURA_MOD_STALKED);
9128 for(AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
9129 if((*iter)->GetCasterGUID()==u->GetGUID())
9130 return true;
9132 // else apply detecting check for stealth
9135 // none other cases for detect invisibility, so invisible
9136 if(invisible)
9137 return false;
9139 // else apply stealth detecting check
9142 // unit got in stealth in this moment and must ignore old detected state
9143 if (m_Visibility == VISIBILITY_GROUP_NO_DETECT)
9144 return false;
9146 // GM invisibility checks early, invisibility if any detectable, so if not stealth then visible
9147 if (m_Visibility != VISIBILITY_GROUP_STEALTH)
9148 return true;
9150 // NOW ONLY STEALTH CASE
9152 // stealth and detected and visible for some seconds
9153 if (u->GetTypeId() == TYPEID_PLAYER && ((Player*)u)->m_DetectInvTimer > 300 && ((Player*)u)->HaveAtClient(this))
9154 return true;
9156 //if in non-detect mode then invisible for unit
9157 if (!detect)
9158 return false;
9160 // Special cases
9162 // If is attacked then stealth is lost, some creature can use stealth too
9163 if( !getAttackers().empty() )
9164 return true;
9166 // If there is collision rogue is seen regardless of level difference
9167 if (IsWithinDist(u,0.24f))
9168 return true;
9170 //If a mob or player is stunned he will not be able to detect stealth
9171 if (u->hasUnitState(UNIT_STAT_STUNNED) && (u != this))
9172 return false;
9174 // Creature can detect target only in aggro radius
9175 if(u->GetTypeId() != TYPEID_PLAYER)
9177 //Always invisible from back and out of aggro range
9178 bool isInFront = u->isInFrontInMap(this,((Creature const*)u)->GetAttackDistance(this));
9179 if(!isInFront)
9180 return false;
9182 else
9184 //Always invisible from back
9185 bool isInFront = u->isInFrontInMap(this,(GetTypeId()==TYPEID_PLAYER || GetCharmerOrOwnerGUID()) ? World::GetMaxVisibleDistanceForPlayer() : World::GetMaxVisibleDistanceForCreature());
9186 if(!isInFront)
9187 return false;
9190 // if doesn't have stealth detection (Shadow Sight), then check how stealthy the unit is, otherwise just check los
9191 if(!u->HasAuraType(SPELL_AURA_DETECT_STEALTH))
9193 //Calculation if target is in front
9195 //Visible distance based on stealth value (stealth rank 4 300MOD, 10.5 - 3 = 7.5)
9196 float visibleDistance = 10.5f - (GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH)/100.0f);
9198 //Visible distance is modified by
9199 //-Level Diff (every level diff = 1.0f in visible distance)
9200 visibleDistance += int32(u->getLevelForTarget(this)) - int32(getLevelForTarget(u));
9202 //This allows to check talent tree and will add addition stealth dependent on used points)
9203 int32 stealthMod = GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH_LEVEL);
9204 if(stealthMod < 0)
9205 stealthMod = 0;
9207 //-Stealth Mod(positive like Master of Deception) and Stealth Detection(negative like paranoia)
9208 //based on wowwiki every 5 mod we have 1 more level diff in calculation
9209 visibleDistance += (int32(u->GetTotalAuraModifier(SPELL_AURA_MOD_DETECT)) - stealthMod)/5.0f;
9211 if(!IsWithinDist(u,visibleDistance))
9212 return false;
9215 // Now check is target visible with LoS
9216 float ox,oy,oz;
9217 u->GetPosition(ox,oy,oz);
9218 return IsWithinLOS(ox,oy,oz);
9221 void Unit::SetVisibility(UnitVisibility x)
9223 m_Visibility = x;
9225 if(IsInWorld())
9227 Map *m = GetMap();
9229 if(GetTypeId()==TYPEID_PLAYER)
9230 m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
9231 else
9232 m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
9236 bool Unit::canDetectInvisibilityOf(Unit const* u) const
9238 if(uint32 mask = (m_detectInvisibilityMask & u->m_invisibilityMask))
9240 for(uint32 i = 0; i < 10; ++i)
9242 if(((1 << i) & mask)==0)
9243 continue;
9245 // find invisibility level
9246 uint32 invLevel = 0;
9247 Unit::AuraList const& iAuras = u->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
9248 for(Unit::AuraList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr)
9249 if(((*itr)->GetModifier()->m_miscvalue)==i && invLevel < (*itr)->GetModifier()->m_amount)
9250 invLevel = (*itr)->GetModifier()->m_amount;
9252 // find invisibility detect level
9253 uint32 detectLevel = 0;
9254 Unit::AuraList const& dAuras = GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
9255 for(Unit::AuraList::const_iterator itr = dAuras.begin(); itr != dAuras.end(); ++itr)
9256 if(((*itr)->GetModifier()->m_miscvalue)==i && detectLevel < (*itr)->GetModifier()->m_amount)
9257 detectLevel = (*itr)->GetModifier()->m_amount;
9259 if(i==6 && GetTypeId()==TYPEID_PLAYER) // special drunk detection case
9261 detectLevel = ((Player*)this)->GetDrunkValue();
9264 if(invLevel <= detectLevel)
9265 return true;
9269 return false;
9272 void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
9274 int32 main_speed_mod = 0;
9275 float stack_bonus = 1.0f;
9276 float non_stack_bonus = 1.0f;
9278 switch(mtype)
9280 case MOVE_WALK:
9281 return;
9282 case MOVE_RUN:
9284 if (IsMounted()) // Use on mount auras
9286 main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED);
9287 stack_bonus = GetTotalAuraMultiplier(SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS);
9288 non_stack_bonus = (100.0f + GetMaxPositiveAuraModifier(SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK))/100.0f;
9290 else
9292 main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_SPEED);
9293 stack_bonus = GetTotalAuraMultiplier(SPELL_AURA_MOD_SPEED_ALWAYS);
9294 non_stack_bonus = (100.0f + GetMaxPositiveAuraModifier(SPELL_AURA_MOD_SPEED_NOT_STACK))/100.0f;
9296 break;
9298 case MOVE_RUN_BACK:
9299 return;
9300 case MOVE_SWIM:
9302 main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_SWIM_SPEED);
9303 break;
9305 case MOVE_SWIM_BACK:
9306 return;
9307 case MOVE_FLIGHT:
9309 if (IsMounted()) // Use on mount auras
9310 main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED);
9311 else // Use not mount (shapeshift for example) auras (should stack)
9312 main_speed_mod = GetTotalAuraModifier(SPELL_AURA_MOD_SPEED_FLIGHT);
9313 stack_bonus = GetTotalAuraMultiplier(SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS);
9314 non_stack_bonus = (100.0 + GetMaxPositiveAuraModifier(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK))/100.0f;
9315 break;
9317 case MOVE_FLIGHT_BACK:
9318 return;
9319 default:
9320 sLog.outError("Unit::UpdateSpeed: Unsupported move type (%d)", mtype);
9321 return;
9324 float bonus = non_stack_bonus > stack_bonus ? non_stack_bonus : stack_bonus;
9325 // now we ready for speed calculation
9326 float speed = main_speed_mod ? bonus*(100.0f + main_speed_mod)/100.0f : bonus;
9328 switch(mtype)
9330 case MOVE_RUN:
9331 case MOVE_SWIM:
9332 case MOVE_FLIGHT:
9334 // Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need
9335 // TODO: possible affect only on MOVE_RUN
9336 if(int32 normalization = GetMaxPositiveAuraModifier(SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED))
9338 // Use speed from aura
9339 float max_speed = normalization / baseMoveSpeed[mtype];
9340 if (speed > max_speed)
9341 speed = max_speed;
9343 break;
9345 default:
9346 break;
9349 // Apply strongest slow aura mod to speed
9350 int32 slow = GetMaxNegativeAuraModifier(SPELL_AURA_MOD_DECREASE_SPEED);
9351 if (slow)
9352 speed *=(100.0f + slow)/100.0f;
9353 SetSpeed(mtype, speed, forced);
9356 float Unit::GetSpeed( UnitMoveType mtype ) const
9358 return m_speed_rate[mtype]*baseMoveSpeed[mtype];
9361 void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
9363 if (rate < 0)
9364 rate = 0.0f;
9366 // Update speed only on change
9367 if (m_speed_rate[mtype] == rate)
9368 return;
9370 m_speed_rate[mtype] = rate;
9372 propagateSpeedChange();
9374 WorldPacket data;
9375 if(!forced)
9377 switch(mtype)
9379 case MOVE_WALK:
9380 data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4);
9381 break;
9382 case MOVE_RUN:
9383 data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4);
9384 break;
9385 case MOVE_RUN_BACK:
9386 data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
9387 break;
9388 case MOVE_SWIM:
9389 data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4);
9390 break;
9391 case MOVE_SWIM_BACK:
9392 data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
9393 break;
9394 case MOVE_TURN_RATE:
9395 data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4);
9396 break;
9397 case MOVE_FLIGHT:
9398 data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4);
9399 break;
9400 case MOVE_FLIGHT_BACK:
9401 data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
9402 break;
9403 case MOVE_PITCH_RATE:
9404 data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4);
9405 break;
9406 default:
9407 sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype);
9408 return;
9411 data.append(GetPackGUID());
9412 data << uint32(0); // movement flags
9413 data << uint16(0); // unk flags
9414 data << uint32(getMSTime());
9415 data << float(GetPositionX());
9416 data << float(GetPositionY());
9417 data << float(GetPositionZ());
9418 data << float(GetOrientation());
9419 data << uint32(0); // fall time
9420 data << float(GetSpeed(mtype));
9421 SendMessageToSet( &data, true );
9423 else
9425 if(GetTypeId() == TYPEID_PLAYER)
9427 // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
9428 // and do it only for real sent packets and use run for run/mounted as client expected
9429 ++((Player*)this)->m_forced_speed_changes[mtype];
9432 switch(mtype)
9434 case MOVE_WALK:
9435 data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16);
9436 break;
9437 case MOVE_RUN:
9438 data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17);
9439 break;
9440 case MOVE_RUN_BACK:
9441 data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16);
9442 break;
9443 case MOVE_SWIM:
9444 data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16);
9445 break;
9446 case MOVE_SWIM_BACK:
9447 data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16);
9448 break;
9449 case MOVE_TURN_RATE:
9450 data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16);
9451 break;
9452 case MOVE_FLIGHT:
9453 data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16);
9454 break;
9455 case MOVE_FLIGHT_BACK:
9456 data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16);
9457 break;
9458 case MOVE_PITCH_RATE:
9459 data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16);
9460 break;
9461 default:
9462 sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype);
9463 return;
9465 data.append(GetPackGUID());
9466 data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39
9467 if (mtype == MOVE_RUN)
9468 data << uint8(0); // new 2.1.0
9469 data << float(GetSpeed(mtype));
9470 SendMessageToSet( &data, true );
9472 if(Pet* pet = GetPet())
9473 pet->SetSpeed(MOVE_RUN, m_speed_rate[mtype],forced);
9476 void Unit::SetHover(bool on)
9478 if(on)
9479 CastSpell(this, 11010, true);
9480 else
9481 RemoveAurasDueToSpell(11010);
9484 void Unit::setDeathState(DeathState s)
9486 if (s != ALIVE && s!= JUST_ALIVED)
9488 CombatStop();
9489 DeleteThreatList();
9490 ClearComboPointHolders(); // any combo points pointed to unit lost at it death
9492 if(IsNonMeleeSpellCasted(false))
9493 InterruptNonMeleeSpells(false);
9496 if (s == JUST_DIED)
9498 RemoveAllAurasOnDeath();
9499 RemoveGuardians();
9500 UnsummonAllTotems();
9502 ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
9503 ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
9504 // remove aurastates allowing special moves
9505 ClearAllReactives();
9506 ClearDiminishings();
9508 else if(s == JUST_ALIVED)
9510 RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // clear skinnable for creature and player (at battleground)
9513 if (m_deathState != ALIVE && s == ALIVE)
9515 //_ApplyAllAuraMods();
9517 m_deathState = s;
9520 /*########################################
9521 ######## ########
9522 ######## AGGRO SYSTEM ########
9523 ######## ########
9524 ########################################*/
9525 bool Unit::CanHaveThreatList() const
9527 // only creatures can have threat list
9528 if( GetTypeId() != TYPEID_UNIT )
9529 return false;
9531 // only alive units can have threat list
9532 if( !isAlive() )
9533 return false;
9535 // totems can not have threat list
9536 if( ((Creature*)this)->isTotem() )
9537 return false;
9539 // vehicles can not have threat list
9540 if( ((Creature*)this)->isVehicle() )
9541 return false;
9543 // pets can not have a threat list, unless they are controlled by a creature
9544 if( ((Creature*)this)->isPet() && IS_PLAYER_GUID(((Pet*)this)->GetOwnerGUID()) )
9545 return false;
9547 return true;
9550 //======================================================================
9552 float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask)
9554 if(!HasAuraType(SPELL_AURA_MOD_THREAT))
9555 return threat;
9557 SpellSchools school = GetFirstSchoolInMask(schoolMask);
9559 return threat * m_threatModifier[school];
9562 //======================================================================
9564 void Unit::AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask, SpellEntry const *threatSpell)
9566 // Only mobs can manage threat lists
9567 if(CanHaveThreatList())
9568 m_ThreatManager.addThreat(pVictim, threat, schoolMask, threatSpell);
9571 //======================================================================
9573 void Unit::DeleteThreatList()
9575 m_ThreatManager.clearReferences();
9578 //======================================================================
9580 void Unit::TauntApply(Unit* taunter)
9582 assert(GetTypeId()== TYPEID_UNIT);
9584 if(!taunter || (taunter->GetTypeId() == TYPEID_PLAYER && ((Player*)taunter)->isGameMaster()))
9585 return;
9587 if(!CanHaveThreatList())
9588 return;
9590 Unit *target = getVictim();
9591 if(target && target == taunter)
9592 return;
9594 SetInFront(taunter);
9595 if (((Creature*)this)->AI())
9596 ((Creature*)this)->AI()->AttackStart(taunter);
9598 m_ThreatManager.tauntApply(taunter);
9601 //======================================================================
9603 void Unit::TauntFadeOut(Unit *taunter)
9605 assert(GetTypeId()== TYPEID_UNIT);
9607 if(!taunter || (taunter->GetTypeId() == TYPEID_PLAYER && ((Player*)taunter)->isGameMaster()))
9608 return;
9610 if(!CanHaveThreatList())
9611 return;
9613 Unit *target = getVictim();
9614 if(!target || target != taunter)
9615 return;
9617 if(m_ThreatManager.isThreatListEmpty())
9619 if(((Creature*)this)->AI())
9620 ((Creature*)this)->AI()->EnterEvadeMode();
9621 return;
9624 m_ThreatManager.tauntFadeOut(taunter);
9625 target = m_ThreatManager.getHostilTarget();
9627 if (target && target != taunter)
9629 SetInFront(target);
9630 if (((Creature*)this)->AI())
9631 ((Creature*)this)->AI()->AttackStart(target);
9635 //======================================================================
9637 bool Unit::SelectHostilTarget()
9639 //function provides main threat functionality
9640 //next-victim-selection algorithm and evade mode are called
9641 //threat list sorting etc.
9643 assert(GetTypeId()== TYPEID_UNIT);
9645 if (!this->isAlive())
9646 return false;
9647 //This function only useful once AI has been initialized
9648 if (!((Creature*)this)->AI())
9649 return false;
9651 Unit* target = NULL;
9653 // First checking if we have some taunt on us
9654 const AuraList& tauntAuras = GetAurasByType(SPELL_AURA_MOD_TAUNT);
9655 if ( !tauntAuras.empty() )
9657 Unit* caster;
9659 // The last taunt aura caster is alive an we are happy to attack him
9660 if ( (caster = tauntAuras.back()->GetCaster()) && caster->isAlive() )
9661 return true;
9662 else if (tauntAuras.size() > 1)
9664 // We do not have last taunt aura caster but we have more taunt auras,
9665 // so find first available target
9667 // Auras are pushed_back, last caster will be on the end
9668 AuraList::const_iterator aura = --tauntAuras.end();
9671 --aura;
9672 if ( (caster = (*aura)->GetCaster()) &&
9673 caster->IsInMap(this) && caster->isTargetableForAttack() && caster->isInAccessablePlaceFor((Creature*)this) )
9675 target = caster;
9676 break;
9678 }while (aura != tauntAuras.begin());
9682 if ( !target && !m_ThreatManager.isThreatListEmpty() )
9683 // No taunt aura or taunt aura caster is dead standart target selection
9684 target = m_ThreatManager.getHostilTarget();
9686 if(target)
9688 if(!hasUnitState(UNIT_STAT_STUNNED))
9689 SetInFront(target);
9690 ((Creature*)this)->AI()->AttackStart(target);
9691 return true;
9694 // no target but something prevent go to evade mode
9695 if( !isInCombat() || HasAuraType(SPELL_AURA_MOD_TAUNT) )
9696 return false;
9698 // last case when creature don't must go to evade mode:
9699 // it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
9700 // for example at owner command to pet attack some far away creature
9701 // Note: creature not have targeted movement generator but have attacker in this case
9702 if( GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE )
9704 for(AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)
9706 if( (*itr)->IsInMap(this) && (*itr)->isTargetableForAttack() && (*itr)->isInAccessablePlaceFor((Creature*)this) )
9707 return false;
9711 // enter in evade mode in other case
9712 ((Creature*)this)->AI()->EnterEvadeMode();
9714 return false;
9717 //======================================================================
9718 //======================================================================
9719 //======================================================================
9721 int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 effBasePoints, Unit const* target)
9723 Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL;
9725 uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0;
9727 int32 level = int32(getLevel());
9728 if (level > (int32)spellProto->maxLevel && spellProto->maxLevel > 0)
9729 level = (int32)spellProto->maxLevel;
9730 else if (level < (int32)spellProto->baseLevel)
9731 level = (int32)spellProto->baseLevel;
9732 level-= (int32)spellProto->spellLevel;
9734 float basePointsPerLevel = spellProto->EffectRealPointsPerLevel[effect_index];
9735 float randomPointsPerLevel = spellProto->EffectDicePerLevel[effect_index];
9736 int32 basePoints = int32(effBasePoints + level * basePointsPerLevel);
9737 int32 randomPoints = int32(spellProto->EffectDieSides[effect_index] + level * randomPointsPerLevel);
9738 float comboDamage = spellProto->EffectPointsPerComboPoint[effect_index];
9740 // range can have possitive and negative values, so order its for irand
9741 int32 randvalue = int32(spellProto->EffectBaseDice[effect_index]) >= randomPoints
9742 ? irand(randomPoints, int32(spellProto->EffectBaseDice[effect_index]))
9743 : irand(int32(spellProto->EffectBaseDice[effect_index]), randomPoints);
9745 int32 value = basePoints + randvalue;
9746 //random damage
9747 if(comboDamage != 0 && unitPlayer && target && (target->GetGUID() == unitPlayer->GetComboTarget()))
9748 value += (int32)(comboDamage * comboPoints);
9750 if(Player* modOwner = GetSpellModOwner())
9752 modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_ALL_EFFECTS, value);
9753 switch(effect_index)
9755 case 0:
9756 modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_EFFECT1, value);
9757 break;
9758 case 1:
9759 modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_EFFECT2, value);
9760 break;
9761 case 2:
9762 modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_EFFECT3, value);
9763 break;
9767 if(spellProto->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION && spellProto->spellLevel &&
9768 spellProto->Effect[effect_index] != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE &&
9769 spellProto->Effect[effect_index] != SPELL_EFFECT_KNOCK_BACK)
9770 value = int32(value*0.25f*exp(getLevel()*(70-spellProto->spellLevel)/1000.0f));
9772 return value;
9775 int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target)
9777 Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL;
9779 uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0;
9781 int32 minduration = GetSpellDuration(spellProto);
9782 int32 maxduration = GetSpellMaxDuration(spellProto);
9784 int32 duration;
9786 if( minduration != -1 && minduration != maxduration )
9787 duration = minduration + int32((maxduration - minduration) * comboPoints / 5);
9788 else
9789 duration = minduration;
9791 if (duration > 0)
9793 int32 mechanic = GetEffectMechanic(spellProto, effect_index);
9794 // Find total mod value (negative bonus)
9795 int32 durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, mechanic);
9796 // Modify from SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL aura (stack always ?)
9797 durationMod_always+=target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL, spellProto->Dispel);
9798 // Find max mod (negative bonus)
9799 int32 durationMod_not_stack = target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic);
9801 int32 durationMod = 0;
9802 // Select strongest negative mod
9803 if (durationMod_always > durationMod_not_stack)
9804 durationMod = durationMod_not_stack;
9805 else
9806 durationMod = durationMod_always;
9808 if (durationMod != 0)
9809 duration = int32(int64(duration) * (100+durationMod) /100);
9811 if (duration < 0) duration = 0;
9814 return duration;
9817 DiminishingLevels Unit::GetDiminishing(DiminishingGroup group)
9819 for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i)
9821 if(i->DRGroup != group)
9822 continue;
9824 if(!i->hitCount)
9825 return DIMINISHING_LEVEL_1;
9827 if(!i->hitTime)
9828 return DIMINISHING_LEVEL_1;
9830 // If last spell was casted more than 15 seconds ago - reset the count.
9831 if(i->stack==0 && getMSTimeDiff(i->hitTime,getMSTime()) > 15000)
9833 i->hitCount = DIMINISHING_LEVEL_1;
9834 return DIMINISHING_LEVEL_1;
9836 // or else increase the count.
9837 else
9839 return DiminishingLevels(i->hitCount);
9842 return DIMINISHING_LEVEL_1;
9845 void Unit::IncrDiminishing(DiminishingGroup group)
9847 // Checking for existing in the table
9848 for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i)
9850 if(i->DRGroup != group)
9851 continue;
9852 if(i->hitCount < DIMINISHING_LEVEL_IMMUNE)
9853 i->hitCount += 1;
9854 return;
9856 m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),DIMINISHING_LEVEL_2));
9859 void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster,DiminishingLevels Level)
9861 if(duration == -1 || group == DIMINISHING_NONE || caster->IsFriendlyTo(this) )
9862 return;
9864 // Duration of crowd control abilities on pvp target is limited by 10 sec. (2.2.0)
9865 if(duration > 10000 && IsDiminishingReturnsGroupDurationLimited(group))
9867 // test pet/charm masters instead pets/charmeds
9868 Unit const* targetOwner = GetCharmerOrOwner();
9869 Unit const* casterOwner = caster->GetCharmerOrOwner();
9871 Unit const* target = targetOwner ? targetOwner : this;
9872 Unit const* source = casterOwner ? casterOwner : caster;
9874 if(target->GetTypeId() == TYPEID_PLAYER && source->GetTypeId() == TYPEID_PLAYER)
9875 duration = 10000;
9878 float mod = 1.0f;
9880 // Some diminishings applies to mobs too (for example, Stun)
9881 if((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && GetTypeId() == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL)
9883 DiminishingLevels diminish = Level;
9884 switch(diminish)
9886 case DIMINISHING_LEVEL_1: break;
9887 case DIMINISHING_LEVEL_2: mod = 0.5f; break;
9888 case DIMINISHING_LEVEL_3: mod = 0.25f; break;
9889 case DIMINISHING_LEVEL_IMMUNE: mod = 0.0f;break;
9890 default: break;
9894 duration = int32(duration * mod);
9897 void Unit::ApplyDiminishingAura( DiminishingGroup group, bool apply )
9899 // Checking for existing in the table
9900 for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i)
9902 if(i->DRGroup != group)
9903 continue;
9905 if(apply)
9906 i->stack += 1;
9907 else if(i->stack)
9909 i->stack -= 1;
9910 // Remember time after last aura from group removed
9911 if (i->stack == 0)
9912 i->hitTime = getMSTime();
9914 break;
9918 Unit* Unit::GetUnit(WorldObject& object, uint64 guid)
9920 return ObjectAccessor::GetUnit(object,guid);
9923 bool Unit::isVisibleForInState( Player const* u, bool inVisibleList ) const
9925 return isVisibleForOrDetect(u, false, inVisibleList, false);
9928 uint32 Unit::GetCreatureType() const
9930 if(GetTypeId() == TYPEID_PLAYER)
9932 SpellShapeshiftEntry const* ssEntry = sSpellShapeshiftStore.LookupEntry(m_form);
9933 if(ssEntry && ssEntry->creatureType > 0)
9934 return ssEntry->creatureType;
9935 else
9936 return CREATURE_TYPE_HUMANOID;
9938 else
9939 return ((Creature*)this)->GetCreatureInfo()->type;
9942 /*#######################################
9943 ######## ########
9944 ######## STAT SYSTEM ########
9945 ######## ########
9946 #######################################*/
9948 bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply)
9950 if(unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END)
9952 sLog.outError("ERROR in HandleStatModifier(): non existed UnitMods or wrong UnitModifierType!");
9953 return false;
9956 float val = 1.0f;
9958 switch(modifierType)
9960 case BASE_VALUE:
9961 case TOTAL_VALUE:
9962 m_auraModifiersGroup[unitMod][modifierType] += apply ? amount : -amount;
9963 break;
9964 case BASE_PCT:
9965 case TOTAL_PCT:
9966 if(amount <= -100.0f) //small hack-fix for -100% modifiers
9967 amount = -200.0f;
9969 val = (100.0f + amount) / 100.0f;
9970 m_auraModifiersGroup[unitMod][modifierType] *= apply ? val : (1.0f/val);
9971 break;
9973 default:
9974 break;
9977 if(!CanModifyStats())
9978 return false;
9980 switch(unitMod)
9982 case UNIT_MOD_STAT_STRENGTH:
9983 case UNIT_MOD_STAT_AGILITY:
9984 case UNIT_MOD_STAT_STAMINA:
9985 case UNIT_MOD_STAT_INTELLECT:
9986 case UNIT_MOD_STAT_SPIRIT: UpdateStats(GetStatByAuraGroup(unitMod)); break;
9988 case UNIT_MOD_ARMOR: UpdateArmor(); break;
9989 case UNIT_MOD_HEALTH: UpdateMaxHealth(); break;
9991 case UNIT_MOD_MANA:
9992 case UNIT_MOD_RAGE:
9993 case UNIT_MOD_FOCUS:
9994 case UNIT_MOD_ENERGY:
9995 case UNIT_MOD_HAPPINESS:
9996 case UNIT_MOD_RUNE:
9997 case UNIT_MOD_RUNIC_POWER: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break;
9999 case UNIT_MOD_RESISTANCE_HOLY:
10000 case UNIT_MOD_RESISTANCE_FIRE:
10001 case UNIT_MOD_RESISTANCE_NATURE:
10002 case UNIT_MOD_RESISTANCE_FROST:
10003 case UNIT_MOD_RESISTANCE_SHADOW:
10004 case UNIT_MOD_RESISTANCE_ARCANE: UpdateResistances(GetSpellSchoolByAuraGroup(unitMod)); break;
10006 case UNIT_MOD_ATTACK_POWER: UpdateAttackPowerAndDamage(); break;
10007 case UNIT_MOD_ATTACK_POWER_RANGED: UpdateAttackPowerAndDamage(true); break;
10009 case UNIT_MOD_DAMAGE_MAINHAND: UpdateDamagePhysical(BASE_ATTACK); break;
10010 case UNIT_MOD_DAMAGE_OFFHAND: UpdateDamagePhysical(OFF_ATTACK); break;
10011 case UNIT_MOD_DAMAGE_RANGED: UpdateDamagePhysical(RANGED_ATTACK); break;
10013 default:
10014 break;
10017 return true;
10020 float Unit::GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const
10022 if( unitMod >= UNIT_MOD_END || modifierType >= MODIFIER_TYPE_END)
10024 sLog.outError("trial to access non existed modifier value from UnitMods!");
10025 return 0.0f;
10028 if(modifierType == TOTAL_PCT && m_auraModifiersGroup[unitMod][modifierType] <= 0.0f)
10029 return 0.0f;
10031 return m_auraModifiersGroup[unitMod][modifierType];
10034 float Unit::GetTotalStatValue(Stats stat) const
10036 UnitMods unitMod = UnitMods(UNIT_MOD_STAT_START + stat);
10038 if(m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
10039 return 0.0f;
10041 // value = ((base_value * base_pct) + total_value) * total_pct
10042 float value = m_auraModifiersGroup[unitMod][BASE_VALUE] + GetCreateStat(stat);
10043 value *= m_auraModifiersGroup[unitMod][BASE_PCT];
10044 value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
10045 value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
10047 return value;
10050 float Unit::GetTotalAuraModValue(UnitMods unitMod) const
10052 if(unitMod >= UNIT_MOD_END)
10054 sLog.outError("trial to access non existed UnitMods in GetTotalAuraModValue()!");
10055 return 0.0f;
10058 if(m_auraModifiersGroup[unitMod][TOTAL_PCT] <= 0.0f)
10059 return 0.0f;
10061 float value = m_auraModifiersGroup[unitMod][BASE_VALUE];
10062 value *= m_auraModifiersGroup[unitMod][BASE_PCT];
10063 value += m_auraModifiersGroup[unitMod][TOTAL_VALUE];
10064 value *= m_auraModifiersGroup[unitMod][TOTAL_PCT];
10066 return value;
10069 SpellSchools Unit::GetSpellSchoolByAuraGroup(UnitMods unitMod) const
10071 SpellSchools school = SPELL_SCHOOL_NORMAL;
10073 switch(unitMod)
10075 case UNIT_MOD_RESISTANCE_HOLY: school = SPELL_SCHOOL_HOLY; break;
10076 case UNIT_MOD_RESISTANCE_FIRE: school = SPELL_SCHOOL_FIRE; break;
10077 case UNIT_MOD_RESISTANCE_NATURE: school = SPELL_SCHOOL_NATURE; break;
10078 case UNIT_MOD_RESISTANCE_FROST: school = SPELL_SCHOOL_FROST; break;
10079 case UNIT_MOD_RESISTANCE_SHADOW: school = SPELL_SCHOOL_SHADOW; break;
10080 case UNIT_MOD_RESISTANCE_ARCANE: school = SPELL_SCHOOL_ARCANE; break;
10082 default:
10083 break;
10086 return school;
10089 Stats Unit::GetStatByAuraGroup(UnitMods unitMod) const
10091 Stats stat = STAT_STRENGTH;
10093 switch(unitMod)
10095 case UNIT_MOD_STAT_STRENGTH: stat = STAT_STRENGTH; break;
10096 case UNIT_MOD_STAT_AGILITY: stat = STAT_AGILITY; break;
10097 case UNIT_MOD_STAT_STAMINA: stat = STAT_STAMINA; break;
10098 case UNIT_MOD_STAT_INTELLECT: stat = STAT_INTELLECT; break;
10099 case UNIT_MOD_STAT_SPIRIT: stat = STAT_SPIRIT; break;
10101 default:
10102 break;
10105 return stat;
10108 Powers Unit::GetPowerTypeByAuraGroup(UnitMods unitMod) const
10110 switch(unitMod)
10112 case UNIT_MOD_MANA: return POWER_MANA;
10113 case UNIT_MOD_RAGE: return POWER_RAGE;
10114 case UNIT_MOD_FOCUS: return POWER_FOCUS;
10115 case UNIT_MOD_ENERGY: return POWER_ENERGY;
10116 case UNIT_MOD_HAPPINESS: return POWER_HAPPINESS;
10117 case UNIT_MOD_RUNE: return POWER_RUNE;
10118 case UNIT_MOD_RUNIC_POWER:return POWER_RUNIC_POWER;
10119 default: return POWER_MANA;
10122 return POWER_MANA;
10125 float Unit::GetTotalAttackPowerValue(WeaponAttackType attType) const
10127 if (attType == RANGED_ATTACK)
10129 int32 ap = GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER) + GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS);
10130 if (ap < 0)
10131 return 0.0f;
10132 return ap * (1.0f + GetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER));
10134 else
10136 int32 ap = GetInt32Value(UNIT_FIELD_ATTACK_POWER) + GetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS);
10137 if (ap < 0)
10138 return 0.0f;
10139 return ap * (1.0f + GetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER));
10143 float Unit::GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const
10145 if (attType == OFF_ATTACK && !haveOffhandWeapon())
10146 return 0.0f;
10148 return m_weaponDamage[attType][type];
10151 void Unit::SetLevel(uint32 lvl)
10153 SetUInt32Value(UNIT_FIELD_LEVEL, lvl);
10155 // group update
10156 if ((GetTypeId() == TYPEID_PLAYER) && ((Player*)this)->GetGroup())
10157 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL);
10160 void Unit::SetHealth(uint32 val)
10162 uint32 maxHealth = GetMaxHealth();
10163 if(maxHealth < val)
10164 val = maxHealth;
10166 SetUInt32Value(UNIT_FIELD_HEALTH, val);
10168 // group update
10169 if(GetTypeId() == TYPEID_PLAYER)
10171 if(((Player*)this)->GetGroup())
10172 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_HP);
10174 else if(((Creature*)this)->isPet())
10176 Pet *pet = ((Pet*)this);
10177 if(pet->isControlled())
10179 Unit *owner = GetOwner();
10180 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
10181 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_HP);
10186 void Unit::SetMaxHealth(uint32 val)
10188 uint32 health = GetHealth();
10189 SetUInt32Value(UNIT_FIELD_MAXHEALTH, val);
10191 // group update
10192 if(GetTypeId() == TYPEID_PLAYER)
10194 if(((Player*)this)->GetGroup())
10195 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_HP);
10197 else if(((Creature*)this)->isPet())
10199 Pet *pet = ((Pet*)this);
10200 if(pet->isControlled())
10202 Unit *owner = GetOwner();
10203 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
10204 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_HP);
10208 if(val < health)
10209 SetHealth(val);
10212 void Unit::SetPower(Powers power, uint32 val)
10214 if(GetPower(power) == val)
10215 return;
10217 uint32 maxPower = GetMaxPower(power);
10218 if(maxPower < val)
10219 val = maxPower;
10221 SetStatInt32Value(UNIT_FIELD_POWER1 + power, val);
10223 WorldPacket data(SMSG_POWER_UPDATE);
10224 data.append(GetPackGUID());
10225 data << uint8(power);
10226 data << uint32(val);
10227 SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER ? true : false);
10229 // group update
10230 if(GetTypeId() == TYPEID_PLAYER)
10232 if(((Player*)this)->GetGroup())
10233 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER);
10235 else if(((Creature*)this)->isPet())
10237 Pet *pet = ((Pet*)this);
10238 if(pet->isControlled())
10240 Unit *owner = GetOwner();
10241 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
10242 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
10245 // Update the pet's character sheet with happiness damage bonus
10246 if(pet->getPetType() == HUNTER_PET && power == POWER_HAPPINESS)
10248 pet->UpdateDamagePhysical(BASE_ATTACK);
10253 void Unit::SetMaxPower(Powers power, uint32 val)
10255 uint32 cur_power = GetPower(power);
10256 SetStatInt32Value(UNIT_FIELD_MAXPOWER1 + power, val);
10258 // group update
10259 if(GetTypeId() == TYPEID_PLAYER)
10261 if(((Player*)this)->GetGroup())
10262 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER);
10264 else if(((Creature*)this)->isPet())
10266 Pet *pet = ((Pet*)this);
10267 if(pet->isControlled())
10269 Unit *owner = GetOwner();
10270 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
10271 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
10275 if(val < cur_power)
10276 SetPower(power, val);
10279 void Unit::ApplyPowerMod(Powers power, uint32 val, bool apply)
10281 ApplyModUInt32Value(UNIT_FIELD_POWER1+power, val, apply);
10283 // group update
10284 if(GetTypeId() == TYPEID_PLAYER)
10286 if(((Player*)this)->GetGroup())
10287 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_CUR_POWER);
10289 else if(((Creature*)this)->isPet())
10291 Pet *pet = ((Pet*)this);
10292 if(pet->isControlled())
10294 Unit *owner = GetOwner();
10295 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
10296 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
10301 void Unit::ApplyMaxPowerMod(Powers power, uint32 val, bool apply)
10303 ApplyModUInt32Value(UNIT_FIELD_MAXPOWER1+power, val, apply);
10305 // group update
10306 if(GetTypeId() == TYPEID_PLAYER)
10308 if(((Player*)this)->GetGroup())
10309 ((Player*)this)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_MAX_POWER);
10311 else if(((Creature*)this)->isPet())
10313 Pet *pet = ((Pet*)this);
10314 if(pet->isControlled())
10316 Unit *owner = GetOwner();
10317 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
10318 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MAX_POWER);
10323 void Unit::ApplyAuraProcTriggerDamage( Aura* aura, bool apply )
10325 AuraList& tAuraProcTriggerDamage = m_modAuras[SPELL_AURA_PROC_TRIGGER_DAMAGE];
10326 if(apply)
10327 tAuraProcTriggerDamage.push_back(aura);
10328 else
10329 tAuraProcTriggerDamage.remove(aura);
10332 uint32 Unit::GetCreatePowers( Powers power ) const
10334 // POWER_FOCUS and POWER_HAPPINESS only have hunter pet
10335 switch(power)
10337 case POWER_MANA: return GetCreateMana();
10338 case POWER_RAGE: return 1000;
10339 case POWER_FOCUS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 100);
10340 case POWER_ENERGY: return 100;
10341 case POWER_HAPPINESS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 1050000);
10342 case POWER_RUNIC_POWER: return 1000;
10343 case POWER_RUNE: return 0;
10344 case POWER_HEALTH: return 0;
10347 return 0;
10350 void Unit::AddToWorld()
10352 Object::AddToWorld();
10355 void Unit::RemoveFromWorld()
10357 // cleanup
10358 if(IsInWorld())
10360 RemoveNotOwnSingleTargetAuras();
10361 RemoveGuardians();
10364 Object::RemoveFromWorld();
10367 void Unit::CleanupsBeforeDelete()
10369 if(m_uint32Values) // only for fully created object
10371 InterruptNonMeleeSpells(true);
10372 m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
10373 CombatStop();
10374 ClearComboPointHolders();
10375 DeleteThreatList();
10376 getHostilRefManager().setOnlineOfflineState(false);
10377 RemoveAllAuras();
10378 RemoveAllGameObjects();
10379 RemoveAllDynObjects();
10380 GetMotionMaster()->Clear(false); // remove different non-standard movement generators.
10382 RemoveFromWorld();
10385 CharmInfo* Unit::InitCharmInfo(Unit *charm)
10387 if(!m_charmInfo)
10388 m_charmInfo = new CharmInfo(charm);
10389 return m_charmInfo;
10392 CharmInfo::CharmInfo(Unit* unit)
10393 : m_unit(unit), m_CommandState(COMMAND_FOLLOW), m_reactState(REACT_PASSIVE), m_petnumber(0)
10395 for(int i =0; i<4; ++i)
10397 m_charmspells[i].spellId = 0;
10398 m_charmspells[i].active = ACT_DISABLED;
10402 void CharmInfo::InitPetActionBar()
10404 // the first 3 SpellOrActions are attack, follow and stay
10405 for(uint32 i = 0; i < ACTION_BAR_INDEX_PET_SPELL_START - ACTION_BAR_INDEX_START; ++i)
10406 SetActionBar(ACTION_BAR_INDEX_START + i,COMMAND_ATTACK - i,ACT_COMMAND);
10408 // middle 4 SpellOrActions are spells/special attacks/abilities
10409 for(uint32 i = 0; i < ACTION_BAR_INDEX_PET_SPELL_END-ACTION_BAR_INDEX_PET_SPELL_START; ++i)
10410 SetActionBar(ACTION_BAR_INDEX_PET_SPELL_START + i,0,ACT_DISABLED);
10412 // last 3 SpellOrActions are reactions
10413 for(uint32 i = 0; i < ACTION_BAR_INDEX_END - ACTION_BAR_INDEX_PET_SPELL_END; ++i)
10414 SetActionBar(ACTION_BAR_INDEX_PET_SPELL_END + i,COMMAND_ATTACK - i,ACT_REACTION);
10417 void CharmInfo::InitEmptyActionBar()
10419 SetActionBar(ACTION_BAR_INDEX_START,COMMAND_ATTACK,ACT_COMMAND);
10420 for(uint32 x = ACTION_BAR_INDEX_START+1; x < ACTION_BAR_INDEX_END; ++x)
10421 SetActionBar(x,0,ACT_PASSIVE);
10424 void CharmInfo::InitPossessCreateSpells()
10426 InitEmptyActionBar(); //charm action bar
10428 if(m_unit->GetTypeId() == TYPEID_PLAYER) //possessed players don't have spells, keep the action bar empty
10429 return;
10431 for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x)
10433 if (IsPassiveSpell(((Creature*)m_unit)->m_spells[x]))
10434 m_unit->CastSpell(m_unit, ((Creature*)m_unit)->m_spells[x], true);
10435 else
10436 AddSpellToActionBar(((Creature*)m_unit)->m_spells[x], ACT_PASSIVE);
10440 void CharmInfo::InitCharmCreateSpells()
10442 if(m_unit->GetTypeId() == TYPEID_PLAYER) //charmed players don't have spells
10444 InitEmptyActionBar();
10445 return;
10448 InitPetActionBar();
10450 for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x)
10452 uint32 spellId = ((Creature*)m_unit)->m_spells[x];
10453 m_charmspells[x].spellId = spellId;
10455 if(!spellId)
10456 continue;
10458 if (IsPassiveSpell(spellId))
10460 m_unit->CastSpell(m_unit, spellId, true);
10461 m_charmspells[x].active = ACT_PASSIVE;
10463 else
10465 ActiveStates newstate;
10466 bool onlyselfcast = true;
10467 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
10469 if(!spellInfo) onlyselfcast = false;
10470 for(uint32 i = 0;i<3 && onlyselfcast;++i) //non existent spell will not make any problems as onlyselfcast would be false -> break right away
10472 if(spellInfo->EffectImplicitTargetA[i] != TARGET_SELF && spellInfo->EffectImplicitTargetA[i] != 0)
10473 onlyselfcast = false;
10476 if(onlyselfcast || !IsPositiveSpell(spellId)) //only self cast and spells versus enemies are autocastable
10477 newstate = ACT_DISABLED;
10478 else
10479 newstate = ACT_PASSIVE;
10481 AddSpellToActionBar(spellId, newstate);
10486 bool CharmInfo::AddSpellToActionBar(uint32 spell_id, ActiveStates newstate)
10488 uint32 first_id = spellmgr.GetFirstSpellInChain(spell_id);
10490 // new spell rank can be already listed
10491 for(uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
10493 if (PetActionBar[i].SpellOrAction && PetActionBar[i].IsActionBarForSpell())
10495 if (spellmgr.GetFirstSpellInChain(PetActionBar[i].SpellOrAction) == first_id)
10497 PetActionBar[i].SpellOrAction = spell_id;
10498 return true;
10503 // or use empty slot in other case
10504 for(uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
10506 if (!PetActionBar[i].SpellOrAction && PetActionBar[i].IsActionBarForSpell())
10508 SetActionBar(i,spell_id,newstate == ACT_DECIDE ? ACT_DISABLED : newstate);
10509 return true;
10512 return false;
10515 bool CharmInfo::RemoveSpellFromActionBar(uint32 spell_id)
10517 uint32 first_id = spellmgr.GetFirstSpellInChain(spell_id);
10519 for(uint8 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
10521 if (PetActionBar[i].SpellOrAction && PetActionBar[i].IsActionBarForSpell())
10523 if (spellmgr.GetFirstSpellInChain(PetActionBar[i].SpellOrAction) == first_id)
10525 SetActionBar(i,0,ACT_DISABLED);
10526 return true;
10531 return false;
10534 void CharmInfo::ToggleCreatureAutocast(uint32 spellid, bool apply)
10536 if(IsPassiveSpell(spellid))
10537 return;
10539 for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x)
10541 if(spellid == m_charmspells[x].spellId)
10543 m_charmspells[x].active = apply ? ACT_ENABLED : ACT_DISABLED;
10548 void CharmInfo::SetPetNumber(uint32 petnumber, bool statwindow)
10550 m_petnumber = petnumber;
10551 if(statwindow)
10552 m_unit->SetUInt32Value(UNIT_FIELD_PETNUMBER, m_petnumber);
10553 else
10554 m_unit->SetUInt32Value(UNIT_FIELD_PETNUMBER, 0);
10557 void CharmInfo::LoadPetActionBar(const std::string& data )
10559 InitPetActionBar();
10561 Tokens tokens = StrSplit(data, " ");
10563 if (tokens.size() != (ACTION_BAR_INDEX_PET_SPELL_END-ACTION_BAR_INDEX_PET_SPELL_START)*2)
10564 return; // non critical, will reset to default
10566 int index;
10567 Tokens::iterator iter;
10568 for(iter = tokens.begin(), index = ACTION_BAR_INDEX_PET_SPELL_START; index < ACTION_BAR_INDEX_PET_SPELL_END; ++iter, ++index )
10570 // use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion
10571 PetActionBar[index].Type = atol((*iter).c_str());
10572 ++iter;
10573 PetActionBar[index].SpellOrAction = atol((*iter).c_str());
10575 // check correctness
10576 if(PetActionBar[index].IsActionBarForSpell() && !sSpellStore.LookupEntry(PetActionBar[index].SpellOrAction))
10577 SetActionBar(index,0,ACT_DISABLED);
10581 void CharmInfo::BuildActionBar( WorldPacket* data )
10583 for(uint32 i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
10585 *data << uint16(PetActionBar[i].SpellOrAction);
10586 *data << uint16(PetActionBar[i].Type);
10590 void CharmInfo::SetSpellAutocast( uint32 spell_id, bool state )
10592 for(int i = 0; i < MAX_UNIT_ACTION_BAR_INDEX; ++i)
10594 if(spell_id == PetActionBar[i].SpellOrAction && PetActionBar[i].IsActionBarForSpell())
10596 PetActionBar[i].Type = state ? ACT_ENABLED : ACT_DISABLED;
10597 break;
10602 bool Unit::isFrozen() const
10604 return HasAuraState(AURA_STATE_FROZEN);
10607 struct ProcTriggeredData
10609 ProcTriggeredData(SpellProcEventEntry const * _spellProcEvent, Aura* _triggeredByAura)
10610 : spellProcEvent(_spellProcEvent), triggeredByAura(_triggeredByAura),
10611 triggeredByAura_SpellPair(Unit::spellEffectPair(triggeredByAura->GetId(),triggeredByAura->GetEffIndex()))
10613 SpellProcEventEntry const *spellProcEvent;
10614 Aura* triggeredByAura;
10615 Unit::spellEffectPair triggeredByAura_SpellPair;
10618 typedef std::list< ProcTriggeredData > ProcTriggeredList;
10619 typedef std::list< uint32> RemoveSpellList;
10621 // List of auras that CAN be trigger but may not exist in spell_proc_event
10622 // in most case need for drop charges
10623 // in some types of aura need do additional check
10624 // for example SPELL_AURA_MECHANIC_IMMUNITY - need check for mechanic
10625 bool InitTriggerAuraData()
10627 for (int i=0;i<TOTAL_AURAS;++i)
10629 isTriggerAura[i]=false;
10630 isNonTriggerAura[i] = false;
10632 isTriggerAura[SPELL_AURA_DUMMY] = true;
10633 isTriggerAura[SPELL_AURA_MOD_CONFUSE] = true;
10634 isTriggerAura[SPELL_AURA_MOD_THREAT] = true;
10635 isTriggerAura[SPELL_AURA_MOD_STUN] = true; // Aura not have charges but need remove him on trigger
10636 isTriggerAura[SPELL_AURA_MOD_DAMAGE_DONE] = true;
10637 isTriggerAura[SPELL_AURA_MOD_DAMAGE_TAKEN] = true;
10638 isTriggerAura[SPELL_AURA_MOD_RESISTANCE] = true;
10639 isTriggerAura[SPELL_AURA_MOD_ROOT] = true;
10640 isTriggerAura[SPELL_AURA_REFLECT_SPELLS] = true;
10641 isTriggerAura[SPELL_AURA_DAMAGE_IMMUNITY] = true;
10642 isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL] = true;
10643 isTriggerAura[SPELL_AURA_PROC_TRIGGER_DAMAGE] = true;
10644 isTriggerAura[SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK] = true;
10645 isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT] = true;
10646 isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL] = true;
10647 isTriggerAura[SPELL_AURA_REFLECT_SPELLS_SCHOOL] = true;
10648 isTriggerAura[SPELL_AURA_MECHANIC_IMMUNITY] = true;
10649 isTriggerAura[SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN] = true;
10650 isTriggerAura[SPELL_AURA_SPELL_MAGNET] = true;
10651 isTriggerAura[SPELL_AURA_MOD_ATTACK_POWER] = true;
10652 isTriggerAura[SPELL_AURA_ADD_CASTER_HIT_TRIGGER] = true;
10653 isTriggerAura[SPELL_AURA_OVERRIDE_CLASS_SCRIPTS] = true;
10654 isTriggerAura[SPELL_AURA_MOD_MECHANIC_RESISTANCE] = true;
10655 isTriggerAura[SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS] = true;
10656 isTriggerAura[SPELL_AURA_MOD_HASTE] = true;
10657 isTriggerAura[SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE]=true;
10658 isTriggerAura[SPELL_AURA_PRAYER_OF_MENDING] = true;
10659 isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true;
10660 isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true;
10661 isTriggerAura[SPELL_AURA_MOD_SPELL_CRIT_CHANCE] = true;
10663 isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN]=true;
10664 isNonTriggerAura[SPELL_AURA_REDUCE_PUSHBACK]=true;
10666 return true;
10669 uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition)
10671 uint32 procEx = PROC_EX_NONE;
10672 // Check victim state
10673 if (missCondition!=SPELL_MISS_NONE)
10674 switch (missCondition)
10676 case SPELL_MISS_MISS: procEx|=PROC_EX_MISS; break;
10677 case SPELL_MISS_RESIST: procEx|=PROC_EX_RESIST; break;
10678 case SPELL_MISS_DODGE: procEx|=PROC_EX_DODGE; break;
10679 case SPELL_MISS_PARRY: procEx|=PROC_EX_PARRY; break;
10680 case SPELL_MISS_BLOCK: procEx|=PROC_EX_BLOCK; break;
10681 case SPELL_MISS_EVADE: procEx|=PROC_EX_EVADE; break;
10682 case SPELL_MISS_IMMUNE: procEx|=PROC_EX_IMMUNE; break;
10683 case SPELL_MISS_IMMUNE2: procEx|=PROC_EX_IMMUNE; break;
10684 case SPELL_MISS_DEFLECT: procEx|=PROC_EX_DEFLECT;break;
10685 case SPELL_MISS_ABSORB: procEx|=PROC_EX_ABSORB; break;
10686 case SPELL_MISS_REFLECT: procEx|=PROC_EX_REFLECT;break;
10687 default:
10688 break;
10690 else
10692 // On block
10693 if (damageInfo->blocked)
10694 procEx|=PROC_EX_BLOCK;
10695 // On absorb
10696 if (damageInfo->absorb)
10697 procEx|=PROC_EX_ABSORB;
10698 // On crit
10699 if (damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT)
10700 procEx|=PROC_EX_CRITICAL_HIT;
10701 else
10702 procEx|=PROC_EX_NORMAL_HIT;
10704 return procEx;
10707 void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage )
10709 // For melee/ranged based attack need update skills and set some Aura states
10710 if (procFlag & MELEE_BASED_TRIGGER_MASK)
10712 // Update skills here for players
10713 if (GetTypeId() == TYPEID_PLAYER)
10715 // On melee based hit/miss/resist need update skill (for victim and attacker)
10716 if (procExtra&(PROC_EX_NORMAL_HIT|PROC_EX_MISS|PROC_EX_RESIST))
10718 if (pTarget->GetTypeId() != TYPEID_PLAYER && pTarget->GetCreatureType() != CREATURE_TYPE_CRITTER)
10719 ((Player*)this)->UpdateCombatSkills(pTarget, attType, isVictim);
10721 // Update defence if player is victim and parry/dodge/block
10722 if (isVictim && procExtra&(PROC_EX_DODGE|PROC_EX_PARRY|PROC_EX_BLOCK))
10723 ((Player*)this)->UpdateDefense();
10725 // If exist crit/parry/dodge/block need update aura state (for victim and attacker)
10726 if (procExtra & (PROC_EX_CRITICAL_HIT|PROC_EX_PARRY|PROC_EX_DODGE|PROC_EX_BLOCK))
10728 // for victim
10729 if (isVictim)
10731 // if victim and dodge attack
10732 if (procExtra&PROC_EX_DODGE)
10734 //Update AURA_STATE on dodge
10735 if (getClass() != CLASS_ROGUE) // skip Rogue Riposte
10737 ModifyAuraState(AURA_STATE_DEFENSE, true);
10738 StartReactiveTimer( REACTIVE_DEFENSE );
10741 // if victim and parry attack
10742 if (procExtra & PROC_EX_PARRY)
10744 // For Hunters only Counterattack (skip Mongoose bite)
10745 if (getClass() == CLASS_HUNTER)
10747 ModifyAuraState(AURA_STATE_HUNTER_PARRY, true);
10748 StartReactiveTimer( REACTIVE_HUNTER_PARRY );
10750 else
10752 ModifyAuraState(AURA_STATE_DEFENSE, true);
10753 StartReactiveTimer( REACTIVE_DEFENSE );
10756 // if and victim block attack
10757 if (procExtra & PROC_EX_BLOCK)
10759 ModifyAuraState(AURA_STATE_DEFENSE,true);
10760 StartReactiveTimer( REACTIVE_DEFENSE );
10763 else //For attacker
10765 // Overpower on victim dodge
10766 if (procExtra&PROC_EX_DODGE && GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)
10768 ((Player*)this)->AddComboPoints(pTarget, 1);
10769 StartReactiveTimer( REACTIVE_OVERPOWER );
10775 RemoveSpellList removedSpells;
10776 ProcTriggeredList procTriggered;
10777 // Fill procTriggered list
10778 for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr)
10780 SpellProcEventEntry const* spellProcEvent = NULL;
10781 if(!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent))
10782 continue;
10784 procTriggered.push_back( ProcTriggeredData(spellProcEvent, itr->second) );
10787 // Nothing found
10788 if (procTriggered.empty())
10789 return;
10791 // Handle effects proceed this time
10792 for(ProcTriggeredList::const_iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)
10794 // Some auras can be deleted in function called in this loop (except first, ofc)
10795 // Until storing auars in std::multimap to hard check deleting by another way
10796 if(i != procTriggered.begin())
10798 bool found = false;
10799 AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair);
10800 AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);
10801 for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)
10803 if(itr->second==i->triggeredByAura)
10805 found = true;
10806 break;
10809 if(!found)
10811 // sLog.outDebug("Spell aura %u (id:%u effect:%u) has been deleted before call spell proc event handler", i->triggeredByAura->GetModifier()->m_auraname, i->triggeredByAura_SpellPair.first, i->triggeredByAura_SpellPair.second);
10812 // sLog.outDebug("It can be deleted one from early proccesed auras:");
10813 // for(ProcTriggeredList::const_iterator i2 = procTriggered.begin(); i != i2; ++i2)
10814 // sLog.outDebug(" Spell aura %u (id:%u effect:%u)", i->triggeredByAura->GetModifier()->m_auraname,i2->triggeredByAura_SpellPair.first,i2->triggeredByAura_SpellPair.second);
10815 // sLog.outDebug(" <end of list>");
10816 continue;
10820 SpellProcEventEntry const *spellProcEvent = i->spellProcEvent;
10821 Aura *triggeredByAura = i->triggeredByAura;
10822 Modifier *auraModifier = triggeredByAura->GetModifier();
10823 SpellEntry const *spellInfo = triggeredByAura->GetSpellProto();
10824 bool useCharges = triggeredByAura->GetAuraCharges() > 0;
10825 // For players set spell cooldown if need
10826 uint32 cooldown = 0;
10827 if (GetTypeId() == TYPEID_PLAYER && spellProcEvent && spellProcEvent->cooldown)
10828 cooldown = spellProcEvent->cooldown;
10830 switch(auraModifier->m_auraname)
10832 case SPELL_AURA_PROC_TRIGGER_SPELL:
10834 sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
10835 // Don`t drop charge or add cooldown for not started trigger
10836 if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
10837 continue;
10838 break;
10840 case SPELL_AURA_PROC_TRIGGER_DAMAGE:
10842 sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", auraModifier->m_amount, spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
10843 SpellNonMeleeDamage damageInfo(this, pTarget, spellInfo->Id, spellInfo->SchoolMask);
10844 CalculateSpellDamage(&damageInfo, auraModifier->m_amount, spellInfo);
10845 DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
10846 SendSpellNonMeleeDamageLog(&damageInfo);
10847 DealSpellDamage(&damageInfo, true);
10848 break;
10850 case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
10851 case SPELL_AURA_MANA_SHIELD:
10852 case SPELL_AURA_OBS_MOD_MANA:
10853 case SPELL_AURA_DUMMY:
10855 sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
10856 if (!HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
10857 continue;
10858 break;
10860 case SPELL_AURA_MOD_HASTE:
10862 sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
10863 if (!HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
10864 continue;
10865 break;
10867 case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
10869 sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
10870 if (!HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown))
10871 continue;
10872 break;
10874 case SPELL_AURA_PRAYER_OF_MENDING:
10876 sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
10877 (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
10879 HandleMeandingAuraProc(triggeredByAura);
10880 break;
10882 case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE:
10884 sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
10886 if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown))
10887 continue;
10888 break;
10890 case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK:
10891 // Skip melee hits or instant cast spells
10892 if (procSpell == NULL || GetSpellCastTime(procSpell) == 0)
10893 continue;
10894 break;
10895 case SPELL_AURA_REFLECT_SPELLS_SCHOOL:
10896 // Skip Melee hits and spells ws wrong school
10897 if (procSpell == NULL || (auraModifier->m_miscvalue & procSpell->SchoolMask) == 0)
10898 continue;
10899 break;
10900 case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT:
10901 case SPELL_AURA_MOD_POWER_COST_SCHOOL:
10902 // Skip melee hits and spells ws wrong school or zero cost
10903 if (procSpell == NULL ||
10904 (procSpell->manaCost == 0 && procSpell->ManaCostPercentage == 0) || // Cost check
10905 (auraModifier->m_miscvalue & procSpell->SchoolMask) == 0) // School check
10906 continue;
10907 break;
10908 case SPELL_AURA_MECHANIC_IMMUNITY:
10909 // Compare mechanic
10910 if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)
10911 continue;
10912 break;
10913 case SPELL_AURA_MOD_MECHANIC_RESISTANCE:
10914 // Compare mechanic
10915 if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)
10916 continue;
10917 break;
10918 case SPELL_AURA_MOD_DAMAGE_FROM_CASTER:
10919 // Compare casters
10920 if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID())
10921 continue;
10922 break;
10923 default:
10924 // nothing do, just charges counter
10925 break;
10927 // Remove charge (aura can be removed by triggers)
10928 if(useCharges)
10930 // need found aura on drop (can be dropped by triggers)
10931 AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair);
10932 AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);
10933 for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)
10935 // If last charge dropped add spell to remove list
10936 if(itr->second == i->triggeredByAura && triggeredByAura->DropAuraCharge())
10938 removedSpells.push_back(triggeredByAura->GetId());
10939 break;
10944 if (!removedSpells.empty())
10946 // Sort spells and remove dublicates
10947 removedSpells.sort();
10948 removedSpells.unique();
10949 // Remove auras from removedAuras
10950 for(RemoveSpellList::const_iterator i = removedSpells.begin(); i != removedSpells.end();++i)
10951 RemoveAurasDueToSpell(*i);
10955 SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const
10957 return SPELL_SCHOOL_MASK_NORMAL;
10960 Player* Unit::GetSpellModOwner()
10962 if(GetTypeId()==TYPEID_PLAYER)
10963 return (Player*)this;
10964 if(((Creature*)this)->isPet() || ((Creature*)this)->isTotem())
10966 Unit* owner = GetOwner();
10967 if(owner && owner->GetTypeId()==TYPEID_PLAYER)
10968 return (Player*)owner;
10970 return NULL;
10973 ///----------Pet responses methods-----------------
10974 void Unit::SendPetCastFail(uint32 spellid, SpellCastResult msg)
10976 if(msg == SPELL_CAST_OK)
10977 return;
10979 Unit *owner = GetCharmerOrOwner();
10980 if(!owner || owner->GetTypeId() != TYPEID_PLAYER)
10981 return;
10983 WorldPacket data(SMSG_PET_CAST_FAILED, 1 + 4 + 1);
10984 data << uint8(0); // cast count?
10985 data << uint32(spellid);
10986 data << uint8(msg);
10987 // uint32 for some reason
10988 // uint32 for some reason
10989 ((Player*)owner)->GetSession()->SendPacket(&data);
10992 void Unit::SendPetActionFeedback (uint8 msg)
10994 Unit* owner = GetOwner();
10995 if(!owner || owner->GetTypeId() != TYPEID_PLAYER)
10996 return;
10998 WorldPacket data(SMSG_PET_ACTION_FEEDBACK, 1);
10999 data << uint8(msg);
11000 ((Player*)owner)->GetSession()->SendPacket(&data);
11003 void Unit::SendPetTalk (uint32 pettalk)
11005 Unit* owner = GetOwner();
11006 if(!owner || owner->GetTypeId() != TYPEID_PLAYER)
11007 return;
11009 WorldPacket data(SMSG_PET_ACTION_SOUND, 8 + 4);
11010 data << uint64(GetGUID());
11011 data << uint32(pettalk);
11012 ((Player*)owner)->GetSession()->SendPacket(&data);
11015 void Unit::SendPetSpellCooldown (uint32 spellid, time_t cooltime)
11017 Unit* owner = GetOwner();
11018 if(!owner || owner->GetTypeId() != TYPEID_PLAYER)
11019 return;
11021 WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+4+4);
11022 data << uint64(GetGUID());
11023 data << uint8(0x0); // flags (0x1, 0x2)
11024 data << uint32(spellid);
11025 data << uint32(cooltime);
11027 ((Player*)owner)->GetSession()->SendPacket(&data);
11030 void Unit::SendPetClearCooldown (uint32 spellid)
11032 Unit* owner = GetOwner();
11033 if(!owner || owner->GetTypeId() != TYPEID_PLAYER)
11034 return;
11036 WorldPacket data(SMSG_CLEAR_COOLDOWN, 4+8);
11037 data << uint32(spellid);
11038 data << uint64(GetGUID());
11039 ((Player*)owner)->GetSession()->SendPacket(&data);
11042 void Unit::SendPetAIReaction(uint64 guid)
11044 Unit* owner = GetOwner();
11045 if(!owner || owner->GetTypeId() != TYPEID_PLAYER)
11046 return;
11048 WorldPacket data(SMSG_AI_REACTION, 8 + 4);
11049 data << uint64(guid);
11050 data << uint32(AI_REACTION_AGGRO);
11051 ((Player*)owner)->GetSession()->SendPacket(&data);
11054 ///----------End of Pet responses methods----------
11056 void Unit::StopMoving()
11058 clearUnitState(UNIT_STAT_MOVING);
11060 // send explicit stop packet
11061 // rely on vmaps here because for example stormwind is in air
11062 //float z = MapManager::Instance().GetBaseMap(GetMapId())->GetHeight(GetPositionX(), GetPositionY(), GetPositionZ(), true);
11063 //if (fabs(GetPositionZ() - z) < 2.0f)
11064 // Relocate(GetPositionX(), GetPositionY(), z);
11065 Relocate(GetPositionX(), GetPositionY(),GetPositionZ());
11067 SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), 0, 0, 0);
11069 // update position and orientation;
11070 WorldPacket data;
11071 BuildHeartBeatMsg(&data);
11072 SendMessageToSet(&data,false);
11075 void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID, uint32 time)
11077 if( apply )
11079 if(HasAuraType(SPELL_AURA_PREVENTS_FLEEING))
11080 return;
11082 SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
11084 GetMotionMaster()->MovementExpired(false);
11085 CastStop(GetGUID()==casterGUID ? spellID : 0);
11087 Unit* caster = ObjectAccessor::GetUnit(*this,casterGUID);
11089 GetMotionMaster()->MoveFleeing(caster, time); // caster==NULL processed in MoveFleeing
11091 else
11093 RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
11095 GetMotionMaster()->MovementExpired(false);
11097 if( GetTypeId() != TYPEID_PLAYER && isAlive() )
11099 // restore appropriate movement generator
11100 if(getVictim())
11101 GetMotionMaster()->MoveChase(getVictim());
11102 else
11103 GetMotionMaster()->Initialize();
11105 // attack caster if can
11106 Unit* caster = ObjectAccessor::GetObjectInWorld(casterGUID, (Unit*)NULL);
11107 if(caster && ((Creature*)this)->AI())
11108 ((Creature*)this)->AI()->AttackedBy(caster);
11112 if (GetTypeId() == TYPEID_PLAYER)
11113 ((Player*)this)->SetClientControl(this, !apply);
11116 void Unit::SetConfused(bool apply, uint64 casterGUID, uint32 spellID)
11118 if( apply )
11120 SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
11122 CastStop(GetGUID()==casterGUID ? spellID : 0);
11124 GetMotionMaster()->MoveConfused();
11126 else
11128 RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
11130 GetMotionMaster()->MovementExpired(false);
11132 if (GetTypeId() == TYPEID_UNIT)
11134 // if in combat restore movement generator
11135 if(getVictim())
11136 GetMotionMaster()->MoveChase(getVictim());
11140 if(GetTypeId() == TYPEID_PLAYER)
11141 ((Player*)this)->SetClientControl(this, !apply);
11144 bool Unit::IsSitState() const
11146 uint8 s = getStandState();
11147 return
11148 s == UNIT_STAND_STATE_SIT_CHAIR || s == UNIT_STAND_STATE_SIT_LOW_CHAIR ||
11149 s == UNIT_STAND_STATE_SIT_MEDIUM_CHAIR || s == UNIT_STAND_STATE_SIT_HIGH_CHAIR ||
11150 s == UNIT_STAND_STATE_SIT;
11153 bool Unit::IsStandState() const
11155 uint8 s = getStandState();
11156 return !IsSitState() && s != UNIT_STAND_STATE_SLEEP && s != UNIT_STAND_STATE_KNEEL;
11159 void Unit::SetStandState(uint8 state)
11161 SetByteValue(UNIT_FIELD_BYTES_1, 0, state);
11163 if (IsStandState())
11164 RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_SEATED);
11166 if(GetTypeId()==TYPEID_PLAYER)
11168 WorldPacket data(SMSG_STANDSTATE_UPDATE, 1);
11169 data << (uint8)state;
11170 ((Player*)this)->GetSession()->SendPacket(&data);
11174 bool Unit::IsPolymorphed() const
11176 return GetSpellSpecific(getTransForm())==SPELL_MAGE_POLYMORPH;
11179 void Unit::SetDisplayId(uint32 modelId)
11181 SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId);
11183 if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
11185 Pet *pet = ((Pet*)this);
11186 if(!pet->isControlled())
11187 return;
11188 Unit *owner = GetOwner();
11189 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
11190 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID);
11194 void Unit::ClearComboPointHolders()
11196 while(!m_ComboPointHolders.empty())
11198 uint32 lowguid = *m_ComboPointHolders.begin();
11200 Player* plr = objmgr.GetPlayer(MAKE_NEW_GUID(lowguid, 0, HIGHGUID_PLAYER));
11201 if(plr && plr->GetComboTarget()==GetGUID()) // recheck for safe
11202 plr->ClearComboPoints(); // remove also guid from m_ComboPointHolders;
11203 else
11204 m_ComboPointHolders.erase(lowguid); // or remove manually
11208 void Unit::ClearAllReactives()
11210 for(int i=0; i < MAX_REACTIVE; ++i)
11211 m_reactiveTimer[i] = 0;
11213 if (HasAuraState( AURA_STATE_DEFENSE))
11214 ModifyAuraState(AURA_STATE_DEFENSE, false);
11215 if (getClass() == CLASS_HUNTER && HasAuraState( AURA_STATE_HUNTER_PARRY))
11216 ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
11217 if(getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
11218 ((Player*)this)->ClearComboPoints();
11221 void Unit::UpdateReactives( uint32 p_time )
11223 for(int i = 0; i < MAX_REACTIVE; ++i)
11225 ReactiveType reactive = ReactiveType(i);
11227 if(!m_reactiveTimer[reactive])
11228 continue;
11230 if ( m_reactiveTimer[reactive] <= p_time)
11232 m_reactiveTimer[reactive] = 0;
11234 switch ( reactive )
11236 case REACTIVE_DEFENSE:
11237 if (HasAuraState(AURA_STATE_DEFENSE))
11238 ModifyAuraState(AURA_STATE_DEFENSE, false);
11239 break;
11240 case REACTIVE_HUNTER_PARRY:
11241 if ( getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY))
11242 ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
11243 break;
11244 case REACTIVE_OVERPOWER:
11245 if(getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
11246 ((Player*)this)->ClearComboPoints();
11247 break;
11248 default:
11249 break;
11252 else
11254 m_reactiveTimer[reactive] -= p_time;
11259 Unit* Unit::SelectNearbyTarget() const
11261 CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
11262 Cell cell(p);
11263 cell.data.Part.reserved = ALL_DISTRICT;
11264 cell.SetNoCreate();
11266 std::list<Unit *> targets;
11269 MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, this, ATTACK_DISTANCE);
11270 MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> searcher(this, targets, u_check);
11272 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
11273 TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
11275 CellLock<GridReadGuard> cell_lock(cell, p);
11276 cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap());
11277 cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap());
11280 // remove current target
11281 if(getVictim())
11282 targets.remove(getVictim());
11284 // remove not LoS targets
11285 for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end();)
11287 if(!IsWithinLOSInMap(*tIter))
11289 std::list<Unit *>::iterator tIter2 = tIter;
11290 ++tIter;
11291 targets.erase(tIter2);
11293 else
11294 ++tIter;
11297 // no appropriate targets
11298 if(targets.empty())
11299 return NULL;
11301 // select random
11302 uint32 rIdx = urand(0,targets.size()-1);
11303 std::list<Unit *>::const_iterator tcIter = targets.begin();
11304 for(uint32 i = 0; i < rIdx; ++i)
11305 ++tcIter;
11307 return *tcIter;
11310 bool Unit::hasNegativeAuraWithInterruptFlag(uint32 flag)
11312 for (AuraMap::const_iterator iter = m_Auras.begin(); iter != m_Auras.end(); ++iter)
11314 if (!iter->second->IsPositive() && iter->second->GetSpellProto()->AuraInterruptFlags & flag)
11315 return true;
11317 return false;
11320 void Unit::ApplyAttackTimePercentMod( WeaponAttackType att,float val, bool apply )
11322 if(val > 0)
11324 ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply);
11325 ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att,val,!apply);
11327 else
11329 ApplyPercentModFloatVar(m_modAttackSpeedPct[att], -val, apply);
11330 ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att,-val,apply);
11334 void Unit::ApplyCastTimePercentMod(float val, bool apply )
11336 if(val > 0)
11337 ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED,val,!apply);
11338 else
11339 ApplyPercentModFloatValue(UNIT_MOD_CAST_SPEED,-val,apply);
11342 uint32 Unit::GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime )
11344 // Not apply this to creature casted spells with casttime==0
11345 if(CastingTime==0 && GetTypeId()==TYPEID_UNIT && !((Creature*)this)->isPet())
11346 return 3500;
11348 if (CastingTime > 7000) CastingTime = 7000;
11349 if (CastingTime < 1500) CastingTime = 1500;
11351 if(damagetype == DOT && !IsChanneledSpell(spellProto))
11352 CastingTime = 3500;
11354 int32 overTime = 0;
11355 uint8 effects = 0;
11356 bool DirectDamage = false;
11357 bool AreaEffect = false;
11359 for ( uint32 i=0; i<3;++i)
11361 switch ( spellProto->Effect[i] )
11363 case SPELL_EFFECT_SCHOOL_DAMAGE:
11364 case SPELL_EFFECT_POWER_DRAIN:
11365 case SPELL_EFFECT_HEALTH_LEECH:
11366 case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
11367 case SPELL_EFFECT_POWER_BURN:
11368 case SPELL_EFFECT_HEAL:
11369 DirectDamage = true;
11370 break;
11371 case SPELL_EFFECT_APPLY_AURA:
11372 switch ( spellProto->EffectApplyAuraName[i] )
11374 case SPELL_AURA_PERIODIC_DAMAGE:
11375 case SPELL_AURA_PERIODIC_HEAL:
11376 case SPELL_AURA_PERIODIC_LEECH:
11377 if ( GetSpellDuration(spellProto) )
11378 overTime = GetSpellDuration(spellProto);
11379 break;
11380 default:
11381 // -5% per additional effect
11382 ++effects;
11383 break;
11385 default:
11386 break;
11389 if(IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetA[i])) || IsAreaEffectTarget(Targets(spellProto->EffectImplicitTargetB[i])))
11390 AreaEffect = true;
11393 // Combined Spells with Both Over Time and Direct Damage
11394 if ( overTime > 0 && CastingTime > 0 && DirectDamage )
11396 // mainly for DoTs which are 3500 here otherwise
11397 uint32 OriginalCastTime = GetSpellCastTime(spellProto);
11398 if (OriginalCastTime > 7000) OriginalCastTime = 7000;
11399 if (OriginalCastTime < 1500) OriginalCastTime = 1500;
11400 // Portion to Over Time
11401 float PtOT = (overTime / 15000.0f) / ((overTime / 15000.0f) + (OriginalCastTime / 3500.0f));
11403 if ( damagetype == DOT )
11404 CastingTime = uint32(CastingTime * PtOT);
11405 else if ( PtOT < 1.0f )
11406 CastingTime = uint32(CastingTime * (1 - PtOT));
11407 else
11408 CastingTime = 0;
11411 // Area Effect Spells receive only half of bonus
11412 if ( AreaEffect )
11413 CastingTime /= 2;
11415 // -5% of total per any additional effect
11416 for ( uint8 i=0; i<effects; ++i)
11418 if ( CastingTime > 175 )
11420 CastingTime -= 175;
11422 else
11424 CastingTime = 0;
11425 break;
11429 return CastingTime;
11432 void Unit::UpdateAuraForGroup(uint8 slot)
11434 if(GetTypeId() == TYPEID_PLAYER)
11436 Player* player = (Player*)this;
11437 if(player->GetGroup())
11439 player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_AURAS);
11440 player->SetAuraUpdateMask(slot);
11443 else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet())
11445 Pet *pet = ((Pet*)this);
11446 if(pet->isControlled())
11448 Unit *owner = GetOwner();
11449 if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup())
11451 ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS);
11452 pet->SetAuraUpdateMask(slot);
11458 float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized)
11460 if (!normalized || GetTypeId() != TYPEID_PLAYER)
11461 return float(GetAttackTime(attType))/1000.0f;
11463 Item *Weapon = ((Player*)this)->GetWeaponForAttack(attType);
11464 if (!Weapon)
11465 return 2.4; // fist attack
11467 switch (Weapon->GetProto()->InventoryType)
11469 case INVTYPE_2HWEAPON:
11470 return 3.3;
11471 case INVTYPE_RANGED:
11472 case INVTYPE_RANGEDRIGHT:
11473 case INVTYPE_THROWN:
11474 return 2.8;
11475 case INVTYPE_WEAPON:
11476 case INVTYPE_WEAPONMAINHAND:
11477 case INVTYPE_WEAPONOFFHAND:
11478 default:
11479 return Weapon->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_DAGGER ? 1.7 : 2.4;
11483 Aura* Unit::GetDummyAura( uint32 spell_id ) const
11485 Unit::AuraList const& mDummy = GetAurasByType(SPELL_AURA_DUMMY);
11486 for(Unit::AuraList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
11487 if ((*itr)->GetId() == spell_id)
11488 return *itr;
11490 return NULL;
11493 bool Unit::IsUnderLastManaUseEffect() const
11495 return getMSTimeDiff(m_lastManaUse,getMSTime()) < 5000;
11498 void Unit::SetContestedPvP(Player *attackedPlayer)
11500 Player* player = GetCharmerOrOwnerPlayerOrPlayerItself();
11502 if(!player || attackedPlayer && (attackedPlayer == player || player->duel && player->duel->opponent == attackedPlayer))
11503 return;
11505 player->SetContestedPvPTimer(30000);
11506 if(!player->hasUnitState(UNIT_STAT_ATTACK_PLAYER))
11508 player->addUnitState(UNIT_STAT_ATTACK_PLAYER);
11509 player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP);
11510 // call MoveInLineOfSight for nearby contested guards
11511 SetVisibility(GetVisibility());
11513 if(!hasUnitState(UNIT_STAT_ATTACK_PLAYER))
11515 addUnitState(UNIT_STAT_ATTACK_PLAYER);
11516 // call MoveInLineOfSight for nearby contested guards
11517 SetVisibility(GetVisibility());
11521 void Unit::AddPetAura(PetAura const* petSpell)
11523 m_petAuras.insert(petSpell);
11524 if(Pet* pet = GetPet())
11525 pet->CastPetAura(petSpell);
11528 void Unit::RemovePetAura(PetAura const* petSpell)
11530 m_petAuras.erase(petSpell);
11531 if(Pet* pet = GetPet())
11532 pet->RemoveAurasDueToSpell(petSpell->GetAura(pet->GetEntry()));
11535 Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id)
11537 Pet* pet = new Pet(HUNTER_PET);
11539 if(!pet->CreateBaseAtCreature(creatureTarget))
11541 delete pet;
11542 return NULL;
11545 pet->SetOwnerGUID(GetGUID());
11546 pet->SetCreatorGUID(GetGUID());
11547 pet->setFaction(getFaction());
11548 pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id);
11550 if(GetTypeId()==TYPEID_PLAYER)
11551 pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
11553 if(IsPvP())
11554 pet->SetPvP(true);
11556 uint32 level = (creatureTarget->getLevel() < (getLevel() - 5)) ? (getLevel() - 5) : creatureTarget->getLevel();
11558 if(!pet->InitStatsForLevel(level))
11560 sLog.outError("Pet::InitStatsForLevel() failed for creature (Entry: %u)!",creatureTarget->GetEntry());
11561 delete pet;
11562 return NULL;
11565 pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true);
11566 // this enables pet details window (Shift+P)
11567 pet->AIM_Initialize();
11568 pet->InitPetCreateSpells();
11569 pet->InitLevelupSpellsForLevel();
11570 pet->InitTalentForLevel();
11571 pet->SetHealth(pet->GetMaxHealth());
11573 return pet;
11576 bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent )
11578 SpellEntry const* spellProto = aura->GetSpellProto ();
11580 // Get proc Event Entry
11581 spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id);
11583 // Aura info stored here
11584 Modifier *mod = aura->GetModifier();
11585 // Skip this auras
11586 if (isNonTriggerAura[mod->m_auraname])
11587 return false;
11588 // If not trigger by default and spellProcEvent==NULL - skip
11589 if (!isTriggerAura[mod->m_auraname] && spellProcEvent==NULL)
11590 return false;
11592 // Get EventProcFlag
11593 uint32 EventProcFlag;
11594 if (spellProcEvent && spellProcEvent->procFlags) // if exist get custom spellProcEvent->procFlags
11595 EventProcFlag = spellProcEvent->procFlags;
11596 else
11597 EventProcFlag = spellProto->procFlags; // else get from spell proto
11598 // Continue if no trigger exist
11599 if (!EventProcFlag)
11600 return false;
11602 // Check spellProcEvent data requirements
11603 if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active))
11604 return false;
11606 // In most cases req get honor or XP from kill
11607 if (EventProcFlag & PROC_FLAG_KILL && GetTypeId() == TYPEID_PLAYER)
11609 bool allow = ((Player*)this)->isHonorOrXPTarget(pVictim);
11610 // Shadow Word: Death - can trigger from every kill
11611 if (aura->GetId() == 32409)
11612 allow = true;
11613 if (!allow)
11614 return false;
11616 // Aura added by spell can`t trogger from self (prevent drop charges/do triggers)
11617 // But except periodic triggers (can triggered from self)
11618 if(procSpell && procSpell->Id == spellProto->Id && !(spellProto->procFlags&PROC_FLAG_ON_TAKE_PERIODIC))
11619 return false;
11621 // Check if current equipment allows aura to proc
11622 if(!isVictim && GetTypeId() == TYPEID_PLAYER)
11624 if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON)
11626 Item *item = NULL;
11627 if(attType == BASE_ATTACK)
11628 item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
11629 else if (attType == OFF_ATTACK)
11630 item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
11631 else
11632 item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
11634 if (!((Player*)this)->IsUseEquipedWeapon(attType==BASE_ATTACK))
11635 return false;
11637 if(!item || item->IsBroken() || item->GetProto()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask))
11638 return false;
11640 else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR)
11642 // Check if player is wearing shield
11643 Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);
11644 if(!item || item->IsBroken() || item->GetProto()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask))
11645 return false;
11648 // Get chance from spell
11649 float chance = (float)spellProto->procChance;
11650 // If in spellProcEvent exist custom chance, chance = spellProcEvent->customChance;
11651 if(spellProcEvent && spellProcEvent->customChance)
11652 chance = spellProcEvent->customChance;
11653 // If PPM exist calculate chance from PPM
11654 if(!isVictim && spellProcEvent && spellProcEvent->ppmRate != 0)
11656 uint32 WeaponSpeed = GetAttackTime(attType);
11657 chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate);
11659 // Apply chance modifer aura
11660 if(Player* modOwner = GetSpellModOwner())
11661 modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance);
11663 return roll_chance_f(chance);
11666 bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
11668 // aura can be deleted at casts
11669 SpellEntry const* spellProto = triggeredByAura->GetSpellProto();
11670 uint32 effIdx = triggeredByAura->GetEffIndex();
11671 int32 heal = triggeredByAura->GetModifier()->m_amount;
11672 uint64 caster_guid = triggeredByAura->GetCasterGUID();
11674 // jumps
11675 int32 jumps = triggeredByAura->GetAuraCharges()-1;
11677 // current aura expire
11678 triggeredByAura->SetAuraCharges(1); // will removed at next charges decrease
11680 // next target selection
11681 if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid))
11683 float radius;
11684 if (spellProto->EffectRadiusIndex[effIdx])
11685 radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx]));
11686 else
11687 radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex));
11689 if(Player* caster = ((Player*)triggeredByAura->GetCaster()))
11691 caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL);
11693 if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius))
11695 // aura will applied from caster, but spell casted from current aura holder
11696 SpellModifier *mod = new SpellModifier;
11697 mod->op = SPELLMOD_CHARGES;
11698 mod->value = jumps-5; // negative
11699 mod->type = SPELLMOD_FLAT;
11700 mod->spellId = spellProto->Id;
11701 mod->mask = spellProto->SpellFamilyFlags;
11702 mod->mask2 = spellProto->SpellFamilyFlags2;
11704 caster->AddSpellMod(mod, true);
11705 CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID());
11706 caster->AddSpellMod(mod, false);
11711 // heal
11712 CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid);
11713 return true;
11716 void Unit::RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo)
11718 uint64 target_guid = GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT);
11720 if(!IS_UNIT_GUID(target_guid))
11721 return;
11723 Unit* target = ObjectAccessor::GetUnit(*this, target_guid);
11724 if(!target)
11725 return;
11727 for (AuraMap::iterator iter = target->GetAuras().begin(); iter != target->GetAuras().end(); )
11729 if (iter->second->GetId() == spellInfo->Id && iter->second->GetCasterGUID()==GetGUID())
11730 target->RemoveAura(iter);
11731 else
11732 ++iter;
11736 void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
11738 WorldObject::SetPhaseMask(newPhaseMask,update);
11740 if(IsInWorld())
11741 if(Pet* pet = GetPet())
11742 pet->SetPhaseMask(newPhaseMask,true);
11745 void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ )
11747 if(GetTypeId() == TYPEID_PLAYER)
11748 ((Player*)this)->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0));
11749 else
11751 GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation);
11753 WorldPacket data;
11754 // Work strange for many spells: triggered active mover set for targeted player to creature
11755 //BuildTeleportAckMsg(&data, x, y, z, orientation);
11756 BuildHeartBeatMsg(&data);
11757 SendMessageToSet(&data, false);
11761 void Unit::SetPvP( bool state )
11763 if(state)
11764 SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
11765 else
11766 RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
11768 if(Pet* pet = GetPet())
11769 pet->SetPvP(state);
11770 if(Unit* charmed = GetCharm())
11771 charmed->SetPvP(state);
11773 for (int8 i = 0; i < MAX_TOTEM; ++i)
11774 if(m_TotemSlot[i])
11775 if(Creature *totem = GetMap()->GetCreature(m_TotemSlot[i]))
11776 totem->SetPvP(state);