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

@@ -47,11 +47,9 @@ public class LightScreenTests
var side = Substitute.For<IBattleSide>();
side.VolatileScripts.Returns(sideScripts);
var battleData = Substitute.For<IPokemonBattleData>();
battleData.BattleSide.Returns(side);
var user = Substitute.For<IPokemon>();
user.BattleData.Returns(battleData);
var user = Substitute.For<IBattlePokemon>();
move.User.Returns(user);
user.BattleSide.Returns(side);
return (script, move, sideScripts);
}
@@ -92,7 +90,7 @@ public class LightScreenTests
/// Creates a mocked incoming move of the given category for <see cref="LightScreenEffect"/> damage
/// tests, with the defending target in a battle with the given amount of positions per side.
/// </summary>
private static (IExecutingMove move, IPokemon target) CreateIncomingMove(MoveCategory category,
private static (IExecutingMove move, IBattlePokemon target) CreateIncomingMove(MoveCategory category,
byte positionsPerSide, bool isCritical = false)
{
var move = Substitute.For<IExecutingMove>();
@@ -100,16 +98,14 @@ public class LightScreenTests
moveData.Category.Returns(category);
move.UseMove.Returns(moveData);
var target = Substitute.For<IPokemon>();
var target = Substitute.For<IBattlePokemon>();
var hitData = Substitute.For<IHitData>();
hitData.IsCritical.Returns(isCritical);
move.GetHitData(target, 0).Returns(hitData);
var battle = Substitute.For<IBattle>();
battle.PositionsPerSide.Returns(positionsPerSide);
var battleData = Substitute.For<IPokemonBattleData>();
battleData.Battle.Returns(battle);
target.BattleData.Returns(battleData);
target.Battle.Returns(battle);
return (move, target);
}
@@ -124,7 +120,7 @@ public class LightScreenTests
var (script, move, sideScripts) = CreateMoveSetup();
// Act
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
script.OnSecondaryEffect(move, Substitute.For<IBattlePokemon>(), 0);
// Assert
await Assert.That(GetAddedEffect(sideScripts)).IsNotNull();
@@ -141,7 +137,7 @@ public class LightScreenTests
var (script, move, sideScripts) = CreateMoveSetup();
// Act
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
script.OnSecondaryEffect(move, Substitute.For<IBattlePokemon>(), 0);
// Assert
var effect = GetAddedEffect(sideScripts);
@@ -164,33 +160,13 @@ public class LightScreenTests
}));
// Act
script.OnSecondaryEffect(move, Substitute.For<IPokemon>(), 0);
script.OnSecondaryEffect(move, Substitute.For<IBattlePokemon>(), 0);
// Assert
var effect = GetAddedEffect(sideScripts);
await Assert.That(CountSurvivedEndTurns(effect!, 10)).IsEqualTo(8);
}
/// <summary>
/// Technical test: outside of battle (no <see cref="IPokemon.BattleData"/>) the hook does nothing.
/// </summary>
[Test]
public async Task OnSecondaryEffect_NoBattleData_DoesNothing()
{
// Arrange
var script = new LightScreen();
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 - the script returns before running the duration trigger over the move's scripts
await Assert.That(move.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "GetScripts")).IsFalse();
}
/// <summary>
/// Bulbapedia (Generation III): Light Screen "halves damage from special attacks" — in a single battle
/// the damage of an incoming special move is halved, with integer truncation.