public static Tuple <List <AttackOutcome>, List <Effect> > castSpell(Character caster, Character target, Spell s, double spellPower, double defensePower)
        {
            Tuple <List <AttackOutcome>, List <Effect> > ret = new Tuple <List <AttackOutcome>, List <Effect> >(new List <AttackOutcome>(), new List <Effect>());

            spellPower += EffectHolder.GetValidEffectsByEffect(caster, EffectHolder.EffectType.SpellBonus);
            foreach (Effect eff in s.SpellEffects.Keys)
            {
                Effect effMultiplied = new Effect(eff.effectTypes,
                                                  eff.effectStrength + s.SpellEffects[eff].Item1 * spellPower,
                                                  eff.effectLength + (int)Math.Round(s.SpellEffects[eff].Item2 * spellPower),
                                                  eff.deterioration + s.SpellEffects[eff].Item3 * spellPower);
                effMultiplied.effectTag = eff.effectTag;
                ret.Item2.Add(effMultiplied);
            }

            foreach (Weapon weap in s.SpellWeapons.Keys)
            {
                Weapon save = caster.CombatStuff.CombatWeapon;
                caster.CombatStuff.CombatWeapon = Utilities.GetWeaponByName(weap.ItemName);

                AttackOutcome outcome = CombatScripts.RunCombat(caster.MakeDeepCopy(), target, s.SpellWeapons[weap] + spellPower, defensePower, null);
                outcome.Attacker.CombatStuff.attackResultsForDisplay = new List <List <string> >();
                outcome.Defender.CombatStuff.defendResultsForDisplay = new List <List <string> >();
                ret.Item1.Add(outcome);

                caster.CombatStuff.CombatWeapon = save;
            }


            return(ret);
        }
 public static void IndexAttacks()
 {
     lock (IndexedAttacks)
     {
         foreach (AttackOutcome ao in MostRecentAttacks)
         {
             while (ao.attackUUID == "" || IndexedAttacks.ContainsKey(ao.attackUUID))
             {
                 ao.attackUUID = Utilities.RandomString(8);
             }
             AttackOutcome attackcopy = new AttackOutcome();
             attackcopy.Attacker    = Utilities.GetSameCharWithCurrentState(ao.Attacker);
             attackcopy.Defender    = Utilities.GetSameCharWithCurrentState(ao.Defender);
             attackcopy.attackRoll  = ao.attackRoll;
             attackcopy.defendRoll  = ao.defendRoll;
             attackcopy.HitLocation = ao.HitLocation;
             attackcopy.Othertext   = ao.Othertext;
             attackcopy.perception  = attackcopy.Attacker.Skills.PerceptionSkill + (int)(attackcopy.Attacker.Statistics.Intelligence / 3.0);
             IndexedAttacks.Add(ao.attackUUID, new Tuple <AttackOutcome, List <List <double> > >(attackcopy, null));
             while (ao.defenceUUID == "" || IndexedAttacks.ContainsKey(ao.defenceUUID))
             {
                 ao.defenceUUID = Utilities.RandomString(8);
             }
             AttackOutcome defendcopy = new AttackOutcome();
             defendcopy.Attacker    = Utilities.GetSameCharWithCurrentState(ao.Attacker);
             defendcopy.Defender    = Utilities.GetSameCharWithCurrentState(ao.Defender);
             defendcopy.attackRoll  = ao.attackRoll;
             defendcopy.defendRoll  = ao.defendRoll;
             defendcopy.HitLocation = ao.HitLocation;
             defendcopy.Othertext   = ao.Othertext;
             defendcopy.perception  = defendcopy.Defender.Skills.PerceptionSkill + (int)(defendcopy.Defender.Statistics.Intelligence / 3.0);
             IndexedAttacks.Add(ao.defenceUUID, new Tuple <AttackOutcome, List <List <double> > >(defendcopy, null));
         }
     }
 }
        //this is what happens when you click the 'Attack' button. The method name is an inside joke.
        private void followTheTaco_Click(object sender, EventArgs e)
        {
            double offenseRoll = 0.0;
            double defendRoll  = 0.0;

            Double.TryParse(txtBoxOffensiveRoll.Text, out offenseRoll);
            Double.TryParse(txtBoxDefensiveRoll.Text, out defendRoll);

            Character _defender = _canAttack.Find(Ch => Ch.CombatStuff.CombatName == comboBox1.Text);

            if (_attacker.Weapons.Any(A => A.ItemName == comboBoxAttackerWeapon.Text))
            {
                _attacker.CombatStuff.CombatWeapon = _attacker.Weapons.Find(A => A.ItemName == comboBoxAttackerWeapon.Text);
            }
            else
            {
                _attacker.CombatStuff.CombatWeapon = Utilities.GetWeaponByName(comboBoxAttackerWeapon.Text);
            }
            if (_defender.Weapons.Any(A => A.ItemName == comboBoxDefenderWeapon.Text))
            {
                _defender.CombatStuff.CombatWeapon = _defender.Weapons.Find(A => A.ItemName == comboBoxDefenderWeapon.Text);
            }
            else
            {
                _defender.CombatStuff.CombatWeapon = Utilities.GetWeaponByName(comboBoxDefenderWeapon.Text);
            }

            _outcome            = new AttackOutcome();
            _outcome.Attacker   = _attacker;
            _outcome.Defender   = _defender;
            _outcome.attackRoll = offenseRoll;
            _outcome.defendRoll = defendRoll;

            _parentForm.AddToAttacks(_outcome);
            SingleAttack frmRemover = this;

            frmRemover.Hide();
        }
        private void FOLLOWTHETACO_Click(object sender, EventArgs e)
        {
            List <AttackOutcome> followedTacos = new List <AttackOutcome>();

            foreach (AttackOutcome tacoToFollow in allAttacks)
            {
                AttackOutcome followedTaco = CombatScripts.RunCombat(tacoToFollow.Attacker, tacoToFollow.Defender, tacoToFollow.attackRoll, tacoToFollow.defendRoll, null);


                followedTaco.Attacker.CombatStuff.AttackNotes = followedTaco.Notes;
                followedTaco.Defender.CombatStuff.DefendNotes = followedTaco.Notes;

                followedTacos.Add(followedTaco);
            }

            CombatScripts.fatigueCharactersAndRecordCombat(followedTacos);

            foreach (AttackOutcome Whack in followedTacos)
            {
                CombatScripts.applyAttackOutcome(Whack);
            }

            EffectHolder.ClearUselessEffects();
            CombatHolder.MoveAttackingCharsToHasAttackedChars();
            if (CombatHolder._masterOfDeclarations != null)
            {
                CombatHolder._masterOfDeclarations.UpdateRTB();
            }
            CombatHolder.updateCombatDeclarations();
            AfterCrits frmCreator = new AfterCrits();

            frmCreator.Show();

            Master_Attacker frmCloser = this;

            frmCloser.Hide();
        }
        public static void applyAttackOutcome(AttackOutcome Whack)
        {
            Whack.Attacker.CombatStuff.attackResultsForDisplay.Insert(0, Utilities.translateAttackOutcomeToDisplayStrings(Whack, Whack.attackUUID));
            Whack.Defender.CombatStuff.defendResultsForDisplay.Insert(0, Utilities.translateAttackOutcomeToDisplayStrings(Whack, Whack.defenceUUID));
            Character Whackee = CombatHolder._inCombatChars.Find(Ch => Ch.CombatStuff.CombatName == Whack.Defender.CombatStuff.CombatName);

            //this can happen in some enchantment cases
            if (Whackee == null)
            {
                return;
            }

            Whackee.HitPoints = Whackee.HitPoints - Whack.harm;
            Effect bleed = new Effect(EffectHolder.EffectType.Regeneration, Whack.bleed * -1, Whack.bleed, -1);

            bleed.effectTag = EffectHolder.EffectTag.Bleed;
            Effect trauma = new Effect(EffectHolder.EffectType.Focus, Whack.trauma * -1, Whack.trauma, -1);

            trauma.effectTag = EffectHolder.EffectTag.Trauma;
            bool   doPermanantImpairment = Whackee.CharTypeTag != "" && Whackee.CharTypeTag != null;
            Effect impairment            = new Effect(EffectHolder.EffectType.OB, Whack.impairment * -1, -1, 0);

            impairment.effectTypes.Add(EffectHolder.EffectType.DB);
            impairment.effectTag = EffectHolder.EffectTag.NerveImpairment;
            Effect disorientation = new Effect(EffectHolder.EffectType.OB, Whack.disorientation * -1, Whack.disorientation, 1);

            disorientation.effectTypes.Add(EffectHolder.EffectType.DB);
            disorientation.effectTag = EffectHolder.EffectTag.Disorientation;
            Effect KO = new Effect(EffectHolder.EffectType.KO, Whack.ko, Whack.ko, 0.02);

            EffectHolder.CreateEffect(disorientation, Whackee, false);
            EffectHolder.CreateEffect(bleed, Whackee, false);
            EffectHolder.CreateEffect(trauma, Whackee, false);
            EffectHolder.CreateEffect(impairment, Whackee, false);
            EffectHolder.CreateEffect(KO, Whackee, false);
        }
 public void AddToAttacks(AttackOutcome toAdd)
 {
     allAttacks.Add(toAdd);
 }
        private void runSingleAttack()
        {
            clearDedPeople();
            if (leftSide.Count == 0 || rightSide.Count == 0)
            {
                return;
            }
            Character attackingChar = new Character();
            Character toAttackChar  = new Character();
            bool      thereIsACharThatHasNotAttacked = false;
            bool      thereIsAnAttackingChar         = false;

            ifThisThenLeftAttacksNext = !ifThisThenLeftAttacksNext;
            foreach (Character c in leftSide.Keys)
            {
                if (!leftSide[c])
                {
                    thereIsACharThatHasNotAttacked = true;
                    break;
                }
            }
            foreach (Character c in rightSide.Keys)
            {
                if (!rightSide[c])
                {
                    thereIsACharThatHasNotAttacked = true;
                    break;
                }
            }
            if (!thereIsACharThatHasNotAttacked)
            {
                EffectHolder.ProcAndDecayEffectsForSingleChar(rightSide.Keys.Last());
                EffectHolder.ProcAndDecayEffectsForSingleChar(leftSide.Keys.Last());
                clearDedPeople();
                //c# really does make you do it this way. Iteration through a dictionary is hard for some reason
                List <Character> temp = new List <Character>();
                foreach (Character c in leftSide.Keys)
                {
                    temp.Add(c);
                }
                foreach (Character c in temp)
                {
                    leftSide[c] = false;
                }
                temp.Clear();
                foreach (Character c in rightSide.Keys)
                {
                    temp.Add(c);
                }
                foreach (Character c in temp)
                {
                    rightSide[c] = false;
                }
                if (leftSide.Count == 0 || rightSide.Count == 0)
                {
                    return;
                }
            }
            if (ifThisThenLeftAttacksNext)
            {
                foreach (Character c in leftSide.Keys)
                {
                    if (!leftSide[c])
                    {
                        attackingChar          = c;
                        thereIsAnAttackingChar = true;
                        leftSide[c]            = true;
                        break;
                    }
                }
                toAttackChar = rightSide.Keys.Last();
            }
            else
            {
                foreach (Character c in rightSide.Keys)
                {
                    if (!rightSide[c])
                    {
                        attackingChar          = c;
                        thereIsAnAttackingChar = true;
                        rightSide[c]           = true;
                        break;
                    }
                }
                toAttackChar = leftSide.Keys.Last();
            }
            if (!thereIsAnAttackingChar)
            {
                return;
            }
            AttackOutcome ao = CombatScripts.RunCombat(attackingChar, toAttackChar, Math.Round(r.NextDouble() * 20), Math.Round(r.NextDouble() * 20), null);


            if (ao.Othertext.ToString() == "Hit")
            {
                toAttackChar.HitPoints = toAttackChar.HitPoints - ao.harm;
                Effect bleed        = new Effect(EffectHolder.EffectType.Regeneration, ao.bleed * -1, -1, 0);
                Effect focus        = new Effect(EffectHolder.EffectType.Focus, ao.trauma * -1, -1, 0);
                Effect impairmentOB = new Effect(EffectHolder.EffectType.OB, ao.impairment * -1, -1, 0);
                Effect impairmentDB = new Effect(EffectHolder.EffectType.DB, ao.impairment * -1, -1, 0);
                Effect OB           = new Effect(EffectHolder.EffectType.OB, ao.disorientation * -1, ao.disorientation, 1);
                Effect DB           = new Effect(EffectHolder.EffectType.DB, ao.disorientation * -1, ao.disorientation, 1);
                EffectHolder.CreateEffect(OB, toAttackChar, false);
                EffectHolder.CreateEffect(DB, toAttackChar, false);
                EffectHolder.CreateEffect(bleed, toAttackChar, false);
                EffectHolder.CreateEffect(focus, toAttackChar, false);
                EffectHolder.CreateEffect(impairmentOB, toAttackChar, false);
                EffectHolder.CreateEffect(impairmentDB, toAttackChar, false);
                EffectHolder.ClearUselessEffects();
            }

            if (doPrinting)
            {
                richTextBoxBig.Text += attackingChar.CombatStuff.CombatName + " -> " + toAttackChar.CombatStuff.CombatName + " " + " " + ao.Othertext.ToString() + "\n";
            }

            clearDedPeople();
        }
        public static List <List <Double> > CreateDataPoints(AttackOutcome ao,
                                                             bool doTotalDamage,
                                                             bool doHarm,
                                                             bool doBleed,
                                                             bool doDisorientation,
                                                             bool doImpairment,
                                                             bool doTrauma,
                                                             bool doKO,
                                                             Utilities.BodyParts?location,
                                                             int perception)
        {
            List <List <Double> > gridOfPoints = new List <List <double> >();

            for (double j = ao.defendRoll - perception; j <= ao.defendRoll + perception; j++)
            {
                List <double> rowOfPoints = new List <double>();
                for (double i = ao.attackRoll - perception; i <= ao.attackRoll + perception; i++)
                {
                    AttackOutcome oneOutcome = CombatScripts.RunCombat(Utilities.GetSameCharWithCurrentState(ao.Attacker), Utilities.GetSameCharWithCurrentState(ao.Defender), i, j, location);
                    double        Damage     = 0.0;
                    switch (oneOutcome.Othertext.ToString())
                    {
                    case "Miss":
                        Damage = -1;
                        break;

                    case "Block":
                        Damage = -2;
                        break;

                    case "Parry":
                        Damage = -3;
                        break;

                    case "Hit":
                        if (doTotalDamage)
                        {
                            Damage += oneOutcome.TotalStrikeAmountFromAllTypes();
                        }
                        if (doHarm)
                        {
                            Damage += oneOutcome.harm;
                        }
                        if (doBleed)
                        {
                            Damage += oneOutcome.bleed;
                        }
                        if (doDisorientation)
                        {
                            Damage += oneOutcome.disorientation;
                        }
                        if (doImpairment)
                        {
                            Damage += oneOutcome.impairment;
                        }
                        if (doTrauma)
                        {
                            Damage += oneOutcome.trauma;
                        }
                        if (doTrauma)
                        {
                            Damage += oneOutcome.ko;
                        }
                        if (ao.Othertext != Utilities.AttackResultType.Hit)
                        {
                            Damage = 99;
                        }
                        break;

                    default:
                        throw new Exception("WTF did you give me?");
                    }
                    rowOfPoints.Add(Damage);
                }
                gridOfPoints.Add(rowOfPoints);
            }
            return(gridOfPoints);
        }
        public static void CalculateCrit(AttackOutcome CritSource)
        {
            double harm;
            double bleed;
            double heavybleed;
            double disorientation;
            double impairment;
            double trauma;
            double ko;

            double harmCumulative           = CritSource.TotalStrikeAmountFromAllTypes() * EffectHolder.GetValidEffectsByEffect(CritSource.Attacker, EffectHolder.EffectType.InflictHarm);
            double bleedCumulative          = CritSource.TotalStrikeAmountFromAllTypes() * EffectHolder.GetValidEffectsByEffect(CritSource.Attacker, EffectHolder.EffectType.InflictBleed);
            double heavybleedCumulative     = CritSource.TotalStrikeAmountFromAllTypes() * EffectHolder.GetValidEffectsByEffect(CritSource.Attacker, EffectHolder.EffectType.InflictBleed);
            double disorientationCumulative = CritSource.TotalStrikeAmountFromAllTypes() * EffectHolder.GetValidEffectsByEffect(CritSource.Attacker, EffectHolder.EffectType.InflictDisorientation);
            double impairmentCumulative     = CritSource.TotalStrikeAmountFromAllTypes() * EffectHolder.GetValidEffectsByEffect(CritSource.Attacker, EffectHolder.EffectType.InflictImpairment);
            double traumaCumulative         = CritSource.TotalStrikeAmountFromAllTypes() * EffectHolder.GetValidEffectsByEffect(CritSource.Attacker, EffectHolder.EffectType.InflictTrauma);
            double koCumulative             = CritSource.TotalStrikeAmountFromAllTypes() * EffectHolder.GetValidEffectsByEffect(CritSource.Attacker, EffectHolder.EffectType.InflictKO);
            bool   locationMatters;

            foreach (Utilities.DamageType critType in CritSource.DamageTypes.Keys)
            {
                switch (critType)
                {
                case Utilities.DamageType.Slash:
                    harm            = 0.3;
                    bleed           = 0.6;
                    heavybleed      = 0.3;
                    disorientation  = 0.3;
                    impairment      = 0.3;
                    trauma          = 0.2;
                    ko              = 0.2;
                    locationMatters = true;
                    break;

                case Utilities.DamageType.Pierce:
                    harm            = 0.3;
                    bleed           = 0.3;
                    heavybleed      = 0.6;
                    disorientation  = 0.1;
                    impairment      = 0.2;
                    trauma          = 0.2;
                    ko              = 0.1;
                    locationMatters = true;
                    break;

                case Utilities.DamageType.Crush:
                    harm            = 0.2;
                    bleed           = 0.0;
                    heavybleed      = 0.1;
                    disorientation  = 0.4;
                    impairment      = 0.4;
                    trauma          = 0.4;
                    ko              = 0.4;
                    locationMatters = true;
                    break;

                case Utilities.DamageType.Heat:
                    harm            = 0.7;
                    bleed           = -0.1;
                    heavybleed      = 0.0;
                    disorientation  = 0.5;
                    impairment      = 0.3;
                    trauma          = 0.3;
                    ko              = 0.0;
                    locationMatters = true;
                    break;

                case Utilities.DamageType.Cold:
                    harm            = 0.2;
                    bleed           = -0.3;
                    heavybleed      = -0.3;
                    disorientation  = 0.5;
                    impairment      = 0.8;
                    trauma          = 0.3;
                    ko              = 0.3;
                    locationMatters = true;
                    break;

                case Utilities.DamageType.Shock:
                    harm            = 0.6;
                    bleed           = 0.0;
                    heavybleed      = 0.0;
                    disorientation  = 0.4;
                    impairment      = 0.5;
                    trauma          = 0.6;
                    ko              = 0.4;
                    locationMatters = false;
                    break;

                case Utilities.DamageType.Mental:
                    harm            = 0;
                    bleed           = 0;
                    heavybleed      = 0.1;
                    disorientation  = 1.0;
                    impairment      = 0.0;
                    trauma          = 1.0;
                    ko              = 0.3;
                    locationMatters = false;
                    break;

                case Utilities.DamageType.Impact:
                    harm            = 0.8;
                    bleed           = 0;
                    heavybleed      = 0.1;
                    disorientation  = 0.5;
                    impairment      = 0.3;
                    trauma          = 0.6;
                    ko              = 0.6;
                    locationMatters = false;
                    break;

                case Utilities.DamageType.Soul:
                    harm            = 1.0;
                    bleed           = 0;
                    heavybleed      = 0.0;
                    disorientation  = 0.0;
                    impairment      = 0.7;
                    trauma          = 0.2;
                    ko              = 0.4;
                    locationMatters = false;
                    break;

                default:
                    throw new Exception("No valid Critical Type found.");
                }
                if (locationMatters)
                {
                    switch (CritSource.HitLocation)
                    {
                    case Utilities.BodyParts.Head:
                        harm           += 0.2;
                        bleed          += 0.0;
                        heavybleed     += 0.0;
                        disorientation += 0.2;
                        impairment     += 0.1;
                        trauma         += 0.2;
                        ko             += 0.2;
                        break;

                    case Utilities.BodyParts.Gut:
                        harm           += 0.4;
                        bleed          += 0.1;
                        heavybleed     += 0.2;
                        disorientation += 0.0;
                        impairment     += 0.0;
                        trauma         += 0.1;
                        ko             += 0.1;
                        break;

                    case Utilities.BodyParts.Groin:
                        harm           += 0.0;
                        bleed          += 0.0;
                        heavybleed     += 0.0;
                        disorientation += 0.5;
                        impairment     += 0.1;
                        trauma         += 0.5;
                        ko             += 0.0;
                        break;

                    case Utilities.BodyParts.Chest:
                        harm           += 0.3;
                        bleed          += 0.1;
                        heavybleed     += 0.2;
                        disorientation += 0.0;
                        impairment     += 0.0;
                        trauma         += 0.0;
                        ko             += 0.2;
                        break;

                    case Utilities.BodyParts.Neck:
                        harm           += 0.2;
                        bleed          += 0.2;
                        heavybleed     += 0.4;
                        disorientation += 0.0;
                        impairment     += 0.0;
                        trauma         += 0.0;
                        ko             += 0.3;
                        break;

                    default:
                        harm           += 0.0;
                        bleed          += 0.1;
                        heavybleed     += 0.1;
                        disorientation += 0.0;
                        impairment     += 0.2;
                        trauma         += 0.0;
                        ko             += 0.0;
                        break;
                    }
                }
                harmCumulative           += harm * CritSource.DamageTypes[critType];
                bleedCumulative          += bleed * CritSource.DamageTypes[critType];
                heavybleedCumulative     += heavybleed * CritSource.DamageTypes[critType];
                disorientationCumulative += disorientation * CritSource.DamageTypes[critType];
                impairmentCumulative     += impairment * CritSource.DamageTypes[critType];
                traumaCumulative         += trauma * CritSource.DamageTypes[critType];
                koCumulative             += ko * CritSource.DamageTypes[critType];
            }
            //ADD THIS FOR SOME  RANDOMNESS

            /*
             * harmCumulative = harmCumulative * (_generator.NextDouble() + 0.5);
             * bleedCumulative = bleedCumulative * (_generator.NextDouble() + 0.5);
             * heavybleedCumulative = heavybleedCumulative * (_generator.NextDouble() + 0.5);
             * disorientationCumulative = disorientationCumulative * (_generator.NextDouble() + 0.5);
             * impairmentCumulative = impairmentCumulative * (_generator.NextDouble() + 0.5);
             * traumaCumulative = traumaCumulative * (_generator.NextDouble() + 0.5);
             * koCumulative = koCumulative * (_generator.NextDouble() + 0.5);*/

            //adjust the values. changing these lines vastly changes the harm dealt by all attacks, futz with caution

            //harm is easy to come by, as it has the smallest impact on its own and needs to accumulate to perform its function
            harmCumulative = harmCumulative * 2;
            //bleed is easy to get in smallish doses, and scales at a moderate rate
            bleedCumulative = bleedCumulative / 2;
            //....until a certain point, when you start hitting arteries and stuff, and it scales rapidly
            heavybleedCumulative = heavybleedCumulative - 7;
            //the plus on the right is necessary, because 1 point of disorientation matters very little, since it dissapates at the end of the round
            disorientationCumulative = (disorientationCumulative / 2) + 0.4;
            //impairment has to scale slowly and be difficult to achieve, since it will accumulate over combat and seriously hamstrings a fighter
            impairmentCumulative = (impairmentCumulative / 4) - 0.5;
            //like disorientation, 1 point of trauma matters very little, unless you held off on your attack for the round
            traumaCumulative = (traumaCumulative / 4);
            //even one point of ko is usually fatal, since you are likely to be bleeding, so this needs to be difficult to achieve
            koCumulative = (koCumulative / 2) - 7.5;

            Character Whackee              = CritSource.Defender;
            double    resistHarm           = EffectHolder.GetValidEffectsByEffect(Whackee, EffectHolder.EffectType.ResistHarm);
            double    resistBleed          = EffectHolder.GetValidEffectsByEffect(Whackee, EffectHolder.EffectType.ResistBleed);
            double    resistDisorientation = EffectHolder.GetValidEffectsByEffect(Whackee, EffectHolder.EffectType.ResistDisorientation);
            double    resistImpairment     = EffectHolder.GetValidEffectsByEffect(Whackee, EffectHolder.EffectType.ResistImpairment);
            double    resistTrauma         = EffectHolder.GetValidEffectsByEffect(Whackee, EffectHolder.EffectType.ResistTrauma);
            double    resistKo             = EffectHolder.GetValidEffectsByEffect(Whackee, EffectHolder.EffectType.ResistKO);

            harmCumulative = (harmCumulative - resistHarm) * 5 / (5 + resistHarm);
            // NOTE bleed and heavybleed both accounted for here
            bleedCumulative          = (Math.Max(0, bleedCumulative) + Math.Max(0, heavybleedCumulative) - resistBleed) * 5 / (5 + resistBleed);
            disorientationCumulative = (disorientationCumulative - resistDisorientation) * 5 / (5 + resistDisorientation);
            impairmentCumulative     = (impairmentCumulative - resistImpairment) * 5 / (5 + resistImpairment);
            traumaCumulative         = (traumaCumulative - resistTrauma) * 5 / (5 + resistTrauma);
            koCumulative             = (koCumulative - resistKo) * 5 / (5 + resistKo);

            //round the values properly and send them back, no negative values accepted
            CritSource.harm           = (int)Math.Round(Math.Max(0, harmCumulative));
            CritSource.bleed          = (int)Math.Round(Math.Max(0, bleedCumulative));
            CritSource.disorientation = (int)Math.Round(Math.Max(0, disorientationCumulative));
            CritSource.impairment     = (int)Math.Round(Math.Max(0, impairmentCumulative));
            CritSource.trauma         = (int)Math.Round(Math.Max(0, traumaCumulative));
            CritSource.ko             = (int)Math.Round(Math.Max(0, koCumulative));
        }
        private List <DataPoint> CreateDataPoints()
        {
            List <DataPoint> lstData = new List <DataPoint>();
            Random           r       = new Random();
            Double           average = 0;
            Character        copy1   = Utilities.GetSameCharWithCurrentState(_char1);
            Character        copy2   = Utilities.GetSameCharWithCurrentState(_char2);

            for (int i = 1; i < 21; i++)
            {
                for (int j = 1; j < 21; j++)
                {
                    copy1.TemporaryEffects = new List <Effect>();
                    foreach (Effect ef in _char1.TemporaryEffects)
                    {
                        copy1.TemporaryEffects.Add(ef);
                    }
                    copy2.TemporaryEffects = new List <Effect>();
                    foreach (Effect ef in _char2.TemporaryEffects)
                    {
                        copy2.TemporaryEffects.Add(ef);
                    }
                    AttackOutcome _outcome = CombatScripts.RunCombat(copy1, copy2, i, j, null);
                    if (!checkBoxDoLocationCheck.Checked)
                    {
                        //_outcome.recalculateWithoutLocation();
                    }

                    double Red    = 0;
                    double Blue   = 0;
                    double Green  = 0;
                    double Damage = 0.0;
                    if (!checkBoxHarm.Checked &&
                        !checkBoxBleed.Checked &&
                        !checkBoxDisorientation.Checked &&
                        !checkBoxImpairment.Checked &&
                        !checkBoxTrauma.Checked &&
                        !checkBoxKO.Checked)
                    {
                        Damage = _outcome.TotalStrikeAmountFromAllTypes();
                    }
                    if (checkBoxHarm.Checked)
                    {
                        Damage += _outcome.harm;
                    }
                    if (checkBoxBleed.Checked)
                    {
                        Damage += _outcome.bleed;
                    }
                    if (checkBoxDisorientation.Checked)
                    {
                        Damage += _outcome.disorientation;
                    }
                    if (checkBoxImpairment.Checked)
                    {
                        Damage += _outcome.impairment;
                    }
                    if (checkBoxTrauma.Checked)
                    {
                        Damage += _outcome.trauma;
                    }
                    if (checkBoxKO.Checked)
                    {
                        Damage += _outcome.ko;
                    }
                    switch (_outcome.Othertext.ToString())
                    {
                    case "Miss":
                        Red   = 0;
                        Blue  = 0;
                        Green = 0;
                        break;

                    case "Block":
                        Red   = 100;
                        Blue  = 100;
                        Green = 100;
                        break;

                    case "Parry":
                        Red   = 200;
                        Blue  = 200;
                        Green = 200;
                        break;

                    case "Hit":
                        if (Damage < 100)
                        {
                            Red   = 255;
                            Blue  = 255;
                            Green = 255;
                        }
                        if (Damage < 50)
                        {
                            Red   = 200;
                            Blue  = 0;
                            Green = 0;
                        }
                        if (Damage < 20)
                        {
                            Red   = 200;
                            Blue  = 0;
                            Green = 200;
                        }
                        if (Damage < 15)
                        {
                            Red   = 0;
                            Blue  = 0;
                            Green = 200;
                        }
                        if (Damage < 10)
                        {
                            Red   = 0;
                            Blue  = 200;
                            Green = 200;
                        }
                        if (Damage < 5)
                        {
                            Red   = 0;
                            Blue  = 250;
                            Green = 100;
                        }
                        if (Damage < 4)
                        {
                            Red   = 50;
                            Blue  = 200;
                            Green = 0;
                        }
                        if (Damage < 3)
                        {
                            Red   = 100;
                            Blue  = 125;
                            Green = 0;
                        }
                        if (Damage < 2)
                        {
                            Red   = 200;
                            Blue  = 100;
                            Green = 50;
                        }
                        if (Damage < 1)
                        {
                            Red   = 225;
                            Blue  = 0;
                            Green = 125;
                        }
                        break;

                    default:
                        throw new Exception("WTF did you give me?");
                    }
                    int       iRed   = Convert.ToInt32(Math.Floor(Red));
                    int       iBlue  = Convert.ToInt32(Math.Floor(Blue));
                    int       iGreen = Convert.ToInt32(Math.Floor(Green));
                    DataPoint dp     = new DataPoint(10, 10, 11 * i, 11 * j, iRed, iGreen, iBlue);
                    lstData.Add(dp);
                    average += Damage;
                }
            }
            lblAverage.Text = "Average Damage: " + Math.Round(average * 10 / 400) / 10;
            return(lstData);
        }
        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);
        }
Beispiel #12
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();
            }
        }