diff options
-rw-r--r-- | src/game/SpellAuras.cpp | 12688 | ||||
-rw-r--r-- | src/game/SpellHandler.cpp | 984 | ||||
-rw-r--r-- | src/game/Unit.cpp | 373 | ||||
-rw-r--r-- | src/game/Unit.h | 2791 |
4 files changed, 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 |