170 lines
7.2 KiB
C#
170 lines
7.2 KiB
C#
using PkmnLib.Dynamic.Events;
|
|
using PkmnLib.Dynamic.Models;
|
|
using PkmnLib.Dynamic.ScriptHandling;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
|
using PkmnLib.Static;
|
|
|
|
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
|
|
|
/// <summary>
|
|
/// Tests for the <see cref="Autotomize"/> move script.
|
|
/// Gen VII Bulbapedia behavior: "Autotomize raises the user's Speed stat by two stages and (if the user
|
|
/// successfully changes its Speed) decreases its weight by 220 lbs. (100 kg). If the user successfully
|
|
/// changes its weight, the message '<Pokémon> became nimble!' is displayed. Autotomize cannot decrease
|
|
/// the user's weight below the minimum 0.2 lbs (0.1 kg); if the user's weight would drop below the minimum,
|
|
/// it becomes the minimum instead. Weight loss from Autotomize stacks".
|
|
/// </summary>
|
|
public class AutotomizeTests
|
|
{
|
|
private static (Autotomize script, IExecutingMove move, IPokemon user, IScriptSet userVolatile, EventHook eventHook)
|
|
CreateTestSetup(float weightInKg, bool speedRaiseSucceeds, AutotomizeEffect? existingEffect = null)
|
|
{
|
|
var script = new Autotomize();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
|
|
var eventHook = new EventHook();
|
|
var battle = Substitute.For<IBattle>();
|
|
battle.EventHook.Returns(eventHook);
|
|
var battleData = Substitute.For<IPokemonBattleData>();
|
|
battleData.Battle.Returns(battle);
|
|
|
|
var userVolatile = Substitute.For<IScriptSet>();
|
|
userVolatile.Get<AutotomizeEffect>().Returns(existingEffect);
|
|
|
|
var user = Substitute.For<IPokemon>();
|
|
user.BattleData.Returns(battleData);
|
|
user.Volatile.Returns(userVolatile);
|
|
user.WeightInKg.Returns(weightInKg);
|
|
user.ChangeStatBoost(Arg.Any<Statistic>(), Arg.Any<sbyte>(), Arg.Any<bool>(), Arg.Any<bool>())
|
|
.Returns(speedRaiseSucceeds);
|
|
move.User.Returns(user);
|
|
|
|
return (script, move, user, userVolatile, eventHook);
|
|
}
|
|
|
|
private static bool ReceivedStackOrAdd(IScriptSet scriptSet) =>
|
|
scriptSet.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "StackOrAdd");
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Autotomize raises the user's Speed stat by two stages". The stat change is self-inflicted.
|
|
/// </summary>
|
|
[Test]
|
|
public void OnSecondaryEffect_RaisesUserSpeedByTwoStages()
|
|
{
|
|
// Arrange
|
|
var (script, move, user, _, _) = CreateTestSetup(100f, true);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
|
|
|
|
// Assert
|
|
user.Received(1).ChangeStatBoost(Statistic.Speed, 2, true, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "(if the user successfully changes its Speed) decreases its weight by 220 lbs. (100 kg).
|
|
/// If the user successfully changes its weight, the message '<Pokémon> became nimble!' is displayed."
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_SpeedRaiseSucceeds_AddsWeightReductionAndShowsMessage()
|
|
{
|
|
// Arrange
|
|
var (script, move, _, userVolatile, eventHook) = CreateTestSetup(100f, true);
|
|
DialogEvent? capturedEvent = null;
|
|
eventHook.Handler += (_, args) =>
|
|
{
|
|
if (args is DialogEvent dialogEvent)
|
|
capturedEvent = dialogEvent;
|
|
};
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
|
|
|
|
// Assert
|
|
await Assert.That(ReceivedStackOrAdd(userVolatile)).IsTrue();
|
|
await Assert.That(capturedEvent).IsNotNull();
|
|
await Assert.That(capturedEvent!.Message).IsEqualTo("pokemon_became_nimble");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: the weight decrease only happens "if the user successfully changes its Speed". When the
|
|
/// Speed stat cannot be raised (already at +6), no weight reduction is applied and no message is shown.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_SpeedRaiseFails_NoWeightReductionOrMessage()
|
|
{
|
|
// Arrange
|
|
var (script, move, _, userVolatile, eventHook) = CreateTestSetup(100f, false);
|
|
var eventFired = false;
|
|
eventHook.Handler += (_, _) => eventFired = true;
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
|
|
|
|
// Assert
|
|
await Assert.That(ReceivedStackOrAdd(userVolatile)).IsFalse();
|
|
await Assert.That(eventFired).IsFalse();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Autotomize cannot decrease the user's weight below the minimum 0.2 lbs (0.1 kg); if the
|
|
/// user's weight would drop below the minimum, it becomes the minimum instead." A first use on a Pokémon
|
|
/// lighter than 100 kg still applies the weight reduction (the weight clamps to the minimum).
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_FirstUseOnLightPokemon_StillAppliesWeightReduction()
|
|
{
|
|
// Arrange - 50 kg Pokémon, no previous Autotomize use
|
|
var (script, move, _, userVolatile, _) = CreateTestSetup(50f, true);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
|
|
|
|
// Assert
|
|
await Assert.That(ReceivedStackOrAdd(userVolatile)).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Weight loss from Autotomize stacks, so using it multiple times will continue to decrease
|
|
/// the user's weight accordingly until it reaches the minimum weight" and "if the user's weight would drop
|
|
/// below the minimum, it becomes the minimum instead." A Pokémon that still weighs more than the minimum
|
|
/// after two stacks must receive another stack (its weight drops to the 0.1 kg minimum).
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_WeightWouldDropBelowMinimum_StillReducesToMinimum()
|
|
{
|
|
// Arrange - the user already has two stacks and currently weighs 50 kg
|
|
var existingEffect = new AutotomizeEffect();
|
|
existingEffect.Stack();
|
|
var (script, move, _, userVolatile, _) = CreateTestSetup(50f, true, existingEffect);
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
|
|
|
|
// Assert - the weight should still be reduced (to the minimum)
|
|
await Assert.That(ReceivedStackOrAdd(userVolatile)).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Autotomize cannot decrease the user's weight below the minimum 0.2 lbs (0.1 kg)".
|
|
/// A Pokémon already at the minimum weight cannot lose more weight, so no new stack is added and no
|
|
/// message is shown; the Speed boost itself is still applied.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnSecondaryEffect_AlreadyAtMinimumWeight_NoFurtherReductionButSpeedStillRaised()
|
|
{
|
|
// Arrange - the user already has a stack and is at the minimum weight
|
|
var (script, move, user, userVolatile, eventHook) = CreateTestSetup(0.1f, true, new AutotomizeEffect());
|
|
var eventFired = false;
|
|
eventHook.Handler += (_, _) => eventFired = true;
|
|
|
|
// Act
|
|
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
|
|
|
|
// Assert
|
|
user.Received(1).ChangeStatBoost(Statistic.Speed, 2, true, false);
|
|
await Assert.That(ReceivedStackOrAdd(userVolatile)).IsFalse();
|
|
await Assert.That(eventFired).IsFalse();
|
|
}
|
|
} |