private HitEffect FindEffectForPosition(int position, DynamicEnumProvider dep, Dictionary <int, HitEffect> effects, Dictionary <int, Match> dcPositions) { HitEffect effect; var dc = dcPositions.LastOrDefault(d => d.Key < position || d.Key - 20 < position && d.Value.Value.Contains("escape")); if (!dc.Equals(default(KeyValuePair <int, Match>))) { if (!effects.ContainsKey(dc.Key)) { effects[dc.Key] = new HitEffect(); if (dc.Value.Value.Contains("escape")) { effects[dc.Key].DC = new SkillCheck { Skill = Skill.Acrobatics | Skill.Athletics, Value = Convert.ToInt32(dc.Value.Groups[5].Value) }; } else if (dc.Value.Value.Contains("check")) { effects[dc.Key].DC = new SkillCheck { Value = Convert.ToInt32(dc.Value.Groups[7].Value) }; var reg = new Regex(@"\([A-Za-z]*\)"); foreach (var s in reg.Matches(dc.Value.Value).Select(s => Enum.Parse <Skill>(s.Value.Trim('(', ')'), true))) { ((SkillCheck)effects[dc.Key].DC).Skill |= s; } } else if (dc.Value.Value.Contains("saving throw")) { var str = dc.Value.Value.Replace("saving throw", "").Replace("DC " + dc.Value.Groups[2].Value, "").Trim(); effects[dc.Key].DC = new SavingThrow() { Value = Convert.ToInt32(dc.Value.Groups[2].Value), Ability = dep.GetEnumValues("Ability").Parse(str) }; } } effect = effects[dc.Key]; } else { if (!effects.ContainsKey(0)) { effects[0] = new HitEffect(); } effect = effects[0]; } return(effect); }
public void Test1() { var ap = new ActionParser(); var dep = new DynamicEnumProvider(null); List <string> errors = new List <string>(); var action = ap.ParseAction(new ActionRaw() { Name = "Bite", Text = @"Melee Weapon Attack: +4 to hit, reach 5 ft., one target. Hit: 7 (1d10 + 2) piercing damage plus 5 (1d10) poison damage, and the target is grappled (escape DC 13). Until this grapple ends, the target is restrained, and the toad can't bite another target. " }, errors, dep); Assert.Equal(new Attack { AttackBonus = 4, LongRange = 0, ShortRange = 0, Reach = 5, Target = "one target", Type = AttackType.Melee_Weapon_Attack }, action.Attack); Assert.Contains(new HitEffect { Condition = null, DamageType = DamageType.Piercing, DC = null, DamageDie = new DieRoll(10, 1, 2) }, action.HitEffects); Assert.Contains(new HitEffect { Condition = null, DamageType = DamageType.Poison, DC = null, DamageDie = new DieRoll(10, 1, 0) }, action.HitEffects); Assert.Contains(new HitEffect { Condition = new List <Condition> { Condition.Grappled, Condition.Restrained }, DamageType = null, DC = new SkillCheck { Skill = Skill.Acrobatics | Skill.Athletics, Value = 13 }, DamageDie = null }, action.HitEffects); }
public Spellcasting CheckForSpellcasting(List <Spell> spells, MonsterRaw raw, ref List <string> errors, DynamicEnumProvider dep) { for (var i = 0; i < raw.Traits.Count; i++) { var trait = raw.Traits[i]; if (trait.Name.Equals("Spellcasting")) { var spellcasting = _spellParser.ParseSpellcasting(trait.Text, spells, ref errors, dep); raw.Traits.RemoveAt(i); return(spellcasting); } } return(null); }
private string TryFindSpellcastingAbility(string spellcastingDescription, DynamicEnumProvider dep, ref List <String> errors) { var desc = spellcastingDescription.ToLower(); foreach (var attr in dep.GetEnumValues("Ability").Data) { if (desc.Contains("ability is " + attr.ToLower())) { return(attr); } if (desc.Contains("that uses " + attr.ToLower() + " as ")) { return(attr); } } errors.Add("Unable to find spellcasting ability in description: " + spellcastingDescription); return("Strength"); }
public Action ParseAction(ActionRaw raw, List <string> errors, DynamicEnumProvider dep) { var action = new Action { Name = raw.Name, Text = new Regex("[ ]{2,}", RegexOptions.None).Replace(raw.Text.Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " "), " "), }; GetAttackTypeFromText(action, errors); if (action.Attack != null) { GetHitBonusFromText(action, errors); GetReachFromText(action, errors, out var reachEnd); GetTargetFromText(action, errors, reachEnd); } var pos = 0; FindHitEffects(action, errors, ref pos, dep); return(action); }
public Monster(DynamicEnumProvider dep) { Abilities = new Dictionary <string, AbilityScore>(); foreach (var ability in dep.GetEnumValues("Ability").Data) { Abilities.Add(ability, new AbilityScore() { Value = 10 }); } Race = new(); Senses = new(); ChallengeRating = new(); HitDie = new(); Skillmodifiers = new(); SavingThrows = new(); Alignment = new(); Speed = new(); ArmorInfo = new(); }
private void FindHitEffects(Action action, List <string> errors, ref int pos, DynamicEnumProvider dep) { var HitDieRegex = new Regex(@"([0-9]*) \(([0-9]*)d([0-9]*)( [\+|\-] [0-9]*)*\) ([a-z]*) damage"); var hitDies = HitDieRegex.Matches(action.Text); var positions = hitDies.ToDictionary(d => d.Index, d => d); var DCRegex = new Regex(@"(DC ([0-9]*) ([A-Za-z]*) saving throw)|(\(escape DC ([0-9]*)\))|(DC ([0-9]*) [A-Za-z]* \(([A-Za-z]*)\)( or [A-Za-z]* \(([A-Za-z]*)\)*)* check)", RegexOptions.None); var dcs = DCRegex.Matches(action.Text); var dcPositions = dcs.ToDictionary(d => d.Index, d => d); var conditionRegex = new Regex(Enum.GetNames(typeof(Condition)).Select(c => "(" + c.ToLower() + ")").ToArray().Join("|")); var conditions = conditionRegex.Matches(action.Text); var effects = new Dictionary <int, HitEffect>(); foreach (var hitDie in positions) { var hitEffect = FindEffectForPosition(hitDie.Key, dep, effects, dcPositions); var damageDie = new DieRoll(Convert.ToInt32(hitDie.Value.Groups[3].Value), Convert.ToInt32(hitDie.Value.Groups[2].Value), hitDie.Value.Groups[4].Value.Length > 0 ? Convert.ToInt32(hitDie.Value.Groups[4].Value.Replace(" ", "")) : 0); var damageType = Enum.Parse <DamageType>(hitDie.Value.Groups[5].Value, true); if (hitEffect.DamageDie != null) { hitEffect = new HitEffect(hitEffect) { DamageDie = damageDie, DamageType = damageType }; action.HitEffects.Add(hitEffect); } else { hitEffect.DamageDie = damageDie; hitEffect.DamageType = damageType; } } foreach (var cond in conditions.ToArray()) { var hitEffect = FindEffectForPosition(cond.Index, dep, effects, dcPositions); hitEffect.Condition.Add(Enum.Parse <Condition>(cond.Value, true)); } action.HitEffects.AddRange(effects.Values); }
public DefaultController(DataProvider dataProvider, DynamicEnumProvider dep) { _dataProvider = dataProvider; this.dep = dep; }
public Spellcasting ParseSpellcasting(string spellcastingDescription, List <Spell> spells, ref List <string> errors, DynamicEnumProvider dep) { spellcastingDescription = spellcastingDescription .Replace("spell caster", "spellcaster") .Replace("level-spellcaster", "level spellcaster") .Replace(": ", ":") .Replace(":", ": ") .Replace("th-level", "th level") .Replace("th level spellcaster", "th-level spellcaster") .Replace("th level slot", "th-level slot") .Replace("Save DC", "save DC") .Replace(" Level", " level") .Replace("st—", "st-"); var SpellcastingLevel = TryFindLevel(spellcastingDescription, ref errors); var SpellListClass = TryFindSpellListClass(spellcastingDescription, ref errors); var SpellcastingAbility = TryFindSpellcastingAbility(spellcastingDescription, dep, ref errors); var SpellslotsByLevel = GetSpellslotByLevel(SpellcastingLevel, SpellListClass); var Spellslots = CheckSpellslotsByDescription(SpellslotsByLevel, SpellListClass, spellcastingDescription); if (!Spellslots.SequenceEqual(SpellslotsByLevel)) { var levelBySlots = FindSpellCastingLevelBySlots(Spellslots, SpellListClass); if (levelBySlots != -1) { spellcastingDescription = FixDescription(SpellcastingLevel, levelBySlots, spellcastingDescription); SpellcastingLevel = levelBySlots; } } var SpellDC = TryFindSpellsaveDC(spellcastingDescription, ref errors); var SpellcastingModifier = TryFindSpellcastingModifier(spellcastingDescription, SpellDC, ref errors); var Spells = TryFindSpells(Spellslots, spellcastingDescription, SpellListClass, spells, ref errors, out var _spellTableStart, out var _spellTableEnd); var(before, _, after) = RemoveSpellTable(_spellTableStart, _spellTableEnd, spellcastingDescription); return(new Spellcasting { Name = "Spellcasting", Text = spellcastingDescription, SpellcastingLevel = SpellcastingLevel, SpellListClass = SpellListClass, SpellcastingAbility = SpellcastingAbility, Spellslots = Spellslots, SpellDC = SpellDC, SpellcastingModifier = SpellcastingModifier, Spells = Spells, TextBeforeTable = before, TextAfterTable = after }); }
public string GetAbility(DynamicEnumProvider dep) { return(dep.GetEnumValues("Ability").GetFromInt(AbilityId)); }
private List <Action> ParseActions(List <ActionRaw> raw, List <string> errors, DynamicEnumProvider dep) { return(raw.Select(r => _actionParser.ParseAction(r, errors, dep)).ToList()); }
public MonsterParser(SpellcastingParser spellParser, ActionParser actionParser, DynamicEnumProvider dep) { _spellParser = spellParser; _actionParser = actionParser; _dep = dep; }