This commit is contained in:
@@ -15,10 +15,6 @@ namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
||||
/// </summary>
|
||||
public class MimicTests
|
||||
{
|
||||
private const string NotImplementedReason =
|
||||
"Mimic is not implemented: Mimic.cs contains only a FIXME comment and implements no script hooks, so " +
|
||||
"the move has no effect (Bulbapedia: 'Mimic copies a move from the target')";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a mocked <see cref="ILearnedMove"/> whose move data has the given name.
|
||||
/// </summary>
|
||||
@@ -46,9 +42,12 @@ public class MimicTests
|
||||
move.GetHitData(target, 0).Returns(hitData);
|
||||
|
||||
// The user knows another move in slot 0, and Mimic in slot 1; Mimic is the chosen move.
|
||||
// The moves are created before the Returns call, as creating substitutes inside Returns arguments
|
||||
// resets NSubstitute's last-call tracking.
|
||||
var mimicMove = CreateLearnedMove("mimic");
|
||||
move.ChosenMove.Returns(mimicMove);
|
||||
user.Moves.Returns(new[] { CreateLearnedMove(userOtherMove), mimicMove });
|
||||
var userMoves = new[] { CreateLearnedMove(userOtherMove), mimicMove };
|
||||
user.Moves.Returns(userMoves);
|
||||
|
||||
var battleData = Substitute.For<IPokemonBattleData>();
|
||||
if (targetLastUsedMove != null)
|
||||
@@ -85,11 +84,11 @@ public class MimicTests
|
||||
hitData.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Fail");
|
||||
|
||||
/// <summary>
|
||||
/// Helper to extract the arguments of the user's received <see cref="IPokemon.LearnMove"/> call.
|
||||
/// Helper to extract the arguments of the user's received <see cref="IPokemon.LearnTemporaryMove"/> call.
|
||||
/// </summary>
|
||||
private static (StringKey moveName, byte index)? GetLearnedMove(IPokemon user)
|
||||
{
|
||||
var call = user.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "LearnMove");
|
||||
var call = user.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "LearnTemporaryMove");
|
||||
if (call == null)
|
||||
return null;
|
||||
return ((StringKey)call.GetArguments()[0]!, (byte)call.GetArguments()[2]!);
|
||||
@@ -100,7 +99,7 @@ public class MimicTests
|
||||
/// place" and (Generation II onwards) "Mimic now copies the target's last used move."
|
||||
/// The target's last used move must be learned in the move slot that holds Mimic.
|
||||
/// </summary>
|
||||
[Test, TestFailing(NotImplementedReason)]
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetUsedMove_UserLearnsTargetsLastMoveInMimicsSlot()
|
||||
{
|
||||
// Arrange
|
||||
@@ -121,7 +120,7 @@ public class MimicTests
|
||||
/// Bulbapedia: (Generation II onwards) "Mimic now copies the target's last used move."
|
||||
/// If the target has not used a move yet, there is nothing to copy and the hit must fail.
|
||||
/// </summary>
|
||||
[Test, TestFailing(NotImplementedReason)]
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetHasNotUsedAMove_FailsHit()
|
||||
{
|
||||
// Arrange
|
||||
@@ -141,8 +140,8 @@ public class MimicTests
|
||||
/// Metronome, or any move the user already knows.", (Generation IV onwards) "Mimic will fail to copy
|
||||
/// Chatter.", and (Generation V onwards) "Mimic is no longer able to copy Transform."
|
||||
/// </summary>
|
||||
[Test, TestFailing(NotImplementedReason), Arguments("sketch"), Arguments("transform"), Arguments("struggle"),
|
||||
Arguments("metronome"), Arguments("chatter")]
|
||||
[Test, Arguments("sketch"), Arguments("transform"), Arguments("struggle"), Arguments("metronome"),
|
||||
Arguments("chatter")]
|
||||
public async Task OnSecondaryEffect_TargetsLastMoveIsUncopyable_FailsHit(string uncopyableMove)
|
||||
{
|
||||
// Arrange
|
||||
@@ -160,7 +159,7 @@ public class MimicTests
|
||||
/// <summary>
|
||||
/// Bulbapedia: (Generation II onwards) "It now fails to copy ... any move the user already knows."
|
||||
/// </summary>
|
||||
[Test, TestFailing(NotImplementedReason)]
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_UserAlreadyKnowsTargetsLastMove_FailsHit()
|
||||
{
|
||||
// Arrange
|
||||
@@ -175,4 +174,22 @@ public class MimicTests
|
||||
await Assert.That(ReceivedFail(hitData)).IsTrue();
|
||||
await Assert.That(GetLearnedMove(user).HasValue).IsFalse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: (Generation II onwards) "The copied move will also only have 5 PP".
|
||||
/// After learning the copy, its current PP must be set to 5.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_TargetUsedMove_CopiedMoveGetsFivePP()
|
||||
{
|
||||
// Arrange
|
||||
var mimic = await GetSecondaryEffectHook();
|
||||
var (move, user, target, _) = CreateTestSetup("tackle");
|
||||
|
||||
// Act
|
||||
mimic.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert - the move in Mimic's slot (slot 1) has its PP set to 5.
|
||||
user.Moves[1]!.Received(1).SetCurrentPP(5);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,43 @@
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Mimic copies the target's last used move into the move slot Mimic occupies, with 5 PP, until the user
|
||||
/// leaves the field. It fails if the target has not used a move, if that move is Sketch, Transform, Struggle,
|
||||
/// Metronome, or Chatter, or if the user already knows it.
|
||||
///
|
||||
/// <see href="https://bulbapedia.bulbagarden.net/wiki/Mimic_(move)">Bulbapedia - Mimic</see>
|
||||
/// </summary>
|
||||
[Script(ScriptCategory.Move, "mimic")]
|
||||
public class Mimic : Script
|
||||
public class Mimic : Script, IScriptOnSecondaryEffect
|
||||
{
|
||||
// FIXME: support for temporarily copying moves to a move slot.
|
||||
/// <inheritdoc />
|
||||
public void OnSecondaryEffect(IExecutingMove move, IPokemon target, byte hit)
|
||||
{
|
||||
var moveSlot = move.User.Moves.IndexOf(move.ChosenMove);
|
||||
if (moveSlot == -1)
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
|
||||
var lastMove = target.BattleData?.LastMoveChoice;
|
||||
if (lastMove == null || !lastMove.ChosenMove.MoveData.CanCopyMove())
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
|
||||
var copiedMoveName = lastMove.ChosenMove.MoveData.Name;
|
||||
if (move.User.Moves.Any(m => m?.MoveData.Name == copiedMoveName))
|
||||
{
|
||||
move.GetHitData(target, hit).Fail();
|
||||
return;
|
||||
}
|
||||
|
||||
move.User.LearnTemporaryMove(copiedMoveName, MoveLearnMethod.Mimic, (byte)moveSlot);
|
||||
// The copied move only has 5 PP, or its own maximum PP if that is lower.
|
||||
move.User.Moves[moveSlot]?.SetCurrentPP(5);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user