diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index 4256a73f2..aad4ef8d4 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -1583,38 +1583,38 @@ namespace Framework.Constants #region Spell Attributes public enum SpellAttr0 : uint { - Unk0 = 0x01, // 0 - ReqAmmo = 0x02, // 1 On Next Ranged - OnNextSwing = 0x04, // 2 - IsReplenishment = 0x08, // 3 Not Set In 3.0.3 - Ability = 0x10, // 4 Client Puts 'Ability' Instead Of 'Spell' In Game Strings For These Spells - Tradespell = 0x20, // 5 Trade Spells (Recipes), Will Be Added By Client To A Sublist Of Profession Spell - Passive = 0x40, // 6 Passive Spell - HiddenClientside = 0x80, // 7 Spells With This Attribute Are Not Visible In Spellbook Or Aura Bar - HideInCombatLog = 0x100, // 8 This Attribite Controls Whether Spell Appears In Combat Logs - TargetMainhandItem = 0x200, // 9 Client Automatically Selects Item From Mainhand Slot As A Cast Target - OnNextSwing2 = 0x400, // 10 - Unk11 = 0x800, // 11 - DaytimeOnly = 0x1000, // 12 Only Useable At Daytime, Not Set In 2.4.2 - NightOnly = 0x2000, // 13 Only Useable At Night, Not Set In 2.4.2 - IndoorsOnly = 0x4000, // 14 Only Useable Indoors, Not Set In 2.4.2 - OutdoorsOnly = 0x8000, // 15 Only Useable Outdoors. - NotShapeshift = 0x10000, // 16 Not While Shapeshifted - OnlyStealthed = 0x20000, // 17 Must Be In Stealth - DontAffectSheathState = 0x40000, // 18 Client Won'T Hide Unit Weapons In Sheath On Cast/Channel - LevelDamageCalculation = 0x80000, // 19 Spelldamage Depends On Caster Level - StopAttackTarget = 0x100000, // 20 Stop Attack After Use This Spell (And Not Begin Attack If Use) - ImpossibleDodgeParryBlock = 0x200000, // 21 Cannot Be Dodged/Parried/Blocked - CastTrackTarget = 0x400000, // 22 Client Automatically Forces Player To Face Target When Casting - CastableWhileDead = 0x800000, // 23 Castable While Dead? - CastableWhileMounted = 0x1000000, // 24 Castable While Mounted - DisabledWhileActive = 0x2000000, // 25 Activate And Start Cooldown After Aura Fade Or Remove Summoned Creature Or Go - Negative1 = 0x4000000, // 26 Many Negative Spells Have This Attr - CastableWhileSitting = 0x8000000, // 27 Castable While Sitting - CantUsedInCombat = 0x10000000, // 28 Cannot Be Used In Combat - UnaffectedByInvulnerability = 0x20000000, // 29 Unaffected By Invulnerability (Hmm Possible Not...) - HeartResistCheck = 0x40000000, // 30 - CantCancel = 0x80000000, // 31 Positive Aura Can'T Be Canceled + ProcFailureBurnsCharge = 0x01, /*Nyi*/ // Proc Failure Burns Charge + UsesRangedSlot = 0x02, // Uses Ranged Slot Description Use Ammo, Ranged Attack Range Modifiers, Ranged Haste, Etc. + OnNextSwingNoDamage = 0x04, // On Next Swing (No Damage) Description Both "On Next Swing" Attributes Have Identical Handling In Server & Client + DoNotLogImmuneMisses = 0x08, // Do Not Log Immune Misses (Client Only) + IsAbility = 0x10, // Is Ability Description Cannot Be Reflected, Not Affected By Cast Speed Modifiers, Etc. + IsTradeskill = 0x20, // Is Tradeskill Description Displayed In Recipe List, Not Affected By Cast Speed Modifiers + Passive = 0x40, // Passive Description Spell Is Automatically Cast On Self By Core + DoNotDisplaySpellbookAuraIconCombatLog = 0x80, // Do Not Display (Spellbook, Aura Icon, Combat Log) (Client Only) Description Not Visible In Spellbook Or Aura Bar + DoNotLog = 0x100, // Do Not Log (Client Only) Description Spell Will Not Appear In Combat Logs + HeldItemOnly = 0x200, // Held Item Only (Client Only) Description Client Will Automatically Select Main-Hand Item As Cast Target + OnNextSwing = 0x400, // On Next Swing Description Both "On Next Swing" Attributes Have Identical Handling In Server & Client + WearerCastsProcTrigger = 0x800, /*Nyi*/ // Wearer Casts Proc Trigger + ServerOnly = 0x1000, // Server Only + AllowItemSpellInPvp = 0x2000, // Allow Item Spell In Pvp + OnlyIndoors = 0x4000, // Only Indoors + OnlyOutdoors = 0x8000, // Only Outdoors + NotShapeshifted = 0x10000, // Not Shapeshifted + OnlyStealthed = 0x20000, // Only Stealthed + DoNotSheath = 0x40000, // Do Not Sheath (Client Only) + ScalesWithCreatureLevel = 0x80000, // Scales W/ Creature Level Description For Non-Player Casts, Scale Impact And Power Cost With Caster'S Level + CancelsAutoAttackCombat = 0x100000, // Cancels Auto Attack Combat Description After Casting This, The Current Auto-Attack Will Be Interrupted + NoActiveDefense = 0x200000, // No Active Defense Description Spell Cannot Be Dodged, Parried Or Blocked + TrackTargetInCastPlayerOnly = 0x400000, // Track Target In Cast (Player Only) (Client Only) + AllowCastWhileDead = 0x800000, // Allow Cast While Dead Description Spells Without This Flag Cannot Be Cast By Dead Units In Non-Triggered Contexts + AllowWhileMounted = 0x1000000, // Allow While Mounted + CooldownOnEvent = 0x2000000, // Cooldown On Event Description Spell Is Unusable While Already Active, And Cooldown Does Not Begin Until The Effects Have Worn Off + AuraIsDebuff = 0x4000000, // Aura Is Debuff Description Forces The Spell To Be Treated As A Negative Spell + AllowWhileSitting = 0x8000000, // Allow While Sitting + NotInCombatOnlyPeaceful = 0x10000000, // Not In Combat (Only Peaceful) + NoImmunities = 0x20000000, // No Immunities Description Allows Spell To Pierce Invulnerability, Unless The Invulnerability Spell Also Has This Attribute + HeartbeatResist = 0x40000000, // Heartbeat Resist Description Periodically Re-Rolls Against Resistance To Potentially Expire Aura Early + NoAuraCancel = 0x80000000 // No Aura Cancel Description Prevents The Player From Voluntarily Canceling A Positive Aura } public enum SpellAttr1 : uint { diff --git a/Source/Game/AI/CoreAI/UnitAI.cs b/Source/Game/AI/CoreAI/UnitAI.cs index b3ae1185d..78350cddc 100644 --- a/Source/Game/AI/CoreAI/UnitAI.cs +++ b/Source/Game/AI/CoreAI/UnitAI.cs @@ -324,7 +324,7 @@ namespace Game.AI Global.SpellMgr.ForEachSpellInfo(spellInfo => { AISpellInfoType AIInfo = new(); - if (spellInfo.HasAttribute(SpellAttr0.CastableWhileDead)) + if (spellInfo.HasAttribute(SpellAttr0.AllowCastWhileDead)) AIInfo.condition = AICondition.Die; else if (spellInfo.IsPassive() || spellInfo.GetDuration() == -1) AIInfo.condition = AICondition.Aggro; diff --git a/Source/Game/AI/PlayerAI/PlayerAI.cs b/Source/Game/AI/PlayerAI/PlayerAI.cs index 0495e14e9..fa11cb855 100644 --- a/Source/Game/AI/PlayerAI/PlayerAI.cs +++ b/Source/Game/AI/PlayerAI/PlayerAI.cs @@ -637,7 +637,7 @@ namespace Game.AI SpellInfo auraInfo = aura.GetSpellInfo(); if (auraInfo == null) continue; - if (auraInfo.HasAttribute(SpellAttr0.CantCancel)) + if (auraInfo.HasAttribute(SpellAttr0.NoAuraCancel)) continue; if (!auraInfo.IsPositive() || auraInfo.IsPassive()) continue; diff --git a/Source/Game/BattleGrounds/BattleGround.cs b/Source/Game/BattleGrounds/BattleGround.cs index 1e4628f5f..b07e20a93 100644 --- a/Source/Game/BattleGrounds/BattleGround.cs +++ b/Source/Game/BattleGrounds/BattleGround.cs @@ -435,7 +435,7 @@ namespace Game.BattleGrounds { Aura aura = aurApp.GetBase(); return !aura.IsPermanent() && aura.GetDuration() <= 30 * Time.InMilliseconds && aurApp.IsPositive() - && !aura.GetSpellInfo().HasAttribute(SpellAttr0.UnaffectedByInvulnerability) && !aura.HasEffectType(AuraType.ModInvisibility); + && !aura.GetSpellInfo().HasAttribute(SpellAttr0.NoImmunities) && !aura.HasEffectType(AuraType.ModInvisibility); }); } } diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 88e458f91..9236ae5d7 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -1914,10 +1914,10 @@ namespace Game.Entities if (!unitCaster) return; - if (!(spellInfo.HasAttribute(SpellAttr0.Ability) || spellInfo.HasAttribute(SpellAttr0.Tradespell) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus)) && + if (!(spellInfo.HasAttribute(SpellAttr0.IsAbility) || spellInfo.HasAttribute(SpellAttr0.IsTradeskill) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus)) && ((IsPlayer() && spellInfo.SpellFamilyName != 0) || IsCreature())) castTime = unitCaster.CanInstantCast() ? 0 : (int)(castTime * unitCaster.m_unitData.ModCastingSpeed); - else if (spellInfo.HasAttribute(SpellAttr0.ReqAmmo) && !spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag)) + else if (spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) && !spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag)) castTime = (int)(castTime * unitCaster.m_modAttackSpeedPct[(int)WeaponAttackType.RangedAttack]); else if (Global.SpellMgr.IsPartOfSkillLine(SkillType.Cooking, spellInfo.Id) && unitCaster.HasAura(67556)) // cooking with Chef Hat. castTime = 500; @@ -1940,10 +1940,10 @@ namespace Game.Entities if (!unitCaster) return; - if (!(spellInfo.HasAttribute(SpellAttr0.Ability) || spellInfo.HasAttribute(SpellAttr0.Tradespell) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus)) && + if (!(spellInfo.HasAttribute(SpellAttr0.IsAbility) || spellInfo.HasAttribute(SpellAttr0.IsTradeskill) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus)) && ((IsPlayer() && spellInfo.SpellFamilyName != 0) || IsCreature())) duration = (int)(duration * unitCaster.m_unitData.ModCastingSpeed); - else if (spellInfo.HasAttribute(SpellAttr0.ReqAmmo) && !spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag)) + else if (spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) && !spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag)) duration = (int)(duration * unitCaster.m_modAttackSpeedPct[(int)WeaponAttackType.RangedAttack]); } @@ -2750,7 +2750,7 @@ namespace Game.Entities public Unit GetMagicHitRedirectTarget(Unit victim, SpellInfo spellInfo) { // Patch 1.2 notes: Spell Reflection no longer reflects abilities - if (spellInfo.HasAttribute(SpellAttr0.Ability) || spellInfo.HasAttribute(SpellAttr1.CantBeRedirected) || spellInfo.HasAttribute(SpellAttr0.UnaffectedByInvulnerability)) + if (spellInfo.HasAttribute(SpellAttr0.IsAbility) || spellInfo.HasAttribute(SpellAttr1.CantBeRedirected) || spellInfo.HasAttribute(SpellAttr0.NoImmunities)) return victim; var magnetAuras = victim.GetAuraEffectsByType(AuraType.SpellMagnet); diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 1a1777a4c..ee2017fdc 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -6398,8 +6398,8 @@ namespace Game.Entities if (IsInFlight()) return; - if (WorldConfig.GetBoolValue(WorldCfg.VmapIndoorCheck) && !IsOutdoors()) - RemoveAurasWithAttribute(SpellAttr0.OutdoorsOnly); + if (WorldConfig.GetBoolValue(WorldCfg.VmapIndoorCheck)) + RemoveAurasWithAttribute(IsOutdoors() ? SpellAttr0.OnlyIndoors : SpellAttr0.OnlyOutdoors); uint areaId = GetAreaId(); if (areaId == 0) diff --git a/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index 4d1fc5200..c787784ae 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -42,7 +42,7 @@ namespace Game.Entities Spell spell = GetCurrentSpell(CurrentSpellTypes.Generic); if (spell != null) if (spell.GetState() == SpellState.Preparing - && spell.m_spellInfo.HasAttribute(SpellAttr0.CantUsedInCombat) + && spell.m_spellInfo.HasAttribute(SpellAttr0.NotInCombatOnlyPeaceful) && spell.m_spellInfo.InterruptFlags.HasFlag(SpellInterruptFlags.Combat)) InterruptNonMeleeSpells(false); diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index 676394868..d08d31ed5 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -758,7 +758,7 @@ namespace Game.Entities return SpellMissInfo.Resist; // Same spells cannot be parried/dodged - if (spellInfo.HasAttribute(SpellAttr0.ImpossibleDodgeParryBlock)) + if (spellInfo.HasAttribute(SpellAttr0.NoActiveDefense)) return SpellMissInfo.None; bool canDodge = !spellInfo.HasAttribute(SpellAttr7.NoAttackDodge); @@ -1223,7 +1223,7 @@ namespace Game.Entities if (idList.ContainsKey(spellInfo.Id)) return true; - if (spellInfo.HasAttribute(SpellAttr0.UnaffectedByInvulnerability)) + if (spellInfo.HasAttribute(SpellAttr0.NoImmunities)) return false; uint dispel = (uint)spellInfo.Dispel; @@ -1379,7 +1379,7 @@ namespace Game.Entities return false; // for example 40175 - if (spellInfo.HasAttribute(SpellAttr0.UnaffectedByInvulnerability) && spellInfo.HasAttribute(SpellAttr3.IgnoreHitResult)) + if (spellInfo.HasAttribute(SpellAttr0.NoImmunities) && spellInfo.HasAttribute(SpellAttr3.IgnoreHitResult)) return false; if (spellInfo.HasAttribute(SpellAttr1.UnaffectedBySchoolImmune) || spellInfo.HasAttribute(SpellAttr2.UnaffectedByAuraSchoolImmune)) @@ -1748,7 +1748,7 @@ namespace Game.Entities bool IsSpellBlocked(Unit victim, SpellInfo spellProto, WeaponAttackType attackType = WeaponAttackType.BaseAttack) { // These spells can't be blocked - if (spellProto != null && (spellProto.HasAttribute(SpellAttr0.ImpossibleDodgeParryBlock) || spellProto.HasAttribute(SpellAttr3.IgnoreHitResult))) + if (spellProto != null && (spellProto.HasAttribute(SpellAttr0.NoActiveDefense) || spellProto.HasAttribute(SpellAttr3.IgnoreHitResult))) return false; // Can't block when casting/controlled diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 5006f8b8a..b11952707 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -292,7 +292,7 @@ namespace Game.Entities { SpellInfo transformSpellInfo = Global.SpellMgr.GetSpellInfo(spellId, GetMap().GetDifficultyID()); if (transformSpellInfo != null) - if (transformSpellInfo.HasAttribute(SpellAttr0.CastableWhileMounted)) + if (transformSpellInfo.HasAttribute(SpellAttr0.AllowWhileMounted)) return false; if (form != 0) @@ -656,7 +656,7 @@ namespace Game.Entities { SpellInfo createBySpell = Global.SpellMgr.GetSpellInfo(gameObj.GetSpellId(), GetMap().GetDifficultyID()); // Need disable spell use for owner - if (createBySpell != null && createBySpell.HasAttribute(SpellAttr0.DisabledWhileActive)) + if (createBySpell != null && createBySpell.IsCooldownStartedOnEvent()) // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existing cases) GetSpellHistory().StartCooldown(createBySpell, 0, null, true); } diff --git a/Source/Game/Handlers/PetHandler.cs b/Source/Game/Handlers/PetHandler.cs index 1f770d538..93fa4a440 100644 --- a/Source/Game/Handlers/PetHandler.cs +++ b/Source/Game/Handlers/PetHandler.cs @@ -79,7 +79,7 @@ namespace Game SpellInfo spell = (flag == ActiveStates.Enabled || flag == ActiveStates.Passive) ? Global.SpellMgr.GetSpellInfo(spellid, pet.GetMap().GetDifficultyID()) : null; if (spell == null) return; - if (!spell.HasAttribute(SpellAttr0.CastableWhileDead)) + if (!spell.HasAttribute(SpellAttr0.AllowCastWhileDead)) return; } diff --git a/Source/Game/Handlers/SpellHandler.cs b/Source/Game/Handlers/SpellHandler.cs index 91693f1f7..d6b02d7c1 100644 --- a/Source/Game/Handlers/SpellHandler.cs +++ b/Source/Game/Handlers/SpellHandler.cs @@ -384,7 +384,7 @@ namespace Game return; // not allow remove spells with attr SPELL_ATTR0_CANT_CANCEL - if (spellInfo.HasAttribute(SpellAttr0.CantCancel)) + if (spellInfo.HasAttribute(SpellAttr0.NoAuraCancel)) return; // channeled spell case (it currently casted then) @@ -412,7 +412,7 @@ namespace Game GetPlayer().RemoveAurasByType(AuraType.ModScale, aurApp => { SpellInfo spellInfo = aurApp.GetBase().GetSpellInfo(); - return !spellInfo.HasAttribute(SpellAttr0.CantCancel) && spellInfo.IsPositive() && !spellInfo.IsPassive(); + return !spellInfo.HasAttribute(SpellAttr0.NoAuraCancel) && spellInfo.IsPositive() && !spellInfo.IsPassive(); }); } @@ -422,7 +422,7 @@ namespace Game GetPlayer().RemoveAurasByType(AuraType.Mounted, aurApp => { SpellInfo spellInfo = aurApp.GetBase().GetSpellInfo(); - return !spellInfo.HasAttribute(SpellAttr0.CantCancel) && spellInfo.IsPositive() && !spellInfo.IsPassive(); + return !spellInfo.HasAttribute(SpellAttr0.NoAuraCancel) && spellInfo.IsPositive() && !spellInfo.IsPassive(); }); } @@ -478,7 +478,7 @@ namespace Game return; // not allow remove spells with attr SPELL_ATTR0_CANT_CANCEL - if (spellInfo.HasAttribute(SpellAttr0.CantCancel)) + if (spellInfo.HasAttribute(SpellAttr0.NoAuraCancel)) return; var spell = mover.GetCurrentSpell(CurrentSpellTypes.Channeled); diff --git a/Source/Game/Loot/LootManager.cs b/Source/Game/Loot/LootManager.cs index 2d3a18146..19c9c5221 100644 --- a/Source/Game/Loot/LootManager.cs +++ b/Source/Game/Loot/LootManager.cs @@ -393,7 +393,7 @@ namespace Game.Loots { // not report about not trainable spells (optionally supported by DB) // ignore 61756 (Northrend Inscription Research (FAST QA VERSION) for example - if (!spellInfo.HasAttribute(SpellAttr0.NotShapeshift) || spellInfo.HasAttribute(SpellAttr0.Tradespell)) + if (!spellInfo.HasAttribute(SpellAttr0.NotShapeshifted) || spellInfo.HasAttribute(SpellAttr0.IsTradeskill)) { Spell.ReportNonExistingId(spellInfo.Id, spellInfo.Id); } diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index 0de7f14b0..c950e5847 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -434,7 +434,7 @@ namespace Game.Spells // set infinity cooldown state for spells if (caster != null && caster.IsTypeId(TypeId.Player)) { - if (m_spellInfo.HasAttribute(SpellAttr0.DisabledWhileActive)) + if (m_spellInfo.IsCooldownStartedOnEvent()) { Item castItem = !m_castItemGuid.IsEmpty() ? caster.ToPlayer().GetItemByGuid(m_castItemGuid) : null; caster.GetSpellHistory().StartCooldown(m_spellInfo, castItem != null ? castItem.GetEntry() : 0, null, true); @@ -1009,7 +1009,7 @@ namespace Game.Spells return GetCasterGUID() == target.GetGUID() && m_spellInfo.Stances != 0 && !m_spellInfo.HasAttribute(SpellAttr2.NotNeedShapeshift) - && !m_spellInfo.HasAttribute(SpellAttr0.NotShapeshift); + && !m_spellInfo.HasAttribute(SpellAttr0.NotShapeshifted); } public bool CanBeSaved() diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index 53ffafba1..260cea85e 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -792,7 +792,7 @@ namespace Game.Spells continue; SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(pair.Key, Difficulty.None); - if (spellInfo == null || !(spellInfo.IsPassive() || spellInfo.HasAttribute(SpellAttr0.HiddenClientside))) + if (spellInfo == null || !(spellInfo.IsPassive() || spellInfo.HasAttribute(SpellAttr0.DoNotDisplaySpellbookAuraIconCombatLog))) continue; if (Convert.ToBoolean(spellInfo.Stances & (1ul << (GetMiscValue() - 1)))) @@ -3190,7 +3190,7 @@ namespace Game.Spells // recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_ABILITY 0x00000010 flag) // this check is total bullshit i think - if ((Convert.ToBoolean(GetMiscValueB() & 1 << (int)Stats.Stamina) || GetMiscValueB() == 0) && m_spellInfo.HasAttribute(SpellAttr0.Ability)) + if ((Convert.ToBoolean(GetMiscValueB() & 1 << (int)Stats.Stamina) || GetMiscValueB() == 0) && m_spellInfo.HasAttribute(SpellAttr0.IsAbility)) target.SetHealth(Math.Max(MathFunctions.CalculatePct(target.GetMaxHealth(), healthPct), (zeroHealth ? 0 : 1ul))); } diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 7d5f1fdab..a8cd1b613 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -105,8 +105,8 @@ namespace Game.Spells // Determine if spell can be reflected back to the caster // Patch 1.2 notes: Spell Reflection no longer reflects abilities - m_canReflect = caster.IsUnit() && m_spellInfo.DmgClass == SpellDmgClass.Magic && !m_spellInfo.HasAttribute(SpellAttr0.Ability) - && !m_spellInfo.HasAttribute(SpellAttr1.CantBeReflected) && !m_spellInfo.HasAttribute(SpellAttr0.UnaffectedByInvulnerability) + m_canReflect = caster.IsUnit() && m_spellInfo.DmgClass == SpellDmgClass.Magic && !m_spellInfo.HasAttribute(SpellAttr0.IsAbility) + && !m_spellInfo.HasAttribute(SpellAttr1.CantBeReflected) && !m_spellInfo.HasAttribute(SpellAttr0.NoImmunities) && !m_spellInfo.IsPassive(); CleanupTargetList(); @@ -2881,7 +2881,7 @@ namespace Game.Spells else procAttacker.Or(ProcFlags.DealHarmfulPeriodic); } - else if (m_spellInfo.HasAttribute(SpellAttr0.Ability)) + else if (m_spellInfo.HasAttribute(SpellAttr0.IsAbility)) { if (IsPositive()) procAttacker.Or(ProcFlags.DealHelpfulAbility); @@ -3156,7 +3156,7 @@ namespace Game.Spells else procAttacker.Or(ProcFlags.DealHarmfulPeriodic); } - else if (m_spellInfo.HasAttribute(SpellAttr0.Ability)) + else if (m_spellInfo.HasAttribute(SpellAttr0.IsAbility)) { if (IsPositive()) procAttacker.Or(ProcFlags.DealHelpfulAbility); @@ -3357,7 +3357,7 @@ namespace Game.Spells } // Stop Attack for some spells - if (m_spellInfo.HasAttribute(SpellAttr0.StopAttackTarget)) + if (m_spellInfo.HasAttribute(SpellAttr0.CancelsAutoAttackCombat)) unitCaster.AttackStop(); } @@ -3654,7 +3654,7 @@ namespace Game.Spells if (((IsTriggered() && !m_spellInfo.IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell != null) && !m_fromClient) castFlags |= SpellCastFlags.Pending; - if (m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) || m_spellInfo.HasAttribute(SpellAttr10.UsesRangedSlotCosmeticOnly) || m_spellInfo.HasAttribute(SpellCustomAttributes.NeedsAmmoData)) + if (m_spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) || m_spellInfo.HasAttribute(SpellAttr10.UsesRangedSlotCosmeticOnly) || m_spellInfo.HasAttribute(SpellCustomAttributes.NeedsAmmoData)) castFlags |= SpellCastFlags.Projectile; if ((m_caster.IsTypeId(TypeId.Player) || (m_caster.IsTypeId(TypeId.Unit) && m_caster.ToCreature().IsPet())) && m_powerCost.Any(cost => cost.Power != PowerType.Health)) @@ -3755,7 +3755,7 @@ namespace Game.Spells if (((IsTriggered() && !m_spellInfo.IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell != null) && !m_fromClient) castFlags |= SpellCastFlags.Pending; - if (m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) || m_spellInfo.HasAttribute(SpellAttr10.UsesRangedSlotCosmeticOnly) || m_spellInfo.HasAttribute(SpellCustomAttributes.NeedsAmmoData)) + if (m_spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) || m_spellInfo.HasAttribute(SpellAttr10.UsesRangedSlotCosmeticOnly) || m_spellInfo.HasAttribute(SpellCustomAttributes.NeedsAmmoData)) castFlags |= SpellCastFlags.Projectile; // arrows/bullets visual if ((m_caster.IsTypeId(TypeId.Player) || (m_caster.IsTypeId(TypeId.Unit) && m_caster.ToCreature().IsPet())) && m_powerCost.Any(cost => cost.Power != PowerType.Health)) @@ -4523,7 +4523,7 @@ namespace Game.Spells SpellCastResult castResult; // check death state - if (m_caster.ToUnit() && !m_caster.ToUnit().IsAlive() && !m_spellInfo.IsPassive() && !(m_spellInfo.HasAttribute(SpellAttr0.CastableWhileDead) || (IsTriggered() && m_triggeredByAuraSpell == null))) + if (m_caster.ToUnit() && !m_caster.ToUnit().IsAlive() && !m_spellInfo.IsPassive() && !(m_spellInfo.HasAttribute(SpellAttr0.AllowCastWhileDead) || (IsTriggered() && m_triggeredByAuraSpell == null))) return SpellCastResult.CasterDead; // Prevent cheating in case the player has an immunity effect and tries to interact with a non-allowed gameobject. The error message is handled by the client so we don't report anything here @@ -4544,7 +4544,7 @@ namespace Game.Spells { // These two auras check SpellFamilyName defined by db2 class data instead of current spell SpellFamilyName if (playerCaster.HasAuraType(AuraType.DisableCastingExceptAbilities) - && !m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) + && !m_spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) && !m_spellInfo.HasEffect(SpellEffectName.Attack) && !m_spellInfo.HasAttribute(SpellAttr12.IgnoreCastingDisabled) && !playerCaster.HasAuraTypeWithFamilyFlags(AuraType.DisableCastingExceptAbilities, CliDB.ChrClassesStorage.LookupByKey(playerCaster.GetClass()).SpellClassSet, m_spellInfo.SpellFamilyFlags)) @@ -4554,7 +4554,7 @@ namespace Game.Spells { if (!playerCaster.HasAuraTypeWithFamilyFlags(AuraType.DisableAttackingExceptAbilities, CliDB.ChrClassesStorage.LookupByKey(playerCaster.GetClass()).SpellClassSet, m_spellInfo.SpellFamilyFlags)) { - if (m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) + if (m_spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) || m_spellInfo.IsNextMeleeSwingSpell() || m_spellInfo.HasAttribute(SpellAttr1.MeleeCombatStart) || m_spellInfo.HasAttribute(SpellAttr2.Unk20) @@ -4590,7 +4590,7 @@ namespace Game.Spells // Check global cooldown if (strict && !Convert.ToBoolean(_triggeredCastFlags & TriggerCastFlags.IgnoreGCD) && HasGlobalCooldown()) - return !m_spellInfo.HasAttribute(SpellAttr0.DisabledWhileActive) ? SpellCastResult.NotReady : SpellCastResult.DontReport; + return !m_spellInfo.HasAttribute(SpellAttr0.CooldownOnEvent) ? SpellCastResult.NotReady : SpellCastResult.DontReport; // only triggered spells can be processed an ended Battleground if (!IsTriggered() && m_caster.IsTypeId(TypeId.Player)) @@ -4603,10 +4603,10 @@ namespace Game.Spells if (m_caster.IsTypeId(TypeId.Player) && Global.VMapMgr.IsLineOfSightCalcEnabled()) { - if (m_spellInfo.HasAttribute(SpellAttr0.OutdoorsOnly) && !m_caster.IsOutdoors()) + if (m_spellInfo.HasAttribute(SpellAttr0.OnlyOutdoors) && !m_caster.IsOutdoors()) return SpellCastResult.OnlyOutdoors; - if (m_spellInfo.HasAttribute(SpellAttr0.IndoorsOnly) && m_caster.IsOutdoors()) + if (m_spellInfo.HasAttribute(SpellAttr0.OnlyIndoors) && m_caster.IsOutdoors()) return SpellCastResult.OnlyIndoors; } @@ -4844,7 +4844,7 @@ namespace Game.Spells // not let players cast spells at mount (and let do it to creatures) if (!_triggeredCastFlags.HasFlag(TriggerCastFlags.IgnoreCasterMountedOrOnVehicle)) { - if (m_caster.IsPlayer() && m_caster.ToPlayer().IsMounted() && !m_spellInfo.IsPassive() && !m_spellInfo.HasAttribute(SpellAttr0.CastableWhileMounted)) + if (m_caster.IsPlayer() && m_caster.ToPlayer().IsMounted() && !m_spellInfo.IsPassive() && !m_spellInfo.HasAttribute(SpellAttr0.AllowWhileMounted)) { if (m_caster.ToPlayer().IsInFlight()) return SpellCastResult.NotOnTaxi; @@ -6129,7 +6129,7 @@ namespace Game.Spells rangeMod += 8.0f / 3.0f; } - if (m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) && m_caster.IsTypeId(TypeId.Player)) + if (m_spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) && m_caster.IsTypeId(TypeId.Player)) { Item ranged = m_caster.ToPlayer().GetWeaponForAttack(WeaponAttackType.RangedAttack, true); if (ranged) @@ -7652,7 +7652,7 @@ namespace Game.Spells } bool isMeleeOrRangedSpell = m_spellInfo.DmgClass == SpellDmgClass.Melee || m_spellInfo.DmgClass == SpellDmgClass.Ranged || - m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) || m_spellInfo.HasAttribute(SpellAttr0.Ability); + m_spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot) || m_spellInfo.HasAttribute(SpellAttr0.IsAbility); // Apply haste rating if (gcd > MinGCD && (m_spellInfo.StartRecoveryCategory == 133 && !isMeleeOrRangedSpell)) @@ -8265,7 +8265,7 @@ namespace Game.Spells procVictim.Or(ProcFlags.TakeHarmfulPeriodic); } } - else if (spell.m_spellInfo.HasAttribute(SpellAttr0.Ability)) + else if (spell.m_spellInfo.HasAttribute(SpellAttr0.IsAbility)) { if (positive) { @@ -8393,7 +8393,7 @@ namespace Game.Spells if (caster.IsPlayer() && procSpellType.HasAnyFlag(ProcFlagsSpellType.Damage | ProcFlagsSpellType.NoDmgHeal)) { if (spell.m_spellInfo.DmgClass == SpellDmgClass.Melee || spell.m_spellInfo.DmgClass == SpellDmgClass.Ranged) - if (!spell.m_spellInfo.HasAttribute(SpellAttr0.StopAttackTarget) && !spell.m_spellInfo.HasAttribute(SpellAttr4.SuppressWeaponProcs)) + if (!spell.m_spellInfo.HasAttribute(SpellAttr0.CancelsAutoAttackCombat) && !spell.m_spellInfo.HasAttribute(SpellAttr4.SuppressWeaponProcs)) caster.ToPlayer().CastItemCombatSpell(spellDamageInfo); } } diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index a7f0af2c6..060121211 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -1002,7 +1002,7 @@ namespace Game.Spells if (effectHandleMode != SpellEffectHandleMode.HitTarget) return; - DoCreateItem(effectInfo.ItemType, m_spellInfo.HasAttribute(SpellAttr0.Tradespell) ? ItemContext.TradeSkill : ItemContext.None); + DoCreateItem(effectInfo.ItemType, m_spellInfo.HasAttribute(SpellAttr0.IsTradeskill) ? ItemContext.TradeSkill : ItemContext.None); ExecuteLogEffectCreateItem(effectInfo.Effect, effectInfo.ItemType); } @@ -1017,7 +1017,7 @@ namespace Game.Spells Player player = unitTarget.ToPlayer(); - ItemContext context = m_spellInfo.HasAttribute(SpellAttr0.Tradespell) ? ItemContext.TradeSkill : ItemContext.None; + ItemContext context = m_spellInfo.HasAttribute(SpellAttr0.IsTradeskill) ? ItemContext.TradeSkill : ItemContext.None; // Pick a random item from spell_loot_template if (m_spellInfo.IsLootCrafting()) @@ -1046,7 +1046,7 @@ namespace Game.Spells Player player = unitTarget.ToPlayer(); // create some random items - player.AutoStoreLoot(m_spellInfo.Id, LootStorage.Spell, m_spellInfo.HasAttribute(SpellAttr0.Tradespell) ? ItemContext.TradeSkill : ItemContext.None); + player.AutoStoreLoot(m_spellInfo.Id, LootStorage.Spell, m_spellInfo.HasAttribute(SpellAttr0.IsTradeskill) ? ItemContext.TradeSkill : ItemContext.None); // @todo ExecuteLogEffectCreateItem(i, GetEffect(i].ItemType); } @@ -2029,7 +2029,7 @@ namespace Game.Spells unitTarget = player; // and add a scroll damage = 1; - DoCreateItem(effectInfo.ItemType, m_spellInfo.HasAttribute(SpellAttr0.Tradespell) ? ItemContext.TradeSkill : ItemContext.None); + DoCreateItem(effectInfo.ItemType, m_spellInfo.HasAttribute(SpellAttr0.IsTradeskill) ? ItemContext.TradeSkill : ItemContext.None); itemTarget = null; m_targets.SetItemTarget(null); } diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index 258ce0add..a9f961e4a 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -480,7 +480,7 @@ namespace Game.Spells public bool IsCooldownStartedOnEvent() { - if (HasAttribute(SpellAttr0.DisabledWhileActive)) + if (HasAttribute(SpellAttr0.CooldownOnEvent)) return true; SpellCategoryRecord category = CliDB.SpellCategoryStorage.LookupByKey(CategoryId); @@ -529,7 +529,7 @@ namespace Game.Spells public bool CanBeUsedInCombat() { - return !HasAttribute(SpellAttr0.CantUsedInCombat); + return !HasAttribute(SpellAttr0.NotInCombatOnlyPeaceful); } public bool IsPositive() @@ -563,7 +563,7 @@ namespace Game.Spells public bool IsNextMeleeSwingSpell() { - return HasAttribute(SpellAttr0.OnNextSwing | SpellAttr0.OnNextSwing2); + return HasAttribute(SpellAttr0.OnNextSwingNoDamage | SpellAttr0.OnNextSwing); } public bool IsBreakingStealth() @@ -575,7 +575,7 @@ namespace Game.Spells { return (SpellFamilyName == SpellFamilyNames.Hunter && !SpellFamilyFlags[1].HasAnyFlag(0x10000000u)) // for 53352, cannot find better way || Convert.ToBoolean(EquippedItemSubClassMask & (int)ItemSubClassWeapon.MaskRanged) - || Attributes.HasAnyFlag(SpellAttr0.ReqAmmo); + || Attributes.HasAnyFlag(SpellAttr0.UsesRangedSlot); } public bool IsAutoRepeatRangedSpell() @@ -681,11 +681,11 @@ namespace Game.Spells public bool CanPierceImmuneAura(SpellInfo auraSpellInfo) { // aura can't be pierced - if (auraSpellInfo == null || auraSpellInfo.HasAttribute(SpellAttr0.UnaffectedByInvulnerability)) + if (auraSpellInfo == null || auraSpellInfo.HasAttribute(SpellAttr0.NoImmunities)) return false; // these spells pierce all avalible spells (Resurrection Sickness for example) - if (HasAttribute(SpellAttr0.UnaffectedByInvulnerability)) + if (HasAttribute(SpellAttr0.NoImmunities)) return true; // these spells (Cyclone for example) can pierce all... @@ -708,11 +708,11 @@ namespace Game.Spells public bool CanDispelAura(SpellInfo auraSpellInfo) { // These auras (like Divine Shield) can't be dispelled - if (auraSpellInfo.HasAttribute(SpellAttr0.UnaffectedByInvulnerability)) + if (auraSpellInfo.HasAttribute(SpellAttr0.NoImmunities)) return false; // These spells (like Mass Dispel) can dispel all auras - if (HasAttribute(SpellAttr0.UnaffectedByInvulnerability)) + if (HasAttribute(SpellAttr0.NoImmunities)) return true; // These auras (Cyclone for example) are not dispelable @@ -827,7 +827,7 @@ namespace Game.Spells if (actAsShifted) { - if (HasAttribute(SpellAttr0.NotShapeshift) || (shapeInfo != null && shapeInfo.Flags.HasAnyFlag(SpellShapeshiftFormFlags.CanOnlyCastShapeshiftSpells))) // not while shapeshifted + if (HasAttribute(SpellAttr0.NotShapeshifted) || (shapeInfo != null && shapeInfo.Flags.HasAnyFlag(SpellShapeshiftFormFlags.CanOnlyCastShapeshiftSpells))) // not while shapeshifted return SpellCastResult.NotShapeshift; else if (Stances != 0) // needs other shapeshift return SpellCastResult.OnlyShapeshift; @@ -1243,7 +1243,7 @@ namespace Game.Spells checkMask = VehicleSeatFlags.CanAttack; var vehicleSeat = vehicle.GetSeatForPassenger(caster); - if (!HasAttribute(SpellAttr6.CastableWhileOnVehicle) && !HasAttribute(SpellAttr0.CastableWhileMounted) + if (!HasAttribute(SpellAttr6.CastableWhileOnVehicle) && !HasAttribute(SpellAttr0.AllowWhileMounted) && (vehicleSeat.Flags & (int)checkMask) != (int)checkMask) return SpellCastResult.CantDoThatRightNow; @@ -2587,7 +2587,7 @@ namespace Game.Spells if (!HasAttribute(SpellAttr1.DispelAurasOnImmunity)) return false; - if (aurEff.GetSpellInfo().HasAttribute(SpellAttr0.UnaffectedByInvulnerability)) + if (aurEff.GetSpellInfo().HasAttribute(SpellAttr0.NoImmunities)) return false; foreach (var effectInfo in GetEffects()) @@ -2715,7 +2715,7 @@ namespace Game.Spells if (spell != null) spell.GetCaster().ModSpellCastTime(this, ref castTime, spell); - if (HasAttribute(SpellAttr0.ReqAmmo) && (!IsAutoRepeatRangedSpell()) && !HasAttribute(SpellAttr9.AimedShot)) + if (HasAttribute(SpellAttr0.UsesRangedSlot) && (!IsAutoRepeatRangedSpell()) && !HasAttribute(SpellAttr9.AimedShot)) castTime += 500; return (castTime > 0) ? castTime : 0; @@ -2949,7 +2949,7 @@ namespace Game.Spells if (!unitCaster.IsControlledByPlayer() && MathFunctions.fuzzyEq(power.PowerCostPct, 0.0f) && SpellLevel != 0 && power.PowerType == PowerType.Mana) { - if (HasAttribute(SpellAttr0.LevelDamageCalculation)) + if (HasAttribute(SpellAttr0.ScalesWithCreatureLevel)) { GtNpcManaCostScalerRecord spellScaler = CliDB.NpcManaCostScalerGameTable.GetRow(SpellLevel); GtNpcManaCostScalerRecord casterScaler = CliDB.NpcManaCostScalerGameTable.GetRow(unitCaster.GetLevel()); @@ -3180,7 +3180,7 @@ namespace Game.Spells return this; // Client ignores spell with these attributes (sub_53D9D0) - if (HasAttribute(SpellAttr0.Negative1) || HasAttribute(SpellAttr2.Unk3) || HasAttribute(SpellAttr3.DrainSoul)) + if (HasAttribute(SpellAttr0.AuraIsDebuff) || HasAttribute(SpellAttr2.Unk3) || HasAttribute(SpellAttr3.DrainSoul)) return this; bool needRankSelection = false; @@ -3325,7 +3325,7 @@ namespace Game.Spells return true; // not found a single positive spell with this attribute - if (spellInfo.HasAttribute(SpellAttr0.Negative1)) + if (spellInfo.HasAttribute(SpellAttr0.AuraIsDebuff)) return false; visited.Add(Tuple.Create(spellInfo, effect.EffectIndex)); @@ -4257,7 +4257,7 @@ namespace Game.Spells ExpectedStatType stat = GetScalingExpectedStat(); if (stat != ExpectedStatType.None) { - if (_spellInfo.HasAttribute(SpellAttr0.LevelDamageCalculation)) + if (_spellInfo.HasAttribute(SpellAttr0.ScalesWithCreatureLevel)) stat = ExpectedStatType.CreatureAutoAttackDps; // TODO - add expansion and content tuning id args? diff --git a/Source/Game/Spells/SpellManager.cs b/Source/Game/Spells/SpellManager.cs index 8dcbf833b..fcfb55634 100644 --- a/Source/Game/Spells/SpellManager.cs +++ b/Source/Game/Spells/SpellManager.cs @@ -1958,7 +1958,7 @@ namespace Game.Entities if (spellInfo != null) { if (spellArea.flags.HasAnyFlag(SpellAreaFlag.AutoCast)) - spellInfo.Attributes |= SpellAttr0.CantCancel; + spellInfo.Attributes |= SpellAttr0.NoAuraCancel; } else { @@ -2776,7 +2776,7 @@ namespace Game.Entities default: { // No value and not interrupt cast or crowd control without SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY flag - if (spellEffectInfo.CalcValue() == 0 && !((spellEffectInfo.Effect == SpellEffectName.InterruptCast || spellInfo.HasAttribute(SpellCustomAttributes.AuraCC)) && !spellInfo.HasAttribute(SpellAttr0.UnaffectedByInvulnerability))) + if (spellEffectInfo.CalcValue() == 0 && !((spellEffectInfo.Effect == SpellEffectName.InterruptCast || spellInfo.HasAttribute(SpellCustomAttributes.AuraCC)) && !spellInfo.HasAttribute(SpellAttr0.NoImmunities))) break; // Sindragosa Frost Breath @@ -4012,7 +4012,7 @@ namespace Game.Entities // Val'kyr Target Search ApplySpellFix(new[] { 69030 }, spellInfo => { - spellInfo.Attributes |= SpellAttr0.UnaffectedByInvulnerability; + spellInfo.Attributes |= SpellAttr0.NoImmunities; }); // Raging Spirit Visual @@ -4141,7 +4141,7 @@ namespace Game.Entities 40167, // Introspection }, spellInfo => { - spellInfo.Attributes |= SpellAttr0.Negative1; + spellInfo.Attributes |= SpellAttr0.AuraIsDebuff; }); // @@ -4185,7 +4185,7 @@ namespace Game.Entities // Travel Form (dummy) - cannot be cast indoors. ApplySpellFix(new[] { 783 }, spellInfo => { - spellInfo.Attributes |= SpellAttr0.OutdoorsOnly; + spellInfo.Attributes |= SpellAttr0.OnlyOutdoors; }); // Tree of Life (Passive) @@ -4288,7 +4288,7 @@ namespace Game.Entities // Torment Damage ApplySpellFix(new[] { 99256 }, spellInfo => { - spellInfo.Attributes |= SpellAttr0.Negative1; + spellInfo.Attributes |= SpellAttr0.AuraIsDebuff; }); // Blaze of Glory @@ -4335,7 +4335,7 @@ namespace Game.Entities // Headless Horseman Climax - Head Is Dead ApplySpellFix(new[] { 42401, 43105, 42428 }, spellInfo => { - spellInfo.Attributes |= SpellAttr0.UnaffectedByInvulnerability; + spellInfo.Attributes |= SpellAttr0.NoImmunities; }); // Horde / Alliance switch (BG mercenary system)