[DTK] updated implementation of spells which reveal dragon cards as a cost

This commit is contained in:
Evan Kranzler 2021-03-23 19:44:45 -04:00
parent 707de23436
commit d54e1c6eac
10 changed files with 377 additions and 466 deletions

View file

@ -1,23 +1,17 @@
package mage.cards.d; package mage.cards.d;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.CostAdjuster; import mage.abilities.condition.common.RevealedOrControlledDragonCondition;
import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.costs.common.RevealDragonFromHandCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher;
import java.util.UUID; import java.util.UUID;
@ -30,14 +24,11 @@ public final class DraconicRoar extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}");
// As an additional cost to cast Draconic Roar, you may reveal a Dragon card from your hand. // As an additional cost to cast Draconic Roar, you may reveal a Dragon card from your hand.
this.getSpellAbility().addEffect(new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand")); this.getSpellAbility().addCost(new RevealDragonFromHandCost());
this.getSpellAbility().setCostAdjuster(DraconicRoarAdjuster.instance);
// Draconic Roar deals 3 damage to target creature. If you revealed a Dragon card or controlled a Dragon as you cast Draconic Roar, Draconic Roar deals 3 damage to that creature's controller. // Draconic Roar deals 3 damage to target creature. If you revealed a Dragon card or controlled a Dragon as you cast Draconic Roar, Draconic Roar deals 3 damage to that creature's controller.
this.getSpellAbility().addEffect(new DamageTargetEffect(3));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new DraconicRoarEffect()); this.getSpellAbility().addEffect(new DraconicRoarEffect());
this.getSpellAbility().addWatcher(new DragonOnTheBattlefieldWhileSpellWasCastWatcher()); this.getSpellAbility().addTarget(new TargetCreaturePermanent());
} }
private DraconicRoar(final DraconicRoar card) { private DraconicRoar(final DraconicRoar card) {
@ -50,34 +41,15 @@ public final class DraconicRoar extends CardImpl {
} }
} }
enum DraconicRoarAdjuster implements CostAdjuster {
instance;
private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)");
static {
filter.add(SubType.DRAGON.getPredicate());
}
@Override
public void adjustCosts(Ability ability, Game game) {
Player controller = game.getPlayer(ability.getControllerId());
if (controller != null) {
if (controller.getHand().count(filter, game) > 0) {
ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter)));
}
}
}
}
class DraconicRoarEffect extends OneShotEffect { class DraconicRoarEffect extends OneShotEffect {
public DraconicRoarEffect() { DraconicRoarEffect() {
super(Outcome.Benefit); super(Outcome.Benefit);
this.staticText = "If you revealed a Dragon card or controlled a Dragon as you cast {this}, {this} deals 3 damage to that creature's controller"; staticText = "{this} deals 3 damage to target creature. If you revealed a Dragon card or controlled " +
"a Dragon as you cast this spell, {this} deals 3 damage to that creatures controller.";
} }
public DraconicRoarEffect(final DraconicRoarEffect effect) { private DraconicRoarEffect(final DraconicRoarEffect effect) {
super(effect); super(effect);
} }
@ -88,21 +60,18 @@ class DraconicRoarEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getFirstTarget());
if (controller != null) { if (permanent == null) {
DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class); return false;
if (watcher != null && watcher.castWithConditionTrue(source.getId())) { }
Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); permanent.damage(3, source.getSourceId(), source, game);
if (permanent != null) { if (!RevealedOrControlledDragonCondition.instance.apply(game, source)) {
return true;
}
Player player = game.getPlayer(permanent.getControllerId()); Player player = game.getPlayer(permanent.getControllerId());
if (player != null) { if (player != null) {
player.damage(3, source.getSourceId(), source, game); player.damage(3, source.getSourceId(), source, game);
} }
}
}
return true; return true;
} }
return false;
}
} }

View file

@ -1,28 +1,15 @@
package mage.cards.d; package mage.cards.d;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition; import mage.abilities.condition.common.RevealedOrControlledDragonCondition;
import mage.abilities.costs.Cost; import mage.abilities.costs.common.RevealDragonFromHandCost;
import mage.abilities.costs.CostAdjuster; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.costs.common.RevealTargetFromHandCost;
import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
import mage.abilities.effects.ContinuousRuleModifyingEffect;
import mage.abilities.effects.common.CantBeCounteredSourceEffect; import mage.abilities.effects.common.CantBeCounteredSourceEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import java.util.UUID; import java.util.UUID;
@ -35,20 +22,19 @@ public final class DragonlordsPrerogative extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}{U}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{U}{U}");
// As an additional cost to cast Dragonlord's Prerogative, you may reveal a Dragon card from your hand. // As an additional cost to cast Dragonlord's Prerogative, you may reveal a Dragon card from your hand.
this.getSpellAbility().addEffect(new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand")); this.getSpellAbility().addCost(new RevealDragonFromHandCost());
this.getSpellAbility().setCostAdjuster(DragonlordsPrerogativeAdjuster.instance);
// If you revealed a Dragon card or controlled a Dragon as you cast Dragonlord's Prerogative, Dragonlord's Prerogative can't be countered. // If you revealed a Dragon card or controlled a Dragon as you cast Dragonlord's Prerogative, Dragonlord's Prerogative can't be countered.
Condition condition = new DragonlordsPrerogativeCondition(); this.addAbility(new SimpleStaticAbility(
ContinuousRuleModifyingEffect cantBeCountered = new CantBeCounteredSourceEffect(); Zone.STACK,
ConditionalContinuousRuleModifyingEffect conditionalCantBeCountered = new ConditionalContinuousRuleModifyingEffect(cantBeCountered, condition); new ConditionalContinuousEffect(
conditionalCantBeCountered.setText("<br/>If you revealed a Dragon card or controlled a Dragon as you cast {this}, this spell can't be countered"); new CantBeCounteredSourceEffect(), RevealedOrControlledDragonCondition.instance,
Ability ability = new SimpleStaticAbility(Zone.STACK, conditionalCantBeCountered); "if you revealed a Dragon card or controlled a Dragon as you cast this spell, this spell can't be countered"
this.addAbility(ability); )
));
// Draw four cards. // Draw four cards.
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4)); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(4));
} }
private DragonlordsPrerogative(final DragonlordsPrerogative card) { private DragonlordsPrerogative(final DragonlordsPrerogative card) {
@ -60,49 +46,3 @@ public final class DragonlordsPrerogative extends CardImpl {
return new DragonlordsPrerogative(this); return new DragonlordsPrerogative(this);
} }
} }
enum DragonlordsPrerogativeAdjuster implements CostAdjuster {
instance;
private static final FilterCard filter = new FilterCard("a Dragon card from your hand");
static {
filter.add(SubType.DRAGON.getPredicate());
}
@Override
public void adjustCosts(Ability ability, Game game) {
Player controller = game.getPlayer(ability.getControllerId());
if (controller != null) {
if (controller.getHand().count(filter, game) > 0) {
ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter)));
}
}
}
}
class DragonlordsPrerogativeCondition implements Condition {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("Dragon");
static {
filter.add(SubType.DRAGON.getPredicate());
}
@Override
public boolean apply(Game game, Ability source) {
boolean applies = false;
Spell spell = game.getStack().getSpell(source.getSourceId());
if (spell != null && spell.getSpellAbility() != null) {
for (Cost cost : spell.getSpellAbility().getCosts()) {
if (cost instanceof RevealTargetFromHandCost) {
applies = !cost.getTargets().isEmpty();
break;
}
}
}
if (!applies) {
applies = game.getBattlefield().countAll(filter, source.getControllerId(), game) > 0;
}
return applies;
}
}

View file

@ -1,24 +1,15 @@
package mage.cards.f; package mage.cards.f;
import mage.abilities.Ability; import mage.abilities.condition.common.RevealedOrControlledDragonCondition;
import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.RevealDragonFromHandCost;
import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.effects.common.SacrificeEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import mage.target.common.TargetCardInHand;
import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher;
import java.util.UUID; import java.util.UUID;
@ -31,14 +22,17 @@ public final class FoulTongueInvocation extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{B}");
// As an additional cost to cast Foul-Tongue Invocation, you may reveal a Dragon card from your hand. // As an additional cost to cast Foul-Tongue Invocation, you may reveal a Dragon card from your hand.
this.getSpellAbility().addEffect(new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand")); this.getSpellAbility().addCost(new RevealDragonFromHandCost());
this.getSpellAbility().setCostAdjuster(FoulTongueInvocationAdjuster.instance);
// Target player sacrifices a creature. If you revealed a Dragon card or controlled a Dragon as you cast Foul-Tongue Invocation, you gain 4 life. // Target player sacrifices a creature. If you revealed a Dragon card or controlled a Dragon as you cast Foul-Tongue Invocation, you gain 4 life.
this.getSpellAbility().addEffect(new SacrificeEffect(
StaticFilters.FILTER_PERMANENT_CREATURE, 1, "target player"
));
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new GainLifeEffect(4), RevealedOrControlledDragonCondition.instance,
"If you revealed a Dragon card or controlled a Dragon as you cast this spell, you gain 4 life."
));
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
this.getSpellAbility().addEffect(new SacrificeEffect(StaticFilters.FILTER_PERMANENT_CREATURE, 1, "target player"));
this.getSpellAbility().addEffect(new FoulTongueInvocationEffect());
this.getSpellAbility().addWatcher(new DragonOnTheBattlefieldWhileSpellWasCastWatcher());
} }
private FoulTongueInvocation(final FoulTongueInvocation card) { private FoulTongueInvocation(final FoulTongueInvocation card) {
@ -50,52 +44,3 @@ public final class FoulTongueInvocation extends CardImpl {
return new FoulTongueInvocation(this); return new FoulTongueInvocation(this);
} }
} }
enum FoulTongueInvocationAdjuster implements CostAdjuster {
instance;
private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)");
static {
filter.add(SubType.DRAGON.getPredicate());
}
@Override
public void adjustCosts(Ability ability, Game game) {
Player controller = game.getPlayer(ability.getControllerId());
if (controller != null) {
if (controller.getHand().count(filter, game) > 0) {
ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter)));
}
}
}
}
class FoulTongueInvocationEffect extends OneShotEffect {
public FoulTongueInvocationEffect() {
super(Outcome.Benefit);
this.staticText = "If you revealed a Dragon card or controlled a Dragon as you cast {this}, you gain 4 life";
}
public FoulTongueInvocationEffect(final FoulTongueInvocationEffect effect) {
super(effect);
}
@Override
public FoulTongueInvocationEffect copy() {
return new FoulTongueInvocationEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class);
if (watcher != null && watcher.castWithConditionTrue(source.getId())) {
controller.gainLife(4, game, source);
}
return true;
}
return false;
}
}

View file

@ -1,40 +1,26 @@
package mage.cards.o; package mage.cards.o;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.common.RevealedOrControlledDragonCondition;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.RevealDragonFromHandCost;
import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.keyword.DefenderAbility; import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.CardType;
import mage.filter.FilterCard; import mage.constants.SubType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher; import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class OratorOfOjutai extends CardImpl { public final class OratorOfOjutai extends CardImpl {
private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)");
static {
filter.add(SubType.DRAGON.getPredicate());
}
public OratorOfOjutai(UUID ownerId, CardSetInfo setInfo) { public OratorOfOjutai(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
this.subtype.add(SubType.BIRD); this.subtype.add(SubType.BIRD);
@ -47,22 +33,14 @@ public final class OratorOfOjutai extends CardImpl {
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// As an additional cost to cast Orator of Ojutai, you may reveal a Dragon card from your hand. // As an additional cost to cast Orator of Ojutai, you may reveal a Dragon card from your hand.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand"))); this.getSpellAbility().addCost(new RevealDragonFromHandCost());
// When Orator of Ojutai enters the battlefield, if you revealed a Dragon card or controlled a Dragon as you cast Orator of Ojutai, draw a card. // When Orator of Ojutai enters the battlefield, if you revealed a Dragon card or controlled a Dragon as you cast Orator of Ojutai, draw a card.
this.addAbility(new OratorOfOjutaiTriggeredAbility(new OratorOfOjutaiEffect()), new DragonOnTheBattlefieldWhileSpellWasCastWatcher()); this.addAbility(new ConditionalInterveningIfTriggeredAbility(
} new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(1)),
RevealedOrControlledDragonCondition.instance, "When {this} enters the battlefield, " +
@Override "if you revealed a Dragon card or controlled a Dragon as you cast this spell, draw a card."
public void adjustCosts(Ability ability, Game game) { ), new DragonOnTheBattlefieldWhileSpellWasCastWatcher());
if (ability.getAbilityType() == AbilityType.SPELL) {
Player controller = game.getPlayer(ability.getControllerId());
if (controller != null) {
if (controller.getHand().count(filter, game) > 0) {
ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter)));
}
}
}
} }
private OratorOfOjutai(final OratorOfOjutai card) { private OratorOfOjutai(final OratorOfOjutai card) {
@ -74,73 +52,3 @@ public final class OratorOfOjutai extends CardImpl {
return new OratorOfOjutai(this); return new OratorOfOjutai(this);
} }
} }
class OratorOfOjutaiTriggeredAbility extends TriggeredAbilityImpl {
public OratorOfOjutaiTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect, false);
}
public OratorOfOjutaiTriggeredAbility(final OratorOfOjutaiTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
//Intervening if must be checked
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(getSourceId());
DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class);
return event.getTargetId().equals(getSourceId())
&& watcher != null
&& watcher.castWithConditionTrue(sourcePermanent.getSpellAbility().getId());
}
@Override
public String getRule() {
return "When {this} enters the battlefield, " + super.getRule();
}
@Override
public OratorOfOjutaiTriggeredAbility copy() {
return new OratorOfOjutaiTriggeredAbility(this);
}
}
class OratorOfOjutaiEffect extends OneShotEffect {
public OratorOfOjutaiEffect() {
super(Outcome.Benefit);
this.staticText = "If you revealed a Dragon card or controlled a Dragon as you cast {this}, draw a card";
}
public OratorOfOjutaiEffect(final OratorOfOjutaiEffect effect) {
super(effect);
}
@Override
public OratorOfOjutaiEffect copy() {
return new OratorOfOjutaiEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
//Intervening if is checked again on resolution
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (sourcePermanent != null) {
DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class);
if (watcher != null && watcher.castWithConditionTrue(sourcePermanent.getSpellAbility().getId())) {
controller.drawCards(1, source, game);
return true;
}
}
}
return false;
}
}

View file

@ -1,39 +1,24 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.condition.Condition; import mage.abilities.condition.common.RevealedOrControlledDragonCondition;
import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.costs.common.RevealDragonFromHandCost;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher; import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class ScaleguardSentinels extends CardImpl { public final class ScaleguardSentinels extends CardImpl {
private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)");
static {
filter.add(SubType.DRAGON.getPredicate());
}
public ScaleguardSentinels(UUID ownerId, CardSetInfo setInfo) { public ScaleguardSentinels(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}");
this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.HUMAN);
@ -42,26 +27,16 @@ public final class ScaleguardSentinels extends CardImpl {
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// As an additional cost to cast Scaleguard Sentinels, you may reveal a Dragon card from your hand. // As an additional cost to cast Scaleguard Sentinels, you may reveal a Dragon card from your hand.
this.getSpellAbility().addEffect(new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand")); this.getSpellAbility().addCost(new RevealDragonFromHandCost());
// Scaleguard Sentinels enters the battlefield with a +1/+1 counter on it if you revealed a Dragon card or controlled a Dragon as you cast Scaleguard Sentinels. // Scaleguard Sentinels enters the battlefield with a +1/+1 counter on it if you revealed a Dragon card or controlled a Dragon as you cast Scaleguard Sentinels.
this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance(), true), this.addAbility(new EntersBattlefieldAbility(
ScaleguardSentinelsCondition.instance, new AddCountersSourceEffect(CounterType.P1P1.createInstance()),
"{this} enters the battlefield with a +1/+1 counter on it if you revealed a Dragon card or controlled a Dragon as you cast {this}.", ""), RevealedOrControlledDragonCondition.instance, "{this} enters the battlefield " +
new DragonOnTheBattlefieldWhileSpellWasCastWatcher()); "with a +1/+1 counter on it if you revealed a Dragon card " +
"or controlled a Dragon as you cast this spell.", ""
} ), new DragonOnTheBattlefieldWhileSpellWasCastWatcher()
);
@Override
public void adjustCosts(Ability ability, Game game) {
if (ability.getAbilityType() == AbilityType.SPELL) {
Player controller = game.getPlayer(ability.getControllerId());
if (controller != null) {
if (controller.getHand().count(filter, game) > 0) {
ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0, 1, filter)));
}
}
}
} }
private ScaleguardSentinels(final ScaleguardSentinels card) { private ScaleguardSentinels(final ScaleguardSentinels card) {
@ -73,18 +48,3 @@ public final class ScaleguardSentinels extends CardImpl {
return new ScaleguardSentinels(this); return new ScaleguardSentinels(this);
} }
} }
enum ScaleguardSentinelsCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
Permanent sourcePermanent = game.getPermanentEntering(source.getSourceId());
if (sourcePermanent != null) {
DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class);
return (watcher != null && watcher.castWithConditionTrue(sourcePermanent.getSpellAbility().getId()));
}
return false;
}
}

View file

@ -1,63 +1,36 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID; import mage.abilities.condition.common.RevealedOrControlledDragonCondition;
import mage.abilities.Ability; import mage.abilities.costs.common.RevealDragonFromHandCost;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.RevealTargetFromHandCost;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.CounterTargetEffect;
import mage.abilities.effects.common.CounterUnlessPaysEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.AbilityType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetSpell; import mage.target.TargetSpell;
import mage.target.common.TargetCardInHand;
import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher; import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class SilumgarsScorn extends CardImpl { public final class SilumgarsScorn extends CardImpl {
private static final FilterCard filter = new FilterCard("a Dragon card from your hand (you don't have to)");
static {
filter.add(SubType.DRAGON.getPredicate());
}
public SilumgarsScorn(UUID ownerId, CardSetInfo setInfo) { public SilumgarsScorn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}{U}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}{U}");
// As an additional cost to cast Silumgar's Scorn, you may reveal a Dragon card from your hand. // As an additional cost to cast Silumgar's Scorn, you may reveal a Dragon card from your hand.
this.getSpellAbility().addEffect(new InfoEffect("as an additional cost to cast this spell, you may reveal a Dragon card from your hand")); this.getSpellAbility().addCost(new RevealDragonFromHandCost());
// Counter target spell unless its controller pays {1}. If you revealed a Dragon card or controlled a Dragon as you cast Silumgar's Scorn, counter that spell instead. // Counter target spell unless its controller pays {1}. If you revealed a Dragon card or controlled a Dragon as you cast Silumgar's Scorn, counter that spell instead.
this.getSpellAbility().addEffect(new SilumgarsScornCounterEffect()); this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new CounterTargetEffect(), new CounterUnlessPaysEffect(new GenericManaCost(1)),
RevealedOrControlledDragonCondition.instance, "counter target spell unless its controller pays {1}. " +
"If you revealed a Dragon card or controlled a Dragon as you cast this spell, counter that spell instead"
));
this.getSpellAbility().addTarget(new TargetSpell()); this.getSpellAbility().addTarget(new TargetSpell());
this.getSpellAbility().addWatcher(new DragonOnTheBattlefieldWhileSpellWasCastWatcher());
}
@Override
public void adjustCosts(Ability ability, Game game) {
if (ability.getAbilityType() == AbilityType.SPELL) {
Player controller = game.getPlayer(ability.getControllerId());
if (controller != null) {
if (controller.getHand().count(filter, game) > 0) {
ability.addCost(new RevealTargetFromHandCost(new TargetCardInHand(0,1, filter)));
}
}
}
} }
private SilumgarsScorn(final SilumgarsScorn card) { private SilumgarsScorn(final SilumgarsScorn card) {
@ -69,48 +42,3 @@ public final class SilumgarsScorn extends CardImpl {
return new SilumgarsScorn(this); return new SilumgarsScorn(this);
} }
} }
class SilumgarsScornCounterEffect extends OneShotEffect {
public SilumgarsScornCounterEffect() {
super(Outcome.Detriment);
staticText = "<br/>Counter target spell unless its controller pays {1}. If you revealed a Dragon card or controlled a Dragon as you cast {this}, counter that spell instead";
}
public SilumgarsScornCounterEffect(final SilumgarsScornCounterEffect effect) {
super(effect);
}
@Override
public SilumgarsScornCounterEffect copy() {
return new SilumgarsScornCounterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
StackObject spell = game.getStack().getStackObject(targetPointer.getFirst(game, source));
if (spell != null) {
Player player = game.getPlayer(spell.getControllerId());
if (player != null) {
DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher = game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class);
boolean condition = watcher != null && watcher.castWithConditionTrue(source.getId());
if (!condition) {
for (Cost cost: source.getCosts()) {
if (cost instanceof RevealTargetFromHandCost) {
condition = ((RevealTargetFromHandCost)cost).getNumberRevealedCards() > 0;
}
}
}
if (condition) {
return game.getStack().counter(spell.getId(), source, game);
}
if (!(player.chooseUse(Outcome.Benefit, "Would you like to pay {1} to prevent counter effect?", source, game) &&
new GenericManaCost(1).pay(source, game, source, spell.getControllerId(), false))) {
return game.getStack().counter(spell.getId(), source, game);
}
}
}
return true;
}
}

View file

@ -0,0 +1,181 @@
package org.mage.test.cards.cost.additional;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author TheElk801
*/
public class RevealedOrControlledDragonTest extends CardTestPlayerBase {
private static final String dragon = "Shivan Dragon";
private static final String roar = "Draconic Roar";
private static final String lion = "Silvercoat Lion";
private static final String orator = "Orator of Ojutai";
private static final String sentinels = "Scaleguard Sentinels";
public void addDragonToHand(String cardName) {
addCard(Zone.HAND, playerA, dragon);
addCard(Zone.HAND, playerA, cardName);
}
public void addDragonToBattlefield(String cardName) {
addCard(Zone.BATTLEFIELD, playerA, dragon);
addCard(Zone.HAND, playerA, cardName);
}
@Test
public void testRoarHand() {
addDragonToHand(roar);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerA, lion);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, roar, lion);
setChoice(playerA, dragon);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, lion, 1);
assertGraveyardCount(playerA, roar, 1);
assertLife(playerA, 20 - 3);
}
@Test
public void testRoarBattlefield() {
addDragonToBattlefield(roar);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerA, lion);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, roar, lion);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, lion, 1);
assertGraveyardCount(playerA, roar, 1);
assertLife(playerA, 20 - 3);
}
@Test
public void testRoarFalse() {
addCard(Zone.HAND, playerA, roar);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
addCard(Zone.BATTLEFIELD, playerA, lion);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, roar, lion);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, lion, 1);
assertGraveyardCount(playerA, roar, 1);
assertLife(playerA, 20);
}
@Test
public void testOratorHand() {
addDragonToHand(orator);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, orator);
setChoice(playerA, dragon);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, orator, 1);
assertHandCount(playerA, 1 + 1);
}
@Test
public void testOratorBattlefield() {
addDragonToBattlefield(orator);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, orator);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, orator, 1);
assertHandCount(playerA, 1);
}
@Test
public void testOratorFalse() {
addCard(Zone.HAND, playerA, orator);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, orator);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, orator, 1);
assertHandCount(playerA, 0);
}
@Test
public void testSentinelsHand() {
addDragonToHand(sentinels);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sentinels);
setChoice(playerA, dragon);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, sentinels, 1);
assertCounterCount(playerA, sentinels, CounterType.P1P1, 1);
}
@Test
public void testSentinelsBattlefield() {
addDragonToBattlefield(sentinels);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sentinels);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, sentinels, 1);
assertCounterCount(playerA, sentinels, CounterType.P1P1, 1);
}
@Test
public void testSentinelsFalse() {
addCard(Zone.HAND, playerA, sentinels);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, sentinels);
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, sentinels, 1);
assertCounterCount(playerA, sentinels, CounterType.P1P1, 0);
}
}

View file

@ -0,0 +1,30 @@
package mage.abilities.condition.common;
import mage.abilities.Ability;
import mage.abilities.condition.Condition;
import mage.abilities.costs.common.RevealDragonFromHandCost;
import mage.constants.AbilityType;
import mage.game.Game;
import mage.watchers.common.DragonOnTheBattlefieldWhileSpellWasCastWatcher;
/**
* @author TheElk801
*/
public enum RevealedOrControlledDragonCondition implements Condition {
instance;
@Override
public boolean apply(Game game, Ability source) {
if (source.getAbilityType() == AbilityType.SPELL) {
return source
.getCosts()
.stream()
.filter(RevealDragonFromHandCost.class::isInstance)
.map(RevealDragonFromHandCost.class::cast)
.anyMatch(RevealDragonFromHandCost::isRevealedOrControlled);
}
DragonOnTheBattlefieldWhileSpellWasCastWatcher watcher
= game.getState().getWatcher(DragonOnTheBattlefieldWhileSpellWasCastWatcher.class);
return watcher != null && watcher.checkCondition(source, game);
}
}

View file

@ -0,0 +1,58 @@
package mage.abilities.costs.common;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.target.common.TargetCardInHand;
import java.util.UUID;
/**
* @author TheElk801
*/
public class RevealDragonFromHandCost extends RevealTargetFromHandCost {
private static final FilterCard filter = new FilterCard("a Dragon card from your hand");
private static final FilterPermanent filter2 = new FilterControlledPermanent(SubType.DRAGON);
static {
filter.add(SubType.DRAGON.getPredicate());
}
private boolean revealedOrControlled = false;
public RevealDragonFromHandCost() {
super(new TargetCardInHand(0, 1, filter));
}
private RevealDragonFromHandCost(final RevealDragonFromHandCost cost) {
super(cost);
this.revealedOrControlled = cost.revealedOrControlled;
}
@Override
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
return true;
}
@Override
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
super.pay(ability, game, source, controllerId, noMana, costToPay);
revealedOrControlled = numberCardsRevealed > 0
|| game.getBattlefield().count(filter2, source.getSourceId(), controllerId, game) > 0;
return paid = true;
}
@Override
public RevealDragonFromHandCost copy() {
return new RevealDragonFromHandCost(this);
}
public boolean isRevealedOrControlled() {
return revealedOrControlled;
}
}

View file

@ -1,10 +1,9 @@
package mage.watchers.common; package mage.watchers.common;
import mage.abilities.costs.Cost; import mage.MageObjectReference;
import mage.abilities.costs.common.RevealTargetFromHandCost; import mage.abilities.Ability;
import mage.constants.SubType; import mage.abilities.costs.common.RevealDragonFromHandCost;
import mage.constants.WatcherScope; import mage.constants.WatcherScope;
import mage.filter.FilterPermanent;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.stack.Spell; import mage.game.stack.Spell;
@ -12,16 +11,13 @@ import mage.watchers.Watcher;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
public class DragonOnTheBattlefieldWhileSpellWasCastWatcher extends Watcher { public class DragonOnTheBattlefieldWhileSpellWasCastWatcher extends Watcher {
private static final FilterPermanent filter = new FilterPermanent(SubType.DRAGON, "Dragons"); private final Set<MageObjectReference> castWithDragonOnTheBattlefield = new HashSet<>();
private final Set<UUID> castWithDragonOnTheBattlefield = new HashSet<>();
public DragonOnTheBattlefieldWhileSpellWasCastWatcher() { public DragonOnTheBattlefieldWhileSpellWasCastWatcher() {
super(WatcherScope.GAME); super(WatcherScope.GAME);
@ -29,28 +25,22 @@ public class DragonOnTheBattlefieldWhileSpellWasCastWatcher extends Watcher {
@Override @Override
public void watch(GameEvent event, Game game) { public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST) { if (event.getType() != GameEvent.EventType.SPELL_CAST) {
return;
}
// targetId is the unique ID of the spell // targetId is the unique ID of the spell
Spell spell = game.getState().getStack().getSpell(event.getTargetId()); Spell spell = game.getSpell(event.getTargetId());
// revealed a Dragon card or controlled a Dragon as you cast the spell // revealed a Dragon card or controlled a Dragon as you cast the spell
if (spell != null) { if (spell != null
boolean revealedOrOnBattlefield = false; && spell
if (spell.getSpellAbility() != null) { .getSpellAbility()
for (Cost cost : spell.getSpellAbility().getCosts()) { .getCosts()
if (cost instanceof RevealTargetFromHandCost) { .stream()
revealedOrOnBattlefield = ((RevealTargetFromHandCost) cost).getNumberRevealedCards() > 0; .filter(RevealDragonFromHandCost.class::isInstance)
break; .map(RevealDragonFromHandCost.class::cast)
} .anyMatch(RevealDragonFromHandCost::isRevealedOrControlled)) {
} castWithDragonOnTheBattlefield.add(new MageObjectReference(spell.getCard(), game, 0));
} castWithDragonOnTheBattlefield.add(new MageObjectReference(spell.getCard(), game, 1));
if (!revealedOrOnBattlefield) {
revealedOrOnBattlefield = game.getBattlefield().countAll(filter, spell.getControllerId(), game) > 0;
}
if (revealedOrOnBattlefield) {
castWithDragonOnTheBattlefield.add(spell.getId());
}
}
} }
} }
@ -60,7 +50,9 @@ public class DragonOnTheBattlefieldWhileSpellWasCastWatcher extends Watcher {
castWithDragonOnTheBattlefield.clear(); castWithDragonOnTheBattlefield.clear();
} }
public boolean castWithConditionTrue(UUID spellId) { public boolean checkCondition(Ability source, Game game) {
return castWithDragonOnTheBattlefield.contains(spellId); return castWithDragonOnTheBattlefield
.stream()
.anyMatch(mor -> mor.refersTo(source.getSourceObject(game), game));
} }
} }