mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
Fixed face down cost modification (related to 653a2dd7b2
)
This commit is contained in:
parent
dfaf09e76c
commit
97c427375d
6 changed files with 92 additions and 29 deletions
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.d;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -9,10 +7,11 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.other.FaceDownPredicate;
|
||||
import mage.filter.predicate.other.FaceDownCastablePredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author North
|
||||
*/
|
||||
public final class DreamChisel extends CardImpl {
|
||||
|
@ -20,11 +19,11 @@ public final class DreamChisel extends CardImpl {
|
|||
private static final FilterCreatureCard filter = new FilterCreatureCard("Face-down creature spells");
|
||||
|
||||
static {
|
||||
filter.add(FaceDownPredicate.instance);
|
||||
filter.add(FaceDownCastablePredicate.instance);
|
||||
}
|
||||
|
||||
public DreamChisel(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
// Face-down creature spells you cast cost {1} less to cast.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new SpellsCostReductionControllerEffect(filter, 1)));
|
||||
|
|
|
@ -5,6 +5,7 @@ import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -14,10 +15,9 @@ import mage.constants.WatcherScope;
|
|||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.ObjectPlayer;
|
||||
import mage.filter.predicate.ObjectPlayerPredicate;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.other.FaceDownCastablePredicate;
|
||||
import mage.filter.predicate.other.FaceDownPredicate;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
|
@ -32,12 +32,12 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class KadenaSlinkingSorcerer extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard();
|
||||
private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent("a face-down creature");
|
||||
private static final FilterCard filterFirstFaceDownSpell = new FilterCard("first face-down creature spell");
|
||||
private static final FilterPermanent filterFaceDownPermanent = new FilterControlledCreaturePermanent("a face-down creature");
|
||||
|
||||
static {
|
||||
filter.add(KadenaSlinkingSorcererPredicate.instance);
|
||||
filter2.add(FaceDownPredicate.instance);
|
||||
filterFirstFaceDownSpell.add(KadenaSlinkingSorcererPredicate.instance);
|
||||
filterFaceDownPermanent.add(FaceDownPredicate.instance);
|
||||
}
|
||||
|
||||
public KadenaSlinkingSorcerer(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
@ -51,13 +51,13 @@ public final class KadenaSlinkingSorcerer extends CardImpl {
|
|||
|
||||
// The first face-down creature spell you cast each turn costs {3} less to cast.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
new SpellsCostReductionControllerEffect(filter, 3)
|
||||
new SpellsCostReductionControllerEffect(filterFirstFaceDownSpell, 3)
|
||||
.setText("The first face-down creature spell you cast each turn costs {3} less to cast.")
|
||||
), new KadenaSlinkingSorcererWatcher());
|
||||
|
||||
// Whenever a face-down creature enters the battlefield under your control, draw a card.
|
||||
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(
|
||||
new DrawCardSourceControllerEffect(1), filter2
|
||||
new DrawCardSourceControllerEffect(1), filterFaceDownPermanent
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -71,16 +71,15 @@ public final class KadenaSlinkingSorcerer extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
enum KadenaSlinkingSorcererPredicate implements ObjectPlayerPredicate<ObjectPlayer<Controllable>> {
|
||||
enum KadenaSlinkingSorcererPredicate implements Predicate<Card> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectPlayer<Controllable> input, Game game) {
|
||||
if (input.getObject() instanceof Spell
|
||||
&& ((Spell) input.getObject()).isCreature()
|
||||
&& ((Spell) input.getObject()).isFaceDown(game)) {
|
||||
KadenaSlinkingSorcererWatcher watcher = game.getState().getWatcher(KadenaSlinkingSorcererWatcher.class);
|
||||
return watcher != null && !watcher.castFaceDownThisTurn(input.getPlayerId());
|
||||
public boolean apply(Card input, Game game) {
|
||||
KadenaSlinkingSorcererWatcher watcher = game.getState().getWatcher(KadenaSlinkingSorcererWatcher.class);
|
||||
if (watcher != null) {
|
||||
return FaceDownCastablePredicate.instance.apply(input, game)
|
||||
&& !watcher.castFaceDownThisTurn(input.getOwnerId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.o;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
@ -14,10 +12,11 @@ import mage.constants.CardType;
|
|||
import mage.constants.Duration;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.other.FaceDownPredicate;
|
||||
import mage.filter.predicate.other.FaceDownCastablePredicate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class ObscuringAether extends CardImpl {
|
||||
|
@ -25,7 +24,7 @@ public final class ObscuringAether extends CardImpl {
|
|||
private static final FilterCreatureCard filter = new FilterCreatureCard("Face-down creature spells");
|
||||
|
||||
static {
|
||||
filter.add(FaceDownPredicate.instance);
|
||||
filter.add(FaceDownCastablePredicate.instance);
|
||||
}
|
||||
|
||||
public ObscuringAether(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
|
|
@ -1089,7 +1089,7 @@ public class MorphTest extends CardTestPlayerBase {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void test_MorphWithCostReductionMustBePlayable_MorphCondition() {
|
||||
public void test_MorphWithCostReductionMustBePlayable_MorphCondition1() {
|
||||
// {1}{U} creature
|
||||
// Morph {1}{U} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)
|
||||
// When Willbender is turned face up, change the target of target spell or ability with a single target.
|
||||
|
@ -1110,4 +1110,36 @@ public class MorphTest extends CardTestPlayerBase {
|
|||
|
||||
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_MorphWithCostReductionMustBePlayable_MorphCondition2() {
|
||||
// {1}{U} creature
|
||||
// Morph {1}{U} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)
|
||||
// When Willbender is turned face up, change the target of target spell or ability with a single target.
|
||||
addCard(Zone.HAND, playerA, "Willbender", 2);
|
||||
//addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
//
|
||||
// The first face-down creature spell you cast each turn costs {3} less to cast.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Kadena, Slinking Sorcerer");
|
||||
|
||||
// creature one - get cost reduce
|
||||
checkPlayableAbility("can", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender", true);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender");
|
||||
setChoice(playerA, "Yes"); // morph
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
|
||||
// creature two - do not get cost reduce
|
||||
checkPlayableAbility("can't by no reduce", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender", false);
|
||||
|
||||
// on next turn it can cost reduce again
|
||||
checkPlayableAbility("can't by not your turn", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender", false);
|
||||
checkPlayableAbility("can", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Willbender", true);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package mage.filter.predicate.other;
|
||||
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public enum FaceDownCastablePredicate implements Predicate<Card> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Card input, Game game) {
|
||||
// is card able to cast as face down
|
||||
return input.getAbilities(game).containsClass(MorphAbility.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Face-down";
|
||||
}
|
||||
}
|
|
@ -3156,6 +3156,11 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
sourceObject.adjustCosts(copyAbility, game);
|
||||
game.getContinuousEffects().costModification(copyAbility, game);
|
||||
|
||||
// reduced all cost
|
||||
if (copyAbility.getManaCostsToPay().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Mana mana : copyAbility.getManaCostsToPay().getOptions()) {
|
||||
if (availableMana.enough(mana)) {
|
||||
return true;
|
||||
|
@ -3193,6 +3198,11 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
sourceObject.adjustCosts(copyAbility, game);
|
||||
game.getContinuousEffects().costModification(copyAbility, game);
|
||||
|
||||
// reduced all cost
|
||||
if (copyAbility.getManaCostsToPay().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Mana mana : copyAbility.getManaCostsToPay().getOptions()) {
|
||||
if (availableMana.enough(mana)) {
|
||||
return true;
|
||||
|
@ -3260,7 +3270,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
// So make it available all the time
|
||||
boolean canUse;
|
||||
if (ability instanceof MorphAbility && object instanceof Card && game.canPlaySorcery(getId())) {
|
||||
canUse = canPlayCardByAlternateCost((Card) object, availableMana, ability, game);
|
||||
canUse = canPlayCardByAlternateCost((Card) object, availableMana, playAbility, game);
|
||||
} else {
|
||||
canUse = canPlay(playAbility, availableMana, object, game); // canPlay already checks alternative source costs and all conditions
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue