static public Animal BuildAnimal(Dice dice, string terrainType, string animalClassName = null, int evolutionRolls = 0)
        {
            //Options
            var selectedTerrainType = TerrainTypeList.Single(x => x.Name == terrainType);
            var terrainPenalty      = 0;

            if (animalClassName == null)
            {
                var animalClassNotes = dice.ChooseWithOdds(selectedTerrainType.AnimalClasses);
                animalClassName = animalClassNotes.AnimalClass;
                terrainPenalty  = animalClassNotes.Penalty;
            }
            else
            {
                var animalClassNotes = selectedTerrainType.AnimalClasses.SingleOrDefault(ac => ac.AnimalClass == animalClassName);
                if (animalClassNotes == null)
                {
                    terrainPenalty = -5; //What is it doing here?
                }
                else
                {
                    terrainPenalty = animalClassNotes.Penalty;
                }
            }
            var animalClass = AnimalClassList.Single(x => x.Name == animalClassName);

            //Type
            var result = new Animal()
            {
                TerrainType = selectedTerrainType.Name, AnimalClass = animalClassName, EvolutionRolls = evolutionRolls
            };
            var movement = dice.ChooseByRoll(selectedTerrainType.MovementChart, "D6");

            result.Movement      = !string.IsNullOrWhiteSpace(animalClass.Movement) ? animalClass.Movement : movement.Movement;
            result.InitiativeDM += animalClass.InitiativeDM;

            //Starting Skills
            foreach (var skill in animalClass.Skills)
            {
                if (skill.ScoreSpecified)
                {
                    result.Skills.Add(skill.Name, skill.Score);
                }
                else
                {
                    result.Skills.Increase(skill.Name, skill.Bonus);
                }
            }

            //Class features
            if (animalClass.Features != null)
            {
                foreach (var feature in animalClass.Features)
                {
                    result.Features.Add(feature.Text);
                }
            }

            //Diet
            var diet = dice.ChooseWithOdds(animalClass.Diets);

            result.Diet = diet.Diet;
            if (diet.Skills != null)
            {
                foreach (var skill in diet.Skills)
                {
                    if (skill.ScoreSpecified)
                    {
                        result.Skills.Add(skill.Name, skill.Score);
                    }
                    else
                    {
                        result.Skills.Increase(skill.Name, skill.Bonus);
                    }
                }
            }

            foreach (var att in diet.Attribute)
            {
                result.Increase(att.Name, dice.D(att.Bonus));
            }

            var weaponDM = 0;

            switch (result.Diet)
            {
            case "Carnivore":
                result.InitiativeDM += 1;
                weaponDM             = 8;
                break;

            case "Omnivore":
                weaponDM = 4;
                break;

            case "Herbivore":
                result.InitiativeDM += -1;
                weaponDM             = -6;
                break;
            }

            //Behavior
            var behaviorMeta = dice.ChooseByRoll(diet.Behaviors, "1D");
            var behavior     = BehaviorList.Single(x => x.Name == behaviorMeta.Behavior);

            result.Behavior      = behaviorMeta.Behavior;
            result.Attack        = behavior.Attack.ToIntOrNull();
            result.Flee          = behavior.Flee.ToIntOrNull();
            result.InitiativeDM += behavior.InitiativeDM;

            if (result.BehaviorCount == 1)
            {//subtract the reaction to make it act like a DM
                result.Attack -= behaviorMeta.Reaction;
                result.Flee   -= behaviorMeta.Reaction;
            }
            else
            {
                var shortList     = diet.Behaviors.Where(x => x.Behavior != behaviorMeta.Behavior).ToList();
                var behaviorMeta2 = dice.ChooseByRoll(shortList, "1D5");
                result.SecondaryBehavior = behaviorMeta2.Behavior;
            }

            AddBehavior(result, behavior, dice);

            result.QuirkRolls += dice.D("D6") == 6 ? 1 : 0;

            //We do this in a loop because each chart can add rolls to other charts
            while (result.QuirkRolls > 0 || result.EvolutionRolls > 0 || result.PhysicalSkills > 0 || result.SocialSkills > 0 || result.EvolutionSkills > 0)
            {
                //Evolution Rolls
                while (result.EvolutionRolls > 0)
                {
                    result.EvolutionRolls -= 1;
                    if (dice.D(2) == 0)
                    {
                        RollOnChart(result, animalClass.Chart.Single(x => x.Name == "AdditionalSkills"), dice, $"1D6+{result.EvolutionDM}");
                    }
                    else
                    {
                        RollOnChart(result, animalClass.Chart.Single(x => x.Name == "OtherBenefits"), dice, $"1D6+{result.EvolutionDM}");
                    }
                }

                //Skill Rolls

                while (result.PhysicalSkills > 0)
                {
                    result.PhysicalSkills -= 1;
                    RollOnChart(result, animalClass.Chart.Single(x => x.Name == "PhysicalSkills"), dice);
                }

                while (result.SocialSkills > 0)
                {
                    result.SocialSkills -= 1;
                    RollOnChart(result, animalClass.Chart.Single(x => x.Name == "SocialSkills"), dice);
                }

                while (result.EvolutionSkills > 0)
                {
                    result.EvolutionSkills -= 1;
                    RollOnChart(result, animalClass.Chart.Single(x => x.Name == "EvolutionSkills"), dice);
                }

                //Quirk Rolls
                while (result.QuirkRolls > 0)
                {
                    result.QuirkRolls -= 1;
                    RollOnChart(result, animalClass.Chart.Single(x => x.Name == "Quirks"), dice, "2D");
                }
            }

            //Size
            var sizeRoll = (dice.D(selectedTerrainType.SizeDM) + dice.D(movement.SizeDM) + dice.D(2, 6)).Limit(1, 13);
            var size     = s_Templates.SizeTable.Single(sizeRoll);

            result.Size     = sizeRoll;
            result.WeightKG = size.WeightKG;

            //Attributes
            result.Strength  += dice.D(size.Strength) + terrainPenalty;
            result.Dexterity += dice.D(size.Dexterity) + terrainPenalty;
            result.Endurance += dice.D(size.Endurance) + terrainPenalty;
            result.Pack      += dice.D(2, 6) + terrainPenalty;
            result.Instinct  += dice.D(2, 6) + terrainPenalty;

            if (dice.D(6) + terrainPenalty >= 5)
            {
                result.Intelligence += 1;
            }

            //Weapons
            var baseDamage = s_Templates.DamageTable.Last(x => result.Strength >= x.MinValue).Damage;

            var weapon = s_Templates.WeaponTable.Single((dice.D("2D6") + weaponDM).Limit(1, 20));

            if (weapon.Weapon != "None")
            {
                result.Weapons.Add(new Weapon()
                {
                    Name = weapon.Weapon, Damage = (baseDamage + weapon.Bonus) + "d6"
                });
            }

            if (result.Weapons.Count > 0)
            {
                result.Skills.Add("Melee"); //always have melee if you have any weapons. Page 23
            }
            //Armor
            result.Armor += s_Templates.ArmorTable.Single(dice.D(2, 6)).Armor;

            //Bonus skills
            if (result.Skills.Count > 0)
            {
                var bonusSkills = dice.D(1, 6);
                dice.Choose(result.Skills).Level += 1;
            }

            //Run post-scripts
            foreach (var script in result.PostScripts)
            {
                RunScript(result, dice, script);
            }
            result.PostScripts.Clear();

            //Finishing touches
            result.NumberEncountered = s_Templates.NumberTable.Last(x => result.Pack.Limit(0, 15) >= x.MinValue).Number;

            result.Strength     = Math.Max(result.Strength, 0);
            result.Dexterity    = Math.Max(result.Dexterity, 0);
            result.Endurance    = Math.Max(result.Endurance, 0);
            result.Pack         = Math.Max(result.Pack, 0);
            result.Instinct     = Math.Max(result.Instinct, 0);
            result.Intelligence = Math.Max(result.Intelligence, 0);
            result.Armor        = Math.Max(result.Armor, 0);

            return(result);
        }
Beispiel #2
0
        static public Animal BuildAnimal(string terrainType, string animalType)
        {
            var dice = new Dice();

            var selectedTerrainType = TerrainTypeList.Single(x => x.Name == terrainType);
            var selectedAnimalType  = AnimalTypeList.Single(x => x.Name == animalType);


            //Type
            var result = new Animal()
            {
                TerrainType = selectedTerrainType.Name, AnimalType = selectedAnimalType.Name
            };
            var behaviorName = (selectedAnimalType.Option.Single((dice.D(selectedTerrainType.TypeDM) + dice.D(2, 6)).Limit(1, 13))).Behavior;
            var behavior     = selectedAnimalType.Behavior.Single(x => x.Name == behaviorName);

            result.Behavior = behaviorName;
            var movement = selectedTerrainType.Option.Single(dice.D(6));

            //Size
            var sizeRoll = (dice.D(selectedTerrainType.SizeDM) + dice.D(movement.SizeDM) + dice.D(2, 6)).Limit(1, 13);
            var size     = s_Templates.SizeTable.Single(sizeRoll);

            result.Size     = sizeRoll;
            result.Movement = movement.Movement;
            result.WeightKG = size.WeightKG;

            //Attributes
            result.Strength  = dice.D(size.Strength);
            result.Dexterity = dice.D(size.Dexterity);
            result.Endurance = dice.D(size.Endurance);
            result.Pack      = dice.D(2, 6);
            result.Instinct  = dice.D(2, 6);

            if (behaviorName == "Killer")
            {
                if (dice.D(2) == 1)
                {
                    result.Strength += 4;
                }
                else
                {
                    result.Dexterity += 4;
                }
            }


            var intOdds = dice.D(100); //Each point of instinct gives a 10% change of intelligence 1 and a 1% chance of intelligence 2

            if (result.Instinct >= intOdds)
            {
                result.Intelligence = 2;
            }
            else if ((result.Instinct * 10) >= intOdds)
            {
                result.Intelligence = 1;
            }

            if (behavior.Attribute != null)
            {
                foreach (var item in behavior.Attribute)
                {
                    int bonus = item.Add;
                    switch (item.Name)
                    {
                    case "Strength": result.Strength += bonus; break;

                    case "Dexterity": result.Dexterity += bonus; break;

                    case "Endurance": result.Endurance += bonus; break;

                    case "Intelligence": result.Intelligence += bonus; break;

                    case "Instinct": result.Instinct += bonus; break;

                    case "Pack": result.Pack += bonus; break;

                    default: throw new System.Exception("Unkonw attribute " + item.Name);
                    }
                }
            }

            //Skills
            var basicTraining = new List <string>()
            {
                "Survival", "Recon", "Athletics", "Melee"
            };

            if (behavior.Skill != null)
            {
                foreach (var item in behavior.Skill)
                {
                    basicTraining.Add(item.Name);
                }
            }

            var skillPicks = dice.D(6) + result.InstinctDM;

            for (int i = 0; i < skillPicks; i++)
            {
                result.Skills.Increase(dice.Choose(basicTraining), 1);
            }


            //Base skills added at level 0 if you don't already have them
            result.Skills.Add("Survival");
            result.Skills.Add("Recon");
            result.Skills.Add("Athletics");

            //Weapons
            var baseDamage = (int)s_Templates.DamageTable.Last(x => result.Strength >= x.MinValue).Damage;

            var weapon = s_Templates.WeaponTable.Single((dice.D(2, 6) + (int)selectedAnimalType.WeaponDM).Limit(1, 13));

            if (weapon.Weapon != "None")
            {
                result.Weapons.Add(new Weapon()
                {
                    Name = weapon.Weapon, Damage = (baseDamage + int.Parse(weapon.Bonus)) + "d6"
                });
            }

            if (selectedAnimalType.Name == "Scavenger" && !(result.Weapons.Any(x => x.Name.Contains("Teeth"))))
            {
                result.Weapons.Add(new Weapon()
                {
                    Name = "Teeth", Damage = baseDamage + "d6"
                });
            }

            result.NumberEncountered = s_Templates.NumberTable.Last(x => result.Pack.Limit(0, 15) >= x.MinValue).Number;
            result.Attack            = behavior.Attack;
            result.Flee = behavior.Flee;

            //Armor
            result.Armor = s_Templates.ArmorTable.Single(dice.D(2, 6)).Armor;

            return(result);
        }