Ejemplo n.º 1
0
        private DamageResult ResolveWeaponAttack(WeaponSystem weapon, int range, ScreenRating screenRating, int evasion = 0, int otherDRM = 0, Constants.DamageType damageTypeModifier = Constants.DamageType.None, AttackSpecialProperties attackPropertiesModifier = AttackSpecialProperties.None)
        {
            AttackSpecialProperties effectiveAttackProperties = weapon.FinalizeAttackProperties(attackPropertiesModifier);

            // Weapons with a hight TrackRating can ignore Evasion, offsetting up to the full Evasion DRM
            int totalDRM = weapon.FinalizeEvasionDRM(evasion) + otherDRM;

            // Weapons can ignore certain kinds of shields but not others
            int totalScreenRating = weapon.FinalizeScreenValue(screenRating, effectiveAttackProperties);

            Constants.DamageType effectiveDamageType = weapon.FinalizeDamageType(weapon.GetDamageType(), damageTypeModifier, effectiveAttackProperties.HasFlag(AttackSpecialProperties.Overrides_Weapon_DamageType));

            // Roll dice here
            this.Logger.LogInformation($"Attack roll! {weapon.SystemName} -- range {range} | screen {screenRating.ToString()} | net DRM {totalDRM} | {effectiveDamageType.ToString()}-type damage | rating {weapon.Rating}");

            /* "Basic" weapon behavior is to shoot like a non-penetrating beam:
             * 1D per Rating, diminishing with range
             * 1 damage on a 4 unless screened
             * 1 damage on a 5, always
             * 2 damage on a 6, unless double-screened -- then 1
             */
            DamageResult damageMatrix = FullThrustDieRolls.RollFTDamage(this.DiceUtility, weapon.GetAttackDice(), totalDRM, totalScreenRating, effectiveDamageType.HasFlag(Constants.DamageType.Penetrating));

            return(damageMatrix);
        }
Ejemplo n.º 2
0
        public void TestPenetratingDamageRollup_Screen1_DRM_Zero()
        {
            IDiceUtility roller = this.services.GetService <IDiceUtility>();

            FullThrustDieRolls.RollFTSuccesses(roller, 1, out IEnumerable <int> rolls);

            var units = new List <GameUnit>();
            var f     = GameEngineTestUtilities.GenerateTestFormation(1, "Test Formation", ref units);
            var fu    = f.Units.First();
            var u     = units[0];

            var result = f.RollManeuverSpeedAndEvasion(this.services, f.Orders.First(), f.FormationId, 1, speedDRM: 0, evasionDRM: 0);

            // Console.WriteLine($"{u.Name} rolls {result.SpeedSuccesses} for Speed and {result.EvasionSuccesses} for Evasion.");
            // Console.WriteLine("Testing penetrating damage versus Screen Rating 2...");
            var damageResult = FullThrustDieRolls
                               .RollFTDamage(
                new DiceNotationUtility(),
                numberOfDice: 20,
                drm: 0,
                targetScreenRating: 1,
                dealPenetrating: true);

            // Console.WriteLine($"Dealt a total of {damageResult.Standard} standard damage and {damageResult.Penetrating} penetrating damage.");
            Assert.IsNotNull(damageResult);

            int natural6sOnInitialRoll      = damageResult.StandardRolls.Count(r => r == 6);
            int natural5sOnInitialRoll      = damageResult.StandardRolls.Count(r => r == 5);
            int natural4sOnInitialRoll      = damageResult.StandardRolls.Count(r => r == 4);
            int natural6sOnPenetratingRolls = damageResult.PenetratingRolls.Count(r => r == 6);
            int natural5sOnPenetratingRolls = damageResult.PenetratingRolls.Count(r => r == 5);
            int natural4sOnPenetratingRolls = damageResult.PenetratingRolls.Count(r => r == 4);

            // Since ScreenRating is 1 and DRM is 0, 6s hit for 2 and penetrate; 5s hit for 1; and 4s miss.
            int expectedStandardDamage = (2 * natural6sOnInitialRoll) + natural5sOnInitialRoll + (0 * natural4sOnInitialRoll);

            // Penetrating damage ignores screens and DRM
            int expectedPenetratingDamage = (2 * natural6sOnPenetratingRolls) + natural5sOnPenetratingRolls + natural4sOnPenetratingRolls;

            Assert.AreEqual(expectedStandardDamage, damageResult.Standard);

            // Penetration dice all come from 6s in the original roll, OR ELSE from rerolls in the penetration pool
            Assert.AreEqual(damageResult.PenetratingRolls.Count - natural6sOnPenetratingRolls, natural6sOnInitialRoll);

            // Penetration dice are unaffected by DRM or screens
            Assert.AreEqual(expectedPenetratingDamage, damageResult.Penetrating);
        }
Ejemplo n.º 3
0
        public void TestPenetratingDamageRollup_Screen2_DRM_Minus_One()
        {
            IDiceUtility roller = this.services.GetService <IDiceUtility>();

            FullThrustDieRolls.RollFTSuccesses(roller, 1, out IEnumerable <int> rolls);

            var units = new List <GameUnit>();
            var f     = GameEngineTestUtilities.GenerateTestFormation(1, "Test Formation", ref units);
            var fu    = f.Units.First();
            var u     = units[0];

            var result = f.RollManeuverSpeedAndEvasion(services: this.services, formationOrders: f.Orders.First(), currentVolley: 1, formationId: f.FormationId, speedDRM: 0, evasionDRM: 0);

            // Console.WriteLine($"{u.Name} rolls {result.SpeedSuccesses} for Speed and {result.EvasionSuccesses} for Evasion.");
            // Console.WriteLine("Testing penetrating damage versus Screen Rating 2...");
            var damageResult = FullThrustDieRolls
                               .RollFTDamage(
                new DiceNotationUtility(),
                numberOfDice: 20,
                drm: -1,
                targetScreenRating: 2,
                dealPenetrating: true);

            // Console.WriteLine($"Dealt a total of {damageResult.Standard} standard damage and {damageResult.Penetrating} penetrating damage.");
            Assert.IsNotNull(damageResult);

            // Since ScreenRating is 2 and DRM is -1, only 6's hit (and they all penetrate).
            int natural6sOnInitialRoll           = damageResult.StandardRolls.Count(r => r == 6);
            int natural6sOnPenetratingRolls      = damageResult.PenetratingRolls.Count(r => r == 6);
            int natural4sAnd5sOnPenetratingRolls = damageResult.PenetratingRolls.Count(r => r == 4 || r == 5);

            Assert.AreEqual(natural6sOnInitialRoll, damageResult.Standard);
            Assert.IsTrue(damageResult.PenetratingRolls.Count >= natural6sOnInitialRoll);

            // Penetration dice all come from 6s in the original roll, OR ELSE from rerolls in the penetration pool
            Assert.AreEqual(damageResult.PenetratingRolls.Count - natural6sOnPenetratingRolls, natural6sOnInitialRoll);

            // Penetration dice are unaffected by DRM or screens
            var penetrationDamageCalc = (2 * natural6sOnPenetratingRolls) + natural4sAnd5sOnPenetratingRolls;

            Assert.AreEqual(penetrationDamageCalc, damageResult.Penetrating);
        }
Ejemplo n.º 4
0
        public ManeuverSuccessSet RollManeuverSpeedAndEvasion(IServiceProvider services, VolleyOrders formationOrders, int formationId, int currentVolley, int speedDRM = 0, int evasionDRM = 0)
        {
            var logger  = services.GetLogger();
            var roller  = services.GetService <IDiceUtility>();
            var builder = new StringBuilder();

            builder.Append($" -- [{this.FormationId}]{this.FormationName} rolls {formationOrders.SpeedDice}D for Speed: ");
            formationOrders.SpeedSuccesses = FullThrustDieRolls.RollFTSuccesses(roller, formationOrders.SpeedDice, out IEnumerable <int> speedRolls);
            builder.AppendLine($" -- {formationOrders.SpeedSuccesses}s ({string.Join(", ", speedRolls)})");

            builder.Append($" -- [{this.FormationId}]{this.FormationName} rolls {formationOrders.EvasionDice}D for Evasion: ");
            formationOrders.EvasionSuccesses = FullThrustDieRolls.RollFTSuccesses(roller, formationOrders.EvasionDice, out IEnumerable <int> evasionRolls);
            builder.AppendLine($" -- {formationOrders.EvasionSuccesses}s ({string.Join(", ", evasionRolls)})");

            logger.LogInformation(builder.ToString());

            return(new ManeuverSuccessSet()
            {
                FormationId = formationId, Volley = currentVolley, SpeedSuccesses = formationOrders.SpeedSuccesses, EvasionSuccesses = formationOrders.EvasionSuccesses
            });
        }