Files
TCPlayerbotCore/src/server/game/Spells/Auras/SpellAuraEffects.cpp
T
XTZGZoReX 946adf469c *** New core <-> script library interface - complete rewrite of the old one.
* Removed the misdesigned on_events script/hooks.
* Lots of related cleanups and assertions.
* The interface is now fully object-oriented.
** Scripts no longer use function pointers.
** Scripts no longer use the general-purpose Script struct for everything.
** Script types are split into separate classes which must be inherited depending on what functionality is desired.
* Several script types have been added to allow extending functionality in a code-only manner (some script types require
  assignment in the recently added ScriptName columns in the database, though).
** SpellHandlerScript: Wrapper around spell scripts (returns new SpellScript objects (`spell_script_names`.`ScriptName`)).
** ServerScript: Allows scripting events that occur in the network layer.
** WorldScript: Allows scripting certain world-global events.
** FormulaScript: Allows hooking and interfering with core formulas.
** *MapScript: Allows hooking different map types (including world, instance, and battleground maps (`instance_template`.`ScriptName`)).
** ItemScript: Allows scripting of items (like the old interface (`item_template`.`ScriptName`)).
** CreatureScript: Allows scripting of creatures/AI (like the old interface (`creature_template`.`ScriptName`)).
** GameObjectScript: Allows scripting of gameobjects (like the old interface (`gameobject_template`.`ScriptName`)).
** AreaTriggerScript: Allows scripting triggered area triggers (like the old interface (`areatrigger_scripts`.`ScriptName`)).
** OutdoorPvPScript: Script which should return OutdoorPvP objects for use by OutdoorPvPMgr (`outdoorpvp_template`.`ScriptName`).
** CommandScript: Allows extending the in-core command table.
** WeatherScript: Allows scripting of weather changes (`game_weather`.`ScriptName`).
** AuctionHouseScript: Allows scripting of auction events.
** ConditionScript: Allows scripting of conditions (`conditions`.`ScriptName`).
** DynamicObjectScript: Allows scripting of dynamicobjects.
** TransportScript: Allows scripting of transport events (`transports`.`ScriptName`).
* OutdoorPvP objects are now created through scripts. This effectively means that they'll need to be moved to scripts
  before the they're functional again.
* The whole idea with this new interface is to allow expanding core functionality without touching core code. If further
  hooks are needed to expand functionality of the core, let us know; we'll add them, if we agree that it is appropriate
  to do so.
*** NOTE: The scripts project will _not_ build before it has been adapted to the new interface.
*** Thanks to everyone who helped out with related preparations and suggestions!

--HG--
branch : trunk
2010-08-06 19:23:43 +02:00

6288 lines
263 KiB
C++

/*
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* Copyright (C) 2008-2010 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 "WorldPacket.h"
#include "Opcodes.h"
#include "Log.h"
#include "ObjectMgr.h"
#include "SpellMgr.h"
#include "Player.h"
#include "Unit.h"
#include "ObjectAccessor.h"
#include "Util.h"
#include "Spell.h"
#include "SpellAuraEffects.h"
#include "BattleGround.h"
#include "OutdoorPvPMgr.h"
#include "Formulas.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "ScriptMgr.h"
class Aura;
//
// EFFECT HANDLER NOTES
//
// in aura handler there should be check for modes:
// AURA_EFFECT_HANDLE_REAL set - aura mod is just applied/removed on the target
// AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK set - aura is just applied/removed, or aura packet request is made
// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK set - aura is recalculated or is just applied/removed - need to redo all things related to m_amount
// AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK - logical or of above conditions
// AURA_EFFECT_HANDLE_STAT - set when stats are reapplied
// such checks will speedup trinity change amount/send for client operations
// because for change amount operation packets will not be send
// aura effect handlers shouldn't contain any AuraEffect or Aura object modifications
pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]=
{
&AuraEffect::HandleNULL, // 0 SPELL_AURA_NONE
&AuraEffect::HandleBindSight, // 1 SPELL_AURA_BIND_SIGHT
&AuraEffect::HandleModPossess, // 2 SPELL_AURA_MOD_POSSESS
&AuraEffect::HandleNoImmediateEffect, // 3 SPELL_AURA_PERIODIC_DAMAGE implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleAuraDummy, // 4 SPELL_AURA_DUMMY
&AuraEffect::HandleModConfuse, // 5 SPELL_AURA_MOD_CONFUSE
&AuraEffect::HandleModCharm, // 6 SPELL_AURA_MOD_CHARM
&AuraEffect::HandleModFear, // 7 SPELL_AURA_MOD_FEAR
&AuraEffect::HandleNoImmediateEffect, // 8 SPELL_AURA_PERIODIC_HEAL implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleModAttackSpeed, // 9 SPELL_AURA_MOD_ATTACKSPEED
&AuraEffect::HandleModThreat, // 10 SPELL_AURA_MOD_THREAT
&AuraEffect::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT
&AuraEffect::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN
&AuraEffect::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE
&AuraEffect::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&AuraEffect::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage
&AuraEffect::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH
&AuraEffect::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_DETECT implement in GameObject::canDetectTrap and Unit::canDetectStealthOf
&AuraEffect::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY
&AuraEffect::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION
&AuraEffect::HandleNoImmediateEffect, // 20 SPELL_AURA_OBS_MOD_HEALTH implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, // 21 SPELL_AURA_OBS_MOD_POWER implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE
&AuraEffect::HandleNoImmediateEffect, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, // 24 SPELL_AURA_PERIODIC_ENERGIZE implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY
&AuraEffect::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT
&AuraEffect::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE
&AuraEffect::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult
&AuraEffect::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT
&AuraEffect::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL
&AuraEffect::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED
&AuraEffect::HandleAuraModIncreaseMountedSpeed, // 32 SPELL_AURA_MOD_INCREASE_MOUNTED_SPEED
&AuraEffect::HandleAuraModDecreaseSpeed, // 33 SPELL_AURA_MOD_DECREASE_SPEED
&AuraEffect::HandleAuraModIncreaseHealth, // 34 SPELL_AURA_MOD_INCREASE_HEALTH
&AuraEffect::HandleAuraModIncreaseEnergy, // 35 SPELL_AURA_MOD_INCREASE_ENERGY
&AuraEffect::HandleAuraModShapeshift, // 36 SPELL_AURA_MOD_SHAPESHIFT
&AuraEffect::HandleAuraModEffectImmunity, // 37 SPELL_AURA_EFFECT_IMMUNITY
&AuraEffect::HandleAuraModStateImmunity, // 38 SPELL_AURA_STATE_IMMUNITY
&AuraEffect::HandleAuraModSchoolImmunity, // 39 SPELL_AURA_SCHOOL_IMMUNITY
&AuraEffect::HandleAuraModDmgImmunity, // 40 SPELL_AURA_DAMAGE_IMMUNITY
&AuraEffect::HandleAuraModDispelImmunity, // 41 SPELL_AURA_DISPEL_IMMUNITY
&AuraEffect::HandleNoImmediateEffect, // 42 SPELL_AURA_PROC_TRIGGER_SPELL implemented in Unit::ProcDamageAndSpellFor and Unit::HandleProcTriggerSpell
&AuraEffect::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor
&AuraEffect::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES
&AuraEffect::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES
&AuraEffect::HandleNULL, // 46 SPELL_AURA_46 (used in test spells 54054 and 54058, and spell 48050) (3.0.8a)
&AuraEffect::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT
&AuraEffect::HandleNULL, // 48 SPELL_AURA_48 spell Napalm (area damage spell with additional delayed damage effect)
&AuraEffect::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT
&AuraEffect::HandleNoImmediateEffect, // 50 SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT implemented in Unit::SpellCriticalHealingBonus
&AuraEffect::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT
&AuraEffect::HandleAuraModWeaponCritPercent, // 52 SPELL_AURA_MOD_WEAPON_CRIT_PERCENT
&AuraEffect::HandleNoImmediateEffect, // 53 SPELL_AURA_PERIODIC_LEECH implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleModHitChance, // 54 SPELL_AURA_MOD_HIT_CHANCE
&AuraEffect::HandleModSpellHitChance, // 55 SPELL_AURA_MOD_SPELL_HIT_CHANCE
&AuraEffect::HandleAuraTransform, // 56 SPELL_AURA_TRANSFORM
&AuraEffect::HandleModSpellCritChance, // 57 SPELL_AURA_MOD_SPELL_CRIT_CHANCE
&AuraEffect::HandleAuraModIncreaseSwimSpeed, // 58 SPELL_AURA_MOD_INCREASE_SWIM_SPEED
&AuraEffect::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&AuraEffect::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE
&AuraEffect::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE
&AuraEffect::HandleNoImmediateEffect, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNULL, // 63 unused (3.2.0) old SPELL_AURA_PERIODIC_MANA_FUNNEL
&AuraEffect::HandleNoImmediateEffect, // 64 SPELL_AURA_PERIODIC_MANA_LEECH implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK
&AuraEffect::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH
&AuraEffect::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM
&AuraEffect::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED
&AuraEffect::HandleNoImmediateEffect, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist
&AuraEffect::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS clientside
&AuraEffect::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL
&AuraEffect::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
&AuraEffect::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL
&AuraEffect::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult
&AuraEffect::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE
&AuraEffect::HandleNoImmediateEffect, // 76 SPELL_AURA_FAR_SIGHT
&AuraEffect::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY
&AuraEffect::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED
&AuraEffect::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE
&AuraEffect::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT
&AuraEffect::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT implemented in Unit::CalcAbsorbResist
&AuraEffect::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING
&AuraEffect::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE
&AuraEffect::HandleNoImmediateEffect, // 84 SPELL_AURA_MOD_REGEN implemented in Player::RegenerateHealth
&AuraEffect::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN implemented in Player::Regenerate
&AuraEffect::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM
&AuraEffect::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus
&AuraEffect::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT implemented in Player::RegenerateHealth
&AuraEffect::HandleNoImmediateEffect, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT
&AuraEffect::HandleNULL, // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE
&AuraEffect::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance
&AuraEffect::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING
&AuraEffect::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE
&AuraEffect::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::Regenerate
&AuraEffect::HandleAuraGhost, // 95 SPELL_AURA_GHOST
&AuraEffect::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Unit::SelectMagnetTarget
&AuraEffect::HandleNoImmediateEffect, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist
&AuraEffect::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT
&AuraEffect::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER
&AuraEffect::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now, but still have spells including GM-spell
&AuraEffect::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT
&AuraEffect::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
&AuraEffect::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT
&AuraEffect::HandleAuraWaterWalk, //104 SPELL_AURA_WATER_WALK
&AuraEffect::HandleAuraFeatherFall, //105 SPELL_AURA_FEATHER_FALL
&AuraEffect::HandleAuraHover, //106 SPELL_AURA_HOVER
&AuraEffect::HandleNoImmediateEffect, //107 SPELL_AURA_ADD_FLAT_MODIFIER implemented in AuraEffect::CalculateSpellMod()
&AuraEffect::HandleNoImmediateEffect, //108 SPELL_AURA_ADD_PCT_MODIFIER implemented in AuraEffect::CalculateSpellMod()
&AuraEffect::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER
&AuraEffect::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT implemented in Player::Regenerate, Creature::Regenerate
&AuraEffect::HandleNoImmediateEffect, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER implemented in Unit::SelectMagnetTarget
&AuraEffect::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS
&AuraEffect::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
&AuraEffect::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
&AuraEffect::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim
&AuraEffect::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT
&AuraEffect::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult
&AuraEffect::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus
&AuraEffect::HandleNULL, //119 unused (3.2.0) old SPELL_AURA_SHARE_PET_TRACKING
&AuraEffect::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE
&AuraEffect::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY
&AuraEffect::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT
&AuraEffect::HandleModTargetResistance, //123 SPELL_AURA_MOD_TARGET_RESISTANCE
&AuraEffect::HandleAuraModRangedAttackPower, //124 SPELL_AURA_MOD_RANGED_ATTACK_POWER
&AuraEffect::HandleNoImmediateEffect, //125 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus
&AuraEffect::HandleNoImmediateEffect, //126 SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus
&AuraEffect::HandleNoImmediateEffect, //127 SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
&AuraEffect::HandleModPossessPet, //128 SPELL_AURA_MOD_POSSESS_PET
&AuraEffect::HandleAuraModIncreaseSpeed, //129 SPELL_AURA_MOD_SPEED_ALWAYS
&AuraEffect::HandleAuraModIncreaseMountedSpeed, //130 SPELL_AURA_MOD_MOUNTED_SPEED_ALWAYS
&AuraEffect::HandleNoImmediateEffect, //131 SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus
&AuraEffect::HandleAuraModIncreaseEnergyPercent, //132 SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT
&AuraEffect::HandleAuraModIncreaseHealthPercent, //133 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT
&AuraEffect::HandleAuraModRegenInterrupt, //134 SPELL_AURA_MOD_MANA_REGEN_INTERRUPT
&AuraEffect::HandleModHealingDone, //135 SPELL_AURA_MOD_HEALING_DONE
&AuraEffect::HandleNoImmediateEffect, //136 SPELL_AURA_MOD_HEALING_DONE_PERCENT implemented in Unit::SpellHealingBonus
&AuraEffect::HandleModTotalPercentStat, //137 SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE
&AuraEffect::HandleHaste, //138 SPELL_AURA_MOD_HASTE
&AuraEffect::HandleForceReaction, //139 SPELL_AURA_FORCE_REACTION
&AuraEffect::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
&AuraEffect::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE
&AuraEffect::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
&AuraEffect::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE
&AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
&AuraEffect::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS
&AuraEffect::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
&AuraEffect::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK
&AuraEffect::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS
&AuraEffect::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK
&AuraEffect::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT
&AuraEffect::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED
&AuraEffect::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance
&AuraEffect::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT
&AuraEffect::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL
&AuraEffect::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING
&AuraEffect::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN
&AuraEffect::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI
&AuraEffect::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE
&AuraEffect::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell
&AuraEffect::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult
&AuraEffect::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT
&AuraEffect::HandleNoImmediateEffect, //162 SPELL_AURA_POWER_BURN_MANA implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE
&AuraEffect::HandleUnused, //164 unused (3.2.0), only one test spell
&AuraEffect::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus
&AuraEffect::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT
&AuraEffect::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT
&AuraEffect::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus
&AuraEffect::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus
&AuraEffect::HandleNULL, //170 SPELL_AURA_DETECT_AMORE various spells that change visual of units for aura target (clientside?)
&AuraEffect::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK
&AuraEffect::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK
&AuraEffect::HandleNULL, //173 unused (3.2.0) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell
&AuraEffect::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus
&AuraEffect::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus
&AuraEffect::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end
&AuraEffect::HandleCharmConvert, //177 SPELL_AURA_AOE_CHARM
&AuraEffect::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult
&AuraEffect::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus
&AuraEffect::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
&AuraEffect::HandleNULL, //181 unused (3.2.0) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS
&AuraEffect::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
&AuraEffect::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 - miscvalue - spell school
&AuraEffect::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
&AuraEffect::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
&AuraEffect::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult
&AuraEffect::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
&AuraEffect::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance
&AuraEffect::HandleModRating, //189 SPELL_AURA_MOD_RATING
&AuraEffect::HandleNoImmediateEffect, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN implemented in Player::CalculateReputationGain
&AuraEffect::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED
&AuraEffect::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE
&AuraEffect::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct)
&AuraEffect::HandleNoImmediateEffect, //194 SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist
&AuraEffect::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist
&AuraEffect::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN - flat mod of spell cooldowns
&AuraEffect::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance
&AuraEffect::HandleNULL, //198 unused (3.2.0) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS
&AuraEffect::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult
&AuraEffect::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::RewardPlayerAndGroupAtKill
&AuraEffect::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode...
&AuraEffect::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst
&AuraEffect::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
&AuraEffect::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage
&AuraEffect::HandleNULL, //205 SPELL_AURA_MOD_SCHOOL_CRIT_DMG_TAKEN
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //206 SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //210 SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS
&AuraEffect::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK
&AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT
&AuraEffect::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage
&AuraEffect::HandleNULL, //214 Tamed Pet Passive
&AuraEffect::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION
&AuraEffect::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS
&AuraEffect::HandleNULL, //217 69106 - killing spree helper - unknown use
&AuraEffect::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
&AuraEffect::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
&AuraEffect::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT
&AuraEffect::HandleNULL, //221 SPELL_AURA_MOD_DETAUNT
&AuraEffect::HandleUnused, //222 unused (3.2.0) only for spell 44586 that not used in real spell cast
&AuraEffect::HandleNoImmediateEffect, //223 SPELL_AURA_RAID_PROC_FROM_CHARGE
&AuraEffect::HandleUnused, //224 unused (3.0.8a)
&AuraEffect::HandleNoImmediateEffect, //225 SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE
&AuraEffect::HandleNoImmediateEffect, //226 SPELL_AURA_PERIODIC_DUMMY implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, //228 SPELL_AURA_DETECT_STEALTH stealth detection
&AuraEffect::HandleNoImmediateEffect, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
&AuraEffect::HandleAuraModIncreaseHealth, //230 SPELL_AURA_MOD_INCREASE_HEALTH_2
&AuraEffect::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
&AuraEffect::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
&AuraEffect::HandleUnused, //233 set model id to the one of the creature with id GetMiscValue() - clientside
&AuraEffect::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
&AuraEffect::HandleNoImmediateEffect, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
&AuraEffect::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE
&AuraEffect::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus
&AuraEffect::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus
&AuraEffect::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61
&AuraEffect::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE
&AuraEffect::HandleForceMoveForward, //241 SPELL_AURA_FORCE_MOVE_FORWARD Forces the player to move forward
&AuraEffect::HandleNULL, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING - 2 test spells: 44183 and 44182
&AuraEffect::HandleAuraModFaction, //243 SPELL_AURA_MOD_FACTION
&AuraEffect::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE
&AuraEffect::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL
&AuraEffect::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura
&AuraEffect::HandleAuraCloneCaster, //247 SPELL_AURA_CLONE_CASTER
&AuraEffect::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
&AuraEffect::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
&AuraEffect::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2
&AuraEffect::HandleNoImmediateEffect, //251 SPELL_AURA_MOD_ENEMY_DODGE
&AuraEffect::HandleModCombatSpeedPct, //252 SPELL_AURA_252 Is there any difference between this and SPELL_AURA_MELEE_SLOW ? maybe not stacking mod?
&AuraEffect::HandleNoImmediateEffect, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE implemented in Unit::isBlockCritical
&AuraEffect::HandleAuraModDisarm, //254 SPELL_AURA_MOD_DISARM_OFFHAND
&AuraEffect::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus
&AuraEffect::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL
&AuraEffect::HandleNoImmediateEffect, //259 SPELL_AURA_MOD_HOT_PCT implemented in Unit::SpellHealingBonus
&AuraEffect::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code
&AuraEffect::HandlePhase, //261 SPELL_AURA_PHASE undetactable invisibility? implemented in Unit::isVisibleForOrDetect
&AuraEffect::HandleNoImmediateEffect, //262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in spell::cancast
&AuraEffect::HandleAuraAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask
&AuraEffect::HandleUnused, //264 unused (3.2.0)
&AuraEffect::HandleUnused, //265 unused (3.2.0)
&AuraEffect::HandleUnused, //266 unused (3.2.0)
&AuraEffect::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect
&AuraEffect::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT
&AuraEffect::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
&AuraEffect::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage
&AuraEffect::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus
&AuraEffect::HandleNoImmediateEffect, //272 SPELL_AURA_IGNORE_MELEE_RESET
&AuraEffect::HandleUnused, //273 clientside
&AuraEffect::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets
&AuraEffect::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select
&AuraEffect::HandleNULL, //276 mod damage % mechanic?
&AuraEffect::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap
&AuraEffect::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon
&AuraEffect::HandleNoImmediateEffect, //279 SPELL_AURA_INITIALIZE_IMAGES
&AuraEffect::HandleNoImmediateEffect, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT
&AuraEffect::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor
&AuraEffect::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT
&AuraEffect::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
&AuraEffect::HandleAuraLinked, //284 SPELL_AURA_LINKED
&AuraEffect::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage
&AuraEffect::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in AuraEffect::PeriodicTick
&AuraEffect::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult
&AuraEffect::HandleNoImmediateEffect, //288 SPELL_AURA_IGNORE_HIT_DIRECTION implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst
&AuraEffect::HandleNULL, //289 unused (3.2.0)
&AuraEffect::HandleAuraModCritPct, //290 SPELL_AURA_MOD_CRIT_PCT
&AuraEffect::HandleNoImmediateEffect, //291 SPELL_AURA_MOD_XP_QUEST_PCT implemented in Player::RewardQuest
&AuraEffect::HandleAuraOpenStable, //292 SPELL_AURA_OPEN_STABLE
&AuraEffect::HandleNULL, //293 auras which probably add set of abilities to their target based on it's miscvalue
&AuraEffect::HandleNoImmediateEffect, //294 SPELL_AURA_PREVENT_REGENERATE_POWER implemented in Player::Regenerate(Powers power)
&AuraEffect::HandleNULL, //295 0 spells in 3.3.5
&AuraEffect::HandleNULL, //296 6 spells, something vehicle or character display related
&AuraEffect::HandleNULL, //297 Spirit Burst spells
&AuraEffect::HandleNULL, //298 70569 - Strangulating, maybe prevents talk or cast
&AuraEffect::HandleNULL, //299 unused
&AuraEffect::HandleNoImmediateEffect, //300 SPELL_AURA_SHARE_DAMAGE_PCT implemented in Unit::DealDamage
&AuraEffect::HandleNoImmediateEffect, //301 SPELL_AURA_SCHOOL_HEAL_ABSORB implemented in Unit::CalcHealAbsorb
&AuraEffect::HandleNULL, //302 0 spells in 3.3.5
&AuraEffect::HandleNULL, //303 SPELL_AURA_MOD_DMG_VERSUS_AURASTATE_PCT? - 22 and 19 look like serverside aurastates (22 - dark, gas cloud, 19 light, ooze)
&AuraEffect::HandleUnused, //304 clientside
&AuraEffect::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED
&AuraEffect::HandleNULL, //306 0 spells in 3.3.5
&AuraEffect::HandleNULL, //307 0 spells in 3.3.5
&AuraEffect::HandleNULL, //308 new aura for hunter traps
&AuraEffect::HandleNULL, //309 0 spells in 3.3.5
&AuraEffect::HandleNoImmediateEffect, //310 SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE implemented in Spell::CalculateDamageDone
&AuraEffect::HandleNULL, //311 0 spells in 3.3.5
&AuraEffect::HandleNULL, //312 0 spells in 3.3.5
&AuraEffect::HandleNULL, //313 0 spells in 3.3.5
&AuraEffect::HandleNoImmediateEffect, //314 SPELL_AURA_PREVENT_RESSURECTION todo
&AuraEffect::HandleNoImmediateEffect, //315 SPELL_AURA_UNDERWATER_WALKING todo
&AuraEffect::HandleNoImmediateEffect, //316 SPELL_AURA_PERIODIC_HASTE implemented in AuraEffect::CalculatePeriodic
};
AuraEffect::AuraEffect(Aura * base, uint8 effIndex, int32 *baseAmount, Unit * caster) :
m_base(base), m_spellProto(base->GetSpellProto()), m_spellmod(NULL), m_periodicTimer(0),
m_tickNumber(0), m_effIndex(effIndex), m_isPeriodic(false), m_canBeRecalculated(true),
m_baseAmount (baseAmount ? *baseAmount : m_spellProto->EffectBasePoints[m_effIndex])
{
CalculatePeriodic(caster, true);
m_amount = CalculateAmount(caster);
CalculateSpellMod();
}
AuraEffect::~AuraEffect()
{
delete m_spellmod;
}
void AuraEffect::GetTargetList(std::list<Unit *> & targetList) const
{
Aura::ApplicationMap const & targetMap = GetBase()->GetApplicationMap();
// remove all targets which were not added to new list - they no longer deserve area aura
for (Aura::ApplicationMap::const_iterator appIter = targetMap.begin(); appIter != targetMap.end(); ++appIter)
{
if (appIter->second->HasEffect(GetEffIndex()))
targetList.push_back(appIter->second->GetTarget());
}
}
int32 AuraEffect::CalculateAmount(Unit * caster)
{
int32 amount;
// default amount calculation
amount = SpellMgr::CalculateSpellEffectAmount(m_spellProto, m_effIndex, caster, &m_baseAmount, NULL);
// check item enchant aura cast
if (!amount && caster)
if (uint64 itemGUID = GetBase()->GetCastItemGUID())
if (Player *playerCaster = dynamic_cast<Player*>(caster))
if (Item *castItem = playerCaster->GetItemByGuid(itemGUID))
if (castItem->GetItemSuffixFactor())
{
ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId()));
if (item_rand_suffix)
{
for (int k=0; k<MAX_SPELL_EFFECTS; k++)
{
SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]);
if (pEnchant)
{
for (int t=0; t<MAX_SPELL_EFFECTS; t++)
if (pEnchant->spellid[t] == m_spellProto->Id)
{
amount = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000);
break;
}
}
if (amount)
break;
}
}
}
float DoneActualBenefit = 0.0f;
// custom amount calculations go here
switch(GetAuraType())
{
// crowd control auras
case SPELL_AURA_MOD_CONFUSE:
case SPELL_AURA_MOD_FEAR:
case SPELL_AURA_MOD_STUN:
case SPELL_AURA_MOD_ROOT:
case SPELL_AURA_TRANSFORM:
m_canBeRecalculated = false;
if (!m_spellProto->procFlags)
break;
amount = GetBase()->GetUnitOwner()->GetMaxHealth()*0.10f;
if (caster)
{
// Glyphs increasing damage cap
Unit::AuraEffectList const& overrideClassScripts = caster->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
for (Unit::AuraEffectList::const_iterator itr = overrideClassScripts.begin(); itr != overrideClassScripts.end(); ++itr)
{
if ((*itr)->IsAffectedOnSpell(m_spellProto))
{
// Glyph of Fear, Glyph of Frost nova and similar auras
if ((*itr)->GetMiscValue() == 7801)
{
amount += (int32)(amount*(*itr)->GetAmount()/100.0f);
break;
}
}
}
}
break;
case SPELL_AURA_SCHOOL_ABSORB:
m_canBeRecalculated = false;
if (!caster)
break;
switch(GetSpellProto()->SpellFamilyName)
{
case SPELLFAMILY_MAGE:
// Ice Barrier
if (GetSpellProto()->SpellFamilyFlags[1] & 0x1 && GetSpellProto()->SpellFamilyFlags[2] & 0x8)
{
// +80.68% from sp bonus
DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
// Glyph of Ice Barrier: its weird having a SPELLMOD_ALL_EFFECTS here but its blizzards doing :)
// Glyph of Ice Barrier is only applied at the spell damage bonus because it was already applied to the base value in CalculateSpellDamage
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetSpellProto()->Id, SPELLMOD_ALL_EFFECTS, DoneActualBenefit);
}
// Fire Ward
else if(GetSpellProto()->SpellFamilyFlags[0] & 0x8 && GetSpellProto()->SpellFamilyFlags[2] & 0x8)
{
// +80.68% from sp bonus
DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
}
// Frost Ward
else if(GetSpellProto()->SpellFamilyFlags[0] & 0x100 && GetSpellProto()->SpellFamilyFlags[2] & 0x8)
{
// +80.68% from sp bonus
DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
}
break;
case SPELLFAMILY_WARLOCK:
// Shadow Ward
if (m_spellProto->SpellFamilyFlags[2] & 0x40)
{
// +80.68% from sp bonus
DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f;
}
break;
case SPELLFAMILY_PRIEST:
// Power Word: Shield
if (GetSpellProto()->SpellFamilyFlags[0] & 0x1 && GetSpellProto()->SpellFamilyFlags[2] & 0x400)
{
//+80.68% from sp bonus
float bonus = 0.8068f;
AuraEffect const* pAurEff;
// Borrowed Time
pAurEff = caster->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_PRIEST, 2899, 1);
if (pAurEff)
bonus += (float)pAurEff->GetAmount() / 100.0f;
// Twin Disciplines
pAurEff = caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PRIEST, 0x400000, 0, 0, caster->GetGUID());
if (pAurEff)
bonus += (float)pAurEff->GetAmount() / 100.0f;
// Focused Power
pAurEff = caster->GetAuraEffect(SPELL_AURA_MOD_HEALING_DONE_PERCENT, SPELLFAMILY_PRIEST, 2210, 2);
if (pAurEff)
bonus += (float)pAurEff->GetAmount() / 100.0f;
DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(GetSpellProto())) * bonus;
}
break;
case SPELLFAMILY_PALADIN:
// Sacred Shield
if (m_spellProto->SpellFamilyFlags[1] & 0x80000)
{
// 0.75 from sp bonus
DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.75f;
}
break;
}
break;
case SPELL_AURA_MANA_SHIELD:
m_canBeRecalculated = false;
if (!caster)
break;
// Mana Shield
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellProto()->SpellFamilyFlags[0] & 0x8000 && m_spellProto->SpellFamilyFlags[2] & 0x8)
{
// +80.53% from +spd bonus
DoneActualBenefit += caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8053f;;
}
break;
case SPELL_AURA_DUMMY:
if (!caster)
break;
// Earth Shield
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellProto->SpellFamilyFlags[1] & 0x400)
amount = caster->SpellHealingBonus(GetBase()->GetUnitOwner(), GetSpellProto(), amount, SPELL_DIRECT_DAMAGE);
break;
case SPELL_AURA_DAMAGE_SHIELD:
if (!caster)
break;
// Thorns
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x100)
// 3.3% from sp bonus
DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.033f;
break;
case SPELL_AURA_PERIODIC_DAMAGE:
if (!caster)
break;
// Rupture
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x100000)
{
m_canBeRecalculated = false;
if (caster->GetTypeId() != TYPEID_PLAYER)
break;
//1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs
//2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs
//3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs
//4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs
//5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs
float AP_per_combo[6] = {0.0f, 0.015f, 0.024f, 0.03f, 0.03428571f, 0.0375f};
uint8 cp = caster->ToPlayer()->GetComboPoints();
if (cp > 5) cp = 5;
amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]);
}
// Rip
else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x00800000 && GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
{
m_canBeRecalculated = false;
// 0.01*$AP*cp
if (caster->GetTypeId() != TYPEID_PLAYER)
break;
uint8 cp = caster->ToPlayer()->GetComboPoints();
// Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs
if (AuraEffect const * aurEff = caster->GetAuraEffect(34241,0))
amount += cp * aurEff->GetAmount();
amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100);
}
// Rend
else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARRIOR && GetSpellProto()->SpellFamilyFlags[0] & 0x20)
{
m_canBeRecalculated = false;
// $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick
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);
amount+=caster->ApplyEffectModifiers(m_spellProto,m_effIndex,int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f));
// "If used while your target is above 75% health, Rend does 35% more damage."
// as for 3.1.3 only ranks above 9 (wrong tooltip?)
if (spellmgr.GetSpellRank(m_spellProto->Id) >= 9)
{
if (GetBase()->GetUnitOwner()->HasAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, m_spellProto, caster))
amount += int32(amount * SpellMgr::CalculateSpellEffectAmount(m_spellProto, 2, caster) / 100.0f);
}
}
// Unholy Blight damage over time effect
else if (GetId() == 50536)
{
m_canBeRecalculated = false;
// we're getting total damage on aura apply, change it to be damage per tick
amount = (float)amount / GetTotalTicks();
}
break;
case SPELL_AURA_PERIODIC_ENERGIZE:
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_GENERIC)
{
// Replenishment (0.25% from max)
// Infinite Replenishment
if (m_spellProto->SpellIconID == 3184 && m_spellProto->SpellVisual[0] == 12495)
amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 25 / 10000;
}
// Innervate
else if (m_spellProto->Id == 29166)
amount = GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA) * amount / (GetTotalTicks() * 100.0f);
// Owlkin Frenzy
else if (m_spellProto->Id == 48391)
amount = GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA) * amount / 100;
break;
case SPELL_AURA_PERIODIC_HEAL:
if (!caster)
break;
// Lightwell Renew
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellProto->SpellFamilyFlags[2] & 0x4000)
{
if (caster->GetTypeId() == TYPEID_PLAYER)
// Bonus from Glyph of Lightwell
if (AuraEffect* modHealing = caster->GetAuraEffect(55673, 0))
amount *= (100.0f + modHealing->GetAmount()) / 100.0f;
}
break;
case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN:
if (!caster)
break;
// Icebound Fortitude
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellProto->SpellFamilyFlags[0] & 0x00100000)
{
if (caster->GetTypeId() == TYPEID_PLAYER)
{
int32 value = int32((amount*-1)-10);
uint32 defva = uint32(caster->ToPlayer()->GetSkillValue(SKILL_DEFENSE) + caster->ToPlayer()->GetRatingBonusValue(CR_DEFENSE_SKILL));
if (defva > 400)
value += int32((defva-400)*0.15);
// Glyph of Icebound Fortitude
if (AuraEffect const * aurEff = caster->GetAuraEffect(58625,0))
{
uint32 valMax = aurEff->GetAmount();
if (value < valMax)
value = valMax;
}
amount = -value;
}
}
// Hand of Salvation
else if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_PALADIN && GetSpellProto()->SpellFamilyFlags[0] & 0x00000100)
{
//Glyph of Salvation
if (caster->GetGUID() == GetBase()->GetUnitOwner()->GetGUID())
if (AuraEffect const * aurEff = caster->GetAuraEffect(63225, 0))
amount = -aurEff->GetAmount();
}
break;
case SPELL_AURA_MOD_THREAT:
{
uint8 level_diff = 0;
float multiplier = 0.0;
switch (GetId())
{
// Arcane Shroud
case 26400:
level_diff = GetBase()->GetUnitOwner()->getLevel() - 60;
multiplier = 2;
break;
// The Eye of Diminution
case 28862:
level_diff = GetBase()->GetUnitOwner()->getLevel() - 60;
multiplier = 1;
break;
}
if (level_diff > 0)
amount += multiplier * level_diff;
break;
}
case SPELL_AURA_MOD_INCREASE_HEALTH:
// Vampiric Blood
if (GetId() == 55233)
amount = GetBase()->GetUnitOwner()->GetMaxHealth() * amount / 100;
break;
case SPELL_AURA_MOD_INCREASE_ENERGY:
// Hymn of Hope
if (GetId() == 64904)
amount = GetBase()->GetUnitOwner()->GetMaxPower(GetBase()->GetUnitOwner()->getPowerType()) * amount / 100;
break;
case SPELL_AURA_MOD_INCREASE_SPEED:
// Dash - do not set speed if not in cat form
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags[2] & 0x00000008)
amount = GetBase()->GetUnitOwner()->m_form == FORM_CAT ? amount : 0;
}
if (DoneActualBenefit != 0.0f)
{
DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto());
amount += (int32)DoneActualBenefit;
}
amount *= GetBase()->GetStackAmount();
return amount;
}
void AuraEffect::CalculatePeriodic(Unit * caster, bool create)
{
m_amplitude = m_spellProto->EffectAmplitude[m_effIndex];
// prepare periodics
switch (GetAuraType())
{
case SPELL_AURA_OBS_MOD_POWER:
// 3 spells have no amplitude set
if (!m_amplitude)
m_amplitude = 1 * IN_MILLISECONDS;
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_PERIODIC_ENERGIZE:
case SPELL_AURA_OBS_MOD_HEALTH:
case SPELL_AURA_PERIODIC_LEECH:
case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
case SPELL_AURA_PERIODIC_MANA_LEECH:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
case SPELL_AURA_POWER_BURN_MANA:
m_isPeriodic = true;
break;
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
if (GetId() == 51912)
{
m_amplitude = 3000;
}
m_isPeriodic = true;
break;
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
case SPELL_AURA_PERIODIC_DUMMY:
m_isPeriodic = true;
break;
case SPELL_AURA_DUMMY:
// Haunting Spirits - perdiodic trigger demon
if (GetId() == 7057)
{
m_isPeriodic = true;
m_amplitude = irand (0, 60) + 30;
m_amplitude *= IN_MILLISECONDS;
}
break;
}
if (!m_isPeriodic)
return;
Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
// Apply casting time mods
if (m_amplitude)
{
// Apply periodic time mod
if (modOwner)
modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_amplitude);
if (caster)
{
// Haste modifies periodic time of channeled spells
if (IsChanneledSpell(m_spellProto))
caster->ModSpellCastTime(m_spellProto, m_amplitude);
// and periodic time of auras affected by SPELL_AURA_PERIODIC_HASTE
if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellProto))
m_amplitude *= caster->GetFloatValue(UNIT_MOD_CAST_SPEED);
}
}
if (create)
{
// Start periodic on next tick or at aura apply
if (m_amplitude && !(m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY))
m_periodicTimer += m_amplitude;
}
else if (m_amplitude) // load aura from character_aura
{
m_tickNumber = GetBase()->GetDuration() / m_amplitude;
m_periodicTimer = GetBase()->GetDuration() % m_amplitude;
if (m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY)
++m_tickNumber;
}
}
void AuraEffect::CalculateSpellMod()
{
switch (GetAuraType())
{
case SPELL_AURA_DUMMY:
switch(GetSpellProto()->SpellFamilyName)
{
case SPELLFAMILY_PRIEST:
// Pain and Suffering
if (m_spellProto->SpellIconID == 2874)
{
if (!m_spellmod)
{
m_spellmod = new SpellModifier(GetBase());
m_spellmod->op = SPELLMOD_DOT;
m_spellmod->type = SPELLMOD_PCT;
m_spellmod->spellId = GetId();
m_spellmod->mask[1] = 0x00002000;
}
m_spellmod->value = GetAmount();
}
break;
case SPELLFAMILY_DRUID:
switch (GetId())
{
case 34246: // Idol of the Emerald Queen
case 60779: // Idol of Lush Moss
{
if (!m_spellmod)
{
m_spellmod = new SpellModifier(GetBase());
m_spellmod->op = SPELLMOD_DOT;
m_spellmod->type = SPELLMOD_FLAT;
m_spellmod->spellId = GetId();
m_spellmod->mask[1] = 0x0010;
}
m_spellmod->value = GetAmount()/7;
}
break;
}
break;
}
case SPELL_AURA_PROC_TRIGGER_SPELL:
switch(GetId())
{
case 51466: // Elemental oath
case 51470: // Elemental oath
// "while Clearcasting from Elemental Focus is active, you deal 5%/10% more spell damage."
if (!m_spellmod)
{
m_spellmod = new SpellModifier(GetBase());
m_spellmod->op = SPELLMOD_EFFECT2;
m_spellmod->type = SPELLMOD_FLAT;
m_spellmod->spellId = GetId();
m_spellmod->mask[1] = 0x0004000;
}
m_spellmod->value = GetBase()->GetUnitOwner()->CalculateSpellDamage(GetBase()->GetUnitOwner(), GetSpellProto(), 1);
break;
}
break;
case SPELL_AURA_ADD_FLAT_MODIFIER:
case SPELL_AURA_ADD_PCT_MODIFIER:
if (!m_spellmod)
{
m_spellmod = new SpellModifier(GetBase());
m_spellmod->op = SpellModOp(GetMiscValue());
ASSERT(m_spellmod->op < MAX_SPELLMOD);
m_spellmod->type = SpellModType(GetAuraType()); // SpellModType value == spell aura types
m_spellmod->spellId = GetId();
m_spellmod->mask = GetSpellProto()->EffectSpellClassMask[GetEffIndex()];
m_spellmod->charges = GetBase()->GetCharges();
}
m_spellmod->value = GetAmount();
break;
}
}
void AuraEffect::ChangeAmount(int32 newAmount, bool mark)
{
//Unit * caster = GetCaster();
// Reapply if amount change
if (newAmount != GetAmount())
{
UnitList targetList;
GetTargetList(targetList);
for (UnitList::iterator aurEffTarget = targetList.begin(); aurEffTarget != targetList.end(); ++aurEffTarget)
{
HandleEffect(*aurEffTarget, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, false);
}
if (!mark)
m_amount = newAmount;
else
SetAmount(newAmount);
CalculateSpellMod();
for (UnitList::iterator aurEffTarget = targetList.begin(); aurEffTarget != targetList.end(); ++aurEffTarget)
{
HandleEffect(*aurEffTarget, AURA_EFFECT_HANDLE_CHANGE_AMOUNT, true);
}
}
}
void AuraEffect::HandleEffect(AuraApplication const * aurApp, uint8 mode, bool apply)
{
// check if call is correct
ASSERT(!mode
|| mode == AURA_EFFECT_HANDLE_REAL
|| mode == AURA_EFFECT_HANDLE_SEND_FOR_CLIENT
|| mode == AURA_EFFECT_HANDLE_CHANGE_AMOUNT
|| mode == AURA_EFFECT_HANDLE_STAT);
// real aura apply/remove, handle modifier
if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
ApplySpellMod(aurApp->GetTarget(), apply);
(*this.*AuraEffectHandler [GetAuraType()])(aurApp, mode, apply);
}
void AuraEffect::HandleEffect(Unit * target, uint8 mode, bool apply)
{
AuraApplication const * aurApp = GetBase()->GetApplicationOfTarget(target->GetGUID());
ASSERT(aurApp);
HandleEffect(aurApp, mode, apply);
}
void AuraEffect::ApplySpellMod(Unit * target, bool apply)
{
if (!m_spellmod || target->GetTypeId() != TYPEID_PLAYER)
return;
target->ToPlayer()->AddSpellMod(m_spellmod, apply);
// Auras with charges do not mod amount of passive auras
if (GetBase()->GetCharges())
return;
// reapply some passive spells after add/remove related spellmods
// Warning: it is a dead loop if 2 auras each other amount-shouldn't happen
switch (GetMiscValue())
{
case SPELLMOD_ALL_EFFECTS:
case SPELLMOD_EFFECT1:
case SPELLMOD_EFFECT2:
case SPELLMOD_EFFECT3:
{
uint64 guid = target->GetGUID();
Unit::AuraApplicationMap & auras = target->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator iter = auras.begin(); iter != auras.end(); ++iter)
{
Aura * aura = iter->second->GetBase();
// only passive auras-active auras should have amount set on spellcast and not be affected
// if aura is casted by others, it will not be affected
if (aura->IsPassive() && aura->GetCasterGUID() == guid && spellmgr.IsAffectedByMod(aura->GetSpellProto(), m_spellmod))
{
if (GetMiscValue() == SPELLMOD_ALL_EFFECTS)
{
for (uint8 i = 0; i<MAX_SPELL_EFFECTS; ++i)
{
if (AuraEffect * aurEff = aura->GetEffect(i))
aurEff->RecalculateAmount();
}
}
else if (GetMiscValue() == SPELLMOD_EFFECT1)
{
if (AuraEffect * aurEff = aura->GetEffect(0))
aurEff->RecalculateAmount();
}
else if (GetMiscValue() == SPELLMOD_EFFECT2)
{
if (AuraEffect * aurEff = aura->GetEffect(1))
aurEff->RecalculateAmount();
}
else //if (modOp == SPELLMOD_EFFECT3)
{
if (AuraEffect * aurEff = aura->GetEffect(2))
aurEff->RecalculateAmount();
}
}
}
}
default:
break;
}
}
void AuraEffect::Update(uint32 diff, Unit * caster)
{
if (m_isPeriodic && (GetBase()->GetDuration() >=0 || GetBase()->IsPassive() || GetBase()->IsPermanent()))
{
if (m_periodicTimer > int32(diff))
m_periodicTimer -= diff;
else // tick also at m_periodicTimer == 0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
{
++m_tickNumber;
// update before tick (aura can be removed in TriggerSpell or PeriodicTick calls)
m_periodicTimer += m_amplitude - diff;
UpdatePeriodic(caster);
UnitList effectTargets;
GetTargetList(effectTargets);
// tick on targets of effects
if (!caster || !caster->hasUnitState(UNIT_STAT_ISOLATED))
{
for (UnitList::iterator targetItr = effectTargets.begin(); targetItr != effectTargets.end(); ++targetItr)
PeriodicTick(*targetItr, caster);
}
}
}
}
void AuraEffect::UpdatePeriodic(Unit * caster)
{
switch(GetAuraType())
{
case SPELL_AURA_PERIODIC_DAMAGE:
switch (GetId())
{
case 41337: // Aura of Anger
if (AuraEffect * aurEff = GetBase()->GetEffect(1))
aurEff->ChangeAmount(aurEff->GetAmount()+5);
SetAmount(100 * m_tickNumber);
break;
case 46394: // Brutallus Burn
if (m_tickNumber % 11 == 0)
SetAmount(GetAmount() * 2);
break;
}
break;
case SPELL_AURA_DUMMY:
// Haunting Spirits
if (GetId() == 7057)
{
m_amplitude = irand (0 , 60) + 30;
m_amplitude *= IN_MILLISECONDS;
}
break;
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
switch (GetId())
{
// Sniper training
case 53302:
case 53303:
case 53304:
Unit * target = GetBase()->GetUnitOwner();
if (target->GetTypeId() != TYPEID_PLAYER)
break;
if (target->ToPlayer()->isMoving())
m_amount = target->CalculateSpellDamage(target, m_spellProto,m_effIndex, &m_baseAmount);
else
--m_amount;
break;
}
break;
case SPELL_AURA_PERIODIC_DUMMY:
switch(GetSpellProto()->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
switch(GetId())
{
// Drink
case 430:
case 431:
case 432:
case 1133:
case 1135:
case 1137:
case 10250:
case 22734:
case 27089:
case 34291:
case 43182:
case 43183:
case 46755:
case 49472: // Drink Coffee
case 57073:
case 61830:
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
// Get SPELL_AURA_MOD_POWER_REGEN aura from spell
if (AuraEffect * aurEff = GetBase()->GetEffect(0))
{
if (aurEff->GetAuraType() != SPELL_AURA_MOD_POWER_REGEN)
{
m_isPeriodic = false;
sLog.outError("Aura %d structure has been changed - first aura is no longer SPELL_AURA_MOD_POWER_REGEN", GetId());
}
else
{
// default case - not in arena
if (!caster->ToPlayer()->InArena())
{
aurEff->ChangeAmount(GetAmount());
m_isPeriodic = false;
}
else
{
//**********************************************
// 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)
// Apply bonus for 1 - 4 tick
switch (m_tickNumber)
{
case 1: // 0%
aurEff->ChangeAmount(0);
break;
case 2: // 166%
aurEff->ChangeAmount(GetAmount() * 5 / 3);
break;
case 3: // 133%
aurEff->ChangeAmount(GetAmount() * 4 / 3);
break;
default: // 100% - normal regen
aurEff->ChangeAmount(GetAmount());
// No need to update after 4th tick
m_isPeriodic = false;
break;
}
}
}
}
break;
case 58549: // Tenacity
case 59911: // Tenacity (vehicle)
GetBase()->RefreshDuration();
break;
}
break;
case SPELLFAMILY_MAGE:
if (GetId() == 55342)// Mirror Image
m_isPeriodic = false;
break;
case SPELLFAMILY_DEATHKNIGHT:
// Chains of Ice
if (GetSpellProto()->SpellFamilyFlags[1] & 0x00004000)
{
// Get 0 effect aura
if (AuraEffect *slow = GetBase()->GetEffect(0))
{
int32 newAmount = slow->GetAmount() + GetAmount();
if (newAmount > 0)
newAmount = 0;
slow->ChangeAmount(newAmount);
}
return;
}
}
}
}
bool AuraEffect::IsPeriodicTickCrit(Unit * target, Unit const * caster) const
{
ASSERT(caster);
Unit::AuraEffectList const& mPeriodicCritAuras= caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_PERIODIC_CRIT);
for (Unit::AuraEffectList::const_iterator itr = mPeriodicCritAuras.begin(); itr != mPeriodicCritAuras.end(); ++itr)
{
if ((*itr)->IsAffectedOnSpell(m_spellProto) && caster->isSpellCrit(target, m_spellProto, GetSpellSchoolMask(m_spellProto)))
return true;
}
// Rupture - since 3.3.3 can crit
if (AuraEffect *AuraRupture = target->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_ROGUE, 0x100000, 0x0, 0x0, caster->GetGUID()))
{
if (caster->isSpellCrit(target, m_spellProto, GetSpellSchoolMask(m_spellProto)))
return true;
}
return false;
}
void AuraEffect::SendTickImmune(Unit * target, Unit *caster) const
{
WorldPacket data(SMSG_SPELLORDAMAGE_IMMUNE, 8+8+4+1);
data << uint64(caster ? caster->GetGUID() : target->GetGUID());
data << uint64(target->GetGUID());
data << uint32(m_spellProto->Id);
data << uint8(1);
target->SendMessageToSet(&data,true);
}
void AuraEffect::PeriodicTick(Unit * target, Unit * caster) const
{
if (!target->isAlive())
return;
if (target->hasUnitState(UNIT_STAT_ISOLATED))
{
SendTickImmune(target, caster);
return;
}
switch(GetAuraType())
{
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
{
if (!caster)
break;
// Consecrate ticks can miss and will not show up in the combat log
if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE)
break;
// Check for immune (not use charges)
if (target->IsImmunedToDamage(GetSpellProto()))
{
SendTickImmune(target, caster);
break;
}
// some auras remove at specific health level or more
if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
{
switch (GetId())
{
case 43093: case 31956: case 38801: // Grievous Wound
case 35321: case 38363: case 39215: // Gushing Wound
if (target->GetHealth() == target->GetMaxHealth())
{
target->RemoveAurasDueToSpell(GetId());
return;
}
break;
case 38772: // Grievous Wound
{
uint32 percent =
GetEffIndex() < 2 && GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_DUMMY ?
caster->CalculateSpellDamage(target, GetSpellProto(),GetEffIndex()+1) :
100;
if (target->GetHealth()*100 >= target->GetMaxHealth()*percent)
{
target->RemoveAurasDueToSpell(GetId());
return;
}
break;
}
}
}
uint32 absorb=0;
uint32 resist=0;
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
// ignore non positive values (can be result apply spellmods to aura damage
uint32 damage = GetAmount() > 0 ? GetAmount() : 0;
if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
{
damage = caster->SpellDamageBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
// 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 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto());
cleanDamage.mitigated_damage += damage - damageReductedArmor;
damage = damageReductedArmor;
}
// Curse of Agony damage-per-tick calculation
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID == 544)
{
uint32 totalTick = GetTotalTicks();
// 1..4 ticks, 1/2 from normal tick damage
if (m_tickNumber <= totalTick / 3)
damage = damage/2;
// 9..12 ticks, 3/2 from normal tick damage
else if (m_tickNumber > totalTick * 2 / 3)
damage += (damage+1)/2; // +1 prevent 0.5 damage possible lost at 1..4 ticks
// 5..8 ticks have normal tick damage
}
// There is a Chance to make a Soul Shard when Drain soul does damage
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x00004000))
{
if (caster->GetTypeId() == TYPEID_PLAYER && caster->ToPlayer()->isHonorOrXPTarget(target))
{
if (roll_chance_i(20))
{
caster->CastSpell(caster, 43836, true, 0, this);
// Glyph of Drain Soul - chance to create an additional Soul Shard
if (AuraEffect *aur = caster->GetAuraEffect(58070, 0))
if (roll_chance_i(aur->GetMiscValue()))
caster->CastSpell(caster, 58068, true, 0, aur);
}
}
}
}
else
damage = uint32(target->GetMaxHealth()*damage/100);
bool crit = IsPeriodicTickCrit(target, caster);
if (crit)
damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target);
// Reduce damage from resilience for players and pets only.
// As of patch 3.3 pets inherit 100% of master resilience.
if (caster->GetSpellModOwner())
if (Player* modOwner = target->GetSpellModOwner())
{
if (crit)
damage -= modOwner->GetSpellCritDamageReduction(damage);
damage -= modOwner->GetSpellDamageReduction(damage);
}
caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto);
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())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(),absorb);
caster->DealDamageMods(target,damage,&absorb);
// Set trigger flag
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;
uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_DOT;
damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
if (damage)
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
int32 overkill = damage - target->GetHealth();
if (overkill < 0)
overkill = 0;
SpellPeriodicAuraLogInfo pInfo(this, damage, overkill, absorb, resist, 0.0f, crit);
target->SendPeriodicAuraLog(&pInfo);
caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
break;
}
case SPELL_AURA_PERIODIC_LEECH:
{
if (!caster)
return;
if (!caster->isAlive())
return;
if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE)
return;
// Check for immune
if (target->IsImmunedToDamage(GetSpellProto()))
{
SendTickImmune(target, caster);
return;
}
uint32 absorb=0;
uint32 resist=0;
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
//uint32 damage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0;
uint32 damage = GetAmount() > 0 ? GetAmount() : 0;
damage = caster->SpellDamageBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
bool crit = IsPeriodicTickCrit(target, caster);
if (crit)
damage = caster->SpellCriticalDamageBonus(m_spellProto, damage, target);
//Calculate armor mitigation if it is a physical spell
if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)
{
uint32 damageReductedArmor = caster->CalcArmorReducedDamage(target, damage, GetSpellProto());
cleanDamage.mitigated_damage += damage - damageReductedArmor;
damage = damageReductedArmor;
}
// Reduce damage from resilience for players and pets only.
// As of patch 3.3 pets inherit 100% of master resilience.
if (caster->GetSpellModOwner())
if (Player* modOwner = target->GetSpellModOwner())
{
if (crit)
damage -= modOwner->GetSpellCritDamageReduction(damage);
damage -= modOwner->GetSpellDamageReduction(damage);
}
caster->CalcAbsorbResist(target, GetSpellSchoolMask(GetSpellProto()), DOT, damage, &absorb, &resist, m_spellProto);
if (target->GetHealth() < damage)
damage = uint32(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())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId(),absorb);
caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0, crit);
// Set trigger flag
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;
uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_DOT;
damage = (damage <= absorb+resist) ? 0 : (damage-absorb-resist);
if (damage)
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
int32 new_damage = caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), false);
if (!target->isAlive() && caster->IsNonMeleeSpellCasted(false))
for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; ++i)
if (Spell* spell = caster->GetCurrentSpell(CurrentSpellTypes(i)))
if (spell->m_spellInfo->Id == GetId())
spell->cancel();
float multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
if (Player *modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetSpellProto()->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
uint32 heal = uint32(caster->SpellHealingBonus(caster, GetSpellProto(), uint32(new_damage * multiplier), DOT, GetBase()->GetStackAmount()));
int32 gain = caster->DealHeal(caster, heal, GetSpellProto());
caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellProto());
break;
}
case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: // only three spells
{
if (!caster || !caster->GetHealth())
break;
uint32 damage = GetAmount();
// do not kill health donator
if (caster->GetHealth() < damage)
damage = caster->GetHealth() - 1;
if (!damage)
break;
//donator->SendSpellNonMeleeDamageLog(donator, GetId(), damage, GetSpellSchoolMask(spellProto), 0, 0, false, 0);
caster->ModifyHealth(-(int32)damage);
sLog.outDebug("PeriodicTick: donator %u target %u damage %u.", target->GetEntry(), target->GetEntry(), damage);
float multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
if (Player *modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetSpellProto()->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
damage *= multiplier;
caster->DealHeal(target, damage, GetSpellProto());
break;
}
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_OBS_MOD_HEALTH:
{
if (!caster)
break;
// heal for caster damage (must be alive)
if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL && !caster->isAlive())
break;
if (GetBase()->GetDuration() == -1 && target->GetHealth() == target->GetMaxHealth())
break;
// ignore non positive values (can be result apply spellmods to aura damage
int32 damage = m_amount > 0 ? m_amount : 0;
if (GetAuraType() == SPELL_AURA_OBS_MOD_HEALTH)
{
// Taken mods
float TakenTotalMod = 1.0f;
// Tenacity increase healing % taken
if (AuraEffect const* Tenacity = target->GetAuraEffect(58549, 0))
TakenTotalMod *= (Tenacity->GetAmount() + 100.0f) / 100.0f;
// Healing taken percent
float minval = target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
if (minval)
TakenTotalMod *= (100.0f + minval) / 100.0f;
float maxval = target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
if (maxval)
TakenTotalMod *= (100.0f + maxval) / 100.0f;
// Healing over time taken percent
float minval_hot = target->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT);
if (minval_hot)
TakenTotalMod *= (100.0f + minval_hot) / 100.0f;
float maxval_hot = target->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT);
if (maxval_hot)
TakenTotalMod *= (100.0f + maxval_hot) / 100.0f;
TakenTotalMod = TakenTotalMod > 0.0f ? TakenTotalMod : 0.0f;
damage = uint32(target->GetMaxHealth() * damage / 100);
damage = uint32(damage * TakenTotalMod);
}
else
{
// Wild Growth = amount + (6 - 2*doneTicks) * ticks* amount / 100
if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellIconID == 2864)
{
damage += float(damage * GetTotalTicks()) * ((6-float(2*(GetTickNumber()-1)))/100);
}
damage = caster->SpellHealingBonus(target, GetSpellProto(), damage, DOT, GetBase()->GetStackAmount());
}
bool crit = IsPeriodicTickCrit(target, caster);
if (crit)
damage = caster->SpellCriticalHealingBonus(m_spellProto, damage, 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())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId());
int32 gain = target->ModifyHealth(damage);
SpellPeriodicAuraLogInfo pInfo(this, damage, damage - gain, 0, 0, 0.0f, crit);
target->SendPeriodicAuraLog(&pInfo);
// add HoTs to amount healed in bgs
if (caster->GetTypeId() == TYPEID_PLAYER)
if (BattleGround *bg = caster->ToPlayer()->GetBattleGround())
bg->UpdatePlayerScore(caster->ToPlayer(), SCORE_HEALING_DONE, gain);
target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
bool haveCastItem = GetBase()->GetCastItemGUID() != 0;
// Health Funnel
// damage caster for heal amount
if (target != caster && GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_HEALTH_FUNNEL)
{
uint32 damage = gain;
uint32 absorb = 0;
caster->DealDamageMods(caster,damage,&absorb);
caster->SendSpellNonMeleeDamageLog(caster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false);
CleanDamage cleanDamage = CleanDamage(0, 0, BASE_ATTACK, MELEE_HIT_NORMAL);
caster->DealDamage(caster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true);
}
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;
uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_HOT;
// ignore item heals
if (!haveCastItem)
caster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, damage, BASE_ATTACK, GetSpellProto());
break;
}
case SPELL_AURA_PERIODIC_MANA_LEECH:
{
if (GetMiscValue() < 0 || GetMiscValue() >= MAX_POWERS)
break;
Powers power = Powers(GetMiscValue());
// power type might have changed between aura applying and tick (druid's shapeshift)
if (target->getPowerType() != power)
break;
if (!caster || !caster->isAlive())
break;
if (GetSpellProto()->Effect[GetEffIndex()] == SPELL_EFFECT_PERSISTENT_AREA_AURA &&
caster->SpellHitResult(target,GetSpellProto(),false) != SPELL_MISS_NONE)
break;
// Check for immune (not use charges)
if (target->IsImmunedToDamage(GetSpellProto()))
{
SendTickImmune(target, caster);
break;
}
// ignore non positive values (can be result apply spellmods to aura damage
uint32 damage = m_amount > 0 ? m_amount : 0;
// Special case: draining x% of mana (up to a maximum of 2*x% of the caster's maximum mana)
// It's mana percent cost spells, m_amount is percent drain from target
if (m_spellProto->ManaCostPercentage)
{
// max value
uint32 maxmana = caster->GetMaxPower(power) * damage * 2 / 100;
damage = target->GetMaxPower(power) * damage / 100;
if (damage > maxmana)
damage = maxmana;
}
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())), target->GetGUIDLow(), target->GetTypeId(), damage, GetId());
int32 drain_amount = target->GetPower(power) > damage ? damage : target->GetPower(power);
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
if (power == POWER_MANA)
drain_amount -= target->GetSpellCritDamageReduction(drain_amount);
target->ModifyPower(power, -drain_amount);
float gain_multiplier = 0.0f;
if (caster->GetMaxPower(power) > 0)
{
gain_multiplier = GetSpellProto()->EffectMultipleValue[GetEffIndex()];
if (Player *modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier);
}
SpellPeriodicAuraLogInfo pInfo(this, drain_amount, 0, 0, 0, gain_multiplier, false);
target->SendPeriodicAuraLog(&pInfo);
int32 gain_amount = int32(drain_amount*gain_multiplier);
if (gain_amount)
{
int32 gain = caster->ModifyPower(power,gain_amount);
target->AddThreat(caster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
}
switch(GetId())
{
case 31447: // Mark of Kaz'rogal
if (target->GetPower(power) == 0)
{
target->CastSpell(target, 31463, true, 0, this);
// Remove aura
GetBase()->SetDuration(0);
}
break;
case 32960: // Mark of Kazzak
int32 modifier = (target->GetPower(power) * 0.05f);
target->ModifyPower(power, -modifier);
if (target->GetPower(power) == 0)
{
target->CastSpell(target, 32961, true, 0, this);
// Remove aura
GetBase()->SetDuration(0);
}
}
// Drain Mana
if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK
&& m_spellProto->SpellFamilyFlags[0] & 0x00000010)
{
int32 manaFeedVal = 0;
if (AuraEffect const * aurEff = GetBase()->GetEffect(1))
manaFeedVal = aurEff->GetAmount();
// Mana Feed - Drain Mana
if (manaFeedVal > 0)
{
manaFeedVal = manaFeedVal * gain_amount / 100;
caster->CastCustomSpell(caster, 32554, &manaFeedVal, NULL, NULL, true, NULL, this);
}
}
break;
}
case SPELL_AURA_OBS_MOD_POWER:
{
if (GetMiscValue() < 0)
return;
Powers power;
if (GetMiscValue() == POWER_ALL)
power = target->getPowerType();
else
power = Powers(GetMiscValue());
if (target->GetMaxPower(power) == 0)
return;
if (GetBase()->GetDuration() == -1 && target->GetPower(power) == target->GetMaxPower(power))
return;
uint32 amount = m_amount * target->GetMaxPower(power) /100;
sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId());
SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
target->SendPeriodicAuraLog(&pInfo);
int32 gain = target->ModifyPower(power,amount);
if (caster)
target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
break;
}
case SPELL_AURA_PERIODIC_ENERGIZE:
{
// ignore non positive values (can be result apply spellmods to aura damage
if (m_amount < 0 || GetMiscValue() >= MAX_POWERS)
return;
Powers power = Powers(GetMiscValue());
if (target->GetMaxPower(power) == 0)
return;
if (GetBase()->GetDuration() == -1 && target->GetPower(power) == target->GetMaxPower(power))
return;
uint32 amount = m_amount;
SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
target->SendPeriodicAuraLog(&pInfo);
sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u",
GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), target->GetGUIDLow(), target->GetTypeId(), amount, GetId());
int32 gain = target->ModifyPower(power,amount);
if (caster)
target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto());
break;
}
case SPELL_AURA_POWER_BURN_MANA:
{
if (!caster)
return;
// Check for immune (not use charges)
if (target->IsImmunedToDamage(GetSpellProto()))
{
SendTickImmune(target, caster);
return;
}
int32 damage = m_amount > 0 ? m_amount : 0;
Powers powerType = Powers(GetMiscValue());
if (!target->isAlive() || target->getPowerType() != powerType)
return;
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
if (powerType == POWER_MANA)
damage -= target->GetSpellCritDamageReduction(damage);
uint32 gain = uint32(-target->ModifyPower(powerType, -damage));
gain = uint32(gain * GetSpellProto()->EffectMultipleValue[GetEffIndex()]);
SpellEntry const* spellProto = GetSpellProto();
//maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG
SpellNonMeleeDamage damageInfo(caster, target, spellProto->Id, spellProto->SchoolMask);
//no SpellDamageBonus for burn mana
caster->CalculateSpellDamageTaken(&damageInfo, gain, spellProto);
caster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb);
caster->SendSpellNonMeleeDamageLog(&damageInfo);
// Set trigger flag
uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;
uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC;
uint32 procEx = createProcExtendMask(&damageInfo, SPELL_MISS_NONE) | PROC_EX_INTERNAL_DOT;
if (damageInfo.damage)
procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE;
caster->ProcDamageAndSpell(damageInfo.target, procAttacker, procVictim, procEx, damageInfo.damage, BASE_ATTACK, spellProto);
caster->DealSpellDamage(&damageInfo, true);
break;
}
case SPELL_AURA_DUMMY:
// Haunting Spirits
if (GetId() == 7057)
target->CastSpell((Unit*)NULL , GetAmount() , true);
break;
case SPELL_AURA_PERIODIC_DUMMY:
PeriodicDummyTick(target, caster);
break;
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
TriggerSpell(target, caster);
break;
case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
TriggerSpellWithValue(target, caster);
break;
}
}
void AuraEffect::PeriodicDummyTick(Unit * target, Unit * caster) const
{
switch (GetSpellProto()->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
switch (GetId())
{
// Forsaken Skills
case 7054:
{
// Possibly need cast one of them (but
// 7038 Forsaken Skill: Swords
// 7039 Forsaken Skill: Axes
// 7040 Forsaken Skill: Daggers
// 7041 Forsaken Skill: Maces
// 7042 Forsaken Skill: Staves
// 7043 Forsaken Skill: Bows
// 7044 Forsaken Skill: Guns
// 7045 Forsaken Skill: 2H Axes
// 7046 Forsaken Skill: 2H Maces
// 7047 Forsaken Skill: 2H Swords
// 7048 Forsaken Skill: Defense
// 7049 Forsaken Skill: Fire
// 7050 Forsaken Skill: Frost
// 7051 Forsaken Skill: Holy
// 7053 Forsaken Skill: Shadow
return;
}
case 45472: // Parachute
if (target->GetTypeId() == TYPEID_PLAYER)
{
Player *plr = (Player*)target;
if (plr->IsFalling())
{
plr->RemoveAurasDueToSpell(45472);
plr->CastSpell(plr, 44795, true);
}
}
break;
case 51685: // Prey on the Weak
case 51686:
case 51687:
case 51688:
case 51689:
if (target->getVictim() && (target->GetHealth() * 100 / target->GetMaxHealth() > target->getVictim()->GetHealth() * 100 / target->getVictim()->GetMaxHealth())) {
if (!target->HasAura(58670)) {
int32 basepoints = GetSpellProto()->EffectBasePoints[0];
target->CastCustomSpell(target, 58670, &basepoints, 0, 0, true);
}
}
else
target->RemoveAurasDueToSpell(58670);
break;
case 62292: // Blaze (Pool of Tar)
// should we use custom damage?
target->CastSpell((Unit*)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
break;
case 62399: // Overload Circuit
if (target->GetMap()->IsDungeon() && target->GetAppliedAuras().count(62399) >= (target->GetMap()->IsHeroic() ? 4 : 2))
{
target->CastSpell(target, 62475, true); // System Shutdown
if (Unit *veh = target->GetVehicleBase())
veh->CastSpell(target, 62475, true);
}
break;
case 64821: // Fuse Armor (Razorscale)
if (GetBase()->GetStackAmount() == GetSpellProto()->StackAmount)
{
target->CastSpell(target, 64774, true, NULL, NULL, GetCasterGUID());
target->RemoveAura(64821);
}
break;
}
break;
case SPELLFAMILY_MAGE:
{
// Mirror Image
if (GetId() == 55342)
// Set name of summons to name of caster
target->CastSpell((Unit *)NULL, m_spellProto->EffectTriggerSpell[m_effIndex], true);
break;
}
case SPELLFAMILY_WARLOCK:
{
switch (GetSpellProto()->Id)
{
// Demonic Circle
case 48018:
if (GameObject* obj = target->GetGameObject(GetSpellProto()->Id))
{
if (target->IsWithinDist(obj, GetSpellMaxRange(48020, true)))
{
if (!target->HasAura(62388))
target->CastSpell(target, 62388, true);
}
else
target->RemoveAura(62388);
}
break;
}
break;
}
case SPELLFAMILY_DRUID:
{
switch (GetSpellProto()->Id)
{
// Frenzied Regeneration
case 22842:
{
// Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
// Should be manauser
if (target->getPowerType() != POWER_RAGE)
break;
uint32 rage = target->GetPower(POWER_RAGE);
// Nothing todo
if (rage == 0)
break;
int32 mod = (rage < 100) ? rage : 100;
int32 points = target->CalculateSpellDamage(target, GetSpellProto(), 1);
int32 regen = target->GetMaxHealth() * (mod * points / 10) / 1000;
target->CastCustomSpell(target, 22845, &regen, 0, 0, true, 0, this);
target->SetPower(POWER_RAGE, rage-mod);
break;
}
// Force of Nature
case 33831:
break;
}
break;
}
case SPELLFAMILY_ROGUE:
{
switch (GetSpellProto()->Id)
{
// Master of Subtlety
case 31666:
if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
target->RemoveAurasDueToSpell(31665);
break;
// Killing Spree
case 51690:
{
// TODO: this should use effect[1] of 51690
UnitList targets;
{
// eff_radius == 0
float radius = GetSpellMaxRange(GetSpellProto(), false);
CellPair p(Trinity::ComputeCellPair(caster->GetPositionX(),caster->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(caster, caster, radius);
Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(caster,targets, u_check);
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker);
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker);
cell.Visit(p, grid_object_checker, *GetBase()->GetOwner()->GetMap(), *caster, radius);
cell.Visit(p, world_object_checker, *GetBase()->GetOwner()->GetMap(), *caster, radius);
}
if (targets.empty())
return;
UnitList::const_iterator itr = targets.begin();
std::advance(itr, rand()%targets.size());
Unit* spellTarget = *itr;
target->CastSpell(spellTarget, 57840, true);
target->CastSpell(spellTarget, 57841, true);
break;
}
// Overkill
case 58428:
if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH))
target->RemoveAurasDueToSpell(58427);
break;
}
break;
}
case SPELLFAMILY_HUNTER:
{
// Explosive Shot
if (GetSpellProto()->SpellFamilyFlags[1] & 0x80000000)
{
if (caster)
caster->CastCustomSpell(53352, SPELLVALUE_BASE_POINT0, m_amount, target, true, NULL, this);
break;
}
switch (GetSpellProto()->Id)
{
// Feeding Frenzy Rank 1
case 53511:
if (target->getVictim() && target->getVictim()->GetHealth() * 100 < target->getVictim()->GetMaxHealth() * 35)
target->CastSpell(target, 60096, true, 0, this);
return;
// Feeding Frenzy Rank 2
case 53512:
if (target->getVictim() && target->getVictim()->GetHealth() * 100 < target->getVictim()->GetMaxHealth() * 35)
target->CastSpell(target, 60097, true, 0, this);
return;
default:
break;
}
break;
}
case SPELLFAMILY_SHAMAN:
if (GetId() == 52179) // Astral Shift
{
// Periodic need for remove visual on stun/fear/silence lost
if (!(target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED)))
target->RemoveAurasDueToSpell(52179);
break;
}
break;
case SPELLFAMILY_DEATHKNIGHT:
switch (GetId())
{
case 49016: // Hysteria
uint32 damage = uint32(target->GetMaxHealth()*0.01f);
target->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
break;
}
// Death and Decay
if (GetSpellProto()->SpellFamilyFlags[0] & 0x20)
{
if (caster)
caster->CastCustomSpell(target, 52212, &m_amount, NULL, NULL, true, 0, this);
break;
}
// Blood of the North
// Reaping
// Death Rune Mastery
if (GetSpellProto()->SpellIconID == 3041 || GetSpellProto()->SpellIconID == 22 || GetSpellProto()->SpellIconID == 2622)
{
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
return;
// timer expired - remove death runes
target->ToPlayer()->RemoveRunesByAuraEffect(this);
}
break;
}
}
Unit* AuraEffect::GetTriggerTarget(Unit * target) const
{
if (target->GetTypeId() == TYPEID_UNIT)
{
if (Unit * trigger = target->ToCreature()->AI()->GetAuraEffectTriggerTarget(GetId(), GetEffIndex()))
return trigger;
}
return target;
}
void AuraEffect::TriggerSpell(Unit * target, Unit * caster) const
{
if (!caster || !target)
return;
Unit* triggerTarget = GetTriggerTarget(target);
// generic casting code with custom spells and target/caster customs
uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[GetEffIndex()];
SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
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)
{
// Thaumaturgy Channel
case 9712:
triggerSpellId = 21029;
break;
// Brood Affliction: Bronze
case 23170:
triggerSpellId = 23171;
return;
// Restoration
case 24379:
case 23493:
{
int32 heal = caster->GetMaxHealth() / 10;
caster->DealHeal(target, heal, auraSpellInfo);
int32 mana = caster->GetMaxPower(POWER_MANA);
if (mana)
{
mana /= 10;
caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA);
}
return;
}
// Nitrous Boost
case 27746:
if (target->GetPower(POWER_MANA) >= 10)
{
target->ModifyPower(POWER_MANA, -10);
target->SendEnergizeSpellLog(caster, 27746, 10, POWER_MANA);
}
else
target->RemoveAurasDueToSpell(27746);
return;
// Frost Blast
case 27808:
caster->CastCustomSpell(29879, SPELLVALUE_BASE_POINT0, (float)target->GetMaxHealth()*0.21f, target, true, NULL, this);
return;
// Detonate Mana
case 27819:
if (int32 mana = (int32)(target->GetMaxPower(POWER_MANA) / 10))
{
mana = target->ModifyPower(POWER_MANA, -mana);
target->CastCustomSpell(27820, SPELLVALUE_BASE_POINT0, -mana*10, target, true, NULL, this);
}
return;
// Inoculate Nestlewood Owlkin
case 29528:
if (triggerTarget->GetTypeId() != TYPEID_UNIT)// prevent error reports in case ignored player target
return;
break;
// Feed Captured Animal
case 29917:
triggerSpellId = 29916;
break;
// Extract Gas
case 30427:
{
// move loot to player inventory and despawn target
if (caster->GetTypeId() == TYPEID_PLAYER &&
triggerTarget->GetTypeId() == TYPEID_UNIT &&
triggerTarget->ToCreature()->GetCreatureInfo()->type == CREATURE_TYPE_GAS_CLOUD)
{
Player* player = (Player*)caster;
Creature* creature = triggerTarget->ToCreature();
// missing lootid has been reported on startup - just return
if (!creature->GetCreatureInfo()->SkinLootId)
return;
player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId,LootTemplates_Skinning,true);
creature->ForcedDespawn();
}
return;
}
// Quake
case 30576: triggerSpellId = 30571; break;
// Doom
// TODO: effect trigger spell may be independant on spell targets, and executed in spell finish phase
// so instakill will be naturally done before trigger spell
case 31347:
{
target->CastSpell(target,31350,true, NULL, this);
target->Kill(target);
return;
}
// Spellcloth
case 31373:
{
// Summon Elemental after create item
target->SummonCreature(17870, 0, 0, 0, target->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
return;
}
// Flame Quills
case 34229:
{
// cast 24 spells 34269-34289, 34314-34316
for (uint32 spell_id = 34269; spell_id != 34290; ++spell_id)
caster->CastSpell(target,spell_id,true, NULL, this);
for (uint32 spell_id = 34314; spell_id != 34317; ++spell_id)
caster->CastSpell(target,spell_id,true, NULL, this);
return;
}
// Remote Toy
case 37027: triggerSpellId = 37029; break;
// Eye of Grillok
case 38495:
{
target->CastSpell(target, 38530, true, NULL, this);
return;
}
// Absorb Eye of Grillok (Zezzak's Shard)
case 38554:
{
if (target->GetTypeId() != TYPEID_UNIT)
return;
caster->CastSpell(caster, 38495, true, NULL, this);
Creature* creatureTarget = target->ToCreature();
creatureTarget->ForcedDespawn();
return;
}
// Tear of Azzinoth Summon Channel - it's not really supposed to do anything,and this only prevents the console spam
case 39857: triggerSpellId = 39856; break;
// Personalized Weather
case 46736: triggerSpellId = 46737; break;
}
break;
}
case SPELLFAMILY_MAGE:
{
switch(auraId)
{
// Invisibility
case 66:
// Here need periodic triger reducing threat spell (or do it manually)
return;
}
break;
}
case SPELLFAMILY_DRUID:
{
switch(auraId)
{
// Cat Form
// triggerSpellId not set and unknown effect triggered in this case, ignoring for while
case 768:
return;
}
break;
}
case SPELLFAMILY_HUNTER:
{
switch (auraId)
{
// Sniper training
case 53302:
case 53303:
case 53304:
// We are standing at the moment
if (GetAmount() > 0)
return;
triggerSpellId = 64418 + auraId - 53302;
// If aura is active - no need to continue
if (target->HasAura(triggerSpellId))
return;
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
if (!target->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_SHAMAN,0x400))
target->RemoveAurasDueToSpell(28820);
return;
}
// Totemic Mastery (Skyshatter Regalia (Shaman Tier 6) - bonus)
case 38443:
{
bool all = true;
for (int i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i)
{
if (!target->m_SummonSlot[i])
{
all = false;
break;
}
}
if (all)
caster->CastSpell(target,38437,true, NULL, this);
else
target->RemoveAurasDueToSpell(38437);
return;
}
}
break;
}
}
// Reget trigger spell proto
triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
}
else
{
// Spell exist but require custom code
switch(auraId)
{
// Mana Tide
case 16191:
{
target->CastCustomSpell(triggerTarget, triggerSpellId, &m_amount, NULL, NULL, true, NULL, this);
return;
}
// Negative Energy Periodic
case 46284:
caster->CastCustomSpell(triggerSpellId, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this);
return;
// Poison (Grobbulus)
case 28158:
case 54362:
target->CastCustomSpell(triggerSpellId, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000), NULL, true, NULL, this);
return;
// Beacon of Light
case 53563:
Unit * triggerCaster = (Unit *)(GetBase()->GetOwner());
triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo, true, 0, this,triggerCaster->GetGUID());
return;
}
}
if (triggeredSpellInfo)
{
Unit * triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, triggerTarget);
triggerCaster->CastSpell(triggerTarget, triggeredSpellInfo, true, 0, this);
sLog.outDebug("AuraEffect::TriggerSpell: Spell %u Trigger %u",GetId(), triggeredSpellInfo->Id);
}
else if (target->GetTypeId() != TYPEID_UNIT || !sScriptMgr.OnDummyEffect(caster, GetId(), SpellEffIndex(GetEffIndex()), triggerTarget->ToCreature()))
sLog.outError("AuraEffect::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
}
void AuraEffect::TriggerSpellWithValue(Unit * target, Unit * caster) const
{
if (!caster || !target)
return;
Unit* triggerTarget = GetTriggerTarget(target);
uint32 triggerSpellId = GetSpellProto()->EffectTriggerSpell[m_effIndex];
SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(triggerSpellId);
if (triggeredSpellInfo)
{
Unit * triggerCaster = GetTriggeredSpellCaster(triggeredSpellInfo, caster, triggerTarget);
// generic casting code with custom spells and target/caster customs
int32 basepoints0 = GetAmount();
triggerCaster->CastCustomSpell(triggerTarget, triggerSpellId, &basepoints0, 0, 0, true, 0, this);
}
else
sLog.outError("AuraEffect::TriggerSpellWithValue: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex());
}
bool AuraEffect::IsAffectedOnSpell(SpellEntry const *spell) const
{
if (!spell)
return false;
// Check family name
if (spell->SpellFamilyName != m_spellProto->SpellFamilyName)
return false;
// Check EffectClassMask
if (m_spellProto->EffectSpellClassMask[m_effIndex] & spell->SpellFamilyFlags)
return true;
return false;
}
void AuraEffect::CleanupTriggeredSpells(Unit * target)
{
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 &&
uint32(GetSpellDuration(m_spellProto)) == m_spellProto->EffectAmplitude[GetEffIndex()])
return;
target->RemoveAurasDueToSpell(tSpellId, GetCasterGUID());
}
void AuraEffect::HandleShapeshiftBoosts(Unit * target, bool apply) const
{
uint32 spellId = 0;
uint32 spellId2 = 0;
//uint32 spellId3 = 0;
uint32 HotWSpellId = 0;
switch(GetMiscValue())
{
case FORM_CAT:
spellId = 3025;
HotWSpellId = 24900;
break;
case FORM_TREE:
spellId = 34123;
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;
spellId2 = 69366;
break;
case FORM_FLIGHT:
spellId = 33948;
spellId2 = 34764;
break;
case FORM_FLIGHT_EPIC:
spellId = 40122;
spellId2 = 40121;
break;
case FORM_METAMORPHOSIS:
spellId = 54817;
spellId2 = 54879;
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_SHADOW:
spellId = 49868;
spellId2 = 71167;
break;
case FORM_GHOSTWOLF:
spellId = 67116;
break;
case FORM_GHOUL:
case FORM_AMBIENT:
case FORM_STEALTH:
case FORM_CREATURECAT:
case FORM_CREATUREBEAR:
break;
}
if (apply)
{
// Remove cooldown of spells triggered on stance change - they may share cooldown with stance spell
if (spellId)
{
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveSpellCooldown(spellId);
target->CastSpell(target, spellId, true, NULL, this);
}
if (spellId2)
{
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveSpellCooldown(spellId2);
target->CastSpell(target, spellId2, true, NULL, this);
}
if (target->GetTypeId() == TYPEID_PLAYER)
{
const PlayerSpellMap& sp_list = target->ToPlayer()->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled) continue;
if (itr->first == spellId || itr->first == spellId2) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue;
if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, itr->first, true, NULL, this);
}
// Leader of the Pack
if (target->ToPlayer()->HasSpell(17007))
{
SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932);
if (spellInfo && spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, 24932, true, NULL, this);
}
// Improved Barkskin - apply/remove armor bonus due to shapeshift
if (target->ToPlayer()->HasSpell(63410) || target->ToPlayer()->HasSpell(63411))
{
target->RemoveAurasDueToSpell(66530);
if (GetMiscValue() == FORM_TRAVEL || GetMiscValue() == FORM_NONE) // "while in Travel Form or while not shapeshifted"
target->CastSpell(target, 66530, true);
}
// Heart of the Wild
if (HotWSpellId)
{ // hacky, but the only way as spell family is not SPELLFAMILY_DRUID
Unit::AuraEffectList const& mModTotalStatPct = target->GetAuraEffectsByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE);
for (Unit::AuraEffectList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i)
{
// Heart of the Wild
if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetMiscValue() == 3)
{
int32 HotWMod = (*i)->GetAmount();
target->CastCustomSpell(target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this);
break;
}
}
}
switch(GetMiscValue())
{
case FORM_CAT:
// Savage Roar
if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_DRUID, 0 , 0x10000000, 0))
target->CastSpell(target, 62071, true);
// Nurturing Instinct
if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT, SPELLFAMILY_DRUID, 2254, 0))
{
uint32 spellId = 0;
switch (aurEff->GetId())
{
case 33872:
spellId = 47179;
break;
case 33873:
spellId = 47180;
break;
}
target->CastSpell(target, spellId, true, NULL, this);
}
// Master Shapeshifter - Cat
if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
{
int32 bp = aurEff->GetAmount();
target->CastCustomSpell(target, 48420, &bp, NULL, NULL, true);
}
break;
case FORM_DIREBEAR:
case FORM_BEAR:
// Master Shapeshifter - Bear
if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
{
int32 bp = aurEff->GetAmount();
target->CastCustomSpell(target, 48418, &bp, NULL, NULL, true);
}
// Survival of the Fittest
if (AuraEffect const * aurEff = target->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DRUID, 961, 0))
{
int32 bp = 100 + SpellMgr::CalculateSpellEffectAmount(aurEff->GetSpellProto(), 2);
target->CastCustomSpell(target, 62069, &bp, NULL, NULL, true, 0, this);
}
break;
case FORM_MOONKIN:
// Master Shapeshifter - Moonkin
if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
{
int32 bp = aurEff->GetAmount();
target->CastCustomSpell(target, 48421, &bp, NULL, NULL, true);
}
break;
// Master Shapeshifter - Tree of Life
case FORM_TREE:
if (AuraEffect const * aurEff = target->GetDummyAuraEffect(SPELLFAMILY_GENERIC, 2851, 0))
{
int32 bp = aurEff->GetAmount();
target->CastCustomSpell(target, 48422, &bp, NULL, NULL, true);
}
break;
}
}
}
else
{
if (spellId)
target->RemoveAurasDueToSpell(spellId);
if (spellId2)
target->RemoveAurasDueToSpell(spellId2);
// Improved Barkskin - apply/remove armor bonus due to shapeshift
if (Player *pl=target->ToPlayer())
{
if (pl->HasSpell(63410) || pl->HasSpell(63411))
{
target->RemoveAurasDueToSpell(66530);
target->CastSpell(target,66530,true);
}
}
Unit::AuraApplicationMap& tAuras = target->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();)
{
if (itr->second->GetBase()->IsRemovedOnShapeLost(target))
target->RemoveAura(itr);
else
++itr;
}
}
}
/*********************************************************/
/*** AURA EFFECT HANDLERS ***/
/*********************************************************/
/**************************************/
/*** VISIBILITY & PHASES ***/
/**************************************/
void AuraEffect::HandleInvisibilityDetect(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
target->m_detectInvisibilityMask |= (1 << GetMiscValue());
}
else
{
// recalculate value at modifier remove (current aura already removed)
target->m_detectInvisibilityMask = 0;
Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
target->m_detectInvisibilityMask |= (1 << GetMiscValue());
}
if (target->GetTypeId() == TYPEID_PLAYER)
target->UpdateObjectVisibility();
}
void AuraEffect::HandleInvisibility(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
target->m_invisibilityMask |= (1 << GetMiscValue());
if (mode & AURA_EFFECT_HANDLE_REAL)
{
// drop flag at invisibiliy in bg
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
}
// apply glow vision
if (target->GetTypeId() == TYPEID_PLAYER)
target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
target->UpdateObjectVisibility();
}
else
{
// recalculate value at modifier remove (current aura already removed)
target->m_invisibilityMask = 0;
Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(SPELL_AURA_MOD_INVISIBILITY);
for (Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
target->m_invisibilityMask |= (1 << GetMiscValue());
// if not have different invisibility auras.
// remove glow vision
if (!target->m_invisibilityMask && target->GetTypeId() == TYPEID_PLAYER)
target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
target->UpdateObjectVisibility();
}
}
void AuraEffect::HandleModStealth(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
if (mode & AURA_EFFECT_HANDLE_REAL)
{
// drop flag at stealth in bg
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
}
target->SetStandFlags(UNIT_STAND_FLAGS_CREEP);
if (target->GetTypeId() == TYPEID_PLAYER)
target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000);
// apply only if not in GM invisibility (and overwrite invisibility state)
if (target->GetVisibility() != VISIBILITY_OFF)
target->SetVisibility(VISIBILITY_GROUP_STEALTH);
}
else if (!target->HasAuraType(SPELL_AURA_MOD_STEALTH)) // if last SPELL_AURA_MOD_STEALTH
{
target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP);
if (target->GetTypeId() == TYPEID_PLAYER)
target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000);
if (target->GetVisibility() != VISIBILITY_OFF)
target->SetVisibility(VISIBILITY_ON);
}
}
void AuraEffect::HandleSpiritOfRedemption(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// prepare spirit state
if (apply)
{
if (target->GetTypeId() == TYPEID_PLAYER)
{
// disable breath/etc timers
target->ToPlayer()->StopMirrorTimers();
// set stand state (expected in this form)
if (!target->IsStandState())
target->SetStandState(UNIT_STAND_STATE_STAND);
}
target->SetHealth(1);
}
// die at aura end
else
target->setDeathState(JUST_DIED);
}
void AuraEffect::HandleAuraGhost(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (apply)
target->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
else
{
if (target->HasAuraType(SPELL_AURA_GHOST))
return;
target->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST);
}
}
void AuraEffect::HandlePhase(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
// no-phase is also phase state so same code for apply and remove
// phase auras normally not expected at BG but anyway better check
if (target->GetTypeId() == TYPEID_PLAYER)
{
// drop flag at invisible in bg
if (target->ToPlayer()->InBattleGround())
if (BattleGround *bg = target->ToPlayer()->GetBattleGround())
bg->EventPlayerDroppedFlag(target->ToPlayer());
// GM-mode have mask 0xFFFFFFFF
if (!target->ToPlayer()->isGameMaster())
target->SetPhaseMask((apply) ? GetMiscValue() : PHASEMASK_NORMAL,false);
target->ToPlayer()->GetSession()->SendSetPhaseShift((apply) ? GetMiscValue() : PHASEMASK_NORMAL);
}
else
target->SetPhaseMask((apply) ? GetMiscValue() : PHASEMASK_NORMAL,false);
// need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases)
if (target->GetVisibility() != VISIBILITY_OFF)
target->SetVisibility(target->GetVisibility());
}
/**********************/
/*** UNIT MODEL ***/
/**********************/
void AuraEffect::HandleAuraModShapeshift(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
uint32 modelid = 0;
Powers PowerType = POWER_MANA;
ShapeshiftForm form = ShapeshiftForm(GetMiscValue());
switch(form)
{
case FORM_CAT:
case FORM_GHOUL:
PowerType = POWER_ENERGY;
break;
case FORM_BEAR:
case FORM_DIREBEAR:
case FORM_BATTLESTANCE:
case FORM_BERSERKERSTANCE:
case FORM_DEFENSIVESTANCE:
PowerType = POWER_RAGE;
break;
case FORM_TRAVEL:
case FORM_AQUA:
case FORM_CREATUREBEAR:
case FORM_GHOSTWOLF:
case FORM_FLIGHT:
case FORM_MOONKIN:
case FORM_FLIGHT_EPIC:
case FORM_METAMORPHOSIS:
case FORM_MASTER_ANGLER:
case FORM_AMBIENT:
case FORM_SHADOW:
case FORM_STEALTH:
case FORM_UNDEAD:
case FORM_SHADOW_DANCE:
case FORM_TREE:
case FORM_SPIRITOFREDEMPTION:
break;
default:
sLog.outError("Auras: Unknown Shapeshift Type: %u", GetMiscValue());
}
modelid = target->GetModelForForm(form);
// 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
target->RemoveMovementImpairingAuras();
// and polymorphic affects
if (target->IsPolymorphed())
target->RemoveAurasDueToSpell(target->getTransForm());
break;
}
default:
break;
}
if (apply)
{
// remove other shapeshift before applying a new one
if (target->m_ShapeShiftFormSpellId)
target->RemoveAurasDueToSpell(target->m_ShapeShiftFormSpellId);
target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
if (modelid > 0)
target->SetDisplayId(modelid);
if (PowerType != POWER_MANA)
{
uint32 oldPower = target->GetPower(PowerType);
// reset power to default values only at power change
if (target->getPowerType() != PowerType)
target->setPowerType(PowerType);
switch (form)
{
case FORM_CAT:
case FORM_BEAR:
case FORM_DIREBEAR:
{
// get furor proc chance
uint32 FurorChance = 0;
if (AuraEffect const *dummy = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, 238, 0))
FurorChance = std::max(dummy->GetAmount(), 0);
switch (GetMiscValue())
{
case FORM_CAT:
{
int32 basePoints = int32(std::min(oldPower, FurorChance));
target->CastCustomSpell(target, 17099, &basePoints, NULL, NULL, true, NULL, this);
}
break;
case FORM_BEAR:
case FORM_DIREBEAR:
if (urand(0,99) < FurorChance)
target->CastSpell(target, 17057, true);
default:
{
uint32 newEnergy = std::min(target->GetPower(POWER_ENERGY), FurorChance);
target->SetPower(POWER_ENERGY, newEnergy);
}
break;
}
break;
}
default:
break;
}
}
target->m_ShapeShiftFormSpellId = GetId();
target->m_form = form;
}
else
{
if (modelid > 0)
target->SetDisplayId(target->GetNativeDisplayId());
target->SetByteValue(UNIT_FIELD_BYTES_2, 3, FORM_NONE);
if (target->getClass() == CLASS_DRUID)
target->setPowerType(POWER_MANA);
target->m_ShapeShiftFormSpellId = 0;
target->m_form = FORM_NONE;
switch(form)
{
// Nordrassil Harness - bonus
case FORM_BEAR:
case FORM_DIREBEAR:
case FORM_CAT:
if (AuraEffect* dummy = target->GetAuraEffect(37315, 0))
target->CastSpell(target,37316,true,NULL,dummy);
break;
// Nordrassil Regalia - bonus
case FORM_MOONKIN:
if (AuraEffect* dummy = target->GetAuraEffect(37324, 0))
target->CastSpell(target,37325,true,NULL,dummy);
break;
case FORM_BATTLESTANCE:
case FORM_DEFENSIVESTANCE:
case FORM_BERSERKERSTANCE:
{
uint32 Rage_val = 0;
// Defensive Tactics
if (form == FORM_DEFENSIVESTANCE)
{
if (AuraEffect const * aurEff = target->IsScriptOverriden(m_spellProto,831))
Rage_val += aurEff->GetAmount() * 10;
}
// Stance mastery + Tactical mastery (both passive, and last have aura only in defense stance, but need apply at any stance switch)
if (target->GetTypeId() == TYPEID_PLAYER)
{
PlayerSpellMap const& sp_list = target->ToPlayer()->GetSpellMap();
for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
{
if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->disabled) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (spellInfo && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && spellInfo->SpellIconID == 139)
Rage_val += target->CalculateSpellDamage(target,spellInfo,0) * 10;
}
}
if (target->GetPower(POWER_RAGE) > Rage_val)
target->SetPower(POWER_RAGE,Rage_val);
break;
}
default:
break;
}
}
// adding/removing linked auras
// add/remove the shapeshift aura's boosts
HandleShapeshiftBoosts(target, apply);
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->InitDataForForm();
if (target->getClass() == CLASS_DRUID)
{
// Dash
if (AuraEffect * aurEff =target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8))
aurEff->RecalculateAmount();
}
if (target->GetTypeId() == TYPEID_PLAYER)
{
SpellShapeshiftEntry const *shapeInfo = sSpellShapeshiftStore.LookupEntry(form);
// Learn spells for shapeshift form - no need to send action bars or add spells to spellbook
for (uint8 i = 0; i<MAX_SHAPESHIFT_SPELLS; ++i)
{
if (!shapeInfo->stanceSpell[i])
continue;
if (apply)
target->ToPlayer()->AddTemporarySpell(shapeInfo->stanceSpell[i]);
else
target->ToPlayer()->RemoveTemporarySpell(shapeInfo->stanceSpell[i]);
}
}
}
void AuraEffect::HandleAuraTransform(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
// special case (spell specific functionality)
if (GetMiscValue() == 0)
{
// player applied only
if (target->GetTypeId() != TYPEID_PLAYER)
return;
switch (GetId())
{
// Orb of Deception
case 16739:
{
uint32 orb_model = target->GetNativeDisplayId();
switch(orb_model)
{
// Troll Female
case 1479: target->SetDisplayId(10134); break;
// Troll Male
case 1478: target->SetDisplayId(10135); break;
// Tauren Male
case 59: target->SetDisplayId(10136); break;
// Human Male
case 49: target->SetDisplayId(10137); break;
// Human Female
case 50: target->SetDisplayId(10138); break;
// Orc Male
case 51: target->SetDisplayId(10139); break;
// Orc Female
case 52: target->SetDisplayId(10140); break;
// Dwarf Male
case 53: target->SetDisplayId(10141); break;
// Dwarf Female
case 54: target->SetDisplayId(10142); break;
// NightElf Male
case 55: target->SetDisplayId(10143); break;
// NightElf Female
case 56: target->SetDisplayId(10144); break;
// Undead Female
case 58: target->SetDisplayId(10145); break;
// Undead Male
case 57: target->SetDisplayId(10146); break;
// Tauren Female
case 60: target->SetDisplayId(10147); break;
// Gnome Male
case 1563: target->SetDisplayId(10148); break;
// Gnome Female
case 1564: target->SetDisplayId(10149); break;
// BloodElf Female
case 15475: target->SetDisplayId(17830); break;
// BloodElf Male
case 15476: target->SetDisplayId(17829); break;
// Dranei Female
case 16126: target->SetDisplayId(17828); break;
// Dranei Male
case 16125: target->SetDisplayId(17827); break;
default: break;
}
break;
}
// Murloc costume
case 42365: target->SetDisplayId(21723); break;
default: break;
}
}
else
{
CreatureInfo const * ci = objmgr.GetCreatureTemplate(GetMiscValue());
if (!ci)
{
target->SetDisplayId(16358); // pig pink ^_^
sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", GetMiscValue(), GetId());
}
else
{
uint32 model_id = 0;
if (uint32 modelid = ci->GetRandomValidModelId())
model_id = modelid; // Will use the default model here
// Polymorph (sheep)
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellProto()->SpellIconID == 82 && GetSpellProto()->SpellVisual[0] == 12978)
if (Unit * caster = GetCaster())
if (caster->HasAura(52648)) // Glyph of the Penguin
model_id = 26452;
target->SetDisplayId(model_id);
// Dragonmaw Illusion (set mount model also)
if (GetId() == 42016 && target->GetMountID() && !target->GetAuraEffectsByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED).empty())
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
}
}
// update active transform spell only not set or not overwriting negative by positive case
if (!target->getTransForm() || !IsPositiveSpell(GetId()) || IsPositiveSpell(target->getTransForm()))
target->setTransForm(GetId());
// polymorph case
if ((mode & AURA_EFFECT_HANDLE_REAL) && target->GetTypeId() == TYPEID_PLAYER && 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()))
target->ToPlayer()->setRegenTimerCount(1*IN_MILLISECONDS);
//dismount polymorphed target (after patch 2.4.2)
if (target->IsMounted())
target->RemoveAurasByType(SPELL_AURA_MOUNTED);
}
}
else
{
// HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true) will reapply it if need
target->setTransForm(0);
target->SetDisplayId(target->GetNativeDisplayId());
// re-aplly some from still active with preference negative cases
Unit::AuraEffectList const& otherTransforms = target->GetAuraEffectsByType(SPELL_AURA_TRANSFORM);
if (!otherTransforms.empty())
{
// look for other transform auras
AuraEffect* handledAura = *otherTransforms.begin();
for (Unit::AuraEffectList::const_iterator i = otherTransforms.begin(); i != otherTransforms.end(); ++i)
{
// negative auras are preferred
if (!IsPositiveSpell((*i)->GetSpellProto()->Id))
{
handledAura = *i;
break;
}
}
handledAura->HandleEffect(target, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true);
}
// Dragonmaw Illusion (restore mount model)
if (GetId() == 42016 && target->GetMountID() == 16314)
{
if (!target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).empty())
{
uint32 cr_id = target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetMiscValue();
if (CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id))
{
uint32 team = 0;
if (target->GetTypeId() == TYPEID_PLAYER)
team = target->ToPlayer()->GetTeam();
uint32 display_id = objmgr.ChooseDisplayId(team,ci);
CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
if (minfo)
display_id = minfo->modelid;
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,display_id);
}
}
}
}
}
void AuraEffect::HandleAuraModScale(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,GetAmount(),apply);
}
void AuraEffect::HandleAuraCloneCaster(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
Unit * caster = GetCaster();
if (!caster)
return;
// Set display id (probably for portrait?)
target->SetDisplayId(caster->GetDisplayId());
target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE);
}
else
{
target->SetDisplayId(target->GetNativeDisplayId());
target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE);
}
}
/************************/
/*** FIGHT ***/
/************************/
void AuraEffect::HandleFeignDeath(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (apply)
{
/*
WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
data<<target->GetGUID();
data<<uint8(0);
target->SendMessageToSet(&data,true);
*/
UnitList targets;
Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(target, target, target->GetMap()->GetVisibilityDistance());
Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, targets, u_check);
target->VisitNearbyObject(target->GetMap()->GetVisibilityDistance(), searcher);
for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter)
{
if (!(*iter)->hasUnitState(UNIT_STAT_CASTING))
continue;
for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
{
if ((*iter)->GetCurrentSpell(i)
&& (*iter)->GetCurrentSpell(i)->m_targets.getUnitTargetGUID() == target->GetGUID())
{
(*iter)->InterruptSpell(CurrentSpellTypes(i), false);
}
}
}
// blizz like 2.0.x
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
// blizz like 2.0.x
target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
// blizz like 2.0.x
target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
target->addUnitState(UNIT_STAT_DIED);
target->CombatStop();
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
// prevent interrupt message
if (GetCasterGUID() == target->GetGUID() && target->GetCurrentSpell(CURRENT_GENERIC_SPELL))
target->FinishSpell(CURRENT_GENERIC_SPELL, false);
target->InterruptNonMeleeSpells(true);
target->getHostileRefManager().deleteReferences();
}
else
{
/*
WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 9);
data<<target->GetGUID();
data<<uint8(1);
target->SendMessageToSet(&data,true);
*/
// blizz like 2.0.x
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29);
// blizz like 2.0.x
target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
// blizz like 2.0.x
target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
target->clearUnitState(UNIT_STAT_DIED);
}
}
void AuraEffect::HandleModUnattackable(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
if (mode & AURA_EFFECT_HANDLE_REAL)
{
target->CombatStop();
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
}
}
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
else if (target->HasAuraType(SPELL_AURA_MOD_UNATTACKABLE))
return;
target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, apply);
}
void AuraEffect::HandleAuraModDisarm(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
AuraType type = GetAuraType();
//Prevent handling aura twice
if ((apply) ? target->GetAuraEffectsByType(type).size() > 1 : target->HasAuraType(type))
return;
uint32 field, flag, slot;
WeaponAttackType attType;
switch (type)
{
case SPELL_AURA_MOD_DISARM:
field=UNIT_FIELD_FLAGS;
flag=UNIT_FLAG_DISARMED;
slot=EQUIPMENT_SLOT_MAINHAND;
attType=BASE_ATTACK;
break;
case SPELL_AURA_MOD_DISARM_OFFHAND:
field=UNIT_FIELD_FLAGS_2;
flag=UNIT_FLAG2_DISARM_OFFHAND;
slot=EQUIPMENT_SLOT_OFFHAND;
attType=OFF_ATTACK;
break;
case SPELL_AURA_MOD_DISARM_RANGED:
field=UNIT_FIELD_FLAGS_2;
flag=UNIT_FLAG2_DISARM_RANGED;
slot=EQUIPMENT_SLOT_RANGED;
attType=RANGED_ATTACK;
break;
default:
return;
}
if (!(apply))
target->RemoveFlag(field, flag);
if (target->GetTypeId() == TYPEID_PLAYER)
{
// This is between the two because there is a check in _ApplyItemMods
// we must make sure that flag is always removed when call that function
// refer to DurabilityPointsLoss
if (Item *pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot))
target->ToPlayer()->_ApplyItemMods(pItem, slot, !apply);
}
if (apply)
target->SetFlag(field, flag);
if (target->GetTypeId() == TYPEID_UNIT && target->ToCreature()->GetCurrentEquipmentId())
target->UpdateDamagePhysical(attType);
}
void AuraEffect::HandleAuraModSilence(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
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)
if (Spell* spell = target->GetCurrentSpell(CurrentSpellTypes(i)))
if (spell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
// Stop spells on prepare or casting state
target->InterruptSpell(CurrentSpellTypes(i), false);
}
else
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(SPELL_AURA_MOD_SILENCE) || target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE))
return;
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED);
}
}
void AuraEffect::HandleAuraModPacify(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
else
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(SPELL_AURA_MOD_PACIFY) || target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE))
return;
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
}
}
void AuraEffect::HandleAuraModPacifyAndSilence(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
// Vengeance of the Blue Flight (TODO: REMOVE THIS!)
if (m_spellProto->Id == 45839)
{
if (apply)
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
else
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
}
if (!(apply))
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(SPELL_AURA_MOD_PACIFY_SILENCE))
return;
}
HandleAuraModPacify(aurApp, mode, apply);
HandleAuraModSilence(aurApp, mode, apply);
}
void AuraEffect::HandleAuraAllowOnlyAbility(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() == TYPEID_PLAYER)
{
if (apply)
target->SetFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY);
else
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(SPELL_AURA_ALLOW_ONLY_ABILITY))
return;
target->RemoveFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY);
}
}
}
/****************************/
/*** TRACKING ***/
/****************************/
void AuraEffect::HandleAuraTrackCreatures(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->SetUInt32Value(PLAYER_TRACK_CREATURES, (apply) ? ((uint32)1)<<(GetMiscValue()-1) : 0);
}
void AuraEffect::HandleAuraTrackResources(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->SetUInt32Value(PLAYER_TRACK_RESOURCES, (apply) ? ((uint32)1)<<(GetMiscValue()-1): 0);
}
void AuraEffect::HandleAuraTrackStealthed(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (!(apply))
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
}
target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply);
}
void AuraEffect::HandleAuraModStalked(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
// used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND
if (apply)
target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
else
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_TRACK_UNIT);
}
}
void AuraEffect::HandleAuraUntrackable(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
target->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE);
else
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
target->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE);
}
}
/****************************/
/*** SKILLS & TALENTS ***/
/****************************/
void AuraEffect::HandleAuraModPetTalentsPoints(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// Recalculate pet talent points
if (Pet *pet = target->ToPlayer()->GetPet())
pet->InitTalentForLevel();
}
void AuraEffect::HandleAuraModSkill(AuraApplication const * aurApp, uint8 /*mode*/, bool apply) const
{
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
uint32 prot = GetSpellProto()->EffectMiscValue[m_effIndex];
int32 points = GetAmount();
target->ToPlayer()->ModifySkillBonus(prot,((apply) ? points: -points),GetAuraType() == SPELL_AURA_MOD_SKILL_TALENT);
if (prot == SKILL_DEFENSE)
target->ToPlayer()->UpdateDefenseBonusesMod();
}
/****************************/
/*** MOVEMENT ***/
/****************************/
void AuraEffect::HandleAuraMounted(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
CreatureInfo const* ci = objmgr.GetCreatureTemplate(GetMiscValue());
if (!ci)
{
sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)",GetMiscValue());
return;
}
uint32 team = 0;
if (target->GetTypeId() == TYPEID_PLAYER)
team = target->ToPlayer()->GetTeam();
uint32 display_id = objmgr.ChooseDisplayId(team,ci);
CreatureModelInfo const *minfo = objmgr.GetCreatureModelRandomGender(display_id);
if (minfo)
display_id = minfo->modelid;
//some spell has one aura of mount and one of vehicle
for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (GetSpellProto()->Effect[i] == SPELL_EFFECT_SUMMON
&& GetSpellProto()->EffectMiscValue[i] == GetMiscValue())
display_id = 0;
target->Mount(display_id,ci->VehicleId);
}
else
{
target->Unmount();
//some mounts like Headless Horseman's Mount or broom stick are skill based spell
// need to remove ALL arura related to mounts, this will stop client crash with broom stick
// and never endless flying after using Headless Horseman's Mount
if (mode & AURA_EFFECT_HANDLE_REAL)
target->RemoveAurasByType(SPELL_AURA_MOUNTED);
}
}
void AuraEffect::HandleAuraAllowFlight(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (!apply)
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()) || target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
return;
}
if (target->GetTypeId() == TYPEID_UNIT)
target->SetFlying(apply);
if (Player *plr = target->m_movedPlayer)
{
// 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(target->GetPackGUID());
data << uint32(0); // unk
plr->SendDirectMessage(&data);
}
}
void AuraEffect::HandleAuraWaterWalk(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (!(apply))
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
}
WorldPacket data;
if (apply)
data.Initialize(SMSG_MOVE_WATER_WALK, 8+4);
else
data.Initialize(SMSG_MOVE_LAND_WALK, 8+4);
data.append(target->GetPackGUID());
data << uint32(0);
target->SendMessageToSet(&data,true);
}
void AuraEffect::HandleAuraFeatherFall(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (!(apply))
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
}
WorldPacket data;
if (apply)
data.Initialize(SMSG_MOVE_FEATHER_FALL, 8+4);
else
data.Initialize(SMSG_MOVE_NORMAL_FALL, 8+4);
data.append(target->GetPackGUID());
data << uint32(0);
target->SendMessageToSet(&data, true);
// start fall from current height
if (!apply && target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->SetFallInformation(0, target->GetPositionZ());
}
void AuraEffect::HandleAuraHover(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (!(apply))
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
}
WorldPacket data;
if (apply)
data.Initialize(SMSG_MOVE_SET_HOVER, 8+4);
else
data.Initialize(SMSG_MOVE_UNSET_HOVER, 8+4);
data.append(target->GetPackGUID());
data << uint32(0);
target->SendMessageToSet(&data,true);
}
void AuraEffect::HandleWaterBreathing(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
// update timers in client
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateMirrorTimers();
}
void AuraEffect::HandleForceMoveForward(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (apply)
target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
else
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE);
}
}
/****************************/
/*** THREAT ***/
/****************************/
void AuraEffect::HandleModThreat(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (!target->isAlive())
return;
Unit * caster = GetCaster();
if (!caster || !caster->isAlive())
return;
if (target->GetTypeId() == TYPEID_PLAYER)
for (int8 x=0; x < MAX_SPELL_SCHOOL; x++)
if (GetMiscValue() & int32(1<<x))
ApplyPercentModFloatVar(target->m_threatModifier[x], GetAmount(), apply);
}
void AuraEffect::HandleAuraModTotalThreat(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (!target->isAlive() || target->GetTypeId() != TYPEID_PLAYER)
return;
Unit * caster = GetCaster();
if (!caster || !caster->isAlive())
return;
target->getHostileRefManager().addTempThreat(GetAmount(), apply);
}
void AuraEffect::HandleModTaunt(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (!target->isAlive() || !target->CanHaveThreatList())
return;
Unit * caster = GetCaster();
if (!caster || !caster->isAlive())
return;
if (apply)
target->TauntApply(caster);
else
{
// When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
target->TauntFadeOut(caster);
}
}
/*****************************/
/*** CONTROL ***/
/*****************************/
void AuraEffect::HandleModConfuse(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
target->SetControlled(apply, UNIT_STAT_CONFUSED);
}
void AuraEffect::HandleModFear(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
target->SetControlled(apply, UNIT_STAT_FLEEING);
}
void AuraEffect::HandleAuraModStun(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
target->SetControlled(apply, UNIT_STAT_STUNNED);
}
void AuraEffect::HandleAuraModRoot(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
target->SetControlled(apply, UNIT_STAT_ROOT);
}
void AuraEffect::HandlePreventFleeing(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
Unit::AuraEffectList const& fearAuras = target->GetAuraEffectsByType(SPELL_AURA_MOD_FEAR);
if (!fearAuras.empty())
target->SetControlled(!(apply), UNIT_STAT_FLEEING);
}
/***************************/
/*** CHARM ***/
/***************************/
void AuraEffect::HandleModPossess(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
Unit * caster = GetCaster();
if (caster && caster->GetTypeId() == TYPEID_UNIT)
{
HandleModCharm(aurApp, mode, apply);
return;
}
if (apply)
target->SetCharmedBy(caster, CHARM_TYPE_POSSESS);
else
target->RemoveCharmedBy(caster);
}
// only one spell has this aura
void AuraEffect::HandleModPossessPet(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
Unit * caster = GetCaster();
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
//seems it may happen that when removing it is no longer owner's pet
//if (caster->ToPlayer()->GetPet() != target)
// return;
if (apply)
{
if (caster->ToPlayer()->GetPet() != target)
return;
target->SetCharmedBy(caster, CHARM_TYPE_POSSESS);
}
else
{
target->RemoveCharmedBy(caster);
// Reinitialize the pet bar and make the pet come back to the owner
caster->ToPlayer()->PetSpellInitialize();
if (!target->getVictim())
{
target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, target->GetFollowAngle());
//if (target->GetCharmInfo())
// target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
}
}
}
void AuraEffect::HandleModCharm(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
Unit * caster = GetCaster();
if (apply)
target->SetCharmedBy(caster, CHARM_TYPE_CHARM);
else
target->RemoveCharmedBy(caster);
}
void AuraEffect::HandleCharmConvert(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
Unit * caster = GetCaster();
if (apply)
target->SetCharmedBy(caster, CHARM_TYPE_CONVERT);
else
target->RemoveCharmedBy(caster);
}
/**
* Such auras are applied from a caster(=player) to a vehicle.
* This has been verified using spell #49256
*/
void AuraEffect::HandleAuraControlVehicle(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (!target->IsVehicle())
return;
Unit * caster = GetCaster();
if (!caster || caster == target)
return;
if (apply)
{
//if (caster->GetTypeId() == TYPEID_PLAYER)
// if (Pet *pet = caster->ToPlayer()->GetPet())
// pet->Remove(PET_SAVE_AS_CURRENT);
caster->EnterVehicle(target->GetVehicleKit(), m_amount - 1);
}
else
{
if (GetId() == 53111) // Devour Humanoid
{
target->Kill(caster);
if (caster->GetTypeId() == TYPEID_UNIT)
caster->ToCreature()->RemoveCorpse();
}
// some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them
caster->RemoveAurasDueToSpell(GetId());
caster->ExitVehicle();
}
}
/*********************************************************/
/*** MODIFY SPEED ***/
/*********************************************************/
void AuraEffect::HandleAuraModIncreaseSpeed(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
target->UpdateSpeed(MOVE_RUN, true);
}
void AuraEffect::HandleAuraModIncreaseMountedSpeed(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
target->UpdateSpeed(MOVE_RUN, true);
}
void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
// Enable Fly mode for flying mounts
if (GetAuraType() == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED)
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK && (apply || (!target->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) && !target->HasAuraType(SPELL_AURA_FLY))))
{
if (Player *plr = target->m_movedPlayer)
{
WorldPacket data;
if (apply)
data.Initialize(SMSG_MOVE_SET_CAN_FLY, 12);
else
data.Initialize(SMSG_MOVE_UNSET_CAN_FLY, 12);
data.append(plr->GetPackGUID());
data << uint32(0); // unknown
plr->SendDirectMessage(&data);
}
}
if (mode & AURA_EFFECT_HANDLE_REAL)
{
//Players on flying mounts must be immune to polymorph
if (target->GetTypeId() == TYPEID_PLAYER)
target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply);
// Dragonmaw Illusion (overwrite mount model, mounted aura already applied)
if (apply && target->HasAuraEffect(42016,0) && target->GetMountID())
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314);
}
}
if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
target->UpdateSpeed(MOVE_FLIGHT, true);
}
void AuraEffect::HandleAuraModIncreaseSwimSpeed(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
target->UpdateSpeed(MOVE_SWIM, true);
}
void AuraEffect::HandleAuraModDecreaseSpeed(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
target->UpdateSpeed(MOVE_RUN, true);
target->UpdateSpeed(MOVE_SWIM, true);
target->UpdateSpeed(MOVE_FLIGHT, true);
target->UpdateSpeed(MOVE_RUN_BACK, true);
target->UpdateSpeed(MOVE_SWIM_BACK, true);
target->UpdateSpeed(MOVE_FLIGHT_BACK, true);
}
void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
target->UpdateSpeed(MOVE_RUN, true);
target->UpdateSpeed(MOVE_SWIM, true);
target->UpdateSpeed(MOVE_FLIGHT, true);
}
/*********************************************************/
/*** IMMUNITY ***/
/*********************************************************/
void AuraEffect::HandleModStateImmunityMask(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
std::list <AuraType> immunity_list;
if (GetMiscValue() & (1<<10))
immunity_list.push_back(SPELL_AURA_MOD_STUN);
if (GetMiscValue() & (1<<7))
immunity_list.push_back(SPELL_AURA_MOD_DISARM);
if (GetMiscValue() & (1<<1))
immunity_list.push_back(SPELL_AURA_TRANSFORM);
// These flag can be recognized wrong:
if (GetMiscValue() & (1<<6))
immunity_list.push_back(SPELL_AURA_MOD_DECREASE_SPEED);
if (GetMiscValue() & (1<<0))
immunity_list.push_back(SPELL_AURA_MOD_ROOT);
if (GetMiscValue() & (1<<2))
immunity_list.push_back(SPELL_AURA_MOD_CONFUSE);
if (GetMiscValue() & (1<<9))
immunity_list.push_back(SPELL_AURA_MOD_FEAR);
// Patch 3.0.3 Bladestorm now breaks all snares and roots on the warrior when activated.
// however not all mechanic specified in immunity
if (apply && GetId() == 46924)
{
target->RemoveAurasByType(SPELL_AURA_MOD_ROOT);
target->RemoveAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
}
if (apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
{
for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter)
{
target->RemoveAurasByType(*iter);
}
}
for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end(); ++iter)
{
target->ApplySpellImmune(GetId(),IMMUNITY_STATE,*iter, apply);
}
}
void AuraEffect::HandleModMechanicImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
uint32 mechanic;
switch (GetId())
{
case 42292: // PvP trinket
case 59752: // Every Man for Himself
mechanic = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
// Actually we should apply immunities here, too, but the aura has only 100 ms duration, so there is practically no point
break;
case 54508: // Demonic Empowerment
mechanic = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT);
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
break;
case 34471: // The Beast Within
case 19574: // Bestial Wrath
mechanic = (1 << MECHANIC_SNARE) | (1 << MECHANIC_ROOT) | (1 << MECHANIC_FEAR) | (1 << MECHANIC_STUN);
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_SNARE, apply);
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_ROOT, apply);
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_FEAR, apply);
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_STUN, apply);
break;
default:
if (GetMiscValue() < 1)
return;
mechanic = 1 << GetMiscValue();
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, GetMiscValue(), apply);
break;
}
if (apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
target->RemoveAurasWithMechanic(mechanic, AURA_REMOVE_BY_DEFAULT, GetId());
}
void AuraEffect::HandleAuraModEffectImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
// when removing flag aura, handle flag drop
if (!(apply) && target->GetTypeId() == TYPEID_PLAYER
&& (GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION))
{
if (target->GetTypeId() == TYPEID_PLAYER)
{
if (target->ToPlayer()->InBattleGround())
{
if (BattleGround *bg = target->ToPlayer()->GetBattleGround())
bg->EventPlayerDroppedFlag(target->ToPlayer());
}
else
sOutdoorPvPMgr.HandleDropFlag((Player*)target,GetSpellProto()->Id);
}
}
target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,GetMiscValue(),apply);
}
void AuraEffect::HandleAuraModStateImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if ((apply) && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
{
target->RemoveAurasByType(AuraType(GetMiscValue()), NULL , GetBase());
}
target->ApplySpellImmune(GetId(), IMMUNITY_STATE, GetMiscValue(), apply);
}
void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if ((apply) && GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL)
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,GetMiscValue(),(apply));
// remove all flag auras (they are positive, but they must be removed when you are immune)
if (GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY
&& GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD)
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
// TODO: optimalize this cycle - use RemoveAurasWithInterruptFlags call or something else
if ((apply)
&& GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY
&& IsPositiveSpell(GetId())) //Only positive immunity removes auras
{
uint32 school_mask = GetMiscValue();
Unit::AuraApplicationMap& Auras = target->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator iter = Auras.begin(); iter != Auras.end();)
{
SpellEntry const *spell = iter->second->GetBase()->GetSpellProto();
if ((GetSpellSchoolMask(spell) & school_mask)//Check for school mask
&& CanSpellDispelAura(GetSpellProto(),spell)
&& !iter->second->IsPositive() //Don't remove positive spells
&& spell->Id != GetId()) //Don't remove self
{
target->RemoveAura(iter);
}
else
++iter;
}
}
if (GetSpellProto()->Mechanic == MECHANIC_BANISH)
{
if (apply)
target->addUnitState(UNIT_STAT_ISOLATED);
else
{
bool banishFound = false;
Unit::AuraEffectList const& banishAuras = target->GetAuraEffectsByType(GetAuraType());
for (Unit::AuraEffectList::const_iterator i = banishAuras.begin(); i != banishAuras.end(); ++i)
if ((*i)->GetSpellProto()->Mechanic == MECHANIC_BANISH)
{
banishFound = true;
break;
}
if (!banishFound)
target->clearUnitState(UNIT_STAT_ISOLATED);
}
}
}
void AuraEffect::HandleAuraModDmgImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,GetMiscValue(), apply);
}
void AuraEffect::HandleAuraModDispelImmunity(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
target->ApplySpellDispelImmunity(m_spellProto, DispelType(GetMiscValue()), (apply));
}
/*********************************************************/
/*** MODIFY STATS ***/
/*********************************************************/
/********************************/
/*** RESISTANCE ***/
/********************************/
void AuraEffect::HandleAuraModResistanceExclusive(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
{
if (GetMiscValue() & int32(1<<x))
{
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER)
target->ApplyResistanceBuffModsMod(SpellSchools(x),aurApp->IsPositive(),GetAmount(), apply);
}
}
}
void AuraEffect::HandleAuraModResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
{
if (GetMiscValue() & int32(1<<x))
{
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
target->ApplyResistanceBuffModsMod(SpellSchools(x),GetAmount() > 0,GetAmount(), apply);
}
}
}
void AuraEffect::HandleAuraModBaseResistancePCT(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
// only players have base stats
if (target->GetTypeId() != TYPEID_PLAYER)
{
//pets only have base armor
if (target->ToCreature()->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetAmount()), apply);
}
else
{
for (int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL; x++)
{
if (GetMiscValue() & int32(1<<x))
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetAmount()), apply);
}
}
}
void AuraEffect::HandleModResistancePercent(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
for (int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
{
if (GetMiscValue() & int32(1<<i))
{
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
{
target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,GetAmount(), apply);
target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,GetAmount(), apply);
}
}
}
}
void AuraEffect::HandleModBaseResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
// only players have base stats
if (target->GetTypeId() != TYPEID_PLAYER)
{
//only pets have base stats
if (target->ToCreature()->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetAmount()), apply);
}
else
{
for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++)
if (GetMiscValue() & (1<<i))
target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetAmount()), apply);
}
}
void AuraEffect::HandleModTargetResistance(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
// applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage
// show armor penetration
if (target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL))
target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,GetAmount(), apply);
// show as spell penetration only full spell penetration bonuses (all resistances except armor and holy
if (target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_SPELL) == SPELL_SCHOOL_MASK_SPELL)
target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,GetAmount(), apply);
}
/********************************/
/*** STAT ***/
/********************************/
void AuraEffect::HandleAuraModStat(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (GetMiscValue() < -2 || GetMiscValue() > 4)
{
sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),GetMiscValue());
return;
}
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
{
// -1 or -2 is all stats (misc < -2 checked in function beginning)
if (GetMiscValue() < 0 || GetMiscValue() == i)
{
//target->ApplyStatMod(Stats(i), m_amount,apply);
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
target->ApplyStatBuffMod(Stats(i),GetAmount(),apply);
}
}
}
void AuraEffect::HandleModPercentStat(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (GetMiscValue() < -1 || GetMiscValue() > 4)
{
sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid");
return;
}
// only players have base stats
if (target->GetTypeId() != TYPEID_PLAYER)
return;
for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i)
{
if (GetMiscValue() == i || GetMiscValue() == -1)
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply);
}
}
void AuraEffect::HandleModSpellDamagePercentFromStat(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// Magic damage modifiers implemented in Unit::SpellDamageBonus
// This information for client side use only
// Recalculate bonus
target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}
void AuraEffect::HandleModSpellHealingPercentFromStat(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// Recalculate bonus
target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}
void AuraEffect::HandleModSpellDamagePercentFromAttackPower(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// Magic damage modifiers implemented in Unit::SpellDamageBonus
// This information for client side use only
// Recalculate bonus
target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}
void AuraEffect::HandleModSpellHealingPercentFromAttackPower(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// Recalculate bonus
target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}
void AuraEffect::HandleModHealingDone(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// implemented in Unit::SpellHealingBonus
// this information is for client side only
target->ToPlayer()->UpdateSpellDamageAndHealingBonus();
}
void AuraEffect::HandleModTotalPercentStat(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (GetMiscValue() < -1 || GetMiscValue() > 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 = target->GetHealth();
uint32 maxHPValue = target->GetMaxHealth();
for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++)
{
if (GetMiscValue() == i || GetMiscValue() == -1)
{
target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER || target->ToCreature()->isPet())
target->ApplyStatPercentBuffMod(Stats(i), GetAmount(), apply);
}
}
//recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag)
if ((GetMiscValue() == 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
uint64 newHPValue = (target->GetMaxHealth() * curHPValue) / maxHPValue;
target->SetHealth(newHPValue);
}
}
void AuraEffect::HandleAuraModResistenceOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
if (GetMiscValue() != 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
target->UpdateArmor();
}
void AuraEffect::HandleAuraModExpertise(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->ToPlayer()->UpdateExpertise(BASE_ATTACK);
target->ToPlayer()->UpdateExpertise(OFF_ATTACK);
}
/********************************/
/*** HEAL & ENERGIZE ***/
/********************************/
void AuraEffect::HandleModPowerRegen(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// Update manaregen value
if (GetMiscValue() == POWER_MANA)
target->ToPlayer()->UpdateManaRegen();
// other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate
}
void AuraEffect::HandleModPowerRegenPCT(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// Update manaregen value
if (GetMiscValue() == POWER_MANA)
target->ToPlayer()->UpdateManaRegen();
// other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate
}
void AuraEffect::HandleModManaRegen(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
//Note: an increase in regen does NOT cause threat.
target->ToPlayer()->UpdateManaRegen();
}
void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
target->ModifyHealth(GetAmount());
}
else
{
if (int32(target->GetHealth()) > GetAmount())
target->ModifyHealth(-GetAmount());
else
target->SetHealth(1);
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
}
}
void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
uint32 oldhealth = target->GetHealth();
double healthPercentage = (double)oldhealth / (double)target->GetMaxHealth();
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
// refresh percentage
if (oldhealth > 0)
{
uint32 newhealth = uint32(ceil((double)target->GetMaxHealth() * healthPercentage));
if (newhealth == 0)
newhealth = 1;
target->SetHealth(newhealth);
}
}
void AuraEffect::HandleAuraModIncreaseEnergy(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
Powers powerType = target->getPowerType();
if (int32(powerType) != GetMiscValue())
return;
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
// Special case with temporary increase max/current power (percent)
if (GetId() == 64904) // Hymn of Hope
{
if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
{
int32 change = target->GetPower(powerType) + (apply ? GetAmount() : -GetAmount());
if (change < 0)
change = 0;
target->SetPower(powerType, change);
}
}
// generic flat case
target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModIncreaseEnergyPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
Powers powerType = target->getPowerType();
if (int32(powerType) != GetMiscValue())
return;
UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType);
target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
// Unit will keep hp% after MaxHealth being modified if unit is alive.
float percent = ((float)target->GetHealth()) / target->GetMaxHealth();
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply);
if (target->isAlive())
target->SetHealth(uint32(target->GetMaxHealth()*percent));
}
void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(GetAmount()), apply);
}
/********************************/
/*** FIGHT ***/
/********************************/
void AuraEffect::HandleAuraModParryPercent(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->ToPlayer()->UpdateParryPercentage();
}
void AuraEffect::HandleAuraModDodgePercent(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->ToPlayer()->UpdateDodgePercentage();
}
void AuraEffect::HandleAuraModBlockPercent(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->ToPlayer()->UpdateBlockPercentage();
}
void AuraEffect::HandleAuraModRegenInterrupt(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->ToPlayer()->UpdateManaRegen();
}
void AuraEffect::HandleAuraModWeaponCritPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
for (int i = 0; i < MAX_ATTACK; ++i)
if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
target->ToPlayer()->_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
// GetMiscValue() comparison with item generated damage types
if (GetSpellProto()->EquippedItemClass == -1)
{
target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
}
else
{
// done in Player::_ApplyWeaponDependentAuraMods
}
}
void AuraEffect::HandleModHitChance(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() == TYPEID_PLAYER)
{
target->ToPlayer()->UpdateMeleeHitChances();
target->ToPlayer()->UpdateRangedHitChances();
}
else
{
target->m_modMeleeHitChance += (apply) ? GetAmount() : (-GetAmount());
target->m_modRangedHitChance += (apply) ? GetAmount() : (-GetAmount());
}
}
void AuraEffect::HandleModSpellHitChance(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateSpellHitChances();
else
target->m_modSpellHitChance += (apply) ? GetAmount(): (-GetAmount());
}
void AuraEffect::HandleModSpellCritChance(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateAllSpellCritChances();
else
target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount();
}
void AuraEffect::HandleModSpellCritChanceShool(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
for (int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school)
if (GetMiscValue() & (1<<school))
target->ToPlayer()->UpdateSpellCritChance(school);
}
void AuraEffect::HandleAuraModCritPct(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
{
target->m_baseSpellCritChance += (apply) ? GetAmount():-GetAmount();
return;
}
target->ToPlayer()->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
target->ToPlayer()->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
target->ToPlayer()->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetAmount()), apply);
// included in Player::UpdateSpellCritChance calculation
target->ToPlayer()->UpdateAllSpellCritChances();
}
/********************************/
/*** ATTACK SPEED ***/
/********************************/
void AuraEffect::HandleModCastingSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->ApplyCastTimePercentMod(GetAmount(),apply);
}
void AuraEffect::HandleModMeleeRangedSpeedPct(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(BASE_ATTACK,GetAmount(),apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK,GetAmount(),apply);
target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetAmount(), apply);
}
void AuraEffect::HandleModCombatSpeedPct(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->ApplyCastTimePercentMod(m_amount,apply);
target->ApplyAttackTimePercentMod(BASE_ATTACK,GetAmount(),apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK,GetAmount(),apply);
target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetAmount(), apply);
}
void AuraEffect::HandleModAttackSpeed(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(BASE_ATTACK,GetAmount(),apply);
target->UpdateDamagePhysical(BASE_ATTACK);
}
void AuraEffect::HandleHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(BASE_ATTACK, GetAmount(),apply);
target->ApplyAttackTimePercentMod(OFF_ATTACK, GetAmount(),apply);
target->ApplyAttackTimePercentMod(RANGED_ATTACK,GetAmount(),apply);
}
void AuraEffect::HandleAuraModRangedHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetAmount(), apply);
}
void AuraEffect::HandleRangedAmmoHaste(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetAmount(), apply);
}
/********************************/
/*** COMBAT RATING ***/
/********************************/
void AuraEffect::HandleModRating(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (GetMiscValue() & (1 << rating))
target->ToPlayer()->ApplyRatingMod(CombatRating(rating), GetAmount(), apply);
}
void AuraEffect::HandleModRatingFromStat(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// Just recalculate ratings
for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating)
if (GetMiscValue() & (1 << rating))
target->ToPlayer()->ApplyRatingMod(CombatRating(rating), 0, apply);
}
/********************************/
/*** ATTACK POWER ***/
/********************************/
void AuraEffect::HandleAuraModAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModRangedAttackPower(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0)
return;
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModAttackPowerPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModRangedAttackPowerPercent(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
if ((target->getClassMask() & CLASSMASK_WAND_USERS) != 0)
return;
//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetAmount()), apply);
}
void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
// Recalculate bonus
if (target->GetTypeId() == TYPEID_PLAYER && !(target->getClassMask() & CLASSMASK_WAND_USERS))
target->ToPlayer()->UpdateAttackPowerAndDamage(true);
}
void AuraEffect::HandleAuraModAttackPowerOfStatPercent(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
// Recalculate bonus
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateAttackPowerAndDamage(false);
}
void AuraEffect::HandleAuraModAttackPowerOfArmor(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
// Recalculate bonus
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->UpdateAttackPowerAndDamage(false);
}
/********************************/
/*** DAMAGE BONUS ***/
/********************************/
void AuraEffect::HandleModDamageDone(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
// apply item specific bonuses for already equipped weapon
if (target->GetTypeId() == TYPEID_PLAYER)
{
for (int i = 0; i < MAX_ATTACK; ++i)
if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
}
// GetMiscValue() 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
// GetMiscValue() comparison with item generated damage types
if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0)
{
// apply generic physical damage bonuses including wand case
if (GetSpellProto()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)
{
target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetAmount()), apply);
if (target->GetTypeId() == TYPEID_PLAYER)
{
if (GetAmount() > 0)
target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,GetAmount(),apply);
else
target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,GetAmount(),apply);
}
}
else
{
// done in Player::_ApplyWeaponDependentAuraMods
}
}
// Skip non magic case for speedup
if ((GetMiscValue() & 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 (target->GetTypeId() == TYPEID_PLAYER)
{
if (GetAmount() > 0)
{
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
{
if ((GetMiscValue() & (1<<i)) != 0)
target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,GetAmount(),apply);
}
}
else
{
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++)
{
if ((GetMiscValue() & (1<<i)) != 0)
target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,GetAmount(),apply);
}
}
if (Guardian* pet = target->ToPlayer()->GetGuardianPet())
pet->UpdateAttackPowerAndDamage();
}
}
void AuraEffect::HandleModDamagePercentDone(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", GetMiscValue(), GetAmount() > 0);
// apply item specific bonuses for already equipped weapon
if (target->GetTypeId() == TYPEID_PLAYER)
{
for (int i = 0; i < MAX_ATTACK; ++i)
if (Item* pItem = target->ToPlayer()->GetWeaponForAttack(WeaponAttackType(i), true))
target->ToPlayer()->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply);
}
// GetMiscValue() 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
// GetMiscValue() comparison with item generated damage types
if ((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0)
{
// apply generic physical damage bonuses including wand case
if (GetSpellProto()->EquippedItemClass == -1 || target->GetTypeId() != TYPEID_PLAYER)
{
target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetAmount()), apply);
// For show in client
if (target->GetTypeId() == TYPEID_PLAYER)
target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,GetAmount()/100.0f,apply);
}
else
{
// done in Player::_ApplyWeaponDependentAuraMods
}
}
// Skip non magic case for speedup
if ((GetMiscValue() & 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 (target->GetTypeId() == TYPEID_PLAYER)
for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,GetAmount()/100.0f,apply);
}
void AuraEffect::HandleModOffhandDamagePercent(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetAmount()), apply);
}
void AuraEffect::HandleShieldBlockValue(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT)))
return;
Unit * target = aurApp->GetTarget();
BaseModType modType = FLAT_MOD;
if (GetAuraType() == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT)
modType = PCT_MOD;
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetAmount()), apply);
}
/********************************/
/*** POWER COST ***/
/********************************/
void AuraEffect::HandleModPowerCostPCT(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
float amount = GetAmount() /100.0f;
for (int i = 0; i < MAX_SPELL_SCHOOL; ++i)
if (GetMiscValue() & (1<<i))
target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply);
}
void AuraEffect::HandleModPowerCost(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
for (int i = 0; i < MAX_SPELL_SCHOOL; ++i)
if (GetMiscValue() & (1<<i))
target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,GetAmount(),apply);
}
void AuraEffect::HandleArenaPreparation(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (apply)
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
else
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
}
}
void AuraEffect::HandleNoReagentUseAura(AuraApplication const * aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
flag96 mask;
Unit::AuraEffectList const& noReagent = target->GetAuraEffectsByType(SPELL_AURA_NO_REAGENT_USE);
for (Unit::AuraEffectList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i)
mask |= (*i)->m_spellProto->EffectSpellClassMask[(*i)->m_effIndex];
target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]);
target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]);
target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]);
}
void AuraEffect::HandleAuraRetainComboPoints(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// 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) && GetBase()->GetDuration() == 0 && target->ToPlayer()->GetComboTarget())
if (Unit* unit = ObjectAccessor::GetUnit(*target,target->ToPlayer()->GetComboTarget()))
target->ToPlayer()->AddComboPoints(unit, -GetAmount());
}
/*********************************************************/
/*** OTHERS ***/
/*********************************************************/
void AuraEffect::HandleAuraDummy(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
Unit * caster = GetCaster();
if (mode & AURA_EFFECT_HANDLE_REAL)
{
// AT APPLY
if (apply)
{
// Overpower
if (caster && m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR &&
m_spellProto->SpellFamilyFlags[0] & 0x4)
{
// In addition, if you strike a player..
if (target->GetTypeId() != TYPEID_PLAYER)
return;
// ..while they are casting
if (target->IsNonMeleeSpellCasted(false, false, true))
{
if (AuraEffect * aurEff = caster->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_WARRIOR, 2775, 0))
{
switch (aurEff->GetId())
{
// Unrelenting Assault, rank 1
case 46859:
target->CastSpell(target,64849,true,NULL,aurEff);
break;
// Unrelenting Assault, rank 2
case 46860:
target->CastSpell(target,64850,true,NULL,aurEff);
break;
}
}
}
}
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 && target->CanHaveThreatList())
target->AddThreat(caster, 10.0f);
break;
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);
break;
case 34026: // kill command
{
Unit * pet = target->GetGuardianPet();
if (!pet)
break;
target->CastSpell(target,34027,true,NULL,this);
// set 3 stacks and 3 charges (to make all auras not disappear at once)
Aura * owner_aura = target->GetAura(34027,GetCasterGUID());
Aura * pet_aura = pet->GetAura(58914, GetCasterGUID());
if (owner_aura)
{
owner_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount);
}
if (pet_aura)
{
pet_aura->SetCharges(0);
pet_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount);
}
break;
}
case 37096: // Blood Elf Illusion
{
if (caster)
{
switch(caster->getGender())
{
case GENDER_FEMALE:
caster->CastSpell(target,37095,true,NULL,this); // Blood Elf Disguise
break;
case GENDER_MALE:
caster->CastSpell(target,37093,true,NULL,this);
break;
default:
break;
}
}
break;
}
case 55198: // Tidal Force
{
target->CastSpell(target,55166,true,NULL,this);
// set 3 stacks and 3 charges (to make all auras not disappear at once)
Aura * owner_aura = target->GetAura(55166,GetCasterGUID());
if (owner_aura)
{
// This aura lasts 2 sec, need this hack to properly proc spells
// TODO: drop aura charges for ApplySpellMod in ProcDamageAndSpell
GetBase()->SetDuration(owner_aura->GetDuration());
// Make aura be not charged-this prevents removing charge on not crit spells
owner_aura->SetCharges(0);
owner_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount);
}
break;
}
case 39850: // Rocket Blast
if (roll_chance_i(20)) // backfire stun
target->CastSpell(target, 51581, true, NULL, this);
break;
case 43873: // Headless Horseman Laugh
target->PlayDistanceSound(11965);
break;
case 46354: // Blood Elf Illusion
if (caster)
{
switch(caster->getGender())
{
case GENDER_FEMALE:
caster->CastSpell(target,46356,true,NULL,this);
break;
case GENDER_MALE:
caster->CastSpell(target,46355,true,NULL,this);
break;
}
}
break;
case 46361: // Reinforced Net
if (caster)
{
float currentGroundLevel = target->GetBaseMap()->GetHeight(target->GetPositionX(), target->GetPositionY(), MAX_HEIGHT);
if (target->GetPositionZ() > currentGroundLevel)
target->GetMotionMaster()->MoveFall(currentGroundLevel);
}
break;
case 46699: // Requires No Ammo
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveAmmo(); // not use ammo and not allow use
break;
case 49028:
if (caster)
if (AuraEffect *aurEff = caster->GetAuraEffect(63330, 0)) // glyph of Dancing Rune Weapon
GetBase()->SetDuration(GetBase()->GetDuration() + aurEff->GetAmount());
break;
case 62061: // Festive Holiday Mount
if (target->HasAuraType(SPELL_AURA_MOUNTED))
target->CastSpell(target, 25860, true, NULL, this); // Reindeer Transformation
break;
case 52916: // Honor Among Thieves
if (target->GetTypeId() == TYPEID_PLAYER)
if (Unit * spellTarget = ObjectAccessor::GetUnit(*target,target->ToPlayer()->GetComboTarget()))
target->CastSpell(spellTarget, 51699, true);
break;
case 28832: // Mark of Korth'azz
case 28833: // Mark of Blaumeux
case 28834: // Mark of Rivendare
case 28835: // Mark of Zeliek
if (caster) // actually we can also use cast(this, originalcasterguid)
{
int32 damage;
switch(GetBase()->GetStackAmount())
{
case 1: damage = 0; break;
case 2: damage = 500; break;
case 3: damage = 1000; break;
case 4: damage = 1500; break;
case 5: damage = 4000; break;
case 6: damage = 12000; break;
default:damage = 20000 + 1000 * (GetBase()->GetStackAmount() - 7); break;
}
if (damage)
caster->CastCustomSpell(28836, SPELLVALUE_BASE_POINT0, damage, target);
}
break;
}
}
// AT REMOVE
else
{
if ((IsQuestTameSpell(GetId())) && caster && caster->isAlive() && 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(target,finalSpelId,true,NULL,this);
}
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
switch(GetId())
{
case 2584: // Waiting to Resurrect
// Waiting to resurrect spell cancel, we must remove player from resurrect queue
if (target->GetTypeId() == TYPEID_PLAYER)
if (BattleGround *bg = target->ToPlayer()->GetBattleGround())
bg->RemovePlayerFromResurrectQueue(target->GetGUID());
break;
case 36730: // Flame Strike
{
target->CastSpell(target, 36731, true, NULL, this);
break;
}
case 44191: // Flame Strike
{
if (target->GetMap()->IsDungeon())
{
uint32 spellId = target->GetMap()->IsHeroic() ? 46163 : 44190;
target->CastSpell(target, spellId, true, NULL, this);
}
break;
}
case 42783: // Wrath of the Astromancer
target->CastSpell(target,GetAmount(),true,NULL,this);
break;
case 46308: // Burning Winds casted only at creatures at spawn
target->CastSpell(target,47287,true,NULL,this);
break;
case 52172: // Coyote Spirit Despawn Aura
case 60244: // Blood Parrot Despawn Aura
target->CastSpell((Unit*)NULL, GetAmount(), true, NULL, this);
break;
case 68839: // Corrupt Soul
target->CastSpell(target, 68846, true, NULL, this, GetCasterGUID());
break;
}
break;
case SPELLFAMILY_MAGE:
// Living Bomb
if (m_spellProto->SpellFamilyFlags[1] & 0x20000)
{
AuraRemoveMode mode = aurApp->GetRemoveMode();
if (caster && (mode == AURA_REMOVE_BY_ENEMY_SPELL || mode == AURA_REMOVE_BY_EXPIRE))
caster->CastSpell(target, GetAmount(), true);
}
break;
case SPELLFAMILY_WARLOCK:
// Haunt
if (m_spellProto->SpellFamilyFlags[1] & 0x40000)
{
if (caster)
caster->CastCustomSpell(caster, 48210, &m_amount, 0, 0, true, NULL, this);
}
break;
case SPELLFAMILY_DRUID:
// Lifebloom
if (GetSpellProto()->SpellFamilyFlags[1] & 0x10)
{
// Final heal only on dispelled or duration end
if (aurApp->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && aurApp->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL)
return;
// final heal
int32 stack = GetBase()->GetStackAmount();
target->CastCustomSpell(target, 33778, &m_amount, &stack, NULL, true, NULL, this, GetCasterGUID());
// restore mana
if (caster)
{
int32 returnmana = (GetSpellProto()->ManaCostPercentage * caster->GetCreateMana() / 100) * stack / 2;
caster->CastCustomSpell(caster, 64372, &returnmana, NULL, NULL, true, NULL, this, GetCasterGUID());
}
}
break;
case SPELLFAMILY_PRIEST:
// Vampiric Touch
if (m_spellProto->SpellFamilyFlags[1] & 0x0400 && aurApp->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL)
{
if (AuraEffect const * aurEff = GetBase()->GetEffect(1))
{
int32 damage = aurEff->GetAmount()*4;
// backfire damage
target->CastCustomSpell(target, 64085, &damage, NULL, NULL, true, NULL, NULL,GetCasterGUID());
}
}
break;
case SPELLFAMILY_HUNTER:
// Misdirection
if (GetId() == 34477)
target->SetReducedThreatPercent(0, 0);
break;
case SPELLFAMILY_DEATHKNIGHT:
// Summon Gargoyle (will start feeding gargoyle)
if (GetId() == 61777)
target->CastSpell(target,m_spellProto->EffectTriggerSpell[m_effIndex],true);
break;
default:
break;
}
}
}
// AT APPLY & REMOVE
switch(m_spellProto->SpellFamilyName)
{
case SPELLFAMILY_GENERIC:
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
break;
switch(GetId())
{
// Recently Bandaged
case 11196:
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, GetMiscValue(), apply);
break;
// Unstable Power
case 24658:
{
uint32 spellId = 24659;
if (apply && caster)
{
SpellEntry const * spell = sSpellStore.LookupEntry(spellId);
for (int i=0; i < spell->StackAmount; ++i)
caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID());
break;
}
target->RemoveAurasDueToSpell(spellId);
break;
}
// Restless Strength
case 24661:
{
uint32 spellId = 24662;
if (apply && caster)
{
SpellEntry const * spell = sSpellStore.LookupEntry(spellId);
for (int i=0; i < spell->StackAmount; ++i)
caster->CastSpell(target, spell->Id, true, NULL, NULL, GetCasterGUID());
break;
}
target->RemoveAurasDueToSpell(spellId);
break;
}
// Tag Murloc
case 30877:
{
// Tag/untag Blacksilt Scout
target->SetEntry(apply ? 17654 : 17326);
break;
}
//Summon Fire Elemental
case 40133:
{
if (!caster)
break;
Unit *owner = caster->GetOwner();
if (owner && owner->GetTypeId() == TYPEID_PLAYER)
{
if (apply)
owner->CastSpell(owner,8985,true);
else
owner->ToPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
}
break;
}
//Summon Earth Elemental
case 40132 :
{
if (!caster)
break;
Unit *owner = caster->GetOwner();
if (owner && owner->GetTypeId() == TYPEID_PLAYER)
{
if (apply)
owner->CastSpell(owner,19704,true);
else
owner->ToPlayer()->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true);
}
break;
}
case 57723: // Exhaustion
case 57724: // Sated
{
switch(GetId())
{
case 57723: target->ApplySpellImmune(GetId(), IMMUNITY_ID, 32182, apply); break; // Heroism
case 57724: target->ApplySpellImmune(GetId(), IMMUNITY_ID, 2825, apply); break; // Bloodlust
}
break;
}
case 57819: // Argent Champion
case 57820: // Ebon Champion
case 57821: // Champion of the Kirin Tor
case 57822: // Wyrmrest Champion
{
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
break;
uint32 FactionID = 0;
if (apply)
{
switch(m_spellProto->Id)
{
case 57819: FactionID = 1106; break; // Argent Crusade
case 57820: FactionID = 1098; break; // Knights of the Ebon Blade
case 57821: FactionID = 1090; break; // Kirin Tor
case 57822: FactionID = 1091; break; // The Wyrmrest Accord
}
}
caster->ToPlayer()->SetChampioningFaction(FactionID);
break;
}
// LK Intro VO (1)
case 58204:
if (target->GetTypeId() == TYPEID_PLAYER)
{
// Play part 1
if (apply)
target->PlayDirectSound(14970, target->ToPlayer());
// continue in 58205
else
target->CastSpell(target, 58205, true);
}
break;
// LK Intro VO (2)
case 58205:
if (target->GetTypeId() == TYPEID_PLAYER)
{
// Play part 2
if (apply)
target->PlayDirectSound(14971, target->ToPlayer());
// Play part 3
else
target->PlayDirectSound(14972, target->ToPlayer());
}
break;
}
break;
}
case SPELLFAMILY_MAGE:
{
//if (!(mode & AURA_EFFECT_HANDLE_REAL))
//break;
break;
}
case SPELLFAMILY_PRIEST:
{
//if (!(mode & AURA_EFFECT_HANDLE_REAL))
//break;
break;
}
case SPELLFAMILY_DRUID:
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
break;
switch(GetId())
{
case 52610: // Savage Roar
{
uint32 spellId = 62071;
if (apply)
{
if (target->m_form != FORM_CAT)
break;
target->CastSpell(target, spellId, true, NULL, NULL, GetCasterGUID());
break;
}
target->RemoveAurasDueToSpell(spellId);
break;
}
case 61336: // Survival Instincts
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
break;
if (apply)
{
if (!target->IsInFeralForm())
break;
int32 bp0 = int32(target->GetMaxHealth() * GetAmount() / 100);
target->CastCustomSpell(target, 50322, &bp0, NULL, NULL, true);
}
else
target-> RemoveAurasDueToSpell(50322);
break;
}
}
// Predatory Strikes
if (target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->SpellIconID == 1563)
{
target->ToPlayer()->UpdateAttackPowerAndDamage();
}
break;
}
case SPELLFAMILY_SHAMAN:
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
break;
// Sentry Totem
if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER)
{
if (apply)
{
uint64 guid = caster->m_SummonSlot[3];
if (guid)
{
Creature *totem = caster->GetMap()->GetCreature(guid);
if (totem && totem->isTotem())
caster->ToPlayer()->CastSpell(totem, 6277, true);
}
}
else
caster->ToPlayer()->StopCastingBindSight();
return;
}
break;
}
case SPELLFAMILY_PALADIN:
if (!(mode & AURA_EFFECT_HANDLE_REAL))
break;
switch (GetSpellProto()->SpellIconID)
{
// Blessing of Sanctuary
// Greater Blessing of Sanctuary
case 19:
case 1804:
{
if (!caster)
break;
if (apply)
caster->CastSpell(target, 67480, true);
else
target->RemoveAura(67480, GetCasterGUID());
break;
}
}
break;
}
if (mode & AURA_EFFECT_HANDLE_REAL)
{
// pet auras
if (PetAura const* petSpell = spellmgr.GetPetAura(GetId(), m_effIndex))
{
if (apply)
target->AddPetAura(petSpell);
else
target->RemovePetAura(petSpell);
}
}
}
void AuraEffect::HandleChannelDeathItem(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
if (!(apply))
{
Unit * caster = GetCaster();
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
Player *plCaster = caster->ToPlayer();
Unit *target = aurApp->GetTarget();
if (target->getDeathState() != JUST_DIED)
return;
// Item amount
if (GetAmount() <= 0)
return;
if (GetSpellProto()->EffectItemType[m_effIndex] == 0)
return;
// Soul Shard
if (GetSpellProto()->EffectItemType[m_effIndex] == 6265)
{
// Soul Shard only from units that grant XP or honor
if (!plCaster->isHonorOrXPTarget(target) ||
(target->GetTypeId() == TYPEID_UNIT && !target->ToCreature()->isTappedBy(plCaster)))
return;
// If this is Drain Soul, check for Glyph of Drain Soul
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x00004000))
{
// Glyph of Drain Soul - chance to create an additional Soul Shard
if (AuraEffect *aur = caster->GetAuraEffect(58070, 0))
if (roll_chance_i(aur->GetMiscValue()))
caster->CastSpell(caster, 58068, true, 0, aur); // We _could_ simply do ++count here, but Blizz does it this way :)
}
}
//Adding items
uint32 noSpaceForCount = 0;
uint32 count = m_amount;
ItemPosCountVec dest;
uint8 msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellProto()->EffectItemType[m_effIndex], count, &noSpaceForCount);
if (msg != EQUIP_ERR_OK)
{
count-=noSpaceForCount;
plCaster->SendEquipError(msg, NULL, NULL, GetSpellProto()->EffectItemType[m_effIndex]);
if (count == 0)
return;
}
Item* newitem = plCaster->StoreNewItem(dest, GetSpellProto()->EffectItemType[m_effIndex], true);
if (!newitem)
{
plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
return;
}
plCaster->SendNewItem(newitem, count, true, true);
}
}
void AuraEffect::HandleBindSight(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
Unit * caster = GetCaster();
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
caster->ToPlayer()->SetViewpoint(target, (apply));
}
void AuraEffect::HandleForceReaction(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
Player* player = (Player*)target;
uint32 faction_id = GetMiscValue();
ReputationRank faction_rank = ReputationRank(m_amount);
player->GetReputationMgr().ApplyForceReaction(faction_id,faction_rank,apply);
player->GetReputationMgr().SendForceReactions();
// stop fighting if at apply forced rank friendly or at remove real rank friendly
if (apply && faction_rank >= REP_FRIENDLY || !apply && player->GetReputationRank(faction_id) >= REP_FRIENDLY)
player->StopAttackFaction(faction_id);
}
void AuraEffect::HandleAuraEmpathy(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_UNIT)
return;
if (!(apply))
{
// do not remove unit flag if there are more than this auraEffect of that kind on unit on unit
if (target->HasAuraType(GetAuraType()))
return;
}
CreatureInfo const * ci = objmgr.GetCreatureTemplate(target->GetEntry());
if (ci && ci->type == CREATURE_TYPE_BEAST)
target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply);
}
void AuraEffect::HandleAuraModFaction(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
target->setFaction(GetMiscValue());
if (target->GetTypeId() == TYPEID_PLAYER)
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
}
else
{
target->RestoreFaction();
if (target->GetTypeId() == TYPEID_PLAYER)
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
}
}
void AuraEffect::HandleComprehendLanguage(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK))
return;
Unit * target = aurApp->GetTarget();
if (apply)
target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
else
{
if (target->HasAuraType(GetAuraType()))
return;
target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG);
}
}
void AuraEffect::HandleAuraConvertRune(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER)
return;
Player *plr = (Player*)target;
if (plr->getClass() != CLASS_DEATH_KNIGHT)
return;
uint32 runes = m_amount;
// convert number of runes specified in aura amount of rune type in miscvalue to runetype in miscvalueb
if (apply)
{
for (uint32 i = 0; i < MAX_RUNES && runes; ++i)
{
if (GetMiscValue() != plr->GetCurrentRune(i))
continue;
if (!plr->GetRuneCooldown(i))
{
// ConvertRune(i,
plr->AddRuneByAuraEffect(i, RuneType(GetMiscValueB()), this);
--runes;
}
}
}
else
plr->RemoveRunesByAuraEffect(this);
}
void AuraEffect::HandleAuraLinked(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (apply)
{
Unit * caster = GetCaster();
if (!caster)
return;
// If amount avalible cast with basepoints (Crypt Fever for example)
if (GetAmount())
caster->CastCustomSpell(target, m_spellProto->EffectTriggerSpell[m_effIndex], &m_amount, NULL, NULL, true, NULL, this);
else
caster->CastSpell(target, m_spellProto->EffectTriggerSpell[m_effIndex],true, NULL, this);
}
else
target->RemoveAura(m_spellProto->EffectTriggerSpell[m_effIndex], GetCasterGUID(), 0, AuraRemoveMode(aurApp->GetRemoveMode()));
}
void AuraEffect::HandleAuraOpenStable(AuraApplication const * aurApp, uint8 mode, bool apply) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
Unit * target = aurApp->GetTarget();
if (target->GetTypeId() != TYPEID_PLAYER || !target->IsInWorld())
return;
if (apply)
target->ToPlayer()->GetSession()->SendStablePet(target->GetGUID());
// client auto close stable dialog at !apply aura
}