diff options
author | Shauren <shauren.trinity@gmail.com> | 2022-05-01 20:01:13 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-05-01 20:01:13 +0200 |
commit | 8d16a79dea4c0100d36e13b068c42499a3a48154 (patch) | |
tree | b7eb987d783e46e9fb74da6bec06dc1b91e29f14 | |
parent | 524d14a162e8d032ad3324acf7cd2ebea5c29fc6 (diff) |
Core/Spells: Rename SpellAttr4 to use official attribute names
* Corrected implementation of SPELL_ATTR4_CLASS_TRIGGER_ONLY_ON_TARGET
* Implemented SPELL_ATTR4_NO_HELPFUL_THREAT
* Implemented SPELL_ATTR4_NO_PARTIAL_IMMUNITY
* Implemented SPELL_ATTR4_ALLOW_PROC_WHILE_SITTING
* Implemented SPELL_ATTR4_USE_FACING_FROM_SPELL
* Implemented SPELL_ATTR4_BOUNCY_CHAIN_MISSILES
* Implemented SPELL_ATTR4_AURA_NEVER_BOUNCES
* Implemented SPELL_ATTR4_AURA_BOUNCE_FAILS_SPELL
* Implemented SPELL_ATTR4_AURA_IS_BUFF
* Implemented SPELL_ATTR5_MELEE_CHAIN_TARGETING
* Implemented SpellEffectAttributes::ChainFromInitialTarget
-rw-r--r-- | src/server/game/Combat/ThreatManager.cpp | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCEnums.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 21 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 23 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 2 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 66 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp | 186 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 11 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 138 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 6 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 9 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 8 |
15 files changed, 257 insertions, 223 deletions
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index 2e0c0f7eba3..ea41b10e61e 100644 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -661,7 +661,7 @@ void ThreatManager::ProcessAIUpdates() void ThreatManager::ForwardThreatForAssistingMe(Unit* assistant, float baseAmount, SpellInfo const* spell, bool ignoreModifiers) { - if (spell && spell->HasAttribute(SPELL_ATTR1_NO_THREAT)) // shortcut, none of the calls would do anything + if (spell && (spell->HasAttribute(SPELL_ATTR1_NO_THREAT) || spell->HasAttribute(SPELL_ATTR4_NO_HELPFUL_THREAT))) // shortcut, none of the calls would do anything return; if (_threatenedByMe.empty()) return; diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index d8fdd7b5237..bd6b9d4cb15 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -1499,6 +1499,7 @@ enum class SpellEffectAttributes None = 0, UnaffectedByInvulnerability = 0x000001, // not cancelled by immunities NoScaleWithStack = 0x000040, + ChainFromInitialTarget = 0x000080, StackAuraAmountOnRecast = 0x008000, // refreshing periodic auras with this attribute will add remaining damage to new aura AllowAnyExplicitTarget = 0x100000, IgnoreDuringCooldownTimeRateCalculation = 0x800000 diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index baba65fca1d..818b09ca171 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2357,27 +2357,6 @@ void Creature::LoadTemplateImmunities() } } -bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster) const -{ - if (!spellInfo) - return false; - - bool immunedToAllEffects = true; - for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects()) - { - if (spellEffectInfo.IsEffect() && !IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster)) - { - immunedToAllEffects = false; - break; - } - } - - if (immunedToAllEffects) - return true; - - return Unit::IsImmunedToSpell(spellInfo, caster); -} - bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const { if (GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL)) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 2c5b1820f4b..a746021f3d3 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -150,7 +150,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool CanResetTalents(Player* player) const; bool CanCreatureAttack(Unit const* victim, bool force = true) const; void LoadTemplateImmunities(); - bool IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster) const override; bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster) const override; bool isElite() const; bool isWorldBoss() const; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 7aca0596c47..2dd429741f4 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -758,7 +758,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons // interrupting auras with SpellAuraInterruptFlags::Damage before checking !damage (absorbed damage breaks that type of auras) if (spellProto) { - if (!spellProto->HasAttribute(SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS)) + if (!spellProto->HasAttribute(SPELL_ATTR4_REACTIVE_DAMAGE_PROC)) victim->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Damage, spellProto); } else @@ -964,7 +964,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(SPELL_AURA_DAMAGE_SHIELD))) victim->ToCreature()->SetLastDamagedTime(GameTime::GetGameTime() + MAX_AGGRO_RESET_TIME); - if (attacker) + if (attacker && (!spellProto || !spellProto->HasAttribute(SPELL_ATTR4_NO_HARMFUL_THREAT))) victim->GetThreatManager().AddThreat(attacker, float(damage), spellProto); } else // victim is a player @@ -1082,8 +1082,8 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama SpellSchoolMask damageSchoolMask = SpellSchoolMask(damageInfo->schoolMask); - // Spells with SPELL_ATTR4_FIXED_DAMAGE ignore resilience because their damage is based off another spell's damage. - if (!spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) + // Spells with SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS ignore resilience because their damage is based off another spell's damage. + if (!spellInfo->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS)) { if (Unit::IsDamageReducedByArmor(damageSchoolMask, spellInfo)) damage = Unit::CalcArmorReducedDamage(damageInfo->attacker, victim, damage, spellInfo, attackType); @@ -1647,13 +1647,6 @@ void Unit::HandleEmoteCommand(Emote emoteId, Player* target /*=nullptr*/, Trinit if ((schoolMask & SPELL_SCHOOL_MASK_HOLY) && victim->GetTypeId() != TYPEID_UNIT) return 0; - // Ignore spells that can't be resisted - if (spellInfo) - { - if (spellInfo->HasAttribute(SPELL_ATTR4_IGNORE_RESISTANCES)) - return 0; - } - float const averageResist = Unit::CalculateAverageResistReduction(attacker, schoolMask, victim, spellInfo); float discreteResistProbability[11] = { }; if (averageResist <= 0.1f) @@ -4151,7 +4144,7 @@ void Unit::RemoveArenaAuras() RemoveAppliedAuras([](AuraApplication const* aurApp) { Aura const* aura = aurApp->GetBase(); - return (!aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_DONT_REMOVE_IN_ARENA) // don't remove stances, shadowform, pally/hunter auras + return (!aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_ALLOW_ENTERING_ARENA) // don't remove stances, shadowform, pally/hunter auras && !aura->IsPassive() // don't remove passive auras && (aurApp->IsPositive() || !aura->GetSpellInfo()->HasAttribute(SPELL_ATTR3_ALLOW_AURA_WHILE_DEAD))) || // not negative death persistent auras aura->GetSpellInfo()->HasAttribute(SPELL_ATTR5_REMOVE_ENTERING_ARENA); // special marker, always remove @@ -6634,8 +6627,8 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui if (cheatDeath->GetMiscValue() & SPELL_SCHOOL_MASK_NORMAL) AddPct(TakenTotalMod, cheatDeath->GetAmount()); - // Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras. - if (!spellProto->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) + // Spells with SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS should only benefit from mechanic damage mod auras. + if (!spellProto->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS)) { // Versatility if (Player* modOwner = GetSpellModOwner()) @@ -7256,6 +7249,8 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caste immuneToAllEffects = false; break; } + if (spellInfo->HasAttribute(SPELL_ATTR4_NO_PARTIAL_IMMUNITY)) + return true; } if (immuneToAllEffects) //Return immune only if the target is immune to all spell effects. diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 1a19d0d1fde..273ce6cd4be 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1708,7 +1708,7 @@ class TC_GAME_API Unit : public WorldObject static uint32 SpellCriticalHealingBonus(Unit const* caster, SpellInfo const* spellProto, uint32 damage, Unit* victim); void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); - virtual bool IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster) const; + bool IsImmunedToSpell(SpellInfo const* spellInfo, WorldObject const* caster) const; uint32 GetSchoolImmunityMask() const; uint32 GetDamageImmunityMask() const; uint32 GetMechanicImmunityMask() const; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index d42987d37c4..af4eecebde0 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -552,38 +552,38 @@ enum SpellAttr3 : uint32 // EnumUtils: DESCRIBE THIS enum SpellAttr4 : uint32 { - SPELL_ATTR4_IGNORE_RESISTANCES = 0x00000001, // TITLE Cannot be resisted - SPELL_ATTR4_PROC_ONLY_ON_CASTER = 0x00000002, // TITLE Only proc on self-cast - SPELL_ATTR4_AURA_EXPIRES_OFFLINE = 0x00000004, // TITLE Aura Expires Offline DESCRIPTION Debuffs (except Resurrection Sickness) will automatically do this - SPELL_ATTR4_UNK3 = 0x00000008, // TITLE Unknown attribute 3@Attr4 - SPELL_ATTR4_UNK4 = 0x00000010, // TITLE Treat as delayed spell - SPELL_ATTR4_UNK5 = 0x00000020, // TITLE Unknown attribute 5@Attr4 - SPELL_ATTR4_NOT_STEALABLE = 0x00000040, // TITLE Aura cannot be stolen - SPELL_ATTR4_CAN_CAST_WHILE_CASTING = 0x00000080, // TITLE Can be cast while casting DESCRIPTION Ignores already in-progress cast and still casts - SPELL_ATTR4_FIXED_DAMAGE = 0x00000100, // TITLE Deals fixed damage - SPELL_ATTR4_TRIGGER_ACTIVATE = 0x00000200, // TITLE Spell is initially disabled (client only) - SPELL_ATTR4_SPELL_VS_EXTEND_COST = 0x00000400, // TITLE Attack speed modifies cost DESCRIPTION Adds 10 to power cost for each 1s of weapon speed - SPELL_ATTR4_UNK11 = 0x00000800, // TITLE Unknown attribute 11@Attr4 - SPELL_ATTR4_UNK12 = 0x00001000, // TITLE Unknown attribute 12@Attr4 - SPELL_ATTR4_COMBAT_LOG_NO_CASTER = 0x00002000, // TITLE Do Not Log Caster - SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS = 0x00004000, // TITLE Damage does not break auras - SPELL_ATTR4_HIDDEN_IN_SPELLBOOK = 0x00008000, // TITLE Not In Spellbook - SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG = 0x00010000, // TITLE Not In Arena or Rated Battleground DESCRIPTION Makes spell unusable despite CD <= 10min - SPELL_ATTR4_USABLE_IN_ARENA = 0x00020000, // TITLE Usable in arena DESCRIPTION Makes spell usable despite CD > 10min - SPELL_ATTR4_AREA_TARGET_CHAIN = 0x00040000, // TITLE Chain area targets DESCRIPTION [NYI] Hits area targets over time instead of all at once - SPELL_ATTR4_UNK19 = 0x00080000, // TITLE Unknown attribute 19@Attr4 - SPELL_ATTR4_NOT_CHECK_SELFCAST_POWER = 0x00100000, // TITLE Allow self-cast to override stronger aura (client only) - SPELL_ATTR4_DONT_REMOVE_IN_ARENA = 0x00200000, // TITLE Allow Entering Arena - SPELL_ATTR4_UNK22 = 0x00400000, // TITLE Unknown attribute 22@Attr4 - SPELL_ATTR4_SUPPRESS_WEAPON_PROCS = 0x00800000, // TITLE Suppress Weapon Procs - SPELL_ATTR4_UNK24 = 0x01000000, // TITLE Unknown attribute 24@Attr4 DESCRIPTION Shoot-type spell? - SPELL_ATTR4_IS_PET_SCALING = 0x02000000, // TITLE Pet Scaling aura - SPELL_ATTR4_CAST_ONLY_IN_OUTLAND = 0x04000000, // TITLE Only in Outland/Northrend - SPELL_ATTR4_UNK27 = 0x08000000, // TITLE Unknown attribute 27@Attr4 - SPELL_ATTR4_UNK28 = 0x10000000, // TITLE Unknown attribute 28@Attr4 - SPELL_ATTR4_UNK29 = 0x20000000, // TITLE Unknown attribute 29@Attr4 - SPELL_ATTR4_UNK30 = 0x40000000, // TITLE Unknown attribute 30@Attr4 - SPELL_ATTR4_UNK31 = 0x80000000 // TITLE Unknown attribute 31@Attr4 + SPELL_ATTR4_NO_CAST_LOG = 0x00000001, // TITLE No Cast Log + SPELL_ATTR4_CLASS_TRIGGER_ONLY_ON_TARGET = 0x00000002, // TITLE Class Trigger Only On Target + SPELL_ATTR4_AURA_EXPIRES_OFFLINE = 0x00000004, // TITLE Aura Expires Offline DESCRIPTION Debuffs (except Resurrection Sickness) will automatically do this + SPELL_ATTR4_NO_HELPFUL_THREAT = 0x00000008, // TITLE No Helpful Threat + SPELL_ATTR4_NO_HARMFUL_THREAT = 0x00000010, // TITLE No Harmful Threat + SPELL_ATTR4_ALLOW_CLIENT_TARGETING = 0x00000020, // TITLE Allow Client Targeting DESCRIPTION Allows client to send spell targets for this spell. Applies only to pet spells, without this attribute CMSG_PET_ACTION is sent instead of CMSG_PET_CAST_SPELL + SPELL_ATTR4_CANNOT_BE_STOLEN = 0x00000040, // TITLE Cannot Be Stolen + SPELL_ATTR4_ALLOW_CAST_WHILE_CASTING = 0x00000080, // TITLE Allow Cast While Casting DESCRIPTION Ignores already in-progress cast and still casts + SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS = 0x00000100, // TITLE Ignore Damage Taken Modifiers + SPELL_ATTR4_COMBAT_FEEDBACK_WHEN_USABLE = 0x00000200, // TITLE Combat Feedback When Usable (client only) + SPELL_ATTR4_WEAPON_SPEED_COST_SCALING = 0x00000400, // TITLE Weapon Speed Cost Scaling DESCRIPTION Adds 10 to power cost for each 1s of weapon speed + SPELL_ATTR4_NO_PARTIAL_IMMUNITY = 0x00000800, // TITLE No Partial Immunity + SPELL_ATTR4_AURA_IS_BUFF = 0x00001000, // TITLE Aura Is Buff + SPELL_ATTR4_DO_NOT_LOG_CASTER = 0x00002000, // TITLE Do Not Log Caster + SPELL_ATTR4_REACTIVE_DAMAGE_PROC = 0x00004000, // TITLE Reactive Damage Proc DESCRIPTION Damage from spells with this attribute doesn't break auras that normally break on damage taken + SPELL_ATTR4_NOT_IN_SPELLBOOK = 0x00008000, // TITLE Not In Spellbook + SPELL_ATTR4_NOT_IN_ARENA_OR_RATED_BATTLEGROUND = 0x00010000, // TITLE Not In Arena or Rated Battleground DESCRIPTION Makes spell unusable despite CD <= 10min + SPELL_ATTR4_IGNORE_DEFAULT_ARENA_RESTRICTIONS = 0x00020000, // TITLE Ignore Default Arena Restrictions DESCRIPTION Makes spell usable despite CD > 10min + SPELL_ATTR4_BOUNCY_CHAIN_MISSILES = 0x00040000, // TITLE Bouncy Chain Missiles DESCRIPTION Hits area targets over time instead of all at once + SPELL_ATTR4_ALLOW_PROC_WHILE_SITTING = 0x00080000, // TITLE Allow Proc While Sitting + SPELL_ATTR4_AURA_NEVER_BOUNCES = 0x00100000, // TITLE Aura Never Bounces + SPELL_ATTR4_ALLOW_ENTERING_ARENA = 0x00200000, // TITLE Allow Entering Arena + SPELL_ATTR4_PROC_SUPPRESS_SWING_ANIM = 0x00400000, // TITLE Proc Suppress Swing Anim + SPELL_ATTR4_SUPPRESS_WEAPON_PROCS = 0x00800000, // TITLE Suppress Weapon Procs + SPELL_ATTR4_AUTO_RANGED_COMBAT = 0x01000000, // TITLE Auto Ranged Combat + SPELL_ATTR4_OWNER_POWER_SCALING = 0x02000000, // TITLE Owner Power Scaling + SPELL_ATTR4_ONLY_FLYING_AREAS = 0x04000000, // TITLE Only Flying Areas + SPELL_ATTR4_FORCE_DISPLAY_CASTBAR = 0x08000000, // TITLE Force Display Castbar + SPELL_ATTR4_IGNORE_COMBAT_TIMER = 0x10000000, // TITLE Ignore Combat Timer + SPELL_ATTR4_AURA_BOUNCE_FAILS_SPELL = 0x20000000, // TITLE Aura Bounce Fails Spell + SPELL_ATTR4_OBSOLETE = 0x40000000, // TITLE Obsolete + SPELL_ATTR4_USE_FACING_FROM_SPELL = 0x80000000 // TITLE Use Facing From Spell }; // EnumUtils: DESCRIBE THIS @@ -601,7 +601,7 @@ enum SpellAttr5 : uint32 SPELL_ATTR5_START_PERIODIC_AT_APPLY = 0x00000200, // TITLE Immediately do periodic tick on apply SPELL_ATTR5_HIDE_DURATION = 0x00000400, // TITLE Do not send aura duration to client SPELL_ATTR5_ALLOW_TARGET_OF_TARGET_AS_TARGET = 0x00000800, // TITLE Auto-target target of target (client only) - SPELL_ATTR5_UNK12 = 0x00001000, // TITLE Unknown attribute 12@Attr5 DESCRIPTION Cleave related? + SPELL_ATTR5_MELEE_CHAIN_TARGETING = 0x00001000, // TITLE Unknown attribute 12@Attr5 DESCRIPTION Cleave related? SPELL_ATTR5_HASTE_AFFECT_DURATION = 0x00002000, // TITLE Duration scales with Haste Rating SPELL_ATTR5_NOT_USABLE_WHILE_CHARMED = 0x00004000, // TITLE Not Available While Charmed SPELL_ATTR5_UNK15 = 0x00008000, // TITLE Unknown attribute 15@Attr5 DESCRIPTION Related to multi-target spells? diff --git a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp index d10ba44c58d..865018aa03c 100644 --- a/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp +++ b/src/server/game/Miscellaneous/enuminfo_SharedDefines.cpp @@ -763,38 +763,38 @@ TC_API_EXPORT EnumText EnumUtils<SpellAttr4>::ToString(SpellAttr4 value) { switch (value) { - case SPELL_ATTR4_IGNORE_RESISTANCES: return { "SPELL_ATTR4_IGNORE_RESISTANCES", "Cannot be resisted", "" }; - case SPELL_ATTR4_PROC_ONLY_ON_CASTER: return { "SPELL_ATTR4_PROC_ONLY_ON_CASTER", "Only proc on self-cast", "" }; + case SPELL_ATTR4_NO_CAST_LOG: return { "SPELL_ATTR4_NO_CAST_LOG", "No Cast Log", "" }; + case SPELL_ATTR4_CLASS_TRIGGER_ONLY_ON_TARGET: return { "SPELL_ATTR4_CLASS_TRIGGER_ONLY_ON_TARGET", "Class Trigger Only On Target", "" }; case SPELL_ATTR4_AURA_EXPIRES_OFFLINE: return { "SPELL_ATTR4_AURA_EXPIRES_OFFLINE", "Aura Expires Offline", "Debuffs (except Resurrection Sickness) will automatically do this" }; - case SPELL_ATTR4_UNK3: return { "SPELL_ATTR4_UNK3", "Unknown attribute 3@Attr4", "" }; - case SPELL_ATTR4_UNK4: return { "SPELL_ATTR4_UNK4", "Treat as delayed spell", "" }; - case SPELL_ATTR4_UNK5: return { "SPELL_ATTR4_UNK5", "Unknown attribute 5@Attr4", "" }; - case SPELL_ATTR4_NOT_STEALABLE: return { "SPELL_ATTR4_NOT_STEALABLE", "Aura cannot be stolen", "" }; - case SPELL_ATTR4_CAN_CAST_WHILE_CASTING: return { "SPELL_ATTR4_CAN_CAST_WHILE_CASTING", "Can be cast while casting", "Ignores already in-progress cast and still casts" }; - case SPELL_ATTR4_FIXED_DAMAGE: return { "SPELL_ATTR4_FIXED_DAMAGE", "Deals fixed damage", "" }; - case SPELL_ATTR4_TRIGGER_ACTIVATE: return { "SPELL_ATTR4_TRIGGER_ACTIVATE", "Spell is initially disabled (client only)", "" }; - case SPELL_ATTR4_SPELL_VS_EXTEND_COST: return { "SPELL_ATTR4_SPELL_VS_EXTEND_COST", "Attack speed modifies cost", "Adds 10 to power cost for each 1s of weapon speed" }; - case SPELL_ATTR4_UNK11: return { "SPELL_ATTR4_UNK11", "Unknown attribute 11@Attr4", "" }; - case SPELL_ATTR4_UNK12: return { "SPELL_ATTR4_UNK12", "Unknown attribute 12@Attr4", "" }; - case SPELL_ATTR4_COMBAT_LOG_NO_CASTER: return { "SPELL_ATTR4_COMBAT_LOG_NO_CASTER", "Do Not Log Caster", "" }; - case SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS: return { "SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS", "Damage does not break auras", "" }; - case SPELL_ATTR4_HIDDEN_IN_SPELLBOOK: return { "SPELL_ATTR4_HIDDEN_IN_SPELLBOOK", "Not In Spellbook", "" }; - case SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG: return { "SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG", "Not In Arena or Rated Battleground", "Makes spell unusable despite CD <= 10min" }; - case SPELL_ATTR4_USABLE_IN_ARENA: return { "SPELL_ATTR4_USABLE_IN_ARENA", "Usable in arena", "Makes spell usable despite CD > 10min" }; - case SPELL_ATTR4_AREA_TARGET_CHAIN: return { "SPELL_ATTR4_AREA_TARGET_CHAIN", "Chain area targets", "[NYI] Hits area targets over time instead of all at once" }; - case SPELL_ATTR4_UNK19: return { "SPELL_ATTR4_UNK19", "Unknown attribute 19@Attr4", "" }; - case SPELL_ATTR4_NOT_CHECK_SELFCAST_POWER: return { "SPELL_ATTR4_NOT_CHECK_SELFCAST_POWER", "Allow self-cast to override stronger aura (client only)", "" }; - case SPELL_ATTR4_DONT_REMOVE_IN_ARENA: return { "SPELL_ATTR4_DONT_REMOVE_IN_ARENA", "Allow Entering Arena", "" }; - case SPELL_ATTR4_UNK22: return { "SPELL_ATTR4_UNK22", "Unknown attribute 22@Attr4", "" }; + case SPELL_ATTR4_NO_HELPFUL_THREAT: return { "SPELL_ATTR4_NO_HELPFUL_THREAT", "No Helpful Threat", "" }; + case SPELL_ATTR4_NO_HARMFUL_THREAT: return { "SPELL_ATTR4_NO_HARMFUL_THREAT", "No Harmful Threat", "" }; + case SPELL_ATTR4_ALLOW_CLIENT_TARGETING: return { "SPELL_ATTR4_ALLOW_CLIENT_TARGETING", "Allow Client Targeting", "Allows client to send spell targets for this spell. Applies only to pet spells, without this attribute CMSG_PET_ACTION is sent instead of CMSG_PET_CAST_SPELL" }; + case SPELL_ATTR4_CANNOT_BE_STOLEN: return { "SPELL_ATTR4_CANNOT_BE_STOLEN", "Cannot Be Stolen", "" }; + case SPELL_ATTR4_ALLOW_CAST_WHILE_CASTING: return { "SPELL_ATTR4_ALLOW_CAST_WHILE_CASTING", "Allow Cast While Casting", "Ignores already in-progress cast and still casts" }; + case SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS: return { "SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS", "Ignore Damage Taken Modifiers", "" }; + case SPELL_ATTR4_COMBAT_FEEDBACK_WHEN_USABLE: return { "SPELL_ATTR4_COMBAT_FEEDBACK_WHEN_USABLE", "Combat Feedback When Usable (client only)", "" }; + case SPELL_ATTR4_WEAPON_SPEED_COST_SCALING: return { "SPELL_ATTR4_WEAPON_SPEED_COST_SCALING", "Weapon Speed Cost Scaling", "Adds 10 to power cost for each 1s of weapon speed" }; + case SPELL_ATTR4_NO_PARTIAL_IMMUNITY: return { "SPELL_ATTR4_NO_PARTIAL_IMMUNITY", "No Partial Immunity", "" }; + case SPELL_ATTR4_AURA_IS_BUFF: return { "SPELL_ATTR4_AURA_IS_BUFF", "Aura Is Buff", "" }; + case SPELL_ATTR4_DO_NOT_LOG_CASTER: return { "SPELL_ATTR4_DO_NOT_LOG_CASTER", "Do Not Log Caster", "" }; + case SPELL_ATTR4_REACTIVE_DAMAGE_PROC: return { "SPELL_ATTR4_REACTIVE_DAMAGE_PROC", "Reactive Damage Proc", "Damage from spells with this attribute doesn't break auras that normally break on damage taken" }; + case SPELL_ATTR4_NOT_IN_SPELLBOOK: return { "SPELL_ATTR4_NOT_IN_SPELLBOOK", "Not In Spellbook", "" }; + case SPELL_ATTR4_NOT_IN_ARENA_OR_RATED_BATTLEGROUND: return { "SPELL_ATTR4_NOT_IN_ARENA_OR_RATED_BATTLEGROUND", "Not In Arena or Rated Battleground", "Makes spell unusable despite CD <= 10min" }; + case SPELL_ATTR4_IGNORE_DEFAULT_ARENA_RESTRICTIONS: return { "SPELL_ATTR4_IGNORE_DEFAULT_ARENA_RESTRICTIONS", "Ignore Default Arena Restrictions", "Makes spell usable despite CD > 10min" }; + case SPELL_ATTR4_BOUNCY_CHAIN_MISSILES: return { "SPELL_ATTR4_BOUNCY_CHAIN_MISSILES", "Bouncy Chain Missiles", "Hits area targets over time instead of all at once" }; + case SPELL_ATTR4_ALLOW_PROC_WHILE_SITTING: return { "SPELL_ATTR4_ALLOW_PROC_WHILE_SITTING", "Allow Proc While Sitting", "" }; + case SPELL_ATTR4_AURA_NEVER_BOUNCES: return { "SPELL_ATTR4_AURA_NEVER_BOUNCES", "Aura Never Bounces", "" }; + case SPELL_ATTR4_ALLOW_ENTERING_ARENA: return { "SPELL_ATTR4_ALLOW_ENTERING_ARENA", "Allow Entering Arena", "" }; + case SPELL_ATTR4_PROC_SUPPRESS_SWING_ANIM: return { "SPELL_ATTR4_PROC_SUPPRESS_SWING_ANIM", "Proc Suppress Swing Anim", "" }; case SPELL_ATTR4_SUPPRESS_WEAPON_PROCS: return { "SPELL_ATTR4_SUPPRESS_WEAPON_PROCS", "Suppress Weapon Procs", "" }; - case SPELL_ATTR4_UNK24: return { "SPELL_ATTR4_UNK24", "Unknown attribute 24@Attr4", "Shoot-type spell?" }; - case SPELL_ATTR4_IS_PET_SCALING: return { "SPELL_ATTR4_IS_PET_SCALING", "Pet Scaling aura", "" }; - case SPELL_ATTR4_CAST_ONLY_IN_OUTLAND: return { "SPELL_ATTR4_CAST_ONLY_IN_OUTLAND", "Only in Outland/Northrend", "" }; - case SPELL_ATTR4_UNK27: return { "SPELL_ATTR4_UNK27", "Unknown attribute 27@Attr4", "" }; - case SPELL_ATTR4_UNK28: return { "SPELL_ATTR4_UNK28", "Unknown attribute 28@Attr4", "" }; - case SPELL_ATTR4_UNK29: return { "SPELL_ATTR4_UNK29", "Unknown attribute 29@Attr4", "" }; - case SPELL_ATTR4_UNK30: return { "SPELL_ATTR4_UNK30", "Unknown attribute 30@Attr4", "" }; - case SPELL_ATTR4_UNK31: return { "SPELL_ATTR4_UNK31", "Unknown attribute 31@Attr4", "" }; + case SPELL_ATTR4_AUTO_RANGED_COMBAT: return { "SPELL_ATTR4_AUTO_RANGED_COMBAT", "Auto Ranged Combat", "" }; + case SPELL_ATTR4_OWNER_POWER_SCALING: return { "SPELL_ATTR4_OWNER_POWER_SCALING", "Owner Power Scaling", "" }; + case SPELL_ATTR4_ONLY_FLYING_AREAS: return { "SPELL_ATTR4_ONLY_FLYING_AREAS", "Only Flying Areas", "" }; + case SPELL_ATTR4_FORCE_DISPLAY_CASTBAR: return { "SPELL_ATTR4_FORCE_DISPLAY_CASTBAR", "Force Display Castbar", "" }; + case SPELL_ATTR4_IGNORE_COMBAT_TIMER: return { "SPELL_ATTR4_IGNORE_COMBAT_TIMER", "Ignore Combat Timer", "" }; + case SPELL_ATTR4_AURA_BOUNCE_FAILS_SPELL: return { "SPELL_ATTR4_AURA_BOUNCE_FAILS_SPELL", "Aura Bounce Fails Spell", "" }; + case SPELL_ATTR4_OBSOLETE: return { "SPELL_ATTR4_OBSOLETE", "Obsolete", "" }; + case SPELL_ATTR4_USE_FACING_FROM_SPELL: return { "SPELL_ATTR4_USE_FACING_FROM_SPELL", "Use Facing From Spell", "" }; default: throw std::out_of_range("value"); } } @@ -807,38 +807,38 @@ TC_API_EXPORT SpellAttr4 EnumUtils<SpellAttr4>::FromIndex(size_t index) { switch (index) { - case 0: return SPELL_ATTR4_IGNORE_RESISTANCES; - case 1: return SPELL_ATTR4_PROC_ONLY_ON_CASTER; + case 0: return SPELL_ATTR4_NO_CAST_LOG; + case 1: return SPELL_ATTR4_CLASS_TRIGGER_ONLY_ON_TARGET; case 2: return SPELL_ATTR4_AURA_EXPIRES_OFFLINE; - case 3: return SPELL_ATTR4_UNK3; - case 4: return SPELL_ATTR4_UNK4; - case 5: return SPELL_ATTR4_UNK5; - case 6: return SPELL_ATTR4_NOT_STEALABLE; - case 7: return SPELL_ATTR4_CAN_CAST_WHILE_CASTING; - case 8: return SPELL_ATTR4_FIXED_DAMAGE; - case 9: return SPELL_ATTR4_TRIGGER_ACTIVATE; - case 10: return SPELL_ATTR4_SPELL_VS_EXTEND_COST; - case 11: return SPELL_ATTR4_UNK11; - case 12: return SPELL_ATTR4_UNK12; - case 13: return SPELL_ATTR4_COMBAT_LOG_NO_CASTER; - case 14: return SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS; - case 15: return SPELL_ATTR4_HIDDEN_IN_SPELLBOOK; - case 16: return SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG; - case 17: return SPELL_ATTR4_USABLE_IN_ARENA; - case 18: return SPELL_ATTR4_AREA_TARGET_CHAIN; - case 19: return SPELL_ATTR4_UNK19; - case 20: return SPELL_ATTR4_NOT_CHECK_SELFCAST_POWER; - case 21: return SPELL_ATTR4_DONT_REMOVE_IN_ARENA; - case 22: return SPELL_ATTR4_UNK22; + case 3: return SPELL_ATTR4_NO_HELPFUL_THREAT; + case 4: return SPELL_ATTR4_NO_HARMFUL_THREAT; + case 5: return SPELL_ATTR4_ALLOW_CLIENT_TARGETING; + case 6: return SPELL_ATTR4_CANNOT_BE_STOLEN; + case 7: return SPELL_ATTR4_ALLOW_CAST_WHILE_CASTING; + case 8: return SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS; + case 9: return SPELL_ATTR4_COMBAT_FEEDBACK_WHEN_USABLE; + case 10: return SPELL_ATTR4_WEAPON_SPEED_COST_SCALING; + case 11: return SPELL_ATTR4_NO_PARTIAL_IMMUNITY; + case 12: return SPELL_ATTR4_AURA_IS_BUFF; + case 13: return SPELL_ATTR4_DO_NOT_LOG_CASTER; + case 14: return SPELL_ATTR4_REACTIVE_DAMAGE_PROC; + case 15: return SPELL_ATTR4_NOT_IN_SPELLBOOK; + case 16: return SPELL_ATTR4_NOT_IN_ARENA_OR_RATED_BATTLEGROUND; + case 17: return SPELL_ATTR4_IGNORE_DEFAULT_ARENA_RESTRICTIONS; + case 18: return SPELL_ATTR4_BOUNCY_CHAIN_MISSILES; + case 19: return SPELL_ATTR4_ALLOW_PROC_WHILE_SITTING; + case 20: return SPELL_ATTR4_AURA_NEVER_BOUNCES; + case 21: return SPELL_ATTR4_ALLOW_ENTERING_ARENA; + case 22: return SPELL_ATTR4_PROC_SUPPRESS_SWING_ANIM; case 23: return SPELL_ATTR4_SUPPRESS_WEAPON_PROCS; - case 24: return SPELL_ATTR4_UNK24; - case 25: return SPELL_ATTR4_IS_PET_SCALING; - case 26: return SPELL_ATTR4_CAST_ONLY_IN_OUTLAND; - case 27: return SPELL_ATTR4_UNK27; - case 28: return SPELL_ATTR4_UNK28; - case 29: return SPELL_ATTR4_UNK29; - case 30: return SPELL_ATTR4_UNK30; - case 31: return SPELL_ATTR4_UNK31; + case 24: return SPELL_ATTR4_AUTO_RANGED_COMBAT; + case 25: return SPELL_ATTR4_OWNER_POWER_SCALING; + case 26: return SPELL_ATTR4_ONLY_FLYING_AREAS; + case 27: return SPELL_ATTR4_FORCE_DISPLAY_CASTBAR; + case 28: return SPELL_ATTR4_IGNORE_COMBAT_TIMER; + case 29: return SPELL_ATTR4_AURA_BOUNCE_FAILS_SPELL; + case 30: return SPELL_ATTR4_OBSOLETE; + case 31: return SPELL_ATTR4_USE_FACING_FROM_SPELL; default: throw std::out_of_range("index"); } } @@ -848,38 +848,38 @@ TC_API_EXPORT size_t EnumUtils<SpellAttr4>::ToIndex(SpellAttr4 value) { switch (value) { - case SPELL_ATTR4_IGNORE_RESISTANCES: return 0; - case SPELL_ATTR4_PROC_ONLY_ON_CASTER: return 1; + case SPELL_ATTR4_NO_CAST_LOG: return 0; + case SPELL_ATTR4_CLASS_TRIGGER_ONLY_ON_TARGET: return 1; case SPELL_ATTR4_AURA_EXPIRES_OFFLINE: return 2; - case SPELL_ATTR4_UNK3: return 3; - case SPELL_ATTR4_UNK4: return 4; - case SPELL_ATTR4_UNK5: return 5; - case SPELL_ATTR4_NOT_STEALABLE: return 6; - case SPELL_ATTR4_CAN_CAST_WHILE_CASTING: return 7; - case SPELL_ATTR4_FIXED_DAMAGE: return 8; - case SPELL_ATTR4_TRIGGER_ACTIVATE: return 9; - case SPELL_ATTR4_SPELL_VS_EXTEND_COST: return 10; - case SPELL_ATTR4_UNK11: return 11; - case SPELL_ATTR4_UNK12: return 12; - case SPELL_ATTR4_COMBAT_LOG_NO_CASTER: return 13; - case SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS: return 14; - case SPELL_ATTR4_HIDDEN_IN_SPELLBOOK: return 15; - case SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG: return 16; - case SPELL_ATTR4_USABLE_IN_ARENA: return 17; - case SPELL_ATTR4_AREA_TARGET_CHAIN: return 18; - case SPELL_ATTR4_UNK19: return 19; - case SPELL_ATTR4_NOT_CHECK_SELFCAST_POWER: return 20; - case SPELL_ATTR4_DONT_REMOVE_IN_ARENA: return 21; - case SPELL_ATTR4_UNK22: return 22; + case SPELL_ATTR4_NO_HELPFUL_THREAT: return 3; + case SPELL_ATTR4_NO_HARMFUL_THREAT: return 4; + case SPELL_ATTR4_ALLOW_CLIENT_TARGETING: return 5; + case SPELL_ATTR4_CANNOT_BE_STOLEN: return 6; + case SPELL_ATTR4_ALLOW_CAST_WHILE_CASTING: return 7; + case SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS: return 8; + case SPELL_ATTR4_COMBAT_FEEDBACK_WHEN_USABLE: return 9; + case SPELL_ATTR4_WEAPON_SPEED_COST_SCALING: return 10; + case SPELL_ATTR4_NO_PARTIAL_IMMUNITY: return 11; + case SPELL_ATTR4_AURA_IS_BUFF: return 12; + case SPELL_ATTR4_DO_NOT_LOG_CASTER: return 13; + case SPELL_ATTR4_REACTIVE_DAMAGE_PROC: return 14; + case SPELL_ATTR4_NOT_IN_SPELLBOOK: return 15; + case SPELL_ATTR4_NOT_IN_ARENA_OR_RATED_BATTLEGROUND: return 16; + case SPELL_ATTR4_IGNORE_DEFAULT_ARENA_RESTRICTIONS: return 17; + case SPELL_ATTR4_BOUNCY_CHAIN_MISSILES: return 18; + case SPELL_ATTR4_ALLOW_PROC_WHILE_SITTING: return 19; + case SPELL_ATTR4_AURA_NEVER_BOUNCES: return 20; + case SPELL_ATTR4_ALLOW_ENTERING_ARENA: return 21; + case SPELL_ATTR4_PROC_SUPPRESS_SWING_ANIM: return 22; case SPELL_ATTR4_SUPPRESS_WEAPON_PROCS: return 23; - case SPELL_ATTR4_UNK24: return 24; - case SPELL_ATTR4_IS_PET_SCALING: return 25; - case SPELL_ATTR4_CAST_ONLY_IN_OUTLAND: return 26; - case SPELL_ATTR4_UNK27: return 27; - case SPELL_ATTR4_UNK28: return 28; - case SPELL_ATTR4_UNK29: return 29; - case SPELL_ATTR4_UNK30: return 30; - case SPELL_ATTR4_UNK31: return 31; + case SPELL_ATTR4_AUTO_RANGED_COMBAT: return 24; + case SPELL_ATTR4_OWNER_POWER_SCALING: return 25; + case SPELL_ATTR4_ONLY_FLYING_AREAS: return 26; + case SPELL_ATTR4_FORCE_DISPLAY_CASTBAR: return 27; + case SPELL_ATTR4_IGNORE_COMBAT_TIMER: return 28; + case SPELL_ATTR4_AURA_BOUNCE_FAILS_SPELL: return 29; + case SPELL_ATTR4_OBSOLETE: return 30; + case SPELL_ATTR4_USE_FACING_FROM_SPELL: return 31; default: throw std::out_of_range("value"); } } @@ -904,7 +904,7 @@ TC_API_EXPORT EnumText EnumUtils<SpellAttr5>::ToString(SpellAttr5 value) case SPELL_ATTR5_START_PERIODIC_AT_APPLY: return { "SPELL_ATTR5_START_PERIODIC_AT_APPLY", "Immediately do periodic tick on apply", "" }; case SPELL_ATTR5_HIDE_DURATION: return { "SPELL_ATTR5_HIDE_DURATION", "Do not send aura duration to client", "" }; case SPELL_ATTR5_ALLOW_TARGET_OF_TARGET_AS_TARGET: return { "SPELL_ATTR5_ALLOW_TARGET_OF_TARGET_AS_TARGET", "Auto-target target of target (client only)", "" }; - case SPELL_ATTR5_UNK12: return { "SPELL_ATTR5_UNK12", "Unknown attribute 12@Attr5", "Cleave related?" }; + case SPELL_ATTR5_MELEE_CHAIN_TARGETING: return { "SPELL_ATTR5_MELEE_CHAIN_TARGETING", "Unknown attribute 12@Attr5", "Cleave related?" }; case SPELL_ATTR5_HASTE_AFFECT_DURATION: return { "SPELL_ATTR5_HASTE_AFFECT_DURATION", "Duration scales with Haste Rating", "" }; case SPELL_ATTR5_NOT_USABLE_WHILE_CHARMED: return { "SPELL_ATTR5_NOT_USABLE_WHILE_CHARMED", "Not Available While Charmed", "" }; case SPELL_ATTR5_UNK15: return { "SPELL_ATTR5_UNK15", "Unknown attribute 15@Attr5", "Related to multi-target spells?" }; @@ -948,7 +948,7 @@ TC_API_EXPORT SpellAttr5 EnumUtils<SpellAttr5>::FromIndex(size_t index) case 9: return SPELL_ATTR5_START_PERIODIC_AT_APPLY; case 10: return SPELL_ATTR5_HIDE_DURATION; case 11: return SPELL_ATTR5_ALLOW_TARGET_OF_TARGET_AS_TARGET; - case 12: return SPELL_ATTR5_UNK12; + case 12: return SPELL_ATTR5_MELEE_CHAIN_TARGETING; case 13: return SPELL_ATTR5_HASTE_AFFECT_DURATION; case 14: return SPELL_ATTR5_NOT_USABLE_WHILE_CHARMED; case 15: return SPELL_ATTR5_UNK15; @@ -989,7 +989,7 @@ TC_API_EXPORT size_t EnumUtils<SpellAttr5>::ToIndex(SpellAttr5 value) case SPELL_ATTR5_START_PERIODIC_AT_APPLY: return 9; case SPELL_ATTR5_HIDE_DURATION: return 10; case SPELL_ATTR5_ALLOW_TARGET_OF_TARGET_AS_TARGET: return 11; - case SPELL_ATTR5_UNK12: return 12; + case SPELL_ATTR5_MELEE_CHAIN_TARGETING: return 12; case SPELL_ATTR5_HASTE_AFFECT_DURATION: return 13; case SPELL_ATTR5_NOT_USABLE_WHILE_CHARMED: return 14; case SPELL_ATTR5_UNK15: return 15; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 326e33e1808..3d9bec79654 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5309,14 +5309,14 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const damage = damageReducedArmor; } - if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS)) { if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, GetBase()->GetCasterGUID()); } int32 dmg = damage; - if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE) && caster && caster->CanApplyResilience()) + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS) && caster && caster->CanApplyResilience()) Unit::ApplyResilience(target, &dmg); damage = dmg; @@ -5398,14 +5398,14 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c damage = damageReducedArmor; } - if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE)) + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS)) { if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) damage = target->CalculateAOEAvoidance(damage, m_spellInfo->SchoolMask, GetBase()->GetCasterGUID()); } int32 dmg = damage; - if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE) && caster && caster->CanApplyResilience()) + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS) && caster && caster->CanApplyResilience()) Unit::ApplyResilience(target, &dmg); damage = dmg; @@ -5581,7 +5581,8 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con { gainedAmount = caster->ModifyPower(powerType, gainAmount); // energize is not modified by threat modifiers - target->GetThreatManager().AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo(), true); + if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_NO_HELPFUL_THREAT)) + target->GetThreatManager().AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo(), true); } // Drain Mana - Mana Feed effect diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 995a697fac1..7e8c66b2015 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1884,6 +1884,10 @@ uint32 Aura::GetProcEffectMask(AuraApplication* aurApp, ProcEventInfo& eventInfo if (target->GetGUID() != GetCasterGUID()) return 0; + if (!m_spellInfo->HasAttribute(SPELL_ATTR4_ALLOW_PROC_WHILE_SITTING)) + if (!target->IsStandState()) + return 0; + bool success = roll_chance_f(CalcProcChance(*procEntry, eventInfo)); const_cast<Aura*>(this)->SetLastProcAttemptTime(now); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index e11e5f2aadd..3a1817b611b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -544,7 +544,7 @@ m_spellValue(new SpellValue(m_spellInfo, caster)), _spellEvent(nullptr) if (info->HasAttribute(SPELL_ATTR2_DO_NOT_REPORT_SPELL_FAILURE)) _triggeredCastFlags = TriggerCastFlags(uint32(_triggeredCastFlags) | TRIGGERED_DONT_REPORT_CAST_ERROR); - if (info->HasAttribute(SPELL_ATTR4_CAN_CAST_WHILE_CASTING)) + if (info->HasAttribute(SPELL_ATTR4_ALLOW_CAST_WHILE_CASTING)) _triggeredCastFlags = TriggerCastFlags(uint32(_triggeredCastFlags) | TRIGGERED_IGNORE_CAST_IN_PROGRESS); m_CastItem = nullptr; @@ -1012,6 +1012,9 @@ void Spell::SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, if (target) { SpellDestination dest(*target); + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } @@ -1023,6 +1026,9 @@ void Spell::SelectImplicitChannelTargets(SpellEffectInfo const& spellEffectInfo, case TARGET_DEST_CHANNEL_CASTER: { SpellDestination dest(*channeledSpell->GetCaster()); + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); break; @@ -1089,6 +1095,9 @@ void Spell::SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, if (focusObject) { SpellDestination dest(*focusObject); + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } @@ -1161,6 +1170,9 @@ void Spell::SelectImplicitNearbyTargets(SpellEffectInfo const& spellEffectInfo, case TARGET_OBJECT_TYPE_DEST: { SpellDestination dest(*target); + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); break; @@ -1320,6 +1332,8 @@ void Spell::SelectImplicitAreaTargets(SpellEffectInfo const& spellEffectInfo, Sp if (targetType.GetObjectType() == TARGET_OBJECT_TYPE_UNIT_AND_DEST) { SpellDestination dest(*referer); + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); @@ -1517,6 +1531,9 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectIn } } + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } @@ -1549,6 +1566,9 @@ void Spell::SelectImplicitTargetDestTargets(SpellEffectInfo const& spellEffectIn } } + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.SetDst(dest); } @@ -1588,6 +1608,9 @@ void Spell::SelectImplicitDestDestTargets(SpellEffectInfo const& spellEffectInfo } } + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.ModDst(dest); } @@ -1696,14 +1719,21 @@ void Spell::SelectImplicitChainTargets(SpellEffectInfo const& spellEffectInfo, S std::list<WorldObject*> targets; SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType() - , spellEffectInfo.ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); + , spellEffectInfo, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY); // Chain primary target is added earlier CallScriptObjectAreaTargetSelectHandlers(targets, spellEffectInfo.EffectIndex, targetType); + Position const* losPosition = m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER) ? m_caster : target; + for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) + { if (Unit* unit = (*itr)->ToUnit()) - AddUnitTarget(unit, effMask, false); + AddUnitTarget(unit, effMask, false, true, losPosition); + + if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER) && !spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::ChainFromInitialTarget)) + losPosition = *itr; + } } } @@ -1797,6 +1827,9 @@ void Spell::SelectImplicitTrajTargets(SpellEffectInfo const& spellEffectInfo, Sp float z = m_targets.GetSrcPos()->m_positionZ + bestDist * (a * bestDist + b); SpellDestination dest(x, y, z, unitCaster->GetOrientation()); + if (m_spellInfo->HasAttribute(SPELL_ATTR4_USE_FACING_FROM_SPELL)) + dest._position.SetOrientation(spellEffectInfo.PositionFacing); + CallScriptDestinationTargetSelectHandlers(dest, spellEffectInfo.EffectIndex, targetType); m_targets.ModDst(dest); } @@ -2049,7 +2082,7 @@ void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Pos SearchTargets<Trinity::WorldObjectListSearcher<Trinity::WorldObjectSpellAreaTargetCheck> > (searcher, containerTypeMask, m_caster, position, range); } -void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionContainer* condList, bool isChainHeal) +void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, SpellEffectInfo const& spellEffectInfo, bool isChainHeal) { // max dist for jump target selection float jumpRadius = 0.0f; @@ -2077,31 +2110,31 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar if (Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo, SpellModOp::ChainJumpDistance, jumpRadius, this); - // chain lightning/heal spells and similar - allow to jump at larger distance and go out of los - bool isBouncingFar = (m_spellInfo->HasAttribute(SPELL_ATTR4_AREA_TARGET_CHAIN) - || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE - || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC); - // max dist which spell can reach - float searchRadius = jumpRadius; - if (isBouncingFar) - searchRadius *= chainTargets; + float searchRadius = [&]() + { + if (m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER)) + return GetMinMaxRange(false).second; + + if (spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::ChainFromInitialTarget)) + return jumpRadius; + + return jumpRadius * chainTargets; + }(); WorldObject* chainSource = m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER) ? m_caster : target; std::list<WorldObject*> tempTargets; - SearchAreaTargets(tempTargets, searchRadius, chainSource, m_caster, objectType, selectType, condList); + SearchAreaTargets(tempTargets, searchRadius, chainSource, m_caster, objectType, selectType, spellEffectInfo.ImplicitTargetConditions); tempTargets.remove(target); // remove targets which are always invalid for chain spells // for some spells allow only chain targets in front of caster (swipe for example) - if (!isBouncingFar) + if (m_spellInfo->HasAttribute(SPELL_ATTR5_MELEE_CHAIN_TARGETING)) { - for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();) + tempTargets.remove_if([&](WorldObject* object) { - std::list<WorldObject*>::iterator checkItr = itr++; - if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr)) - tempTargets.erase(checkItr); - } + return !m_caster->HasInArc(static_cast<float>(M_PI), object); + }); } while (chainTargets) @@ -2132,7 +2165,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar { if (foundItr == tempTargets.end()) { - if ((!isBouncingFar || chainSource->IsWithinDist(*itr, jumpRadius)) && chainSource->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) + if (chainSource->IsWithinDist(*itr, jumpRadius) && chainSource->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) foundItr = itr; } else if (chainSource->GetDistanceOrder(*itr, *foundItr) && chainSource->IsWithinLOSInMap(*itr, LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags::M2)) @@ -2143,7 +2176,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar if (foundItr == tempTargets.end()) break; - if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER)) + if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CHAIN_FROM_CASTER) && !spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes::ChainFromInitialTarget)) chainSource = *foundItr; targets.push_back(*foundItr); @@ -2290,17 +2323,35 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= if (m_caster != target) { float hitDelay = m_spellInfo->LaunchDelay; + WorldObject const* missileSource = m_caster; + if (m_spellInfo->HasAttribute(SPELL_ATTR4_BOUNCY_CHAIN_MISSILES)) + { + auto previousTargetItr = std::find_if(m_UniqueTargetInfo.rbegin(), m_UniqueTargetInfo.rend(), [effectMask](TargetInfo const& target) + { + return (target.EffectMask & effectMask) != 0; + }); + if (previousTargetItr != std::rend(m_UniqueTargetInfo)) + { + hitDelay = 0.0f; // this is not the first target in chain, LaunchDelay was already included + + if (WorldObject* previousTarget = ObjectAccessor::GetWorldObject(*m_caster, previousTargetItr->TargetGUID)) + missileSource = previousTarget; + + targetInfo.TimeDelay += previousTargetItr->TimeDelay; + } + } + if (m_spellInfo->HasAttribute(SPELL_ATTR9_SPECIAL_DELAY_CALCULATION)) hitDelay += m_spellInfo->Speed; else if (m_spellInfo->Speed > 0.0f) { // calculate spell incoming interval /// @todo this is a hack - float dist = std::max(m_caster->GetDistance(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()), 5.0f); + float dist = std::max(missileSource->GetDistance(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()), 5.0f); hitDelay += dist / m_spellInfo->Speed; } - targetInfo.TimeDelay = uint64(std::floor(hitDelay * 1000.0f)); + targetInfo.TimeDelay += uint64(std::floor(hitDelay * 1000.0f)); } else targetInfo.TimeDelay = 0ULL; @@ -2603,8 +2654,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) // Spells with this flag cannot trigger if effect is cast on self bool const canEffectTrigger = (!spell->m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_CASTER_PROCS) || !spell->m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS)) - && spell->unitTarget->CanProc() - && (spell->CanExecuteTriggersOnHit(EffectMask) || MissCondition == SPELL_MISS_IMMUNE || MissCondition == SPELL_MISS_IMMUNE2); + && spell->unitTarget->CanProc(); // Trigger info was not filled in Spell::prepareDataForTriggerSystem - we do it now if (canEffectTrigger && !procAttacker && !procVictim) @@ -2834,7 +2884,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell) } // Needs to be called after dealing damage/healing to not remove breaking on damage auras - spell->DoTriggersOnSpellHit(_spellHitTarget, EffectMask); + spell->DoTriggersOnSpellHit(_spellHitTarget); } if (_enablePVP) @@ -3099,7 +3149,7 @@ void Spell::DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, _spellAura = nullptr; } -void Spell::DoTriggersOnSpellHit(Unit* unit, uint32 effMask) +void Spell::DoTriggersOnSpellHit(Unit* unit) { // handle SPELL_AURA_ADD_TARGET_TRIGGER auras // this is executed after spell proc spells on target hit @@ -3110,7 +3160,7 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint32 effMask) int32 _duration = 0; for (auto i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i) { - if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance)) + if (CanExecuteTriggersOnHit(unit, i->triggeredByAura) && roll_chance_i(i->chance)) { m_caster->CastSpell(unit, i->triggeredSpell->Id, CastSpellExtraArgs(TRIGGERED_FULL_MASK) .SetTriggeringSpell(this) @@ -3668,7 +3718,7 @@ void Spell::_cast(bool skipCheck) creatureCaster->ReleaseSpellFocus(this); // Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells - if ((m_spellInfo->HasHitDelay() && !m_spellInfo->IsChanneled()) || m_spellInfo->HasAttribute(SPELL_ATTR4_UNK4)) + if ((m_spellInfo->HasHitDelay() && !m_spellInfo->IsChanneled()) || m_spellInfo->HasAttribute(SPELL_ATTR4_NO_HARMFUL_THREAT)) { // Remove used for cast item if need (it can be already NULL after TakeReagents call // in case delayed spell remove item at cast delay start @@ -6500,7 +6550,10 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32 } // check if target already has the same type, but more powerful aura - if (!nonAuraEffectMask && (approximateAuraEffectMask & (1 << spellEffectInfo.EffectIndex)) && !m_spellInfo->IsTargetingArea()) + if (!m_spellInfo->HasAttribute(SPELL_ATTR4_AURA_NEVER_BOUNCES) + && (!nonAuraEffectMask || m_spellInfo->HasAttribute(SPELL_ATTR4_AURA_BOUNCE_FAILS_SPELL)) + && (approximateAuraEffectMask & (1 << spellEffectInfo.EffectIndex)) + && !m_spellInfo->IsTargetingArea()) if (Unit* target = m_targets.GetUnitTarget()) if (!target->IsHighestExclusiveAuraEffect(m_spellInfo, spellEffectInfo.ApplyAuraName, spellEffectInfo.CalcValue(m_caster, &m_spellValue->EffectBasePoints[spellEffectInfo.EffectIndex], nullptr, nullptr, m_castItemEntry, m_castItemLevel), @@ -6786,11 +6839,11 @@ SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules() if (isRatedBattleground && m_spellInfo->HasAttribute(SPELL_ATTR9_USABLE_IN_RATED_BATTLEGROUNDS)) return SPELL_CAST_OK; - if (isArena && m_spellInfo->HasAttribute(SPELL_ATTR4_USABLE_IN_ARENA)) + if (isArena && m_spellInfo->HasAttribute(SPELL_ATTR4_IGNORE_DEFAULT_ARENA_RESTRICTIONS)) return SPELL_CAST_OK; // check NOT_USABLE attributes - if (m_spellInfo->HasAttribute(SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG)) + if (m_spellInfo->HasAttribute(SPELL_ATTR4_NOT_IN_ARENA_OR_RATED_BATTLEGROUND)) return isArena ? SPELL_FAILED_NOT_IN_ARENA : SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND; if (isArena && m_spellInfo->HasAttribute(SPELL_ATTR9_NOT_USABLE_IN_ARENA)) @@ -8530,15 +8583,20 @@ bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToC return true; } -bool Spell::CanExecuteTriggersOnHit(uint32 effMask, SpellInfo const* triggeredByAura /*= nullptr*/) const +bool Spell::CanExecuteTriggersOnHit(Unit* unit, SpellInfo const* triggeredByAura /*= nullptr*/) const { - bool only_on_caster = (triggeredByAura && (triggeredByAura->HasAttribute(SPELL_ATTR4_PROC_ONLY_ON_CASTER))); - // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a cast spell with TARGET_UNIT_CASTER - for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects()) - { - if ((effMask & (1 << spellEffectInfo.EffectIndex)) && (!only_on_caster || (spellEffectInfo.TargetA.GetTarget() == TARGET_UNIT_CASTER))) - return true; - } + bool onlyOnTarget = (triggeredByAura && (triggeredByAura->HasAttribute(SPELL_ATTR4_CLASS_TRIGGER_ONLY_ON_TARGET))); + if (!onlyOnTarget) + return true; + + // If triggeredByAura has SPELL_ATTR4_CLASS_TRIGGER_ONLY_ON_TARGET then it can only proc on either noncaster units... + if (unit != m_caster) + return true; + + // ... or caster if it is the only target + if (m_UniqueTargetInfo.size() == 1) + return true; + return false; } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 64f7b6db188..23e044c30e2 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -433,7 +433,7 @@ class TC_GAME_API Spell WorldObject* SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList = nullptr); void SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, WorldObject* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionContainer* condList); - void SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionContainer* condList, bool isChainHeal); + void SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, SpellEffectInfo const& spellEffectInfo, bool isChainHeal); GameObject* SearchSpellFocus(); @@ -805,7 +805,7 @@ class TC_GAME_API Spell SpellMissInfo PreprocessSpellHit(Unit* unit, TargetInfo& targetInfo); void DoSpellEffectHit(Unit* unit, SpellEffectInfo const& spellEffectInfo, TargetInfo& targetInfo); - void DoTriggersOnSpellHit(Unit* unit, uint32 effMask); + void DoTriggersOnSpellHit(Unit* unit); bool UpdateChanneledTargetList(); bool IsValidDeadOrAliveTarget(Unit const* target) const; void HandleLaunchPhase(); @@ -846,7 +846,7 @@ class TC_GAME_API Spell int32 chance; }; - bool CanExecuteTriggersOnHit(uint32 effMask, SpellInfo const* triggeredByAura = nullptr) const; + bool CanExecuteTriggersOnHit(Unit* unit, SpellInfo const* triggeredByAura = nullptr) const; void PrepareTriggersExecutedOnHit(); typedef std::vector<HitTriggerSpell> HitTriggerSpellList; HitTriggerSpellList m_hitTriggerSpells; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 38e0661c9d9..ec7104c0561 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -4590,7 +4590,7 @@ void Spell::EffectStealBeneficialBuff() if ((aura->GetSpellInfo()->GetDispelMask()) & dispelMask) { // Need check for passive? this - if (!aurApp->IsPositive() || aura->IsPassive() || aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_NOT_STEALABLE)) + if (!aurApp->IsPositive() || aura->IsPassive() || aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_CANNOT_BE_STOLEN)) continue; // 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance." diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 23c1b9c670c..b362e91621c 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1675,7 +1675,7 @@ bool SpellInfo::IsAutoRepeatRangedSpell() const bool SpellInfo::HasInitialAggro() const { - return !(HasAttribute(SPELL_ATTR1_NO_THREAT) || HasAttribute(SPELL_ATTR2_NO_INITIAL_THREAT)); + return !(HasAttribute(SPELL_ATTR1_NO_THREAT) || HasAttribute(SPELL_ATTR2_NO_INITIAL_THREAT) || HasAttribute(SPELL_ATTR4_NO_HARMFUL_THREAT)); } bool SpellInfo::HasHitDelay() const @@ -1952,7 +1952,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a } // continent limitation (virtual continent) - if (HasAttribute(SPELL_ATTR4_CAST_ONLY_IN_OUTLAND)) + if (HasAttribute(SPELL_ATTR4_ONLY_FLYING_AREAS)) { uint32 mountFlags = 0; if (player && player->HasAuraType(SPELL_AURA_MOUNT_RESTRICTIONS)) @@ -3943,7 +3943,7 @@ Optional<SpellPowerCost> SpellInfo::CalcPowerCost(SpellPowerEntry const* power, bool initiallyNegative = powerCost < 0; // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost) - if (HasAttribute(SPELL_ATTR4_SPELL_VS_EXTEND_COST)) + if (HasAttribute(SPELL_ATTR4_WEAPON_SPEED_COST_SCALING)) { uint32 speed = 0; if (SpellShapeshiftFormEntry const* ss = sSpellShapeshiftFormStore.LookupEntry(unitCaster->GetShapeshiftForm())) @@ -4407,6 +4407,9 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, SpellEffectInfo const& ef if (spellInfo->HasAttribute(SPELL_ATTR0_AURA_IS_DEBUFF)) return false; + if (spellInfo->HasAttribute(SPELL_ATTR4_AURA_IS_BUFF)) + return true; + visited.insert({ spellInfo, effect.EffectIndex }); //We need scaling level info for some auras that compute bp 0 or positive but should be debuffs diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index b67cbed7112..8b56ff8b98a 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3478,7 +3478,7 @@ void SpellMgr::LoadSpellInfoCorrections() 60864 // Jaws of Death }, [](SpellInfo* spellInfo) { - spellInfo->AttributesEx4 |= SPELL_ATTR4_FIXED_DAMAGE; + spellInfo->AttributesEx4 |= SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS; }); // Howl of Azgalor @@ -4144,12 +4144,6 @@ void SpellMgr::LoadSpellInfoCorrections() }); }); - // Coldflame (Lord Marrowgar) - ApplySpellFix({ 69146 }, [](SpellInfo* spellInfo) - { - spellInfo->AttributesEx4 &= ~SPELL_ATTR4_IGNORE_RESISTANCES; - }); - // Shadow's Fate ApplySpellFix({ 71169 }, [](SpellInfo* spellInfo) { |