private void ProcessFullEffects(ModifierEffect effect, bool RemoveStatBonuses = false) { // Stat modifiers and condition changes are only processed during start/remove ProcessConditions(effect); ProcessStatModifiers(XMLStatus.Effects?.OnApply?.StatModifiers, RemoveStatBonuses); ProcessSfx(effect); ProcessDamageEffects(effect); }
private void ProcessConditions(ModifierEffect effect) { if (effect.Conditions?.Set != null) { Target.Condition.Conditions |= effect.Conditions.Set; } if (effect.Conditions?.Unset != null) { Target.Condition.Conditions &= ~effect.Conditions.Unset; } }
void HandleModifierEffects(System.Random dice) { // Effects that can modify the opponent's effect, or depend on the opponent's effect, // need to be applied in priority order for consistent stacking. // This is ugly and could probably be improved. while (true) { // Search the four effect slots for any special effects that need this treatment. // Remember the one that comes first in priority order. // We have to do this search multiple times, because effects can change // slots that we already looked at. float firstPriority = float.PositiveInfinity; ModifierEffect nextEffect = default; foreach (var side in _sides) { var mutual = side.effectOnOpponent.successfulSpecial as MutualModifierEffect; if (mutual != null && mutual.priorityOrder < firstPriority) { firstPriority = mutual.priorityOrder; nextEffect = new ModifierEffect(side, false); } mutual = side.effectOnSelf.successfulSpecial as MutualModifierEffect; if (mutual != null && mutual.priorityOrder < firstPriority) { firstPriority = mutual.priorityOrder; nextEffect = new ModifierEffect(side, true); } } // If we didn't find any effects that need this treatment, abort. We're done. if (float.IsInfinity(firstPriority)) { break; } // Otherwise, cache the effect, clear it out (so we don't handle it again), and handle it. if (nextEffect.self) { var mutual = (MutualModifierEffect)nextEffect.side.effectOnSelf.successfulSpecial; nextEffect.side.effectOnSelf.successfulSpecial = null; mutual.OnPostAbilitiesRolled(nextEffect.side, nextEffect.side.currentMonster, dice); } else { var mutual = (MutualModifierEffect)nextEffect.side.effectOnOpponent.successfulSpecial; nextEffect.side.effectOnOpponent.successfulSpecial = null; mutual.OnPostAbilitiesRolled(nextEffect.side, nextEffect.side.opponent.currentMonster, dice); } } }
private void ProcessSfx(ModifierEffect effect) { if (effect.Sound?.Id != null) { User?.PlaySound(effect.Sound.Id); } if (effect.Animations != null) { if (effect.Animations?.Target?.Id != 0) { var animation = effect.Animations.Target; if (Target is Monster || !Target.Condition.Comatose || (Target.Condition.Comatose && animation.Id == (Game.Config.Handlers?.Death?.Coma?.Effect ?? 24))) { Target.Effect(effect.Animations.Target.Id, effect.Animations.Target.Speed); } } if (effect.Animations?.SpellEffect?.Id != 0) { Source?.Effect(effect.Animations.SpellEffect.Id, effect.Animations.SpellEffect.Speed); } } // Message handling if (effect.Messages != null && User != null) { if (effect.Messages?.Target != null) { User.SendSystemMessage(string.Format(effect.Messages.Target, User.Name)); } if (effect.Messages?.Group != null) { User.Group.SendMessage(string.Format(effect.Messages.Group, User.Name)); } if (effect.Messages?.Source != null) { (Source as User)?.SendSystemMessage(string.Format(effect.Messages.Source, User.Name)); } if (effect.Messages?.Say != null) { User?.Say(string.Format(effect.Messages.Say, User.Name)); } if (effect.Messages?.Shout != null) { User?.Say(string.Format(effect.Messages.Shout, User.Name)); } } }
private void ProcessDamageEffects(ModifierEffect effect) { if (!effect.Heal.IsEmpty) { var heal = NumberCruncher.CalculateHeal(Castable, effect, Target, Source, Name); if (heal != 0) { Target.Heal(heal); } } if (!effect.Damage.IsEmpty) { var dmg = NumberCruncher.CalculateDamage(Castable, effect, Target, Source, Name); if (dmg.Amount != 0) { Target.Damage(dmg.Amount, Enums.Element.None, dmg.Type); } } }
/// <summary> /// Calculate the healing for a status tick. /// </summary> /// <param name="castable">Castable responsible for the status</param> /// <param name="effect">ModifierEffect structure for the status</param> /// <param name="target">Target for the healing (e.g. the player or creature with the status)</param> /// <param name="source">Original source of the status</param> /// <param name="statusName">The name of the status</param> /// <returns></returns> public static double CalculateHeal(Castable castable, ModifierEffect effect, Creature target, Creature source, string statusName) { // Defaults double heal = 0; if (effect?.Heal == null) { return(heal); } var statusAdd = castable?.Statuses?.Add?.Where(e => e.Value == statusName)?.ToList(); var intensity = statusAdd != null ? statusAdd[0].Intensity : 1; if (effect.Heal.IsSimple) { heal = _evalSimple(effect.Heal.Simple); } else { heal = _evalFormula(effect.Damage.Formula, castable, target, source); } return(heal * intensity * target.Stats.HealModifier); }
private void ProcessEffects(ModifierEffect effect) { ProcessSfx(effect); ProcessDamageEffects(effect); }
private void StatusesEffectsDialog_Load(object sender, EventArgs e) { var test = statusVM; setBindings(); if (_effectType.Equals(onApply)) { if (statusVM.Effects.OnApply == null) { OnApply = new ModifierEffect(); } else { OnApply = statusVM.Effects.OnApply; } for (int i = 0; i < listBoxCondSet.Items.Count; i++) { if (statusVM.Effects_OnApply_Conditions_Set_List.Contains(listBoxCondSet.Items[i].ToString())) { listBoxCondSet.SetSelected(i, true); } } for (int i = 0; i < listBoxCondUnset.Items.Count; i++) { if (statusVM.Effects_OnApply_Conditions_Unset_List.Contains(listBoxCondUnset.Items[i].ToString())) { listBoxCondUnset.SetSelected(i, true); } } } else if (_effectType.Equals(onTick)) { if (statusVM.Effects.OnTick == null) { OnTick = new ModifierEffect(); } else { OnTick = statusVM.Effects.OnTick; } for (int i = 0; i < listBoxCondSet.Items.Count; i++) { if (statusVM.Effects_OnTick_Conditions_Set_List.Contains(listBoxCondSet.Items[i].ToString())) { listBoxCondSet.SetSelected(i, true); } } for (int i = 0; i < listBoxCondUnset.Items.Count; i++) { if (statusVM.Effects_OnTick_Conditions_Unset_List.Contains(listBoxCondUnset.Items[i].ToString())) { listBoxCondUnset.SetSelected(i, true); } } } else { if (statusVM.Effects.OnRemove == null) { OnRemove = new ModifierEffect(); } else { OnRemove = statusVM.Effects.OnRemove; } for (int i = 0; i < listBoxCondSet.Items.Count; i++) { if (statusVM.Effects_OnRemove_Conditions_Set_List.Contains(listBoxCondSet.Items[i].ToString())) { listBoxCondSet.SetSelected(i, true); } } for (int i = 0; i < listBoxCondUnset.Items.Count; i++) { if (statusVM.Effects_OnRemove_Conditions_Unset_List.Contains(listBoxCondUnset.Items[i].ToString())) { listBoxCondUnset.SetSelected(i, true); } } } labelTitleValue.Text = _effectType; }
/// <summary> /// Calculate the damage for a status tick. /// </summary> /// <param name="castable">Castable responsible for the status</param> /// <param name="effect">ModifierEffect structure for the status</param> /// <param name="target">Target for the damage (e.g. the player or creature with the status)</param> /// <param name="source">Original source of the status</param> /// <param name="statusName">The name of the status</param> /// <returns></returns> public static (double Amount, Enums.DamageType Type, Castables.DamageFlags Flags) CalculateDamage(Castable castable, ModifierEffect effect, Creature target, Creature source, string statusName) { // Defaults double dmg = 0; var type = EnumUtil.ParseEnum(effect.Damage.Type.ToString(), Enums.DamageType.Magical); if (effect?.Damage == null) { return(dmg, type, Castables.DamageFlags.None); } var statusAdd = castable?.Statuses?.Add?.Where(e => e.Value == statusName)?.ToList(); var intensity = statusAdd != null ? statusAdd[0].Intensity : 1; if (effect.Damage.IsSimple) { dmg = _evalSimple(effect.Damage.Simple); } else { dmg = _evalFormula(effect.Damage.Formula, castable, target, source); } return(dmg * intensity * target.Stats.DamageModifier, type, (Castables.DamageFlags)effect.Damage.Flags); }