예제 #1
0
        public virtual List <Shoot> GenerateShoots(Model soldier, ShootingParams shootingParams)
        {
            List <Shoot> shoots = new List <Shoot>();

            var weapons = soldier.SelectShootingWeapons();

            if (weapons.Any())
            {
                foreach (var cweapon in weapons)
                {
                    var weapon = shootingParams.SuperchargeWeapons ? cweapon.SuperchargeProfile ?? cweapon : cweapon;

                    int count = weapon.GenerateShoots(shootingParams.Distance);

                    shoots.Add(new Shoot()
                    {
                        Attacker = soldier,
                        Weapon   = weapon,
                        Attacks  = count,
                    });
                }
            }

            return(shoots);
        }
예제 #2
0
        public virtual ShootingPhaseStats ShootingPhase(Unit target, ShootingParams shootingParams)
        {
            ShootingPhaseStats stats = new ShootingPhaseStats();

            var shoots = GenerateShoots(shootingParams);

            if (shoots.Any())
            {
                var impacts = ResolveShoots(shoots, shootingParams);
                if (impacts.Any())
                {
                    stats.Shoots += impacts.Count;
                    stats.Hits   += impacts.Count(i => i.Impacted);

                    var targetSoldiers = target.Soldiers.Where(s => s.W > 0);

                    ResolveWounds(impacts, targetSoldiers, shootingParams, out int wounds, out int generatedDamage, out int damage);

                    stats.Wounds          += wounds;
                    stats.GeneratedDamage += generatedDamage;
                    stats.Damage          += damage;

                    ResolveBearerWounds(impacts);
                }
            }

            return(stats);
        }
예제 #3
0
 public override Impact ImpactTest(Model attacker, ShootingParams shootingParams)
 {
     return(new Impact()
     {
         Attacker = attacker,
         Weapon = this,
         Impacted = true,
     });
 }
예제 #4
0
        public override int CalcDamage(Wound wound, Model target, ShootingParams shootingParams)
        {
            if (Range / 2 >= shootingParams.Distance)
            {
                return(CalcDamage(shootingParams, Damage * 2, DamageDice, DiceModes.Max));
            }

            return(base.CalcDamage(wound, target, shootingParams));
        }
예제 #5
0
        public override Impact ImpactTest(Model attacker, ShootingParams shootingParams)
        {
            var impact = base.ImpactTest(attacker, shootingParams);

            if (impact.CriticalFail)
            {
                impact.BearerDamage = BearerDamageTypes.Slain;
            }

            return(impact);
        }
예제 #6
0
        public override Impact ImpactTest(Model attacker, ShootingParams shootingParams)
        {
            if (Range / 2 >= shootingParams.Distance)
            {
                //+1 to impact at short range
                var nShootingParams = shootingParams.Clone();
                nShootingParams.ShootingModifiers++;

                return(base.ImpactTest(attacker, nShootingParams));
            }

            return(base.ImpactTest(attacker, shootingParams));
        }
예제 #7
0
        public virtual Impact ImpactTest(Model attacker, ShootingParams shootingParams)
        {
            bool impacted = CalcImpacts(attacker.BS, shootingParams, out int roll, out int rollModified);

            return(new Impact()
            {
                Attacker = attacker,
                Weapon = this,
                Impacted = impacted,
                Roll = roll,
                RollModified = rollModified,
            });
        }
예제 #8
0
        public virtual List <Impact> ResolveShoots(List <Shoot> shoots, ShootingParams shootingParams)
        {
            List <Impact> impacts = new List <Impact>();

            foreach (var shoot in shoots)
            {
                for (int i = 0; i < shoot.Attacks; i++)
                {
                    impacts.Add(shoot.Weapon.ImpactTest(shoot.Attacker, shootingParams));
                }
            }

            return(impacts);
        }
예제 #9
0
        public virtual List <Wound> WoundTest(int t, ShootingParams shootingParams)
        {
            List <Wound> wounds = new List <Wound>();

            int s = CalcStrength();

            bool wounded = CalcWounds(s, t, shootingParams, out int roll, out int rollModified);

            if (wounded)
            {
                Wound w = new Wound(this, rollModified, false);
                wounds.Add(w);
            }

            return(wounds);
        }
예제 #10
0
        public virtual List <Shoot> GenerateShoots(ShootingParams shootingParams)
        {
            List <Shoot> shoots = new List <Shoot>();

            var attackingSoldiers = this.Soldiers.Where(s => s.W > 0);

            if (attackingSoldiers.Any())
            {
                foreach (var soldier in attackingSoldiers)
                {
                    shoots.AddRange(GenerateShoots(soldier, shootingParams));
                }
            }

            return(shoots);
        }
예제 #11
0
        public static bool CalcWounds(int s, int t, ShootingParams shootingParams, out int roll, out int rollModified)
        {
            int toWoundRoll = CalcToWoundRoll(s, t);

            roll         = Dice.D6();
            rollModified = roll + shootingParams.WoundingModifiers;

            if (shootingParams.WoundingRerolls == 0 && roll != 1 && rollModified >= toWoundRoll)
            {
                return(true);
            }

            bool reroll = false;

            if (roll == 1 && shootingParams.WoundingRerollUnmodifiedOnes)
            {
                reroll = true;
            }
            else if (roll < toWoundRoll && shootingParams.WoundingRerollUnmodifiedFails)
            {
                reroll = true;
            }
            else if (rollModified == 1 && shootingParams.WoundingRerollOnes)
            {
                reroll = true;
            }
            else if (rollModified < toWoundRoll && shootingParams.WoundingRerollFails)
            {
                reroll = true;
            }

            if (reroll && shootingParams.WoundingRerolls > 0)
            {
                roll         = Dice.D6();
                rollModified = roll + shootingParams.WoundingModifiers;

                shootingParams.WoundingRerolls--;
            }

            if (roll != 1 && rollModified >= toWoundRoll)
            {
                return(true);
            }

            return(false);
        }
예제 #12
0
        public static bool CalcImpacts(int bs, ShootingParams shootingParams, out int roll, out int rollModified)
        {
            roll         = Dice.D6();
            rollModified = roll + shootingParams.ShootingModifiers;

            if (shootingParams.ShootingRerolls == 0)
            {
                return(roll != 1 && rollModified >= bs);
            }

            bool reroll = false;

            if (roll == 1 && shootingParams.ShootingRerollUnmodifiedOnes)
            {
                //Reroll ones before modifiers
                reroll = true;
            }
            else if (roll < bs && shootingParams.ShootingRerollUnmodifiedFails)
            {
                //Reroll fails before modifiers
                reroll = true;
            }
            else if (rollModified == 1 && shootingParams.ShootingRerollOnes)
            {
                //Reroll ones after modifiers
                reroll = true;
            }
            else if (rollModified < bs && shootingParams.ShootingRerollFails)
            {
                //Reroll fails after modifiers
                reroll = true;
            }

            if (reroll && shootingParams.ShootingRerolls > 0)
            {
                roll         = Dice.D6();
                rollModified = roll + shootingParams.ShootingModifiers;

                shootingParams.ShootingRerolls--;
            }

            return(roll != 1 && rollModified >= bs);
        }
예제 #13
0
 public virtual int CalcDamage(Wound wound, Model target, ShootingParams shootingParams)
 {
     return(CalcDamage(shootingParams, Damage, DamageDice, DiceModes.Sum));
 }
예제 #14
0
        private bool ReadShootingParams(out ShootingParams shootingParams)
        {
            StringBuilder sb = new StringBuilder();

            string distanceError          = "Write a valid distance number (positive integer)";
            string toHitModifiersError    = "Write a valid to hit modifiers number (integer)";
            string toHitRerollsError      = "Write a valid to hit number of rerolls (integer, -1 for all rolls)";
            string toWoundModifiersError  = "Write a valid to wound modifiers number (integer)";
            string toWoundRerollsError    = "Write a valid to wound number of rerolls (integer, -1 for all rolls)";
            string toDamageThresholdError = "Write a valid damage reroll threshold number (positive integer from 0 to 100)";
            string toDamageRerollsError   = "Write a valid damage number of rerolls (integer, -1 for all rolls)";

            if (!int.TryParse(txtSPDistance.Text, out int distance))
            {
                sb.AppendLine(distanceError);
            }
            else if (distance <= 0)
            {
                sb.AppendLine(distanceError);
            }

            if (!int.TryParse(txtSPToHitModifiers.Text, out int shootingModifiers))
            {
                sb.AppendLine(toHitModifiersError);
            }

            if (!int.TryParse(txtSPToHitRerolls.Text, out int shootingRerolls))
            {
                sb.AppendLine(toHitRerollsError);
            }
            else if (shootingRerolls < -1)
            {
                sb.AppendLine(toHitRerollsError);
            }

            if (!int.TryParse(txtSPToWoundModifiers.Text, out int woundingModifiers))
            {
                sb.AppendLine(toWoundModifiersError);
            }

            if (!int.TryParse(txtSPToWoundRerolls.Text, out int woundingRerolls))
            {
                sb.AppendLine(toWoundRerollsError);
            }
            else if (woundingRerolls < -1)
            {
                sb.AppendLine(toWoundRerollsError);
            }

            if (!int.TryParse(txtSPToDamageThreshold.Text, out int damageThreshold))
            {
                sb.AppendLine(toDamageThresholdError);
            }
            else if (damageThreshold < 0 || damageThreshold > 100)
            {
                sb.AppendLine(toDamageThresholdError);
            }

            if (!int.TryParse(txtSPToDamageRerolls.Text, out int damageRerolls))
            {
                sb.AppendLine(toDamageRerollsError);
            }
            else if (damageRerolls < -1)
            {
                sb.AppendLine(toDamageRerollsError);
            }

            if (sb.Length > 0)
            {
                MessageBox.Show(sb.ToString());

                shootingParams = null;

                return(false);
            }

            shootingParams = new ShootingParams()
            {
                Distance = distance,

                SuperchargeWeapons = cbSPSupercharge.Checked,
                OverKill           = cbSPOverkill.Checked,

                ShootingModifiers             = shootingModifiers,
                ShootingRerollUnmodifiedOnes  = cbSPToHitRerollUOnes.Checked,
                ShootingRerollUnmodifiedFails = cbSPToHitRerollUFails.Checked,
                ShootingRerollOnes            = cbSPToHitRerollOnes.Checked,
                ShootingRerollFails           = cbSPToHitRerollFails.Checked,
                ShootingRerolls = shootingRerolls,

                WoundingModifiers             = woundingModifiers,
                WoundingRerollUnmodifiedOnes  = cbSPToWoundRerollUOnes.Checked,
                WoundingRerollUnmodifiedFails = cbSPToWoundRerollUFails.Checked,
                WoundingRerollOnes            = cbSPToWoundRerollOnes.Checked,
                WoundingRerollFails           = cbSPToWoundRerollFails.Checked,
                WoundingRerolls = woundingRerolls,

                DamageReroll          = cbSPToDamageReroll.Checked,
                PercentToRerollDamage = damageThreshold,
                DamageRerolls         = damageRerolls,
            };

            return(true);
        }
예제 #15
0
        private void Test(UnitGen unitGenerator, ShootingParams shootingParams, int testCount)
        {
            TestResults.Text = "Testing...";

            StringBuilder tests = new StringBuilder();

            string attackerName = null;
            string defenderName = null;

            int attackerWounds = 0;
            int defenderWounds = 0;

            int totalModels       = 0;
            int totalModelsKilled = 0;

            int totalShoots          = 0;
            int totalHits            = 0;
            int totalWounds          = 0;
            int totalDamage          = 0;
            int totalGeneratedDamage = 0;
            int totalKills           = 0;

            int maxDamage = 0;

            for (int i = 0; i < testCount; i++)
            {
                //Set units
                var attacker = unitGenerator.GetAttacker();
                var defender = unitGenerator.GetDefender();

                //Get model names
                attackerName = attacker.Name;
                defenderName = defender.Name;

                //Get model wounds counters
                attackerWounds = attacker.Soldiers.Sum(s => s.W);
                defenderWounds = defender.Soldiers.Sum(s => s.W);

                //Do the shooting phase
                var stats = attacker.ShootingPhase(defender, shootingParams);

                //Refresh model wounds counters
                var attackerRemainWounds = attacker.Soldiers.Sum(s => s.W);
                var defenderRemainWounds = defender.Soldiers.Sum(s => s.W);

                var modelsKilledString = " ";
                if (defenderRemainWounds == 0)
                {
                    totalKills++;
                    modelsKilledString = "*";
                }

                //Models killed versus total models in unit
                var modelsKilled = defender.Soldiers.Count(s => s.W <= 0);
                var models       = defender.Soldiers.Count;
                totalModels       += models;
                totalModelsKilled += modelsKilled;

                totalShoots          += stats.Shoots;
                totalHits            += stats.Hits;
                totalWounds          += stats.Wounds;
                totalGeneratedDamage += stats.GeneratedDamage;
                totalDamage          += stats.Damage;

                if (stats.GeneratedDamage > maxDamage)
                {
                    maxDamage = stats.GeneratedDamage;
                }

                tests.AppendLine($"{stats.Shoots:000} shoots : {stats.HitPercentage:000.00}% of hits | {stats.Hits:000} hits : {stats.WoundPercentage:000.00}% of wounds | {stats.GeneratedDamage:00}/{defenderWounds:00} Damage done | {modelsKilledString} {modelsKilled:00}/{models:00} Kills | Attacker lost {attackerWounds - attackerRemainWounds:00} wounds");
            }

            TestResults.Text =
                $"{testCount} tests - {attackerName} vs {defenderName}\r\n\r\n" +
                $"Medimum stats by test\r\n\r\n" +
                $"{totalShoots / (float)testCount:000} shoots : {totalHits / (float)totalShoots * 100f:000.00}% of hits | {totalHits / (float)testCount:000} hits : {totalWounds / (float)totalHits * 100f:000.00}% of wounds | {totalDamage / testCount:00}/{defenderWounds:00} Damage done |   {totalKills / (float)testCount * 100:00.0}% Kills | {maxDamage:00} Maximum wounds done\r\n\r\n" +
                $"All tests detail\r\n\r\n" +
                $"{tests}";
        }
예제 #16
0
        public virtual void ResolveWounds(List <Impact> impacts, IEnumerable <Model> targets, ShootingParams shootingParams, out int generatedWounds, out int generatedDamage, out int damageDone)
        {
            generatedWounds = 0;
            generatedDamage = 0;
            damageDone      = 0;

            //Resolve wounds
            foreach (var impact in impacts.Where(i => i.Impacted))
            {
                //Get max T
                var maxT = targets
                           .Where(s => s.W > 0)
                           .OrderByDescending(s => s.T)
                           .Select(s => s.T)
                           .FirstOrDefault();

                if (maxT == 0)
                {
                    //No targets
                    break;
                }

                var wounds = impact.Weapon.WoundTest(maxT, shootingParams);
                if (wounds.Any())
                {
                    generatedWounds += wounds.Count;

                    //Find target model
                    var activeTarget = targets
                                       .Where(s => s.W > 0)
                                       .OrderBy(s => s.W)
                                       .FirstOrDefault();

                    foreach (var wound in wounds)
                    {
                        //Not saved
                        int damage = impact.Weapon.CalcDamage(wound, activeTarget, shootingParams);

                        generatedDamage += damage;

                        //Save roll
                        var saved = activeTarget.SaveTest(wound);
                        if (!saved)
                        {
                            damageDone += damage;

                            //Set damage to target
                            activeTarget.Damage(damage);
                        }
                    }
                }
            }
        }