public static AttackOutcome RunCombat(Character _attacker, Character _defender, double AttackRoll, double DefendRoll, Utilities.BodyParts?location)
        {
            AttackOutcome outcome = new AttackOutcome();

            _attacker.CombatStuff.aoForEnchantments = outcome;
            _defender.CombatStuff.aoForEnchantments = outcome;
            outcome.attackRoll = AttackRoll;
            outcome.defendRoll = DefendRoll;
            //this is to give the option of one-roll combat on the specific input of DefensiveRoll == -999.0

            /*
             * if (DefendRoll == -999.0)
             * {
             *  DefendRoll = 20 - AttackRoll;
             * }*/

            outcome.Attacker = _attacker;
            outcome.Defender = _defender;

            Weapon _attackerSelectedWeapon = _attacker.CombatStuff.CombatWeapon;
            Weapon _defenderSelectedWeapon = _defender.CombatStuff.CombatWeapon;
            Shield _attackerSelectedShield = _attacker.CombatStuff.CombatShield;
            Shield _defenderSelectedShield = _defender.CombatStuff.CombatShield;

            outcome.Notes.attackerWeaponName = _attackerSelectedWeapon.ItemName;
            outcome.Notes.defenderWeaponName = _defenderSelectedWeapon.ItemName;
            outcome.Notes.stun = -1 * EffectHolder.GetValidEffectsByEffect(_defender, EffectHolder.EffectType.Focus);

            double _attackerWeightFactor = GetWeightFactor(_attacker);
            double _defenderWeightFactor = GetWeightFactor(_defender);

            double _attackerStaminaFactor = GetStaminaFactor(_attacker);
            double _defenderStaminaFactor = GetStaminaFactor(_defender);
            //primary calculators
            double offensiveCalculator = (AttackRoll + _attacker.CombatStuff.CombatOB + _attackerSelectedWeapon.OffensiveBonus + _attackerSelectedShield.OffensiveBonus + EffectHolder.GetValidEffectsByEffect(_attacker, EffectHolder.EffectType.OB) + _attackerWeightFactor) * _attackerStaminaFactor;
            double defensiveCalculator = (DefendRoll + _defender.CombatStuff.CombatDB + _defenderSelectedWeapon.DefensiveBonus + _defenderSelectedShield.DefensiveBonus + EffectHolder.GetValidEffectsByEffect(_defender, EffectHolder.EffectType.DB) + _defenderWeightFactor) * _defenderStaminaFactor;

            foreach (Armor a in _attacker.Armor)
            {
                offensiveCalculator += a.OffensiveBonus;
            }
            foreach (Armor a in _defender.Armor)
            {
                defensiveCalculator += a.DefensiveBonus;
            }

            outcome.Notes.attackroll  = AttackRoll;
            outcome.Notes.attackValue = offensiveCalculator;
            outcome.Notes.defendRoll  = DefendRoll;
            outcome.Notes.defendValue = defensiveCalculator;

            EnchantmentUtilities.triggerAllEnchantmentsForChar(_attacker, new EnchantmentParameters()
            {
                triggerSource = EnchantmentUtilities.SourceTypes.Attack
            });
            EnchantmentUtilities.triggerAllEnchantmentsForChar(_defender, new EnchantmentParameters()
            {
                triggerSource = EnchantmentUtilities.SourceTypes.WasAttacked
            });

            //generate reflex
            double defenderReflex = CalculateReflex(_defender, defensiveCalculator);

            //adjust by a percentage if stamina is low
            defenderReflex = defenderReflex * _defenderStaminaFactor;

            outcome.Notes.reflex = defenderReflex;

            //generate blocking difficulty
            double attackerBlockingDifficulty = _attackerSelectedWeapon.BlockingDifficulty + EffectHolder.GetValidEffectsByEffect(_attacker, EffectHolder.EffectType.BlockingDifficulty) + 0.2 * offensiveCalculator;

            outcome.Notes.blockingDifficulty = attackerBlockingDifficulty;

            //apply 25% of blocking difficulty
            defensiveCalculator -= attackerBlockingDifficulty * 0.25;

            //generate block
            double defenderBlock = defensiveCalculator * (_defenderSelectedShield.Coverage + EffectHolder.GetValidEffectsByEffect(_defender, EffectHolder.EffectType.ShieldCoverage));

            outcome.Notes.block = defenderBlock;

            //apply rest of blocking difficulty
            defensiveCalculator -= attackerBlockingDifficulty * 0.75;

            //generate parry
            double defenderParry = defensiveCalculator * _defenderSelectedWeapon.ParryStrength / System.Math.Max(_attackerSelectedWeapon.ParryBreak, 0.01);

            outcome.Notes.parryBreak    = _attackerSelectedWeapon.ParryBreak;
            outcome.Notes.parryStrength = _defenderSelectedWeapon.ParryStrength;
            outcome.Notes.parry         = defenderParry;
            outcome.Notes.defendValueAfterBlockingDifficulty = defensiveCalculator;


            //perform dodge
            if (defenderReflex > 0)
            {
                offensiveCalculator -= defenderReflex;
            }

            //if the attack has been reduced to 0, it was dodged
            if (offensiveCalculator <= 0)
            {
                outcome.Othertext  = Utilities.AttackResultType.Miss;
                outcome.HitCaliber = offensiveCalculator;
                return(outcome);
            }

            outcome.Notes.attackAfterReflex = offensiveCalculator;

            //perform block
            if (defenderBlock > 0)
            {
                offensiveCalculator -= defenderBlock;
            }

            //if the attack has been reduced to 0, it was blocked
            if (offensiveCalculator <= 0)
            {
                outcome.Othertext  = Utilities.AttackResultType.Block;
                outcome.HitCaliber = offensiveCalculator;
                return(outcome);
            }

            outcome.Notes.attackAfterBlock = offensiveCalculator;

            //perform parry
            if (defenderParry > 0)
            {
                offensiveCalculator -= defenderParry;
            }

            //if the attack has been reduced to 0, it was parried
            if (offensiveCalculator <= 0)
            {
                outcome.Othertext  = Utilities.AttackResultType.Parry;
                outcome.HitCaliber = offensiveCalculator;
                return(outcome);
            }

            outcome.Notes.attackAfterParry = offensiveCalculator;
            if (location == null)
            {
                Utilities.FindCritLocation(outcome);
            }
            else
            {
                outcome.HitLocation = (Utilities.BodyParts)location;
            }

            //otherwise, attacker hit! do damage/armor calculation
            Dictionary <Utilities.DamageType, Double> tempDamageValues = new Dictionary <Utilities.DamageType, double>();

            foreach (Utilities.DamageType dt in _attackerSelectedWeapon.DamageTypes.Keys)
            {
                tempDamageValues.Add(dt, _attackerSelectedWeapon.DamageTypes[dt]);
            }
            foreach (Utilities.DamageType dt in Enum.GetValues(typeof(Utilities.DamageType)))
            {
                double addedDamage = EffectHolder.GetValidEffectsByEffectAndDamageType(_attacker, EffectHolder.EffectType.WeaponDamage, dt);
                if (addedDamage != 0)
                {
                    if (tempDamageValues.ContainsKey(dt))
                    {
                        tempDamageValues[dt] += addedDamage;
                    }
                    else
                    {
                        tempDamageValues.Add(dt, addedDamage);
                    }
                }
            }
            foreach (Utilities.DamageType dt in tempDamageValues.Keys)
            {
                Double strikeAmountForDamageType = offensiveCalculator * tempDamageValues[dt];
                outcome.HitStrength             = outcome.HitStrength + strikeAmountForDamageType;
                outcome.Notes.damageBeforeArmor = outcome.HitStrength;
                //actually percentage of damage that will go through
                double damageResistance = 1.0 - EffectHolder.GetValidEffectsByEffectAndDamageType(_defender, EffectHolder.EffectType.DamageResistance, null);
                damageResistance -= EffectHolder.GetValidEffectsByEffectAndDamageType(_defender, EffectHolder.EffectType.DamageResistance, dt);
                foreach (Armor arm in _defender.Armor)
                {
                    if (arm.CoveredAreas.Contains(outcome.HitLocation) && arm.DamageResistanceTypes.ContainsKey(dt))
                    {
                        //subtraction because a lower percentage of the damage will get through
                        damageResistance -= (arm.DamageResistanceTypes[dt]);
                    }
                }
                outcome.DamageTypes.Add(dt, Math.Max(0, (strikeAmountForDamageType * damageResistance)));
            }

            double generalDamageReduction     = EffectHolder.GetValidEffectsByEffectAndDamageType(_defender, EffectHolder.EffectType.DamageReduction, null);
            double totalDamageBeforeReduction = outcome.TotalStrikeAmountFromAllTypes();

            //weird things happen if this is less than or equal to zero
            if (totalDamageBeforeReduction > 0)
            {
                foreach (Utilities.DamageType dt in tempDamageValues.Keys)
                {
                    //the amount of damage that will be prevented
                    outcome.DamageTypes[dt] -= generalDamageReduction * (outcome.DamageTypes[dt] / totalDamageBeforeReduction);
                    outcome.DamageTypes[dt] -= EffectHolder.GetValidEffectsByEffectAndDamageType(_defender, EffectHolder.EffectType.DamageReduction, dt);
                    foreach (Armor arm in _defender.Armor)
                    {
                        if (arm.CoveredAreas.Contains(outcome.HitLocation) && arm.DamageReductionTypes.ContainsKey(dt))
                        {
                            outcome.DamageTypes[dt] -= (arm.DamageReductionTypes[dt]);
                        }
                    }
                    if (outcome.DamageTypes[dt] < 0)
                    {
                        outcome.DamageTypes[dt] = 0;
                    }
                }
            }



            outcome.Notes.damageAfterArmor = outcome.TotalStrikeAmountFromAllTypes();

            outcome.Othertext  = Utilities.AttackResultType.Hit;
            outcome.HitCaliber = offensiveCalculator;


            CritCalculator.CalculateCrit(outcome);

            EnchantmentUtilities.triggerAllEnchantmentsForChar(_attacker, new EnchantmentParameters()
            {
                triggerSource = EnchantmentUtilities.SourceTypes.PostAttack
            });
            EnchantmentUtilities.triggerAllEnchantmentsForChar(_defender, new EnchantmentParameters()
            {
                triggerSource = EnchantmentUtilities.SourceTypes.PostWasAttacked
            });

            return(outcome);
        }
Ejemplo n.º 2
0
        private void button1_Click(object sender, EventArgs e)
        {
            if (!Utilities.ValidateComboBox(cboBoxChar1.Text))
            {
                return;
            }
            if (!Utilities.ValidateComboBox(cboBoxChar2.Text))
            {
                return;/*
                        * if (!Utilities.ValidateComboBox(cboBoxWeapon1.Text))
                        * return;
                        * if (!Utilities.ValidateComboBox(cboBoxWeapon2.Text))
                        * return;*/
            }
            Character char1 = Utilities.getCharacterFromXmlOrCombatHolderByString(cboBoxChar1.Text);

            if (!CombatHolder._inCombatChars.Contains(char1))
            {
                char1.HitPoints = CombatScripts.GetBaseHealth(char1);
                char1.Stamina   = CombatScripts.GetBaseStamina(char1);
            }
            Character char2 = Utilities.getCharacterFromXmlOrCombatHolderByString(cboBoxChar2.Text);

            if (!CombatHolder._inCombatChars.Contains(char1))
            {
                char2.HitPoints = CombatScripts.GetBaseHealth(char2);
                char2.Stamina   = CombatScripts.GetBaseStamina(char2);
            }
            Character CharCopy1 = Utilities.GetSameCharWithCurrentState(char1);
            Character CharCopy2 = Utilities.GetSameCharWithCurrentState(char2);

            CharCopy1.CombatStuff.CombatOB     = Utilities.ParseDoubleFromDangerousString(txtBoxOffensiveBonus.Text);
            CharCopy1.CombatStuff.CombatWeapon = char1.Weapons.Find(A => A.ItemName == cboBoxWeapon1.Text);
            CharCopy1.CombatStuff.CombatShield = char1.Shields.Find(A => A.ItemName == cboBoxShield1.Text);
            if (CharCopy1.CombatStuff.CombatShield == null)
            {
                CharCopy1.CombatStuff.CombatShield = new Shield();
            }


            CharCopy2.CombatStuff.CombatDB     = Utilities.ParseDoubleFromDangerousString(txtBoxDefensiveBonus.Text);
            CharCopy2.CombatStuff.CombatWeapon = char2.Weapons.Find(A => A.ItemName == cboBoxWeapon2.Text);
            CharCopy2.CombatStuff.CombatShield = char2.Shields.Find(A => A.ItemName == cboBoxShield2.Text);
            if (CharCopy2.CombatStuff.CombatShield == null)
            {
                CharCopy2.CombatStuff.CombatShield = new Shield();
            }
            if (checkBoxStartup.Checked)
            {
                EnchantmentUtilities.triggerAllEnchantmentsForChar(CharCopy1, new EnchantmentParameters()
                {
                    triggerSource = EnchantmentUtilities.SourceTypes.CombatEntry
                });
                EnchantmentUtilities.triggerAllEnchantmentsForChar(CharCopy2, new EnchantmentParameters()
                {
                    triggerSource = EnchantmentUtilities.SourceTypes.CombatEntry
                });
            }
            _outcome            = CombatScripts.RunCombat(Utilities.GetSameCharWithCurrentState(CharCopy1), Utilities.GetSameCharWithCurrentState(CharCopy2), Utilities.ParseDoubleFromDangerousString(txtBoxOffensiveRoll.Text), Utilities.ParseDoubleFromDangerousString(txtBoxDefensiveRoll.Text), null);
            txtBoxCrit.Text     = _outcome.Othertext.ToString();
            txtBoxDamage.Text   = Convert.ToString(0);
            lblHitCaliber.Text  = Convert.ToString(0);
            lblHitStrength.Text = Convert.ToString(0);
            if (_outcome.Othertext.ToString() == "Hit")
            {
                lblHitCaliber.Text  = "Hit Caliber: " + _outcome.HitCaliber.ToString();
                lblHitStrength.Text = "Hit Strength: " + _outcome.HitStrength.ToString();
                double damage = _outcome.TotalStrikeAmountFromAllTypes();
                txtBoxDamage.Text = Convert.ToString(damage);
                txtBoxCrit.Text   = _outcome.HitLocation.ToString();
                AttackOutcome cumulative = new AttackOutcome();
                for (int i = 0; i < 1000; i++)
                {
                    //calculate the same crit every time
                    Utilities.FindCritLocation(_outcome);
                    CritCalculator.CalculateCrit(_outcome);
                    //store it in a different place so it doesnt get reset
                    cumulative.bleed          += _outcome.bleed;
                    cumulative.harm           += _outcome.harm;
                    cumulative.disorientation += _outcome.disorientation;
                    cumulative.impairment     += _outcome.impairment;
                    cumulative.ko             += _outcome.ko;
                    cumulative.trauma         += _outcome.trauma;
                }

                Console.WriteLine("Harm: " + Convert.ToDouble(cumulative.harm) / 1000);
                Console.WriteLine("Bleed: " + Convert.ToDouble(cumulative.bleed) / 1000);
                Console.WriteLine("Disorientation: " + Convert.ToDouble(cumulative.disorientation) / 1000);
                Console.WriteLine("Impairment: " + Convert.ToDouble(cumulative.impairment) / 1000);
                Console.WriteLine("Trauma: " + Convert.ToDouble(cumulative.trauma) / 1000);
                Console.WriteLine("KO: " + Convert.ToDouble(cumulative.ko) / 1000);

                rtbAverageResults.Text  = "";
                rtbAverageResults.Text += "Harm: " + Convert.ToDouble(cumulative.harm) / 1000 + "\n";
                rtbAverageResults.Text += "Bleed: " + Convert.ToDouble(cumulative.bleed) / 1000 + "\n";
                rtbAverageResults.Text += "Disorientation: " + Convert.ToDouble(cumulative.disorientation) / 1000 + "\n";
                rtbAverageResults.Text += "Impairment: " + Convert.ToDouble(cumulative.impairment) / 1000 + "\n";
                rtbAverageResults.Text += "Trauma: " + Convert.ToDouble(cumulative.trauma) / 1000 + "\n";
                rtbAverageResults.Text += "KO: " + Convert.ToDouble(cumulative.ko) / 1000 + "\n";
            }
            if (chkBoxGraph.Checked)
            {
                AttackChart frmCreator = new AttackChart(Utilities.GetSameCharWithCurrentState(CharCopy1), Utilities.GetSameCharWithCurrentState(CharCopy2));
                frmCreator.Show();
            }
        }