This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Dynamic.Models.Choices;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
using PkmnLib.Static.Species;
|
||||
using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="CoreEnforcer"/> move script.
|
||||
/// Gen VII Bulbapedia behavior: "Core Enforcer deals damage. If the target has already used a move or had
|
||||
/// a Bag item used on it by its Trainer in the same turn, Core Enforcer also suppresses the target's
|
||||
/// Ability while it remains in battle."
|
||||
/// </summary>
|
||||
public class CoreEnforcerTests
|
||||
{
|
||||
private static (CoreEnforcer script, IExecutingMove move, IMoveChoice currentChoice, IPokemon target, IHitData
|
||||
hitData, IBattle battle) CreateTestSetup()
|
||||
{
|
||||
var script = new CoreEnforcer();
|
||||
var battle = Substitute.For<IBattle>();
|
||||
var battleData = Substitute.For<IPokemonBattleData>();
|
||||
battleData.Battle.Returns(battle);
|
||||
var target = Substitute.For<IPokemon>();
|
||||
target.BattleData.Returns(battleData);
|
||||
|
||||
var currentChoice = Substitute.For<IMoveChoice>();
|
||||
var move = Substitute.For<IExecutingMove>();
|
||||
move.MoveChoice.Returns(currentChoice);
|
||||
var hitData = Substitute.For<IHitData>();
|
||||
move.GetHitData(target, 0).Returns(hitData);
|
||||
|
||||
return (script, move, currentChoice, target, hitData, battle);
|
||||
}
|
||||
|
||||
private static void SetTurnChoices(IBattle battle, params ITurnChoice[] choices)
|
||||
{
|
||||
battle.PreviousTurnChoices.Returns(new List<IReadOnlyList<ITurnChoice>> { choices });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If the target has already used a move [...] in the same turn, Core Enforcer also
|
||||
/// suppresses the target's Ability while it remains in battle."
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OnSecondaryEffect_TargetMovedEarlierInTurn_SuppressesTargetAbility()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, currentChoice, target, hitData, battle) = CreateTestSetup();
|
||||
var targetChoice = Substitute.For<IMoveChoice>();
|
||||
targetChoice.User.Returns(target);
|
||||
SetTurnChoices(battle, targetChoice, currentChoice);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
target.Received(1).SuppressAbility();
|
||||
hitData.DidNotReceive().Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the suppression also happens if the target "had a Bag item used on it by its Trainer in
|
||||
/// the same turn".
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OnSecondaryEffect_ItemUsedEarlierInTurn_SuppressesTargetAbility()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, currentChoice, target, hitData, battle) = CreateTestSetup();
|
||||
var itemChoice = Substitute.For<IItemChoice>();
|
||||
itemChoice.User.Returns(target);
|
||||
SetTurnChoices(battle, itemChoice, currentChoice);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
target.Received(1).SuppressAbility();
|
||||
hitData.DidNotReceive().Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the Ability is only suppressed "If the target has already used a move [...] in the same
|
||||
/// turn" — when Core Enforcer strikes before the target has acted, no suppression happens.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OnSecondaryEffect_TargetActsLaterInTurn_DoesNotSuppressAbility()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, currentChoice, target, hitData, battle) = CreateTestSetup();
|
||||
var targetChoice = Substitute.For<IMoveChoice>();
|
||||
targetChoice.User.Returns(target);
|
||||
SetTurnChoices(battle, currentChoice, targetChoice);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
target.DidNotReceive().SuppressAbility();
|
||||
hitData.Received(1).Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: suppression requires the target to have already acted — as the very first action of the
|
||||
/// turn, Core Enforcer never suppresses.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OnSecondaryEffect_CoreEnforcerIsFirstActionOfTurn_DoesNotSuppressAbility()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, currentChoice, target, hitData, battle) = CreateTestSetup();
|
||||
SetTurnChoices(battle, currentChoice);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
target.DidNotReceive().SuppressAbility();
|
||||
hitData.Received(1).Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Technical test: a target without battle data (not in battle) is left untouched.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OnSecondaryEffect_TargetHasNoBattleData_DoesNothing()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, _, target, hitData, _) = CreateTestSetup();
|
||||
target.BattleData.Returns((IPokemonBattleData?)null);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
target.DidNotReceive().SuppressAbility();
|
||||
hitData.DidNotReceive().Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the condition is that "the target has already used a move" — an action by a different
|
||||
/// Pokémon (e.g. the user's ally in a Double Battle) does not count as the target having acted.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void OnSecondaryEffect_OnlyOtherPokemonActedEarlier_DoesNotSuppressAbility()
|
||||
{
|
||||
// Arrange
|
||||
var (script, move, currentChoice, target, hitData, battle) = CreateTestSetup();
|
||||
var allyChoice = Substitute.For<IMoveChoice>();
|
||||
allyChoice.User.Returns(Substitute.For<IPokemon>());
|
||||
SetTurnChoices(battle, allyChoice, currentChoice);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
target.DidNotReceive().SuppressAbility();
|
||||
hitData.Received(1).Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "The move cannot suppress certain signature abilities including Multitype, Stance
|
||||
/// Change, Schooling, Comatose, Shields Down, Disguise, RKS System, Battle Bond, Power Construct".
|
||||
/// The script requests the suppression unconditionally; <see cref="IPokemon.SuppressAbility"/> refuses
|
||||
/// it when <see cref="IAbility.CanBeChanged"/> is false, so these abilities must carry that flag in the
|
||||
/// Gen7 data.
|
||||
/// </summary>
|
||||
[Test, Arguments("multitype"), Arguments("stance_change"), Arguments("schooling"), Arguments("comatose"),
|
||||
Arguments("shields_down"), Arguments("disguise"), Arguments("rks_system"), Arguments("battle_bond"),
|
||||
Arguments("power_construct")]
|
||||
public async Task OnSecondaryEffect_UnsuppressableAbility_IsProtectedByAbilityData(string abilityName)
|
||||
{
|
||||
// Arrange
|
||||
var library = LibraryHelpers.LoadLibrary();
|
||||
|
||||
// Assert
|
||||
await Assert.That(library.StaticLibrary.Abilities.TryGet(new StringKey(abilityName), out var ability)).IsTrue();
|
||||
await Assert.That(ability!.CanBeChanged).IsFalse();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user