public IActionResult DisplaySheetWithID(string id)
        {
            string username = HttpContext.Session.GetString("username");

            if (username != null && username != "")
            {
                //sheetService.CreateDnDSheet(username, "PlaceHolder");
                ModularSheet sheet = sheetService.Get(id);
                currentSheet = sheet;
                return(View("DisplaySheet", sheet));
            }
            return(RedirectToAction("Login", "Home"));
        }
Exemple #2
0
        public async Task ChangeHP(int value, [Remainder] string args = null)
        {
            Character c;

            args = args.ToLower();

            if (args.Contains("-c"))
            {
                c    = GetCompanion();
                args = args.Replace("-c", "").Trim();
                if (c == null)
                {
                    await ReplyAsync("You have no active companion.");

                    return;
                }
            }
            else
            {
                c = GetCharacter();
                if (c == null)
                {
                    await ReplyAsync("You have no active character.");

                    return;
                }
            }

            int CurrentHp = 0;
            int MaxHp     = 0;
            int TempHP    = 0;
            int Damage    = 0;

            JArray Json1 = await SheetService.Get(c, "damage+hptemp/");

            Damage = (string)Json1["damage"] == "null" ? 0 : (int)Json1["damage"];
            TempHP = (string)Json1["hptemp"] == "null" ? 0 : (int)Json1["hptemp"];

            JObject values = await SheetService.GetValues(c);

            MaxHp = (int)values["hp"]["value"];

            CurrentHp = MaxHp - Damage;
        }
Exemple #3
0
        public async Task Attack([Remainder] string args = "")
        {
            Character c;

            args = args.ToLower();

            if (args.Contains("-c"))
            {
                c    = GetCompanion();
                args = args.Replace("-c", "");
                if (c == null)
                {
                    await ReplyAsync("You have no active companion.");

                    return;
                }
            }
            else
            {
                c = GetCharacter();
                if (c == null)
                {
                    await ReplyAsync("You have no active character.");

                    return;
                }
            }
            if (args.NullorEmpty())
            {
                var strikes = await SheetService.Get(c, "strikes");

                var embed = new EmbedBuilder()
                            .WithTitle(c.Name + "'s strikes")
                            .WithThumbnailUrl(c.ImageUrl);

                if (strikes.Count() == 0)
                {
                    await ReplyAsync(c.Name + " has no strikes.");

                    return;
                }

                var sb = new StringBuilder();
                foreach (var s in strikes)
                {
                    string act = Icons.Actions["1"];
                    if (!((string)s["actions"]).NullorEmpty())
                    {
                        if (Icons.Actions.TryGetValue((string)s["actions"], out string ic))
                        {
                            act = ic;
                        }
                        else
                        {
                            act = "[" + s["actions"] + "]";
                        }
                    }
                    sb.AppendLine(Icons.Strike[(string)s["attack"]] + " " + (((string)s["name"]).NullorEmpty() ? "Unnamed Strike" : (string)s["name"]) + " " + act);
                }
                embed.WithDescription(sb.ToString());

                if (c.Color != null)
                {
                    embed.WithColor(new Color(c.Color[0], c.Color[1], c.Color[2]));
                }
                else
                {
                    Random randonGen   = new Random();
                    Color  randomColor = new Color(randonGen.Next(255), randonGen.Next(255),
                                                   randonGen.Next(255));
                    embed.WithColor(randomColor);
                }

                await ReplyAsync("", embed.Build());

                return;
            }
            else
            {
                string[] Bonuses = new string[0];

                if (BonusRegex.IsMatch(args))
                {
                    Bonuses = BonusRegex.Matches(args).Select(x => x.Value).ToArray();
                    foreach (var b in Bonuses)
                    {
                        args = args.Replace(b, "");
                    }
                    args = args.Trim();
                }

                var Jstrikes = await SheetService.Get(c, "strikes");

                var values = await SheetService.GetValues(c);

                if (values == null || Jstrikes == null)
                {
                    var err = new EmbedBuilder()
                              .WithTitle("Click here")
                              .WithUrl("https://character.pf2.tools/?" + c.RemoteId)
                              .WithDescription("Seems like we cannot fetch " + c.Name + "'s values. This is due to the fact values are only updated when you open the sheet in pf2.tools. To fix this, click the link above to generate those values.");
                    await ReplyAsync("", err.Build());

                    return;
                }

                var strikes = from sk in Jstrikes
                              where ((string)sk["name"]).ToLower().StartsWith(args)
                              orderby sk["name"]
                              select sk;

                if (strikes.Count() == 0)
                {
                    await ReplyAsync("You have no strikes whose name starts with '" + args + "'.");

                    return;
                }

                var s     = strikes.FirstOrDefault();
                var embed = new EmbedBuilder()
                            .WithTitle(c.Name + " strikes with a " + (((string)s["name"]).NullorEmpty() ? "Unnamed Strike" : (string)s["name"]) + "!")
                            .WithThumbnailUrl(c.ImageUrl);

                if (c.Color != null)
                {
                    embed.WithColor(new Color(c.Color[0], c.Color[1], c.Color[2]));
                }
                else
                {
                    Random randonGen   = new Random();
                    Color  randomColor = new Color(randonGen.Next(255), randonGen.Next(255),
                                                   randonGen.Next(255));
                    embed.WithColor(randomColor);
                }

                await ReplyAsync("Rolling...");

                string hit         = "";
                string dmg         = "";
                string penalties   = "";
                string damagebonus = "";
                string dmgtype     = "Untyped";

                if ((string)s["attack"] == "spell")
                {
                    dmgtype = "Spell";
                    var classes = await SheetService.Get(c, "classes");

                    JToken cl = null;
                    if (((string)s["class"]).NullorEmpty())
                    {
                        cl = classes.FirstOrDefault();
                    }
                    else
                    {
                        cl = classes.First(x => (string)x["id"] == (string)s["class"]);
                    }
                    if (classes == null || classes.Count == 0)
                    {
                        await ReplyAsync("You don't seem to have a class. Without one you can't make spell attacks.");

                        return;
                    }

                    if (!values.ContainsKey(((string)cl["name"]).ToLower()))
                    {
                        await ReplyAsync("Sorry! It seems we cannot retrieve the data for this strike! This issue is outside of the bot's control and will likely be solved later.");

                        return;
                    }

                    hit = (string)values[((string)cl["name"]).ToLower()]["bonus"];

                    int dc = int.Parse(hit ?? "0") + 10;

                    dmg = (string)s["overridedamage"];

                    if (!dmg.NullorEmpty() && AttributeRegex.IsMatch(dmg))
                    {
                        dmg = await ParseValues(dmg, c, values);
                    }

                    string summary = "";

                    var result = Roller.Roll("d20 + " + hit + (Bonuses.Length > 0?string.Join(" ", Bonuses):""));

                    summary += "Spell Attack roll: " + result.ParseResult() + " = `" + result.Value + "`" +
                               "\nDC: `" + dc + "`";

                    if (!((string)s["spell"]).NullorEmpty())
                    {
                        var spells = await SheetService.Get(c, "spells");

                        var sp = spells.First(x => (string)x["id"] == (string)s["spell"]);
                        if (!((string)sp["body"]).NullorEmpty())
                        {
                            embed.AddField("Spell description", sp["body"]);
                        }
                        if (!((string)sp["savingthrow"]).NullorEmpty())
                        {
                            summary += "\nSaving Throw: " + sp["savingthrow"];
                        }
                        embed.WithTitle(c.Name + " casts " + (sp["name"] ?? "Unnamed Spell") + "!");
                    }
                    if (!dmg.NullorEmpty())
                    {
                        try
                        {
                            RollResult result2 = Roller.Roll(dmg + damagebonus);

                            summary += "\n" + dmgtype.Uppercase() + " damage: " + result2.ParseResult() + " = `" + result2.Value + "` ";

                            if (!((string)s["extradamage"]).NullorEmpty())
                            {
                                RollResult result3 = Roller.Roll((string)s["extradamage"]);
                                summary += "\n" + ((string)s["overridedamage"]).Uppercase() + " damage: " + result3.ParseResult() + " = `" + result3.Value + "`";
                            }
                        }
                        catch
                        {
                            await ReplyAsync("It seems like this strike doesn't have a valid dice roll on its damage or additional damage fields. If this is a spell make sure you have a valid dice expression on the damage fields.");

                            return;
                        }
                    }


                    embed.WithDescription(summary)
                    .WithFooter((c.ValuesLastUpdated.Outdated() ? "⚠️ Couldn't retrieve updated values. Roll might not be accurate" : DateTime.Now.ToString()));



                    await ReplyAsync(" ", embed.Build());
                }
                else
                {
                    if (!((string)s["weapon"]).NullorEmpty())
                    {
                        var items = await SheetService.Get(c, "items");

                        var i = items.First(x => (string)x["id"] == (string)s["weapon"]);
                        dmgtype = (string)i["damagetype"] ?? "Untyped";
                    }
                    else
                    {
                        dmgtype = "Bludgeoning";
                    }

                    if ((string)s["attack"] == "melee" || ((string)s["attack"]).NullorEmpty())
                    {
                        hit       = (string)values["melee " + (string)s["name"]]["bonus"];
                        penalties = (string)values["melee " + (string)s["name"]]["penalty"];
                    }
                    else
                    {
                        hit       = (string)values["ranged " + (string)s["name"]]["bonus"];
                        penalties = (string)values["ranged " + (string)s["name"]]["penalty"];
                    }

                    damagebonus = (string)values["damage " + (string)s["name"]]["value"];

                    dmg = (string)values["damagedice " + (string)s["name"]]["value"] + GetDie((int)values["damagedie " + (string)s["name"]]["value"]);

                    string summary = "";

                    var result = Roller.Roll("d20 + " + hit + (penalties != "0"? "-" + penalties:"") + (Bonuses.Length > 0 ? string.Join(" ", Bonuses) : ""));

                    summary += "Attack roll: " + result.ParseResult() + " = `" + result.Value + "`";

                    if (!dmg.NullorEmpty())
                    {
                        try
                        {
                            RollResult result2 = Roller.Roll(dmg + "+" + damagebonus);
                            summary += "\n" + dmgtype.Uppercase() + " damage: " + result2.ParseResult() + " = `" + result2.Value + "` ";

                            if (!((string)s["extradamage"]).NullorEmpty())
                            {
                                RollResult result3 = Roller.Roll((string)s["extradamage"]);
                                summary += "\n" + ((string)s["overridedamage"]).Uppercase() + " damage: " + result3.ParseResult() + " = `" + result3.Value + "`";
                            }
                        }
                        catch
                        {
                            await ReplyAsync("It seems like this strike doesn't have a valid dice roll on its damage or additional damage fields. If this is a spell make sure you have a valid dice expression on the damage fields.");

                            return;
                        }
                    }


                    embed.WithDescription(summary)
                    .WithFooter((c.ValuesLastUpdated.Outdated() ? "⚠️ Couldn't retrieve updated values. Roll might not be accurate" : DateTime.Now.ToString()));



                    await ReplyAsync(" ", embed.Build());
                }
            }
        }
 public ActionResult <List <ModularSheet> > Get()
 {
     return(sheetService.Get());
 }
Exemple #5
0
        public async Task Attack([Remainder] string args = "")
        {
            Character c;

            args = args.ToLower();

            if (args.Contains("-c"))
            {
                c    = GetCompanion();
                args = args.Replace("-c", "").Trim();
                if (c == null)
                {
                    await ReplyAsync("You have no active companion.");

                    return;
                }
            }
            else
            {
                c = GetCharacter();
                if (c == null)
                {
                    await ReplyAsync("You have no active character.");

                    return;
                }
            }
            if (args.NullorEmpty())
            {
                var strikes = await SheetService.Get(c, "strikes");

                var embed = new EmbedBuilder()
                            .WithTitle(c.Name + "'s strikes")
                            .WithThumbnailUrl(c.ImageUrl);

                if (strikes.Count() == 0)
                {
                    await ReplyAsync(c.Name + " has no strikes.");

                    return;
                }

                var sb = new StringBuilder();
                foreach (var s in strikes)
                {
                    string act = Icons.Actions["1"];
                    if (!((string)s["actions"]).NullorEmpty())
                    {
                        if (Icons.Actions.TryGetValue((string)s["actions"], out string ic))
                        {
                            act = ic;
                        }
                        else
                        {
                            act = "[" + s["actions"] + "]";
                        }
                    }
                    sb.AppendLine(Icons.Strike[(string)s["attack"]] + " " + (((string)s["name"]).NullorEmpty() ? "Unnamed Strike" : (string)s["name"]) + " " + act);
                }
                embed.WithDescription(sb.ToString());

                if (c.Color != null)
                {
                    embed.WithColor(new Color(c.Color[0], c.Color[1], c.Color[2]));
                }
                else
                {
                    Random randonGen   = new Random();
                    Color  randomColor = new Color(randonGen.Next(255), randonGen.Next(255),
                                                   randonGen.Next(255));
                    embed.WithColor(randomColor);
                }

                await ReplyAsync("", embed.Build());

                return;
            }
            else
            {
                string[] Bonuses = new string[0];

                if (BonusRegex.IsMatch(args))
                {
                    Bonuses = BonusRegex.Matches(args).Select(x => x.Value).ToArray();
                    foreach (var b in Bonuses)
                    {
                        args = args.Replace(b, "");
                    }
                    args = args.Trim();
                }

                List <string> Toggles = new List <string>();
                if (ToggleableRegex.IsMatch(args))
                {
                    MatchCollection RawToggles = ToggleableRegex.Matches(args);
                    foreach (Match m in RawToggles)
                    {
                        args = args.Replace(m.Value, "");
                        Toggles.Add(m.Groups[2].Value.Trim());
                    }
                    args = args.Trim();
                }

                var Jstrikes = await SheetService.Get(c, "strikes");

                var values = await SheetService.GetValues(c);

                if (values == null || Jstrikes == null)
                {
                    var err = new EmbedBuilder()
                              .WithTitle("Click here")
                              .WithUrl("https://character.pf2.tools/?" + c.RemoteId)
                              .WithDescription("Seems like we cannot fetch " + c.Name + "'s values. This is due to the fact values are only updated when you open the sheet in pf2.tools. To fix this, click the link above to generate those values.");
                    await ReplyAsync("", err.Build());

                    return;
                }

                var strikes = from sk in Jstrikes
                              where ((string)sk["name"]).ToLower().StartsWith(args)
                              orderby sk["name"]
                              select sk;

                if (strikes.Count() == 0)
                {
                    await ReplyAsync("You have no strikes whose name starts with '" + args + "'.");

                    return;
                }
                string strikename = "";
                var    s          = strikes.FirstOrDefault();
                var    embed      = new EmbedBuilder()
                                    .WithTitle(c.Name + " strikes with a " + (((string)s["name"]).NullorEmpty() ? "Unnamed Strike" : (string)s["name"]) + "!")
                                    .WithThumbnailUrl(c.ImageUrl);

                if (c.Color != null)
                {
                    embed.WithColor(new Color(c.Color[0], c.Color[1], c.Color[2]));
                }
                else
                {
                    Random randonGen   = new Random();
                    Color  randomColor = new Color(randonGen.Next(255), randonGen.Next(255),
                                                   randonGen.Next(255));
                    embed.WithColor(randomColor);
                }

                await ReplyAsync("Rolling...");

                string hit         = "";
                string dmg         = "";
                string penalties   = "";
                string damagebonus = "";
                string dmgtype     = "Untyped";

                if ((string)s["attack"] == "spell")
                {
                    JToken cl = null;

                    var classes = await SheetService.Get(c, "classes");

                    var traditions = await SheetService.Get(c, "traditions");

                    classes.Merge(traditions);
                    if (classes == null || classes.Count == 0)
                    {
                        await ReplyAsync("You don't seem to have a class. Without one you can't make spell attacks.");

                        return;
                    }
                    if (((string)s["class"]).NullorEmpty())
                    {
                        cl = classes.FirstOrDefault();
                    }
                    else
                    {
                        cl = classes.First(x => (string)x["id"] == (string)s["class"]);
                    }



                    if (!values.ContainsKey(((string)cl["name"]).ToLower()))
                    {
                        await ReplyAsync("Sorry! It seems we cannot retrieve the data for this strike! This issue is outside of the bot's control and will likely be solved later.");

                        return;
                    }

                    hit = (string)values[((string)cl["name"]).ToLower()]["bonus"];

                    int dc = int.Parse(hit ?? "0") + 10;


                    string summary = "";



                    if (!((string)s["spell"]).NullorEmpty())
                    {
                        var spells = await SheetService.Get(c, "spells");

                        var sp = spells.First(x => (string)x["id"] == (string)s["spell"]);
                        if (!((string)sp["body"]).NullorEmpty())
                        {
                            var sb = new StringBuilder();
                            sb.AppendLine((string)sp["body"]);
                            if (sb.Length <= 1024)
                            {
                                embed.AddField("Spell Description", sb.ToString());
                            }
                            else
                            {
                                var segments = sb.ToString().Split(1000).ToArray();
                                for (int i = 0; i < segments.Length; i++)
                                {
                                    embed.AddField("Spell Description (" + (i + 1) + "/" + (segments.Length) + ")", segments[i]);
                                }
                            }
                        }
                        if (!((string)sp["attackroll"]).NullorEmpty() && (bool)sp["attackroll"])
                        {
                            var result = Roller.Roll("d20 + " + hit + (Bonuses.Length > 0 ? string.Join(" ", Bonuses) : ""));

                            summary += "**Spell Attack roll**: " + result.ParseResult() + " = `" + result.Value + "`";
                        }
                        if (!((string)sp["savingthrow"]).NullorEmpty())
                        {
                            summary += "\n**Saving Throw**: " + sp["savingthrow"] + " (DC: `" + dc + "`)";
                        }
                        embed.WithTitle(c.Name + " casts " + (sp["name"] ?? "Unnamed Spell") + "!");
                    }

                    dmg = (string)s["extradamage"];
                    if (!dmg.NullorEmpty() && AttributeRegex.IsMatch(dmg))
                    {
                        dmg = await ParseValues(dmg, c, values);
                    }

                    if (DmgRegex.IsMatch(dmg))
                    {
                        foreach (var m in DmgRegex.Matches(dmg).ToList())
                        {
                            try
                            {
                                RollResult dmgroll = Roller.Roll(m.Groups[2].Value.ToLower());
                                summary += "\n**" + m.Groups[1].Value + " damage**: " + dmgroll.ParseResult() + " = `" + dmgroll.Value + "` ";
                            }
                            catch
                            {
                                continue;
                            }
                        }
                    }

                    JToken details = s["details"];

                    if (details != null && details.HasValues)
                    {
                        foreach (var value in details.Where(x => (bool)x["active"] == true || Toggles.Contains(((string)x["name"]).ToLower())))
                        {
                            try
                            {
                                RollResult Eresult = Roller.Roll(((string)value["comment"]).ToLower());
                                summary += "\n**" + (((string)value["name"]).NullorEmpty() ? "Extra Damage (" + (((string)value["type"]).NullorEmpty() ? "Untyped" : (string)value["type"]) + ") " : (string)value["name"] + " (" + (((string)value["type"]).NullorEmpty() ? "Untyped" : (string)value["type"]) + ") ") + "**: " + Eresult.ParseResult() + " = `" + Eresult.Value + "`";
                            }
                            catch
                            {
                                continue;
                            }
                        }
                    }

                    embed.WithDescription(summary)
                    .WithFooter((c.ValuesLastUpdated.Outdated() ? "⚠️ Couldn't retrieve updated values. Roll might not be accurate" : DateTime.Now.ToString()));



                    await ReplyAsync(" ", embed.Build());
                }
                else if ((string)s["attack"] == "custom")
                {
                    string summary = "";
                    if (!((string)s["weaponcustom"]).NullorEmpty())
                    {
                        embed.WithTitle(c.Name + " strikes with a " + s["weaponcustom"]);
                    }
                    if (!((string)s["damagetypecustom"]).NullorEmpty())
                    {
                        dmgtype = (string)s["damagetypecustom"];
                    }
                    if (!((string)s["traitscustom"]).NullorEmpty())
                    {
                        string[] traits = ((string)s["traitscustom"]).Split(',');
                        foreach (var x in traits)
                        {
                            summary += "[" + x.ToUpper() + "] ";
                        }
                        summary += "\n";
                    }
                    int range = 0;
                    if (!((string)s["range"]).NullorEmpty())
                    {
                        range += int.Parse((string)s["range"]);
                    }
                    if (!((string)s["modrange"]).NullorEmpty())
                    {
                        range += int.Parse((string)s["modrange"]);
                    }
                    summary += "**Range** " + range + "ft.\n";


                    if ((string)s["attackcustom"] == "ranged" || ((string)s["attack"]).NullorEmpty())
                    {
                        hit       = (string)values["ranged " + (string)s["name"]]["bonus"];
                        penalties = (string)values["ranged " + (string)s["name"]]["penalty"];
                        var result = Roller.Roll("d20 + " + hit + (penalties != "0" ? "-" + penalties : "") + (Bonuses.Length > 0 ? string.Join(" ", Bonuses) : ""));

                        summary += "**Attack roll**: " + result.ParseResult() + " = `" + result.Value + "`";
                    }
                    else if ((string)s["attackcustom"] == "melee" || ((string)s["attack"]).NullorEmpty())
                    {
                        hit       = (string)values["melee " + (string)s["name"]]["bonus"];
                        penalties = (string)values["melee " + (string)s["name"]]["penalty"];
                        var result = Roller.Roll("d20 + " + hit + (penalties != "0" ? "-" + penalties : "") + (Bonuses.Length > 0 ? string.Join(" ", Bonuses) : ""));

                        summary += "**Attack roll**: " + result.ParseResult() + " = `" + result.Value + "`";
                    }

                    damagebonus = (string)values["damage " + (string)s["name"]]["value"];

                    dmg = (string)values["damagedice " + (string)s["name"]]["value"] + GetDie((int)values["damagedie " + (string)s["name"]]["value"]);


                    if (!dmg.NullorEmpty())
                    {
                        try
                        {
                            RollResult result2 = Roller.Roll(dmg + "+" + damagebonus);
                            summary += "\n**" + dmgtype.Uppercase() + " damage**: " + result2.ParseResult() + " = `" + result2.Value + "` ";

                            if (!((string)s["extradamage"]).NullorEmpty())
                            {
                                string extradmg = (string)s["extradamage"];
                                if (!extradmg.NullorEmpty() && AttributeRegex.IsMatch(extradmg))
                                {
                                    extradmg = await ParseValues(extradmg, c, values);
                                }

                                if (DmgRegex.IsMatch(extradmg))
                                {
                                    foreach (var m in DmgRegex.Matches(extradmg).ToList())
                                    {
                                        try
                                        {
                                            RollResult dmgroll = Roller.Roll(m.Groups[2].Value);
                                            summary += "\n**" + m.Groups[1].Value + " damage**: " + dmgroll.ParseResult() + " = `" + dmgroll.Value + "` ";
                                        }
                                        catch
                                        {
                                            continue;
                                        }
                                    }
                                }
                            }
                        }
                        catch
                        {
                            await ReplyAsync("It seems like this strike doesn't have a valid dice roll on its damage or additional damage fields. If this is a spell make sure you have a valid dice expression on the damage fields.");

                            return;
                        }
                    }
                    JToken details = s["details"];

                    if (details != null && details.HasValues)
                    {
                        foreach (var value in details.Where(x => (bool)x["active"] == true || Toggles.Contains(((string)x["name"]).ToLower())))
                        {
                            try
                            {
                                RollResult Eresult = Roller.Roll((string)value["comment"]);
                                summary += "\n**" + (((string)value["name"]).NullorEmpty() ? "Extra Damage (" + (((string)value["type"]).NullorEmpty() ? "Untyped" : (string)value["type"]) + ") " : (string)value["name"] + " (" + (((string)value["type"]).NullorEmpty() ? "Untyped" : (string)value["type"]) + ") ") + "**: " + Eresult.ParseResult() + " = `" + Eresult.Value + "`";
                            }
                            catch
                            {
                                continue;
                            }
                        }
                    }

                    embed.WithDescription(summary)
                    .WithFooter((c.ValuesLastUpdated.Outdated() ? "⚠️ Couldn't retrieve updated values. Roll might not be accurate" : DateTime.Now.ToString()));



                    await ReplyAsync(" ", embed.Build());
                }
                else
                {
                    string summary = "";
                    if (!((string)s["weapon"]).NullorEmpty())
                    {
                        var items = await SheetService.Get(c, "items");

                        var i = items.First(x => (string)x["id"] == (string)s["weapon"]);
                        dmgtype = (string)i["damagetype"] ?? "Untyped";

                        if (!((string)i["traits"]).NullorEmpty())
                        {
                            string[] traits = ((string)i["traits"]).Split(',');
                            foreach (var x in traits)
                            {
                                summary += "[" + x.ToUpper() + "] ";
                            }
                            summary += "\n";
                        }


                        int range = 0;
                        if (!((string)i["range"]).NullorEmpty() && int.TryParse((string)i["range"], out int r))
                        {
                            range += r;
                        }
                        if (!((string)s["modrange"]).NullorEmpty() && int.TryParse((string)s["modrange"], out int r2))
                        {
                            range += r2;
                        }
                        summary += "**Range**: " + range + "ft.\n";

                        if ((string)i["attack"] == "melee")
                        {
                            hit       = (string)values["melee " + (string)s["name"]]["bonus"];
                            penalties = (string)values["melee " + (string)s["name"]]["penalty"];
                        }
                        else if ((string)i["attack"] == "ranged")
                        {
                            hit       = (string)values["ranged " + (string)s["name"]]["bonus"];
                            penalties = (string)values["ranged " + (string)s["name"]]["penalty"];
                        }
                        if (!((string)i["name"]).NullorEmpty())
                        {
                            embed.WithTitle(c.Name + " strikes with a " + (string)i["name"] + "!");
                        }
                    }

                    if ((string)s["attack"] == "melee")
                    {
                        hit       = (string)values["melee " + (string)s["name"]]["bonus"];
                        penalties = (string)values["melee " + (string)s["name"]]["penalty"];
                    }
                    else if ((string)s["attack"] == "ranged")
                    {
                        hit       = (string)values["ranged " + (string)s["name"]]["bonus"];
                        penalties = (string)values["ranged " + (string)s["name"]]["penalty"];
                    }

                    damagebonus = (string)values["damage " + (string)s["name"]]["value"];

                    dmg = (string)values["damagedice " + (string)s["name"]]["value"] + GetDie((int)values["damagedie " + (string)s["name"]]["value"]);



                    var result = Roller.Roll("d20 + " + hit + (penalties != "0"? "-" + penalties:"") + (Bonuses.Length > 0 ? string.Join(" ", Bonuses) : ""));

                    summary += "**Attack roll**: " + result.ParseResult() + " = `" + result.Value + "`";

                    if (!dmg.NullorEmpty())
                    {
                        try
                        {
                            RollResult result2 = Roller.Roll(dmg + "+" + damagebonus);
                            summary += "\n**" + dmgtype.Uppercase() + " damage**: " + result2.ParseResult() + " = `" + result2.Value + "` ";

                            if (!((string)s["extradamage"]).NullorEmpty())
                            {
                                string extradmg = (string)s["extradamage"];
                                if (!extradmg.NullorEmpty() && AttributeRegex.IsMatch(extradmg))
                                {
                                    extradmg = await ParseValues(extradmg, c, values);
                                }

                                if (DmgRegex.IsMatch(extradmg))
                                {
                                    foreach (var m in DmgRegex.Matches(extradmg).ToList())
                                    {
                                        try
                                        {
                                            RollResult dmgroll = Roller.Roll(m.Groups[2].Value);
                                            summary += "\n**" + m.Groups[1].Value + " damage**: " + dmgroll.ParseResult() + " = `" + dmgroll.Value + "` ";
                                        }
                                        catch
                                        {
                                            continue;
                                        }
                                    }
                                }
                            }
                        }
                        catch
                        {
                            await ReplyAsync("It seems like this strike doesn't have a valid dice roll on its damage or additional damage fields. If this is a spell make sure you have a valid dice expression on the damage fields.");

                            return;
                        }
                    }
                    JToken details = s["details"];

                    if (details != null && details.HasValues)
                    {
                        foreach (var value in details.Where(x => (bool)x["active"] == true || Toggles.Contains(((string)x["name"]).ToLower())))
                        {
                            try
                            {
                                RollResult Eresult = Roller.Roll((string)value["comment"]);
                                summary += "\n**" + (((string)value["name"]).NullorEmpty() ? "Extra Damage (" + (((string)value["type"]).NullorEmpty() ? "Untyped" : (string)value["type"]) + ") " : (string)value["name"] + " (" + (((string)value["type"]).NullorEmpty() ? "Untyped" : (string)value["type"]) + ") ") + "**: " + Eresult.ParseResult() + " = `" + Eresult.Value + "`";
                            }
                            catch
                            {
                                continue;
                            }
                        }
                    }

                    embed.WithDescription(summary)
                    .WithFooter((c.ValuesLastUpdated.Outdated() ? "⚠️ Couldn't retrieve updated values. Roll might not be accurate" : DateTime.Now.ToString()));



                    await ReplyAsync(" ", embed.Build());
                }
            }
        }