Move all battle state from IPokemon to an ephemeral IBattlePokemon wrapper

This commit is contained in:
2026-08-28 15:20:26 +02:00
parent 942be8eaeb
commit 8a2733a0a9
859 changed files with 4408 additions and 5331 deletions

View File

@@ -22,7 +22,7 @@ public class MeFirstTests
/// <summary>
/// Creates a substitute move choice for the target, queued with the given move name and category.
/// </summary>
private static IMoveChoice CreateTargetMoveChoice(IPokemon target, string moveName,
private static IMoveChoice CreateTargetMoveChoice(IBattlePokemon target, string moveName,
MoveCategory category = MoveCategory.Physical)
{
var moveData = Substitute.For<IMoveData>();
@@ -41,13 +41,13 @@ public class MeFirstTests
/// position 0, where <paramref name="target"/> is standing (or nothing, when null). The battle's
/// choice queue holds the given remaining choices for this turn.
/// </summary>
private static (MeFirst script, IMoveChoice choice) CreateTestSetup(IPokemon? target, ITurnChoice[] queuedChoices,
bool targetChoiceIsReplacement = false)
private static (MeFirst script, IMoveChoice choice) CreateTestSetup(IBattlePokemon? target,
ITurnChoice[] queuedChoices, bool targetChoiceIsReplacement = false)
{
var script = new MeFirst();
var side = Substitute.For<IBattleSide>();
side.Pokemon.Returns(new List<IPokemon?> { target });
side.Pokemon.Returns(new List<IBattlePokemon?> { target });
var miscLibrary = Substitute.For<IMiscLibrary>();
miscLibrary.IsReplacementChoice(Arg.Any<ITurnChoice>()).Returns(targetChoiceIsReplacement);
@@ -59,11 +59,9 @@ public class MeFirstTests
battle.ChoiceQueue.Returns(new BattleChoiceQueue(queuedChoices));
battle.Library.Returns(library);
var battleData = Substitute.For<IPokemonBattleData>();
battleData.Battle.Returns(battle);
var user = Substitute.For<IPokemon>();
user.BattleData.Returns(battleData);
var user = Substitute.For<IBattlePokemon>();
user.Battle.Returns(battle);
var choice = Substitute.For<IMoveChoice>();
choice.User.Returns(user);
choice.TargetSide.Returns((byte)0);
@@ -84,7 +82,7 @@ public class MeFirstTests
public async Task ChangeMove_TargetSelectedDamagingMove_ChangesMoveToTargetsMove()
{
// Arrange
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var targetChoice = CreateTargetMoveChoice(target, "tackle");
var (script, choice) = CreateTestSetup(target, [targetChoice]);
StringKey moveName = "me_first";
@@ -106,7 +104,7 @@ public class MeFirstTests
public async Task ChangeMove_TargetSelectedDamagingMove_AddsPowerBoostVolatile()
{
// Arrange
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var targetChoice = CreateTargetMoveChoice(target, "tackle");
var (script, choice) = CreateTestSetup(target, [targetChoice]);
StringKey moveName = "me_first";
@@ -130,7 +128,7 @@ public class MeFirstTests
// Arrange
var boost = new MeFirstPowerBoost();
var move = Substitute.For<IExecutingMove>();
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
// Act
boost.ChangeBasePower(move, target, 0, ref basePower);
@@ -148,7 +146,7 @@ public class MeFirstTests
public async Task ChangeMove_TargetAlreadyExecutedMove_Fails()
{
// Arrange
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var (script, choice) = CreateTestSetup(target, []);
StringKey moveName = "me_first";
@@ -188,7 +186,7 @@ public class MeFirstTests
public async Task ChangeMove_TargetChoiceIsNotAMoveChoice_Fails()
{
// Arrange
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var switchChoice = Substitute.For<ISwitchChoice>();
switchChoice.User.Returns(target);
var (script, choice) = CreateTestSetup(target, [switchChoice]);
@@ -211,7 +209,7 @@ public class MeFirstTests
public async Task ChangeMove_TargetChoiceIsReplacementChoice_Fails()
{
// Arrange
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var targetChoice = CreateTargetMoveChoice(target, "struggle");
var (script, choice) = CreateTestSetup(target, [targetChoice], true);
StringKey moveName = "me_first";
@@ -224,28 +222,6 @@ public class MeFirstTests
await Assert.That(moveName).IsEqualTo(new StringKey("me_first"));
}
/// <summary>
/// Technical test: outside of battle (no battle data) the script returns without throwing and without
/// changing the move.
/// </summary>
[Test]
public async Task ChangeMove_NoBattleData_DoesNotChangeMove()
{
// Arrange
var script = new MeFirst();
var user = Substitute.For<IPokemon>();
user.BattleData.Returns((IPokemonBattleData?)null);
var choice = Substitute.For<IMoveChoice>();
choice.User.Returns(user);
StringKey moveName = "me_first";
// Act
script.ChangeMove(choice, ref moveName);
// Assert
await Assert.That(moveName).IsEqualTo(new StringKey("me_first"));
}
/// <summary>
/// Bulbapedia: "Me First will fail if the target selected a non-damaging move, or if the target already
/// executed its move this turn."
@@ -255,7 +231,7 @@ public class MeFirstTests
public async Task ChangeMove_TargetSelectedNonDamagingMove_Fails()
{
// Arrange
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var targetChoice = CreateTargetMoveChoice(target, "swords_dance", MoveCategory.Status);
var (script, choice) = CreateTestSetup(target, [targetChoice]);
StringKey moveName = "me_first";
@@ -279,7 +255,7 @@ public class MeFirstTests
public async Task ChangeMove_TargetSelectedUncopyableMove_Fails(string targetMove)
{
// Arrange
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var targetChoice = CreateTargetMoveChoice(target, targetMove);
var (script, choice) = CreateTestSetup(target, [targetChoice]);
StringKey moveName = "me_first";