private void InitAura() { // procs if (ProcTriggerFlags != ProcTriggerFlags.None || CasterProcSpells != null) { ProcTriggerEffects = Effects.Where(effect => effect.IsProc).ToArray(); if (ProcTriggerEffects.Length == 0) { // no proc-specific effects -> all effects are triggered on proc ProcTriggerEffects = null; } //else if (ProcTriggerEffects.Length > 1) //{ // log.Warn("Spell {0} had more than one ProcTriggerEffect", this); //} IsProc = ProcTriggerEffects != null || ProcHandlers != null || CasterProcSpells != null || ProcCharges > 0; } IsAura = IsProc || HasEffectWith(effect => { if (effect.AuraType != AuraType.None) { return(true); } return(false); }); ForeachEffect(effect => { if (effect.IsAuraEffect) { HasNonPeriodicAuraEffects = HasNonPeriodicAuraEffects || !effect.IsPeriodic; HasPeriodicAuraEffects = HasPeriodicAuraEffects || effect.IsPeriodic; } }); IsAutoRepeating = AttributesExB.HasFlag(SpellAttributesExB.AutoRepeat); HasManaShield = HasEffectWith(effect => effect.AuraType == AuraType.ManaShield); AuraEffects = GetEffectsWhere(effect => effect.AuraEffectHandlerCreator != null); AreaAuraEffects = GetEffectsWhere(effect => effect.IsAreaAuraEffect); IsAreaAura = AreaAuraEffects != null; IsPureAura = !IsDamageSpell && !HasEffectWith(effect => effect.EffectType != SpellEffectType.ApplyAura || effect.EffectType != SpellEffectType.ApplyAuraToMaster || effect.EffectType != SpellEffectType.ApplyStatAura || effect.EffectType != SpellEffectType.ApplyStatAuraPercent); IsPureBuff = IsPureAura && HasBeneficialEffects && !HasHarmfulEffects; IsPureDebuff = IsPureAura && HasHarmfulEffects && !HasBeneficialEffects; IsVehicle = HasEffectWith(effect => effect.AuraType == AuraType.Vehicle); IsShapeshift = HasEffectWith(effect => { //if (effect.AuraType == AuraType.ModShapeshift) //{ // var info = SpellHandler.ShapeshiftEntries.Get((uint)effect.MiscValue); // return info.CreatureType > 0; //} return(effect.AuraType == AuraType.ModShapeshift || effect.AuraType == AuraType.Transform); }); // charges and stacks: CanStack = MaxStackCount > 0; if (ProcCharges > 0) { // applications will be used up by procs InitialStackCount = ProcCharges; } else { // applications can be added by re-applying InitialStackCount = 1; } IsGhost = HasEffectWith(effect => effect.AuraType == AuraType.Ghost); HasFlyEffect = HasEffectWith(effect => effect.AuraType == AuraType.Fly); IsFlyingMount = IsMount && HasEffectWith(effect => effect.AuraType == AuraType.ModSpeedMountedFlight); CanApplyMultipleTimes = Attributes == (SpellAttributes.InvisibleAura | SpellAttributes.Passive) && Ability == null && Talent == null; HasShapeshiftDependentEffects = HasEffectWith(effect => effect.RequiredShapeshiftMask != 0); IsModalShapeshiftDependentAura = IsPassive && (RequiredShapeshiftMask != 0 || HasShapeshiftDependentEffects); if (AuraUID == 0) { CreateAuraUID(); } }
/// <summary> /// Checks whether the given target is valid for the given caster. /// Is called automatically when SpellCast selects Targets. /// Does not do maximum range check. /// </summary> public SpellFailedReason CheckValidTarget(WorldObject caster, WorldObject target) { if (AttributesEx.HasAnyFlag(SpellAttributesEx.CannotTargetSelf) && target == caster) { return(SpellFailedReason.NoValidTargets); } if (target is Unit) { // AuraState if (RequiredTargetAuraState != 0 || ExcludeTargetAuraState != 0) { var state = ((Unit)target).AuraState; if ((RequiredTargetAuraState != 0 && !state.HasAnyFlag(RequiredTargetAuraState)) || (ExcludeTargetAuraState != 0 && state.HasAnyFlag(ExcludeTargetAuraState))) { return(SpellFailedReason.TargetAurastate); } } // Required Auras if ((ExcludeTargetAuraId != 0 && ((Unit)target).Auras.Contains(ExcludeTargetAuraId)) || (RequiredTargetAuraId != 0 && !((Unit)target).Auras.Contains(RequiredTargetAuraId))) { return(SpellFailedReason.TargetAurastate); } } // Make sure that we have a GameObject if the Spell requires one if (TargetFlags.HasAnyFlag(SpellTargetFlags.UnkUnit_0x100) && (!(target is GameObject) || !target.IsInWorld)) { return(SpellFailedReason.BadTargets); } // CreatureTypes /*if (CreatureMask != CreatureMask.None && * (!(target is NPC) || !((NPC)target).CheckCreatureType(CreatureMask))) * { * return SpellFailedReason.BadImplicitTargets; * }*/ if (!CanCastOnPlayer && target is Character) { return(SpellFailedReason.BadImplicitTargets); } // Corpse target if (RequiresDeadTarget) { if (TargetFlags.HasAnyFlag(SpellTargetFlags.PvPCorpse | SpellTargetFlags.Corpse)) { if (!(target is Corpse) || (TargetFlags.HasAnyFlag(SpellTargetFlags.PvPCorpse) && caster != null && !caster.IsHostileWith(target))) { return(SpellFailedReason.BadImplicitTargets); } } else if ((target is NPC)) { // need to be dead and looted empty if (((NPC)target).IsAlive || target.Loot != null) { return(SpellFailedReason.TargetNotDead); } } else if ((target is Character)) { if (((Character)target).IsAlive) { return(SpellFailedReason.TargetNotDead); } } } else { if (target is Unit && !((Unit)target).IsAlive) { return(SpellFailedReason.TargetsDead); } } // Rogues do it from behind if (AttributesExB.HasFlag(SpellAttributesExB.RequiresBehindTarget)) { if (caster != null && !caster.IsBehind(target)) { return(SpellFailedReason.NotBehind); } } //if (AttributesExC.HasFlag(SpellAttributesExC.NoInitialAggro)) //{ // if (target is Unit && ((Unit)target).IsInCombat) // { // return SpellFailedReason.TargetAffectingCombat; // } //} if (Range.MinDist > 0 && caster != null && //caster.IsInRadius(target, caster.GetSpellMinRange(Range.MinDist, target))) caster.IsInRadius(target, Range.MinDist)) { return(SpellFailedReason.TooClose); } return(SpellFailedReason.Ok); }
/// <summary> /// Checks whether the given spell can be casted by the casting Unit. /// Does not do range checks. /// </summary> public SpellFailedReason CheckCasterConstraints(Unit caster) { // check for combat if (caster.IsInCombat && RequiresCasterOutOfCombat) { return(SpellFailedReason.AffectingCombat); } // Power Type if (CostsPower && PowerType != caster.PowerType && PowerType != PowerType.Health && !AttributesExB.HasFlag(SpellAttributesExB.DoesNotNeedShapeshift)) { return(SpellFailedReason.OnlyShapeshift); } if (!caster.CanDoHarm && HasHarmfulEffects) { return(SpellFailedReason.Pacified); } // Not while silenced if (InterruptFlags.HasFlag(InterruptFlags.OnSilence) && caster.IsUnderInfluenceOf(SpellMechanic.Silenced)) { return(SpellFailedReason.Silenced); } // Check if castable while stunned if (!AttributesExD.HasFlag(SpellAttributesExD.UsableWhileStunned) && !caster.CanInteract) { return(SpellFailedReason.CantDoThatRightNow); } // Combo points if (IsFinishingMove && caster.ComboPoints == 0) { return(SpellFailedReason.NoComboPoints); } // spell focus if (!CheckSpellFocus(caster)) { return(SpellFailedReason.RequiresSpellFocus); } // Not while silenced else if (!caster.CanCastSpells && (!IsPhysicalAbility || (InterruptFlags.HasFlag(InterruptFlags.OnSilence) && caster.IsUnderInfluenceOf(SpellMechanic.Silenced)))) { return(SpellFailedReason.Silenced); } // cannot use physical ability or not do harm at all else if ((!caster.CanDoPhysicalActivity && IsPhysicalAbility) || (!caster.CanDoHarm && HasHarmfulEffects)) { return(SpellFailedReason.Pacified); } else if (!AttributesExD.HasFlag(SpellAttributesExD.UsableWhileStunned) && !caster.CanInteract) { return(SpellFailedReason.Stunned); } // Combo points else if (IsFinishingMove && caster.ComboPoints == 0) { return(SpellFailedReason.NoComboPoints); } // AuraStates if (RequiredCasterAuraState != 0 || ExcludeCasterAuraState != 0) { // check AuraStates var state = caster.AuraState; if ((RequiredCasterAuraState != 0 && !state.HasAnyFlag(RequiredCasterAuraState)) || (ExcludeCasterAuraState != 0 && state.HasAnyFlag(ExcludeCasterAuraState))) { return(SpellFailedReason.CasterAurastate); } } // Required Auras if ((ExcludeCasterAuraId != 0 && caster.Auras.Contains(ExcludeCasterAuraId)) || (RequiredCasterAuraId != 0 && !caster.Auras.Contains(RequiredCasterAuraId))) { return(SpellFailedReason.CasterAurastate); } // Shapeshift var shapeshiftMask = caster.ShapeshiftMask; bool ignoreShapeshiftRequirement = false; // use this to allow for lazy requirement lookup if (ExcludeShapeshiftMask.HasAnyFlag(shapeshiftMask)) { if (!(ignoreShapeshiftRequirement = caster.Auras.IsShapeshiftRequirementIgnored(this))) { return(SpellFailedReason.NotShapeshift); } } else if (!RequiredShapeshiftMask.HasAnyFlag(shapeshiftMask)) { // our mask did not pass -> do the default checks var shapeshiftEntry = caster.ShapeshiftEntry; var shapeshifted = shapeshiftEntry != null && (shapeshiftEntry.Flags & ShapeshiftInfoFlags.NotActualShapeshift) == 0; if (shapeshifted) { if (RequiredShapeshiftMask != 0) { // When shapeshifted, can only use spells that allow this form if (!(ignoreShapeshiftRequirement = caster.Auras.IsShapeshiftRequirementIgnored(this))) { return(SpellFailedReason.OnlyShapeshift); } } else if (Attributes.HasAnyFlag(SpellAttributes.NotWhileShapeshifted)) { if (!(ignoreShapeshiftRequirement = caster.Auras.IsShapeshiftRequirementIgnored(this))) { // cannot cast this spell when shapeshifted return(SpellFailedReason.NotShapeshift); } } } if (Attributes.HasFlag(SpellAttributes.RequiresStealth) && caster.Stealthed < 1) { if (!caster.Auras.IsShapeshiftRequirementIgnored(this)) { // Stealth Required, but not stealthed and not ignored by a SPELL_AURA_MOD_IGNORE_SHAPESHIFT aura return(SpellFailedReason.OnlyStealthed); } } } var spells = caster.Spells as PlayerSpellCollection; // check cooldown and power cost if (spells != null && !spells.IsReady(this)) { return(SpellFailedReason.NotReady); } if (!IsPassive) { if (!caster.HasEnoughPowerToCast(this, null)) { return(SpellFailedReason.NoPower); } } return(SpellFailedReason.Ok); }