Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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();
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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);
        }
Ejemplo n.º 5
0
        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"));
        }
Ejemplo n.º 6
0
        public Alignment Generate(string creatureName)
        {
            var weightedAlignments = collectionSelector.ExplodeAndPreserveDuplicates(TableNameConstants.Collection.AlignmentGroups, creatureName);
            var randomAlignment    = collectionSelector.SelectRandomFrom(weightedAlignments);

            return(new Alignment(randomAlignment));
        }
Ejemplo n.º 7
0
        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);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
        private string Replace(string source, string target, IEnumerable <string> replacements)
        {
            var replacement = collectionsSelector.SelectRandomFrom(replacements);
            var result      = source.Replace(target, replacement);

            return(result);
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
        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));
        }
Ejemplo n.º 14
0
        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 });
        }
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
0
        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);
        }
Ejemplo n.º 17
0
        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));
        }
Ejemplo n.º 18
0
        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));
        }
Ejemplo n.º 19
0
        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));
        }
Ejemplo n.º 20
0
        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);
        }
Ejemplo n.º 21
0
        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));
 }
Ejemplo n.º 23
0
        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);
        }
Ejemplo n.º 24
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);
        }
Ejemplo n.º 25
0
        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);
        }
Ejemplo n.º 26
0
        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);
        }
Ejemplo n.º 27
0
        public void SelectRandomFromTable(string name, params string[] collection)
        {
            var entry = collectionsSelector.SelectRandomFrom("CollectionTable", name);

            Assert.That(new[] { entry }, Is.SubsetOf(collection));
        }
Ejemplo n.º 28
0
        private void GenerateAndAssertCreature()
        {
            var randomCreatureName = collectionSelector.SelectRandomFrom(allCreatures);

            GenerateAndAssertCreature(randomCreatureName);
        }