public static void LoadData() { Context.ImportZips(false); Context.ImportSkills(false); Context.ImportLanguages(false); Context.ImportSpells(false); Context.ImportItems(false); Context.ImportBackgrounds(false); Context.ImportRaces(false); Context.ImportSubRaces(false); Context.ImportStandaloneFeatures(false); Context.ImportConditions(false); Context.ImportMagic(false); foreach (ClassDefinition c in Context.Classes.Values) { c.ApplyKeywords(Context); } foreach (SubClass c in Context.SubClasses.Values) { c.ApplyKeywords(Context); } Context.ImportClasses(false, true); Context.ImportSubClasses(false, true); Context.ImportMonsters(false); }
public static void LoadData() { Context.ImportSkills(); Context.ImportLanguages(); Context.ImportSpells(); Context.ImportItems(); Context.ImportBackgrounds(); Context.ImportRaces(); Context.ImportSubRaces(); Context.ImportStandaloneFeatures(); Context.ImportConditions(); Context.ImportMagic(); Context.ImportClasses(true); Context.ImportSubClasses(true); }
static void Main() { //String s = "Name = \"hallo'welt\" or name = \"Foobar\""; //String Name = "Hallo'Welt"; //var e = new Expression(ConfigManager.fixQuotes(s)); //e.EvaluateParameter += (name, args) => args.Result = (name.ToLowerInvariant() == "name") ? Name.ToLowerInvariant() : ""; //Console.WriteLine(s + " = " + e.Evaluate()); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); ConfigManager.LogEvents += (sender, text, e) => Console.WriteLine((text != null ? text + ": " : "") + e?.StackTrace); ConfigManager.LicenseProvider = new LicenseProvider(); Errorlog = new ErrorLog(); ConfigManager.AlwaysShowSource = true; Context.LoadConfig(Application.StartupPath); if (SourceManager.Init(Program.Context, Application.StartupPath, true)) { string[] args = Environment.GetCommandLineArgs(); if (args.Length > 1) { Dictionary <string, OGL.Base.Ability> skills = new Dictionary <string, OGL.Base.Ability>(); Dictionary <string, OGL.Base.Ability> abilities = new Dictionary <string, OGL.Base.Ability>(); abilities.Add("str", OGL.Base.Ability.Strength); abilities.Add("strength", OGL.Base.Ability.Strength); abilities.Add("dex", OGL.Base.Ability.Dexterity); abilities.Add("dexterity", OGL.Base.Ability.Dexterity); abilities.Add("con", OGL.Base.Ability.Constitution); abilities.Add("constitution", OGL.Base.Ability.Constitution); abilities.Add("int", OGL.Base.Ability.Intelligence); abilities.Add("intelligence", OGL.Base.Ability.Intelligence); abilities.Add("wis", OGL.Base.Ability.Wisdom); abilities.Add("wisdom", OGL.Base.Ability.Wisdom); abilities.Add("cha", OGL.Base.Ability.Charisma); abilities.Add("charisma", OGL.Base.Ability.Charisma); Context.ImportSkills(); foreach (OGL.Skill s in Context.SkillsSimple.Values) { skills.Add(s.Name.ToLowerInvariant(), s.Base); } Dictionary <decimal, int> crs = new Dictionary <decimal, int>(); crs.Add(0, 10); crs.Add(0.125m, 25); crs.Add(0.25m, 50); crs.Add(0.5m, 100); crs.Add(1, 200); crs.Add(2, 450); crs.Add(3, 700); crs.Add(4, 1100); crs.Add(5, 1800); crs.Add(6, 2300); crs.Add(7, 2900); crs.Add(8, 3900); crs.Add(9, 5000); crs.Add(10, 5900); crs.Add(11, 7200); crs.Add(12, 8400); crs.Add(13, 10000); crs.Add(14, 11500); crs.Add(15, 13000); crs.Add(16, 15000); crs.Add(17, 18000); crs.Add(18, 20000); crs.Add(19, 22000); crs.Add(20, 25000); crs.Add(21, 33000); crs.Add(22, 41000); crs.Add(23, 50000); crs.Add(24, 62000); crs.Add(25, 75000); crs.Add(26, 90000); crs.Add(27, 105000); crs.Add(28, 120000); crs.Add(29, 135000); crs.Add(30, 155000); string file = args[1]; if (File.Exists(file) && ".json".Equals(Path.GetExtension(file), StringComparison.InvariantCultureIgnoreCase)) { using (StreamReader sr = new StreamReader(file)) { JObject input = JObject.Load(new JsonTextReader(sr)); var monsters = input["monster"]; foreach (var monster in monsters) { Console.WriteLine(monster["name"].ToString()); Monster m = new Monster(); List <string> monsterSkills = new List <string>(); List <string> monsterSaves = new List <string>(); int passive = 10; foreach (var e in monster) { if (e is JProperty prop) { switch (prop.Name.ToLowerInvariant()) { case "name": m.Name = prop.Value.ToString(); break; case "size": switch (prop.Value.ToString().ToLowerInvariant()) { case "t": m.Size = OGL.Base.Size.Tiny; break; case "m": m.Size = OGL.Base.Size.Medium; break; case "s": m.Size = OGL.Base.Size.Small; break; case "l": m.Size = OGL.Base.Size.Large; break; case "g": m.Size = OGL.Base.Size.Gargantuan; break; case "h": m.Size = OGL.Base.Size.Huge; break; default: throw new Exception("Unexpected " + prop + " in " + m); } break; case "type": string type = prop.Value.ToString(); string[] types = type.Split(','); if (types.Length == 1) { types = new string[] { types[0], "Unknown Source" }; } string[] firsttypes = types[0].Split('('); for (int i = 0; i < firsttypes.Length; i++) { m.Keywords.Add(new OGL.Keywords.Keyword(i == firsttypes.Length - 1 ? firsttypes[i].Trim().TrimEnd(')') : firsttypes[i].Trim())); } for (int i = 1; i < types.Length - 1; i++) { m.Keywords.Add(new OGL.Keywords.Keyword(i == types.Length - 2 ? types[i].Trim().TrimEnd(')') : types[i].Trim())); } string source = types.Last(); switch (source.ToLowerInvariant().Trim()) { case "monster manual": m.Source = "Monster Manual"; break; case "tome of beasts": m.Source = "Tome of Beasts"; break; case "volo's guide": m.Source = "Volo's Guide to Monsters"; break; case "elemental evil": m.Source = "Elemental Evil"; break; case "tyranny of dragons": m.Source = "Tyranny of Dragons"; break; case "storm kings thunder": m.Source = "Storm King's Thunder"; break; case "unknown source": m.Source = "No Source"; break; case "out of the abyss": m.Source = "Out of the Abyss"; break; case "curse of strahd": m.Source = "Curse of Strahd"; break; case "lost mine of phandelver": m.Source = "Lost Mine of Phandelver"; break; default: m.Source = source; break; } break; case "alignment": m.Alignment = prop.Value.ToString(); break; case "ac": string[] ac = prop.Value.ToString().Split(" (".ToCharArray(), 2); if (TryParse(ac[0], out int acvalue)) { m.AC = acvalue; } else { throw new Exception("Unexpected " + prop + " in " + m); } if (ac.Length > 1) { m.ACText = ac[1].TrimStart('(').TrimEnd(')'); } break; case "hp": string[] hp = prop.Value.ToString().Split(" (".ToCharArray(), 2); if (TryParse(hp[0], out int hpvalue)) { m.HP = hpvalue; } else { throw new Exception("Unexpected " + prop + " in " + m); } if (hp.Length > 1) { m.HPRoll = hp[1].TrimStart('(').TrimEnd(')'); } break; case "speed": string[] speeds = prop.Value.ToString().Split(','); foreach (string speed in speeds) { m.Speeds.Add(speed.Trim()); } break; case "str": if (TryParse(prop.Value.ToString(), out int str)) { m.Strength = str; } else { throw new Exception("Unexpected " + prop + " in " + m); } break; case "dex": if (TryParse(prop.Value.ToString(), out int dex)) { m.Dexterity = dex; } else { throw new Exception("Unexpected " + prop + " in " + m); } break; case "con": if (TryParse(prop.Value.ToString(), out int con)) { m.Constitution = con; } else { throw new Exception("Unexpected " + prop + " in " + m); } break; case "int": if (TryParse(prop.Value.ToString(), out int intt)) { m.Intelligence = intt; } else { throw new Exception("Unexpected " + prop + " in " + m); } break; case "wis": if (TryParse(prop.Value.ToString(), out int wis)) { m.Wisdom = wis; } else { throw new Exception("Unexpected " + prop + " in " + m); } break; case "cha": if (TryParse(prop.Value.ToString(), out int cha)) { m.Charisma = cha; } else { throw new Exception("Unexpected " + prop + " in " + m); } break; case "skill": string[] skillss = prop.Value.ToString().Split(','); foreach (string skill in skillss) { monsterSkills.Add(skill.Trim()); } break; case "passive": if (TryParse(prop.Value.ToString().ToLowerInvariant().Replace("passive perception", "").Trim(), out passive)) { ; } else { throw new Exception("Unexpected " + prop + " in " + m); } break; case "languages": string[] languages = prop.Value.ToString().Split(','); foreach (string lang in languages) { m.Languages.Add(lang.Trim()); } break; case "cr": string cr = prop.Value.ToString(); if ("1/8".Equals(cr)) { m.CR = 0.125m; } else if ("1/4".Equals(cr)) { m.CR = 0.25m; } else if ("1/2".Equals(cr)) { m.CR = 0.5m; } else if ("I".Equals(cr)) { m.CR = 1m; } else if ("l".Equals(cr)) { m.CR = 1m; } else if (decimal.TryParse(prop.Value.ToString(), out decimal crvalue)) { m.CR = crvalue; } else { throw new Exception("Unexpected " + prop + " in " + m); } m.XP = crs[m.CR]; break; case "trait": if (prop.Value is JArray traits) { foreach (var trait in traits) { String text; if (trait["text"] is JArray a) { text = string.Join("\n", a.Select(s => s.ToString())); } else { text = trait["text"]?.ToString(); } m.Traits.Add(new OGL.Monsters.MonsterTrait(trait["name"]?.ToString(), text)); } } else { String text; if (prop.Value["text"] is JArray a) { text = string.Join("\n", a.Select(s => s.ToString())); } else { text = prop.Value["text"]?.ToString(); } m.Traits.Add(new OGL.Monsters.MonsterTrait(prop.Value["name"]?.ToString(), text)); } break; case "action": if (prop.Value is JArray actions) { foreach (var trait in actions) { String text; if (trait["text"] is JArray a) { text = string.Join("\n", a.Select(s => s.ToString())); } else { text = trait["text"]?.ToString(); } if (trait["attack"] != null) { string[] attack = trait["attack"].ToString().Split('|'); int attackbonus = 0; if (attack.Length > 1) { TryParse(attack[1], out attackbonus); } m.Actions.Add(new OGL.Monsters.MonsterAction(trait["name"]?.ToString(), text, attackbonus, attack.Length > 2 ? attack[2] : null)); } else { m.Actions.Add(new OGL.Monsters.MonsterTrait(trait["name"]?.ToString(), text)); } } } else { String text; if (prop.Value["text"] is JArray a) { text = string.Join("\n", a.Select(s => s.ToString())); } else { text = prop.Value["text"]?.ToString(); } if (prop.Value["attack"] != null) { string[] attack = prop.Value["attack"].ToString().Split('|'); int attackbonus = 0; if (attack.Length > 1) { TryParse(attack[1], out attackbonus); } m.Actions.Add(new OGL.Monsters.MonsterAction(prop.Value["name"]?.ToString(), text, attackbonus, attack.Length > 2 ? attack[2] : null)); } else { m.Actions.Add(new OGL.Monsters.MonsterTrait(prop.Value["name"]?.ToString(), text)); } } break; case "save": string[] saves = prop.Value.ToString().Split(','); foreach (string save in saves) { monsterSaves.Add(save.Trim()); } break; case "spells": string[] spells = prop.Value.ToString().Split(','); foreach (string s in spells) { m.Spells.Add(s.Trim()); } break; case "slots": string[] slots = prop.Value.ToString().Split(','); foreach (string s in slots) { m.Slots.Add(int.Parse(s.Trim())); } break; case "senses": string[] senses = prop.Value.ToString().Split(','); foreach (string s in senses) { m.Senses.Add(s.Trim()); } break; case "legendary": if (prop.Value is JArray legendary) { foreach (var trait in legendary) { String text; if (trait["text"] is JArray a) { text = string.Join("\n", a.Select(s => s.ToString())); } else { text = trait["text"]?.ToString(); } if (trait["attack"] != null) { string[] attack = trait["attack"].ToString().Split('|'); int attackbonus = 0; if (attack.Length > 1) { TryParse(attack[1], out attackbonus); } m.LegendaryActions.Add(new OGL.Monsters.MonsterAction(trait["name"]?.ToString(), text, attackbonus, attack.Length > 2 ? attack[2] : null)); } else { m.LegendaryActions.Add(new OGL.Monsters.MonsterTrait(trait["name"]?.ToString(), text)); } } } else { String text; if (prop.Value["text"] is JArray a) { text = string.Join("\n", a.Select(s => s.ToString())); } else { text = prop.Value["text"]?.ToString(); } if (prop.Value["attack"] != null) { string[] attack = prop.Value["attack"].ToString().Split('|'); int attackbonus = 0; if (attack.Length > 1) { TryParse(attack[1], out attackbonus); } m.LegendaryActions.Add(new OGL.Monsters.MonsterAction(prop.Value["name"]?.ToString(), text, attackbonus, attack.Length > 2 ? attack[2] : null)); } else { m.LegendaryActions.Add(new OGL.Monsters.MonsterTrait(prop.Value["name"]?.ToString(), text)); } } break; case "reaction": if (prop.Value is JArray reaction) { foreach (var trait in reaction) { String text; if (trait["text"] is JArray a) { text = string.Join("\n", a.Select(s => s.ToString())); } else { text = trait["text"]?.ToString(); } if (trait["attack"] != null) { string[] attack = trait["attack"].ToString().Split('|'); int attackbonus = 0; if (attack.Length > 1) { TryParse(attack[1], out attackbonus); } m.Reactions.Add(new OGL.Monsters.MonsterAction(trait["name"]?.ToString(), text, attackbonus, attack.Length > 2 ? attack[2] : null)); } else { m.Reactions.Add(new OGL.Monsters.MonsterTrait(trait["name"]?.ToString(), text)); } } } else { String text; if (prop.Value["text"] is JArray a) { text = string.Join("\n", a.Select(s => s.ToString())); } else { text = prop.Value["text"]?.ToString(); } if (prop.Value["attack"] != null) { string[] attack = prop.Value["attack"].ToString().Split('|'); int attackbonus = 0; if (attack.Length > 1) { TryParse(attack[1], out attackbonus); } m.Reactions.Add(new OGL.Monsters.MonsterAction(prop.Value["name"]?.ToString(), text, attackbonus, attack.Length > 2 ? attack[2] : null)); } else { m.Reactions.Add(new OGL.Monsters.MonsterTrait(prop.Value["name"]?.ToString(), text)); } } break; case "immune": string[] immune = prop.Value.ToString().Split(','); foreach (string s in immune) { m.Immunities.Add(s.Trim()); } break; case "description": case "text": m.Description = prop.Value.ToString(); break; case "resist": string[] resist = prop.Value.ToString().Split(','); foreach (string s in resist) { m.Resistances.Add(s.Trim()); } break; case "conditionimmune": string[] conditionImmune = prop.Value.ToString().Split(','); foreach (string s in conditionImmune) { m.ConditionImmunities.Add(s.Trim()); } break; case "vulnerable": string[] vulnerable = prop.Value.ToString().Split(','); foreach (string s in vulnerable) { m.Vulnerablities.Add(s.Trim()); } break; default: throw new Exception("Unexpected property " + prop + " in " + m); } } else { throw new Exception("Expected property instead of " + e + " in " + m); } } m.PassivePerception = passive - (m.Wisdom / 2 - 5) - 10; foreach (string skill in monsterSkills) { foreach (Match match in Regex.Matches(skill, @"(\D+?)\s+\+?(\-?\s*\d+)(?:\s*\(([^\)]+)\))?", RegexOptions.IgnoreCase)) { string name = match.Groups[1].Value.Trim(); if (TryParse(match.Groups[2].Value, out int bonus)) { if ("perception".Equals(name, StringComparison.OrdinalIgnoreCase)) { m.PassivePerception -= bonus - (m.Wisdom / 2 - 5); } if (skills.ContainsKey(name.ToLowerInvariant())) { m.SkillBonus.Add(new OGL.Monsters.MonsterSkillBonus() { Skill = name, Bonus = bonus - m.getAbility(skills[name.ToLowerInvariant()]) / 2 + 5, Text = match.Groups.Count > 2 ? match.Groups[3].Value : null }); } else { m.SkillBonus.Add(new OGL.Monsters.MonsterSkillBonus() { Skill = name, Bonus = bonus, Text = match.Captures.Count > 2 ? match.Captures[3].Value : null }); } } else { throw new Exception("Unexpected bonus " + bonus + " in " + skill); } } } foreach (string save in monsterSaves) { foreach (Match match in Regex.Matches(save, @"(\D+?)\s+\+?(\-?\s*\d+)(?:\s*\(([^\)]+)\))?", RegexOptions.IgnoreCase)) { string name = match.Groups[1].Value.Trim(); if (TryParse(match.Groups[2].Value, out int bonus)) { if (abilities.ContainsKey(name.ToLowerInvariant())) { m.SaveBonus.Add(new OGL.Monsters.MonsterSaveBonus() { Ability = abilities[name.ToLowerInvariant()], Bonus = bonus - m.getAbility(abilities[name.ToLowerInvariant()]) / 2 + 5, Text = match.Captures.Count > 2 ? match.Groups[3].Value : null }); } else { throw new Exception("Unexpected ability in " + save); } } else { throw new Exception("Unexpected bonus " + bonus + " in " + save); } } } m.Save(false); } } return; } } Application.Run(new MainTab()); } else { Application.Exit(); } }