public void LightWeaponsMatchConstants() { var light = WeaponConstants.GetAllLightMelee(false, false); VerifyAttribute(light, AttributeConstants.Light); }
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); }