mirror of
https://github.com/correl/mage.git
synced 2024-11-22 03:00:11 +00:00
Blast-Furnace Hellkite - fixed game error on offering an artifact lands and treasures (#9940, #10218)
This commit is contained in:
parent
d3b976cc46
commit
ce3cf742c9
2 changed files with 50 additions and 40 deletions
|
@ -9,10 +9,8 @@ public class OfferingTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
private static final String nezumiPatron = "Patron of the Nezumi";
|
private static final String nezumiPatron = "Patron of the Nezumi";
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOfferRatDecreaseCC() {
|
public void test_OfferRatDecreaseCC() {
|
||||||
|
|
||||||
String kurosTaken = "Kuro's Taken";
|
String kurosTaken = "Kuro's Taken";
|
||||||
|
|
||||||
addCard(Zone.HAND, playerA, nezumiPatron, 1);
|
addCard(Zone.HAND, playerA, nezumiPatron, 1);
|
||||||
|
@ -22,6 +20,8 @@ public class OfferingTest extends CardTestPlayerBase {
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nezumiPatron);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nezumiPatron);
|
||||||
setChoice(playerA, true);
|
setChoice(playerA, true);
|
||||||
addTarget(playerA, kurosTaken);
|
addTarget(playerA, kurosTaken);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ public class OfferingTest extends CardTestPlayerBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDontOfferRatNotDecreaseCC() {
|
public void test_DontOfferRatNotDecreaseCC() {
|
||||||
|
|
||||||
String kurosTaken = "Kuro's Taken";
|
String kurosTaken = "Kuro's Taken";
|
||||||
|
|
||||||
|
@ -41,6 +41,8 @@ public class OfferingTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nezumiPatron);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, nezumiPatron);
|
||||||
setChoice(playerA, false);
|
setChoice(playerA, false);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
|
@ -48,92 +50,100 @@ public class OfferingTest extends CardTestPlayerBase {
|
||||||
assertPermanentCount(playerA, nezumiPatron, 1);
|
assertPermanentCount(playerA, nezumiPatron, 1);
|
||||||
assertTappedCount("Swamp", true, 7); // {5}{B}{B} - {1}{B} = {4}{B} = 7 swamps tapped
|
assertTappedCount("Swamp", true, 7); // {5}{B}{B} - {1}{B} = {4}{B} = 7 swamps tapped
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCastWithMinimalMana() {
|
public void test_CastWithMinimalMana() {
|
||||||
setStrictChooseMode(true);
|
|
||||||
|
|
||||||
// Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.)
|
// Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.)
|
||||||
// Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn.
|
// Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn.
|
||||||
String patron = "Patron of the Akki"; // Creature {4}{R}{R} (5/5)
|
String patron = "Patron of the Akki"; // Creature {4}{R}{R} (5/5)
|
||||||
|
|
||||||
addCard(Zone.HAND, playerA, patron, 1);
|
addCard(Zone.HAND, playerA, patron, 1);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Akki Drillmaster"); // Creature Goblin {2}{R} (2/2)
|
addCard(Zone.BATTLEFIELD, playerA, "Akki Drillmaster"); // Creature Goblin {2}{R} (2/2)
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, patron);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, patron);
|
||||||
setChoice(playerA, true);
|
setChoice(playerA, true);
|
||||||
addTarget(playerA, "Akki Drillmaster");
|
addTarget(playerA, "Akki Drillmaster");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertPermanentCount(playerA, patron, 1);
|
assertPermanentCount(playerA, patron, 1);
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Akki Drillmaster", 1);
|
assertGraveyardCount(playerA, "Akki Drillmaster", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCastWithBorosRecruit() {
|
public void test_CastWithBorosRecruit() {
|
||||||
setStrictChooseMode(true);
|
|
||||||
|
|
||||||
// Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.)
|
// Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.)
|
||||||
// Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn.
|
// Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn.
|
||||||
String patron = "Patron of the Akki"; // Creature {4}{R}{R} (5/5)
|
String patron = "Patron of the Akki"; // Creature {4}{R}{R} (5/5)
|
||||||
|
|
||||||
addCard(Zone.HAND, playerA, patron, 1);
|
addCard(Zone.HAND, playerA, patron, 1);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||||
|
|
||||||
// First strike
|
// First strike
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Boros Recruit"); // Creature Goblin {R/W} (1/1)
|
addCard(Zone.BATTLEFIELD, playerA, "Boros Recruit"); // Creature Goblin {R/W} (1/1)
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, patron);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, patron);
|
||||||
setChoice(playerA, true);
|
setChoice(playerA, true);
|
||||||
addTarget(playerA, "Boros Recruit");
|
addTarget(playerA, "Boros Recruit");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertPermanentCount(playerA, patron, 1);
|
assertPermanentCount(playerA, patron, 1);
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Boros Recruit", 1);
|
assertGraveyardCount(playerA, "Boros Recruit", 1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCastWithMultipleOptions() {
|
public void test_CastWithMultipleOptions() {
|
||||||
setStrictChooseMode(true);
|
|
||||||
|
|
||||||
// Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.)
|
// Goblin offering (You may cast this card any time you could cast an instant by sacrificing a Goblin and paying the difference in mana costs between this and the sacrificed Goblin. Mana cost includes color.)
|
||||||
// Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn.
|
// Whenever Patron of the Akki attacks, creatures you control get +2/+0 until end of turn.
|
||||||
String patron = "Patron of the Akki"; // Creature {4}{R}{R} (5/5)
|
String patron = "Patron of the Akki"; // Creature {4}{R}{R} (5/5)
|
||||||
|
|
||||||
addCard(Zone.HAND, playerA, patron, 1);
|
addCard(Zone.HAND, playerA, patron, 1);
|
||||||
|
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||||
|
|
||||||
// First strike
|
// First strike
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Boros Recruit"); // Creature Goblin {R/W} (1/1)
|
addCard(Zone.BATTLEFIELD, playerA, "Boros Recruit"); // Creature Goblin {R/W} (1/1)
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Akki Drillmaster"); // Creature Goblin {2}{R} (2/2)
|
addCard(Zone.BATTLEFIELD, playerA, "Akki Drillmaster"); // Creature Goblin {2}{R} (2/2)
|
||||||
addCard(Zone.BATTLEFIELD, playerA, "Boggart Ram-Gang"); // Creature Goblin Warrior {R/G}{R/G}{R/G} (3/3)
|
addCard(Zone.BATTLEFIELD, playerA, "Boggart Ram-Gang"); // Creature Goblin Warrior {R/G}{R/G}{R/G} (3/3)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, patron);
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, patron);
|
||||||
setChoice(playerA, true);
|
setChoice(playerA, true);
|
||||||
addTarget(playerA, "Boggart Ram-Gang");
|
addTarget(playerA, "Boggart Ram-Gang");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
execute();
|
execute();
|
||||||
|
|
||||||
assertPermanentCount(playerA, patron, 1);
|
assertPermanentCount(playerA, patron, 1);
|
||||||
|
|
||||||
assertGraveyardCount(playerA, "Boggart Ram-Gang", 1);
|
assertGraveyardCount(playerA, "Boggart Ram-Gang", 1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
@Test
|
||||||
|
public void test_SacrificeLand() {
|
||||||
|
// bug: sacrifce permanent without a spell ability can cause NPE error
|
||||||
|
|
||||||
|
// Artifact offering
|
||||||
|
addCard(Zone.HAND, playerA, "Blast-Furnace Hellkite", 1); // {7}{R}{R}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 9);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Ancient Den", 1); // Artifact Land
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Blast-Furnace Hellkite");
|
||||||
|
setChoice(playerA, true); // use offering
|
||||||
|
addTarget(playerA, "Ancient Den");
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Blast-Furnace Hellkite", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,6 @@ public class OfferingAbility extends StaticAbility implements AlternateManaPayme
|
||||||
|
|
||||||
private final FilterControlledPermanent filter;
|
private final FilterControlledPermanent filter;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param subtype name of the subtype that can be offered
|
|
||||||
*/
|
|
||||||
public OfferingAbility(FilterControlledPermanent filter) {
|
public OfferingAbility(FilterControlledPermanent filter) {
|
||||||
super(Zone.ALL, null);
|
super(Zone.ALL, null);
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
@ -226,7 +223,10 @@ class OfferingCostReductionEffect extends CostModificationEffectImpl {
|
||||||
Permanent toOffer = game.getPermanent(getTargetPointer().getFirst(game, source));
|
Permanent toOffer = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||||
if (toOffer != null) {
|
if (toOffer != null) {
|
||||||
toOffer.sacrifice(source, game);
|
toOffer.sacrifice(source, game);
|
||||||
CardUtil.reduceCost((SpellAbility) abilityToModify, toOffer.getSpellAbility().getManaCosts());
|
if (toOffer.getSpellAbility() != null) {
|
||||||
|
// artifact land don't have spell ability
|
||||||
|
CardUtil.reduceCost((SpellAbility) abilityToModify, toOffer.getSpellAbility().getManaCosts());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
game.getState().setValue("offering_" + source.getSourceId(), null);
|
game.getState().setValue("offering_" + source.getSourceId(), null);
|
||||||
game.getState().setValue("offering_ok_" + source.getSourceId(), null);
|
game.getState().setValue("offering_ok_" + source.getSourceId(), null);
|
||||||
|
|
Loading…
Reference in a new issue