Esempio n. 1
0
        public async Task AttackWithRangedWeapon(int range = 0, string weaponName = null)
        {
            if (range < 0)
            {
                await ReplyAsync($"Range can't be negative.");

                return;
            }

            var activeCharacter =
                _stewardContext.PlayerCharacters
                .Include(c => c.DefaultRangedWeapon)
                .Include(c => c.House)
                .Include(c => c.CharacterTraits)
                .ThenInclude(ct => ct.Trait)
                .SingleOrDefault(c => c.DiscordUserId == Context.User.Id.ToString() && c.YearOfDeath == null);

            ValkFinderWeapon valkFinderWeapon = null;

            valkFinderWeapon = activeCharacter.DefaultRangedWeapon ?? _stewardContext.ValkFinderWeapons.FirstOrDefault(w => w.WeaponName == weaponName);

            if (valkFinderWeapon == null)
            {
                await ReplyAsync($"Could not find weapon.");

                return;
            }

            if (!_inventoryService.CheckInv(activeCharacter, valkFinderWeapon.WeaponName, "weapon", 1))
            {
                await ReplyAsync($"You do not have a {valkFinderWeapon.WeaponName} in your inventory");

                return;
            }

            if (!valkFinderWeapon.IsRanged)
            {
                await ReplyAsync($"{weaponName} is not a ranged weapon.");

                return;
            }

            var message = _rollService.RollRangedAttack(activeCharacter, valkFinderWeapon, range);

            await ReplyAsync(embed : message.Build());
        }
Esempio n. 2
0
        public EmbedBuilder RollMeleeAttack(PlayerCharacter character, ValkFinderWeapon weapon, string attackType)
        {
            var attackTypeHitBonus    = 0;
            var attackTypeDamageBonus = 0;

            switch (attackType)
            {
            case "heavy":
                attackTypeHitBonus    = 2;
                attackTypeDamageBonus = 1;
                break;

            case "light":
                attackTypeHitBonus    = -4;
                attackTypeDamageBonus = -2;
                break;

            case "normal":
                break;

            default:
                var embedBuilderError = new EmbedBuilder().WithColor(Color.Purple);
                embedBuilderError.AddField("Error", "Unknown attack type");
                return(embedBuilderError);
            }

            var rnd = new Random();

            var strMod = GetStatAsModifier(CharacterAttribute.STR, character);
            var dexMod = 0; //GetStatAsModifier(CharacterAttribute.DEX, character); -- ditto as below

            if (weapon.WeaponTrait == WeaponTrait.Finesse)
            {
                strMod = 0;
                dexMod = GetStatAsModifier(CharacterAttribute.DEX, character);
            }

            var attackRollRaw = rnd.Next(1, 21);

            var attackRoll = attackRollRaw + strMod + dexMod + attackTypeHitBonus + weapon.HitBonus;

            if (attackRoll < 0)
            {
                attackRoll = 0;
            }

            var crit = attackRollRaw == 20;             //are we crittin'?

            var damageRollsRaw = new List <int>();

            for (var i = 0; i < weapon.DamageDieAmount; i++)
            {
                damageRollsRaw.Add(rnd.Next(1, weapon.DamageDieSize + 1));
            }

            var critRolls = new List <int>();

            if (crit)
            {
                for (var i = 0; i < weapon.DamageDieAmount; i++)
                {
                    critRolls.Add(rnd.Next(1, weapon.DamageDieSize + 1));
                }
            }
            strMod = GetStatAsModifier(CharacterAttribute.STR, character);
            dexMod = GetStatAsModifier(CharacterAttribute.DEX, character);
            var damage = damageRollsRaw.Sum() + weapon.DamageBonus + attackTypeDamageBonus + critRolls.Sum() + strMod + dexMod;

            //TODO: Clean this up into something modular, redefining the entire string each time just isn't maintainable.
            //Done: cleaned up into something modular
            var attackRollString = $"(1d20 = {attackRollRaw}) + {strMod + dexMod}";

            if (attackTypeHitBonus != 0)
            {
                attackRollString += $" + {attackTypeHitBonus} from attack type";
            }
            if (weapon.HitBonus != 0)
            {
                attackRollString += $" + {weapon.HitBonus} from weapon";
            }
            attackRollString += $" = {attackRoll}";

            if (crit)
            {
                attackRollString += " **!Critical Hit!**";
            }

            var damageRollsRawString = string.Join(" + ", damageRollsRaw);
            var critRollsString      = string.Join(" + ", critRolls);
            var damageRollString     = $"({weapon.DamageDieAmount}d{weapon.DamageDieSize} = {damageRollsRawString})";

            if (crit)
            {
                damageRollString += $" + ({weapon.DamageDieAmount}d{weapon.DamageDieSize} = {critRollsString}) from crit";
            }

            if (attackTypeDamageBonus != 0)
            {
                damageRollString += $" + {attackTypeDamageBonus} from attack type";
            }

            if (weapon.DamageBonus != 0)
            {
                damageRollString += $" + {weapon.DamageBonus} from weapon";
            }
            damageRollString += $" + {strMod}(STR) + {dexMod}(DEX) = {damage}";

            var embedBuilder = new EmbedBuilder().WithColor(Color.Purple).WithTitle($"Melee: {weapon.WeaponName} ({attackType}) by {character.CharacterName}");

            embedBuilder.AddField("Attack Roll", attackRollString);
            embedBuilder.AddField("Damage Roll", damageRollString);

            return(embedBuilder);
        }
Esempio n. 3
0
        public EmbedBuilder RollRangedAttack(PlayerCharacter character, ValkFinderWeapon weapon, int range = 0)
        {
            var rnd = new Random();

            var perMod = GetStatAsModifier(CharacterAttribute.PER, character);
            var dexMod = GetStatAsModifier(CharacterAttribute.DEX, character);

            var rangePenalty = 0;             //-(range / 2);

            var attackRollRaw = rnd.Next(1, 21);
            var attackRoll    = attackRollRaw + perMod + dexMod + rangePenalty + weapon.HitBonus;
            var crit          = attackRollRaw == 20;

            /*if (attackRoll < 0)
             * {
             *      attackRoll = 0;
             * }
             *
             * var damageRollBonus = 0; //GetStatAsModifier(weapon.DamageModifier, character); -- ―〃―
             * var rawDamageRoll = rnd.Next(1, weapon.DamageDieSize + 1);
             * var damageRoll =  rawDamageRoll + damageRollBonus;
             *
             * if (crit)
             * damageRoll += rawDamageRoll;
             *
             * if (damageRoll < 0)
             * {
             *      damageRoll = 0;
             * }*/

            var damageRollsRaw = new List <int>();

            for (int i = 0; i < weapon.DamageDieAmount; i++)
            {
                damageRollsRaw.Add(rnd.Next(1, weapon.DamageDieSize + 1));
            }

            var damage = damageRollsRaw.Sum() + weapon.DamageBonus + dexMod;

            if (crit)
            {
                damage = damageRollsRaw.Sum() * 2 + weapon.DamageBonus;
            }

            var attackRollString = $"(1d20 = {attackRollRaw}) + {perMod + dexMod}";

            if (weapon.HitBonus != 0)
            {
                attackRollString += $" + {weapon.HitBonus} from weapon";
            }
            attackRollString += $" = {attackRoll}";

            if (crit)
            {
                attackRollString += " **!Critical Hit!**";
            }

            var damageRollsRawString = string.Join(" + ", damageRollsRaw);
            var damageRollString     = $"({weapon.DamageDieAmount}d{weapon.DamageDieSize} = {damageRollsRawString})";

            if (crit)
            {
                damageRollString += $" * 2 from crit";
            }

            if (weapon.DamageBonus != 0)
            {
                damageRollString += $" + {weapon.DamageBonus} from weapon";
            }
            damageRollString += $" + {dexMod}(DEX) = {damage}";

            var embedBuilder = new EmbedBuilder().WithColor(Color.Purple).WithTitle($"Ranged: {weapon.WeaponName}");

            embedBuilder.AddField("Attack Roll", attackRollString);
            embedBuilder.AddField("Damage Roll", damageRollString);

            return(embedBuilder);
        }
Esempio n. 4
0
        public async Task AddWeapon(string name, string rangedOrMelee, string damage, int hitBonus, string weaponTraitString = "None", bool unique = false)
        {
            if (name.Length > 100)
            {
                await ReplyAsync("Weapon name can't be longer than 100 characters.");

                return;
            }

            if (rangedOrMelee != "ranged" && rangedOrMelee != "melee")
            {
                await ReplyAsync("Weapon has to be either melee or ranged.");

                return;
            }
            var damageDieAmount = 0;
            var damageDieSize   = 0;
            var damageBonus     = 0;

            var pattern = @"(\d+)d(\d+)([+-])(\d+)";

            if (Regex.IsMatch(damage, pattern))
            {
                foreach (System.Text.RegularExpressions.Match m in System.Text.RegularExpressions.Regex.Matches(damage, pattern))
                {
                    damageDieAmount = Int32.Parse(m.Groups[1].Value);
                    damageDieSize   = Int32.Parse(m.Groups[2].Value);
                    damageBonus     = Int32.Parse(m.Groups[3].Value + m.Groups[4].Value);
                }
            }
            else
            {
                await ReplyAsync($"{damage}: is not a valid damage die and modifier");

                return;
            }

            if (!Enum.TryParse(weaponTraitString, true, out WeaponTrait weaponTrait))
            {
                await ReplyAsync("Not a valid attribute.");

                return;
            }

            var doesWeaponAlreadyExist =
                _stewardContext.ValkFinderWeapons.SingleOrDefault(vfw => vfw.WeaponName == name);

            if (doesWeaponAlreadyExist != null)
            {
                await ReplyAsync("Weapon already exists.");

                return;
            }

            var newWeapon = new ValkFinderWeapon()
            {
                WeaponName      = name,
                DamageDieAmount = damageDieAmount,
                DamageDieSize   = damageDieSize,
                DamageBonus     = damageBonus,
                HitBonus        = hitBonus,
                IsRanged        = rangedOrMelee == "ranged",
                IsUnique        = unique,
                WeaponTrait     = weaponTrait
            };

            _stewardContext.ValkFinderWeapons.Add(newWeapon);
            await _stewardContext.SaveChangesAsync();

            await ReplyAsync("Weapon added.");
        }