Merge origin/master

This commit is contained in:
fireshoes 2016-03-04 10:51:50 -06:00
commit 8096d2f4aa
149 changed files with 3642 additions and 1338 deletions

View file

@ -97,11 +97,7 @@ class AliFromCairoReplacementEffect extends ReplacementEffectImpl {
&& (controller.getLife() > 0) &&(controller.getLife() - event.getAmount()) < 1
&& event.getPlayerId().equals(controller.getId())
) {
return true;
//unsure how to make this comply with
// 10/1/2008: The ability doesn't change how much damage is dealt;
// it just changes how much life that damage makes you lose.
// An effect such as Spirit Link will see the full amount of damage being dealt.
return true;
}
}
return false;
@ -110,10 +106,17 @@ class AliFromCairoReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player controller = game.getPlayer(source.getControllerId());
// 10/1/2008: The ability doesn't change how much damage is dealt;
// it just changes how much life that damage makes you lose.
// An effect such as Spirit Link will see the full amount of damage being dealt.
game.fireEvent(event);
if (controller != null) {
event.setAmount(controller.getLife() - 1);
controller.setLife(1, game);
}
return false;
return true;
}
}

View file

@ -77,7 +77,7 @@ class SecondSpellPredicate implements Predicate<Spell> {
@Override
public boolean apply(Spell input, Game game) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher.getSpellOrder(new MageObjectReference(input.getId(), game), game) == 2) {
return true;

View file

@ -0,0 +1,125 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.blessedvscursed;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.targetpointer.FixedTargets;
import mage.util.CardUtil;
/**
*
* @author LevelX2
*/
public class EerieInterlude extends CardImpl {
public EerieInterlude(UUID ownerId) {
super(ownerId, 8, "Eerie Interlude", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{W}");
this.expansionSetCode = "DDQ";
// Exile any number of target creatures you control. Return those cards to the battlefield under their owner's control at the beginning of the next end step.
this.getSpellAbility().addEffect(new EerieInterludeEffect());
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent(0, Integer.MAX_VALUE, new FilterControlledCreaturePermanent(), false));
}
public EerieInterlude(final EerieInterlude card) {
super(card);
}
@Override
public EerieInterlude copy() {
return new EerieInterlude(this);
}
}
class EerieInterludeEffect extends OneShotEffect {
public EerieInterludeEffect() {
super(Outcome.Neutral);
staticText = "Exile any number of target creatures you control. Return those cards to the battlefield under their owner's control at the beginning of the next end step";
}
public EerieInterludeEffect(final EerieInterludeEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (sourceObject != null && controller != null) {
Set<Card> toExile = new HashSet<>();
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
Permanent targetCreature = game.getPermanent(targetId);
if (targetCreature != null) {
toExile.add(targetCreature);
}
}
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
controller.moveCardsToExile(toExile, source, game, true, exileId, sourceObject.getIdName());
Cards cardsToReturn = new CardsImpl();
for (Card exiled : toExile) {
if (((Permanent) exiled).getZoneChangeCounter(game) == game.getState().getZoneChangeCounter(exiled.getId()) - 1) {
cardsToReturn.add(exiled);
}
}
Effect effect = new ReturnToBattlefieldUnderOwnerControlTargetEffect();
effect.setTargetPointer(new FixedTargets(cardsToReturn, game));
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect);
game.addDelayedTriggeredAbility(delayedAbility, source);
return true;
}
return false;
}
@Override
public EerieInterludeEffect copy() {
return new EerieInterludeEffect(this);
}
}

View file

@ -35,7 +35,7 @@ import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@ -74,7 +74,7 @@ public class MyojinOfCleansingFire extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Cleansing Fire enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Cleansing Fire is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));

View file

@ -35,7 +35,7 @@ import mage.MageInt;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@ -70,7 +70,7 @@ public class MyojinOfInfiniteRage extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Infinite Rage enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Infinite Rage is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));

View file

@ -35,7 +35,7 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@ -75,7 +75,7 @@ public class MyojinOfLifesWeb extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Life's Web enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Life's Web is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),

View file

@ -35,7 +35,7 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@ -68,7 +68,7 @@ public class MyojinOfNightsReach extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Night's Reach enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Night's Reach is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));

View file

@ -35,7 +35,7 @@ import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.RemoveCountersSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@ -73,7 +73,7 @@ public class MyojinOfSeeingWinds extends CardImpl {
this.getSpellAbility().addWatcher(new CastFromHandWatcher());
// Myojin of Seeing Winds enters the battlefield with a divinity counter on it if you cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.DIVINITY.createInstance()), new CastFromHandSourceCondition(), ""), "{this} enters the battlefield with a divinity counter on it if you cast it from your hand"));
// Myojin of Seeing Winds is indestructible as long as it has a divinity counter on it.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new GainAbilitySourceEffect(IndestructibleAbility.getInstance(), Duration.WhileOnBattlefield),
new SourceHasCounterCondition(CounterType.DIVINITY), "{this} is indestructible as long as it has a divinity counter on it")));

View file

@ -0,0 +1,86 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.commander;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.effects.common.TapAllEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.watchers.common.CastFromHandWatcher;
/**
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public class DreadCacodemon extends CardImpl {
private static final FilterCreaturePermanent opponentsCreatures = new FilterCreaturePermanent("creatures your opponents control");
static {
opponentsCreatures.add(new ControllerPredicate(TargetController.OPPONENT));
}
private static final FilterCreaturePermanent otherCreaturesYouControl = new FilterCreaturePermanent("other creatures you control");
static {
otherCreaturesYouControl.add(new ControllerPredicate(TargetController.YOU));
otherCreaturesYouControl.add(new AnotherPredicate());
}
public DreadCacodemon(UUID ownerId) {
super(ownerId, 79, "Dread Cacodemon", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{7}{B}{B}{B}");
this.expansionSetCode = "CMD";
this.subtype.add("Demon");
this.power = new MageInt(8);
this.toughness = new MageInt(8);
// When Dread Cacodemon enters the battlefield,
// if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control.
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(opponentsCreatures, false));
ability.addEffect(new TapAllEffect(otherCreaturesYouControl));
this.addAbility(new ConditionalTriggeredAbility(ability, new CastFromHandSourceCondition(),
"When {this} enters the battlefield, if you cast it from your hand, destroy all creatures your opponents control, then tap all other creatures you control."), new CastFromHandWatcher());
}
public DreadCacodemon(final DreadCacodemon card) {
super(card);
}
@Override
public DreadCacodemon copy() {
return new DreadCacodemon(this);
}
}

View file

@ -53,7 +53,6 @@ public class AEtherSnap extends CardImpl {
super(ownerId, 133, "AEther Snap", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
this.expansionSetCode = "C14";
// Remove all counters from all permanents and exile all tokens.
this.getSpellAbility().addEffect(new AEtherSnapEffect());
}
@ -88,13 +87,13 @@ class AEtherSnapEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
for (Permanent permanent :game.getBattlefield().getActivePermanents(new FilterPermanent(), controller.getId(), source.getSourceId(), game)) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterPermanent(), controller.getId(), source.getSourceId(), game)) {
if (permanent instanceof PermanentToken) {
controller.moveCardToExileWithInfo(permanent, null, "", source.getSourceId(), game, Zone.BATTLEFIELD, true);
} else if (!permanent.getCounters().isEmpty()){
} else if (!permanent.getCounters().isEmpty()) {
Counters counters = permanent.getCounters().copy();
for (Counter counter: counters.values()) {
permanent.getCounters().removeCounter(counter.getName(), counter.getCount());
for (Counter counter : counters.values()) {
permanent.removeCounters(counter, game);
}
}
}

View file

@ -29,10 +29,9 @@ package mage.sets.commander2014;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.ExileAllEffect;
import mage.abilities.keyword.FlashAbility;
import mage.abilities.keyword.FlyingAbility;
@ -61,10 +60,11 @@ public class AngelOfTheDireHour extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Angel of the Dire Hour enters the battlefield, if you cast it from your hand, exile all attacking creatures.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), new CastFromHandCondition(),
" if you cast it from your hand, exile all attacking creatures"));
this.addAbility(ability, new CastFromHandWatcher());
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new ExileAllEffect(new FilterAttackingCreature("attacking creatures")), false),
new CastFromHandSourceCondition(),
"When {this} enters the battlefield, if you cast it from your hand, exile all attacking creatures."),
new CastFromHandWatcher());
}
public AngelOfTheDireHour(final AngelOfTheDireHour card) {

View file

@ -32,8 +32,8 @@ import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
@ -64,10 +64,11 @@ public class BreachingLeviathan extends CardImpl {
this.toughness = new MageInt(9);
// When Breaching Leviathan enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new BreachingLeviathanEffect(), new CastFromHandCondition(),
"if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps"));
this.addAbility(ability, new CastFromHandWatcher());
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new BreachingLeviathanEffect(), false),
new CastFromHandSourceCondition(),
"When {this} enters the battlefield, if you cast it from your hand, tap all nonblue creatures. Those creatures don't untap during their controllers' next untap steps."),
new CastFromHandWatcher());
}
public BreachingLeviathan(final BreachingLeviathan card) {
@ -104,7 +105,7 @@ class BreachingLeviathanEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
for (Permanent creature: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
for (Permanent creature : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
creature.tap(game);
ContinuousEffect effect = new DontUntapInControllersNextUntapStepTargetEffect();
effect.setTargetPointer(new FixedTarget(creature.getId()));

View file

@ -57,10 +57,10 @@ public class ThiefOfBlood extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
this.subtype.add("Vampire");
// Flying
this.addAbility(FlyingAbility.getInstance());
// As Thief of Blood enters the battlefield, remove all counters from all permanents. Thief of Blood enters the battlefield with a +1/+1 counter on it for each counter removed this way.
this.addAbility(new EntersBattlefieldAbility(new ThiefOfBloodEffect(), null, "As {this} enters the battlefield, remove all counters from all permanents. {this} enters the battlefield with a +1/+1 counter on it for each counter removed this way", null));
}
@ -76,33 +76,34 @@ public class ThiefOfBlood extends CardImpl {
}
class ThiefOfBloodEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("permanent with a counter");
static {
filter.add(new CounterPredicate(null));
}
ThiefOfBloodEffect() {
super(Outcome.BoostCreature);
this.staticText = "remove all counters from all permanents. {this} enters the battlefield with a +1/+1 counter on it for each counter removed this way";
}
ThiefOfBloodEffect(final ThiefOfBloodEffect effect) {
super(effect);
}
@Override
public ThiefOfBloodEffect copy() {
return new ThiefOfBloodEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int countersRemoved = 0;
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) {
Counters counters = permanent.getCounters().copy();
for (Counter counter : counters.values()) {
permanent.getCounters().removeCounter(counter.getName(), counter.getCount());
permanent.removeCounters(counter.getName(), counter.getCount(), game);
countersRemoved += counter.getCount();
}
}

View file

@ -104,7 +104,7 @@ class CurseOfExhaustionEffect extends ContinuousRuleModifyingEffectImpl {
if (enchantment != null && enchantment.getAttachedTo() != null) {
Player player = game.getPlayer(enchantment.getAttachedTo());
if (player != null && event.getPlayerId().equals(player.getId())) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) > 0) {
return true;
}

View file

@ -29,10 +29,9 @@ package mage.sets.darksteel;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.ExileAllEffect;
import mage.abilities.keyword.AffinityForArtifactsAbility;
import mage.abilities.keyword.FlyingAbility;
@ -41,9 +40,6 @@ import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
import mage.watchers.common.CastFromHandWatcher;
/**
@ -51,7 +47,7 @@ import mage.watchers.common.CastFromHandWatcher;
* @author fireshoes
*/
public class FurnaceDragon extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("artifacts");
static {
@ -67,12 +63,16 @@ public class FurnaceDragon extends CardImpl {
// Affinity for artifacts
this.addAbility(new AffinityForArtifactsAbility());
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Furnace Dragon enters the battlefield, if you cast it from your hand, exile all artifacts.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new ExileAllEffect(filter), new FurnaceDragonCondition()), false), new CastFromHandWatcher());
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new ExileAllEffect(filter), false),
new CastFromHandSourceCondition(),
"When {this} enters the battlefield, if you cast it from your hand, exile all artifacts."),
new CastFromHandWatcher());
}
public FurnaceDragon(final FurnaceDragon card) {
@ -84,24 +84,3 @@ public class FurnaceDragon extends CardImpl {
return new FurnaceDragon(this);
}
}
class FurnaceDragonCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
boolean applies = false;
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
Watcher watcher = game.getState().getWatchers().get("CastFromHand", source.getSourceId());
if (watcher != null && watcher.conditionMet()) {
applies = true;
}
}
return applies;
}
@Override
public String toString() {
return "you cast it from your hand";
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.darksteel;
import java.util.UUID;
import mage.abilities.effects.common.TapAllEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.common.FilterArtifactPermanent;
/**
*
* @author djbrez
*/
public class MetalFatigue extends CardImpl {
public MetalFatigue(UUID ownerId) {
super(ownerId, 8, "Metal Fatigue", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{W}");
this.expansionSetCode = "DST";
// Tap all artifacts.
this.getSpellAbility().addEffect(new TapAllEffect(new FilterArtifactPermanent("artifacts")));
}
public MetalFatigue(final MetalFatigue card) {
super(card);
}
@Override
public MetalFatigue copy() {
return new MetalFatigue(this);
}
}

View file

@ -30,10 +30,9 @@ package mage.sets.divinevsdemonic;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@ -50,9 +49,9 @@ import mage.watchers.common.CastFromHandWatcher;
* @author daagar
*/
public class ReiverDemon extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact, nonblack creatures");
static {
filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT)));
filter.add(Predicates.not(new ColorPredicate(ObjectColor.BLACK)));
@ -67,12 +66,13 @@ public class ReiverDemon extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Reiver Demon enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new DestroyAllEffect(filter), new CastFromHandCondition(),
"if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated"));
this.addAbility(ability, new CastFromHandWatcher());
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter, true), false),
new CastFromHandSourceCondition(),
"When {this} enters the battlefield, if you cast it from your hand, destroy all nonartifact, nonblack creatures. They can't be regenerated."),
new CastFromHandWatcher());
}
public ReiverDemon(final ReiverDemon card) {

View file

@ -25,15 +25,14 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.dragonsmaze;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.PopulateEffect;
import mage.cards.CardImpl;
@ -46,11 +45,9 @@ import mage.watchers.common.CastFromHandWatcher;
*
* @author LevelX2
*/
public class ScionOfVituGhazi extends CardImpl {
public ScionOfVituGhazi (UUID ownerId) {
public ScionOfVituGhazi(UUID ownerId) {
super(ownerId, 7, "Scion of Vitu-Ghazi", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{W}{W}");
this.expansionSetCode = "DGM";
this.subtype.add("Elemental");
@ -58,15 +55,14 @@ public class ScionOfVituGhazi extends CardImpl {
this.power = new MageInt(4);
this.toughness = new MageInt(4);
// When Scion of Vitu-Ghazi enters the battlefield, if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield, then populate.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new CreateTokenEffect(new BirdToken()), new CastFromHandCondition(),
"if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield,"));
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new BirdToken()), false);
ability.addEffect(new PopulateEffect("then"));
this.addAbility(ability, new CastFromHandWatcher());
this.addAbility(new ConditionalTriggeredAbility(ability, new CastFromHandSourceCondition(),
"When {this} enters the battlefield, if you cast it from your hand, put a 1/1 white Bird creature token with flying onto the battlefield, then populate."),
new CastFromHandWatcher());
}
public ScionOfVituGhazi (final ScionOfVituGhazi card) {
public ScionOfVituGhazi(final ScionOfVituGhazi card) {
super(card);
}

View file

@ -32,7 +32,8 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.DestroyAllEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
@ -41,8 +42,6 @@ import mage.constants.Rarity;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
import mage.watchers.common.CastFromHandWatcher;
/**
@ -50,9 +49,9 @@ import mage.watchers.common.CastFromHandWatcher;
* @author jeffwadsworth
*/
public class DeathbringerRegent extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creatures");
static {
filter.add(new AnotherPredicate());
}
@ -66,10 +65,13 @@ public class DeathbringerRegent extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Deathbringer Regent enters the battlefield, if you cast it from your hand and there are five or more other creatures on the battlefield, destroy all other creatures.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DestroyAllEffect(filter), new DeathbringerRegentCondition()), false), new CastFromHandWatcher());
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new DestroyAllEffect(filter), false),
new DeathbringerRegentCondition(),
"When {this} enters the battlefield, if you cast it from your hand and there are five or more other creatures on the battlefield, destroy all other creatures."),
new CastFromHandWatcher());
}
public DeathbringerRegent(final DeathbringerRegent card) {
@ -86,22 +88,7 @@ class DeathbringerRegentCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
boolean applies = false;
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
Watcher watcher = game.getState().getWatchers().get("CastFromHand", source.getSourceId());
if (watcher != null && watcher.conditionMet()) {
applies = true;
}
}
if (applies) {
applies = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game).size() >= 6;
}
return applies;
return new CastFromHandSourceCondition().apply(game, source)
&& game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game).size() >= 6;
}
@Override
public String toString() {
return "you cast it from your hand and there are five or more other creatures on the battlefield";
}
}
}

View file

@ -88,7 +88,7 @@ class HardenedBerserkerSpellsCostReductionEffect extends CostModificationEffectI
@Override
public void init(Ability source, Game game) {
super.init(source, game);
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null) {
spellsCast = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId());
}
@ -102,7 +102,7 @@ class HardenedBerserkerSpellsCostReductionEffect extends CostModificationEffectI
@Override
public boolean applies(Ability abilityToModify, Ability source, Game game) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null) {
if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()) > spellsCast) {
discard(); // only one use

View file

@ -29,7 +29,6 @@ package mage.sets.eventide;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.Condition;
@ -39,14 +38,9 @@ import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.watchers.Watcher;
import mage.watchers.common.SpellsCastWatcher;
/**
*
@ -69,7 +63,8 @@ public class DreamThief extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// When Dream Thief enters the battlefield, draw a card if you've cast another blue spell this turn.
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule)), new DreamThiefWatcher(this.getId()));
this.addAbility(new EntersBattlefieldTriggeredAbility(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new CastBlueSpellThisTurnCondition(), rule)),
new SpellsCastWatcher());
}
@ -87,55 +82,14 @@ class CastBlueSpellThisTurnCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
DreamThiefWatcher watcher = (DreamThiefWatcher) game.getState().getWatchers().get("DreamThiefWatcher", source.getControllerId());
SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getName());
if (watcher != null) {
return watcher.conditionMet();
for (Spell spell : watcher.getSpellsCastThisTurn(source.getControllerId())) {
if (!spell.getSourceId().equals(source.getSourceId()) && spell.getColor(game).isBlue()) {
return true;
}
}
}
return false;
}
}
class DreamThiefWatcher extends Watcher {
private static final FilterSpell filter = new FilterSpell();
static {
filter.add(new ColorPredicate(ObjectColor.BLUE));
}
private UUID cardId;
public DreamThiefWatcher(UUID cardId) {
super("DreamThiefWatcher", WatcherScope.PLAYER);
this.cardId = cardId;
}
public DreamThiefWatcher(final DreamThiefWatcher watcher) {
super(watcher);
this.cardId = watcher.cardId;
}
@Override
public DreamThiefWatcher copy() {
return new DreamThiefWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (condition == true) { //no need to check - condition has already occured
return;
}
if (event.getType() == EventType.SPELL_CAST
&& controllerId.equals(event.getPlayerId())) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (!spell.getSourceId().equals(cardId) && filter.match(spell, game)) {
condition = true;
}
}
}
@Override
public void reset() {
super.reset();
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.exodus;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.DealsDamageToACreatureTriggeredAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
/**
*
* @author djbrez
*/
public class PitSpawn extends CardImpl {
public PitSpawn(UUID ownerId) {
super(ownerId, 70, "Pit Spawn", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{B}{B}{B}");
this.expansionSetCode = "EXO";
this.subtype.add("Demon");
this.power = new MageInt(6);
this.toughness = new MageInt(4);
// First strike
this.addAbility(FirstStrikeAbility.getInstance());
// At the beginning of your upkeep, sacrifice Pit Spawn unless you pay {B}{B}.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new ManaCostsImpl("{B}{B}")), TargetController.YOU, false));
// Whenever Pit Spawn deals damage to a creature, exile that creature.
this.addAbility(new DealsDamageToACreatureTriggeredAbility(new ExileTargetEffect("exile that creature"), false, false, true));
}
public PitSpawn(final PitSpawn card) {
super(card);
}
@Override
public PitSpawn copy() {
return new PitSpawn(this);
}
}

View file

@ -80,7 +80,7 @@ class OtherSpellsCastThisTurnCount implements DynamicValue {
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
return watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() - 1;
}

View file

@ -95,7 +95,7 @@ class IncursionTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(controllerId)) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) {
return true;
}

View file

@ -28,9 +28,6 @@
package mage.sets.innistrad;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -41,7 +38,9 @@ import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.DefenderAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
@ -83,6 +82,7 @@ public class LudevicsTestSubject extends CardImpl {
}
class LudevicsTestSubjectEffect extends OneShotEffect {
LudevicsTestSubjectEffect() {
super(Outcome.Benefit);
staticText = "Then if there are five or more hatchling counters on it, remove all of them and transform it";
@ -97,7 +97,7 @@ class LudevicsTestSubjectEffect extends OneShotEffect {
Permanent p = game.getPermanent(source.getSourceId());
if (p != null) {
if (p.getCounters().getCount(CounterType.HATCHLING) >= 5) {
p.getCounters().removeCounter(CounterType.HATCHLING, p.getCounters().getCount(CounterType.HATCHLING));
p.removeCounters(CounterType.HATCHLING.getName(), p.getCounters().getCount(CounterType.HATCHLING), game);
TransformSourceEffect effect = new TransformSourceEffect(true);
return effect.apply(game, source);
}
@ -109,4 +109,4 @@ class LudevicsTestSubjectEffect extends OneShotEffect {
public LudevicsTestSubjectEffect copy() {
return new LudevicsTestSubjectEffect(this);
}
}
}

View file

@ -83,21 +83,12 @@ class RevivingVaporsEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller == null || sourceObject == null) {
if (controller == null || sourceObject == null) {
return false;
}
Cards cards = new CardsImpl();
int count = Math.min(controller.getLibrary().size(), 3);
for (int i = 0; i < count; i++) {
Card card = controller.getLibrary().removeFromTop(game);
if (card != null) {
cards.add(card);
} else {
return false;
}
}
cards.addAll(controller.getLibrary().getTopCards(game, 3));
if (!cards.isEmpty()) {
controller.revealCards(sourceObject.getName(), cards, game);
Card card = null;
@ -112,9 +103,9 @@ class RevivingVaporsEffect extends OneShotEffect {
}
if (card != null) {
cards.remove(card);
controller.moveCards(card, Zone.LIBRARY, Zone.GRAVEYARD, source, game);
controller.moveCards(card, Zone.HAND, source, game);
}
controller.moveCards(cards, Zone.LIBRARY, Zone.GRAVEYARD, source, game);
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
}
return true;
}

View file

@ -39,7 +39,6 @@ import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.SpiritWhiteToken;
import mage.game.permanent.token.Token;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
@ -55,7 +54,6 @@ public class CribSwap extends CardImpl {
this.expansionSetCode = "LRW";
this.subtype.add("Shapeshifter");
// Changeling
this.addAbility(ChangelingAbility.getInstance());
// Exile target creature. Its controller puts a 1/1 colorless Shapeshifter creature token with changeling onto the battlefield.
@ -112,7 +110,6 @@ class CribSwapShapeshifterWhiteToken extends Token {
this.setOriginalExpansionSetCode("LRW");
cardType.add(CardType.CREATURE);
subtype.add("Shapeshifter");
color.setWhite(true);
power = new MageInt(1);
toughness = new MageInt(1);
addAbility(ChangelingAbility.getInstance());

View file

@ -141,7 +141,7 @@ class AngelicArbiterCantAttackTargetEffect extends RestrictionEffect {
@Override
public boolean applies(Permanent permanent, Ability source, Game game) {
if (game.getActivePlayerId().equals(permanent.getControllerId()) && game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(permanent.getControllerId()) > 0) {
return true;
}

View file

@ -173,7 +173,7 @@ class AlhammarretHighArbiterCantCastEffect extends ContinuousRuleModifyingEffect
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == EventType.CAST_SPELL;
return event.getType() == EventType.CAST_SPELL_LATE;
}
@Override

View file

@ -28,9 +28,6 @@
package mage.sets.mirrodin;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
@ -39,7 +36,9 @@ import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
@ -78,6 +77,7 @@ public class OblivionStone extends CardImpl {
}
class OblivionStoneEffect extends OneShotEffect {
OblivionStoneEffect() {
super(Outcome.DestroyPermanent);
staticText = "Destroy each nonland permanent without a fate counter on it, then remove all fate counters from all permanents";
@ -96,7 +96,7 @@ class OblivionStoneEffect extends OneShotEffect {
}
for (Permanent p : game.getBattlefield().getAllActivePermanents()) {
if (p.getCounters().containsKey(CounterType.FATE)) {
p.getCounters().removeCounter(CounterType.FATE, p.getCounters().getCount(CounterType.FATE));
p.removeCounters(CounterType.FATE.getName(), p.getCounters().getCount(CounterType.FATE), game);
}
}
return true;

View file

@ -34,7 +34,7 @@ import mage.abilities.Ability;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainSuspendEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@ -67,7 +67,7 @@ public class Epochrasite extends CardImpl {
// Epochrasite enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand.
this.addAbility(new EntersBattlefieldAbility(
new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)),
new InvertCondition(new CastFromHandCondition()),
new InvertCondition(new CastFromHandSourceCondition()),
"{this} enters the battlefield with three +1/+1 counters on it if you didn't cast it from your hand",""),
new CastFromHandWatcher());

View file

@ -28,8 +28,6 @@
package mage.sets.newphyrexia;
import java.util.UUID;
import mage.constants.*;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -37,6 +35,7 @@ import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.*;
import mage.filter.FilterPermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
@ -50,6 +49,7 @@ import mage.target.TargetPermanent;
* @author Loki
*/
public class ExclusionRitual extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("nonland permanent");
static {
@ -60,7 +60,6 @@ public class ExclusionRitual extends CardImpl {
super(ownerId, 10, "Exclusion Ritual", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}{W}");
this.expansionSetCode = "NPH";
// Imprint - When Exclusion Ritual enters the battlefield, exile target nonland permanent.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExclusionRitualImprintEffect(), false);
ability.addTarget(new TargetPermanent(filter));
@ -80,6 +79,7 @@ public class ExclusionRitual extends CardImpl {
}
class ExclusionRitualImprintEffect extends OneShotEffect {
ExclusionRitualImprintEffect() {
super(Outcome.Exile);
staticText = "exile target nonland permanent";
@ -108,6 +108,7 @@ class ExclusionRitualImprintEffect extends OneShotEffect {
}
class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl {
ExclusionRitualReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Detriment);
staticText = "Players can't cast spells with the same name as the exiled card";
@ -116,12 +117,12 @@ class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl
ExclusionRitualReplacementEffect(final ExclusionRitualReplacementEffect effect) {
super(effect);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.CAST_SPELL;
return event.getType() == GameEvent.EventType.CAST_SPELL_LATE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());

View file

@ -103,13 +103,13 @@ class HexParasiteEffect extends OneShotEffect {
for (String counterName : counterNames) {
if (player.chooseUse(Outcome.Neutral, "Do you want to remove " + counterName + " counters?", source, game)) {
if (permanent.getCounters().get(counterName).getCount() == 1 || toRemove == 1) {
permanent.getCounters().removeCounter(counterName, 1);
permanent.removeCounters(counterName, 1, game);
removed++;
} else {
int amount = player.getAmount(1, Math.min(permanent.getCounters().get(counterName).getCount(), toRemove - removed), "How many?", game);
if (amount > 0) {
removed += amount;
permanent.getCounters().removeCounter(counterName, amount);
permanent.removeCounters(counterName, amount, game);
}
}
}

View file

@ -92,7 +92,7 @@ class JoriEnTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(controllerId)) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) {
return true;
}

View file

@ -90,7 +90,7 @@ class PyromancersAssaultTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(controllerId)) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 2) {
return true;
}

View file

@ -47,6 +47,7 @@ import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.game.turn.Step;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
@ -110,7 +111,9 @@ class ReflectorMageEffect extends OneShotEffect {
Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
if (targetCreature != null) {
controller.moveCards(targetCreature, Zone.HAND, source, game);
game.addEffect(new ExclusionRitualReplacementEffect(targetCreature.getName(), targetCreature.getOwnerId()), source);
if (!targetCreature.getName().isEmpty()) { // if the creature had no name, no restrict effect will be created
game.addEffect(new ExclusionRitualReplacementEffect(targetCreature.getName(), targetCreature.getOwnerId()), source);
}
}
return true;
}
@ -138,13 +141,17 @@ class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.CAST_SPELL;
return event.getType() == GameEvent.EventType.CAST_SPELL_LATE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Card card = game.getCard(event.getSourceId());
if (card != null) {
Spell spell = game.getState().getStack().getSpell(event.getSourceId());
if (spell != null && spell.isFaceDown(game)) {
return false; // Face Down cast spell (Morph creature) has no name
}
return card.getName().equals(creatureName);
}
return false;

View file

@ -0,0 +1,94 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.onslaught;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
import mage.cards.CardImpl;
import mage.cards.repository.CardRepository;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
/**
*
* @author Quercitron
*/
public class AphettoDredging extends CardImpl {
public AphettoDredging(UUID ownerId) {
super(ownerId, 125, "Aphetto Dredging", Rarity.COMMON, new CardType[]{CardType.SORCERY}, "{3}{B}");
this.expansionSetCode = "ONS";
// Return up to three target creature cards of the creature type of your choice from your graveyard to your hand.
Effect effect = new ReturnFromGraveyardToHandTargetEffect();
effect.setText("Return up to three target creature cards of the creature type of your choice from your graveyard to your hand");
this.getSpellAbility().addEffect(effect);
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (ability instanceof SpellAbility) {
Player controller = game.getPlayer(ability.getControllerId());
if (controller != null) {
Choice typeChoice = new ChoiceImpl(true);
typeChoice.setMessage("Choose a creature type");
typeChoice.setChoices(CardRepository.instance.getCreatureTypes());
while (!controller.choose(Outcome.PutCreatureInPlay, typeChoice, game)) {
if (!controller.canRespond()) {
return;
}
}
String chosenType = typeChoice.getChoice();
FilterCreatureCard filter = new FilterCreatureCard(chosenType + " cards");
filter.add(new SubtypePredicate(chosenType));
ability.addTarget(new TargetCardInYourGraveyard(0, 3, filter));
}
}
}
public AphettoDredging(final AphettoDredging card) {
super(card);
}
@Override
public AphettoDredging copy() {
return new AphettoDredging(this);
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.pdsslivers;
import java.util.UUID;
/**
*
* @author Quercitron
*/
public class AphettoDredging extends mage.sets.onslaught.AphettoDredging {
public AphettoDredging(UUID ownerId) {
super(ownerId);
this.cardNumber = 28;
this.expansionSetCode = "PDS";
}
public AphettoDredging(final AphettoDredging card) {
super(card);
}
@Override
public AphettoDredging copy() {
return new AphettoDredging(this);
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.pdsslivers;
import java.util.UUID;
/**
*
* @author fenhl
*/
public class WildPair extends mage.sets.planarchaos.WildPair {
public WildPair(UUID ownerId) {
super(ownerId);
this.cardNumber = 30;
this.expansionSetCode = "H09";
}
public WildPair(final WildPair card) {
super(card);
}
@Override
public WildPair copy() {
return new WildPair(this);
}
}

View file

@ -0,0 +1,175 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.planarchaos;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.Filter;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.IntComparePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.watchers.common.CastFromHandWatcher;
/**
*
* @author fenhl
*/
public class WildPair extends CardImpl {
public WildPair(UUID ownerID) {
super(ownerID, 30, "Wild Pair", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{4}{G}{G}");
this.expansionSetCode = "PLC";
// Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library.
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new WildPairEffect(), new FilterCreaturePermanent("a creature"), true, SetTargetPointer.PERMANENT, ""),
new CastFromHandTargetCondition(),
"Whenever a creature enters the battlefield, if you cast it from your hand, you may search your library for a creature card with the same total power and toughness and put it onto the battlefield. If you do, shuffle your library."
), new CastFromHandWatcher());
}
public WildPair(final WildPair card) {
super(card);
}
@Override
public WildPair copy() {
return new WildPair(this);
}
}
class WildPairEffect extends OneShotEffect {
public WildPairEffect() {
super(Outcome.PutCreatureInPlay);
this.staticText = "search your library for a creature card with the same total power and toughness and put it onto the battlefield";
}
public WildPairEffect(final WildPairEffect effect) {
super(effect);
}
@Override
public WildPairEffect copy() {
return new WildPairEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source));
if (permanent != null) {
int totalPT = permanent.getPower().getValue() + permanent.getToughness().getValue();
FilterCreatureCard filter = new FilterCreatureCard("creature card with total power and toughness " + totalPT);
filter.add(new TotalPowerAndToughnessPredicate(Filter.ComparisonType.Equal, totalPT));
TargetCardInLibrary target = new TargetCardInLibrary(1, filter);
if (controller.searchLibrary(target, game)) {
if (target.getTargets().size() > 0) {
controller.moveCards(new CardsImpl(target.getTargets()), Zone.BATTLEFIELD, source, game);
}
}
controller.shuffleLibrary(game);
return true;
}
}
return false;
}
}
/**
*
* @author fenhl
*/
class TotalPowerAndToughnessPredicate extends IntComparePredicate<MageObject> {
public TotalPowerAndToughnessPredicate(Filter.ComparisonType type, int value) {
super(type, value);
}
@Override
protected int getInputValue(MageObject input) {
return input.getPower().getValue() + input.getToughness().getValue();
}
@Override
public String toString() {
return "TotalPowerAndToughness" + super.toString();
}
}
class CastFromHandTargetCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
UUID targetId = source.getEffects().get(0).getTargetPointer().getFirst(game, source);
Permanent permanent = game.getPermanentEntering(targetId);
int zccDiff = 0;
if (permanent == null) {
permanent = game.getPermanentOrLKIBattlefield(targetId); // can be alredy again removed from battlefield so also check LKI
zccDiff = -1;
}
if (permanent != null) {
// check that the spell is still in the LKI
Spell spell = game.getStack().getSpell(targetId);
if (spell == null || spell.getZoneChangeCounter(game) != permanent.getZoneChangeCounter(game) + zccDiff) {
if (game.getLastKnownInformation(targetId, Zone.STACK, permanent.getZoneChangeCounter(game) + zccDiff) == null) {
return false;
}
}
CastFromHandWatcher watcher = (CastFromHandWatcher) game.getState().getWatchers().get(CastFromHandWatcher.class.getName());
if (watcher != null && watcher.spellWasCastFromHand(targetId)) {
return true;
}
}
return false;
}
@Override
public String toString() {
return "you cast it from your hand";
}
}

View file

@ -101,8 +101,8 @@ class DescendantOfMasumaroEffect extends OneShotEffect {
}
Player targetOpponent = game.getPlayer(getTargetPointer().getFirst(game, source));
if (targetOpponent != null && targetOpponent.getHand().size() > 0) {
sourcePermanent.getCounters().removeCounter(CounterType.P1P1, targetOpponent.getHand().size());
game.informPlayers(controller.getLogName() + " removes " + targetOpponent.getHand().size() + " +1/+1 counters from " + sourcePermanent.getLogName());
sourcePermanent.removeCounters(CounterType.P1P1.getName(), targetOpponent.getHand().size(), game);
game.informPlayers(controller.getLogName() + " removes " + targetOpponent.getHand().size() + " +1/+1 counters from " + sourcePermanent.getLogName());
}
return true;
}

View file

@ -103,7 +103,7 @@ class ErayoSoratamiAscendantTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
return watcher != null && watcher.getAmountOfSpellsAllPlayersCastOnCurrentTurn() == 4;
}
@ -152,7 +152,7 @@ class ErayosEssenceTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (game.getOpponents(getControllerId()).contains(event.getPlayerId())) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null && watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(event.getPlayerId()) == 1) {
for (Effect effect : getEffects()) {
effect.setTargetPointer(new FixedTarget(event.getTargetId()));

View file

@ -33,8 +33,8 @@ import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSourceEffect;
@ -75,13 +75,14 @@ public class InameAsOne extends CardImpl {
this.toughness = new MageInt(8);
// When Iname as One enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, filter), false),
new CastFromHandCondition()));
this.addAbility(ability, new CastFromHandWatcher());
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(0, 1, filter)), true),
new CastFromHandSourceCondition(),
"When {this} enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle your library."),
new CastFromHandWatcher());
// When Iname as One dies, you may exile it. If you do, return target Spirit permanent card from your graveyard to the battlefield.
ability = new DiesTriggeredAbility(new InameAsOneEffect(), false);
Ability ability = new DiesTriggeredAbility(new InameAsOneEffect(), false);
ability.addTarget(new TargetCardInYourGraveyard(filter));
this.addAbility(ability);
}

View file

@ -73,7 +73,7 @@ class ImpatienceCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
return watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(game.getActivePlayerId()) == 0;
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public class EerieInterlude extends mage.sets.blessedvscursed.EerieInterlude {
public EerieInterlude(UUID ownerId) {
super(ownerId);
this.cardNumber = 994; //TODO: Fix card number
this.expansionSetCode = "SOI";
}
public EerieInterlude(final EerieInterlude card) {
super(card);
}
@Override
public EerieInterlude copy() {
return new EerieInterlude(this);
}
}

View file

@ -0,0 +1,130 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.condition.common.DeliriumCondition;
import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetSpell;
/**
*
* @author LevelX2
*/
public class InvasiveSurgery extends CardImpl {
private final static FilterSpell filter = new FilterSpell("sorcery spell");
static {
filter.add(new CardTypePredicate(CardType.SORCERY));
}
public InvasiveSurgery(UUID ownerId) {
super(ownerId, 68, "Invasive Surgery", Rarity.UNCOMMON, new CardType[]{CardType.INSTANT}, "{U}");
this.expansionSetCode = "SOI";
// Counter target sorcery spell.
// <i>Delirium</i> &mdash; If there are four or more card types among cards in your graveyard, search the graveyard, hand, and library of that spell's controller for any number of cards with the same name as that spell, exile those cards, then that player shuffles his or her library.
this.getSpellAbility().addEffect(new InvasiveSurgeryEffect());
this.getSpellAbility().addTarget(new TargetSpell(filter));
}
public InvasiveSurgery(final InvasiveSurgery card) {
super(card);
}
@Override
public InvasiveSurgery copy() {
return new InvasiveSurgery(this);
}
}
class InvasiveSurgeryEffect extends SearchTargetGraveyardHandLibraryForCardNameAndExileEffect {
public InvasiveSurgeryEffect() {
super(true, "that spell's controller", "all cards with the same name as that spell");
}
public InvasiveSurgeryEffect(final InvasiveSurgeryEffect effect) {
super(effect);
}
@Override
public InvasiveSurgeryEffect copy() {
return new InvasiveSurgeryEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
String cardName = "";
UUID spellController = null;
if (source.getTargets().get(0) instanceof TargetSpell) {
UUID objectId = source.getFirstTarget();
StackObject stackObject = game.getStack().getStackObject(objectId);
if (stackObject != null) {
MageObject targetObject = game.getObject(stackObject.getSourceId());
if (targetObject instanceof Card) {
cardName = targetObject.getName();
}
spellController = stackObject.getControllerId();
game.getStack().counter(objectId, source.getSourceId(), game);
}
}
// Check the Delirium condition
if (!DeliriumCondition.getInstance().apply(game, source)) {
return true;
}
return this.applySearchAndExile(game, source, cardName, spellController);
}
@Override
public String getText(Mode mode) {
return "Counter target sorcery spell.<br><br>"
+ "<i>Delirium</i> &mdash; If there are four or more card types among cards in your graveyard, "
+ "search the graveyard, hand, and library of that spell's controller for any number of cards "
+ "with the same name as that spell, exile those cards, then that player shuffles his or her library";
}
}

View file

@ -0,0 +1,82 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.shadowsoverinnistrad;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.EntersBattlefieldTappedAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.target.common.TargetCreaturePermanent;
/**
*
* @author LevelX2
*/
public class StichedMangler extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature an opponent controls");
static {
filter.add(new ControllerPredicate(TargetController.OPPONENT));
}
public StichedMangler(UUID ownerId) {
super(ownerId, 89, "Stiched Mangler", Rarity.COMMON, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.expansionSetCode = "SOI";
this.subtype.add("Zombie");
this.subtype.add("Horror");
this.power = new MageInt(2);
this.toughness = new MageInt(3);
// Stitched Mangler enters the battlefield tapped.
this.addAbility(new EntersBattlefieldTappedAbility());
// When Stitched Mangler enters the battlefield, tap target creature an opponent controls. That creature doesn't untap during its controller's next untap step.
EntersBattlefieldTriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new TapTargetEffect());
ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect());
ability.addTarget(new TargetCreaturePermanent(filter));
this.addAbility(ability);
}
public StichedMangler(final StichedMangler card) {
super(card);
}
@Override
public StichedMangler copy() {
return new StichedMangler(this);
}
}

View file

@ -30,16 +30,13 @@ package mage.sets.sorinvstibalt;
import java.util.UUID;
import mage.MageInt;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.BasicManaEffect;
import mage.abilities.effects.common.ExileAllEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.common.FilterAttackingCreature;
import mage.watchers.common.CastFromHandWatcher;
/**
@ -56,10 +53,11 @@ public class CoalStoker extends CardImpl {
this.toughness = new MageInt(3);
// When Coal Stoker enters the battlefield, if you cast it from your hand, add {R}{R}{R} to your mana pool.
Ability ability = new EntersBattlefieldTriggeredAbility(
new ConditionalOneShotEffect(new BasicManaEffect(new Mana(3, 0, 0, 0, 0, 0, 0, 0)), new CastFromHandCondition(),
" if you cast it from your hand, add {R}{R}{R} to your mana pool."));
this.addAbility(ability, new CastFromHandWatcher());
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new BasicManaEffect(new Mana(3, 0, 0, 0, 0, 0, 0, 0)), false),
new CastFromHandSourceCondition(),
"When {this} enters the battlefield, if you cast it from your hand, add {R}{R}{R} to your mana pool."),
new CastFromHandWatcher());
}
public CoalStoker(final CoalStoker card) {

View file

@ -73,10 +73,9 @@ public class CrovaxTheCursed extends CardImpl {
Ability ability = new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new CrovaxTheCursedEffect(), TargetController.YOU, false);
this.addAbility(ability);
// {B}: Crovax gains flying until end of turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{B}")));
}
public CrovaxTheCursed(final CrovaxTheCursed card) {
@ -118,11 +117,9 @@ class CrovaxTheCursedEffect extends OneShotEffect {
game.informPlayers(controller.getLogName() + " puts a +1/+1 counter on " + sourceObject.getName());
}
}
} else {
if (sourceObject != null && sourceObject.getCounters().containsKey(CounterType.P1P1)) {
sourceObject.getCounters().removeCounter(CounterType.P1P1, 1);
game.informPlayers(controller.getLogName() + " removes a +1/+1 counter from " + sourceObject.getName());
}
} else if (sourceObject != null && sourceObject.getCounters().containsKey(CounterType.P1P1)) {
sourceObject.removeCounters(CounterType.P1P1.getName(), 1, game);
game.informPlayers(controller.getLogName() + " removes a +1/+1 counter from " + sourceObject.getName());
}
return true;
}

View file

@ -107,10 +107,10 @@ class MagmasaurEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent sourceObject = (Permanent)source.getSourceObjectIfItStillExists(game);
Permanent sourceObject = (Permanent) source.getSourceObjectIfItStillExists(game);
if (sourceObject != null && controller != null) {
if (controller.chooseUse(outcome, "Remove a +1/+1 counter from " + sourceObject.getLogName() + "?", source, game)) {
sourceObject.getCounters().removeCounter(CounterType.P1P1, 1);
sourceObject.removeCounters(CounterType.P1P1.getName(), 1, game);
} else {
int counters = sourceObject.getCounters().getCount(CounterType.P1P1);
sourceObject.sacrifice(source.getSourceId(), game);

View file

@ -33,7 +33,7 @@ import mage.abilities.common.DealsCombatDamageToACreatureTriggeredAbility;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.CastFromHandCondition;
import mage.abilities.condition.common.CastFromHandSourceCondition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.LoseGameSourceControllerEffect;
@ -62,7 +62,7 @@ public class PhageTheUntouchable extends CardImpl {
// When Phage the Untouchable enters the battlefield, if you didn't cast it from your hand, you lose the game.
this.addAbility(new ConditionalTriggeredAbility(
new EntersBattlefieldTriggeredAbility(new LoseGameSourceControllerEffect(), false),
new InvertCondition(new CastFromHandCondition()),
new InvertCondition(new CastFromHandSourceCondition()),
"When {this} enters the battlefield, if you didn't cast it from your hand, you lose the game"
), new CastFromHandWatcher());

View file

@ -0,0 +1,131 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.timespiral;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.MorphAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetControlledCreaturePermanent;
/**
*
* @author djbrez
*/
public class LiegeOfThePit extends CardImpl {
public LiegeOfThePit(UUID ownerId) {
super(ownerId, 113, "Liege of the Pit", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{B}{B}{B}");
this.expansionSetCode = "TSP";
this.subtype.add("Demon");
this.power = new MageInt(7);
this.toughness = new MageInt(7);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Trample
this.addAbility(TrampleAbility.getInstance());
// At the beginning of your upkeep, sacrifice a creature other than Liege of the Pit. If you can't, Liege of the Pit deals 7 damage to you.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new LiegeOfThePitEffect(), TargetController.YOU, false));
// Morph {B}{B}{B}{B}
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{B}{B}{B}{B}")));
}
public LiegeOfThePit(final LiegeOfThePit card) {
super(card);
}
@Override
public LiegeOfThePit copy() {
return new LiegeOfThePit(this);
}
}
class LiegeOfThePitEffect extends OneShotEffect {
public LiegeOfThePitEffect() {
super(Outcome.Damage);
this.staticText = "Sacrifice a creature other than {this}. If you can't {this} deals 7 damage to you.";
}
public LiegeOfThePitEffect(final LiegeOfThePitEffect effect) {
super(effect);
}
@Override
public LiegeOfThePitEffect copy() {
return new LiegeOfThePitEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent == null) {
sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD);
}
if (player == null || sourcePermanent == null) {
return false;
}
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature other than " + sourcePermanent.getName());
filter.add(new AnotherPredicate());
Target target = new TargetControlledCreaturePermanent(1, 1, filter, true);
if (target.canChoose(source.getSourceId(), player.getId(), game)) {
player.choose(Outcome.Sacrifice, target, source.getSourceId(), game);
Permanent permanent = game.getPermanent(target.getFirstTarget());
if (permanent != null) {
permanent.sacrifice(source.getSourceId(), game);
return true;
}
} else {
player.damage(7, source.getSourceId(), game, false, true);
return true;
}
return false;
}
}

View file

@ -0,0 +1,207 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.timespiral;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.AsTurnedFaceUpEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CopyEffect;
import mage.abilities.effects.common.CopyPermanentEffect;
import mage.abilities.keyword.MorphAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.util.functions.ApplyToPermanent;
/**
*
* @author spjspj
*/
public class VesuvanShapeshifter extends CardImpl {
protected Ability turnFaceUpAbility = null;
private static final String effectText = "as a copy of any creature on the battlefield until {this} is turned faced down";
public VesuvanShapeshifter(UUID ownerId) {
super(ownerId, 90, "Vesuvan Shapeshifter", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{3}{U}{U}");
this.expansionSetCode = "TSP";
this.subtype.add("Shapeshifter");
this.power = new MageInt(0);
this.toughness = new MageInt(0);
// Morph {1}{U}
this.addAbility(new MorphAbility(this, new ManaCostsImpl("{1}{U}")));
// As Vesuvan Shapeshifter turned face up, may choose another creature. If you do, until Vesuvan Shapeshifter is turned face down, it becomes a copy of that creature
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new AsTurnedFaceUpEffect(new VesuvanShapeshifterEffect(), false));
ability.setWorksFaceDown(true);
this.addAbility(ability);
// As Vesuvan Shapeshifter etbs, may choose another creature. If you do, until Vesuvan Shapeshifter is turned face down, it becomes a copy of that creature
Effect effect = new CopyPermanentEffect(new FilterCreaturePermanent());
effect.setText(effectText);
ability = new EntersBattlefieldAbility(effect, true);
ability.setWorksFaceDown(false);
this.addAbility(ability);
// At the beginning of your upkeep, you may turn this creature face down
effect = new VesuvanShapeshifterFaceDownEffect();
ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true);
this.addAbility(ability);
}
public VesuvanShapeshifter(final VesuvanShapeshifter card) {
super(card);
}
@Override
public VesuvanShapeshifter copy() {
return new VesuvanShapeshifter(this);
}
}
class VesuvanShapeshifterEffect extends OneShotEffect {
public VesuvanShapeshifterEffect() {
super(Outcome.Copy);
staticText = "have {this} become a copy of a creature and gain this ability";
}
public VesuvanShapeshifterEffect(final VesuvanShapeshifterEffect effect) {
super(effect);
}
@Override
public VesuvanShapeshifterEffect copy() {
return new VesuvanShapeshifterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
ApplyToPermanent vesuvanShapeShifterFaceUpApplier = new ApplyToPermanent() {
@Override
public Boolean apply(Game game, Permanent permanent) {
Effect effect = new VesuvanShapeshifterFaceDownEffect();
Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true);
permanent.getAbilities().add(ability);
permanent.addAbility(new MorphAbility(permanent, new ManaCostsImpl("{1}{U}")), permanent.getId(), game);
return true;
}
@Override
public Boolean apply(Game game, MageObject mageObject) {
Effect effect = new VesuvanShapeshifterFaceDownEffect();
Ability ability = new BeginningOfUpkeepTriggeredAbility(effect, TargetController.YOU, true);
mageObject.getAbilities().add(ability);
return true;
}
};
Permanent copyToCreature = game.getPermanent(source.getSourceId());
if (copyToCreature != null) {
FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature");
filter.add(new AnotherPredicate());
TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false);
if (controller.chooseTarget(Outcome.BecomeCreature, target, source, game) && !target.getTargets().isEmpty()) {
Permanent copyFromCreature = game.getPermanentOrLKIBattlefield(target.getFirstTarget());
if (copyFromCreature != null) {
game.copyPermanent(Duration.Custom, copyFromCreature, copyToCreature.getId(), source, vesuvanShapeShifterFaceUpApplier);
source.getTargets().clear();
return true;
}
}
}
return false;
}
}
class VesuvanShapeshifterFaceDownEffect extends OneShotEffect {
public VesuvanShapeshifterFaceDownEffect() {
super(Outcome.Copy);
staticText = "have {this} become a morphed, faced down creature";
}
public VesuvanShapeshifterFaceDownEffect(final VesuvanShapeshifterFaceDownEffect effect) {
super(effect);
}
@Override
public VesuvanShapeshifterFaceDownEffect copy() {
return new VesuvanShapeshifterFaceDownEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Permanent permanent = game.getPermanent(source.getSourceId());
if (controller != null && permanent != null) {
permanent.removeAllAbilities(source.getSourceId(), game);
// Set any previous copy effects to 'discarded'
for (Effect effect : game.getState().getContinuousEffects().getLayeredEffects(game)) {
if (effect instanceof CopyEffect) {
CopyEffect copyEffect = (CopyEffect) effect;
if (copyEffect.getSourceId().equals(permanent.getId())) {
copyEffect.discard();
}
}
}
permanent.turnFaceDown(game, source.getControllerId());
permanent.setManifested(false);
permanent.setMorphed(true);
return permanent.isFaceDown(game);
}
return false;
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.sets.weatherlight;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.target.TargetSpell;
import mage.target.common.TargetControlledPermanent;
/**
*
* @author djbrez
*/
public class Abjure extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("a blue permanent");
static {
filter.add(new ColorPredicate(ObjectColor.BLUE));
}
public Abjure(UUID ownerId) {
super(ownerId, 31, "Abjure", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{U}");
this.expansionSetCode = "WTH";
// As an additional cost to cast Abjure, sacrifice a blue permanent.
this.getSpellAbility().addCost(new SacrificeTargetCost(new TargetControlledPermanent(1,1,filter, true)));
// Counter target spell.
this.getSpellAbility().addEffect(new CounterTargetEffect());
this.getSpellAbility().addTarget(new TargetSpell());
}
public Abjure(final Abjure card) {
super(card);
}
@Override
public Abjure copy() {
return new Abjure(this);
}
}

View file

@ -27,25 +27,20 @@
*/
package mage.sets.worldwake;
import java.util.List;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
import mage.abilities.effects.common.TapTargetEffect;
import mage.cards.CardImpl;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.Watcher;
import mage.watchers.common.PermanentsEnteredBattlefieldWatcher;
/**
*
@ -58,16 +53,13 @@ public class PermafrostTrap extends CardImpl {
this.expansionSetCode = "WWK";
this.subtype.add("Trap");
// If an opponent had a green creature enter the battlefield under his or her control this turn, you may pay {U} rather than pay Permafrost Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new PermafrostTrapAlternativeCost());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{U}"), PermafrostTrapCondition.getInstance()), new PermanentsEnteredBattlefieldWatcher());
// Tap up to two target creatures. Those creatures don't untap during their controller's next untap step.
TargetCreaturePermanent target = new TargetCreaturePermanent(0, 2);
this.getSpellAbility().addTarget(target);
this.getSpellAbility().addEffect(new PermafrostTrapEffect());
this.getSpellAbility().addWatcher(new PermafrostTrapWatcher());
this.getSpellAbility().addEffect(new TapTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(0, 2));
this.getSpellAbility().addEffect(new DontUntapInControllersNextUntapStepTargetEffect());
}
public PermafrostTrap(final PermafrostTrap card) {
@ -80,99 +72,34 @@ public class PermafrostTrap extends CardImpl {
}
}
class PermafrostTrapWatcher extends Watcher {
class PermafrostTrapCondition implements Condition {
public PermafrostTrapWatcher() {
super("PermafrostTrapWatcher", WatcherScope.GAME);
}
private static final PermafrostTrapCondition fInstance = new PermafrostTrapCondition();
public PermafrostTrapWatcher(final PermafrostTrapWatcher watcher) {
super(watcher);
}
@Override
public PermafrostTrapWatcher copy() {
return new PermafrostTrapWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (condition == true) { // no need to check - condition has already occured
return;
}
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
Permanent perm = game.getPermanent(event.getTargetId());
if (perm.getCardType().contains(CardType.CREATURE) && perm.getColor(game).contains(ObjectColor.GREEN) && !perm.getControllerId().equals(controllerId)) {
condition = true;
}
}
}
@Override
public void reset() {
super.reset();
condition = false;
}
}
class PermafrostTrapAlternativeCost extends AlternativeCostImpl<Cost> {
public PermafrostTrapAlternativeCost() {
super("you may pay {U} rather than pay Permafrost Trap's mana cost");
this.add(new ColoredManaCost(ColoredManaSymbol.U));
}
public PermafrostTrapAlternativeCost(final PermafrostTrapAlternativeCost cost) {
super(cost);
}
@Override
public PermafrostTrapAlternativeCost copy() {
return new PermafrostTrapAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
PermafrostTrapWatcher watcher = (PermafrostTrapWatcher) game.getState().getWatchers().get("PermafrostTrapWatcher");
if (watcher != null && watcher.conditionMet()) {
return true;
}
return false;
}
@Override
public String getText() {
return "If an opponent had a green creature enter the battlefield under his or her control this turn, you may pay {U} rather than pay Permafrost Trap's mana cost";
}
}
class PermafrostTrapEffect extends OneShotEffect {
public PermafrostTrapEffect() {
super(Outcome.Detriment);
staticText = "Tap up to two target creatures. Those creatures don't untap during their controller's next untap step";
}
public PermafrostTrapEffect(final PermafrostTrapEffect effect) {
super(effect);
public static Condition getInstance() {
return fInstance;
}
@Override
public boolean apply(Game game, Ability source) {
for (UUID targetId : this.targetPointer.getTargets(game, source)) {
Permanent creature = game.getPermanent(targetId);
if (creature != null) {
creature.tap(game);
DontUntapInControllersNextUntapStepTargetEffect effect = new DontUntapInControllersNextUntapStepTargetEffect();
effect.setTargetPointer(new FixedTarget(targetId));
game.addEffect(effect, source);
PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getName());
if (watcher != null) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
List<Permanent> permanents = watcher.getThisTurnEnteringPermanents(opponentId);
if (permanents != null) {
for (Permanent permanent : permanents) {
if (permanent.getCardType().contains(CardType.CREATURE) && permanent.getColor(game).isGreen()) {
return true;
}
}
}
}
}
return false;
}
@Override
public PermafrostTrapEffect copy() {
return new PermafrostTrapEffect(this);
public String toString() {
return "If an opponent had a green creature enter the battlefield under his or her control this turn";
}
}

View file

@ -27,13 +27,12 @@
*/
package mage.sets.worldwake;
import java.util.HashSet;
import java.util.Set;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.PreventionEffectData;
import mage.abilities.effects.PreventionEffectImpl;
@ -42,7 +41,6 @@ import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@ -51,7 +49,7 @@ import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetSource;
import mage.target.common.TargetCreatureOrPlayer;
import mage.watchers.Watcher;
import mage.watchers.common.SpellsCastWatcher;
/**
*
@ -65,13 +63,11 @@ public class RefractionTrap extends CardImpl {
this.subtype.add("Trap");
// If an opponent cast a red instant or sorcery spell this turn, you may pay {W} rather than pay Refraction Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new RefractionTrapAlternativeCost());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{W}"), RefractionTrapCondition.getInstance()), new SpellsCastWatcher());
// Prevent the next 3 damage that a source of your choice would deal to you and/or permanents you control this turn. If damage is prevented this way, Refraction Trap deals that much damage to target creature or player.
this.getSpellAbility().addEffect(new RefractionTrapPreventDamageEffect(Duration.EndOfTurn, 3));
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
this.getSpellAbility().addWatcher(new RefractionTrapWatcher());
}
public RefractionTrap(final RefractionTrap card) {
@ -84,89 +80,43 @@ public class RefractionTrap extends CardImpl {
}
}
class RefractionTrapWatcher extends Watcher {
class RefractionTrapCondition implements Condition {
Set<UUID> playersMetCondition = new HashSet<>();
private static final RefractionTrapCondition fInstance = new RefractionTrapCondition();
public RefractionTrapWatcher() {
super("RefractionTrapWatcher", WatcherScope.GAME);
}
public RefractionTrapWatcher(final RefractionTrapWatcher watcher) {
super(watcher);
this.playersMetCondition.addAll(watcher.playersMetCondition);
public static Condition getInstance() {
return fInstance;
}
@Override
public RefractionTrapWatcher copy() {
return new RefractionTrapWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell.getColor(game).isRed()) {
if (spell.getCardType().contains(CardType.INSTANT)
|| spell.getCardType().contains(CardType.SORCERY)) {
playersMetCondition.add(event.getPlayerId());
}
}
}
}
public boolean conditionMetForAnOpponent(UUID controllerId, Game game) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
for (UUID playerId : playersMetCondition) {
if (controller.hasOpponent(playerId, game)) {
return true;
public boolean apply(Game game, Ability source) {
SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getName());
if (watcher != null) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
List<Spell> spells = watcher.getSpellsCastThisTurn(opponentId);
if (spells != null) {
for (Spell spell : spells) {
if ((spell.getCardType().contains(CardType.SORCERY) || spell.getCardType().contains(CardType.INSTANT))
&& spell.getColor(game).isRed()) {
return true;
}
}
}
}
}
return false;
}
@Override
public void reset() {
playersMetCondition.clear();
super.reset();
}
}
class RefractionTrapAlternativeCost extends AlternativeCostImpl {
public RefractionTrapAlternativeCost() {
super("You may pay {W} rather than pay Refraction Trap's mana cost");
this.add(new ManaCostsImpl<ManaCost>("{W}"));
}
public RefractionTrapAlternativeCost(final RefractionTrapAlternativeCost cost) {
super(cost);
}
@Override
public RefractionTrapAlternativeCost copy() {
return new RefractionTrapAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
RefractionTrapWatcher watcher = (RefractionTrapWatcher) game.getState().getWatchers().get("RefractionTrapWatcher");
return watcher != null && watcher.conditionMetForAnOpponent(source.getControllerId(), game);
}
@Override
public String getText() {
return "If an opponent cast a red instant or sorcery spell this turn, you may pay {W} rather than pay {this} mana cost";
public String toString() {
return "If an opponent cast a red instant or sorcery spell this turn";
}
}
class RefractionTrapPreventDamageEffect extends PreventionEffectImpl {
private final TargetSource target;
private int amount;
private final int amount;
public RefractionTrapPreventDamageEffect(Duration duration, int amount) {
super(duration, amount, false, false);

View file

@ -27,26 +27,22 @@
*/
package mage.sets.worldwake;
import java.util.List;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ChooseNewTargetsTargetEffect;
import mage.cards.CardImpl;
import mage.constants.ColoredManaSymbol;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.FilterSpell;
import mage.filter.predicate.mageobject.NumberOfTargetsPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.target.TargetSpell;
import mage.watchers.Watcher;
import mage.watchers.common.SpellsCastWatcher;
/**
*
@ -65,15 +61,14 @@ public class RicochetTrap extends CardImpl {
this.expansionSetCode = "WWK";
this.subtype.add("Trap");
// If an opponent cast a blue spell this turn, you may pay {R} rather than pay Ricochet Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new RicochetTrapAlternativeCost());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{R}"), RicochetTrapCondition.getInstance()));
// Change the target of target spell with a single target.
this.getSpellAbility().addEffect(new ChooseNewTargetsTargetEffect(true, true));
this.getSpellAbility().addTarget(new TargetSpell(filter));
this.getSpellAbility().addWatcher(new RicochetTrapWatcher());
this.getSpellAbility().addWatcher(new SpellsCastWatcher());
}
public RicochetTrap(final RicochetTrap card) {
@ -86,70 +81,34 @@ public class RicochetTrap extends CardImpl {
}
}
class RicochetTrapWatcher extends Watcher {
class RicochetTrapCondition implements Condition {
public RicochetTrapWatcher() {
super("RicochetTrapWatcher", WatcherScope.GAME);
}
private static final RicochetTrapCondition fInstance = new RicochetTrapCondition();
public RicochetTrapWatcher(final RicochetTrapWatcher watcher) {
super(watcher);
public static Condition getInstance() {
return fInstance;
}
@Override
public RicochetTrapWatcher copy() {
return new RicochetTrapWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (condition == true) //no need to check - condition has already occured
{
return;
}
if (event.getType() == EventType.SPELL_CAST
&& game.getOpponents(controllerId).contains(event.getPlayerId())) {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell.getColor(game).isBlue()) {
condition = true;
public boolean apply(Game game, Ability source) {
SpellsCastWatcher watcher = (SpellsCastWatcher) game.getState().getWatchers().get(SpellsCastWatcher.class.getName());
if (watcher != null) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
List<Spell> spells = watcher.getSpellsCastThisTurn(opponentId);
if (spells != null) {
for (Spell spell : spells) {
if (spell.getColor(game).isBlue()) {
return true;
}
}
}
}
}
}
@Override
public void reset() {
super.reset();
condition = false;
}
}
class RicochetTrapAlternativeCost extends AlternativeCostImpl<Cost> {
public RicochetTrapAlternativeCost() {
super("You may pay {R} rather than pay Ricochet Trap's mana cost");
this.add(new ColoredManaCost(ColoredManaSymbol.R));
}
public RicochetTrapAlternativeCost(final RicochetTrapAlternativeCost cost) {
super(cost);
}
@Override
public RicochetTrapAlternativeCost copy() {
return new RicochetTrapAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
RicochetTrapWatcher watcher = (RicochetTrapWatcher) game.getState().getWatchers().get("RicochetTrapWatcher");
if (watcher != null && watcher.conditionMet()) {
return true;
}
return false;
}
@Override
public String getText() {
return "If an opponent cast a blue spell this turn, you may pay {R} rather than pay {this} mana cost";
public String toString() {
return "If an opponent cast a blue spell this turn";
}
}

View file

@ -27,17 +27,16 @@
*/
package mage.sets.worldwake;
import java.util.List;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.game.Game;
@ -61,9 +60,8 @@ public class SlingbowTrap extends CardImpl {
this.expansionSetCode = "WWK";
this.subtype.add("Trap");
// If a black creature with flying is attacking, you may pay {G} rather than pay Slingbow Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new SlingbowTrapAlternativeCost());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{G}"), SlingbowTrapCondition.getInstance()));
// Destroy target attacking creature with flying.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
@ -80,37 +78,29 @@ public class SlingbowTrap extends CardImpl {
}
}
class SlingbowTrapAlternativeCost extends AlternativeCostImpl<Cost> {
class SlingbowTrapCondition implements Condition {
public SlingbowTrapAlternativeCost() {
super("you may pay {G} rather than pay {this}'s mana cost");
this.add(new ManaCostsImpl("{G}"));
}
private static final SlingbowTrapCondition fInstance = new SlingbowTrapCondition();
public SlingbowTrapAlternativeCost(final SlingbowTrapAlternativeCost cost) {
super(cost);
public static Condition getInstance() {
return fInstance;
}
@Override
public SlingbowTrapAlternativeCost copy() {
return new SlingbowTrapAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
List<UUID> attackers = game.getCombat().getAttackers();
for (UUID creatureId : attackers) {
Permanent creature = game.getPermanent(creatureId);
if (creature.getColor(game).isBlack()
&& creature.getAbilities().contains(FlyingAbility.getInstance())) {
return true;
public boolean apply(Game game, Ability source) {
for (UUID attackingCreatureId : game.getCombat().getAttackers()) {
Permanent attackingCreature = game.getPermanent(attackingCreatureId);
if (attackingCreature != null) {
if (attackingCreature.getColor(game).isBlack() && attackingCreature.hasAbility(FlyingAbility.getInstance().getId(), game)) {
return true;
}
}
}
return false;
}
@Override
public String getText() {
return "If a black creature with flying is attacking, you may pay {G} rather than pay Slingbow Trap's mana cost";
public String toString() {
return "If a black creature with flying is attacking";
}
}

View file

@ -29,7 +29,8 @@ package mage.sets.zendikar;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageMultiEffect;
import mage.cards.CardImpl;
@ -50,7 +51,7 @@ public class ArrowVolleyTrap extends CardImpl {
this.subtype.add("Trap");
// If four or more creatures are attacking, you may pay {1}{W} rather than pay Arrow Volley Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new ArrowVolleyTrapAlternativeCost());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{1}{W}"), ArrowVolleyTrapCondition.getInstance()));
// Arrow Volley Trap deals 5 damage divided as you choose among any number of target attacking creatures.
this.getSpellAbility().addEffect(new DamageMultiEffect(5));
@ -68,29 +69,21 @@ public class ArrowVolleyTrap extends CardImpl {
}
}
class ArrowVolleyTrapAlternativeCost extends AlternativeCostImpl {
class ArrowVolleyTrapCondition implements Condition {
public ArrowVolleyTrapAlternativeCost() {
super("you may pay {1}{W} rather than pay Arrow Volley Trap's mana cost");
this.add(new ManaCostsImpl("{1}{W}"));
}
private static final ArrowVolleyTrapCondition fInstance = new ArrowVolleyTrapCondition();
public ArrowVolleyTrapAlternativeCost(final ArrowVolleyTrapAlternativeCost cost) {
super(cost);
public static Condition getInstance() {
return fInstance;
}
@Override
public ArrowVolleyTrapAlternativeCost copy() {
return new ArrowVolleyTrapAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
public boolean apply(Game game, Ability source) {
return game.getCombat().getAttackers().size() > 3;
}
@Override
public String getText() {
return "If four or more creatures are attacking, you may pay {1}{W} rather than pay {this}'s mana cost";
public String toString() {
return "If four or more creatures are attacking";
}
}

View file

@ -27,20 +27,20 @@
*/
package mage.sets.zendikar;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.BeastToken2;
import mage.watchers.Watcher;
import mage.watchers.common.PermanentsEnteredBattlefieldWatcher;
/**
*
@ -54,8 +54,7 @@ public class BalothCageTrap extends CardImpl {
this.subtype.add("Trap");
// If an opponent had an artifact enter the battlefield under his or her control this turn, you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new BalothCageTrapAlternativeCost());
this.getSpellAbility().addWatcher(new BalothCageTrapWatcher());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{1}{G}"), BalothCageTrapCondition.getInstance()), new PermanentsEnteredBattlefieldWatcher());
// Put a 4/4 green Beast creature token onto the battlefield.
this.getSpellAbility().addEffect(new CreateTokenEffect(new BeastToken2()));
@ -71,68 +70,34 @@ public class BalothCageTrap extends CardImpl {
}
}
class BalothCageTrapWatcher extends Watcher {
class BalothCageTrapCondition implements Condition {
public BalothCageTrapWatcher() {
super("BalothCageTrapWatcher", WatcherScope.GAME);
}
private static final BalothCageTrapCondition fInstance = new BalothCageTrapCondition();
public BalothCageTrapWatcher(final BalothCageTrapWatcher watcher) {
super(watcher);
public static Condition getInstance() {
return fInstance;
}
@Override
public BalothCageTrapWatcher copy() {
return new BalothCageTrapWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (condition == true) { // no need to check - condition has already occured
return;
}
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
Permanent perm = game.getPermanent(event.getTargetId());
if (perm.getCardType().contains(CardType.ARTIFACT) && !perm.getControllerId().equals(controllerId)) {
condition = true;
public boolean apply(Game game, Ability source) {
PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getName());
if (watcher != null) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
List<Permanent> permanents = watcher.getThisTurnEnteringPermanents(opponentId);
if (permanents != null) {
for (Permanent permanent : permanents) {
if (permanent.getCardType().contains(CardType.ARTIFACT)) {
return true;
}
}
}
}
}
}
@Override
public void reset() {
super.reset();
condition = false;
}
}
class BalothCageTrapAlternativeCost extends AlternativeCostImpl {
public BalothCageTrapAlternativeCost() {
super("you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost");
this.add(new ManaCostsImpl("{1}{G}"));
}
public BalothCageTrapAlternativeCost(final BalothCageTrapAlternativeCost cost) {
super(cost);
}
@Override
public BalothCageTrapAlternativeCost copy() {
return new BalothCageTrapAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
BalothCageTrapWatcher watcher = (BalothCageTrapWatcher) game.getState().getWatchers().get("BalothCageTrapWatcher");
if (watcher != null && watcher.conditionMet()) {
return true;
}
return false;
}
@Override
public String getText() {
return "If an opponent had an artifact enter the battlefield under his or her control this turn, you may pay {1}{G} rather than pay Baloth Cage Trap's mana cost";
public String toString() {
return "If an opponent had an artifact enter the battlefield under his or her control this turn";
}
}

View file

@ -27,25 +27,24 @@
*/
package mage.sets.zendikar;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ColoredManaCost;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.SnakeToken;
import mage.game.stack.StackObject;
import mage.players.Player;
import mage.watchers.Watcher;
/**
@ -59,11 +58,9 @@ public class CobraTrap extends CardImpl {
this.expansionSetCode = "ZEN";
this.subtype.add("Trap");
// If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled, you may pay {G} rather than pay Cobra Trap's mana cost.
this.getSpellAbility().addAlternativeCost(
new CobraTrapAlternativeCost());
this.getSpellAbility().addWatcher(new CobraTrapWatcher());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{G}"), CobraTrapCondition.getInstance()), new CobraTrapWatcher());
// Put four 1/1 green Snake creature tokens onto the battlefield.
this.getSpellAbility().addEffect(new CreateTokenEffect(new SnakeToken(), 4));
}
@ -78,10 +75,33 @@ public class CobraTrap extends CardImpl {
}
}
class CobraTrapCondition implements Condition {
private static final CobraTrapCondition fInstance = new CobraTrapCondition();
public static Condition getInstance() {
return fInstance;
}
@Override
public boolean apply(Game game, Ability source) {
CobraTrapWatcher watcher = (CobraTrapWatcher) game.getState().getWatchers().get(CobraTrapWatcher.class.getName());
return watcher != null && watcher.conditionMet(source.getControllerId());
}
@Override
public String toString() {
return "If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled";
}
}
class CobraTrapWatcher extends Watcher {
Set<UUID> players = new HashSet<>();
public CobraTrapWatcher() {
super("noncreature permanent destroyed", WatcherScope.PLAYER);
super(CobraTrapWatcher.class.getName(), WatcherScope.GAME);
}
public CobraTrapWatcher(final CobraTrapWatcher watcher) {
@ -95,51 +115,26 @@ class CobraTrapWatcher extends Watcher {
@Override
public void watch(GameEvent event, Game game) {
if (condition == true) { // no need to check - condition has already occured
return;
}
Player player = game.getPlayer(controllerId);
if (player != null && event.getType() == EventType.DESTROYED_PERMANENT) {
Permanent perm = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
if (event.getType() == EventType.DESTROYED_PERMANENT) {
Permanent perm = (Permanent) game.getPermanentOrLKIBattlefield(event.getTargetId()); // can regenerate or be indestructible
if (perm != null && !perm.getCardType().contains(CardType.CREATURE)) {
if (game.getStack().size() > 0) {
StackObject spell = game.getStack().getStackObject(event.getSourceId());
if (spell != null && game.getOpponents(controllerId).contains(spell.getControllerId())) {
condition = true;
if (spell != null && game.getOpponents(perm.getControllerId()).contains(spell.getControllerId())) {
players.add(perm.getControllerId());
}
}
}
}
}
}
class CobraTrapAlternativeCost extends AlternativeCostImpl<Cost> {
public CobraTrapAlternativeCost() {
super("you may pay {G} rather than pay Cobra Trap's mana cost");
this.add(new ColoredManaCost(ColoredManaSymbol.G));
}
public CobraTrapAlternativeCost(final CobraTrapAlternativeCost cost) {
super(cost);
}
@Override
public CobraTrapAlternativeCost copy() {
return new CobraTrapAlternativeCost(this);
public void reset() {
super.reset();
players.clear();
}
@Override
public boolean isAvailable(Game game, Ability source) {
Watcher watcher = game.getState().getWatchers().get("noncreature permanent destroyed", source.getControllerId());
if (watcher != null && watcher.conditionMet()) {
return true;
}
return false;
}
@Override
public String getText() {
return "If a noncreature permanent under your control was destroyed this turn by a spell or ability an opponent controlled, you may pay {G} rather than pay Cobra Trap's mana cost";
public boolean conditionMet(UUID playerId) {
return players.contains(playerId);
}
}

View file

@ -28,15 +28,14 @@
package mage.sets.zendikar;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
@ -54,11 +53,10 @@ public class InfernoTrap extends CardImpl {
this.expansionSetCode = "ZEN";
this.subtype.add("Trap");
// If you've been dealt damage by two or more creatures this turn, you may pay {R} rather than pay Inferno Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new InfernoTrapAlternativeCost());
this.getSpellAbility().addWatcher(new ControllerDamagedByCreatureWatcher());
// Inferno Trap deals 4 damage to target creature.
this.getSpellAbility().addEffect(new DamageTargetEffect(4));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());

View file

@ -27,26 +27,23 @@
*/
package mage.sets.zendikar;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DamageAllEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterLandPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetLandPermanent;
import mage.watchers.Watcher;
import mage.watchers.common.PermanentsEnteredBattlefieldWatcher;
/**
*
@ -60,8 +57,7 @@ public class LavaballTrap extends CardImpl {
this.subtype.add("Trap");
// If an opponent had two or more lands enter the battlefield under his or her control this turn, you may pay {3}{R}{R} rather than pay Lavaball Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new LavaballTrapAlternativeCost());
this.getSpellAbility().addWatcher(new LavaballTrapWatcher());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{3}{R}{R}"), LavaballTrapCondition.getInstance()), new PermanentsEnteredBattlefieldWatcher());
// Destroy two target lands. Lavaball Trap deals 4 damage to each creature.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
@ -80,87 +76,38 @@ public class LavaballTrap extends CardImpl {
}
}
class LavaballTrapWatcher extends Watcher {
class LavaballTrapCondition implements Condition {
private Map<UUID, Integer> amountOfLandsPlayedThisTurn = new HashMap<>();
private static final LavaballTrapCondition fInstance = new LavaballTrapCondition();
public LavaballTrapWatcher() {
super("LavaballTrapWatcher", WatcherScope.GAME);
}
public LavaballTrapWatcher(final LavaballTrapWatcher watcher) {
super(watcher);
for (Map.Entry<UUID, Integer> entry : watcher.amountOfLandsPlayedThisTurn.entrySet()) {
amountOfLandsPlayedThisTurn.put(entry.getKey(), entry.getValue());
}
public static Condition getInstance() {
return fInstance;
}
@Override
public LavaballTrapWatcher copy() {
return new LavaballTrapWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
Permanent perm = game.getPermanent(event.getTargetId());
if (perm.getCardType().contains(CardType.LAND)) {
Integer amount = amountOfLandsPlayedThisTurn.get(perm.getControllerId());
if (amount == null) {
amount = 1;
} else {
++amount;
public boolean apply(Game game, Ability source) {
PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getName());
if (watcher != null) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
List<Permanent> permanents = watcher.getThisTurnEnteringPermanents(opponentId);
if (permanents != null) {
int count = 0;
for (Permanent permanent : permanents) {
if (permanent.getCardType().contains(CardType.LAND)) {
count++;
if (count == 2) {
return true;
}
}
}
}
amountOfLandsPlayedThisTurn.put(perm.getControllerId(), amount);
}
}
}
public int maxLandsAnOpponentPlayedThisTurn(UUID playerId, Game game) {
int maxLands = 0;
for (UUID opponentId : game.getOpponents(playerId)) {
Integer amount = amountOfLandsPlayedThisTurn.get(opponentId);
if (amount != null && amount > maxLands) {
maxLands = amount;
}
}
return maxLands;
}
@Override
public void reset() {
super.reset();
amountOfLandsPlayedThisTurn.clear();
}
}
class LavaballTrapAlternativeCost extends AlternativeCostImpl<Cost> {
public LavaballTrapAlternativeCost() {
super("you may pay {3}{R}{R} rather than pay Lavaball Trap's mana cost");
this.add(new ManaCostsImpl("{3}{R}{R}"));
}
public LavaballTrapAlternativeCost(final LavaballTrapAlternativeCost cost) {
super(cost);
}
@Override
public LavaballTrapAlternativeCost copy() {
return new LavaballTrapAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
LavaballTrapWatcher watcher = (LavaballTrapWatcher) game.getState().getWatchers().get("LavaballTrapWatcher");
if (watcher != null && watcher.maxLandsAnOpponentPlayedThisTurn(source.getControllerId(), game) > 1) {
return true;
}
return false;
}
@Override
public String getText() {
return "If an opponent had two or more lands enter the battlefield under his or her control this turn, you may pay {3}{R}{R} rather than pay Lavaball Trap's mana cost";
public String toString() {
return "If an opponent had two or more lands enter the battlefield under his or her control this turn";
}
}

View file

@ -28,16 +28,15 @@
package mage.sets.zendikar;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.costs.Cost;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Rarity;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.AttackingPredicate;
import mage.game.Game;
@ -47,25 +46,24 @@ import mage.game.Game;
* @author jeffwadsworth
*/
public class LethargyTrap extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("attacking creatures");
static {
filter.add(new AttackingPredicate());
}
public LethargyTrap(UUID ownerId) {
super(ownerId, 51, "Lethargy Trap", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{3}{U}");
this.expansionSetCode = "ZEN";
this.subtype.add("Trap");
// If three or more creatures are attacking, you may pay {U} rather than pay Lethargy Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new LethargyTrapAlternativeCost());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{U}"), LethargyTrapCondition.getInstance()));
// Attacking creatures get -3/-0 until end of turn.
this.getSpellAbility().addEffect(new BoostAllEffect(-3, 0, Duration.EndOfTurn, filter, false));
}
public LethargyTrap(final LethargyTrap card) {
@ -78,32 +76,21 @@ public class LethargyTrap extends CardImpl {
}
}
class LethargyTrapAlternativeCost extends AlternativeCostImpl<Cost> {
class LethargyTrapCondition implements Condition {
public LethargyTrapAlternativeCost() {
super("you may pay {U} rather than pay Lethargy Trap's mana cost");
this.add(new ManaCostsImpl("{U}"));
}
private static final LethargyTrapCondition fInstance = new LethargyTrapCondition();
public LethargyTrapAlternativeCost(final LethargyTrapAlternativeCost cost) {
super(cost);
public static Condition getInstance() {
return fInstance;
}
@Override
public LethargyTrapAlternativeCost copy() {
return new LethargyTrapAlternativeCost(this);
public boolean apply(Game game, Ability source) {
return game.getCombat().getAttackers().size() > 2;
}
@Override
public boolean isAvailable(Game game, Ability source) {
if (game.getCombat().getAttackers().size() >= 3) {
return true;
}
return false;
public String toString() {
return "If three or more creatures are attacking";
}
@Override
public String getText() {
return "If three or more creatures are attacking, you may pay {U} rather than pay Lethargy Trap's mana cost";
}
}
}

View file

@ -27,28 +27,19 @@
*/
package mage.sets.zendikar;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.filter.FilterSpell;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetSpell;
import mage.watchers.Watcher;
import mage.watchers.common.CastSpellLastTurnWatcher;
/**
*
@ -63,14 +54,12 @@ public class MindbreakTrap extends CardImpl {
this.expansionSetCode = "ZEN";
this.subtype.add("Trap");
// If an opponent cast three or more spells this turn, you may pay {0} rather than pay Mindbreak Trap's mana cost.
this.getSpellAbility().addAlternativeCost(
new MindbreakTrapAlternativeCost());
this.getSpellAbility().addWatcher(new MindbreakTrapWatcher());
this.addAbility(new AlternativeCostSourceAbility(new GenericManaCost(0), MindbreakTrapCondition.getInstance()));
// Exile any number of target spells.
this.getSpellAbility().addTarget(new TargetSpell(0, Integer.MAX_VALUE, filter));
this.getSpellAbility().addEffect(new MindbreakEffect());
this.getSpellAbility().addEffect(new ExileTargetEffect("Exile any number of target spells"));
}
public MindbreakTrap(final MindbreakTrap card) {
@ -83,116 +72,30 @@ public class MindbreakTrap extends CardImpl {
}
}
class MindbreakTrapWatcher extends Watcher {
class MindbreakTrapCondition implements Condition {
private Map<UUID, Integer> counts = new HashMap<>();
private static final MindbreakTrapCondition fInstance = new MindbreakTrapCondition();
public MindbreakTrapWatcher() {
super("opponent cast three or more spells", WatcherScope.PLAYER);
}
public MindbreakTrapWatcher(final MindbreakTrapWatcher watcher) {
super(watcher);
for (Entry<UUID, Integer> entry: watcher.counts.entrySet()) {
counts.put(entry.getKey(), entry.getValue());
}
}
@Override
public MindbreakTrapWatcher copy() {
return new MindbreakTrapWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (condition == true) { // no need to check - condition has already occured
return;
}
if (event.getType() == EventType.SPELL_CAST
&& game.getOpponents(controllerId).contains(event.getPlayerId())) {
int count = 1;
if (counts.containsKey(event.getPlayerId())) {
count += counts.get(event.getPlayerId());
if (count >= 3) {
condition = true;
}
}
counts.put(event.getPlayerId(), count);
}
}
@Override
public void reset() {
super.reset();
counts.clear();
}
}
class MindbreakTrapAlternativeCost extends AlternativeCostImpl {
public MindbreakTrapAlternativeCost() {
super("you may pay {0} rather than pay {this}'s mana cost");
this.add(new GenericManaCost(0));
}
public MindbreakTrapAlternativeCost(final MindbreakTrapAlternativeCost cost) {
super(cost);
}
@Override
public MindbreakTrapAlternativeCost copy() {
return new MindbreakTrapAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
Watcher watcher = game.getState().getWatchers().get("opponent cast three or more spells", source.getControllerId());
if (watcher != null && watcher.conditionMet()) {
return true;
}
return false;
}
@Override
public String getText() {
return "If an opponent cast three or more spells this turn, you may pay {0} rather than pay {this}'s mana cost";
}
}
class MindbreakEffect extends OneShotEffect{
MindbreakEffect(MindbreakEffect effect) {
super(effect);
}
MindbreakEffect() {
super(Outcome.Exile);
staticText = "Exile any number of target spells";
public static Condition getInstance() {
return fInstance;
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int affectedTargets = 0;
if (targetPointer.getTargets(game, source).size() > 0) {
for (UUID spellId : targetPointer.getTargets(game, source)) {
Spell spell = game.getStack().getSpell(spellId);
if (spell != null) {
controller.moveCardToExileWithInfo(spell, null, "", source.getSourceId(), game, Zone.STACK, true);
affectedTargets++;
}
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get(CastSpellLastTurnWatcher.class.getName());
if (watcher != null) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
if (watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(opponentId) > 2) {
return true;
}
}
return affectedTargets > 0;
}
return false;
}
@Override
public MindbreakEffect copy() {
return new MindbreakEffect(this);
public String toString() {
return "If an opponent cast three or more spells this turn";
}
}

View file

@ -29,7 +29,8 @@ package mage.sets.zendikar;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.keyword.FlyingAbility;
@ -60,7 +61,7 @@ public class PitfallTrap extends CardImpl {
this.subtype.add("Trap");
// If exactly one creature is attacking, you may pay {W} rather than pay Pitfall Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new PitfallTrapAlternativeCost());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{W}"), PitfallTrapCondition.getInstance()));
// Destroy target attacking creature without flying.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
@ -77,32 +78,21 @@ public class PitfallTrap extends CardImpl {
}
}
class PitfallTrapAlternativeCost extends AlternativeCostImpl {
class PitfallTrapCondition implements Condition {
public PitfallTrapAlternativeCost() {
super("you may pay {W} rather than pay Pitfall Trap's mana cost");
this.add(new ManaCostsImpl("{W}"));
}
private static final PitfallTrapCondition fInstance = new PitfallTrapCondition();
public PitfallTrapAlternativeCost(final PitfallTrapAlternativeCost cost) {
super(cost);
public static Condition getInstance() {
return fInstance;
}
@Override
public PitfallTrapAlternativeCost copy() {
return new PitfallTrapAlternativeCost(this);
public boolean apply(Game game, Ability source) {
return game.getCombat().getAttackers().size() == 1;
}
@Override
public boolean isAvailable(Game game, Ability source) {
if (game.getCombat().getAttackers().size() == 1) {
return true;
}
return false;
}
@Override
public String getText() {
return "If exactly one creature is attacking, you may pay {W} rather than pay Pitfall Trap's mana cost";
public String toString() {
return "If exactly one creature is attacking";
}
}

View file

@ -63,15 +63,10 @@ public class SummoningTrap extends CardImpl {
this.expansionSetCode = "ZEN";
this.subtype.add("Trap");
// If a creature spell you cast this turn was countered by a spell or
// ability an opponent controlled, you may pay {0} rather than pay
// Summoning Trap's mana cost.
this.getSpellAbility().addAlternativeCost(
new SummoningTrapAlternativeCost());
// If a creature spell you cast this turn was countered by a spell or ability an opponent controlled, you may pay {0} rather than pay Summoning Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new SummoningTrapAlternativeCost());
this.getSpellAbility().addWatcher(new SummoningTrapWatcher());
// Look at the top seven cards of your library. You may put a creature
// card from among them onto the battlefield. Put the rest on the bottom
// of your library in any order.
// Look at the top seven cards of your library. You may put a creature card from among them onto the battlefield. Put the rest on the bottom of your library in any order.
this.getSpellAbility().addEffect(new SummoningTrapEffect());
}

View file

@ -27,23 +27,20 @@
*/
package mage.sets.zendikar;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.UUID;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.abilities.Ability;
import mage.abilities.costs.AlternativeCostImpl;
import mage.abilities.condition.Condition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl;
import mage.constants.WatcherScope;
import mage.constants.CardType;
import mage.constants.Rarity;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.watchers.Watcher;
import mage.watchers.common.PermanentsEnteredBattlefieldWatcher;
/**
*
@ -56,15 +53,13 @@ public class WhiplashTrap extends CardImpl {
this.expansionSetCode = "ZEN";
this.subtype.add("Trap");
// If an opponent had two or more creatures enter the battlefield under his or her control this turn, you may pay {U} rather than pay Whiplash Trap's mana cost.
this.getSpellAbility().addAlternativeCost(new WhiplashAlternativeCost());
this.getSpellAbility().addWatcher(new WhiplashTrapWatcher());
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{U}"), WhiplashTrapCondition.getInstance()), new PermanentsEnteredBattlefieldWatcher());
// Return two target creatures to their owners' hands.
this.getSpellAbility().addEffect(new ReturnToHandTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(2));
}
public WhiplashTrap(final WhiplashTrap card) {
@ -77,87 +72,38 @@ public class WhiplashTrap extends CardImpl {
}
}
class WhiplashTrapWatcher extends Watcher {
class WhiplashTrapCondition implements Condition {
private Map<UUID, Integer> amountOfCreaturesPlayedThisTurn = new HashMap<>();
private static final WhiplashTrapCondition fInstance = new WhiplashTrapCondition();
public WhiplashTrapWatcher() {
super("WhiplashTrapWatcher", WatcherScope.GAME);
}
public WhiplashTrapWatcher(final WhiplashTrapWatcher watcher) {
super(watcher);
for (Map.Entry<UUID, Integer> entry : watcher.amountOfCreaturesPlayedThisTurn.entrySet()) {
amountOfCreaturesPlayedThisTurn.put(entry.getKey(), entry.getValue());
}
public static Condition getInstance() {
return fInstance;
}
@Override
public WhiplashTrapWatcher copy() {
return new WhiplashTrapWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
Permanent perm = game.getPermanent(event.getTargetId());
if (perm.getCardType().contains(CardType.CREATURE)) {
Integer amount = amountOfCreaturesPlayedThisTurn.get(perm.getControllerId());
if (amount == null) {
amount = 1;
} else {
++amount;
public boolean apply(Game game, Ability source) {
PermanentsEnteredBattlefieldWatcher watcher = (PermanentsEnteredBattlefieldWatcher) game.getState().getWatchers().get(PermanentsEnteredBattlefieldWatcher.class.getName());
if (watcher != null) {
for (UUID opponentId : game.getOpponents(source.getControllerId())) {
List<Permanent> permanents = watcher.getThisTurnEnteringPermanents(opponentId);
if (permanents != null) {
int count = 0;
for (Permanent permanent : permanents) {
if (permanent.getCardType().contains(CardType.CREATURE)) {
count++;
if (count == 2) {
return true;
}
}
}
}
amountOfCreaturesPlayedThisTurn.put(perm.getControllerId(), amount);
}
}
}
public int maxCreaturesAnOpponentPlayedThisTurn(UUID playerId, Game game) {
int maxCreatures = 0;
for (UUID opponentId : game.getOpponents(playerId)) {
Integer amount = amountOfCreaturesPlayedThisTurn.get(opponentId);
if (amount != null && amount > maxCreatures) {
maxCreatures = amount;
}
}
return maxCreatures;
}
@Override
public void reset() {
super.reset();
amountOfCreaturesPlayedThisTurn.clear();
}
}
class WhiplashAlternativeCost extends AlternativeCostImpl {
public WhiplashAlternativeCost() {
super("you may pay {U} rather than pay Whiplash Trap's mana cost");
this.add(new ManaCostsImpl("{U}"));
}
public WhiplashAlternativeCost(final WhiplashAlternativeCost cost) {
super(cost);
}
@Override
public WhiplashAlternativeCost copy() {
return new WhiplashAlternativeCost(this);
}
@Override
public boolean isAvailable(Game game, Ability source) {
WhiplashTrapWatcher watcher = (WhiplashTrapWatcher) game.getState().getWatchers().get("WhiplashTrapWatcher");
if (watcher != null && watcher.maxCreaturesAnOpponentPlayedThisTurn(source.getControllerId(), game) >= 2) {
return true;
}
return false;
}
@Override
public String getText() {
return "If an opponent had two or more creatures enter the battlefield under his or her control this turn, you may pay {U} rather than pay {this}'s mana cost";
public String toString() {
return "If an opponent had two or more creatures enter the battlefield under his or her control this turn";
}
}
}