/// <summary> /// Handles the <see cref="ElementInteractionResult"/> received from being damaged. /// <para>The base behavior deals damage for <see cref="ElementInteractionResult.Damage"/>, /// KOs for <see cref="ElementInteractionResult.KO"/>, /// and heals for <see cref="ElementInteractionResult.Heal"/>.</para> /// </summary> /// <param name="damageResult">The InteractionHolder containing the result of a damage interaction.</param> protected virtual void HandleDamageResult(InteractionHolder damageResult) { Elements element = damageResult.DamageElement; int damage = damageResult.TotalDamage; bool piercing = damageResult.Piercing; //Handle the elemental interaction results ElementInteractionResult elementResult = damageResult.ElementResult; if (elementResult == ElementInteractionResult.Damage || elementResult == ElementInteractionResult.KO) { if (elementResult == ElementInteractionResult.Damage) { Debug.Log($"{Name} was hit with {damage} {element} " + (piercing ? "piercing" : "non-piercing") + " damage!"); //If the entity took damage during their sequence, it's an interruption, and this event should not occur if (damage > 0 && (IsTurn == false || PreviousAction?.MoveSequence.InSequence == false)) { BattleManager.Instance.battleEventManager.QueueBattleEvent((int)BattleGlobals.BattleEventPriorities.Damage, new BattleManager.BattleState[] { BattleManager.BattleState.Turn, BattleManager.BattleState.TurnEnd }, new DamagedBattleEvent(this)); //Play the damaged sound SoundManager.Instance.PlaySound(SoundManager.Sound.Damaged); } else if (damage <= 0) { //Play the immune sound SoundManager.Instance.PlaySound(SoundManager.Sound.Immune); } //Show the star indicating damage BattleObjManager.Instance.AddBattleObject(new DamageStarVFX(damage, Position + (EntityType == EntityTypes.Player ? new Vector2(-40, -35) : new Vector2(50, -35)))); //Lose HP LoseHP(damage); } //Kill the entity now on an instant KO else if (elementResult == ElementInteractionResult.KO) { Debug.Log($"{Name} was instantly KO'd from {element} because it has a {nameof(WeaknessTypes.KO)} weakness"); Die(); } } //Heal the entity else if (elementResult == ElementInteractionResult.Heal) { Debug.Log($"{Name} was healed for {damage} HP because it has a {nameof(ResistanceTypes.Heal)} resistance to Element {element}"); //Heal the damage HealHP(damage); } }
public InteractionHolder(BattleEntity entity, int totalDamage, Enumerations.Elements damageElement, ElementInteractionResult elementResult, Enumerations.ContactTypes contactType, Enumerations.ContactProperties contactProperty, bool piercing, StatusChanceHolder[] statusesInflicted, bool hit, Enumerations.DamageEffects damageEffect) { Entity = entity; TotalDamage = totalDamage; DamageElement = damageElement; ElementResult = elementResult; ContactType = contactType; ContactProperty = contactProperty; Piercing = piercing; StatusesInflicted = statusesInflicted; Hit = hit; DamageEffect = damageEffect; DefensiveActionsPerformed = Enumerations.DefensiveActionTypes.None; IsPaybackDamage = false; DontDamageEntity = false; }
public ElementDamageResultHolder(ElementInteractionResult interactionResult, int damage) { InteractionResult = interactionResult; Damage = damage; }
/// <summary> /// Makes the entity take damage from an attack, factoring in stats such as defense, weaknesses, and resistances /// </summary> /// <param name="damageResult">The InteractionHolder containing the result of a damage interaction</param> /*This is how Paper Mario: The Thousand Year Door calculates damage: * 1. Start with base attack * 2. Subtract damage from Defend Plus, Defend Command, and any additional Defense * 3. Subtract or Add from P-Down D-up and P-Up D-Down * 4. Reduce damage to 0 if superguarded. Reduce by 1 + each Damage Dodge if guarded * 5. Multiply by the number of Double Pains + 1 * 6. Divide by the number of Last Stands + 1 (if in danger) * * Therefore, two Double Pains = Triple Pain. * Max Damage is 99.*/ public void TakeDamage(InteractionHolder damageResult) { Elements element = damageResult.DamageElement; int damage = damageResult.TotalDamage; bool piercing = damageResult.Piercing; StatusChanceHolder[] statusesInflicted = damageResult.StatusesInflicted; //Handle the elemental interaction results ElementInteractionResult elementResult = damageResult.ElementResult; if (elementResult == ElementInteractionResult.Damage || elementResult == ElementInteractionResult.KO) { if (elementResult == ElementInteractionResult.Damage) { Debug.Log($"{Name} was hit with {damage} {element} " + (piercing ? "piercing" : "non-piercing") + " damage!"); //If the entity took damage during their sequence, it's an interruption, and this event should not occur if (damage > 0 && (IsTurn == false || PreviousAction?.MoveSequence.InSequence == false)) { BattleEventManager.Instance.QueueBattleEvent((int)BattleGlobals.StartEventPriorities.Damage, new BattleManager.BattleState[] { BattleManager.BattleState.Turn, BattleManager.BattleState.TurnEnd }, new DamagedBattleEvent(this)); } //Lose HP LoseHP(damage); } //Kill the entity now on an instant KO else if (elementResult == ElementInteractionResult.KO) { Debug.Log($"{Name} was instantly KO'd from {element} because it has a {nameof(WeaknessTypes.KO)} weakness"); Die(); } } //Heal the entity else if (elementResult == ElementInteractionResult.Heal) { Debug.Log($"{Name} was healed for {damage} HP because it has a {nameof(ResistanceTypes.Heal)} resistance to Element {element}"); //Heal the damage HealHP(damage); } //Inflict Statuses if the entity isn't dead if (HealthState != HealthStates.Dead && statusesInflicted != null) { for (int i = 0; i < statusesInflicted.Length; i++) { EntityProperties.AfflictStatus(statusesInflicted[i].Status, true); } } //Handle DamageEffects HandleDamageEffects(damageResult.DamageEffect); //If this entity received damage during its action sequence, it has been interrupted //The null check is necessary in the event that a StatusEffect that deals damage at the start of the phase, such as Poison, //is inflicted at the start of the battle before any entity has moved if (damage > 0 && IsTurn == true && PreviousAction?.MoveSequence.InSequence == true) { PreviousAction.MoveSequence.StartInterruption(element); } }