//internal static readonly ObjectPool<List<AuraApplicationInfo>> AuraAppListPool = ObjectPoolMgr.CreatePool(() => new List<AuraApplicationInfo>()); public static void Trigger(WorldObject caster, SpellEffect triggerEffect, Spell spell) { var cast = SpellCastPool.Obtain(); cast.Caster = caster; cast.m_triggerEffect = triggerEffect; caster.ExecuteInContext(() => { cast.Start(spell, true); cast.Dispose(); }); }
private void CreateHandler(SpellEffect effect, int h, SpellEffectHandler[] handlers, ref SpellTargetCollection targets, ref SpellFailedReason failReason) { var handler = effect.SpellEffectHandlerCreator(this, effect); handlers[h] = handler; // make sure, we have the right Caster-Type handler.CheckCasterType(ref failReason); if (failReason != SpellFailedReason.Ok) { return; } // find targets and amount SpellTargetCollection if effects have same ImplicitTargetTypes if (InitialTargets != null) { // do we have given targets? if (targets == null) { targets = CreateSpellTargetCollection(); } } else if (handler.HasOwnTargets) { // see if targets are shared between effects targets = null; for (var j = 0; j < h; j++) { var handler2 = handlers[j]; if (handler.Effect.SharesTargetsWith(handler2.Effect, IsAICast)) { // same targets -> share target collection targets = handler2.m_targets; break; } } if (targets == null) { targets = CreateSpellTargetCollection(); } } if (targets != null) { handler.m_targets = targets; targets.m_handlers.Add(handler); } }
/// <summary> /// Leeches the given amount of power from this Unit and adds it to the receiver (if receiver != null and is Unit). /// </summary> public void LeechPower(Unit receiver, int amount, float factor, SpellEffect effect) { var currentPower = Power; // Resilience reduces mana drain by 2.2%, amount is rounded. amount -= (amount * GetResiliencePct() * 2.2f).RoundInt(); if (amount > currentPower) { amount = currentPower; } Power = currentPower - amount; if (receiver != null) { receiver.Energize(this, amount, effect); } }
/// <summary> /// Leeches the given amount of health from this Unit and adds it to the receiver (if receiver != null and is Unit). /// </summary> /// <param name="factor">The factor applied to the amount that was leeched before adding it to the receiver</param> public void LeechHealth(Unit receiver, int amount, float factor, SpellEffect effect) { var initialHealth = Health; DoSpellDamage(receiver != null ? receiver.Master : this, effect, amount); // only apply as much as was leeched amount = initialHealth - Health; if (factor > 0) { amount = (int)(amount * factor); } if (receiver != null) { receiver.Heal(this, amount, effect); } }
/// <summary> /// Heals this unit and sends the corresponding animation (healer might be null) /// </summary> /// <param name="effect">The effect of the spell that triggered the healing (or null)</param> /// <param name="healer">The object that heals this Unit (or null)</param> /// <param name="value">The amount to be healed</param> public void Heal(Unit healer, int value, SpellEffect effect) { var critChance = 0f; var crit = false; int overheal = 0; if (effect != null) { var oldVal = value; if (healer != null) { if (effect.IsPeriodic) { // add periodic boni if (healer is Character) { value = ((Character)healer).PlayerSpells.GetModifiedInt(SpellModifierType.PeriodicEffectValue, effect.Spell, value); } } else { // add healing mods (spell power for healing) value = healer.AddHealingModsToAction(value, effect, effect.Spell.Schools[0]); } } if (this is Character) { value += (int) ((oldVal*((Character) this).HealingTakenModPct)/100); } critChance = GetSpellCritChance((DamageSchool) effect.Spell.SchoolMask)*100; // do a critcheck if (!effect.Spell.AttributesExB.HasFlag(SpellAttributesExB.CannotCrit) && critChance != 0) { var roll = Utility.Random(1f, 10001); if (roll <= critChance) { value = (int) (value*(SpellHandler.SpellCritBaseFactor + GetIntMod(StatModifierInt.CriticalHealValuePct))); crit = true; } } } if (value > 0) { value = (int)(value * Utility.Random(0.95f, 1.05f)); if (Health + value > MaxHealth) { overheal = (Health + value) - MaxHealth; value = (MaxHealth - Health); } Health += value; value += overheal; CombatLogHandler.SendHealLog(healer, this, effect != null ? effect.Spell.Id : 0, value, crit, overheal); } if (healer != null) { var action = new HealAction { Attacker = (Unit)healer, Victim = this, Spell = effect != null ? effect.Spell : null, IsCritical = crit, Value = value }; healer.Proc(ProcTriggerFlags.HealOther, this, action, true); Proc(ProcTriggerFlags.Heal, healer, action, false); OnHeal(healer, effect, value); } }
public void ClearEffects() { Effects = new SpellEffect[0]; }
/// <summary> /// Removes the first Effect of the given Type and replace it with a new one which will be returned. /// Appends a new one if none of the given type was found. /// </summary> /// <param name="type"></param> /// <returns></returns> public SpellEffect ReplaceEffect(SpellEffectType type) { for (var i = 0; i < Effects.Length; i++) { var effect = Effects[i]; if (effect.EffectType == type) { return Effects[i] = new SpellEffect(); } } return AddEffect(SpellEffectType.None); }
/// <summary> /// Sets all default variables /// </summary> internal void Initialize() { var learnSpellEffect = GetEffect(SpellEffectType.LearnSpell); if (learnSpellEffect == null) { learnSpellEffect = GetEffect(SpellEffectType.LearnPetSpell); } if (learnSpellEffect != null && learnSpellEffect.TriggerSpellId != 0) { IsTeachSpell = true; } // figure out Trigger spells for (var i = 0; i < Effects.Length; i++) { var effect = Effects[i]; if (effect.TriggerSpellId != SpellId.None || effect.AuraType == AuraType.PeriodicTriggerSpell) { var triggeredSpell = SpellHandler.Get((uint)effect.TriggerSpellId); if (triggeredSpell != null) { if (!IsTeachSpell) { triggeredSpell.IsTriggeredSpell = true; } else { LearnSpell = triggeredSpell; } effect.TriggerSpell = triggeredSpell; } else { if (IsTeachSpell) { IsTeachSpell = GetEffect(SpellEffectType.LearnSpell) != null; } Effects[i].IsInvalid = true; } } } foreach (var effect in Effects) { if (effect.EffectType == SpellEffectType.PersistantAreaAura || effect.HasTarget(ImplicitTargetType.DynamicObject)) { DOEffect = effect; break; } } //foreach (var effect in Effects) //{ // effect.Initialize(); //} }
public ClearCastingAndPresenceOfMindHandler(SpellCast cast, SpellEffect effect) : base(cast, effect) { }
public DeathCoilHandler(SpellCast cast, SpellEffect effect) : base(cast, effect) { }
public AddBleedWeaponDamageHandler(SpellCast cast, SpellEffect effect) : base(cast, effect) { }
public FerociousBiteHandler(SpellCast cast, SpellEffect effect) : base(cast, effect) { }
/// <summary> /// Adds immunity against given damage-schools /// </summary> public void IncDmgImmunityCount(SpellEffect effect) { if (m_dmgImmunities == null) { m_dmgImmunities = CreateDamageSchoolArr(); } foreach (var school in effect.MiscBitSet) { m_dmgImmunities[(int)school]++; } Auras.RemoveWhere(aura => aura.Spell.AuraUID != effect.Spell.AuraUID && aura.Spell.SchoolMask.HasAnyFlag(effect.Spell.SchoolMask) && !aura.Spell.Attributes.HasFlag(SpellAttributes.UnaffectedByInvulnerability)); }
/// <summary> /// Threat mod in percent /// </summary> public virtual int GetGeneratedThreat(int dmg, DamageSchool school, SpellEffect effect) { if (m_threatMods == null) { return dmg; } return dmg + ((dmg * m_threatMods[(int)school]) / 100); }
public DeathStrikeHealHandler(SpellCast cast, SpellEffect effect) : base(cast, effect) { }
public void RemoveEffect(SpellEffect toRemove) { var effects = new SpellEffect[Effects.Length - 1]; var e = 0; foreach (var effct in Effects) { if (effct != toRemove) { effects[e++] = effct; } } Effects = effects; }
public CorpseExplosionHandler(SpellCast cast, SpellEffect effect) : base(cast, effect) { }
public BurnoutHandler(SpellCast cast, SpellEffect effect) : base(cast, effect) { }
/// <summary> /// Heals this unit and sends the corresponding animation (healer might be null) /// </summary> /// <param name="effect">The effect of the spell that triggered the healing (or null)</param> /// <param name="healer">The object that heals this Unit (or null)</param> /// <param name="value">The amount to be healed</param> public void HealPercent(int value, Unit healer = null, SpellEffect effect = null) { Heal((value * MaxHealth + 50) / 100, healer, effect); }
/// <summary> /// For all things that depend on info of all spells from first Init-round and other things /// </summary> internal void Init2() { if (inited) { return; } inited = true; IsChanneled = AttributesEx.HasAnyFlag(SpellAttributesEx.Channeled_1 | SpellAttributesEx.Channeled_2) || // don't use Enum.HasFlag! ChannelInterruptFlags > 0; IsPassive = (!IsChanneled && Attributes.HasFlag(SpellAttributes.Passive)) || // tracking spells are also passive HasEffectWith(effect => effect.AuraType == AuraType.TrackCreatures) || HasEffectWith(effect => effect.AuraType == AuraType.TrackResources) || HasEffectWith(effect => effect.AuraType == AuraType.TrackStealthed); foreach (var effect in Effects) { effect.Init2(); if (effect.IsHealEffect) { IsHealSpell = true; } if (effect.EffectType == SpellEffectType.NormalizedWeaponDamagePlus) { IsDualWieldAbility = true; } } InitAura(); if (IsChanneled) { if (Durations.Min == 0) { Durations.Min = Durations.Max = 1000; } foreach (var effect in Effects) { if (effect.IsPeriodic) { ChannelAmplitude = effect.Amplitude; break; } } } IsOnNextStrike = Attributes.HasAnyFlag(SpellAttributes.OnNextMelee | SpellAttributes.OnNextMelee_2); // don't use Enum.HasFlag! IsRangedAbility = !IsTriggeredSpell && (Attributes.HasAnyFlag(SpellAttributes.Ranged) || AttributesExC.HasFlag(SpellAttributesExC.ShootRangedWeapon)); IsStrikeSpell = HasEffectWith(effect => effect.IsStrikeEffect); IsWeaponAbility = IsRangedAbility || IsOnNextStrike || IsStrikeSpell; DamageIncreasedByAP = DamageIncreasedByAP || (PowerType == PowerType.Rage && SchoolMask == DamageSchoolMask.Physical); IsFinishingMove = AttributesEx.HasAnyFlag(SpellAttributesEx.FinishingMove) || HasEffectWith(effect => effect.PointsPerComboPoint > 0 && effect.EffectType != SpellEffectType.Dummy); TotemEffect = GetFirstEffectWith(effect => effect.HasTarget( ImplicitTargetType.TotemAir, ImplicitTargetType.TotemEarth, ImplicitTargetType.TotemFire, ImplicitTargetType.TotemWater)); // Required Item slot for weapon abilities if (RequiredItemClass == ItemClass.Armor && RequiredItemSubClassMask == ItemSubClassMask.Shield) { EquipmentSlot = EquipmentSlot.OffHand; } else { EquipmentSlot = (IsRangedAbility || AttributesExC.HasFlag(SpellAttributesExC.RequiresWand)) ? EquipmentSlot.ExtraWeapon : (AttributesExC.HasFlag(SpellAttributesExC.RequiresOffHandWeapon) ? EquipmentSlot.OffHand : (AttributesExC.HasFlag(SpellAttributesExC.RequiresMainHandWeapon) ? EquipmentSlot.MainHand : EquipmentSlot.End)); } HasIndividualCooldown = CooldownTime > 0 || (IsWeaponAbility && !IsOnNextStrike && EquipmentSlot != EquipmentSlot.End); //IsAoe = HasEffectWith((effect) => { // if (effect.ImplicitTargetA == ImplicitTargetType.) // effect.ImplicitTargetA = ImplicitTargetType.None; // if (effect.ImplicitTargetB == ImplicitTargetType.Unused_EnemiesInAreaChanneledWithExceptions) // effect.ImplicitTargetB = ImplicitTargetType.None; // return false; //}); var profEffect = GetEffect(SpellEffectType.SkillStep); if (profEffect != null) { TeachesApprenticeAbility = profEffect.BasePoints == 0; } IsProfession = !IsRangedAbility && Ability != null && Ability.Skill.Category == SkillCategory.Profession; IsEnhancer = SpellClassSet != 0 && !SpellClassMask.Contains(val => val != 0) && HasEffectWith(effect => effect.AffectMask.Contains(val => val != 0)); IsFishing = HasEffectWith(effect => effect.HasTarget(ImplicitTargetType.SelfFishing)); IsSkinning = HasEffectWith(effect => effect.EffectType == SpellEffectType.Skinning); IsTameEffect = HasEffectWith(effect => effect.EffectType == SpellEffectType.TameCreature); if (Id == 18425) { ToString(); } if (IsPreventionDebuff || Mechanic.IsNegative()) { HasHarmfulEffects = true; HasBeneficialEffects = false; HarmType = HarmType.Harmful; } else { HasHarmfulEffects = HasEffectWith(effect => effect.HarmType == HarmType.Harmful); HasBeneficialEffects = HasEffectWith(effect => effect.HarmType == HarmType.Beneficial); if (HasHarmfulEffects != HasBeneficialEffects && !HasEffectWith(effect => effect.HarmType == HarmType.Neutral)) { HarmType = HasHarmfulEffects ? HarmType.Harmful : HarmType.Beneficial; } else { HarmType = HarmType.Neutral; } } ReqDeadTarget = TargetFlags.HasAnyFlag(SpellTargetFlags.Corpse | SpellTargetFlags.PvPCorpse | SpellTargetFlags.UnitCorpse); CostsMana = PowerCost > 0 || PowerCostPercentage > 0; HasTargets = !HasEffectWith(effect => effect.HasTargets); CasterIsTarget = HasTargets && HasEffectWith(effect => effect.HasTarget(ImplicitTargetType.Self)); //HasSingleNotSelfTarget = IsAreaSpell = HasEffectWith(effect => effect.IsAreaEffect); IsDamageSpell = HasHarmfulEffects && !HasBeneficialEffects && HasEffectWith(effect => effect.EffectType == SpellEffectType.Attack || effect.EffectType == SpellEffectType.EnvironmentalDamage || effect.EffectType == SpellEffectType.InstantKill || effect.EffectType == SpellEffectType.SchoolDamage || effect.IsStrikeEffect); if (DamageMultipliers[0] <= 0) { DamageMultipliers[0] = 1; } IsHearthStoneSpell = HasEffectWith(effect => effect.HasTarget(ImplicitTargetType.HeartstoneLocation)); ForeachEffect(effect => { if (effect.EffectType == SpellEffectType.Skill) { SkillId = (SkillId)effect.MiscValue; } }); Schools = Utility.GetSetIndices<DamageSchool>((uint)SchoolMask); if (Schools.Length == 0) { Schools = new[] { DamageSchool.Physical }; } RequiresCasterOutOfCombat = !HasHarmfulEffects && CastDelay > 0 && (Attributes.HasFlag(SpellAttributes.CannotBeCastInCombat) || AttributesEx.HasFlag(SpellAttributesEx.RemainOutOfCombat) || AuraInterruptFlags.HasFlag(AuraInterruptFlags.OnStartAttack)); if (RequiresCasterOutOfCombat) { // We fail if being attacked (among others) InterruptFlags |= InterruptFlags.OnTakeDamage; } IsThrow = AttributesExC.HasFlag(SpellAttributesExC.ShootRangedWeapon) && Attributes.HasFlag(SpellAttributes.Ranged) && Ability != null && Ability.Skill.Id == SkillId.Thrown; HasModifierEffects = HasEffectWith(effect => effect.AuraType == AuraType.AddModifierFlat || effect.AuraType == AuraType.AddModifierPercent); ForeachEffect(effect => { for (var i = 0; i < 3; i++) { AllAffectingMasks[i] |= effect.AffectMask[i]; } }); if (Range.MaxDist == 0) { Range.MaxDist = 5; } if (RequiredToolIds == null) { RequiredToolIds = new uint[0]; } else { if (RequiredToolIds.Length > 0 && (RequiredToolIds[0] > 0 || RequiredToolIds[1] > 0)) { SpellHandler.SpellsRequiringTools.Add(this); } ArrayUtil.PruneVals(ref RequiredToolIds); } ArrayUtil.PruneVals(ref RequiredTotemCategories); ForeachEffect(effect => { if (effect.SpellEffectHandlerCreator != null) { EffectHandlerCount++; } }); //IsHealSpell = HasEffectWith((effect) => effect.IsHealEffect); }
/// <summary> /// Restores Power and sends the corresponding Packet /// </summary> public void EnergizePercent(int value, Unit energizer = null, SpellEffect effect = null) { Energize((value * MaxPower + 50) / 100, energizer, effect); }
/// <summary> /// Adds a new Effect to this Spell /// </summary> /// <param name="type"></param> /// <returns></returns> public SpellEffect AddEffect(SpellEffectType type, ImplicitTargetType target) { var effect = new SpellEffect(this, Effects.Length > 0 ? Effects[Effects.Length - 1].EffectIndex : 0) { EffectType = type }; var effects = new SpellEffect[Effects.Length + 1]; Array.Copy(Effects, effects, Effects.Length); Effects = effects; Effects[effects.Length - 1] = effect; effect.ImplicitTargetA = target; return effect; }
/// <summary> /// Restores Power and sends the corresponding Packet /// </summary> public void Energize(int value, Unit energizer = null, SpellEffect effect = null) { if (value != 0) { var power = Power; value = MathUtil.ClampMinMax(value, -power, MaxPower - value); CombatLogHandler.SendEnergizeLog(energizer, this, effect != null ? effect.Spell.Id : 0, PowerType, value); Power = power + value; } }
public QuestCompleteEffectHandler(SpellCast cast, SpellEffect effect) : base(cast, effect) { }
/// <summary> /// Drains the given amount of power and applies damage for it /// </summary> /// <param name="dmgTyp">The type of the damage applied</param> /// <param name="dmgFactor">The factor to be applied to amount for the damage to be received by this unit</param> public void BurnPower(int amount, float dmgFactor = 1, Unit attacker = null, SpellEffect effect = null) { int currentPower = Power; // Resilience reduces mana drain by 2.2%, amount is rounded. amount -= MathUtil.RoundInt(amount * GetResiliencePct() * 2.2f); if (amount > currentPower) { amount = currentPower; } Power = currentPower - amount; DealSpellDamage(attacker, effect, (int)(amount * dmgFactor)); }
/// <summary> /// This method is called whenever a heal is placed on a Unit by another Unit /// </summary> /// <param name="healer">The healer</param> /// <param name="value">The amount of points healed</param> protected virtual void OnHeal(Unit healer, SpellEffect effect, int value) { // TODO: Remove method and instead trigger region-wide event (a lot more efficient than this) IterateEnvironment(40.0f, obj => { if (obj is Unit && ((Unit)obj).m_brain != null) { ((Unit)obj).m_brain.OnHeal(healer, this, value); } return true; }); }
/// <summary> /// Whether this effect can share targets with the given effect /// </summary> public bool SharesTargetsWith(SpellEffect b, bool aiCast) { // if a TargetDefinition is set, it overrides the default implicit targets var targetDef = GetTargetDefinition(aiCast); return (targetDef != null && targetDef.Equals(b.GetTargetDefinition(aiCast))) || (ImplicitTargetA == b.ImplicitTargetA && ImplicitTargetB == b.ImplicitTargetB); }
/// <summary> /// Restores Power and sends the corresponding Packet /// </summary> /// <param name="energizer"></param> /// <param name="value"></param> /// <param name="effect"></param> public void Energize(Unit energizer, int value, SpellEffect effect) { if (value > 0) { if (Power + value > MaxPower) { value = MaxPower - Power; Power = MaxPower; } else { Power += value; } CombatLogHandler.SendEnergizeLog(energizer, this, effect != null ? effect.Spell.Id : 0, PowerType, value); } }
public void CopyValuesTo(SpellEffect effect) { effect.BasePoints = BasePoints; effect.DiceSides = DiceSides; }
/// <summary> /// Drains the given amount of power and applies damage for it /// </summary> /// <param name="dmgTyp">The type of the damage applied</param> /// <param name="dmgFactor">The factor to be applied to amount for the damage to be received by this unit</param> public void BurnPower(Unit attacker, SpellEffect effect, DamageSchool dmgTyp, int amount, float dmgFactor) { int currentPower = Power; // Resilience reduces mana drain by 2.2%, amount is rounded. amount -= (amount * GetResiliencePct() * 2.2f).RoundInt(); if (amount > currentPower) { amount = currentPower; } Power = currentPower - amount; DoSpellDamage(attacker, effect, (int)(amount * dmgFactor)); }
protected SpellEffectHandler(SpellCast cast, SpellEffect effect) { m_cast = cast; Effect = effect; }