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,8 +23,8 @@ public class HealingWishTests
/// side 0 and the given position, and the side's volatile scripts backed by a real
/// <see cref="ScriptSet"/>.
/// </summary>
private static (HealingWish script, IExecutingMove move, IPokemon user, IScriptSet sideVolatile) CreateMoveSetup(
byte position = 1, bool hasUsablePartyMembers = true)
private static (HealingWish script, IExecutingMove move, IBattlePokemon user, IScriptSet sideVolatile)
CreateMoveSetup(byte position = 1, bool hasUsablePartyMembers = true)
{
var script = new HealingWish();
var move = Substitute.For<IExecutingMove>();
@@ -44,14 +44,11 @@ public class HealingWishTests
battle.Sides.Returns(new[] { side });
battle.Parties.Returns(new[] { party });
var battleData = Substitute.For<IPokemonBattleData>();
battleData.Battle.Returns(battle);
battleData.SideIndex.Returns((byte)0);
battleData.Position.Returns(position);
var user = Substitute.For<IPokemon>();
user.BattleData.Returns(battleData);
var user = Substitute.For<IBattlePokemon>();
move.User.Returns(user);
user.Position.Returns(position);
user.SideIndex.Returns((byte)0);
user.Battle.Returns(battle);
return (script, move, user, sideVolatile);
}
@@ -60,9 +57,9 @@ public class HealingWishTests
/// Creates a mocked replacement Pokémon with the given maximum HP for
/// <see cref="HealingWishEffect"/> tests.
/// </summary>
private static IPokemon CreateReplacement(uint maxHp = 200)
private static IBattlePokemon CreateReplacement(uint maxHp = 200)
{
var pokemon = Substitute.For<IPokemon>();
var pokemon = Substitute.For<IBattlePokemon>();
pokemon.BoostedStats.Returns(new StatisticSet<uint>(maxHp, 0, 0, 0, 0, 0));
return pokemon;
}
@@ -71,7 +68,7 @@ public class HealingWishTests
/// Helper to extract the heal amount from a substitute's received Heal calls, or null when Heal was
/// never called.
/// </summary>
private static uint? GetHealAmount(IPokemon pokemon)
private static uint? GetHealAmount(IBattlePokemon pokemon)
{
var call = pokemon.ReceivedCalls().FirstOrDefault(c => c.GetMethodInfo().Name == "Heal");
return call != null ? (uint)call.GetArguments()[0]! : null;
@@ -87,7 +84,7 @@ public class HealingWishTests
var (script, move, user, _) = CreateMoveSetup();
// Act
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
script.OnSecondaryEffect(move, Substitute.For<IBattlePokemon>(), 0);
// Assert
await Assert.That(user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Faint")).IsTrue();
@@ -105,7 +102,7 @@ public class HealingWishTests
var (script, move, _, sideVolatile) = CreateMoveSetup();
// Act
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
script.OnSecondaryEffect(move, Substitute.For<IBattlePokemon>(), 0);
// Assert
await Assert.That(sideVolatile.Contains(ScriptUtils.ResolveName<HealingWishEffect>())).IsTrue();
@@ -120,7 +117,7 @@ public class HealingWishTests
{
// Arrange
var (script, move, _, sideVolatile) = CreateMoveSetup(1);
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
script.OnSecondaryEffect(move, Substitute.For<IBattlePokemon>(), 0);
var effect = (HealingWishEffect)sideVolatile.Get(new StringKey("healing_wish"))!.Script!;
var replacement = CreateReplacement();
@@ -131,27 +128,6 @@ public class HealingWishTests
await Assert.That(GetHealAmount(replacement)).IsNotNull();
}
/// <summary>
/// Technical test: outside of battle (no <see cref="IPokemon.BattleData"/>) the hook does nothing and
/// the user does not faint.
/// </summary>
[Test]
public async Task OnSecondaryEffect_NoBattleData_UserDoesNotFaint()
{
// Arrange
var script = new HealingWish();
var move = Substitute.For<IExecutingMove>();
var user = Substitute.For<IPokemon>();
user.BattleData.Returns((IPokemonBattleData?)null);
move.User.Returns(user);
// Act
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
// Assert
await Assert.That(user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "Faint")).IsFalse();
}
/// <summary>
/// Bulbapedia: "Healing Wish will fail if its Trainer has no other conscious Pokémon in their party".
/// </summary>
@@ -160,7 +136,7 @@ public class HealingWishTests
{
// Arrange
var (script, move, _, _) = CreateMoveSetup(hasUsablePartyMembers: false);
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var hitData = Substitute.For<IHitData>();
move.GetHitData(target, 0).Returns(hitData);
@@ -180,7 +156,7 @@ public class HealingWishTests
{
// Arrange
var (script, move, user, sideVolatile) = CreateMoveSetup(hasUsablePartyMembers: false);
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
move.GetHitData(target, 0).Returns(Substitute.For<IHitData>());
// Act