Merge pull request #2709 from MTGfan/master

Cyclopean Tomb TODO: inside watcher get ID for card
This commit is contained in:
LevelX2 2016-12-27 16:38:27 +01:00 committed by GitHub
commit cebfadbf34
12 changed files with 481 additions and 28 deletions

View file

@ -30,22 +30,18 @@ package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.game.events.GameEvent;
import mage.target.common.TargetControlledCreaturePermanent;
/**

View file

@ -0,0 +1,344 @@
/*
* 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.cards.c;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.PutIntoGraveFromBattlefieldSourceTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.IsStepCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalActivatedAbility;
import mage.abilities.decorator.ConditionalOneShotEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.effects.common.counter.RemoveAllCountersTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.PhaseStep;
import mage.constants.SubLayer;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.CounterPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetLandPermanent;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import mage.watchers.Watcher;
/**
*
* @author MTGfan
*/
public class CyclopeanTomb extends CardImpl {
private static final FilterLandPermanent filter = new FilterLandPermanent();
static {
filter.add(Predicates.not(new SubtypePredicate("Swamp")));
}
public CyclopeanTomb(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// {2}, {tap}: Put a mire counter on target non-Swamp land. That land is a Swamp for as long as it has a mire counter on it. Activate this ability only during your upkeep.
Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.MIRE.createInstance()), new GenericManaCost(2), new IsStepCondition(PhaseStep.UPKEEP), "{2}, {T}: Put a mire counter on target non-Swamp land. That land is a Swamp for as long as it has a mire counter on it. Activate this ability only during your upkeep.");
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetLandPermanent(filter));
ability.addEffect(new BecomeSwampEffect(Duration.Custom, false, true, "Swamp"));
this.addAbility(ability, new CyclopeanTombCounterWatcher());
// When Cyclopean Tomb is put into a graveyard from the battlefield, at the beginning of each of your upkeeps for the rest of the game, remove all mire counters from a land that a mire counter was put onto with Cyclopean Tomb but that a mire counter has not been removed from with Cyclopean Tomb.
Effect effect = new CreateDelayedTriggeredAbilityEffect(new CyclopeanTombDelayedTriggeredAbility());
effect.setText("at the beginning of each of your upkeeps for the rest of the game, remove all mire counters from a land that a mire counter was put onto with {this} but that a mire counter has not been removed from with {this}.");
this.addAbility(new PutIntoGraveFromBattlefieldSourceTriggeredAbility(effect));
}
public CyclopeanTomb(final CyclopeanTomb card) {
super(card);
}
@Override
public CyclopeanTomb copy() {
return new CyclopeanTomb(this);
}
}
class BecomeSwampEffect extends BecomesBasicLandTargetEffect {
public BecomeSwampEffect(Duration duration, boolean chooseLandType, boolean loseOther, String... landNames) {
super(duration, chooseLandType, loseOther, landNames);
staticText = "That land is a Swamp for as long as it has a mire counter on it.";
}
public BecomeSwampEffect(final BecomeSwampEffect effect) {
super(effect);
}
@Override
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
Permanent land = game.getPermanent(this.targetPointer.getFirst(game, source));
if (land == null) {
// if permanent left battlefield the effect can be removed because it was only valid for that object
this.discard();
} else if (land.getCounters(game).getCount(CounterType.MIRE) > 0) {
// only if Mire counter is on the object it becomes a Swamp.
super.apply(layer, sublayer, source, game);
}
return true;
}
@Override
public BecomeSwampEffect copy() {
return new BecomeSwampEffect(this);
}
}
class CyclopeanTombDelayedTriggeredAbility extends DelayedTriggeredAbility {
CyclopeanTombDelayedTriggeredAbility() {
super(new CyclopeanTombEffect(), Duration.OneUse, true, false);
}
CyclopeanTombDelayedTriggeredAbility(CyclopeanTombDelayedTriggeredAbility ability) {
super(ability);
}
@Override
public CyclopeanTombDelayedTriggeredAbility copy() {
return new CyclopeanTombDelayedTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.BEGINNING_PHASE_PRE;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
return event.getPlayerId().equals(this.controllerId);
}
}
class CyclopeanTombEffect extends OneShotEffect {
public CyclopeanTombEffect() {
super(Outcome.Benefit);
this.staticText = "at the beginning of each of your upkeeps for the rest of the game, remove all mire counters from a land that a mire counter was put onto with {this} but that a mire counter has not been removed from with {this}.";
}
public CyclopeanTombEffect(final CyclopeanTombEffect effect) {
super(effect);
}
@Override
public CyclopeanTombEffect copy() {
return new CyclopeanTombEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if(controller != null){
new ChooseLandEffect().apply(game, source);
Effect effect = new RemoveAllCountersTargetEffect(CounterType.MIRE);
effect.setTargetPointer(new FixedTarget((UUID) game.getState().getValue(source.getSourceId().toString() + "_land")));
effect.apply(game, source);
//CyclopianTombEffect and CyclopeanTombDelayedTriggeredAbility will maintain a loop
//as long as there are one or more mire counters left to be removed
new ConditionalOneShotEffect(new CreateDelayedTriggeredAbilityEffect(new CyclopeanTombDelayedTriggeredAbility(), false), new CyclopeanTombCounterCondition()).apply(game, source);
return true;
}
return false;
}
}
class CyclopeanTombCounterCondition implements Condition {
private static final FilterLandPermanent mireFilter = new FilterLandPermanent();
static {
mireFilter.add(new CounterPredicate(CounterType.MIRE));
}
public CyclopeanTombCounterCondition() {
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = game.getBattlefield().getAllActivePermanents(mireFilter, game);
Permanent cyclopeanTombInstance = game.getPermanentOrLKIBattlefield(source.getSourceId());
CyclopeanTombCounterWatcher watcher = (CyclopeanTombCounterWatcher) game.getState().getWatchers().get(CyclopeanTombCounterWatcher.class.getName());
for(Permanent land : permanents) {
if(watcher.landMiredByCyclopeanTombInstance(land, cyclopeanTombInstance, game)) {
return land.getCounters(game).getCount(CounterType.MIRE) > 0;
}
}
return false;
}
}
class ChooseLandEffect extends OneShotEffect {
public ChooseLandEffect() {
super(Outcome.Neutral);
this.staticText = "choose a land that a mire counter was put onto with Cyclopean Tomb but that a mire counter has not been removed from with Cyclopean Tomb";
}
public ChooseLandEffect(final ChooseLandEffect effect) {
super(effect);
}
@Override
public ChooseLandEffect copy() {
return new ChooseLandEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject mageObject = game.getPermanentEntering(source.getSourceId());
if (mageObject == null) {
mageObject = game.getObject(source.getSourceId());
}
FilterLandPermanent filter = new FilterLandPermanent();
filter.add(new LandIdPredicate(source));
if(controller != null && mageObject != null){
TargetLandPermanent target = new TargetLandPermanent(1, 1, filter, true);
/*Player must choose a land each upkeep. Using the message are above the player hand where frequent interactions
* take place is the most logical way to prompt for this scenario. A new constructor added to provide a not optional
* option for any cards like this where the player must choose a target in such the way this card requires.
*/
if (controller.chooseTarget(Outcome.Neutral, target, source, game, false)) {
Permanent chosenLand = game.getPermanent(target.getFirstTarget());
if(chosenLand != null) {
game.getState().setValue(mageObject.getId() + "_land", target.getFirstTarget());
if (mageObject instanceof Permanent) {
((Permanent) mageObject).addInfo("chosen land", CardUtil.addToolTipMarkTags("Chosen player: " + chosenLand.getLogName()), game);
}
return true;
}
}
}
return false;
}
}
class LandIdPredicate implements Predicate<Permanent> {
public Ability source;
public LandIdPredicate(Ability source) {
this.source = source;
}
@Override
public boolean apply(Permanent input, Game game) {
Permanent cyclopeanTombInstance = game.getPermanentOrLKIBattlefield(source.getSourceId());
CyclopeanTombCounterWatcher watcher = (CyclopeanTombCounterWatcher) game.getState().getWatchers().get(CyclopeanTombCounterWatcher.class.getName());
return watcher.landMiredByCyclopeanTombInstance(input, cyclopeanTombInstance, game);
}
}
class CyclopeanTombCounterWatcher extends Watcher {
public HashMap<MageObjectReference, Set<MageObjectReference>> counterData = new HashMap<>();
public CyclopeanTombCounterWatcher() {
super(CyclopeanTombCounterWatcher.class.getName(), WatcherScope.GAME);
}
public CyclopeanTombCounterWatcher(final CyclopeanTombCounterWatcher watcher) {
super(watcher);
for (MageObjectReference mageObjectReference : watcher.counterData.keySet()) {
Set<MageObjectReference> miredLands = new HashSet<>();
miredLands.addAll(watcher.counterData.get(mageObjectReference));
counterData.put(mageObjectReference, miredLands);
}
}
@Override
public CyclopeanTombCounterWatcher copy() {
return new CyclopeanTombCounterWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if(event.getType() == GameEvent.EventType.COUNTER_ADDED || event.getType() == GameEvent.EventType.COUNTERS_ADDED) {
MageObjectReference cylopeanTombInstance = new MageObjectReference(/*ID needs to go here*/, game);
Set<MageObjectReference> miredLands = counterData.get(cylopeanTombInstance);
if (miredLands != null) {
miredLands.add(new MageObjectReference(event.getTargetId(), game));
} else {
miredLands = new HashSet<>();
miredLands.add(new MageObjectReference(event.getTargetId(), game));
counterData.put(cylopeanTombInstance, miredLands);
}
}
}
@Override
public void reset() {
super.reset();
counterData.clear();
}
public boolean landMiredByCyclopeanTombInstance(Permanent land, Permanent cylopeanTombInstance, Game game) {
Set<MageObjectReference> miredLands = counterData.get(new MageObjectReference(cylopeanTombInstance, game));
return miredLands != null && miredLands.contains(new MageObjectReference(land, game));
}
}

View file

@ -32,6 +32,7 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.SourceAttackingCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.decorator.ConditionalContinuousEffect;
@ -74,9 +75,9 @@ public class GaeasLiege extends CardImpl {
// As long as Gaea's Liege isn't attacking, its power and toughness are each equal to the number of Forests you control. As long as Gaea's Liege is attacking, its power and toughness are each equal to the number of Forests defending player controls.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new ConditionalContinuousEffect(
new SetPowerToughnessSourceEffect(new DefendersForestCount(), Duration.EndOfCombat),
new SetPowerToughnessSourceEffect(new PermanentsOnBattlefieldCount(filterLands), Duration.EndOfGame),
SourceAttackingCondition.getInstance(),
new SetPowerToughnessSourceEffect(new DefendersForestCount(), Duration.EndOfCombat),
new InvertCondition(SourceAttackingCondition.getInstance()),
"As long as {this} isn't attacking, its power and toughness are each equal to the number of Forests you control. As long as {this} is attacking, its power and toughness are each equal to the number of Forests defending player controls.")));
// {tap}: Target land becomes a Forest until Gaea's Liege leaves the battlefield.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesBasicLandTargetEffect(Duration.WhileOnBattlefield, "Forest"), new TapSourceCost());
@ -131,4 +132,4 @@ class DefendersForestCount implements DynamicValue {
public String getMessage() {
return "the number of Forests defending player controls";
}
}
}

View file

@ -40,6 +40,8 @@ import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.Counter;
import mage.filter.FilterPermanent;
import mage.filter.predicate.permanent.CounterAnyPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
@ -49,6 +51,12 @@ import mage.target.TargetPermanent;
* @author LevelX2
*/
public class GilderBairn extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent();
static {
filter.add(new CounterAnyPredicate());
}
public GilderBairn(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G/U}{G/U}");
@ -60,7 +68,7 @@ public class GilderBairn extends CardImpl {
// {2}{GU}, {untap}: For each counter on target permanent, put another of those counters on that permanent.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GilderBairnEffect(), new ManaCostsImpl("{2}{G/U}"));
ability.addCost(new UntapSourceCost());
ability.addTarget(new TargetPermanent());
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}

View file

@ -40,11 +40,11 @@ import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.OnEventTriggeredAbility;
import mage.abilities.StateTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition;
import mage.abilities.decorator.ConditionalTriggeredAbility;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.constants.Duration;
@ -74,15 +74,10 @@ public class Jihad extends CardImpl {
this.addAbility(new AsEntersBattlefieldAbility(new ChooseOpponentEffect(Outcome.Detriment)));
// White creatures get +2/+1 as long as the chosen player controls a nontoken permanent of the chosen color.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(2, 1, Duration.WhileOnBattlefield, filter, false)));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostAllEffect(2, 1, Duration.WhileOnBattlefield, filter, false), new JihadOpponentCondition(), "White creatures get +2/+1 as long as the chosen player controls a nontoken permanent of the chosen color.")));
// When the chosen player controls no nontoken permanents of the chosen color, sacrifice Jihad.
// Not quite as immediate as I'd like but.. Static doesnt accept that effect and probably only work upon casting (maybe a continuous ability would, if not hog the system)
TriggeredAbility triggered = new OnEventTriggeredAbility(GameEvent.EventType.STEP_CHANGED, "end Jihad", true, new SacrificeSourceEffect());
this.addAbility(new ConditionalTriggeredAbility(triggered, new NoColoredPermanentOpponentCondition(), "no nontoken permanents of the chosen color, sacrifice Jihad"));
//this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalOneShotEffect(new SacrificeSourceEffect()), new NoColoredPermanentOpponentCondition(), "Jihad ending"));
this.addAbility(new JihadTriggeredAbility(new SacrificeSourceEffect()));
}
public Jihad(final Jihad card) {
@ -95,24 +90,44 @@ public class Jihad extends CardImpl {
}
}
class NoColoredPermanentOpponentCondition implements Condition {
class JihadTriggeredAbility extends StateTriggeredAbility {
private static NoColoredPermanentOpponentCondition fInstance = new NoColoredPermanentOpponentCondition();
public static Condition getInstance() {
return fInstance;
public JihadTriggeredAbility(Effect effect) {
super(Zone.BATTLEFIELD, effect);
}
public JihadTriggeredAbility(final JihadTriggeredAbility ability) {
super(ability);
}
@Override
public JihadTriggeredAbility copy() {
return new JihadTriggeredAbility(this);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
UUID chosenOpponent = (UUID) game.getState().getValue(getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY);
FilterPermanent filter = new FilterPermanent();
filter.add(new ColorPredicate((ObjectColor) game.getState().getValue(getSourceId() + "_color")));
filter.add(Predicates.not(new TokenPredicate()));
return game.getBattlefield().countAll(filter, chosenOpponent, game) == 0;
}
@Override
public String getRule() {
return "When the chosen player controls no nontoken permanents of the chosen color, " + super.getRule();
}
}
class JihadOpponentCondition implements Condition {
@Override
public boolean apply(Game game, Ability source) {
UUID chosenOpponent = (UUID) game.getState().getValue(source.getSourceId().toString() + ChooseOpponentEffect.VALUE_KEY);
FilterPermanent filter = new FilterPermanent();
filter.add(new ColorPredicate((ObjectColor) game.getState().getValue(source.getSourceId() + "_color")));
filter.add(Predicates.not(new TokenPredicate()));
//filter.add(new ColorPredicate(ObjectColor.WHITE)); // Given this typing, somehow the above doesn't seem right, but I copied from StoryCircle card
return game.getBattlefield().countAll(filter, chosenOpponent, game)==0;
return game.getBattlefield().countAll(filter, chosenOpponent, game) > 0;
}
}

View file

@ -73,6 +73,7 @@ public class LimitedEditionAlpha extends ExpansionSet {
cards.add(new SetCardInfo("Crusade", 200, Rarity.RARE, mage.cards.c.Crusade.class));
cards.add(new SetCardInfo("Crystal Rod", 239, Rarity.UNCOMMON, mage.cards.c.CrystalRod.class));
cards.add(new SetCardInfo("Cursed Land", 6, Rarity.UNCOMMON, mage.cards.c.CursedLand.class));
cards.add(new SetCardInfo("Cyclopean Tomb", 240, Rarity.RARE, mage.cards.c.CyclopeanTomb.class));
cards.add(new SetCardInfo("Dark Ritual", 7, Rarity.COMMON, mage.cards.d.DarkRitual.class));
cards.add(new SetCardInfo("Deathgrip", 9, Rarity.UNCOMMON, mage.cards.d.Deathgrip.class));
cards.add(new SetCardInfo("Deathlace", 10, Rarity.RARE, mage.cards.d.Deathlace.class));

View file

@ -74,6 +74,7 @@ public class LimitedEditionBeta extends ExpansionSet {
cards.add(new SetCardInfo("Crusade", 202, Rarity.RARE, mage.cards.c.Crusade.class));
cards.add(new SetCardInfo("Crystal Rod", 241, Rarity.UNCOMMON, mage.cards.c.CrystalRod.class));
cards.add(new SetCardInfo("Cursed Land", 6, Rarity.UNCOMMON, mage.cards.c.CursedLand.class));
cards.add(new SetCardInfo("Cyclopean Tomb", 242, Rarity.RARE, mage.cards.c.CyclopeanTomb.class));
cards.add(new SetCardInfo("Dark Ritual", 7, Rarity.COMMON, mage.cards.d.DarkRitual.class));
cards.add(new SetCardInfo("Deathgrip", 9, Rarity.UNCOMMON, mage.cards.d.Deathgrip.class));
cards.add(new SetCardInfo("Deathlace", 10, Rarity.RARE, mage.cards.d.Deathlace.class));

View file

@ -105,6 +105,7 @@ public class MastersEditionIV extends ExpansionSet {
cards.add(new SetCardInfo("Crumble", 147, Rarity.COMMON, mage.cards.c.Crumble.class));
cards.add(new SetCardInfo("Cyclone", 148, Rarity.RARE, mage.cards.c.Cyclone.class));
cards.add(new SetCardInfo("Cyclopean Mummy", 72, Rarity.COMMON, mage.cards.c.CyclopeanMummy.class));
cards.add(new SetCardInfo("Cyclopean Tomb", 195, Rarity.RARE, mage.cards.c.CyclopeanTomb.class));
cards.add(new SetCardInfo("Dakmor Plague", 73, Rarity.UNCOMMON, mage.cards.d.DakmorPlague.class));
cards.add(new SetCardInfo("Dark Ritual", 74, Rarity.COMMON, mage.cards.d.DarkRitual.class));
cards.add(new SetCardInfo("Deathcoil Wurm", 149, Rarity.RARE, mage.cards.d.DeathcoilWurm.class));

View file

@ -74,6 +74,7 @@ public class UnlimitedEdition extends ExpansionSet {
cards.add(new SetCardInfo("Crusade", 201, Rarity.RARE, mage.cards.c.Crusade.class));
cards.add(new SetCardInfo("Crystal Rod", 240, Rarity.UNCOMMON, mage.cards.c.CrystalRod.class));
cards.add(new SetCardInfo("Cursed Land", 6, Rarity.UNCOMMON, mage.cards.c.CursedLand.class));
cards.add(new SetCardInfo("Cyclopean Tomb", 241, Rarity.RARE, mage.cards.c.CyclopeanTomb.class));
cards.add(new SetCardInfo("Dark Ritual", 7, Rarity.COMMON, mage.cards.d.DarkRitual.class));
cards.add(new SetCardInfo("Deathgrip", 9, Rarity.UNCOMMON, mage.cards.d.Deathgrip.class));
cards.add(new SetCardInfo("Deathlace", 10, Rarity.RARE, mage.cards.d.Deathlace.class));