253 lines
9.3 KiB
C#
253 lines
9.3 KiB
C#
using PkmnLib.Dynamic.Models;
|
|
using PkmnLib.Dynamic.Models.Choices;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
|
using PkmnLib.Static.Moves;
|
|
using PkmnLib.Static.Utils;
|
|
|
|
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
|
|
|
/// <summary>
|
|
/// Tests for the <see cref="FusionFlare"/> move script.
|
|
/// Gen VII Bulbapedia behavior: "Fusion Flare inflicts damage. The base power of Fusion Flare will double
|
|
/// if any Pokémon has successfully used Fusion Bolt previously in the same turn, with no intervening moves
|
|
/// in between, except perhaps for failed moves."
|
|
/// </summary>
|
|
public class FusionFlareTests
|
|
{
|
|
/// <summary>
|
|
/// Creates a concrete <see cref="MoveChoice"/> whose chosen move has the given name. Concrete choices
|
|
/// are required because the script filters the turn's choices by the <see cref="MoveChoice"/> type.
|
|
/// </summary>
|
|
private static MoveChoice CreateMoveChoice(string moveName, bool failed = false)
|
|
{
|
|
var moveData = Substitute.For<IMoveData>();
|
|
moveData.Name.Returns(new StringKey(moveName));
|
|
moveData.SecondaryEffect.Returns((ISecondaryEffect?)null);
|
|
var learnedMove = Substitute.For<ILearnedMove>();
|
|
learnedMove.MoveData.Returns(moveData);
|
|
var user = Substitute.For<IPokemon>();
|
|
var choice = new MoveChoice(user, learnedMove, 0, 0);
|
|
if (failed)
|
|
choice.Fail();
|
|
return choice;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a fully mocked test setup where the current turn consists of the given choices, executed in
|
|
/// order, and the script is evaluating the given executing choice.
|
|
/// </summary>
|
|
private static (FusionFlare script, IExecutingMove move, IPokemon target) CreateTestSetup(
|
|
IMoveChoice executingChoice, params ITurnChoice[] currentTurnChoices)
|
|
{
|
|
var script = new FusionFlare();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
move.MoveChoice.Returns(executingChoice);
|
|
|
|
var battle = Substitute.For<IBattle>();
|
|
battle.PreviousTurnChoices.Returns(new List<IReadOnlyList<ITurnChoice>> { currentTurnChoices });
|
|
|
|
var battleData = Substitute.For<IPokemonBattleData>();
|
|
battleData.Battle.Returns(battle);
|
|
var target = Substitute.For<IPokemon>();
|
|
target.BattleData.Returns(battleData);
|
|
|
|
return (script, move, target);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "The base power of Fusion Flare will double if any Pokémon has successfully used Fusion
|
|
/// Bolt previously in the same turn".
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_FusionBoltUsedEarlierInTurn_ModifierDoubles()
|
|
{
|
|
// Arrange
|
|
var flareChoice = CreateMoveChoice("fusion_flare");
|
|
var boltChoice = CreateMoveChoice("fusion_bolt");
|
|
var (script, move, target) = CreateTestSetup(flareChoice, boltChoice, flareChoice);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(2f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: the power only doubles "if any Pokémon has successfully used Fusion Bolt previously in
|
|
/// the same turn" — with no Fusion Bolt used this turn, the modifier stays unchanged.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_NoFusionBoltInTurn_ModifierUnchanged()
|
|
{
|
|
// Arrange
|
|
var flareChoice = CreateMoveChoice("fusion_flare");
|
|
var tackleChoice = CreateMoveChoice("tackle");
|
|
var (script, move, target) = CreateTestSetup(flareChoice, tackleChoice, flareChoice);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(1f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: Fusion Bolt must have been used "previously in the same turn" — a Fusion Bolt that
|
|
/// executes after this Fusion Flare does not boost it.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_FusionBoltLaterInTurn_ModifierUnchanged()
|
|
{
|
|
// Arrange
|
|
var flareChoice = CreateMoveChoice("fusion_flare");
|
|
var boltChoice = CreateMoveChoice("fusion_bolt");
|
|
var (script, move, target) = CreateTestSetup(flareChoice, flareChoice, boltChoice);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(1f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: the boost only applies "in the same turn" — a Fusion Bolt used on the previous turn does
|
|
/// not double this turn's Fusion Flare.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_FusionBoltOnPreviousTurn_ModifierUnchanged()
|
|
{
|
|
// Arrange
|
|
var flareChoice = CreateMoveChoice("fusion_flare");
|
|
var boltChoice = CreateMoveChoice("fusion_bolt");
|
|
var script = new FusionFlare();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
move.MoveChoice.Returns(flareChoice);
|
|
|
|
var battle = Substitute.For<IBattle>();
|
|
battle.PreviousTurnChoices.Returns(new List<IReadOnlyList<ITurnChoice>>
|
|
{
|
|
new ITurnChoice[] { boltChoice },
|
|
new ITurnChoice[] { flareChoice },
|
|
});
|
|
|
|
var battleData = Substitute.For<IPokemonBattleData>();
|
|
battleData.Battle.Returns(battle);
|
|
var target = Substitute.For<IPokemon>();
|
|
target.BattleData.Returns(battleData);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(1f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: the boost requires Fusion Bolt "with no intervening moves in between" — another
|
|
/// successful move executed between Fusion Bolt and Fusion Flare breaks the combination.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_SuccessfulMoveBetweenBoltAndFlare_ModifierUnchanged()
|
|
{
|
|
// Arrange
|
|
var flareChoice = CreateMoveChoice("fusion_flare");
|
|
var boltChoice = CreateMoveChoice("fusion_bolt");
|
|
var tackleChoice = CreateMoveChoice("tackle");
|
|
var (script, move, target) = CreateTestSetup(flareChoice, boltChoice, tackleChoice, flareChoice);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(1f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "with no intervening moves in between, except perhaps for failed moves" — a failed move
|
|
/// between Fusion Bolt and Fusion Flare does not break the combination.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_FailedMoveBetweenBoltAndFlare_ModifierStillDoubles()
|
|
{
|
|
// Arrange
|
|
var flareChoice = CreateMoveChoice("fusion_flare");
|
|
var boltChoice = CreateMoveChoice("fusion_bolt");
|
|
var failedTackleChoice = CreateMoveChoice("tackle", true);
|
|
var (script, move, target) = CreateTestSetup(flareChoice, boltChoice, failedTackleChoice, flareChoice);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(2f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: the boost requires that a Pokémon "has successfully used Fusion Bolt" — a Fusion Bolt
|
|
/// that failed does not double the power.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_FusionBoltFailed_ModifierUnchanged()
|
|
{
|
|
// Arrange
|
|
var flareChoice = CreateMoveChoice("fusion_flare");
|
|
var failedBoltChoice = CreateMoveChoice("fusion_bolt", true);
|
|
var (script, move, target) = CreateTestSetup(flareChoice, failedBoltChoice, flareChoice);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(1f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: only Fusion Bolt boosts Fusion Flare — another Fusion Flare used earlier in the turn
|
|
/// does not double the power.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_AnotherFusionFlareUsedEarlier_ModifierUnchanged()
|
|
{
|
|
// Arrange
|
|
var flareChoice = CreateMoveChoice("fusion_flare");
|
|
var earlierFlareChoice = CreateMoveChoice("fusion_flare");
|
|
var (script, move, target) = CreateTestSetup(flareChoice, earlierFlareChoice, flareChoice);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(1f);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Technical test: outside of battle (no battle data on the target) the modifier is left unchanged and
|
|
/// the hook does not throw.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task ChangeDamageModifier_TargetHasNoBattleData_ModifierUnchanged()
|
|
{
|
|
// Arrange
|
|
var script = new FusionFlare();
|
|
var move = Substitute.For<IExecutingMove>();
|
|
var target = Substitute.For<IPokemon>();
|
|
target.BattleData.Returns((IPokemonBattleData?)null);
|
|
var modifier = 1f;
|
|
|
|
// Act
|
|
script.ChangeDamageModifier(move, target, 0, ref modifier);
|
|
|
|
// Assert
|
|
await Assert.That(modifier).IsEqualTo(1f);
|
|
}
|
|
} |