aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/SpellAuras.cpp12688
-rw-r--r--src/game/SpellHandler.cpp984
-rw-r--r--src/game/Unit.cpp373
-rw-r--r--src/game/Unit.h2791
4 files changed, 8389 insertions, 8447 deletions
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index 4c98d590a9d..37c02fb549d 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -1,6349 +1,6339 @@
-/*
- * 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);
-}
+/*
+ * 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);
+}
diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp
index 830dcc4d9a6..3ed9c04a259 100644
--- a/src/game/SpellHandler.cpp
+++ b/src/game/SpellHandler.cpp
@@ -1,496 +1,488 @@
-/*
- * 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);
- }
-}
+/*
+ * 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);
+ }
+}
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index e0345950ffc..22249af36d6 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -4094,17 +4094,12 @@ void Unit::RemoveNotOwnSingleTargetAuras()
void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
{
- Aura* Aur = i->second;
- SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
-
- Unit* caster = NULL;
- if (IsSingleTargetSpell(AurSpellInfo))
+ if (IsSingleTargetSpell((*i).second->GetSpellProto()))
{
- caster = Aur->GetCaster();
- if(caster)
+ if(Unit* caster = (*i).second->GetCaster())
{
AuraList& scAuras = caster->GetSingleCastAuras();
- scAuras.remove(Aur);
+ scAuras.remove((*i).second);
}
else
{
@@ -4113,19 +4108,20 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
}
}
- // 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)
+ if ((*i).second->GetModifier()->m_auraname < TOTAL_AURAS)
{
- m_modAuras[Aur->GetModifier()->m_auraname].remove(Aur);
- if(Aur->GetSpellProto()->AuraInterruptFlags)
+ m_modAuras[(*i).second->GetModifier()->m_auraname].remove((*i).second);
+ if((*i).second->GetSpellProto()->AuraInterruptFlags)
{
- m_interruptableAuras.remove(Aur);
+ m_interruptableAuras.remove((*i).second);
UpdateInterruptMask();
}
- if(Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE)
- m_ccAuras.remove(Aur);
+ if((*i).second->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE)
+ m_ccAuras.remove((*i).second);
}
+ // 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
@@ -4133,22 +4129,12 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
m_Auras.erase(i);
++m_removedAuras; // internal count used by unit update
- // Statue unsummoned at aura remove
+ // Status unsummoned at aura remove
Totem* statue = NULL;
- bool caster_channeled = false;
- if(IsChanneledSpell(AurSpellInfo))
- {
- if(!caster) // can be already located for IsSingleTargetSpell case
- caster = Aur->GetCaster();
-
- if(caster)
- {
+ if(IsChanneledSpell(Aur->GetSpellProto()))
+ if(Unit* caster = Aur->GetCaster())
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))
@@ -4167,9 +4153,6 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
Aur->_RemoveAura();
delete Aur;
- if(caster_channeled)
- RemoveAurasAtChanneledTarget (AurSpellInfo);
-
if(statue)
statue->UnSummon();
@@ -4595,10 +4578,8 @@ void Unit::CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchool
ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, damageSchoolMask, spellCasted, isTriggeredSpell, attType);
}
-bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * /*procSpell*/, uint32 /*procFlag*/, uint32 cooldown)
+bool Unit::HandleHasteAuraProc(Unit *pVictim, SpellEntry const *hasteSpell, uint32 /*effIndex*/, 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;
@@ -4658,11 +4639,8 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
return true;
}
-bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 cooldown)
+bool Unit::HandleDummyAuraProc(Unit *pVictim, SpellEntry const *dummySpell, uint32 effIndex, 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;
@@ -6480,10 +6458,8 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
return true;
}
-bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown)
+bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint32 damage, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown)
{
- int32 scriptId = triggeredByAura->GetModifier()->m_miscvalue;
-
if(!pVictim || !pVictim->isAlive())
return false;
@@ -9947,15 +9923,17 @@ bool Unit::isFrozen() const
struct ProcTriggeredData
{
- ProcTriggeredData(Aura* _triggeredByAura, uint32 _cooldown)
- : triggeredByAura(_triggeredByAura),
+ ProcTriggeredData(SpellEntry const * _spellInfo, uint32 _spellParam, Aura* _triggeredByAura, uint32 _cooldown)
+ : spellInfo(_spellInfo), spellParam(_spellParam), triggeredByAura(_triggeredByAura),
triggeredByAura_SpellPair(Unit::spellEffectPair(triggeredByAura->GetId(),triggeredByAura->GetEffIndex())),
cooldown(_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
+ SpellEntry const * spellInfo;
+ uint32 spellParam;
+ Aura* triggeredByAura;
+ Unit::spellEffectPair triggeredByAura_SpellPair;
+ uint32 cooldown;
};
typedef std::list< ProcTriggeredData > ProcTriggeredList;
@@ -9972,13 +9950,87 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
{
next = i; ++next;
- Aura* i_aura = *i;
+ SpellEntry const *spellProto = (*i)->GetSpellProto();
+ if(!spellProto)
+ continue;
- uint32 cooldown; // returned at next line
- if(!IsTriggeredAtSpellProcEvent(i_aura->GetSpellProto(), procSpell, procFlag,attType,isVictim,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.
continue;
+ }
- procTriggered.push_back( ProcTriggeredData(i_aura, cooldown) );
+ // 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) );
+ }
}
// Handle effects proceed this time
@@ -10011,66 +10063,106 @@ 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 = triggeredByAura->m_procCharges > 0;
+ bool triggeredByAuraWithCharges = i->triggeredByAura->m_procCharges > 0;
bool casted = false;
switch(*aur)
{
case SPELL_AURA_PROC_TRIGGER_SPELL:
{
- 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);
+ 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);
break;
}
case SPELL_AURA_PROC_TRIGGER_DAMAGE:
{
- 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);
+ 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);
casted = true;
break;
}
case SPELL_AURA_DUMMY:
{
- 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);
+ 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);
break;
}
case SPELL_AURA_PRAYER_OF_MENDING:
{
- sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)",
- (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId());
+ 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));
- casted = HandleMeandingAuraProc(triggeredByAura);
+ 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;
break;
}
case SPELL_AURA_MOD_HASTE:
{
- 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);
+ 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);
break;
}
case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
{
// nothing do, just charges counter
// but count only in case appropriate school damage
- casted = triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask;
+ casted = i->triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask;
break;
}
case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS:
{
- 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);
+ 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);
break;
}
default:
@@ -10718,132 +10810,3 @@ 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 1ec669bcfd3..028c590c06f 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1,1397 +1,1394 @@
-/*
- * 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
+/*
+ * 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