/// <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."); }
/// <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); } }; }
/// <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)); }