102 lines
3.8 KiB
C#
102 lines
3.8 KiB
C#
using PkmnLib.Dynamic.Models;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
|
|
|
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
|
|
|
/// <summary>
|
|
/// Tests for the <see cref="FinalGambit"/> move script.
|
|
/// Bulbapedia: "Final Gambit causes the user to faint, and the target receives damage equal to the user's
|
|
/// remaining HP before using Final Gambit."
|
|
/// </summary>
|
|
public class FinalGambitTests
|
|
{
|
|
/// <summary>
|
|
/// Creates a fully mocked test setup for Final Gambit tests.
|
|
/// </summary>
|
|
private static (FinalGambit script, IExecutingMove move, IPokemon user, IPokemon target) CreateTestSetup(
|
|
uint userCurrentHealth)
|
|
{
|
|
var script = new FinalGambit();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
var user = Substitute.For<IPokemon>();
|
|
user.CurrentHealth.Returns(userCurrentHealth);
|
|
move.User.Returns(user);
|
|
var target = Substitute.For<IPokemon>();
|
|
return (script, move, user, target);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper to extract the damage amount from the user's received Damage calls.
|
|
/// </summary>
|
|
private static uint? GetDamageAmount(IPokemon pokemon)
|
|
{
|
|
var call = pokemon.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "Damage");
|
|
return call != null ? (uint)call.GetArguments()[0]! : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Helper to extract the damage source from the user's received Damage calls.
|
|
/// </summary>
|
|
private static DamageSource? GetDamageSource(IPokemon pokemon)
|
|
{
|
|
var call = pokemon.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "Damage");
|
|
return call != null ? (DamageSource)call.GetArguments()[1]! : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "the target receives damage equal to the user's remaining HP before using Final Gambit."
|
|
/// The move damage is replaced with the user's current HP, regardless of what the damage formula produced.
|
|
/// </summary>
|
|
[Test, Arguments(1u), Arguments(150u), Arguments(400u)]
|
|
public async Task ChangeMoveDamage_SetsDamageToUserRemainingHp(uint userCurrentHealth)
|
|
{
|
|
// Arrange
|
|
var (script, move, _, target) = CreateTestSetup(userCurrentHealth);
|
|
uint damage = 9999;
|
|
|
|
// Act
|
|
script.ChangeMoveDamage(move, target, 0, ref damage);
|
|
|
|
// Assert
|
|
await Assert.That(damage).IsEqualTo(userCurrentHealth);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Final Gambit causes the user to faint".
|
|
/// After the move hits, the user takes at least its full remaining HP as damage, so it always faints.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_MoveHits_UserTakesAtLeastItsRemainingHpAsDamage()
|
|
{
|
|
// Arrange
|
|
const uint currentHealth = 100;
|
|
var (script, move, user, target) = CreateTestSetup(currentHealth);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, target, 0);
|
|
|
|
// Assert - the self-damage is at least the user's remaining HP, so the user faints
|
|
var damage = GetDamageAmount(user);
|
|
await Assert.That(damage).IsNotNull();
|
|
await Assert.That(damage!.Value >= currentHealth).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "The move's side effect is not considered as inflicting damage to the user, and so if the
|
|
/// user is holding a Focus Band, Focus Sash, or has Sturdy, they will not activate and the user will
|
|
/// still faint."
|
|
/// The self-inflicted faint is therefore indirect damage (<see cref="DamageSource.Misc"/>), not move damage.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_MoveHits_SelfFaintUsesMiscDamageSource()
|
|
{
|
|
// Arrange
|
|
var (script, move, user, target) = CreateTestSetup(100);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, target, 0);
|
|
|
|
// Assert
|
|
await Assert.That(GetDamageSource(user)!.Value).IsEqualTo(DamageSource.Misc);
|
|
}
|
|
} |