/// <summary> /// Calculate the damage for a castable. /// </summary> /// <param name="castable">The castable to use for the calculation</param> /// <param name="target">The target of the castable (i.e. the spell/skill target)</param> /// <param name="source">The source of the castable (i.e. the caster)</param> /// <returns></returns> public static DamageOutput CalculateDamage(Xml.Castable castable, Creature target, Creature source = null) { var rand = new Random(); // Defaults double dmg = 1; var type = castable.Effects?.Damage?.Type ?? Xml.DamageType.Magical; if (castable.Effects?.Damage == null) { return new DamageOutput() { Amount = dmg, Type = type, Flags = Xml.DamageFlags.None, Element = castable.Element } } ; if (castable.Effects.Damage.IsSimple) { var simple = castable.Effects.Damage.Simple; dmg = _evalSimple(simple); } else { var formula = castable.Effects.Damage.Formula; dmg = _evalFormula(formula, castable, target, source); } return(new DamageOutput() { Amount = dmg * target.Stats.DamageModifier, Type = type, Flags = castable.Effects.Damage.Flags, Element = castable.Element }); }
/// <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 DamageOutput CalculateDamage(Xml.Castable castable, Xml.ModifierEffect effect, Creature target, Creature source, string statusName) { // Defaults double dmg = 0; var type = effect.Damage?.Type ?? Xml.DamageType.Magical; if (effect?.Damage == null) { return new DamageOutput() { Amount = dmg, Type = type, Flags = Xml.DamageFlags.None, Element = castable.Element } } ; var statusAdd = castable?.Effects?.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(new DamageOutput() { Amount = (dmg * intensity * target.Stats.DamageModifier), Type = type, Flags = effect.Damage.Flags, Element = castable.Element }); }
public CreatureStatus(Xml.Status xmlstatus, Creature target, Xml.Castable castable = null, Creature source = null, int duration = -1, int tickFrequency = -1, double intensity = 1.0) { Target = target; XmlStatus = xmlstatus; Start = DateTime.Now; Target = target; Source = source; Duration = duration == -1 ? xmlstatus.Duration : duration; Tick = tickFrequency == -1 ? xmlstatus.Tick : tickFrequency; Intensity = intensity; // Calculate damage/heal effects. Note that a castable MUST be passed here for a status // to have damage effects as the castable itself has fields we need to access // (intensity, etc) in order to do damage calculations. if (castable != null) { var start = CalculateNumericEffects(castable, xmlstatus.Effects.OnApply, source); var tick = CalculateNumericEffects(castable, xmlstatus.Effects.OnTick, source); var end = CalculateNumericEffects(castable, xmlstatus.Effects.OnRemove, source); var expire = CalculateNumericEffects(castable, xmlstatus.Effects.OnExpire, source); OnStartEffect = new SimpleStatusEffect(start.Heal, start.Damage); OnTickEffect = new SimpleStatusEffect(tick.Heal, tick.Damage); OnRemoveEffect = new SimpleStatusEffect(end.Heal, end.Damage); OnExpireEffect = new SimpleStatusEffect(expire.Heal, expire.Damage); } }
private static double _evalFormula(string formula, Xml.Castable castable, Creature target, Creature source) { try { return(new FormulaParser(source, castable, target).Eval(formula)); } catch (Exception e) { GameLog.Error($"NumberCruncher formula error: castable {castable.Name}, target {target.Name}, source {source?.Name ?? "no source"}: {formula}, error: {e}"); return(0); } }
/// <summary> /// Deserializes xml markup from file into an Castable object /// </summary> /// <param name="fileName">File to load and deserialize</param> /// <param name="obj">Output Castable object</param> /// <param name="exception">output Exception value if deserialize failed</param> /// <returns>true if this Serializer can deserialize the object; otherwise, false</returns> public static bool LoadFromFile(string fileName, out Castable obj, out Exception exception) { exception = null; obj = default(Castable); try { obj = LoadFromFile(fileName); return(true); } catch (Exception ex) { exception = ex; return(false); } }
/// <summary> /// Deserializes Castable object /// </summary> /// <param name="input">string to deserialize</param> /// <param name="obj">Output Castable object</param> /// <param name="exception">output Exception value if deserialize failed</param> /// <returns>true if this Serializer can deserialize the object; otherwise, false</returns> public static bool Deserialize(string input, out Castable obj, out Exception exception) { exception = null; obj = default(Castable); try { obj = Deserialize(input); return(true); } catch (Exception ex) { exception = ex; return(false); } }
private (double Heal, DamageOutput Damage) CalculateNumericEffects(Xml.Castable castable, Xml.ModifierEffect effect, Creature source) { double heal = 0; DamageOutput dmg = new DamageOutput(); if (!effect.Heal.IsEmpty) { heal = NumberCruncher.CalculateHeal(castable, effect, Target, source, Name); } if (!effect.Damage.IsEmpty) { dmg = NumberCruncher.CalculateDamage(castable, effect, Target, source, Name); } return(heal, dmg); }
/// <summary> /// Calculate the healing for a castable. /// </summary> /// <param name="castable">The castable to use for the calculation</param> /// <param name="target">The target of the castable (i.e. the spell/skill target)</param> /// <param name="source">The source of the castable (i.e. the caster), optional parameter</param> /// <returns></returns> public static double CalculateHeal(Xml.Castable castable, Creature target, Creature source = null) { var rand = new Random(); double heal = 0; if (castable.Effects?.Heal == null) { return(heal); } if (castable.Effects.Heal.IsSimple) { heal = _evalSimple(castable.Effects.Heal.Simple) * target.Stats.HealModifier; } else { heal = _evalFormula(castable.Effects.Heal.Formula, castable, target, source); } return(heal * target.Stats.HealModifier); }
/// <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(Xml.Castable castable, Xml.ModifierEffect effect, Creature target, Creature source, string statusName) { // Defaults double heal = 0; if (effect?.Heal == null) { return(heal); } var statusAdd = castable?.Effects?.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.Heal.Formula, castable, target, source); } return(heal * intensity * target.Stats.HealModifier); }
public FormulaParser(Creature caster, Xml.Castable castable, Creature target = null) { _caster = caster; _castable = castable; _target = target; }
public static bool LoadFromFile(string fileName, out Castable obj) { Exception exception = null; return(LoadFromFile(fileName, out obj, out exception)); }
public static bool Deserialize(string input, out Castable obj) { Exception exception = null; return(Deserialize(input, out obj, out exception)); }