This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Dynamic.ScriptHandling;
|
||||
using PkmnLib.Dynamic.ScriptHandling.Registry;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Pokemon;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="LaserFocus"/> move script and its volatile effect script
|
||||
/// <see cref="LaserFocusEffect"/>.
|
||||
/// Gen VII Bulbapedia behavior: "Laser Focus causes the user's move to result in a critical hit until the
|
||||
/// end of the next turn, unless that move's target has Battle Armor, Shell Armor, or is under the effect
|
||||
/// of Lucky Chant."
|
||||
/// </summary>
|
||||
public class LaserFocusTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a real <see cref="ScriptSet"/> hosting the given effect, so that
|
||||
/// <see cref="Script.RemoveSelf"/> calls can be observed through <see cref="IScriptSet.Contains"/>.
|
||||
/// </summary>
|
||||
private static IScriptSet CreateHostedSet(Script effect)
|
||||
{
|
||||
var owner = Substitute.For<IPokemon>();
|
||||
owner.GetScripts().Returns(_ => new ScriptIterator(Array.Empty<IEnumerable<ScriptContainer>>()));
|
||||
IScriptSet set = new ScriptSet(owner);
|
||||
set.Add(effect);
|
||||
return set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Laser Focus causes the user's move to result in a critical hit" — using the move places
|
||||
/// the <see cref="LaserFocusEffect"/> on the target (Laser Focus targets the user itself).
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnSecondaryEffect_Used_AddsLaserFocusEffectToTarget()
|
||||
{
|
||||
// Arrange
|
||||
var script = new LaserFocus();
|
||||
var move = Substitute.For<IExecutingMove>();
|
||||
var target = Substitute.For<IPokemon>();
|
||||
var targetVolatile = Substitute.For<IScriptSet>();
|
||||
target.Volatile.Returns(targetVolatile);
|
||||
|
||||
// Act
|
||||
script.OnSecondaryEffect(move, target, 0);
|
||||
|
||||
// Assert
|
||||
targetVolatile.Received(1).Add(Arg.Any<LaserFocusEffect>());
|
||||
await Assert.That(targetVolatile.ReceivedCalls().Count(c => c.GetMethodInfo().Name == "Add")).IsEqualTo(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the user's move will "result in a critical hit" — the effect raises the critical stage
|
||||
/// to at least 3, which the Gen 7 damage calculator treats as a guaranteed critical hit.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeCriticalStage_EffectActive_GuaranteesCriticalHit()
|
||||
{
|
||||
// Arrange
|
||||
var effect = new LaserFocusEffect();
|
||||
var move = Substitute.For<IExecutingMove>();
|
||||
var target = Substitute.For<IPokemon>();
|
||||
byte stage = 0;
|
||||
|
||||
// Act
|
||||
effect.ChangeCriticalStage(move, target, 0, ref stage);
|
||||
|
||||
// Assert
|
||||
await Assert.That(stage).IsGreaterThanOrEqualTo((byte)3);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the guarantee lasts "until the end of the next turn" — it is not consumed by a single
|
||||
/// critical-stage check, so e.g. every hit of a multi-hit move is a critical hit.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeCriticalStage_AfterFirstCheck_EffectStillActive()
|
||||
{
|
||||
// Arrange
|
||||
var effect = new LaserFocusEffect();
|
||||
var set = CreateHostedSet(effect);
|
||||
var move = Substitute.For<IExecutingMove>();
|
||||
var target = Substitute.For<IPokemon>();
|
||||
byte stage = 0;
|
||||
|
||||
// Act
|
||||
effect.ChangeCriticalStage(move, target, 0, ref stage);
|
||||
|
||||
// Assert
|
||||
await Assert.That(set.Contains(ScriptUtils.ResolveName<LaserFocusEffect>())).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the guarantee lasts "until the end of the next turn" — at the end of the turn Laser
|
||||
/// Focus was used the effect is still active, so the move used on the following turn is a critical hit.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnEndTurn_EndOfTurnUsed_EffectStillActive()
|
||||
{
|
||||
// Arrange
|
||||
var effect = new LaserFocusEffect();
|
||||
var set = CreateHostedSet(effect);
|
||||
|
||||
// Act - the end of the turn Laser Focus was used
|
||||
if (effect is IScriptOnEndTurn onEndTurn)
|
||||
onEndTurn.OnEndTurn(Substitute.For<IScriptSource>(), Substitute.For<IBattle>());
|
||||
|
||||
// Assert
|
||||
await Assert.That(set.Contains(ScriptUtils.ResolveName<LaserFocusEffect>())).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: the guarantee only lasts "until the end of the next turn" — if the user does not move,
|
||||
/// the effect expires at the end of the turn after it was used.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task OnEndTurn_EndOfNextTurn_EffectExpires()
|
||||
{
|
||||
// Arrange
|
||||
var effect = new LaserFocusEffect();
|
||||
var set = CreateHostedSet(effect);
|
||||
|
||||
// Act - end of the turn Laser Focus was used, and end of the next turn
|
||||
if (effect is IScriptOnEndTurn onEndTurn)
|
||||
{
|
||||
onEndTurn.OnEndTurn(Substitute.For<IScriptSource>(), Substitute.For<IBattle>());
|
||||
onEndTurn.OnEndTurn(Substitute.For<IScriptSource>(), Substitute.For<IBattle>());
|
||||
}
|
||||
|
||||
// Assert
|
||||
await Assert.That(set.Contains(ScriptUtils.ResolveName<LaserFocusEffect>())).IsFalse();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user