diff options
Diffstat (limited to 'src/game/SpellAuras.cpp')
-rw-r--r-- | src/game/SpellAuras.cpp | 5687 |
1 files changed, 3389 insertions, 2298 deletions
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 937833eab7d..bf765f65c74 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 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 @@ -31,11 +31,9 @@ #include "Player.h" #include "Unit.h" #include "Spell.h" -#include "SpellAuras.h" #include "DynamicObject.h" #include "Group.h" #include "UpdateData.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "Policies/SingletonImp.h" #include "Totem.h" @@ -45,13 +43,14 @@ #include "OutdoorPvP.h" #include "OutdoorPvPMgr.h" #include "CreatureAI.h" +#include "ScriptCalls.h" #include "Util.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" +#include "Vehicle.h" #include "CellImpl.h" -#define NULL_AURA_SLOT 0xFF - +#define Aura AuraEffect pAuraHandler AuraHandler[TOTAL_AURAS]= { &Aura::HandleNULL, // 0 SPELL_AURA_NONE @@ -75,14 +74,14 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH - &Aura::HandleAuraModTotalManaPercentRegen, // 21 SPELL_AURA_OBS_MOD_MANA + &Aura::HandleAuraModTotalEnergyPercentRegen, // 21 SPELL_AURA_OBS_MOD_ENERGY &Aura::HandleAuraModResistance, // 22 SPELL_AURA_MOD_RESISTANCE &Aura::HandlePeriodicTriggerSpell, // 23 SPELL_AURA_PERIODIC_TRIGGER_SPELL &Aura::HandlePeriodicEnergize, // 24 SPELL_AURA_PERIODIC_ENERGIZE &Aura::HandleAuraModPacify, // 25 SPELL_AURA_MOD_PACIFY &Aura::HandleAuraModRoot, // 26 SPELL_AURA_MOD_ROOT &Aura::HandleAuraModSilence, // 27 SPELL_AURA_MOD_SILENCE - &Aura::HandleNoImmediateEffect, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult + &Aura::HandleReflectSpells, // 28 SPELL_AURA_REFLECT_SPELLS implement in Unit::SpellHitResult &Aura::HandleAuraModStat, // 29 SPELL_AURA_MOD_STAT &Aura::HandleAuraModSkill, // 30 SPELL_AURA_MOD_SKILL &Aura::HandleAuraModIncreaseSpeed, // 31 SPELL_AURA_MOD_INCREASE_SPEED @@ -100,11 +99,11 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES - &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete? + &Aura::HandleUnused, // 46 SPELL_AURA_46 (used in test spells 54054 and 54058, and spell 48050) (3.0.8a) &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT - &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete? + &Aura::HandleNULL, // 48 SPELL_AURA_48 spell Napalm (area damage spell with additional delayed damage effect) &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT - &Aura::HandleUnused, // 50 SPELL_AURA_MOD_BLOCK_SKILL obsolete? + &Aura::HandleNoImmediateEffect, // 50 SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT implemented in Unit::SpellCriticalHealingBonus &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT &Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT &Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH @@ -116,10 +115,10 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE - &Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL - &Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete? + &Aura::HandlePeriodicHealthFunnel, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL + &Aura::HandleUnused, // 63 unused (3.0.8a) old SPELL_AURA_PERIODIC_MANA_FUNNEL &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH - &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED + &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED @@ -144,17 +143,17 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT &Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT - &Aura::HandleUnused, // 90 SPELL_AURA_MOD_RESIST_CHANCE Useless + &Aura::HandleUnused, // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE &Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance &Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE &Aura::HandleNoImmediateEffect, // 94 SPELL_AURA_INTERRUPT_REGEN implemented in Player::RegenerateAll &Aura::HandleAuraGhost, // 95 SPELL_AURA_GHOST - &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Spell::SelectMagnetTarget + &Aura::HandleNoImmediateEffect, // 96 SPELL_AURA_SPELL_MAGNET implemented in Unit::SelectMagnetTarget &Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER - &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now + &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now, but still have spells including GM-spell &Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT &Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus &Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT @@ -165,7 +164,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT - &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER + &Aura::HandleNoImmediateEffect, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER implemented in Unit::SelectMagnetTarget &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus @@ -173,7 +172,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult &Aura::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus - &Aura::HandleUnused, //119 SPELL_AURA_SHARE_PET_TRACKING useless + &Aura::HandleUnused, //119 unused (3.0.8a) old SPELL_AURA_SHARE_PET_TRACKING &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT @@ -198,12 +197,12 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE - &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes - &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete? - &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete? - &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY + &Aura::HandleAuraSafeFall, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes + &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS + &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE + &Aura::HandleModStateImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS - &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK + &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance @@ -218,41 +217,41 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE - &Aura::HandleUnused, //164 useless, only one test spell + &Aura::HandleUnused, //164 unused (3.0.8a), only one test spell &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT &Aura::HandleNoImmediateEffect, //168 SPELL_AURA_MOD_DAMAGE_DONE_VERSUS implemented in Unit::SpellDamageBonus, Unit::MeleeDamageBonus &Aura::HandleNoImmediateEffect, //169 SPELL_AURA_MOD_CRIT_PERCENT_VERSUS implemented in Unit::DealDamageBySchool, Unit::DoAttackDamage, Unit::SpellCriticalBonus - &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE only for Detect Amore spell + &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE different spells that ignore transformation effects &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK - &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell - &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by default intellect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT) + &Aura::HandleUnused, //173 unused (3.0.8a) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell + &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end - &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM + &Aura::HandleCharmConvert, //177 SPELL_AURA_AOE_CHARM &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus - &Aura::HandleUnused, //181 SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS unused + &Aura::HandleUnused, //181 unused (3.0.8a) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT - &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT + &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING - &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN + &Aura::HandleNoImmediateEffect, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN implemented in Player::CalculateReputationGain &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) - &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT) - &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT) + &Aura::HandleNULL, //194 SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist + &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance - &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS + &Aura::HandleUnused, //198 unused (3.0.8a) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode... @@ -260,210 +259,319 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage &Aura::HandleNULL, //205 vulnerable to school dmg? - &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED - &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED - &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive) - &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS - &Aura::HandleNULL, //210 Commentator's Command + &Aura::HandleAuraModIncreaseFlightSpeed, //206 SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED + &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED + &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED + &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_MOUNTED_FLIGHT_SPEED_ALWAYS + &Aura::HandleAuraModIncreaseFlightSpeed, //210 SPELL_AURA_MOD_VEHICLE_SPEED_ALWAYS &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage &Aura::HandleNULL, //214 Tamed Pet Passive &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS - &Aura::HandleUnused, //217 unused + &Aura::HandleUnused, //217 unused (3.0.8a) &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT - &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT + &Aura::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT &Aura::HandleNULL, //221 ignored - &Aura::HandleUnused, //222 unused - &Aura::HandleNULL, //223 Cold Stare - &Aura::HandleUnused, //224 unused - &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING + &Aura::HandleUnused, //222 unused (3.0.8a) only for spell 44586 that not used in real spell cast + &Aura::HandleNoImmediateEffect, //223 SPELL_AURA_RAID_PROC_FROM_CHARGE + &Aura::HandleUnused, //224 unused (3.0.8a) + &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY - &Aura::HandleNULL, //227 periodic trigger spell + &Aura::HandlePeriodicTriggerSpellWithValue, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE &Aura::HandleNoImmediateEffect, //228 stealth detection &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE - &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout - &Aura::HandleNULL, //231 + &Aura::HandleAuraModIncreaseHealth, //230 SPELL_AURA_MOD_INCREASE_HEALTH_2 + &Aura::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration - &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue + &Aura::HandleNULL, //233 set model id to the one of the creature with id GetMiscValue() &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration - &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult - &Aura::HandleUnused, //236 unused + &Aura::HandleNoImmediateEffect, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult + &Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61 &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE &Aura::HandleForceMoveForward, //241 Forces the player to move forward &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING - &Aura::HandleUnused, //243 used by two test spells + &Aura::HandleNULL, //243 faction reaction override spells &Aura::HandleComprehendLanguage, //244 Comprehend language - &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS - &Aura::HandleUnused, //246 unused - &Aura::HandleUnused, //247 unused + &Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL + &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura + &Aura::HandleNULL, //247 target to become a clone of the caster &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleNULL, //249 + &Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2 - &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE - &Aura::HandleUnused, //252 unused - &Aura::HandleUnused, //253 unused - &Aura::HandleUnused, //254 unused - &Aura::HandleUnused, //255 unused - &Aura::HandleUnused, //256 unused - &Aura::HandleUnused, //257 unused - &Aura::HandleUnused, //258 unused - &Aura::HandleUnused, //259 unused - &Aura::HandleUnused, //260 unused - &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell) + &Aura::HandleNoImmediateEffect, //251 SPELL_AURA_MOD_ENEMY_DODGE + &Aura::HandleNULL, //252 haste all? + &Aura::HandleNoImmediateEffect, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE implemented in Unit::isBlockCritical + &Aura::HandleAuraModDisarm, //254 SPELL_AURA_MOD_DISARM_OFFHAND + &Aura::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus + &Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select + &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select + &Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL + &Aura::HandleNoImmediateEffect, //259 SPELL_AURA_MOD_HOT_PCT implemented in Unit::SpellHealingBonus + &Aura::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code + &Aura::HandlePhase, //261 SPELL_AURA_PHASE undetactable invisibility? implemented in Unit::isVisibleForOrDetect + &Aura::HandleNoImmediateEffect, //262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in spell::cancast + &Aura::HandleAuraAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask + &Aura::HandleUnused, //264 unused (3.0.8a) + &Aura::HandleUnused, //265 unused (3.0.8a) + &Aura::HandleUnused, //266 unused (3.0.8a) + &Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect + &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT + &Aura::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage + &Aura::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage + &Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus + &Aura::HandleNULL, //272 reduce spell cast time? + &Aura::HandleUnused, //273 clientside + &Aura::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets + &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select + &Aura::HandleNULL, //276 mod damage % mechanic? + &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap + &Aura::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon + &Aura::HandleNULL, //279 visual effects? 58836 and 57507 + &Aura::HandleModArmorPenetrationPct, //280 SPELL_AURA_MOD_ARMOR_PENETRATION_PCT + &Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor + &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT + &Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus + &Aura::HandleUnused, //284 not used by any spells (3.08a) + &Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage + &Aura::HandleUnused, //286 not used by any spells (3.08a) + &Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult + &Aura::HandleUnused, //288 not used by any spells (3.09) except 1 test spell. + &Aura::HandleUnused, //289 unused + &Aura::HandleUnused, //290 unused + &Aura::HandleUnused, //291 unused + &Aura::HandleNULL, //292 call stabled pet + &Aura::HandleNULL, //293 2 test spells + &Aura::HandleNULL //294 2 spells, possible prevent mana regen }; +#undef Aura -Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) : -m_procCharges(0), m_stackAmount(1), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target), -m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS), -m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), -m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false), -m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) -,m_tickNumber(0) +Aura::Aura(SpellEntry const* spellproto, uint32 effMask, int32 *currentBasePoints, Unit *target, WorldObject *source, Unit *caster, Item* castItem) : +m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target), +m_timeCla(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE), +m_auraSlot(MAX_AURAS), m_auraLevel(1), m_procCharges(0), m_stackAmount(1),m_auraStateMask(0), m_updated(false), m_isRemoved(false) { assert(target); assert(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element"); + m_auraFlags = effMask; + m_spellProto = spellproto; - int32 damage; - if(currentBasePoints) - { - damage = *currentBasePoints; - m_currentBasePoints = damage - 1; - } - else - { - m_currentBasePoints = m_spellProto->EffectBasePoints[eff]; - if(caster) - damage = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, target); - else - damage = m_currentBasePoints + 1; - } + if(m_spellProto->manaPerSecond || m_spellProto->manaPerSecondPerLevel) + m_timeCla = 1000; m_isPassive = IsPassiveSpell(GetId()); - m_positive = IsPositiveEffect(GetId(), m_effIndex); - m_applyTime = time(NULL); + m_auraStateMask = 0; m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto); + m_applyTime = time(NULL); + if(!caster) { m_caster_guid = target->GetGUID(); //damage = m_currentBasePoints+1; // stored value-1 - m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target); + m_maxduration = target->CalcSpellDuration(m_spellProto); } else { m_caster_guid = caster->GetGUID(); //damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target); - m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target); - - if (!damage && castItem && castItem->GetItemSuffixFactor()) - { - ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId())); - if(item_rand_suffix) - { - for (int k=0; k<3; k++) - { - SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]); - if(pEnchant) - { - for (int t=0; t<3; t++) - if(pEnchant->spellid[t] == m_spellProto->Id) - { - damage = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 ); - break; - } - } - - if(damage) - break; - } - } - } + m_maxduration = caster->CalcSpellDuration(m_spellProto); } if(m_maxduration == -1 || m_isPassive && m_spellProto->DurationIndex == 0) m_permanent = true; + else + m_permanent = false; Player* modOwner = caster ? caster->GetSpellModOwner() : NULL; if(!m_permanent && modOwner) + { + // Glyph of Thorns + if (m_target == caster && m_spellProto->SpellFamilyName==SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x100) + if (AuraEffect * aurEff = m_target->GetDummyAura(57862)) + m_maxduration += aurEff->GetAmount() * MINUTE * IN_MILISECONDS; + modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, m_maxduration); + // Get zero duration aura after - need set m_maxduration > 0 for apply/remove aura work + if (m_maxduration<=0) + m_maxduration = 1; + } m_duration = m_maxduration; - if(modOwner) - modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer); - - sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage); + m_isDeathPersist = IsDeathPersistentSpell(m_spellProto); - m_effIndex = eff; - SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]); + m_procCharges = m_spellProto->procCharges; + if(modOwner) + modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); - m_isDeathPersist = IsDeathPersistentSpell(m_spellProto); + m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && + m_spellProto->Stances && + !(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && + !(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT)); - if(m_spellProto->procCharges) + for (uint8 i=0 ;i<MAX_SPELL_EFFECTS;++i) { - m_procCharges = m_spellProto->procCharges; - - if(modOwner) - modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); + if (m_auraFlags & (uint8(1) << i)) + { + if (currentBasePoints) + m_partAuras[i] = CreateAuraEffect(this, i, currentBasePoints + i, caster, NULL, source); + else + m_partAuras[i] = CreateAuraEffect(this, i, NULL, caster, NULL, source); + // correct flags if aura couldn't be created + if (!m_partAuras[i]) + m_auraFlags &= uint8(~(1<< i)); + } + else + { + m_partAuras[i]=NULL; + } } - else - m_procCharges = -1; - m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances && - !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000)); + // Aura is positive when it is casted by friend and at least one aura is positive + // or when it is casted by enemy and at least one aura is negative + bool swap=false; + if (!caster || caster==target) // caster == target - 1 negative effect is enough for aura to be negative + m_positive = false; + else + m_positive = !caster->IsHostileTo(m_target); + for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i) + { + if (!(1<<i & GetEffectMask())) + continue; + if (m_positive == IsPositiveEffect(GetId(), i)) + { + swap = true; + break; + } + } + if (!swap) + m_positive=!m_positive; } Aura::~Aura() { + // free part auras memory + for (uint8 i=0 ; i<MAX_SPELL_EFFECTS;++i) + if (m_partAuras[i]) + delete m_partAuras[i]; } -AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, -Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem) +AuraEffect::AuraEffect(Aura * parentAura, uint8 effIndex, int32 * currentBasePoints , Unit *caster, Item* castItem, WorldObject *source) : +m_parentAura(parentAura), m_spellmod(NULL), m_periodicTimer(0), m_isPeriodic(false), m_isAreaAura(false), m_isPersistent(false), +m_target(parentAura->GetTarget()), m_tickNumber(0) +, m_spellProto(parentAura->GetSpellProto()), m_effIndex(effIndex), m_auraName(AuraType(m_spellProto->EffectApplyAuraName[m_effIndex])) { + assert(m_auraName < TOTAL_AURAS); + + if(currentBasePoints) + m_currentBasePoints = *currentBasePoints; + else + m_currentBasePoints = m_spellProto->EffectBasePoints[m_effIndex]; + + if(caster) + m_amount = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); + else + m_amount = m_currentBasePoints + 1; + + if (!m_amount && castItem && castItem->GetItemSuffixFactor()) + { + ItemRandomSuffixEntry const *item_rand_suffix = sItemRandomSuffixStore.LookupEntry(abs(castItem->GetItemRandomPropertyId())); + if(item_rand_suffix) + { + for (int k=0; k<3; k++) + { + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(item_rand_suffix->enchant_id[k]); + if(pEnchant) + { + for (int t=0; t<3; t++) + if(pEnchant->spellid[t] == m_spellProto->Id) + { + m_amount = uint32((item_rand_suffix->prefix[k]*castItem->GetItemSuffixFactor()) / 10000 ); + break; + } + } + + if(m_amount) + break; + } + } + } + + Player* modOwner = caster ? caster->GetSpellModOwner() : NULL; + m_sourceGUID = source ? source->GetGUID() : (caster ? caster->GetGUID() : 0); + m_amplitude = m_spellProto->EffectAmplitude[m_effIndex]; + + //apply casting time mods for channeled spells + if (modOwner && m_amplitude && IsChanneledSpell(m_spellProto)) + modOwner->ModSpellCastTime(m_spellProto, m_amplitude); + + // Apply periodic time mod + if(modOwner && m_amplitude) + modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_amplitude); + + // Start periodic on next tick or at aura apply + if (!(m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY)) + m_periodicTimer += m_amplitude; + + m_isApplied = false; +} + +AreaAuraEffect::AreaAuraEffect(Aura * parentAura, uint32 effIndex, int32 * currentBasePoints, Unit * caster, Item * castItem, Unit * source) +: AuraEffect(parentAura, effIndex, currentBasePoints, caster, castItem, source) +{ + m_removeTime = FRIENDLY_AA_REMOVE_TIME; m_isAreaAura = true; - // caster==NULL in constructor args if target==caster in fact - Unit* caster_ptr = caster ? caster : target; + Unit* caster_ptr = caster ? caster : source ? source : m_target; + + if (m_spellProto->Effect[effIndex] == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY) + m_radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); + else + m_radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); - m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex])); if(Player* modOwner = caster_ptr->GetSpellModOwner()) modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius); - switch(spellproto->Effect[eff]) + switch(m_spellProto->Effect[effIndex]) { case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: m_areaAuraType = AREA_AURA_PARTY; - if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) - m_modifier.m_auraname = SPELL_AURA_NONE; + if(m_target->GetTypeId() == TYPEID_UNIT && ((Creature*)m_target)->isTotem()) + *const_cast<AuraType*>(&m_auraName) = SPELL_AURA_NONE; + break; + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + m_areaAuraType = AREA_AURA_RAID; + if(m_target->GetTypeId() == TYPEID_UNIT && ((Creature*)m_target)->isTotem()) + *const_cast<AuraType*>(&m_auraName) = SPELL_AURA_NONE; break; case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: m_areaAuraType = AREA_AURA_FRIEND; break; case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: m_areaAuraType = AREA_AURA_ENEMY; - if(target == caster_ptr) - m_modifier.m_auraname = SPELL_AURA_NONE; // Do not do any effect on self + if(m_target == caster_ptr) + *const_cast<AuraType*>(&m_auraName) = SPELL_AURA_NONE; // Do not do any effect on self break; case SPELL_EFFECT_APPLY_AREA_AURA_PET: m_areaAuraType = AREA_AURA_PET; break; case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: m_areaAuraType = AREA_AURA_OWNER; - if(target == caster_ptr) - m_modifier.m_auraname = SPELL_AURA_NONE; + if(m_target == caster_ptr) + *const_cast<AuraType*>(&m_auraName) = SPELL_AURA_NONE; break; default: sLog.outError("Wrong spell effect in AreaAura constructor"); @@ -472,26 +580,37 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, } } -AreaAura::~AreaAura() +AreaAuraEffect::~AreaAuraEffect() { } -PersistentAreaAura::PersistentAreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, -Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem) +PersistentAreaAuraEffect::PersistentAreaAuraEffect(Aura * parentAura, uint32 effIndex, int32 * currentBasePoints, Unit * caster,Item * castItem, DynamicObject *source) +: AuraEffect(parentAura, effIndex, currentBasePoints, caster, castItem, source) { m_isPersistent = true; } -PersistentAreaAura::~PersistentAreaAura() +PersistentAreaAuraEffect::~PersistentAreaAuraEffect() { } -Aura* CreateAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) +AuraEffect* CreateAuraEffect(Aura * parentAura, uint32 effIndex, int32 *currentBasePoints, Unit * caster, Item * castItem, WorldObject* source) { - if (IsAreaAuraEffect(spellproto->Effect[eff])) - return new AreaAura(spellproto, eff, currentBasePoints, target, caster, castItem); - - return new Aura(spellproto, eff, currentBasePoints, target, caster, castItem); + // TODO: source should belong to aura, but not areaeffect. multiple areaaura/persistent aura should use one source + assert(parentAura); + if (IsAreaAuraEffect(parentAura->GetSpellProto()->Effect[effIndex])) + { + if(!source) + source = caster; + //TODO: determine source here + if(source && source->isType(TYPEMASK_UNIT)) + return new AreaAuraEffect(parentAura, effIndex, currentBasePoints, caster, castItem, (Unit*)source); + } + else if (parentAura->GetSpellProto()->Effect[effIndex] == SPELL_EFFECT_APPLY_AURA) + return new AuraEffect(parentAura, effIndex, currentBasePoints, caster, castItem, source); + else if (parentAura->GetSpellProto()->Effect[effIndex] == SPELL_EFFECT_PERSISTENT_AREA_AURA) + return new PersistentAreaAuraEffect(parentAura, effIndex, currentBasePoints, caster, castItem); + return NULL; } Unit* Aura::GetCaster() const @@ -505,139 +624,142 @@ Unit* Aura::GetCaster() const return unit && unit->IsInWorld() ? unit : NULL; } -void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue) +Unit* AuraEffect::GetSource() const { - m_modifier.m_auraname = t; - m_modifier.m_amount = a; - m_modifier.m_miscvalue = miscValue; - m_modifier.periodictime = pt; + if(m_sourceGUID == m_target->GetGUID()) + return m_target; + + //return ObjectAccessor::GetUnit(*m_target,m_caster_guid); + //must return caster even if it's in another grid/map + Unit *unit = ObjectAccessor::GetObjectInWorld(m_sourceGUID, (Unit*)NULL); + //only player can be not in world while in objectaccessor + return unit && unit->IsInWorld() ? unit : NULL; } void Aura::Update(uint32 diff) { + // TODO: store pointer to caster in aura class for update/mod handling code + if (m_duration > 0) { m_duration -= diff; if (m_duration < 0) m_duration = 0; - m_timeCla -= diff; - // GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras // all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0 - if(GetEffIndex()==0 && m_timeCla <= 0) + if(m_timeCla) { - if(Unit* caster = GetCaster()) + if(m_timeCla > diff) + m_timeCla -= diff; + else if(Unit* caster = GetCaster()) { - Powers powertype = Powers(m_spellProto->powerType); - int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel(); - m_timeCla = 1000; - if (manaPerSecond) + if(int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel()) { - if(powertype==POWER_HEALTH) - caster->ModifyHealth(-manaPerSecond); + m_timeCla += 1000 - diff; + + Powers powertype = Powers(m_spellProto->powerType); + if(powertype == POWER_HEALTH) + { + if (caster->GetHealth() > manaPerSecond) + caster->ModifyHealth(-manaPerSecond); + else + { + m_target->RemoveAura(this); + return; + } + } else - caster->ModifyPower(powertype,-manaPerSecond); + { + if (caster->GetPower(powertype) >= manaPerSecond) + caster->ModifyPower(powertype, -manaPerSecond); + else + { + m_target->RemoveAura(this); + return; + } + } } } } } - // Channeled aura required check distance from caster except in possessed cases - Unit *pRealTarget = (GetSpellProto()->EffectApplyAuraName[m_effIndex] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && - sSpellStore.LookupEntry(GetSpellProto()->EffectTriggerSpell[m_effIndex]) && - !IsAreaOfEffectSpell(sSpellStore.LookupEntry(GetSpellProto()->EffectTriggerSpell[m_effIndex])) && - GetTriggerTarget()) ? GetTriggerTarget() : m_target; - - - if(IsChanneledSpell(m_spellProto) && !pRealTarget->isPossessed() && pRealTarget->GetGUID() != GetCasterGUID()) + // Apply charged spellmods for channeled auras + // used for example when triggered spell of spell:10 is modded + Spell * modSpell = NULL; + Unit* caster = NULL; + if (IS_PLAYER_GUID(GetCasterGUID())) { - Unit* caster = GetCaster(); - if(!caster) - { - m_target->RemoveAura(GetId(),GetEffIndex()); - return; - } - - // Get spell range - float radius; - SpellModOp mod; - if (m_spellProto->EffectRadiusIndex[GetEffIndex()]) - { - radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()])); - mod = SPELLMOD_RADIUS; - } - else + caster = GetCaster(); + if (caster) { - radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex)); - mod = SPELLMOD_RANGE; + modSpell = ((Player*)caster)->FindCurrentSpellBySpellId(GetId()); + ((Player*)caster)->SetSpellModTakingSpell(modSpell, true); } - - if(Player* modOwner = caster->GetSpellModOwner()) - modOwner->ApplySpellMod(GetId(), mod, radius,NULL); - - if(!caster->IsWithinDistInMap(pRealTarget, radius)) - return; } + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if (m_partAuras[i]) + m_partAuras[i]->Update(diff); - if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent)) + if (caster) + ((Player*)caster)->SetSpellModTakingSpell(modSpell, false); +} + +void AuraEffect::Update(uint32 diff) +{ + if (m_isPeriodic && (GetParentAura()->GetAuraDuration() >=0 || GetParentAura()->IsPassive() || GetParentAura()->IsPermanent())) { - m_periodicTimer -= diff; - if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N + if(m_periodicTimer > 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; - if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN || - m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN || - // Cannibalize, eating items and other spells - m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH || - // Eating items and other spells - m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA ) - { - ApplyModifier(true); - return; - } // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls) - m_periodicTimer += m_modifier.periodictime; + m_periodicTimer += m_amplitude - diff; if(!m_target->hasUnitState(UNIT_STAT_ISOLATED)) - { - if(m_isTrigger) - TriggerSpell(); - else - PeriodicTick(); - } + PeriodicTick(); } } } -void AreaAura::Update(uint32 diff) +void AreaAuraEffect::Update(uint32 diff) { // update for the caster of the aura - if(m_caster_guid == m_target->GetGUID()) + if(m_sourceGUID == m_target->GetGUID()) { - Unit* caster = m_target; + Unit *source = m_target; + Unit *caster = GetCaster(); + if (!caster) + { + m_target->RemoveAura(GetParentAura()); + return; + } - if( !caster->hasUnitState(UNIT_STAT_ISOLATED) ) + if( !source->hasUnitState(UNIT_STAT_ISOLATED) ) { std::list<Unit *> targets; switch(m_areaAuraType) { case AREA_AURA_PARTY: - caster->GetPartyMember(targets, m_radius); + source->GetPartyMemberInDist(targets, m_radius); + break; + case AREA_AURA_RAID: + source->GetRaidMember(targets, m_radius); break; case AREA_AURA_FRIEND: { - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(caster, caster, m_radius); - Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check); - caster->VisitNearbyObject(m_radius, searcher); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(source, caster, m_radius); + Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(source, targets, u_check); + source->VisitNearbyObject(m_radius, searcher); break; } case AREA_AURA_ENEMY: { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(caster, caster, m_radius); // No GetCharmer in searcher - Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check); - caster->VisitNearbyObject(m_radius, searcher); + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(source, caster, m_radius); // No GetCharmer in searcher + Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(source, targets, u_check); + source->VisitNearbyObject(m_radius, searcher); break; } case AREA_AURA_OWNER: @@ -649,10 +771,28 @@ void AreaAura::Update(uint32 diff) } } - for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++) + for(std::list<Unit*>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++) { - if((*tIter)->HasAura(GetId(), m_effIndex)) - continue; + if(Aura *aur = (*tIter)->GetAura(GetId(), GetCasterGUID())) + { + if(aur->HasEffect(GetEffIndex())) + continue; + } + else + { + bool skip = false; + for(Unit::AuraMap::iterator iter = (*tIter)->GetAuras().begin(); iter != (*tIter)->GetAuras().end();++iter) + { + bool samecaster = iter->second->GetCasterGUID() == GetCasterGUID(); + if(spellmgr.IsNoStackSpellDueToSpell(GetId(), iter->first, samecaster)) + { + skip = true; + break; + } + } + if(skip) + continue; + } if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel())) { @@ -660,152 +800,217 @@ void AreaAura::Update(uint32 diff) // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?) //if(actualSpellInfo != GetSpellProto()) // actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex]; - AreaAura *aur; - if(actualSpellInfo == GetSpellProto()) - aur = new AreaAura(actualSpellInfo, m_effIndex, &m_modifier.m_amount, (*tIter), caster, NULL); - else - aur = new AreaAura(actualSpellInfo, m_effIndex, NULL, (*tIter), caster, NULL); - (*tIter)->AddAura(aur); + (*tIter)->AddAuraEffect(actualSpellInfo, GetEffIndex(), caster, &m_currentBasePoints, source); if(m_areaAuraType == AREA_AURA_ENEMY) caster->CombatStart(*tIter); } } } - Aura::Update(diff); + AuraEffect::Update(diff); } else // aura at non-caster { - Unit * tmp_target = m_target; - Unit* caster = GetCaster(); - uint32 tmp_spellId = GetId(), tmp_effIndex = m_effIndex; - // WARNING: the aura may get deleted during the update // DO NOT access its members after update! - Aura::Update(diff); + AuraEffect::Update(diff); + + // Speedup - no need to do more checks + if (GetParentAura()->IsRemoved()) + return; + + // Caster may be deleted due to update + Unit *caster = GetCaster(); + Unit *source = GetSource(); // remove aura if out-of-range from caster (after teleport for example) // or caster is isolated or caster no longer has the aura // or caster is (no longer) friendly bool needFriendly = (m_areaAuraType == AREA_AURA_ENEMY ? false : true); - if( !caster || caster->hasUnitState(UNIT_STAT_ISOLATED) || - !caster->IsWithinDistInMap(tmp_target, m_radius) || - !caster->HasAura(tmp_spellId, tmp_effIndex) || - caster->IsFriendlyTo(tmp_target) != needFriendly + if( !source || !caster || + source->hasUnitState(UNIT_STAT_ISOLATED) || !source->HasAuraEffect(GetId(), m_effIndex) || + caster->IsFriendlyTo(m_target) != needFriendly ) { - tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + m_target->RemoveAura(GetParentAura()); } - else if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group + else if (!source->IsWithinDistInMap(m_target, m_radius)) { - if(!tmp_target->IsInPartyWith(caster)) - tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + if (needFriendly) + { + m_removeTime -= diff; + if (m_removeTime < 0) + m_target->RemoveAura(GetParentAura()); + } + else + m_target->RemoveAura(GetParentAura()); } - else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) + else { - if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) - tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + // Reset aura remove timer + m_removeTime = FRIENDLY_AA_REMOVE_TIME; + if( m_areaAuraType == AREA_AURA_PARTY) // check if in same sub group + { + if(!m_target->IsInPartyWith(caster)) + m_target->RemoveAura(GetParentAura()); + } + else if( m_areaAuraType == AREA_AURA_RAID) + { + if(!m_target->IsInRaidWith(caster)) + m_target->RemoveAura(GetParentAura()); + } + else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) + { + if( m_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) + m_target->RemoveAura(GetParentAura()); + } } } } -void PersistentAreaAura::Update(uint32 diff) +void PersistentAreaAuraEffect::Update(uint32 diff) { - bool remove = false; - - // remove the aura if its caster or the dynamic object causing it was removed - // or if the target moves too far from the dynamic object - Unit *caster = GetCaster(); - if (caster) + if(Unit *caster = GetParentAura()->GetCaster()) { - DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex()); - if (dynObj) + if(DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex())) { - if (!m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius())) - remove = true; + if(m_target->IsWithinDistInMap(dynObj, dynObj->GetRadius())) + { + AuraEffect::Update(diff); + return; + } } - else - remove = true; } - else - remove = true; - Unit *tmp_target = m_target; - uint32 tmp_id = GetId(), tmp_index = GetEffIndex(); + // remove the aura if its caster or the dynamic object causing it was removed + // or if the target moves too far from the dynamic object + m_target->RemoveAura(GetParentAura()); +} - // WARNING: the aura may get deleted during the update - // DO NOT access its members after update! - Aura::Update(diff); +void AuraEffect::ApplyModifier(bool apply, bool Real, bool changeAmount) +{ + if (GetParentAura()->IsRemoved()) + return; - if(remove) - tmp_target->RemoveAura(tmp_id, tmp_index); + (*this.*AuraHandler [m_auraName])(apply,Real, changeAmount); } -void Aura::ApplyModifier(bool apply, bool Real) +void AuraEffect::RecalculateAmount(bool applied) { - AuraType aura = m_modifier.m_auraname; + Unit *caster = GetParentAura()->GetCaster(); + int32 amount = GetParentAura()->GetStackAmount() * (caster ? caster->CalculateSpellDamage(m_spellProto, GetEffIndex(), GetBasePoints(), NULL) : GetBasePoints()); + // Reapply if amount change + if (amount!=GetAmount()) + { + // Auras which are applying spellmod should have removed spellmods for real + if (applied) + ApplyModifier(false,false,true); + SetAmount(amount); + if (applied) + ApplyModifier(true,false,true); + } +} + +void AuraEffect::CleanupTriggeredSpells() +{ + uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; + if(!tSpellId) + return; + + SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId); + if(!tProto) + return; + + if(GetSpellDuration(tProto) != -1) + return; - m_in_use = true; - if(aura<TOTAL_AURAS) - (*this.*AuraHandler [aura])(apply,Real); - m_in_use = false; + // needed for spell 43680, maybe others + // TODO: is there a spell flag, which can solve this in a more sophisticated way? + if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && + GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()]) + return; + + m_target->RemoveAurasDueToSpell(tSpellId, GetCasterGUID()); +} + +void Aura::ApplyAllModifiers(bool apply, bool Real) +{ + for (uint8 i = 0; i<MAX_SPELL_EFFECTS;++i) + if (m_partAuras[i]) + m_partAuras[i]->ApplyModifier(apply, Real); } -void Aura::UpdateAuraDuration() +void Aura::SendAuraUpdate() { - if(m_auraSlot >= MAX_AURAS || m_isPassive) + if (m_auraSlot>=MAX_AURAS) return; + WorldPacket data(SMSG_AURA_UPDATE); - if( m_target->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5); - data << (uint8)m_auraSlot << (uint32)m_duration; - ((Player*)m_target)->SendDirectMessage(&data); + data.append(m_target->GetPackGUID()); + data << uint8(m_auraSlot); - data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4)); - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - data << uint32(GetId()); - data << uint32(GetAuraMaxDuration()); - data << uint32(GetAuraDuration()); - ((Player*)m_target)->SendDirectMessage(&data); + if(!m_target->GetVisibleAura(m_auraSlot)) + { + data << uint32(0); + sLog.outDebug("Aura %u removed slot %u",GetId(), m_auraSlot); + m_target->SendMessageToSet(&data, true); + return; } - // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code - if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()) - return; + data << uint32(GetId()); + data << uint8(m_auraFlags); + data << uint8(m_auraLevel); + data << uint8(m_stackAmount > 1 ? m_stackAmount : m_procCharges); - Unit* caster = GetCaster(); + if(!(m_auraFlags & AFLAG_CASTER)) + { + if (Unit * caster = GetCaster()) + data.append(caster->GetPackGUID()); + else + data << uint8(0); + } - if(caster && caster->GetTypeId() == TYPEID_PLAYER) + if(m_auraFlags & AFLAG_DURATION) { - SendAuraDurationForCaster((Player*)caster); + data << uint32(m_maxduration); + data << uint32(m_duration); + } + + m_target->SendMessageToSet(&data, true); +} + +bool Aura::IsVisible() const +{ + // passive auras (except totem auras) do not get placed in the slots + // area auras with SPELL_AURA_NONE are not shown on target + //(m_spellProto->Attributes & 0x80 && GetTalentSpellPos(GetId())) - Group* CasterGroup = ((Player*)caster)->GetGroup(); - if (CasterGroup && (spellmgr.GetSpellCustomAttr(GetId()) & SPELL_ATTR_CU_AURA_CC)) + if(!m_isPassive) + return true; + + bool noneAreaAura = true; + for(uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if(m_partAuras[i]) { - for (GroupReference *itr = CasterGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + if(m_partAuras[i]->IsAreaAura()) { - Player* player = itr->getSource(); - if(player && player != caster) - SendAuraDurationForCaster(player); + if(WorldObject *source = m_partAuras[i]->GetSource()) + if(source->GetTypeId() == TYPEID_UNIT && ((Creature*)source)->isTotem()) + return true; + + if(m_partAuras[i]->GetAuraName() != SPELL_AURA_NONE) + noneAreaAura = false; } + else + noneAreaAura = false; } } -} -void Aura::SendAuraDurationForCaster(Player* caster) -{ - if (caster == m_target) - return; + if(noneAreaAura) + return false; - WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4)); - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - data << uint32(GetId()); - data << uint32(GetAuraMaxDuration()); // full - data << uint32(GetAuraDuration()); // remain - caster->GetSession()->SendPacket(&data); + return IsAuraType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); } void Aura::_AddAura() @@ -815,334 +1020,640 @@ void Aura::_AddAura() if(!m_target) return; - // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT - bool secondaura = false; - uint8 slot = NULL_AURA_SLOT; + Unit* caster = GetCaster(); - for(uint8 i = 0; i < 3; i++) + // set infinity cooldown state for spells + if(caster && caster->GetTypeId() == TYPEID_PLAYER) { - Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); - for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) + if (m_spellProto->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) + { + Item* castItem = m_castItemGuid ? ((Player*)caster)->GetItemByGuid(m_castItemGuid) : NULL; + ((Player*)caster)->AddSpellAndCategoryCooldowns(m_spellProto,castItem ? castItem->GetEntry() : 0, NULL,true); + } + } + + if(IsVisible()) + { + // Try find slot for aura + uint8 slot = MAX_AURAS; + // Lookup for auras already applied from spell + if (Aura * foundAura = m_target->GetAura(GetId(), GetCasterGUID())) { // allow use single slot only by auras from same caster - if(itr->second->GetCasterGUID()==GetCasterGUID()) + slot = foundAura->GetAuraSlot(); + } + else + { + Unit::VisibleAuraMap const * visibleAuras= m_target->GetVisibleAuras(); + // lookup for free slots in units visibleAuras + Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(0); + for(uint32 freeSlot = 0; freeSlot < MAX_AURAS; ++itr , ++freeSlot) { - secondaura = true; - slot = itr->second->GetAuraSlot(); - break; + if(itr == visibleAuras->end() || itr->first != freeSlot) + { + slot = freeSlot; + break; + } } } - if(secondaura) - break; + // Register Visible Aura + if(slot < MAX_AURAS) + { + m_auraFlags |= (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE) | + (GetCasterGUID() == m_target->GetGUID() ? AFLAG_CASTER : AFLAG_NONE) | + (GetAuraMaxDuration() > 0 ? AFLAG_DURATION : AFLAG_NONE); + m_auraLevel = (caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + SetAuraSlot( slot ); + m_target->SetVisibleAura(slot, this); + m_target->UpdateAuraForGroup(slot); + SendAuraUpdate(); + sLog.outDebug("Aura: %u Effect: %d put to unit visible auras slot: %u",GetId(), GetEffectMask(), slot); + } + else + sLog.outDebug("Aura: %u Effect: %d could not find empty unit visible slot",GetId(), GetEffectMask()); } - Unit* caster = GetCaster(); + // Sitdown on apply aura req seated + if (m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !m_target->IsSitState()) + m_target->SetStandState(UNIT_STAND_STATE_SIT); - // not call total regen auras at adding - switch (m_modifier.m_auraname) - { - /*case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_LEECH: - if(caster) - m_modifier.m_amount = caster->SpellDamageBonus(m_target, m_spellProto, m_modifier.m_amount, DOT); - break; - case SPELL_AURA_PERIODIC_HEAL: - if(caster) - m_modifier.m_amount = caster->SpellHealingBonus(m_spellProto, m_modifier.m_amount, DOT, m_target); - break;*/ - case SPELL_AURA_OBS_MOD_HEALTH: - case SPELL_AURA_OBS_MOD_MANA: - m_periodicTimer = m_modifier.periodictime; - break; - case SPELL_AURA_MOD_REGEN: - case SPELL_AURA_MOD_POWER_REGEN: - case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT: - m_periodicTimer = 5000; - break; - } - - // register aura + // register aura diminishing on apply if (getDiminishGroup() != DIMINISHING_NONE ) m_target->ApplyDiminishingAura(getDiminishGroup(),true); - // passive auras (except totem auras) do not get placed in the slots - // area auras with SPELL_AURA_NONE are not shown on target - if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && - (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)) + // Apply linked auras (On first aura apply) + uint32 id = GetId(); + if(spellmgr.GetSpellCustomAttr(id) & SPELL_ATTR_CU_LINK_AURA) { - if(!secondaura) // new slot need - { - if (IsPositive()) // empty positive slot - { - for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++) - { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } - } - } - else // empty negative slot + if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA)) + for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) { - for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++) - { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } - } + if(*itr < 0) + m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), true); + else if(Unit* caster = GetCaster()) + caster->AddAura(*itr, m_target); } + } - SetAuraSlot( slot ); + //***************************************************** + // Update target aura state flag + //***************************************************** - // Not update fields for not first spell's aura, all data already in fields - if(slot < MAX_AURAS) // slot found - { - SetAura(slot, false); - SetAuraFlag(slot, true); - SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - UpdateAuraCharges(); + // Update Seals information + if (IsSealSpell(m_spellProto)) + SetAuraState(AURA_STATE_JUDGEMENT); - // update for out of range group members - m_target->UpdateAuraForGroup(slot); - } - } - else // use found slot - { - SetAuraSlot( slot ); - } + // Conflagrate aura state on Immolate or Shadowflame + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && (m_spellProto->SpellFamilyFlags[0] & 4 + || m_spellProto->SpellFamilyFlags[2] & 2)) + SetAuraState(AURA_STATE_IMMOLATE); + + // Faerie Fire (druid versions) + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x400) + SetAuraState(AURA_STATE_FAERIE_FIRE); + + // Victorious + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x00040000) + SetAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH); - UpdateSlotCounterAndDuration(); + // Swiftmend state on Regrowth & Rejuvenation + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x50 ) + SetAuraState(AURA_STATE_SWIFTMEND); - // Update Seals information - if( IsSealSpell(GetSpellProto()) ) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); + // Deadly poison aura state + if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x10000) + SetAuraState(AURA_STATE_DEADLY_POISON); - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); + // Enrage aura state + if(m_spellProto->Dispel == DISPEL_ENRAGE) + SetAuraState(AURA_STATE_ENRAGE); - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) + // Bleeding aura state + if (GetAllSpellMechanicMask(m_spellProto) & 1<<MECHANIC_BLEED) + SetAuraState(AURA_STATE_BLEEDING); + + if(GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST) + { + for (uint8 i = 0;i<MAX_SPELL_EFFECTS;++i) { - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); + if (m_spellProto->EffectApplyAuraName[i]==SPELL_AURA_MOD_STUN + || m_spellProto->EffectApplyAuraName[i]==SPELL_AURA_MOD_ROOT) + { + SetAuraState(AURA_STATE_FROZEN); + break; + } } } + + m_target->ApplyModFlag(UNIT_FIELD_AURASTATE, GetAuraStateMask(), true); +} + +bool Aura::SetPartAura(AuraEffect* aurEff, uint8 effIndex) +{ + if (IsRemoved()) + return false; + if (m_auraFlags & (1<<effIndex)) + return false; + m_auraFlags |= 1<<effIndex; + m_partAuras[effIndex]=aurEff; + m_target->HandleAuraEffect(aurEff, true); + SendAuraUpdate(); + return true; } void Aura::_RemoveAura() { Unit* caster = GetCaster(); - if(caster && IsPersistent()) + uint8 slot = GetAuraSlot(); + + if (Aura * foundAura = m_target->GetAura(GetId(), GetCasterGUID())) { - DynamicObject *dynObj = caster->GetDynObject(GetId(), GetEffIndex()); - if (dynObj) - dynObj->RemoveAffected(m_target); + // allow use single slot only by auras from same caster + slot = foundAura->GetAuraSlot(); + if(slot < MAX_AURAS) // slot not set + if (Aura *entry = m_target->GetVisibleAura(slot)) + { + // set not valid slot for aura - prevent removing other visible aura + slot = MAX_AURAS; + } + } + + // update for out of range group members + if (slot < MAX_AURAS) + { + m_target->RemoveVisibleAura(slot); + m_target->UpdateAuraForGroup(slot); + SendAuraUpdate(); } - // unregister aura + // unregister aura diminishing (and store last time) if (getDiminishGroup() != DIMINISHING_NONE ) m_target->ApplyDiminishingAura(getDiminishGroup(),false); - //passive auras do not get put in slots - // Note: but totem can be not accessible for aura target in time remove (to far for find in grid) - //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) - // return; - - uint8 slot = GetAuraSlot(); - - if(slot >= MAX_AURAS) // slot not set - return; + // Check needed only if aura applies aurastate + if(GetAuraStateMask()) + { + uint32 foundMask = 0; + Unit::AuraMap& Auras = m_target->GetAuras(); + // Get mask of all aurastates from remaining auras + for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + { + foundMask|=(*i).second->GetAuraStateMask(); + } + // Remove only aurastates which were not found + foundMask = GetAuraStateMask() &~foundMask; + if (foundMask) + m_target->ApplyModFlag(UNIT_FIELD_AURASTATE, foundMask, false); + } - if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0) - return; + // since now aura cannot apply/remove it's modifiers + m_isRemoved = true; + // disable client server communication for removed aura + SetAuraSlot(MAX_AURAS); - bool samespell = false; + // reset cooldown state for spells + if(caster && caster->GetTypeId() == TYPEID_PLAYER) + { + if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) + // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) + ((Player*)caster)->SendCooldownEvent(GetSpellProto()); + } + uint32 id = GetId(); + // Remove Linked Auras + if(m_removeMode != AURA_REMOVE_BY_STACK && m_removeMode != AURA_REMOVE_BY_DEATH) + { + if(uint32 customAttr = spellmgr.GetSpellCustomAttr(id)) + { + if(customAttr & SPELL_ATTR_CU_LINK_REMOVE) + { + if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(-(int32)id)) + for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) + { + if(*itr < 0) + m_target->RemoveAurasDueToSpell(-(*itr)); + else if (m_removeMode != AURA_REMOVE_BY_DEFAULT) + m_target->CastSpell(m_target, *itr, true, 0, 0, GetCasterGUID()); + } + } + if(customAttr & SPELL_ATTR_CU_LINK_AURA) + { + if(const std::vector<int32> *spell_triggered = spellmgr.GetSpellLinked(id + SPELL_LINK_AURA)) + for(std::vector<int32>::const_iterator itr = spell_triggered->begin(); itr != spell_triggered->end(); ++itr) + { + if(*itr < 0) + m_target->ApplySpellImmune(id, IMMUNITY_ID, -(*itr), false); + else + m_target->RemoveAurasDueToSpell(*itr); + } + } + } + } - // find other aura in same slot (current already removed from list) - for(uint8 i = 0; i < 3; i++) + // Proc on aura remove (only spell flags for now) + if (caster) { - Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); - for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) + uint32 procEx=0; + if (m_removeMode == AURA_REMOVE_BY_ENEMY_SPELL) + procEx = PROC_EX_AURA_REMOVE_DESTROY; + else if (m_removeMode == AURA_REMOVE_BY_EXPIRE || m_removeMode == AURA_REMOVE_BY_CANCEL) + procEx = PROC_EX_AURA_REMOVE_EXPIRE; + if (procEx) { - if(itr->second->GetAuraSlot()==slot) + uint32 ProcCaster, ProcVictim; + if (IsPositiveSpell(GetId())) + { + ProcCaster = PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL; + ProcVictim = PROC_FLAG_TAKEN_POSITIVE_SPELL; + } + else { - samespell = true; + ProcCaster = PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT; + ProcVictim = PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT; + } + caster->ProcDamageAndSpell(m_target,ProcCaster, ProcVictim, procEx, m_procDamage, BASE_ATTACK, m_spellProto); + } + } +} - break; +void Aura::SetStackAmount(uint8 stackAmount, bool applied) +{ + if (stackAmount != m_stackAmount) + { + m_stackAmount = stackAmount; + for (uint8 i=0;i<MAX_SPELL_EFFECTS;++i) + { + if (AuraEffect * part = GetPartAura(i)) + { + part->RecalculateAmount(applied); } } - if(samespell) - break; } + RefreshAura(); +} - // only remove icon when the last aura of the spell is removed (current aura already removed from list) - if (!samespell) +bool Aura::modStackAmount(int32 num) +{ + // Can`t mod + if (!m_spellProto->StackAmount) + return true; + + // Modify stack but limit it + int32 stackAmount = m_stackAmount + num; + if (stackAmount > m_spellProto->StackAmount) + stackAmount = m_spellProto->StackAmount; + else if (stackAmount <=0) // Last aura from stack removed { - SetAura(slot, true); - SetAuraFlag(slot, false); - SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + m_stackAmount = 0; + return true; // need remove aura + } - SetAuraApplication(slot, 0); - // update for out of range group members - m_target->UpdateAuraForGroup(slot); + // Update stack amount + SetStackAmount(stackAmount); + return false; +} - if( IsSealSpell(GetSpellProto()) ) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); +void Aura::SetAuraDuration(int32 duration, bool withMods) +{ + if (withMods) + { + if (Player * modOwner = m_target->GetSpellModOwner()) + modOwner->ApplySpellMod(GetId(), SPELLMOD_DURATION, duration); + } + m_duration = duration; + //if (duration<0) + //m_permanent=true; + //else + //m_permanent=false; + SendAuraUpdate(); +} - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); +void Aura::SetAuraCharges(uint8 charges) +{ + if (m_procCharges == charges) + return; + m_procCharges = charges; + SendAuraUpdate(); +} - // Swiftmend aura state - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) +bool Aura::DropAuraCharge() +{ + if(m_procCharges) //auras without charges always have charge = 0 + { + if(--m_procCharges) // Send charge change + SendAuraUpdate(); + else // Last charge dropped { - bool found = false; - Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); - for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) - { - if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) - { - found = true; - break; - } - } - if(!found) - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); + m_target->RemoveAura(this, AURA_REMOVE_BY_EXPIRE); + return true; } + } + return false; +} - // reset cooldown state for spells - if(caster && caster->GetTypeId() == TYPEID_PLAYER) - { - if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) - ((Player*)caster)->SendCooldownEvent(GetSpellProto()); - } +bool Aura::IsPersistent() const +{ + for(uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if(m_partAuras[i] && m_partAuras[i]->IsPersistent()) + return true; } + return false; } -void Aura::SetAuraFlag(uint32 slot, bool add) +bool Aura::IsAreaAura() const { - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index); - val &= ~((uint32)AFLAG_MASK << byte); - if(add) + for(uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { - if (IsPositive()) - val |= ((uint32)AFLAG_POSITIVE << byte); - else - val |= ((uint32)AFLAG_NEGATIVE << byte); + if(m_partAuras[i] && m_partAuras[i]->IsAreaAura()) + return true; } - m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val); + return false; } -void Aura::SetAuraLevel(uint32 slot,uint32 level) +bool Aura::IsAuraType(AuraType type) const { - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index); - val &= ~(0xFF << byte); - val |= (level << byte); - m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val); + for(uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if(m_partAuras[i] && m_partAuras[i]->GetAuraName() == type) + return true; + } + return false; } -void Aura::SetAuraApplication(uint32 slot, int8 count) +void Aura::SetLoadedState(uint64 caster_guid,int32 maxduration,int32 duration,int32 charges, uint8 stackamount, int32 * amount) { - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index); - val &= ~(0xFF << byte); - val |= ((uint8(count)) << byte); - m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val); + m_caster_guid = caster_guid; + m_maxduration = maxduration; + m_duration = duration; + m_procCharges = charges; + m_stackAmount = stackamount; + for (uint8 i=0; i<MAX_SPELL_EFFECTS;++i) + if (m_partAuras[i]) + m_partAuras[i]->SetAmount(amount[i]); } -void Aura::UpdateSlotCounterAndDuration() +void AuraEffect::HandleShapeshiftBoosts(bool apply) { - uint8 slot = GetAuraSlot(); - if(slot >= MAX_AURAS) - return; + uint32 spellId = 0; + uint32 spellId2 = 0; + uint32 HotWSpellId = 0; + + switch(GetMiscValue()) + { + case FORM_CAT: + spellId = 3025; + HotWSpellId = 24900; + break; + case FORM_TREE: + spellId = 5420; + spellId2 = 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; + // aura from effect trigger spell + spellId2 = 24907; + 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_GHOUL: + case FORM_GHOSTWOLF: + case FORM_AMBIENT: + case FORM_SHADOW: + case FORM_STEALTH: + case FORM_CREATURECAT: + case FORM_CREATUREBEAR: + spellId = 0; + break; + } + + uint32 form = GetMiscValue()-1; + + if(apply) + { + if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this ); + if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + if(itr->second->state == PLAYERSPELL_REMOVED) continue; + if(itr->first==spellId || itr->first==spellId2) continue; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); + if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue; + if (spellInfo->Stances & (1<<form)) + m_target->CastSpell(m_target, itr->first, true, NULL, this); + } + //LotP + if (((Player*)m_target)->HasSpell(17007)) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932); + if (spellInfo && spellInfo->Stances & (1<<form)) + m_target->CastSpell(m_target, 24932, true, NULL, this); + } + // HotW + if (HotWSpellId) + { + Unit::AuraEffectList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); + for(Unit::AuraEffectList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) + { + if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetMiscValue() == 3) + { + int32 HotWMod = (*i)->GetAmount(); + if(GetMiscValue() == FORM_CAT) + HotWMod /= 2; + + m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this); + break; + } + } + } + } + } + else + { + m_target->RemoveAurasDueToSpell(spellId); + m_target->RemoveAurasDueToSpell(spellId2); - // Three possibilities: - // Charge = 0; Stack >= 0 - // Charge = 1; Stack >= 0 - // Charge > 1; Stack = 0 - if(m_procCharges < 2) - SetAuraApplication(slot, m_stackAmount-1); + Unit::AuraMap& tAuras = m_target->GetAuras(); + for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) + { + if (itr->second->IsRemovedOnShapeLost()) + { + m_target->RemoveAura(itr); + } + else + { + ++itr; + } + } + } +} + +bool AuraEffect::isAffectedOnSpell(SpellEntry const *spell) const +{ + if (!spell) + return false; + // Check family name + if (spell->SpellFamilyName != m_spellProto->SpellFamilyName) + return false; + + // Check EffectClassMask and Spell_Affect table + flag96 const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); + if (!spellAffect) + spellAffect = &m_spellProto->EffectSpellClassMask[m_effIndex]; + + if (*spellAffect & spell->SpellFamilyFlags) + return true; + return false; +} - UpdateAuraDuration(); +void Aura::UnregisterSingleCastAura() +{ + if (IsSingleTarget()) + { + Unit* caster = NULL; + caster = GetCaster(); + if(caster) + { + caster->GetSingleCastAuras().remove(this); + } + else + { + sLog.outError("Couldn't find the caster of the single target aura, may crash later!"); + assert(false); + } + m_isSingleTargetAura = false; + } } /*********************************************************/ /*** BASIC AURA FUNCTION ***/ /*********************************************************/ -void Aura::HandleAddModifier(bool apply, bool Real) +void AuraEffect::HandleAddModifier(bool apply, bool Real, bool changeAmount) { - if(m_target->GetTypeId() != TYPEID_PLAYER || !Real) + if(m_target->GetTypeId() != TYPEID_PLAYER || (!Real && !changeAmount)) return; - SpellEntry const *spellInfo = GetSpellProto(); - if(!spellInfo) - return; + uint32 modOp = GetMiscValue(); - if(m_modifier.m_miscvalue >= MAX_SPELLMOD) + if(modOp >= MAX_SPELLMOD) return; if (apply) { - // Add custom charges for some mod aura - switch (m_spellProto->Id) - { - case 17941: // Shadow Trance - case 22008: // Netherwind Focus - case 34936: // Backlash - m_procCharges = 1; - break; - } - - SpellModifier *mod = new SpellModifier; - mod->op = SpellModOp(m_modifier.m_miscvalue); - mod->value = GetModifierValue(); - mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types + SpellModifier *mod = new SpellModifier(GetParentAura()); + mod->op = SpellModOp(modOp); + mod->value = m_amount; + mod->type = SpellModType(m_auraName); // SpellModType value == spell aura types mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - - uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex); - - if (spellAffectMask) - mod->mask = spellAffectMask; - else - mod->mask = spellInfo->EffectItemType[m_effIndex]; - if (m_procCharges > 0) - mod->charges = m_procCharges; - else - mod->charges = 0; + flag96 const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); + if (!spellAffect) + spellAffect = &m_spellProto->EffectSpellClassMask[m_effIndex]; + mod->mask = *spellAffect; + mod->charges = GetParentAura()->GetAuraCharges(); m_spellmod = mod; } - uint64 spellFamilyMask = m_spellmod->mask; - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); + // Auras with charges do not mod amount of passive auras + if (GetParentAura()->GetAuraCharges()) + return; // reapply some passive spells after add/remove related spellmods - if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL)) + // Warning: it is a dead loop if 2 auras each other amount-shouldn't happen + switch (modOp) { - m_target->RemoveAurasDueToSpell(45471); - - if(apply) - m_target->CastSpell(m_target,45471,true); + case SPELLMOD_ALL_EFFECTS: + case SPELLMOD_EFFECT1: + case SPELLMOD_EFFECT2: + case SPELLMOD_EFFECT3: + { + uint64 guid = m_target->GetGUID(); + Unit::AuraMap & auras = m_target->GetAuras(); + for(Unit::AuraMap::iterator iter = auras.begin(); iter != auras.end();++iter) + { + Aura * aur = iter->second; + // 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 (aur->IsPassive() && aur->GetCasterGUID() == guid && spellmgr.IsAffectedByMod(aur->GetSpellProto(), m_spellmod)) + { + if (modOp == SPELLMOD_ALL_EFFECTS) + { + for (uint8 i = 0; i<MAX_SPELL_EFFECTS;++i) + { + if (AuraEffect * aurEff = aur->GetPartAura(i)) + aurEff->RecalculateAmount(); + } + } + else if (modOp ==SPELLMOD_EFFECT1) + { + if (AuraEffect * aurEff = aur->GetPartAura(0)) + aurEff->RecalculateAmount(); + } + else if (modOp ==SPELLMOD_EFFECT2) + { + if (AuraEffect * aurEff = aur->GetPartAura(1)) + aurEff->RecalculateAmount(); + } + else //if (modOp ==SPELLMOD_EFFECT3) + { + if (AuraEffect * aurEff = aur->GetPartAura(2)) + aurEff->RecalculateAmount(); + } + } + } + } + default: + break; } } -void Aura::TriggerSpell() +void AuraEffect::TriggerSpell() { Unit* caster = GetCaster(); Unit* target = GetTriggerTarget(); @@ -1153,8 +1664,6 @@ void Aura::TriggerSpell() // generic casting code with custom spells and target/caster customs uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; - uint64 originalCasterGUID = GetCasterGUID(); - SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); SpellEntry const *auraSpellInfo = GetSpellProto(); uint32 auraId = auraSpellInfo->Id; @@ -1193,7 +1702,7 @@ void Aura::TriggerSpell() } // remove old enchanting before applying new ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,false); - item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_modifier.periodictime+1000, 0); + item->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, m_amplitude+1000, 0); // add new enchanting ((Player*)caster)->ApplyEnchantment(item,TEMP_ENCHANTMENT_SLOT,true); return; @@ -1239,17 +1748,15 @@ void Aura::TriggerSpell() case 23493: { int32 heal = caster->GetMaxHealth() / 10; - caster->ModifyHealth( heal ); - caster->SendHealSpellLog(caster, 23493, heal); + caster->DealHeal(m_target, heal, auraSpellInfo); int32 mana = caster->GetMaxPower(POWER_MANA); if (mana) { mana /= 10; - caster->ModifyPower( POWER_MANA, mana ); - caster->SendEnergizeSpellLog(caster, 23493, mana, POWER_MANA); + caster->EnergizeBySpell(caster, 23493, mana, POWER_MANA); } - break; + return; } // // Stoneclaw Totem Passive TEST // case 23792: break; @@ -1306,10 +1813,18 @@ void Aura::TriggerSpell() } break; // // Steam Tank Passive // case 27747: break; -// // Frost Blast -// case 27808: break; -// // Detonate Mana -// case 27819: break; + // Frost Blast + case 27808: + caster->CastCustomSpell(29879, SPELLVALUE_BASE_POINT0, (float)m_target->GetMaxHealth()*0.26f, m_target, true, NULL, this); + return; + // Detonate Mana + case 27819: + if(int32 mana = (int32)(m_target->GetMaxPower(POWER_MANA) / 4)) + { + mana = m_target->ModifyPower(POWER_MANA, -mana); + m_target->CastCustomSpell(27820, SPELLVALUE_BASE_POINT0, -mana*4, NULL, true, NULL, this, caster->GetGUID()); + } + return; // // Controller Timer // case 28095: break; // // Stalagg Chain @@ -1328,8 +1843,11 @@ void Aura::TriggerSpell() // case 28522: break; // // Silithyst // case 29519: break; -// // Inoculate Nestlewood Owlkin - case 29528: trigger_spell_id = 28713; break; + // Inoculate Nestlewood Owlkin + case 29528: + if(target->GetTypeId()!=TYPEID_UNIT)// prevent error reports in case ignored player target + return; + break; // // Overload // case 29768: break; // // Return Fire @@ -1362,32 +1880,13 @@ void Aura::TriggerSpell() Creature* creature = (Creature*)target; // missing lootid has been reported on startup - just return if (!creature->GetCreatureInfo()->SkinLootId) - { return; - } - Loot *loot = &creature->loot; - loot->clear(); - loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL); - for(uint8 i=0;i<loot->items.size();i++) - { - LootItem *item = loot->LootItemInSlot(i,player); - ItemPosCountVec dest; - uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count ); - if ( msg == EQUIP_ERR_OK ) - { - Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId); - - player->SendNewItem(newitem, uint32(item->count), false, false, true); - } - else - player->SendEquipError( msg, NULL, NULL ); - } - creature->setDeathState(JUST_DIED); - creature->RemoveCorpse(); - creature->SetHealth(0); // just for nice GM-mode view + + player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId,LootTemplates_Skinning,true); + + creature->ForcedDespawn(); } return; - break; } // Quake case 30576: trigger_spell_id = 30571; break; @@ -1407,7 +1906,7 @@ void Aura::TriggerSpell() // Doom case 31347: { - m_target->CastSpell(m_target,31350,true); + m_target->CastSpell(m_target,31350,true, NULL, this); m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); return; } @@ -1437,9 +1936,9 @@ void Aura::TriggerSpell() { // cast 24 spells 34269-34289, 34314-34316 for(uint32 spell_id = 34269; spell_id != 34290; ++spell_id) - caster->CastSpell(m_target,spell_id,true); + caster->CastSpell(m_target,spell_id,true, NULL, this); for(uint32 spell_id = 34314; spell_id != 34317; ++spell_id) - caster->CastSpell(m_target,spell_id,true); + caster->CastSpell(m_target,spell_id,true, NULL, this); return; } // // Gravity Lapse @@ -1521,7 +2020,7 @@ void Aura::TriggerSpell() // Eye of Grillok case 38495: { - m_target->CastSpell(m_target, 38530, true); + m_target->CastSpell(m_target, 38530, true, NULL, this); return; } // Absorb Eye of Grillok (Zezzak's Shard) @@ -1530,13 +2029,11 @@ void Aura::TriggerSpell() if(m_target->GetTypeId() != TYPEID_UNIT) return; - caster->CastSpell(caster, 38495, true); + caster->CastSpell(caster, 38495, true, NULL, this); Creature* creatureTarget = (Creature*)m_target; - creatureTarget->setDeathState(JUST_DIED); - creatureTarget->RemoveCorpse(); - creatureTarget->SetHealth(0); // just for nice GM-mode view + creatureTarget->ForcedDespawn(); return; } // // Magic Sucker Device timer @@ -1590,13 +2087,13 @@ void Aura::TriggerSpell() // Aura of Desire case 41350: { - Unit::AuraList const& mMod = m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT); - for(Unit::AuraList::const_iterator i = mMod.begin(); i != mMod.end(); ++i) + Unit::AuraEffectList const& mMod = m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT); + for(Unit::AuraEffectList::const_iterator i = mMod.begin(); i != mMod.end(); ++i) { if ((*i)->GetId() == 41350) { (*i)->ApplyModifier(false); - (*i)->GetModifier()->m_amount -= 5; + (*i)->SetAmount((*i)->GetAmount()-5); (*i)->ApplyModifier(true); break; } @@ -1637,11 +2134,8 @@ void Aura::TriggerSpell() { // Invisibility case 66: - { - if(!m_duration) - m_target->CastSpell(m_target, 32612, true, NULL, this); + // Here need periodic triger reducing threat spell (or do it manually) return; - } default: break; } @@ -1687,7 +2181,7 @@ void Aura::TriggerSpell() case 22896: case 26999: { - int32 LifePerRage = GetModifier()->m_amount; + int32 LifePerRage = GetAmount(); int32 lRage = m_target->GetPower(POWER_RAGE); if(lRage > 100) // rage stored as rage*10 @@ -1751,7 +2245,7 @@ void Aura::TriggerSpell() { SpellEntry const* spell = itr->second->GetSpellProto(); if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN && - spell->SpellFamilyFlags & 0x0000000000000400L) + spell->SpellFamilyFlags[0] & 0x400) return; } target->RemoveAurasDueToSpell(28820); @@ -1761,9 +2255,9 @@ void Aura::TriggerSpell() case 38443: { bool all = true; - for(int i = 0; i < MAX_TOTEM; ++i) + for(int i = SUMMON_SLOT_TOTEM; i < MAX_TOTEM_SLOT; ++i) { - if(!caster->m_TotemSlot[i]) + if(!caster->m_SummonSlot[i]) { all = false; break; @@ -1771,7 +2265,7 @@ void Aura::TriggerSpell() } if(all) - caster->CastSpell(caster,38437,true); + caster->CastSpell(caster,38437,true, NULL, this); else caster->RemoveAurasDueToSpell(38437); return; @@ -1784,13 +2278,9 @@ void Aura::TriggerSpell() default: break; } + // Reget trigger spell proto triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); - if(triggeredSpellInfo == NULL) - { - sLog.outError("Aura::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex()); - return; - } } else { @@ -1807,22 +2297,22 @@ void Aura::TriggerSpell() // 2) maybe aura must be replace by new with accumulative stat mods instead stacking // prevent cast by triggered auras - if(m_caster_guid == m_target->GetGUID()) + if(GetCasterGUID() == m_target->GetGUID()) return; // stop triggering after each affected stats lost > 90 int32 intellectLoss = 0; int32 spiritLoss = 0; - Unit::AuraList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT); - for(Unit::AuraList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i) + Unit::AuraEffectList const& mModStat = m_target->GetAurasByType(SPELL_AURA_MOD_STAT); + for(Unit::AuraEffectList::const_iterator i = mModStat.begin(); i != mModStat.end(); ++i) { if ((*i)->GetId() == 1010) { - switch((*i)->GetModifier()->m_miscvalue) + switch((*i)->GetMiscValue()) { - case STAT_INTELLECT: intellectLoss += (*i)->GetModifierValue(); break; - case STAT_SPIRIT: spiritLoss += (*i)->GetModifierValue(); break; + case STAT_INTELLECT: intellectLoss += (*i)->GetAmount(); break; + case STAT_SPIRIT: spiritLoss += (*i)->GetAmount(); break; default: break; } } @@ -1832,54 +2322,87 @@ void Aura::TriggerSpell() return; caster = target; - originalCasterGUID = 0; break; } // Mana Tide case 16191: { - caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID); + caster->CastCustomSpell(target, trigger_spell_id, &m_amount, NULL, NULL, true, NULL, this); return; } // Negative Energy Periodic case 46284: - { - caster->CastCustomSpell(trigger_spell_id, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this, originalCasterGUID); + caster->CastCustomSpell(trigger_spell_id, SPELLVALUE_MAX_TARGETS, m_tickNumber / 10 + 1, NULL, true, NULL, this); + return; + // Poison (Grobbulus) + case 28158: + case 54362: + m_target->CastCustomSpell(trigger_spell_id, SPELLVALUE_RADIUS_MOD, (int32)((((float)m_tickNumber / 60) * 0.9f + 0.1f) * 10000), NULL, true, NULL, this); + return; + // Mind Sear (target 76/16) if let m_target cast, will damage caster + case 48045: + case 53023: + // Curse of the Plaguebringer (22/15) + case 29213: + case 54835: + caster->CastSpell(m_target, trigger_spell_id, true, NULL, this); return; - } } } - if(!GetSpellMaxRange(sSpellRangeStore.LookupEntry(triggeredSpellInfo->rangeIndex))) - target = m_target; //for druid dispel poison - m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, originalCasterGUID); + + if(triggeredSpellInfo) + { + if(!caster->GetSpellMaxRangeForTarget(m_target,sSpellRangeStore.LookupEntry(triggeredSpellInfo->rangeIndex))) + target = m_target; //for druid dispel poison + m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, GetCasterGUID()); + } + else if(target->GetTypeId()!=TYPEID_UNIT || !Script->EffectDummyCreature(caster, GetId(), GetEffIndex(), (Creature*)target)) + sLog.outError("AuraEffect::TriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",GetId(),GetEffIndex()); } -Unit* Aura::GetTriggerTarget() const +Unit* AuraEffect::GetTriggerTarget() const { - Unit* target = ObjectAccessor::GetUnit(*m_target, - /*m_target->GetTypeId()==TYPEID_PLAYER ? - ((Player*)m_target)->GetSelection() :*/ - m_target->GetUInt64Value(UNIT_FIELD_TARGET)); + Unit* target = ObjectAccessor::GetUnit(*m_target, m_target->GetUInt64Value(UNIT_FIELD_TARGET)); return target ? target : m_target; } +void AuraEffect::TriggerSpellWithValue() +{ + Unit* caster = GetCaster(); + Unit* target = GetTriggerTarget(); + + if(!caster || !target) + return; + + // generic casting code with custom spells and target/caster customs + uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; + int32 basepoints0 = this->GetAmount(); + + caster->CastCustomSpell(target, trigger_spell_id, &basepoints0, 0, 0, true, 0, this); +} + /*********************************************************/ /*** AURA EFFECTS ***/ /*********************************************************/ -void Aura::HandleAuraDummy(bool apply, bool Real) +void AuraEffect::HandleAuraDummy(bool apply, bool Real, bool changeAmount) { - // spells required only Real aura add/remove - if(!Real) - return; - Unit* caster = GetCaster(); + // spells required only Real aura add/remove + if (Real) + { // AT APPLY if(apply) { switch(GetId()) { + // Haunting Spirits - perdiodic trigger demon + case 7057: + m_isPeriodic = true; + m_amplitude = irand (0, 60) + 30; + m_amplitude *= IN_MILISECONDS; + return; case 1515: // Tame beast // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness if( caster && m_target->CanHaveThreatList()) @@ -1890,13 +2413,50 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if(caster) caster->CastSpell(caster,13138,true,NULL,this); return; + case 34026: // kill command + { + Unit * pet = m_target->GetGuardianPet(); + if (!pet) + return; + + m_target->CastSpell(m_target,34027,true,NULL,this); + + // set 3 stacks and 3 charges (to make all auras not disappear at once) + Aura* owner_aura = m_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->SetAuraCharges(0); + pet_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount); + } + return; + } + case 55198: // Tidal Force + { + m_target->CastSpell(m_target,55166,true,NULL,this); + // set 3 stacks and 3 charges (to make all auras not disappear at once) + Aura* owner_aura = m_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 + GetParentAura()->SetAuraDuration(owner_aura->GetAuraDuration()); + // Make aura be not charged-this prevents removing charge on not crit spells + owner_aura->SetAuraCharges(0); + owner_aura->SetStackAmount(owner_aura->GetSpellProto()->StackAmount); + } + return; + } case 39850: // Rocket Blast if(roll_chance_i(20)) // backfire stun m_target->CastSpell(m_target, 51581, true, NULL, this); return; case 43873: // Headless Horseman Laugh - if(caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)caster)->SendPlaySound(11965, false); + m_target->PlayDistanceSound(11965); return; case 46354: // Blood Elf Illusion if(caster) @@ -1918,27 +2478,33 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if(m_target->GetTypeId()==TYPEID_PLAYER) ((Player*)m_target)->RemoveAmmo(); // not use ammo and not allow use return; + case 52916: // Honor Among Thieves + if (Unit * target = ObjectAccessor::GetUnit(*m_target, m_target->GetUInt64Value(UNIT_FIELD_TARGET))) + m_target->CastSpell(target, 51699, true); + return; } // Earth Shield - if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL)) + if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags[1] & 0x400)) { // prevent double apply bonuses if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) - m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); + m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_amount, SPELL_DIRECT_DAMAGE); return; } + //Druid, Survival Instincts + if(GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID && GetSpellProto()->SpellFamilyFlags[2]& 0x40 ) + { + if(!m_target) + return; + + int32 bp0 = int32(m_target->GetMaxHealth() * m_amount / 100); + m_target->CastCustomSpell(m_target, 50322, &bp0, NULL, NULL, true); + } } // AT REMOVE else { - if( m_target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->Effect[0]==72 ) - { - // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425 - ((Player*)m_target)->ClearFarsight(); - return; - } - if( (IsQuestTameSpell(GetId())) && caster && caster->isAlive() && m_target->isAlive()) { uint32 finalSpelId = 0; @@ -1969,30 +2535,57 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; } - // Waiting to Resurrect - if(GetId()==2584) - { - // Waiting to resurrect spell cancel, we must remove player from resurrect queue - if(m_target->GetTypeId() == TYPEID_PLAYER) - if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) - bg->RemovePlayerFromResurrectQueue(m_target->GetGUID()); - return; - } - - // Burning Winds - if(GetId()==46308) // casted only at creatures at spawn - { - m_target->CastSpell(m_target,47287,true,NULL,this); - return; - } - - // Misdirection - if(GetId()==34477) + switch(m_spellProto->SpellFamilyName) { - m_target->SetReducedThreatPercent(0, 0); - return; + case SPELLFAMILY_GENERIC: + switch(GetId()) + { + case 2584: // Waiting to Resurrect + // Waiting to resurrect spell cancel, we must remove player from resurrect queue + if(m_target->GetTypeId() == TYPEID_PLAYER) + if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) + bg->RemovePlayerFromResurrectQueue(m_target->GetGUID()); + return; + case 42783: // Wrath of the Astromancer + m_target->CastSpell(m_target,m_amount,true,NULL,this); + return; + case 46308: // Burning Winds casted only at creatures at spawn + m_target->CastSpell(m_target,47287,true,NULL,this); + return; + } + break; + case SPELLFAMILY_WARLOCK: + // Haunt + if(m_spellProto->SpellFamilyFlags[1] & 0x40000) + { + int32 bp0 = GetParentAura()->GetProcDamage() * m_amount / 100; + if(caster) + caster->CastCustomSpell(caster, 48210, &bp0, 0, 0, true, NULL, this); + return; + } + break; + case SPELLFAMILY_MAGE: + // Living Bomb + if(m_spellProto->SpellFamilyFlags[1] & 0x20000) + { + if(caster && (GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL || GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)) + caster->CastSpell(m_target, GetAmount(), true); + return; + } + break; + case SPELLFAMILY_HUNTER: + // Misdirection + if(GetId()==34477) + { + m_target->SetReducedThreatPercent(0, 0); + return; + } + break; + default: + break; } } + } // AT APPLY & REMOVE @@ -2000,105 +2593,209 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { case SPELLFAMILY_GENERIC: { - // Unstable Power - if( GetId()==24658 ) + if (!Real) + break; + switch(GetId()) { - uint32 spellId = 24659; - if (apply) + // Unstable Power + case 24658: { - const SpellEntry *spell = sSpellStore.LookupEntry(spellId); - if (!spell) + uint32 spellId = 24659; + if (apply && caster) + { + const SpellEntry *spell = sSpellStore.LookupEntry(spellId); + if (!spell) + return; + + for (int i=0; i < spell->StackAmount; ++i) + caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); return; - for (int i=0; i < spell->StackAmount; ++i) - caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); + } + m_target->RemoveAurasDueToSpell(spellId); return; } - m_target->RemoveAurasDueToSpell(spellId); - return; - } - // Restless Strength - if( GetId()==24661 ) - { - uint32 spellId = 24662; - if (apply) + // Restless Strength + case 24661: { - const SpellEntry *spell = sSpellStore.LookupEntry(spellId); - if (!spell) + uint32 spellId = 24662; + if (apply && caster) + { + const SpellEntry *spell = sSpellStore.LookupEntry(spellId); + if (!spell) + return; + for (int i=0; i < spell->StackAmount; ++i) + caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); return; - for (int i=0; i < spell->StackAmount; ++i) - caster->CastSpell(m_target, spell->Id, true, NULL, NULL, GetCasterGUID()); + } + m_target->RemoveAurasDueToSpell(spellId); return; } - m_target->RemoveAurasDueToSpell(spellId); - return; - } - // Victorious - if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR) - { - m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply); - return; - } - //Summon Fire Elemental - if (GetId() == 40133 && caster) - { - Unit *owner = caster->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER) + //Summon Fire Elemental + case 40133: { - if(apply) - owner->CastSpell(owner,8985,true); - else - ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); - } - return; - } + if (!caster) + return; - //Summon Earth Elemental - if (GetId() == 40132 && caster) - { - Unit *owner = caster->GetOwner(); - if (owner && owner->GetTypeId() == TYPEID_PLAYER) + Unit *owner = caster->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + { + if(apply) + owner->CastSpell(owner,8985,true); + else + ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + } + return; + } + //Summon Earth Elemental + case 40132 : { - if(apply) - owner->CastSpell(owner,19704,true); - else - ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + if (!caster) + return; + + Unit *owner = caster->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + { + if(apply) + owner->CastSpell(owner,19704,true); + else + ((Player*)owner)->RemovePet(NULL, PET_SAVE_NOT_IN_SLOT, true); + } + return; } - return; + // LK Intro VO (1) + case 58204: + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + // Play part 1 + if(apply) + m_target->PlayDirectSound(14970, (Player *)m_target); + // continue in 58205 + else + m_target->CastSpell(m_target, 58205, true); + } + return; + // LK Intro VO (2) + case 58205: + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + // Play part 2 + if(apply) + m_target->PlayDirectSound(14971, (Player *)m_target); + // Play part 3 + else + m_target->PlayDirectSound(14972, (Player *)m_target); + } + return; } break; } case SPELLFAMILY_MAGE: { - // Hypothermia - if( GetId()==41425 ) + //if (!Real) + //break; + break; + } + case SPELLFAMILY_PRIEST: + { + if (!Real && !changeAmount) + break; + // Pain and Suffering + if( m_spellProto->SpellIconID == 2874 && m_target->GetTypeId()==TYPEID_PLAYER ) { - m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply); + if(apply) + { + // Reduce backfire damage (dot damage) from Shadow Word: Death + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_DOT; + mod->value = m_amount; + mod->type = SPELLMOD_PCT; + mod->spellId = GetId(); + mod->mask[1] = 0x00002000; + m_spellmod = mod; + } + ((Player*)m_target)->AddSpellMod(m_spellmod, apply); return; } break; } case SPELLFAMILY_DRUID: { + if (!Real && !changeAmount) + break; + switch(GetId()) + { + case 34246: // Idol of the Emerald Queen + case 60779: // Idol of Lush Moss + { + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + { + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_DOT; + mod->value = m_amount/7; + mod->type = SPELLMOD_FLAT; + mod->spellId = GetId(); + mod->mask[1] = 0x0010; + + m_spellmod = mod; + } + + ((Player*)m_target)->AddSpellMod(m_spellmod, apply); + return; + } + case 61336: // Survival Instincts + { + if (!Real) + break; + if(apply) + { + if (!m_target->IsInFeralForm()) + return; + + int32 bp0 = int32(m_target->GetMaxHealth() * m_amount / 100); + m_target->CastCustomSpell(m_target, 50322, &bp0, NULL, NULL, true); + } + else + m_target-> RemoveAurasDueToSpell(50322); + return; + } + } // Lifebloom - if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL ) + if ( GetSpellProto()->SpellFamilyFlags[1] & 0x10 ) { if ( apply ) { if ( caster ) // prevent double apply bonuses if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) - m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); + m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_amount, SPELL_DIRECT_DAMAGE); } - // Do final heal for real !apply - else if (Real) + else { - if (GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) + // Final heal only on dispelled or duration end + if (GetParentAura()->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE && GetParentAura()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + return; + + // final heal + if(m_target->IsInWorld()) + m_target->CastCustomSpell(m_target,33778,&m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + + /*// have a look if there is still some other Lifebloom dummy aura + Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); ++itr) + if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && + (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL) + return; + + // final heal + if(m_target->IsInWorld() && m_stackAmount > 0) { - // final heal - if(m_target->IsInWorld()) - m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); - } + int32 amount = m_amount / m_stackAmount; + m_target->CastCustomSpell(m_target,33778,&amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + }*/ } return; } @@ -2109,50 +2806,27 @@ void Aura::HandleAuraDummy(bool apply, bool Real) ((Player*)m_target)->UpdateAttackPowerAndDamage(); return; } - // Idol of the Emerald Queen - if ( GetId() == 34246 && m_target->GetTypeId()==TYPEID_PLAYER ) - { - if(apply) - { - SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_DOT; - mod->value = m_modifier.m_amount/7; - mod->type = SPELLMOD_FLAT; - mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - mod->mask = 0x001000000000LL; - mod->charges = 0; - - m_spellmod = mod; - } - - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); - return; - } break; } case SPELLFAMILY_HUNTER: { - // Improved Aspect of the Viper - if( GetId()==38390 && m_target->GetTypeId()==TYPEID_PLAYER ) + if (!Real) + break; + // Glyph of Aspect of the Monkey + if(m_spellProto->Id==56833) { if(apply) { - // + effect value for Aspect of the Viper SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_EFFECT1; - mod->value = m_modifier.m_amount; + mod->op = SPELLMOD_CHANCE_OF_SUCCESS; + mod->value = 100; mod->type = SPELLMOD_FLAT; mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - mod->mask = 0x4000000000000LL; - mod->charges = 0; - + mod->mask[2] = 8192; + mod->mask[1] = 0x00000000; + mod->mask[0] = 524288; m_spellmod = mod; } - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); return; } @@ -2160,6 +2834,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } case SPELLFAMILY_SHAMAN: { + if (!Real && !changeAmount) + break; // Improved Weapon Totems if( GetSpellProto()->SpellIconID == 57 && m_target->GetTypeId()==TYPEID_PLAYER ) { @@ -2167,21 +2843,18 @@ void Aura::HandleAuraDummy(bool apply, bool Real) { SpellModifier *mod = new SpellModifier; mod->op = SPELLMOD_EFFECT1; - mod->value = m_modifier.m_amount; + mod->value = m_amount; mod->type = SPELLMOD_PCT; mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; switch (m_effIndex) { case 0: - mod->mask = 0x00200000000LL; // Windfury Totem + mod->mask[1] = 0x002; // Windfury Totem break; case 1: - mod->mask = 0x00400000000LL; // Flametongue Totem + mod->mask[1] = 0x004; // Flametongue Totem break; } - mod->charges = 0; m_spellmod = mod; } @@ -2189,16 +2862,17 @@ void Aura::HandleAuraDummy(bool apply, bool Real) ((Player*)m_target)->AddSpellMod(m_spellmod, apply); return; } - + if (!Real) + break; // Sentry Totem if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER) { if (apply) { - uint64 guid = caster->m_TotemSlot[3]; + uint64 guid = caster->m_SummonSlot[3]; if (guid) { - Creature *totem = ObjectAccessor::GetCreature(*caster, guid); + Creature *totem = caster->GetMap()->GetCreature(guid); if (totem && totem->isTotem()) ((Player*)caster)->CastSpell(totem, 6277, true); } @@ -2211,54 +2885,44 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } } - // pet auras - if(PetAura const* petSpell = spellmgr.GetPetAura(GetId())) - { - if(apply) - m_target->AddPetAura(petSpell); - else - m_target->RemovePetAura(petSpell); - return; - } -} - -void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - SpellEntry const*spell = GetSpellProto(); - switch( spell->SpellFamilyName) + if (Real) { - case SPELLFAMILY_ROGUE: + // pet auras + if(PetAura const* petSpell = spellmgr.GetPetAura(GetId())) { - // Master of Subtlety - if (spell->Id==31666 && !apply && Real) - { - m_target->RemoveAurasDueToSpell(31665); - break; - } - break; + if(apply) + m_target->AddPetAura(petSpell); + else + m_target->RemovePetAura(petSpell); + return; } - case SPELLFAMILY_HUNTER: + + if(GetEffIndex()==0 && m_target->GetTypeId()==TYPEID_PLAYER) { - // Aspect of the Viper - if (spell->SpellFamilyFlags&0x0004000000000000LL) + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); + if(saBounds.first != saBounds.second) { - // Update regen on remove - if (!apply && m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->UpdateManaRegen(); - break; + uint32 zone, area; + m_target->GetZoneAndAreaId(zone,area); + + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + { + // some auras remove at aura remove + if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area)) + m_target->RemoveAurasDueToSpell(itr->second->spellId); + // some auras applied at aura apply + else if(itr->second->autocast) + { + if( !m_target->HasAuraEffect(itr->second->spellId,0) ) + m_target->CastSpell(m_target,itr->second->spellId,true); + } + } } - break; } } - - m_isPeriodic = apply; } -void Aura::HandleAuraMounted(bool apply, bool Real) +void AuraEffect::HandleAuraMounted(bool apply, bool Real, bool /*changeAmount*/) { // only at real add/remove aura if(!Real) @@ -2266,10 +2930,10 @@ void Aura::HandleAuraMounted(bool apply, bool Real) if(apply) { - CreatureInfo const* ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue); + CreatureInfo const* ci = objmgr.GetCreatureTemplate(GetMiscValue()); if(!ci) { - sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)", m_modifier.m_miscvalue); + sLog.outErrorDb("AuraMounted: `creature_template`='%u' not found in database (only need it modelid)",GetMiscValue()); return; } @@ -2282,6 +2946,11 @@ void Aura::HandleAuraMounted(bool apply, bool Real) 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; m_target->Mount(display_id); } else @@ -2290,7 +2959,7 @@ void Aura::HandleAuraMounted(bool apply, bool Real) } } -void Aura::HandleAuraWaterWalk(bool apply, bool Real) +void AuraEffect::HandleAuraWaterWalk(bool apply, bool Real, bool /*changeAmount*/) { // only at real add/remove aura if(!Real) @@ -2306,7 +2975,7 @@ void Aura::HandleAuraWaterWalk(bool apply, bool Real) m_target->SendMessageToSet(&data,true); } -void Aura::HandleAuraFeatherFall(bool apply, bool Real) +void AuraEffect::HandleAuraFeatherFall(bool apply, bool Real, bool /*changeAmount*/) { // only at real add/remove aura if(!Real) @@ -2322,7 +2991,7 @@ void Aura::HandleAuraFeatherFall(bool apply, bool Real) m_target->SendMessageToSet(&data,true); } -void Aura::HandleAuraHover(bool apply, bool Real) +void AuraEffect::HandleAuraHover(bool apply, bool Real, bool /*changeAmount*/) { // only at real add/remove aura if(!Real) @@ -2338,31 +3007,21 @@ void Aura::HandleAuraHover(bool apply, bool Real) m_target->SendMessageToSet(&data,true); } -void Aura::HandleWaterBreathing(bool apply, bool Real) +void AuraEffect::HandleWaterBreathing(bool apply, bool Real, bool /*changeAmount*/) { - if(apply) - m_target->waterbreath = true; - else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty()) - { - m_target->waterbreath = false; - - // update for enable timer in case not moving target - if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld()) - { - ((Player*)m_target)->UpdateUnderwaterState(m_target->GetMap(),m_target->GetPositionX(),m_target->GetPositionY(),m_target->GetPositionZ()); - ((Player*)m_target)->HandleDrowning(); - } - } + // update timers in client + if(m_target->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_target)->UpdateMirrorTimers(); } -void Aura::HandleAuraModShapeshift(bool apply, bool Real) +void AuraEffect::HandleAuraModShapeshift(bool apply, bool Real, bool changeAmount) { - if(!Real) + if(!Real && !changeAmount) return; uint32 modelid = 0; Powers PowerType = POWER_MANA; - ShapeshiftForm form = ShapeshiftForm(m_modifier.m_miscvalue); + ShapeshiftForm form = ShapeshiftForm(GetMiscValue()); switch(form) { case FORM_CAT: @@ -2389,8 +3048,8 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) PowerType = POWER_RAGE; break; case FORM_GHOUL: - if(Player::TeamForRace(m_target->getRace())==ALLIANCE) - modelid = 10045; + modelid = 24994; + PowerType = POWER_ENERGY; break; case FORM_DIREBEAR: if(Player::TeamForRace(m_target->getRace())==ALLIANCE) @@ -2423,6 +3082,9 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) else modelid = 21244; break; + case FORM_METAMORPHOSIS: + modelid = 25277; + break; case FORM_AMBIENT: case FORM_SHADOW: case FORM_STEALTH: @@ -2439,7 +3101,7 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) modelid = 16031; break; default: - sLog.outError("Auras: Unknown Shapeshift Type: %u", m_modifier.m_miscvalue); + sLog.outError("Auras: Unknown Shapeshift Type: %u", GetMiscValue()); } // remove polymorph before changing display id to keep new display id @@ -2469,7 +3131,7 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) { // remove other shapeshift before applying a new one if(m_target->m_ShapeShiftFormSpellId) - m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId,this); + m_target->RemoveAurasDueToSpell(m_target->m_ShapeShiftFormSpellId); m_target->SetByteValue(UNIT_FIELD_BYTES_2, 3, form); @@ -2489,22 +3151,22 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) case FORM_DIREBEAR: { // get furor proc chance - uint32 FurorChance = 0; - Unit::AuraList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i) + int32 FurorChance = 0; + Unit::AuraEffectList const& mDummy = m_target->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraEffectList::const_iterator i = mDummy.begin(); i != mDummy.end(); ++i) { if ((*i)->GetSpellProto()->SpellIconID == 238) { - FurorChance = (*i)->GetModifier()->m_amount; + FurorChance = (*i)->GetAmount(); break; } } - if (m_modifier.m_miscvalue == FORM_CAT) + if (GetMiscValue() == FORM_CAT) { m_target->SetPower(POWER_ENERGY,0); if(urand(1,100) <= FurorChance) - m_target->CastSpell(m_target,17099,true,NULL,this); + m_target->CastCustomSpell(m_target,17099,&FurorChance, NULL, NULL,true,NULL,this); } else { @@ -2560,18 +3222,16 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) case FORM_BEAR: case FORM_DIREBEAR: case FORM_CAT: - { - if(Aura* dummy = m_target->GetDummyAura(37315) ) + if(AuraEffect* dummy = m_target->GetDummyAura(37315) ) m_target->CastSpell(m_target,37316,true,NULL,dummy); break; - } // Nordrassil Regalia - bonus case FORM_MOONKIN: - { - if(Aura* dummy = m_target->GetDummyAura(37324) ) + if(AuraEffect* dummy = m_target->GetDummyAura(37324) ) m_target->CastSpell(m_target,37325,true,NULL,dummy); break; - } + default: + break; } } @@ -2581,20 +3241,55 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) if(m_target->GetTypeId()==TYPEID_PLAYER) ((Player*)m_target)->InitDataForForm(); + + if(m_target->getClass() == CLASS_DRUID) + { + if(form == FORM_CAT && apply) // add dash if in cat-from + { + Unit::AuraMap & auras = m_target->GetAuras(); + for (Unit::AuraMap::iterator iter = auras.begin(); iter != auras.end();++iter) + { + Aura * aur = iter->second; + if (aur->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID && aur->GetSpellProto()->SpellFamilyFlags[2] & 0x8) + { + m_target->HandleAuraEffect(aur->GetPartAura(0), true); + } + } + } + else // remove dash effect(not buff) if out of cat-from + { + if(AuraEffect * aurEff =m_target->GetAura(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8)) + m_target->HandleAuraEffect(aurEff, false); + } + } + if (m_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) + ((Player*)m_target)->AddTemporarySpell(shapeInfo->stanceSpell[i]); + else + ((Player*)m_target)->RemoveTemporarySpell(shapeInfo->stanceSpell[i]); + } + } } -void Aura::HandleAuraTransform(bool apply, bool Real) +void AuraEffect::HandleAuraTransform(bool apply, bool Real, bool /*changeAmount*/) { if (apply) { // special case (spell specific functionality) - if(m_modifier.m_miscvalue==0) + if(GetMiscValue()==0) { // player applied only - if(m_target->GetTypeId()!=TYPEID_PLAYER) + if (m_target->GetTypeId()!=TYPEID_PLAYER) return; - switch(GetId()) + switch (GetId()) { // Orb of Deception case 16739: @@ -2653,12 +3348,12 @@ void Aura::HandleAuraTransform(bool apply, bool Real) } else { - CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_modifier.m_miscvalue); + CreatureInfo const * ci = objmgr.GetCreatureTemplate(GetMiscValue()); if(!ci) { //pig pink ^_^ m_target->SetDisplayId(16358); - sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", m_modifier.m_miscvalue, GetId()); + sLog.outError("Auras: unknown creature id = %d (only need its modelid) Form Spell Aura Transform in Spell ID = %d", GetMiscValue(), GetId()); } else { @@ -2667,41 +3362,44 @@ void Aura::HandleAuraTransform(bool apply, bool Real) m_target->SetDisplayId(modelid); // Dragonmaw Illusion (set mount model also) - if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED).empty()) + if(GetId()==42016 && m_target->GetMountID() && !m_target->GetAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED).empty()) m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); } - m_target->setTransForm(GetId()); } + // update active transform spell only not set or not overwriting negative by positive case + if (!m_target->getTransForm() || !IsPositiveSpell(GetId()) || IsPositiveSpell(m_target->getTransForm())) + m_target->setTransForm(GetId()); + // polymorph case - if( Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed()) + if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_target->IsPolymorphed()) { // for players, start regeneration after 1s (in polymorph fast regeneration case) // only if caster is Player (after patch 2.4.2) - if(IS_PLAYER_GUID(GetCasterGUID()) ) - ((Player*)m_target)->setRegenTimer(1000); + if (IS_PLAYER_GUID(GetCasterGUID()) ) + ((Player*)m_target)->setRegenTimer(1*IN_MILISECONDS); //dismount polymorphed target (after patch 2.4.2) if (m_target->IsMounted()) - m_target->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + m_target->RemoveAurasByType(SPELL_AURA_MOUNTED); } } else { - Unit::AuraList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM); - if(otherTransforms.empty()) - { - m_target->SetDisplayId(m_target->GetNativeDisplayId()); - m_target->setTransForm(0); - } - else + // ApplyModifier(true) will reapply it if need + m_target->setTransForm(0); + m_target->SetDisplayId(m_target->GetNativeDisplayId()); + + // re-aplly some from still active with preference negative cases + Unit::AuraEffectList const& otherTransforms = m_target->GetAurasByType(SPELL_AURA_TRANSFORM); + if (!otherTransforms.empty()) { // look for other transform auras - Aura* handledAura = *otherTransforms.begin(); - for(Unit::AuraList::const_iterator i = otherTransforms.begin();i != otherTransforms.end(); ++i) + 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)) + if (!IsPositiveSpell((*i)->GetSpellProto()->Id)) { handledAura = *i; break; @@ -2711,11 +3409,11 @@ void Aura::HandleAuraTransform(bool apply, bool Real) } // Dragonmaw Illusion (restore mount model) - if(GetId()==42016 && m_target->GetMountID()==16314) + if (GetId()==42016 && m_target->GetMountID()==16314) { - if(!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty()) + if (!m_target->GetAurasByType(SPELL_AURA_MOUNTED).empty()) { - uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetModifier()->m_miscvalue; + uint32 cr_id = m_target->GetAurasByType(SPELL_AURA_MOUNTED).front()->GetMiscValue(); if(CreatureInfo const* ci = objmgr.GetCreatureTemplate(cr_id)) { uint32 team = 0; @@ -2734,54 +3432,42 @@ void Aura::HandleAuraTransform(bool apply, bool Real) } } -void Aura::HandleForceReaction(bool apply, bool Real) +void AuraEffect::HandleForceReaction(bool apply, bool Real, bool changeAmount) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; - if(!Real) + if(!Real && !changeAmount) return; Player* player = (Player*)m_target; - uint32 faction_id = m_modifier.m_miscvalue; - uint32 faction_rank = m_modifier.m_amount; + uint32 faction_id = GetMiscValue(); + uint32 faction_rank = m_amount; - if(apply) - player->m_forcedReactions[faction_id] = ReputationRank(faction_rank); - else - player->m_forcedReactions.erase(faction_id); - - WorldPacket data; - data.Initialize(SMSG_SET_FORCED_REACTIONS, 4+player->m_forcedReactions.size()*(4+4)); - data << uint32(player->m_forcedReactions.size()); - for(ForcedReactions::const_iterator itr = player->m_forcedReactions.begin(); itr != player->m_forcedReactions.end(); ++itr) - { - data << uint32(itr->first); // faction_id (Faction.dbc) - data << uint32(itr->second); // reputation rank - } - player->SendDirectMessage(&data); + player->GetReputationMgr().ApplyForceReaction(faction_id,ReputationRank(faction_rank),apply); + player->GetReputationMgr().SendForceReactions(); } -void Aura::HandleAuraModSkill(bool apply, bool Real) +void AuraEffect::HandleAuraModSkill(bool apply, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex]; - int32 points = GetModifierValue(); + int32 points = m_amount; - ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT); + ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_auraName==SPELL_AURA_MOD_SKILL_TALENT); if(prot == SKILL_DEFENSE) ((Player*)m_target)->UpdateDefenseBonusesMod(); } -void Aura::HandleChannelDeathItem(bool apply, bool Real) +void AuraEffect::HandleChannelDeathItem(bool apply, bool Real, bool /*changeAmount*/) { if(Real && !apply) { Unit* caster = GetCaster(); - Unit* victim = GetTarget(); + Unit* victim = m_target; if(!caster || caster->GetTypeId() != TYPEID_PLAYER || !victim)// || m_removeMode!=AURA_REMOVE_BY_DEATH) return; @@ -2789,6 +3475,9 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real) //talent will remove the caster's aura->interrupt channel->remove victim aura if(victim->GetHealth() > 0) return; + // Item amount + if (m_amount <= 0) + return; SpellEntry const *spellInfo = GetSpellProto(); if(spellInfo->EffectItemType[m_effIndex] == 0) @@ -2799,100 +3488,157 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real) (victim->getLevel() <= Trinity::XP::GetGrayLevel(caster->getLevel()) || victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) ) return; + //Adding items + uint32 noSpaceForCount = 0; + uint32 count = m_amount; + ItemPosCountVec dest; - uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 ); + uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], count, &noSpaceForCount); if( msg != EQUIP_ERR_OK ) { + count-=noSpaceForCount; ((Player*)caster)->SendEquipError( msg, NULL, NULL ); - return; + if (count==0) + return; } Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true); - ((Player*)caster)->SendNewItem(newitem, 1, true, false); + ((Player*)caster)->SendNewItem(newitem, count, true, false); } } -void Aura::HandleBindSight(bool apply, bool Real) +void AuraEffect::HandleBindSight(bool apply, bool Real, bool /*changeAmount*/) { + if (!Real) + return; Unit* caster = GetCaster(); if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - if (apply) - m_target->AddPlayerToVision((Player*)caster); - else - m_target->RemovePlayerFromVision((Player*)caster); + ((Player*)caster)->SetViewpoint(m_target, apply); } -void Aura::HandleFarSight(bool apply, bool Real) +void AuraEffect::HandleFarSight(bool apply, bool Real, bool /*changeAmount*/) { - Unit* caster = GetCaster(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); + //Handled by client } -void Aura::HandleAuraTrackCreatures(bool apply, bool Real) +void AuraEffect::HandleAuraTrackCreatures(bool apply, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; - if(apply) - m_target->RemoveNoStackAurasDueToAura(this); - m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1) : 0 ); + m_target->SetUInt32Value(PLAYER_TRACK_CREATURES, apply ? ((uint32)1)<<(GetMiscValue()-1) : 0 ); } -void Aura::HandleAuraTrackResources(bool apply, bool Real) +void AuraEffect::HandleAuraTrackResources(bool apply, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; - if(apply) - m_target->RemoveNoStackAurasDueToAura(this); - m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(m_modifier.m_miscvalue-1): 0 ); + m_target->SetUInt32Value(PLAYER_TRACK_RESOURCES, apply ? ((uint32)1)<<(GetMiscValue()-1): 0 ); } -void Aura::HandleAuraTrackStealthed(bool apply, bool Real) +void AuraEffect::HandleAuraTrackStealthed(bool apply, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; - if(apply) - m_target->RemoveNoStackAurasDueToAura(this); - m_target->ApplyModFlag(PLAYER_FIELD_BYTES,PLAYER_FIELD_BYTE_TRACK_STEALTHED,apply); } -void Aura::HandleAuraModScale(bool apply, bool Real) +void AuraEffect::HandleAuraModScale(bool apply, bool Real, bool /*changeAmount*/) { - m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,GetModifierValue(),apply); + m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_amount,apply); } -void Aura::HandleModPossess(bool apply, bool Real) +/*void AuraEffect::HandleModPossess(bool apply, bool Real) { if(!Real) return; + if(m_target->getLevel() > m_amount) + return; + + // not possess yourself + if(GetCasterGUID() == m_target->GetGUID()) + return; + Unit* caster = GetCaster(); - if(caster && caster->GetTypeId() == TYPEID_UNIT) - { - HandleModCharm(apply, Real); + if(!caster) return; - } - if(apply) + if( apply ) { - if(m_target->getLevel() > m_modifier.m_amount) - return; + m_target->SetCharmerGUID(GetCasterGUID()); + m_target->setFaction(caster->getFaction()); + + caster->SetCharm(m_target); + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)caster)->SetFarSightGUID(m_target->GetGUID()); + ((Player*)caster)->SetClientControl(m_target, 1); + } + + m_target->CombatStop(); + m_target->DeleteThreatList(); + if(m_target->GetTypeId() == TYPEID_UNIT) + { + m_target->StopMoving(); + m_target->GetMotionMaster()->Clear(); + m_target->GetMotionMaster()->MoveIdle(); + } + else if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->SetClientControl(m_target, 0); + } - m_target->SetCharmedOrPossessedBy(caster, true); + if(CharmInfo *charmInfo = m_target->InitCharmInfo(m_target)) + charmInfo->InitPossessCreateSpells(); + + if(caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)caster)->PossessSpellInitialize(); } else - m_target->RemoveCharmedOrPossessedBy(caster); + { + m_target->SetCharmerGUID(0); + caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now + + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->setFactionForRace(m_target->getRace()); + ((Player*)m_target)->SetClientControl(m_target, 1); + } + else if(m_target->GetTypeId() == TYPEID_UNIT) + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + m_target->setFaction(cinfo->faction_A); + } + + caster->SetCharm(NULL); + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)caster)->SetFarSightGUID(0); + ((Player*)caster)->SetClientControl(m_target,0); + + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + ((Player*)caster)->GetSession()->SendPacket(&data); + } + + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackedBy(caster); + } + } } -void Aura::HandleModPossessPet(bool apply, bool Real) +void AuraEffect::HandleModPossessPet(bool apply, bool Real) { if(!Real) return; @@ -2901,46 +3647,157 @@ void Aura::HandleModPossessPet(bool apply, bool Real) if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; + Pet *pet = caster->GetGuardianPet(); + if(!pet || pet != m_target) + return; + if(apply) - { - if(caster->GetPet() != m_target) - return; + pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + else + pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); - m_target->SetCharmedOrPossessedBy(caster, true); + ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : 0); + ((Player*)caster)->SetCharm(apply ? pet : NULL); + ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); + + if(apply) + { + pet->StopMoving(); + pet->GetMotionMaster()->Clear(); + pet->GetMotionMaster()->MoveIdle(); } else { - m_target->RemoveCharmedOrPossessedBy(caster); - - // Reinitialize the pet bar and make the pet come back to the owner - ((Player*)caster)->PetSpellInitialize(); - if(!m_target->getVictim()) - { - m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); - } + pet->AttackStop(); + pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + pet->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); } +}*/ + +void AuraEffect::HandleAuraModPetTalentsPoints(bool Apply, bool Real, bool changeAmount) +{ + if(!Real && !changeAmount) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + // Recalculate pet tlaent points + if (Pet *pet = ((Player*)m_target)->GetPet()) + pet->InitTalentForLevel(); } -void Aura::HandleModCharm(bool apply, bool Real) +/*void AuraEffect::HandleModCharm(bool apply, bool Real) { if(!Real) return; + // not charm yourself + if(GetCasterGUID() == m_target->GetGUID()) + return; + Unit* caster = GetCaster(); + if(!caster) + return; - if(apply) + if(int32(m_target->getLevel()) <= m_amount) { - if(int32(m_target->getLevel()) > m_modifier.m_amount) - return; + if( apply ) + { + m_target->SetCharmerGUID(GetCasterGUID()); + m_target->setFaction(caster->getFaction()); + m_target->CastStop(m_target == caster ? GetId() : 0); + caster->SetCharm(m_target); + + m_target->CombatStop(); + m_target->DeleteThreatList(); - m_target->SetCharmedOrPossessedBy(caster, false); + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + CharmInfo *charmInfo = m_target->InitCharmInfo(m_target); + charmInfo->InitCharmCreateSpells(); + charmInfo->SetReactState( REACT_DEFENSIVE ); + + if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK) + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) + { + //does not appear to have relevance. Why code added initially? See note below at !apply + //to prevent client crash + //m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); + //just to enable stat window + charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); + //if charmed two demons the same session, the 2nd gets the 1st one's name + m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); + } + } + } + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)caster)->CharmSpellInitialize(); + } + } + else + { + m_target->SetCharmerGUID(0); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->setFactionForRace(m_target->getRace()); + else + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + + // restore faction + if(((Creature*)m_target)->isPet()) + { + if(Unit* owner = m_target->GetOwner()) + m_target->setFaction(owner->getFaction()); + else if(cinfo) + m_target->setFaction(cinfo->faction_A); + } + else if(cinfo) // normal creature + m_target->setFaction(cinfo->faction_A); + + // restore UNIT_FIELD_BYTES_0 + if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) + { + //does not appear to have relevance. Why code added initially? Class, gender, powertype should be same. + //db field removed and replaced with better way to set class, restore using this if problems + /*CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); + if(cainfo && cainfo->bytes0 != 0) + m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); + else + m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048); + + if(m_target->GetCharmInfo()) + m_target->GetCharmInfo()->SetPetNumber(0, true); + else + sLog.outError("AuraEffect::HandleModCharm: target="UI64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId()); + } + } + + caster->SetCharm(NULL); + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + ((Player*)caster)->GetSession()->SendPacket(&data); + } + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackedBy(caster); + } + } } - else - m_target->RemoveCharmedOrPossessedBy(caster); -} +}*/ -void Aura::HandleModConfuse(bool apply, bool Real) +void AuraEffect::HandleModConfuse(bool apply, bool Real, bool /*changeAmount*/) { if(!Real) return; @@ -2949,7 +3806,7 @@ void Aura::HandleModConfuse(bool apply, bool Real) m_target->SetControlled(apply, UNIT_STAT_CONFUSED); } -void Aura::HandleModFear(bool apply, bool Real) +void AuraEffect::HandleModFear(bool apply, bool Real, bool /*changeAmount*/) { if (!Real) return; @@ -2958,7 +3815,7 @@ void Aura::HandleModFear(bool apply, bool Real) m_target->SetControlled(apply, UNIT_STAT_FLEEING); } -void Aura::HandleFeignDeath(bool apply, bool Real) +void AuraEffect::HandleFeignDeath(bool apply, bool Real, bool /*changeAmount*/) { if(!Real) return; @@ -2977,7 +3834,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_target, m_target, World::GetMaxVisibleDistance()); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_target, targets, u_check); m_target->VisitNearbyObject(World::GetMaxVisibleDistance(), searcher); for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter) { @@ -2994,7 +3851,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) } } // blizz like 2.0.x - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); // blizz like 2.0.x m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); // blizz like 2.0.x @@ -3002,10 +3859,10 @@ void Aura::HandleFeignDeath(bool apply, bool Real) m_target->addUnitState(UNIT_STAT_DIED); m_target->CombatStop(); - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); // prevent interrupt message - if(m_caster_guid==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL]) + if(GetCasterGUID()==m_target->GetGUID() && m_target->m_currentSpells[CURRENT_GENERIC_SPELL]) m_target->m_currentSpells[CURRENT_GENERIC_SPELL]->finish(); m_target->InterruptNonMeleeSpells(true); m_target->getHostilRefManager().deleteReferences(); @@ -3019,7 +3876,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) m_target->SendMessageToSet(&data,true); */ // blizz like 2.0.x - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); // blizz like 2.0.x m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); // blizz like 2.0.x @@ -3029,221 +3886,146 @@ void Aura::HandleFeignDeath(bool apply, bool Real) } } -void Aura::HandleAuraModDisarm(bool apply, bool Real) +void AuraEffect::HandleAuraModDisarm(bool apply, bool Real, bool /*changeAmount*/) { - if(!Real) + if (!Real) return; + AuraType type = AuraType(GetAuraName()); - if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM)) + //Prevent handling aura twice + if(apply ? m_target->GetAurasByType(type).size() > 1 : m_target->HasAuraType(type)) return; - // not sure for it's correctness - if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); - else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); - - if (m_target->GetTypeId() == TYPEID_PLAYER) + uint32 field, flag, slot; + WeaponAttackType attType; + switch (type) { - // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove. - if (((Player *)m_target)->IsInFeralForm()) - return; - - if (apply) - m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME); - else - ((Player *)m_target)->SetRegularAttackTime(); + 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; } - else + + if(!apply) + m_target->RemoveFlag(field, flag); + + if (m_target->GetTypeId() == TYPEID_PLAYER) { - // creature does not have equipment - if(apply && !((Creature*)m_target)->GetCurrentEquipmentId()) - return; + // 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 = ((Player*)m_target)->GetItemByPos( INVENTORY_SLOT_BAG_0, slot )) + ((Player*)m_target)->_ApplyItemMods(pItem, slot, !apply); } - m_target->UpdateDamagePhysical(BASE_ATTACK); + if(apply) + m_target->SetFlag(field, flag); + + if (m_target->GetTypeId() == TYPEID_UNIT && ((Creature*)m_target)->GetCurrentEquipmentId()) + m_target->UpdateDamagePhysical(attType); } -void Aura::HandleAuraModStun(bool apply, bool Real) +void AuraEffect::HandleModStealth(bool apply, bool Real, bool /*changeAmount*/) { if(!Real) return; - m_target->SetControlled(apply, UNIT_STAT_STUNNED); -} - -void Aura::HandleModStealth(bool apply, bool Real) -{ if(apply) { - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) - { - // drop flag at stealth in bg - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); - - // remove player from the objective's active player count at stealth - if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) - pvp->HandlePlayerActivityChanged((Player*)m_target); - } + // drop flag at stealth in bg + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - // only at real aura add - if(Real) - { - m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02); - if(m_target->GetTypeId()==TYPEID_PLAYER) - m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); - - // apply only if not in GM invisibility (and overwrite invisibility state) - if(m_target->GetVisibility()!=VISIBILITY_OFF) - { - //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); - //m_target->SetVisibility(VISIBILITY_OFF); - m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); - } + m_target->SetStandFlags(UNIT_STAND_FLAGS_CREEP); + if(m_target->GetTypeId()==TYPEID_PLAYER) + m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); - // for RACE_NIGHTELF stealth - if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) - m_target->CastSpell(m_target, 21009, true, NULL, this); - } + // apply only if not in GM invisibility (and overwrite invisibility state) + if(m_target->GetVisibility() != VISIBILITY_OFF) + m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); } - else + else if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) // if last SPELL_AURA_MOD_STEALTH { - // only at real aura remove - if(Real) - { - // for RACE_NIGHTELF stealth - if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) - m_target->RemoveAurasDueToSpell(21009); - - // if last SPELL_AURA_MOD_STEALTH and no GM invisibility - if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF) - { - m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00); - if(m_target->GetTypeId()==TYPEID_PLAYER) - m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); - - // restore invisibility if any - if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY)) - { - //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); - //m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); - m_target->SetVisibility(VISIBILITY_ON); - } - else - { - m_target->SetVisibility(VISIBILITY_ON); - if(m_target->GetTypeId() == TYPEID_PLAYER) - if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) - pvp->HandlePlayerActivityChanged((Player*)m_target); - } - } - } - } + m_target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP); + if(m_target->GetTypeId()==TYPEID_PLAYER) + m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); - // Master of Subtlety - Unit::AuraList const& mDummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 2114 && Real) - { - if (apply) - { - int32 bp = (*i)->GetModifier()->m_amount; - m_target->CastCustomSpell(m_target,31665,&bp,NULL,NULL,true); - } - else - m_target->CastSpell(m_target,31666,true); - break; - } + if(m_target->GetVisibility() != VISIBILITY_OFF) + m_target->SetVisibility(VISIBILITY_ON); } } -void Aura::HandleInvisibility(bool apply, bool Real) +void AuraEffect::HandleInvisibility(bool apply, bool Real, bool /*changeAmount*/) { if(apply) { - m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); + m_target->m_invisibilityMask |= (1 << GetMiscValue()); - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); - - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) + if(Real) { + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + // apply glow vision - m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); - // remove player from the objective's active player count at invisibility - if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) - pvp->HandlePlayerActivityChanged((Player*)m_target); - } + if(m_target->GetTypeId()==TYPEID_PLAYER) + m_target->SetFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); - // apply only if not in GM invisibility and not stealth - if(m_target->GetVisibility()==VISIBILITY_ON) - { - // Aura not added yet but visibility code expect temporary add aura - //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); - //m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); - m_target->SetVisibility(VISIBILITY_ON); + m_target->SetToNotify(); } } else { // recalculate value at modifier remove (current aura already removed) m_target->m_invisibilityMask = 0; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - m_target->m_invisibilityMask |= (1 << m_modifier.m_miscvalue); + Unit::AuraEffectList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY); + for(Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + m_target->m_invisibilityMask |= (1 << GetMiscValue()); // only at real aura remove and if not have different invisibility auras. - if(Real && m_target->m_invisibilityMask==0) + if(Real) { // remove glow vision - if(m_target->GetTypeId() == TYPEID_PLAYER) + if(!m_target->m_invisibilityMask && m_target->GetTypeId() == TYPEID_PLAYER) m_target->RemoveFlag(PLAYER_FIELD_BYTES2,PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW); - // apply only if not in GM invisibility & not stealthed while invisible - if(m_target->GetVisibility()!=VISIBILITY_OFF) - { - // if have stealth aura then already have stealth visibility - if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) - { - m_target->SetVisibility(VISIBILITY_ON); - if(m_target->GetTypeId() == TYPEID_PLAYER) - if(OutdoorPvP * pvp = ((Player*)m_target)->GetOutdoorPvP()) - pvp->HandlePlayerActivityChanged((Player*)m_target); - } - } + m_target->SetToNotify(); } } } -void Aura::HandleInvisibilityDetect(bool apply, bool Real) +void AuraEffect::HandleInvisibilityDetect(bool apply, bool Real, bool /*changeAmount*/) { if(apply) { - m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); + m_target->m_detectInvisibilityMask |= (1 << GetMiscValue()); } else { // recalculate value at modifier remove (current aura already removed) m_target->m_detectInvisibilityMask = 0; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - m_target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); + Unit::AuraEffectList const& auras = m_target->GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION); + for(Unit::AuraEffectList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) + m_target->m_detectInvisibilityMask |= (1 << GetMiscValue()); } if(Real && m_target->GetTypeId()==TYPEID_PLAYER) - //ObjectAccessor::UpdateVisibilityForPlayer((Player*)m_target); m_target->SetToNotify(); } -void Aura::HandleAuraModRoot(bool apply, bool Real) -{ - // only at real add/remove aura - if(!Real) - return; - - m_target->SetControlled(apply, UNIT_STAT_ROOT); -} - -void Aura::HandleAuraModSilence(bool apply, bool Real) +void AuraEffect::HandleAuraModSilence(bool apply, bool Real, bool /*changeAmount*/) { // only at real add/remove aura if(!Real) @@ -3254,38 +4036,8 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED); // Stop cast only spells vs PreventionType == SPELL_PREVENTION_TYPE_SILENCE for (uint32 i = CURRENT_MELEE_SPELL; i < CURRENT_MAX_SPELL;i++) - { - Spell* currentSpell = m_target->m_currentSpells[i]; - if (currentSpell && currentSpell->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) - { - uint32 state = currentSpell->getState(); - // Stop spells on prepare or casting state - if ( state == SPELL_STATE_PREPARING || state == SPELL_STATE_CASTING ) - { - currentSpell->cancel(); - } - } - } - - switch (GetId()) - { - // Arcane Torrent (Energy) - case 25046: - { - Unit * caster = GetCaster(); - if (!caster) - return; - - // Search Mana Tap auras on caster - Aura * dummy = m_target->GetDummyAura(28734); - if (dummy) - { - int32 bp = dummy->GetStackAmount() * 10; - caster->CastCustomSpell(caster, 25048, &bp, NULL, NULL, true); - m_target->RemoveAurasDueToSpell(28734); - } - } - } + if (m_target->m_currentSpells[i] && m_target->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) + m_target->InterruptSpell(i,false); // Stop spells on prepare or casting state } else { @@ -3297,10 +4049,10 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) } } -void Aura::HandleModThreat(bool apply, bool Real) +void AuraEffect::HandleModThreat(bool apply, bool Real, bool changeAmount) { // only at real add/remove aura - if(!Real) + if(!Real && !changeAmount) return; if(!m_target->isAlive()) @@ -3327,22 +4079,22 @@ void Aura::HandleModThreat(bool apply, bool Real) break; } if (level_diff > 0) - m_modifier.m_amount += multiplier * level_diff; + m_amount += multiplier * level_diff; for(int8 x=0;x < MAX_SPELL_SCHOOL;x++) { - if(m_modifier.m_miscvalue & int32(1<<x)) + if(GetMiscValue() & int32(1<<x)) { if(m_target->GetTypeId() == TYPEID_PLAYER) - ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? GetModifierValue() : -GetModifierValue(), apply); + ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_amount, apply); } } } -void Aura::HandleAuraModTotalThreat(bool apply, bool Real) +void AuraEffect::HandleAuraModTotalThreat(bool apply, bool Real, bool changeAmount) { // only at real add/remove aura - if(!Real) + if(!Real && !changeAmount) return; if(!m_target->isAlive() || m_target->GetTypeId()!= TYPEID_PLAYER) @@ -3355,14 +4107,14 @@ void Aura::HandleAuraModTotalThreat(bool apply, bool Real) float threatMod = 0.0f; if(apply) - threatMod = float(GetModifierValue()); + threatMod = float(m_amount); else - threatMod = float(-GetModifierValue()); + threatMod = float(-m_amount); m_target->getHostilRefManager().threatAssist(caster, threatMod); } -void Aura::HandleModTaunt(bool apply, bool Real) +void AuraEffect::HandleModTaunt(bool apply, bool Real, bool /*changeAmount*/) { // only at real add/remove aura if(!Real) @@ -3388,32 +4140,39 @@ void Aura::HandleModTaunt(bool apply, bool Real) /*********************************************************/ /*** MODIFY SPEED ***/ /*********************************************************/ -void Aura::HandleAuraModIncreaseSpeed(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModIncreaseSpeed(bool apply, bool Real, bool changeAmount) { // all applied/removed only at real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; + if(apply) // Dash wont work if you are not in cat form + if(m_spellProto->SpellFamilyName==SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[2] & 0x8 && m_target->m_form != FORM_CAT ) + { + m_target->HandleAuraEffect(this, false); + return; + } + m_target->UpdateSpeed(MOVE_RUN, true); } -void Aura::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModIncreaseMountedSpeed(bool /*apply*/, bool Real, bool changeAmount) { // all applied/removed only at real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; m_target->UpdateSpeed(MOVE_RUN, true); } -void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real) +void AuraEffect::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real, bool changeAmount) { // all applied/removed only at real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; // Enable Fly mode for flying mounts - if (m_modifier.m_auraname == SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) + if (m_auraName == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) { WorldPacket data; if(apply) @@ -3429,38 +4188,37 @@ void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real) m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply); // Dragonmaw Illusion (overwrite mount model, mounted aura already applied) - if( apply && m_target->HasAura(42016,0) && m_target->GetMountID()) + if( apply && m_target->HasAuraEffect(42016,0) && m_target->GetMountID()) m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); } m_target->UpdateSpeed(MOVE_FLIGHT, true); } -void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real, bool changeAmount) { // all applied/removed only at real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; m_target->UpdateSpeed(MOVE_SWIM, true); } -void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real, bool changeAmount) { // all applied/removed only at real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; - //m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); m_target->UpdateSpeed(MOVE_RUN, true); m_target->UpdateSpeed(MOVE_SWIM, true); m_target->UpdateSpeed(MOVE_FLIGHT, true); } -void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real, bool changeAmount) { // all applied/removed only at real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; m_target->UpdateSpeed(MOVE_RUN, true); @@ -3472,51 +4230,84 @@ void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real) /*** IMMUNITY ***/ /*********************************************************/ -void Aura::HandleModMechanicImmunity(bool apply, bool Real) +void AuraEffect::HandleModStateImmunityMask(bool apply, bool Real, bool /*changeAmount*/) +{ + if (!Real) + return; + 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_MOD_TAUNT); + + // 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) + { + m_target->RemoveAurasByType(SPELL_AURA_MOD_ROOT); + m_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) + { + m_target->RemoveAurasByType(*iter); + } + } + for (std::list <AuraType>::iterator iter = immunity_list.begin(); iter != immunity_list.end();++iter) + { + m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,*iter,apply); + } +} + +void AuraEffect::HandleModMechanicImmunity(bool apply, bool Real, bool /*changeAmount*/) { - uint32 mechanic = 1 << m_modifier.m_miscvalue; + if (!Real) + return; + uint32 mechanic; + mechanic = 1 << GetMiscValue(); //immune movement impairment and loss of control - if(GetId()==42292) + if(GetId()==42292 || GetId()==59752) mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; + if (!mechanic) + return; if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) { Unit::AuraMap& Auras = m_target->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) { - next = iter; - ++next; SpellEntry const *spell = iter->second->GetSpellProto(); - if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability - && !iter->second->IsPositive() // only remove negative spells - && spell->Id != GetId()) + if (spell->Id != GetId()) { //check for mechanic mask - if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic) + if(GetAllSpellMechanicMask(spell) & mechanic) { - m_target->RemoveAurasDueToSpell(spell->Id); - if(Auras.empty()) - break; - else - next = Auras.begin(); + m_target->RemoveAura(iter); } + else + ++iter; } + else + ++iter; } } - m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply); - - // special cases - switch(m_modifier.m_miscvalue) - { - case MECHANIC_INVULNERABILITY: - m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply); - break; - case MECHANIC_SHIELD: - m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply); - break; - } + m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,GetMiscValue(),apply); // Bestial Wrath if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->Id == 19574) @@ -3525,8 +4316,8 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real) if ( Unit* owner = m_target->GetOwner() ) { // Search talent - Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) + Unit::AuraEffectList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraEffectList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) { if ( (*i)->GetSpellProto()->SpellIconID == 2229 ) { @@ -3545,10 +4336,10 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real) { if(apply) { - m_target->CastSpell(m_target,24395,true); - m_target->CastSpell(m_target,24396,true); - m_target->CastSpell(m_target,24397,true); - m_target->CastSpell(m_target,26592,true); + m_target->CastSpell(m_target,24395,true, NULL, this); + m_target->CastSpell(m_target,24396,true, NULL, this); + m_target->CastSpell(m_target,24397,true, NULL, this); + m_target->CastSpell(m_target,26592,true, NULL, this); } else { @@ -3558,103 +4349,98 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real) m_target->RemoveAurasDueToSpell(26592); } } + + // Heroic Fury (remove Intercept cooldown) + else if( apply && GetId() == 60970 && m_target->GetTypeId() == TYPEID_PLAYER ) + { + ((Player*)m_target)->RemoveSpellCooldown(20252, true); + } + // Demonic Empowerment -- voidwalker -- missing movement impairing effects immunity + else if (GetId() == 54508) + { + if (apply) + m_target->RemoveMovementImpairingAuras(); + + m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,SPELL_AURA_MOD_ROOT,apply); + m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,SPELL_AURA_MOD_DECREASE_SPEED,apply); + } + // Demonic Circle + else if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellIconID == 3221) + { + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + if (apply) + { + GameObject* obj = m_target->GetGameObject(48018); + if (obj) + ((Player*)m_target)->TeleportTo(obj->GetMapId(),obj->GetPositionX(),obj->GetPositionY(),obj->GetPositionZ(),obj->GetOrientation()); + } + } } -void Aura::HandleAuraModEffectImmunity(bool apply, bool Real) +//this method is called whenever we add / remove aura which gives m_target some imunity to some spell effect +void AuraEffect::HandleAuraModEffectImmunity(bool apply, bool Real, bool /*changeAmount*/) { - if(!apply) + // when removing flag aura, handle flag drop + if( !apply && m_target->GetTypeId() == TYPEID_PLAYER + && (GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION) ) { if(m_target->GetTypeId() == TYPEID_PLAYER) { if(((Player*)m_target)->InBattleGround()) { - BattleGround *bg = ((Player*)m_target)->GetBattleGround(); - if(bg) - { - switch(bg->GetTypeID()) - { - case BATTLEGROUND_AV: - { - break; - } - case BATTLEGROUND_WS: - { - // Warsong Flag, horde // Silverwing Flag, alliance - if(GetId() == 23333 || GetId() == 23335) - bg->EventPlayerDroppedFlag(((Player*)m_target)); - break; - } - case BATTLEGROUND_AB: - { - break; - } - case BATTLEGROUND_EY: - { - if(GetId() == 34976) - bg->EventPlayerDroppedFlag(((Player*)m_target)); - break; - } - } - } + if( BattleGround *bg = ((Player*)m_target)->GetBattleGround() ) + bg->EventPlayerDroppedFlag(((Player*)m_target)); } else sOutdoorPvPMgr.HandleDropFlag((Player*)m_target,GetSpellProto()->Id); } } - m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,m_modifier.m_miscvalue,apply); + m_target->ApplySpellImmune(GetId(),IMMUNITY_EFFECT,GetMiscValue(),apply); } -void Aura::HandleAuraModStateImmunity(bool apply, bool Real) +void AuraEffect::HandleAuraModStateImmunity(bool apply, bool Real, bool /*changeAmount*/) { if(apply && Real && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) { - Unit::AuraList const& auraList = m_target->GetAurasByType(AuraType(m_modifier.m_miscvalue)); - for(Unit::AuraList::const_iterator itr = auraList.begin(); itr != auraList.end();) - { - if (auraList.front() != this) // skip itself aura (it already added) - { - m_target->RemoveAurasDueToSpell(auraList.front()->GetId()); - itr = auraList.begin(); - } - else - ++itr; - } + m_target->RemoveAurasByType(AuraType(GetMiscValue()), NULL , GetParentAura()); } - m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,m_modifier.m_miscvalue,apply); + m_target->ApplySpellImmune(GetId(),IMMUNITY_STATE,GetMiscValue(),apply); } -void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real) +void AuraEffect::HandleAuraModSchoolImmunity(bool apply, bool Real, bool /*changeAmount*/) { - if(apply && m_modifier.m_miscvalue == SPELL_SCHOOL_MASK_NORMAL) - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); + if(apply && GetMiscValue() == SPELL_SCHOOL_MASK_NORMAL) + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); - m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,m_modifier.m_miscvalue,apply); + m_target->ApplySpellImmune(GetId(),IMMUNITY_SCHOOL,GetMiscValue(),apply); - if(Real && apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) + // remove all flag auras (they are positive, but they must be removed when you are immune) + if( this->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY + && this->GetSpellProto()->AttributesEx2 & SPELL_ATTR_EX2_DAMAGE_REDUCED_SHIELD ) + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); + + // TODO: optimalize this cycle - use RemoveAurasWithInterruptFlags call or something else + if( Real && apply + && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY + && IsPositiveSpell(GetId()) ) //Only positive immunity removes auras { - if(IsPositiveSpell(GetId())) //Only positive immunity removes auras + uint32 school_mask = GetMiscValue(); + Unit::AuraMap& Auras = m_target->GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) { - uint32 school_mask = m_modifier.m_miscvalue; - Unit::AuraMap& Auras = m_target->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + SpellEntry const *spell = iter->second->GetSpellProto(); + if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask + && IsDispelableBySpell(GetSpellProto(),spell->Id, true) + && !iter->second->IsPositive() //Don't remove positive spells + && spell->Id != GetId() ) //Don't remove self { - next = iter; - ++next; - SpellEntry const *spell = iter->second->GetSpellProto(); - if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask - && !( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) //Spells unaffected by invulnerability - && !iter->second->IsPositive() //Don't remove positive spells - && spell->Id != GetId() ) //Don't remove self - { - m_target->RemoveAurasDueToSpell(spell->Id); - if(Auras.empty()) - break; - else - next = Auras.begin(); - } + m_target->RemoveAura(iter); } + else + ++iter; } } if( Real && GetSpellProto()->Mechanic == MECHANIC_BANISH ) @@ -3666,40 +4452,43 @@ void Aura::HandleAuraModSchoolImmunity(bool apply, bool Real) } } -void Aura::HandleAuraModDmgImmunity(bool apply, bool Real) +void AuraEffect::HandleAuraModDmgImmunity(bool apply, bool Real, bool /*changeAmount*/) { - m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,m_modifier.m_miscvalue,apply); + m_target->ApplySpellImmune(GetId(),IMMUNITY_DAMAGE,GetMiscValue(),apply); } -void Aura::HandleAuraModDispelImmunity(bool apply, bool Real) +void AuraEffect::HandleAuraModDispelImmunity(bool apply, bool Real, bool /*changeAmount*/) { // all applied/removed only at real aura add/remove if(!Real) return; - m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(m_modifier.m_miscvalue), apply); + m_target->ApplySpellDispelImmunity(m_spellProto, DispelType(GetMiscValue()), apply); } -void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real) +void AuraEffect::HandleAuraProcTriggerSpell(bool apply, bool Real, bool /*changeAmount*/) { if(!Real) return; - - if(apply) + // Elemental oath - "while Clearcasting from Elemental Focus is active, you deal 5%/10% more spell damage." + if (m_target->GetTypeId()==TYPEID_PLAYER && (GetId() == 51466 || GetId() == 51470)) { - // some spell have charges by functionality not have its in spell data - switch (GetId()) + if (apply) { - case 28200: // Ascendance (Talisman of Ascendance trinket) - m_procCharges = 6; - UpdateAuraCharges(); - break; - default: break; + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_EFFECT2; + mod->value = (GetId() == 51466) ? 5 : 10; + mod->type = SPELLMOD_FLAT; + mod->spellId = GetId(); + mod->mask[1] = 0x0004000; + m_spellmod = mod; } + ((Player*)m_target)->AddSpellMod(m_spellmod, apply); } + } -void Aura::HandleAuraModStalked(bool apply, bool Real) +void AuraEffect::HandleAuraModStalked(bool apply, bool Real, bool /*changeAmount*/) { // used by spells: Hunter's Mark, Mind Vision, Syndicate Tracker (MURP) DND if(apply) @@ -3712,111 +4501,133 @@ void Aura::HandleAuraModStalked(bool apply, bool Real) /*** PERIODIC ***/ /*********************************************************/ -void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real) +void AuraEffect::HandlePeriodicTriggerSpell(bool apply, bool Real, bool /*changeAmount*/) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; - m_isTrigger = apply; - - // Curse of the Plaguebringer - if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL) + if (Real && m_spellProto->Id == 66 && !apply) { - // Cast Wrath of the Plaguebringer if not dispelled - m_target->CastSpell(m_target, 29214, true, 0, this); + if (GetParentAura()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + m_target->CastSpell(m_target, 32612, true, NULL, this); } +} - // Wrath of the Astromancer - if(!apply && m_spellProto->Id == 42783) - { - m_target->CastSpell(m_target, 42787, true, 0, this); - } +void AuraEffect::HandlePeriodicTriggerSpellWithValue(bool apply, bool Real, bool /*changeAmount*/) +{ + m_isPeriodic = apply; } -void Aura::HandlePeriodicEnergize(bool apply, bool Real) +void AuraEffect::HandlePeriodicEnergize(bool apply, bool Real, bool changeAmount) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; + if(!Real && !changeAmount) + return; m_isPeriodic = apply; + + // Replenishment (0.25% from max) + // Infinite Replenishment + if (m_spellProto->SpellIconID == 3184 && m_spellProto->SpellVisual[0] == 12495) + m_amount = m_target->GetMaxPower(POWER_MANA) * 25 / 10000; } -void Aura::HandlePeriodicHeal(bool apply, bool Real) +void AuraEffect::HandleAuraPowerBurn(bool apply, bool Real, bool /*changeAmount*/) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; +} - // only at real apply - if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE) - { - // provided m_target as original caster to prevent apply aura caster selection for this negative buff - m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID()); - } +void AuraEffect::HandleAuraPeriodicDummy(bool apply, bool Real, bool changeAmount) +{ + // spells required only Real aura add/remove + if(!Real && !changeAmount) + return; // For prevent double apply bonuses bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); - if(!loading && apply) + Unit* caster = GetCaster(); + + SpellEntry const*spell = GetSpellProto(); + switch( spell->SpellFamilyName) { - switch (m_spellProto->SpellFamilyName) + case SPELLFAMILY_WARLOCK: { - case SPELLFAMILY_DRUID: + switch (spell->Id) { - // Rejuvenation - if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL) - { - if(Unit* caster = GetCaster()) + // Demonic Circle + case 48018: + if (apply) + // set to false at initial cast to enable button at next enable in periodic handler + m_target->SendAuraVisualForSelf(false,62388); + else { - Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) - { - int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; - switch((*k)->GetModifier()->m_miscvalue) - { - case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura - case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura - { - m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; - break; - } - } - } + // Do not remove GO when aura is removed by stack + // to prevent remove GO added by new spell + // old one is already removed + if (GetParentAura()->GetRemoveMode()!=AURA_REMOVE_BY_STACK) + m_target->RemoveGameObject(spell->Id,true); + m_target->SendAuraVisualForSelf(false,62388); } - } + break; } } + case SPELLFAMILY_HUNTER: + { + // Explosive Shot + if (apply && !loading && caster) + m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 14 / 100); + break; + } } + + m_isPeriodic = apply; +} + +void AuraEffect::HandlePeriodicHeal(bool apply, bool Real, bool /*changeAmount*/) +{ + m_isPeriodic = apply; } -void Aura::HandlePeriodicDamage(bool apply, bool Real) +void AuraEffect::HandlePeriodicDamage(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; // For prevent double apply bonuses bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); + // Curse of Doom + // This is a hack - this aura should be handled by passive aura and proc doomguard spawn on kill, however there is no such aura in dbcs + if(m_spellProto->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags.IsEqual(0,0x02,0)) + { + if (Real && !apply && GetParentAura()->GetRemoveMode()==AURA_REMOVE_BY_DEATH) + { + if (Unit * caster = GetCaster()) + { + if (caster->GetTypeId()==TYPEID_PLAYER && ((Player*)caster)->isHonorOrXPTarget(m_target)) + caster->CastSpell(m_target, 18662, true); + } + } + } + + // Custom damage calculation after + if (!apply || loading) + return; + Unit *caster = GetCaster(); + if (!caster) + return; switch (m_spellProto->SpellFamilyName) { case SPELLFAMILY_GENERIC: { // Pounce Bleed - if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 ) + if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 ) { // $AP*0.18/6 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); + m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); return; } break; @@ -3824,18 +4635,14 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_WARRIOR: { // Rend - if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) + if (m_spellProto->SpellFamilyFlags[0] & 0x20) { - // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick - if (apply && !loading && caster) - { - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 mws = caster->GetAttackTime(BASE_ATTACK); - float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); - float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); - // WARNING! in 3.0 multiplier 0.00743f change to 0.6 - m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f); - } + // $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); + m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f); return; } break; @@ -3843,92 +4650,80 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_DRUID: { // Rake - if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL) + if (m_spellProto->SpellFamilyFlags[0] & 0x1000) { - // $AP*0.06/3 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100); + // $AP*0.06 bonus per tick + m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100); return; } // Lacerate - if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL) + if (m_spellProto->SpellFamilyFlags[1] & 0x0000000100) { // $AP*0.05/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); + m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); return; } // Rip - if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL) + if (m_spellProto->SpellFamilyFlags[1] & 0x800000) { - // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used] - if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - uint8 cp = ((Player*)caster)->GetComboPoints(); + // 0.01*$AP*cp + if (caster->GetTypeId() != TYPEID_PLAYER) + return; + + uint8 cp = ((Player*)caster)->GetComboPoints(); - // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs - Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs + Unit::AuraEffectList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraEffectList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + { + if((*itr)->GetId()==34241) { - if((*itr)->GetId()==34241) - { - m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount; - break; - } + m_amount += cp * (*itr)->GetAmount(); + break; } - - if (cp > 4) cp = 4; - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); } + m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); + return; + } + // Lock Jaw + if (m_spellProto->SpellFamilyFlags[1] & 0x10000000) + { + // 0.15*$AP + m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 15 / 100); return; } break; } case SPELLFAMILY_ROGUE: { - // Deadly poison aura state - if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100) + // Rupture + if (m_spellProto->SpellFamilyFlags[0] & 0x100000) { - if(apply) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true); - else - { - // current aura already removed, search present of another - bool found = false; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - { - SpellEntry const* itr_spell = (*itr)->GetSpellProto(); - if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100) - { - found = true; - break; - } - } - // this has been last deadly poison aura - if(!found) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false); - } + if (caster->GetTypeId() != TYPEID_PLAYER) + return; + //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 = ((Player*)caster)->GetComboPoints(); + if (cp > 5) cp = 5; + m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]); return; } - // Rupture - if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL) + // Garrote + if (m_spellProto->SpellFamilyFlags[0] & 0x100) { - // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP] - if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - uint8 cp = ((Player*)caster)->GetComboPoints(); - if (cp > 3) cp = 3; - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); - } + // $AP*0.07 bonus per tick + m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 7 / 100); return; } - // Garrote - if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL) + // Deadly Poison + if (m_spellProto->SpellFamilyFlags[0] & 0x10000) { - // $AP*0.18/6 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); + // 0.08*$AP / 4 * amount of stack + m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 * GetParentAura()->GetStackAmount() / 100); return; } break; @@ -3936,47 +4731,17 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_HUNTER: { // Serpent Sting - if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL) + if (m_spellProto->SpellFamilyFlags[0] & 0x4000) { // $RAP*0.1/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); + m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); return; } // Immolation Trap - if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678) + if (m_spellProto->SpellFamilyFlags[0] & 0x4 && m_spellProto->SpellIconID == 678) { // $RAP*0.1/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); - return; - } - break; - } - case SPELLFAMILY_PALADIN: - { - // Consecration - if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) - { - if (apply && !loading) - { - if(Unit* caster = GetCaster()) - { - Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) - { - int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; - switch((*k)->GetModifier()->m_miscvalue) - { - case 5147: // Improved Consecration - Libram of the Eternal Rest - { - m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; - break; - } - } - } - } - } + m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); return; } break; @@ -3986,27 +4751,23 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) } } -void Aura::HandlePeriodicDamagePCT(bool apply, bool Real) +void AuraEffect::HandlePeriodicDamagePCT(bool apply, bool Real, bool /*changeAmount*/) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; } -void Aura::HandlePeriodicLeech(bool apply, bool Real) +void AuraEffect::HandlePeriodicLeech(bool apply, bool Real, bool /*changeAmount*/) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; } -void Aura::HandlePeriodicManaLeech(bool apply, bool Real) +void AuraEffect::HandlePeriodicManaLeech(bool apply, bool Real, bool /*changeAmount*/) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; + m_isPeriodic = apply; +} +void AuraEffect::HandlePeriodicHealthFunnel(bool apply, bool Real, bool /*changeAmount*/) +{ m_isPeriodic = apply; } @@ -4018,90 +4779,82 @@ void Aura::HandlePeriodicManaLeech(bool apply, bool Real) /*** RESISTANCE ***/ /********************************/ -void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real) +void AuraEffect::HandleAuraModResistanceExclusive(bool apply, bool Rea, bool /*changeAmount*/) { for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) { - if(m_modifier.m_miscvalue & int32(1<<x)) + if(GetMiscValue() & int32(1<<x)) { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,GetModifierValue(), apply); + m_target->ApplyResistanceBuffModsMod(SpellSchools(x),GetParentAura()->IsPositive(),m_amount, apply); } } } -void Aura::HandleAuraModResistance(bool apply, bool Real) +void AuraEffect::HandleAuraModResistance(bool apply, bool Real, bool /*changeAmount*/) { for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) { - if(m_modifier.m_miscvalue & int32(1<<x)) + if(GetMiscValue() & int32(1<<x)) { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,GetModifierValue(), apply); + m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_amount > 0,m_amount, apply); } } - // Faerie Fire (druid versions) - if( (m_spellProto->SpellIconID == 109 && - m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && - m_spellProto->SpellFamilyFlags & 0x0000000000000400LL) - || m_spellProto->Id == 35325) - { - m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply); - } } -void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real) +void AuraEffect::HandleAuraModBaseResistancePCT(bool apply, bool Real, bool /*changeAmount*/) { // only players have base stats if(m_target->GetTypeId() != TYPEID_PLAYER) { //pets only have base armor - if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetModifierValue()), apply); + if(((Creature*)m_target)->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_amount), apply); } else { for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) { - if(m_modifier.m_miscvalue & int32(1<<x)) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetModifierValue()), apply); + if(GetMiscValue() & int32(1<<x)) + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_amount), apply); } } } -void Aura::HandleModResistancePercent(bool apply, bool Real) +void AuraEffect::HandleModResistancePercent(bool apply, bool Real, bool /*changeAmount*/) { for(int8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) { - if(m_modifier.m_miscvalue & int32(1<<i)) + if(GetMiscValue() & int32(1<<i)) { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) { - m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,GetModifierValue(), apply); - m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,GetModifierValue(), apply); + m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_amount, apply); + m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_amount, apply); } } } } -void Aura::HandleModBaseResistance(bool apply, bool Real) +void AuraEffect::HandleModBaseResistance(bool apply, bool Real, bool /*changeAmount*/) { // only players have base stats if(m_target->GetTypeId() != TYPEID_PLAYER) { //only pets have base stats - if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetModifierValue()), apply); + if(((Creature*)m_target)->isPet() && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_amount), apply); } else { for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) - if(m_modifier.m_miscvalue & (1<<i)) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetModifierValue()), apply); + if(GetMiscValue() & (1<<i)) + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_amount), apply); } } @@ -4109,30 +4862,30 @@ void Aura::HandleModBaseResistance(bool apply, bool Real) /*** STAT ***/ /********************************/ -void Aura::HandleAuraModStat(bool apply, bool Real) +void AuraEffect::HandleAuraModStat(bool apply, bool Real, bool /*changeAmount*/) { - if (m_modifier.m_miscvalue < -2 || m_modifier.m_miscvalue > 4) + if (GetMiscValue() < -2 || GetMiscValue() > 4) { - sLog.outError("WARNING: Spell %u effect %u have unsupported misc value (%i) for SPELL_AURA_MOD_STAT ",GetId(),GetEffIndex(),m_modifier.m_miscvalue); + 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 (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i) + if (GetMiscValue() < 0 || GetMiscValue() == i) { - //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply); - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetModifierValue()), apply); + //m_target->ApplyStatMod(Stats(i), m_amount,apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyStatBuffMod(Stats(i),GetModifierValue(),apply); + m_target->ApplyStatBuffMod(Stats(i),m_amount,apply); } } } -void Aura::HandleModPercentStat(bool apply, bool Real) +void AuraEffect::HandleModPercentStat(bool apply, bool Real, bool /*changeAmount*/) { - if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) + if (GetMiscValue() < -1 || GetMiscValue() > 4) { sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); return; @@ -4144,12 +4897,12 @@ void Aura::HandleModPercentStat(bool apply, bool Real) for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { - if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(GetModifierValue()), apply); + if(GetMiscValue() == i || GetMiscValue() == -1) + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_amount), apply); } } -void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real) +void AuraEffect::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4160,7 +4913,7 @@ void Aura::HandleModSpellDamagePercentFromStat(bool /*apply*/, bool Real) ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); } -void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real) +void AuraEffect::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4169,16 +4922,7 @@ void Aura::HandleModSpellHealingPercentFromStat(bool /*apply*/, bool Real) ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); } -void Aura::HandleAuraModDispelResist(bool apply, bool Real) -{ - if(!Real || !apply) - return; - - if(GetId()==33206) - m_target->CastSpell(m_target,44416,true,NULL,this,GetCasterGUID()); -} - -void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real) +void AuraEffect::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4189,7 +4933,7 @@ void Aura::HandleModSpellDamagePercentFromAttackPower(bool /*apply*/, bool Real) ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); } -void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real) +void AuraEffect::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4198,7 +4942,7 @@ void Aura::HandleModSpellHealingPercentFromAttackPower(bool /*apply*/, bool Real ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); } -void Aura::HandleModHealingDone(bool /*apply*/, bool Real) +void AuraEffect::HandleModHealingDone(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -4207,9 +4951,9 @@ void Aura::HandleModHealingDone(bool /*apply*/, bool Real) ((Player*)m_target)->UpdateSpellDamageAndHealingBonus(); } -void Aura::HandleModTotalPercentStat(bool apply, bool Real) +void AuraEffect::HandleModTotalPercentStat(bool apply, bool Real, bool /*changeAmount*/) { - if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) + if (GetMiscValue() < -1 || GetMiscValue() > 4) { sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); return; @@ -4221,16 +4965,16 @@ void Aura::HandleModTotalPercentStat(bool apply, bool Real) for (int32 i = STAT_STRENGTH; i < MAX_STATS; i++) { - if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) + if(GetMiscValue() == i || GetMiscValue() == -1) { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyStatPercentBuffMod(Stats(i), GetModifierValue(), apply ); + m_target->ApplyStatPercentBuffMod(Stats(i), m_amount, apply ); } } //recalculate current HP/MP after applying aura modifications (only for spells with 0x10 flag) - if ((m_modifier.m_miscvalue == STAT_STAMINA) && (maxHPValue > 0) && (m_spellProto->Attributes & 0x10)) + 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 uint32 newHPValue = (m_target->GetMaxHealth() * curHPValue) / maxHPValue; @@ -4238,12 +4982,12 @@ void Aura::HandleModTotalPercentStat(bool apply, bool Real) } } -void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; - if(m_modifier.m_miscvalue != SPELL_SCHOOL_MASK_NORMAL) + 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. @@ -4258,145 +5002,70 @@ void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real) /********************************/ /*** HEAL & ENERGIZE ***/ /********************************/ -void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real) +void AuraEffect::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real, bool /*changeAmount*/) { - /* - Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic, - so this aura not fully working. - */ - if(apply) - { - if(!m_target->isAlive()) - return; - - if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - - if(m_periodicTimer <= 0) - { - m_periodicTimer += m_modifier.periodictime; - - if(m_target->GetHealth() < m_target->GetMaxHealth()) - { - // PeriodicTick can cast triggered spells with stats changes - PeriodicTick(); - } - } - } - m_isPeriodic = apply; } -void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real) +void AuraEffect::HandleAuraModTotalEnergyPercentRegen(bool apply, bool Real, bool /*changeAmount*/) { - if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - if(apply) - { - if(m_modifier.periodictime == 0) - m_modifier.periodictime = 1000; - if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA) - { - m_periodicTimer += m_modifier.periodictime; - - if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA)) - { - // PeriodicTick can cast triggered spells with stats changes - PeriodicTick(); - } - } - } + if(m_amplitude == 0) + m_amplitude = 1000; + m_periodicTimer = m_amplitude; m_isPeriodic = apply; } -void Aura::HandleModRegen(bool apply, bool Real) // eating +void AuraEffect::HandleModRegen(bool apply, bool Real, bool /*changeAmount*/) // eating { - if(apply) - { - if(!m_target->isAlive()) - return; - - if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - - if(m_periodicTimer <= 0) - { - m_periodicTimer += 5000; - int32 gain = m_target->ModifyHealth(GetModifierValue()); - Unit *caster = GetCaster(); - if (caster) - { - SpellEntry const *spellProto = GetSpellProto(); - if (spellProto) - m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto); - } - } - } + if(m_amplitude == 0) + m_amplitude = 5000; + m_periodicTimer = 5000; m_isPeriodic = apply; } -void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking +void AuraEffect::HandleModPowerRegen(bool apply, bool Real, bool changeAmount) // drinking { - if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); + if(!Real && !changeAmount) + return; - if(apply && m_periodicTimer <= 0) + Powers pt = m_target->getPowerType(); + if(m_amplitude == 0) { - - Powers pt = m_target->getPowerType(); + // Anger Management (only spell use this aura for rage) if (pt == POWER_RAGE) - m_periodicTimer = 3000; - else - m_periodicTimer = 2000; + m_amplitude = 3000; + else + m_amplitude = 2000; + } - if(int32(pt) != m_modifier.m_miscvalue) - return; + m_periodicTimer = 5000; - if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED ) - { - // eating anim - m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT); - } - else if( GetId() == 20577 ) - { - // cannibalize anim - m_target->HandleEmoteCommand(398); - } + if (m_target->GetTypeId() == TYPEID_PLAYER && GetMiscValue() == POWER_MANA) + ((Player*)m_target)->UpdateManaRegen(); - // Warrior talent, gain 1 rage every 3 seconds while in combat - // Anger Menagement - // amount = 1+ 16 = 17 = 3,4*5 = 10,2*5/3 - // so 17 is rounded amount for 5 sec tick grow ~ 1 range grow in 3 sec - if(pt == POWER_RAGE) - { - m_target->ModifyPower(pt, m_modifier.m_amount*3/5); - } - } m_isPeriodic = apply; - if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA) - ((Player*)m_target)->UpdateManaRegen(); } -void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real) +void AuraEffect::HandleModPowerRegenPCT(bool /*apply*/, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; if (m_target->GetTypeId() != TYPEID_PLAYER) return; // Update manaregen value - if (m_modifier.m_miscvalue == POWER_MANA) + if (GetMiscValue() == POWER_MANA) ((Player*)m_target)->UpdateManaRegen(); } -void Aura::HandleModManaRegen(bool /*apply*/, bool Real) +void AuraEffect::HandleModManaRegen(bool /*apply*/, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; if (m_target->GetTypeId() != TYPEID_PLAYER) @@ -4406,7 +5075,7 @@ void Aura::HandleModManaRegen(bool /*apply*/, bool Real) ((Player*)m_target)->UpdateManaRegen(); } -void Aura::HandleComprehendLanguage(bool apply, bool Real) +void AuraEffect::HandleComprehendLanguage(bool apply, bool Real, bool /*changeAmount*/) { if(apply) m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); @@ -4414,32 +5083,36 @@ void Aura::HandleComprehendLanguage(bool apply, bool Real) m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_COMPREHEND_LANG); } -void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real) +void AuraEffect::HandleAuraModIncreaseHealth(bool apply, bool Real, bool changeAmount) { - if(Real) + if(Real || changeAmount) { if(apply) { - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetModifierValue()), apply); - m_target->ModifyHealth(m_modifier.m_amount); + // Vampiric Blood + if(GetSpellProto()->Id == 55233) + m_amount = m_target->GetMaxHealth() * m_amount / 100; + + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_amount), apply); + m_target->ModifyHealth(m_amount); } else { - if (int32(m_target->GetHealth()) > m_modifier.m_amount) - m_target->ModifyHealth(-m_modifier.m_amount); + if (int32(m_target->GetHealth()) > m_amount) + m_target->ModifyHealth(-m_amount); else m_target->SetHealth(1); - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_amount), apply); } } } -void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real) +void AuraEffect::HandleAuraModIncreaseMaxHealth(bool apply, bool Real, bool /*changeAmount*/) { uint32 oldhealth = m_target->GetHealth(); double healthPercentage = (double)oldhealth / (double)m_target->GetMaxHealth(); - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_amount), apply); // refresh percentage if(oldhealth > 0) @@ -4452,38 +5125,56 @@ void Aura::HandleAuraModIncreaseMaxHealth(bool apply, bool Real) } } -void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real) +void AuraEffect::HandleAuraModIncreaseEnergy(bool apply, bool Real, bool /*changeAmount*/) { Powers powerType = m_target->getPowerType(); - if(int32(powerType) != m_modifier.m_miscvalue) + if(int32(powerType) != GetMiscValue()) return; UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); - m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetModifierValue()), apply); + // Special case with temporary increase max/current power (percent) + if (GetId()==64904) // Hymn of Hope + { + if(Real) + { + uint32 val = m_target->GetPower(powerType); + m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_amount), apply); + m_target->SetPower(powerType, apply ? val*(100+m_amount)/100 : val*100/(100+m_amount)); + } + return; + } + + // generic flat case + m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_amount), apply); } -void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/) +void AuraEffect::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/, bool /*changeAmount*/) { Powers powerType = m_target->getPowerType(); - if(int32(powerType) != m_modifier.m_miscvalue) + if(int32(powerType) != GetMiscValue()) return; UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); - m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_amount), apply); } -void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/) +void AuraEffect::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/, bool /*changeAmount*/) { - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_amount), apply); +} + +void AuraEffect::HandleAuraIncreaseBaseHealthPercent(bool apply, bool /*Real*/, bool /*changeAmount*/) +{ + m_target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(m_amount), apply); } /********************************/ /*** FIGHT ***/ /********************************/ -void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModParryPercent(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; @@ -4491,28 +5182,28 @@ void Aura::HandleAuraModParryPercent(bool /*apply*/, bool Real) ((Player*)m_target)->UpdateParryPercentage(); } -void Aura::HandleAuraModDodgePercent(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModDodgePercent(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; ((Player*)m_target)->UpdateDodgePercentage(); - //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_modifier.m_amount)); + //sLog.outError("BONUS DODGE CHANCE: + %f", float(m_amount)); } -void Aura::HandleAuraModBlockPercent(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModBlockPercent(bool /*apply*/, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; ((Player*)m_target)->UpdateBlockPercentage(); - //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_modifier.m_amount)); + //sLog.outError("BONUS BLOCK CHANCE: + %f", float(m_amount)); } -void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; if(m_target->GetTypeId()!=TYPEID_PLAYER) @@ -4521,13 +5212,13 @@ void Aura::HandleAuraModRegenInterrupt(bool /*apply*/, bool Real) ((Player*)m_target)->UpdateManaRegen(); } -void Aura::HandleAuraModCritPercent(bool apply, bool Real) +void AuraEffect::HandleAuraModCritPercent(bool apply, bool Real, bool changeAmount) { if(m_target->GetTypeId()!=TYPEID_PLAYER) return; // apply item specific bonuses for already equipped weapon - if(Real) + if(Real || changeAmount) { for(int i = 0; i < MAX_ATTACK; ++i) if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) @@ -4536,13 +5227,13 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real) // mods must be applied base at equipped weapon class and subclass comparison // with spell->EquippedItemClass and EquippedItemSubClassMask and EquippedItemInventoryTypeMask - // m_modifier.m_miscvalue comparison with item generated damage types + // GetMiscValue() comparison with item generated damage types if (GetSpellProto()->EquippedItemClass == -1) { - ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply); - ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply); - ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply); + ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); + ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); + ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_amount), apply); } else { @@ -4550,21 +5241,36 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real) } } -void Aura::HandleModHitChance(bool apply, bool Real) +void AuraEffect::HandleModHitChance(bool apply, bool Real, bool /*changeAmount*/) { - m_target->m_modMeleeHitChance += apply ? GetModifierValue() : -GetModifierValue(); - m_target->m_modRangedHitChance += apply ? GetModifierValue() : -GetModifierValue(); + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->UpdateMeleeHitChances(); + ((Player*)m_target)->UpdateRangedHitChances(); + } + else + { + m_target->m_modMeleeHitChance += apply ? m_amount : (-m_amount); + m_target->m_modRangedHitChance += apply ? m_amount : (-m_amount); + } } -void Aura::HandleModSpellHitChance(bool apply, bool Real) +void AuraEffect::HandleModSpellHitChance(bool apply, bool Real, bool /*changeAmount*/) { - m_target->m_modSpellHitChance += apply ? GetModifierValue(): -GetModifierValue(); + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->UpdateSpellHitChances(); + } + else + { + m_target->m_modSpellHitChance += apply ? m_amount: (-m_amount); + } } -void Aura::HandleModSpellCritChance(bool apply, bool Real) +void AuraEffect::HandleModSpellCritChance(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; if(m_target->GetTypeId() == TYPEID_PLAYER) @@ -4573,21 +5279,21 @@ void Aura::HandleModSpellCritChance(bool apply, bool Real) } else { - m_target->m_baseSpellCritChance += apply ? GetModifierValue():-GetModifierValue(); + m_target->m_baseSpellCritChance += apply ? m_amount:-m_amount; } } -void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real) +void AuraEffect::HandleModSpellCritChanceShool(bool /*apply*/, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; if(m_target->GetTypeId() != TYPEID_PLAYER) return; for(int school = SPELL_SCHOOL_NORMAL; school < MAX_SPELL_SCHOOL; ++school) - if (m_modifier.m_miscvalue & (1<<school)) + if (GetMiscValue() & (1<<school)) ((Player*)m_target)->UpdateSpellCritChance(school); } @@ -4595,157 +5301,147 @@ void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real) /*** ATTACK SPEED ***/ /********************************/ -void Aura::HandleModCastingSpeed(bool apply, bool Real) +void AuraEffect::HandleModCastingSpeed(bool apply, bool Real, bool /*changeAmount*/) { - m_target->ApplyCastTimePercentMod(GetModifierValue(),apply); + m_target->ApplyCastTimePercentMod(m_amount,apply); } -void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real) +void AuraEffect::HandleModMeleeRangedSpeedPct(bool apply, bool Real, bool /*changeAmount*/) { - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK,GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_amount, apply); } -void Aura::HandleModCombatSpeedPct(bool apply, bool Real) +void AuraEffect::HandleModCombatSpeedPct(bool apply, bool Real, bool /*changeAmount*/) { - m_target->ApplyCastTimePercentMod(GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK,GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply); + m_target->ApplyCastTimePercentMod(m_amount,apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_amount, apply); } -void Aura::HandleModAttackSpeed(bool apply, bool Real) +void AuraEffect::HandleModAttackSpeed(bool apply, bool Real, bool /*changeAmount*/) { if(!m_target->isAlive() ) return; - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_amount,apply); } -void Aura::HandleHaste(bool apply, bool Real) +void AuraEffect::HandleHaste(bool apply, bool Real, bool /*changeAmount*/) { - m_target->ApplyAttackTimePercentMod(BASE_ATTACK, GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK, GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,GetModifierValue(),apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_amount,apply); } -void Aura::HandleAuraModRangedHaste(bool apply, bool Real) +void AuraEffect::HandleAuraModRangedHaste(bool apply, bool Real, bool /*changeAmount*/) { - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_amount, apply); } -void Aura::HandleRangedAmmoHaste(bool apply, bool Real) +void AuraEffect::HandleRangedAmmoHaste(bool apply, bool Real, bool /*changeAmount*/) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,GetModifierValue(), apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_amount, apply); } /********************************/ /*** ATTACK POWER ***/ /********************************/ -void Aura::HandleAuraModAttackPower(bool apply, bool Real) -{ - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetModifierValue()), apply); - if(apply) - switch(m_spellProto->Id){ - // Warrior & Druid Demoshout should remove stealth - case 1160: - case 6190: - case 11554: - case 11555: - case 11556: - case 25202: - case 25203: - case 47437: //WotLK spell - case 99: - case 1735: - case 9490: - case 9747: - case 9898: - case 26998: - case 48559: //WotLK spell - case 48560: //WotLK spell - m_target->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - break; - } -} - -void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real) +void AuraEffect::HandleAuraModAttackPower(bool apply, bool Real, bool /*changeAmount*/) +{ + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_amount), apply); +} + +void AuraEffect::HandleAuraModRangedAttackPower(bool apply, bool Real, bool /*changeAmount*/) { if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) return; - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_amount), apply); } -void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real) +void AuraEffect::HandleAuraModAttackPowerPercent(bool apply, bool Real, bool /*changeAmount*/) { //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_amount), apply); } -void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real) +void AuraEffect::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real, bool /*changeAmount*/) { if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) return; //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1 - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_amount), apply); } -void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real) +void AuraEffect::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; - if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) - return; + // Recalculate bonus + if(m_target->GetTypeId() == TYPEID_PLAYER && !(m_target->getClassMask() & CLASSMASK_WAND_USERS)) + ((Player*)m_target)->UpdateAttackPowerAndDamage(true); +} - if(m_modifier.m_miscvalue != STAT_INTELLECT) - { - // support required adding UpdateAttackPowerAndDamage calls at stat update - sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intellect stats!"); +void AuraEffect::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real, bool changeAmount) +{ + // spells required only Real aura add/remove + if(!Real && !changeAmount) return; - } // Recalculate bonus - ((Player*)m_target)->UpdateAttackPowerAndDamage(true); + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->UpdateAttackPowerAndDamage(false); } +void AuraEffect::HandleAuraModAttackPowerOfArmor(bool /*apply*/, bool Real, bool /*changeAmount*/) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + // Recalculate bonus + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->UpdateAttackPowerAndDamage(false); +} /********************************/ /*** DAMAGE BONUS ***/ /********************************/ -void Aura::HandleModDamageDone(bool apply, bool Real) +void AuraEffect::HandleModDamageDone(bool apply, bool Real, bool changeAmount) { // apply item specific bonuses for already equipped weapon - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) + if((Real || changeAmount) && m_target->GetTypeId()==TYPEID_PLAYER) { for(int i = 0; i < MAX_ATTACK; ++i) if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); } - // m_modifier.m_miscvalue is bitmask of spell schools + // 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 - // m_modifier.m_miscvalue comparison with item generated damage types + // GetMiscValue() comparison with item generated damage types - if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0) + if((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0) { // apply generic physical damage bonuses including wand case if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) { - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetModifierValue()), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetModifierValue()), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_amount), apply); } else { @@ -4754,15 +5450,15 @@ void Aura::HandleModDamageDone(bool apply, bool Real) if(m_target->GetTypeId() == TYPEID_PLAYER) { - if(m_positive) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,GetModifierValue(),apply); + if(m_amount > 0) + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_amount,apply); else - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,GetModifierValue(),apply); + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_amount,apply); } } // Skip non magic case for speedup - if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0) + if((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0) return; if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) @@ -4778,57 +5474,56 @@ void Aura::HandleModDamageDone(bool apply, bool Real) // This information for client side use only if(m_target->GetTypeId() == TYPEID_PLAYER) { - if(m_positive) + if(m_amount > 0) { for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) { - if((m_modifier.m_miscvalue & (1<<i)) != 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,GetModifierValue(),apply); + if((GetMiscValue() & (1<<i)) != 0) + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_amount,apply); } } else { for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) { - if((m_modifier.m_miscvalue & (1<<i)) != 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,GetModifierValue(),apply); + if((GetMiscValue() & (1<<i)) != 0) + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_amount,apply); } } - Pet* pet = m_target->GetPet(); - if(pet) + if(Guardian* pet = ((Player*)m_target)->GetGuardianPet()) pet->UpdateAttackPowerAndDamage(); } } -void Aura::HandleModDamagePercentDone(bool apply, bool Real) +void AuraEffect::HandleModDamagePercentDone(bool apply, bool Real, bool changeAmount) { - sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", m_modifier.m_miscvalue, m_positive ? 0 : 1); + sLog.outDebug("AURA MOD DAMAGE type:%u negative:%u", GetMiscValue(), m_amount > 0); // apply item specific bonuses for already equipped weapon - if(Real && m_target->GetTypeId()==TYPEID_PLAYER) + if((Real || changeAmount) && m_target->GetTypeId()==TYPEID_PLAYER) { for(int i = 0; i < MAX_ATTACK; ++i) if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i))) ((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem,WeaponAttackType(i),this,apply); } - // m_modifier.m_miscvalue is bitmask of spell schools + // 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 - // m_modifier.m_miscvalue comparison with item generated damage types + // GetMiscValue() comparison with item generated damage types - if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) != 0) + if((GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) != 0) { // apply generic physical damage bonuses including wand case if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) { - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetModifierValue()), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetModifierValue()), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_amount), apply); } else { @@ -4836,11 +5531,11 @@ void Aura::HandleModDamagePercentDone(bool apply, bool Real) } // For show in client if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_modifier.m_amount/100.0f,apply); + m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT,m_amount/100.0f,apply); } // Skip non magic case for speedup - if((m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_MAGIC) == 0) + if((GetMiscValue() & SPELL_SCHOOL_MASK_MAGIC) == 0) return; if( GetSpellProto()->EquippedItemClass != -1 || GetSpellProto()->EquippedItemInventoryTypeMask != 0 ) @@ -4856,190 +5551,88 @@ void Aura::HandleModDamagePercentDone(bool apply, bool Real) // Send info to client if(m_target->GetTypeId() == TYPEID_PLAYER) for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) - m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_modifier.m_amount/100.0f,apply); + m_target->ApplyModSignedFloatValue(PLAYER_FIELD_MOD_DAMAGE_DONE_PCT+i,m_amount/100.0f,apply); } -void Aura::HandleModOffhandDamagePercent(bool apply, bool Real) +void AuraEffect::HandleModOffhandDamagePercent(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; sLog.outDebug("AURA MOD OFFHAND DAMAGE"); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_amount), apply); } /********************************/ /*** POWER COST ***/ /********************************/ -void Aura::HandleModPowerCostPCT(bool apply, bool Real) +void AuraEffect::HandleModPowerCostPCT(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; - float amount = GetModifierValue() /100.0f; + float amount = m_amount /100.0f; for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) - if(m_modifier.m_miscvalue & (1<<i)) + if(GetMiscValue() & (1<<i)) m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply); } -void Aura::HandleModPowerCost(bool apply, bool Real) +void AuraEffect::HandleModPowerCost(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) - if(m_modifier.m_miscvalue & (1<<i)) - m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,GetModifierValue(),apply); + if(GetMiscValue() & (1<<i)) + m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_amount,apply); +} + +void AuraEffect::HandleNoReagentUseAura(bool Apply, bool Real, bool /*changeAmount*/) +{ + // spells required only Real aura add/remove + if(!Real) + return; + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + flag96 mask; + Unit::AuraEffectList const& noReagent = m_target->GetAurasByType(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]; + + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]); } /*********************************************************/ /*** OTHERS ***/ /*********************************************************/ -void Aura::HandleShapeshiftBoosts(bool apply) +void AuraEffect::HandleAuraAllowOnlyAbility(bool apply, bool Real, bool /*changeAmount*/) { - uint32 spellId = 0; - uint32 spellId2 = 0; - uint32 HotWSpellId = 0; - - switch(GetModifier()->m_miscvalue) - { - case FORM_CAT: - spellId = 3025; - HotWSpellId = 24900; - break; - case FORM_TREE: - spellId = 5420; - break; - case FORM_TRAVEL: - spellId = 5419; - break; - case FORM_AQUA: - spellId = 5421; - break; - case FORM_BEAR: - spellId = 1178; - spellId2 = 21178; - HotWSpellId = 24899; - break; - case FORM_DIREBEAR: - spellId = 9635; - spellId2 = 21178; - HotWSpellId = 24899; - break; - case FORM_BATTLESTANCE: - spellId = 21156; - break; - case FORM_DEFENSIVESTANCE: - spellId = 7376; - break; - case FORM_BERSERKERSTANCE: - spellId = 7381; - break; - case FORM_MOONKIN: - spellId = 24905; - // aura from effect trigger spell - spellId2 = 24907; - break; - case FORM_FLIGHT: - spellId = 33948; - break; - case FORM_FLIGHT_EPIC: - spellId = 40122; - spellId2 = 40121; - break; - case FORM_SPIRITOFREDEMPTION: - spellId = 27792; - spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation. - break; - case FORM_GHOSTWOLF: - case FORM_AMBIENT: - case FORM_GHOUL: - case FORM_SHADOW: - case FORM_STEALTH: - case FORM_CREATURECAT: - case FORM_CREATUREBEAR: - spellId = 0; - break; - } - - uint32 form = GetModifier()->m_miscvalue-1; - - if(apply) - { - if (spellId) m_target->CastSpell(m_target, spellId, true, NULL, this ); - if (spellId2) m_target->CastSpell(m_target, spellId2, true, NULL, this); + if(!Real) + return; - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - const PlayerSpellMap& sp_list = ((Player *)m_target)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - if(itr->second->state == PLAYERSPELL_REMOVED) continue; - if(itr->first==spellId || itr->first==spellId2) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue; - if (spellInfo->Stances & (1<<form)) - m_target->CastSpell(m_target, itr->first, true, NULL, this); - } - //LotP - if (((Player*)m_target)->HasSpell(17007)) - { - SpellEntry const *spellInfo = sSpellStore.LookupEntry(24932); - if (spellInfo && spellInfo->Stances & (1<<form)) - m_target->CastSpell(m_target, 24932, true, NULL, this); - } - // HotW - if (HotWSpellId) - { - Unit::AuraList const& mModTotalStatPct = m_target->GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); - for(Unit::AuraList::const_iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 240 && (*i)->GetModifier()->m_miscvalue == 3) - { - int32 HotWMod = (*i)->GetModifier()->m_amount; - if(GetModifier()->m_miscvalue == FORM_CAT) - HotWMod /= 2; + if(!apply && m_target->HasAuraType(SPELL_AURA_ALLOW_ONLY_ABILITY)) + return; - m_target->CastCustomSpell(m_target, HotWSpellId, &HotWMod, NULL, NULL, true, NULL, this); - break; - } - } - } - } - } - else + if(m_target->GetTypeId()==TYPEID_PLAYER) { - m_target->RemoveAurasDueToSpell(spellId); - m_target->RemoveAurasDueToSpell(spellId2); - - Unit::AuraMap& tAuras = m_target->GetAuras(); - for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) - { - if (itr->second->IsRemovedOnShapeLost()) - { - m_target->RemoveAurasDueToSpell(itr->second->GetId()); - itr = tAuras.begin(); - } - else - { - ++itr; - } - } + if (apply) + m_target->SetFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); + else + m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); } - - /*double healthPercentage = (double)m_target->GetHealth() / (double)m_target->GetMaxHealth(); - m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/ } -void Aura::HandleAuraEmpathy(bool apply, bool Real) +void AuraEffect::HandleAuraEmpathy(bool apply, bool Real, bool /*changeAmount*/) { - if(m_target->GetTypeId() != TYPEID_UNIT) + if(!Real || m_target->GetTypeId() != TYPEID_UNIT) return; CreatureInfo const * ci = objmgr.GetCreatureTemplate(m_target->GetEntry()); @@ -5047,43 +5640,43 @@ void Aura::HandleAuraEmpathy(bool apply, bool Real) m_target->ApplyModUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_SPECIALINFO, apply); } -void Aura::HandleAuraUntrackable(bool apply, bool Real) +void AuraEffect::HandleAuraUntrackable(bool apply, bool Real, bool /*changeAmount*/) { + if (!Real) + return; if(apply) - m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE); + m_target->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE); else - m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE); + m_target->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE); } -void Aura::HandleAuraModPacify(bool apply, bool Real) +void AuraEffect::HandleAuraModPacify(bool apply, bool Real, bool /*changeAmount*/) { - if(m_target->GetTypeId() != TYPEID_PLAYER) + if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) return; if(apply) m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); else m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); - - - if(m_spellProto->Id == 45839){ - if(apply){ - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - }else{ - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } } -void Aura::HandleAuraModPacifyAndSilence(bool apply, bool Real) +void AuraEffect::HandleAuraModPacifyAndSilence(bool apply, bool Real, bool changeAmount) { - HandleAuraModPacify(apply,Real); - HandleAuraModSilence(apply,Real); + if(m_spellProto->Id == 45839) + { + if(apply) + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + else + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + HandleAuraModPacify(apply,Real, changeAmount); + HandleAuraModSilence(apply,Real, changeAmount); } -void Aura::HandleAuraGhost(bool apply, bool Real) +void AuraEffect::HandleAuraGhost(bool apply, bool Real, bool /*changeAmount*/) { - if(m_target->GetTypeId() != TYPEID_PLAYER) + if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) return; if(apply) @@ -5096,12 +5689,15 @@ void Aura::HandleAuraGhost(bool apply, bool Real) } } -void Aura::HandleAuraAllowFlight(bool apply, bool Real) +void AuraEffect::HandleAuraAllowFlight(bool apply, bool Real, bool /*changeAmount*/) { // all applied/removed only at real aura add/remove if(!Real) return; + if(m_target->GetTypeId() == TYPEID_UNIT) + m_target->SetFlying(apply); + // allow fly WorldPacket data; if(apply) @@ -5113,21 +5709,35 @@ void Aura::HandleAuraAllowFlight(bool apply, bool Real) m_target->SendMessageToSet(&data, true); } -void Aura::HandleModRating(bool apply, bool Real) +void AuraEffect::HandleModRating(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; if(m_target->GetTypeId() != TYPEID_PLAYER) return; for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) - if (m_modifier.m_miscvalue & (1 << rating)) - ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), GetModifierValue(), apply); + if (GetMiscValue() & (1 << rating)) + ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_amount, apply); +} + +void AuraEffect::HandleModRatingFromStat(bool apply, bool Real, bool changeAmount) +{ + // spells required only Real aura add/remove + if(!Real && !changeAmount) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Just recalculate ratings + for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + if (GetMiscValue() & (1 << rating)) + ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), 0, apply); } -void Aura::HandleForceMoveForward(bool apply, bool Real) +void AuraEffect::HandleForceMoveForward(bool apply, bool Real, bool /*changeAmount*/) { if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -5137,7 +5747,7 @@ void Aura::HandleForceMoveForward(bool apply, bool Real) m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FORCE_MOVE); } -void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real) +void AuraEffect::HandleAuraModExpertise(bool /*apply*/, bool Real, bool changeAmount) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; @@ -5146,36 +5756,36 @@ void Aura::HandleAuraModExpertise(bool /*apply*/, bool Real) ((Player*)m_target)->UpdateExpertise(OFF_ATTACK); } -void Aura::HandleModTargetResistance(bool apply, bool Real) +void AuraEffect::HandleModTargetResistance(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; // applied to damage as HandleNoImmediateEffect in Unit::CalcAbsorbResist and Unit::CalcArmorReducedDamage // show armor penetration - if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,GetModifierValue(), apply); + if (m_target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL)) + m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_amount, apply); // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy - if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL) - m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,GetModifierValue(), apply); + if (m_target->GetTypeId() == TYPEID_PLAYER && (GetMiscValue() & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL) + m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_amount, apply); } -void Aura::HandleShieldBlockValue(bool apply, bool Real) +void AuraEffect::HandleShieldBlockValue(bool apply, bool Real, bool /*changeAmount*/) { BaseModType modType = FLAT_MOD; - if(m_modifier.m_auraname == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT) + if(m_auraName == SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT) modType = PCT_MOD; if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetModifierValue()), apply); + ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_amount), apply); } -void Aura::HandleAuraRetainComboPoints(bool apply, bool Real) +void AuraEffect::HandleAuraRetainComboPoints(bool apply, bool Real, bool changeAmount) { // spells required only Real aura add/remove - if(!Real) + if(!Real && !changeAmount) return; if(m_target->GetTypeId() != TYPEID_PLAYER) @@ -5185,23 +5795,26 @@ void Aura::HandleAuraRetainComboPoints(bool apply, bool Real) // combo points was added in SPELL_EFFECT_ADD_COMBO_POINTS handler // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost) - if( !apply && m_duration==0 && target->GetComboTarget()) + if( !apply && GetParentAura()->GetAuraDuration()==0 && target->GetComboTarget()) if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget())) - target->AddComboPoints(unit, -GetModifierValue()); + target->AddComboPoints(unit, -m_amount); } -void Aura::HandleModUnattackable( bool Apply, bool Real ) +void AuraEffect::HandleModUnattackable( bool Apply, bool Real , bool /*changeAmount*/) { - if(Real && Apply) + if(!Real) + return; + + if(Apply) { m_target->CombatStop(); - m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_UNATTACKABLE); + m_target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); } - m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE,Apply); + m_target->ApplyModFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE, Apply); } -void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) +void AuraEffect::HandleSpiritOfRedemption( bool apply, bool Real , bool /*changeAmount*/) { // spells required only Real aura add/remove if(!Real) @@ -5217,7 +5830,7 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) // set stand state (expected in this form) if(!m_target->IsStandState()) - m_target->SetStandState(PLAYER_STATE_NONE); + m_target->SetStandState(UNIT_STAND_STATE_STAND); } m_target->SetHealth(1); @@ -5227,38 +5840,9 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) m_target->setDeathState(JUST_DIED); } -void Aura::CleanupTriggeredSpells() +void AuraEffect::HandleSchoolAbsorb(bool apply, bool Real, bool changeAmount) { - uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; - if(!tSpellId) - return; - - SpellEntry const* tProto = sSpellStore.LookupEntry(tSpellId); - if(!tProto) - return; - - if(GetSpellDuration(tProto) != -1) - return; - - // needed for spell 43680, maybe others - // TODO: is there a spell flag, which can solve this in a more sophisticated way? - if(m_spellProto->EffectApplyAuraName[GetEffIndex()] == SPELL_AURA_PERIODIC_TRIGGER_SPELL && - GetSpellDuration(m_spellProto) == m_spellProto->EffectAmplitude[GetEffIndex()]) - return; - m_target->RemoveAurasDueToSpell(tSpellId); -} - -void Aura::HandleAuraPowerBurn(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; -} - -void Aura::HandleSchoolAbsorb(bool apply, bool Real) -{ - if(!Real) + if(!Real && !changeAmount) return; // prevent double apply bonuses @@ -5270,29 +5854,44 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) switch(m_spellProto->SpellFamilyName) { case SPELLFAMILY_PRIEST: - if(m_spellProto->SpellFamilyFlags == 0x1) //PW:S + // Power Word: Shield + if(m_spellProto->SpellFamilyFlags.IsEqual(0x1, 0, 0x400)) { - //+30% from +healing bonus - DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f; - break; + // +80.68% from sp bonus + DoneActualBenefit = caster->SpellBaseHealingBonus(GetSpellSchoolMask(m_spellProto)) * 0.8068f; } break; case SPELLFAMILY_MAGE: - if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL) + // ice barrier + if(m_spellProto->SpellFamilyFlags.IsEqual(0, 0x1, 0x8)) + { + // +80.67% from sp bonus + DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.8067f; + } + /* + TODO: find the correct spell power coefficient for frost ward and fire ward (if has) + // frost ward, fire ward + else if(m_spellProto->SpellFamilyFlags.IsEqual(0x100, 0, 0x8) || m_spellProto->SpellFamilyFlags.IsEqual(0x8, 0, 0x8)) { - //frost ward, fire ward, ice barrier //+10% from +spd bonus DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f; - break; } + */ break; case SPELLFAMILY_WARLOCK: - if(m_spellProto->SpellFamilyFlags == 0x00) + // shadow ward + if(m_spellProto->SpellFamilyFlags.IsEqual(0, 0, 0x40)) { - //shadow ward - //+10% from +spd bonus - DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.1f; - break; + // +30% from sp bonus + DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.3f; + } + break; + case SPELLFAMILY_PALADIN: + // Sacred Shield + if (m_spellProto->SpellFamilyFlags[1] & 0x80000) + { + // 0.75 from sp bonus + DoneActualBenefit = caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellProto)) * 0.75f; } break; default: @@ -5301,17 +5900,17 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto()); - m_modifier.m_amount += (int32)DoneActualBenefit; + m_amount += (int32)DoneActualBenefit; } } } -void Aura::PeriodicTick() +void AuraEffect::PeriodicTick() { if(!m_target->isAlive()) return; - switch(m_modifier.m_auraname) + switch(GetAuraName()) { case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: @@ -5320,16 +5919,17 @@ void Aura::PeriodicTick() if(!pCaster) return; + // Consecrate ticks can miss and will not show up in the combat log if( GetSpellProto()->Effect[GetEffIndex()]==SPELL_EFFECT_PERSISTENT_AREA_AURA && pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) return; // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) + if(m_target->IsImmunedToDamage(GetSpellProto())) return; // some auras remove at specific health level or more - if(m_modifier.m_auraname==SPELL_AURA_PERIODIC_DAMAGE) + if(m_auraName==SPELL_AURA_PERIODIC_DAMAGE) { switch(GetId()) { @@ -5356,19 +5956,20 @@ void Aura::PeriodicTick() } case 41337:// aura of anger { - Unit::AuraList const& mMod = m_target->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - for(Unit::AuraList::const_iterator i = mMod.begin(); i != mMod.end(); ++i) + Unit::AuraEffectList const& mMod = m_target->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + for(Unit::AuraEffectList::const_iterator i = mMod.begin(); i != mMod.end(); ++i) { if ((*i)->GetId() == 41337) { (*i)->ApplyModifier(false); - (*i)->GetModifier()->m_amount += 5; + (*i)->SetAmount((*i)->GetAmount()+5); (*i)->ApplyModifier(true); break; } } - m_modifier.m_amount = 100 * m_tickNumber; - }break; + m_amount = 100 * m_tickNumber; + break; + } default: break; } @@ -5379,30 +5980,27 @@ void Aura::PeriodicTick() CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 pdamage = GetAmount() > 0 ? GetAmount() : 0; - uint32 pdamage; - - if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE) + if(GetAuraName() == SPELL_AURA_PERIODIC_DAMAGE) { - pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),amount,DOT); + pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetParentAura()->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 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage); + uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage, GetSpellProto()); cleanDamage.damage += pdamage - pdamageReductedArmor; pdamage = pdamageReductedArmor; } - //pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); - // Curse of Agony damage-per-tick calculation - if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544) + if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID==544) { - uint32 totalTick = m_maxduration / m_modifier.periodictime; + uint32 totalTick = GetParentAura()->GetAuraMaxDuration() / m_amplitude; // 1..4 ticks, 1/2 from normal tick damage if(m_tickNumber <= totalTick / 3) pdamage = pdamage/2; @@ -5413,31 +6011,22 @@ void Aura::PeriodicTick() } } else - pdamage = uint32(m_target->GetMaxHealth()*amount/100); + pdamage = uint32(m_target->GetMaxHealth()*pdamage/100); //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit // Reduce dot damage from resilience for players if (m_target->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pdamage *= GetStackAmount(); - - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &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())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)pdamage; - data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x - data << (uint32)absorb; - data << (uint32)resist; - m_target->SendMessageToSet(&data,true); + pCaster->DealDamageMods(m_target,pdamage,&absorb); + + SpellPeriodicAuraLogInfo pInfo(this, pdamage, 0, absorb, resist, 0.0f); + m_target->SendPeriodicAuraLog(&pInfo); Unit* target = m_target; // aura can be deleted in DealDamage SpellEntry const* spellProto = GetSpellProto(); @@ -5445,7 +6034,7 @@ void Aura::PeriodicTick() // Set trigger flag uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; - uint32 procEx = PROC_EX_INTERNAL_DOT | PROC_EX_NORMAL_HIT; + uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_DOT; pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist); if (pdamage) procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; @@ -5467,88 +6056,32 @@ void Aura::PeriodicTick() pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) return; - // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) + // Check for immune + if(m_target->IsImmunedToDamage(GetSpellProto())) return; uint32 absorb=0; uint32 resist=0; CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); + //uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 pdamage = GetAmount() > 0 ? GetAmount() : 0; + pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetParentAura()->GetStackAmount()); //Calculate armor mitigation if it is a physical spell if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL) { - uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage); + uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage, GetSpellProto()); cleanDamage.damage += pdamage - pdamageReductedArmor; pdamage = pdamageReductedArmor; } - //pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); - - // talent Soul Siphon add bonus to Drain Life spells - if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) ) - { - // find talent max bonus percentage - Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i) - { - if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993) - { - if((*i)->GetEffIndex()!=1) - { - sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId()); - break; - } - - // effect 1 m_amount - int32 maxPercent = (*i)->GetModifier()->m_amount; - // effect 0 m_amount - int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster); - - // count affliction effects and calc additional damage in percentage - int32 modPercent = 0; - Unit::AuraMap const& victimAuras = m_target->GetAuras(); - for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) - { - Aura* aura = itr->second; - if (aura->IsPositive())continue; - SpellEntry const* m_spell = aura->GetSpellProto(); - if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK) - continue; - - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id); - - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - if(_spell_idx->second->skillId == SKILL_AFFLICTION) - { - modPercent += stepPercent; - if (modPercent >= maxPercent) - { - modPercent = maxPercent; - break; - } - } - } - } - pdamage += (pdamage*modPercent/100); - break; - } - } - } - //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit // Reduce dot damage from resilience for players if (m_target->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pdamage *= GetStackAmount(); - - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto); if(m_target->GetHealth() < pdamage) pdamage = uint32(m_target->GetHealth()); @@ -5558,15 +6091,15 @@ void Aura::PeriodicTick() pCaster->SendSpellNonMeleeDamageLog(m_target, GetId(), pdamage, GetSpellSchoolMask(GetSpellProto()), absorb, resist, false, 0); - Unit* target = m_target; // aura can be deleted in DealDamage SpellEntry const* spellProto = GetSpellProto(); float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1; + int32 stackAmount = GetParentAura()->GetStackAmount(); // Set trigger flag uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC; uint32 procVictim = PROC_FLAG_ON_TAKE_PERIODIC; - uint32 procEx = PROC_EX_INTERNAL_DOT | PROC_EX_NORMAL_HIT; + uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_DOT; pdamage = (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist); if (pdamage) procVictim|=PROC_FLAG_TAKEN_ANY_DAMAGE; @@ -5582,16 +6115,37 @@ void Aura::PeriodicTick() } } - if(Player *modOwner = pCaster->GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); - uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster); + uint32 heal = uint32(pCaster->SpellHealingBonus(pCaster, spellProto, uint32(new_damage * multiplier), DOT, stackAmount)); - int32 gain = pCaster->ModifyHealth(heal); + int32 gain = pCaster->DealHeal(pCaster, heal, spellProto); pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto); + break; + } + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: // only three spells + { + Unit *donator = GetCaster(); + if(!donator || !donator->GetHealth()) + return; + + uint32 pdamage = GetAmount() * GetParentAura()->GetStackAmount(); + if(donator->GetHealth() < pdamage) + pdamage = donator->GetHealth() - 1; + if(!pdamage) + return; + + Unit* target = m_target; // aura can be deleted in DealDamage + SpellEntry const* spellProto = GetSpellProto(); + //donator->SendSpellNonMeleeDamageLog(donator, GetId(), pdamage, GetSpellSchoolMask(spellProto), 0, 0, false, 0); + donator->ModifyHealth(-(int32)pdamage); + sLog.outDetail("PeriodicTick: donator %u target %u damage %u.", donator->GetEntry(), target->GetEntry(), pdamage); - pCaster->SendHealSpellLog(pCaster, spellProto->Id, heal); + if(spellProto->EffectMultipleValue[GetEffIndex()] > 0) + pdamage *= spellProto->EffectMultipleValue[GetEffIndex()]; + + donator->DealHeal(target, pdamage, spellProto); break; } case SPELL_AURA_PERIODIC_HEAL: @@ -5602,53 +6156,43 @@ void Aura::PeriodicTick() return; // heal for caster damage (must be alive) - if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive()) + if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive()) return; - // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + if(GetParentAura()->GetAuraDuration() ==-1 && m_target->GetHealth()==m_target->GetMaxHealth()) + return; - uint32 pdamage; + // ignore non positive values (can be result apply spellmods to aura damage + //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + int32 pdamage = GetAmount() > 0 ? GetAmount() : 0; - if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH) - pdamage = uint32(m_target->GetMaxHealth() * amount/100); + if(m_auraName==SPELL_AURA_OBS_MOD_HEALTH) + pdamage = uint32(m_target->GetMaxHealth() * pdamage * GetParentAura()->GetStackAmount() / 100); else - pdamage = pCaster->SpellHealingBonus(GetSpellProto(), amount, DOT, m_target); - - pdamage *= GetStackAmount(); - - //pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target); + pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetParentAura()->GetStackAmount()); sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)pdamage; - m_target->SendMessageToSet(&data,true); - int32 gain = m_target->ModifyHealth(pdamage); + SpellPeriodicAuraLogInfo pInfo(this, pdamage, pdamage - gain, 0, 0, 0.0f); + m_target->SendPeriodicAuraLog(&pInfo); + // add HoTs to amount healed in bgs if( pCaster->GetTypeId() == TYPEID_PLAYER ) if( BattleGround *bg = ((Player*)pCaster)->GetBattleGround() ) bg->UpdatePlayerScore(((Player*)pCaster), SCORE_HEALING_DONE, gain); - //Do check before because m_modifier.auraName can be invalidate by DealDamage. - bool procSpell = (m_modifier.m_auraname == SPELL_AURA_PERIODIC_HEAL && m_target != pCaster); - m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); Unit* target = m_target; // aura can be deleted in DealDamage SpellEntry const* spellProto = GetSpellProto(); - bool haveCastItem = GetCastItemGUID()!=0; + bool haveCastItem = GetParentAura()->GetCastItemGUID()!=0; + // Health Funnel // heal for caster damage - if(m_target!=pCaster && spellProto->SpellVisual==163) + if(m_target!=pCaster && spellProto->SpellVisual[0]==163) { uint32 dmg = spellProto->manaPerSecond; if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER) @@ -5668,23 +6212,35 @@ void Aura::PeriodicTick() } else { - pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false); + uint32 damage = gain; + uint32 absorb = 0; + pCaster->DealDamageMods(pCaster,damage,&absorb); + pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false); CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); + pCaster->DealDamage(pCaster, 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_INTERNAL_HOT | PROC_EX_NORMAL_HIT; + uint32 procEx = PROC_EX_NORMAL_HIT | PROC_EX_INTERNAL_HOT; // ignore item heals - if(procSpell && !haveCastItem) + if(!haveCastItem) pCaster->ProcDamageAndSpell(target, procAttacker, procVictim, procEx, pdamage, BASE_ATTACK, spellProto); break; } case SPELL_AURA_PERIODIC_MANA_LEECH: { + if(GetMiscValue() < 0 || GetMiscValue() >= MAX_POWERS) + return; + + Powers power = Powers(GetMiscValue()); + + // power type might have changed between aura applying and tick (druid's shapeshift) + if(m_target->getPowerType() != power) + return; + Unit *pCaster = GetCaster(); if(!pCaster) return; @@ -5697,24 +6253,26 @@ void Aura::PeriodicTick() return; // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) + if(m_target->IsImmunedToDamage(GetSpellProto())) return; // ignore non positive values (can be result apply spellmods to aura damage - uint32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0; + uint32 pdamage = 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 = pCaster->GetMaxPower(power) * pdamage * 2 / 100; + pdamage = m_target->GetMaxPower(power) * pdamage / 100; + if(pdamage > maxmana) + pdamage = 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())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4) - break; - - Powers power = Powers(m_modifier.m_miscvalue); - - // power type might have changed between aura applying and tick (druid's shapeshift) - if(m_target->getPowerType() != power) - break; - int32 drain_amount = m_target->GetPower(power) > pdamage ? pdamage : m_target->GetPower(power); // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) @@ -5733,16 +6291,8 @@ void Aura::PeriodicTick() modOwner->ApplySpellMod(GetId(), SPELLMOD_MULTIPLE_VALUE, gain_multiplier); } - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)power; // power type - data << (uint32)drain_amount; - data << (float)gain_multiplier; - m_target->SendMessageToSet(&data,true); + SpellPeriodicAuraLogInfo pInfo(this, drain_amount, 0, 0, 0, gain_multiplier); + m_target->SendPeriodicAuraLog(&pInfo); int32 gain_amount = int32(drain_amount*gain_multiplier); @@ -5757,7 +6307,7 @@ void Aura::PeriodicTick() { m_target->CastSpell(m_target, 31463, true, 0, this); // Remove aura - SetAuraDuration(0); + GetParentAura()->SetAuraDuration(0); } // Mark of Kazzak @@ -5770,67 +6320,64 @@ void Aura::PeriodicTick() { m_target->CastSpell(m_target, 32961, true, 0, this); // Remove aura - SetAuraDuration(0); + GetParentAura()->SetAuraDuration(0); } } break; } - case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_OBS_MOD_ENERGY: { - // ignore non positive values (can be result apply spellmods to aura damage - uint32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0; + if(GetMiscValue() < 0) + return; - sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); + Powers power; + if (GetMiscValue() == POWER_ALL) + power = m_target->getPowerType(); + else + power = Powers(GetMiscValue()); - if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4) - break; + if(m_target->GetMaxPower(power) == 0) + return; - Powers power = Powers(m_modifier.m_miscvalue); + if(GetParentAura()->GetAuraDuration() ==-1 && m_target->GetPower(power)==m_target->GetMaxPower(power)) + return; - if(m_target->GetMaxPower(power) == 0) - break; + uint32 amount = m_amount * m_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())), m_target->GetGUIDLow(), m_target->GetTypeId(), amount, GetId()); - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)power; // power type - data << (uint32)pdamage; - m_target->SendMessageToSet(&data,true); + SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f); + m_target->SendPeriodicAuraLog(&pInfo); - int32 gain = m_target->ModifyPower(power,pdamage); + int32 gain = m_target->ModifyPower(power,amount); if(Unit* pCaster = GetCaster()) m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); break; } - case SPELL_AURA_OBS_MOD_MANA: + case SPELL_AURA_PERIODIC_ENERGIZE: { // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = GetModifierValue() > 0 ? GetModifierValue() : 0; + if(m_amount < 0 || GetMiscValue() >= MAX_POWERS) + return; - uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100); + Powers power = Powers(GetMiscValue()); - sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u mana inflicted by %u", - GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); + if(m_target->GetMaxPower(power) == 0) + return; - if(m_target->GetMaxPower(POWER_MANA) == 0) - break; + if(GetParentAura()->GetAuraDuration() ==-1 && m_target->GetPower(power)==m_target->GetMaxPower(power)) + return; + + uint32 amount = m_amount; + + SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f); + m_target->SendPeriodicAuraLog(&pInfo); - WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size - data.append(m_target->GetPackGUID()); - data.appendPackGUID(GetCasterGUID()); - data << uint32(GetId()); - data << uint32(1); - data << uint32(m_modifier.m_auraname); - data << (uint32)0; // ? - data << (uint32)pdamage; - m_target->SendMessageToSet(&data,true); + sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", + GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), amount, GetId()); - int32 gain = m_target->ModifyPower(POWER_MANA, pdamage); + int32 gain = m_target->ModifyPower(power,amount); if(Unit* pCaster = GetCaster()) m_target->getHostilRefManager().threatAssist(pCaster, float(gain) * 0.5f, GetSpellProto()); @@ -5843,12 +6390,12 @@ void Aura::PeriodicTick() return; // Check for immune (not use charges) - if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) + if(m_target->IsImmunedToDamage(GetSpellProto())) return; - int32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0; + int32 pdamage = m_amount > 0 ? m_amount : 0; - Powers powerType = Powers(m_modifier.m_miscvalue); + Powers powerType = Powers(GetMiscValue()); if(!m_target->isAlive() || m_target->getPowerType() != powerType) return; @@ -5866,6 +6413,9 @@ void Aura::PeriodicTick() SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask); //no SpellDamageBonus for burn mana pCaster->CalculateSpellDamageTaken(&damageInfo, gain, spellProto); + + pCaster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb); + pCaster->SendSpellNonMeleeDamageLog(&damageInfo); // Set trigger flag @@ -5880,124 +6430,188 @@ void Aura::PeriodicTick() pCaster->DealSpellDamage(&damageInfo, true); break; } + case SPELL_AURA_MOD_REGEN: + { + int32 gain = m_target->ModifyHealth(m_amount); + if (Unit *caster = GetCaster()) + m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto()); + break; + } + case SPELL_AURA_MOD_POWER_REGEN: + { + Powers pt = m_target->getPowerType(); + if(int32(pt) != GetMiscValue()) + return; + + if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED ) + { + // eating anim + m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT); + } + else if( GetId() == 20577 ) + { + // cannibalize anim + m_target->HandleEmoteCommand(EMOTE_STATE_CANNIBALIZE); + } + // Butchery + else if (m_spellProto->SpellFamilyName==SPELLFAMILY_DEATHKNIGHT + && m_spellProto->SpellIconID==2664) + { + if (m_target->isInCombat()) + m_target->ModifyPower(pt,m_amount); + } + + // Anger Management + // amount = 1+ 16 = 17 = 3,4*5 = 10,2*5/3 + // so 17 is rounded amount for 5 sec tick grow ~ 1 range grow in 3 sec + if(pt == POWER_RAGE) + m_target->ModifyPower(pt, m_amount*3/5); + break; + } + case SPELL_AURA_DUMMY: + { + // Haunting Spirits + if (GetId() == 7057) + { + m_target->CastSpell((Unit*)NULL , m_amount , true); + m_amplitude = irand (0 , 60 ) + 30; + m_amplitude *= IN_MILISECONDS; + break; + } + break; + } // Here tick dummy auras case SPELL_AURA_PERIODIC_DUMMY: { PeriodicDummyTick(); break; } + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + { + TriggerSpell(); + break; + } + case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: + { + TriggerSpellWithValue(); + break; + } default: break; } } -void Aura::PeriodicDummyTick() +void AuraEffect::PeriodicDummyTick() { + Unit *caster = GetCaster(); SpellEntry const* spell = GetSpellProto(); - switch (spell->Id) - { - // Drink - case 430: - case 431: - case 432: - case 1133: - case 1135: - case 1137: - case 10250: - case 22734: - case 27089: - case 34291: - case 43706: - case 46755: - { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus - Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); - for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i) + switch (spell->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + switch (spell->Id) + { + // Drink + case 430: + case 431: + case 432: + case 1133: + case 1135: + case 1137: + case 10250: + case 22734: + case 27089: + case 34291: + case 43182: + case 43183: + case 46755: + case 49472: // Drink Coffee + case 57073: + case 61830: { - if ((*i)->GetId() == GetId()) + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Get SPELL_AURA_MOD_POWER_REGEN aura from spell + if (AuraEffect * aurEff = GetParentAura()->GetPartAura(0)) { - BattleGround *bg = ((Player*)m_target)->GetBattleGround(); - if(!bg || !bg->isArena()) + if (aurEff->GetAuraName() !=SPELL_AURA_MOD_POWER_REGEN) { - // default case - not in arena m_isPeriodic = false; - if(m_tickNumber == 1) - (*i)->GetModifier()->m_amount = m_modifier.m_amount; - ((Player*)m_target)->UpdateManaRegen(); - return; + sLog.outError("Aura %d structure has been changed - first aura is no longer SPELL_AURA_MOD_POWER_REGEN", spell->Id); } - //********************************************** - // This feature uses only in arenas - //********************************************** - // Here need increase mana regen per tick (6 second rule) - // on 0 tick - 0 (handled in 2 second) - // on 1 tick - 166% (handled in 4 second) - // on 2 tick - 133% (handled in 6 second) - // Not need update after 4 tick - if (m_tickNumber > 4) - return; - // Apply bonus for 1 - 4 tick - switch (m_tickNumber) + else { - case 1: // 0% - (*i)->GetModifier()->m_amount = 0; - break; - case 2: // 166% - (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3; - break; - case 3: // 133% - (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3; - break; - default: // 100% - normal regen - (*i)->GetModifier()->m_amount = m_modifier.m_amount; - break; + // default case - not in arena + if (!((Player*)m_target)->InArena()) + { + aurEff->SetAmount(GetAmount()); + ((Player*)m_target)->UpdateManaRegen(); + 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->SetAmount(0); + break; + case 2: // 166% + aurEff->SetAmount(GetAmount() * 5 / 3); + break; + case 3: // 133% + aurEff->SetAmount(GetAmount() * 4 / 3); + break; + default: // 100% - normal regen + aurEff->SetAmount(GetAmount()); + // No need to update after 4th tick + m_isPeriodic = false; + break; + } + ((Player*)m_target)->UpdateManaRegen(); + } } - ((Player*)m_target)->UpdateManaRegen(); - return; } + return; + } + // 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; } - return; - } // // Panda // case 19230: break; -// // Master of Subtlety -// case 31666: break; // // Gossip NPC Periodic - Talk // case 33208: break; // // Gossip NPC Periodic - Despawn // case 33209: break; -// // Force of Nature -// case 33831: break; - // Aspect of the Viper - case 34074: - { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Should be manauser - if (m_target->getPowerType()!=POWER_MANA) - return; - Unit *caster = GetCaster(); - if (!caster) - return; - // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell) - int mana = m_target->GetPower(POWER_MANA); - int max_mana = m_target->GetMaxPower(POWER_MANA); - int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); - float regen_pct = 1.20f - 1.1f * mana / max_mana; - if (regen_pct > 1.0f) regen_pct = 1.0f; - else if (regen_pct < 0.2f) regen_pct = 0.2f; - m_modifier.m_amount = int32 (base_regen * regen_pct); - ((Player*)m_target)->UpdateManaRegen(); - return; - } // // Steal Weapon // case 36207: break; // // Simon Game START timer, (DND) // case 39993: break; -// // Harpooner's Mark -// case 40084: break; // // Knockdown Fel Cannon: break; The Aggro Burst // case 40119: break; // // Old Mount Spell @@ -6010,6 +6624,8 @@ void Aura::PeriodicDummyTick() // case 40846: break; // // Copy Weapon // case 41054: break; +// // Dementia +// case 41404: break; // // Ethereal Ring Visual, Lightning Aura // case 41477: break; // // Ethereal Ring Visual, Lightning Aura (Fork) @@ -6058,6 +6674,8 @@ void Aura::PeriodicDummyTick() // case 43310: break; // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17 // case 43884: break; +// // Wretched! +// case 43963: break; // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17 // case 44000: break; // // Energy Feedback @@ -6124,25 +6742,232 @@ void Aura::PeriodicDummyTick() // case 47407: break; // // Mole Machine Port Schedule // case 47489: break; +// case 47941: break; // Crystal Spike +// case 48200: break; // Healer Aura +// case 48630: break; // Summon Gauntlet Mobs Periodic +// case 49313: break; // Proximity Mine Area Aura // // Mole Machine Portal Schedule // case 49466: break; -// // Drink Coffee -// case 49472: break; +// case 49555: break; // Corpse Explode +// case 49592: break; // Temporal Rift +// case 49957: break; // Cutting Laser +// case 50085: break; // Slow Fall // // Listening to Music // case 50493: break; // // Love Rocket Barrage // case 50530: break; + case 58549: // Tenacity + case 59911: // Tenacity (vehicle) + GetParentAura()->RefreshAura(); + break; +// Exist more after, need add later + default: + break; + } + break; + case SPELLFAMILY_MAGE: + { + // Mirror Image +// if (spell->Id == 55342) +// return; + break; + } + case SPELLFAMILY_WARLOCK: + { + switch (spell->Id) + { + // Demonic Circle + case 48018: + if(GameObject* obj = m_target->GetGameObject(spell->Id)) + // We must take a range of teleport spell, not summon. + m_target->SendAuraVisualForSelf(m_target->IsWithinDist(obj, GetSpellMaxRange(48020, true)), 62388, 1); + return; + } + break; + } + case SPELLFAMILY_DRUID: + { + switch (spell->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 (m_target->getPowerType()!=POWER_RAGE) + return; + uint32 rage = m_target->GetPower(POWER_RAGE); + // Nothing todo + if (rage == 0) + return; + int32 mod = (rage < 100) ? rage : 100; + int32 points = m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); + int32 regen = m_target->GetMaxHealth() * (mod * points / 10) / 1000; + m_target->CastCustomSpell(m_target, 22845, ®en, 0, 0, true, 0, this); + m_target->SetPower(POWER_RAGE, rage-mod); + return; + } + // Force of Nature + case 33831: + return; + default: + break; + } + break; + } + case SPELLFAMILY_ROGUE: + { + switch (spell->Id) + { + // Master of Subtlety + case 31666: + if (!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) + m_target->RemoveAurasDueToSpell(31665); + break; + // Killing Spree + case 51690: + { + // TODO: this should use effect[1] of 51690 + std::list<Unit*> targets; + { + // eff_radius ==0 + float radius = GetSpellMaxRange(spell, false); + + CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(),caster->GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + + MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck u_check(caster, caster, radius); + MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck> checker(caster,targets, u_check); + + TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); + TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnfriendlyVisibleUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); + + CellLock<GridReadGuard> cell_lock(cell, p); + + cell_lock->Visit(cell_lock, grid_object_checker, *caster->GetMap()); + cell_lock->Visit(cell_lock, world_object_checker, *caster->GetMap()); + } + + if(targets.empty()) + return; + + std::list<Unit*>::const_iterator itr = targets.begin(); + std::advance(itr, rand()%targets.size()); + Unit* target = *itr; + + caster->CastSpell(target, 57840, true); + caster->CastSpell(target, 57841, true); + return; + } + // Overkill + case 58428: + if (!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH)) + m_target->RemoveAurasDueToSpell(58427); + break; +// default: +// break; + } + break; + } + case SPELLFAMILY_HUNTER: + { + // Explosive Shot + if (spell->SpellFamilyFlags[1] & 0x80000000) + { + if(caster) + caster->CastCustomSpell(53352, SPELLVALUE_BASE_POINT0, m_amount, m_target, true, NULL, this); + return; + } + switch (spell->Id) + { + // Harpooner's Mark + // case 40084: + // return; + // Feeding Frenzy Rank 1 + case 53511: + if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 ) + m_target->CastSpell(m_target, 60096, true, 0, this); + return; + // Feeding Frenzy Rank 2 + case 53512: + if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 ) + m_target->CastSpell(m_target, 60097, true, 0, this); + return; + default: + break; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + // Astral Shift + if (spell->Id == 52179) + { + // Periodic need for remove visual on stun/fear/silence lost + if (!(m_target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))) + m_target->RemoveAurasDueToSpell(52179); + return; + } + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Death and Decay + if (spell->SpellFamilyFlags[0] & 0x20) + { + if (caster) + caster->CastCustomSpell(m_target, 52212, &m_amount, NULL, NULL, true, 0, this); + return; + } + // Chains of Ice + if (spell->SpellFamilyFlags[1] & 0x00004000) + { + // Get 0 effect aura + AuraEffect *slow = GetParentAura()->GetPartAura(0); + if (slow) + { + slow->ApplyModifier(false, true); + slow->SetAmount(slow->GetAmount() + GetAmount()); + if (slow->GetAmount() > 0) slow->SetAmount(0); + slow->ApplyModifier(true, true); + } + return; + } + // Summon Gargoyle +// if (spell->SpellFamilyFlags & 0x0000008000000000LL) +// return; + // Death Rune Mastery +// if (spell->SpellFamilyFlags & 0x0000000000004000LL) +// return; + // Bladed Armor + if (spell->SpellIconID == 2653) + { + // Increases your attack power by $s1 for every $s2 armor value you have. + // Calculate AP bonus (from 1 efect of this spell) + int32 apBonus = m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); + m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this); + return; + } + // Reaping +// if (spell->SpellIconID == 22) +// return; + // Blood of the North +// if (spell->SpellIconID == 30412) +// return; + break; + } default: break; } } -void Aura::HandlePreventFleeing(bool apply, bool Real) +void AuraEffect::HandlePreventFleeing(bool apply, bool Real, bool /*changeAmount*/) { if(!Real) return; - Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR); + Unit::AuraEffectList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR); if( !fearAuras.empty() ) { m_target->SetControlled(!apply, UNIT_STAT_FLEEING); @@ -6153,9 +6978,9 @@ void Aura::HandlePreventFleeing(bool apply, bool Real) } } -void Aura::HandleManaShield(bool apply, bool Real) +void AuraEffect::HandleManaShield(bool apply, bool Real, bool changeAmount) { - if(!Real) + if(!Real && !changeAmount) return; // prevent double apply bonuses @@ -6167,7 +6992,7 @@ void Aura::HandleManaShield(bool apply, bool Real) switch(m_spellProto->SpellFamilyName) { case SPELLFAMILY_MAGE: - if(m_spellProto->SpellFamilyFlags & 0x8000) + if(m_spellProto->SpellFamilyFlags[0] & 0x8000) { // Mana Shield // +50% from +spd bonus @@ -6181,12 +7006,12 @@ void Aura::HandleManaShield(bool apply, bool Real) DoneActualBenefit *= caster->CalculateLevelPenalty(GetSpellProto()); - m_modifier.m_amount += (int32)DoneActualBenefit; + m_amount += (int32)DoneActualBenefit; } } } -void Aura::HandleArenaPreparation(bool apply, bool Real) +void AuraEffect::HandleArenaPreparation(bool apply, bool Real, bool /*changeAmount*/) { if(!Real) return; @@ -6197,21 +7022,287 @@ void Aura::HandleArenaPreparation(bool apply, bool Real) m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); } -void Aura::UnregisterSingleCastAura() +/** + * Such auras are applied from a caster(=player) to a vehicle. + * This has been verified using spell #49256 + */ +void AuraEffect::HandleAuraControlVehicle(bool apply, bool Real, bool /*changeAmount*/) { - if (IsSingleTarget()) + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_UNIT || !((Creature*)m_target)->isVehicle()) + return; + + Unit *caster = GetSource(); + if(!caster || caster == m_target) + return; + + Vehicle * const vehicle = dynamic_cast<Vehicle * const>(m_target); + + if (apply) { - Unit* caster = NULL; - caster = GetCaster(); - if(caster) + //if(caster->GetTypeId() == TYPEID_PLAYER) + // if(Pet *pet = ((Player*)caster)->GetPet()) + // pet->Remove(PET_SAVE_AS_CURRENT); + caster->EnterVehicle(vehicle, m_amount - 1); + } + else + { + if(GetId() == 53111) // Devour Humanoid { - caster->GetSingleCastAuras().remove(this); + vehicle->Kill(caster); + if(caster->GetTypeId() == TYPEID_UNIT) + ((Creature*)caster)->RemoveCorpse(); + } + + // some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them + caster->RemoveAurasDueToSpell(GetId()); + caster->ExitVehicle(); + } +} + +void AuraEffect::HandleAuraConvertRune(bool apply, bool Real, bool /*changeAmount*/) +{ + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)m_target; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + // how to determine what rune need to be converted? + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + if(apply) + { + if(!plr->GetRuneCooldown(i)) + { + plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]); + break; + } } else { - sLog.outError("Couldn't find the caster of the single target aura, may crash later!"); - assert(false); + if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex]) + { + plr->ConvertRune(i, plr->GetBaseRune(i)); + break; + } } - m_isSingleTargetAura = false; } } + +// Control Auras + +void AuraEffect::HandleAuraModStun(bool apply, bool Real, bool /*changeAmount*/) +{ + if(!Real) + return; + + m_target->SetControlled(apply, UNIT_STAT_STUNNED); +} + +void AuraEffect::HandleAuraModRoot(bool apply, bool Real, bool /*changeAmount*/) +{ + if(!Real) + return; + + m_target->SetControlled(apply, UNIT_STAT_ROOT); +} + +// Charm Auras + +void AuraEffect::HandleModPossess(bool apply, bool Real, bool /*changeAmount*/) +{ + if(!Real) + return; + + Unit* caster = GetCaster(); + if(caster && caster->GetTypeId() == TYPEID_UNIT) + { + HandleModCharm(apply, Real, false); + return; + } + + if(apply) + { + if(m_target->getLevel() > m_amount) + return; + + m_target->SetCharmedBy(caster, CHARM_TYPE_POSSESS); + } + else + m_target->RemoveCharmedBy(caster); +} + +void AuraEffect::HandleModPossessPet(bool apply, bool Real, bool /*changeAmount*/) +{ + if(!Real) + return; + + Unit* caster = GetCaster(); + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + + if(apply) + { + if(caster->GetGuardianPet() != m_target) + return; + + m_target->SetCharmedBy(caster, CHARM_TYPE_POSSESS); + } + else + { + m_target->RemoveCharmedBy(caster); + + // Reinitialize the pet bar and make the pet come back to the owner + ((Player*)caster)->PetSpellInitialize(); + if(!m_target->getVictim()) + { + m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); + } + } +} + +void AuraEffect::HandleModCharm(bool apply, bool Real, bool /*changeAmount*/) +{ + if(!Real) + return; + + Unit* caster = GetCaster(); + + if(apply) + { + if(m_amount && int32(m_target->getLevel()) > m_amount) + return; + + m_target->SetCharmedBy(caster, CHARM_TYPE_CHARM); + } + else + m_target->RemoveCharmedBy(caster); +} + +void AuraEffect::HandleCharmConvert(bool apply, bool Real, bool /*changeAmount*/) +{ + if(!Real) + return; + + Unit* caster = GetCaster(); + + if(apply) + { + if(m_amount && int32(m_target->getLevel()) > m_amount) + return; + + m_target->SetCharmedBy(caster, CHARM_TYPE_CONVERT); + } + else + m_target->RemoveCharmedBy(caster); +} + +void AuraEffect::HandlePhase(bool apply, bool Real, bool /*changeAmount*/) +{ + if(!Real) + return; + + // always non stackable + if(apply) + { + m_target->RemoveAurasByType(SPELL_AURA_PHASE, NULL, GetParentAura()); + } + + // 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(m_target->GetTypeId()==TYPEID_PLAYER) + { + // drop flag at invisible in bg + if(((Player*)m_target)->InBattleGround()) + if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) + bg->EventPlayerDroppedFlag((Player*)m_target); + + // GM-mode have mask 0xFFFFFFFF + if(!((Player*)m_target)->isGameMaster()) + m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false); + + ((Player*)m_target)->GetSession()->SendSetPhaseShift(apply ? GetMiscValue() : PHASEMASK_NORMAL); + + if(GetEffIndex()==0) + { + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); + if(saBounds.first != saBounds.second) + { + uint32 zone, area; + m_target->GetZoneAndAreaId(zone,area); + + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + { + // some auras remove at aura remove + if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area)) + m_target->RemoveAurasDueToSpell(itr->second->spellId); + // some auras applied at aura apply + else if(itr->second->autocast) + { + if( !m_target->HasAura(itr->second->spellId) ) + m_target->CastSpell(m_target,itr->second->spellId,true); + } + } + } + } + } + else + m_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(m_target->GetVisibility()!=VISIBILITY_OFF) + m_target->SetVisibility(m_target->GetVisibility()); +} + +void AuraEffect::HandleAuraSafeFall( bool Apply, bool Real , bool /*changeAmount*/) +{ + // implemented in WorldSession::HandleMovementOpcodes + + // only special case + if(Apply && Real && GetId()==32474 && m_target->GetTypeId()==TYPEID_PLAYER) + ((Player*)m_target)->ActivateTaxiPathTo(506,GetId()); +} + +void AuraEffect::HandleModArmorPenetrationPct(bool apply, bool Real, bool changeAmount) +{ + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + ((Player*)m_target)->RecalculateRating(CR_ARMOR_PENETRATION); +} + +void AuraEffect::HandleReflectSpells( bool Apply, bool Real , bool /*changeAmount*/) +{ + // implemented in Unit::SpellHitResult + + // only special case + if(!Apply && Real && m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x2) + { + if (Unit * caster = GetCaster()) + { + // Improved Spell Reflection + if (caster->GetDummyAura(SPELLFAMILY_WARRIOR,1935)) + { + // aura remove - remove auras from all party members + std::list<Unit*> PartyMembers; + m_target->GetPartyMembers(PartyMembers); + for (std::list<Unit*>::iterator itr = PartyMembers.begin();itr!=PartyMembers.end();++itr) + { + if ((*itr)!= m_target) + (*itr)->RemoveAurasWithFamily(SPELLFAMILY_WARRIOR, 0, 0x2, 0, GetCasterGUID()); + } + } + } + } +} + |