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

@@ -20,24 +20,22 @@ public class FireFangTests
/// Creates a fully mocked test setup for Fire Fang tests. The target has not yet moved this turn when
/// <paramref name="queue"/> contains a choice for it.
/// </summary>
private static (FireFang script, IExecutingMove move, IPokemon user, IPokemon target, IBattleRandom random,
IScriptSet targetVolatile) CreateTestSetup(BattleChoiceQueue? queue)
private static (FireFang script, IExecutingMove move, IBattlePokemon user, IBattlePokemon target, IBattleRandom
random, IScriptSet targetVolatile) CreateTestSetup(BattleChoiceQueue? queue)
{
var script = new FireFang();
var move = Substitute.For<IExecutingMove>();
var user = Substitute.For<IPokemon>();
var user = Substitute.For<IBattlePokemon>();
move.User.Returns(user);
var random = Substitute.For<IBattleRandom>();
var battle = Substitute.For<IBattle>();
battle.Random.Returns(random);
battle.ChoiceQueue.Returns(queue);
var battleData = Substitute.For<IPokemonBattleData>();
battleData.Battle.Returns(battle);
var target = Substitute.For<IPokemon>();
target.BattleData.Returns(battleData);
var target = Substitute.For<IBattlePokemon>();
var targetVolatile = Substitute.For<IScriptSet>();
target.Battle.Returns(battle);
target.Volatile.Returns(targetVolatile);
return (script, move, user, target, random, targetVolatile);
@@ -46,7 +44,7 @@ public class FireFangTests
/// <summary>
/// Creates a choice queue containing a single yet-to-execute move choice for the given Pokémon.
/// </summary>
private static BattleChoiceQueue CreateQueueWithChoiceFor(IPokemon pokemon)
private static BattleChoiceQueue CreateQueueWithChoiceFor(IBattlePokemon pokemon)
{
var choice = Substitute.For<IMoveChoice>();
choice.User.Returns(pokemon);
@@ -58,7 +56,7 @@ public class FireFangTests
/// matchers cannot be used for <see cref="EventBatchId"/> parameters: its parameterless constructor
/// generates a random Guid, which breaks NSubstitute's argument specification binding.)
/// </summary>
private static bool ReceivedSetStatus(IPokemon pokemon) =>
private static bool ReceivedSetStatus(IBattlePokemon pokemon) =>
pokemon.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "SetStatus");
/// <summary>
@@ -126,7 +124,7 @@ public class FireFangTests
// Arrange
var (script, move, _, target, random, targetVolatile) = CreateTestSetup(null);
var queue = CreateQueueWithChoiceFor(target);
target.BattleData!.Battle.ChoiceQueue.Returns(queue);
target.Battle.ChoiceQueue.Returns(queue);
random.EffectChance(10, move, target, 0).Returns(true, true);
// Act
@@ -147,7 +145,7 @@ public class FireFangTests
// Arrange
var (script, move, _, target, random, targetVolatile) = CreateTestSetup(null);
var queue = CreateQueueWithChoiceFor(target);
target.BattleData!.Battle.ChoiceQueue.Returns(queue);
target.Battle.ChoiceQueue.Returns(queue);
// First roll (burn) fails, second roll (flinch) succeeds.
random.EffectChance(10, move, target, 0).Returns(false, true);
@@ -170,8 +168,8 @@ public class FireFangTests
// Arrange
var (script, move, _, target, random, targetVolatile) = CreateTestSetup(null);
// The queue only holds a choice for some other Pokémon; the target's choice already executed.
var queue = CreateQueueWithChoiceFor(Substitute.For<IPokemon>());
target.BattleData!.Battle.ChoiceQueue.Returns(queue);
var queue = CreateQueueWithChoiceFor(Substitute.For<IBattlePokemon>());
target.Battle.ChoiceQueue.Returns(queue);
random.EffectChance(10, move, target, 0).Returns(true, true);
// Act
@@ -199,26 +197,4 @@ public class FireFangTests
target.Received(1).SetStatus("burned", user);
targetVolatile.DidNotReceive().Add(Arg.Any<Script>());
}
/// <summary>
/// Technical test: if the target has no <see cref="IPokemon.BattleData"/>, the script does nothing.
/// </summary>
[Test]
public async Task OnSecondaryEffect_TargetHasNoBattleData_DoesNothing()
{
// Arrange
var script = new FireFang();
var move = Substitute.For<IExecutingMove>();
var target = Substitute.For<IPokemon>();
target.BattleData.Returns((IPokemonBattleData?)null);
var targetVolatile = Substitute.For<IScriptSet>();
target.Volatile.Returns(targetVolatile);
// Act
script.OnSecondaryEffect(move, target, 0);
// Assert
await Assert.That(ReceivedSetStatus(target)).IsFalse();
targetVolatile.DidNotReceive().Add(Arg.Any<Script>());
}
}