/// <summary>
        /// Gets the result of a ContactType on a set of PhysicalAttributes
        /// </summary>
        /// <param name="attacker">The BattleEntity performing the attack</param>
        /// <param name="contactType">The ContactType performed</param>
        /// <param name="physAttributes">The set of PhysicalAttributes to test against</param>
        /// <param name="attributesToIgnore">A set of PhysicalAttributes to ignore</param>
        /// <returns>A ContactResultInfo of the interaction</returns>
        public static ContactResultInfo GetContactResult(BattleEntity attacker, ContactTypes contactType, PhysicalAttributes[] physAttributes, params PhysicalAttributes[] attributesToIgnore)
        {
            //Return the default value
            if (ContactTable.ContainsKey(contactType) == false || physAttributes == null)
            {
                Debug.LogWarning($"{nameof(physAttributes)} array is null or {nameof(ContactTable)} does not contain the ContactType {contactType}!");
                return(ContactResultInfo.Default);
            }

            //Look through the attributes and find the first match
            for (int i = 0; i < physAttributes.Length; i++)
            {
                Dictionary <PhysicalAttributes, ContactResultInfo> tableForContact = ContactTable[contactType];
                PhysicalAttributes attribute = physAttributes[i];

                //If this attribute is ignored, move onto the next
                if (attributesToIgnore?.Contains(attribute) == true)
                {
                    continue;
                }

                if (tableForContact.ContainsKey(attribute) == true)
                {
                    ContactResultInfo contactResult = tableForContact[attribute];
                    //If the ContactResult is a Success if the entity has the same PhysicalAttribute as the one tested, set its result to Success
                    if (contactResult.SuccessIfSameAttr == true && attacker.EntityProperties.HasPhysAttributes(true, attribute) == true)
                    {
                        contactResult.ContactResult = ContactResult.Success;
                    }
                    return(contactResult);
                }
            }

            return(ContactResultInfo.Default);
        }
 public InteractionResult Calculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
 {
     StepResult            = new InteractionResult(curResult);
     StepContactResultInfo = curContactResult;
     OnCalculate(damageInfo, curResult, curContactResult);
     return(StepResult);
 }
        /// <summary>
        /// Determines the result of contact, based on the type of contact made, when it's made with this entity.
        /// <para>Contacts that aren't a Success are prioritized over any Payback.
        /// If a ContactResult of Success is found, then the Payback for this entity is added if it exists
        /// and the ContactResult becomes a PartialSuccess.</para>
        /// </summary>
        /// <param name="attacker">The entity attacking this one</param>
        /// <param name="contactType">The type of contact made with this entity</param>
        /// <returns>A ContactResultInfo containing the result of the interaction</returns>
        public ContactResultInfo GetContactResult(BattleEntity attacker, ContactTypes contactType)
        {
            ContactResultInfo contactResultInfo = Interactions.GetContactResult(attacker, contactType, GetAllPhysAttributes(), attacker.EntityProperties.GetContactExceptions(contactType));

            //On a Success, check if this Entity has any Payback and add it if so
            if ((contactResultInfo.ContactResult == ContactResult.Success || contactResultInfo.ContactResult == ContactResult.PartialSuccess) && HasPayback() == true)
            {
                PaybackHolder paybackholder;

                //Factor in the contact's Payback on a PartialSuccess
                if (contactResultInfo.ContactResult == ContactResult.PartialSuccess)
                {
                    paybackholder = GetPayback(contactResultInfo.Paybackholder);
                }
                //Get only the BattleEntity's Payback on a Success
                else
                {
                    paybackholder = GetPayback();
                }

                //Since there's Payback, the result is now a PartialSuccess
                contactResultInfo.ContactResult = ContactResult.PartialSuccess;
                contactResultInfo.Paybackholder = paybackholder;
            }

            return(contactResultInfo);
        }
        /// <summary>
        /// Calculates and returns the entire damage interaction between two BattleEntities.
        /// <para>This returns all the necessary information for both BattleEntities, including the total amount of damage dealt,
        /// the type of Elemental damage to deal, the Status Effects to inflict, and whether the attack successfully hit or not.</para>
        /// </summary>
        /// <param name="interactionParam">An InteractionParamHolder containing the BattleEntities interacting and data about their interaction.</param>
        /// <returns>An InteractionResult containing InteractionHolders for both the victim and the attacker.</returns>
        public static InteractionResult GetDamageInteraction(InteractionParamHolder interactionParam)
        {
            InteractionResult finalInteraction  = new InteractionResult();
            ContactResultInfo contactResultInfo = new ContactResultInfo();

            for (int i = 0; i < DamageCalculationSteps.Count; i++)
            {
                finalInteraction  = DamageCalculationSteps[i].Calculate(interactionParam, finalInteraction, contactResultInfo);
                contactResultInfo = DamageCalculationSteps[i].StepContactResultInfo;
            }

            return(finalInteraction);
        }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                //Factor in Double Pain for the Victim
                int doublePainCount = StepResult.VictimResult.Entity.GetEquippedBadgeCount(BadgeGlobals.BadgeTypes.DoublePain);

                StepResult.VictimResult.TotalDamage *= (1 + doublePainCount);
            }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                //If the attack didn't hit, don't factor in DamageEffects
                if (StepResult.VictimResult.Hit == false)
                {
                    StepResult.VictimResult.DamageEffect = DamageEffects.None;
                }

                //If the current result has no DamageEffects (whether the move didn't have any or a Defensive Action removed them)
                //or if the BattleEntity isn't vulnerable to any DamageEffects, then don't bother doing anything else
                if (StepResult.VictimResult.DamageEffect == DamageEffects.None ||
                    StepResult.VictimResult.Entity.EntityProperties.HasDamageEffectVulnerabilities() == false)
                {
                    return;
                }

                //The DamageEffects stored in the result
                DamageEffects resultEffects = DamageEffects.None;

                //Get all the DamageEffects
                DamageEffects[] damageEffects = UtilityGlobals.GetEnumValues <DamageEffects>();

                //Start at index 1, as 0 is the value of None indicating no DamageEffects
                for (int i = 1; i < damageEffects.Length; i++)
                {
                    DamageEffects curEffect = damageEffects[i];

                    //If the move has the DamageEffect and the entity is affected by it, add it to the result
                    //This approach is easier and more readable than removing effects
                    if (UtilityGlobals.EnumHasFlag(StepResult.VictimResult.DamageEffect, curEffect) == true &&
                        StepResult.VictimResult.Entity.EntityProperties.IsVulnerableToDamageEffect(curEffect) == true)
                    {
                        resultEffects |= curEffect;
                    }
                }

                //Set the result
                StepResult.VictimResult.DamageEffect = resultEffects;
            }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                //Defense added from Damage Dodge Badges upon a successful Guard
                int damageDodgeDefense = 0;

                //Defensive actions take priority. If the attack didn't hit, don't check for defensive actions
                BattleGlobals.DefensiveActionHolder?victimDefenseData = null;
                if (StepResult.VictimResult.Hit == true)
                {
                    victimDefenseData = StepResult.VictimResult.Entity.GetDefensiveActionResult(StepResult.VictimResult.TotalDamage,
                                                                                                StepResult.VictimResult.StatusesInflicted, StepResult.VictimResult.DamageEffect);
                }

                //A Defensive Action has been performed
                if (victimDefenseData.HasValue == true)
                {
                    StepResult.VictimResult.TotalDamage       = victimDefenseData.Value.Damage;
                    StepResult.VictimResult.StatusesInflicted = victimDefenseData.Value.Statuses;
                    StepResult.VictimResult.DamageEffect      = victimDefenseData.Value.DamageEffect;

                    //Store the damage dealt to the attacker, if any
                    if (victimDefenseData.Value.ElementHolder.HasValue == true)
                    {
                        ElementDamageHolder elementHolder = victimDefenseData.Value.ElementHolder.Value;

                        //If the Defensive action dealt damage and the contact was direct
                        //the Defensive action has caused a Failure for the Attacker (Ex. Superguarding)
                        if (StepResult.VictimResult.ContactType == ContactTypes.TopDirect ||
                            StepResult.VictimResult.ContactType == ContactTypes.SideDirect)
                        {
                            StepContactResultInfo.ContactResult = ContactResult.Failure;

                            //Use the damage from the Defensive Action
                            StepResult.AttackerResult.TotalDamage = elementHolder.Damage;

                            //Update the Paybackholder to use the Payback data from the Defensive Action
                            StepContactResultInfo.Paybackholder = new PaybackHolder(PaybackTypes.Constant, elementHolder.Element, elementHolder.Damage);
                        }

                        StepResult.AttackerResult.DamageElement = victimDefenseData.Value.ElementHolder.Value.Element;
                    }

                    //Factor in the additional Guard defense for all DefensiveActions (for now, at least)
                    //If it's not Piercing, this will be subtracted, in addition to the Victim's Defense, from the damage dealt to the Victim
                    damageDodgeDefense = StepResult.VictimResult.Entity.GetEquippedBadgeCount(BadgeGlobals.BadgeTypes.DamageDodge);
                }

                //Subtract Defense on non-piercing damage
                if (StepResult.VictimResult.Piercing == false)
                {
                    int totalDefense = StepResult.VictimResult.Entity.BattleStats.TotalDefense + damageDodgeDefense;
                    StepResult.VictimResult.TotalDamage -= totalDefense;
                }

                //Store the final unscaled damage in the Attacker's result if there was no Defensive Action payback, as it will use it later
                if (victimDefenseData.HasValue == false || victimDefenseData.Value.ElementHolder.HasValue == false)
                {
                    StepResult.AttackerResult.TotalDamage = StepResult.VictimResult.TotalDamage;
                }
            }
 protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
 {
     //If the move cannot miss, hit is set to true
     if (damageInfo.CantMiss == true)
     {
         StepResult.VictimResult.Hit = true;
     }
     else
     {
         StepResult.VictimResult.Hit = StepResult.AttackerResult.Entity.AttemptHitEntity(StepResult.VictimResult.Entity);
     }
 }
 protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
 {
     //Check if the Attacker is Invincible. If so, ignore all damage and Status Effects
     if (StepResult.AttackerResult.Entity.EntityProperties.GetAdditionalProperty <bool>(AdditionalProperty.Invincible) == true)
     {
         StepResult.AttackerResult.TotalDamage       = 0;
         StepResult.AttackerResult.ElementResult     = ElementInteractionResult.Damage;
         StepResult.AttackerResult.StatusesInflicted = null;
     }
 }
 protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
 {
     StepResult.AttackerResult.TotalDamage =
         UtilityGlobals.Clamp(StepResult.AttackerResult.TotalDamage, BattleGlobals.MinDamage, BattleGlobals.MaxDamage);
 }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                Elements     element = StepResult.VictimResult.DamageElement;
                BattleEntity victim  = StepResult.VictimResult.Entity;

                //Retrieve an overridden type of Elemental damage to inflict based on the Victim's PhysicalAttributes
                //(Ex. The Ice Power Badge only deals Ice damage to Fiery entities)
                ElementOverrideHolder newElement = StepResult.AttackerResult.Entity.EntityProperties.GetTotalElementOverride(victim);

                if (newElement.Element != Elements.Invalid)
                {
                    /*NOTE: Idea for stacking weaknesses
                     * (Ex. 1 Ice Power is 1 weakness, Ice Power + Ice Smash = 2 weaknesses)
                     *
                     * Ex. damage = 2
                     * player inflicts ice 2 times: ice power & ice smash
                     *
                     * ice_inflicted_times = 2
                     * if (enemy weak to ice)
                     *  damage += ice_inflicted_times
                     * end
                     *
                     #damage = 4
                     */

                    //Add the number of element overrides to the damage if the element used already exists as an override and the victim has a Weakness
                    //to the Element. This allows Badges such as Ice Power to deal more damage if used in conjunction with attacks
                    //that deal the same type of damage (Ex. Ice Power and Ice Smash deal 2 additional damage total rather than 1).
                    //If any new knowledge is discovered to improve this, this will be changed
                    //Ice Power is the only Badge of its kind across the first two PM games that does anything like this
                    if (element == newElement.Element && victim.EntityProperties.HasWeakness(element) == true)
                    {
                        StepResult.VictimResult.TotalDamage += newElement.OverrideCount;
                    }

                    StepResult.VictimResult.DamageElement = newElement.Element;
                }
            }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                BattleEntity victim   = StepResult.VictimResult.Entity;
                BattleEntity attacker = StepResult.AttackerResult.Entity;

                //Get contact results
                StepContactResultInfo = victim.EntityProperties.GetContactResult(attacker, StepResult.VictimResult.ContactType);
            }
 protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
 {
     StepResult.AttackerResult.Entity          = damageInfo.Attacker;
     StepResult.VictimResult.Entity            = damageInfo.Victim;
     StepResult.VictimResult.ContactType       = damageInfo.ContactType;
     StepResult.VictimResult.DamageElement     = damageInfo.DamagingElement;
     StepResult.VictimResult.StatusesInflicted = damageInfo.Statuses;
     StepResult.VictimResult.TotalDamage       = damageInfo.Damage;
     StepResult.VictimResult.Piercing          = damageInfo.Piercing;
     StepResult.VictimResult.DamageEffect      = damageInfo.DamageEffect;
 }
 protected abstract void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult);
        public static InteractionResult GetDamageInteractionOld(InteractionParamHolder interactionParam)
        {
            InteractionResult finalInteractionResult = new InteractionResult();

            BattleEntity attacker    = interactionParam.Attacker;
            BattleEntity victim      = interactionParam.Victim;
            ContactTypes contactType = interactionParam.ContactType;
            Elements     element     = interactionParam.DamagingElement;

            StatusChanceHolder[] statuses = interactionParam.Statuses;
            int  damage   = interactionParam.Damage;
            bool piercing = interactionParam.Piercing;

            //Get contact results
            ContactResultInfo contactResultInfo = victim.EntityProperties.GetContactResult(attacker, contactType);
            ContactResult     contactResult     = contactResultInfo.ContactResult;

            //Retrieve an overridden type of Elemental damage to inflict based on the Victim's PhysicalAttributes
            //(Ex. The Ice Power Badge only deals Ice damage to Fiery entities)
            ElementOverrideHolder newElement = attacker.EntityProperties.GetTotalElementOverride(victim);

            if (newElement.Element != Elements.Invalid)
            {
                //Add the number of element overrides to the damage if the element used already exists as an override and the victim has a Weakness
                //to the Element. This allows Badges such as Ice Power to deal more damage if used in conjunction with attacks
                //that deal the same type of damage (Ex. Ice Power and Ice Smash deal 2 additional damage total rather than 1).
                //If any new knowledge is discovered to improve this, this will be changed
                //Ice Power is the only Badge of its kind across the first two PM games that does anything like this
                if (element == newElement.Element && victim.EntityProperties.HasWeakness(element) == true)
                {
                    damage += newElement.OverrideCount;
                }

                element = newElement.Element;
            }

            /*Get the total damage dealt to the Victim. The amount of Full or Half Payback damage dealt to the Attacker
             * uses the resulting damage value from this because Payback uses the total damage that would be dealt to the Victim.
             * This occurs before factoring in elemental resistances/weaknesses from the Attacker*/
            ElementDamageResultHolder victimElementDamage = GetElementalDamage(victim, element, damage);

            int unscaledVictimDamage = victimElementDamage.Damage;

            //Subtract damage reduction (P-Up, D-Down and P-Down, D-Up Badges)
            unscaledVictimDamage -= victim.BattleStats.DamageReduction;

            //Check if the attack hit. If not, then don't consider defensive actions
            bool attackHit = interactionParam.CantMiss == true ? true : attacker.AttemptHitEntity(victim);

            //Defense added from Damage Dodge Badges upon a successful Guard
            int damageDodgeDefense = 0;

            //Defensive actions take priority. If the attack didn't hit, don't check for defensive actions
            BattleGlobals.DefensiveActionHolder?victimDefenseData = null;
            if (attackHit == true)
            {
                victimDefenseData = victim.GetDefensiveActionResult(unscaledVictimDamage, statuses, interactionParam.DamageEffect);
            }

            if (victimDefenseData.HasValue == true)
            {
                unscaledVictimDamage = victimDefenseData.Value.Damage;
                statuses             = victimDefenseData.Value.Statuses;
                //If the Defensive action dealt damage and the contact was direct
                //the Defensive action has caused a Failure for the Attacker (Ex. Superguarding)
                if ((contactType == ContactTypes.TopDirect || contactType == ContactTypes.SideDirect) && victimDefenseData.Value.ElementHolder.HasValue == true)
                {
                    contactResult = ContactResult.Failure;
                }

                //Factor in the additional Guard defense for all DefensiveActions (for now, at least)
                damageDodgeDefense = victim.GetEquippedBadgeCount(BadgeGlobals.BadgeTypes.DamageDodge);
            }

            //Subtract Defense on non-piercing damage
            if (piercing == false)
            {
                int totalDefense = victim.BattleStats.TotalDefense + damageDodgeDefense;
                unscaledVictimDamage -= totalDefense;
            }

            int scaledVictimDamage = unscaledVictimDamage;

            //Factor in Double Pain for the Victim
            scaledVictimDamage *= (1 + victim.GetEquippedBadgeCount(BadgeGlobals.BadgeTypes.DoublePain));

            //Factor in Last Stand for the Victim, if the Victim is in Danger or Peril
            if (victim.IsInDanger == true)
            {
                //PM rounds down, whereas TTYD rounds up. We're going with the latter
                //TTYD always ceilings the value (Ex. 3.2 turns to 4)
                int lastStandDivider = (1 + victim.GetEquippedBadgeCount(BadgeGlobals.BadgeTypes.LastStand));
                scaledVictimDamage = (int)Math.Ceiling(scaledVictimDamage / (float)lastStandDivider);
            }

            /*If the Victim is Invincible, ignore all damage and Status Effects
             * If the Attacker is Invincible, ignore all Payback damage and Status Effects
             *
             * It won't ignore the Payback's effects automatically; that has to be done manually by adding
             * contact exceptions or something else*/

            //Clamp Victim damage
            scaledVictimDamage = UtilityGlobals.Clamp(scaledVictimDamage, BattleGlobals.MinDamage, BattleGlobals.MaxDamage);

            #region Victim Damage Dealt

            //Calculating damage dealt to the Victim
            if (contactResult == ContactResult.Success || contactResult == ContactResult.PartialSuccess)
            {
                //Get the Status Effects to inflict on the Victim
                StatusChanceHolder[] victimInflictedStatuses = GetFilteredInflictedStatuses(victim, statuses);

                //Check if the Victim is Invincible. If so, ignore all damage and Status Effects
                if (victim.EntityProperties.GetAdditionalProperty <bool>(AdditionalProperty.Invincible) == true)
                {
                    scaledVictimDamage = 0;
                    victimElementDamage.InteractionResult = ElementInteractionResult.Damage;
                    victimInflictedStatuses = null;
                }

                finalInteractionResult.VictimResult = new InteractionHolder(victim, scaledVictimDamage, element,
                                                                            victimElementDamage.InteractionResult, contactType, piercing, victimInflictedStatuses, attackHit, DamageEffects.None);
            }

            #endregion

            #region Attacker Damage Dealt

            //Calculating damage dealt to the Attacker
            if (contactResult == ContactResult.Failure || contactResult == ContactResult.PartialSuccess)
            {
                //The damage the Attacker dealt to the Victim
                int           damageDealt   = unscaledVictimDamage;
                PaybackHolder paybackHolder = contactResultInfo.Paybackholder;

                //Override the PaybackHolder with a Defensive Action's results, if any
                if (victimDefenseData.HasValue == true && victimDefenseData.Value.ElementHolder.HasValue == true)
                {
                    damageDealt   = victimDefenseData.Value.ElementHolder.Value.Damage;
                    paybackHolder = new PaybackHolder(PaybackTypes.Constant, victimDefenseData.Value.ElementHolder.Value.Element, damageDealt);
                }

                //Get the damage done to the Attacker, factoring in Weaknesses/Resistances
                ElementDamageResultHolder attackerElementDamage = GetElementalDamage(attacker, paybackHolder.Element, damageDealt);

                //Get Payback damage - Payback damage is calculated after everything else, including Constant Payback.
                //However, it does NOT factor in Double Pain or any sort of Defense modifiers.
                int paybackDamage = paybackHolder.GetPaybackDamage(attackerElementDamage.Damage);

                //If Constant Payback, update the damage value to use the element
                if (paybackHolder.PaybackType == PaybackTypes.Constant)
                {
                    paybackDamage = GetElementalDamage(attacker, paybackHolder.Element, paybackDamage).Damage;
                }

                //Clamp Attacker damage
                attackerElementDamage.Damage = UtilityGlobals.Clamp(paybackDamage, BattleGlobals.MinDamage, BattleGlobals.MaxDamage);

                //Get the Status Effects to inflict
                StatusChanceHolder[] attackerInflictedStatuses = GetFilteredInflictedStatuses(attacker, paybackHolder.StatusesInflicted);

                //Check if the Attacker is Invincible. If so, ignore all damage and Status Effects
                if (attacker.EntityProperties.GetAdditionalProperty <bool>(AdditionalProperty.Invincible) == true)
                {
                    attackerElementDamage.Damage            = 0;
                    attackerElementDamage.InteractionResult = ElementInteractionResult.Damage;
                    attackerInflictedStatuses = null;
                }

                finalInteractionResult.AttackerResult = new InteractionHolder(attacker, attackerElementDamage.Damage, paybackHolder.Element,
                                                                              attackerElementDamage.InteractionResult, ContactTypes.None, true, attackerInflictedStatuses, true, DamageEffects.None);
            }

            #endregion

            return(finalInteractionResult);
        }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                //Factor in Last Stand for the Victim, if the Victim is in Danger or Peril
                if (StepResult.VictimResult.Entity.IsInDanger == true)
                {
                    //PM rounds down, whereas TTYD rounds up. We're going with the latter
                    //TTYD always ceilings the value (Ex. 3.2 turns to 4)
                    int lastStandCount = StepResult.VictimResult.Entity.GetEquippedBadgeCount(BadgeGlobals.BadgeTypes.LastStand);

                    int lastStandDivider = (1 + lastStandCount);
                    StepResult.VictimResult.TotalDamage = (int)Math.Ceiling(StepResult.VictimResult.TotalDamage / (float)lastStandDivider);
                }
            }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                //The unscaled damage the Attacker dealt to the Victim
                //This will be the Payback damage dealt from a Defensive Action if one that deals damage has been performed
                int unscaledAttackerDamage = StepResult.AttackerResult.TotalDamage;

                int           damageDealt   = unscaledAttackerDamage;
                PaybackHolder paybackHolder = StepContactResultInfo.Paybackholder;

                //Get the damage done to the Attacker, factoring in Weaknesses/Resistances
                ElementDamageResultHolder attackerElementDamage = GetElementalDamage(StepResult.AttackerResult.Entity,
                                                                                     paybackHolder.Element, damageDealt);

                //Get Payback damage - Payback damage is calculated after everything else
                //However, it does NOT factor in Double Pain or Last Stand, hence why we use the unscaled Victim damage
                int paybackDamage = paybackHolder.GetPaybackDamage(attackerElementDamage.Damage);

                //If Constant Payback, the constant damage value will be returned as the Payback damage
                //Therefore, update the final Payback damage value to factor in Weaknesses/Resistances using the constant Payback damage
                //Ex. This causes an enemy with a +1 Weakness to Fire to be dealt 2 damage instead of 1 for a Constant 1 Fire Payback
                if (paybackHolder.PaybackType == PaybackTypes.Constant)
                {
                    paybackDamage = GetElementalDamage(StepResult.AttackerResult.Entity, paybackHolder.Element, paybackDamage).Damage;
                }

                //Fill out the rest of the Attacker information since we have it
                //Payback damage is always direct, piercing, and guaranteed to hit
                StepResult.AttackerResult.TotalDamage       = paybackDamage;
                StepResult.AttackerResult.DamageElement     = paybackHolder.Element;
                StepResult.AttackerResult.ElementResult     = attackerElementDamage.InteractionResult;
                StepResult.AttackerResult.ContactType       = ContactTypes.TopDirect;
                StepResult.AttackerResult.Piercing          = true;
                StepResult.AttackerResult.StatusesInflicted = paybackHolder.StatusesInflicted;
                StepResult.AttackerResult.Hit = true;
            }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                StrengthHolder totalStrength = StepResult.AttackerResult.Entity.EntityProperties.GetTotalStrength(StepResult.VictimResult.Entity);

                StepResult.VictimResult.TotalDamage += totalStrength.Value;
            }
 protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
 {
     StepResult.AttackerResult.StatusesInflicted =
         GetFilteredInflictedStatuses(StepResult.AttackerResult.Entity, StepResult.AttackerResult.StatusesInflicted);
 }
            protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
            {
                ElementDamageResultHolder victimElementDamage = GetElementalDamage(StepResult.VictimResult.Entity,
                                                                                   StepResult.VictimResult.DamageElement, StepResult.VictimResult.TotalDamage);

                StepResult.VictimResult.ElementResult = victimElementDamage.InteractionResult;
                StepResult.VictimResult.TotalDamage   = victimElementDamage.Damage;
            }
 protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
 {
     if (StepContactResultInfo.ContactResult == ContactResult.Success)
     {
         //If the Attacker succeeded to attack, set the Attacker to null to mark it as not having a value
         //This prevents the code afterwards from dealing damage to the Attacker
         StepResult.AttackerResult.Entity = null;
     }
 }
 protected override void OnCalculate(InteractionParamHolder damageInfo, InteractionResult curResult, ContactResultInfo curContactResult)
 {
     StepResult.VictimResult.TotalDamage -= StepResult.VictimResult.Entity.BattleStats.DamageReduction;
 }