173 lines
6.7 KiB
C#
173 lines
6.7 KiB
C#
using PkmnLib.Dynamic.Models;
|
|
using PkmnLib.Dynamic.ScriptHandling;
|
|
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
|
using PkmnLib.Static.Moves;
|
|
using PkmnLib.Static.Utils;
|
|
|
|
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
|
|
|
/// <summary>
|
|
/// Tests for the <see cref="FuryCutter"/> move script and its <see cref="FuryCutterEffect"/> volatile.
|
|
/// Gen VII Bulbapedia behavior: "Every time Fury Cutter hits the power will double", and (Generation VI
|
|
/// onwards) "Fury Cutter's base power increased even further from 20 to 40, meaning that it takes three
|
|
/// consecutive turns to reach the maximum power of 160."
|
|
/// </summary>
|
|
public class FuryCutterTests
|
|
{
|
|
/// <summary>
|
|
/// Creates a fully mocked test setup where the user's volatile scripts are a real
|
|
/// <see cref="ScriptSet"/>, so the <see cref="FuryCutterEffect"/> added by the move can be inspected.
|
|
/// </summary>
|
|
private static (FuryCutter script, IExecutingMove move, IPokemon target, IPokemon user, ScriptSet userVolatile)
|
|
CreateTestSetup()
|
|
{
|
|
var script = new FuryCutter();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
var target = Substitute.For<IPokemon>();
|
|
var user = Substitute.For<IPokemon>();
|
|
var userVolatile = new ScriptSet(user);
|
|
user.Volatile.Returns(userVolatile);
|
|
user.GetScripts().Returns(_ => new ScriptIterator(Array.Empty<IEnumerable<ScriptContainer>>()));
|
|
move.User.Returns(user);
|
|
return (script, move, target, user, userVolatile);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Simulates the given number of consecutive uses of Fury Cutter, feeding the Gen VII base power of 40
|
|
/// into each use, and returns the base power of the final use.
|
|
/// </summary>
|
|
private static ushort SimulateConsecutiveUses(FuryCutter script, IExecutingMove move, IPokemon target, int uses)
|
|
{
|
|
ushort basePower = 40;
|
|
for (var i = 0; i < uses; i++)
|
|
{
|
|
basePower = 40;
|
|
script.ChangeBasePower(move, target, 0, ref basePower);
|
|
}
|
|
|
|
return basePower;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation VI onwards): "Fury Cutter's base power increased even further from 20 to 40" —
|
|
/// on the first use there is no previous hit, so the base power is not modified.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeBasePower_FirstUse_BasePowerUnchanged()
|
|
{
|
|
// Arrange
|
|
var (script, move, target, _, _) = CreateTestSetup();
|
|
|
|
// Act
|
|
var basePower = SimulateConsecutiveUses(script, move, target, 1);
|
|
|
|
// Assert
|
|
await Assert.That(basePower).IsEqualTo((ushort)40);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: the power doubles on consecutive hits — the first use attaches the
|
|
/// <see cref="FuryCutterEffect"/> volatile to the user so the next use is recognized as consecutive.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeBasePower_FirstUse_AddsFuryCutterEffectToUser()
|
|
{
|
|
// Arrange
|
|
var (script, move, target, _, userVolatile) = CreateTestSetup();
|
|
|
|
// Act
|
|
SimulateConsecutiveUses(script, move, target, 1);
|
|
|
|
// Assert
|
|
await Assert.That(userVolatile.Contains(ScriptUtils.ResolveName<FuryCutterEffect>())).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Every time Fury Cutter hits the power will double" — the second consecutive use has
|
|
/// power 80 and the third consecutive use reaches the maximum of 160.
|
|
/// </summary>
|
|
[Test, Arguments(2, (ushort)80), Arguments(3, (ushort)160)]
|
|
public async Task ChangeBasePower_ConsecutiveUses_PowerDoublesEachTurn(int uses, ushort expectedPower)
|
|
{
|
|
// Arrange
|
|
var (script, move, target, _, _) = CreateTestSetup();
|
|
|
|
// Act
|
|
var basePower = SimulateConsecutiveUses(script, move, target, uses);
|
|
|
|
// Assert
|
|
await Assert.That(basePower).IsEqualTo(expectedPower);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation VI onwards): "it takes three consecutive turns to reach the maximum power of
|
|
/// 160" — uses beyond the third consecutive turn stay capped at 160 and do not keep doubling.
|
|
/// </summary>
|
|
[Test, Arguments(4), Arguments(5), Arguments(6)]
|
|
public async Task ChangeBasePower_BeyondThirdConsecutiveUse_PowerCappedAt160(int uses)
|
|
{
|
|
// Arrange
|
|
var (script, move, target, _, _) = CreateTestSetup();
|
|
|
|
// Act
|
|
var basePower = SimulateConsecutiveUses(script, move, target, uses);
|
|
|
|
// Assert
|
|
await Assert.That(basePower).IsEqualTo((ushort)160);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia (Generation V onwards): "If another move is selected, its power resets to normal." — when
|
|
/// the user executes a different move, the <see cref="FuryCutterEffect"/> removes itself, resetting the
|
|
/// doubling progression.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnBeforeMove_DifferentMoveUsed_EffectRemovesItself()
|
|
{
|
|
// Arrange
|
|
var user = Substitute.For<IPokemon>();
|
|
user.GetScripts().Returns(_ => new ScriptIterator(Array.Empty<IEnumerable<ScriptContainer>>()));
|
|
var userVolatile = new ScriptSet(user);
|
|
var effect = new FuryCutterEffect();
|
|
userVolatile.Add(effect);
|
|
|
|
var otherMove = Substitute.For<IExecutingMove>();
|
|
var otherMoveData = Substitute.For<IMoveData>();
|
|
otherMoveData.Name.Returns(new StringKey("tackle"));
|
|
otherMove.UseMove.Returns(otherMoveData);
|
|
|
|
// Act
|
|
effect.OnBeforeMove(otherMove);
|
|
|
|
// Assert
|
|
await Assert.That(userVolatile.Contains(ScriptUtils.ResolveName<FuryCutterEffect>())).IsFalse();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: the doubling continues on "consecutive turns" — when Fury Cutter is used again, the
|
|
/// <see cref="FuryCutterEffect"/> stays on the user so the progression continues.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task OnBeforeMove_FuryCutterUsedAgain_EffectPersists()
|
|
{
|
|
// Arrange
|
|
var user = Substitute.For<IPokemon>();
|
|
user.GetScripts().Returns(_ => new ScriptIterator(Array.Empty<IEnumerable<ScriptContainer>>()));
|
|
var userVolatile = new ScriptSet(user);
|
|
var effect = new FuryCutterEffect();
|
|
userVolatile.Add(effect);
|
|
|
|
var furyCutterMove = Substitute.For<IExecutingMove>();
|
|
var furyCutterMoveData = Substitute.For<IMoveData>();
|
|
furyCutterMoveData.Name.Returns(new StringKey("fury_cutter"));
|
|
furyCutterMove.UseMove.Returns(furyCutterMoveData);
|
|
|
|
// Act
|
|
effect.OnBeforeMove(furyCutterMove);
|
|
|
|
// Assert
|
|
await Assert.That(userVolatile.Contains(ScriptUtils.ResolveName<FuryCutterEffect>())).IsTrue();
|
|
}
|
|
} |