Exemplo n.º 1
0
        public void SelectWithQuantityOf0_Thrown(string weapon)
        {
            var thrown = WeaponConstants.GetAllThrown(false, false);
            var simple = WeaponConstants.GetAllSimple(false, false);
            var melee  = WeaponConstants.GetAllMelee(false, false);

            var thrownRanged = thrown.Except(melee).Intersect(simple);

            Assert.That(thrownRanged, Contains.Item(weapon)
                        .And.EquivalentTo(new[]
            {
                WeaponConstants.Javelin,
                WeaponConstants.Dart,
            }));

            var item = itemSelector.SelectFrom($"{weapon}[{ItemTypeConstants.Weapon}]");

            Assert.That(item.Name, Is.EqualTo(weapon), weapon);
            Assert.That(item.ItemType, Is.EqualTo(ItemTypeConstants.Weapon), weapon);
            Assert.That(item.Traits, Is.Empty, weapon);
            Assert.That(item.Magic.SpecialAbilities, Is.Empty, weapon);
            Assert.That(item.Magic.Bonus, Is.Zero, weapon);
            Assert.That(item.IsMagical, Is.False, weapon);
            Assert.That(item.Quantity, Is.Zero, weapon);
        }
Exemplo n.º 2
0
        public Item SelectFrom(string source)
        {
            var template = new Item();

            template.Name = source;
            template.Name = itemTypeRegex.Replace(template.Name, string.Empty);
            template.Name = itemBonusRegex.Replace(template.Name, string.Empty);
            template.Name = specialAbilityRegex.Replace(template.Name, string.Empty);
            template.Name = traitRegex.Replace(template.Name, string.Empty);
            template.Name = isMagicRegex.Replace(template.Name, string.Empty);

            template.ItemType = GetMatchValue(itemTypeRegex, source, "[", "]");

            if (isMagicRegex.IsMatch(source))
            {
                var rawIsMagic = GetMatchValue(isMagicRegex, source, "@", "@");
                template.IsMagical = Convert.ToBoolean(rawIsMagic);
            }

            if (itemBonusRegex.IsMatch(source))
            {
                var rawBonus = GetMatchValue(itemBonusRegex, source, "(", ")");
                template.Magic.Bonus = Convert.ToInt32(rawBonus);
            }

            if (specialAbilityRegex.IsMatch(source))
            {
                var rawSpecialAbilities = GetMatchValue(specialAbilityRegex, source, "{", "}");
                var specialAbilities    = rawSpecialAbilities.Split(',');
                template.Magic.SpecialAbilities = GetSpecialAbilities(specialAbilities);
            }

            if (traitRegex.IsMatch(source))
            {
                var rawTraits = GetMatchValue(traitRegex, source, "#");
                var traits    = rawTraits.Split(',');

                foreach (var trait in traits)
                {
                    template.Traits.Add(trait);
                }
            }

            var ammunition         = WeaponConstants.GetAllAmmunition(false, false);
            var thrown             = WeaponConstants.GetAllThrown(false, false);
            var simple             = WeaponConstants.GetAllSimple(false, false);
            var melee              = WeaponConstants.GetAllMelee(false, false);
            var thrownRanged       = thrown.Except(melee).Intersect(simple);
            var needRandomQuantity = ammunition.Union(thrownRanged);

            if (needRandomQuantity.Contains(template.Name))
            {
                template.Quantity = 0;
            }

            return(template);
        }
Exemplo n.º 3
0
        public void SelectWithQuantityOf1_AllOtherWeapons()
        {
            var allWeapons   = WeaponConstants.GetAllWeapons(false, false);
            var ammos        = WeaponConstants.GetAllAmmunition(false, false);
            var thrown       = WeaponConstants.GetAllThrown(false, false);
            var simple       = WeaponConstants.GetAllSimple(false, false);
            var melee        = WeaponConstants.GetAllMelee(false, false);
            var thrownRanged = thrown.Except(melee).Intersect(simple);

            var weapons = allWeapons.Except(ammos).Except(thrownRanged);

            foreach (var weapon in weapons)
            {
                var item = itemSelector.SelectFrom($"{weapon}[{ItemTypeConstants.Weapon}]");
                Assert.That(item.Name, Is.EqualTo(weapon), weapon);
                Assert.That(item.ItemType, Is.EqualTo(ItemTypeConstants.Weapon), weapon);
                Assert.That(item.Traits, Is.Empty, weapon);
                Assert.That(item.Magic.SpecialAbilities, Is.Empty, weapon);
                Assert.That(item.Magic.Bonus, Is.Zero, weapon);
                Assert.That(item.IsMagical, Is.False, weapon);
                Assert.That(item.Quantity, Is.EqualTo(1), weapon);
            }
        }
Exemplo n.º 4
0
        public void MeleeWeaponsMatchConstants()
        {
            var melee = WeaponConstants.GetAllMelee(false, false);

            VerifyAttribute(melee, AttributeConstants.Melee);
        }
Exemplo n.º 5
0
        public Equipment Generate(string creatureName, bool canUseEquipment, IEnumerable <Feat> feats, int level, IEnumerable <Attack> attacks, Dictionary <string, Ability> abilities, string size)
        {
            var equipment = new Equipment();

            var weaponSize = GetWeaponSize(feats, size);

            //Get predetermined items
            var allPredeterminedItems = GetPredeterminedItems(creatureName, size, weaponSize);
            var predeterminedWeapons  = allPredeterminedItems
                                        .Where(i => i is Weapon)
                                        .Select(i => i as Weapon)
                                        .ToList();
            var predeterminedArmors = allPredeterminedItems
                                      .Where(i => i is Armor)
                                      .Select(i => i as Armor)
                                      .ToList();

            equipment.Items = allPredeterminedItems.Except(predeterminedWeapons).Except(predeterminedArmors);

            if (predeterminedArmors.Any())
            {
                equipment.Shield = predeterminedArmors.FirstOrDefault(a => a.Attributes.Contains(AttributeConstants.Shield));
                equipment.Armor  = predeterminedArmors.FirstOrDefault(a => !a.Attributes.Contains(AttributeConstants.Shield));
            }

            //INFO: If there are equipment attacks, but the level is 0, then this is a humanoid character
            //These attacks will be updated when the character is generated
            if (!canUseEquipment || level < 1)
            {
                return(equipment);
            }

            //Generate weapons and attacks
            var unnaturalAttacks = attacks.Where(a => !a.IsNatural);

            var weaponProficiencyFeatNames = collectionSelector.SelectFrom(TableNameConstants.Collection.FeatGroups, GroupConstants.WeaponProficiency);
            var weaponProficiencyFeats     = feats.Where(f => weaponProficiencyFeatNames.Contains(f.Name));

            var weapons = new List <Weapon>();
            var hasMultipleEquippedMeleeAttacks = unnaturalAttacks.Count(a => a.Name == AttributeConstants.Melee) >= 2;

            if (weaponProficiencyFeats.Any() && unnaturalAttacks.Any())
            {
                //Generate melee weapons
                var weaponNames = WeaponConstants.GetAllWeapons(false, false);

                var equipmentMeleeAttacks = unnaturalAttacks.Where(a => a.Name == AttributeConstants.Melee);
                if (equipmentMeleeAttacks.Any())
                {
                    var meleeWeaponNames = WeaponConstants.GetAllMelee(false, false);

                    var nonProficiencyFeats = feats.Except(weaponProficiencyFeats);
                    var hasWeaponFinesse    = feats.Any(f => f.Name == FeatConstants.WeaponFinesse);
                    var light = WeaponConstants.GetAllLightMelee(true, false);

                    var proficientMeleeWeaponNames    = GetProficientWeaponNames(feats, weaponProficiencyFeats, meleeWeaponNames, !hasMultipleEquippedMeleeAttacks);
                    var nonProficientMeleeWeaponNames = meleeWeaponNames
                                                        .Except(proficientMeleeWeaponNames.Common)
                                                        .Except(proficientMeleeWeaponNames.Uncommon);

                    if (hasMultipleEquippedMeleeAttacks)
                    {
                        var twoHandedWeapons = WeaponConstants.GetAllTwoHandedMelee(false, false);
                        nonProficientMeleeWeaponNames = nonProficientMeleeWeaponNames.Except(twoHandedWeapons);
                    }

                    var primaryMeleeAttacks    = equipmentMeleeAttacks.Where(a => a.IsPrimary).ToArray();
                    var primaryLightBonusAdded = false;

                    foreach (var attack in equipmentMeleeAttacks)
                    {
                        Weapon weapon = null;

                        if (predeterminedWeapons.Any(i => i.Attributes.Contains(AttributeConstants.Melee)))
                        {
                            weapon = predeterminedWeapons.First(i => i.Attributes.Contains(AttributeConstants.Melee));

                            predeterminedWeapons.Remove(weapon);
                        }
                        else
                        {
                            var weaponName = collectionSelector.SelectRandomFrom(
                                proficientMeleeWeaponNames.Common,
                                proficientMeleeWeaponNames.Uncommon,
                                null,
                                nonProficientMeleeWeaponNames);
                            weapon = itemGenerator.GenerateAtLevel(level, ItemTypeConstants.Weapon, weaponName, weaponSize) as Weapon;
                        }

                        weapons.Add(weapon);

                        attack.Name = weapon.Description;
                        attack.Damages.AddRange(weapon.Damages);

                        //Is not proficient with the weapon
                        if (!proficientMeleeWeaponNames.Common.Any(weapon.NameMatches) &&
                            !proficientMeleeWeaponNames.Uncommon.Any(weapon.NameMatches))
                        {
                            attack.AttackBonuses.Add(-4);
                        }

                        if (weapon.Magic.Bonus != 0)
                        {
                            attack.AttackBonuses.Add(weapon.Magic.Bonus);
                        }
                        else if (weapon.Traits.Contains(TraitConstants.Masterwork))
                        {
                            attack.AttackBonuses.Add(1);
                        }

                        var bonusFeats = nonProficiencyFeats.Where(f => f.Foci.Any(weapon.NameMatches));
                        foreach (var feat in bonusFeats)
                        {
                            if (feat.Power != 0)
                            {
                                attack.AttackBonuses.Add(feat.Power);
                            }
                        }

                        var isLight = light.Any(weapon.NameMatches);
                        if (hasWeaponFinesse && isLight)
                        {
                            attack.BaseAbility = abilities[AbilityConstants.Dexterity];
                        }

                        if (hasMultipleEquippedMeleeAttacks && !attack.IsPrimary && isLight)
                        {
                            attack.AttackBonuses.Add(2);

                            if (!primaryLightBonusAdded)
                            {
                                foreach (var primaryAttack in primaryMeleeAttacks)
                                {
                                    primaryAttack.AttackBonuses.Add(2);
                                }
                            }

                            primaryLightBonusAdded = true;
                        }
                    }
                }

                //Generate ranged weapons
                var equipmentRangedAttacks = unnaturalAttacks.Where(a => a.Name == AttributeConstants.Ranged);
                if (equipmentRangedAttacks.Any())
                {
                    var rangedWeaponNames = GetRangedWithBowTemplates();

                    var proficientRangedWeaponNames    = GetProficientWeaponNames(feats, weaponProficiencyFeats, rangedWeaponNames, !hasMultipleEquippedMeleeAttacks);
                    var nonProficientRangedWeaponNames = rangedWeaponNames
                                                         .Except(proficientRangedWeaponNames.Common)
                                                         .Except(proficientRangedWeaponNames.Uncommon);

                    var nonProficiencyFeats = feats.Except(weaponProficiencyFeats);
                    var crossbows           = new[]
                    {
                        WeaponConstants.HandCrossbow,
                        WeaponConstants.HeavyCrossbow,
                        WeaponConstants.LightCrossbow,
                    };

                    var rapidReload = feats.FirstOrDefault(f => f.Name == FeatConstants.RapidReload);

                    foreach (var attack in equipmentRangedAttacks)
                    {
                        Weapon weapon = null;

                        if (predeterminedWeapons.Any(i =>
                                                     i.Attributes.Contains(AttributeConstants.Ranged) &&
                                                     !i.Attributes.Contains(AttributeConstants.Melee)))
                        {
                            weapon = predeterminedWeapons.First(i =>
                                                                i.Attributes.Contains(AttributeConstants.Ranged) &&
                                                                !i.Attributes.Contains(AttributeConstants.Melee));

                            predeterminedWeapons.Remove(weapon);
                        }
                        else
                        {
                            var weaponName = collectionSelector.SelectRandomFrom(
                                proficientRangedWeaponNames.Common,
                                proficientRangedWeaponNames.Uncommon,
                                null,
                                nonProficientRangedWeaponNames);
                            weapon = itemGenerator.GenerateAtLevel(level, ItemTypeConstants.Weapon, weaponName, weaponSize) as Weapon;
                        }

                        weapons.Add(weapon);

                        //Get ammunition
                        if (!string.IsNullOrEmpty(weapon.Ammunition))
                        {
                            Weapon ammo = null;

                            if (predeterminedWeapons.Any(i => i.NameMatches(weapon.Ammunition)))
                            {
                                ammo = predeterminedWeapons.First(i => i.NameMatches(weapon.Ammunition));

                                predeterminedWeapons.Remove(ammo);
                            }
                            else
                            {
                                ammo = itemGenerator.GenerateAtLevel(level, ItemTypeConstants.Weapon, weapon.Ammunition, weaponSize) as Weapon;
                            }

                            weapons.Add(ammo);
                        }

                        //Set up the attack
                        attack.Name = weapon.Description;
                        attack.Damages.AddRange(weapon.Damages);

                        if (!proficientRangedWeaponNames.Common.Any(weapon.NameMatches) &&
                            !proficientRangedWeaponNames.Uncommon.Any(weapon.NameMatches))
                        {
                            attack.AttackBonuses.Add(-4);
                        }

                        if (weapon.Magic.Bonus != 0)
                        {
                            attack.AttackBonuses.Add(weapon.Magic.Bonus);
                        }
                        else if (weapon.Traits.Contains(TraitConstants.Masterwork))
                        {
                            attack.AttackBonuses.Add(1);
                        }

                        var bonusFeats = nonProficiencyFeats.Where(f => f.Foci.Any(weapon.NameMatches));
                        foreach (var feat in bonusFeats)
                        {
                            if (feat.Power != 0)
                            {
                                attack.AttackBonuses.Add(feat.Power);
                            }
                        }

                        if (!weapon.Attributes.Contains(AttributeConstants.Thrown) &&
                            !weapon.Attributes.Contains(AttributeConstants.Projectile))
                        {
                            attack.MaxNumberOfAttacks = 1;
                        }

                        if (crossbows.Any(weapon.NameMatches))
                        {
                            attack.MaxNumberOfAttacks = 1;

                            if (rapidReload?.Foci?.Any(weapon.NameMatches) == true &&
                                (weapon.NameMatches(WeaponConstants.LightCrossbow) ||
                                 weapon.NameMatches(WeaponConstants.HandCrossbow)))
                            {
                                attack.MaxNumberOfAttacks = 4;
                            }
                        }
                    }
                }

                equipment.Weapons = weapons;
            }

            var armorProficiencyFeatNames = collectionSelector.SelectFrom(TableNameConstants.Collection.FeatGroups, GroupConstants.ArmorProficiency);
            var armorProficiencyFeats     = feats.Where(f => armorProficiencyFeatNames.Contains(f.Name));

            if (armorProficiencyFeats.Any())
            {
                var armorNames           = ArmorConstants.GetAllArmors(false);
                var proficientArmorNames = GetProficientArmorNames(armorProficiencyFeats);

                if (proficientArmorNames.Any() && equipment.Armor == null)
                {
                    var nonProficientArmorNames = armorNames.Except(proficientArmorNames);
                    var armorName = collectionSelector.SelectRandomFrom(proficientArmorNames, null, null, nonProficientArmorNames);

                    equipment.Armor = itemGenerator.GenerateAtLevel(level, ItemTypeConstants.Armor, armorName, size) as Armor;
                }

                var shieldNames           = ArmorConstants.GetAllShields(false);
                var proficientShieldNames = GetProficientShieldNames(armorProficiencyFeats);
                var hasTwoHandedWeapon    = weapons.Any(w => w.Attributes.Contains(AttributeConstants.Melee) && w.Attributes.Contains(AttributeConstants.TwoHanded));

                if (proficientShieldNames.Any() &&
                    !hasTwoHandedWeapon &&
                    !hasMultipleEquippedMeleeAttacks &&
                    equipment.Shield == null)
                {
                    var nonProficientShieldNames = shieldNames.Except(proficientShieldNames);
                    var shieldName = collectionSelector.SelectRandomFrom(proficientShieldNames, null, null, nonProficientShieldNames);

                    equipment.Shield = itemGenerator.GenerateAtLevel(level, ItemTypeConstants.Armor, shieldName, size) as Armor;
                }
            }

            return(equipment);
        }
Exemplo n.º 6
0
        private Item GetWeapon(Item rod)
        {
            var weapons         = WeaponConstants.GetAllMelee(false, false);
            var weaponBaseNames = weapons.Intersect(rod.BaseNames);

            if (!weaponBaseNames.Any())
            {
                return(rod);
            }

            var weaponName = weaponBaseNames.First();

            var mundaneWeaponGenerator = justInTimeFactory.Build <MundaneItemGenerator>(ItemTypeConstants.Weapon);
            var mundaneWeapon          = mundaneWeaponGenerator.Generate(weaponName, rod.Traits.ToArray()) as Weapon;

            rod.Attributes = rod.Attributes.Union(mundaneWeapon.Attributes);
            rod.CloneInto(mundaneWeapon);

            if (mundaneWeapon.IsMagical)
            {
                mundaneWeapon.Traits.Add(TraitConstants.Masterwork);
            }

            if (mundaneWeapon.IsDoubleWeapon)
            {
                mundaneWeapon.SecondaryHasAbilities = true;
                mundaneWeapon.SecondaryMagicBonus   = rod.Magic.Bonus;
            }

            foreach (var specialAbility in mundaneWeapon.Magic.SpecialAbilities)
            {
                if (specialAbility.Damages.Any())
                {
                    var damages    = specialAbility.Damages.Select(d => d.Clone()).ToArray();
                    var damageType = mundaneWeapon.Damages[0].Type;

                    foreach (var damage in damages)
                    {
                        if (string.IsNullOrEmpty(damage.Type))
                        {
                            damage.Type = damageType;
                        }
                    }

                    mundaneWeapon.Damages.AddRange(damages);

                    if (mundaneWeapon.SecondaryHasAbilities)
                    {
                        var secondaryDamages    = specialAbility.Damages.Select(d => d.Clone()).ToArray();
                        var secondaryDamageType = mundaneWeapon.SecondaryDamages[0].Type;

                        foreach (var damage in secondaryDamages)
                        {
                            if (string.IsNullOrEmpty(damage.Type))
                            {
                                damage.Type = secondaryDamageType;
                            }
                        }

                        mundaneWeapon.SecondaryDamages.AddRange(secondaryDamages);
                    }
                }

                if (specialAbility.CriticalDamages.Any())
                {
                    var damageType = mundaneWeapon.CriticalDamages[0].Type;
                    foreach (var damage in specialAbility.CriticalDamages[mundaneWeapon.CriticalMultiplier])
                    {
                        if (string.IsNullOrEmpty(damage.Type))
                        {
                            damage.Type = damageType;
                        }
                    }

                    mundaneWeapon.CriticalDamages.AddRange(specialAbility.CriticalDamages[mundaneWeapon.CriticalMultiplier]);

                    if (mundaneWeapon.SecondaryHasAbilities)
                    {
                        foreach (var damage in specialAbility.CriticalDamages[mundaneWeapon.SecondaryCriticalMultiplier])
                        {
                            if (string.IsNullOrEmpty(damage.Type))
                            {
                                damage.Type = damageType;
                            }
                        }

                        mundaneWeapon.SecondaryCriticalDamages.AddRange(specialAbility.CriticalDamages[mundaneWeapon.SecondaryCriticalMultiplier]);
                    }
                }

                if (specialAbility.Name == SpecialAbilityConstants.Keen)
                {
                    mundaneWeapon.ThreatRange *= 2;
                }
            }

            return(mundaneWeapon);
        }