diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/SpellAuras.cpp | 12688 | ||||
-rw-r--r-- | src/game/SpellHandler.cpp | 984 | ||||
-rw-r--r-- | src/game/Unit.cpp | 373 | ||||
-rw-r--r-- | src/game/Unit.h | 2791 |
4 files changed, 8447 insertions, 8389 deletions
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 37c02fb549d..4c98d590a9d 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1,6339 +1,6349 @@ -/* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> - * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DatabaseEnv.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "Log.h" -#include "UpdateMask.h" -#include "World.h" -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "Player.h" -#include "Unit.h" -#include "Spell.h" -#include "SpellAuras.h" -#include "DynamicObject.h" -#include "Group.h" -#include "UpdateData.h" -#include "MapManager.h" -#include "ObjectAccessor.h" -#include "Policies/SingletonImp.h" -#include "Totem.h" -#include "Creature.h" -#include "Formulas.h" -#include "BattleGround.h" -#include "OutdoorPvP.h" -#include "OutdoorPvPMgr.h" -#include "CreatureAI.h" -#include "Util.h" -#include "GridNotifiers.h" -#include "GridNotifiersImpl.h" -#include "CellImpl.h" -#include "TemporarySummon.h" - -#define NULL_AURA_SLOT 0xFF - -pAuraHandler AuraHandler[TOTAL_AURAS]= -{ - &Aura::HandleNULL, // 0 SPELL_AURA_NONE - &Aura::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT - &Aura::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS - &Aura::HandlePeriodicDamage, // 3 SPELL_AURA_PERIODIC_DAMAGE - &Aura::HandleAuraDummy, // 4 SPELL_AURA_DUMMY - &Aura::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE - &Aura::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM - &Aura::HandleModFear, // 7 SPELL_AURA_MOD_FEAR - &Aura::HandlePeriodicHeal, // 8 SPELL_AURA_PERIODIC_HEAL - &Aura::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED - &Aura::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT - &Aura::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT - &Aura::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN - &Aura::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE - &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus - &Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage - &Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH - &Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT - &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY - &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION - &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH - &Aura::HandleAuraModTotalManaPercentRegen, // 21 SPELL_AURA_OBS_MOD_MANA - &Aura::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE - &Aura::HandlePeriodicTriggerSpell, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL - &Aura::HandlePeriodicEnergize, // 24 SPELL_AURA_PERIODIC_ENERGIZE - &Aura::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY - &Aura::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT - &Aura::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE - &Aura::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult - &Aura::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT - &Aura::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL - &Aura::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED - &Aura::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED - &Aura::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED - &Aura::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH - &Aura::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY - &Aura::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT - &Aura::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY - &Aura::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY - &Aura::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY - &Aura::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY - &Aura::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY - &Aura::HandleAuraProcTriggerSpell, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell - &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor - &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES - &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES - &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete? - &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT - &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete? - &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT - &Aura::HandleUnused, // 50 SPELL_AURA_MOD_BLOCK_SKILL obsolete? - &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT - &Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT - &Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH - &Aura::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE - &Aura::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE - &Aura::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM - &Aura::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE - &Aura::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED - &Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus - &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE - &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE - &Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL - &Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete? - &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH - &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED - &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH - &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM - &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED - &Aura::HandleSchoolAbsorb, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist - &Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect - &Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL - &Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT - &Aura::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL - &Aura::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult - &Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE - &Aura::HandleFarSight, // 76 SPELL_AURA_FAR_SIGHT - &Aura::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY - &Aura::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED - &Aura::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE - &Aura::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT - &Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT - &Aura::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING - &Aura::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE - &Aura::HandleModRegen, // 84 SPELL_AURA_MOD_REGEN - &Aura::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN - &Aura::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM - &Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus - &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT - &Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT - &Aura::HandleUnused, // 90 SPELL_AURA_MOD_RESIST_CHANCE Useless - &Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance - &Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING - &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE - &Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll - &Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST - &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Spell::SelectMagnetTarget - &Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist - &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT - &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER - &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now - &Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT - &Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus - &Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT - &Aura::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK - &Aura::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL - &Aura::HandleAuraHover, //106 SPELL_AURA_HOVER - &Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER - &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER - &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER - &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT - &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER - &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS - &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus - &Aura::HandleAuraHealing, //115 SPELL_AURA_MOD_HEALING - &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT - &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleAuraHealingPct, //118 SPELL_AURA_MOD_HEALING_PCT - &Aura::HandleUnused, //119 SPELL_AURA_SHARE_PET_TRACKING useless - &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE - &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY - &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT - &Aura::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE - &Aura::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER - &Aura::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus - &Aura::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET - &Aura::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS - &Aura::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS - &Aura::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus - &Aura::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT - &Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT - &Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT - &Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE - &Aura::HandleAuraHealingPct, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus - &Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE - &Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE - &Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION - &Aura::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE - &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE - &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT - &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE - &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes - &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete? - &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete? - &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY - &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS - &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK - &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT - &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED - &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance - &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT - &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL - &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING - &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN - &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI - &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE - &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell - &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT - &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA - &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE - &Aura::HandleUnused, //164 useless, only one test spell - &Aura::HandleAuraAttackPowerAttacker, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus - &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT - &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT - &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus - &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus - &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE only for Detect Amore spell - &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK - &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK - &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell - &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by default intellect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT) - &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus - &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end - &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM - &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus - &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus - &Aura::HandleUnused, //181 SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS unused - &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT - &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT - &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance - &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance - &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING - &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN - &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED - &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE - &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) - &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT) - &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT) - &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN - &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance - &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS - &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP - &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode... - &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst - &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::DoAttackDamage - &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::DoAttackDamage - &Aura::HandleNULL, //205 vulnerable to school dmg? - &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED - &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED - &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive) - &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS - &Aura::HandleNULL, //210 Commentator's Command - &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK - &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT - &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage - &Aura::HandleNULL, //214 Tamed Pet Passive - &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION - &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS - &Aura::HandleUnused, //217 unused - &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED - &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT - &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT - &Aura::HandleNULL, //221 ignored - &Aura::HandleUnused, //222 unused - &Aura::HandleNULL, //223 Cold Stare - &Aura::HandleUnused, //224 unused - &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING - &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY - &Aura::HandleNULL, //227 periodic trigger spell - &Aura::HandleNoImmediateEffect, //228 stealth detection - &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE - &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout - &Aura::HandleNULL, //231 - &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration - &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue - &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration - &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult - &Aura::HandleUnused, //236 unused - &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus - &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus - &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61 - &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE - &Aura::HandleForceMoveForward, //241 Forces the player to move forward - &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING - &Aura::HandleUnused, //243 used by two test spells - &Aura::HandleComprehendLanguage, //244 Comprehend language - &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS - &Aura::HandleUnused, //246 unused - &Aura::HandleUnused, //247 unused - &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleNULL, //249 - &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2 - &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE - &Aura::HandleUnused, //252 unused - &Aura::HandleUnused, //253 unused - &Aura::HandleUnused, //254 unused - &Aura::HandleUnused, //255 unused - &Aura::HandleUnused, //256 unused - &Aura::HandleUnused, //257 unused - &Aura::HandleUnused, //258 unused - &Aura::HandleUnused, //259 unused - &Aura::HandleUnused, //260 unused - &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell) -}; - -Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) : -m_procCharges(0), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target), -m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS), -m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), -m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false), -m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) -{ - assert(target); - - assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element"); - - m_spellProto = spellproto; - - m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff]; - - m_isPassive = IsPassiveSpell(GetId()); - m_positive = IsPositiveEffect(GetId(), m_effIndex); - - m_applyTime = time(NULL); - - int32 damage; - if(!caster) - { - m_caster_guid = target->GetGUID(); - damage = m_currentBasePoints+1; // stored value-1 - m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target); - } - else - { - m_caster_guid = caster->GetGUID(); - - damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target); - m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target); - - if (!damage && castItem && castItem->GetItemSuffixFactor()) - { - ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId())); - if(item_rand_suffix) - { - for (int k=0; k<3; k++) - { - SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]); - if(pEnchant) - { - for (int t=0; t<3; t++) - if(pEnchant->spellid[t] == m_spellProto->Id) - { - damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 ); - break; - } - } - - if(damage) - break; - } - } - } - } - - if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0) - m_permanent = true; - - Player* modOwner = caster ? caster->GetSpellModOwner() : NULL; - - if(!m_permanent && modOwner) - modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration); - - m_duration = m_maxduration; - - if(modOwner) - modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer); - - sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage); - - m_effIndex = eff; - SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]); - - m_isDeathPersist = IsDeathPersistentSpell(m_spellProto); - - if(m_spellProto->procCharges) - { - m_procCharges = m_spellProto->procCharges; - - if(modOwner) - modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); - } - else - m_procCharges = -1; - - m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances && - !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000)); -} - -Aura::~Aura() -{ -} - -AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, -Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem) -{ - m_isAreaAura = true; - - // caster==NULL in constructor args if target==caster in fact - Unit* caster_ptr = caster ? caster : target; - - m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); - if(Player* modOwner = caster_ptr->GetSpellModOwner()) - modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius); - - switch(spellproto->Effect[eff]) - { - case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: - m_areaAuraType = AREA_AURA_PARTY; - if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) - m_modifier.m_auraname = SPELL_AURA_NONE; - break; - case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: - m_areaAuraType = AREA_AURA_FRIEND; - break; - case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: - m_areaAuraType = AREA_AURA_ENEMY; - if(target == caster_ptr) - m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self - break; - case SPELL_EFFECT_APPLY_AREA_AURA_PET: - m_areaAuraType = AREA_AURA_PET; - break; - case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: - m_areaAuraType = AREA_AURA_OWNER; - if(target == caster_ptr) - m_modifier.m_auraname = SPELL_AURA_NONE; - break; - default: - sLog.outError("Wrong spell effect in AreaAura constructor"); - ASSERT(false); - break; - } -} - -AreaAura::~AreaAura() -{ -} - -PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, -Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem) -{ - m_isPersistent = true; -} - -PersistentAreaAura::~PersistentAreaAura() -{ -} - -Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) -{ - if (IsAreaAuraEffect(spellproto->Effect[eff])) - return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem); - - return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem); -} - -Unit* Aura::GetCaster() const -{ - if(m_caster_guid==m_target->GetGUID()) - return m_target; - - //return ObjectAccessor::GetUnit(*m_target,m_caster_guid); - //must return caster even if it's in another grid/map - Unit *unit = ObjectAccessor::GetObjectInWorld(m_caster_guid, (Unit*)NULL); - return unit && unit->IsInWorld() ? unit : NULL; -} - -void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue) -{ - m_modifier.m_auraname = t; - m_modifier.m_amount = a; - m_modifier.m_miscvalue = miscValue; - m_modifier.periodictime = pt; -} - -void Aura::Update(uint32 diff) -{ - if (m_duration > 0) - { - m_duration -= diff; - if (m_duration < 0) - m_duration = 0; - m_timeCla -= diff; - - // GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras - // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0 - if(GetEffIndex()==0 && m_timeCla <= 0) - { - if(Unit* caster = GetCaster()) - { - Powers powertype = Powers(m_spellProto->powerType); - int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel(); - m_timeCla = 1000; - if (manaPerSecond) - { - if(powertype==POWER_HEALTH) - caster->ModifyHealth(-manaPerSecond); - else - caster->ModifyPower(powertype,-manaPerSecond); - } - } - } - } - - // Channeled aura required check distance from caster except in possessed cases - if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID() && !m_target->isPossessed()) - { - Unit* caster = GetCaster(); - if(!caster) - { - m_target->RemoveAura(GetId(),GetEffIndex()); - return; - } - - // Get spell range - float radius; - SpellModOp mod; - if (m_spellProto->EffectRadiusIndex[GetEffIndex()]) - { - radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()])); - mod = SPELLMOD_RADIUS; - } - else - { - radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex)); - mod = SPELLMOD_RANGE; - } - - if(Player* modOwner = caster->GetSpellModOwner()) - modOwner->ApplySpellMod(GetId(), mod, radius,NULL); - - if(!caster->IsWithinDistInMap(m_target,radius)) - { - m_target->RemoveAura(GetId(),GetEffIndex()); - return; - } - } - - if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent)) - { - m_periodicTimer -= diff; - if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N - { - if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN || - m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN || - // Cannibalize, eating items and other spells - m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH || - // Eating items and other spells - m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA ) - { - ApplyModifier(true); - return; - } - // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls) - m_periodicTimer += m_modifier.periodictime; - - if(m_isTrigger) - TriggerSpell(); - else - PeriodicTick(); - } - } -} - -void AreaAura::Update(uint32 diff) -{ - // update for the caster of the aura - if(m_caster_guid == m_target->GetGUID()) - { - Unit* caster = m_target; - - if( !caster->hasUnitState(UNIT_STAT_ISOLATED) ) - { - Unit* owner = caster->GetCharmerOrOwner(); - if (!owner) - owner = caster; - std::list<Unit *> targets; - - switch(m_areaAuraType) - { - case AREA_AURA_PARTY: - { - Group *pGroup = NULL; - - if (owner->GetTypeId() == TYPEID_PLAYER) - pGroup = ((Player*)owner)->GetGroup(); - - if( pGroup) - { - uint8 subgroup = ((Player*)owner)->GetSubGroup(); - for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* Target = itr->getSource(); - if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target)) - { - if(caster->IsWithinDistInMap(Target, m_radius)) - targets.push_back(Target); - Pet *pet = Target->GetPet(); - if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius)) - targets.push_back(pet); - } - } - } - else - { - // add owner - if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) ) - targets.push_back(owner); - // add caster's pet - Unit* pet = caster->GetPet(); - if( pet && caster->IsWithinDistInMap(pet, m_radius)) - targets.push_back(pet); - } - break; - } - case AREA_AURA_FRIEND: - { - CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius); - Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check); - TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); - TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster)); - cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster)); - break; - } - case AREA_AURA_ENEMY: - { - CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher - Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check); - TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); - TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster)); - cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster)); - break; - } - case AREA_AURA_OWNER: - case AREA_AURA_PET: - { - if(owner != caster) - targets.push_back(owner); - break; - } - } - - for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++) - { - if((*tIter)->HasAura(GetId(), m_effIndex)) - continue; - - if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel())) - { - int32 actualBasePoints = m_currentBasePoints; - // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?) - if(actualSpellInfo != GetSpellProto()) - actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex]; - AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL); - (*tIter)->AddAura(aur); - } - } - } - Aura::Update(diff); - } - else // aura at non-caster - { - Unit * tmp_target = m_target; - Unit* caster = GetCaster(); - uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex; - - // WARNING: the aura may get deleted during the update - // DO NOT access its members after update! - Aura::Update(diff); - - // remove aura if out-of-range from caster (after teleport for example) - // or caster is isolated or caster no longer has the aura - // or caster is (no longer) friendly - bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true); - if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) || - !caster->IsWithinDistInMap(tmp_target, m_radius) || - !caster->HasAura(tmp_spellId, tmp_effIndex) || - caster->IsFriendlyTo(tmp_target) != needFriendly - ) - { - tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); - } - else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group - { - // not check group if target == owner or target == pet - if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID()) - { - Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself(); - - Group *pGroup = check ? check->GetGroup() : NULL; - if( pGroup ) - { - Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself(); - if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget)) - tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); - } - else - tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); - } - } - else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) - { - if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) - tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); - } - } -} - -void PersistentAreaAura::Update(uint32 diff) -{ - bool remove = false; - - // remove the aura if its caster or the dynamic object causing it was removed - // or if the target moves too far from the dynamic object - Unit *caster = GetCaster(); - if (caster) - { - DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex()); - if (dynObj) - { - if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius())) - remove = true; - } - else - remove = true; - } - else - remove = true; - - Unit *tmp_target = m_target; - uint32 tmp_id = GetId(), tmp_index = GetEffIndex(); - - // WARNING: the aura may get deleted during the update - // DO NOT access its members after update! - Aura::Update(diff); - - if(remove) - tmp_target->RemoveAura(tmp_id, tmp_index); -} - -void Aura::ApplyModifier(bool apply, bool Real) -{ - AuraType aura = m_modifier.m_auraname; - - m_in_use = true; - if(aura<TOTAL_AURAS) - (*this.*AuraHandler [aura])(apply,Real); - m_in_use = false; -} - -void Aura::UpdateAuraDuration() -{ - if(m_auraSlot >= MAX_AURAS || m_isPassive) - return; - - if( m_target->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5); - data << (uint8)m_auraSlot << (uint32)m_duration; - ((Player*)m_target)->SendDirectMessage(&data); - - data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4)); - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - data << uint32(GetId()); - data << uint32(GetAuraMaxDuration()); - data << uint32(GetAuraDuration()); - ((Player*)m_target)->SendDirectMessage(&data); - } - - // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code - if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()) - return; - - Unit* caster = GetCaster(); - - if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target) - SendAuraDurationForCaster((Player*)caster); -} - -void Aura::SendAuraDurationForCaster(Player* caster) -{ - WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4)); - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - data << uint32(GetId()); - data << uint32(GetAuraMaxDuration()); // full - data << uint32(GetAuraDuration()); // remain - caster->GetSession()->SendPacket(&data); -} - -void Aura::_AddAura() -{ - if (!GetId()) - return; - if(!m_target) - return; - - // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT - bool samespell = false; - bool secondaura = false; - uint8 slot = NULL_AURA_SLOT; - - for(uint8 i = 0; i < 3; i++) - { - Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); - for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) - { - // allow use single slot only by auras from same caster - if(itr->second->GetCasterGUID()==GetCasterGUID()) - { - samespell = true; - if (m_effIndex > itr->second->GetEffIndex()) - secondaura = true; - slot = itr->second->GetAuraSlot(); - break; - } - } - - if(samespell) - break; - } - - // not call total regen auras at adding - switch (m_modifier.m_auraname) - { - case SPELL_AURA_OBS_MOD_HEALTH: - case SPELL_AURA_OBS_MOD_MANA: - m_periodicTimer = m_modifier.periodictime; - break; - case SPELL_AURA_MOD_REGEN: - case SPELL_AURA_MOD_POWER_REGEN: - case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT: - m_periodicTimer = 5000; - break; - } - - // register aura - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),true); - - Unit* caster = GetCaster(); - - // passive auras (except totem auras) do not get placed in the slots - // area auras with SPELL_AURA_NONE are not shown on target - if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && - (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)) - { - if(!samespell) // new slot need - { - if (IsPositive()) // empty positive slot - { - for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++) - { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } - } - } - else // empty negative slot - { - for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++) - { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } - } - } - - SetAuraSlot( slot ); - - // Not update fields for not first spell's aura, all data already in fields - if(!secondaura) - { - if(slot < MAX_AURAS) // slot found - { - SetAura(slot, false); - SetAuraFlag(slot, true); - SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - UpdateAuraCharges(); - - // update for out of range group members - m_target->UpdateAuraForGroup(slot); - } - - UpdateAuraDuration(); - } - } - else // use found slot - { - SetAuraSlot( slot ); - // Not recalculate stack count for second aura of the same spell - if (!secondaura) - UpdateSlotCounterAndDuration(true); - } - - // Update Seals information - if( IsSealSpell(GetSpellProto()) ) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); - - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); - - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) - { - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); - } - } -} - -void Aura::_RemoveAura() -{ - // Remove all triggered by aura spells vs unlimited duration - // except same aura replace case - if(m_removeMode!=AURA_REMOVE_BY_STACK) - CleanupTriggeredSpells(); - - Unit* caster = GetCaster(); - - if(caster && IsPersistent()) - { - DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex()); - if (dynObj) - dynObj->RemoveAffected(m_target); - } - - // unregister aura - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),false); - - //passive auras do not get put in slots - // Note: but totem can be not accessible for aura target in time remove (to far for find in grid) - //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) - // return; - - uint8 slot = GetAuraSlot(); - - if(slot >= MAX_AURAS) // slot not set - return; - - if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0) - return; - - bool samespell = false; - bool sameaura = false; - - // find other aura in same slot (current already removed from list) - for(uint8 i = 0; i < 3; i++) - { - Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); - for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) - { - if(itr->second->GetAuraSlot()==slot) - { - samespell = true; - - if(GetEffIndex()==i) - sameaura = true; - - break; - } - } - if(samespell) - break; - } - - // only remove icon when the last aura of the spell is removed (current aura already removed from list) - if (!samespell) - { - SetAura(slot, true); - SetAuraFlag(slot, false); - SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - - SetAuraApplication(slot, 0); - // update for out of range group members - m_target->UpdateAuraForGroup(slot); - - if( IsSealSpell(GetSpellProto()) ) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); - - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); - - // Swiftmend aura state - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) - { - bool found = false; - Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); - for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) - { - if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) - { - found = true; - break; - } - } - if(!found) - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); - } - - // reset cooldown state for spells - if(caster && caster->GetTypeId() == TYPEID_PLAYER) - { - if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) - ((Player*)caster)->SendCooldownEvent(GetSpellProto()); - } - } - else if(sameaura) // decrease count for spell, only for same aura effect, or this spell auras in remove process. - UpdateSlotCounterAndDuration(false); -} - -void Aura::SetAuraFlag(uint32 slot, bool add) -{ - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index); - val &= ~((uint32)AFLAG_MASK << byte); - if(add) - { - if (IsPositive()) - val |= ((uint32)AFLAG_POSITIVE << byte); - else - val |= ((uint32)AFLAG_NEGATIVE << byte); - } - m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val); -} - -void Aura::SetAuraLevel(uint32 slot,uint32 level) -{ - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index); - val &= ~(0xFF << byte); - val |= (level << byte); - m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val); -} - -void Aura::SetAuraApplication(uint32 slot, int8 count) -{ - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index); - val &= ~(0xFF << byte); - val |= ((uint8(count)) << byte); - m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val); -} - -void Aura::UpdateSlotCounterAndDuration(bool add) -{ - uint8 slot = GetAuraSlot(); - if(slot >= MAX_AURAS) - return; - - // calculate amount of similar auras by same effect index (similar different spells) - int8 count = 0; - - // calculate auras and update durations in case aura adding - Unit::AuraList const& aura_list = m_target->GetAurasByType(GetModifier()->m_auraname); - for(Unit::AuraList::const_iterator i = aura_list.begin();i != aura_list.end(); ++i) - { - if( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex && - (*i)->GetCasterGUID()==GetCasterGUID() ) - { - ++count; - - if(add) - (*i)->SetAuraDuration(GetAuraDuration()); - } - } - - // at aura add aura not added yet, at aura remove aura already removed - // in field stored (count-1) - if(!add) - --count; - - SetAuraApplication(slot, count); - - UpdateAuraDuration(); -} - -/*********************************************************/ -/*** BASIC AURA FUNCTION ***/ -/*********************************************************/ -void Aura::HandleAddModifier(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER || !Real) - return; - - SpellEntry const *spellInfo = GetSpellProto(); - if(!spellInfo) - return; - - if(m_modifier.m_miscvalue >= MAX_SPELLMOD) - return; - - if (apply) - { - // Add custom charges for some mod aura - switch (m_spellProto->Id) - { - case 17941: // Shadow Trance - case 22008: // Netherwind Focus - case 34936: // Backlash - m_procCharges = 1; - break; - } - - SpellModifier *mod = new SpellModifier; - mod->op = SpellModOp(m_modifier.m_miscvalue); - mod->value = m_modifier.m_amount; - mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types - mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - - uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex); - - if (spellAffectMask) - mod->mask = spellAffectMask; - else - mod->mask = spellInfo->EffectItemType[m_effIndex]; - - if (m_procCharges > 0) - mod->charges = m_procCharges; - else - mod->charges = 0; - - m_spellmod = mod; - } - - uint64 spellFamilyMask = m_spellmod->mask; - - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - - // reapply some passive spells after add/remove related spellmods - if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL)) - { - m_target->RemoveAurasDueToSpell(45471); - - if(apply) - m_target->CastSpell(m_target,45471,true); - } -} - -void Aura::TriggerSpell() -{ - Unit* caster = GetCaster(); - Unit* target = GetTriggerTarget(); - - if(!caster || !target) - return; - - // generic casting code with custom spells and target/caster customs - uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; - - uint64 originalCasterGUID = GetCasterGUID(); - - SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); - SpellEntry const *auraSpellInfo = GetSpellProto(); - uint32 auraId = auraSpellInfo->Id; - - // specific code for cases with no trigger spell provided in field - if (triggeredSpellInfo == NULL) - { - switch(auraSpellInfo->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - switch(auraId) - { - // Firestone Passive (1-5 ranks) - case 758: - case 17945: - case 17947: - case 17949: - case 27252: - { - if (caster->GetTypeId()!=TYPEID_PLAYER) - return; - Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK); - if (!item) - return; - uint32 enchant_id = 0; - switch (GetId()) - { - case 758: enchant_id = 1803; break; // Rank 1 - case 17945: enchant_id = 1823; break; // Rank 2 - case 17947: enchant_id = 1824; break; // Rank 3 - case 17949: enchant_id = 1825; break; // Rank 4 - case 27252: enchant_id = 2645; break; // Rank 5 - default: - return; - } - // remove old enchanting before applying new - ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); - item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0); - // add new enchanting - ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true); - return; - } -// // Periodic Mana Burn -// case 812: break; -// // Polymorphic Ray -// case 6965: break; -// // Fire Nova (1-7 ranks) -// case 8350: -// case 8508: -// case 8509: -// case 11312: -// case 11313: -// case 25540: -// case 25544: -// break; - // Thaumaturgy Channel - case 9712: trigger_spell_id = 21029; break; -// // Egan's Blaster -// case 17368: break; -// // Haunted -// case 18347: break; -// // Ranshalla Waiting -// case 18953: break; -// // Inferno -// case 19695: break; -// // Frostwolf Muzzle DND -// case 21794: break; -// // Alterac Ram Collar DND -// case 21866: break; -// // Celebras Waiting -// case 21916: break; - // Brood Affliction: Bronze - case 23170: - { - m_target->CastSpell(m_target, 23171, true, 0, this); - return; - } -// // Mark of Frost -// case 23184: break; - // Restoration - case 23493: - { - int32 heal = caster->GetMaxHealth() / 10; - caster->ModifyHealth( heal ); - caster->SendHealSpellLog(caster, 23493, heal); - - int32 mana = caster->GetMaxPower(POWER_MANA); - if (mana) - { - mana /= 10; - caster->ModifyPower( POWER_MANA, mana ); - caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA); - } - break; - } -// // Stoneclaw Totem Passive TEST -// case 23792: break; -// // Axe Flurry -// case 24018: break; -// // Mark of Arlokk -// case 24210: break; -// // Restoration -// case 24379: break; -// // Happy Pet -// case 24716: break; -// // Dream Fog -// case 24780: break; -// // Cannon Prep -// case 24832: break; -// // Shadow Bolt Whirl -// case 24834: break; -// // Stink Trap -// case 24918: break; -// // Mark of Nature -// case 25041: break; -// // Agro Drones -// case 25152: break; -// // Consume -// case 25371: break; -// // Pain Spike -// case 25572: break; -// // Rotate 360 -// case 26009: break; -// // Rotate -360 -// case 26136: break; -// // Consume -// case 26196: break; -// // Berserk -// case 26615: break; -// // Defile -// case 27177: break; -// // Teleport: IF/UC -// case 27601: break; -// // Five Fat Finger Exploding Heart Technique -// case 27673: break; -// // Nitrous Boost -// case 27746: break; -// // Steam Tank Passive -// case 27747: break; -// // Frost Blast -// case 27808: break; -// // Detonate Mana -// case 27819: break; -// // Controller Timer -// case 28095: break; -// // Stalagg Chain -// case 28096: break; -// // Stalagg Tesla Passive -// case 28097: break; -// // Feugen Tesla Passive -// case 28109: break; -// // Feugen Chain -// case 28111: break; -// // Mark of Didier -// case 28114: break; -// // Communique Timer, camp -// case 28346: break; -// // Icebolt -// case 28522: break; -// // Silithyst -// case 29519: break; -// // Inoculate Nestlewood Owlkin - case 29528: trigger_spell_id = 28713; break; -// // Overload -// case 29768: break; -// // Return Fire -// case 29788: break; -// // Return Fire -// case 29793: break; -// // Return Fire -// case 29794: break; -// // Guardian of Icecrown Passive -// case 29897: break; - // Feed Captured Animal - case 29917: trigger_spell_id = 29916; break; -// // Flame Wreath -// case 29946: break; -// // Flame Wreath -// case 29947: break; -// // Mind Exhaustion Passive -// case 30025: break; -// // Nether Beam - Serenity -// case 30401: break; - // Extract Gas - case 30427: - { - // move loot to player inventory and despawn target - if(caster->GetTypeId() ==TYPEID_PLAYER && - target->GetTypeId() == TYPEID_UNIT && - ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD) - { - Player* player = (Player*)caster; - Creature* creature = (Creature*)target; - // missing lootid has been reported on startup - just return - if (!creature->GetCreatureInfo()->SkinLootId) - { - return; - } - Loot *loot = &creature->loot; - loot->clear(); - loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL); - for(uint8 i=0;i<loot->items.size();i++) - { - LootItem *item = loot->LootItemInSlot(i,player); - ItemPosCountVec dest; - uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count ); - if ( msg == EQUIP_ERR_OK ) - { - Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId); - - player->SendNewItem(newitem, uint32(item->count), false, false, true); - } - else - player->SendEquipError( msg, NULL, NULL ); - } - creature->setDeathState(JUST_DIED); - creature->RemoveCorpse(); - creature->SetHealth(0); // just for nice GM-mode view - } - return; - break; - } - // Quake - case 30576: trigger_spell_id = 30571; break; -// // Burning Maul -// case 30598: break; -// // Regeneration -// case 30799: -// case 30800: -// case 30801: -// break; -// // Despawn Self - Smoke cloud -// case 31269: break; -// // Time Rift Periodic -// case 31320: break; -// // Corrupt Medivh -// case 31326: break; - // Doom - case 31347: - { - m_target->CastSpell(m_target,31350,true); - m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - // Spellcloth - case 31373: - { - // Summon Elemental after create item - caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0); - return; - } -// // Bloodmyst Tesla -// case 31611: break; -// // Doomfire -// case 31944: break; -// // Teleport Test -// case 32236: break; -// // Earthquake -// case 32686: break; -// // Possess -// case 33401: break; -// // Draw Shadows -// case 33563: break; -// // Murmur's Touch -// case 33711: break; - // Flame Quills - case 34229: - { - // cast 24 spells 34269-34289, 34314-34316 - for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id) - caster->CastSpell(m_target,spell_id,true); - for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id) - caster->CastSpell(m_target,spell_id,true); - return; - } -// // Gravity Lapse -// case 34480: break; -// // Tornado -// case 34683: break; -// // Frostbite Rotate -// case 34748: break; -// // Arcane Flurry -// case 34821: break; -// // Interrupt Shutdown -// case 35016: break; -// // Interrupt Shutdown -// case 35176: break; -// // Inferno -// case 35268: break; -// // Salaadin's Tesla -// case 35515: break; -// // Ethereal Channel (Red) -// case 35518: break; -// // Nether Vapor -// case 35879: break; -// // Dark Portal Storm -// case 36018: break; -// // Burning Maul -// case 36056: break; -// // Living Grove Defender Lifespan -// case 36061: break; -// // Professor Dabiri Talks -// case 36064: break; -// // Kael Gaining Power -// case 36091: break; -// // They Must Burn Bomb Aura -// case 36344: break; -// // They Must Burn Bomb Aura (self) -// case 36350: break; -// // Stolen Ravenous Ravager Egg -// case 36401: break; -// // Activated Cannon -// case 36410: break; -// // Stolen Ravenous Ravager Egg -// case 36418: break; -// // Enchanted Weapons -// case 36510: break; -// // Cursed Scarab Periodic -// case 36556: break; -// // Cursed Scarab Despawn Periodic -// case 36561: break; -// // Vision Guide -// case 36573: break; -// // Cannon Charging (platform) -// case 36785: break; -// // Cannon Charging (self) -// case 36860: break; - // Remote Toy - case 37027: trigger_spell_id = 37029; break; -// // Mark of Death -// case 37125: break; -// // Arcane Flurry -// case 37268: break; -// // Spout -// case 37429: break; -// // Spout -// case 37430: break; -// // Karazhan - Chess NPC AI, Snapshot timer -// case 37440: break; -// // Karazhan - Chess NPC AI, action timer -// case 37504: break; -// // Karazhan - Chess: Is Square OCCUPIED aura (DND) -// case 39400: break; -// // Banish -// case 37546: break; -// // Shriveling Gaze -// case 37589: break; -// // Fake Aggro Radius (2 yd) -// case 37815: break; -// // Corrupt Medivh -// case 37853: break; - // Eye of Grillok - case 38495: - { - m_target->CastSpell(m_target, 38530, true); - return; - } - // Absorb Eye of Grillok (Zezzak's Shard) - case 38554: - { - if(m_target->GetTypeId() != TYPEID_UNIT) - return; - - caster->CastSpell(caster, 38495, true); - - Creature* creatureTarget = (Creature*)m_target; - - creatureTarget->setDeathState(JUST_DIED); - creatureTarget->RemoveCorpse(); - creatureTarget->SetHealth(0); // just for nice GM-mode view - return; - } -// // Magic Sucker Device timer -// case 38672: break; -// // Tomb Guarding Charging -// case 38751: break; -// // Murmur's Touch -// case 38794: break; -// // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item) -// case 39105: break; -// // Drain World Tree Visual -// case 39140: break; -// // Quest - Dustin's Undead Dragon Visual aura -// case 39259: break; -// // Hellfire - The Exorcism, Jules releases darkness, aura -// case 39306: break; -// // Inferno -// case 39346: break; -// // Enchanted Weapons -// case 39489: break; -// // Shadow Bolt Whirl -// case 39630: break; -// // Shadow Bolt Whirl -// case 39634: break; -// // Shadow Inferno -// case 39645: break; - // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam - case 39857: trigger_spell_id = 39856; break; -// // Soulgrinder Ritual Visual (Smashed) -// case 39974: break; -// // Simon Game Pre-game timer -// case 40041: break; -// // Knockdown Fel Cannon: The Aggro Check Aura -// case 40113: break; -// // Spirit Lance -// case 40157: break; -// // Demon Transform 2 -// case 40398: break; -// // Demon Transform 1 -// case 40511: break; -// // Ancient Flames -// case 40657: break; -// // Ethereal Ring Cannon: Cannon Aura -// case 40734: break; -// // Cage Trap -// case 40760: break; -// // Random Periodic -// case 40867: break; -// // Prismatic Shield -// case 40879: break; - // Aura of Desire - case 41350: - { - Unit::AuraList const& mMod = m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT); - for(Unit::AuraList::const_iterator i = mMod.begin(); i != mMod.end(); ++i) - { - if ((*i)->GetId() == 41350) - { - (*i)->ApplyModifier(false); - (*i)->GetModifier()->m_amount -= 5; - (*i)->ApplyModifier(true); - break; - } - } - }break; -// // Dementia -// case 41404: break; -// // Chaos Form -// case 41629: break; -// // Alert Drums -// case 42177: break; -// // Spout -// case 42581: break; -// // Spout -// case 42582: break; -// // Return to the Spirit Realm -// case 44035: break; -// // Curse of Boundless Agony -// case 45050: break; -// // Earthquake -// case 46240: break; - // Personalized Weather - case 46736: trigger_spell_id = 46737; break; -// // Stay Submerged -// case 46981: break; -// // Dragonblight Ram -// case 47015: break; -// // Party G.R.E.N.A.D.E. -// case 51510: break; - default: - break; - } - break; - } - case SPELLFAMILY_MAGE: - { - switch(auraId) - { - // Invisibility - case 66: - { - if(!m_duration) - m_target->CastSpell(m_target, 32612, true, NULL, this); - return; - } - default: - break; - } - break; - } -// case SPELLFAMILY_WARRIOR: -// { -// switch(auraId) -// { -// // Wild Magic -// case 23410: break; -// // Corrupted Totems -// case 23425: break; -// default: -// break; -// } -// break; -// } -// case SPELLFAMILY_PRIEST: -// { -// switch(auraId) -// { -// // Blue Beam -// case 32930: break; -// // Fury of the Dreghood Elders -// case 35460: break; -// default: -// break; -// } - // break; - // } - case SPELLFAMILY_DRUID: - { - switch(auraId) - { - // Cat Form - // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while - case 768: - return; - // Frenzied Regeneration - case 22842: - case 22895: - case 22896: - case 26999: - { - int32 LifePerRage = GetModifier()->m_amount; - - int32 lRage = m_target->GetPower(POWER_RAGE); - if(lRage > 100) // rage stored as rage*10 - lRage = 100; - m_target->ModifyPower(POWER_RAGE, -lRage); - int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10); - m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this); - return; - } - default: - break; - } - break; - } - -// case SPELLFAMILY_HUNTER: -// { -// switch(auraId) -// { -// //Frost Trap Aura -// case 13810: -// return; -// //Rizzle's Frost Trap -// case 39900: -// return; -// // Tame spells -// case 19597: // Tame Ice Claw Bear -// case 19676: // Tame Snow Leopard -// case 19677: // Tame Large Crag Boar -// case 19678: // Tame Adult Plainstrider -// case 19679: // Tame Prairie Stalker -// case 19680: // Tame Swoop -// case 19681: // Tame Dire Mottled Boar -// case 19682: // Tame Surf Crawler -// case 19683: // Tame Armored Scorpid -// case 19684: // Tame Webwood Lurker -// case 19685: // Tame Nightsaber Stalker -// case 19686: // Tame Strigid Screecher -// case 30100: // Tame Crazed Dragonhawk -// case 30103: // Tame Elder Springpaw -// case 30104: // Tame Mistbat -// case 30647: // Tame Barbed Crawler -// case 30648: // Tame Greater Timberstrider -// case 30652: // Tame Nightstalker -// return; -// default: -// break; -// } -// break; -// } - case SPELLFAMILY_SHAMAN: - { - switch(auraId) - { - // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield) - case 28820: - { - // Need remove self if Lightning Shield not active - Unit::AuraMap const& auras = target->GetAuras(); - for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - { - SpellEntry const* spell = itr->second->GetSpellProto(); - if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN && - spell->SpellFamilyFlags & 0x0000000000000400L) - return; - } - target->RemoveAurasDueToSpell(28820); - return; - } - // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus) - case 38443: - { - bool all = true; - for(int i = 0; i < MAX_TOTEM; ++i) - { - if(!caster->m_TotemSlot[i]) - { - all = false; - break; - } - } - - if(all) - caster->CastSpell(caster,38437,true); - else - caster->RemoveAurasDueToSpell(38437); - return; - } - default: - break; - } - break; - } - default: - break; - } - // Reget trigger spell proto - triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); - if(triggeredSpellInfo == NULL) - { - sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex()); - return; - } - } - else - { - // Spell exist but require custom code - switch(auraId) - { - // Curse of Idiocy - case 1010: - { - // TODO: spell casted by result in correct way mostly - // BUT: - // 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell - // but must show affect apply like item casting - // 2) maybe aura must be replace by new with accumulative stat mods instead stacking - - // prevent cast by triggered auras - if(m_caster_guid == m_target->GetGUID()) - return; - - // stop triggering after each affected stats lost > 90 - int32 intellectLoss = 0; - int32 spiritLoss = 0; - - Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT); - for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i) - { - if ((*i)->GetId() == 1010) - { - switch((*i)->GetModifier()->m_miscvalue) - { - case STAT_INTELLECT: intellectLoss += (*i)->GetModifier()->m_amount; break; - case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break; - default: break; - } - } - } - - if(intellectLoss <= -90 && spiritLoss <= -90) - return; - - caster = target; - originalCasterGUID = 0; - break; - } - // Mana Tide - case 16191: - { - caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID); - return; - } - } - } - m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, originalCasterGUID); -} - -Unit* Aura::GetTriggerTarget() const -{ - Unit* target = ObjectAccessor::GetUnit(*m_target, - /*m_target->GetTypeId()==TYPEID_PLAYER ? - ((Player*)m_target)->GetSelection() :*/ - m_target->GetUInt64Value(UNIT_FIELD_TARGET)); - return target ? target : m_target; -} - -/*********************************************************/ -/*** AURA EFFECTS ***/ -/*********************************************************/ - -void Aura::HandleAuraDummy(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - Unit* caster = GetCaster(); - - // AT APPLY - if(apply) - { - switch(GetId()) - { - case 1515: // Tame beast - // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness - if( caster && m_target->CanHaveThreatList()) - m_target->AddThreat(caster, 10.0f); - return; - case 13139: // net-o-matic - // root to self part of (root_target->charge->root_self sequence - if(caster) - caster->CastSpell(caster,13138,true,NULL,this); - return; - case 39850: // Rocket Blast - if(roll_chance_i(20)) // backfire stun - m_target->CastSpell(m_target, 51581, true, NULL, this); - return; - case 43873: // Headless Horseman Laugh - if(caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)caster)->SendPlaySound(11965, false); - return; - case 46354: // Blood Elf Illusion - if(caster) - { - switch(caster->getGender()) - { - case GENDER_FEMALE: - caster->CastSpell(m_target,46356,true,NULL,this); - break; - case GENDER_MALE: - caster->CastSpell(m_target,46355,true,NULL,this); - break; - default: - break; - } - } - return; - case 46699: // Requires No Ammo - if(m_target->GetTypeId()==TYPEID_PLAYER) - ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use - return; - } - - // Earth Shield - if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL)) - { - // prevent double apply bonuses - if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) - m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); - return; - } - } - // AT REMOVE - else - { - if( m_target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->Effect[0]==72 ) - { - // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425 - ((Player*)m_target)->ClearFarsight(); - return; - } - - if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive()) - { - uint32 finalSpelId = 0; - switch(GetId()) - { - case 19548: finalSpelId = 19597; break; - case 19674: finalSpelId = 19677; break; - case 19687: finalSpelId = 19676; break; - case 19688: finalSpelId = 19678; break; - case 19689: finalSpelId = 19679; break; - case 19692: finalSpelId = 19680; break; - case 19693: finalSpelId = 19684; break; - case 19694: finalSpelId = 19681; break; - case 19696: finalSpelId = 19682; break; - case 19697: finalSpelId = 19683; break; - case 19699: finalSpelId = 19685; break; - case 19700: finalSpelId = 19686; break; - case 30646: finalSpelId = 30647; break; - case 30653: finalSpelId = 30648; break; - case 30654: finalSpelId = 30652; break; - case 30099: finalSpelId = 30100; break; - case 30102: finalSpelId = 30103; break; - case 30105: finalSpelId = 30104; break; - } - - if(finalSpelId) - caster->CastSpell(m_target,finalSpelId,true,NULL,this); - return; - } - - // Dark Fiend - if(GetId()==45934) - { - // Kill target if dispelled - if (m_removeMode==AURA_REMOVE_BY_DISPEL) - m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - - // Burning Winds - if(GetId()==46308) // casted only at creatures at spawn - { - m_target->CastSpell(m_target,47287,true,NULL,this); - return; - } - - // Eye of Kilrogg, unsummon eye when aura is gone - if(GetId() == 126 && caster->GetTypeId() == TYPEID_PLAYER && caster->GetCharm()) - { - ((TemporarySummon*)caster->GetCharm())->UnSummon(); - return; - } - } - - // AT APPLY & REMOVE - - switch(m_spellProto->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - // Unstable Power - if( GetId()==24658 ) - { - uint32 spellId = 24659; - if (apply) - { - const SpellEntry *spell = sSpellStore.LookupEntry(spellId); - if (!spell) - return; - for (int i=0; i < spell->StackAmount; ++i) - caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); - return; - } - m_target->RemoveAurasDueToSpell(spellId); - return; - } - // Restless Strength - if( GetId()==24661 ) - { - uint32 spellId = 24662; - if (apply) - { - const SpellEntry *spell = sSpellStore.LookupEntry(spellId); - if (!spell) - return; - for (int i=0; i < spell->StackAmount; ++i) - caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); - return; - } - m_target->RemoveAurasDueToSpell(spellId); - return; - } - // Victorious - if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR) - { - m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply); - return; - } - //Summon Fire Elemental - if (GetId() == 40133 && caster) - { - Unit *owner = caster->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER) - { - if(apply) - owner->CastSpell(owner,8985,true); - else - ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - } - return; - } - - //Summon Earth Elemental - if (GetId() == 40132 && caster) - { - Unit *owner = caster->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER) - { - if(apply) - owner->CastSpell(owner,19704,true); - else - ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - } - return; - } - break; - } - case SPELLFAMILY_MAGE: - { - // Hypothermia - if( GetId()==41425 ) - { - m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply); - return; - } - break; - } - case SPELLFAMILY_DRUID: - { - // Lifebloom - if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL ) - { - if ( apply ) - { - if ( caster ) - // prevent double apply bonuses - if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) - m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); - } - else - { - // Final heal only on dispelled or duration end - if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) ) - return; - - // have a look if there is still some other Lifebloom dummy aura - Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); itr++) - if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && - (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL) - return; - - // final heal - m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); - } - return; - } - - // Predatory Strikes - if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563) - { - ((Player*)m_target)->UpdateAttackPowerAndDamage(); - return; - } - // Idol of the Emerald Queen - if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER ) - { - if(apply) - { - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_DOT; - mod->value = m_modifier.m_amount/7; - mod->type = SPELLMOD_FLAT; - mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - mod->mask = 0x001000000000LL; - mod->charges = 0; - - m_spellmod = mod; - } - - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - return; - } - break; - } - case SPELLFAMILY_HUNTER: - { - // Improved Aspect of the Viper - if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER ) - { - if(apply) - { - // + effect value for Aspect of the Viper - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_EFFECT1; - mod->value = m_modifier.m_amount; - mod->type = SPELLMOD_FLAT; - mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - mod->mask = 0x4000000000000LL; - mod->charges = 0; - - m_spellmod = mod; - } - - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - return; - } - break; - } - case SPELLFAMILY_SHAMAN: - { - // Improved Weapon Totems - if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER ) - { - if(apply) - { - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_EFFECT1; - mod->value = m_modifier.m_amount; - mod->type = SPELLMOD_PCT; - mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - switch (m_effIndex) - { - case 0: - mod->mask = 0x00200000000LL; // Windfury Totem - break; - case 1: - mod->mask = 0x00400000000LL; // Flametongue Totem - break; - } - mod->charges = 0; - - m_spellmod = mod; - } - - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - return; - } - - // Sentry Totem - if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER) - { - if (apply) - { - uint64 guid = caster->m_TotemSlot[3]; - if (guid) - { - Creature *totem = ObjectAccessor::GetCreature(*caster, guid); - if (totem && totem->isTotem()) - totem->AddPlayerToVision((Player*)caster); - } - } - else - ((Player*)caster)->RemoveFarsightTarget(); - return; - } - break; - } - } - - // pet auras - if(PetAura const* petSpell = spellmgr.GetPetAura(GetId())) - { - if(apply) - m_target->AddPetAura(petSpell); - else - m_target->RemovePetAura(petSpell); - return; - } -} - -void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - SpellEntry const*spell = GetSpellProto(); - switch( spell->SpellFamilyName) - { - case SPELLFAMILY_ROGUE: - { - // Master of Subtlety - if (spell->Id==31666 && !apply && Real) - { - m_target->RemoveAurasDueToSpell(31665); - break; - } - break; - } - case SPELLFAMILY_HUNTER: - { - // Aspect of the Viper - if (spell->SpellFamilyFlags&0x0004000000000000LL) - { - // Update regen on remove - if (!apply && m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->UpdateManaRegen(); - break; - } - break; - } - } - - m_isPeriodic = apply; -} - -void Aura::HandleAuraMounted(bool apply, bool Real) -{ - if(apply) - { - CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue); - if(!ci) - { - sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue); - return; - } - - uint32 team = 0; - if (m_target->GetTypeId()==TYPEID_PLAYER) - team = ((Player*)m_target)->GetTeam(); - - uint32 display_id = objmgr.ChooseDisplayId(team,ci); - CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); - if (minfo) - display_id = minfo->modelid; - - m_target->Mount(display_id); - } - else - { - m_target->Unmount(); - } -} - -void Aura::HandleAuraWaterWalk(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_WATER_WALK, 8+4); - else - data.Initialize(SMSG_MOVE_LAND_WALK, 8+4); - data.append(m_target->GetPackGUID()); - data << uint32(0); - m_target->SendMessageToSet(&data,true); -} - -void Aura::HandleAuraFeatherFall(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4); - else - data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4); - data.append(m_target->GetPackGUID()); - data << (uint32)0; - m_target->SendMessageToSet(&data,true); -} - -void Aura::HandleAuraHover(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_SET_HOVER, 8+4); - else - data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4); - data.append(m_target->GetPackGUID()); - data << uint32(0); - m_target->SendMessageToSet(&data,true); -} - -void Aura::HandleWaterBreathing(bool apply, bool Real) -{ - if(apply) - m_target->waterbreath = true; - else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty()) - { - m_target->waterbreath = false; - - // update for enable timer in case not moving target - if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld()) - { - ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ()); - ((Player*)m_target)->HandleDrowning(); - } - } -} - -void Aura::HandleAuraModShapeshift(bool apply, bool Real) -{ - if(!Real) - return; - - uint32 modelid = 0; - Powers PowerType = POWER_MANA; - ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue); - switch(form) - { - case FORM_CAT: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 892; - else - modelid = 8571; - PowerType = POWER_ENERGY; - break; - case FORM_TRAVEL: - modelid = 632; - break; - case FORM_AQUA: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 2428; - else - modelid = 2428; - break; - case FORM_BEAR: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 2281; - else - modelid = 2289; - PowerType = POWER_RAGE; - break; - case FORM_GHOUL: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 10045; - break; - case FORM_DIREBEAR: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 2281; - else - modelid = 2289; - PowerType = POWER_RAGE; - break; - case FORM_CREATUREBEAR: - modelid = 902; - break; - case FORM_GHOSTWOLF: - modelid = 4613; - break; - case FORM_FLIGHT: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 20857; - else - modelid = 20872; - break; - case FORM_MOONKIN: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 15374; - else - modelid = 15375; - break; - case FORM_FLIGHT_EPIC: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 21243; - else - modelid = 21244; - break; - case FORM_AMBIENT: - case FORM_SHADOW: - case FORM_STEALTH: - break; - case FORM_TREE: - modelid = 864; - break; - case FORM_BATTLESTANCE: - case FORM_BERSERKERSTANCE: - case FORM_DEFENSIVESTANCE: - PowerType = POWER_RAGE; - break; - case FORM_SPIRITOFREDEMPTION: - modelid = 16031; - break; - default: - sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue); - } - - // remove polymorph before changing display id to keep new display id - switch ( form ) - { - case FORM_CAT: - case FORM_TREE: - case FORM_TRAVEL: - case FORM_AQUA: - case FORM_BEAR: - case FORM_DIREBEAR: - case FORM_FLIGHT_EPIC: - case FORM_FLIGHT: - case FORM_MOONKIN: - // remove movement affects - m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); - m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); - - // and polymorphic affects - if(m_target->IsPolymorphed()) - m_target->RemoveAurasDueToSpell(m_target->getTransForm()); - break; - default: - break; - } - - if(apply) - { - // remove other shapeshift before applying a new one - if(m_target->m_ShapeShiftFormSpellId) - m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this); - - m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form); - - if(modelid > 0) - m_target->SetDisplayId(modelid); - - if(PowerType != POWER_MANA) - { - // reset power to default values only at power change - if(m_target->getPowerType()!=PowerType) - m_target->setPowerType(PowerType); - - switch(form) - { - case FORM_CAT: - case FORM_BEAR: - case FORM_DIREBEAR: - { - // get furor proc chance - uint32 FurorChance = 0; - Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 238) - { - FurorChance = (*i)->GetModifier()->m_amount; - break; - } - } - - if (m_modifier.m_miscvalue == FORM_CAT) - { - m_target->SetPower(POWER_ENERGY,0); - if(urand(1,100) <= FurorChance) - m_target->CastSpell(m_target,17099,true,NULL,this); - } - else - { - m_target->SetPower(POWER_RAGE,0); - if(urand(1,100) <= FurorChance) - m_target->CastSpell(m_target,17057,true,NULL,this); - } - break; - } - case FORM_BATTLESTANCE: - case FORM_DEFENSIVESTANCE: - case FORM_BERSERKERSTANCE: - { - uint32 Rage_val = 0; - // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch) - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - if(itr->second->state == PLAYERSPELL_REMOVED) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139) - Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10; - } - } - - if (m_target->GetPower(POWER_RAGE) > Rage_val) - m_target->SetPower(POWER_RAGE,Rage_val); - break; - } - default: - break; - } - } - - m_target->m_ShapeShiftFormSpellId = GetId(); - m_target->m_form = form; - } - else - { - if(modelid > 0) - m_target->SetDisplayId(m_target->GetNativeDisplayId()); - m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE); - if(m_target->getClass() == CLASS_DRUID) - m_target->setPowerType(POWER_MANA); - m_target->m_ShapeShiftFormSpellId = 0; - m_target->m_form = FORM_NONE; - - switch(form) - { - // Nordrassil Harness - bonus - case FORM_BEAR: - case FORM_DIREBEAR: - case FORM_CAT: - { - if(Aura* dummy = m_target->GetDummyAura(37315) ) - m_target->CastSpell(m_target,37316,true,NULL,dummy); - break; - } - // Nordrassil Regalia - bonus - case FORM_MOONKIN: - { - if(Aura* dummy = m_target->GetDummyAura(37324) ) - m_target->CastSpell(m_target,37325,true,NULL,dummy); - break; - } - } - } - - // adding/removing linked auras - // add/remove the shapeshift aura's boosts - HandleShapeshiftBoosts(apply); - - if(m_target->GetTypeId()==TYPEID_PLAYER) - ((Player*)m_target)->InitDataForForm(); -} - -void Aura::HandleAuraTransform(bool apply, bool Real) -{ - if (apply) - { - // special case (spell specific functionality) - if(m_modifier.m_miscvalue==0) - { - // player applied only - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - switch(GetId()) - { - // Orb of Deception - case 16739: - { - uint32 orb_model = m_target->GetNativeDisplayId(); - switch(orb_model) - { - // Troll Female - case 1479: m_target->SetDisplayId(10134); break; - // Troll Male - case 1478: m_target->SetDisplayId(10135); break; - // Tauren Male - case 59: m_target->SetDisplayId(10136); break; - // Human Male - case 49: m_target->SetDisplayId(10137); break; - // Human Female - case 50: m_target->SetDisplayId(10138); break; - // Orc Male - case 51: m_target->SetDisplayId(10139); break; - // Orc Female - case 52: m_target->SetDisplayId(10140); break; - // Dwarf Male - case 53: m_target->SetDisplayId(10141); break; - // Dwarf Female - case 54: m_target->SetDisplayId(10142); break; - // NightElf Male - case 55: m_target->SetDisplayId(10143); break; - // NightElf Female - case 56: m_target->SetDisplayId(10144); break; - // Undead Female - case 58: m_target->SetDisplayId(10145); break; - // Undead Male - case 57: m_target->SetDisplayId(10146); break; - // Tauren Female - case 60: m_target->SetDisplayId(10147); break; - // Gnome Male - case 1563: m_target->SetDisplayId(10148); break; - // Gnome Female - case 1564: m_target->SetDisplayId(10149); break; - // BloodElf Female - case 15475: m_target->SetDisplayId(17830); break; - // BloodElf Male - case 15476: m_target->SetDisplayId(17829); break; - // Dranei Female - case 16126: m_target->SetDisplayId(17828); break; - // Dranei Male - case 16125: m_target->SetDisplayId(17827); break; - default: break; - } - break; - } - // Murloc costume - case 42365: m_target->SetDisplayId(21723); break; - default: break; - } - } - else - { - CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue); - if(!ci) - { - //pig pink ^_^ - m_target->SetDisplayId(16358); - sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId()); - } - else - { - if (uint32 modelid = ci->GetRandomValidModelId()) m_target->SetDisplayId(modelid); - - // Dragonmaw Illusion (set mount model also) - if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty()) - m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); - } - m_target->setTransForm(GetId()); - } - - // polymorph case - if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed()) - { - // for players, start regeneration after 1s (in polymorph fast regeneration case) - // only if caster is Player (after patch 2.4.2) - if(IS_PLAYER_GUID(GetCasterGUID()) ) - ((Player*)m_target)->setRegenTimer(1000); - - //dismount polymorphed target (after patch 2.4.2) - if (m_target->IsMounted()) - m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); - } - } - else - { - Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM); - if(otherTransforms.empty()) - { - m_target->SetDisplayId(m_target->GetNativeDisplayId()); - m_target->setTransForm(0); - } - else - { - // look for other transform auras - Aura* handledAura = *otherTransforms.begin(); - for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i) - { - // negative auras are preferred - if(!IsPositiveSpell((*i)->GetSpellProto()->Id)) - { - handledAura = *i; - break; - } - } - handledAura->ApplyModifier(true); - } - - // Dragonmaw Illusion (restore mount model) - if(GetId()==42016 && m_target->GetMountID()==16314) - { - if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty()) - { - uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue; - if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id)) - { - uint32 team = 0; - if (m_target->GetTypeId()==TYPEID_PLAYER) - team = ((Player*)m_target)->GetTeam(); - - uint32 display_id = objmgr.ChooseDisplayId(team,ci); - CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id); - if (minfo) - display_id = minfo->modelid; - - m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id); - } - } - } - } -} - -void Aura::HandleForceReaction(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if(!Real) - return; - - Player* player = (Player*)m_target; - - uint32 faction_id = m_modifier.m_miscvalue; - uint32 faction_rank = m_modifier.m_amount; - - if(apply) - player->m_forcedReactions[faction_id] = ReputationRank(faction_rank); - else - player->m_forcedReactions.erase(faction_id); - - WorldPacket data; - data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4)); - data << uint32(player->m_forcedReactions.size()); - for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr) - { - data << uint32(itr->first); // faction_id (Faction.dbc) - data << uint32(itr->second); // reputation rank - } - player->SendDirectMessage(&data); -} - -void Aura::HandleAuraModSkill(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex]; - int32 points = GetModifier()->m_amount; - - ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT); - if(prot == SKILL_DEFENSE) - ((Player*)m_target)->UpdateDefenseBonusesMod(); -} - -void Aura::HandleChannelDeathItem(bool apply, bool Real) -{ - if(Real && !apply) - { - Unit* caster = GetCaster(); - Unit* victim = GetTarget(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH) - return; - - SpellEntry const *spellInfo = GetSpellProto(); - if(spellInfo->EffectItemType[m_effIndex] == 0) - return; - - // Soul Shard only from non-grey units - if( spellInfo->EffectItemType[m_effIndex] == 6265 && - (victim->getLevel() <= Trinity::XP::GetGrayLevel(caster->getLevel()) || - victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) ) - return; - ItemPosCountVec dest; - uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 ); - if( msg != EQUIP_ERR_OK ) - { - ((Player*)caster)->SendEquipError( msg, NULL, NULL ); - return; - } - - Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true); - ((Player*)caster)->SendNewItem(newitem, 1, true, false); - } -} - -void Aura::HandleBindSight(bool apply, bool Real) -{ - Unit* caster = GetCaster(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; - - if (apply) - m_target->AddPlayerToVision((Player*)caster); - else - m_target->RemovePlayerFromVision((Player*)caster); -} - -void Aura::HandleFarSight(bool apply, bool Real) -{ - Unit* caster = GetCaster(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; - - caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_modifier.m_miscvalue : 0); -} - -void Aura::HandleAuraTrackCreatures(bool apply, bool Real) -{ - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - if(apply) - m_target->RemoveNoStackAurasDueToAura(this); - m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 ); -} - -void Aura::HandleAuraTrackResources(bool apply, bool Real) -{ - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - if(apply) - m_target->RemoveNoStackAurasDueToAura(this); - m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 ); -} - -void Aura::HandleAuraTrackStealthed(bool apply, bool Real) -{ - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - if(apply) - m_target->RemoveNoStackAurasDueToAura(this); - - m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply); -} - -void Aura::HandleAuraModScale(bool apply, bool Real) -{ - m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply); -} - -void Aura::HandleModPossess(bool apply, bool Real) -{ - if(!Real) - return; - - if(m_target->getLevel() > m_modifier.m_amount) - return; - - // not possess yourself - if(GetCasterGUID() == m_target->GetGUID()) - return; - - Unit* caster = GetCaster(); - if(!caster) - return; - - if( apply ) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)caster)->Possess(m_target); - } - else - m_target->UnpossessSelf(true); -} - -void Aura::HandleModPossessPet(bool apply, bool Real) -{ - if(!Real) - return; - - Unit* caster = GetCaster(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; - if(caster->GetPet() != m_target) - return; - - if(apply) - { - ((Player*)caster)->Possess(m_target); - } - else - { - ((Player*)caster)->RemovePossess(false); - } -} - -void Aura::HandleModCharm(bool apply, bool Real) -{ - if(!Real) - return; - - // not charm yourself - if(GetCasterGUID() == m_target->GetGUID()) - return; - - Unit* caster = GetCaster(); - if(!caster) - return; - - if(int32(m_target->getLevel()) <= m_modifier.m_amount) - { - if( apply ) - { - m_target->SetCharmerGUID(GetCasterGUID()); - m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction()); - m_target->CastStop(m_target==caster ? GetId() : 0); - caster->SetCharm(m_target); - - m_target->CombatStop(); - m_target->DeleteThreatList(); - - if(m_target->GetTypeId() == TYPEID_UNIT) - { - ((Creature*)m_target)->AIM_Initialize(); - CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target); - charmInfo->InitCharmCreateSpells(); - charmInfo->SetReactState( REACT_DEFENSIVE ); - - if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK) - { - CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); - if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) - { - //to prevent client crash - m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); - //just to enable stat window - charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); - //if charmed two demons the same session, the 2nd gets the 1st one's name - m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); - } - } - } - - if(caster->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)caster)->CharmSpellInitialize(); - } - } - else - { - m_target->SetCharmerGUID(0); - - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->setFactionForRace(m_target->getRace()); - else - { - CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); - - // restore faction - if(((Creature*)m_target)->isPet()) - { - if(Unit* owner = m_target->GetOwner()) - m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction()); - else if(cinfo) - m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A); - } - else if(cinfo) // normal creature - m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A); - - // restore UNIT_FIELD_BYTES_0 - if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) - { - CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); - if(cainfo && cainfo->bytes0 != 0) - m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); - else - m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048); - - if(m_target->GetCharmInfo()) - m_target->GetCharmInfo()->SetPetNumber(0, true); - else - sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId()); - } - } - - caster->SetCharm(0); - - if(caster->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_PET_SPELLS, 8); - data << uint64(0); - ((Player*)caster)->GetSession()->SendPacket(&data); - } - if(m_target->GetTypeId() == TYPEID_UNIT) - { - ((Creature*)m_target)->AIM_Initialize(); - if (((Creature*)m_target)->AI()) - ((Creature*)m_target)->AI()->AttackStart(caster); - } - } - } -} - -void Aura::HandleModConfuse(bool apply, bool Real) -{ - if(!Real) - return; - - m_target->SetConfused(apply, GetCasterGUID(), GetId()); -} - -void Aura::HandleModFear(bool apply, bool Real) -{ - if (!Real) - return; - - m_target->SetFeared(apply, GetCasterGUID(), GetId()); -} - -void Aura::HandleFeignDeath(bool apply, bool Real) -{ - if(!Real) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if( apply ) - { - /* - WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); - data<<m_target->GetGUID(); - data<<uint8(0); - m_target->SendMessageToSet(&data,true); - */ - // blizz like 2.0.x - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); - // blizz like 2.0.x - m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - // blizz like 2.0.x - m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - - m_target->addUnitState(UNIT_STAT_DIED); - m_target->CombatStop(); - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); - - // prevent interrupt message - if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL]) - m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish(); - m_target->InterruptNonMeleeSpells(true); - m_target->getHostilRefManager().deleteReferences(); - } - else - { - /* - WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9); - data<<m_target->GetGUID(); - data<<uint8(1); - m_target->SendMessageToSet(&data,true); - */ - // blizz like 2.0.x - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); - // blizz like 2.0.x - m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - // blizz like 2.0.x - m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); - - m_target->clearUnitState(UNIT_STAT_DIED); - } -} - -void Aura::HandleAuraModDisarm(bool apply, bool Real) -{ - if(!Real) - return; - - if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM)) - return; - - // not sure for it's correctness - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); - - // only at real add/remove aura - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove. - if (((Player *)m_target)->IsInFeralForm()) - return; - - if (apply) - m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME); - else - ((Player *)m_target)->SetRegularAttackTime(); - - m_target->UpdateDamagePhysical(BASE_ATTACK); -} - -void Aura::HandleAuraModStun(bool apply, bool Real) -{ - if(!Real) - return; - - if (apply) - { - m_target->addUnitState(UNIT_STAT_STUNNED); - m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); - m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0); - - // Creature specific - if(m_target->GetTypeId() != TYPEID_PLAYER) - ((Creature*)m_target)->StopMoving(); - else - m_target->SetUnitMovementFlags(0); //Clear movement flags - - WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8); - - data.append(m_target->GetPackGUID()); - data << uint32(0); - m_target->SendMessageToSet(&data,true); - } - else - { - // Real remove called after current aura remove from lists, check if other similar auras active - if(m_target->HasAuraType(SPELL_AURA_MOD_STUN)) - return; - - m_target->clearUnitState(UNIT_STAT_STUNNED); - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); - - if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect - { - if(m_target->getVictim() && m_target->isAlive()) - m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() ); - - WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4); - data.append(m_target->GetPackGUID()); - data << uint32(0); - m_target->SendMessageToSet(&data,true); - } - - // Wyvern Sting - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721) - { - Unit* caster = GetCaster(); - if( !caster || caster->GetTypeId()!=TYPEID_PLAYER ) - return; - - uint32 spell_id = 0; - - switch(GetId()) - { - case 19386: spell_id = 24131; break; - case 24132: spell_id = 24134; break; - case 24133: spell_id = 24135; break; - case 27068: spell_id = 27069; break; - default: - sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId()); - return; - } - - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id); - - if(!spellInfo) - return; - - caster->CastSpell(m_target,spellInfo,true,NULL,this); - return; - } - } -} - -void Aura::HandleModStealth(bool apply, bool Real) -{ - if(apply) - { - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) - { - // drop flag at stealth in bg - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); - - // remove player from the objective's active player count at stealth - if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) - pvp->HandlePlayerActivityChanged((Player*)m_target); - } - - // only at real aura add - if(Real) - { - m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02); - if(m_target->GetTypeId()==TYPEID_PLAYER) - m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); - - // apply only if not in GM invisibility (and overwrite invisibility state) - if(m_target->GetVisibility()!=VISIBILITY_OFF) - { - //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); - m_target->SetVisibility(VISIBILITY_OFF); - m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); - } - - // for RACE_NIGHTELF stealth - if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) - m_target->CastSpell(m_target, 21009, true, NULL, this); - } - } - else - { - // only at real aura remove - if(Real) - { - // for RACE_NIGHTELF stealth - if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) - m_target->RemoveAurasDueToSpell(21009); - - // if last SPELL_AURA_MOD_STEALTH and no GM invisibility - if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF) - { - m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00); - if(m_target->GetTypeId()==TYPEID_PLAYER) - m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); - - // restore invisibility if any - if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY)) - { - //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); - //m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); - m_target->SetVisibility(VISIBILITY_ON); - } - else - { - m_target->SetVisibility(VISIBILITY_ON); - if(m_target->GetTypeId() == TYPEID_PLAYER) - if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) - pvp->HandlePlayerActivityChanged((Player*)m_target); - } - } - } - } - - // Master of Subtlety - Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 2114) - { - if (apply) - { - int32 bp = (*i)->GetModifier()->m_amount; - m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true); - } - else - m_target->CastSpell(m_target,31666,true); - break; - } - } -} - -void Aura::HandleInvisibility(bool apply, bool Real) -{ - if(apply) - { - m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); - - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); - - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) - { - // apply glow vision - m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); - // remove player from the objective's active player count at invisibility - if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) - pvp->HandlePlayerActivityChanged((Player*)m_target); - } - - // apply only if not in GM invisibility and not stealth - if(m_target->GetVisibility()==VISIBILITY_ON) - { - // Aura not added yet but visibility code expect temporary add aura - //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); - //m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); - m_target->SetVisibility(VISIBILITY_ON); - } - } - else - { - // recalculate value at modifier remove (current aura already removed) - m_target->m_invisibilityMask = 0; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); - - // only at real aura remove and if not have different invisibility auras. - if(Real && m_target->m_invisibilityMask==0) - { - // remove glow vision - if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); - - // apply only if not in GM invisibility & not stealthed while invisible - if(m_target->GetVisibility()!=VISIBILITY_OFF) - { - // if have stealth aura then already have stealth visibility - if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) - { - m_target->SetVisibility(VISIBILITY_ON); - if(m_target->GetTypeId() == TYPEID_PLAYER) - if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) - pvp->HandlePlayerActivityChanged((Player*)m_target); - } - } - } - } -} - -void Aura::HandleInvisibilityDetect(bool apply, bool Real) -{ - if(apply) - { - m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); - } - else - { - // recalculate value at modifier remove (current aura already removed) - m_target->m_detectInvisibilityMask = 0; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); - } - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) - ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target); -} - -void Aura::HandleAuraModRoot(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - uint32 apply_stat = UNIT_STAT_ROOT; - if (apply) - { - m_target->addUnitState(UNIT_STAT_ROOT); - m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0); - // probably wrong - m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16)); - - //Save last orientation - if( m_target->getVictim() ) - m_target->SetOrientation(m_target->GetAngle(m_target->getVictim())); - - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10); - data.append(m_target->GetPackGUID()); - data << (uint32)2; - m_target->SendMessageToSet(&data,true); - - //Clear unit movement flags - m_target->SetUnitMovementFlags(0); - } - else - ((Creature *)m_target)->StopMoving(); - } - else - { - // Real remove called after current aura remove from lists, check if other similar auras active - if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT)) - return; - - m_target->clearUnitState(UNIT_STAT_ROOT); - // probably wrong - m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16)); - - if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect - { - if(m_target->getVictim() && m_target->isAlive()) - m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() ); - - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10); - data.append(m_target->GetPackGUID()); - data << (uint32)2; - m_target->SendMessageToSet(&data,true); - } - } - } -} - -void Aura::HandleAuraModSilence(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - if(apply) - { - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); - // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE - for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++) - { - Spell* currentSpell = m_target->m_currentSpells[i]; - if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) - { - uint32 state = currentSpell->getState(); - // Stop spells on prepare or casting state - if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING ) - { - currentSpell->cancel(); - currentSpell->SetReferencedFromCurrent(false); - m_target->m_currentSpells[i] = NULL; - } - } - } - - switch (GetId()) - { - // Arcane Torrent (Energy) - case 25046: - { - Unit * caster = GetCaster(); - if (!caster) - return; - - // Search Mana Tap auras on caster - int32 energy = 0; - Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) - if ((*i)->GetId() == 28734) - ++energy; - if (energy) - { - energy *= 10; - caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true); - caster->RemoveAurasDueToSpell(28734); - } - } - } - } - else - { - // Real remove called after current aura remove from lists, check if other similar auras active - if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE)) - return; - - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); - } -} - -void Aura::HandleModThreat(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - if(!m_target->isAlive()) - return; - - Unit* caster = GetCaster(); - - if(!caster || !caster->isAlive()) - return; - - int level_diff = 0; - int multiplier = 0; - switch (GetId()) - { - // Arcane Shroud - case 26400: - level_diff = m_target->getLevel() - 60; - multiplier = 2; - break; - // The Eye of Diminution - case 28862: - level_diff = m_target->getLevel() - 60; - multiplier = 1; - break; - } - if (level_diff > 0) - m_modifier.m_amount += multiplier * level_diff; - - for(int8 x=0;x < MAX_SPELL_SCHOOL;x++) - { - if(m_modifier.m_miscvalue & int32(1<<x)) - { - if(m_target->GetTypeId() == TYPEID_PLAYER) - ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply); - } - } -} - -void Aura::HandleAuraModTotalThreat(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER) - return; - - Unit* caster = GetCaster(); - - if(!caster || !caster->isAlive()) - return; - - float threatMod = 0.0f; - if(apply) - threatMod = float(m_modifier.m_amount); - else - threatMod = float(-m_modifier.m_amount); - - m_target->getHostilRefManager().threatAssist(caster, threatMod); -} - -void Aura::HandleModTaunt(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - if(!m_target->isAlive() || !m_target->CanHaveThreatList()) - return; - - Unit* caster = GetCaster(); - - if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER) - return; - - if(apply) - m_target->TauntApply(caster); - else - { - // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat - m_target->TauntFadeOut(caster); - } -} - -/*********************************************************/ -/*** MODIFY SPEED ***/ -/*********************************************************/ -void Aura::HandleAuraModIncreaseSpeed(bool apply, bool Real) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - m_target->UpdateSpeed(MOVE_RUN, true); -} - -void Aura::HandleAuraModIncreaseMountedSpeed(bool apply, bool Real) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - m_target->UpdateSpeed(MOVE_RUN, true); -} - -void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - // Enable Fly mode for flying mounts - if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) - { - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); - else - data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); - data.append(m_target->GetPackGUID()); - data << uint32(0); // unknown - m_target->SendMessageToSet(&data, true); - - //Players on flying mounts must be immune to polymorph - if (m_target->GetTypeId()==TYPEID_PLAYER) - m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply); - - // Dragonmaw Illusion (overwrite mount model, mounted aura already applied) - if( apply && m_target->HasAura(42016,0) && m_target->GetMountID()) - m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); - } - - m_target->UpdateSpeed(MOVE_FLY, true); -} - -void Aura::HandleAuraModIncreaseSwimSpeed(bool apply, bool Real) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - m_target->UpdateSpeed(MOVE_SWIM, true); -} - -void Aura::HandleAuraModDecreaseSpeed(bool apply, bool Real) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - m_target->UpdateSpeed(MOVE_RUN, true); - m_target->UpdateSpeed(MOVE_SWIM, true); - m_target->UpdateSpeed(MOVE_FLY, true); -} - -void Aura::HandleAuraModUseNormalSpeed(bool apply, bool Real) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - m_target->UpdateSpeed(MOVE_RUN, true); - m_target->UpdateSpeed(MOVE_SWIM, true); - m_target->UpdateSpeed(MOVE_FLY, true); -} - -/*********************************************************/ -/*** IMMUNITY ***/ -/*********************************************************/ - -void Aura::HandleModMechanicImmunity(bool apply, bool Real) -{ - uint32 mechanic = 1 << m_modifier.m_miscvalue; - - //immune movement impairment and loss of control - if(GetId()==42292) - mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; - - if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) - { - Unit::AuraMap& Auras = m_target->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) - { - next = iter; - ++next; - SpellEntry const *spell = iter->second->GetSpellProto(); - if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability - && !iter->second->IsPositive() // only remove negative spells - && spell->Id != GetId()) - { - //check for mechanic mask - if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic) - { - m_target->RemoveAurasDueToSpell(spell->Id); - if(Auras.empty()) - break; - else - next = Auras.begin(); - } - } - } - } - - m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply); - - // special cases - switch(m_modifier.m_miscvalue) - { - case MECHANIC_INVULNERABILITY: - m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply); - break; - case MECHANIC_SHIELD: - m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply); - break; - } - - // Bestial Wrath - if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->Id == 19574) - { - // The Beast Within cast on owner if talent present - if ( Unit* owner = m_target->GetOwner() ) - { - // Search talent - Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) - { - if ( (*i)->GetSpellProto()->SpellIconID == 2229 ) - { - if (apply) - owner->CastSpell(owner, 34471, true, 0, this); - else - owner->RemoveAurasDueToSpell(34471); - break; - } - } - } - } - - // The Beast Within and Bestial Wrath - immunity - if(GetId() == 19574 || GetId() == 34471) - { - if(apply) - { - m_target->CastSpell(m_target,24395,true); - m_target->CastSpell(m_target,24396,true); - m_target->CastSpell(m_target,24397,true); - m_target->CastSpell(m_target,26592,true); - } - else - { - m_target->RemoveAurasDueToSpell(24395); - m_target->RemoveAurasDueToSpell(24396); - m_target->RemoveAurasDueToSpell(24397); - m_target->RemoveAurasDueToSpell(26592); - } - } -} - -void Aura::HandleAuraModEffectImmunity(bool apply, bool Real) -{ - if(!apply) - { - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - if(((Player*)m_target)->InBattleGround()) - { - BattleGround *bg = ((Player*)m_target)->GetBattleGround(); - if(bg) - { - switch(bg->GetTypeID()) - { - case BATTLEGROUND_AV: - { - break; - } - case BATTLEGROUND_WS: - { - // Warsong Flag, horde // Silverwing Flag, alliance - if(GetId() == 23333 || GetId() == 23335) - bg->EventPlayerDroppedFlag(((Player*)m_target)); - break; - } - case BATTLEGROUND_AB: - { - break; - } - case BATTLEGROUND_EY: - { - if(GetId() == 34976) - bg->EventPlayerDroppedFlag(((Player*)m_target)); - break; - } - } - } - } - else - sOutdoorPvPMgr.HandleDropFlag((Player*)m_target,GetSpellProto()->Id); - } - } - - m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply); -} - -void Aura::HandleAuraModStateImmunity(bool apply, bool Real) -{ - if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) - { - Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue)); - for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();) - { - if (auraList.front() != this) // skip itself aura (it already added) - { - m_target->RemoveAurasDueToSpell(auraList.front()->GetId()); - itr = auraList.begin(); - } - else - ++itr; - } - } - - m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply); -} - -void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real) -{ - if(apply && m_modifier.m_miscvalue == SPELL_SCHOOL_MASK_NORMAL) - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); - - m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply); - - if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) - { - if(IsPositiveSpell(GetId())) //Only positive immunity removes auras - { - uint32 school_mask = m_modifier.m_miscvalue; - Unit::AuraMap& Auras = m_target->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) - { - next = iter; - ++next; - SpellEntry const *spell = iter->second->GetSpellProto(); - if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask - && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability - && !iter->second->IsPositive() //Don't remove positive spells - && spell->Id != GetId() ) //Don't remove self - { - m_target->RemoveAurasDueToSpell(spell->Id); - if(Auras.empty()) - break; - else - next = Auras.begin(); - } - } - } - } - if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH ) - { - if( apply ) - m_target->addUnitState(UNIT_STAT_ISOLATED); - else - m_target->clearUnitState(UNIT_STAT_ISOLATED); - } -} - -void Aura::HandleAuraModDmgImmunity(bool apply, bool Real) -{ - m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply); -} - -void Aura::HandleAuraModDispelImmunity(bool apply, bool Real) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply); -} - -void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real) -{ - if(!Real) - return; - - if(apply) - { - // some spell have charges by functionality not have its in spell data - switch (GetId()) - { - case 28200: // Ascendance (Talisman of Ascendance trinket) - m_procCharges = 6; - UpdateAuraCharges(); - break; - default: break; - } - } -} - -void Aura::HandleAuraModStalked(bool apply, bool Real) -{ - // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND - if(apply) - m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); - else - m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT); -} - -/*********************************************************/ -/*** PERIODIC ***/ -/*********************************************************/ - -void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; - m_isTrigger = apply; - - // Curse of the Plaguebringer - if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL) - { - // Cast Wrath of the Plaguebringer if not dispelled - m_target->CastSpell(m_target, 29214, true, 0, this); - } -} - -void Aura::HandlePeriodicEnergize(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; -} - -void Aura::HandlePeriodicHeal(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; - - // only at real apply - if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE) - { - // provided m_target as original caster to prevent apply aura caster selection for this negative buff - m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID()); - } - - // For prevent double apply bonuses - bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); - - if(!loading && apply) - { - switch (m_spellProto->SpellFamilyName) - { - case SPELLFAMILY_DRUID: - { - // Rejuvenation - if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL) - { - if(Unit* caster = GetCaster()) - { - Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) - { - int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; - switch((*k)->GetModifier()->m_miscvalue) - { - case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura - case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura - { - m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; - break; - } - } - } - } - } - } - } - } -} - -void Aura::HandlePeriodicDamage(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; - - // For prevent double apply bonuses - bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); - - Unit *caster = GetCaster(); - - switch (m_spellProto->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - // Pounce Bleed - if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 ) - { - // $AP*0.18/6 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); - return; - } - break; - } - case SPELLFAMILY_WARRIOR: - { - // Rend - if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) - { - // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick - if (apply && !loading && caster) - { - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 mws = caster->GetAttackTime(BASE_ATTACK); - float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); - float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); - // WARNING! in 3.0 multiplier 0.00743f change to 0.6 - m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f); - } - return; - } - break; - } - case SPELLFAMILY_DRUID: - { - // Rake - if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL) - { - // $AP*0.06/3 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100); - return; - } - // Lacerate - if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL) - { - // $AP*0.05/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); - return; - } - // Rip - if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL) - { - // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used] - if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - uint8 cp = ((Player*)caster)->GetComboPoints(); - - // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs - Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) - { - if((*itr)->GetId()==34241) - { - m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount; - break; - } - } - - if (cp > 4) cp = 4; - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); - } - return; - } - break; - } - case SPELLFAMILY_ROGUE: - { - // Deadly poison aura state - if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100) - { - if(apply) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true); - else - { - // current aura already removed, search present of another - bool found = false; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - { - SpellEntry const* itr_spell = (*itr)->GetSpellProto(); - if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100) - { - found = true; - break; - } - } - // this has been last deadly poison aura - if(!found) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false); - } - return; - } - // Rupture - if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL) - { - // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP] - if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - uint8 cp = ((Player*)caster)->GetComboPoints(); - if (cp > 3) cp = 3; - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); - } - return; - } - // Garrote - if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL) - { - // $AP*0.18/6 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); - return; - } - break; - } - case SPELLFAMILY_HUNTER: - { - // Serpent Sting - if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL) - { - // $RAP*0.1/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); - return; - } - // Immolation Trap - if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678) - { - // $RAP*0.1/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); - return; - } - break; - } - case SPELLFAMILY_PALADIN: - { - // Consecration - if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) - { - if (apply && !loading) - { - if(Unit* caster = GetCaster()) - { - Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) - { - int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; - switch((*k)->GetModifier()->m_miscvalue) - { - case 5147: // Improved Consecration - Libram of the Eternal Rest - { - m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; - break; - } - } - } - } - } - return; - } - break; - } - default: - break; - } -} - -void Aura::HandlePeriodicDamagePCT(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; -} - -void Aura::HandlePeriodicLeech(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; -} - -void Aura::HandlePeriodicManaLeech(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; -} - -/*********************************************************/ -/*** MODIFY STATS ***/ -/*********************************************************/ - -/********************************/ -/*** RESISTANCE ***/ -/********************************/ - -void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real) -{ - for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) - { - if(m_modifier.m_miscvalue & int32(1<<x)) - { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply); - } - } -} - -void Aura::HandleAuraModResistance(bool apply, bool Real) -{ - for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) - { - if(m_modifier.m_miscvalue & int32(1<<x)) - { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply); - } - } - - // Faerie Fire (druid versions) - if( m_spellProto->SpellIconID == 109 && - m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && - m_spellProto->SpellFamilyFlags & 0x0000000000000400LL ) - { - m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply); - } -} - -void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real) -{ - // only players have base stats - if(m_target->GetTypeId() != TYPEID_PLAYER) - { - //pets only have base armor - if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply); - } - else - { - for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) - { - if(m_modifier.m_miscvalue & int32(1<<x)) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply); - } - } -} - -void Aura::HandleModResistancePercent(bool apply, bool Real) -{ - for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) - { - if(m_modifier.m_miscvalue & int32(1<<i)) - { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - { - m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply); - m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply); - } - } - } -} - -void Aura::HandleModBaseResistance(bool apply, bool Real) -{ - // only players have base stats - if(m_target->GetTypeId() != TYPEID_PLAYER) - { - //only pets have base stats - if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply); - } - else - { - for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) - if(m_modifier.m_miscvalue & (1<<i)) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply); - } -} - -/********************************/ -/*** STAT ***/ -/********************************/ - -void Aura::HandleAuraModStat(bool apply, bool Real) -{ - if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4) - { - sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue); - return; - } - - for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++) - { - // -1 or -2 is all stats ( misc < -2 checked in function beginning ) - if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i) - { - //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply); - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply); - } - } -} - -void Aura::HandleModPercentStat(bool apply, bool Real) -{ - if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); - return; - } - - // only players have base stats - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) - { - if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply); - } -} - -void Aura::HandleModSpellDamagePercentFromStat(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Magic damage modifiers implemented in Unit::SpellDamageBonus - // This information for client side use only - // Recalculate bonus - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void Aura::HandleModSpellHealingPercentFromStat(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Recalculate bonus - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void Aura::HandleAuraModDispelResist(bool apply, bool Real) -{ - if(!Real || !apply) - return; - - if(GetId()==33206) - m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID()); -} - -void Aura::HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Magic damage modifiers implemented in Unit::SpellDamageBonus - // This information for client side use only - // Recalculate bonus - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void Aura::HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Recalculate bonus - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void Aura::HandleModHealingDone(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - // implemented in Unit::SpellHealingBonus - // this information is for client side only - ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); -} - -void Aura::HandleModTotalPercentStat(bool apply, bool Real) -{ - if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); - return; - } - - //save current and max HP before applying aura - uint32 curHPValue = m_target->GetHealth(); - uint32 maxHPValue = m_target->GetMaxHealth(); - - for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) - { - if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) - { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply); - if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply ); - } - } - - //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag) - if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10)) - { - // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed - uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue; - m_target->SetHealth(newHPValue); - } -} - -void Aura::HandleAuraModResistenceOfStatPercent(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL) - { - // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update - // and include in UpdateResistence same code as in UpdateArmor for aura mod apply. - sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!"); - return; - } - - // Recalculate Armor - m_target->UpdateArmor(); -} - -/********************************/ -/*** HEAL & ENERGIZE ***/ -/********************************/ -void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real) -{ - /* - Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic, - so this aura not fully working. - */ - if(apply) - { - if(!m_target->isAlive()) - return; - - if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - - if(m_periodicTimer <= 0) - { - m_periodicTimer += m_modifier.periodictime; - - if(m_target->GetHealth() < m_target->GetMaxHealth()) - { - // PeriodicTick can cast triggered spells with stats changes - PeriodicTick(); - } - } - } - - m_isPeriodic = apply; -} - -void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real) -{ - if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - if(apply) - { - if(m_modifier.periodictime == 0) - m_modifier.periodictime = 1000; - if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA) - { - m_periodicTimer += m_modifier.periodictime; - - if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA)) - { - // PeriodicTick can cast triggered spells with stats changes - PeriodicTick(); - } - } - } - - m_isPeriodic = apply; -} - -void Aura::HandleModRegen(bool apply, bool Real) // eating -{ - if(apply) - { - if(!m_target->isAlive()) - return; - - if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - - if(m_periodicTimer <= 0) - { - m_periodicTimer += 5000; - int32 gain = m_target->ModifyHealth(m_modifier.m_amount); - Unit *caster = GetCaster(); - if (caster) - { - SpellEntry const *spellProto = GetSpellProto(); - if (spellProto) - m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto); - } - } - } - - m_isPeriodic = apply; -} - -void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking -{ - if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - - if(apply && m_periodicTimer <= 0) - { - m_periodicTimer += 2000; - - Powers pt = m_target->getPowerType(); - if(int32(pt) != m_modifier.m_miscvalue) - return; - - if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED ) - { - // eating anim - m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT); - } - else if( GetId() == 20577 ) - { - // cannibalize anim - m_target->HandleEmoteCommand(398); - } - - // Warrior talent, gain 1 rage every 3 seconds while in combat - if(pt == POWER_RAGE && m_target->isInCombat()) - { - m_target->ModifyPower(pt, m_modifier.m_amount*10/17); - m_periodicTimer += 1000; - } - } - m_isPeriodic = apply; - if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA) - ((Player*)m_target)->UpdateManaRegen(); -} - -void Aura::HandleModPowerRegenPCT(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - // Update manaregen value - if (m_modifier.m_miscvalue == POWER_MANA) - ((Player*)m_target)->UpdateManaRegen(); -} - -void Aura::HandleModManaRegen(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - - //Note: an increase in regen does NOT cause threat. - ((Player*)m_target)->UpdateManaRegen(); -} - -void Aura::HandleComprehendLanguage(bool apply, bool Real) -{ - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); -} - -void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real) -{ - if(Real) - { - if(apply) - { - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); - m_target->ModifyHealth(m_modifier.m_amount); - } - else - { - if (int32(m_target->GetHealth()) > m_modifier.m_amount) - m_target->ModifyHealth(-m_modifier.m_amount); - else - m_target->SetHealth(1); - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); - } - } -} - -void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real) -{ - uint32 oldhealth = m_target->GetHealth(); - double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth(); - - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); - - // refresh percentage - if(oldhealth > 0) - { - uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)); - if(newhealth==0) - newhealth = 1; - - m_target->SetHealth(newhealth); - } -} - -void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real) -{ - Powers powerType = m_target->getPowerType(); - if(int32(powerType) != m_modifier.m_miscvalue) - return; - - m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_VALUE, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool Real) -{ - Powers powerType = m_target->getPowerType(); - if(int32(powerType) != m_modifier.m_miscvalue) - return; - - m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_PCT, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool Real) -{ - //m_target->ApplyMaxHealthPercentMod(m_modifier.m_amount,apply); - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply); -} - -/********************************/ -/*** FIGHT ***/ -/********************************/ - -void Aura::HandleAuraModParryPercent(bool apply, bool Real) -{ - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateParryPercentage(); -} - -void Aura::HandleAuraModDodgePercent(bool apply, bool Real) -{ - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateDodgePercentage(); - //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount)); -} - -void Aura::HandleAuraModBlockPercent(bool apply, bool Real) -{ - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateBlockPercentage(); - //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount)); -} - -void Aura::HandleAuraModRegenInterrupt(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateManaRegen(); -} - -void Aura::HandleAuraModCritPercent(bool apply, bool Real) -{ - if(m_target->GetTypeId()!=TYPEID_PLAYER) - return; - - // apply item specific bonuses for already equipped weapon - if(Real) - { - for(int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) - ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply); - } - - // mods must be applied base at equipped weapon class and subclass comparison - // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // m_modifier.m_miscvalue comparison with item generated damage types - - if (GetSpellProto()->EquippedItemClass == -1) - { - ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); - ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); - ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods - } -} - -void Aura::HandleModHitChance(bool apply, bool Real) -{ - m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); - m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); -} - -void Aura::HandleModSpellHitChance(bool apply, bool Real) -{ - m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount); -} - -void Aura::HandleModSpellCritChance(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)m_target)->UpdateAllSpellCritChances(); - } - else - { - m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount); - } -} - -void Aura::HandleModSpellCritChanceShool(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school) - if (m_modifier.m_miscvalue & (1<<school)) - ((Player*)m_target)->UpdateSpellCritChance(school); -} - -/********************************/ -/*** ATTACK SPEED ***/ -/********************************/ - -void Aura::HandleModCastingSpeed(bool apply, bool Real) -{ - m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply); -} - -void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real) -{ - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); -} - -void Aura::HandleModCombatSpeedPct(bool apply, bool Real) -{ - m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply); - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); -} - -void Aura::HandleModAttackSpeed(bool apply, bool Real) -{ - if(!m_target->isAlive() ) - return; - - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); -} - -void Aura::HandleHaste(bool apply, bool Real) -{ - m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply); -} - -void Aura::HandleAuraModRangedHaste(bool apply, bool Real) -{ - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); -} - -void Aura::HandleRangedAmmoHaste(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply); -} - -/********************************/ -/*** ATTACK POWER ***/ -/********************************/ - -void Aura::HandleAuraModAttackPower(bool apply, bool Real) -{ - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real) -{ - if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) - return; - - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraAttackPowerAttacker(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - Unit *caster = GetCaster(); - - if (!caster) - return; - - // Hunter's Mark - if (m_spellProto->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) - { - // Check Improved Hunter's Mark bonus on caster - Unit::AuraList const& mOverrideClassScript = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) - { - Modifier* mod = (*i)->GetModifier(); - // mproved Hunter's Mark script from 5236 to 5240 - if (mod->m_miscvalue >= 5236 && mod->m_miscvalue <= 5240) - { - // Get amount of ranged bonus for this spell.. - int32 ranged_bonus = caster->CalculateSpellDamage(m_spellProto, 1, m_spellProto->EffectBasePoints[1], m_target); - // Set melee attack power bonus % from ranged depends from Improved mask aura - m_modifier.m_amount = mod->m_amount * ranged_bonus / 100; - m_currentBasePoints = m_modifier.m_amount; - break; - } - } - return; - } -} - -void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real) -{ - //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real) -{ - if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) - return; - - //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1 - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) - return; - - if(m_modifier.m_miscvalue != STAT_INTELLECT) - { - // support required adding UpdateAttackPowerAndDamage calls at stat update - sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intellect stats!"); - return; - } - - // Recalculate bonus - ((Player*)m_target)->UpdateAttackPowerAndDamage(true); -} - -/********************************/ -/*** DAMAGE BONUS ***/ -/********************************/ -void Aura::HandleModDamageDone(bool apply, bool Real) -{ - // apply item specific bonuses for already equipped weapon - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) - { - for(int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) - ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); - } - - // m_modifier.m_miscvalue is bitmask of spell schools - // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) - // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands - // 127 - full bitmask any damages - // - // mods must be applied base at equipped weapon class and subclass comparison - // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // m_modifier.m_miscvalue comparison with item generated damage types - - if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0) - { - // apply generic physical damage bonuses including wand case - if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) - { - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply); - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods - } - - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - if(m_positive) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply); - else - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply); - } - } - - // Skip non magic case for speedup - if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0) - return; - - if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) - { - // wand magic case (skip generic to all item spell bonuses) - // done in Player::_ApplyWeaponDependentAuraMods - - // Skip item specific requirements for not wand magic damage - return; - } - - // Magic damage modifiers implemented in Unit::SpellDamageBonus - // This information for client side use only - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - if(m_positive) - { - for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) - { - if((m_modifier.m_miscvalue & (1<<i)) != 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply); - } - } - else - { - for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) - { - if((m_modifier.m_miscvalue & (1<<i)) != 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply); - } - } - Pet* pet = m_target->GetPet(); - if(pet) - pet->UpdateAttackPowerAndDamage(); - } -} - -void Aura::HandleModDamagePercentDone(bool apply, bool Real) -{ - sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1); - - // apply item specific bonuses for already equipped weapon - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) - { - for(int i = 0; i < MAX_ATTACK; ++i) - if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) - ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); - } - - // m_modifier.m_miscvalue is bitmask of spell schools - // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL) - // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand - // 127 - full bitmask any damages - // - // mods must be applied base at equipped weapon class and subclass comparison - // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // m_modifier.m_miscvalue comparison with item generated damage types - - if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0) - { - // apply generic physical damage bonuses including wand case - if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) - { - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply); - } - else - { - // done in Player::_ApplyWeaponDependentAuraMods - } - // For show in client - if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply); - } - - // Skip non magic case for speedup - if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0) - return; - - if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) - { - // wand magic case (skip generic to all item spell bonuses) - // done in Player::_ApplyWeaponDependentAuraMods - - // Skip item specific requirements for not wand magic damage - return; - } - - // Magic damage percent modifiers implemented in Unit::SpellDamageBonus - // Send info to client - if(m_target->GetTypeId() == TYPEID_PLAYER) - for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) - m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply); -} - -void Aura::HandleModOffhandDamagePercent(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - sLog.outDebug("AURA MOD OFFHAND DAMAGE"); - - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); -} - -/********************************/ -/*** POWER COST ***/ -/********************************/ - -void Aura::HandleModPowerCostPCT(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - float amount = m_modifier.m_amount/100.0f; - for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) - if(m_modifier.m_miscvalue & (1<<i)) - m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply); -} - -void Aura::HandleModPowerCost(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) - if(m_modifier.m_miscvalue & (1<<i)) - m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply); -} - -/*********************************************************/ -/*** OTHERS ***/ -/*********************************************************/ - -void Aura::HandleShapeshiftBoosts(bool apply) -{ - uint32 spellId = 0; - uint32 spellId2 = 0; - uint32 HotWSpellId = 0; - - switch(GetModifier()->m_miscvalue) - { - case FORM_CAT: - spellId = 3025; - HotWSpellId = 24900; - break; - case FORM_TREE: - spellId = 5420; - break; - case FORM_TRAVEL: - spellId = 5419; - break; - case FORM_AQUA: - spellId = 5421; - break; - case FORM_BEAR: - spellId = 1178; - spellId2 = 21178; - HotWSpellId = 24899; - break; - case FORM_DIREBEAR: - spellId = 9635; - spellId2 = 21178; - HotWSpellId = 24899; - break; - case FORM_BATTLESTANCE: - spellId = 21156; - break; - case FORM_DEFENSIVESTANCE: - spellId = 7376; - break; - case FORM_BERSERKERSTANCE: - spellId = 7381; - break; - case FORM_MOONKIN: - spellId = 24905; - // aura from effect trigger spell - spellId2 = 24907; - break; - case FORM_FLIGHT: - spellId = 33948; - break; - case FORM_FLIGHT_EPIC: - spellId = 40122; - spellId2 = 40121; - break; - case FORM_SPIRITOFREDEMPTION: - spellId = 27792; - spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation. - break; - case FORM_GHOSTWOLF: - case FORM_AMBIENT: - case FORM_GHOUL: - case FORM_SHADOW: - case FORM_STEALTH: - case FORM_CREATURECAT: - case FORM_CREATUREBEAR: - spellId = 0; - break; - } - - uint32 form = GetModifier()->m_miscvalue-1; - - if(apply) - { - if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this ); - if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this); - - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - if(itr->second->state == PLAYERSPELL_REMOVED) continue; - if(itr->first==spellId || itr->first==spellId2) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue; - if (spellInfo->Stances & (1<<form)) - m_target->CastSpell(m_target, itr->first, true, NULL, this); - } - //LotP - if (((Player*)m_target)->HasSpell(17007)) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932); - if (spellInfo && spellInfo->Stances & (1<<form)) - m_target->CastSpell(m_target, 24932, true, NULL, this); - } - // HotW - if (HotWSpellId) - { - Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); - for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3) - { - int32 HotWMod = (*i)->GetModifier()->m_amount; - if(GetModifier()->m_miscvalue == FORM_CAT) - HotWMod /= 2; - - m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this); - break; - } - } - } - } - } - else - { - m_target->RemoveAurasDueToSpell(spellId); - m_target->RemoveAurasDueToSpell(spellId2); - - Unit::AuraMap& tAuras = m_target->GetAuras(); - for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) - { - if (itr->second->IsRemovedOnShapeLost()) - { - m_target->RemoveAurasDueToSpell(itr->second->GetId()); - itr = tAuras.begin(); - } - else - { - ++itr; - } - } - } - - /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth(); - m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/ -} - -void Aura::HandleAuraEmpathy(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_UNIT) - return; - - CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry()); - if(ci && ci->type == CREATURE_TYPE_BEAST) - m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply); -} - -void Aura::HandleAuraUntrackable(bool apply, bool Real) -{ - if(apply) - m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE); - else - m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE); -} - -void Aura::HandleAuraModPacify(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); -} - -void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real) -{ - HandleAuraModPacify(apply,Real); - HandleAuraModSilence(apply,Real); -} - -void Aura::HandleAuraGhost(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - if(apply) - { - m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); - } - else - { - m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST); - } -} - -void Aura::HandleAuraAllowFlight(bool apply, bool Real) -{ - // all applied/removed only at real aura add/remove - if(!Real) - return; - - // allow fly - WorldPacket data; - if(apply) - data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12); - else - data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12); - data.append(m_target->GetPackGUID()); - data << uint32(0); // unk - m_target->SendMessageToSet(&data, true); -} - -void Aura::HandleModRating(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) - if (m_modifier.m_miscvalue & (1 << rating)) - ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply); -} - -void Aura::HandleForceMoveForward(bool apply, bool Real) -{ - if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) - return; - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); -} - -void Aura::HandleAuraModExpertise(bool apply, bool Real) -{ - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)m_target)->UpdateExpertise(BASE_ATTACK); - ((Player*)m_target)->UpdateExpertise(OFF_ATTACK); -} - -void Aura::HandleModTargetResistance(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage - - // show armor penetration - if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply); - - // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy - if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL) - m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply); -} - -//HandleNoImmediateEffect auras implementation to support new stat system -void Aura::HandleAuraHealing(bool apply, bool Real) -{ - //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_VALUE, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraHealingPct(bool apply, bool Real) -{ - //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_PCT, float(m_modifier.m_amount), apply); -} - -void Aura::HandleShieldBlockValue(bool apply, bool Real) -{ - BaseModType modType = FLAT_MOD; - if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT) - modType = PCT_MOD; - - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply); -} - -void Aura::HandleAuraRetainComboPoints(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - - Player *target = (Player*)m_target; - - // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler - // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost) - if( !apply && m_duration==0 && target->GetComboTarget()) - if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget())) - target->AddComboPoints(unit, -m_modifier.m_amount); -} - -void Aura::HandleModUnattackable( bool Apply, bool Real ) -{ - if(Real && Apply) - { - m_target->CombatStop(); - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); - } - - m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply); -} - -void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - // prepare spirit state - if(apply) - { - if(m_target->GetTypeId()==TYPEID_PLAYER) - { - // disable breath/etc timers - ((Player*)m_target)->StopMirrorTimers(); - - // set stand state (expected in this form) - if(!m_target->IsStandState()) - m_target->SetStandState(PLAYER_STATE_NONE); - } - - m_target->SetHealth(1); - } - // die at aura end - else - m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false); -} - -void Aura::CleanupTriggeredSpells() -{ - uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; - if(!tSpellId) - return; - - SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId); - if(!tProto) - return; - - if(GetSpellDuration(tProto) != -1) - return; - - // needed for spell 43680, maybe others - // TODO: is there a spell flag, which can solve this in a more sophisticated way? - if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && - GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()]) - return; - m_target->RemoveAurasDueToSpell(tSpellId); -} - -void Aura::HandleAuraPowerBurn(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; -} - -void Aura::HandleSchoolAbsorb(bool apply, bool Real) -{ - if(!Real) - return; - - // prevent double apply bonuses - if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())) - { - if(Unit* caster = GetCaster()) - { - float DoneActualBenefit = 0.0f; - switch(m_spellProto->SpellFamilyName) - { - case SPELLFAMILY_PRIEST: - if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S - { - //+30% from +healing bonus - DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f; - break; - } - break; - case SPELLFAMILY_MAGE: - if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL) - { - //frost ward, fire ward, ice barrier - //+10% from +spd bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f; - break; - } - break; - case SPELLFAMILY_WARLOCK: - if(m_spellProto->SpellFamilyFlags == 0x00) - { - //shadow ward - //+10% from +spd bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f; - break; - } - break; - default: - break; - } - - DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto()); - - m_modifier.m_amount += (int32)DoneActualBenefit; - } - } -} - -void Aura::PeriodicTick() -{ - if(!m_target->isAlive()) - return; - - switch(m_modifier.m_auraname) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && - pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) - return; - - // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) - return; - - // some auras remove at specific health level or more - if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE) - { - switch(GetId()) - { - case 43093: case 31956: case 38801: - case 35321: case 38363: case 39215: - if(m_target->GetHealth() == m_target->GetMaxHealth() ) - { - m_target->RemoveAurasDueToSpell(GetId()); - return; - } - break; - case 38772: - { - uint32 percent = - GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ? - pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) : - 100; - if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent ) - { - m_target->RemoveAurasDueToSpell(GetId()); - return; - } - break; - } - case 41337:// aura of anger - { - Unit::AuraList const& mMod = m_target->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - for(Unit::AuraList::const_iterator i = mMod.begin(); i != mMod.end(); ++i) - { - if ((*i)->GetId() == 41337) - { - (*i)->ApplyModifier(false); - (*i)->GetModifier()->m_amount += 5; - (*i)->ApplyModifier(true); - break; - } - } - m_modifier.m_amount += 100; - }break; - default: - break; - } - } - - uint32 absorb=0; - uint32 resist=0; - CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - - // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; - - uint32 pdamage; - - if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE) - { - pdamage = amount; - - // Calculate armor mitigation if it is a physical spell - // But not for bleed mechanic spells - if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL && - GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED) - { - uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage); - cleanDamage.damage += pdamage - pdamageReductedArmor; - pdamage = pdamageReductedArmor; - } - - pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); - - // Curse of Agony damage-per-tick calculation - if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544) - { - // 1..4 ticks, 1/2 from normal tick damage - if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3)) - pdamage = pdamage/2; - // 9..12 ticks, 3/2 from normal tick damage - else if(m_duration<((m_maxduration-m_modifier.periodictime)/3)) - pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks - // 5..8 ticks have normal tick damage - } - } - else - pdamage = uint32(m_target->GetMaxHealth()*amount/100); - - //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit - // Reduce dot damage from resilience for players - if (m_target->GetTypeId()==TYPEID_PLAYER) - pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); - - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)pdamage; - data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x - data << (uint32)absorb; - data << (uint32)resist; - m_target->SendMessageToSet(&data,true); - - Unit* target = m_target; // aura can be deleted in DealDamage - SpellEntry const* spellProto = GetSpellProto(); - - pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); - - // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura) - - pCaster->ProcDamageAndSpell(target, PROC_FLAG_NONE, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), GetSpellSchoolMask(spellProto), spellProto); - break; - } - case SPELL_AURA_PERIODIC_LEECH: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - if(!pCaster->isAlive()) - return; - - if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && - pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) - return; - - // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) - return; - - uint32 absorb=0; - uint32 resist=0; - CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - - uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; - - //Calculate armor mitigation if it is a physical spell - if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL) - { - uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage); - cleanDamage.damage += pdamage - pdamageReductedArmor; - pdamage = pdamageReductedArmor; - } - - pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); - - // talent Soul Siphon add bonus to Drain Life spells - if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) ) - { - // find talent max bonus percentage - Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i) - { - if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993) - { - if((*i)->GetEffIndex()!=1) - { - sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId()); - break; - } - - // effect 1 m_amount - int32 maxPercent = (*i)->GetModifier()->m_amount; - // effect 0 m_amount - int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster); - - // count affliction effects and calc additional damage in percentage - int32 modPercent = 0; - Unit::AuraMap const& victimAuras = m_target->GetAuras(); - for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) - { - Aura* aura = itr->second; - if (aura->IsPositive())continue; - SpellEntry const* m_spell = aura->GetSpellProto(); - if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK) - continue; - - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id); - - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - if(_spell_idx->second->skillId == SKILL_AFFLICTION) - { - modPercent += stepPercent; - if (modPercent >= maxPercent) - { - modPercent = maxPercent; - break; - } - } - } - } - pdamage += (pdamage*modPercent/100); - break; - } - } - } - - //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit - // Reduce dot damage from resilience for players - if (m_target->GetTypeId()==TYPEID_PLAYER) - pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); - - if(m_target->GetHealth() < pdamage) - pdamage = uint32(m_target->GetHealth()); - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); - - pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0); - - - Unit* target = m_target; // aura can be deleted in DealDamage - SpellEntry const* spellProto = GetSpellProto(); - float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1; - - uint32 new_damage = pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false); - - // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura) - - pCaster->ProcDamageAndSpell(target, PROC_FLAG_HEALED, PROC_FLAG_TAKE_DAMAGE, new_damage, GetSpellSchoolMask(spellProto), spellProto); - if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false)) - { - for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) - { - if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id) - pCaster->m_currentSpells[i]->cancel(); - } - } - - - if(Player *modOwner = pCaster->GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); - - uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster); - - int32 gain = pCaster->ModifyHealth(heal); - pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto); - - pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal); - break; - } - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_OBS_MOD_HEALTH: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - // heal for caster damage (must be alive) - if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive()) - return; - - // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; - - uint32 pdamage; - - if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH) - pdamage = uint32(m_target->GetMaxHealth() * amount/100); - else - pdamage = amount; - - pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target); - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)pdamage; - m_target->SendMessageToSet(&data,true); - - int32 gain = m_target->ModifyHealth(pdamage); - - // add HoTs to amount healed in bgs - if( pCaster->GetTypeId() == TYPEID_PLAYER ) - if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() ) - bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain); - - //Do check before because m_modifier.auraName can be invalidate by DealDamage. - bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster); - - m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); - - Unit* target = m_target; // aura can be deleted in DealDamage - SpellEntry const* spellProto = GetSpellProto(); - bool haveCastItem = GetCastItemGUID()!=0; - - // heal for caster damage - if(m_target!=pCaster && spellProto->SpellVisual==163) - { - uint32 dmg = spellProto->manaPerSecond; - if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER) - { - pCaster->RemoveAurasDueToSpell(GetId()); - - // finish current generic/channeling spells, don't affect autorepeat - if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]) - { - pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish(); - } - if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]) - { - pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); - pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish(); - } - } - else - { - pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false); - - CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); - } - } - - // ignore item heals - if(procSpell && !haveCastItem) - pCaster->ProcDamageAndSpell(target,PROC_FLAG_NONE, PROC_FLAG_HEALED, pdamage, SPELL_SCHOOL_MASK_NONE, spellProto); - break; - } - case SPELL_AURA_PERIODIC_MANA_LEECH: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - if(!pCaster->isAlive()) - return; - - if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && - pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) - return; - - // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) - return; - - // ignore non positive values (can be result apply spellmods to aura damage - uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - - if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4) - break; - - Powers power = Powers(m_modifier.m_miscvalue); - - // power type might have changed between aura applying and tick (druid's shapeshift) - if(m_target->getPowerType() != power) - break; - - int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power); - - // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) - if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER) - drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount); - - m_target->ModifyPower(power, -drain_amount); - - float gain_multiplier = 0; - - if(pCaster->GetMaxPower(power) > 0) - { - gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()]; - - if(Player *modOwner = pCaster->GetSpellModOwner()) - modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier); - } - - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)power; // power type - data << (uint32)drain_amount; - data << (float)gain_multiplier; - m_target->SendMessageToSet(&data,true); - - int32 gain_amount = int32(drain_amount*gain_multiplier); - - if(gain_amount) - { - int32 gain = pCaster->ModifyPower(power,gain_amount); - m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); - } - break; - } - case SPELL_AURA_PERIODIC_ENERGIZE: - { - // ignore non positive values (can be result apply spellmods to aura damage - uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - - if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4) - break; - - Powers power = Powers(m_modifier.m_miscvalue); - - if(m_target->GetMaxPower(power) == 0) - break; - - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)power; // power type - data << (uint32)pdamage; - m_target->SendMessageToSet(&data,true); - - int32 gain = m_target->ModifyPower(power,pdamage); - - if(Unit* pCaster = GetCaster()) - m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); - break; - } - case SPELL_AURA_OBS_MOD_MANA: - { - // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; - - uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100); - - sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - - if(m_target->GetMaxPower(POWER_MANA) == 0) - break; - - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)0; // ? - data << (uint32)pdamage; - m_target->SendMessageToSet(&data,true); - - int32 gain = m_target->ModifyPower(POWER_MANA, pdamage); - - if(Unit* pCaster = GetCaster()) - m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); - break; - } - case SPELL_AURA_POWER_BURN_MANA: - { - Unit *pCaster = GetCaster(); - if(!pCaster) - return; - - // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) - return; - - int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; - - Powers powerType = Powers(m_modifier.m_miscvalue); - - if(!m_target->isAlive() || m_target->getPowerType() != powerType) - return; - - // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) - if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER) - pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage); - - uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage)); - - gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]); - - //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG - pCaster->SpellNonMeleeDamageLog(m_target, GetId(), gain); - break; - } - // Here tick dummy auras - case SPELL_AURA_PERIODIC_DUMMY: - { - PeriodicDummyTick(); - break; - } - default: - break; - } -} - -void Aura::PeriodicDummyTick() -{ - SpellEntry const* spell = GetSpellProto(); - switch (spell->Id) - { - // Drink - case 430: - case 431: - case 432: - case 1133: - case 1135: - case 1137: - case 10250: - case 22734: - case 27089: - case 34291: - case 43706: - case 46755: - { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus - Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); - for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i) - { - if ((*i)->GetId() == GetId()) - { - // Get tick number - int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime; - // Default case (not on arenas) - if (tick == 0) - { - (*i)->GetModifier()->m_amount = m_modifier.m_amount; - ((Player*)m_target)->UpdateManaRegen(); - // Disable continue - m_isPeriodic = false; - } - return; - //********************************************** - // Code commended since arena patch not added - // This feature uses only in arenas - //********************************************** - // Here need increase mana regen per tick (6 second rule) - // on 0 tick - 0 (handled in 2 second) - // on 1 tick - 166% (handled in 4 second) - // on 2 tick - 133% (handled in 6 second) - // Not need update after 3 tick - /* - if (tick > 3) - return; - // Apply bonus for 0 - 3 tick - switch (tick) - { - case 0: // 0% - (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0; - break; - case 1: // 166% - (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3; - break; - case 2: // 133% - (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3; - break; - default: // 100% - normal regen - (*i)->GetModifier()->m_amount = m_modifier.m_amount; - break; - } - ((Player*)m_target)->UpdateManaRegen(); - return;*/ - } - } - return; - } -// // Panda -// case 19230: break; -// // Master of Subtlety -// case 31666: break; -// // Gossip NPC Periodic - Talk -// case 33208: break; -// // Gossip NPC Periodic - Despawn -// case 33209: break; -// // Force of Nature -// case 33831: break; - // Aspect of the Viper - case 34074: - { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Should be manauser - if (m_target->getPowerType()!=POWER_MANA) - return; - Unit *caster = GetCaster(); - if (!caster) - return; - // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell) - int mana = m_target->GetPower(POWER_MANA); - int max_mana = m_target->GetMaxPower(POWER_MANA); - int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); - float regen_pct = 1.20f - 1.1f * mana / max_mana; - if (regen_pct > 1.0f) regen_pct = 1.0f; - else if (regen_pct < 0.2f) regen_pct = 0.2f; - m_modifier.m_amount = int32 (base_regen * regen_pct); - ((Player*)m_target)->UpdateManaRegen(); - return; - } -// // Steal Weapon -// case 36207: break; -// // Simon Game START timer, (DND) -// case 39993: break; -// // Harpooner's Mark -// case 40084: break; -// // Knockdown Fel Cannon: break; The Aggro Burst -// case 40119: break; -// // Old Mount Spell -// case 40154: break; -// // Magnetic Pull -// case 40581: break; -// // Ethereal Ring: break; The Bolt Burst -// case 40801: break; -// // Crystal Prison -// case 40846: break; -// // Copy Weapon -// case 41054: break; -// // Ethereal Ring Visual, Lightning Aura -// case 41477: break; -// // Ethereal Ring Visual, Lightning Aura (Fork) -// case 41525: break; -// // Ethereal Ring Visual, Lightning Jumper Aura -// case 41567: break; -// // No Man's Land -// case 41955: break; -// // Headless Horseman - Fire -// case 42074: break; -// // Headless Horseman - Visual - Large Fire -// case 42075: break; -// // Headless Horseman - Start Fire, Periodic Aura -// case 42140: break; -// // Ram Speed Boost -// case 42152: break; -// // Headless Horseman - Fires Out Victory Aura -// case 42235: break; -// // Pumpkin Life Cycle -// case 42280: break; -// // Brewfest Request Chick Chuck Mug Aura -// case 42537: break; -// // Squashling -// case 42596: break; -// // Headless Horseman Climax, Head: Periodic -// case 42603: break; -// // Fire Bomb -// case 42621: break; -// // Headless Horseman - Conflagrate, Periodic Aura -// case 42637: break; -// // Headless Horseman - Create Pumpkin Treats Aura -// case 42774: break; -// // Headless Horseman Climax - Summoning Rhyme Aura -// case 42879: break; -// // Tricky Treat -// case 42919: break; -// // Giddyup! -// case 42924: break; -// // Ram - Trot -// case 42992: break; -// // Ram - Canter -// case 42993: break; -// // Ram - Gallop -// case 42994: break; -// // Ram Level - Neutral -// case 43310: break; -// // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17 -// case 43884: break; -// // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17 -// case 44000: break; -// // Energy Feedback -// case 44328: break; -// // Romantic Picnic -// case 45102: break; -// // Romantic Picnic -// case 45123: break; -// // Looking for Love -// case 45124: break; -// // Kite - Lightning Strike Kite Aura -// case 45197: break; -// // Rocket Chicken -// case 45202: break; -// // Copy Offhand Weapon -// case 45205: break; -// // Upper Deck - Kite - Lightning Periodic Aura -// case 45207: break; -// // Kite -Sky Lightning Strike Kite Aura -// case 45251: break; -// // Ribbon Pole Dancer Check Aura -// case 45390: break; -// // Holiday - Midsummer, Ribbon Pole Periodic Visual -// case 45406: break; -// // Parachute -// case 45472: break; -// // Alliance Flag, Extra Damage Debuff -// case 45898: break; -// // Horde Flag, Extra Damage Debuff -// case 45899: break; -// // Ahune - Summoning Rhyme Aura -// case 45926: break; -// // Ahune - Slippery Floor -// case 45945: break; -// // Ahune's Shield -// case 45954: break; -// // Nether Vapor Lightning -// case 45960: break; -// // Darkness -// case 45996: break; -// // Summon Blood Elves Periodic -// case 46041: break; -// // Transform Visual Missile Periodic -// case 46205: break; -// // Find Opening Beam End -// case 46333: break; -// // Ice Spear Control Aura -// case 46371: break; -// // Hailstone Chill -// case 46458: break; -// // Hailstone Chill, Internal -// case 46465: break; -// // Chill, Internal Shifter -// case 46549: break; -// // Summon Ice Spear Knockback Delayer -// case 46878: break; -// // Burninate Effect -// case 47214: break; -// // Fizzcrank Practice Parachute -// case 47228: break; -// // Send Mug Control Aura -// case 47369: break; -// // Direbrew's Disarm (precast) -// case 47407: break; -// // Mole Machine Port Schedule -// case 47489: break; -// // Mole Machine Portal Schedule -// case 49466: break; -// // Drink Coffee -// case 49472: break; -// // Listening to Music -// case 50493: break; -// // Love Rocket Barrage -// case 50530: break; - default: - break; - } -} - -void Aura::HandlePreventFleeing(bool apply, bool Real) -{ - if(!Real) - return; - - Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR); - if( !fearAuras.empty() ) - { - if (apply) - m_target->SetFeared(false, fearAuras.front()->GetCasterGUID()); - else - m_target->SetFeared(true); - } -} - -void Aura::HandleManaShield(bool apply, bool Real) -{ - if(!Real) - return; - - // prevent double apply bonuses - if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())) - { - if(Unit* caster = GetCaster()) - { - float DoneActualBenefit = 0.0f; - switch(m_spellProto->SpellFamilyName) - { - case SPELLFAMILY_MAGE: - if(m_spellProto->SpellFamilyFlags & 0x8000) - { - // Mana Shield - // +50% from +spd bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f; - break; - } - break; - default: - break; - } - - DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto()); - - m_modifier.m_amount += (int32)DoneActualBenefit; - } - } -} - -void Aura::HandleArenaPreparation(bool apply, bool Real) -{ - if(!Real) - return; - - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); -} +/*
+ * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ *
+ * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "Database/DatabaseEnv.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+#include "Opcodes.h"
+#include "Log.h"
+#include "UpdateMask.h"
+#include "World.h"
+#include "ObjectMgr.h"
+#include "SpellMgr.h"
+#include "Player.h"
+#include "Unit.h"
+#include "Spell.h"
+#include "SpellAuras.h"
+#include "DynamicObject.h"
+#include "Group.h"
+#include "UpdateData.h"
+#include "MapManager.h"
+#include "ObjectAccessor.h"
+#include "Policies/SingletonImp.h"
+#include "Totem.h"
+#include "Creature.h"
+#include "Formulas.h"
+#include "BattleGround.h"
+#include "OutdoorPvP.h"
+#include "OutdoorPvPMgr.h"
+#include "CreatureAI.h"
+#include "Util.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+#include "CellImpl.h"
+#include "TemporarySummon.h"
+
+#define NULL_AURA_SLOT 0xFF
+
+pAuraHandler AuraHandler[TOTAL_AURAS]=
+{
+ &Aura::HandleNULL, // 0 SPELL_AURA_NONE
+ &Aura::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT
+ &Aura::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS
+ &Aura::HandlePeriodicDamage, // 3 SPELL_AURA_PERIODIC_DAMAGE
+ &Aura::HandleAuraDummy, // 4 SPELL_AURA_DUMMY
+ &Aura::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE
+ &Aura::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM
+ &Aura::HandleModFear, // 7 SPELL_AURA_MOD_FEAR
+ &Aura::HandlePeriodicHeal, // 8 SPELL_AURA_PERIODIC_HEAL
+ &Aura::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED
+ &Aura::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT
+ &Aura::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT
+ &Aura::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN
+ &Aura::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE
+ &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
+ &Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage
+ &Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH
+ &Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT
+ &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY
+ &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION
+ &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH
+ &Aura::HandleAuraModTotalManaPercentRegen, // 21 SPELL_AURA_OBS_MOD_MANA
+ &Aura::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE
+ &Aura::HandlePeriodicTriggerSpell, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL
+ &Aura::HandlePeriodicEnergize, // 24 SPELL_AURA_PERIODIC_ENERGIZE
+ &Aura::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY
+ &Aura::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT
+ &Aura::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE
+ &Aura::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult
+ &Aura::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT
+ &Aura::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL
+ &Aura::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED
+ &Aura::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED
+ &Aura::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED
+ &Aura::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH
+ &Aura::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY
+ &Aura::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT
+ &Aura::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY
+ &Aura::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY
+ &Aura::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY
+ &Aura::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY
+ &Aura::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY
+ &Aura::HandleAuraProcTriggerSpell, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell
+ &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor
+ &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES
+ &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES
+ &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete?
+ &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT
+ &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete?
+ &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT
+ &Aura::HandleUnused, // 50 SPELL_AURA_MOD_BLOCK_SKILL obsolete?
+ &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT
+ &Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT
+ &Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH
+ &Aura::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE
+ &Aura::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE
+ &Aura::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM
+ &Aura::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE
+ &Aura::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED
+ &Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
+ &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
+ &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
+ &Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL
+ &Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete?
+ &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH
+ &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED
+ &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
+ &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM
+ &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED
+ &Aura::HandleSchoolAbsorb, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist
+ &Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect
+ &Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
+ &Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
+ &Aura::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL
+ &Aura::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult
+ &Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE
+ &Aura::HandleFarSight, // 76 SPELL_AURA_FAR_SIGHT
+ &Aura::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY
+ &Aura::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED
+ &Aura::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
+ &Aura::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT
+ &Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT
+ &Aura::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING
+ &Aura::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE
+ &Aura::HandleModRegen, // 84 SPELL_AURA_MOD_REGEN
+ &Aura::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN
+ &Aura::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM
+ &Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
+ &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT
+ &Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT
+ &Aura::HandleUnused, // 90 SPELL_AURA_MOD_RESIST_CHANCE Useless
+ &Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance
+ &Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING
+ &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE
+ &Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll
+ &Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST
+ &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Spell::SelectMagnetTarget
+ &Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist
+ &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT
+ &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER
+ &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now
+ &Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT
+ &Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
+ &Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT
+ &Aura::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK
+ &Aura::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL
+ &Aura::HandleAuraHover, //106 SPELL_AURA_HOVER
+ &Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER
+ &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER
+ &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER
+ &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT
+ &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER
+ &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
+ &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
+ &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
+ &Aura::HandleAuraHealing, //115 SPELL_AURA_MOD_HEALING
+ &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
+ &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult
+ &Aura::HandleAuraHealingPct, //118 SPELL_AURA_MOD_HEALING_PCT
+ &Aura::HandleUnused, //119 SPELL_AURA_SHARE_PET_TRACKING useless
+ &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE
+ &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY
+ &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
+ &Aura::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE
+ &Aura::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER
+ &Aura::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
+ &Aura::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
+ &Aura::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
+ &Aura::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET
+ &Aura::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS
+ &Aura::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS
+ &Aura::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
+ &Aura::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT
+ &Aura::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT
+ &Aura::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
+ &Aura::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE
+ &Aura::HandleAuraHealingPct, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus
+ &Aura::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE
+ &Aura::HandleHaste, //138 SPELL_AURA_MOD_HASTE
+ &Aura::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
+ &Aura::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
+ &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
+ &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
+ &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
+ &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
+ &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete?
+ &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete?
+ &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY
+ &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
+ &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK
+ &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
+ &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
+ &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
+ &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
+ &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL
+ &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
+ &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
+ &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
+ &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
+ &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
+ &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
+ &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
+ &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA
+ &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE
+ &Aura::HandleUnused, //164 useless, only one test spell
+ &Aura::HandleAuraAttackPowerAttacker, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
+ &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
+ &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
+ &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
+ &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
+ &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE only for Detect Amore spell
+ &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
+ &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
+ &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
+ &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by default intellect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT)
+ &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
+ &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
+ &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM
+ &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult
+ &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
+ &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
+ &Aura::HandleUnused, //181 SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS unused
+ &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
+ &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT
+ &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
+ &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
+ &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult
+ &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
+ &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
+ &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING
+ &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN
+ &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
+ &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
+ &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
+ &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT)
+ &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT)
+ &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN
+ &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
+ &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS
+ &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
+ &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP
+ &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
+ &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
+ &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::DoAttackDamage
+ &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::DoAttackDamage
+ &Aura::HandleNULL, //205 vulnerable to school dmg?
+ &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED
+ &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
+ &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive)
+ &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS
+ &Aura::HandleNULL, //210 Commentator's Command
+ &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
+ &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
+ &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
+ &Aura::HandleNULL, //214 Tamed Pet Passive
+ &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
+ &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
+ &Aura::HandleUnused, //217 unused
+ &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
+ &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
+ &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT
+ &Aura::HandleNULL, //221 ignored
+ &Aura::HandleUnused, //222 unused
+ &Aura::HandleNULL, //223 Cold Stare
+ &Aura::HandleUnused, //224 unused
+ &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING
+ &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY
+ &Aura::HandleNULL, //227 periodic trigger spell
+ &Aura::HandleNoImmediateEffect, //228 stealth detection
+ &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
+ &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
+ &Aura::HandleNULL, //231
+ &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
+ &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue
+ &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
+ &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
+ &Aura::HandleUnused, //236 unused
+ &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus
+ &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus
+ &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61
+ &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE
+ &Aura::HandleForceMoveForward, //241 Forces the player to move forward
+ &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING
+ &Aura::HandleUnused, //243 used by two test spells
+ &Aura::HandleComprehendLanguage, //244 Comprehend language
+ &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS
+ &Aura::HandleUnused, //246 unused
+ &Aura::HandleUnused, //247 unused
+ &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
+ &Aura::HandleNULL, //249
+ &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
+ &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE
+ &Aura::HandleUnused, //252 unused
+ &Aura::HandleUnused, //253 unused
+ &Aura::HandleUnused, //254 unused
+ &Aura::HandleUnused, //255 unused
+ &Aura::HandleUnused, //256 unused
+ &Aura::HandleUnused, //257 unused
+ &Aura::HandleUnused, //258 unused
+ &Aura::HandleUnused, //259 unused
+ &Aura::HandleUnused, //260 unused
+ &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell)
+};
+
+Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) :
+m_procCharges(0), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target),
+m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS),
+m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false),
+m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false),
+m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE)
+{
+ assert(target);
+
+ assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
+
+ m_spellProto = spellproto;
+
+ m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->EffectBasePoints[eff];
+
+ m_isPassive = IsPassiveSpell(GetId());
+ m_positive = IsPositiveEffect(GetId(), m_effIndex);
+
+ m_applyTime = time(NULL);
+
+ int32 damage;
+ if(!caster)
+ {
+ m_caster_guid = target->GetGUID();
+ damage = m_currentBasePoints+1; // stored value-1
+ m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target);
+ }
+ else
+ {
+ m_caster_guid = caster->GetGUID();
+
+ damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target);
+ m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target);
+
+ if (!damage && castItem && castItem->GetItemSuffixFactor())
+ {
+ ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
+ if(item_rand_suffix)
+ {
+ for (int k=0; k<3; k++)
+ {
+ SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
+ if(pEnchant)
+ {
+ for (int t=0; t<3; t++)
+ if(pEnchant->spellid[t] == m_spellProto->Id)
+ {
+ damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 );
+ break;
+ }
+ }
+
+ if(damage)
+ break;
+ }
+ }
+ }
+ }
+
+ if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0)
+ m_permanent = true;
+
+ Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
+
+ if(!m_permanent && modOwner)
+ modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration);
+
+ m_duration = m_maxduration;
+
+ if(modOwner)
+ modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer);
+
+ sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage);
+
+ m_effIndex = eff;
+ SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]);
+
+ m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
+
+ if(m_spellProto->procCharges)
+ {
+ m_procCharges = m_spellProto->procCharges;
+
+ if(modOwner)
+ modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
+ }
+ else
+ m_procCharges = -1;
+
+ m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances &&
+ !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000));
+}
+
+Aura::~Aura()
+{
+}
+
+AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
+Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
+{
+ m_isAreaAura = true;
+
+ // caster==NULL in constructor args if target==caster in fact
+ Unit* caster_ptr = caster ? caster : target;
+
+ m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex]));
+ if(Player* modOwner = caster_ptr->GetSpellModOwner())
+ modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius);
+
+ switch(spellproto->Effect[eff])
+ {
+ case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
+ m_areaAuraType = AREA_AURA_PARTY;
+ if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem())
+ m_modifier.m_auraname = SPELL_AURA_NONE;
+ break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
+ m_areaAuraType = AREA_AURA_FRIEND;
+ break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
+ m_areaAuraType = AREA_AURA_ENEMY;
+ if(target == caster_ptr)
+ m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self
+ break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_PET:
+ m_areaAuraType = AREA_AURA_PET;
+ break;
+ case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
+ m_areaAuraType = AREA_AURA_OWNER;
+ if(target == caster_ptr)
+ m_modifier.m_auraname = SPELL_AURA_NONE;
+ break;
+ default:
+ sLog.outError("Wrong spell effect in AreaAura constructor");
+ ASSERT(false);
+ break;
+ }
+}
+
+AreaAura::~AreaAura()
+{
+}
+
+PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
+Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
+{
+ m_isPersistent = true;
+}
+
+PersistentAreaAura::~PersistentAreaAura()
+{
+}
+
+Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem)
+{
+ if (IsAreaAuraEffect(spellproto->Effect[eff]))
+ return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem);
+
+ return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem);
+}
+
+Unit* Aura::GetCaster() const
+{
+ if(m_caster_guid==m_target->GetGUID())
+ return m_target;
+
+ //return ObjectAccessor::GetUnit(*m_target,m_caster_guid);
+ //must return caster even if it's in another grid/map
+ Unit *unit = ObjectAccessor::GetObjectInWorld(m_caster_guid, (Unit*)NULL);
+ return unit && unit->IsInWorld() ? unit : NULL;
+}
+
+void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
+{
+ m_modifier.m_auraname = t;
+ m_modifier.m_amount = a;
+ m_modifier.m_miscvalue = miscValue;
+ m_modifier.periodictime = pt;
+}
+
+void Aura::Update(uint32 diff)
+{
+ if (m_duration > 0)
+ {
+ m_duration -= diff;
+ if (m_duration < 0)
+ m_duration = 0;
+ m_timeCla -= diff;
+
+ // GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras
+ // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0
+ if(GetEffIndex()==0 && m_timeCla <= 0)
+ {
+ if(Unit* caster = GetCaster())
+ {
+ Powers powertype = Powers(m_spellProto->powerType);
+ int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel();
+ m_timeCla = 1000;
+ if (manaPerSecond)
+ {
+ if(powertype==POWER_HEALTH)
+ caster->ModifyHealth(-manaPerSecond);
+ else
+ caster->ModifyPower(powertype,-manaPerSecond);
+ }
+ }
+ }
+ }
+
+ // Channeled aura required check distance from caster except in possessed cases
+ if(IsChanneledSpell(m_spellProto) && m_caster_guid != m_target->GetGUID() && !m_target->isPossessed())
+ {
+ Unit* caster = GetCaster();
+ if(!caster)
+ {
+ m_target->RemoveAura(GetId(),GetEffIndex());
+ return;
+ }
+
+ // Get spell range
+ float radius;
+ SpellModOp mod;
+ if (m_spellProto->EffectRadiusIndex[GetEffIndex()])
+ {
+ radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()]));
+ mod = SPELLMOD_RADIUS;
+ }
+ else
+ {
+ radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex));
+ mod = SPELLMOD_RANGE;
+ }
+
+ if(Player* modOwner = caster->GetSpellModOwner())
+ modOwner->ApplySpellMod(GetId(), mod, radius,NULL);
+
+ if(!caster->IsWithinDistInMap(m_target,radius))
+ {
+ m_target->RemoveAura(GetId(),GetEffIndex());
+ return;
+ }
+ }
+
+ if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
+ {
+ m_periodicTimer -= diff;
+ if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
+ {
+ if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN ||
+ m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN ||
+ // Cannibalize, eating items and other spells
+ m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH ||
+ // Eating items and other spells
+ m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA )
+ {
+ ApplyModifier(true);
+ return;
+ }
+ // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls)
+ m_periodicTimer += m_modifier.periodictime;
+
+ if(m_isTrigger)
+ TriggerSpell();
+ else
+ PeriodicTick();
+ }
+ }
+}
+
+void AreaAura::Update(uint32 diff)
+{
+ // update for the caster of the aura
+ if(m_caster_guid == m_target->GetGUID())
+ {
+ Unit* caster = m_target;
+
+ if( !caster->hasUnitState(UNIT_STAT_ISOLATED) )
+ {
+ Unit* owner = caster->GetCharmerOrOwner();
+ if (!owner)
+ owner = caster;
+ std::list<Unit *> targets;
+
+ switch(m_areaAuraType)
+ {
+ case AREA_AURA_PARTY:
+ {
+ Group *pGroup = NULL;
+
+ if (owner->GetTypeId() == TYPEID_PLAYER)
+ pGroup = ((Player*)owner)->GetGroup();
+
+ if( pGroup)
+ {
+ uint8 subgroup = ((Player*)owner)->GetSubGroup();
+ for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player* Target = itr->getSource();
+ if(Target && Target->isAlive() && Target->GetSubGroup()==subgroup && caster->IsFriendlyTo(Target))
+ {
+ if(caster->IsWithinDistInMap(Target, m_radius))
+ targets.push_back(Target);
+ Pet *pet = Target->GetPet();
+ if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius))
+ targets.push_back(pet);
+ }
+ }
+ }
+ else
+ {
+ // add owner
+ if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) )
+ targets.push_back(owner);
+ // add caster's pet
+ Unit* pet = caster->GetPet();
+ if( pet && caster->IsWithinDistInMap(pet, m_radius))
+ targets.push_back(pet);
+ }
+ break;
+ }
+ case AREA_AURA_FRIEND:
+ {
+ CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius);
+ Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check);
+ TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
+ TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
+ cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
+ break;
+ }
+ case AREA_AURA_ENEMY:
+ {
+ CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher
+ Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check);
+ TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
+ TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
+ cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
+ break;
+ }
+ case AREA_AURA_OWNER:
+ case AREA_AURA_PET:
+ {
+ if(owner != caster)
+ targets.push_back(owner);
+ break;
+ }
+ }
+
+ for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
+ {
+ if((*tIter)->HasAura(GetId(), m_effIndex))
+ continue;
+
+ if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
+ {
+ int32 actualBasePoints = m_currentBasePoints;
+ // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
+ if(actualSpellInfo != GetSpellProto())
+ actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
+ AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL);
+ (*tIter)->AddAura(aur);
+ }
+ }
+ }
+ Aura::Update(diff);
+ }
+ else // aura at non-caster
+ {
+ Unit * tmp_target = m_target;
+ Unit* caster = GetCaster();
+ uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex;
+
+ // WARNING: the aura may get deleted during the update
+ // DO NOT access its members after update!
+ Aura::Update(diff);
+
+ // remove aura if out-of-range from caster (after teleport for example)
+ // or caster is isolated or caster no longer has the aura
+ // or caster is (no longer) friendly
+ bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true);
+ if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) ||
+ !caster->IsWithinDistInMap(tmp_target, m_radius) ||
+ !caster->HasAura(tmp_spellId, tmp_effIndex) ||
+ caster->IsFriendlyTo(tmp_target) != needFriendly
+ )
+ {
+ tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+ }
+ else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group
+ {
+ // not check group if target == owner or target == pet
+ if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID())
+ {
+ Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself();
+
+ Group *pGroup = check ? check->GetGroup() : NULL;
+ if( pGroup )
+ {
+ Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself();
+ if(!checkTarget || !pGroup->SameSubGroup(check, checkTarget))
+ tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+ }
+ else
+ tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+ }
+ }
+ else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER )
+ {
+ if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() )
+ tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+ }
+ }
+}
+
+void PersistentAreaAura::Update(uint32 diff)
+{
+ bool remove = false;
+
+ // remove the aura if its caster or the dynamic object causing it was removed
+ // or if the target moves too far from the dynamic object
+ Unit *caster = GetCaster();
+ if (caster)
+ {
+ DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
+ if (dynObj)
+ {
+ if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius()))
+ remove = true;
+ }
+ else
+ remove = true;
+ }
+ else
+ remove = true;
+
+ Unit *tmp_target = m_target;
+ uint32 tmp_id = GetId(), tmp_index = GetEffIndex();
+
+ // WARNING: the aura may get deleted during the update
+ // DO NOT access its members after update!
+ Aura::Update(diff);
+
+ if(remove)
+ tmp_target->RemoveAura(tmp_id, tmp_index);
+}
+
+void Aura::ApplyModifier(bool apply, bool Real)
+{
+ AuraType aura = m_modifier.m_auraname;
+
+ m_in_use = true;
+ if(aura<TOTAL_AURAS)
+ (*this.*AuraHandler [aura])(apply,Real);
+ m_in_use = false;
+}
+
+void Aura::UpdateAuraDuration()
+{
+ if(m_auraSlot >= MAX_AURAS || m_isPassive)
+ return;
+
+ if( m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5);
+ data << (uint8)m_auraSlot << (uint32)m_duration;
+ ((Player*)m_target)->SendDirectMessage(&data);
+
+ data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4));
+ data.append(m_target->GetPackGUID());
+ data << uint8(m_auraSlot);
+ data << uint32(GetId());
+ data << uint32(GetAuraMaxDuration());
+ data << uint32(GetAuraDuration());
+ ((Player*)m_target)->SendDirectMessage(&data);
+ }
+
+ // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code
+ if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading())
+ return;
+
+ Unit* caster = GetCaster();
+
+ if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target)
+ SendAuraDurationForCaster((Player*)caster);
+}
+
+void Aura::SendAuraDurationForCaster(Player* caster)
+{
+ WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4));
+ data.append(m_target->GetPackGUID());
+ data << uint8(m_auraSlot);
+ data << uint32(GetId());
+ data << uint32(GetAuraMaxDuration()); // full
+ data << uint32(GetAuraDuration()); // remain
+ caster->GetSession()->SendPacket(&data);
+}
+
+void Aura::_AddAura()
+{
+ if (!GetId())
+ return;
+ if(!m_target)
+ return;
+
+ // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT
+ bool samespell = false;
+ bool secondaura = false;
+ uint8 slot = NULL_AURA_SLOT;
+
+ for(uint8 i = 0; i < 3; i++)
+ {
+ Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
+ for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
+ {
+ // allow use single slot only by auras from same caster
+ if(itr->second->GetCasterGUID()==GetCasterGUID())
+ {
+ samespell = true;
+ if (m_effIndex > itr->second->GetEffIndex())
+ secondaura = true;
+ slot = itr->second->GetAuraSlot();
+ break;
+ }
+ }
+
+ if(samespell)
+ break;
+ }
+
+ // not call total regen auras at adding
+ switch (m_modifier.m_auraname)
+ {
+ case SPELL_AURA_OBS_MOD_HEALTH:
+ case SPELL_AURA_OBS_MOD_MANA:
+ m_periodicTimer = m_modifier.periodictime;
+ break;
+ case SPELL_AURA_MOD_REGEN:
+ case SPELL_AURA_MOD_POWER_REGEN:
+ case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT:
+ m_periodicTimer = 5000;
+ break;
+ }
+
+ // register aura
+ if (getDiminishGroup() != DIMINISHING_NONE )
+ m_target->ApplyDiminishingAura(getDiminishGroup(),true);
+
+ Unit* caster = GetCaster();
+
+ // passive auras (except totem auras) do not get placed in the slots
+ // area auras with SPELL_AURA_NONE are not shown on target
+ if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) &&
+ (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))
+ {
+ if(!samespell) // new slot need
+ {
+ if (IsPositive()) // empty positive slot
+ {
+ for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++)
+ {
+ if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0)
+ {
+ slot = i;
+ break;
+ }
+ }
+ }
+ else // empty negative slot
+ {
+ for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++)
+ {
+ if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0)
+ {
+ slot = i;
+ break;
+ }
+ }
+ }
+
+ SetAuraSlot( slot );
+
+ // Not update fields for not first spell's aura, all data already in fields
+ if(!secondaura)
+ {
+ if(slot < MAX_AURAS) // slot found
+ {
+ SetAura(slot, false);
+ SetAuraFlag(slot, true);
+ SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
+ UpdateAuraCharges();
+
+ // update for out of range group members
+ m_target->UpdateAuraForGroup(slot);
+ }
+
+ UpdateAuraDuration();
+ }
+ }
+ else // use found slot
+ {
+ SetAuraSlot( slot );
+ // Not recalculate stack count for second aura of the same spell
+ if (!secondaura)
+ UpdateSlotCounterAndDuration(true);
+ }
+
+ // Update Seals information
+ if( IsSealSpell(GetSpellProto()) )
+ m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true);
+
+ // Conflagrate aura state
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
+ m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true);
+
+ if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
+ && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
+ {
+ m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true);
+ }
+ }
+}
+
+void Aura::_RemoveAura()
+{
+ // Remove all triggered by aura spells vs unlimited duration
+ // except same aura replace case
+ if(m_removeMode!=AURA_REMOVE_BY_STACK)
+ CleanupTriggeredSpells();
+
+ Unit* caster = GetCaster();
+
+ if(caster && IsPersistent())
+ {
+ DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex());
+ if (dynObj)
+ dynObj->RemoveAffected(m_target);
+ }
+
+ // unregister aura
+ if (getDiminishGroup() != DIMINISHING_NONE )
+ m_target->ApplyDiminishingAura(getDiminishGroup(),false);
+
+ //passive auras do not get put in slots
+ // Note: but totem can be not accessible for aura target in time remove (to far for find in grid)
+ //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()))
+ // return;
+
+ uint8 slot = GetAuraSlot();
+
+ if(slot >= MAX_AURAS) // slot not set
+ return;
+
+ if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0)
+ return;
+
+ bool samespell = false;
+ bool sameaura = false;
+
+ // find other aura in same slot (current already removed from list)
+ for(uint8 i = 0; i < 3; i++)
+ {
+ Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i);
+ for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr)
+ {
+ if(itr->second->GetAuraSlot()==slot)
+ {
+ samespell = true;
+
+ if(GetEffIndex()==i)
+ sameaura = true;
+
+ break;
+ }
+ }
+ if(samespell)
+ break;
+ }
+
+ // only remove icon when the last aura of the spell is removed (current aura already removed from list)
+ if (!samespell)
+ {
+ SetAura(slot, true);
+ SetAuraFlag(slot, false);
+ SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
+
+ SetAuraApplication(slot, 0);
+ // update for out of range group members
+ m_target->UpdateAuraForGroup(slot);
+
+ if( IsSealSpell(GetSpellProto()) )
+ m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false);
+
+ // Conflagrate aura state
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4))
+ m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false);
+
+ // Swiftmend aura state
+ if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
+ && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10))
+ {
+ bool found = false;
+ Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
+ for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
+ {
+ if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
+ && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false);
+ }
+
+ // reset cooldown state for spells
+ if(caster && caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE )
+ ((Player*)caster)->SendCooldownEvent(GetSpellProto());
+ }
+ }
+ else if(sameaura) // decrease count for spell, only for same aura effect, or this spell auras in remove process.
+ UpdateSlotCounterAndDuration(false);
+}
+
+void Aura::SetAuraFlag(uint32 slot, bool add)
+{
+ uint32 index = slot / 4;
+ uint32 byte = (slot % 4) * 8;
+ uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index);
+ val &= ~((uint32)AFLAG_MASK << byte);
+ if(add)
+ {
+ if (IsPositive())
+ val |= ((uint32)AFLAG_POSITIVE << byte);
+ else
+ val |= ((uint32)AFLAG_NEGATIVE << byte);
+ }
+ m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val);
+}
+
+void Aura::SetAuraLevel(uint32 slot,uint32 level)
+{
+ uint32 index = slot / 4;
+ uint32 byte = (slot % 4) * 8;
+ uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index);
+ val &= ~(0xFF << byte);
+ val |= (level << byte);
+ m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val);
+}
+
+void Aura::SetAuraApplication(uint32 slot, int8 count)
+{
+ uint32 index = slot / 4;
+ uint32 byte = (slot % 4) * 8;
+ uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index);
+ val &= ~(0xFF << byte);
+ val |= ((uint8(count)) << byte);
+ m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val);
+}
+
+void Aura::UpdateSlotCounterAndDuration(bool add)
+{
+ uint8 slot = GetAuraSlot();
+ if(slot >= MAX_AURAS)
+ return;
+
+ // calculate amount of similar auras by same effect index (similar different spells)
+ int8 count = 0;
+
+ // calculate auras and update durations in case aura adding
+ Unit::AuraList const& aura_list = m_target->GetAurasByType(GetModifier()->m_auraname);
+ for(Unit::AuraList::const_iterator i = aura_list.begin();i != aura_list.end(); ++i)
+ {
+ if( (*i)->GetId()==GetId() && (*i)->GetEffIndex()==m_effIndex &&
+ (*i)->GetCasterGUID()==GetCasterGUID() )
+ {
+ ++count;
+
+ if(add)
+ (*i)->SetAuraDuration(GetAuraDuration());
+ }
+ }
+
+ // at aura add aura not added yet, at aura remove aura already removed
+ // in field stored (count-1)
+ if(!add)
+ --count;
+
+ SetAuraApplication(slot, count);
+
+ UpdateAuraDuration();
+}
+
+/*********************************************************/
+/*** BASIC AURA FUNCTION ***/
+/*********************************************************/
+void Aura::HandleAddModifier(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER || !Real)
+ return;
+
+ SpellEntry const *spellInfo = GetSpellProto();
+ if(!spellInfo)
+ return;
+
+ if(m_modifier.m_miscvalue >= MAX_SPELLMOD)
+ return;
+
+ if (apply)
+ {
+ // Add custom charges for some mod aura
+ switch (m_spellProto->Id)
+ {
+ case 17941: // Shadow Trance
+ case 22008: // Netherwind Focus
+ case 34936: // Backlash
+ m_procCharges = 1;
+ break;
+ }
+
+ SpellModifier *mod = new SpellModifier;
+ mod->op = SpellModOp(m_modifier.m_miscvalue);
+ mod->value = m_modifier.m_amount;
+ mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types
+ mod->spellId = GetId();
+ mod->effectId = m_effIndex;
+ mod->lastAffected = NULL;
+
+ uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex);
+
+ if (spellAffectMask)
+ mod->mask = spellAffectMask;
+ else
+ mod->mask = spellInfo->EffectItemType[m_effIndex];
+
+ if (m_procCharges > 0)
+ mod->charges = m_procCharges;
+ else
+ mod->charges = 0;
+
+ m_spellmod = mod;
+ }
+
+ uint64 spellFamilyMask = m_spellmod->mask;
+
+ ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
+
+ // reapply some passive spells after add/remove related spellmods
+ if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL))
+ {
+ m_target->RemoveAurasDueToSpell(45471);
+
+ if(apply)
+ m_target->CastSpell(m_target,45471,true);
+ }
+}
+
+void Aura::TriggerSpell()
+{
+ Unit* caster = GetCaster();
+ Unit* target = GetTriggerTarget();
+
+ if(!caster || !target)
+ return;
+
+ // generic casting code with custom spells and target/caster customs
+ uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex];
+
+ uint64 originalCasterGUID = GetCasterGUID();
+
+ SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
+ SpellEntry const *auraSpellInfo = GetSpellProto();
+ uint32 auraId = auraSpellInfo->Id;
+
+ // specific code for cases with no trigger spell provided in field
+ if (triggeredSpellInfo == NULL)
+ {
+ switch(auraSpellInfo->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ {
+ switch(auraId)
+ {
+ // Firestone Passive (1-5 ranks)
+ case 758:
+ case 17945:
+ case 17947:
+ case 17949:
+ case 27252:
+ {
+ if (caster->GetTypeId()!=TYPEID_PLAYER)
+ return;
+ Item* item = ((Player*)caster)->GetWeaponForAttack(BASE_ATTACK);
+ if (!item)
+ return;
+ uint32 enchant_id = 0;
+ switch (GetId())
+ {
+ case 758: enchant_id = 1803; break; // Rank 1
+ case 17945: enchant_id = 1823; break; // Rank 2
+ case 17947: enchant_id = 1824; break; // Rank 3
+ case 17949: enchant_id = 1825; break; // Rank 4
+ case 27252: enchant_id = 2645; break; // Rank 5
+ default:
+ return;
+ }
+ // remove old enchanting before applying new
+ ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false);
+ item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0);
+ // add new enchanting
+ ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true);
+ return;
+ }
+// // Periodic Mana Burn
+// case 812: break;
+// // Polymorphic Ray
+// case 6965: break;
+// // Fire Nova (1-7 ranks)
+// case 8350:
+// case 8508:
+// case 8509:
+// case 11312:
+// case 11313:
+// case 25540:
+// case 25544:
+// break;
+ // Thaumaturgy Channel
+ case 9712: trigger_spell_id = 21029; break;
+// // Egan's Blaster
+// case 17368: break;
+// // Haunted
+// case 18347: break;
+// // Ranshalla Waiting
+// case 18953: break;
+// // Inferno
+// case 19695: break;
+// // Frostwolf Muzzle DND
+// case 21794: break;
+// // Alterac Ram Collar DND
+// case 21866: break;
+// // Celebras Waiting
+// case 21916: break;
+ // Brood Affliction: Bronze
+ case 23170:
+ {
+ m_target->CastSpell(m_target, 23171, true, 0, this);
+ return;
+ }
+// // Mark of Frost
+// case 23184: break;
+ // Restoration
+ case 23493:
+ {
+ int32 heal = caster->GetMaxHealth() / 10;
+ caster->ModifyHealth( heal );
+ caster->SendHealSpellLog(caster, 23493, heal);
+
+ int32 mana = caster->GetMaxPower(POWER_MANA);
+ if (mana)
+ {
+ mana /= 10;
+ caster->ModifyPower( POWER_MANA, mana );
+ caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA);
+ }
+ break;
+ }
+// // Stoneclaw Totem Passive TEST
+// case 23792: break;
+// // Axe Flurry
+// case 24018: break;
+// // Mark of Arlokk
+// case 24210: break;
+// // Restoration
+// case 24379: break;
+// // Happy Pet
+// case 24716: break;
+// // Dream Fog
+// case 24780: break;
+// // Cannon Prep
+// case 24832: break;
+// // Shadow Bolt Whirl
+// case 24834: break;
+// // Stink Trap
+// case 24918: break;
+// // Mark of Nature
+// case 25041: break;
+// // Agro Drones
+// case 25152: break;
+// // Consume
+// case 25371: break;
+// // Pain Spike
+// case 25572: break;
+// // Rotate 360
+// case 26009: break;
+// // Rotate -360
+// case 26136: break;
+// // Consume
+// case 26196: break;
+// // Berserk
+// case 26615: break;
+// // Defile
+// case 27177: break;
+// // Teleport: IF/UC
+// case 27601: break;
+// // Five Fat Finger Exploding Heart Technique
+// case 27673: break;
+// // Nitrous Boost
+// case 27746: break;
+// // Steam Tank Passive
+// case 27747: break;
+// // Frost Blast
+// case 27808: break;
+// // Detonate Mana
+// case 27819: break;
+// // Controller Timer
+// case 28095: break;
+// // Stalagg Chain
+// case 28096: break;
+// // Stalagg Tesla Passive
+// case 28097: break;
+// // Feugen Tesla Passive
+// case 28109: break;
+// // Feugen Chain
+// case 28111: break;
+// // Mark of Didier
+// case 28114: break;
+// // Communique Timer, camp
+// case 28346: break;
+// // Icebolt
+// case 28522: break;
+// // Silithyst
+// case 29519: break;
+// // Inoculate Nestlewood Owlkin
+ case 29528: trigger_spell_id = 28713; break;
+// // Overload
+// case 29768: break;
+// // Return Fire
+// case 29788: break;
+// // Return Fire
+// case 29793: break;
+// // Return Fire
+// case 29794: break;
+// // Guardian of Icecrown Passive
+// case 29897: break;
+ // Feed Captured Animal
+ case 29917: trigger_spell_id = 29916; break;
+// // Flame Wreath
+// case 29946: break;
+// // Flame Wreath
+// case 29947: break;
+// // Mind Exhaustion Passive
+// case 30025: break;
+// // Nether Beam - Serenity
+// case 30401: break;
+ // Extract Gas
+ case 30427:
+ {
+ // move loot to player inventory and despawn target
+ if(caster->GetTypeId() ==TYPEID_PLAYER &&
+ target->GetTypeId() == TYPEID_UNIT &&
+ ((Creature*)target)->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
+ {
+ Player* player = (Player*)caster;
+ Creature* creature = (Creature*)target;
+ // missing lootid has been reported on startup - just return
+ if (!creature->GetCreatureInfo()->SkinLootId)
+ {
+ return;
+ }
+ Loot *loot = &creature->loot;
+ loot->clear();
+ loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL);
+ for(uint8 i=0;i<loot->items.size();i++)
+ {
+ LootItem *item = loot->LootItemInSlot(i,player);
+ ItemPosCountVec dest;
+ uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count );
+ if ( msg == EQUIP_ERR_OK )
+ {
+ Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId);
+
+ player->SendNewItem(newitem, uint32(item->count), false, false, true);
+ }
+ else
+ player->SendEquipError( msg, NULL, NULL );
+ }
+ creature->setDeathState(JUST_DIED);
+ creature->RemoveCorpse();
+ creature->SetHealth(0); // just for nice GM-mode view
+ }
+ return;
+ break;
+ }
+ // Quake
+ case 30576: trigger_spell_id = 30571; break;
+// // Burning Maul
+// case 30598: break;
+// // Regeneration
+// case 30799:
+// case 30800:
+// case 30801:
+// break;
+// // Despawn Self - Smoke cloud
+// case 31269: break;
+// // Time Rift Periodic
+// case 31320: break;
+// // Corrupt Medivh
+// case 31326: break;
+ // Doom
+ case 31347:
+ {
+ m_target->CastSpell(m_target,31350,true);
+ m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ return;
+ }
+ // Spellcloth
+ case 31373:
+ {
+ // Summon Elemental after create item
+ caster->SummonCreature(17870, 0, 0, 0, caster->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
+ return;
+ }
+// // Bloodmyst Tesla
+// case 31611: break;
+// // Doomfire
+// case 31944: break;
+// // Teleport Test
+// case 32236: break;
+// // Earthquake
+// case 32686: break;
+// // Possess
+// case 33401: break;
+// // Draw Shadows
+// case 33563: break;
+// // Murmur's Touch
+// case 33711: break;
+ // Flame Quills
+ case 34229:
+ {
+ // cast 24 spells 34269-34289, 34314-34316
+ for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
+ caster->CastSpell(m_target,spell_id,true);
+ for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
+ caster->CastSpell(m_target,spell_id,true);
+ return;
+ }
+// // Gravity Lapse
+// case 34480: break;
+// // Tornado
+// case 34683: break;
+// // Frostbite Rotate
+// case 34748: break;
+// // Arcane Flurry
+// case 34821: break;
+// // Interrupt Shutdown
+// case 35016: break;
+// // Interrupt Shutdown
+// case 35176: break;
+// // Inferno
+// case 35268: break;
+// // Salaadin's Tesla
+// case 35515: break;
+// // Ethereal Channel (Red)
+// case 35518: break;
+// // Nether Vapor
+// case 35879: break;
+// // Dark Portal Storm
+// case 36018: break;
+// // Burning Maul
+// case 36056: break;
+// // Living Grove Defender Lifespan
+// case 36061: break;
+// // Professor Dabiri Talks
+// case 36064: break;
+// // Kael Gaining Power
+// case 36091: break;
+// // They Must Burn Bomb Aura
+// case 36344: break;
+// // They Must Burn Bomb Aura (self)
+// case 36350: break;
+// // Stolen Ravenous Ravager Egg
+// case 36401: break;
+// // Activated Cannon
+// case 36410: break;
+// // Stolen Ravenous Ravager Egg
+// case 36418: break;
+// // Enchanted Weapons
+// case 36510: break;
+// // Cursed Scarab Periodic
+// case 36556: break;
+// // Cursed Scarab Despawn Periodic
+// case 36561: break;
+// // Vision Guide
+// case 36573: break;
+// // Cannon Charging (platform)
+// case 36785: break;
+// // Cannon Charging (self)
+// case 36860: break;
+ // Remote Toy
+ case 37027: trigger_spell_id = 37029; break;
+// // Mark of Death
+// case 37125: break;
+// // Arcane Flurry
+// case 37268: break;
+// // Spout
+// case 37429: break;
+// // Spout
+// case 37430: break;
+// // Karazhan - Chess NPC AI, Snapshot timer
+// case 37440: break;
+// // Karazhan - Chess NPC AI, action timer
+// case 37504: break;
+// // Karazhan - Chess: Is Square OCCUPIED aura (DND)
+// case 39400: break;
+// // Banish
+// case 37546: break;
+// // Shriveling Gaze
+// case 37589: break;
+// // Fake Aggro Radius (2 yd)
+// case 37815: break;
+// // Corrupt Medivh
+// case 37853: break;
+ // Eye of Grillok
+ case 38495:
+ {
+ m_target->CastSpell(m_target, 38530, true);
+ return;
+ }
+ // Absorb Eye of Grillok (Zezzak's Shard)
+ case 38554:
+ {
+ if(m_target->GetTypeId() != TYPEID_UNIT)
+ return;
+
+ caster->CastSpell(caster, 38495, true);
+
+ Creature* creatureTarget = (Creature*)m_target;
+
+ creatureTarget->setDeathState(JUST_DIED);
+ creatureTarget->RemoveCorpse();
+ creatureTarget->SetHealth(0); // just for nice GM-mode view
+ return;
+ }
+// // Magic Sucker Device timer
+// case 38672: break;
+// // Tomb Guarding Charging
+// case 38751: break;
+// // Murmur's Touch
+// case 38794: break;
+// // Activate Nether-wraith Beacon (31742 Nether-wraith Beacon item)
+// case 39105: break;
+// // Drain World Tree Visual
+// case 39140: break;
+// // Quest - Dustin's Undead Dragon Visual aura
+// case 39259: break;
+// // Hellfire - The Exorcism, Jules releases darkness, aura
+// case 39306: break;
+// // Inferno
+// case 39346: break;
+// // Enchanted Weapons
+// case 39489: break;
+// // Shadow Bolt Whirl
+// case 39630: break;
+// // Shadow Bolt Whirl
+// case 39634: break;
+// // Shadow Inferno
+// case 39645: break;
+ // Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam
+ case 39857: trigger_spell_id = 39856; break;
+// // Soulgrinder Ritual Visual (Smashed)
+// case 39974: break;
+// // Simon Game Pre-game timer
+// case 40041: break;
+// // Knockdown Fel Cannon: The Aggro Check Aura
+// case 40113: break;
+// // Spirit Lance
+// case 40157: break;
+// // Demon Transform 2
+// case 40398: break;
+// // Demon Transform 1
+// case 40511: break;
+// // Ancient Flames
+// case 40657: break;
+// // Ethereal Ring Cannon: Cannon Aura
+// case 40734: break;
+// // Cage Trap
+// case 40760: break;
+// // Random Periodic
+// case 40867: break;
+// // Prismatic Shield
+// case 40879: break;
+ // Aura of Desire
+ case 41350:
+ {
+ Unit::AuraList const& mMod = m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT);
+ for(Unit::AuraList::const_iterator i = mMod.begin(); i != mMod.end(); ++i)
+ {
+ if ((*i)->GetId() == 41350)
+ {
+ (*i)->ApplyModifier(false);
+ (*i)->GetModifier()->m_amount -= 5;
+ (*i)->ApplyModifier(true);
+ break;
+ }
+ }
+ }break;
+// // Dementia
+// case 41404: break;
+// // Chaos Form
+// case 41629: break;
+// // Alert Drums
+// case 42177: break;
+// // Spout
+// case 42581: break;
+// // Spout
+// case 42582: break;
+// // Return to the Spirit Realm
+// case 44035: break;
+// // Curse of Boundless Agony
+// case 45050: break;
+// // Earthquake
+// case 46240: break;
+ // Personalized Weather
+ case 46736: trigger_spell_id = 46737; break;
+// // Stay Submerged
+// case 46981: break;
+// // Dragonblight Ram
+// case 47015: break;
+// // Party G.R.E.N.A.D.E.
+// case 51510: break;
+ default:
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_MAGE:
+ {
+ switch(auraId)
+ {
+ // Invisibility
+ case 66:
+ {
+ if(!m_duration)
+ m_target->CastSpell(m_target, 32612, true, NULL, this);
+ return;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+// case SPELLFAMILY_WARRIOR:
+// {
+// switch(auraId)
+// {
+// // Wild Magic
+// case 23410: break;
+// // Corrupted Totems
+// case 23425: break;
+// default:
+// break;
+// }
+// break;
+// }
+// case SPELLFAMILY_PRIEST:
+// {
+// switch(auraId)
+// {
+// // Blue Beam
+// case 32930: break;
+// // Fury of the Dreghood Elders
+// case 35460: break;
+// default:
+// break;
+// }
+ // break;
+ // }
+ case SPELLFAMILY_DRUID:
+ {
+ switch(auraId)
+ {
+ // Cat Form
+ // trigger_spell_id not set and unknown effect triggered in this case, ignoring for while
+ case 768:
+ return;
+ // Frenzied Regeneration
+ case 22842:
+ case 22895:
+ case 22896:
+ case 26999:
+ {
+ int32 LifePerRage = GetModifier()->m_amount;
+
+ int32 lRage = m_target->GetPower(POWER_RAGE);
+ if(lRage > 100) // rage stored as rage*10
+ lRage = 100;
+ m_target->ModifyPower(POWER_RAGE, -lRage);
+ int32 FRTriggerBasePoints = int32(lRage*LifePerRage/10);
+ m_target->CastCustomSpell(m_target,22845,&FRTriggerBasePoints,NULL,NULL,true,NULL,this);
+ return;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+
+// case SPELLFAMILY_HUNTER:
+// {
+// switch(auraId)
+// {
+// //Frost Trap Aura
+// case 13810:
+// return;
+// //Rizzle's Frost Trap
+// case 39900:
+// return;
+// // Tame spells
+// case 19597: // Tame Ice Claw Bear
+// case 19676: // Tame Snow Leopard
+// case 19677: // Tame Large Crag Boar
+// case 19678: // Tame Adult Plainstrider
+// case 19679: // Tame Prairie Stalker
+// case 19680: // Tame Swoop
+// case 19681: // Tame Dire Mottled Boar
+// case 19682: // Tame Surf Crawler
+// case 19683: // Tame Armored Scorpid
+// case 19684: // Tame Webwood Lurker
+// case 19685: // Tame Nightsaber Stalker
+// case 19686: // Tame Strigid Screecher
+// case 30100: // Tame Crazed Dragonhawk
+// case 30103: // Tame Elder Springpaw
+// case 30104: // Tame Mistbat
+// case 30647: // Tame Barbed Crawler
+// case 30648: // Tame Greater Timberstrider
+// case 30652: // Tame Nightstalker
+// return;
+// default:
+// break;
+// }
+// break;
+// }
+ case SPELLFAMILY_SHAMAN:
+ {
+ switch(auraId)
+ {
+ // Lightning Shield (The Earthshatterer set trigger after cast Lighting Shield)
+ case 28820:
+ {
+ // Need remove self if Lightning Shield not active
+ Unit::AuraMap const& auras = target->GetAuras();
+ for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
+ {
+ SpellEntry const* spell = itr->second->GetSpellProto();
+ if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN &&
+ spell->SpellFamilyFlags & 0x0000000000000400L)
+ return;
+ }
+ target->RemoveAurasDueToSpell(28820);
+ return;
+ }
+ // Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
+ case 38443:
+ {
+ bool all = true;
+ for(int i = 0; i < MAX_TOTEM; ++i)
+ {
+ if(!caster->m_TotemSlot[i])
+ {
+ all = false;
+ break;
+ }
+ }
+
+ if(all)
+ caster->CastSpell(caster,38437,true);
+ else
+ caster->RemoveAurasDueToSpell(38437);
+ return;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ // Reget trigger spell proto
+ triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id);
+ if(triggeredSpellInfo == NULL)
+ {
+ sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
+ return;
+ }
+ }
+ else
+ {
+ // Spell exist but require custom code
+ switch(auraId)
+ {
+ // Curse of Idiocy
+ case 1010:
+ {
+ // TODO: spell casted by result in correct way mostly
+ // BUT:
+ // 1) target show casting at each triggered cast: target don't must show casting animation for any triggered spell
+ // but must show affect apply like item casting
+ // 2) maybe aura must be replace by new with accumulative stat mods instead stacking
+
+ // prevent cast by triggered auras
+ if(m_caster_guid == m_target->GetGUID())
+ return;
+
+ // stop triggering after each affected stats lost > 90
+ int32 intellectLoss = 0;
+ int32 spiritLoss = 0;
+
+ Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT);
+ for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i)
+ {
+ if ((*i)->GetId() == 1010)
+ {
+ switch((*i)->GetModifier()->m_miscvalue)
+ {
+ case STAT_INTELLECT: intellectLoss += (*i)->GetModifier()->m_amount; break;
+ case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break;
+ default: break;
+ }
+ }
+ }
+
+ if(intellectLoss <= -90 && spiritLoss <= -90)
+ return;
+
+ caster = target;
+ originalCasterGUID = 0;
+ break;
+ }
+ // Mana Tide
+ case 16191:
+ {
+ caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID);
+ return;
+ }
+ }
+ }
+ m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, originalCasterGUID);
+}
+
+Unit* Aura::GetTriggerTarget() const
+{
+ Unit* target = ObjectAccessor::GetUnit(*m_target,
+ /*m_target->GetTypeId()==TYPEID_PLAYER ?
+ ((Player*)m_target)->GetSelection() :*/
+ m_target->GetUInt64Value(UNIT_FIELD_TARGET));
+ return target ? target : m_target;
+}
+
+/*********************************************************/
+/*** AURA EFFECTS ***/
+/*********************************************************/
+
+void Aura::HandleAuraDummy(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ Unit* caster = GetCaster();
+
+ // AT APPLY
+ if(apply)
+ {
+ switch(GetId())
+ {
+ case 1515: // Tame beast
+ // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
+ if( caster && m_target->CanHaveThreatList())
+ m_target->AddThreat(caster, 10.0f);
+ return;
+ case 13139: // net-o-matic
+ // root to self part of (root_target->charge->root_self sequence
+ if(caster)
+ caster->CastSpell(caster,13138,true,NULL,this);
+ return;
+ case 39850: // Rocket Blast
+ if(roll_chance_i(20)) // backfire stun
+ m_target->CastSpell(m_target, 51581, true, NULL, this);
+ return;
+ case 43873: // Headless Horseman Laugh
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)caster)->SendPlaySound(11965, false);
+ return;
+ case 46354: // Blood Elf Illusion
+ if(caster)
+ {
+ switch(caster->getGender())
+ {
+ case GENDER_FEMALE:
+ caster->CastSpell(m_target,46356,true,NULL,this);
+ break;
+ case GENDER_MALE:
+ caster->CastSpell(m_target,46355,true,NULL,this);
+ break;
+ default:
+ break;
+ }
+ }
+ return;
+ case 46699: // Requires No Ammo
+ if(m_target->GetTypeId()==TYPEID_PLAYER)
+ ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use
+ return;
+ }
+
+ // Earth Shield
+ if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL))
+ {
+ // prevent double apply bonuses
+ if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
+ m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
+ return;
+ }
+ }
+ // AT REMOVE
+ else
+ {
+ if( m_target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->Effect[0]==72 )
+ {
+ // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
+ ((Player*)m_target)->ClearFarsight();
+ return;
+ }
+
+ if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive())
+ {
+ uint32 finalSpelId = 0;
+ switch(GetId())
+ {
+ case 19548: finalSpelId = 19597; break;
+ case 19674: finalSpelId = 19677; break;
+ case 19687: finalSpelId = 19676; break;
+ case 19688: finalSpelId = 19678; break;
+ case 19689: finalSpelId = 19679; break;
+ case 19692: finalSpelId = 19680; break;
+ case 19693: finalSpelId = 19684; break;
+ case 19694: finalSpelId = 19681; break;
+ case 19696: finalSpelId = 19682; break;
+ case 19697: finalSpelId = 19683; break;
+ case 19699: finalSpelId = 19685; break;
+ case 19700: finalSpelId = 19686; break;
+ case 30646: finalSpelId = 30647; break;
+ case 30653: finalSpelId = 30648; break;
+ case 30654: finalSpelId = 30652; break;
+ case 30099: finalSpelId = 30100; break;
+ case 30102: finalSpelId = 30103; break;
+ case 30105: finalSpelId = 30104; break;
+ }
+
+ if(finalSpelId)
+ caster->CastSpell(m_target,finalSpelId,true,NULL,this);
+ return;
+ }
+
+ // Waiting to Resurrect
+ if(GetId()==2584)
+ {
+ // Waiting to resurrect spell cancel, we must remove player from resurrect queue
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
+ bg->RemovePlayerFromResurrectQueue(m_target->GetGUID());
+ return;
+ }
+
+ // Dark Fiend
+ /*if(GetId()==45934)
+ {
+ // Kill target if dispelled
+ if (m_removeMode==AURA_REMOVE_BY_DISPEL)
+ m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ return;
+ }*/
+
+ // Burning Winds
+ if(GetId()==46308) // casted only at creatures at spawn
+ {
+ m_target->CastSpell(m_target,47287,true,NULL,this);
+ return;
+ }
+
+ // Eye of Kilrogg, unsummon eye when aura is gone
+ if(GetId() == 126 && caster->GetTypeId() == TYPEID_PLAYER && caster->GetCharm())
+ {
+ ((TemporarySummon*)caster->GetCharm())->UnSummon();
+ return;
+ }
+ }
+
+ // AT APPLY & REMOVE
+
+ switch(m_spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ {
+ // Unstable Power
+ if( GetId()==24658 )
+ {
+ uint32 spellId = 24659;
+ if (apply)
+ {
+ const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
+ if (!spell)
+ return;
+ for (int i=0; i < spell->StackAmount; ++i)
+ caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
+ return;
+ }
+ m_target->RemoveAurasDueToSpell(spellId);
+ return;
+ }
+ // Restless Strength
+ if( GetId()==24661 )
+ {
+ uint32 spellId = 24662;
+ if (apply)
+ {
+ const SpellEntry *spell = sSpellStore.LookupEntry(spellId);
+ if (!spell)
+ return;
+ for (int i=0; i < spell->StackAmount; ++i)
+ caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID());
+ return;
+ }
+ m_target->RemoveAurasDueToSpell(spellId);
+ return;
+ }
+ // Victorious
+ if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR)
+ {
+ m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply);
+ return;
+ }
+ //Summon Fire Elemental
+ if (GetId() == 40133 && caster)
+ {
+ Unit *owner = caster->GetOwner();
+ if (owner && owner->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(apply)
+ owner->CastSpell(owner,8985,true);
+ else
+ ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
+ }
+ return;
+ }
+
+ //Summon Earth Elemental
+ if (GetId() == 40132 && caster)
+ {
+ Unit *owner = caster->GetOwner();
+ if (owner && owner->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(apply)
+ owner->CastSpell(owner,19704,true);
+ else
+ ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
+ }
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_MAGE:
+ {
+ // Hypothermia
+ if( GetId()==41425 )
+ {
+ m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply);
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_DRUID:
+ {
+ // Lifebloom
+ if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL )
+ {
+ if ( apply )
+ {
+ if ( caster )
+ // prevent double apply bonuses
+ if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading())
+ m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target);
+ }
+ else
+ {
+ // Final heal only on dispelled or duration end
+ if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) )
+ return;
+
+ // have a look if there is still some other Lifebloom dummy aura
+ Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); itr++)
+ if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID &&
+ (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL)
+ return;
+
+ // final heal
+ m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID());
+ }
+ return;
+ }
+
+ // Predatory Strikes
+ if(m_target->GetTypeId()==TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
+ {
+ ((Player*)m_target)->UpdateAttackPowerAndDamage();
+ return;
+ }
+ // Idol of the Emerald Queen
+ if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER )
+ {
+ if(apply)
+ {
+ SpellModifier *mod = new SpellModifier;
+ mod->op = SPELLMOD_DOT;
+ mod->value = m_modifier.m_amount/7;
+ mod->type = SPELLMOD_FLAT;
+ mod->spellId = GetId();
+ mod->effectId = m_effIndex;
+ mod->lastAffected = NULL;
+ mod->mask = 0x001000000000LL;
+ mod->charges = 0;
+
+ m_spellmod = mod;
+ }
+
+ ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_HUNTER:
+ {
+ // Improved Aspect of the Viper
+ if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER )
+ {
+ if(apply)
+ {
+ // + effect value for Aspect of the Viper
+ SpellModifier *mod = new SpellModifier;
+ mod->op = SPELLMOD_EFFECT1;
+ mod->value = m_modifier.m_amount;
+ mod->type = SPELLMOD_FLAT;
+ mod->spellId = GetId();
+ mod->effectId = m_effIndex;
+ mod->lastAffected = NULL;
+ mod->mask = 0x4000000000000LL;
+ mod->charges = 0;
+
+ m_spellmod = mod;
+ }
+
+ ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_SHAMAN:
+ {
+ // Improved Weapon Totems
+ if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER )
+ {
+ if(apply)
+ {
+ SpellModifier *mod = new SpellModifier;
+ mod->op = SPELLMOD_EFFECT1;
+ mod->value = m_modifier.m_amount;
+ mod->type = SPELLMOD_PCT;
+ mod->spellId = GetId();
+ mod->effectId = m_effIndex;
+ mod->lastAffected = NULL;
+ switch (m_effIndex)
+ {
+ case 0:
+ mod->mask = 0x00200000000LL; // Windfury Totem
+ break;
+ case 1:
+ mod->mask = 0x00400000000LL; // Flametongue Totem
+ break;
+ }
+ mod->charges = 0;
+
+ m_spellmod = mod;
+ }
+
+ ((Player*)m_target)->AddSpellMod(m_spellmod, apply);
+ return;
+ }
+
+ // Sentry Totem
+ if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (apply)
+ {
+ uint64 guid = caster->m_TotemSlot[3];
+ if (guid)
+ {
+ Creature *totem = ObjectAccessor::GetCreature(*caster, guid);
+ if (totem && totem->isTotem())
+ totem->AddPlayerToVision((Player*)caster);
+ }
+ }
+ else
+ ((Player*)caster)->RemoveFarsightTarget();
+ return;
+ }
+ break;
+ }
+ }
+
+ // pet auras
+ if(PetAura const* petSpell = spellmgr.GetPetAura(GetId()))
+ {
+ if(apply)
+ m_target->AddPetAura(petSpell);
+ else
+ m_target->RemovePetAura(petSpell);
+ return;
+ }
+}
+
+void Aura::HandleAuraPeriodicDummy(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ SpellEntry const*spell = GetSpellProto();
+ switch( spell->SpellFamilyName)
+ {
+ case SPELLFAMILY_ROGUE:
+ {
+ // Master of Subtlety
+ if (spell->Id==31666 && !apply && Real)
+ {
+ m_target->RemoveAurasDueToSpell(31665);
+ break;
+ }
+ break;
+ }
+ case SPELLFAMILY_HUNTER:
+ {
+ // Aspect of the Viper
+ if (spell->SpellFamilyFlags&0x0004000000000000LL)
+ {
+ // Update regen on remove
+ if (!apply && m_target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)m_target)->UpdateManaRegen();
+ break;
+ }
+ break;
+ }
+ }
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandleAuraMounted(bool apply, bool Real)
+{
+ if(apply)
+ {
+ CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
+ if(!ci)
+ {
+ sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue);
+ return;
+ }
+
+ uint32 team = 0;
+ if (m_target->GetTypeId()==TYPEID_PLAYER)
+ team = ((Player*)m_target)->GetTeam();
+
+ uint32 display_id = objmgr.ChooseDisplayId(team,ci);
+ CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
+ if (minfo)
+ display_id = minfo->modelid;
+
+ m_target->Mount(display_id);
+ }
+ else
+ {
+ m_target->Unmount();
+ }
+}
+
+void Aura::HandleAuraWaterWalk(bool apply, bool Real)
+{
+ // only at real add/remove aura
+ if(!Real)
+ return;
+
+ WorldPacket data;
+ if(apply)
+ data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
+ else
+ data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
+ data.append(m_target->GetPackGUID());
+ data << uint32(0);
+ m_target->SendMessageToSet(&data,true);
+}
+
+void Aura::HandleAuraFeatherFall(bool apply, bool Real)
+{
+ // only at real add/remove aura
+ if(!Real)
+ return;
+
+ WorldPacket data;
+ if(apply)
+ data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
+ else
+ data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
+ data.append(m_target->GetPackGUID());
+ data << (uint32)0;
+ m_target->SendMessageToSet(&data,true);
+}
+
+void Aura::HandleAuraHover(bool apply, bool Real)
+{
+ // only at real add/remove aura
+ if(!Real)
+ return;
+
+ WorldPacket data;
+ if(apply)
+ data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
+ else
+ data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
+ data.append(m_target->GetPackGUID());
+ data << uint32(0);
+ m_target->SendMessageToSet(&data,true);
+}
+
+void Aura::HandleWaterBreathing(bool apply, bool Real)
+{
+ if(apply)
+ m_target->waterbreath = true;
+ else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty())
+ {
+ m_target->waterbreath = false;
+
+ // update for enable timer in case not moving target
+ if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld())
+ {
+ ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ());
+ ((Player*)m_target)->HandleDrowning();
+ }
+ }
+}
+
+void Aura::HandleAuraModShapeshift(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ uint32 modelid = 0;
+ Powers PowerType = POWER_MANA;
+ ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue);
+ switch(form)
+ {
+ case FORM_CAT:
+ if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
+ modelid = 892;
+ else
+ modelid = 8571;
+ PowerType = POWER_ENERGY;
+ break;
+ case FORM_TRAVEL:
+ modelid = 632;
+ break;
+ case FORM_AQUA:
+ if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
+ modelid = 2428;
+ else
+ modelid = 2428;
+ break;
+ case FORM_BEAR:
+ if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
+ modelid = 2281;
+ else
+ modelid = 2289;
+ PowerType = POWER_RAGE;
+ break;
+ case FORM_GHOUL:
+ if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
+ modelid = 10045;
+ break;
+ case FORM_DIREBEAR:
+ if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
+ modelid = 2281;
+ else
+ modelid = 2289;
+ PowerType = POWER_RAGE;
+ break;
+ case FORM_CREATUREBEAR:
+ modelid = 902;
+ break;
+ case FORM_GHOSTWOLF:
+ modelid = 4613;
+ break;
+ case FORM_FLIGHT:
+ if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
+ modelid = 20857;
+ else
+ modelid = 20872;
+ break;
+ case FORM_MOONKIN:
+ if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
+ modelid = 15374;
+ else
+ modelid = 15375;
+ break;
+ case FORM_FLIGHT_EPIC:
+ if(Player::TeamForRace(m_target->getRace())==ALLIANCE)
+ modelid = 21243;
+ else
+ modelid = 21244;
+ break;
+ case FORM_AMBIENT:
+ case FORM_SHADOW:
+ case FORM_STEALTH:
+ break;
+ case FORM_TREE:
+ modelid = 864;
+ break;
+ case FORM_BATTLESTANCE:
+ case FORM_BERSERKERSTANCE:
+ case FORM_DEFENSIVESTANCE:
+ PowerType = POWER_RAGE;
+ break;
+ case FORM_SPIRITOFREDEMPTION:
+ modelid = 16031;
+ break;
+ default:
+ sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue);
+ }
+
+ // remove polymorph before changing display id to keep new display id
+ switch ( form )
+ {
+ case FORM_CAT:
+ case FORM_TREE:
+ case FORM_TRAVEL:
+ case FORM_AQUA:
+ case FORM_BEAR:
+ case FORM_DIREBEAR:
+ case FORM_FLIGHT_EPIC:
+ case FORM_FLIGHT:
+ case FORM_MOONKIN:
+ // remove movement affects
+ m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
+ m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
+
+ // and polymorphic affects
+ if(m_target->IsPolymorphed())
+ m_target->RemoveAurasDueToSpell(m_target->getTransForm());
+ break;
+ default:
+ break;
+ }
+
+ if(apply)
+ {
+ // remove other shapeshift before applying a new one
+ if(m_target->m_ShapeShiftFormSpellId)
+ m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this);
+
+ m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
+
+ if(modelid > 0)
+ m_target->SetDisplayId(modelid);
+
+ if(PowerType != POWER_MANA)
+ {
+ // reset power to default values only at power change
+ if(m_target->getPowerType()!=PowerType)
+ m_target->setPowerType(PowerType);
+
+ switch(form)
+ {
+ case FORM_CAT:
+ case FORM_BEAR:
+ case FORM_DIREBEAR:
+ {
+ // get furor proc chance
+ uint32 FurorChance = 0;
+ Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i)
+ {
+ if ((*i)->GetSpellProto()->SpellIconID == 238)
+ {
+ FurorChance = (*i)->GetModifier()->m_amount;
+ break;
+ }
+ }
+
+ if (m_modifier.m_miscvalue == FORM_CAT)
+ {
+ m_target->SetPower(POWER_ENERGY,0);
+ if(urand(1,100) <= FurorChance)
+ m_target->CastSpell(m_target,17099,true,NULL,this);
+ }
+ else
+ {
+ m_target->SetPower(POWER_RAGE,0);
+ if(urand(1,100) <= FurorChance)
+ m_target->CastSpell(m_target,17057,true,NULL,this);
+ }
+ break;
+ }
+ case FORM_BATTLESTANCE:
+ case FORM_DEFENSIVESTANCE:
+ case FORM_BERSERKERSTANCE:
+ {
+ uint32 Rage_val = 0;
+ // Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ PlayerSpellMap const& sp_list = ((Player *)m_target)->GetSpellMap();
+ for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
+ {
+ if(itr->second->state == PLAYERSPELL_REMOVED) continue;
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
+ if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
+ Rage_val += m_target->CalculateSpellDamage(spellInfo,0,spellInfo->EffectBasePoints[0],m_target) * 10;
+ }
+ }
+
+ if (m_target->GetPower(POWER_RAGE) > Rage_val)
+ m_target->SetPower(POWER_RAGE,Rage_val);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ m_target->m_ShapeShiftFormSpellId = GetId();
+ m_target->m_form = form;
+ }
+ else
+ {
+ if(modelid > 0)
+ m_target->SetDisplayId(m_target->GetNativeDisplayId());
+ m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
+ if(m_target->getClass() == CLASS_DRUID)
+ m_target->setPowerType(POWER_MANA);
+ m_target->m_ShapeShiftFormSpellId = 0;
+ m_target->m_form = FORM_NONE;
+
+ switch(form)
+ {
+ // Nordrassil Harness - bonus
+ case FORM_BEAR:
+ case FORM_DIREBEAR:
+ case FORM_CAT:
+ {
+ if(Aura* dummy = m_target->GetDummyAura(37315) )
+ m_target->CastSpell(m_target,37316,true,NULL,dummy);
+ break;
+ }
+ // Nordrassil Regalia - bonus
+ case FORM_MOONKIN:
+ {
+ if(Aura* dummy = m_target->GetDummyAura(37324) )
+ m_target->CastSpell(m_target,37325,true,NULL,dummy);
+ break;
+ }
+ }
+ }
+
+ // adding/removing linked auras
+ // add/remove the shapeshift aura's boosts
+ HandleShapeshiftBoosts(apply);
+
+ if(m_target->GetTypeId()==TYPEID_PLAYER)
+ ((Player*)m_target)->InitDataForForm();
+}
+
+void Aura::HandleAuraTransform(bool apply, bool Real)
+{
+ if (apply)
+ {
+ // special case (spell specific functionality)
+ if(m_modifier.m_miscvalue==0)
+ {
+ // player applied only
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ switch(GetId())
+ {
+ // Orb of Deception
+ case 16739:
+ {
+ uint32 orb_model = m_target->GetNativeDisplayId();
+ switch(orb_model)
+ {
+ // Troll Female
+ case 1479: m_target->SetDisplayId(10134); break;
+ // Troll Male
+ case 1478: m_target->SetDisplayId(10135); break;
+ // Tauren Male
+ case 59: m_target->SetDisplayId(10136); break;
+ // Human Male
+ case 49: m_target->SetDisplayId(10137); break;
+ // Human Female
+ case 50: m_target->SetDisplayId(10138); break;
+ // Orc Male
+ case 51: m_target->SetDisplayId(10139); break;
+ // Orc Female
+ case 52: m_target->SetDisplayId(10140); break;
+ // Dwarf Male
+ case 53: m_target->SetDisplayId(10141); break;
+ // Dwarf Female
+ case 54: m_target->SetDisplayId(10142); break;
+ // NightElf Male
+ case 55: m_target->SetDisplayId(10143); break;
+ // NightElf Female
+ case 56: m_target->SetDisplayId(10144); break;
+ // Undead Female
+ case 58: m_target->SetDisplayId(10145); break;
+ // Undead Male
+ case 57: m_target->SetDisplayId(10146); break;
+ // Tauren Female
+ case 60: m_target->SetDisplayId(10147); break;
+ // Gnome Male
+ case 1563: m_target->SetDisplayId(10148); break;
+ // Gnome Female
+ case 1564: m_target->SetDisplayId(10149); break;
+ // BloodElf Female
+ case 15475: m_target->SetDisplayId(17830); break;
+ // BloodElf Male
+ case 15476: m_target->SetDisplayId(17829); break;
+ // Dranei Female
+ case 16126: m_target->SetDisplayId(17828); break;
+ // Dranei Male
+ case 16125: m_target->SetDisplayId(17827); break;
+ default: break;
+ }
+ break;
+ }
+ // Murloc costume
+ case 42365: m_target->SetDisplayId(21723); break;
+ default: break;
+ }
+ }
+ else
+ {
+ CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue);
+ if(!ci)
+ {
+ //pig pink ^_^
+ m_target->SetDisplayId(16358);
+ sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId());
+ }
+ else
+ {
+ if (uint32 modelid = ci->GetRandomValidModelId()) m_target->SetDisplayId(modelid);
+
+ // Dragonmaw Illusion (set mount model also)
+ if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty())
+ m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
+ }
+ m_target->setTransForm(GetId());
+ }
+
+ // polymorph case
+ if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed())
+ {
+ // for players, start regeneration after 1s (in polymorph fast regeneration case)
+ // only if caster is Player (after patch 2.4.2)
+ if(IS_PLAYER_GUID(GetCasterGUID()) )
+ ((Player*)m_target)->setRegenTimer(1000);
+
+ //dismount polymorphed target (after patch 2.4.2)
+ if (m_target->IsMounted())
+ m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
+ }
+ }
+ else
+ {
+ Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM);
+ if(otherTransforms.empty())
+ {
+ m_target->SetDisplayId(m_target->GetNativeDisplayId());
+ m_target->setTransForm(0);
+ }
+ else
+ {
+ // look for other transform auras
+ Aura* handledAura = *otherTransforms.begin();
+ for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i)
+ {
+ // negative auras are preferred
+ if(!IsPositiveSpell((*i)->GetSpellProto()->Id))
+ {
+ handledAura = *i;
+ break;
+ }
+ }
+ handledAura->ApplyModifier(true);
+ }
+
+ // Dragonmaw Illusion (restore mount model)
+ if(GetId()==42016 && m_target->GetMountID()==16314)
+ {
+ if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty())
+ {
+ uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue;
+ if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
+ {
+ uint32 team = 0;
+ if (m_target->GetTypeId()==TYPEID_PLAYER)
+ team = ((Player*)m_target)->GetTeam();
+
+ uint32 display_id = objmgr.ChooseDisplayId(team,ci);
+ CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
+ if (minfo)
+ display_id = minfo->modelid;
+
+ m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
+ }
+ }
+ }
+ }
+}
+
+void Aura::HandleForceReaction(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if(!Real)
+ return;
+
+ Player* player = (Player*)m_target;
+
+ uint32 faction_id = m_modifier.m_miscvalue;
+ uint32 faction_rank = m_modifier.m_amount;
+
+ if(apply)
+ player->m_forcedReactions[faction_id] = ReputationRank(faction_rank);
+ else
+ player->m_forcedReactions.erase(faction_id);
+
+ WorldPacket data;
+ data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4));
+ data << uint32(player->m_forcedReactions.size());
+ for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr)
+ {
+ data << uint32(itr->first); // faction_id (Faction.dbc)
+ data << uint32(itr->second); // reputation rank
+ }
+ player->SendDirectMessage(&data);
+}
+
+void Aura::HandleAuraModSkill(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex];
+ int32 points = GetModifier()->m_amount;
+
+ ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT);
+ if(prot == SKILL_DEFENSE)
+ ((Player*)m_target)->UpdateDefenseBonusesMod();
+}
+
+void Aura::HandleChannelDeathItem(bool apply, bool Real)
+{
+ if(Real && !apply)
+ {
+ Unit* caster = GetCaster();
+ Unit* victim = GetTarget();
+ if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim || m_removeMode!=AURA_REMOVE_BY_DEATH)
+ return;
+
+ SpellEntry const *spellInfo = GetSpellProto();
+ if(spellInfo->EffectItemType[m_effIndex] == 0)
+ return;
+
+ // Soul Shard only from non-grey units
+ if( spellInfo->EffectItemType[m_effIndex] == 6265 &&
+ (victim->getLevel() <= Trinity::XP::GetGrayLevel(caster->getLevel()) ||
+ victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) )
+ return;
+ ItemPosCountVec dest;
+ uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 );
+ if( msg != EQUIP_ERR_OK )
+ {
+ ((Player*)caster)->SendEquipError( msg, NULL, NULL );
+ return;
+ }
+
+ Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true);
+ ((Player*)caster)->SendNewItem(newitem, 1, true, false);
+ }
+}
+
+void Aura::HandleBindSight(bool apply, bool Real)
+{
+ Unit* caster = GetCaster();
+ if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (apply)
+ m_target->AddPlayerToVision((Player*)caster);
+ else
+ m_target->RemovePlayerFromVision((Player*)caster);
+}
+
+void Aura::HandleFarSight(bool apply, bool Real)
+{
+ Unit* caster = GetCaster();
+ if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_modifier.m_miscvalue : 0);
+}
+
+void Aura::HandleAuraTrackCreatures(bool apply, bool Real)
+{
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ if(apply)
+ m_target->RemoveNoStackAurasDueToAura(this);
+ m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 );
+}
+
+void Aura::HandleAuraTrackResources(bool apply, bool Real)
+{
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ if(apply)
+ m_target->RemoveNoStackAurasDueToAura(this);
+ m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 );
+}
+
+void Aura::HandleAuraTrackStealthed(bool apply, bool Real)
+{
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ if(apply)
+ m_target->RemoveNoStackAurasDueToAura(this);
+
+ m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
+}
+
+void Aura::HandleAuraModScale(bool apply, bool Real)
+{
+ m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply);
+}
+
+void Aura::HandleModPossess(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ if(m_target->getLevel() > m_modifier.m_amount)
+ return;
+
+ // not possess yourself
+ if(GetCasterGUID() == m_target->GetGUID())
+ return;
+
+ Unit* caster = GetCaster();
+ if(!caster)
+ return;
+
+ if( apply )
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)caster)->Possess(m_target);
+ }
+ else
+ m_target->UnpossessSelf(true);
+}
+
+void Aura::HandleModPossessPet(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ Unit* caster = GetCaster();
+ if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+ if(caster->GetPet() != m_target)
+ return;
+
+ if(apply)
+ {
+ ((Player*)caster)->Possess(m_target);
+ }
+ else
+ {
+ ((Player*)caster)->RemovePossess(false);
+ }
+}
+
+void Aura::HandleModCharm(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ // not charm yourself
+ if(GetCasterGUID() == m_target->GetGUID())
+ return;
+
+ Unit* caster = GetCaster();
+ if(!caster)
+ return;
+
+ if(int32(m_target->getLevel()) <= m_modifier.m_amount)
+ {
+ if( apply )
+ {
+ m_target->SetCharmerGUID(GetCasterGUID());
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction());
+ m_target->CastStop(m_target==caster ? GetId() : 0);
+ caster->SetCharm(m_target);
+
+ m_target->CombatStop();
+ m_target->DeleteThreatList();
+
+ if(m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ ((Creature*)m_target)->AIM_Initialize();
+ CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
+ charmInfo->InitCharmCreateSpells();
+ charmInfo->SetReactState( REACT_DEFENSIVE );
+
+ if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK)
+ {
+ CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
+ if(cinfo && cinfo->type == CREATURE_TYPE_DEMON)
+ {
+ //to prevent client crash
+ m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048);
+ //just to enable stat window
+ charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true);
+ //if charmed two demons the same session, the 2nd gets the 1st one's name
+ m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
+ }
+ }
+ }
+
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Player*)caster)->CharmSpellInitialize();
+ }
+ }
+ else
+ {
+ m_target->SetCharmerGUID(0);
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)m_target)->setFactionForRace(m_target->getRace());
+ else
+ {
+ CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo();
+
+ // restore faction
+ if(((Creature*)m_target)->isPet())
+ {
+ if(Unit* owner = m_target->GetOwner())
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction());
+ else if(cinfo)
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
+ }
+ else if(cinfo) // normal creature
+ m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A);
+
+ // restore UNIT_FIELD_BYTES_0
+ if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON)
+ {
+ CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon();
+ if(cainfo && cainfo->bytes0 != 0)
+ m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0);
+ else
+ m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048);
+
+ if(m_target->GetCharmInfo())
+ m_target->GetCharmInfo()->SetPetNumber(0, true);
+ else
+ sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId());
+ }
+ }
+
+ caster->SetCharm(0);
+
+ if(caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_PET_SPELLS, 8);
+ data << uint64(0);
+ ((Player*)caster)->GetSession()->SendPacket(&data);
+ }
+ if(m_target->GetTypeId() == TYPEID_UNIT)
+ {
+ ((Creature*)m_target)->AIM_Initialize();
+ if (((Creature*)m_target)->AI())
+ ((Creature*)m_target)->AI()->AttackStart(caster);
+ }
+ }
+ }
+}
+
+void Aura::HandleModConfuse(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ m_target->SetConfused(apply, GetCasterGUID(), GetId());
+}
+
+void Aura::HandleModFear(bool apply, bool Real)
+{
+ if (!Real)
+ return;
+
+ m_target->SetFeared(apply, GetCasterGUID(), GetId());
+}
+
+void Aura::HandleFeignDeath(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if( apply )
+ {
+ /*
+ WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
+ data<<m_target->GetGUID();
+ data<<uint8(0);
+ m_target->SendMessageToSet(&data,true);
+ */
+ // blizz like 2.0.x
+ m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
+ // blizz like 2.0.x
+ m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+ // blizz like 2.0.x
+ m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+
+ m_target->addUnitState(UNIT_STAT_DIED);
+ m_target->CombatStop();
+ m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE);
+
+ // prevent interrupt message
+ if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL])
+ m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
+ m_target->InterruptNonMeleeSpells(true);
+ m_target->getHostilRefManager().deleteReferences();
+ }
+ else
+ {
+ /*
+ WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
+ data<<m_target->GetGUID();
+ data<<uint8(1);
+ m_target->SendMessageToSet(&data,true);
+ */
+ // blizz like 2.0.x
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6);
+ // blizz like 2.0.x
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
+ // blizz like 2.0.x
+ m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+
+ m_target->clearUnitState(UNIT_STAT_DIED);
+ }
+}
+
+void Aura::HandleAuraModDisarm(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM))
+ return;
+
+ // not sure for it's correctness
+ if(apply)
+ m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
+ else
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
+
+ // only at real add/remove aura
+ if (m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove.
+ if (((Player *)m_target)->IsInFeralForm())
+ return;
+
+ if (apply)
+ m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME);
+ else
+ ((Player *)m_target)->SetRegularAttackTime();
+
+ m_target->UpdateDamagePhysical(BASE_ATTACK);
+}
+
+void Aura::HandleAuraModStun(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ if (apply)
+ {
+ m_target->addUnitState(UNIT_STAT_STUNNED);
+ m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
+
+ m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
+
+ // Creature specific
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ ((Creature*)m_target)->StopMoving();
+ else
+ m_target->SetUnitMovementFlags(0); //Clear movement flags
+
+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
+
+ data.append(m_target->GetPackGUID());
+ data << uint32(0);
+ m_target->SendMessageToSet(&data,true);
+ }
+ else
+ {
+ // Real remove called after current aura remove from lists, check if other similar auras active
+ if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
+ return;
+
+ m_target->clearUnitState(UNIT_STAT_STUNNED);
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+
+ if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
+ {
+ if(m_target->getVictim() && m_target->isAlive())
+ m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
+
+ WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
+ data.append(m_target->GetPackGUID());
+ data << uint32(0);
+ m_target->SendMessageToSet(&data,true);
+ }
+
+ // Wyvern Sting
+ if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
+ {
+ Unit* caster = GetCaster();
+ if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
+ return;
+
+ uint32 spell_id = 0;
+
+ switch(GetId())
+ {
+ case 19386: spell_id = 24131; break;
+ case 24132: spell_id = 24134; break;
+ case 24133: spell_id = 24135; break;
+ case 27068: spell_id = 27069; break;
+ default:
+ sLog.outError("Spell selection called for unexpected original spell %u, new spell for this spell family?",GetId());
+ return;
+ }
+
+ SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
+
+ if(!spellInfo)
+ return;
+
+ caster->CastSpell(m_target,spellInfo,true,NULL,this);
+ return;
+ }
+ }
+}
+
+void Aura::HandleModStealth(bool apply, bool Real)
+{
+ if(apply)
+ {
+ if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
+ {
+ // drop flag at stealth in bg
+ m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE);
+
+ // remove player from the objective's active player count at stealth
+ if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP())
+ pvp->HandlePlayerActivityChanged((Player*)m_target);
+ }
+
+ // only at real aura add
+ if(Real)
+ {
+ m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02);
+ if(m_target->GetTypeId()==TYPEID_PLAYER)
+ m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
+
+ // apply only if not in GM invisibility (and overwrite invisibility state)
+ if(m_target->GetVisibility()!=VISIBILITY_OFF)
+ {
+ //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
+ m_target->SetVisibility(VISIBILITY_OFF);
+ m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
+ }
+
+ // for RACE_NIGHTELF stealth
+ if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
+ m_target->CastSpell(m_target, 21009, true, NULL, this);
+ }
+ }
+ else
+ {
+ // only at real aura remove
+ if(Real)
+ {
+ // for RACE_NIGHTELF stealth
+ if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580)
+ m_target->RemoveAurasDueToSpell(21009);
+
+ // if last SPELL_AURA_MOD_STEALTH and no GM invisibility
+ if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF)
+ {
+ m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00);
+ if(m_target->GetTypeId()==TYPEID_PLAYER)
+ m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
+
+ // restore invisibility if any
+ if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
+ {
+ //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
+ //m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
+ m_target->SetVisibility(VISIBILITY_ON);
+ }
+ else
+ {
+ m_target->SetVisibility(VISIBILITY_ON);
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP())
+ pvp->HandlePlayerActivityChanged((Player*)m_target);
+ }
+ }
+ }
+ }
+
+ // Master of Subtlety
+ Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
+ {
+ if ((*i)->GetSpellProto()->SpellIconID == 2114)
+ {
+ if (apply)
+ {
+ int32 bp = (*i)->GetModifier()->m_amount;
+ m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true);
+ }
+ else
+ m_target->CastSpell(m_target,31666,true);
+ break;
+ }
+ }
+}
+
+void Aura::HandleInvisibility(bool apply, bool Real)
+{
+ if(apply)
+ {
+ m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
+
+ m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE);
+
+ if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
+ {
+ // apply glow vision
+ m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
+ // remove player from the objective's active player count at invisibility
+ if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP())
+ pvp->HandlePlayerActivityChanged((Player*)m_target);
+ }
+
+ // apply only if not in GM invisibility and not stealth
+ if(m_target->GetVisibility()==VISIBILITY_ON)
+ {
+ // Aura not added yet but visibility code expect temporary add aura
+ //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
+ //m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
+ m_target->SetVisibility(VISIBILITY_ON);
+ }
+ }
+ else
+ {
+ // recalculate value at modifier remove (current aura already removed)
+ m_target->m_invisibilityMask = 0;
+ Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY);
+ for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
+ m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue);
+
+ // only at real aura remove and if not have different invisibility auras.
+ if(Real && m_target->m_invisibilityMask==0)
+ {
+ // remove glow vision
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
+
+ // apply only if not in GM invisibility & not stealthed while invisible
+ if(m_target->GetVisibility()!=VISIBILITY_OFF)
+ {
+ // if have stealth aura then already have stealth visibility
+ if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH))
+ {
+ m_target->SetVisibility(VISIBILITY_ON);
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP())
+ pvp->HandlePlayerActivityChanged((Player*)m_target);
+ }
+ }
+ }
+ }
+}
+
+void Aura::HandleInvisibilityDetect(bool apply, bool Real)
+{
+ if(apply)
+ {
+ m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
+ }
+ else
+ {
+ // recalculate value at modifier remove (current aura already removed)
+ m_target->m_detectInvisibilityMask = 0;
+ Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
+ for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
+ m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
+ }
+ if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
+ ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target);
+}
+
+void Aura::HandleAuraModRoot(bool apply, bool Real)
+{
+ // only at real add/remove aura
+ if(!Real)
+ return;
+
+ uint32 apply_stat = UNIT_STAT_ROOT;
+ if (apply)
+ {
+ m_target->addUnitState(UNIT_STAT_ROOT);
+ m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
+ // probably wrong
+ m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
+
+ //Save last orientation
+ if( m_target->getVictim() )
+ m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
+ data.append(m_target->GetPackGUID());
+ data << (uint32)2;
+ m_target->SendMessageToSet(&data,true);
+
+ //Clear unit movement flags
+ m_target->SetUnitMovementFlags(0);
+ }
+ else
+ ((Creature *)m_target)->StopMoving();
+ }
+ else
+ {
+ // Real remove called after current aura remove from lists, check if other similar auras active
+ if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
+ return;
+
+ m_target->clearUnitState(UNIT_STAT_ROOT);
+ // probably wrong
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
+
+ if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
+ {
+ if(m_target->getVictim() && m_target->isAlive())
+ m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
+ data.append(m_target->GetPackGUID());
+ data << (uint32)2;
+ m_target->SendMessageToSet(&data,true);
+ }
+ }
+ }
+}
+
+void Aura::HandleAuraModSilence(bool apply, bool Real)
+{
+ // only at real add/remove aura
+ if(!Real)
+ return;
+
+ if(apply)
+ {
+ m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
+ // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE
+ for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++)
+ {
+ Spell* currentSpell = m_target->m_currentSpells[i];
+ if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
+ {
+ uint32 state = currentSpell->getState();
+ // Stop spells on prepare or casting state
+ if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING )
+ {
+ currentSpell->cancel();
+ currentSpell->SetReferencedFromCurrent(false);
+ m_target->m_currentSpells[i] = NULL;
+ }
+ }
+ }
+
+ switch (GetId())
+ {
+ // Arcane Torrent (Energy)
+ case 25046:
+ {
+ Unit * caster = GetCaster();
+ if (!caster)
+ return;
+
+ // Search Mana Tap auras on caster
+ int32 energy = 0;
+ Unit::AuraList const& m_dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
+ if ((*i)->GetId() == 28734)
+ ++energy;
+ if (energy)
+ {
+ energy *= 10;
+ caster->CastCustomSpell(caster, 25048, &energy, NULL, NULL, true);
+ caster->RemoveAurasDueToSpell(28734);
+ }
+ }
+ }
+ }
+ else
+ {
+ // Real remove called after current aura remove from lists, check if other similar auras active
+ if(m_target->HasAuraType(SPELL_AURA_MOD_SILENCE))
+ return;
+
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
+ }
+}
+
+void Aura::HandleModThreat(bool apply, bool Real)
+{
+ // only at real add/remove aura
+ if(!Real)
+ return;
+
+ if(!m_target->isAlive())
+ return;
+
+ Unit* caster = GetCaster();
+
+ if(!caster || !caster->isAlive())
+ return;
+
+ int level_diff = 0;
+ int multiplier = 0;
+ switch (GetId())
+ {
+ // Arcane Shroud
+ case 26400:
+ level_diff = m_target->getLevel() - 60;
+ multiplier = 2;
+ break;
+ // The Eye of Diminution
+ case 28862:
+ level_diff = m_target->getLevel() - 60;
+ multiplier = 1;
+ break;
+ }
+ if (level_diff > 0)
+ m_modifier.m_amount += multiplier * level_diff;
+
+ for(int8 x=0;x < MAX_SPELL_SCHOOL;x++)
+ {
+ if(m_modifier.m_miscvalue & int32(1<<x))
+ {
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply);
+ }
+ }
+}
+
+void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
+{
+ // only at real add/remove aura
+ if(!Real)
+ return;
+
+ if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER)
+ return;
+
+ Unit* caster = GetCaster();
+
+ if(!caster || !caster->isAlive())
+ return;
+
+ float threatMod = 0.0f;
+ if(apply)
+ threatMod = float(m_modifier.m_amount);
+ else
+ threatMod = float(-m_modifier.m_amount);
+
+ m_target->getHostilRefManager().threatAssist(caster, threatMod);
+}
+
+void Aura::HandleModTaunt(bool apply, bool Real)
+{
+ // only at real add/remove aura
+ if(!Real)
+ return;
+
+ if(!m_target->isAlive() || !m_target->CanHaveThreatList())
+ return;
+
+ Unit* caster = GetCaster();
+
+ if(!caster || !caster->isAlive() || caster->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if(apply)
+ m_target->TauntApply(caster);
+ else
+ {
+ // When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
+ m_target->TauntFadeOut(caster);
+ }
+}
+
+/*********************************************************/
+/*** MODIFY SPEED ***/
+/*********************************************************/
+void Aura::HandleAuraModIncreaseSpeed(bool apply, bool Real)
+{
+ // all applied/removed only at real aura add/remove
+ if(!Real)
+ return;
+
+ m_target->UpdateSpeed(MOVE_RUN, true);
+}
+
+void Aura::HandleAuraModIncreaseMountedSpeed(bool apply, bool Real)
+{
+ // all applied/removed only at real aura add/remove
+ if(!Real)
+ return;
+
+ m_target->UpdateSpeed(MOVE_RUN, true);
+}
+
+void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real)
+{
+ // all applied/removed only at real aura add/remove
+ if(!Real)
+ return;
+
+ // Enable Fly mode for flying mounts
+ if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)
+ {
+ WorldPacket data;
+ if(apply)
+ data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
+ else
+ data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
+ data.append(m_target->GetPackGUID());
+ data << uint32(0); // unknown
+ m_target->SendMessageToSet(&data, true);
+
+ //Players on flying mounts must be immune to polymorph
+ if (m_target->GetTypeId()==TYPEID_PLAYER)
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
+
+ // Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
+ if( apply && m_target->HasAura(42016,0) && m_target->GetMountID())
+ m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
+ }
+
+ m_target->UpdateSpeed(MOVE_FLY, true);
+}
+
+void Aura::HandleAuraModIncreaseSwimSpeed(bool apply, bool Real)
+{
+ // all applied/removed only at real aura add/remove
+ if(!Real)
+ return;
+
+ m_target->UpdateSpeed(MOVE_SWIM, true);
+}
+
+void Aura::HandleAuraModDecreaseSpeed(bool apply, bool Real)
+{
+ // all applied/removed only at real aura add/remove
+ if(!Real)
+ return;
+
+ m_target->UpdateSpeed(MOVE_RUN, true);
+ m_target->UpdateSpeed(MOVE_SWIM, true);
+ m_target->UpdateSpeed(MOVE_FLY, true);
+}
+
+void Aura::HandleAuraModUseNormalSpeed(bool apply, bool Real)
+{
+ // all applied/removed only at real aura add/remove
+ if(!Real)
+ return;
+
+ m_target->UpdateSpeed(MOVE_RUN, true);
+ m_target->UpdateSpeed(MOVE_SWIM, true);
+ m_target->UpdateSpeed(MOVE_FLY, true);
+}
+
+/*********************************************************/
+/*** IMMUNITY ***/
+/*********************************************************/
+
+void Aura::HandleModMechanicImmunity(bool apply, bool Real)
+{
+ uint32 mechanic = 1 << m_modifier.m_miscvalue;
+
+ //immune movement impairment and loss of control
+ if(GetId()==42292)
+ mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
+
+ if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
+ {
+ Unit::AuraMap& Auras = m_target->GetAuras();
+ for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
+ {
+ next = iter;
+ ++next;
+ SpellEntry const *spell = iter->second->GetSpellProto();
+ if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability
+ && !iter->second->IsPositive() // only remove negative spells
+ && spell->Id != GetId())
+ {
+ //check for mechanic mask
+ if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
+ {
+ m_target->RemoveAurasDueToSpell(spell->Id);
+ if(Auras.empty())
+ break;
+ else
+ next = Auras.begin();
+ }
+ }
+ }
+ }
+
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply);
+
+ // special cases
+ switch(m_modifier.m_miscvalue)
+ {
+ case MECHANIC_INVULNERABILITY:
+ m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply);
+ break;
+ case MECHANIC_SHIELD:
+ m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply);
+ break;
+ }
+
+ // Bestial Wrath
+ if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->Id == 19574)
+ {
+ // The Beast Within cast on owner if talent present
+ if ( Unit* owner = m_target->GetOwner() )
+ {
+ // Search talent
+ Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
+ {
+ if ( (*i)->GetSpellProto()->SpellIconID == 2229 )
+ {
+ if (apply)
+ owner->CastSpell(owner, 34471, true, 0, this);
+ else
+ owner->RemoveAurasDueToSpell(34471);
+ break;
+ }
+ }
+ }
+ }
+
+ // The Beast Within and Bestial Wrath - immunity
+ if(GetId() == 19574 || GetId() == 34471)
+ {
+ if(apply)
+ {
+ m_target->CastSpell(m_target,24395,true);
+ m_target->CastSpell(m_target,24396,true);
+ m_target->CastSpell(m_target,24397,true);
+ m_target->CastSpell(m_target,26592,true);
+ }
+ else
+ {
+ m_target->RemoveAurasDueToSpell(24395);
+ m_target->RemoveAurasDueToSpell(24396);
+ m_target->RemoveAurasDueToSpell(24397);
+ m_target->RemoveAurasDueToSpell(26592);
+ }
+ }
+}
+
+void Aura::HandleAuraModEffectImmunity(bool apply, bool Real)
+{
+ if(!apply)
+ {
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(((Player*)m_target)->InBattleGround())
+ {
+ BattleGround *bg = ((Player*)m_target)->GetBattleGround();
+ if(bg)
+ {
+ switch(bg->GetTypeID())
+ {
+ case BATTLEGROUND_AV:
+ {
+ break;
+ }
+ case BATTLEGROUND_WS:
+ {
+ // Warsong Flag, horde // Silverwing Flag, alliance
+ if(GetId() == 23333 || GetId() == 23335)
+ bg->EventPlayerDroppedFlag(((Player*)m_target));
+ break;
+ }
+ case BATTLEGROUND_AB:
+ {
+ break;
+ }
+ case BATTLEGROUND_EY:
+ {
+ if(GetId() == 34976)
+ bg->EventPlayerDroppedFlag(((Player*)m_target));
+ break;
+ }
+ }
+ }
+ }
+ else
+ sOutdoorPvPMgr.HandleDropFlag((Player*)m_target,GetSpellProto()->Id);
+ }
+ }
+
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply);
+}
+
+void Aura::HandleAuraModStateImmunity(bool apply, bool Real)
+{
+ if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
+ {
+ Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue));
+ for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();)
+ {
+ if (auraList.front() != this) // skip itself aura (it already added)
+ {
+ m_target->RemoveAurasDueToSpell(auraList.front()->GetId());
+ itr = auraList.begin();
+ }
+ else
+ ++itr;
+ }
+ }
+
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply);
+}
+
+void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real)
+{
+ if(apply && m_modifier.m_miscvalue == SPELL_SCHOOL_MASK_NORMAL)
+ m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE);
+
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply);
+
+ if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
+ {
+ if(IsPositiveSpell(GetId())) //Only positive immunity removes auras
+ {
+ uint32 school_mask = m_modifier.m_miscvalue;
+ Unit::AuraMap& Auras = m_target->GetAuras();
+ for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
+ {
+ next = iter;
+ ++next;
+ SpellEntry const *spell = iter->second->GetSpellProto();
+ if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
+ && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability
+ && !iter->second->IsPositive() //Don't remove positive spells
+ && spell->Id != GetId() ) //Don't remove self
+ {
+ m_target->RemoveAurasDueToSpell(spell->Id);
+ if(Auras.empty())
+ break;
+ else
+ next = Auras.begin();
+ }
+ }
+ }
+ }
+ if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH )
+ {
+ if( apply )
+ m_target->addUnitState(UNIT_STAT_ISOLATED);
+ else
+ m_target->clearUnitState(UNIT_STAT_ISOLATED);
+ }
+}
+
+void Aura::HandleAuraModDmgImmunity(bool apply, bool Real)
+{
+ m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply);
+}
+
+void Aura::HandleAuraModDispelImmunity(bool apply, bool Real)
+{
+ // all applied/removed only at real aura add/remove
+ if(!Real)
+ return;
+
+ m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply);
+}
+
+void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ if(apply)
+ {
+ // some spell have charges by functionality not have its in spell data
+ switch (GetId())
+ {
+ case 28200: // Ascendance (Talisman of Ascendance trinket)
+ m_procCharges = 6;
+ UpdateAuraCharges();
+ break;
+ default: break;
+ }
+ }
+}
+
+void Aura::HandleAuraModStalked(bool apply, bool Real)
+{
+ // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
+ if(apply)
+ m_target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
+ else
+ m_target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
+}
+
+/*********************************************************/
+/*** PERIODIC ***/
+/*********************************************************/
+
+void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real)
+{
+ if (m_periodicTimer <= 0)
+ m_periodicTimer += m_modifier.periodictime;
+
+ m_isPeriodic = apply;
+ m_isTrigger = apply;
+
+ // Curse of the Plaguebringer
+ if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL)
+ {
+ // Cast Wrath of the Plaguebringer if not dispelled
+ m_target->CastSpell(m_target, 29214, true, 0, this);
+ }
+}
+
+void Aura::HandlePeriodicEnergize(bool apply, bool Real)
+{
+ if (m_periodicTimer <= 0)
+ m_periodicTimer += m_modifier.periodictime;
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandlePeriodicHeal(bool apply, bool Real)
+{
+ if (m_periodicTimer <= 0)
+ m_periodicTimer += m_modifier.periodictime;
+
+ m_isPeriodic = apply;
+
+ // only at real apply
+ if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE)
+ {
+ // provided m_target as original caster to prevent apply aura caster selection for this negative buff
+ m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID());
+ }
+
+ // For prevent double apply bonuses
+ bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
+
+ if(!loading && apply)
+ {
+ switch (m_spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_DRUID:
+ {
+ // Rejuvenation
+ if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL)
+ {
+ if(Unit* caster = GetCaster())
+ {
+ Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
+ {
+ int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
+ switch((*k)->GetModifier()->m_miscvalue)
+ {
+ case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura
+ case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura
+ {
+ m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void Aura::HandlePeriodicDamage(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if (m_periodicTimer <= 0)
+ m_periodicTimer += m_modifier.periodictime;
+
+ m_isPeriodic = apply;
+
+ // For prevent double apply bonuses
+ bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading());
+
+ Unit *caster = GetCaster();
+
+ switch (m_spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_GENERIC:
+ {
+ // Pounce Bleed
+ if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 )
+ {
+ // $AP*0.18/6 bonus per tick
+ if (apply && !loading && caster)
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_WARRIOR:
+ {
+ // Rend
+ if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
+ {
+ // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
+ if (apply && !loading && caster)
+ {
+ float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK);
+ int32 mws = caster->GetAttackTime(BASE_ATTACK);
+ float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE);
+ float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE);
+ // WARNING! in 3.0 multiplier 0.00743f change to 0.6
+ m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f);
+ }
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_DRUID:
+ {
+ // Rake
+ if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL)
+ {
+ // $AP*0.06/3 bonus per tick
+ if (apply && !loading && caster)
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100);
+ return;
+ }
+ // Lacerate
+ if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL)
+ {
+ // $AP*0.05/5 bonus per tick
+ if (apply && !loading && caster)
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
+ return;
+ }
+ // Rip
+ if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL)
+ {
+ // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used]
+ if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ uint8 cp = ((Player*)caster)->GetComboPoints();
+
+ // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
+ Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY);
+ for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr)
+ {
+ if((*itr)->GetId()==34241)
+ {
+ m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount;
+ break;
+ }
+ }
+
+ if (cp > 4) cp = 4;
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
+ }
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_ROGUE:
+ {
+ // Deadly poison aura state
+ if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100)
+ {
+ if(apply)
+ m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true);
+ else
+ {
+ // current aura already removed, search present of another
+ bool found = false;
+ Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
+ for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
+ {
+ SpellEntry const* itr_spell = (*itr)->GetSpellProto();
+ if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100)
+ {
+ found = true;
+ break;
+ }
+ }
+ // this has been last deadly poison aura
+ if(!found)
+ m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false);
+ }
+ return;
+ }
+ // Rupture
+ if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL)
+ {
+ // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP]
+ if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ uint8 cp = ((Player*)caster)->GetComboPoints();
+ if (cp > 3) cp = 3;
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
+ }
+ return;
+ }
+ // Garrote
+ if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL)
+ {
+ // $AP*0.18/6 bonus per tick
+ if (apply && !loading && caster)
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100);
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_HUNTER:
+ {
+ // Serpent Sting
+ if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL)
+ {
+ // $RAP*0.1/5 bonus per tick
+ if (apply && !loading && caster)
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
+ return;
+ }
+ // Immolation Trap
+ if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678)
+ {
+ // $RAP*0.1/5 bonus per tick
+ if (apply && !loading && caster)
+ m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500);
+ return;
+ }
+ break;
+ }
+ case SPELLFAMILY_PALADIN:
+ {
+ // Consecration
+ if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL)
+ {
+ if (apply && !loading)
+ {
+ if(Unit* caster = GetCaster())
+ {
+ Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k)
+ {
+ int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex];
+ switch((*k)->GetModifier()->m_miscvalue)
+ {
+ case 5147: // Improved Consecration - Libram of the Eternal Rest
+ {
+ m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void Aura::HandlePeriodicDamagePCT(bool apply, bool Real)
+{
+ if (m_periodicTimer <= 0)
+ m_periodicTimer += m_modifier.periodictime;
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandlePeriodicLeech(bool apply, bool Real)
+{
+ if (m_periodicTimer <= 0)
+ m_periodicTimer += m_modifier.periodictime;
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandlePeriodicManaLeech(bool apply, bool Real)
+{
+ if (m_periodicTimer <= 0)
+ m_periodicTimer += m_modifier.periodictime;
+
+ m_isPeriodic = apply;
+}
+
+/*********************************************************/
+/*** MODIFY STATS ***/
+/*********************************************************/
+
+/********************************/
+/*** RESISTANCE ***/
+/********************************/
+
+void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real)
+{
+ for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
+ {
+ if(m_modifier.m_miscvalue & int32(1<<x))
+ {
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply);
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
+ }
+ }
+}
+
+void Aura::HandleAuraModResistance(bool apply, bool Real)
+{
+ for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
+ {
+ if(m_modifier.m_miscvalue & int32(1<<x))
+ {
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
+ m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply);
+ }
+ }
+
+ // Faerie Fire (druid versions)
+ if( m_spellProto->SpellIconID == 109 &&
+ m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID &&
+ m_spellProto->SpellFamilyFlags & 0x0000000000000400LL )
+ {
+ m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply);
+ }
+}
+
+void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real)
+{
+ // only players have base stats
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ {
+ //pets only have base armor
+ if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
+ m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply);
+ }
+ else
+ {
+ for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++)
+ {
+ if(m_modifier.m_miscvalue & int32(1<<x))
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply);
+ }
+ }
+}
+
+void Aura::HandleModResistancePercent(bool apply, bool Real)
+{
+ for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
+ {
+ if(m_modifier.m_miscvalue & int32(1<<i))
+ {
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
+ if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
+ {
+ m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply);
+ m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply);
+ }
+ }
+ }
+}
+
+void Aura::HandleModBaseResistance(bool apply, bool Real)
+{
+ // only players have base stats
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ {
+ //only pets have base stats
+ if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
+ m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ }
+ else
+ {
+ for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
+ if(m_modifier.m_miscvalue & (1<<i))
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ }
+}
+
+/********************************/
+/*** STAT ***/
+/********************************/
+
+void Aura::HandleAuraModStat(bool apply, bool Real)
+{
+ if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4)
+ {
+ sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue);
+ return;
+ }
+
+ for(int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
+ {
+ // -1 or -2 is all stats ( misc < -2 checked in function beginning )
+ if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i)
+ {
+ //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply);
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
+ m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply);
+ }
+ }
+}
+
+void Aura::HandleModPercentStat(bool apply, bool Real)
+{
+ if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
+ {
+ sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
+ return;
+ }
+
+ // only players have base stats
+ if (m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
+ {
+ if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply);
+ }
+}
+
+void Aura::HandleModSpellDamagePercentFromStat(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ // Magic damage modifiers implemented in Unit::SpellDamageBonus
+ // This information for client side use only
+ // Recalculate bonus
+ ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
+}
+
+void Aura::HandleModSpellHealingPercentFromStat(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ // Recalculate bonus
+ ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
+}
+
+void Aura::HandleAuraModDispelResist(bool apply, bool Real)
+{
+ if(!Real || !apply)
+ return;
+
+ if(GetId()==33206)
+ m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID());
+}
+
+void Aura::HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ // Magic damage modifiers implemented in Unit::SpellDamageBonus
+ // This information for client side use only
+ // Recalculate bonus
+ ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
+}
+
+void Aura::HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ // Recalculate bonus
+ ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
+}
+
+void Aura::HandleModHealingDone(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ // implemented in Unit::SpellHealingBonus
+ // this information is for client side only
+ ((Player*)m_target)->UpdateSpellDamageAndHealingBonus();
+}
+
+void Aura::HandleModTotalPercentStat(bool apply, bool Real)
+{
+ if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4)
+ {
+ sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
+ return;
+ }
+
+ //save current and max HP before applying aura
+ uint32 curHPValue = m_target->GetHealth();
+ uint32 maxHPValue = m_target->GetMaxHealth();
+
+ for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
+ {
+ if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1)
+ {
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply);
+ if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet())
+ m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply );
+ }
+ }
+
+ //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
+ if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10))
+ {
+ // newHP = (curHP / maxHP) * newMaxHP = (newMaxHP * curHP) / maxHP -> which is better because no int -> double -> int conversion is needed
+ uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue;
+ m_target->SetHealth(newHPValue);
+ }
+}
+
+void Aura::HandleAuraModResistenceOfStatPercent(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL)
+ {
+ // support required adding replace UpdateArmor by loop by UpdateResistence at intellect update
+ // and include in UpdateResistence same code as in UpdateArmor for aura mod apply.
+ sLog.outError("Aura SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT(182) need adding support for non-armor resistances!");
+ return;
+ }
+
+ // Recalculate Armor
+ m_target->UpdateArmor();
+}
+
+/********************************/
+/*** HEAL & ENERGIZE ***/
+/********************************/
+void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real)
+{
+ /*
+ Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic,
+ so this aura not fully working.
+ */
+ if(apply)
+ {
+ if(!m_target->isAlive())
+ return;
+
+ if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
+ m_target->SetStandState(PLAYER_STATE_SIT);
+
+ if(m_periodicTimer <= 0)
+ {
+ m_periodicTimer += m_modifier.periodictime;
+
+ if(m_target->GetHealth() < m_target->GetMaxHealth())
+ {
+ // PeriodicTick can cast triggered spells with stats changes
+ PeriodicTick();
+ }
+ }
+ }
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real)
+{
+ if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
+ m_target->SetStandState(PLAYER_STATE_SIT);
+ if(apply)
+ {
+ if(m_modifier.periodictime == 0)
+ m_modifier.periodictime = 1000;
+ if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA)
+ {
+ m_periodicTimer += m_modifier.periodictime;
+
+ if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA))
+ {
+ // PeriodicTick can cast triggered spells with stats changes
+ PeriodicTick();
+ }
+ }
+ }
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandleModRegen(bool apply, bool Real) // eating
+{
+ if(apply)
+ {
+ if(!m_target->isAlive())
+ return;
+
+ if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState())
+ m_target->SetStandState(PLAYER_STATE_SIT);
+
+ if(m_periodicTimer <= 0)
+ {
+ m_periodicTimer += 5000;
+ int32 gain = m_target->ModifyHealth(m_modifier.m_amount);
+ Unit *caster = GetCaster();
+ if (caster)
+ {
+ SpellEntry const *spellProto = GetSpellProto();
+ if (spellProto)
+ m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto);
+ }
+ }
+ }
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking
+{
+ if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState())
+ m_target->SetStandState(PLAYER_STATE_SIT);
+
+ if(apply && m_periodicTimer <= 0)
+ {
+ m_periodicTimer += 2000;
+
+ Powers pt = m_target->getPowerType();
+ if(int32(pt) != m_modifier.m_miscvalue)
+ return;
+
+ if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED )
+ {
+ // eating anim
+ m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT);
+ }
+ else if( GetId() == 20577 )
+ {
+ // cannibalize anim
+ m_target->HandleEmoteCommand(398);
+ }
+
+ // Warrior talent, gain 1 rage every 3 seconds while in combat
+ if(pt == POWER_RAGE && m_target->isInCombat())
+ {
+ m_target->ModifyPower(pt, m_modifier.m_amount*10/17);
+ m_periodicTimer += 1000;
+ }
+ }
+ m_isPeriodic = apply;
+ if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA)
+ ((Player*)m_target)->UpdateManaRegen();
+}
+
+void Aura::HandleModPowerRegenPCT(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if (m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ // Update manaregen value
+ if (m_modifier.m_miscvalue == POWER_MANA)
+ ((Player*)m_target)->UpdateManaRegen();
+}
+
+void Aura::HandleModManaRegen(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if (m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ //Note: an increase in regen does NOT cause threat.
+ ((Player*)m_target)->UpdateManaRegen();
+}
+
+void Aura::HandleComprehendLanguage(bool apply, bool Real)
+{
+ if(apply)
+ m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
+ else
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
+}
+
+void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real)
+{
+ if(Real)
+ {
+ if(apply)
+ {
+ m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ m_target->ModifyHealth(m_modifier.m_amount);
+ }
+ else
+ {
+ if (int32(m_target->GetHealth()) > m_modifier.m_amount)
+ m_target->ModifyHealth(-m_modifier.m_amount);
+ else
+ m_target->SetHealth(1);
+ m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ }
+ }
+}
+
+void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real)
+{
+ uint32 oldhealth = m_target->GetHealth();
+ double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth();
+
+ m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+
+ // refresh percentage
+ if(oldhealth > 0)
+ {
+ uint32 newhealth = uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage));
+ if(newhealth==0)
+ newhealth = 1;
+
+ m_target->SetHealth(newhealth);
+ }
+}
+
+void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real)
+{
+ Powers powerType = m_target->getPowerType();
+ if(int32(powerType) != m_modifier.m_miscvalue)
+ return;
+
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_VALUE, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool Real)
+{
+ Powers powerType = m_target->getPowerType();
+ if(int32(powerType) != m_modifier.m_miscvalue)
+ return;
+
+ m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_PCT, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool Real)
+{
+ //m_target->ApplyMaxHealthPercentMod(m_modifier.m_amount,apply);
+ m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply);
+}
+
+/********************************/
+/*** FIGHT ***/
+/********************************/
+
+void Aura::HandleAuraModParryPercent(bool apply, bool Real)
+{
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ ((Player*)m_target)->UpdateParryPercentage();
+}
+
+void Aura::HandleAuraModDodgePercent(bool apply, bool Real)
+{
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ ((Player*)m_target)->UpdateDodgePercentage();
+ //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount));
+}
+
+void Aura::HandleAuraModBlockPercent(bool apply, bool Real)
+{
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ ((Player*)m_target)->UpdateBlockPercentage();
+ //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount));
+}
+
+void Aura::HandleAuraModRegenInterrupt(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ ((Player*)m_target)->UpdateManaRegen();
+}
+
+void Aura::HandleAuraModCritPercent(bool apply, bool Real)
+{
+ if(m_target->GetTypeId()!=TYPEID_PLAYER)
+ return;
+
+ // apply item specific bonuses for already equipped weapon
+ if(Real)
+ {
+ for(int i = 0; i < MAX_ATTACK; ++i)
+ if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
+ ((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem,WeaponAttackType(i),this,apply);
+ }
+
+ // mods must be applied base at equipped weapon class and subclass comparison
+ // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
+ // m_modifier.m_miscvalue comparison with item generated damage types
+
+ if (GetSpellProto()->EquippedItemClass == -1)
+ {
+ ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
+ ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
+ ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply);
+ }
+ else
+ {
+ // done in Player::_ApplyWeaponDependentAuraMods
+ }
+}
+
+void Aura::HandleModHitChance(bool apply, bool Real)
+{
+ m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
+ m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount);
+}
+
+void Aura::HandleModSpellHitChance(bool apply, bool Real)
+{
+ m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount);
+}
+
+void Aura::HandleModSpellCritChance(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ ((Player*)m_target)->UpdateAllSpellCritChances();
+ }
+ else
+ {
+ m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:(-m_modifier.m_amount);
+ }
+}
+
+void Aura::HandleModSpellCritChanceShool(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
+ if (m_modifier.m_miscvalue & (1<<school))
+ ((Player*)m_target)->UpdateSpellCritChance(school);
+}
+
+/********************************/
+/*** ATTACK SPEED ***/
+/********************************/
+
+void Aura::HandleModCastingSpeed(bool apply, bool Real)
+{
+ m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
+}
+
+void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real)
+{
+ m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
+}
+
+void Aura::HandleModCombatSpeedPct(bool apply, bool Real)
+{
+ m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
+}
+
+void Aura::HandleModAttackSpeed(bool apply, bool Real)
+{
+ if(!m_target->isAlive() )
+ return;
+
+ m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply);
+}
+
+void Aura::HandleHaste(bool apply, bool Real)
+{
+ m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply);
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply);
+}
+
+void Aura::HandleAuraModRangedHaste(bool apply, bool Real)
+{
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply);
+}
+
+void Aura::HandleRangedAmmoHaste(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply);
+}
+
+/********************************/
+/*** ATTACK POWER ***/
+/********************************/
+
+void Aura::HandleAuraModAttackPower(bool apply, bool Real)
+{
+ m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real)
+{
+ if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
+ return;
+
+ m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraAttackPowerAttacker(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+ Unit *caster = GetCaster();
+
+ if (!caster)
+ return;
+
+ // Hunter's Mark
+ if (m_spellProto->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellProto->SpellFamilyFlags & 0x0000000000000400LL)
+ {
+ // Check Improved Hunter's Mark bonus on caster
+ Unit::AuraList const& mOverrideClassScript = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(Unit::AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i)
+ {
+ Modifier* mod = (*i)->GetModifier();
+ // mproved Hunter's Mark script from 5236 to 5240
+ if (mod->m_miscvalue >= 5236 && mod->m_miscvalue <= 5240)
+ {
+ // Get amount of ranged bonus for this spell..
+ int32 ranged_bonus = caster->CalculateSpellDamage(m_spellProto, 1, m_spellProto->EffectBasePoints[1], m_target);
+ // Set melee attack power bonus % from ranged depends from Improved mask aura
+ m_modifier.m_amount = mod->m_amount * ranged_bonus / 100;
+ m_currentBasePoints = m_modifier.m_amount;
+ break;
+ }
+ }
+ return;
+ }
+}
+
+void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real)
+{
+ //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
+ m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real)
+{
+ if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
+ return;
+
+ //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
+ m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0)
+ return;
+
+ if(m_modifier.m_miscvalue != STAT_INTELLECT)
+ {
+ // support required adding UpdateAttackPowerAndDamage calls at stat update
+ sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intellect stats!");
+ return;
+ }
+
+ // Recalculate bonus
+ ((Player*)m_target)->UpdateAttackPowerAndDamage(true);
+}
+
+/********************************/
+/*** DAMAGE BONUS ***/
+/********************************/
+void Aura::HandleModDamageDone(bool apply, bool Real)
+{
+ // apply item specific bonuses for already equipped weapon
+ if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
+ {
+ for(int i = 0; i < MAX_ATTACK; ++i)
+ if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
+ ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
+ }
+
+ // m_modifier.m_miscvalue is bitmask of spell schools
+ // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
+ // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wands
+ // 127 - full bitmask any damages
+ //
+ // mods must be applied base at equipped weapon class and subclass comparison
+ // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
+ // m_modifier.m_miscvalue comparison with item generated damage types
+
+ if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
+ {
+ // apply generic physical damage bonuses including wand case
+ if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
+ {
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+ }
+ else
+ {
+ // done in Player::_ApplyWeaponDependentAuraMods
+ }
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(m_positive)
+ m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply);
+ else
+ m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply);
+ }
+ }
+
+ // Skip non magic case for speedup
+ if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
+ return;
+
+ if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
+ {
+ // wand magic case (skip generic to all item spell bonuses)
+ // done in Player::_ApplyWeaponDependentAuraMods
+
+ // Skip item specific requirements for not wand magic damage
+ return;
+ }
+
+ // Magic damage modifiers implemented in Unit::SpellDamageBonus
+ // This information for client side use only
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ if(m_positive)
+ {
+ for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
+ {
+ if((m_modifier.m_miscvalue & (1<<i)) != 0)
+ m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply);
+ }
+ }
+ else
+ {
+ for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
+ {
+ if((m_modifier.m_miscvalue & (1<<i)) != 0)
+ m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply);
+ }
+ }
+ Pet* pet = m_target->GetPet();
+ if(pet)
+ pet->UpdateAttackPowerAndDamage();
+ }
+}
+
+void Aura::HandleModDamagePercentDone(bool apply, bool Real)
+{
+ sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1);
+
+ // apply item specific bonuses for already equipped weapon
+ if(Real && m_target->GetTypeId()==TYPEID_PLAYER)
+ {
+ for(int i = 0; i < MAX_ATTACK; ++i)
+ if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
+ ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
+ }
+
+ // m_modifier.m_miscvalue is bitmask of spell schools
+ // 1 ( 0-bit ) - normal school damage (SPELL_SCHOOL_MASK_NORMAL)
+ // 126 - full bitmask all magic damages (SPELL_SCHOOL_MASK_MAGIC) including wand
+ // 127 - full bitmask any damages
+ //
+ // mods must be applied base at equipped weapon class and subclass comparison
+ // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask
+ // m_modifier.m_miscvalue comparison with item generated damage types
+
+ if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0)
+ {
+ // apply generic physical damage bonuses including wand case
+ if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER)
+ {
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply);
+ }
+ else
+ {
+ // done in Player::_ApplyWeaponDependentAuraMods
+ }
+ // For show in client
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply);
+ }
+
+ // Skip non magic case for speedup
+ if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0)
+ return;
+
+ if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 )
+ {
+ // wand magic case (skip generic to all item spell bonuses)
+ // done in Player::_ApplyWeaponDependentAuraMods
+
+ // Skip item specific requirements for not wand magic damage
+ return;
+ }
+
+ // Magic damage percent modifiers implemented in Unit::SpellDamageBonus
+ // Send info to client
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
+ m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply);
+}
+
+void Aura::HandleModOffhandDamagePercent(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ sLog.outDebug("AURA MOD OFFHAND DAMAGE");
+
+ m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply);
+}
+
+/********************************/
+/*** POWER COST ***/
+/********************************/
+
+void Aura::HandleModPowerCostPCT(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ float amount = m_modifier.m_amount/100.0f;
+ for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ if(m_modifier.m_miscvalue & (1<<i))
+ m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
+}
+
+void Aura::HandleModPowerCost(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ for(int i = 0; i < MAX_SPELL_SCHOOL; ++i)
+ if(m_modifier.m_miscvalue & (1<<i))
+ m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply);
+}
+
+/*********************************************************/
+/*** OTHERS ***/
+/*********************************************************/
+
+void Aura::HandleShapeshiftBoosts(bool apply)
+{
+ uint32 spellId = 0;
+ uint32 spellId2 = 0;
+ uint32 HotWSpellId = 0;
+
+ switch(GetModifier()->m_miscvalue)
+ {
+ case FORM_CAT:
+ spellId = 3025;
+ HotWSpellId = 24900;
+ break;
+ case FORM_TREE:
+ spellId = 5420;
+ break;
+ case FORM_TRAVEL:
+ spellId = 5419;
+ break;
+ case FORM_AQUA:
+ spellId = 5421;
+ break;
+ case FORM_BEAR:
+ spellId = 1178;
+ spellId2 = 21178;
+ HotWSpellId = 24899;
+ break;
+ case FORM_DIREBEAR:
+ spellId = 9635;
+ spellId2 = 21178;
+ HotWSpellId = 24899;
+ break;
+ case FORM_BATTLESTANCE:
+ spellId = 21156;
+ break;
+ case FORM_DEFENSIVESTANCE:
+ spellId = 7376;
+ break;
+ case FORM_BERSERKERSTANCE:
+ spellId = 7381;
+ break;
+ case FORM_MOONKIN:
+ spellId = 24905;
+ // aura from effect trigger spell
+ spellId2 = 24907;
+ break;
+ case FORM_FLIGHT:
+ spellId = 33948;
+ break;
+ case FORM_FLIGHT_EPIC:
+ spellId = 40122;
+ spellId2 = 40121;
+ break;
+ case FORM_SPIRITOFREDEMPTION:
+ spellId = 27792;
+ spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation.
+ break;
+ case FORM_GHOSTWOLF:
+ case FORM_AMBIENT:
+ case FORM_GHOUL:
+ case FORM_SHADOW:
+ case FORM_STEALTH:
+ case FORM_CREATURECAT:
+ case FORM_CREATUREBEAR:
+ spellId = 0;
+ break;
+ }
+
+ uint32 form = GetModifier()->m_miscvalue-1;
+
+ if(apply)
+ {
+ if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this );
+ if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this);
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap();
+ for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
+ {
+ if(itr->second->state == PLAYERSPELL_REMOVED) continue;
+ if(itr->first==spellId || itr->first==spellId2) continue;
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
+ if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue;
+ if (spellInfo->Stances & (1<<form))
+ m_target->CastSpell(m_target, itr->first, true, NULL, this);
+ }
+ //LotP
+ if (((Player*)m_target)->HasSpell(17007))
+ {
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
+ if (spellInfo && spellInfo->Stances & (1<<form))
+ m_target->CastSpell(m_target, 24932, true, NULL, this);
+ }
+ // HotW
+ if (HotWSpellId)
+ {
+ Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
+ for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
+ {
+ if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3)
+ {
+ int32 HotWMod = (*i)->GetModifier()->m_amount;
+ if(GetModifier()->m_miscvalue == FORM_CAT)
+ HotWMod /= 2;
+
+ m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_target->RemoveAurasDueToSpell(spellId);
+ m_target->RemoveAurasDueToSpell(spellId2);
+
+ Unit::AuraMap& tAuras = m_target->GetAuras();
+ for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
+ {
+ if (itr->second->IsRemovedOnShapeLost())
+ {
+ m_target->RemoveAurasDueToSpell(itr->second->GetId());
+ itr = tAuras.begin();
+ }
+ else
+ {
+ ++itr;
+ }
+ }
+ }
+
+ /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth();
+ m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/
+}
+
+void Aura::HandleAuraEmpathy(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_UNIT)
+ return;
+
+ CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry());
+ if(ci && ci->type == CREATURE_TYPE_BEAST)
+ m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
+}
+
+void Aura::HandleAuraUntrackable(bool apply, bool Real)
+{
+ if(apply)
+ m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
+ else
+ m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE);
+}
+
+void Aura::HandleAuraModPacify(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if(apply)
+ m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
+ else
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
+}
+
+void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real)
+{
+ HandleAuraModPacify(apply,Real);
+ HandleAuraModSilence(apply,Real);
+}
+
+void Aura::HandleAuraGhost(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if(apply)
+ {
+ m_target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
+ }
+ else
+ {
+ m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
+ }
+}
+
+void Aura::HandleAuraAllowFlight(bool apply, bool Real)
+{
+ // all applied/removed only at real aura add/remove
+ if(!Real)
+ return;
+
+ // allow fly
+ WorldPacket data;
+ if(apply)
+ data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
+ else
+ data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
+ data.append(m_target->GetPackGUID());
+ data << uint32(0); // unk
+ m_target->SendMessageToSet(&data, true);
+}
+
+void Aura::HandleModRating(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
+ if (m_modifier.m_miscvalue & (1 << rating))
+ ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply);
+}
+
+void Aura::HandleForceMoveForward(bool apply, bool Real)
+{
+ if(!Real || m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ if(apply)
+ m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
+ else
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
+}
+
+void Aura::HandleAuraModExpertise(bool apply, bool Real)
+{
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ ((Player*)m_target)->UpdateExpertise(BASE_ATTACK);
+ ((Player*)m_target)->UpdateExpertise(OFF_ATTACK);
+}
+
+void Aura::HandleModTargetResistance(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+ // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
+
+ // show armor penetration
+ if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL))
+ m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply);
+
+ // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
+ if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL)
+ m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply);
+}
+
+//HandleNoImmediateEffect auras implementation to support new stat system
+void Aura::HandleAuraHealing(bool apply, bool Real)
+{
+ //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_VALUE, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraHealingPct(bool apply, bool Real)
+{
+ //m_target->HandleStatModifier(UNIT_MOD_HEALING, TOTAL_PCT, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleShieldBlockValue(bool apply, bool Real)
+{
+ BaseModType modType = FLAT_MOD;
+ if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
+ modType = PCT_MOD;
+
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply);
+}
+
+void Aura::HandleAuraRetainComboPoints(bool apply, bool Real)
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ if(m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ Player *target = (Player*)m_target;
+
+ // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler
+ // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost)
+ if( !apply && m_duration==0 && target->GetComboTarget())
+ if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget()))
+ target->AddComboPoints(unit, -m_modifier.m_amount);
+}
+
+void Aura::HandleModUnattackable( bool Apply, bool Real )
+{
+ if(Real && Apply)
+ {
+ m_target->CombatStop();
+ m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE);
+ }
+
+ m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply);
+}
+
+void Aura::HandleSpiritOfRedemption( bool apply, bool Real )
+{
+ // spells required only Real aura add/remove
+ if(!Real)
+ return;
+
+ // prepare spirit state
+ if(apply)
+ {
+ if(m_target->GetTypeId()==TYPEID_PLAYER)
+ {
+ // disable breath/etc timers
+ ((Player*)m_target)->StopMirrorTimers();
+
+ // set stand state (expected in this form)
+ if(!m_target->IsStandState())
+ m_target->SetStandState(PLAYER_STATE_NONE);
+ }
+
+ m_target->SetHealth(1);
+ }
+ // die at aura end
+ else
+ m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false);
+}
+
+void Aura::CleanupTriggeredSpells()
+{
+ uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()];
+ if(!tSpellId)
+ return;
+
+ SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId);
+ if(!tProto)
+ return;
+
+ if(GetSpellDuration(tProto) != -1)
+ return;
+
+ // needed for spell 43680, maybe others
+ // TODO: is there a spell flag, which can solve this in a more sophisticated way?
+ if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL &&
+ GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()])
+ return;
+ m_target->RemoveAurasDueToSpell(tSpellId);
+}
+
+void Aura::HandleAuraPowerBurn(bool apply, bool Real)
+{
+ if (m_periodicTimer <= 0)
+ m_periodicTimer += m_modifier.periodictime;
+
+ m_isPeriodic = apply;
+}
+
+void Aura::HandleSchoolAbsorb(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ // prevent double apply bonuses
+ if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
+ {
+ if(Unit* caster = GetCaster())
+ {
+ float DoneActualBenefit = 0.0f;
+ switch(m_spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_PRIEST:
+ if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S
+ {
+ //+30% from +healing bonus
+ DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f;
+ break;
+ }
+ break;
+ case SPELLFAMILY_MAGE:
+ if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL)
+ {
+ //frost ward, fire ward, ice barrier
+ //+10% from +spd bonus
+ DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
+ break;
+ }
+ break;
+ case SPELLFAMILY_WARLOCK:
+ if(m_spellProto->SpellFamilyFlags == 0x00)
+ {
+ //shadow ward
+ //+10% from +spd bonus
+ DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
+
+ m_modifier.m_amount += (int32)DoneActualBenefit;
+ }
+ }
+}
+
+void Aura::PeriodicTick()
+{
+ if(!m_target->isAlive())
+ return;
+
+ switch(m_modifier.m_auraname)
+ {
+ case SPELL_AURA_PERIODIC_DAMAGE:
+ case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
+ {
+ Unit *pCaster = GetCaster();
+ if(!pCaster)
+ return;
+
+ if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
+ pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
+ return;
+
+ // Check for immune (not use charges)
+ if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
+ return;
+
+ // some auras remove at specific health level or more
+ if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE)
+ {
+ switch(GetId())
+ {
+ case 43093: case 31956: case 38801:
+ case 35321: case 38363: case 39215:
+ if(m_target->GetHealth() == m_target->GetMaxHealth() )
+ {
+ m_target->RemoveAurasDueToSpell(GetId());
+ return;
+ }
+ break;
+ case 38772:
+ {
+ uint32 percent =
+ GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_DUMMY ?
+ pCaster->CalculateSpellDamage(GetSpellProto(),GetEffIndex()+1,GetSpellProto()->EffectBasePoints[GetEffIndex()+1],m_target) :
+ 100;
+ if(m_target->GetHealth()*100 >= m_target->GetMaxHealth()*percent )
+ {
+ m_target->RemoveAurasDueToSpell(GetId());
+ return;
+ }
+ break;
+ }
+ case 41337:// aura of anger
+ {
+ Unit::AuraList const& mMod = m_target->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
+ for(Unit::AuraList::const_iterator i = mMod.begin(); i != mMod.end(); ++i)
+ {
+ if ((*i)->GetId() == 41337)
+ {
+ (*i)->ApplyModifier(false);
+ (*i)->GetModifier()->m_amount += 5;
+ (*i)->ApplyModifier(true);
+ break;
+ }
+ }
+ m_modifier.m_amount += 100;
+ }break;
+ default:
+ break;
+ }
+ }
+
+ uint32 absorb=0;
+ uint32 resist=0;
+ CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
+
+ // ignore non positive values (can be result apply spellmods to aura damage
+ uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
+
+ uint32 pdamage;
+
+ if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE)
+ {
+ pdamage = amount;
+
+ // Calculate armor mitigation if it is a physical spell
+ // But not for bleed mechanic spells
+ if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL &&
+ GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED)
+ {
+ uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
+ cleanDamage.damage += pdamage - pdamageReductedArmor;
+ pdamage = pdamageReductedArmor;
+ }
+
+ pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
+
+ // Curse of Agony damage-per-tick calculation
+ if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544)
+ {
+ // 1..4 ticks, 1/2 from normal tick damage
+ if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3))
+ pdamage = pdamage/2;
+ // 9..12 ticks, 3/2 from normal tick damage
+ else if(m_duration<((m_maxduration-m_modifier.periodictime)/3))
+ pdamage += (pdamage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
+ // 5..8 ticks have normal tick damage
+ }
+ }
+ else
+ pdamage = uint32(m_target->GetMaxHealth()*amount/100);
+
+ //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
+ // Reduce dot damage from resilience for players
+ if (m_target->GetTypeId()==TYPEID_PLAYER)
+ pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
+
+ pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
+
+ sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
+
+ WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
+ data.append(m_target->GetPackGUID());
+ data.appendPackGUID(GetCasterGUID());
+ data << uint32(GetId());
+ data << uint32(1);
+ data << uint32(m_modifier.m_auraname);
+ data << (uint32)pdamage;
+ data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x
+ data << (uint32)absorb;
+ data << (uint32)resist;
+ m_target->SendMessageToSet(&data,true);
+
+ Unit* target = m_target; // aura can be deleted in DealDamage
+ SpellEntry const* spellProto = GetSpellProto();
+
+ pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
+
+ // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
+
+ pCaster->ProcDamageAndSpell(target, PROC_FLAG_NONE, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), GetSpellSchoolMask(spellProto), spellProto);
+ break;
+ }
+ case SPELL_AURA_PERIODIC_LEECH:
+ {
+ Unit *pCaster = GetCaster();
+ if(!pCaster)
+ return;
+
+ if(!pCaster->isAlive())
+ return;
+
+ if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
+ pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
+ return;
+
+ // Check for immune (not use charges)
+ if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
+ return;
+
+ uint32 absorb=0;
+ uint32 resist=0;
+ CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
+
+ uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
+
+ //Calculate armor mitigation if it is a physical spell
+ if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
+ {
+ uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage);
+ cleanDamage.damage += pdamage - pdamageReductedArmor;
+ pdamage = pdamageReductedArmor;
+ }
+
+ pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT);
+
+ // talent Soul Siphon add bonus to Drain Life spells
+ if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) )
+ {
+ // find talent max bonus percentage
+ Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i)
+ {
+ if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993)
+ {
+ if((*i)->GetEffIndex()!=1)
+ {
+ sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId());
+ break;
+ }
+
+ // effect 1 m_amount
+ int32 maxPercent = (*i)->GetModifier()->m_amount;
+ // effect 0 m_amount
+ int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster);
+
+ // count affliction effects and calc additional damage in percentage
+ int32 modPercent = 0;
+ Unit::AuraMap const& victimAuras = m_target->GetAuras();
+ for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr)
+ {
+ Aura* aura = itr->second;
+ if (aura->IsPositive())continue;
+ SpellEntry const* m_spell = aura->GetSpellProto();
+ if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK)
+ continue;
+
+ SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id);
+ SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id);
+
+ for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
+ {
+ if(_spell_idx->second->skillId == SKILL_AFFLICTION)
+ {
+ modPercent += stepPercent;
+ if (modPercent >= maxPercent)
+ {
+ modPercent = maxPercent;
+ break;
+ }
+ }
+ }
+ }
+ pdamage += (pdamage*modPercent/100);
+ break;
+ }
+ }
+ }
+
+ //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit
+ // Reduce dot damage from resilience for players
+ if (m_target->GetTypeId()==TYPEID_PLAYER)
+ pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage);
+
+ pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
+
+ if(m_target->GetHealth() < pdamage)
+ pdamage = uint32(m_target->GetHealth());
+
+ sLog.outDetail("PeriodicTick: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb);
+
+ pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0);
+
+
+ Unit* target = m_target; // aura can be deleted in DealDamage
+ SpellEntry const* spellProto = GetSpellProto();
+ float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1;
+
+ uint32 new_damage = pCaster->DealDamage(m_target, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
+
+ // DO NOT ACCESS MEMBERS OF THE AURA FROM NOW ON (DealDamage can delete aura)
+
+ pCaster->ProcDamageAndSpell(target, PROC_FLAG_HEALED, PROC_FLAG_TAKE_DAMAGE, new_damage, GetSpellSchoolMask(spellProto), spellProto);
+ if (!target->isAlive() && pCaster->IsNonMeleeSpellCasted(false))
+ {
+ for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
+ {
+ if (pCaster->m_currentSpells[i] && pCaster->m_currentSpells[i]->m_spellInfo->Id == spellProto->Id)
+ pCaster->m_currentSpells[i]->cancel();
+ }
+ }
+
+
+ if(Player *modOwner = pCaster->GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
+
+ uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster);
+
+ int32 gain = pCaster->ModifyHealth(heal);
+ pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto);
+
+ pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal);
+ break;
+ }
+ case SPELL_AURA_PERIODIC_HEAL:
+ case SPELL_AURA_OBS_MOD_HEALTH:
+ {
+ Unit *pCaster = GetCaster();
+ if(!pCaster)
+ return;
+
+ // heal for caster damage (must be alive)
+ if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive())
+ return;
+
+ // ignore non positive values (can be result apply spellmods to aura damage
+ uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
+
+ uint32 pdamage;
+
+ if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH)
+ pdamage = uint32(m_target->GetMaxHealth() * amount/100);
+ else
+ pdamage = amount;
+
+ pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target);
+
+ sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
+
+ WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
+ data.append(m_target->GetPackGUID());
+ data.appendPackGUID(GetCasterGUID());
+ data << uint32(GetId());
+ data << uint32(1);
+ data << uint32(m_modifier.m_auraname);
+ data << (uint32)pdamage;
+ m_target->SendMessageToSet(&data,true);
+
+ int32 gain = m_target->ModifyHealth(pdamage);
+
+ // add HoTs to amount healed in bgs
+ if( pCaster->GetTypeId() == TYPEID_PLAYER )
+ if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() )
+ bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain);
+
+ //Do check before because m_modifier.auraName can be invalidate by DealDamage.
+ bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster);
+
+ m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
+
+ Unit* target = m_target; // aura can be deleted in DealDamage
+ SpellEntry const* spellProto = GetSpellProto();
+ bool haveCastItem = GetCastItemGUID()!=0;
+
+ // heal for caster damage
+ if(m_target!=pCaster && spellProto->SpellVisual==163)
+ {
+ uint32 dmg = spellProto->manaPerSecond;
+ if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER)
+ {
+ pCaster->RemoveAurasDueToSpell(GetId());
+
+ // finish current generic/channeling spells, don't affect autorepeat
+ if(pCaster->m_currentSpells[CURRENT_GENERIC_SPELL])
+ {
+ pCaster->m_currentSpells[CURRENT_GENERIC_SPELL]->finish();
+ }
+ if(pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL])
+ {
+ pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0);
+ pCaster->m_currentSpells[CURRENT_CHANNELED_SPELL]->finish();
+ }
+ }
+ else
+ {
+ pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false);
+
+ CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
+ pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
+ }
+ }
+
+ // ignore item heals
+ if(procSpell && !haveCastItem)
+ pCaster->ProcDamageAndSpell(target,PROC_FLAG_NONE, PROC_FLAG_HEALED, pdamage, SPELL_SCHOOL_MASK_NONE, spellProto);
+ break;
+ }
+ case SPELL_AURA_PERIODIC_MANA_LEECH:
+ {
+ Unit *pCaster = GetCaster();
+ if(!pCaster)
+ return;
+
+ if(!pCaster->isAlive())
+ return;
+
+ if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA &&
+ pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE)
+ return;
+
+ // Check for immune (not use charges)
+ if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
+ return;
+
+ // ignore non positive values (can be result apply spellmods to aura damage
+ uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
+
+ sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
+
+ if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
+ break;
+
+ Powers power = Powers(m_modifier.m_miscvalue);
+
+ // power type might have changed between aura applying and tick (druid's shapeshift)
+ if(m_target->getPowerType() != power)
+ break;
+
+ int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power);
+
+ // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
+ if (power == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
+ drain_amount -= ((Player*)m_target)->GetSpellCritDamageReduction(drain_amount);
+
+ m_target->ModifyPower(power, -drain_amount);
+
+ float gain_multiplier = 0;
+
+ if(pCaster->GetMaxPower(power) > 0)
+ {
+ gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
+
+ if(Player *modOwner = pCaster->GetSpellModOwner())
+ modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
+ }
+
+ WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
+ data.append(m_target->GetPackGUID());
+ data.appendPackGUID(GetCasterGUID());
+ data << uint32(GetId());
+ data << uint32(1);
+ data << uint32(m_modifier.m_auraname);
+ data << (uint32)power; // power type
+ data << (uint32)drain_amount;
+ data << (float)gain_multiplier;
+ m_target->SendMessageToSet(&data,true);
+
+ int32 gain_amount = int32(drain_amount*gain_multiplier);
+
+ if(gain_amount)
+ {
+ int32 gain = pCaster->ModifyPower(power,gain_amount);
+ m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
+ }
+ break;
+ }
+ case SPELL_AURA_PERIODIC_ENERGIZE:
+ {
+ // ignore non positive values (can be result apply spellmods to aura damage
+ uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
+
+ sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
+
+ if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4)
+ break;
+
+ Powers power = Powers(m_modifier.m_miscvalue);
+
+ if(m_target->GetMaxPower(power) == 0)
+ break;
+
+ WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
+ data.append(m_target->GetPackGUID());
+ data.appendPackGUID(GetCasterGUID());
+ data << uint32(GetId());
+ data << uint32(1);
+ data << uint32(m_modifier.m_auraname);
+ data << (uint32)power; // power type
+ data << (uint32)pdamage;
+ m_target->SendMessageToSet(&data,true);
+
+ int32 gain = m_target->ModifyPower(power,pdamage);
+
+ if(Unit* pCaster = GetCaster())
+ m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
+ break;
+ }
+ case SPELL_AURA_OBS_MOD_MANA:
+ {
+ // ignore non positive values (can be result apply spellmods to aura damage
+ uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
+
+ uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100);
+
+ sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u",
+ GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId());
+
+ if(m_target->GetMaxPower(POWER_MANA) == 0)
+ break;
+
+ WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size
+ data.append(m_target->GetPackGUID());
+ data.appendPackGUID(GetCasterGUID());
+ data << uint32(GetId());
+ data << uint32(1);
+ data << uint32(m_modifier.m_auraname);
+ data << (uint32)0; // ?
+ data << (uint32)pdamage;
+ m_target->SendMessageToSet(&data,true);
+
+ int32 gain = m_target->ModifyPower(POWER_MANA, pdamage);
+
+ if(Unit* pCaster = GetCaster())
+ m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto());
+ break;
+ }
+ case SPELL_AURA_POWER_BURN_MANA:
+ {
+ Unit *pCaster = GetCaster();
+ if(!pCaster)
+ return;
+
+ // Check for immune (not use charges)
+ if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto())))
+ return;
+
+ int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0;
+
+ Powers powerType = Powers(m_modifier.m_miscvalue);
+
+ if(!m_target->isAlive() || m_target->getPowerType() != powerType)
+ return;
+
+ // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
+ if (powerType == POWER_MANA && m_target->GetTypeId() == TYPEID_PLAYER)
+ pdamage -= ((Player*)m_target)->GetSpellCritDamageReduction(pdamage);
+
+ uint32 gain = uint32(-m_target->ModifyPower(powerType, -pdamage));
+
+ gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
+
+ //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
+ pCaster->SpellNonMeleeDamageLog(m_target, GetId(), gain);
+ break;
+ }
+ // Here tick dummy auras
+ case SPELL_AURA_PERIODIC_DUMMY:
+ {
+ PeriodicDummyTick();
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void Aura::PeriodicDummyTick()
+{
+ SpellEntry const* spell = GetSpellProto();
+ switch (spell->Id)
+ {
+ // Drink
+ case 430:
+ case 431:
+ case 432:
+ case 1133:
+ case 1135:
+ case 1137:
+ case 10250:
+ case 22734:
+ case 27089:
+ case 34291:
+ case 43706:
+ case 46755:
+ {
+ if (m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus
+ Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN);
+ for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i)
+ {
+ if ((*i)->GetId() == GetId())
+ {
+ // Get tick number
+ int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime;
+ // Default case (not on arenas)
+ if (tick == 0)
+ {
+ (*i)->GetModifier()->m_amount = m_modifier.m_amount;
+ ((Player*)m_target)->UpdateManaRegen();
+ // Disable continue
+ m_isPeriodic = false;
+ }
+ return;
+ //**********************************************
+ // Code commended since arena patch not added
+ // This feature uses only in arenas
+ //**********************************************
+ // Here need increase mana regen per tick (6 second rule)
+ // on 0 tick - 0 (handled in 2 second)
+ // on 1 tick - 166% (handled in 4 second)
+ // on 2 tick - 133% (handled in 6 second)
+ // Not need update after 3 tick
+ /*
+ if (tick > 3)
+ return;
+ // Apply bonus for 0 - 3 tick
+ switch (tick)
+ {
+ case 0: // 0%
+ (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0;
+ break;
+ case 1: // 166%
+ (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3;
+ break;
+ case 2: // 133%
+ (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3;
+ break;
+ default: // 100% - normal regen
+ (*i)->GetModifier()->m_amount = m_modifier.m_amount;
+ break;
+ }
+ ((Player*)m_target)->UpdateManaRegen();
+ return;*/
+ }
+ }
+ return;
+ }
+// // Panda
+// case 19230: break;
+// // Master of Subtlety
+// case 31666: break;
+// // Gossip NPC Periodic - Talk
+// case 33208: break;
+// // Gossip NPC Periodic - Despawn
+// case 33209: break;
+// // Force of Nature
+// case 33831: break;
+ // Aspect of the Viper
+ case 34074:
+ {
+ if (m_target->GetTypeId() != TYPEID_PLAYER)
+ return;
+ // Should be manauser
+ if (m_target->getPowerType()!=POWER_MANA)
+ return;
+ Unit *caster = GetCaster();
+ if (!caster)
+ return;
+ // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell)
+ int mana = m_target->GetPower(POWER_MANA);
+ int max_mana = m_target->GetMaxPower(POWER_MANA);
+ int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target);
+ float regen_pct = 1.20f - 1.1f * mana / max_mana;
+ if (regen_pct > 1.0f) regen_pct = 1.0f;
+ else if (regen_pct < 0.2f) regen_pct = 0.2f;
+ m_modifier.m_amount = int32 (base_regen * regen_pct);
+ ((Player*)m_target)->UpdateManaRegen();
+ return;
+ }
+// // Steal Weapon
+// case 36207: break;
+// // Simon Game START timer, (DND)
+// case 39993: break;
+// // Harpooner's Mark
+// case 40084: break;
+// // Knockdown Fel Cannon: break; The Aggro Burst
+// case 40119: break;
+// // Old Mount Spell
+// case 40154: break;
+// // Magnetic Pull
+// case 40581: break;
+// // Ethereal Ring: break; The Bolt Burst
+// case 40801: break;
+// // Crystal Prison
+// case 40846: break;
+// // Copy Weapon
+// case 41054: break;
+// // Ethereal Ring Visual, Lightning Aura
+// case 41477: break;
+// // Ethereal Ring Visual, Lightning Aura (Fork)
+// case 41525: break;
+// // Ethereal Ring Visual, Lightning Jumper Aura
+// case 41567: break;
+// // No Man's Land
+// case 41955: break;
+// // Headless Horseman - Fire
+// case 42074: break;
+// // Headless Horseman - Visual - Large Fire
+// case 42075: break;
+// // Headless Horseman - Start Fire, Periodic Aura
+// case 42140: break;
+// // Ram Speed Boost
+// case 42152: break;
+// // Headless Horseman - Fires Out Victory Aura
+// case 42235: break;
+// // Pumpkin Life Cycle
+// case 42280: break;
+// // Brewfest Request Chick Chuck Mug Aura
+// case 42537: break;
+// // Squashling
+// case 42596: break;
+// // Headless Horseman Climax, Head: Periodic
+// case 42603: break;
+// // Fire Bomb
+// case 42621: break;
+// // Headless Horseman - Conflagrate, Periodic Aura
+// case 42637: break;
+// // Headless Horseman - Create Pumpkin Treats Aura
+// case 42774: break;
+// // Headless Horseman Climax - Summoning Rhyme Aura
+// case 42879: break;
+// // Tricky Treat
+// case 42919: break;
+// // Giddyup!
+// case 42924: break;
+// // Ram - Trot
+// case 42992: break;
+// // Ram - Canter
+// case 42993: break;
+// // Ram - Gallop
+// case 42994: break;
+// // Ram Level - Neutral
+// case 43310: break;
+// // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17
+// case 43884: break;
+// // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17
+// case 44000: break;
+// // Energy Feedback
+// case 44328: break;
+// // Romantic Picnic
+// case 45102: break;
+// // Romantic Picnic
+// case 45123: break;
+// // Looking for Love
+// case 45124: break;
+// // Kite - Lightning Strike Kite Aura
+// case 45197: break;
+// // Rocket Chicken
+// case 45202: break;
+// // Copy Offhand Weapon
+// case 45205: break;
+// // Upper Deck - Kite - Lightning Periodic Aura
+// case 45207: break;
+// // Kite -Sky Lightning Strike Kite Aura
+// case 45251: break;
+// // Ribbon Pole Dancer Check Aura
+// case 45390: break;
+// // Holiday - Midsummer, Ribbon Pole Periodic Visual
+// case 45406: break;
+// // Parachute
+// case 45472: break;
+// // Alliance Flag, Extra Damage Debuff
+// case 45898: break;
+// // Horde Flag, Extra Damage Debuff
+// case 45899: break;
+// // Ahune - Summoning Rhyme Aura
+// case 45926: break;
+// // Ahune - Slippery Floor
+// case 45945: break;
+// // Ahune's Shield
+// case 45954: break;
+// // Nether Vapor Lightning
+// case 45960: break;
+// // Darkness
+// case 45996: break;
+// // Summon Blood Elves Periodic
+// case 46041: break;
+// // Transform Visual Missile Periodic
+// case 46205: break;
+// // Find Opening Beam End
+// case 46333: break;
+// // Ice Spear Control Aura
+// case 46371: break;
+// // Hailstone Chill
+// case 46458: break;
+// // Hailstone Chill, Internal
+// case 46465: break;
+// // Chill, Internal Shifter
+// case 46549: break;
+// // Summon Ice Spear Knockback Delayer
+// case 46878: break;
+// // Burninate Effect
+// case 47214: break;
+// // Fizzcrank Practice Parachute
+// case 47228: break;
+// // Send Mug Control Aura
+// case 47369: break;
+// // Direbrew's Disarm (precast)
+// case 47407: break;
+// // Mole Machine Port Schedule
+// case 47489: break;
+// // Mole Machine Portal Schedule
+// case 49466: break;
+// // Drink Coffee
+// case 49472: break;
+// // Listening to Music
+// case 50493: break;
+// // Love Rocket Barrage
+// case 50530: break;
+ default:
+ break;
+ }
+}
+
+void Aura::HandlePreventFleeing(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
+ if( !fearAuras.empty() )
+ {
+ if (apply)
+ m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
+ else
+ m_target->SetFeared(true);
+ }
+}
+
+void Aura::HandleManaShield(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ // prevent double apply bonuses
+ if(apply && (m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()))
+ {
+ if(Unit* caster = GetCaster())
+ {
+ float DoneActualBenefit = 0.0f;
+ switch(m_spellProto->SpellFamilyName)
+ {
+ case SPELLFAMILY_MAGE:
+ if(m_spellProto->SpellFamilyFlags & 0x8000)
+ {
+ // Mana Shield
+ // +50% from +spd bonus
+ DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.5f;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
+
+ m_modifier.m_amount += (int32)DoneActualBenefit;
+ }
+ }
+}
+
+void Aura::HandleArenaPreparation(bool apply, bool Real)
+{
+ if(!Real)
+ return;
+
+ if(apply)
+ m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
+ else
+ m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
+}
diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 3ed9c04a259..830dcc4d9a6 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -1,488 +1,496 @@ -/* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> - * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" -#include "Database/DBCStores.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "World.h" -#include "ObjectMgr.h" -#include "SpellMgr.h" -#include "Log.h" -#include "Opcodes.h" -#include "Spell.h" -#include "SpellAuras.h" -#include "BattleGround.h" -#include "MapManager.h" -#include "ScriptCalls.h" -#include "Totem.h" - -void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) -{ - // TODO: add targets.read() check - CHECK_PACKET_SIZE(recvPacket,1+1+1+1+8); - - Player* pUser = _player; - uint8 bagIndex, slot; - uint8 spell_count; // number of spells at item, not used - uint8 cast_count; // next cast if exists (single or not) - uint64 item_guid; - - recvPacket >> bagIndex >> slot >> spell_count >> cast_count >> item_guid; - - Item *pItem = pUser->GetItemByPos(bagIndex, slot); - if(!pItem) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); - return; - } - - sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , cast_count: %u, Item: %u, data length = %i", bagIndex, slot, spell_count, cast_count, pItem->GetEntry(), recvPacket.size()); - - ItemPrototype const *proto = pItem->GetProto(); - if(!proto) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); - return; - } - - // some item classes can be used only in equipped state - if(proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped()) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); - return; - } - - uint8 msg = pUser->CanUseItem(pItem); - if( msg != EQUIP_ERR_OK ) - { - pUser->SendEquipError( msg, pItem, NULL ); - return; - } - - // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB) - if( proto->Class == ITEM_CLASS_CONSUMABLE && - !(proto->Flags & ITEM_FLAGS_USEABLE_IN_ARENA) && - pUser->InArena()) - { - pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL); - return; - } - - if (pUser->isInCombat()) - { - for(int i = 0; i < 5; ++i) - { - if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId)) - { - if (IsNonCombatSpell(spellInfo)) - { - pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT,pItem,NULL); - return; - } - } - } - } - - // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory) - if( pItem->GetProto()->Bonding == BIND_WHEN_USE || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM ) - { - if (!pItem->IsSoulBound()) - { - pItem->SetState(ITEM_CHANGED, pUser); - pItem->SetBinding( true ); - } - } - - SpellCastTargets targets; - if(!targets.read(&recvPacket, pUser)) - return; - - //Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state. - if(!Script->ItemUse(pUser,pItem,targets)) - { - // no script or script not process request by self - - // special learning case - if(pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN) - { - uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_ID_GENERIC_LEARN); - if(!spellInfo) - { - sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, SPELL_ID_GENERIC_LEARN); - pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL); - return; - } - - Spell *spell = new Spell(pUser, spellInfo, false); - spell->m_CastItem = pItem; - spell->m_cast_count = cast_count; //set count of casts - spell->m_currentBasePoints[0] = learning_spell_id; - spell->prepare(&targets); - return; - } - - // use triggered flag only for items with many spell casts and for not first cast - int count = 0; - - for(int i = 0; i < 5; ++i) - { - _Spell const& spellData = pItem->GetProto()->Spells[i]; - - // no spell - if(!spellData.SpellId) - continue; - - // wrong triggering type - if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) - continue; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); - if(!spellInfo) - { - sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, spellData.SpellId); - continue; - } - - Spell *spell = new Spell(pUser, spellInfo, (count > 0)); - spell->m_CastItem = pItem; - spell->m_cast_count = cast_count; //set count of casts - spell->prepare(&targets); - - ++count; - } - } -} - -#define OPEN_CHEST 11437 -#define OPEN_SAFE 11535 -#define OPEN_CAGE 11792 -#define OPEN_BOOTY_CHEST 5107 -#define OPEN_STRONGBOX 8517 - -void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) -{ - CHECK_PACKET_SIZE(recvPacket,1+1); - - sLog.outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i",recvPacket.size()); - - Player* pUser = _player; - uint8 bagIndex, slot; - - recvPacket >> bagIndex >> slot; - - sLog.outDetail("bagIndex: %u, slot: %u",bagIndex,slot); - - Item *pItem = pUser->GetItemByPos(bagIndex, slot); - if(!pItem) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); - return; - } - - ItemPrototype const *proto = pItem->GetProto(); - if(!proto) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL ); - return; - } - - // locked item - uint32 lockId = proto->LockID; - if(lockId) - { - LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); - - if (!lockInfo) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL ); - sLog.outError( "WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", pItem->GetGUIDLow() , lockId); - return; - } - - // required picklocking - if(lockInfo->requiredlockskill || lockInfo->requiredminingskill) - { - pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL ); - return; - } - } - - if(pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))// wrapped? - { - QueryResult *result = CharacterDatabase.PQuery("SELECT entry, flags FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); - if (result) - { - Field *fields = result->Fetch(); - uint32 entry = fields[0].GetUInt32(); - uint32 flags = fields[1].GetUInt32(); - - pItem->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, 0); - pItem->SetUInt32Value(OBJECT_FIELD_ENTRY, entry); - pItem->SetUInt32Value(ITEM_FIELD_FLAGS, flags); - pItem->SetState(ITEM_CHANGED, pUser); - delete result; - } - else - { - sLog.outError("Wrapped item %u don't have record in character_gifts table and will deleted", pItem->GetGUIDLow()); - pUser->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); - return; - } - CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow()); - } - else - pUser->SendLoot(pItem->GetGUID(),LOOT_CORPSE); -} - -void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data ) -{ - CHECK_PACKET_SIZE(recv_data,8); - - uint64 guid; - uint32 spellId = OPEN_CHEST; - - recv_data >> guid; - - sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid)); - GameObject *obj = ObjectAccessor::GetGameObject(*_player, guid); - - if(!obj) - return; - - if (Script->GOHello(_player, obj)) - return; - - obj->Use(_player); -} - -void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) -{ - CHECK_PACKET_SIZE(recvPacket,4+1+2); - - uint32 spellId; - uint8 cast_count; - recvPacket >> spellId; - recvPacket >> cast_count; - - sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i", - spellId, cast_count, recvPacket.size()); - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); - - if(!spellInfo) - { - sLog.outError("WORLD: unknown spell id %u", spellId); - return; - } - - // not have spell or spell passive and not casted by client - if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) ) - { - //cheater? kick? ban? - return; - } - - // can't use our own spells when we're in possession of another unit, - if(_player->isPossessing()) - return; - - // client provided targets - SpellCastTargets targets; - if(!targets.read(&recvPacket,_player)) - return; - - // auto-selection buff level base at target level (in spellInfo) - if(targets.getUnitTarget()) - { - SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel()); - - // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message - if(actualSpellInfo) - spellInfo = actualSpellInfo; - } - - Spell *spell = new Spell(_player, spellInfo, false); - spell->m_cast_count = cast_count; //set count of casts - spell->prepare(&targets); -} - -void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) -{ - CHECK_PACKET_SIZE(recvPacket,4); - - uint32 spellId; - recvPacket >> spellId; - - //FIXME: hack, ignore unexpected client cancel Deadly Throw cast - if(spellId==26679) - return; - - if(_player->IsNonMeleeSpellCasted(false)) - _player->InterruptNonMeleeSpells(false,spellId); -} - -void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) -{ - CHECK_PACKET_SIZE(recvPacket,4); - - uint32 spellId; - recvPacket >> spellId; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo) - return; - - // Remove possess/charm/sight aura from the possessed/charmed as well - // TODO: Remove this once the ability to cancel aura sets at once is implemented - if(_player->GetCharm() || _player->GetFarsightTarget()) - { - for (int i = 0; i < 3; ++i) - { - if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS_PET || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_CHARM || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_BIND_SIGHT) - { - _player->RemoveAurasDueToSpellByCancel(spellId); - if (_player->GetCharm()) - _player->GetCharm()->RemoveAurasDueToSpellByCancel(spellId); - else if (_player->GetFarsightTarget()->GetTypeId() != TYPEID_DYNAMICOBJECT) - ((Unit*)_player->GetFarsightTarget())->RemoveAurasDueToSpellByCancel(spellId); - return; - } - } - } - - // not allow remove non positive spells and spells with attr SPELL_ATTR_CANT_CANCEL - if(!IsPositiveSpell(spellId) || (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL)) - return; - - _player->RemoveAurasDueToSpellByCancel(spellId); - - if (spellId == 2584) // Waiting to resurrect spell cancel, we must remove player from resurrect queue - { - BattleGround *bg = _player->GetBattleGround(); - if(!bg) - return; - bg->RemovePlayerFromResurrectQueue(_player->GetGUID()); - } -} - -void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket) -{ - CHECK_PACKET_SIZE(recvPacket, 8+4); - - uint64 guid; - uint32 spellId; - - recvPacket >> guid; - recvPacket >> spellId; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); - if(!spellInfo) - { - sLog.outError("WORLD: unknown PET spell id %u", spellId); - return; - } - - Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid); - - if(!pet) - { - sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid)) ); - return; - } - - if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) - { - sLog.outError( "HandlePetCancelAura.Pet %u isn't pet of player %s", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() ); - return; - } - - if(!pet->isAlive()) - { - pet->SendPetActionFeedback(FEEDBACK_PET_DEAD); - return; - } - - pet->RemoveAurasDueToSpell(spellId); - - pet->AddCreatureSpellCooldown(spellId); -} - -void WorldSession::HandleCancelGrowthAuraOpcode( WorldPacket& /*recvPacket*/) -{ - // nothing do -} - -void WorldSession::HandleCancelAutoRepeatSpellOpcode( WorldPacket& /*recvPacket*/) -{ - // may be better send SMSG_CANCEL_AUTO_REPEAT? - // cancel and prepare for deleting - _player->InterruptSpell(CURRENT_AUTOREPEAT_SPELL); -} - -/// \todo Complete HandleCancelChanneling function -void WorldSession::HandleCancelChanneling( WorldPacket & /*recv_data */) -{ - /* - CHECK_PACKET_SIZE(recv_data, 4); - - uint32 spellid; - recv_data >> spellid; - */ -} - -void WorldSession::HandleTotemDestroy( WorldPacket& recvPacket) -{ - CHECK_PACKET_SIZE(recvPacket, 1); - - uint8 slotId; - - recvPacket >> slotId; - - if (slotId >= MAX_TOTEM) - return; - - if(!_player->m_TotemSlot[slotId]) - return; - - Creature* totem = ObjectAccessor::GetCreature(*_player,_player->m_TotemSlot[slotId]); - // Don't unsummon sentry totem - if(totem && totem->isTotem() && totem->GetEntry() != SENTRY_TOTEM_ENTRY) - ((Totem*)totem)->UnSummon(); -} - -void WorldSession::HandleSelfResOpcode( WorldPacket & /*recv_data*/ ) -{ - sLog.outDebug("WORLD: CMSG_SELF_RES"); // empty opcode - - if(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL)); - if(spellInfo) - _player->CastSpell(_player,spellInfo,false,0); - - _player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); - } -} +/*
+ * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ *
+ * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "Database/DBCStores.h"
+#include "WorldPacket.h"
+#include "WorldSession.h"
+#include "World.h"
+#include "ObjectMgr.h"
+#include "SpellMgr.h"
+#include "Log.h"
+#include "Opcodes.h"
+#include "Spell.h"
+#include "SpellAuras.h"
+#include "BattleGround.h"
+#include "MapManager.h"
+#include "ScriptCalls.h"
+#include "Totem.h"
+
+void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
+{
+ // TODO: add targets.read() check
+ CHECK_PACKET_SIZE(recvPacket,1+1+1+1+8);
+
+ Player* pUser = _player;
+ uint8 bagIndex, slot;
+ uint8 spell_count; // number of spells at item, not used
+ uint8 cast_count; // next cast if exists (single or not)
+ uint64 item_guid;
+
+ recvPacket >> bagIndex >> slot >> spell_count >> cast_count >> item_guid;
+
+ Item *pItem = pUser->GetItemByPos(bagIndex, slot);
+ if(!pItem)
+ {
+ pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
+ return;
+ }
+
+ sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , cast_count: %u, Item: %u, data length = %i", bagIndex, slot, spell_count, cast_count, pItem->GetEntry(), recvPacket.size());
+
+ ItemPrototype const *proto = pItem->GetProto();
+ if(!proto)
+ {
+ pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL );
+ return;
+ }
+
+ // some item classes can be used only in equipped state
+ if(proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped())
+ {
+ pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL );
+ return;
+ }
+
+ uint8 msg = pUser->CanUseItem(pItem);
+ if( msg != EQUIP_ERR_OK )
+ {
+ pUser->SendEquipError( msg, pItem, NULL );
+ return;
+ }
+
+ // only allow conjured consumable, bandage, poisons (all should have the 2^21 item flag set in DB)
+ if( proto->Class == ITEM_CLASS_CONSUMABLE &&
+ !(proto->Flags & ITEM_FLAGS_USEABLE_IN_ARENA) &&
+ pUser->InArena())
+ {
+ pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL);
+ return;
+ }
+
+ if (pUser->isInCombat())
+ {
+ for(int i = 0; i < 5; ++i)
+ {
+ if (SpellEntry const *spellInfo = sSpellStore.LookupEntry(proto->Spells[i].SpellId))
+ {
+ if (IsNonCombatSpell(spellInfo))
+ {
+ pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT,pItem,NULL);
+ return;
+ }
+ }
+ }
+ }
+
+ // check also BIND_WHEN_PICKED_UP and BIND_QUEST_ITEM for .additem or .additemset case by GM (not binded at adding to inventory)
+ if( pItem->GetProto()->Bonding == BIND_WHEN_USE || pItem->GetProto()->Bonding == BIND_WHEN_PICKED_UP || pItem->GetProto()->Bonding == BIND_QUEST_ITEM )
+ {
+ if (!pItem->IsSoulBound())
+ {
+ pItem->SetState(ITEM_CHANGED, pUser);
+ pItem->SetBinding( true );
+ }
+ }
+
+ SpellCastTargets targets;
+ if(!targets.read(&recvPacket, pUser))
+ return;
+
+ //Note: If script stop casting it must send appropriate data to client to prevent stuck item in gray state.
+ if(!Script->ItemUse(pUser,pItem,targets))
+ {
+ // no script or script not process request by self
+
+ // special learning case
+ if(pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN)
+ {
+ uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_ID_GENERIC_LEARN);
+ if(!spellInfo)
+ {
+ sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, SPELL_ID_GENERIC_LEARN);
+ pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL);
+ return;
+ }
+
+ Spell *spell = new Spell(pUser, spellInfo, false);
+ spell->m_CastItem = pItem;
+ spell->m_cast_count = cast_count; //set count of casts
+ spell->m_currentBasePoints[0] = learning_spell_id;
+ spell->prepare(&targets);
+ return;
+ }
+
+ // use triggered flag only for items with many spell casts and for not first cast
+ int count = 0;
+
+ for(int i = 0; i < 5; ++i)
+ {
+ _Spell const& spellData = pItem->GetProto()->Spells[i];
+
+ // no spell
+ if(!spellData.SpellId)
+ continue;
+
+ // wrong triggering type
+ if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)
+ continue;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId);
+ if(!spellInfo)
+ {
+ sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, spellData.SpellId);
+ continue;
+ }
+
+ Spell *spell = new Spell(pUser, spellInfo, (count > 0));
+ spell->m_CastItem = pItem;
+ spell->m_cast_count = cast_count; //set count of casts
+ spell->prepare(&targets);
+
+ ++count;
+ }
+ }
+}
+
+#define OPEN_CHEST 11437
+#define OPEN_SAFE 11535
+#define OPEN_CAGE 11792
+#define OPEN_BOOTY_CHEST 5107
+#define OPEN_STRONGBOX 8517
+
+void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
+{
+ CHECK_PACKET_SIZE(recvPacket,1+1);
+
+ sLog.outDetail("WORLD: CMSG_OPEN_ITEM packet, data length = %i",recvPacket.size());
+
+ Player* pUser = _player;
+ uint8 bagIndex, slot;
+
+ recvPacket >> bagIndex >> slot;
+
+ sLog.outDetail("bagIndex: %u, slot: %u",bagIndex,slot);
+
+ Item *pItem = pUser->GetItemByPos(bagIndex, slot);
+ if(!pItem)
+ {
+ pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
+ return;
+ }
+
+ ItemPrototype const *proto = pItem->GetProto();
+ if(!proto)
+ {
+ pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL );
+ return;
+ }
+
+ // locked item
+ uint32 lockId = proto->LockID;
+ if(lockId)
+ {
+ LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
+
+ if (!lockInfo)
+ {
+ pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL );
+ sLog.outError( "WORLD::OpenItem: item [guid = %u] has an unknown lockId: %u!", pItem->GetGUIDLow() , lockId);
+ return;
+ }
+
+ // required picklocking
+ if(lockInfo->requiredlockskill || lockInfo->requiredminingskill)
+ {
+ pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL );
+ return;
+ }
+ }
+
+ if(pItem->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_WRAPPED))// wrapped?
+ {
+ QueryResult *result = CharacterDatabase.PQuery("SELECT entry, flags FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow());
+ if (result)
+ {
+ Field *fields = result->Fetch();
+ uint32 entry = fields[0].GetUInt32();
+ uint32 flags = fields[1].GetUInt32();
+
+ pItem->SetUInt64Value(ITEM_FIELD_GIFTCREATOR, 0);
+ pItem->SetUInt32Value(OBJECT_FIELD_ENTRY, entry);
+ pItem->SetUInt32Value(ITEM_FIELD_FLAGS, flags);
+ pItem->SetState(ITEM_CHANGED, pUser);
+ delete result;
+ }
+ else
+ {
+ sLog.outError("Wrapped item %u don't have record in character_gifts table and will deleted", pItem->GetGUIDLow());
+ pUser->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true);
+ return;
+ }
+ CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE item_guid = '%u'", pItem->GetGUIDLow());
+ }
+ else
+ pUser->SendLoot(pItem->GetGUID(),LOOT_CORPSE);
+}
+
+void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data )
+{
+ CHECK_PACKET_SIZE(recv_data,8);
+
+ uint64 guid;
+ uint32 spellId = OPEN_CHEST;
+
+ recv_data >> guid;
+
+ sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid));
+ GameObject *obj = ObjectAccessor::GetGameObject(*_player, guid);
+
+ if(!obj)
+ return;
+
+ if (Script->GOHello(_player, obj))
+ return;
+
+ obj->Use(_player);
+}
+
+void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
+{
+ CHECK_PACKET_SIZE(recvPacket,4+1+2);
+
+ uint32 spellId;
+ uint8 cast_count;
+ recvPacket >> spellId;
+ recvPacket >> cast_count;
+
+ sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i",
+ spellId, cast_count, recvPacket.size());
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
+
+ if(!spellInfo)
+ {
+ sLog.outError("WORLD: unknown spell id %u", spellId);
+ return;
+ }
+
+ // not have spell or spell passive and not casted by client
+ if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) )
+ {
+ //cheater? kick? ban?
+ return;
+ }
+
+ // can't use our own spells when we're in possession of another unit,
+ if(_player->isPossessing())
+ return;
+
+ // client provided targets
+ SpellCastTargets targets;
+ if(!targets.read(&recvPacket,_player))
+ return;
+
+ // auto-selection buff level base at target level (in spellInfo)
+ if(targets.getUnitTarget())
+ {
+ SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel());
+
+ // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message
+ if(actualSpellInfo)
+ spellInfo = actualSpellInfo;
+ }
+
+ Spell *spell = new Spell(_player, spellInfo, false);
+ spell->m_cast_count = cast_count; //set count of casts
+ spell->prepare(&targets);
+}
+
+void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket)
+{
+ CHECK_PACKET_SIZE(recvPacket,4);
+
+ uint32 spellId;
+ recvPacket >> spellId;
+
+ //FIXME: hack, ignore unexpected client cancel Deadly Throw cast
+ if(spellId==26679)
+ return;
+
+ if(_player->IsNonMeleeSpellCasted(false))
+ _player->InterruptNonMeleeSpells(false,spellId);
+}
+
+void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
+{
+ CHECK_PACKET_SIZE(recvPacket,4);
+
+ uint32 spellId;
+ recvPacket >> spellId;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
+ if (!spellInfo)
+ return;
+
+ // Remove possess/charm/sight aura from the possessed/charmed as well
+ // TODO: Remove this once the ability to cancel aura sets at once is implemented
+ if(_player->GetCharm() || _player->GetFarsightTarget())
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS ||
+ spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS_PET ||
+ spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_CHARM ||
+ spellInfo->EffectApplyAuraName[i] == SPELL_AURA_BIND_SIGHT)
+ {
+ _player->RemoveAurasDueToSpellByCancel(spellId);
+ if (_player->GetCharm())
+ _player->GetCharm()->RemoveAurasDueToSpellByCancel(spellId);
+ else if (_player->GetFarsightTarget()->GetTypeId() != TYPEID_DYNAMICOBJECT)
+ ((Unit*)_player->GetFarsightTarget())->RemoveAurasDueToSpellByCancel(spellId);
+ return;
+ }
+ }
+ }
+
+ // not allow remove non positive spells and spells with attr SPELL_ATTR_CANT_CANCEL
+ if(!IsPositiveSpell(spellId) || (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL))
+ return;
+
+ // channeled spell case (it currently casted then)
+ if(IsChanneledSpell(spellInfo))
+ {
+ if(Spell* spell = _player->m_currentSpells[CURRENT_CHANNELED_SPELL])
+ {
+ if(spell->m_spellInfo->Id==spellId)
+ {
+ spell->cancel();
+ spell->SetReferencedFromCurrent(false);
+ _player->m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL;
+ }
+ }
+ return;
+ }
+
+ // non channeled case
+ _player->RemoveAurasDueToSpellByCancel(spellId);
+}
+
+void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket)
+{
+ CHECK_PACKET_SIZE(recvPacket, 8+4);
+
+ uint64 guid;
+ uint32 spellId;
+
+ recvPacket >> guid;
+ recvPacket >> spellId;
+
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
+ if(!spellInfo)
+ {
+ sLog.outError("WORLD: unknown PET spell id %u", spellId);
+ return;
+ }
+
+ Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid);
+
+ if(!pet)
+ {
+ sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid)) );
+ return;
+ }
+
+ if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm())
+ {
+ sLog.outError( "HandlePetCancelAura.Pet %u isn't pet of player %s", uint32(GUID_LOPART(guid)),GetPlayer()->GetName() );
+ return;
+ }
+
+ if(!pet->isAlive())
+ {
+ pet->SendPetActionFeedback(FEEDBACK_PET_DEAD);
+ return;
+ }
+
+ pet->RemoveAurasDueToSpell(spellId);
+
+ pet->AddCreatureSpellCooldown(spellId);
+}
+
+void WorldSession::HandleCancelGrowthAuraOpcode( WorldPacket& /*recvPacket*/)
+{
+ // nothing do
+}
+
+void WorldSession::HandleCancelAutoRepeatSpellOpcode( WorldPacket& /*recvPacket*/)
+{
+ // may be better send SMSG_CANCEL_AUTO_REPEAT?
+ // cancel and prepare for deleting
+ _player->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
+}
+
+/// \todo Complete HandleCancelChanneling function
+void WorldSession::HandleCancelChanneling( WorldPacket & /*recv_data */)
+{
+ /*
+ CHECK_PACKET_SIZE(recv_data, 4);
+
+ uint32 spellid;
+ recv_data >> spellid;
+ */
+}
+
+void WorldSession::HandleTotemDestroy( WorldPacket& recvPacket)
+{
+ CHECK_PACKET_SIZE(recvPacket, 1);
+
+ uint8 slotId;
+
+ recvPacket >> slotId;
+
+ if (slotId >= MAX_TOTEM)
+ return;
+
+ if(!_player->m_TotemSlot[slotId])
+ return;
+
+ Creature* totem = ObjectAccessor::GetCreature(*_player,_player->m_TotemSlot[slotId]);
+ // Don't unsummon sentry totem
+ if(totem && totem->isTotem() && totem->GetEntry() != SENTRY_TOTEM_ENTRY)
+ ((Totem*)totem)->UnSummon();
+}
+
+void WorldSession::HandleSelfResOpcode( WorldPacket & /*recv_data*/ )
+{
+ sLog.outDebug("WORLD: CMSG_SELF_RES"); // empty opcode
+
+ if(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL))
+ {
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(_player->GetUInt32Value(PLAYER_SELF_RES_SPELL));
+ if(spellInfo)
+ _player->CastSpell(_player,spellInfo,false,0);
+
+ _player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0);
+ }
+}
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 22249af36d6..e0345950ffc 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4094,12 +4094,17 @@ void Unit::RemoveNotOwnSingleTargetAuras() void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
{
- if (IsSingleTargetSpell((*i).second->GetSpellProto()))
+ Aura* Aur = i->second;
+ SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
+
+ Unit* caster = NULL;
+ if (IsSingleTargetSpell(AurSpellInfo))
{
- if(Unit* caster = (*i).second->GetCaster())
+ caster = Aur->GetCaster();
+ if(caster)
{
AuraList& scAuras = caster->GetSingleCastAuras();
- scAuras.remove((*i).second);
+ scAuras.remove(Aur);
}
else
{
@@ -4108,20 +4113,19 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) }
}
- if ((*i).second->GetModifier()->m_auraname < TOTAL_AURAS)
+ // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order)
+ if (Aur->GetModifier()->m_auraname < TOTAL_AURAS)
{
- m_modAuras[(*i).second->GetModifier()->m_auraname].remove((*i).second);
- if((*i).second->GetSpellProto()->AuraInterruptFlags)
+ m_modAuras[Aur->GetModifier()->m_auraname].remove(Aur);
+ if(Aur->GetSpellProto()->AuraInterruptFlags)
{
- m_interruptableAuras.remove((*i).second);
+ m_interruptableAuras.remove(Aur);
UpdateInterruptMask();
}
- if((*i).second->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE)
- m_ccAuras.remove((*i).second);
+ if(Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE)
+ m_ccAuras.remove(Aur);
}
- // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order)
- Aura* Aur = i->second;
// Set remove mode
Aur->SetRemoveMode(mode);
// some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura
@@ -4129,12 +4133,22 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) m_Auras.erase(i);
++m_removedAuras; // internal count used by unit update
- // Status unsummoned at aura remove
+ // Statue unsummoned at aura remove
Totem* statue = NULL;
- if(IsChanneledSpell(Aur->GetSpellProto()))
- if(Unit* caster = Aur->GetCaster())
+ bool caster_channeled = false;
+ if(IsChanneledSpell(AurSpellInfo))
+ {
+ if(!caster) // can be already located for IsSingleTargetSpell case
+ caster = Aur->GetCaster();
+
+ if(caster)
+ {
if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE)
statue = ((Totem*)caster);
+ else
+ caster_channeled = caster==this;
+ }
+ }
if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)Aur->GetSpellProto()->Id))
@@ -4153,6 +4167,9 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) Aur->_RemoveAura();
delete Aur;
+ if(caster_channeled)
+ RemoveAurasAtChanneledTarget (AurSpellInfo);
+
if(statue)
statue->UnSummon();
@@ -4578,8 +4595,10 @@ void Unit::CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchool ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, damageSchoolMask, spellCasted, isTriggeredSpell, attType);
}
-bool Unit::HandleHasteAuraProc(Unit *pVictim, SpellEntry const *hasteSpell, uint32 /*effIndex*/, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 /*procFlag*/, uint32 cooldown)
+bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * /*procSpell*/, uint32 /*procFlag*/, uint32 cooldown)
{
+ SpellEntry const *hasteSpell = triggeredByAura->GetSpellProto();
+
Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
@@ -4639,8 +4658,11 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, SpellEntry const *hasteSpell, uint return true;
}
-bool Unit::HandleDummyAuraProc(Unit *pVictim, SpellEntry const *dummySpell, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 cooldown)
+bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 cooldown)
{
+ SpellEntry const *dummySpell = triggeredByAura->GetSpellProto ();
+ uint32 effIndex = triggeredByAura->GetEffIndex ();
+
Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER
? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL;
@@ -6458,8 +6480,10 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return true;
}
-bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 damage, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown)
+bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown)
{
+ int32 scriptId = triggeredByAura->GetModifier()->m_miscvalue;
+
if(!pVictim || !pVictim->isAlive())
return false;
@@ -9923,17 +9947,15 @@ bool Unit::isFrozen() const struct ProcTriggeredData
{
- ProcTriggeredData(SpellEntry const * _spellInfo, uint32 _spellParam, Aura* _triggeredByAura, uint32 _cooldown)
- : spellInfo(_spellInfo), spellParam(_spellParam), triggeredByAura(_triggeredByAura),
+ ProcTriggeredData(Aura* _triggeredByAura, uint32 _cooldown)
+ : triggeredByAura(_triggeredByAura),
triggeredByAura_SpellPair(Unit::spellEffectPair(triggeredByAura->GetId(),triggeredByAura->GetEffIndex())),
cooldown(_cooldown)
- {}
+ {}
- SpellEntry const * spellInfo;
- uint32 spellParam;
- Aura* triggeredByAura;
- Unit::spellEffectPair triggeredByAura_SpellPair;
- uint32 cooldown;
+ Aura* triggeredByAura; // triggred aura, can be invalidate at triggered aura proccessing
+ Unit::spellEffectPair triggeredByAura_SpellPair; // spell pair, used for re-find aura (by pointer comparison in range)
+ uint32 cooldown; // possible hidden cooldown
};
typedef std::list< ProcTriggeredData > ProcTriggeredList;
@@ -9950,87 +9972,13 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag {
next = i; ++next;
- SpellEntry const *spellProto = (*i)->GetSpellProto();
- if(!spellProto)
- continue;
+ Aura* i_aura = *i;
- SpellProcEventEntry const *spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id);
- if(!spellProcEvent)
- {
- // used to prevent spam in log about same non-handled spells
- static std::set<uint32> nonHandledSpellProcSet;
-
- if(spellProto->procFlags != 0 && nonHandledSpellProcSet.find(spellProto->Id)==nonHandledSpellProcSet.end())
- {
- sLog.outError("ProcDamageAndSpell: spell %u (%s aura source) not have record in `spell_proc_event`)",spellProto->Id,(isVictim?"a victim's":"an attacker's"));
- nonHandledSpellProcSet.insert(spellProto->Id);
- }
-
- // spell.dbc use totally different flags, that only can create problems if used.
+ uint32 cooldown; // returned at next line
+ if(!IsTriggeredAtSpellProcEvent(i_aura->GetSpellProto(), procSpell, procFlag,attType,isVictim,cooldown))
continue;
- }
- // Check spellProcEvent data requirements
- if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, procSpell,procFlag))
- continue;
-
- // Check if current equipment allows aura to proc
- if(!isVictim && GetTypeId() == TYPEID_PLAYER )
- {
- if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON)
- {
- Item *item = ((Player*)this)->GetWeaponForAttack(attType,true);
-
- if(!item || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask))
- continue;
- }
- else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR)
- {
- // Check if player is wearing shield
- Item *item = ((Player*)this)->GetShield(true);
- if(!item || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask))
- continue;
- }
- }
-
- float chance = (float)spellProto->procChance;
-
- if(Player* modOwner = GetSpellModOwner())
- modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance);
-
- if(!isVictim && spellProcEvent->ppmRate != 0)
- {
- uint32 WeaponSpeed = GetAttackTime(attType);
- chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate);
- }
-
- if(roll_chance_f(chance))
- {
- uint32 cooldown = spellProcEvent->cooldown;
-
- uint32 i_spell_eff = (*i)->GetEffIndex();
-
- int32 i_spell_param;
- switch(*aur)
- {
- case SPELL_AURA_PROC_TRIGGER_SPELL:
- i_spell_param = procFlag;
- break;
- case SPELL_AURA_DUMMY:
- case SPELL_AURA_PRAYER_OF_MENDING:
- case SPELL_AURA_MOD_HASTE:
- i_spell_param = i_spell_eff;
- break;
- case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
- i_spell_param = (*i)->GetModifier()->m_miscvalue;
- break;
- default:
- i_spell_param = (*i)->GetModifier()->m_amount;
- break;
- }
-
- procTriggered.push_back( ProcTriggeredData(spellProto,i_spell_param,*i, cooldown) );
- }
+ procTriggered.push_back( ProcTriggeredData(i_aura, cooldown) );
}
// Handle effects proceed this time
@@ -10063,106 +10011,66 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag }
}
+ // this is aura triggering code call
+ Aura* triggeredByAura = i->triggeredByAura;
+
// save charges existence before processing to prevent crash at access to deleted triggered aura after
- bool triggeredByAuraWithCharges = i->triggeredByAura->m_procCharges > 0;
+ bool triggeredByAuraWithCharges = triggeredByAura->m_procCharges > 0;
bool casted = false;
switch(*aur)
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
{
- sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId());
- casted = HandleProcTriggerSpell(pTarget, damage, i->triggeredByAura, procSpell,i->spellParam,attType,i->cooldown);
+ sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s proc aura of spell %u)",
+ (isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId());
+ casted = HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, attType, i->cooldown);
break;
}
case SPELL_AURA_PROC_TRIGGER_DAMAGE:
{
- sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", i->spellParam, i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId());
- uint32 damage = i->spellParam;
- SpellNonMeleeDamageLog(pTarget, i->spellInfo->Id, damage, true, true);
+ uint32 triggered_damage = triggeredByAura->GetModifier()->m_amount;
+ sLog.outDebug("ProcDamageAndSpell: doing %u damage (triggered by %s aura of spell %u)",
+ triggered_damage, (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
+ SpellNonMeleeDamageLog(pTarget, triggeredByAura->GetId(), triggered_damage, true, true);
casted = true;
break;
}
case SPELL_AURA_DUMMY:
{
- sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId());
- casted = HandleDummyAuraProc(pTarget, i->spellInfo, i->spellParam, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown);
+ uint32 effect = triggeredByAura->GetEffIndex();
+ sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s dummy aura of spell %u)",
+ (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
+ casted = HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag,i->cooldown);
break;
}
case SPELL_AURA_PRAYER_OF_MENDING:
{
- sLog.outDebug("ProcDamageAndSpell(mending): casting spell id %u (triggered by %s dummy aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId());
-
- // aura can be deleted at casts
- int32 heal = i->triggeredByAura->GetModifier()->m_amount;
- uint64 caster_guid = i->triggeredByAura->GetCasterGUID();
-
- // jumps
- int32 jumps = i->triggeredByAura->m_procCharges-1;
-
- // current aura expire
- i->triggeredByAura->m_procCharges = 1; // will removed at next charges decrease
-
- // next target selection
- if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid))
- {
- Aura* aura = i->triggeredByAura;
-
- SpellEntry const* spellProto = aura->GetSpellProto();
- uint32 effIdx = aura->GetEffIndex();
-
- float radius;
- if (spellProto->EffectRadiusIndex[effIdx])
- radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx]));
- else
- radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex));
+ sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
+ (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
- if(Player* caster = ((Player*)aura->GetCaster()))
- {
- caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL);
-
- if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius))
- {
- // aura will applied from caster, but spell casted from current aura holder
- SpellModifier *mod = new SpellModifier;
- mod->op = SPELLMOD_CHARGES;
- mod->value = jumps-5; // negative
- mod->type = SPELLMOD_FLAT;
- mod->spellId = spellProto->Id;
- mod->effectId = effIdx;
- mod->lastAffected = NULL;
- mod->mask = spellProto->SpellFamilyFlags;
- mod->charges = 0;
-
- caster->AddSpellMod(mod, true);
- CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,aura,caster->GetGUID());
- caster->AddSpellMod(mod, false);
- }
- }
- }
-
- // heal
- CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid);
- casted = true;
+ casted = HandleMeandingAuraProc(triggeredByAura);
break;
}
case SPELL_AURA_MOD_HASTE:
{
- sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s haste aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId());
- casted = HandleHasteAuraProc(pTarget, i->spellInfo, i->spellParam, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown);
+ sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s haste aura of spell %u)",
+ (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
+ casted = HandleHasteAuraProc(pTarget, damage, i->triggeredByAura, procSpell, procFlag,i->cooldown);
break;
}
case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
{
// nothing do, just charges counter
// but count only in case appropriate school damage
- casted = i->triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask;
+ casted = triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask;
break;
}
case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
{
- sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", i->spellInfo->Id,(isVictim?"a victim's":"an attacker's"),i->triggeredByAura->GetId());
- casted = HandleOverrideClassScriptAuraProc(pTarget, i->spellParam, damage, i->triggeredByAura, procSpell,i->cooldown);
+ sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s class script aura of spell %u)",
+ (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
+ casted = HandleOverrideClassScriptAuraProc(pTarget, i->triggeredByAura, procSpell,i->cooldown);
break;
}
default:
@@ -10810,3 +10718,132 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) return pet;
}
+
+bool Unit::IsTriggeredAtSpellProcEvent(SpellEntry const* spellProto, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, bool isVictim, uint32& cooldown )
+{
+ SpellProcEventEntry const * spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id);
+
+ if(!spellProcEvent)
+ {
+ // used to prevent spam in log about same non-handled spells
+ static std::set<uint32> nonHandledSpellProcSet;
+
+ if(spellProto->procFlags != 0 && nonHandledSpellProcSet.find(spellProto->Id)==nonHandledSpellProcSet.end())
+ {
+ sLog.outError("ProcDamageAndSpell: spell %u (%s aura source) not have record in `spell_proc_event`)",spellProto->Id,(isVictim?"a victim's":"an attacker's"));
+ nonHandledSpellProcSet.insert(spellProto->Id);
+ }
+
+ // spell.dbc use totally different flags, that only can create problems if used.
+ return false;
+ }
+
+ // Check spellProcEvent data requirements
+ if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, procSpell,procFlag))
+ return false;
+
+ // Check if current equipment allows aura to proc
+ if(!isVictim && GetTypeId() == TYPEID_PLAYER )
+ {
+ if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON)
+ {
+ Item *item = ((Player*)this)->GetWeaponForAttack(attType,true);
+
+ if(!item || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask))
+ return false;
+ }
+ else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR)
+ {
+ // Check if player is wearing shield
+ Item *item = ((Player*)this)->GetShield(true);
+ if(!item || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask))
+ return false;
+ }
+ }
+
+ float chance = (float)spellProto->procChance;
+
+ if(Player* modOwner = GetSpellModOwner())
+ modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance);
+
+ if(!isVictim && spellProcEvent && spellProcEvent->ppmRate != 0)
+ {
+ uint32 WeaponSpeed = GetAttackTime(attType);
+ chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate);
+ }
+
+ cooldown = spellProcEvent ? spellProcEvent->cooldown : 0;
+ return roll_chance_f(chance);
+}
+
+bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
+{
+ // aura can be deleted at casts
+ SpellEntry const* spellProto = triggeredByAura->GetSpellProto();
+ uint32 effIdx = triggeredByAura->GetEffIndex();
+ int32 heal = triggeredByAura->GetModifier()->m_amount;
+ uint64 caster_guid = triggeredByAura->GetCasterGUID();
+
+ // jumps
+ int32 jumps = triggeredByAura->m_procCharges-1;
+
+ // current aura expire
+ triggeredByAura->m_procCharges = 1; // will removed at next charges decrease
+
+ // next target selection
+ if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid))
+ {
+ float radius;
+ if (spellProto->EffectRadiusIndex[effIdx])
+ radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellProto->EffectRadiusIndex[effIdx]));
+ else
+ radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(spellProto->rangeIndex));
+
+ if(Player* caster = ((Player*)triggeredByAura->GetCaster()))
+ {
+ caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL);
+
+ if(Player* target = ((Player*)this)->GetNextRandomRaidMember(radius))
+ {
+ // aura will applied from caster, but spell casted from current aura holder
+ SpellModifier *mod = new SpellModifier;
+ mod->op = SPELLMOD_CHARGES;
+ mod->value = jumps-5; // negative
+ mod->type = SPELLMOD_FLAT;
+ mod->spellId = spellProto->Id;
+ mod->effectId = effIdx;
+ mod->lastAffected = NULL;
+ mod->mask = spellProto->SpellFamilyFlags;
+ mod->charges = 0;
+
+ caster->AddSpellMod(mod, true);
+ CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID());
+ caster->AddSpellMod(mod, false);
+ }
+ }
+ }
+
+ // heal
+ CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid);
+ return true;
+}
+
+void Unit::RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo)
+{
+ uint64 target_guid = GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT);
+
+ if(!IS_UNIT_GUID(target_guid))
+ return;
+
+ Unit* target = ObjectAccessor::GetUnit(*this, target_guid);
+ if(!target)
+ return;
+
+ for (AuraMap::iterator iter = target->GetAuras().begin(); iter != target->GetAuras().end(); )
+ {
+ if (iter->second->GetId() == spellInfo->Id && iter->second->GetCasterGUID()==GetGUID())
+ target->RemoveAura(iter);
+ else
+ ++iter;
+ }
+}
\ No newline at end of file diff --git a/src/game/Unit.h b/src/game/Unit.h index 028c590c06f..1ec669bcfd3 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1,1394 +1,1397 @@ -/* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> - * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __UNIT_H -#define __UNIT_H - -#include "Common.h" -#include "Object.h" -#include "Opcodes.h" -#include "Mthread.h" -#include "SpellAuraDefines.h" -#include "UpdateFields.h" -#include "SharedDefines.h" -#include "ThreatManager.h" -#include "HostilRefManager.h" -#include "FollowerReference.h" -#include "FollowerRefManager.h" -#include "Utilities/EventProcessor.h" -#include "MotionMaster.h" -#include "Database/DBCStructure.h" -#include <list> - -enum SpellInterruptFlags -{ - SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant? - SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back - SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, // interrupt - SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, // no - SPELL_INTERRUPT_FLAG_DAMAGE = 0x10 // _complete_ interrupt on direct damage? -}; - -enum SpellChannelInterruptFlags -{ - CHANNEL_FLAG_DAMAGE = 0x0002, - CHANNEL_FLAG_MOVEMENT = 0x0008, - CHANNEL_FLAG_TURNING = 0x0010, - CHANNEL_FLAG_DAMAGE2 = 0x0080, - CHANNEL_FLAG_DELAY = 0x4000 -}; - -enum SpellAuraInterruptFlags -{ - AURA_INTERRUPT_FLAG_HITBYSPELL = 0x00000001, // 0 removed when getting hit by a negative spell? - AURA_INTERRUPT_FLAG_DAMAGE = 0x00000002, // 1 removed by any damage - AURA_INTERRUPT_FLAG_CC = 0x00000004, // 2 crowd control - AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement - AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning - AURA_INTERRUPT_FLAG_JUMP = 0x00000020, // 5 removed by entering combat - AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by unmounting - AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water - AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water - AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing - AURA_INTERRUPT_FLAG_TALK = 0x00000400, // 10 talk to npc / loot? action on creature - AURA_INTERRUPT_FLAG_USE = 0x00000800, // 11 mine/use/open action on gameobject - AURA_INTERRUPT_FLAG_ATTACK = 0x00001000, // 12 removed by attacking - AURA_INTERRUPT_FLAG_CAST = 0x00002000, // 13 ??? - AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 - AURA_INTERRUPT_FLAG_TRANSFORM = 0x00008000, // 15 removed by transform? - AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 - AURA_INTERRUPT_FLAG_MOUNT = 0x00020000, // 17 misdirect, aspect, swim speed - AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up - AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported - AURA_INTERRUPT_FLAG_UNATTACKABLE = 0x00100000, // 20 invulnerable or stealth - AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21 - AURA_INTERRUPT_FLAG_TELEPORTED = 0x00400000, // 22 - AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat - AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000 // 24 removed by any direct damage -}; - -enum SpellModOp -{ - SPELLMOD_DAMAGE = 0, - SPELLMOD_DURATION = 1, - SPELLMOD_THREAT = 2, - SPELLMOD_EFFECT1 = 3, - SPELLMOD_CHARGES = 4, - SPELLMOD_RANGE = 5, - SPELLMOD_RADIUS = 6, - SPELLMOD_CRITICAL_CHANCE = 7, - SPELLMOD_ALL_EFFECTS = 8, - SPELLMOD_NOT_LOSE_CASTING_TIME = 9, - SPELLMOD_CASTING_TIME = 10, - SPELLMOD_COOLDOWN = 11, - SPELLMOD_EFFECT2 = 12, - // spellmod 13 unused - SPELLMOD_COST = 14, - SPELLMOD_CRIT_DAMAGE_BONUS = 15, - SPELLMOD_RESIST_MISS_CHANCE = 16, - SPELLMOD_JUMP_TARGETS = 17, - SPELLMOD_CHANCE_OF_SUCCESS = 18, - SPELLMOD_ACTIVATION_TIME = 19, - SPELLMOD_EFFECT_PAST_FIRST = 20, - SPELLMOD_CASTING_TIME_OLD = 21, - SPELLMOD_DOT = 22, - SPELLMOD_EFFECT3 = 23, - SPELLMOD_SPELL_BONUS_DAMAGE = 24, - // spellmod 25, 26 unused - SPELLMOD_MULTIPLE_VALUE = 27, - SPELLMOD_RESIST_DISPEL_CHANCE = 28 -}; - -#define MAX_SPELLMOD 32 - -enum SpellFacingFlags -{ - SPELL_FACING_FLAG_INFRONT = 0x0001 -}; - -#define BASE_MINDAMAGE 1.0f -#define BASE_MAXDAMAGE 2.0f -#define BASE_ATTACK_TIME 2000 - -// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 -enum ShapeshiftForm -{ - FORM_NONE = 0x00, - FORM_CAT = 0x01, - FORM_TREE = 0x02, - FORM_TRAVEL = 0x03, - FORM_AQUA = 0x04, - FORM_BEAR = 0x05, - FORM_AMBIENT = 0x06, - FORM_GHOUL = 0x07, - FORM_DIREBEAR = 0x08, - FORM_CREATUREBEAR = 0x0E, - FORM_CREATURECAT = 0x0F, - FORM_GHOSTWOLF = 0x10, - FORM_BATTLESTANCE = 0x11, - FORM_DEFENSIVESTANCE = 0x12, - FORM_BERSERKERSTANCE = 0x13, - FORM_TEST = 0x14, - FORM_ZOMBIE = 0x15, - FORM_FLIGHT_EPIC = 0x1B, - FORM_SHADOW = 0x1C, - FORM_FLIGHT = 0x1D, - FORM_STEALTH = 0x1E, - FORM_MOONKIN = 0x1F, - FORM_SPIRITOFREDEMPTION = 0x20 -}; - -// low byte ( 0 from 0..3 ) of UNIT_FIELD_BYTES_2 -enum SheathState -{ - SHEATH_STATE_UNARMED = 0, // non prepared weapon - SHEATH_STATE_MELEE = 1, // prepared melee weapon - SHEATH_STATE_RANGED = 2 // prepared ranged weapon -}; - -// byte (1 from 0..3) of UNIT_FIELD_BYTES_2 -enum UnitBytes2_Flags -{ - UNIT_BYTE2_FLAG_UNK0 = 0x01, - UNIT_BYTE2_FLAG_UNK1 = 0x02, - UNIT_BYTE2_FLAG_UNK2 = 0x04, - UNIT_BYTE2_FLAG_UNK3 = 0x08, - UNIT_BYTE2_FLAG_AURAS = 0x10, // show possitive auras as positive, and allow its dispel - UNIT_BYTE2_FLAG_UNK5 = 0x20, - UNIT_BYTE2_FLAG_UNK6 = 0x40, - UNIT_BYTE2_FLAG_UNK7 = 0x80 -}; - -// byte (2 from 0..3) of UNIT_FIELD_BYTES_2 -enum UnitRename -{ - UNIT_RENAME_NOT_ALLOWED = 0x02, - UNIT_RENAME_ALLOWED = 0x03 -}; - -#define CREATURE_MAX_SPELLS 4 - -enum Swing -{ - NOSWING = 0, - SINGLEHANDEDSWING = 1, - TWOHANDEDSWING = 2 -}; - -enum VictimState -{ - VICTIMSTATE_UNKNOWN1 = 0, - VICTIMSTATE_NORMAL = 1, - VICTIMSTATE_DODGE = 2, - VICTIMSTATE_PARRY = 3, - VICTIMSTATE_INTERRUPT = 4, - VICTIMSTATE_BLOCKS = 5, - VICTIMSTATE_EVADES = 6, - VICTIMSTATE_IS_IMMUNE = 7, - VICTIMSTATE_DEFLECTS = 8 -}; - -enum HitInfo -{ - HITINFO_NORMALSWING = 0x00000000, - HITINFO_UNK1 = 0x00000001, // req correct packet structure - HITINFO_NORMALSWING2 = 0x00000002, - HITINFO_LEFTSWING = 0x00000004, - HITINFO_MISS = 0x00000010, - HITINFO_ABSORB = 0x00000020, // plays absorb sound - HITINFO_RESIST = 0x00000040, // resisted at least some damage - HITINFO_CRITICALHIT = 0x00000080, - HITINFO_UNK2 = 0x00000100, // wotlk? - HITINFO_UNK3 = 0x00002000, // wotlk? - HITINFO_GLANCING = 0x00004000, - HITINFO_CRUSHING = 0x00008000, - HITINFO_NOACTION = 0x00010000, - HITINFO_SWINGNOHITSOUND = 0x00080000 -}; - -//i would like to remove this: (it is defined in item.h -enum InventorySlot -{ - NULL_BAG = 0, - NULL_SLOT = 255 -}; - -struct FactionTemplateEntry; -struct Modifier; -struct SpellEntry; -struct SpellEntryExt; - -class Aura; -class Creature; -class Spell; -class DynamicObject; -class GameObject; -class Item; -class Pet; -class Path; -class PetAura; - -struct SpellImmune -{ - uint32 type; - uint32 spellId; -}; - -typedef std::list<SpellImmune> SpellImmuneList; - -enum UnitModifierType -{ - BASE_VALUE = 0, - BASE_PCT = 1, - TOTAL_VALUE = 2, - TOTAL_PCT = 3, - MODIFIER_TYPE_END = 4 -}; - -enum WeaponDamageRange -{ - MINDAMAGE, - MAXDAMAGE -}; - -enum DamageTypeToSchool -{ - RESISTANCE, - DAMAGE_DEALT, - DAMAGE_TAKEN -}; - -enum AuraRemoveMode -{ - AURA_REMOVE_BY_DEFAULT, - AURA_REMOVE_BY_STACK, // at replace by semillar aura - AURA_REMOVE_BY_CANCEL, - AURA_REMOVE_BY_DISPEL, - AURA_REMOVE_BY_DEATH -}; - -enum UnitMods -{ - UNIT_MOD_STAT_STRENGTH, // UNIT_MOD_STAT_STRENGTH..UNIT_MOD_STAT_SPIRIT must be in existed order, it's accessed by index values of Stats enum. - UNIT_MOD_STAT_AGILITY, - UNIT_MOD_STAT_STAMINA, - UNIT_MOD_STAT_INTELLECT, - UNIT_MOD_STAT_SPIRIT, - UNIT_MOD_HEALTH, - UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_HAPPINESS must be in existed order, it's accessed by index values of Powers enum. - UNIT_MOD_RAGE, - UNIT_MOD_FOCUS, - UNIT_MOD_ENERGY, - UNIT_MOD_HAPPINESS, - UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum. - UNIT_MOD_RESISTANCE_HOLY, - UNIT_MOD_RESISTANCE_FIRE, - UNIT_MOD_RESISTANCE_NATURE, - UNIT_MOD_RESISTANCE_FROST, - UNIT_MOD_RESISTANCE_SHADOW, - UNIT_MOD_RESISTANCE_ARCANE, - UNIT_MOD_ATTACK_POWER, - UNIT_MOD_ATTACK_POWER_RANGED, - UNIT_MOD_DAMAGE_MAINHAND, - UNIT_MOD_DAMAGE_OFFHAND, - UNIT_MOD_DAMAGE_RANGED, - UNIT_MOD_END, - // synonyms - UNIT_MOD_STAT_START = UNIT_MOD_STAT_STRENGTH, - UNIT_MOD_STAT_END = UNIT_MOD_STAT_SPIRIT + 1, - UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR, - UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1, - UNIT_MOD_POWER_START = UNIT_MOD_MANA, - UNIT_MOD_POWER_END = UNIT_MOD_HAPPINESS + 1 -}; - -enum BaseModGroup -{ - CRIT_PERCENTAGE, - RANGED_CRIT_PERCENTAGE, - OFFHAND_CRIT_PERCENTAGE, - SHIELD_BLOCK_VALUE, - BASEMOD_END -}; - -enum BaseModType -{ - FLAT_MOD, - PCT_MOD -}; - -#define MOD_END (PCT_MOD+1) - -enum DeathState -{ - ALIVE = 0, - JUST_DIED = 1, - CORPSE = 2, - DEAD = 3, - JUST_ALIVED = 4 -}; - -enum UnitState -{ - UNIT_STAT_DIED = 0x0001, - UNIT_STAT_MELEE_ATTACKING = 0x0002, // player is melee attacking someone - //UNIT_STAT_MELEE_ATTACK_BY = 0x0004, // player is melee attack by someone - UNIT_STAT_STUNNED = 0x0008, - UNIT_STAT_ROAMING = 0x0010, - UNIT_STAT_CHASE = 0x0020, - UNIT_STAT_SEARCHING = 0x0040, - UNIT_STAT_FLEEING = 0x0080, - UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING), - UNIT_STAT_IN_FLIGHT = 0x0100, // player is in flight mode - UNIT_STAT_FOLLOW = 0x0200, - UNIT_STAT_ROOT = 0x0400, - UNIT_STAT_CONFUSED = 0x0800, - UNIT_STAT_DISTRACTED = 0x1000, - UNIT_STAT_ISOLATED = 0x2000, // area auras do not affect other players - UNIT_STAT_ATTACK_PLAYER = 0x4000, - UNIT_STAT_CASTING = 0x8000, - UNIT_STAT_ALL_STATE = 0xffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT) -}; - -enum UnitMoveType -{ - MOVE_WALK = 0, - MOVE_RUN = 1, - MOVE_WALKBACK = 2, - MOVE_SWIM = 3, - MOVE_SWIMBACK = 4, - MOVE_TURN = 5, - MOVE_FLY = 6, - MOVE_FLYBACK = 7 -}; - -#define MAX_MOVE_TYPE 8 - -extern float baseMoveSpeed[MAX_MOVE_TYPE]; - -enum WeaponAttackType -{ - BASE_ATTACK = 0, - OFF_ATTACK = 1, - RANGED_ATTACK = 2 -}; - -#define MAX_ATTACK 3 - -enum CombatRating -{ - CR_WEAPON_SKILL = 0, - CR_DEFENSE_SKILL = 1, - CR_DODGE = 2, - CR_PARRY = 3, - CR_BLOCK = 4, - CR_HIT_MELEE = 5, - CR_HIT_RANGED = 6, - CR_HIT_SPELL = 7, - CR_CRIT_MELEE = 8, - CR_CRIT_RANGED = 9, - CR_CRIT_SPELL = 10, - CR_HIT_TAKEN_MELEE = 11, - CR_HIT_TAKEN_RANGED = 12, - CR_HIT_TAKEN_SPELL = 13, - CR_CRIT_TAKEN_MELEE = 14, - CR_CRIT_TAKEN_RANGED = 15, - CR_CRIT_TAKEN_SPELL = 16, - CR_HASTE_MELEE = 17, - CR_HASTE_RANGED = 18, - CR_HASTE_SPELL = 19, - CR_WEAPON_SKILL_MAINHAND = 20, - CR_WEAPON_SKILL_OFFHAND = 21, - CR_WEAPON_SKILL_RANGED = 22, - CR_EXPERTISE = 23 -}; - -#define MAX_COMBAT_RATING 24 - -enum DamageEffectType -{ - DIRECT_DAMAGE = 0, // used for normal weapon damage (not for class abilities or spells) - SPELL_DIRECT_DAMAGE = 1, // spell/class abilities damage - DOT = 2, - HEAL = 3, - NODAMAGE = 4, // used also in case when damage applied to health but not applied to spell channelInterruptFlags/etc - SELF_DAMAGE = 5 -}; - -enum UnitVisibility -{ - VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other - VISIBILITY_ON = 1, - VISIBILITY_GROUP_STEALTH = 2, // detect chance, seen and can see group members - //VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit, set only if not stealthed, and in checks not used (mask used instead) - //VISIBILITY_GROUP_NO_DETECT = 4, // state just at stealth apply for update Grid state. Don't remove, otherwise stealth spells will break - VISIBILITY_RESPAWN = 5 // special totally not detectable visibility for force delete object at respawn command -}; - -// Value masks for UNIT_FIELD_FLAGS -enum UnitFlags -{ - UNIT_FLAG_UNKNOWN7 = 0x00000001, - UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable - UNIT_FLAG_DISABLE_MOVE = 0x00000004, - UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state - UNIT_FLAG_RENAME = 0x00000010, - UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP - UNIT_FLAG_UNKNOWN9 = 0x00000040, - UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE - UNIT_FLAG_UNKNOWN2 = 0x00000100, // 2.0.8 - UNIT_FLAG_UNKNOWN11 = 0x00000200, - UNIT_FLAG_LOOTING = 0x00000400, // loot animation - UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 - UNIT_FLAG_PVP = 0x00001000, - UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 - UNIT_FLAG_UNKNOWN4 = 0x00004000, // 2.0.8 - UNIT_FLAG_UNKNOWN13 = 0x00008000, - UNIT_FLAG_UNKNOWN14 = 0x00010000, - UNIT_FLAG_PACIFIED = 0x00020000, - UNIT_FLAG_DISABLE_ROTATE = 0x00040000, // stunned, 2.1.1 - UNIT_FLAG_IN_COMBAT = 0x00080000, - UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag - UNIT_FLAG_DISARMED = 0x00200000, // disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. - UNIT_FLAG_CONFUSED = 0x00400000, - UNIT_FLAG_FLEEING = 0x00800000, - UNIT_FLAG_UNKNOWN5 = 0x01000000, // used in spell Eyes of the Beast for pet... - UNIT_FLAG_NOT_SELECTABLE = 0x02000000, - UNIT_FLAG_SKINNABLE = 0x04000000, - UNIT_FLAG_MOUNT = 0x08000000, - UNIT_FLAG_UNKNOWN17 = 0x10000000, - UNIT_FLAG_UNKNOWN6 = 0x20000000, // used in Feing Death spell - UNIT_FLAG_SHEATHE = 0x40000000 -}; - -// Value masks for UNIT_FIELD_FLAGS_2 -enum UnitFlags2 -{ - UNIT_FLAG2_FEIGN_DEATH = 0x00000001, - UNIT_FLAG2_COMPREHEND_LANG= 0x00000008, - UNIT_FLAG2_FORCE_MOVE = 0x00000040 -}; - -/// Non Player Character flags -enum NPCFlags -{ - UNIT_NPC_FLAG_NONE = 0x00000000, - UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100% - UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // guessed, probably ok - UNIT_NPC_FLAG_UNK1 = 0x00000004, - UNIT_NPC_FLAG_UNK2 = 0x00000008, - UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100% - UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // 100% - UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // 100% - UNIT_NPC_FLAG_VENDOR = 0x00000080, // 100% - UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // 100%, general goods vendor - UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // 100% - UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // guessed - UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // 100% - UNIT_NPC_FLAG_REPAIR = 0x00001000, // 100% - UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // 100% - UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // guessed - UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // guessed - UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // 100% - UNIT_NPC_FLAG_BANKER = 0x00020000, // 100% - UNIT_NPC_FLAG_PETITIONER = 0x00040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions - UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // 100% - UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // 100% - UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100% - UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100% - UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode - UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click) - UNIT_NPC_FLAG_GUARD = 0x10000000, // custom flag for guards - UNIT_NPC_FLAG_OUTDOORPVP = 0x20000000, // custom flag for outdoor pvp creatures -}; - -enum MovementFlags -{ - MOVEMENTFLAG_NONE = 0x00000000, - MOVEMENTFLAG_FORWARD = 0x00000001, - MOVEMENTFLAG_BACKWARD = 0x00000002, - MOVEMENTFLAG_STRAFE_LEFT = 0x00000004, - MOVEMENTFLAG_STRAFE_RIGHT = 0x00000008, - MOVEMENTFLAG_LEFT = 0x00000010, - MOVEMENTFLAG_RIGHT = 0x00000020, - MOVEMENTFLAG_PITCH_UP = 0x00000040, - MOVEMENTFLAG_PITCH_DOWN = 0x00000080, - MOVEMENTFLAG_WALK_MODE = 0x00000100, // Walking - MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures - MOVEMENTFLAG_LEVITATING = 0x00000400, - MOVEMENTFLAG_FLY_UNK1 = 0x00000800, - MOVEMENTFLAG_JUMPING = 0x00001000, - MOVEMENTFLAG_UNK4 = 0x00002000, - MOVEMENTFLAG_FALLING = 0x00004000, - // 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000 - MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also - MOVEMENTFLAG_FLY_UP = 0x00400000, - MOVEMENTFLAG_CAN_FLY = 0x00800000, - MOVEMENTFLAG_FLYING = 0x01000000, - MOVEMENTFLAG_FLYING2 = 0x02000000, // Actual flying mode - MOVEMENTFLAG_SPLINE = 0x04000000, // used for flight paths - MOVEMENTFLAG_SPLINE2 = 0x08000000, // used for flight paths - MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water - MOVEMENTFLAG_SAFE_FALL = 0x20000000, // active rogue safe fall spell (passive) - MOVEMENTFLAG_UNK3 = 0x40000000 -}; - -enum DiminishingLevels -{ - DIMINISHING_LEVEL_1 = 0, - DIMINISHING_LEVEL_2 = 1, - DIMINISHING_LEVEL_3 = 2, - DIMINISHING_LEVEL_IMMUNE = 3 -}; - -struct DiminishingReturn -{ - DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count) : DRGroup(group), hitTime(t), hitCount(count), stack(0) {} - - DiminishingGroup DRGroup:16; - uint16 stack:16; - uint32 hitTime; - uint32 hitCount; -}; - -enum MeleeHitOutcome -{ - MELEE_HIT_EVADE, MELEE_HIT_MISS, MELEE_HIT_DODGE, MELEE_HIT_BLOCK, MELEE_HIT_PARRY, - MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL, MELEE_HIT_BLOCK_CRIT -}; -struct CleanDamage -{ - CleanDamage(uint32 _damage, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) : - damage(_damage), attackType(_attackType), hitOutCome(_hitOutCome) {} - - uint32 damage; - WeaponAttackType attackType; - MeleeHitOutcome hitOutCome; -}; - -struct UnitActionBarEntry -{ - uint32 Type; - uint32 SpellOrAction; -}; - -#define MAX_DECLINED_NAME_CASES 5 - -struct DeclinedName -{ - std::string name[MAX_DECLINED_NAME_CASES]; -}; - -enum CurrentSpellTypes -{ - CURRENT_MELEE_SPELL = 0, - CURRENT_FIRST_NON_MELEE_SPELL = 1, // just counter - CURRENT_GENERIC_SPELL = 1, - CURRENT_AUTOREPEAT_SPELL = 2, - CURRENT_CHANNELED_SPELL = 3, - CURRENT_MAX_SPELL = 4 // just counter -}; - -enum ActiveStates -{ - ACT_ENABLED = 0xC100, - ACT_DISABLED = 0x8100, - ACT_COMMAND = 0x0700, - ACT_REACTION = 0x0600, - ACT_CAST = 0x0100, - ACT_PASSIVE = 0x0000, - ACT_DECIDE = 0x0001 -}; - -enum ReactStates -{ - REACT_PASSIVE = 0, - REACT_DEFENSIVE = 1, - REACT_AGGRESSIVE = 2 -}; - -enum CommandStates -{ - COMMAND_STAY = 0, - COMMAND_FOLLOW = 1, - COMMAND_ATTACK = 2, - COMMAND_ABANDON = 3 -}; - -struct CharmSpellEntry -{ - uint16 spellId; - uint16 active; -}; - -typedef std::list<Player*> SharedVisionList; - -struct CharmInfo -{ - public: - explicit CharmInfo(Unit* unit); - uint32 GetPetNumber() const { return m_petnumber; } - void SetPetNumber(uint32 petnumber, bool statwindow); - - void SetCommandState(CommandStates st) { m_CommandState = st; } - CommandStates GetCommandState() { return m_CommandState; } - bool HasCommandState(CommandStates state) { return (m_CommandState == state); } - void SetReactState(ReactStates st) { m_reactState = st; } - ReactStates GetReactState() { return m_reactState; } - bool HasReactState(ReactStates state) { return (m_reactState == state); } - - void InitPossessCreateSpells(); - void InitCharmCreateSpells(); - void InitPetActionBar(); - void InitEmptyActionBar(); - //return true if successful - bool AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate = ACT_DECIDE); - void ToggleCreatureAutocast(uint32 spellid, bool apply); - - UnitActionBarEntry* GetActionBarEntry(uint8 index) { return &(PetActionBar[index]); } - CharmSpellEntry* GetCharmSpell(uint8 index) { return &(m_charmspells[index]); } - private: - Unit* m_unit; - UnitActionBarEntry PetActionBar[10]; - CharmSpellEntry m_charmspells[4]; - CommandStates m_CommandState; - ReactStates m_reactState; - uint32 m_petnumber; -}; - -// for clearing special attacks -#define REACTIVE_TIMER_START 4000 - -enum ReactiveType -{ - REACTIVE_DEFENSE = 1, - REACTIVE_HUNTER_PARRY = 2, - REACTIVE_CRIT = 3, - REACTIVE_HUNTER_CRIT = 4, - REACTIVE_OVERPOWER = 5 -}; - -#define MAX_REACTIVE 6 -#define MAX_TOTEM 4 - -// delay time next attack to prevent client attack animation problems -#define ATTACK_DISPLAY_DELAY 200 - -class TRINITY_DLL_SPEC Unit : public WorldObject -{ - public: - typedef std::set<Unit*> AttackerSet; - typedef std::pair<uint32, uint8> spellEffectPair; - typedef std::multimap< spellEffectPair, Aura*> AuraMap; - typedef std::list<Aura *> AuraList; - typedef std::list<DiminishingReturn> Diminishing; - typedef std::set<AuraType> AuraTypeSet; - typedef std::set<uint32> ComboPointHolderSet; - - virtual ~Unit ( ); - - void AddToWorld(); - void RemoveFromWorld(); - - void CleanupsBeforeDelete(); // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) - - DiminishingLevels GetDiminishing(DiminishingGroup group); - void IncrDiminishing(DiminishingGroup group); - void ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster, DiminishingLevels Level); - void ApplyDiminishingAura(DiminishingGroup group, bool apply); - void ClearDiminishings() { m_Diminishing.clear(); } - - virtual void Update( uint32 time ); - - void setAttackTimer(WeaponAttackType type, uint32 time) { m_attackTimer[type] = time; } - void resetAttackTimer(WeaponAttackType type = BASE_ATTACK); - uint32 getAttackTimer(WeaponAttackType type) const { return m_attackTimer[type]; } - bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const { return m_attackTimer[type] == 0; } - bool haveOffhandWeapon() const; - bool CanDualWield() const { return m_canDualWield; } - void SetCanDualWield(bool value) { m_canDualWield = value; } - bool canReachWithAttack(Unit *pVictim) const; - float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; } - bool IsWithinCombatDist(Unit *obj, float dist2compare) const; - void GetRandomContactPoint( const Unit* target, float &x, float &y, float &z, float distance2dMin, float distance2dMax ) const; - uint32 m_extraAttacks; - bool m_canDualWield; - - void _addAttacker(Unit *pAttacker) // must be called only from Unit::Attack(Unit*) - { - AttackerSet::iterator itr = m_attackers.find(pAttacker); - if(itr == m_attackers.end()) - m_attackers.insert(pAttacker); - } - void _removeAttacker(Unit *pAttacker) // must be called only from Unit::AttackStop() - { - AttackerSet::iterator itr = m_attackers.find(pAttacker); - if(itr != m_attackers.end()) - m_attackers.erase(itr); - } - Unit * getAttackerForHelper() // If someone wants to help, who to give them - { - if (getVictim() != NULL) - return getVictim(); - - if (!m_attackers.empty()) - return *(m_attackers.begin()); - - return NULL; - } - bool Attack(Unit *victim, bool meleeAttack); - void CastStop(uint32 except_spellid = 0); - bool AttackStop(); - void RemoveAllAttackers(); - AttackerSet const& getAttackers() const { return m_attackers; } - bool isAttackingPlayer() const; - Unit* getVictim() const { return m_attacking; } - void CombatStop(bool cast = false); - void CombatStopWithPets(bool cast = false); - Unit* SelectNearbyTarget() const; - - void addUnitState(uint32 f) { m_state |= f; } - bool hasUnitState(const uint32 f) const { return (m_state & f); } - void clearUnitState(uint32 f) { m_state &= ~f; } - bool CanFreeMove() const - { - return !hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_IN_FLIGHT | - UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED ) && GetOwnerGUID()==0; - } - - uint32 getLevel() const { return GetUInt32Value(UNIT_FIELD_LEVEL); } - virtual uint32 getLevelForTarget(Unit const* /*target*/) const { return getLevel(); } - void SetLevel(uint32 lvl); - uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, 0); } - uint32 getRaceMask() const { return 1 << (getRace()-1); } - uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); } - uint32 getClassMask() const { return 1 << (getClass()-1); } - uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); } - - float GetStat(Stats stat) const { return float(GetUInt32Value(UNIT_FIELD_STAT0+stat)); } - void SetStat(Stats stat, int32 val) { SetStatInt32Value(UNIT_FIELD_STAT0+stat, val); } - uint32 GetArmor() const { return GetResistance(SPELL_SCHOOL_NORMAL) ; } - void SetArmor(int32 val) { SetResistance(SPELL_SCHOOL_NORMAL, val); } - - uint32 GetResistance(SpellSchools school) const { return GetUInt32Value(UNIT_FIELD_RESISTANCES+school); } - void SetResistance(SpellSchools school, int32 val) { SetStatInt32Value(UNIT_FIELD_RESISTANCES+school,val); } - - uint32 GetHealth() const { return GetUInt32Value(UNIT_FIELD_HEALTH); } - uint32 GetMaxHealth() const { return GetUInt32Value(UNIT_FIELD_MAXHEALTH); } - void SetHealth( uint32 val); - void SetMaxHealth(uint32 val); - int32 ModifyHealth(int32 val); - - Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); } - void setPowerType(Powers power); - uint32 GetPower( Powers power) const { return GetUInt32Value(UNIT_FIELD_POWER1 +power); } - uint32 GetMaxPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_MAXPOWER1+power); } - void SetPower( Powers power, uint32 val); - void SetMaxPower(Powers power, uint32 val); - int32 ModifyPower(Powers power, int32 val); - void ApplyPowerMod(Powers power, uint32 val, bool apply); - void ApplyMaxPowerMod(Powers power, uint32 val, bool apply); - - uint32 GetAttackTime(WeaponAttackType att) const { return (uint32)(GetFloatValue(UNIT_FIELD_BASEATTACKTIME+att)/m_modAttackSpeedPct[att]); } - void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME+att,val*m_modAttackSpeedPct[att]); } - void ApplyAttackTimePercentMod(WeaponAttackType att,float val, bool apply); - void ApplyCastTimePercentMod(float val, bool apply); - - // faction template id - uint32 getFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); } - void setFaction(uint32 faction) { SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction ); } - FactionTemplateEntry const* getFactionTemplateEntry() const; - bool IsHostileTo(Unit const* unit) const; - bool IsHostileToPlayers() const; - bool IsFriendlyTo(Unit const* unit) const; - bool IsNeutralToAll() const; - bool IsContestedGuard() const - { - if(FactionTemplateEntry const* entry = getFactionTemplateEntry()) - return entry->IsContestedGuardFaction(); - - return false; - } - bool IsPvP() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); } - void SetPvP(bool state) { if(state) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); else RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); } - uint32 GetCreatureType() const; - uint32 GetCreatureTypeMask() const - { - uint32 creatureType = GetCreatureType(); - return (creatureType >= 1) ? (1 << (creatureType - 1)) : 0; - } - - uint8 getStandState() const { return GetByteValue(UNIT_FIELD_BYTES_1, 0); } - bool IsSitState() const; - bool IsStandState() const; - void SetStandState(uint8 state); - - bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); } - uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); } - void Mount(uint32 mount); - void Unmount(); - - uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } - void RemoveSpellbyDamageTaken(uint32 damage, uint32 spell); - uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss); - void DealFlatDamage(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit = false, bool isTriggeredSpell = false); - void DoAttackDamage(Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false); - - void CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchoolMask damageSchoolMask, WeaponAttackType attType, MeleeHitOutcome outcome, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false); - void ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 damage = 0, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NONE, SpellEntry const *procSpell = NULL, bool isTriggeredSpell = false, WeaponAttackType attType = BASE_ATTACK); - void HandleEmoteCommand(uint32 anim_id); - void AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType = BASE_ATTACK, bool extra = false ); - - float MeleeMissChanceCalc(const Unit *pVictim, WeaponAttackType attType) const; - SpellMissInfo MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell); - SpellMissInfo SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool canReflect = false); - - float GetUnitDodgeChance() const; - float GetUnitParryChance() const; - float GetUnitBlockChance() const; - float GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const; - - virtual uint32 GetShieldBlockValue() const =0; - uint32 GetUnitMeleeSkill(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } - uint32 GetDefenseSkillValue(Unit const* target = NULL) const; - uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target = NULL) const; - float GetWeaponProcChance() const; - float GetPPMProcChance(uint32 WeaponSpeed, float PPM) const; - MeleeHitOutcome RollPhysicalOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo); - MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType) const; - MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const; - - bool isVendor() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR ); } - bool isTrainer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER ); } - bool isQuestGiver() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER ); } - bool isGossip() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP ); } - bool isTaxi() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER ); } - bool isGuildMaster() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER ); } - bool isBattleMaster() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER ); } - bool isBanker() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER ); } - bool isInnkeeper() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER ); } - bool isSpiritHealer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER ); } - bool isSpiritGuide() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE ); } - bool isTabardDesigner()const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER ); } - bool isAuctioner() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER ); } - bool isArmorer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR ); } - bool isServiceProvider() const - { - return HasFlag( UNIT_NPC_FLAGS, - UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_FLIGHTMASTER | - UNIT_NPC_FLAG_PETITIONER | UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER | - UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_GUARD | UNIT_NPC_FLAG_SPIRITHEALER | - UNIT_NPC_FLAG_SPIRITGUIDE | UNIT_NPC_FLAG_TABARDDESIGNER | UNIT_NPC_FLAG_AUCTIONEER ); - } - bool isSpiritService() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE ); } - - //Need fix or use this - bool isGuard() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GUARD); } - - bool isInFlight() const { return hasUnitState(UNIT_STAT_IN_FLIGHT); } - - bool isInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); } - void CombatStart(Unit* target); - void SetInCombatState(bool PvP); - void SetInCombatWith(Unit* enemy); - void ClearInCombat(); - uint32 GetCombatTimer() const { return m_CombatTimer; } - - bool HasAuraType(AuraType auraType) const; - bool HasAura(uint32 spellId, uint32 effIndex) const - { return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end(); } - - bool virtual HasSpell(uint32 /*spellID*/) const { return false; } - - bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); } - bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); } - bool isFeared() const { return HasAuraType(SPELL_AURA_MOD_FEAR); } - bool isInRoots() const { return HasAuraType(SPELL_AURA_MOD_ROOT); } - bool IsPolymorphed() const; - - bool isFrozen() const; - - bool isTargetableForAttack() const; - bool isAttackableByAOE() const; - bool canAttack(Unit const* target) const; - virtual bool IsInWater() const; - virtual bool IsUnderWater() const; - bool isInAccessiblePlaceFor(Creature const* c) const; - - void SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool critical = false); - void SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage,Powers powertype, bool critical = false); - uint32 SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell = false, bool useSpellDamage = true); - void CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem= NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem= NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastCustomSpell(Unit* Victim,SpellEntry const *spellInfo, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem= NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0); - void CastSpell(float x, float y, float z, SpellEntry const *spellInfo, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0); - - bool IsDamageToThreatSpell(SpellEntry const * spellInfo) const; - - void DeMorph(); - - void SendAttackStart(Unit* pVictim); - void SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount); - void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); - void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo); - - void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); - void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags); - void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 MovementFlags, uint32 transitTime = 0, Player* player = NULL); - void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL); - - virtual void MoveOutOfRange(Player &) { }; - - bool isAlive() const { return (m_deathState == ALIVE); }; - bool isDead() const { return ( m_deathState == DEAD || m_deathState == CORPSE ); }; - DeathState getDeathState() { return m_deathState; }; - virtual void setDeathState(DeathState s); // overwrited in Creature/Player/Pet - - uint64 const& GetOwnerGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMONEDBY); } - uint64 GetPetGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMON); } - uint64 GetCharmerGUID() const { return GetUInt64Value(UNIT_FIELD_CHARMEDBY); } - uint64 GetCharmGUID() const { return GetUInt64Value(UNIT_FIELD_CHARM); } - void SetCharmerGUID(uint64 owner) { SetUInt64Value(UNIT_FIELD_CHARMEDBY, owner); } - - uint64 GetCharmerOrOwnerGUID() const { return GetCharmerGUID() ? GetCharmerGUID() : GetOwnerGUID(); } - uint64 GetCharmerOrOwnerOrOwnGUID() const - { - if(uint64 guid = GetCharmerOrOwnerGUID()) - return guid; - return GetGUID(); - } - bool isCharmedOwnedByPlayerOrPlayer() const { return IS_PLAYER_GUID(GetCharmerOrOwnerOrOwnGUID()); } - - Player* GetSpellModOwner(); - - Unit* GetOwner() const; - Pet* GetPet() const; - Unit* GetCharmer() const; - Unit* GetCharm() const; - Unit* GetCharmerOrOwner() const { return GetCharmerGUID() ? GetCharmer() : GetOwner(); } - Unit* GetCharmerOrOwnerOrSelf() - { - if(Unit* u = GetCharmerOrOwner()) - return u; - - return this; - } - Player* GetCharmerOrOwnerPlayerOrPlayerItself(); - - void SetPet(Pet* pet); - void SetCharm(Unit* pet); - void SetPossessedTarget(Unit* target) - { - if (!target) return; - SetCharm(target); - target->SetCharmerGUID(GetGUID()); - target->m_isPossessed = true; - } - void RemovePossessedTarget() - { - if (!GetCharm()) return; - GetCharm()->SetCharmerGUID(0); - GetCharm()->m_isPossessed = false; - SetCharm(0); - } - - bool isCharmed() const { return GetCharmerGUID() != 0; } - bool isPossessed() const { return m_isPossessed; } - bool isPossessedByPlayer() const { return m_isPossessed && IS_PLAYER_GUID(GetCharmerGUID()); } - bool isPossessing() const { return GetCharm() && GetCharm()->isPossessed(); } - bool isPossessing(Unit* u) const { return u->isPossessed() && GetCharmGUID() == u->GetGUID(); } - bool isPossessingCreature() const { return isPossessing() && IS_CREATURE_GUID(GetCharmGUID()); } - - CharmInfo* GetCharmInfo() { return m_charmInfo; } - CharmInfo* InitCharmInfo(Unit* charm); - SharedVisionList const& GetSharedVisionList() { return m_sharedVision; } - void AddPlayerToVision(Player* plr); - void RemovePlayerFromVision(Player* plr); - void RemoveAllFromVision(); - void UncharmSelf(); - void UnpossessSelf(bool attack); - - Pet* CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id = 0); - - bool AddAura(Aura *aur); - - void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); - void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL); - void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex); - void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL); - void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId); - void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler); - void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer); - void RemoveAurasDueToSpellByCancel(uint32 spellId); - void RemoveNotOwnSingleTargetAuras(); - - void RemoveSpellsCausingAura(AuraType auraType); - void RemoveRankAurasDueToSpell(uint32 spellId); - bool RemoveNoStackAurasDueToAura(Aura *Aur); - void RemoveAurasWithInterruptFlags(uint32 flags); - void RemoveAurasWithDispelType( DispelType type ); - - void RemoveAllAuras(); - void RemoveArenaAuras(bool onleave = false); - void RemoveAllAurasOnDeath(); - void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime); - - float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); } - void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); } - void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModSignedFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } - void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } - void InitStatBuffMods() - { - for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_POSSTAT0+i, 0); - for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_NEGSTAT0+i, 0); - } - void ApplyStatBuffMod(Stats stat, float val, bool apply) { ApplyModSignedFloatValue((val > 0 ? UNIT_FIELD_POSSTAT0+stat : UNIT_FIELD_NEGSTAT0+stat), val, apply); } - void ApplyStatPercentBuffMod(Stats stat, float val, bool apply) - { - ApplyPercentModFloatValue(UNIT_FIELD_POSSTAT0+stat, val, apply); - ApplyPercentModFloatValue(UNIT_FIELD_NEGSTAT0+stat, val, apply); - } - void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; } - void SetCreateHealth(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_HEALTH, val); } - uint32 GetCreateHealth() const { return GetUInt32Value(UNIT_FIELD_BASE_HEALTH); } - void SetCreateMana(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_MANA, val); } - uint32 GetCreateMana() const { return GetUInt32Value(UNIT_FIELD_BASE_MANA); } - uint32 GetCreatePowers(Powers power) const; - float GetPosStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_POSSTAT0+stat); } - float GetNegStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_NEGSTAT0+stat); } - float GetCreateStat(Stats stat) const { return m_createStats[stat]; } - - void SetCurrentCastedSpell(Spell * pSpell); - virtual void ProhibitSpellScholl(SpellSchoolMask /*idSchoolMask*/, uint32 /*unTimeMs*/ ) { } - void InterruptSpell(uint32 spellType, bool withDelayed = true); - - // set withDelayed to true to account delayed spells as casted - // delayed+channeled spells are always accounted as casted - // we can skip channeled or delayed checks using flags - bool IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled = false, bool skipAutorepeat = false) const; - - // set withDelayed to true to interrupt delayed spells too - // delayed+channeled spells are always interrupted - void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0); - - Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; - - Spell* m_currentSpells[CURRENT_MAX_SPELL]; - - uint32 m_addDmgOnce; - uint64 m_TotemSlot[MAX_TOTEM]; - uint64 m_ObjectSlot[4]; - uint32 m_detectInvisibilityMask; - uint32 m_invisibilityMask; - uint32 m_ShapeShiftFormSpellId; - ShapeshiftForm m_form; - float m_modMeleeHitChance; - float m_modRangedHitChance; - float m_modSpellHitChance; - int32 m_baseSpellCritChance; - - float m_threatModifier[MAX_SPELL_SCHOOL]; - float m_modAttackSpeedPct[3]; - - // Event handler - EventProcessor m_Events; - - // stat system - bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply); - void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; } - float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const; - float GetTotalStatValue(Stats stat) const; - float GetTotalAuraModValue(UnitMods unitMod) const; - SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const; - Stats GetStatByAuraGroup(UnitMods unitMod) const; - Powers GetPowerTypeByAuraGroup(UnitMods unitMod) const; - bool CanModifyStats() const { return m_canModifyStats; } - void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; } - virtual bool UpdateStats(Stats stat) = 0; - virtual bool UpdateAllStats() = 0; - virtual void UpdateResistances(uint32 school) = 0; - virtual void UpdateArmor() = 0; - virtual void UpdateMaxHealth() = 0; - virtual void UpdateMaxPower(Powers power) = 0; - virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0; - virtual void UpdateDamagePhysical(WeaponAttackType attType) = 0; - float GetTotalAttackPowerValue(WeaponAttackType attType) const; - float GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const; - void SetBaseWeaponDamage(WeaponAttackType attType ,WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } - - bool isInFront(Unit const* target,float distance, float arc = M_PI) const; - void SetInFront(Unit const* target); - bool isInBack(Unit const* target, float distance, float arc = M_PI) const; - bool isInLine(Unit const* target, float distance) const; - - // Visibility system - UnitVisibility GetVisibility() const { return m_Visibility; } - void SetVisibility(UnitVisibility x); - - // common function for visibility checks for player/creatures with detection code - virtual bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const; - bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false) const; - bool canDetectInvisibilityOf(Unit const* u) const; - bool canDetectStealthOf(Unit const* u, float distance) const; - - // virtual functions for all world objects types - bool isVisibleForInState(Player const* u, bool inVisibleList) const; - // function for low level grid visibility checks in player/creature cases - virtual bool IsVisibleInGridForPlayer(Player const* pl) const = 0; - - bool waterbreath; - AuraList & GetSingleCastAuras() { return m_scAuras; } - AuraList const& GetSingleCastAuras() const { return m_scAuras; } - SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; - - // Threat related methodes - bool CanHaveThreatList() const; - void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); - float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); - void DeleteThreatList(); - bool SelectHostilTarget(); - void TauntApply(Unit* pVictim); - void TauntFadeOut(Unit *taunter); - ThreatManager& getThreatManager() { return m_ThreatManager; } - void addHatedBy(HostilReference* pHostilReference) { m_HostilRefManager.insertFirst(pHostilReference); }; - void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ } - HostilRefManager& getHostilRefManager() { return m_HostilRefManager; } - - Aura* GetAura(uint32 spellId, uint32 effindex); - AuraMap & GetAuras() { return m_Auras; } - AuraMap const& GetAuras() const { return m_Auras; } - AuraList const& GetAurasByType(AuraType type) const { return m_modAuras[type]; } - void ApplyAuraProcTriggerDamage(Aura* aura, bool apply); - - int32 GetTotalAuraModifier(AuraType auratype) const; - float GetTotalAuraMultiplier(AuraType auratype) const; - int32 GetMaxPositiveAuraModifier(AuraType auratype) const; - int32 GetMaxNegativeAuraModifier(AuraType auratype) const; - - int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; - float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const; - int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; - int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const; - - int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; - float GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const; - int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; - int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const; - - Aura* GetDummyAura(uint32 spell_id) const; - uint32 GetInterruptMask() const { return m_interruptMask; } - void AddInterruptMask(uint32 mask) { m_interruptMask |= mask; } - void UpdateInterruptMask(); - - uint32 GetDisplayId() { return GetUInt32Value(UNIT_FIELD_DISPLAYID); } - void SetDisplayId(uint32 modelId); - uint32 GetNativeDisplayId() { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); } - void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); } - void setTransForm(uint32 spellid) { m_transform = spellid;} - uint32 getTransForm() const { return m_transform;} - void AddDynObject(DynamicObject* dynObj); - void RemoveDynObject(uint32 spellid); - void RemoveDynObjectWithGUID(uint64 guid) { m_dynObjGUIDs.remove(guid); } - void RemoveAllDynObjects(); - void AddGameObject(GameObject* gameObj); - void RemoveGameObject(GameObject* gameObj, bool del); - void RemoveGameObject(uint32 spellid, bool del); - void RemoveAllGameObjects(); - DynamicObject *GetDynObject(uint32 spellId, uint32 effIndex); - DynamicObject *GetDynObject(uint32 spellId); - uint32 CalculateDamage(WeaponAttackType attType, bool normalized); - float GetAPMultiplier(WeaponAttackType attType, bool normalized); - void ModifyAuraState(AuraState flag, bool apply); - bool HasAuraState(AuraState flag) const { return HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); } - void UnsummonAllTotems(); - int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask); - int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask); - int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); - int32 SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); - uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype); - uint32 SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim); - bool isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType); - uint32 SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim); - - void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; } - bool IsUnderLastManaUseEffect() const; - - void SetContestedPvP(Player *attackedPlayer = NULL); - - void MeleeDamageBonus(Unit *pVictim, uint32 *damage, WeaponAttackType attType, SpellEntry const *spellProto = NULL); - uint32 GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime ); - - void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); - void ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType type, bool apply); - virtual bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false); - // redefined in Creature - bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask, bool useCharges = false); - virtual bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const; - // redefined in Creature - - uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage); - void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist); - - void UpdateSpeed(UnitMoveType mtype, bool forced); - float GetSpeed( UnitMoveType mtype ) const; - float GetSpeedRate( UnitMoveType mtype ) const { return m_speed_rate[mtype]; } - void SetSpeed(UnitMoveType mtype, float rate, bool forced = false); - - void SetHover(bool on); - bool isHover() const { return HasAuraType(SPELL_AURA_HOVER); } - - void _RemoveAllAuraMods(); - void _ApplyAllAuraMods(); - - int32 CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 basePoints, Unit const* target); - int32 CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target); - float CalculateLevelPenalty(SpellEntry const* spellProto) const; - - void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); } - void removeFollower(FollowerReference* /*pRef*/ ) { /* nothing to do yet */ } - static Unit* GetUnit(WorldObject& object, uint64 guid); - - MotionMaster* GetMotionMaster() { return &i_motionMaster; } - - bool IsStopped() const { return !(hasUnitState(UNIT_STAT_MOVING)); } - void StopMoving(); - - void AddUnitMovementFlag(uint32 f) { m_unit_movement_flags |= f; } - void RemoveUnitMovementFlag(uint32 f) - { - uint32 oldval = m_unit_movement_flags; - m_unit_movement_flags = oldval & ~f; - } - uint32 HasUnitMovementFlag(uint32 f) const { return m_unit_movement_flags & f; } - uint32 GetUnitMovementFlags() const { return m_unit_movement_flags; } - void SetUnitMovementFlags(uint32 f) { m_unit_movement_flags = f; } - - void SetFeared(bool apply, uint64 casterGUID = 0, uint32 spellID = 0); - void SetConfused(bool apply, uint64 casterGUID = 0, uint32 spellID = 0); - - void AddComboPointHolder(uint32 lowguid) { m_ComboPointHolders.insert(lowguid); } - void RemoveComboPointHolder(uint32 lowguid) { m_ComboPointHolders.erase(lowguid); } - void ClearComboPointHolders(); - - ///----------Pet responses methods----------------- - void SendPetCastFail(uint32 spellid, uint8 msg); - void SendPetActionFeedback (uint8 msg); - void SendPetTalk (uint32 pettalk); - void SendPetSpellCooldown (uint32 spellid, time_t cooltime); - void SendPetClearCooldown (uint32 spellid); - void SendPetAIReaction(uint64 guid); - ///----------End of Pet responses methods---------- - - void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); } - - // reactive attacks - void ClearAllReactives(); - void StartReactiveTimer( ReactiveType reactive ) { m_reactiveTimer[reactive] = REACTIVE_TIMER_START;} - void UpdateReactives(uint32 p_time); - - // group updates - void UpdateAuraForGroup(uint8 slot); - - // pet auras - typedef std::set<PetAura const*> PetAuraSet; - PetAuraSet m_petAuras; - void AddPetAura(PetAura const* petSpell); - void RemovePetAura(PetAura const* petSpell); - - protected: - explicit Unit (); - - void _UpdateSpells(uint32 time); - - void _UpdateAutoRepeatSpell(); - bool m_AutoRepeatFirstCast; - - uint32 m_attackTimer[MAX_ATTACK]; - - float m_createStats[MAX_STATS]; - - AttackerSet m_attackers; - Unit* m_attacking; - - DeathState m_deathState; - - AuraMap m_Auras; - - std::list<Aura *> m_scAuras; // casted singlecast auras - - typedef std::list<uint64> DynObjectGUIDs; - DynObjectGUIDs m_dynObjGUIDs; - - std::list<GameObject*> m_gameObj; - bool m_isSorted; - uint32 m_transform; - uint32 m_removedAuras; - - AuraList m_modAuras[TOTAL_AURAS]; - uint32 m_interruptMask; - AuraList m_interruptableAuras; - AuraList m_ccAuras; - float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; - float m_weaponDamage[MAX_ATTACK][2]; - bool m_canModifyStats; - //std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem - - float m_speed_rate[MAX_MOVE_TYPE]; - - CharmInfo *m_charmInfo; - bool m_isPossessed; - SharedVisionList m_sharedVision; - - virtual SpellSchoolMask GetMeleeDamageSchoolMask() const; - - MotionMaster i_motionMaster; - uint32 m_unit_movement_flags; - - uint32 m_reactiveTimer[MAX_REACTIVE]; - - private: - void SendAttackStop(Unit* victim); // only from AttackStop(Unit*) - //void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*) - - void ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, AuraTypeSet const& procAuraTypes, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage, SpellSchoolMask damageSchoolMask ); - bool HandleDummyAuraProc(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag,uint32 cooldown); - bool HandleProcTriggerSpell(Unit *pVictim,uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags,WeaponAttackType attType,uint32 cooldown); - bool HandleHasteAuraProc(Unit *pVictim, SpellEntry const *spellProto, uint32 effIndex, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag,uint32 cooldown); - bool HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell,uint32 cooldown); - - uint32 m_state; // Even derived shouldn't modify - uint32 m_CombatTimer; - uint32 m_lastManaUse; // msecs - - UnitVisibility m_Visibility; - - Diminishing m_Diminishing; - // Manage all Units threatening us - ThreatManager m_ThreatManager; - // Manage all Units that are threatened by us - HostilRefManager m_HostilRefManager; - - FollowerRefManager m_FollowingRefManager; - - ComboPointHolderSet m_ComboPointHolders; -}; -#endif +/*
+ * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
+ *
+ * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __UNIT_H
+#define __UNIT_H
+
+#include "Common.h"
+#include "Object.h"
+#include "Opcodes.h"
+#include "Mthread.h"
+#include "SpellAuraDefines.h"
+#include "UpdateFields.h"
+#include "SharedDefines.h"
+#include "ThreatManager.h"
+#include "HostilRefManager.h"
+#include "FollowerReference.h"
+#include "FollowerRefManager.h"
+#include "Utilities/EventProcessor.h"
+#include "MotionMaster.h"
+#include "Database/DBCStructure.h"
+#include <list>
+
+enum SpellInterruptFlags
+{
+ SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant?
+ SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back
+ SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, // interrupt
+ SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, // no
+ SPELL_INTERRUPT_FLAG_DAMAGE = 0x10 // _complete_ interrupt on direct damage?
+};
+
+enum SpellChannelInterruptFlags
+{
+ CHANNEL_FLAG_DAMAGE = 0x0002,
+ CHANNEL_FLAG_MOVEMENT = 0x0008,
+ CHANNEL_FLAG_TURNING = 0x0010,
+ CHANNEL_FLAG_DAMAGE2 = 0x0080,
+ CHANNEL_FLAG_DELAY = 0x4000
+};
+
+enum SpellAuraInterruptFlags
+{
+ AURA_INTERRUPT_FLAG_HITBYSPELL = 0x00000001, // 0 removed when getting hit by a negative spell?
+ AURA_INTERRUPT_FLAG_DAMAGE = 0x00000002, // 1 removed by any damage
+ AURA_INTERRUPT_FLAG_CC = 0x00000004, // 2 crowd control
+ AURA_INTERRUPT_FLAG_MOVE = 0x00000008, // 3 removed by any movement
+ AURA_INTERRUPT_FLAG_TURNING = 0x00000010, // 4 removed by any turning
+ AURA_INTERRUPT_FLAG_JUMP = 0x00000020, // 5 removed by entering combat
+ AURA_INTERRUPT_FLAG_NOT_MOUNTED = 0x00000040, // 6 removed by unmounting
+ AURA_INTERRUPT_FLAG_NOT_ABOVEWATER = 0x00000080, // 7 removed by entering water
+ AURA_INTERRUPT_FLAG_NOT_UNDERWATER = 0x00000100, // 8 removed by leaving water
+ AURA_INTERRUPT_FLAG_NOT_SHEATHED = 0x00000200, // 9 removed by unsheathing
+ AURA_INTERRUPT_FLAG_TALK = 0x00000400, // 10 talk to npc / loot? action on creature
+ AURA_INTERRUPT_FLAG_USE = 0x00000800, // 11 mine/use/open action on gameobject
+ AURA_INTERRUPT_FLAG_ATTACK = 0x00001000, // 12 removed by attacking
+ AURA_INTERRUPT_FLAG_CAST = 0x00002000, // 13 ???
+ AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14
+ AURA_INTERRUPT_FLAG_TRANSFORM = 0x00008000, // 15 removed by transform?
+ AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16
+ AURA_INTERRUPT_FLAG_MOUNT = 0x00020000, // 17 misdirect, aspect, swim speed
+ AURA_INTERRUPT_FLAG_NOT_SEATED = 0x00040000, // 18 removed by standing up
+ AURA_INTERRUPT_FLAG_CHANGE_MAP = 0x00080000, // 19 leaving map/getting teleported
+ AURA_INTERRUPT_FLAG_UNATTACKABLE = 0x00100000, // 20 invulnerable or stealth
+ AURA_INTERRUPT_FLAG_UNK21 = 0x00200000, // 21
+ AURA_INTERRUPT_FLAG_TELEPORTED = 0x00400000, // 22
+ AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat
+ AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000 // 24 removed by any direct damage
+};
+
+enum SpellModOp
+{
+ SPELLMOD_DAMAGE = 0,
+ SPELLMOD_DURATION = 1,
+ SPELLMOD_THREAT = 2,
+ SPELLMOD_EFFECT1 = 3,
+ SPELLMOD_CHARGES = 4,
+ SPELLMOD_RANGE = 5,
+ SPELLMOD_RADIUS = 6,
+ SPELLMOD_CRITICAL_CHANCE = 7,
+ SPELLMOD_ALL_EFFECTS = 8,
+ SPELLMOD_NOT_LOSE_CASTING_TIME = 9,
+ SPELLMOD_CASTING_TIME = 10,
+ SPELLMOD_COOLDOWN = 11,
+ SPELLMOD_EFFECT2 = 12,
+ // spellmod 13 unused
+ SPELLMOD_COST = 14,
+ SPELLMOD_CRIT_DAMAGE_BONUS = 15,
+ SPELLMOD_RESIST_MISS_CHANCE = 16,
+ SPELLMOD_JUMP_TARGETS = 17,
+ SPELLMOD_CHANCE_OF_SUCCESS = 18,
+ SPELLMOD_ACTIVATION_TIME = 19,
+ SPELLMOD_EFFECT_PAST_FIRST = 20,
+ SPELLMOD_CASTING_TIME_OLD = 21,
+ SPELLMOD_DOT = 22,
+ SPELLMOD_EFFECT3 = 23,
+ SPELLMOD_SPELL_BONUS_DAMAGE = 24,
+ // spellmod 25, 26 unused
+ SPELLMOD_MULTIPLE_VALUE = 27,
+ SPELLMOD_RESIST_DISPEL_CHANCE = 28
+};
+
+#define MAX_SPELLMOD 32
+
+enum SpellFacingFlags
+{
+ SPELL_FACING_FLAG_INFRONT = 0x0001
+};
+
+#define BASE_MINDAMAGE 1.0f
+#define BASE_MAXDAMAGE 2.0f
+#define BASE_ATTACK_TIME 2000
+
+// high byte (3 from 0..3) of UNIT_FIELD_BYTES_2
+enum ShapeshiftForm
+{
+ FORM_NONE = 0x00,
+ FORM_CAT = 0x01,
+ FORM_TREE = 0x02,
+ FORM_TRAVEL = 0x03,
+ FORM_AQUA = 0x04,
+ FORM_BEAR = 0x05,
+ FORM_AMBIENT = 0x06,
+ FORM_GHOUL = 0x07,
+ FORM_DIREBEAR = 0x08,
+ FORM_CREATUREBEAR = 0x0E,
+ FORM_CREATURECAT = 0x0F,
+ FORM_GHOSTWOLF = 0x10,
+ FORM_BATTLESTANCE = 0x11,
+ FORM_DEFENSIVESTANCE = 0x12,
+ FORM_BERSERKERSTANCE = 0x13,
+ FORM_TEST = 0x14,
+ FORM_ZOMBIE = 0x15,
+ FORM_FLIGHT_EPIC = 0x1B,
+ FORM_SHADOW = 0x1C,
+ FORM_FLIGHT = 0x1D,
+ FORM_STEALTH = 0x1E,
+ FORM_MOONKIN = 0x1F,
+ FORM_SPIRITOFREDEMPTION = 0x20
+};
+
+// low byte ( 0 from 0..3 ) of UNIT_FIELD_BYTES_2
+enum SheathState
+{
+ SHEATH_STATE_UNARMED = 0, // non prepared weapon
+ SHEATH_STATE_MELEE = 1, // prepared melee weapon
+ SHEATH_STATE_RANGED = 2 // prepared ranged weapon
+};
+
+// byte (1 from 0..3) of UNIT_FIELD_BYTES_2
+enum UnitBytes2_Flags
+{
+ UNIT_BYTE2_FLAG_UNK0 = 0x01,
+ UNIT_BYTE2_FLAG_UNK1 = 0x02,
+ UNIT_BYTE2_FLAG_UNK2 = 0x04,
+ UNIT_BYTE2_FLAG_UNK3 = 0x08,
+ UNIT_BYTE2_FLAG_AURAS = 0x10, // show possitive auras as positive, and allow its dispel
+ UNIT_BYTE2_FLAG_UNK5 = 0x20,
+ UNIT_BYTE2_FLAG_UNK6 = 0x40,
+ UNIT_BYTE2_FLAG_UNK7 = 0x80
+};
+
+// byte (2 from 0..3) of UNIT_FIELD_BYTES_2
+enum UnitRename
+{
+ UNIT_RENAME_NOT_ALLOWED = 0x02,
+ UNIT_RENAME_ALLOWED = 0x03
+};
+
+#define CREATURE_MAX_SPELLS 4
+
+enum Swing
+{
+ NOSWING = 0,
+ SINGLEHANDEDSWING = 1,
+ TWOHANDEDSWING = 2
+};
+
+enum VictimState
+{
+ VICTIMSTATE_UNKNOWN1 = 0,
+ VICTIMSTATE_NORMAL = 1,
+ VICTIMSTATE_DODGE = 2,
+ VICTIMSTATE_PARRY = 3,
+ VICTIMSTATE_INTERRUPT = 4,
+ VICTIMSTATE_BLOCKS = 5,
+ VICTIMSTATE_EVADES = 6,
+ VICTIMSTATE_IS_IMMUNE = 7,
+ VICTIMSTATE_DEFLECTS = 8
+};
+
+enum HitInfo
+{
+ HITINFO_NORMALSWING = 0x00000000,
+ HITINFO_UNK1 = 0x00000001, // req correct packet structure
+ HITINFO_NORMALSWING2 = 0x00000002,
+ HITINFO_LEFTSWING = 0x00000004,
+ HITINFO_MISS = 0x00000010,
+ HITINFO_ABSORB = 0x00000020, // plays absorb sound
+ HITINFO_RESIST = 0x00000040, // resisted at least some damage
+ HITINFO_CRITICALHIT = 0x00000080,
+ HITINFO_UNK2 = 0x00000100, // wotlk?
+ HITINFO_UNK3 = 0x00002000, // wotlk?
+ HITINFO_GLANCING = 0x00004000,
+ HITINFO_CRUSHING = 0x00008000,
+ HITINFO_NOACTION = 0x00010000,
+ HITINFO_SWINGNOHITSOUND = 0x00080000
+};
+
+//i would like to remove this: (it is defined in item.h
+enum InventorySlot
+{
+ NULL_BAG = 0,
+ NULL_SLOT = 255
+};
+
+struct FactionTemplateEntry;
+struct Modifier;
+struct SpellEntry;
+struct SpellEntryExt;
+
+class Aura;
+class Creature;
+class Spell;
+class DynamicObject;
+class GameObject;
+class Item;
+class Pet;
+class Path;
+class PetAura;
+
+struct SpellImmune
+{
+ uint32 type;
+ uint32 spellId;
+};
+
+typedef std::list<SpellImmune> SpellImmuneList;
+
+enum UnitModifierType
+{
+ BASE_VALUE = 0,
+ BASE_PCT = 1,
+ TOTAL_VALUE = 2,
+ TOTAL_PCT = 3,
+ MODIFIER_TYPE_END = 4
+};
+
+enum WeaponDamageRange
+{
+ MINDAMAGE,
+ MAXDAMAGE
+};
+
+enum DamageTypeToSchool
+{
+ RESISTANCE,
+ DAMAGE_DEALT,
+ DAMAGE_TAKEN
+};
+
+enum AuraRemoveMode
+{
+ AURA_REMOVE_BY_DEFAULT,
+ AURA_REMOVE_BY_STACK, // at replace by semillar aura
+ AURA_REMOVE_BY_CANCEL,
+ AURA_REMOVE_BY_DISPEL,
+ AURA_REMOVE_BY_DEATH
+};
+
+enum UnitMods
+{
+ UNIT_MOD_STAT_STRENGTH, // UNIT_MOD_STAT_STRENGTH..UNIT_MOD_STAT_SPIRIT must be in existed order, it's accessed by index values of Stats enum.
+ UNIT_MOD_STAT_AGILITY,
+ UNIT_MOD_STAT_STAMINA,
+ UNIT_MOD_STAT_INTELLECT,
+ UNIT_MOD_STAT_SPIRIT,
+ UNIT_MOD_HEALTH,
+ UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_HAPPINESS must be in existed order, it's accessed by index values of Powers enum.
+ UNIT_MOD_RAGE,
+ UNIT_MOD_FOCUS,
+ UNIT_MOD_ENERGY,
+ UNIT_MOD_HAPPINESS,
+ UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum.
+ UNIT_MOD_RESISTANCE_HOLY,
+ UNIT_MOD_RESISTANCE_FIRE,
+ UNIT_MOD_RESISTANCE_NATURE,
+ UNIT_MOD_RESISTANCE_FROST,
+ UNIT_MOD_RESISTANCE_SHADOW,
+ UNIT_MOD_RESISTANCE_ARCANE,
+ UNIT_MOD_ATTACK_POWER,
+ UNIT_MOD_ATTACK_POWER_RANGED,
+ UNIT_MOD_DAMAGE_MAINHAND,
+ UNIT_MOD_DAMAGE_OFFHAND,
+ UNIT_MOD_DAMAGE_RANGED,
+ UNIT_MOD_END,
+ // synonyms
+ UNIT_MOD_STAT_START = UNIT_MOD_STAT_STRENGTH,
+ UNIT_MOD_STAT_END = UNIT_MOD_STAT_SPIRIT + 1,
+ UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR,
+ UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1,
+ UNIT_MOD_POWER_START = UNIT_MOD_MANA,
+ UNIT_MOD_POWER_END = UNIT_MOD_HAPPINESS + 1
+};
+
+enum BaseModGroup
+{
+ CRIT_PERCENTAGE,
+ RANGED_CRIT_PERCENTAGE,
+ OFFHAND_CRIT_PERCENTAGE,
+ SHIELD_BLOCK_VALUE,
+ BASEMOD_END
+};
+
+enum BaseModType
+{
+ FLAT_MOD,
+ PCT_MOD
+};
+
+#define MOD_END (PCT_MOD+1)
+
+enum DeathState
+{
+ ALIVE = 0,
+ JUST_DIED = 1,
+ CORPSE = 2,
+ DEAD = 3,
+ JUST_ALIVED = 4
+};
+
+enum UnitState
+{
+ UNIT_STAT_DIED = 0x0001,
+ UNIT_STAT_MELEE_ATTACKING = 0x0002, // player is melee attacking someone
+ //UNIT_STAT_MELEE_ATTACK_BY = 0x0004, // player is melee attack by someone
+ UNIT_STAT_STUNNED = 0x0008,
+ UNIT_STAT_ROAMING = 0x0010,
+ UNIT_STAT_CHASE = 0x0020,
+ UNIT_STAT_SEARCHING = 0x0040,
+ UNIT_STAT_FLEEING = 0x0080,
+ UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING),
+ UNIT_STAT_IN_FLIGHT = 0x0100, // player is in flight mode
+ UNIT_STAT_FOLLOW = 0x0200,
+ UNIT_STAT_ROOT = 0x0400,
+ UNIT_STAT_CONFUSED = 0x0800,
+ UNIT_STAT_DISTRACTED = 0x1000,
+ UNIT_STAT_ISOLATED = 0x2000, // area auras do not affect other players
+ UNIT_STAT_ATTACK_PLAYER = 0x4000,
+ UNIT_STAT_CASTING = 0x8000,
+ UNIT_STAT_ALL_STATE = 0xffff //(UNIT_STAT_STOPPED | UNIT_STAT_MOVING | UNIT_STAT_IN_COMBAT | UNIT_STAT_IN_FLIGHT)
+};
+
+enum UnitMoveType
+{
+ MOVE_WALK = 0,
+ MOVE_RUN = 1,
+ MOVE_WALKBACK = 2,
+ MOVE_SWIM = 3,
+ MOVE_SWIMBACK = 4,
+ MOVE_TURN = 5,
+ MOVE_FLY = 6,
+ MOVE_FLYBACK = 7
+};
+
+#define MAX_MOVE_TYPE 8
+
+extern float baseMoveSpeed[MAX_MOVE_TYPE];
+
+enum WeaponAttackType
+{
+ BASE_ATTACK = 0,
+ OFF_ATTACK = 1,
+ RANGED_ATTACK = 2
+};
+
+#define MAX_ATTACK 3
+
+enum CombatRating
+{
+ CR_WEAPON_SKILL = 0,
+ CR_DEFENSE_SKILL = 1,
+ CR_DODGE = 2,
+ CR_PARRY = 3,
+ CR_BLOCK = 4,
+ CR_HIT_MELEE = 5,
+ CR_HIT_RANGED = 6,
+ CR_HIT_SPELL = 7,
+ CR_CRIT_MELEE = 8,
+ CR_CRIT_RANGED = 9,
+ CR_CRIT_SPELL = 10,
+ CR_HIT_TAKEN_MELEE = 11,
+ CR_HIT_TAKEN_RANGED = 12,
+ CR_HIT_TAKEN_SPELL = 13,
+ CR_CRIT_TAKEN_MELEE = 14,
+ CR_CRIT_TAKEN_RANGED = 15,
+ CR_CRIT_TAKEN_SPELL = 16,
+ CR_HASTE_MELEE = 17,
+ CR_HASTE_RANGED = 18,
+ CR_HASTE_SPELL = 19,
+ CR_WEAPON_SKILL_MAINHAND = 20,
+ CR_WEAPON_SKILL_OFFHAND = 21,
+ CR_WEAPON_SKILL_RANGED = 22,
+ CR_EXPERTISE = 23
+};
+
+#define MAX_COMBAT_RATING 24
+
+enum DamageEffectType
+{
+ DIRECT_DAMAGE = 0, // used for normal weapon damage (not for class abilities or spells)
+ SPELL_DIRECT_DAMAGE = 1, // spell/class abilities damage
+ DOT = 2,
+ HEAL = 3,
+ NODAMAGE = 4, // used also in case when damage applied to health but not applied to spell channelInterruptFlags/etc
+ SELF_DAMAGE = 5
+};
+
+enum UnitVisibility
+{
+ VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other
+ VISIBILITY_ON = 1,
+ VISIBILITY_GROUP_STEALTH = 2, // detect chance, seen and can see group members
+ //VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit, set only if not stealthed, and in checks not used (mask used instead)
+ //VISIBILITY_GROUP_NO_DETECT = 4, // state just at stealth apply for update Grid state. Don't remove, otherwise stealth spells will break
+ VISIBILITY_RESPAWN = 5 // special totally not detectable visibility for force delete object at respawn command
+};
+
+// Value masks for UNIT_FIELD_FLAGS
+enum UnitFlags
+{
+ UNIT_FLAG_UNKNOWN7 = 0x00000001,
+ UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable
+ UNIT_FLAG_DISABLE_MOVE = 0x00000004,
+ UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state
+ UNIT_FLAG_RENAME = 0x00000010,
+ UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP
+ UNIT_FLAG_UNKNOWN9 = 0x00000040,
+ UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE
+ UNIT_FLAG_UNKNOWN2 = 0x00000100, // 2.0.8
+ UNIT_FLAG_UNKNOWN11 = 0x00000200,
+ UNIT_FLAG_LOOTING = 0x00000400, // loot animation
+ UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8
+ UNIT_FLAG_PVP = 0x00001000,
+ UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1
+ UNIT_FLAG_UNKNOWN4 = 0x00004000, // 2.0.8
+ UNIT_FLAG_UNKNOWN13 = 0x00008000,
+ UNIT_FLAG_UNKNOWN14 = 0x00010000,
+ UNIT_FLAG_PACIFIED = 0x00020000,
+ UNIT_FLAG_DISABLE_ROTATE = 0x00040000, // stunned, 2.1.1
+ UNIT_FLAG_IN_COMBAT = 0x00080000,
+ UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
+ UNIT_FLAG_DISARMED = 0x00200000, // disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
+ UNIT_FLAG_CONFUSED = 0x00400000,
+ UNIT_FLAG_FLEEING = 0x00800000,
+ UNIT_FLAG_UNKNOWN5 = 0x01000000, // used in spell Eyes of the Beast for pet...
+ UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
+ UNIT_FLAG_SKINNABLE = 0x04000000,
+ UNIT_FLAG_MOUNT = 0x08000000,
+ UNIT_FLAG_UNKNOWN17 = 0x10000000,
+ UNIT_FLAG_UNKNOWN6 = 0x20000000, // used in Feing Death spell
+ UNIT_FLAG_SHEATHE = 0x40000000
+};
+
+// Value masks for UNIT_FIELD_FLAGS_2
+enum UnitFlags2
+{
+ UNIT_FLAG2_FEIGN_DEATH = 0x00000001,
+ UNIT_FLAG2_COMPREHEND_LANG= 0x00000008,
+ UNIT_FLAG2_FORCE_MOVE = 0x00000040
+};
+
+/// Non Player Character flags
+enum NPCFlags
+{
+ UNIT_NPC_FLAG_NONE = 0x00000000,
+ UNIT_NPC_FLAG_GOSSIP = 0x00000001, // 100%
+ UNIT_NPC_FLAG_QUESTGIVER = 0x00000002, // guessed, probably ok
+ UNIT_NPC_FLAG_UNK1 = 0x00000004,
+ UNIT_NPC_FLAG_UNK2 = 0x00000008,
+ UNIT_NPC_FLAG_TRAINER = 0x00000010, // 100%
+ UNIT_NPC_FLAG_TRAINER_CLASS = 0x00000020, // 100%
+ UNIT_NPC_FLAG_TRAINER_PROFESSION = 0x00000040, // 100%
+ UNIT_NPC_FLAG_VENDOR = 0x00000080, // 100%
+ UNIT_NPC_FLAG_VENDOR_AMMO = 0x00000100, // 100%, general goods vendor
+ UNIT_NPC_FLAG_VENDOR_FOOD = 0x00000200, // 100%
+ UNIT_NPC_FLAG_VENDOR_POISON = 0x00000400, // guessed
+ UNIT_NPC_FLAG_VENDOR_REAGENT = 0x00000800, // 100%
+ UNIT_NPC_FLAG_REPAIR = 0x00001000, // 100%
+ UNIT_NPC_FLAG_FLIGHTMASTER = 0x00002000, // 100%
+ UNIT_NPC_FLAG_SPIRITHEALER = 0x00004000, // guessed
+ UNIT_NPC_FLAG_SPIRITGUIDE = 0x00008000, // guessed
+ UNIT_NPC_FLAG_INNKEEPER = 0x00010000, // 100%
+ UNIT_NPC_FLAG_BANKER = 0x00020000, // 100%
+ UNIT_NPC_FLAG_PETITIONER = 0x00040000, // 100% 0xC0000 = guild petitions, 0x40000 = arena team petitions
+ UNIT_NPC_FLAG_TABARDDESIGNER = 0x00080000, // 100%
+ UNIT_NPC_FLAG_BATTLEMASTER = 0x00100000, // 100%
+ UNIT_NPC_FLAG_AUCTIONEER = 0x00200000, // 100%
+ UNIT_NPC_FLAG_STABLEMASTER = 0x00400000, // 100%
+ UNIT_NPC_FLAG_GUILD_BANKER = 0x00800000, // cause client to send 997 opcode
+ UNIT_NPC_FLAG_SPELLCLICK = 0x01000000, // cause client to send 1015 opcode (spell click)
+ UNIT_NPC_FLAG_GUARD = 0x10000000, // custom flag for guards
+ UNIT_NPC_FLAG_OUTDOORPVP = 0x20000000, // custom flag for outdoor pvp creatures
+};
+
+enum MovementFlags
+{
+ MOVEMENTFLAG_NONE = 0x00000000,
+ MOVEMENTFLAG_FORWARD = 0x00000001,
+ MOVEMENTFLAG_BACKWARD = 0x00000002,
+ MOVEMENTFLAG_STRAFE_LEFT = 0x00000004,
+ MOVEMENTFLAG_STRAFE_RIGHT = 0x00000008,
+ MOVEMENTFLAG_LEFT = 0x00000010,
+ MOVEMENTFLAG_RIGHT = 0x00000020,
+ MOVEMENTFLAG_PITCH_UP = 0x00000040,
+ MOVEMENTFLAG_PITCH_DOWN = 0x00000080,
+ MOVEMENTFLAG_WALK_MODE = 0x00000100, // Walking
+ MOVEMENTFLAG_ONTRANSPORT = 0x00000200, // Used for flying on some creatures
+ MOVEMENTFLAG_LEVITATING = 0x00000400,
+ MOVEMENTFLAG_FLY_UNK1 = 0x00000800,
+ MOVEMENTFLAG_JUMPING = 0x00001000,
+ MOVEMENTFLAG_UNK4 = 0x00002000,
+ MOVEMENTFLAG_FALLING = 0x00004000,
+ // 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000
+ MOVEMENTFLAG_SWIMMING = 0x00200000, // appears with fly flag also
+ MOVEMENTFLAG_FLY_UP = 0x00400000,
+ MOVEMENTFLAG_CAN_FLY = 0x00800000,
+ MOVEMENTFLAG_FLYING = 0x01000000,
+ MOVEMENTFLAG_FLYING2 = 0x02000000, // Actual flying mode
+ MOVEMENTFLAG_SPLINE = 0x04000000, // used for flight paths
+ MOVEMENTFLAG_SPLINE2 = 0x08000000, // used for flight paths
+ MOVEMENTFLAG_WATERWALKING = 0x10000000, // prevent unit from falling through water
+ MOVEMENTFLAG_SAFE_FALL = 0x20000000, // active rogue safe fall spell (passive)
+ MOVEMENTFLAG_UNK3 = 0x40000000
+};
+
+enum DiminishingLevels
+{
+ DIMINISHING_LEVEL_1 = 0,
+ DIMINISHING_LEVEL_2 = 1,
+ DIMINISHING_LEVEL_3 = 2,
+ DIMINISHING_LEVEL_IMMUNE = 3
+};
+
+struct DiminishingReturn
+{
+ DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count) : DRGroup(group), hitTime(t), hitCount(count), stack(0) {}
+
+ DiminishingGroup DRGroup:16;
+ uint16 stack:16;
+ uint32 hitTime;
+ uint32 hitCount;
+};
+
+enum MeleeHitOutcome
+{
+ MELEE_HIT_EVADE, MELEE_HIT_MISS, MELEE_HIT_DODGE, MELEE_HIT_BLOCK, MELEE_HIT_PARRY,
+ MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL, MELEE_HIT_BLOCK_CRIT
+};
+struct CleanDamage
+{
+ CleanDamage(uint32 _damage, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) :
+ damage(_damage), attackType(_attackType), hitOutCome(_hitOutCome) {}
+
+ uint32 damage;
+ WeaponAttackType attackType;
+ MeleeHitOutcome hitOutCome;
+};
+
+struct UnitActionBarEntry
+{
+ uint32 Type;
+ uint32 SpellOrAction;
+};
+
+#define MAX_DECLINED_NAME_CASES 5
+
+struct DeclinedName
+{
+ std::string name[MAX_DECLINED_NAME_CASES];
+};
+
+enum CurrentSpellTypes
+{
+ CURRENT_MELEE_SPELL = 0,
+ CURRENT_FIRST_NON_MELEE_SPELL = 1, // just counter
+ CURRENT_GENERIC_SPELL = 1,
+ CURRENT_AUTOREPEAT_SPELL = 2,
+ CURRENT_CHANNELED_SPELL = 3,
+ CURRENT_MAX_SPELL = 4 // just counter
+};
+
+enum ActiveStates
+{
+ ACT_ENABLED = 0xC100,
+ ACT_DISABLED = 0x8100,
+ ACT_COMMAND = 0x0700,
+ ACT_REACTION = 0x0600,
+ ACT_CAST = 0x0100,
+ ACT_PASSIVE = 0x0000,
+ ACT_DECIDE = 0x0001
+};
+
+enum ReactStates
+{
+ REACT_PASSIVE = 0,
+ REACT_DEFENSIVE = 1,
+ REACT_AGGRESSIVE = 2
+};
+
+enum CommandStates
+{
+ COMMAND_STAY = 0,
+ COMMAND_FOLLOW = 1,
+ COMMAND_ATTACK = 2,
+ COMMAND_ABANDON = 3
+};
+
+struct CharmSpellEntry
+{
+ uint16 spellId;
+ uint16 active;
+};
+
+typedef std::list<Player*> SharedVisionList;
+
+struct CharmInfo
+{
+ public:
+ explicit CharmInfo(Unit* unit);
+ uint32 GetPetNumber() const { return m_petnumber; }
+ void SetPetNumber(uint32 petnumber, bool statwindow);
+
+ void SetCommandState(CommandStates st) { m_CommandState = st; }
+ CommandStates GetCommandState() { return m_CommandState; }
+ bool HasCommandState(CommandStates state) { return (m_CommandState == state); }
+ void SetReactState(ReactStates st) { m_reactState = st; }
+ ReactStates GetReactState() { return m_reactState; }
+ bool HasReactState(ReactStates state) { return (m_reactState == state); }
+
+ void InitPossessCreateSpells();
+ void InitCharmCreateSpells();
+ void InitPetActionBar();
+ void InitEmptyActionBar();
+ //return true if successful
+ bool AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate = ACT_DECIDE);
+ void ToggleCreatureAutocast(uint32 spellid, bool apply);
+
+ UnitActionBarEntry* GetActionBarEntry(uint8 index) { return &(PetActionBar[index]); }
+ CharmSpellEntry* GetCharmSpell(uint8 index) { return &(m_charmspells[index]); }
+ private:
+ Unit* m_unit;
+ UnitActionBarEntry PetActionBar[10];
+ CharmSpellEntry m_charmspells[4];
+ CommandStates m_CommandState;
+ ReactStates m_reactState;
+ uint32 m_petnumber;
+};
+
+// for clearing special attacks
+#define REACTIVE_TIMER_START 4000
+
+enum ReactiveType
+{
+ REACTIVE_DEFENSE = 1,
+ REACTIVE_HUNTER_PARRY = 2,
+ REACTIVE_CRIT = 3,
+ REACTIVE_HUNTER_CRIT = 4,
+ REACTIVE_OVERPOWER = 5
+};
+
+#define MAX_REACTIVE 6
+#define MAX_TOTEM 4
+
+// delay time next attack to prevent client attack animation problems
+#define ATTACK_DISPLAY_DELAY 200
+
+class TRINITY_DLL_SPEC Unit : public WorldObject
+{
+ public:
+ typedef std::set<Unit*> AttackerSet;
+ typedef std::pair<uint32, uint8> spellEffectPair;
+ typedef std::multimap< spellEffectPair, Aura*> AuraMap;
+ typedef std::list<Aura *> AuraList;
+ typedef std::list<DiminishingReturn> Diminishing;
+ typedef std::set<AuraType> AuraTypeSet;
+ typedef std::set<uint32> ComboPointHolderSet;
+
+ virtual ~Unit ( );
+
+ void AddToWorld();
+ void RemoveFromWorld();
+
+ void CleanupsBeforeDelete(); // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units)
+
+ DiminishingLevels GetDiminishing(DiminishingGroup group);
+ void IncrDiminishing(DiminishingGroup group);
+ void ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster, DiminishingLevels Level);
+ void ApplyDiminishingAura(DiminishingGroup group, bool apply);
+ void ClearDiminishings() { m_Diminishing.clear(); }
+
+ virtual void Update( uint32 time );
+
+ void setAttackTimer(WeaponAttackType type, uint32 time) { m_attackTimer[type] = time; }
+ void resetAttackTimer(WeaponAttackType type = BASE_ATTACK);
+ uint32 getAttackTimer(WeaponAttackType type) const { return m_attackTimer[type]; }
+ bool isAttackReady(WeaponAttackType type = BASE_ATTACK) const { return m_attackTimer[type] == 0; }
+ bool haveOffhandWeapon() const;
+ bool CanDualWield() const { return m_canDualWield; }
+ void SetCanDualWield(bool value) { m_canDualWield = value; }
+ bool canReachWithAttack(Unit *pVictim) const;
+ float GetCombatReach() const { return m_floatValues[UNIT_FIELD_COMBATREACH]; }
+ bool IsWithinCombatDist(Unit *obj, float dist2compare) const;
+ void GetRandomContactPoint( const Unit* target, float &x, float &y, float &z, float distance2dMin, float distance2dMax ) const;
+ uint32 m_extraAttacks;
+ bool m_canDualWield;
+
+ void _addAttacker(Unit *pAttacker) // must be called only from Unit::Attack(Unit*)
+ {
+ AttackerSet::iterator itr = m_attackers.find(pAttacker);
+ if(itr == m_attackers.end())
+ m_attackers.insert(pAttacker);
+ }
+ void _removeAttacker(Unit *pAttacker) // must be called only from Unit::AttackStop()
+ {
+ AttackerSet::iterator itr = m_attackers.find(pAttacker);
+ if(itr != m_attackers.end())
+ m_attackers.erase(itr);
+ }
+ Unit * getAttackerForHelper() // If someone wants to help, who to give them
+ {
+ if (getVictim() != NULL)
+ return getVictim();
+
+ if (!m_attackers.empty())
+ return *(m_attackers.begin());
+
+ return NULL;
+ }
+ bool Attack(Unit *victim, bool meleeAttack);
+ void CastStop(uint32 except_spellid = 0);
+ bool AttackStop();
+ void RemoveAllAttackers();
+ AttackerSet const& getAttackers() const { return m_attackers; }
+ bool isAttackingPlayer() const;
+ Unit* getVictim() const { return m_attacking; }
+ void CombatStop(bool cast = false);
+ void CombatStopWithPets(bool cast = false);
+ Unit* SelectNearbyTarget() const;
+
+ void addUnitState(uint32 f) { m_state |= f; }
+ bool hasUnitState(const uint32 f) const { return (m_state & f); }
+ void clearUnitState(uint32 f) { m_state &= ~f; }
+ bool CanFreeMove() const
+ {
+ return !hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_IN_FLIGHT |
+ UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED ) && GetOwnerGUID()==0;
+ }
+
+ uint32 getLevel() const { return GetUInt32Value(UNIT_FIELD_LEVEL); }
+ virtual uint32 getLevelForTarget(Unit const* /*target*/) const { return getLevel(); }
+ void SetLevel(uint32 lvl);
+ uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, 0); }
+ uint32 getRaceMask() const { return 1 << (getRace()-1); }
+ uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); }
+ uint32 getClassMask() const { return 1 << (getClass()-1); }
+ uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); }
+
+ float GetStat(Stats stat) const { return float(GetUInt32Value(UNIT_FIELD_STAT0+stat)); }
+ void SetStat(Stats stat, int32 val) { SetStatInt32Value(UNIT_FIELD_STAT0+stat, val); }
+ uint32 GetArmor() const { return GetResistance(SPELL_SCHOOL_NORMAL) ; }
+ void SetArmor(int32 val) { SetResistance(SPELL_SCHOOL_NORMAL, val); }
+
+ uint32 GetResistance(SpellSchools school) const { return GetUInt32Value(UNIT_FIELD_RESISTANCES+school); }
+ void SetResistance(SpellSchools school, int32 val) { SetStatInt32Value(UNIT_FIELD_RESISTANCES+school,val); }
+
+ uint32 GetHealth() const { return GetUInt32Value(UNIT_FIELD_HEALTH); }
+ uint32 GetMaxHealth() const { return GetUInt32Value(UNIT_FIELD_MAXHEALTH); }
+ void SetHealth( uint32 val);
+ void SetMaxHealth(uint32 val);
+ int32 ModifyHealth(int32 val);
+
+ Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
+ void setPowerType(Powers power);
+ uint32 GetPower( Powers power) const { return GetUInt32Value(UNIT_FIELD_POWER1 +power); }
+ uint32 GetMaxPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_MAXPOWER1+power); }
+ void SetPower( Powers power, uint32 val);
+ void SetMaxPower(Powers power, uint32 val);
+ int32 ModifyPower(Powers power, int32 val);
+ void ApplyPowerMod(Powers power, uint32 val, bool apply);
+ void ApplyMaxPowerMod(Powers power, uint32 val, bool apply);
+
+ uint32 GetAttackTime(WeaponAttackType att) const { return (uint32)(GetFloatValue(UNIT_FIELD_BASEATTACKTIME+att)/m_modAttackSpeedPct[att]); }
+ void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME+att,val*m_modAttackSpeedPct[att]); }
+ void ApplyAttackTimePercentMod(WeaponAttackType att,float val, bool apply);
+ void ApplyCastTimePercentMod(float val, bool apply);
+
+ // faction template id
+ uint32 getFaction() const { return GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE); }
+ void setFaction(uint32 faction) { SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction ); }
+ FactionTemplateEntry const* getFactionTemplateEntry() const;
+ bool IsHostileTo(Unit const* unit) const;
+ bool IsHostileToPlayers() const;
+ bool IsFriendlyTo(Unit const* unit) const;
+ bool IsNeutralToAll() const;
+ bool IsContestedGuard() const
+ {
+ if(FactionTemplateEntry const* entry = getFactionTemplateEntry())
+ return entry->IsContestedGuardFaction();
+
+ return false;
+ }
+ bool IsPvP() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); }
+ void SetPvP(bool state) { if(state) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); else RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); }
+ uint32 GetCreatureType() const;
+ uint32 GetCreatureTypeMask() const
+ {
+ uint32 creatureType = GetCreatureType();
+ return (creatureType >= 1) ? (1 << (creatureType - 1)) : 0;
+ }
+
+ uint8 getStandState() const { return GetByteValue(UNIT_FIELD_BYTES_1, 0); }
+ bool IsSitState() const;
+ bool IsStandState() const;
+ void SetStandState(uint8 state);
+
+ bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); }
+ uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); }
+ void Mount(uint32 mount);
+ void Unmount();
+
+ uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
+ void RemoveSpellbyDamageTaken(uint32 damage, uint32 spell);
+ uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss);
+ void DealFlatDamage(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit = false, bool isTriggeredSpell = false);
+ void DoAttackDamage(Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false);
+
+ void CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchoolMask damageSchoolMask, WeaponAttackType attType, MeleeHitOutcome outcome, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false);
+ void ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 damage = 0, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NONE, SpellEntry const *procSpell = NULL, bool isTriggeredSpell = false, WeaponAttackType attType = BASE_ATTACK);
+ void HandleEmoteCommand(uint32 anim_id);
+ void AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType = BASE_ATTACK, bool extra = false );
+
+ float MeleeMissChanceCalc(const Unit *pVictim, WeaponAttackType attType) const;
+ SpellMissInfo MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell);
+ SpellMissInfo SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool canReflect = false);
+
+ float GetUnitDodgeChance() const;
+ float GetUnitParryChance() const;
+ float GetUnitBlockChance() const;
+ float GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const;
+
+ virtual uint32 GetShieldBlockValue() const =0;
+ uint32 GetUnitMeleeSkill(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; }
+ uint32 GetDefenseSkillValue(Unit const* target = NULL) const;
+ uint32 GetWeaponSkillValue(WeaponAttackType attType, Unit const* target = NULL) const;
+ float GetWeaponProcChance() const;
+ float GetPPMProcChance(uint32 WeaponSpeed, float PPM) const;
+ MeleeHitOutcome RollPhysicalOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo);
+ MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType) const;
+ MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const;
+
+ bool isVendor() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR ); }
+ bool isTrainer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER ); }
+ bool isQuestGiver() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER ); }
+ bool isGossip() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP ); }
+ bool isTaxi() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_FLIGHTMASTER ); }
+ bool isGuildMaster() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PETITIONER ); }
+ bool isBattleMaster() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BATTLEMASTER ); }
+ bool isBanker() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER ); }
+ bool isInnkeeper() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_INNKEEPER ); }
+ bool isSpiritHealer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER ); }
+ bool isSpiritGuide() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITGUIDE ); }
+ bool isTabardDesigner()const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TABARDDESIGNER ); }
+ bool isAuctioner() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_AUCTIONEER ); }
+ bool isArmorer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_REPAIR ); }
+ bool isServiceProvider() const
+ {
+ return HasFlag( UNIT_NPC_FLAGS,
+ UNIT_NPC_FLAG_VENDOR | UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_FLIGHTMASTER |
+ UNIT_NPC_FLAG_PETITIONER | UNIT_NPC_FLAG_BATTLEMASTER | UNIT_NPC_FLAG_BANKER |
+ UNIT_NPC_FLAG_INNKEEPER | UNIT_NPC_FLAG_GUARD | UNIT_NPC_FLAG_SPIRITHEALER |
+ UNIT_NPC_FLAG_SPIRITGUIDE | UNIT_NPC_FLAG_TABARDDESIGNER | UNIT_NPC_FLAG_AUCTIONEER );
+ }
+ bool isSpiritService() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE ); }
+
+ //Need fix or use this
+ bool isGuard() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GUARD); }
+
+ bool isInFlight() const { return hasUnitState(UNIT_STAT_IN_FLIGHT); }
+
+ bool isInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); }
+ void CombatStart(Unit* target);
+ void SetInCombatState(bool PvP);
+ void SetInCombatWith(Unit* enemy);
+ void ClearInCombat();
+ uint32 GetCombatTimer() const { return m_CombatTimer; }
+
+ bool HasAuraType(AuraType auraType) const;
+ bool HasAura(uint32 spellId, uint32 effIndex) const
+ { return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end(); }
+
+ bool virtual HasSpell(uint32 /*spellID*/) const { return false; }
+
+ bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); }
+ bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); }
+ bool isFeared() const { return HasAuraType(SPELL_AURA_MOD_FEAR); }
+ bool isInRoots() const { return HasAuraType(SPELL_AURA_MOD_ROOT); }
+ bool IsPolymorphed() const;
+
+ bool isFrozen() const;
+
+ bool isTargetableForAttack() const;
+ bool isAttackableByAOE() const;
+ bool canAttack(Unit const* target) const;
+ virtual bool IsInWater() const;
+ virtual bool IsUnderWater() const;
+ bool isInAccessiblePlaceFor(Creature const* c) const;
+
+ void SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool critical = false);
+ void SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage,Powers powertype, bool critical = false);
+ uint32 SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell = false, bool useSpellDamage = true);
+ void CastSpell(Unit* Victim, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0);
+ void CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, Item *castItem= NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0);
+ void CastCustomSpell(Unit* Victim, uint32 spellId, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem= NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0);
+ void CastCustomSpell(Unit* Victim,SpellEntry const *spellInfo, int32 const* bp0, int32 const* bp1, int32 const* bp2, bool triggered, Item *castItem= NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0);
+ void CastSpell(float x, float y, float z, uint32 spellId, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0);
+ void CastSpell(float x, float y, float z, SpellEntry const *spellInfo, bool triggered, Item *castItem = NULL, Aura* triggeredByAura = NULL, uint64 originalCaster = 0);
+
+ bool IsDamageToThreatSpell(SpellEntry const * spellInfo) const;
+
+ void DeMorph();
+
+ void SendAttackStart(Unit* pVictim);
+ void SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount);
+ void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false);
+ void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo);
+
+ void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL);
+ void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags);
+ void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 MovementFlags, uint32 transitTime = 0, Player* player = NULL);
+ void SendMonsterMoveWithSpeedToCurrentDestination(Player* player = NULL);
+
+ virtual void MoveOutOfRange(Player &) { };
+
+ bool isAlive() const { return (m_deathState == ALIVE); };
+ bool isDead() const { return ( m_deathState == DEAD || m_deathState == CORPSE ); };
+ DeathState getDeathState() { return m_deathState; };
+ virtual void setDeathState(DeathState s); // overwrited in Creature/Player/Pet
+
+ uint64 const& GetOwnerGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMONEDBY); }
+ uint64 GetPetGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMON); }
+ uint64 GetCharmerGUID() const { return GetUInt64Value(UNIT_FIELD_CHARMEDBY); }
+ uint64 GetCharmGUID() const { return GetUInt64Value(UNIT_FIELD_CHARM); }
+ void SetCharmerGUID(uint64 owner) { SetUInt64Value(UNIT_FIELD_CHARMEDBY, owner); }
+
+ uint64 GetCharmerOrOwnerGUID() const { return GetCharmerGUID() ? GetCharmerGUID() : GetOwnerGUID(); }
+ uint64 GetCharmerOrOwnerOrOwnGUID() const
+ {
+ if(uint64 guid = GetCharmerOrOwnerGUID())
+ return guid;
+ return GetGUID();
+ }
+ bool isCharmedOwnedByPlayerOrPlayer() const { return IS_PLAYER_GUID(GetCharmerOrOwnerOrOwnGUID()); }
+
+ Player* GetSpellModOwner();
+
+ Unit* GetOwner() const;
+ Pet* GetPet() const;
+ Unit* GetCharmer() const;
+ Unit* GetCharm() const;
+ Unit* GetCharmerOrOwner() const { return GetCharmerGUID() ? GetCharmer() : GetOwner(); }
+ Unit* GetCharmerOrOwnerOrSelf()
+ {
+ if(Unit* u = GetCharmerOrOwner())
+ return u;
+
+ return this;
+ }
+ Player* GetCharmerOrOwnerPlayerOrPlayerItself();
+
+ void SetPet(Pet* pet);
+ void SetCharm(Unit* pet);
+ void SetPossessedTarget(Unit* target)
+ {
+ if (!target) return;
+ SetCharm(target);
+ target->SetCharmerGUID(GetGUID());
+ target->m_isPossessed = true;
+ }
+ void RemovePossessedTarget()
+ {
+ if (!GetCharm()) return;
+ GetCharm()->SetCharmerGUID(0);
+ GetCharm()->m_isPossessed = false;
+ SetCharm(0);
+ }
+
+ bool isCharmed() const { return GetCharmerGUID() != 0; }
+ bool isPossessed() const { return m_isPossessed; }
+ bool isPossessedByPlayer() const { return m_isPossessed && IS_PLAYER_GUID(GetCharmerGUID()); }
+ bool isPossessing() const { return GetCharm() && GetCharm()->isPossessed(); }
+ bool isPossessing(Unit* u) const { return u->isPossessed() && GetCharmGUID() == u->GetGUID(); }
+ bool isPossessingCreature() const { return isPossessing() && IS_CREATURE_GUID(GetCharmGUID()); }
+
+ CharmInfo* GetCharmInfo() { return m_charmInfo; }
+ CharmInfo* InitCharmInfo(Unit* charm);
+ SharedVisionList const& GetSharedVisionList() { return m_sharedVision; }
+ void AddPlayerToVision(Player* plr);
+ void RemovePlayerFromVision(Player* plr);
+ void RemoveAllFromVision();
+ void UncharmSelf();
+ void UnpossessSelf(bool attack);
+
+ Pet* CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id = 0);
+
+ bool AddAura(Aura *aur);
+
+ void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
+ void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL);
+ void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex);
+ void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL);
+ void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId);
+ void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler);
+ void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer);
+ void RemoveAurasDueToSpellByCancel(uint32 spellId);
+ void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo);
+ void RemoveNotOwnSingleTargetAuras();
+
+ void RemoveSpellsCausingAura(AuraType auraType);
+ void RemoveRankAurasDueToSpell(uint32 spellId);
+ bool RemoveNoStackAurasDueToAura(Aura *Aur);
+ void RemoveAurasWithInterruptFlags(uint32 flags);
+ void RemoveAurasWithDispelType( DispelType type );
+
+ void RemoveAllAuras();
+ void RemoveArenaAuras(bool onleave = false);
+ void RemoveAllAurasOnDeath();
+ void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime);
+
+ float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); }
+ void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); }
+ void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModSignedFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); }
+ void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); }
+ void InitStatBuffMods()
+ {
+ for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_POSSTAT0+i, 0);
+ for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) SetFloatValue(UNIT_FIELD_NEGSTAT0+i, 0);
+ }
+ void ApplyStatBuffMod(Stats stat, float val, bool apply) { ApplyModSignedFloatValue((val > 0 ? UNIT_FIELD_POSSTAT0+stat : UNIT_FIELD_NEGSTAT0+stat), val, apply); }
+ void ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
+ {
+ ApplyPercentModFloatValue(UNIT_FIELD_POSSTAT0+stat, val, apply);
+ ApplyPercentModFloatValue(UNIT_FIELD_NEGSTAT0+stat, val, apply);
+ }
+ void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; }
+ void SetCreateHealth(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_HEALTH, val); }
+ uint32 GetCreateHealth() const { return GetUInt32Value(UNIT_FIELD_BASE_HEALTH); }
+ void SetCreateMana(uint32 val) { SetUInt32Value(UNIT_FIELD_BASE_MANA, val); }
+ uint32 GetCreateMana() const { return GetUInt32Value(UNIT_FIELD_BASE_MANA); }
+ uint32 GetCreatePowers(Powers power) const;
+ float GetPosStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_POSSTAT0+stat); }
+ float GetNegStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_NEGSTAT0+stat); }
+ float GetCreateStat(Stats stat) const { return m_createStats[stat]; }
+
+ void SetCurrentCastedSpell(Spell * pSpell);
+ virtual void ProhibitSpellScholl(SpellSchoolMask /*idSchoolMask*/, uint32 /*unTimeMs*/ ) { }
+ void InterruptSpell(uint32 spellType, bool withDelayed = true);
+
+ // set withDelayed to true to account delayed spells as casted
+ // delayed+channeled spells are always accounted as casted
+ // we can skip channeled or delayed checks using flags
+ bool IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled = false, bool skipAutorepeat = false) const;
+
+ // set withDelayed to true to interrupt delayed spells too
+ // delayed+channeled spells are always interrupted
+ void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0);
+
+ Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
+
+ Spell* m_currentSpells[CURRENT_MAX_SPELL];
+
+ uint32 m_addDmgOnce;
+ uint64 m_TotemSlot[MAX_TOTEM];
+ uint64 m_ObjectSlot[4];
+ uint32 m_detectInvisibilityMask;
+ uint32 m_invisibilityMask;
+ uint32 m_ShapeShiftFormSpellId;
+ ShapeshiftForm m_form;
+ float m_modMeleeHitChance;
+ float m_modRangedHitChance;
+ float m_modSpellHitChance;
+ int32 m_baseSpellCritChance;
+
+ float m_threatModifier[MAX_SPELL_SCHOOL];
+ float m_modAttackSpeedPct[3];
+
+ // Event handler
+ EventProcessor m_Events;
+
+ // stat system
+ bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply);
+ void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; }
+ float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const;
+ float GetTotalStatValue(Stats stat) const;
+ float GetTotalAuraModValue(UnitMods unitMod) const;
+ SpellSchools GetSpellSchoolByAuraGroup(UnitMods unitMod) const;
+ Stats GetStatByAuraGroup(UnitMods unitMod) const;
+ Powers GetPowerTypeByAuraGroup(UnitMods unitMod) const;
+ bool CanModifyStats() const { return m_canModifyStats; }
+ void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; }
+ virtual bool UpdateStats(Stats stat) = 0;
+ virtual bool UpdateAllStats() = 0;
+ virtual void UpdateResistances(uint32 school) = 0;
+ virtual void UpdateArmor() = 0;
+ virtual void UpdateMaxHealth() = 0;
+ virtual void UpdateMaxPower(Powers power) = 0;
+ virtual void UpdateAttackPowerAndDamage(bool ranged = false) = 0;
+ virtual void UpdateDamagePhysical(WeaponAttackType attType) = 0;
+ float GetTotalAttackPowerValue(WeaponAttackType attType) const;
+ float GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const;
+ void SetBaseWeaponDamage(WeaponAttackType attType ,WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; }
+
+ bool isInFront(Unit const* target,float distance, float arc = M_PI) const;
+ void SetInFront(Unit const* target);
+ bool isInBack(Unit const* target, float distance, float arc = M_PI) const;
+ bool isInLine(Unit const* target, float distance) const;
+
+ // Visibility system
+ UnitVisibility GetVisibility() const { return m_Visibility; }
+ void SetVisibility(UnitVisibility x);
+
+ // common function for visibility checks for player/creatures with detection code
+ virtual bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const;
+ bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false) const;
+ bool canDetectInvisibilityOf(Unit const* u) const;
+ bool canDetectStealthOf(Unit const* u, float distance) const;
+
+ // virtual functions for all world objects types
+ bool isVisibleForInState(Player const* u, bool inVisibleList) const;
+ // function for low level grid visibility checks in player/creature cases
+ virtual bool IsVisibleInGridForPlayer(Player const* pl) const = 0;
+
+ bool waterbreath;
+ AuraList & GetSingleCastAuras() { return m_scAuras; }
+ AuraList const& GetSingleCastAuras() const { return m_scAuras; }
+ SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
+
+ // Threat related methodes
+ bool CanHaveThreatList() const;
+ void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL);
+ float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL);
+ void DeleteThreatList();
+ bool SelectHostilTarget();
+ void TauntApply(Unit* pVictim);
+ void TauntFadeOut(Unit *taunter);
+ ThreatManager& getThreatManager() { return m_ThreatManager; }
+ void addHatedBy(HostilReference* pHostilReference) { m_HostilRefManager.insertFirst(pHostilReference); };
+ void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ }
+ HostilRefManager& getHostilRefManager() { return m_HostilRefManager; }
+
+ Aura* GetAura(uint32 spellId, uint32 effindex);
+ AuraMap & GetAuras() { return m_Auras; }
+ AuraMap const& GetAuras() const { return m_Auras; }
+ AuraList const& GetAurasByType(AuraType type) const { return m_modAuras[type]; }
+ void ApplyAuraProcTriggerDamage(Aura* aura, bool apply);
+
+ int32 GetTotalAuraModifier(AuraType auratype) const;
+ float GetTotalAuraMultiplier(AuraType auratype) const;
+ int32 GetMaxPositiveAuraModifier(AuraType auratype) const;
+ int32 GetMaxNegativeAuraModifier(AuraType auratype) const;
+
+ int32 GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const;
+ float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const;
+ int32 GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const;
+ int32 GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) const;
+
+ int32 GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
+ float GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_value) const;
+ int32 GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
+ int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_value) const;
+
+ Aura* GetDummyAura(uint32 spell_id) const;
+ uint32 GetInterruptMask() const { return m_interruptMask; }
+ void AddInterruptMask(uint32 mask) { m_interruptMask |= mask; }
+ void UpdateInterruptMask();
+
+ uint32 GetDisplayId() { return GetUInt32Value(UNIT_FIELD_DISPLAYID); }
+ void SetDisplayId(uint32 modelId);
+ uint32 GetNativeDisplayId() { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); }
+ void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); }
+ void setTransForm(uint32 spellid) { m_transform = spellid;}
+ uint32 getTransForm() const { return m_transform;}
+ void AddDynObject(DynamicObject* dynObj);
+ void RemoveDynObject(uint32 spellid);
+ void RemoveDynObjectWithGUID(uint64 guid) { m_dynObjGUIDs.remove(guid); }
+ void RemoveAllDynObjects();
+ void AddGameObject(GameObject* gameObj);
+ void RemoveGameObject(GameObject* gameObj, bool del);
+ void RemoveGameObject(uint32 spellid, bool del);
+ void RemoveAllGameObjects();
+ DynamicObject *GetDynObject(uint32 spellId, uint32 effIndex);
+ DynamicObject *GetDynObject(uint32 spellId);
+ uint32 CalculateDamage(WeaponAttackType attType, bool normalized);
+ float GetAPMultiplier(WeaponAttackType attType, bool normalized);
+ void ModifyAuraState(AuraState flag, bool apply);
+ bool HasAuraState(AuraState flag) const { return HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); }
+ void UnsummonAllTotems();
+ int32 SpellBaseDamageBonus(SpellSchoolMask schoolMask);
+ int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask);
+ int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim);
+ int32 SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim);
+ uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype);
+ uint32 SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim);
+ bool isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType);
+ uint32 SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim);
+
+ void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; }
+ bool IsUnderLastManaUseEffect() const;
+
+ void SetContestedPvP(Player *attackedPlayer = NULL);
+
+ void MeleeDamageBonus(Unit *pVictim, uint32 *damage, WeaponAttackType attType, SpellEntry const *spellProto = NULL);
+ uint32 GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime );
+
+ void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply);
+ void ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType type, bool apply);
+ virtual bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false);
+ // redefined in Creature
+ bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask, bool useCharges = false);
+ virtual bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const;
+ // redefined in Creature
+
+ uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage);
+ void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist);
+
+ void UpdateSpeed(UnitMoveType mtype, bool forced);
+ float GetSpeed( UnitMoveType mtype ) const;
+ float GetSpeedRate( UnitMoveType mtype ) const { return m_speed_rate[mtype]; }
+ void SetSpeed(UnitMoveType mtype, float rate, bool forced = false);
+
+ void SetHover(bool on);
+ bool isHover() const { return HasAuraType(SPELL_AURA_HOVER); }
+
+ void _RemoveAllAuraMods();
+ void _ApplyAllAuraMods();
+
+ int32 CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 basePoints, Unit const* target);
+ int32 CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target);
+ float CalculateLevelPenalty(SpellEntry const* spellProto) const;
+
+ void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); }
+ void removeFollower(FollowerReference* /*pRef*/ ) { /* nothing to do yet */ }
+ static Unit* GetUnit(WorldObject& object, uint64 guid);
+
+ MotionMaster* GetMotionMaster() { return &i_motionMaster; }
+
+ bool IsStopped() const { return !(hasUnitState(UNIT_STAT_MOVING)); }
+ void StopMoving();
+
+ void AddUnitMovementFlag(uint32 f) { m_unit_movement_flags |= f; }
+ void RemoveUnitMovementFlag(uint32 f)
+ {
+ uint32 oldval = m_unit_movement_flags;
+ m_unit_movement_flags = oldval & ~f;
+ }
+ uint32 HasUnitMovementFlag(uint32 f) const { return m_unit_movement_flags & f; }
+ uint32 GetUnitMovementFlags() const { return m_unit_movement_flags; }
+ void SetUnitMovementFlags(uint32 f) { m_unit_movement_flags = f; }
+
+ void SetFeared(bool apply, uint64 casterGUID = 0, uint32 spellID = 0);
+ void SetConfused(bool apply, uint64 casterGUID = 0, uint32 spellID = 0);
+
+ void AddComboPointHolder(uint32 lowguid) { m_ComboPointHolders.insert(lowguid); }
+ void RemoveComboPointHolder(uint32 lowguid) { m_ComboPointHolders.erase(lowguid); }
+ void ClearComboPointHolders();
+
+ ///----------Pet responses methods-----------------
+ void SendPetCastFail(uint32 spellid, uint8 msg);
+ void SendPetActionFeedback (uint8 msg);
+ void SendPetTalk (uint32 pettalk);
+ void SendPetSpellCooldown (uint32 spellid, time_t cooltime);
+ void SendPetClearCooldown (uint32 spellid);
+ void SendPetAIReaction(uint64 guid);
+ ///----------End of Pet responses methods----------
+
+ void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); }
+
+ // reactive attacks
+ void ClearAllReactives();
+ void StartReactiveTimer( ReactiveType reactive ) { m_reactiveTimer[reactive] = REACTIVE_TIMER_START;}
+ void UpdateReactives(uint32 p_time);
+
+ // group updates
+ void UpdateAuraForGroup(uint8 slot);
+
+ // pet auras
+ typedef std::set<PetAura const*> PetAuraSet;
+ PetAuraSet m_petAuras;
+ void AddPetAura(PetAura const* petSpell);
+ void RemovePetAura(PetAura const* petSpell);
+
+ protected:
+ explicit Unit ();
+
+ void _UpdateSpells(uint32 time);
+
+ void _UpdateAutoRepeatSpell();
+ bool m_AutoRepeatFirstCast;
+
+ uint32 m_attackTimer[MAX_ATTACK];
+
+ float m_createStats[MAX_STATS];
+
+ AttackerSet m_attackers;
+ Unit* m_attacking;
+
+ DeathState m_deathState;
+
+ AuraMap m_Auras;
+
+ std::list<Aura *> m_scAuras; // casted singlecast auras
+
+ typedef std::list<uint64> DynObjectGUIDs;
+ DynObjectGUIDs m_dynObjGUIDs;
+
+ std::list<GameObject*> m_gameObj;
+ bool m_isSorted;
+ uint32 m_transform;
+ uint32 m_removedAuras;
+
+ AuraList m_modAuras[TOTAL_AURAS];
+ uint32 m_interruptMask;
+ AuraList m_interruptableAuras;
+ AuraList m_ccAuras;
+ float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
+ float m_weaponDamage[MAX_ATTACK][2];
+ bool m_canModifyStats;
+ //std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem
+
+ float m_speed_rate[MAX_MOVE_TYPE];
+
+ CharmInfo *m_charmInfo;
+ bool m_isPossessed;
+ SharedVisionList m_sharedVision;
+
+ virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
+
+ MotionMaster i_motionMaster;
+ uint32 m_unit_movement_flags;
+
+ uint32 m_reactiveTimer[MAX_REACTIVE];
+
+ private:
+ void SendAttackStop(Unit* victim); // only from AttackStop(Unit*)
+ //void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*)
+
+ void ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, AuraTypeSet const& procAuraTypes, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage, SpellSchoolMask damageSchoolMask );
+ bool IsTriggeredAtSpellProcEvent( SpellEntry const* spellProto, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, bool isVictim, uint32& cooldown );
+ bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 cooldown);
+ bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, WeaponAttackType attType, uint32 cooldown);
+ bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const* procSpell, uint32 procFlag, uint32 cooldown);
+ bool HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 cooldown);
+ bool HandleMeandingAuraProc(Aura* triggeredByAura);
+
+ uint32 m_state; // Even derived shouldn't modify
+ uint32 m_CombatTimer;
+ uint32 m_lastManaUse; // msecs
+
+ UnitVisibility m_Visibility;
+
+ Diminishing m_Diminishing;
+ // Manage all Units threatening us
+ ThreatManager m_ThreatManager;
+ // Manage all Units that are threatened by us
+ HostilRefManager m_HostilRefManager;
+
+ FollowerRefManager m_FollowingRefManager;
+
+ ComboPointHolderSet m_ComboPointHolders;
+};
+#endif
|