/// <summary>
        /// Calculates the market price of an armor or shield made of dragonhide.
        /// </summary>
        /// <exception cref="System.ArgumentNullException">Thrown when an argument is null.</exception>
        /// <exception cref="System.ComponentModel.InvalidEnumArgumentException">Thrown when an argument is a nonstandard enum.</exception>
        private static double GetBaseMarketPrice <E, I>(double basePrice, IEnchantmentAggregator <E, I> enchantmentAggregator, DragonhideColor color) where E : IEnchantment
            where I : IItem
        {
            if (null == enchantmentAggregator)
            {
                throw new ArgumentNullException(nameof(enchantmentAggregator), "Argument may not be null.");
            }
            double physicalCost = 2 * (basePrice + 150); // twice the masterwork cost

            // Dragonhide reduces the cost of energy resistance enchantments by 25%
            double energyResistanceEnchantmentDiscount = 0; // keep track of total discounts

            foreach (var enchantment in enchantmentAggregator.GetEnchantments().Where((ench) => ench is EnergyResistanceEnchantment))
            {
                switch (color)
                {
                case DragonhideColor.Black:
                case DragonhideColor.Copper:
                case DragonhideColor.Green:
                    if (enchantment is AcidResistance)
                    {
                        energyResistanceEnchantmentDiscount += 0.25 * enchantment.Cost;
                    }
                    break;

                case DragonhideColor.Silver:
                case DragonhideColor.White:
                    if (enchantment is ColdResistance)
                    {
                        energyResistanceEnchantmentDiscount += 0.25 * enchantment.Cost;
                    }
                    break;

                case DragonhideColor.Blue:
                case DragonhideColor.Bronze:
                    if (enchantment is ElectricityResistance)
                    {
                        energyResistanceEnchantmentDiscount += 0.25 * enchantment.Cost;
                    }
                    break;

                case DragonhideColor.Brass:
                case DragonhideColor.Gold:
                case DragonhideColor.Red:
                    if (enchantment is FireResistance)
                    {
                        energyResistanceEnchantmentDiscount += 0.25 * enchantment.Cost;
                    }
                    break;

                default:
                    throw new InvalidEnumArgumentException(nameof(color), (int)color, color.GetType());
                }
            }
            return(physicalCost - energyResistanceEnchantmentDiscount);
        }
        public void Shield_PlusFive_Enchant()
        {
            // Arrange
            var armorEnhancementBonus = Mock.Of <IModifierTracker>();
            var mockShieldBonusAgg    = new Mock <IArmorClassAggregator>();

            mockShieldBonusAgg.Setup(agg => agg.EnhancementBonuses)
            .Returns(armorEnhancementBonus);
            IArmorClassAggregator shieldBonus = mockShieldBonusAgg.Object;

            var hardnessEnhancementBonus = Mock.Of <IModifierTracker>();
            var mockHardnessAgg          = new Mock <IHardnessAggregator>();

            mockHardnessAgg.Setup(agg => agg.EnhancementBonuses)
            .Returns(hardnessEnhancementBonus);
            IHardnessAggregator hardness = mockHardnessAgg.Object;

            var hitPointsEnhancementBonus = Mock.Of <IModifierTracker>();
            var mockHitPointAgg           = new Mock <IHitPointsAggregator>();

            mockHitPointAgg.Setup(agg => agg.EnhancementBonuses)
            .Returns(hitPointsEnhancementBonus);
            IHitPointsAggregator hitPoints = mockHitPointAgg.Object;

            IEnchantmentAggregator <IShieldEnchantment, Shield> enchantments = null;

            var shield = new Mock <Shield>(MockBehavior.Loose, shieldBonus, hardness, hitPoints, enchantments)
            {
                CallBase = true
            }.Object;

            IShieldEnchantment enchantment = new EnhancementBonus(5);

            // Act
            enchantment.Enchant(shield);

            // Assert
            Mock.Get(armorEnhancementBonus)
            .Verify(ac => ac.Add(It.Is <Func <byte> >(calc => 5 == calc())),
                    "A +5 bonus was not applied to the shield's armor class bonus correctly.");
            Mock.Get(hardnessEnhancementBonus)
            .Verify(bhn => bhn.Add(It.Is <Func <byte> >(calc => 10 == calc())),
                    "A +10 bonus was not applied to the shield's hardness correctly.");
            Mock.Get(hitPointsEnhancementBonus)
            .Verify(hp => hp.Add(It.Is <Func <byte> >(calc => 50 == calc())),
                    "A +50 bonus was not applied to the shield's hit points correctly.");
        }
Beispiel #3
0
 /// <summary>
 /// Dependency injection constructor (used for testing).
 /// Initializes a new instance of the <see cref="T:Core.Domain.Items.Shields.Shield"/> class.
 /// </summary>
 /// <param name="shieldBonus">Tied to the ArmorClass property; cannot be null.</param>
 /// <param name="hardness">Tied to the Hardness property; cannot be null.</param>
 /// <param name="hitPoints">Tied to the HitPoints property; cannot be null.</param>
 /// <param name="enchantments">If this is null, this will assign a new instance of ShieldEnchantmentAggregator to the Enchantments property.</param>
 /// <exception cref="System.ArgumentNullException">Thrown when an argument is null.</exception>
 internal Shield(IArmorClassAggregator shieldBonus,
                 IHardnessAggregator hardness,
                 IHitPointsAggregator hitPoints,
                 IEnchantmentAggregator <IShieldEnchantment, Shield> enchantments)
 {
     _armorClass   = shieldBonus ?? throw new ArgumentNullException(nameof(shieldBonus), "Argument may not be null.");
     _hardness     = hardness ?? throw new ArgumentNullException(nameof(hardness), "Argument cannot be null.");
     _hitPoints    = hitPoints ?? throw new ArgumentNullException(nameof(hitPoints), "Argument cannot be null.");
     _enchantments = enchantments ?? new ShieldEnchantmentAggregator(this);
     // Adds shields bonus to character's armor class.
     this.OnApplied += (sender, e) => {
         e.Character?.ArmorClass?.ShieldBonuses?.Add(this.GetShieldBonus);
     };
     // Adds armor check penalty to skills
     this.OnApplied += (sender, e) => {
         foreach (var skill in e.Character?.Skills?.GetAllSkills() ?? Enumerable.Empty <ISkill>())
         {
             skill.Penalties?.Add(() => skill.ArmorCheckPenaltyApplies ? this.GetArmorCheckPenalty() : (byte)0);
         }
     };
 }
Beispiel #4
0
 /// <summary>
 /// Dependency injection constructor (used for testing).
 /// Initializes a new instance of the <see cref="T:Core.Domain.Items.Armor.Armor"/> class.
 /// </summary>
 /// <param name="armorClass">Tied to the ArmorClass property; cannot be null.</param>
 /// <param name="hardness">Tied to the Hardness property; cannot be null.</param>
 /// <param name="hitPoints">Tied to the HitPoints property; cannot be null.</param>
 /// <param name="enchantments">If this is null, this will assign a new instance of ArmorEnchantmentAggregator to the Enchantments property.</param>
 internal Armor(IArmorClassAggregator armorClass,
                IHardnessAggregator hardness,
                IHitPointsAggregator hitPoints,
                IEnchantmentAggregator <IArmorEnchantment, Armor> enchantments)
 {
     _armorClass   = armorClass ?? throw new ArgumentNullException(nameof(armorClass), "Argument may not be null.");
     _hardness     = hardness ?? throw new ArgumentNullException(nameof(hardness), "Argument may not be null.");
     _hitPoints    = hitPoints ?? throw new ArgumentNullException(nameof(hitPoints), "Argument may not be null.");
     _enchantments = enchantments ?? new ArmorEnchantmentAggregator(this);
     // Applies armor bonus to armor class
     this.OnApplied += (sender, e) => {
         e.Character?.ArmorClass?.ArmorBonuses?.Add(this.GetArmorBonus);
     };
     // Applies dex cap to AC
     this.OnApplied += (sender, e) => {
         e.Character?.ArmorClass?.MaxKeyAbilityScore?.Add(this.GetMaximumDexterityBonus);
     };
     // Applies armor check penalty to skills
     this.OnApplied += (sender, e) => {
         foreach (var skill in e.Character?.Skills?.GetAllSkills() ?? Enumerable.Empty <ISkill>())
         {
             skill.Penalties?.Add(() => skill.ArmorCheckPenaltyApplies ? this.GetArmorCheckPenalty() : (byte)0);
         }
     };
     // Applies movement penalties to movement speeds
     this.OnApplied += (sender, e) => {
         foreach (IMovement movement in e.Character?.MovementModes?.GetAll() ?? Enumerable.Empty <IMovement>())
         {
             movement.Penalties.Add(() => {
                 if (!movement.BaseSpeed.HasValue)
                 {
                     return(0);
                 }
                 var finalSpeed = Math.Floor((1f - this.SpeedPenalty) * movement.BaseSpeed.Value);
                 return(Convert.ToByte(movement.BaseSpeed.Value - finalSpeed));
             });
         }
     };
 }
        public void GetArmorBaseMarketPrice_NullEnchantments_Throws()
        {
            // Arrange
            double baseCost = 200;
            IEnchantmentAggregator <IArmorEnchantment, Core.Domain.Items.Armor.Armor> enchantments = null;
            var color = DragonhideColor.Black;

            // Act
            TestDelegate getPrice = () => Dragonhide.GetArmorBaseMarketPrice(baseCost, enchantments, color);

            // Assert
            Assert.Throws <ArgumentNullException>(getPrice);
        }
 /// <summary>
 /// Determines the market value for a Dragonhide shield.
 /// The cost is: base cost, plus masterwork cost, multiplied by two.
 /// </summary>
 /// <returns>The market value.</returns>
 /// <param name="basePrice">The base cost of the shield (including adjustments for size).</param>
 /// <param name="enchantments">The enchantments placed on the shield.</param>
 /// <param name="color">The color of the dragon's hide.</param>
 /// <exception cref="System.ArgumentNullException">Thrown when an argument is null.</exception>
 /// <exception cref="System.ComponentModel.InvalidEnumArgumentException">Thrown when an argument is a nonstandard enum.</exception>
 public static double GetShieldBaseMarketPrice(double basePrice, IEnchantmentAggregator <IShieldEnchantment, Shield> enchantments, DragonhideColor color)
 {
     return(GetBaseMarketPrice(basePrice, enchantments, color));
 }
 /// <summary>
 /// Determines the market value for Dragonhide armor.
 /// The cost is: base cost, plus masterwork cost, multiplied by two.
 /// </summary>
 /// <returns>The market value.</returns>
 /// <param name="basePrice">The base cost of the armor (including adjustments for size).</param>
 /// <param name="enchantments">The enchantments placed on the armor.</param>
 /// <param name="color">The color of the dragon's hide.</param>
 /// <exception cref="System.ArgumentNullException">Thrown when an argument is null.</exception>
 /// <exception cref="System.ComponentModel.InvalidEnumArgumentException">Thrown when an argument is a nonstandard enum.</exception>
 public static double GetArmorBaseMarketPrice(double basePrice, IEnchantmentAggregator <IArmorEnchantment, Armor.Armor> enchantments, DragonhideColor color)
 {
     return(GetBaseMarketPrice(basePrice, enchantments, color));
 }