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

@@ -23,7 +23,7 @@ public class FutureSightTests
/// Creates a fully mocked test setup for the <see cref="FutureSight"/> script where the battle's
/// volatile scripts are a real <see cref="ScriptSet"/>.
/// </summary>
private static (FutureSight script, IExecutingMove move, IPokemon user, IScriptSet battleVolatile)
private static (FutureSight script, IExecutingMove move, IBattlePokemon user, IScriptSet battleVolatile)
CreateScriptSetup()
{
var script = new FutureSight();
@@ -34,11 +34,9 @@ public class FutureSightTests
IScriptSet battleVolatile = new ScriptSet(battle);
battle.Volatile.Returns(battleVolatile);
var battleData = Substitute.For<IPokemonBattleData>();
battleData.Battle.Returns(battle);
var user = Substitute.For<IPokemon>();
user.BattleData.Returns(battleData);
var user = Substitute.For<IBattlePokemon>();
move.User.Returns(user);
user.Battle.Returns(battle);
var moveChoice = Substitute.For<IMoveChoice>();
move.MoveChoice.Returns(moveChoice);
@@ -50,8 +48,8 @@ public class FutureSightTests
/// Creates a fully mocked test setup for the <see cref="FutureSightEffect"/>, with a target at side 1,
/// position 0 and a damage calculator that computes the given damage when the delayed strike lands.
/// </summary>
private static (FutureSightEffect effect, IBattle battle, IPokemon target, EventHook eventHook) CreateEffectSetup(
uint damage = 100, bool targetUsable = true)
private static (FutureSightEffect effect, IBattle battle, IBattlePokemon target, EventHook eventHook)
CreateEffectSetup(uint damage = 100, bool targetUsable = true)
{
var moveData = Substitute.For<IMoveData>();
var learnedMove = Substitute.For<ILearnedMove>();
@@ -65,12 +63,13 @@ public class FutureSightTests
var eventHook = new EventHook();
battle.EventHook.Returns(eventHook);
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
target.IsUsable.Returns(targetUsable);
battle.GetPokemon(1, 0).Returns(target);
battle.Library.DamageCalculator.GetDamage(Arg.Any<IExecutingMove?>(), Arg.Any<MoveCategory>(),
Arg.Any<IPokemon>(), Arg.Any<IPokemon>(), Arg.Any<int>(), Arg.Any<byte>(), Arg.Any<IHitData>())
Arg.Any<IBattlePokemon>(), Arg.Any<IBattlePokemon>(), Arg.Any<int>(), Arg.Any<byte>(),
Arg.Any<IHitData>())
.Returns(damage);
var effect = new FutureSightEffect(moveChoice);
@@ -113,25 +112,6 @@ public class FutureSightTests
await Assert.That(battleVolatile.Contains(ScriptUtils.ResolveName<FutureSightEffect>())).IsTrue();
}
/// <summary>
/// Technical test: outside of battle (no battle data on the user) the hook does nothing and does not
/// stop the move.
/// </summary>
[Test]
public async Task StopBeforeMove_UserHasNoBattleData_DoesNotStopMove()
{
// Arrange
var (script, move, user, _) = CreateScriptSetup();
user.BattleData.Returns((IPokemonBattleData?)null);
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(stop).IsFalse();
}
/// <summary>
/// Bulbapedia: "Two turns later, Future Sight will do damage against the target." One end-of-turn tick
/// after selection (the selection turn itself) plus one more is not enough for the strike to land.
@@ -244,10 +224,8 @@ public class FutureSightTests
moveChoice.TargetSide.Returns(targetSide);
moveChoice.TargetPosition.Returns(targetPosition);
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 move = Substitute.For<IExecutingMove>();
move.User.Returns(user);
@@ -325,15 +303,16 @@ public class FutureSightTests
var (battle, battleVolatile) = CreateBattleWithRealVolatile();
battle.EventHook.Returns(new EventHook());
var targetA = Substitute.For<IPokemon>();
var targetA = Substitute.For<IBattlePokemon>();
targetA.IsUsable.Returns(true);
battle.GetPokemon(1, 0).Returns(targetA);
var targetB = Substitute.For<IPokemon>();
var targetB = Substitute.For<IBattlePokemon>();
targetB.IsUsable.Returns(true);
battle.GetPokemon(1, 1).Returns(targetB);
battle.Library.DamageCalculator.GetDamage(Arg.Any<IExecutingMove?>(), Arg.Any<MoveCategory>(),
Arg.Any<IPokemon>(), Arg.Any<IPokemon>(), Arg.Any<int>(), Arg.Any<byte>(), Arg.Any<IHitData>())
Arg.Any<IBattlePokemon>(), Arg.Any<IBattlePokemon>(), Arg.Any<int>(), Arg.Any<byte>(),
Arg.Any<IHitData>())
.Returns(100u);
var useA = CreateFutureSightUse(battle, 1, 0);