public IEnumerable <Skill> ApplySkillPointsAsRanks( IEnumerable <Skill> skills, HitPoints hitPoints, CreatureType creatureType, Dictionary <string, Ability> abilities, bool includeFirstHitDieBonus) { var points = GetTotalSkillPoints(creatureType, hitPoints.RoundedHitDiceQuantity, abilities[AbilityConstants.Intelligence], includeFirstHitDieBonus); var totalRanksAvailable = skills.Sum(s => s.RankCap - s.Ranks); if (points >= totalRanksAvailable) { return(MaxOutSkills(skills)); } var skillsWithAvailableRanks = skills.Where(s => !s.RanksMaxedOut); var creatureSkills = skillsWithAvailableRanks.Where(s => s.ClassSkill); var untrainedSkills = skillsWithAvailableRanks.Where(s => !s.ClassSkill); while (points > 0) { var skill = collectionsSelector.SelectRandomFrom(creatureSkills, untrainedSkills); var availableRanks = Math.Min(skill.RankCap - skill.Ranks, points); var rankRoll = RollHelper.GetRollWithMostEvenDistribution(1, availableRanks); var ranks = dice.Roll(rankRoll).AsSum(); skill.Ranks += ranks; points -= ranks; } return(skills); }
private void UpdateCreatureLanguages(Creature creature) { if (!creature.Languages.Any()) { return; } var languages = new List <string>(creature.Languages); var automaticLanguage = collectionSelector.SelectRandomFrom( TableNameConstants.Collection.LanguageGroups, CreatureConstants.Templates.HalfFiend + LanguageConstants.Groups.Automatic); languages.Add(automaticLanguage); var bonusLanguages = collectionSelector.SelectFrom( TableNameConstants.Collection.LanguageGroups, CreatureConstants.Templates.HalfFiend + LanguageConstants.Groups.Bonus); var quantity = Math.Min(2, creature.Abilities[AbilityConstants.Intelligence].Modifier); var availableBonusLanguages = bonusLanguages.Except(languages); if (availableBonusLanguages.Count() <= quantity && quantity > 0) { languages.AddRange(availableBonusLanguages); } while (quantity-- > 0 && availableBonusLanguages.Any()) { var bonusLanguage = collectionSelector.SelectRandomFrom(availableBonusLanguages); languages.Add(bonusLanguage); } creature.Languages = languages.Distinct(); }
private void ValidateRandomCreatureAndTemplate() { var randomCreatureName = collectionSelector.SelectRandomFrom(allCreatures); var randomTemplate = collectionSelector.SelectRandomFrom(allTemplates); stopwatch.Restart(); var verified = creatureVerifier.VerifyCompatibility(randomCreatureName, randomTemplate); stopwatch.Stop(); var message = $"Creature: {randomCreatureName}; Template: {randomTemplate}; Verified: {verified}"; Assert.That(stopwatch.Elapsed, Is.LessThan(timeLimit), message); }
private IEnumerable <Spell> GetRandomKnownSpellsForLevel(string creature, SpellQuantity spellQuantity, string caster, Alignment alignment, IEnumerable <string> domains) { var spellNames = GetSpellNamesForCaster(creature, caster, alignment, spellQuantity.Level, domains); var knownSpells = new HashSet <Spell>(); if (spellQuantity.Quantity >= spellNames.Count()) { foreach (var spellName in spellNames) { var spell = BuildSpell(spellName, spellQuantity.Level, caster); knownSpells.Add(spell); } return(knownSpells); } while (spellQuantity.Quantity > knownSpells.Count) { var spellName = collectionsSelector.SelectRandomFrom(spellNames); var spell = BuildSpell(spellName, spellQuantity.Level, caster); knownSpells.Add(spell); } var specialistSpellsForLevel = GetSpellNamesForFields(domains, spellQuantity.Level); var knownSpellNames = knownSpells.Select(s => s.Name); var unknownSpecialistSpells = specialistSpellsForLevel.Except(knownSpellNames); if (spellQuantity.HasDomainSpell && unknownSpecialistSpells.Any()) { while (spellQuantity.Quantity + 1 > knownSpells.Count) { var spellName = collectionsSelector.SelectRandomFrom(specialistSpellsForLevel); var spell = BuildSpell(spellName, spellQuantity.Level, caster); knownSpells.Add(spell); } } else if (spellQuantity.HasDomainSpell) { while (spellQuantity.Quantity + 1 > knownSpells.Count) { var spellName = collectionsSelector.SelectRandomFrom(spellNames); var spell = BuildSpell(spellName, spellQuantity.Level, caster); knownSpells.Add(spell); } } return(knownSpells); }
public void SelectRandomFrom_Weighted_ReturnsInnerResult() { var common = new[] { "common 1", "common 2" }; var uncommon = new[] { "uncommon 1", "uncommon 2" }; var rare = new[] { "rare 1", "rare 2" }; var veryRare = new[] { "very rare 1", "very rare 2" }; mockInnerSelector .Setup(s => s.SelectRandomFrom(common, uncommon, rare, veryRare)) .Returns("my result"); var result = proxy.SelectRandomFrom(common, uncommon, rare, veryRare); Assert.That(result, Is.EqualTo("my result")); }
public Alignment Generate(string creatureName) { var weightedAlignments = collectionSelector.ExplodeAndPreserveDuplicates(TableNameConstants.Collection.AlignmentGroups, creatureName); var randomAlignment = collectionSelector.SelectRandomFrom(weightedAlignments); return(new Alignment(randomAlignment)); }
private void UpdateCreatureAttacks(Creature creature) { var ghostAttacks = attacksGenerator.GenerateAttacks( CreatureConstants.Templates.Ghost, creature.Size, creature.Size, creature.BaseAttackBonus, creature.Abilities, creature.HitPoints.RoundedHitDiceQuantity); var manifestation = ghostAttacks.First(a => a.Name == "Manifestation"); var newAttacks = new List <Attack> { manifestation }; var amount = dice.Roll().d3().AsSum(); var availableAttacks = ghostAttacks.Except(newAttacks); while (newAttacks.Count < amount + 1) { var attack = collectionSelector.SelectRandomFrom(availableAttacks); newAttacks.Add(attack); } creature.Attacks = creature.Attacks.Union(newAttacks); }
public Item Generate(string power, string itemName, params string[] traits) { var possiblePowers = collectionsSelector.SelectFrom(TableNameConstants.Collections.Set.PowerGroups, itemName); var adjustedPower = PowerHelper.AdjustPower(power, possiblePowers); var tableName = string.Format(TableNameConstants.Percentiles.Formattable.POWERITEMTYPEs, adjustedPower, ItemTypeConstants.WondrousItem); var results = typeAndAmountPercentileSelector.SelectAllFrom(tableName); var matches = results.Where(r => r.Type == itemName); var result = collectionsSelector.SelectRandomFrom(matches); var item = BuildWondrousItem(itemName, traits); item.Magic.Bonus = result.Amount; return(item); }
public string GenerateFor(string itemType, IEnumerable <string> attributes, IEnumerable <string> traits) { if (itemType != ItemTypeConstants.Weapon && itemType != ItemTypeConstants.Armor) { throw new ArgumentException(itemType); } var attributesWithType = attributes.Union(new[] { itemType }); if (!AttributesAllowForSpecialMaterials(attributesWithType)) { throw new ArgumentException(string.Join(",", attributesWithType)); } if (!TraitsAllowForSpecialMaterials(attributesWithType, traits)) { throw new ArgumentException(string.Join(",", traits)); } var filteredSpecialMaterials = GetAllowedMaterials(attributesWithType); var allowedSpecialMaterials = filteredSpecialMaterials.Except(traits); var specialMaterial = collectionsSelector.SelectRandomFrom(allowedSpecialMaterials); return(specialMaterial); }
private string Replace(string source, string target, IEnumerable <string> replacements) { var replacement = collectionsSelector.SelectRandomFrom(replacements); var result = source.Replace(target, replacement); return(result); }
public IEnumerable <string> GenerateWith(string creature, Dictionary <string, Ability> abilities, IEnumerable <Skill> skills) { var languages = new List <string>(); var automaticLanguages = collectionsSelector.SelectFrom(TableNameConstants.Collection.LanguageGroups, creature + LanguageConstants.Groups.Automatic); languages.AddRange(automaticLanguages); var bonusLanguages = collectionsSelector.SelectFrom(TableNameConstants.Collection.LanguageGroups, creature + LanguageConstants.Groups.Bonus); var remainingBonusLanguages = bonusLanguages.Except(languages); var numberOfBonusLanguages = abilities[AbilityConstants.Intelligence].Modifier; if (IsInterpreter(skills)) { numberOfBonusLanguages = Math.Max(1, abilities[AbilityConstants.Intelligence].Modifier + 1); } if (numberOfBonusLanguages >= remainingBonusLanguages.Count()) { languages.AddRange(remainingBonusLanguages); return(languages); } while (numberOfBonusLanguages-- > 0 && remainingBonusLanguages.Any()) { var language = collectionsSelector.SelectRandomFrom(remainingBonusLanguages); languages.Add(language); } return(languages); }
public AdvancementSelection SelectRandomFor(string creature, CreatureType creatureType, string originalSize, string originalChallengeRating) { var advancements = typeAndAmountSelector.Select(TableNameConstants.TypeAndAmount.Advancements, creature); var randomAdvancement = collectionSelector.SelectRandomFrom(advancements); var selection = GetAdvancementSelection(creature, creatureType, originalSize, originalChallengeRating, randomAdvancement); return(selection); }
public Item Generate(string power, string itemName, params string[] traits) { var possiblePowers = collectionSelector.SelectFrom(TableNameConstants.Collections.Set.PowerGroups, itemName); var adjustedPower = PowerHelper.AdjustPower(power, possiblePowers); var tableName = string.Format(TableNameConstants.Percentiles.Formattable.POWERITEMTYPEs, adjustedPower, ItemTypeConstants.Potion); var results = typeAndAmountPercentileSelector.SelectAllFrom(tableName); var matches = results.Where(r => NameMatches(r.Type, itemName)); var result = collectionSelector.SelectRandomFrom(matches); return(GeneratePotion(result.Type, result.Amount, traits)); }
private void UpdateCreatureLanguages(Creature creature) { if (!creature.Languages.Any()) { return; } var automaticLanguage = collectionSelector.SelectRandomFrom( TableNameConstants.Collection.LanguageGroups, CreatureConstants.Templates.Lich + LanguageConstants.Groups.Automatic); creature.Languages = creature.Languages.Union(new[] { automaticLanguage }); }
private string GetCursedName(string itemName) { if (IsSpecificCursedItem(itemName)) { return(itemName); } var cursedItems = collectionsSelector.SelectFrom(TableNameConstants.Collections.Set.ItemGroups, CurseConstants.SpecificCursedItem); var cursedNames = new List <string>(); foreach (var cursedName in cursedItems) { var baseNames = collectionsSelector.SelectFrom(TableNameConstants.Collections.Set.ItemGroups, cursedName); if (baseNames.Contains(itemName)) { cursedNames.Add(cursedName); } } var name = collectionsSelector.SelectRandomFrom(cursedNames); return(name); }
private Good GenerateGood(TypeAndAmountSelection quantity) { var valueTableName = string.Format(TableNameConstants.Percentiles.Formattable.GOODTYPEValues, quantity.Type); var descriptionTableName = string.Format(TableNameConstants.Collections.Formattable.GOODTYPEDescriptions, quantity.Type); var valueSelection = typeAndAmountPercentileSelector.SelectFrom(valueTableName); var good = new Good(); good.Description = collectionSelector.SelectRandomFrom(descriptionTableName, valueSelection.Type); good.ValueInGold = valueSelection.Amount; return(good); }
public Item Generate(string power, string itemName, params string[] traits) { var staffName = GetStaffName(itemName); var powers = collectionsSelector.SelectFrom(TableNameConstants.Collections.Set.PowerGroups, staffName); var adjustedPower = PowerHelper.AdjustPower(power, powers); var tablename = string.Format(TableNameConstants.Percentiles.Formattable.POWERITEMTYPEs, adjustedPower, ItemTypeConstants.Staff); var selections = typeAndAmountPercentileSelector.SelectAllFrom(tablename); var matches = selections.Where(s => s.Type == staffName).ToList(); var selection = collectionsSelector.SelectRandomFrom(matches); return(GenerateStaff(selection.Type, selection.Amount, traits)); }
public Item Generate(string power, string itemName, params string[] traits) { var rodName = GetRodName(itemName); var powers = collectionsSelector.SelectFrom(TableNameConstants.Collections.Set.PowerGroups, rodName); var adjustedPower = PowerHelper.AdjustPower(power, powers); var tablename = string.Format(TableNameConstants.Percentiles.Formattable.POWERITEMTYPEs, adjustedPower, ItemTypeConstants.Rod); var results = typeAndAmountPercentileSelector.SelectAllFrom(tablename); var matches = results.Where(r => r.Type == rodName).ToList(); var match = collectionsSelector.SelectRandomFrom(matches); return(GenerateRod(match.Type, match.Amount, traits)); }
private string SelectRandomAndIncludeSkills(IEnumerable <string> foci, IEnumerable <Skill> skills) { var skillFoci = collectionsSelector.SelectFrom(TableNameConstants.Collection.FeatFoci, GroupConstants.Skills); var applicableSkillFoci = skillFoci.Intersect(foci); if (applicableSkillFoci.Any()) { var potentialSkillFoci = skills.Select(s => SkillConstants.Build(s.Name, s.Focus)); foci = applicableSkillFoci.Intersect(potentialSkillFoci); } if (!foci.Any()) { return(FeatConstants.Foci.NoValidFociAvailable); } return(collectionsSelector.SelectRandomFrom(foci)); }
private string GetRandomItemName(string itemType) { var itemNames = Enumerable.Empty <string>(); switch (itemType) { case ItemTypeConstants.AlchemicalItem: itemNames = AlchemicalItemConstants.GetAllAlchemicalItems(); break; case ItemTypeConstants.Armor: itemNames = ArmorConstants.GetAllArmorsAndShields(true); break; case ItemTypeConstants.Potion: itemNames = PotionConstants.GetAllPotions(true); break; case ItemTypeConstants.Ring: itemNames = RingConstants.GetAllRings(); break; case ItemTypeConstants.Rod: itemNames = RodConstants.GetAllRods(); break; case ItemTypeConstants.Scroll: itemNames = new[] { $"Scroll {Guid.NewGuid()}" }; break; case ItemTypeConstants.Staff: itemNames = StaffConstants.GetAllStaffs(); break; case ItemTypeConstants.Tool: itemNames = ToolConstants.GetAllTools(); break; case ItemTypeConstants.Wand: itemNames = new[] { $"Wand {Guid.NewGuid()}" }; break; case ItemTypeConstants.Weapon: itemNames = WeaponConstants.GetAllWeapons(true, true); break; case ItemTypeConstants.WondrousItem: itemNames = WondrousItemConstants.GetAllWondrousItems(); break; } var itemName = collectionSelector.SelectRandomFrom(itemNames); return(itemName); }
private SpecialAbility GenerateAbilityFrom(IEnumerable <SpecialAbility> availableAbilities, IEnumerable <string> tableNames) { var abilityName = string.Empty; do { var tableName = collectionsSelector.SelectRandomFrom(tableNames); abilityName = percentileSelector.SelectFrom(tableName); if (abilityName == "BonusSpecialAbility") { return new SpecialAbility { Name = abilityName } } ; } while (!availableAbilities.Any(a => a.Name == abilityName)); return(availableAbilities.First(a => a.Name == abilityName)); }
public T SelectRandomFrom <T>(IEnumerable <T> collection) { return(innerSelector.SelectRandomFrom(collection)); }
private List <Feat> PopulateFeatsRandomlyFrom( Dictionary <string, Ability> abilities, IEnumerable <Skill> skills, int baseAttackBonus, IEnumerable <Feat> preselectedFeats, IEnumerable <FeatSelection> sourceFeatSelections, int quantity, int casterLevel, IEnumerable <Attack> attacks) { var feats = new List <Feat>(); var chosenFeats = new List <Feat>(preselectedFeats); var chosenFeatSelections = new List <FeatSelection>(); var preselectedFeatSelections = GetSelectedSelections(sourceFeatSelections, preselectedFeats); chosenFeatSelections.AddRange(preselectedFeatSelections); var availableFeatSelections = new List <FeatSelection>(); var newAvailableFeatSelections = AddNewlyAvailableFeatSelections(availableFeatSelections, sourceFeatSelections, chosenFeatSelections, chosenFeats); availableFeatSelections.AddRange(newAvailableFeatSelections); while (quantity-- > 0 && availableFeatSelections.Any()) { var featSelection = collectionsSelector.SelectRandomFrom(availableFeatSelections); var preliminaryFocus = featFocusGenerator.GenerateFrom(featSelection.Feat, featSelection.FocusType, skills, featSelection.RequiredFeats, chosenFeats, casterLevel, abilities, attacks); if (preliminaryFocus == FeatConstants.Foci.NoValidFociAvailable) { quantity++; chosenFeatSelections.Add(featSelection); availableFeatSelections.Remove(featSelection); newAvailableFeatSelections = AddNewlyAvailableFeatSelections(availableFeatSelections, sourceFeatSelections, chosenFeatSelections, chosenFeats); availableFeatSelections.AddRange(newAvailableFeatSelections); continue; } var feat = new Feat(); var hasMatchingFeat = feats.Any(f => FeatsWithFociMatch(f, featSelection)); if (hasMatchingFeat) { feat = feats.First(f => FeatsWithFociMatch(f, featSelection)); } else { feat.Name = featSelection.Feat; feat.Frequency = featSelection.Frequency; feat.Power = featSelection.Power; feat.CanBeTakenMultipleTimes = featSelection.CanBeTakenMultipleTimes; feats.Add(feat); chosenFeats.Add(feat); } if (!FeatSelectionCanBeSelectedAgain(featSelection)) { chosenFeatSelections.Add(featSelection); availableFeatSelections.Remove(featSelection); } newAvailableFeatSelections = AddNewlyAvailableFeatSelections(availableFeatSelections, sourceFeatSelections, chosenFeatSelections, chosenFeats); availableFeatSelections.AddRange(newAvailableFeatSelections); if (!string.IsNullOrEmpty(preliminaryFocus)) { feat.Foci = feat.Foci.Union(new[] { preliminaryFocus }); } } return(feats); }
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); }
private Item SetPrototypeAttributes(Item prototype, string specificGearType) { var gear = prototype.Clone(); if (gear.Name == WeaponConstants.JavelinOfLightning) { gear.IsMagical = true; } else if (gear.Name == ArmorConstants.CastersShield) { var hasSpell = percentileSelector.SelectFrom <bool>(TableNameConstants.Percentiles.Set.CastersShieldContainsSpell); if (hasSpell) { var spellType = percentileSelector.SelectFrom(TableNameConstants.Percentiles.Set.CastersShieldSpellTypes); var spellLevel = spellGenerator.GenerateLevel(PowerConstants.Medium); var spell = spellGenerator.Generate(spellType, spellLevel); var formattedSpell = $"{spell} ({spellType}, {spellLevel})"; gear.Contents.Add(formattedSpell); } } var templateName = gear.Name; gear.Name = replacementSelector.SelectSingle(templateName); gear.Magic.SpecialAbilities = GetSpecialAbilities(specificGearType, templateName, prototype.Magic.SpecialAbilities); var tableName = string.Format(TableNameConstants.Collections.Formattable.SpecificITEMTYPEAttributes, specificGearType); gear.Attributes = collectionsSelector.SelectFrom(tableName, templateName); tableName = string.Format(TableNameConstants.Collections.Formattable.SpecificITEMTYPETraits, specificGearType); var traits = collectionsSelector.SelectFrom(tableName, templateName); foreach (var trait in traits) { gear.Traits.Add(trait); } if (gear.Attributes.Contains(AttributeConstants.Charged)) { gear.Magic.Charges = chargesGenerator.GenerateFor(specificGearType, templateName); } if (gear.Name == WeaponConstants.SlayingArrow || gear.Name == WeaponConstants.GreaterSlayingArrow) { var designatedFoe = collectionsSelector.SelectRandomFrom(TableNameConstants.Collections.Set.ReplacementStrings, ReplacementStringConstants.DesignatedFoe); var trait = $"Designated Foe: {designatedFoe}"; gear.Traits.Add(trait); } if (gear.IsMagical) { gear.Traits.Add(TraitConstants.Masterwork); } if (gear.ItemType == ItemTypeConstants.Armor) { return(GetArmor(gear)); } if (gear.ItemType == ItemTypeConstants.Weapon) { return(GetWeapon(gear)); } if (gear.Quantity == 0) { gear.Quantity = 1; } return(gear); }
public Magic GenerateWith(string creatureName, Alignment alignment, Dictionary <string, Ability> abilities, Equipment equipment) { var magic = new Magic(); var casters = typeAndAmountSelector.Select(TableNameConstants.TypeAndAmount.Casters, creatureName); if (!casters.Any()) { return(magic); } var caster = casters.First(); magic.Caster = caster.Type; magic.CasterLevel = caster.Amount; var spellAbility = collectionsSelector.SelectFrom(TableNameConstants.Collection.AbilityGroups, $"{magic.Caster}:Spellcaster").Single(); magic.CastingAbility = abilities[spellAbility]; var domainTypesAndAmounts = typeAndAmountSelector.Select(TableNameConstants.TypeAndAmount.SpellDomains, creatureName); var domains = new List <string>(); if (domainTypesAndAmounts.Any()) { var domainCount = domainTypesAndAmounts.First().Amount; var possibleDomains = domainTypesAndAmounts .Select(d => d.Type) .Except(domains); if (domainCount >= possibleDomains.Count()) { domains.AddRange(possibleDomains); } while (domains.Count < domainCount && possibleDomains.Any()) { var domain = collectionsSelector.SelectRandomFrom(possibleDomains); domains.Add(domain); } } magic.Domains = domains; magic = MakeSpells(creatureName, magic, alignment); if (equipment.Armor == null && equipment.Shield == null) { return(magic); } var arcaneSpellcasters = collectionsSelector.SelectFrom(TableNameConstants.Collection.CasterGroups, SpellConstants.Sources.Arcane); if (!arcaneSpellcasters.Contains(magic.Caster)) { return(magic); } if (equipment.Armor != null) { magic.ArcaneSpellFailure += GetArcaneSpellFailure(equipment.Armor); } if (equipment.Shield != null) { magic.ArcaneSpellFailure += GetArcaneSpellFailure(equipment.Shield); } return(magic); }
public void SelectRandomFromTable(string name, params string[] collection) { var entry = collectionsSelector.SelectRandomFrom("CollectionTable", name); Assert.That(new[] { entry }, Is.SubsetOf(collection)); }
private void GenerateAndAssertCreature() { var randomCreatureName = collectionSelector.SelectRandomFrom(allCreatures); GenerateAndAssertCreature(randomCreatureName); }