/// <summary> /// Afflicts the BattleEntity with a StatusEffect. /// <para>This wraps around the method in <see cref="BattleEntityProperties"/>. It calls the <see cref="StatusInflictedEvent"/> and handles the Battle Message.</para> /// <para>In most cases, this method should be used. If you wish to bypass all of these, directly call the method in <see cref="BattleEntityProperties"/> instead.</para> /// </summary> /// <param name="status">The StatusEffect to afflict the BattleEntity with</param> /// <param name="showMessage">Whether to show the StatusEffect's AfflictedMessage as a Battle Message when it is afflicted.</param> public void AfflictStatus(StatusEffect statusEffect, bool showMessage) { EntityProperties.AfflictStatus(statusEffect); //Invoke the status inflicted event StatusInflictedEvent?.Invoke(statusEffect); //Show a battle message when the status is afflicted, provided the message isn't empty if (showMessage == true && string.IsNullOrEmpty(statusEffect.AfflictedMessage) == false) { BattleManager.Instance.battleEventManager.QueueBattleEvent((int)BattleGlobals.BattleEventPriorities.Message + statusEffect.Priority, new BattleManager.BattleState[] { BattleManager.BattleState.TurnEnd }, new MessageBattleEvent(statusEffect.AfflictedMessage, 2000d)); } }
/// <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); } }