Merge pull request #91 from magefree/master

Merge https://github.com/magefree/mage
This commit is contained in:
L_J 2019-01-27 08:37:32 +01:00 committed by GitHub
commit dc8a2fbce8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 988 additions and 452 deletions

View file

@ -47,6 +47,7 @@
<SubComponents> <SubComponents>
<Component class="mage.client.components.ColorPane" name="txtConversation"> <Component class="mage.client.components.ColorPane" name="txtConversation">
<Properties> <Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo"> <Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
<EmptyBorder/> <EmptyBorder/>

View file

@ -366,6 +366,7 @@ public class ChatPanelBasic extends javax.swing.JPanel {
jScrollPaneTxt.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); jScrollPaneTxt.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
jScrollPaneTxt.setPreferredSize(new java.awt.Dimension(32767, 32767)); jScrollPaneTxt.setPreferredSize(new java.awt.Dimension(32767, 32767));
txtConversation.setEditable(false);
txtConversation.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1)); txtConversation.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
txtConversation.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N txtConversation.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N
txtConversation.setFocusCycleRoot(false); txtConversation.setFocusCycleRoot(false);

View file

@ -28,6 +28,7 @@ import org.ocpsoft.prettytime.units.JustNow;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelEvent;
@ -163,13 +164,33 @@ public class TablesPanel extends javax.swing.JPanel {
} }
}; };
// center text render // seats render
TableCellRenderer centerCellRenderer = new DefaultTableCellRenderer() { TableCellRenderer seatsCellRenderer = new DefaultTableCellRenderer() {
JLabel greenLabel = new JLabel();
@Override @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); JLabel defaultLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
label.setHorizontalAlignment(JLabel.CENTER); defaultLabel.setHorizontalAlignment(JLabel.CENTER);
return label; // colors
String val = (String) value;
String[] valsList = val.split("/");
if (valsList.length == 2 && !valsList[0].equals(valsList[1])) {
// green draw
Color defaultBack = defaultLabel.getBackground();
greenLabel.setText(val);
greenLabel.setHorizontalAlignment(JLabel.CENTER);
greenLabel.setFont(defaultLabel.getFont());
greenLabel.setForeground(Color.black);
greenLabel.setOpaque(true);
greenLabel.setBackground(new Color(156, 240, 146));
greenLabel.setBorder(new LineBorder(defaultBack, 1));
return greenLabel;
} else {
// default draw
return defaultLabel;
}
} }
}; };
@ -200,7 +221,7 @@ public class TablesPanel extends javax.swing.JPanel {
// skill level // skill level
tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_SKILL).setCellRenderer(skillCellRenderer); tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_SKILL).setCellRenderer(skillCellRenderer);
// seats // seats
tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_SEATS).setCellRenderer(centerCellRenderer); tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_SEATS).setCellRenderer(seatsCellRenderer);
/* date sorter (not need, default is good - see getColumnClass) /* date sorter (not need, default is good - see getColumnClass)
activeTablesSorter.setComparator(TablesTableModel.COLUMN_CREATED, new Comparator<Date>() { activeTablesSorter.setComparator(TablesTableModel.COLUMN_CREATED, new Comparator<Date>() {
@ -626,16 +647,21 @@ public class TablesPanel extends javax.swing.JPanel {
// reload server messages // reload server messages
java.util.List<String> serverMessages = SessionHandler.getServerMessages(); java.util.List<String> serverMessages = SessionHandler.getServerMessages();
synchronized (this) { synchronized (this) {
this.messages = serverMessages; if (serverMessages != null) {
this.messages = serverMessages;
} else {
this.messages = new ArrayList<>();
}
this.currentMessage = 0; this.currentMessage = 0;
} }
if (serverMessages.isEmpty()) { if (this.messages.isEmpty()) {
this.jPanelBottom.setVisible(false); this.jPanelBottom.setVisible(false);
} else { } else {
this.jPanelBottom.setVisible(true); this.jPanelBottom.setVisible(true);
URLHandler.RemoveMouseAdapter(jLabelFooterText); URLHandler.RemoveMouseAdapter(jLabelFooterText);
URLHandler.handleMessage(serverMessages.get(0), this.jLabelFooterText); URLHandler.handleMessage(this.messages.get(0), this.jLabelFooterText);
this.jButtonFooterNext.setVisible(serverMessages.size() > 1); this.jButtonFooterNext.setVisible(this.messages.size() > 1);
} }
} }

View file

@ -442,6 +442,29 @@ public final class SystemUtil {
perm.addCounters(CounterType.LOYALTY.createInstance(command.Amount), null, game); perm.addCounters(CounterType.LOYALTY.createInstance(command.Amount), null, game);
} }
} }
continue;
} else if ("stack".equalsIgnoreCase(command.zone)) {
// simple cast (without targets or modes)
// find card info
CardInfo cardInfo = CardRepository.instance.findCard(command.cardName);
if (cardInfo == null) {
logger.warn("Unknown card for stack command [" + command.cardName + "]: " + line);
continue;
}
// put card to game
Set<Card> cardsToLoad = new HashSet<>();
for (int i = 0; i < command.Amount; i++) {
cardsToLoad.add(cardInfo.getCard());
}
game.loadCards(cardsToLoad, player.getId());
// move card from exile to stack
for (Card card : cardsToLoad) {
swapWithAnyCard(game, player, card, Zone.STACK);
}
continue; continue;
} }
@ -516,6 +539,8 @@ public final class SystemUtil {
game.getExile().getPermanentExile().remove(card); game.getExile().getPermanentExile().remove(card);
player.getLibrary().putOnTop(card, game); player.getLibrary().putOnTop(card, game);
break; break;
case STACK:
card.cast(game, Zone.EXILED, card.getSpellAbility(), player.getId());
default: default:
card.moveToZone(zone, null, game, false); card.moveToZone(zone, null, game, false);
} }

View file

@ -1,11 +1,11 @@
package mage.cards.a; package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.costs.common.ExileSourceCost;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ColorlessManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
@ -16,27 +16,32 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class AmuletOfUnmaking extends CardImpl { public final class AmuletOfUnmaking extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("artifact, creature, or enchantment"); private static final FilterPermanent filter = new FilterPermanent("artifact, creature, or land");
static { static {
filter.add(Predicates.or( filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT), new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE), new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.ENCHANTMENT))); new CardTypePredicate(CardType.LAND)
));
} }
public AmuletOfUnmaking(UUID ownerId, CardSetInfo setInfo) { public AmuletOfUnmaking(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
// {5}, {tap}, Exile Amulet of Unmaking: Exile target artifact, creature, or land. Activate this ability only any time you could cast a sorcery. // {5}, {tap}, Exile Amulet of Unmaking: Exile target artifact, creature, or land. Activate this ability only any time you could cast a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new ExileTargetEffect("Exile target artifact, creature or land"), new ColorlessManaCost(5)); Ability ability = new ActivateAsSorceryActivatedAbility(
Zone.BATTLEFIELD, new ExileTargetEffect(), new GenericManaCost(5)
);
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
ability.addCost(new ExileSourceCost());
ability.addTarget(new TargetPermanent(filter)); ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -0,0 +1,124 @@
package mage.cards.b;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.common.DiesTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.constants.SubType;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import mage.watchers.Watcher;
/**
*
* @author TheElk801 & L_J
*/
public final class BlazingEffigy extends CardImpl {
public BlazingEffigy(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}");
this.subtype.add(SubType.ELEMENTAL);
this.power = new MageInt(0);
this.toughness = new MageInt(3);
// When Blazing Effigy dies, it deals X damage to target creature, where X is 3 plus the amount of damage dealt to Blazing Effigy this turn by other sources named Blazing Effigy.
Ability ability = new DiesTriggeredAbility(new DamageTargetEffect(BlazingEffigyCount.instance), false);
ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability, new BlazingEffigyWatcher());
}
public BlazingEffigy(final BlazingEffigy card) {
super(card);
}
@Override
public BlazingEffigy copy() {
return new BlazingEffigy(this);
}
}
enum BlazingEffigyCount implements DynamicValue {
instance;
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
BlazingEffigyWatcher watcher = (BlazingEffigyWatcher) game.getState().getWatchers().get(BlazingEffigyWatcher.class.getSimpleName());
if (watcher == null) {
return 3;
}
int effigyDamage = watcher.damageDoneTo(sourceAbility.getSourceId(), sourceAbility.getSourceObjectZoneChangeCounter() - 1, game);
return CardUtil.addWithOverflowCheck(3, effigyDamage);
}
@Override
public BlazingEffigyCount copy() {
return BlazingEffigyCount.instance;
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "3 plus the amount of damage dealt to {this} this turn by other sources named Blazing Effigy";
}
}
class BlazingEffigyWatcher extends Watcher {
public final Map<MageObjectReference, Integer> damagedObjects = new HashMap<>();
public BlazingEffigyWatcher() {
super(BlazingEffigyWatcher.class.getSimpleName(), WatcherScope.GAME);
}
public BlazingEffigyWatcher(final BlazingEffigyWatcher watcher) {
super(watcher);
this.damagedObjects.putAll(watcher.damagedObjects);
}
@Override
public BlazingEffigyWatcher copy() {
return new BlazingEffigyWatcher(this);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DAMAGED_CREATURE) {
if (!event.getSourceId().equals(event.getTargetId())) {
MageObjectReference damageSourceRef = new MageObjectReference(event.getSourceId(), game);
MageObjectReference damageTargetRef = new MageObjectReference(event.getTargetId(), game);
if (game.getPermanentOrLKIBattlefield(event.getSourceId()) != null && game.getPermanentOrLKIBattlefield(event.getSourceId()).getName().equals("Blazing Effigy")) {
damagedObjects.putIfAbsent(damageTargetRef, 0);
damagedObjects.compute(damageTargetRef, (k, damage) -> damage + event.getAmount());
}
}
}
}
@Override
public void reset() {
super.reset();
damagedObjects.clear();
}
public int damageDoneTo(UUID objectId, int zoneChangeCounter, Game game) {
MageObjectReference mor = new MageObjectReference(objectId, zoneChangeCounter, game);
return damagedObjects.getOrDefault(mor, 0);
}
}

View file

@ -1,23 +1,24 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl; import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility; import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.RemoveAllCountersSourceEffect; import mage.abilities.effects.common.RemoveAllCountersSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class BloodHound extends CardImpl { public final class BloodHound extends CardImpl {
@ -33,10 +34,12 @@ public final class BloodHound extends CardImpl {
this.addAbility(new BloodHoundTriggeredAbility()); this.addAbility(new BloodHoundTriggeredAbility());
// At the beginning of your end step, remove all +1/+1 counters from Blood Hound. // At the beginning of your end step, remove all +1/+1 counters from Blood Hound.
this.addAbility(new BeginningOfEndStepTriggeredAbility(new RemoveAllCountersSourceEffect(CounterType.P1P1), TargetController.YOU, false)); this.addAbility(new BeginningOfEndStepTriggeredAbility(
new RemoveAllCountersSourceEffect(CounterType.P1P1), TargetController.YOU, false
));
} }
public BloodHound(final BloodHound card) { private BloodHound(final BloodHound card) {
super(card); super(card);
} }
@ -48,11 +51,11 @@ public final class BloodHound extends CardImpl {
class BloodHoundTriggeredAbility extends TriggeredAbilityImpl { class BloodHoundTriggeredAbility extends TriggeredAbilityImpl {
public BloodHoundTriggeredAbility() { BloodHoundTriggeredAbility() {
super(Zone.BATTLEFIELD, new BloodHoundEffect(), true); super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), true);
} }
public BloodHoundTriggeredAbility(final BloodHoundTriggeredAbility ability) { private BloodHoundTriggeredAbility(final BloodHoundTriggeredAbility ability) {
super(ability); super(ability);
} }
@ -68,8 +71,9 @@ class BloodHoundTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(this.getControllerId())) { if (event.getTargetId().equals(this.getControllerId()) && event.getAmount() > 0) {
this.getEffects().get(0).setValue("damageAmount", event.getAmount()); this.getEffects().clear();
this.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(event.getAmount())));
return true; return true;
} }
return false; return false;
@ -77,31 +81,6 @@ class BloodHoundTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public String getRule() { public String getRule() {
return "Whenever you are dealt damage, you may put that many +1/+1 counters on {this}."; return "Whenever you're dealt damage, you may put that many +1/+1 counters on {this}.";
}
}
class BloodHoundEffect extends OneShotEffect {
public BloodHoundEffect() {
super(Outcome.Benefit);
}
public BloodHoundEffect(final BloodHoundEffect effect) {
super(effect);
}
@Override
public BloodHoundEffect copy() {
return new BloodHoundEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getSourceId());
if (permanent != null) {
permanent.addCounters(CounterType.P1P1.createInstance((Integer) this.getValue("damageAmount")), source, game);
}
return true;
} }
} }

View file

@ -1,7 +1,6 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
@ -13,31 +12,21 @@ import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterSpell;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.TargetSpell; import mage.target.TargetSpell;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class BrineShaman extends CardImpl { public final class BrineShaman extends CardImpl {
private static final FilterSpell filter = new FilterSpell("creature spell");
static {
filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE)));
}
public BrineShaman(UUID ownerId, CardSetInfo setInfo) { public BrineShaman(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
@ -46,16 +35,14 @@ public final class BrineShaman extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// {tap}, Sacrifice a creature: Target creature gets +2/+2 until end of turn. // {tap}, Sacrifice a creature: Target creature gets +2/+2 until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(2, 2, Duration.EndOfTurn), Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(2, 2), new TapSourceCost());
new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT)));
ability.addCost(new TapSourceCost());
ability.addTarget(new TargetCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability); this.addAbility(ability);
// {1}{U}{U}, Sacrifice a creature: Counter target creature spell. // {1}{U}{U}, Sacrifice a creature: Counter target creature spell.
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), ability = new SimpleActivatedAbility(new CounterTargetEffect(), new ManaCostsImpl("{1}{U}{U}"));
new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT))); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT)));
ability.addCost(new ManaCostsImpl("{1}{U}{U}"));
ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_CREATURE)); ability.addTarget(new TargetSpell(StaticFilters.FILTER_SPELL_CREATURE));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -1,7 +1,6 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
@ -12,12 +11,12 @@ import mage.abilities.keyword.ShroudAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Zone; import mage.constants.SubType;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class CephalidInkshrouder extends CardImpl { public final class CephalidInkshrouder extends CardImpl {
@ -30,12 +29,17 @@ public final class CephalidInkshrouder extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// Discard a card: Cephalid Inkshrouder gains shroud until end of turn and is unblockable this turn. // Discard a card: Cephalid Inkshrouder gains shroud until end of turn and is unblockable this turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilitySourceEffect(ShroudAbility.getInstance(),Duration.EndOfTurn), new DiscardCardCost()); Ability ability = new SimpleActivatedAbility(
ability.addEffect(new CantBeBlockedSourceEffect(Duration.EndOfTurn)); new GainAbilitySourceEffect(
ShroudAbility.getInstance(),
Duration.EndOfTurn
), new DiscardCardCost()
);
ability.addEffect(new CantBeBlockedSourceEffect(Duration.EndOfTurn).setText("and can't be blocked this turn"));
this.addAbility(ability); this.addAbility(ability);
} }
public CephalidInkshrouder(final CephalidInkshrouder card) { private CephalidInkshrouder(final CephalidInkshrouder card) {
super(card); super(card);
} }

View file

@ -1,21 +1,20 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.filter.common.FilterAttackingCreature; import mage.constants.SubType;
import mage.filter.StaticFilters;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class ChieftainEnDal extends CardImpl { public final class ChieftainEnDal extends CardImpl {
@ -29,11 +28,12 @@ public final class ChieftainEnDal extends CardImpl {
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// Whenever Chieftain en-Dal attacks, attacking creatures gain first strike until end of turn. // Whenever Chieftain en-Dal attacks, attacking creatures gain first strike until end of turn.
Ability ability = new AttacksTriggeredAbility(new GainAbilityAllEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, new FilterAttackingCreature()), false); this.addAbility(new AttacksTriggeredAbility(new GainAbilityAllEffect(
this.addAbility(ability); FirstStrikeAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES
), false));
} }
public ChieftainEnDal(final ChieftainEnDal card) { private ChieftainEnDal(final ChieftainEnDal card) {
super(card); super(card);
} }

View file

@ -1,7 +1,6 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.abilities.costs.common.ExileXFromYourGraveCost; import mage.abilities.costs.common.ExileXFromYourGraveCost;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.dynamicvalue.common.GetXValue;
@ -11,28 +10,30 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.filter.common.FilterCreatureCard; import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class ChillHaunting extends CardImpl { public final class ChillHaunting extends CardImpl {
private static final DynamicValue xval = new SignInversionDynamicValue(GetXValue.instance);
public ChillHaunting(UUID ownerId, CardSetInfo setInfo) { public ChillHaunting(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}");
// As an additional cost to cast Chill Haunting, exile X creature cards from your graveyard. // As an additional cost to cast Chill Haunting, exile X creature cards from your graveyard.
this.getSpellAbility().addCost(new ExileXFromYourGraveCost(new FilterCreatureCard("creature cards from your graveyard"), true)); this.getSpellAbility().addCost(new ExileXFromYourGraveCost(StaticFilters.FILTER_CARD_CREATURES_YOUR_GRAVEYARD, true));
// Target creature gets -X/-X until end of turn. // Target creature gets -X/-X until end of turn.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
DynamicValue xval = new SignInversionDynamicValue(GetXValue.instance);
this.getSpellAbility().addEffect(new BoostTargetEffect(xval, xval, Duration.EndOfTurn)); this.getSpellAbility().addEffect(new BoostTargetEffect(xval, xval, Duration.EndOfTurn));
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
} }
public ChillHaunting(final ChillHaunting card) { private ChillHaunting(final ChillHaunting card) {
super(card); super(card);
} }

View file

@ -1,9 +1,7 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility; import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.CompoundCondition; import mage.abilities.condition.CompoundCondition;
import mage.abilities.condition.Condition; import mage.abilities.condition.Condition;
@ -22,18 +20,28 @@ import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class CoffinPuppets extends CardImpl { public final class CoffinPuppets extends CardImpl {
private static final FilterControlledPermanent filter = new FilterControlledPermanent("you control a Swamp"); private static final FilterControlledPermanent filter
= new FilterControlledPermanent("you control a Swamp");
private static final FilterControlledPermanent filter2
= new FilterControlledLandPermanent("two lands");
static { static {
filter.add(new SubtypePredicate(SubType.SWAMP)); filter.add(new SubtypePredicate(SubType.SWAMP));
} }
private static final Condition condition = new CompoundCondition(
"during your upkeep and only if you control a Swamp",
new PermanentsOnTheBattlefieldCondition(filter),
new IsStepCondition(PhaseStep.UPKEEP)
);
public CoffinPuppets(UUID ownerId, CardSetInfo setInfo) { public CoffinPuppets(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}");
@ -42,12 +50,13 @@ public final class CoffinPuppets extends CardImpl {
this.toughness = new MageInt(3); this.toughness = new MageInt(3);
// Sacrifice two lands: Return Coffin Puppets from your graveyard to the battlefield. Activate this ability only during your upkeep and only if you control a Swamp. // Sacrifice two lands: Return Coffin Puppets from your graveyard to the battlefield. Activate this ability only during your upkeep and only if you control a Swamp.
Condition condition = new CompoundCondition("during your upkeep and only if you control a Swamp",new PermanentsOnTheBattlefieldCondition(filter), new IsStepCondition(PhaseStep.UPKEEP)); this.addAbility(new ActivateIfConditionActivatedAbility(
Ability ability = new ActivateIfConditionActivatedAbility(Zone.GRAVEYARD, Zone.GRAVEYARD,
new ReturnSourceFromGraveyardToBattlefieldEffect(), new ReturnSourceFromGraveyardToBattlefieldEffect(),
new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent("two lands"), true)), new SacrificeTargetCost(
condition); new TargetControlledPermanent(2, 2, filter2, true)
this.addAbility(ability); ), condition
));
} }
public CoffinPuppets(final CoffinPuppets card) { public CoffinPuppets(final CoffinPuppets card) {

View file

@ -1,9 +1,9 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.continuous.SetPowerSourceEffect; import mage.abilities.effects.common.continuous.SetPowerSourceEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -13,19 +13,17 @@ import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class CoilingWoodworm extends CardImpl { public final class CoilingWoodworm extends CardImpl {
final static FilterPermanent filterLands = new FilterPermanent("Forests you control"); private static final DynamicValue count = new PermanentsOnBattlefieldCount(
new FilterPermanent(SubType.FOREST, "Forests on the battlefield")
static { );
filterLands.add(new SubtypePredicate(SubType.FOREST));
}
public CoilingWoodworm(UUID ownerId, CardSetInfo setInfo) { public CoilingWoodworm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
@ -36,10 +34,10 @@ public final class CoilingWoodworm extends CardImpl {
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// Coiling Woodworm's power is equal to the number of Forests on the battlefield. // Coiling Woodworm's power is equal to the number of Forests on the battlefield.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerSourceEffect(new PermanentsOnBattlefieldCount(filterLands), Duration.EndOfGame))); this.addAbility(new SimpleStaticAbility(Zone.ALL, new SetPowerSourceEffect(count, Duration.EndOfGame)));
} }
public CoilingWoodworm(final CoilingWoodworm card) { private CoilingWoodworm(final CoilingWoodworm card) {
super(card); super(card);
} }

View file

@ -1,7 +1,6 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -12,15 +11,15 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class CommonCause extends CardImpl { public final class CommonCause extends CardImpl {
@ -35,9 +34,11 @@ public final class CommonCause extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
// Nonartifact creatures get +2/+2 as long as they all share a color. // Nonartifact creatures get +2/+2 as long as they all share a color.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostAllEffect(2, 2, Duration.WhileOnBattlefield, filter, false), this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new AllColorCondition(), new BoostAllEffect(2, 2, Duration.WhileOnBattlefield, filter, false),
"nonartifact creatures get +2/+2 as long as they all share a color."))); AllColorCondition.instance,
"nonartifact creatures get +2/+2 as long as they all share a color.")
));
} }
public CommonCause(final CommonCause card) { public CommonCause(final CommonCause card) {
@ -50,7 +51,8 @@ public final class CommonCause extends CardImpl {
} }
} }
class AllColorCondition implements Condition { enum AllColorCondition implements Condition {
instance;
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
@ -58,7 +60,7 @@ class AllColorCondition implements Condition {
filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT))); filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT)));
ObjectColor allColor = new ObjectColor("WUBRG"); ObjectColor allColor = new ObjectColor("WUBRG");
for (Permanent thing : game.getBattlefield().getAllActivePermanents(filter, game)) { for (Permanent thing : game.getBattlefield().getAllActivePermanents(filter, game)) {
allColor = allColor.intersection(thing.getColor(game)); allColor = allColor.intersection(thing.getColor(game));
} }
return !allColor.isColorless(); return !allColor.isColorless();
} }

View file

@ -1,27 +1,31 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.ComparisonType; import mage.constants.ComparisonType;
import mage.constants.SubType;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.filter.common.FilterControlledPermanent; import mage.filter.StaticFilters;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class ComplexAutomaton extends CardImpl { public final class ComplexAutomaton extends CardImpl {
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(
StaticFilters.FILTER_CONTROLLED_PERMANENT, ComparisonType.MORE_THAN, 6
);
public ComplexAutomaton(UUID ownerId, CardSetInfo setInfo) { public ComplexAutomaton(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}");
@ -30,12 +34,16 @@ public final class ComplexAutomaton extends CardImpl {
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// At the beginning of your upkeep, if you control seven or more permanents, return Complex Automaton to its owner's hand. // At the beginning of your upkeep, if you control seven or more permanents, return Complex Automaton to its owner's hand.
TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new ReturnToHandSourceEffect(true), TargetController.YOU, false); this.addAbility(new ConditionalInterveningIfTriggeredAbility(
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(), ComparisonType.MORE_THAN, 6), new BeginningOfUpkeepTriggeredAbility(
"At the beginning of your upkeep, if you control seven or more permanents, return Complex Automaton to its owner's hand.")); new ReturnToHandSourceEffect(true),
TargetController.YOU, false
), condition, "At the beginning of your upkeep, " +
"if you control seven or more permanents, return {this} to its owner's hand."
));
} }
public ComplexAutomaton(final ComplexAutomaton card) { private ComplexAutomaton(final ComplexAutomaton card) {
super(card); super(card);
} }

View file

@ -1,7 +1,6 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
@ -14,28 +13,29 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TappedPredicate; import mage.filter.predicate.permanent.TappedPredicate;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class CrookclawElder extends CardImpl { public final class CrookclawElder extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Bird you control"); private static final FilterControlledCreaturePermanent filter
private static final FilterControlledCreaturePermanent filter2 = new FilterControlledCreaturePermanent("untapped Wizards you control"); = new FilterControlledCreaturePermanent(SubType.BIRD, "untapped Birds you control");
private static final FilterControlledCreaturePermanent filter2
= new FilterControlledCreaturePermanent(SubType.WIZARD, "untapped Wizards you control");
private static final Predicate pred = Predicates.not(TappedPredicate.instance);
static { static {
filter.add(new SubtypePredicate(SubType.BIRD)); filter.add(pred);
filter.add(Predicates.not(TappedPredicate.instance)); filter2.add(pred);
filter2.add(new SubtypePredicate(SubType.WIZARD));
filter2.add(Predicates.not(TappedPredicate.instance));
} }
public CrookclawElder(UUID ownerId, CardSetInfo setInfo) { public CrookclawElder(UUID ownerId, CardSetInfo setInfo) {
@ -50,16 +50,26 @@ public final class CrookclawElder extends CardImpl {
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// Tap two untapped Birds you control: Draw a card. // Tap two untapped Birds you control: Draw a card.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, true))); Ability ability = new SimpleActivatedAbility(
new DrawCardSourceControllerEffect(1),
new TapTargetCost(new TargetControlledCreaturePermanent(
2, 2, filter, true
))
);
this.addAbility(ability); this.addAbility(ability);
// Tap two untapped Wizards you control: Target creature gains flying until end of turn. // Tap two untapped Wizards you control: Target creature gains flying until end of turn.
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter2, true))); ability = new SimpleActivatedAbility(
new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn),
new TapTargetCost(new TargetControlledCreaturePermanent(
2, 2, filter2, true
))
);
ability.addTarget(new TargetCreaturePermanent()); ability.addTarget(new TargetCreaturePermanent());
this.addAbility(ability); this.addAbility(ability);
} }
public CrookclawElder(final CrookclawElder card) { private CrookclawElder(final CrookclawElder card) {
super(card); super(card);
} }

View file

@ -1,7 +1,7 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID; import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.costs.AlternativeCostSourceAbility; import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.SacrificeTargetCost;
@ -11,30 +11,30 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.SubType; import mage.constants.SubType;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT; import mage.filter.FilterPermanent;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class DarkTriumph extends CardImpl { public final class DarkTriumph extends CardImpl {
private static final FilterLandPermanent filterSwamp = new FilterLandPermanent("If you control a Swamp"); private static final Condition condition = new PermanentsOnTheBattlefieldCondition(
new FilterPermanent(SubType.SWAMP, "If you control a Swamp")
static { );
filterSwamp.add(new SubtypePredicate(SubType.SWAMP));
}
public DarkTriumph(UUID ownerId, CardSetInfo setInfo) { public DarkTriumph(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{B}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{B}");
// If you control a Swamp, you may sacrifice a creature rather than pay Dark Triumph's mana cost. // If you control a Swamp, you may sacrifice a creature rather than pay Dark Triumph's mana cost.
this.addAbility(new AlternativeCostSourceAbility( this.addAbility(new AlternativeCostSourceAbility(
new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT)), new SacrificeTargetCost(
new PermanentsOnTheBattlefieldCondition(filterSwamp), null new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT)
), condition
)); ));
// Creatures you control get +2/+0 until end of turn. // Creatures you control get +2/+0 until end of turn.

View file

@ -1,4 +1,3 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID; import java.util.UUID;
@ -21,13 +20,10 @@ import mage.players.Player;
* *
* @author LevelX2 * @author LevelX2
*/ */
public final class DeadbridgeChant extends CardImpl { public final class DeadbridgeChant extends CardImpl {
public DeadbridgeChant(UUID ownerId, CardSetInfo setInfo) { public DeadbridgeChant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{B}{G}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{B}{G}");
// When Deadbridge Chant enters the battlefield, put the top ten cards of your library into your graveyard. // When Deadbridge Chant enters the battlefield, put the top ten cards of your library into your graveyard.
this.addAbility(new EntersBattlefieldTriggeredAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(10))); this.addAbility(new EntersBattlefieldTriggeredAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(10)));
@ -64,9 +60,10 @@ class DeadbridgeChantEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (player != null && !player.getGraveyard().isEmpty()) { if (controller != null
Card card = player.getGraveyard().getRandom(game); && !controller.getGraveyard().isEmpty()) {
Card card = controller.getGraveyard().getRandom(game);
if (card != null) { if (card != null) {
Zone targetZone = Zone.HAND; Zone targetZone = Zone.HAND;
String text = " put into hand of "; String text = " put into hand of ";
@ -74,8 +71,8 @@ class DeadbridgeChantEffect extends OneShotEffect {
targetZone = Zone.BATTLEFIELD; targetZone = Zone.BATTLEFIELD;
text = " put onto battlefield for "; text = " put onto battlefield for ";
} }
card.moveToZone(targetZone, source.getSourceId(), game, false); controller.moveCards(card, targetZone, source, game);
game.informPlayers("Deadbridge Chant: " + card.getName() + text + player.getLogName()); game.informPlayers("Deadbridge Chant: " + card.getName() + text + controller.getLogName());
return true; return true;
} }
} }

View file

@ -1,7 +1,6 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.costs.AlternativeCostSourceAbility; import mage.abilities.costs.AlternativeCostSourceAbility;
@ -15,13 +14,15 @@ import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate; import mage.filter.predicate.mageobject.ColorPredicate;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class Delraich extends CardImpl { public final class Delraich extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("black creature"); private static final FilterControlledCreaturePermanent filter
= new FilterControlledCreaturePermanent("black creature");
static { static {
filter.add(new ColorPredicate(ObjectColor.BLACK)); filter.add(new ColorPredicate(ObjectColor.BLACK));
@ -34,15 +35,16 @@ public final class Delraich extends CardImpl {
this.power = new MageInt(6); this.power = new MageInt(6);
this.toughness = new MageInt(6); this.toughness = new MageInt(6);
// You may sacrifice three black creatures rather than pay Delraich's mana cost.
this.addAbility(new AlternativeCostSourceAbility(new SacrificeTargetCost(
new TargetControlledPermanent(3, 3, filter, false)
)));
// Trample // Trample
this.addAbility(TrampleAbility.getInstance()); this.addAbility(TrampleAbility.getInstance());
// You may sacrifice three black creatures rather than pay Delraich's mana cost.
AlternativeCostSourceAbility alternateCosts = new AlternativeCostSourceAbility(new SacrificeTargetCost(new TargetControlledPermanent(3, 3, filter, false)));
this.addAbility(alternateCosts);
} }
public Delraich(final Delraich card) { private Delraich(final Delraich card) {
super(card); super(card);
} }

View file

@ -1,23 +1,23 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility; import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility;
import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.SacrificeEffect; import mage.abilities.effects.common.SacrificeEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType; import mage.constants.SubType;
import mage.filter.common.FilterLandPermanent; import mage.filter.StaticFilters;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class DestructiveUrge extends CardImpl { public final class DestructiveUrge extends CardImpl {
@ -35,8 +35,10 @@ public final class DestructiveUrge extends CardImpl {
this.addAbility(ability); this.addAbility(ability);
// Whenever enchanted creature deals combat damage to a player, that player sacrifices a land. // Whenever enchanted creature deals combat damage to a player, that player sacrifices a land.
ability = new DealsDamageToAPlayerAttachedTriggeredAbility(new SacrificeEffect(new FilterLandPermanent(), 1, "that player"), "enchanted", false, true); this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility(
this.addAbility(ability); new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "that player"),
"enchanted", false, true
));
} }
public DestructiveUrge(final DestructiveUrge card) { public DestructiveUrge(final DestructiveUrge card) {

View file

@ -1,7 +1,6 @@
package mage.cards.d; package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -10,13 +9,14 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.StaticFilters;
import mage.game.Game; import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class DivineCongregation extends CardImpl { public final class DivineCongregation extends CardImpl {
@ -32,7 +32,7 @@ public final class DivineCongregation extends CardImpl {
this.addAbility(new SuspendAbility(5, new ManaCostsImpl("{1}{W}"), this)); this.addAbility(new SuspendAbility(5, new ManaCostsImpl("{1}{W}"), this));
} }
public DivineCongregation(final DivineCongregation card) { private DivineCongregation(final DivineCongregation card) {
super(card); super(card);
} }
@ -44,12 +44,12 @@ public final class DivineCongregation extends CardImpl {
class DivineCongregationEffect extends OneShotEffect { class DivineCongregationEffect extends OneShotEffect {
public DivineCongregationEffect() { DivineCongregationEffect() {
super(Outcome.Benefit); super(Outcome.Benefit);
staticText = "You gain 2 life for each creature target player controls"; staticText = "You gain 2 life for each creature target player controls";
} }
public DivineCongregationEffect(final DivineCongregationEffect effect) { private DivineCongregationEffect(final DivineCongregationEffect effect) {
super(effect); super(effect);
} }
@ -63,7 +63,7 @@ class DivineCongregationEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(source.getFirstTarget()); Player player = game.getPlayer(source.getFirstTarget());
if (controller != null && player != null) { if (controller != null && player != null) {
int critters = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game).size(); int critters = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game).size();
controller.gainLife(2 * critters, game, source); controller.gainLife(2 * critters, game, source);
} }
return true; return true;

View file

@ -1,8 +1,6 @@
package mage.cards.e; package mage.cards.e;
import java.util.Iterator;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.condition.InvertCondition; import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.CardsInControllerGraveCondition; import mage.abilities.condition.common.CardsInControllerGraveCondition;
@ -18,8 +16,10 @@ import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import java.util.Iterator;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class Epicenter extends CardImpl { public final class Epicenter extends CardImpl {
@ -31,12 +31,15 @@ public final class Epicenter extends CardImpl {
this.getSpellAbility().addEffect(new ConditionalOneShotEffect( this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "Target player"), new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "Target player"),
new InvertCondition(new CardsInControllerGraveCondition(7)), new InvertCondition(new CardsInControllerGraveCondition(7)),
"Target player sacrifices a land")); "Target player sacrifices a land"
));
// Threshold - Each player sacrifices all lands he or she controls instead if seven or more cards are in your graveyard. // Threshold - Each player sacrifices all lands he or she controls instead if seven or more cards are in your graveyard.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect( this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new EpicenterEffect(), new EpicenterEffect(),
new CardsInControllerGraveCondition(7), new CardsInControllerGraveCondition(7),
"<br/><br/><i>Threshold</i> &mdash; Each player sacrifices all lands he or she controls instead if seven or more cards are in your graveyard.")); "<br/><br/><i>Threshold</i> &mdash; Each player sacrifices all lands they control instead " +
"if seven or more cards are in your graveyard."
));
this.getSpellAbility().addTarget(new TargetPlayer()); this.getSpellAbility().addTarget(new TargetPlayer());
} }
@ -55,10 +58,9 @@ class EpicenterEffect extends OneShotEffect {
EpicenterEffect() { EpicenterEffect() {
super(Outcome.DestroyPermanent); super(Outcome.DestroyPermanent);
staticText = "Each player sacrifices all lands he or she controls";
} }
EpicenterEffect(final EpicenterEffect effect) { private EpicenterEffect(final EpicenterEffect effect) {
super(effect); super(effect);
} }

View file

@ -1,4 +1,3 @@
package mage.cards.g; package mage.cards.g;
import java.util.HashSet; import java.util.HashSet;
@ -10,7 +9,6 @@ import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.Card; import mage.cards.Card;
@ -30,7 +28,6 @@ import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import mage.target.common.TargetCardInExile; import mage.target.common.TargetCardInExile;
import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInHand;
import mage.util.CardUtil;
/** /**
* *
@ -84,7 +81,11 @@ class GusthasScepterExileEffect extends OneShotEffect {
Card card = game.getCard(target.getFirstTarget()); Card card = game.getCard(target.getFirstTarget());
MageObject sourceObject = game.getObject(source.getSourceId()); MageObject sourceObject = game.getObject(source.getSourceId());
if (card != null && sourceObject != null) { if (card != null && sourceObject != null) {
if (card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceObject.getIdName(), source.getSourceId(), game)) { UUID exileId = source.getSourceId();
if (card.moveToExile(exileId,
sourceObject.getIdName(),
source.getSourceId(),
game)) {
card.setFaceDown(true, game); card.setFaceDown(true, game);
game.addEffect(new GusthasScepterLookAtCardEffect(card.getId()), source); game.addEffect(new GusthasScepterLookAtCardEffect(card.getId()), source);
return true; return true;
@ -116,7 +117,7 @@ class TargetCardInGusthasScepterExile extends TargetCardInExile {
Set<UUID> possibleTargets = new HashSet<>(); Set<UUID> possibleTargets = new HashSet<>();
Card sourceCard = game.getCard(sourceId); Card sourceCard = game.getCard(sourceId);
if (sourceCard != null) { if (sourceCard != null) {
UUID exileId = CardUtil.getCardExileZoneId(game, sourceId); UUID exileId = sourceId;
ExileZone exile = game.getExile().getExileZone(exileId); ExileZone exile = game.getExile().getExileZone(exileId);
if (exile != null && !exile.isEmpty()) { if (exile != null && !exile.isEmpty()) {
possibleTargets.addAll(exile); possibleTargets.addAll(exile);
@ -129,7 +130,7 @@ class TargetCardInGusthasScepterExile extends TargetCardInExile {
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
Card sourceCard = game.getCard(sourceId); Card sourceCard = game.getCard(sourceId);
if (sourceCard != null) { if (sourceCard != null) {
UUID exileId = CardUtil.getCardExileZoneId(game, sourceId); UUID exileId = sourceId;
ExileZone exile = game.getExile().getExileZone(exileId); ExileZone exile = game.getExile().getExileZone(exileId);
if (exile != null && !exile.isEmpty()) { if (exile != null && !exile.isEmpty()) {
return true; return true;
@ -141,14 +142,16 @@ class TargetCardInGusthasScepterExile extends TargetCardInExile {
@Override @Override
public boolean canTarget(UUID id, Ability source, Game game) { public boolean canTarget(UUID id, Ability source, Game game) {
Card card = game.getCard(id); Card card = game.getCard(id);
if (card != null && game.getState().getZone(card.getId()) == Zone.EXILED) { if (card != null
&& game.getState().getZone(card.getId()) == Zone.EXILED) {
ExileZone exile = null; ExileZone exile = null;
Card sourceCard = game.getCard(source.getSourceId()); Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null) { if (sourceCard != null) {
UUID exileId = CardUtil.getCardExileZoneId(game, source); UUID exileId = source.getSourceId();
exile = game.getExile().getExileZone(exileId); exile = game.getExile().getExileZone(exileId);
} }
if (exile != null && exile.contains(id)) { if (exile != null
&& exile.contains(id)) {
return filter.match(card, source.getControllerId(), game); return filter.match(card, source.getControllerId(), game);
} }
} }
@ -190,13 +193,16 @@ class GusthasScepterLookAtCardEffect extends AsThoughEffectImpl {
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (objectId.equals(cardId) && affectedControllerId.equals(source.getControllerId())) { if (objectId.equals(cardId) && affectedControllerId.equals(source.getControllerId())) {
MageObject sourceObject = source.getSourceObject(game); MageObject sourceObject = source.getSourceObject(game);
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); if (sourceObject != null) {
if (exileId != null && sourceObject != null) { UUID exileId = source.getSourceId();
ExileZone exileZone = game.getExile().getExileZone(exileId); ExileZone exileZone = game.getExile().getExileZone(exileId);
if (exileZone != null && exileZone.contains(cardId)) { if (exileZone != null
&& exileZone.contains(cardId)) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
Card card = game.getCard(cardId); Card card = game.getCard(cardId);
if (controller != null && card != null && game.getState().getZone(cardId) == Zone.EXILED) { if (controller != null
&& card != null
&& game.getState().getZone(cardId) == Zone.EXILED) {
return true; return true;
} }
} else { } else {
@ -233,16 +239,10 @@ class GusthasScepterLoseControlAbility extends DelayedTriggeredAbility {
if (event.getType() == GameEvent.EventType.LOST_CONTROL) { if (event.getType() == GameEvent.EventType.LOST_CONTROL) {
return event.getPlayerId().equals(controllerId) return event.getPlayerId().equals(controllerId)
&& event.getTargetId().equals(this.getSourceId()); && event.getTargetId().equals(this.getSourceId());
} } else if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
else if (event.getType() == GameEvent.EventType.ZONE_CHANGE) {
if (event.getTargetId().equals(this.getSourceId())) { if (event.getTargetId().equals(this.getSourceId())) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event; ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.getFromZone() == Zone.BATTLEFIELD) { return (zEvent.getFromZone() == Zone.BATTLEFIELD);
for (Effect effect : getEffects()) {
effect.setValue("permanentLeftBattlefield", ((ZoneChangeEvent) event).getTarget());
}
return true;
}
} }
} }
return false; return false;
@ -268,13 +268,12 @@ class GusthasScepterPutExiledCardsInOwnersGraveyard extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId()); if (controller != null) {
if (controller != null UUID exileId = source.getSourceId();
&& sourceObject != null) { ExileZone exileZone = game.getExile().getExileZone(exileId);
UUID exileId = CardUtil.getCardExileZoneId(game, source); if (exileZone != null) {
Set<Card> cardsInExile = game.getExile().getExileZone(exileId).getCards(game); return controller.moveCards(exileZone.getCards(game), Zone.GRAVEYARD, source, game);
controller.moveCardsToGraveyardWithInfo(cardsInExile, source, game, Zone.EXILED); }
return true;
} }
return false; return false;
} }

View file

@ -1,7 +1,6 @@
package mage.cards.i; package mage.cards.i;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SpellCastOpponentTriggeredAbility; import mage.abilities.common.SpellCastOpponentTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
@ -11,22 +10,21 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SubType; import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.FilterSpell; import mage.filter.FilterSpell;
import mage.filter.common.FilterArtifactCard; import mage.filter.common.FilterArtifactCard;
import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.common.FilterArtifactSpell;
import mage.game.permanent.token.InsectToken; import mage.game.permanent.token.InsectToken;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class InfestedRoothold extends CardImpl { public final class InfestedRoothold extends CardImpl {
private final static FilterSpell filter = new FilterSpell("an artifact spell"); private static final FilterCard filter = new FilterArtifactCard("artifacts");
private static final FilterSpell filter2 = new FilterArtifactSpell("an artifact spell");
static {
filter.add(new CardTypePredicate(CardType.ARTIFACT));
}
public InfestedRoothold(UUID ownerId, CardSetInfo setInfo) { public InfestedRoothold(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}");
@ -39,10 +37,12 @@ public final class InfestedRoothold extends CardImpl {
this.addAbility(DefenderAbility.getInstance()); this.addAbility(DefenderAbility.getInstance());
// Protection from artifacts // Protection from artifacts
this.addAbility(new ProtectionAbility(new FilterArtifactCard("artifacts"))); this.addAbility(new ProtectionAbility(filter));
// Whenever an opponent casts an artifact spell, you may create a 1/1 green Insect creature token. // Whenever an opponent casts an artifact spell, you may create a 1/1 green Insect creature token.
this.addAbility(new SpellCastOpponentTriggeredAbility(new CreateTokenEffect(new InsectToken()), filter, true)); this.addAbility(new SpellCastOpponentTriggeredAbility(
new CreateTokenEffect(new InsectToken()), filter2, true)
);
} }

View file

@ -0,0 +1,148 @@
package mage.cards.i;
import java.util.Objects;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author jeffwadsworth & L_J
*/
public final class InfiniteAuthority extends CardImpl {
public InfiniteAuthority(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{W}{W}");
this.subtype.add(SubType.AURA);
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Whenever enchanted creature blocks or becomes blocked by a creature with toughness 3 or less, destroy the other creature at end of combat. At the beginning of the next end step, if that creature was destroyed this way, put a +1/+1 counter on the first creature.
this.addAbility(new InfiniteAuthorityTriggeredAbility());
}
public InfiniteAuthority(final InfiniteAuthority card) {
super(card);
}
@Override
public InfiniteAuthority copy() {
return new InfiniteAuthority(this);
}
}
class InfiniteAuthorityTriggeredAbility extends TriggeredAbilityImpl {
InfiniteAuthorityTriggeredAbility() {
super(Zone.BATTLEFIELD, new CreateDelayedTriggeredAbilityEffect(new AtTheEndOfCombatDelayedTriggeredAbility(new InfiniteAuthorityEffect())));
}
InfiniteAuthorityTriggeredAbility(final InfiniteAuthorityTriggeredAbility ability) {
super(ability);
}
@Override
public InfiniteAuthorityTriggeredAbility copy() {
return new InfiniteAuthorityTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.BLOCKER_DECLARED;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent aura = game.getPermanentOrLKIBattlefield(sourceId);
if (aura != null) {
Permanent enchantedCreature = game.getPermanentOrLKIBattlefield(aura.getAttachedTo());
if (enchantedCreature != null) {
Permanent blocker = game.getPermanent(event.getSourceId());
Permanent blocked = game.getPermanent(event.getTargetId());
Effect effect = this.getEffects().get(0);
if (blocker != null
&& Objects.equals(blocked, enchantedCreature)
&& blocker.getToughness().getValue() <= 3) {
effect.setTargetPointer(new FixedTarget(blocker.getId()));
return true;
}
if (blocked != null
&& Objects.equals(blocker, enchantedCreature)
&& blocked.getToughness().getValue() <= 3) {
effect.setTargetPointer(new FixedTarget(blocked.getId()));
return true;
}
}
}
return false;
}
@Override
public String getRule() {
return "Whenever enchanted creature blocks or becomes blocked by a creature with toughness 3 or less, " + super.getRule();
}
}
class InfiniteAuthorityEffect extends OneShotEffect {
InfiniteAuthorityEffect() {
super(Outcome.Detriment);
staticText = "destroy the other creature at end of combat. At the beginning of the next end step, if that creature was destroyed this way, put a +1/+1 counter on the first creature";
}
InfiniteAuthorityEffect(final InfiniteAuthorityEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Permanent aura = game.getPermanentOrLKIBattlefield(source.getSourceId());
if (aura != null) {
Permanent enchantedCreature = game.getPermanentOrLKIBattlefield(aura.getAttachedTo());
if (enchantedCreature != null) {
Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source));
if (permanent != null) {
if (permanent.destroy(source.getSourceId(), game, false)) {
AtTheBeginOfNextEndStepDelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new AddCountersTargetEffect(CounterType.P1P1.createInstance()));
delayedAbility.getEffects().get(0).setTargetPointer(new FixedTarget(enchantedCreature, game));
game.addDelayedTriggeredAbility(delayedAbility, source);
}
return true;
}
}
}
return false;
}
@Override
public InfiniteAuthorityEffect copy() {
return new InfiniteAuthorityEffect(this);
}
}

View file

@ -1,8 +1,5 @@
package mage.cards.i; package mage.cards.i;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
@ -40,13 +37,17 @@ public final class IntetTheDreamer extends CardImpl {
// Flying // Flying
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// Whenever Intet, the Dreamer deals combat damage to a player, you may pay {2}{U}. If you do, exile the top card of your library face down. // Whenever Intet, the Dreamer deals combat damage to a player, you may pay {2}{U}. If you do, exile the top card of your library face down.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
new DoIfCostPaid(new IntetTheDreamerExileEffect(), new ManaCostsImpl("{2}{U}")), false, true)); new DoIfCostPaid(new IntetTheDreamerExileEffect(), new ManaCostsImpl("{2}{U}")), false, true));
// You may look at that card for as long as it remains exiled. // You may look at that card for as long as it remains exiled.
this.addAbility(new SimpleStaticAbility(Zone.ALL, new IntetTheDreamerLookEffect())); this.addAbility(new SimpleStaticAbility(Zone.ALL, new IntetTheDreamerLookEffect()));
// You may play that card without paying its mana cost for as long as Intet remains on the battlefield. // You may play that card without paying its mana cost for as long as Intet remains on the battlefield.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new IntetTheDreamerCastEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new IntetTheDreamerCastEffect()));
} }
public IntetTheDreamer(final IntetTheDreamer card) { public IntetTheDreamer(final IntetTheDreamer card) {
@ -76,17 +77,20 @@ class IntetTheDreamerExileEffect extends OneShotEffect {
if (controller != null) { if (controller != null) {
Card card = controller.getLibrary().getFromTop(game); Card card = controller.getLibrary().getFromTop(game);
MageObject sourceObject = source.getSourceObject(game); MageObject sourceObject = source.getSourceObject(game);
if (card != null && sourceObject != null) { if (card != null
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); && sourceObject != null) {
card.setFaceDown(true, game); card.setFaceDown(true, game);
controller.moveCardsToExile(card, source, game, false, exileZoneId, sourceObject.getIdName()); controller.moveCardsToExile(
card,
source,
game,
false,
CardUtil.getExileZoneId(game,
source.getSourceId(),
sourceObject.getZoneChangeCounter(game)), // sourceObject must be used due to source not working correctly
sourceObject.getIdName());
card.setFaceDown(true, game); card.setFaceDown(true, game);
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(IntetTheDreamer.VALUE_PREFIX + source.getSourceId().toString()); game.getState().setValue("Exiled_IntetTheDreamer" + card.getId(), Boolean.TRUE);
if (exileZones == null) {
exileZones = new HashSet<>();
game.getState().setValue(IntetTheDreamer.VALUE_PREFIX + source.getSourceId().toString(), exileZones);
}
exileZones.add(exileZoneId);
return true; return true;
} }
} }
@ -122,20 +126,29 @@ class IntetTheDreamerCastEffect extends AsThoughEffectImpl {
@Override @Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (affectedControllerId.equals(source.getControllerId()) && game.getState().getZone(objectId) == Zone.EXILED) { if (affectedControllerId.equals(source.getControllerId())) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game); MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) { if (controller != null
&& sourceObject != null) {
Card card = game.getCard(objectId); Card card = game.getCard(objectId);
if (card != null && card.isFaceDown(game)) { if (card != null
ExileZone zone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter())); && card.isFaceDown(game)) {
if (zone != null && zone.contains(card.getId())/* && CardUtil.cardCanBePlayedNow(card, controller.getId(), game)*/) { ExileZone zone = game.getExile().getExileZone(
CardUtil.getExileZoneId(game,
source.getSourceId(),
sourceObject.getZoneChangeCounter(game))); // sourceObject must be used due to source not working correctly
if (zone != null
&& zone.contains(card.getId())) {
if (card.isLand()) { if (card.isLand()) {
if (game.canPlaySorcery(controller.getId()) && game.getPlayer(controller.getId()).canPlayLand()) { if (game.canPlaySorcery(controller.getId())
&& game.getPlayer(controller.getId()).canPlayLand()) {
return controller.chooseUse(outcome, "Play " + card.getIdName() + '?', source, game); return controller.chooseUse(outcome, "Play " + card.getIdName() + '?', source, game);
} }
} else { } else {
controller.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts()); controller.setCastSourceIdWithAlternateMana(objectId,
null,
card.getSpellAbility().getCosts());
return true; return true;
} }
} }
@ -170,24 +183,14 @@ class IntetTheDreamerLookEffect extends AsThoughEffectImpl {
@Override @Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (affectedControllerId.equals(source.getControllerId()) && game.getState().getZone(objectId) == Zone.EXILED) { if (affectedControllerId.equals(source.getControllerId())) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game); if (controller != null) {
if (controller != null && sourceObject != null) {
Card card = game.getCard(objectId); Card card = game.getCard(objectId);
if (card != null && card.isFaceDown(game)) { return (card != null
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(IntetTheDreamer.VALUE_PREFIX + source.getSourceId().toString()); && card.isFaceDown(game)
if (exileZones != null) { && game.getExile().containsId(card.getId(), game)
for (ExileZone exileZone : game.getExile().getExileZones()) { && (Boolean) game.getState().getValue("Exiled_IntetTheDreamer" + card.getId()));
if (exileZone.contains(objectId)) {
if (!exileZones.contains(exileZone.getId())) {
return false;
}
}
}
return true;
}
}
} }
} }
return false; return false;

View file

@ -19,6 +19,7 @@ import mage.game.stack.StackObject;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetSpell; import mage.target.TargetSpell;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID; import java.util.UUID;
@ -81,7 +82,8 @@ class KheruSpellsnatcherEffect extends OneShotEffect {
if (!stackObject.isCopy()) { if (!stackObject.isCopy()) {
MageObject card = game.getObject(stackObject.getSourceId()); MageObject card = game.getObject(stackObject.getSourceId());
if (card instanceof Card) { if (card instanceof Card) {
((Card) card).moveToZone(Zone.EXILED, sourceId, game, true); UUID exileId = CardUtil.getCardExileZoneId(game, sourceId);
((Card) card).moveToExile(exileId, "Kheru Spellsnatcher - cast without mana cost", sourceId, game);
ContinuousEffect effect = new KheruSpellsnatcherCastFromExileEffect(); ContinuousEffect effect = new KheruSpellsnatcherCastFromExileEffect();
effect.setTargetPointer(new FixedTarget(card.getId())); effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source); game.addEffect(effect, source);

View file

@ -1,37 +1,30 @@
package mage.cards.k; package mage.cards.k;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DestroyTargetEffect;
import mage.constants.SubType; import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.keyword.FlankingAbility; import mage.abilities.keyword.FlankingAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent; import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.SubtypePredicate; import mage.target.TargetPermanent;
import mage.game.Game;
import mage.players.Player; import java.util.UUID;
import mage.target.common.TargetCreaturePermanent;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class KnightOfTheMists extends CardImpl { public final class KnightOfTheMists extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Knight"); private static final FilterPermanent filter = new FilterCreaturePermanent(SubType.KNIGHT, "Knight");
static {
filter.add(new SubtypePredicate(SubType.KNIGHT));
}
public KnightOfTheMists(UUID ownerId, CardSetInfo setInfo) { public KnightOfTheMists(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
@ -45,12 +38,14 @@ public final class KnightOfTheMists extends CardImpl {
this.addAbility(new FlankingAbility()); this.addAbility(new FlankingAbility());
// When Knight of the Mists enters the battlefield, you may pay {U}. If you don't, destroy target Knight and it can't be regenerated. // When Knight of the Mists enters the battlefield, you may pay {U}. If you don't, destroy target Knight and it can't be regenerated.
Ability ability = new EntersBattlefieldTriggeredAbility(new KnightOfTheMistsEffect()); Ability ability = new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(
ability.addTarget(new TargetCreaturePermanent(filter)); new InfoEffect(""), new DestroyTargetEffect(), new ManaCostsImpl("{U}")
).setText("you may pay {U}. If you don't, destroy target Knight and it can't be regenerated."));
ability.addTarget(new TargetPermanent(filter));
addAbility(ability); addAbility(ability);
} }
public KnightOfTheMists(final KnightOfTheMists card) { private KnightOfTheMists(final KnightOfTheMists card) {
super(card); super(card);
} }
@ -59,35 +54,3 @@ public final class KnightOfTheMists extends CardImpl {
return new KnightOfTheMists(this); return new KnightOfTheMists(this);
} }
} }
class KnightOfTheMistsEffect extends OneShotEffect {
KnightOfTheMistsEffect() {
super(Outcome.Neutral);
this.staticText = "When {this} enters the battlefield, you may pay {U}. If you don't, destroy target Knight and it can't be regenerated.";
}
KnightOfTheMistsEffect(final KnightOfTheMistsEffect effect) {
super(effect);
}
@Override
public KnightOfTheMistsEffect copy() {
return new KnightOfTheMistsEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getSourceId());
if (player == null) {
return false;
}
Cost cost = new ManaCostsImpl("{U}");
if (!(cost.canPay(source, source.getSourceId(), player.getId(), game)
&& player.chooseUse(outcome, "Pay {U}?", source, game)
&& cost.pay(source, game, source.getSourceId(), player.getId(), false))) {
return new DestroyTargetEffect(true).apply(game, source);
}
return true;
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -10,7 +9,10 @@ import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect; import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent; import mage.game.events.EntersTheBattlefieldEvent;
@ -19,14 +21,15 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class MasterBiomancer extends CardImpl { public final class MasterBiomancer extends CardImpl {
public MasterBiomancer(UUID ownerId, CardSetInfo setInfo) { public MasterBiomancer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{U}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}");
this.subtype.add(SubType.ELF); this.subtype.add(SubType.ELF);
this.subtype.add(SubType.WIZARD); this.subtype.add(SubType.WIZARD);
@ -34,10 +37,10 @@ public final class MasterBiomancer extends CardImpl {
this.toughness = new MageInt(4); this.toughness = new MageInt(4);
// Each other creature you control enters the battlefield with a number of additional +1/+1 counters on it equal to Master Biomancer's power and as a Mutant in addition to its other types. // Each other creature you control enters the battlefield with a number of additional +1/+1 counters on it equal to Master Biomancer's power and as a Mutant in addition to its other types.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MasterBiomancerEntersBattlefieldEffect())); this.addAbility(new SimpleStaticAbility(new MasterBiomancerEntersBattlefieldEffect()));
} }
public MasterBiomancer(final MasterBiomancer card) { private MasterBiomancer(final MasterBiomancer card) {
super(card); super(card);
} }
@ -49,12 +52,12 @@ public final class MasterBiomancer extends CardImpl {
class MasterBiomancerEntersBattlefieldEffect extends ReplacementEffectImpl { class MasterBiomancerEntersBattlefieldEffect extends ReplacementEffectImpl {
public MasterBiomancerEntersBattlefieldEffect() { MasterBiomancerEntersBattlefieldEffect() {
super(Duration.WhileOnBattlefield, Outcome.BoostCreature); super(Duration.WhileOnBattlefield, Outcome.BoostCreature);
staticText = "Each other creature you control enters the battlefield with a number of additional +1/+1 counters on it equal to Master Biomancer's power and as a Mutant in addition to its other types"; staticText = "Each other creature you control enters the battlefield with a number of additional +1/+1 counters on it equal to {this}'s power and as a Mutant in addition to its other types";
} }
public MasterBiomancerEntersBattlefieldEffect(MasterBiomancerEntersBattlefieldEffect effect) { private MasterBiomancerEntersBattlefieldEffect(MasterBiomancerEntersBattlefieldEffect effect) {
super(effect); super(effect);
} }

View file

@ -4,6 +4,8 @@ import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect; import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
@ -13,7 +15,9 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID; import java.util.UUID;
@ -38,7 +42,7 @@ public final class MinionOfTheWastes extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield"))); this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield")));
} }
public MinionOfTheWastes(final MinionOfTheWastes card) { private MinionOfTheWastes(final MinionOfTheWastes card) {
super(card); super(card);
} }
@ -50,12 +54,12 @@ public final class MinionOfTheWastes extends CardImpl {
class MinionOfTheWastesEffect extends OneShotEffect { class MinionOfTheWastesEffect extends OneShotEffect {
public MinionOfTheWastesEffect() { MinionOfTheWastesEffect() {
super(Outcome.LoseLife); super(Outcome.LoseLife);
staticText = "pay any amount of life"; staticText = "pay any amount of life";
} }
public MinionOfTheWastesEffect(final MinionOfTheWastesEffect effect) { private MinionOfTheWastesEffect(final MinionOfTheWastesEffect effect) {
super(effect); super(effect);
} }
@ -67,15 +71,22 @@ class MinionOfTheWastesEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { Permanent permanent = game.getPermanentEntering(source.getSourceId());
int payAmount = controller.getAmount(0, controller.getLife(), "Pay any amount of life", game); if (controller == null || permanent == null) {
controller.loseLife(payAmount, game, false); return false;
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getLogName() : "") + ": " + controller.getLogName() +
" pays " + payAmount + " life");
game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source);
return true;
} }
return false; int payAmount = controller.getAmount(0, controller.getLife(), "Pay any amount of life", game);
Cost cost = new PayLifeCost(payAmount);
if (!cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) {
return false;
}
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getLogName() : "") + ": " + controller.getLogName() +
" pays " + payAmount + " life");
game.addEffect(new SetPowerToughnessSourceEffect(
payAmount, payAmount, Duration.Custom, SubLayer.CharacteristicDefining_7a
), source);
permanent.addInfo("life paid", CardUtil.addToolTipMarkTags("Life paid: " + payAmount), game);
return true;
} }
} }

View file

@ -1,35 +1,39 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseCreatureTypeEffect; import mage.abilities.effects.common.ChooseCreatureTypeEffect;
import mage.abilities.effects.common.continuous.AddCardTypeTargetEffect; import mage.abilities.effects.common.continuous.AddCardTypeSourceEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone; import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ChosenSubtypePredicate; import mage.filter.predicate.mageobject.ChosenSubtypePredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
import mage.util.functions.EmptyApplyToPermanent; import mage.util.functions.EmptyApplyToPermanent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class MirrorOfTheForebears extends CardImpl { public final class MirrorOfTheForebears extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(new ChosenSubtypePredicate());
}
public MirrorOfTheForebears(UUID ownerId, CardSetInfo setInfo) { public MirrorOfTheForebears(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
@ -37,14 +41,12 @@ public final class MirrorOfTheForebears extends CardImpl {
this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Copy))); this.addAbility(new AsEntersBattlefieldAbility(new ChooseCreatureTypeEffect(Outcome.Copy)));
// 1: Until end of turn, Mirror of the Forebears becomes a copy of target creature you control of the chosen type, except it's an artifact in addition to its other types. // 1: Until end of turn, Mirror of the Forebears becomes a copy of target creature you control of the chosen type, except it's an artifact in addition to its other types.
FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); Ability ability = new SimpleActivatedAbility(new MirrorOfTheForebearsCopyEffect(), new GenericManaCost(1));
filter.add(new ChosenSubtypePredicate());
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MirrorOfTheForebearsCopyEffect(), new ManaCostsImpl("{1}"));
ability.addTarget(new TargetPermanent(filter)); ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability); this.addAbility(ability);
} }
public MirrorOfTheForebears(final MirrorOfTheForebears card) { private MirrorOfTheForebears(final MirrorOfTheForebears card) {
super(card); super(card);
} }
@ -56,12 +58,12 @@ public final class MirrorOfTheForebears extends CardImpl {
class MirrorOfTheForebearsCopyEffect extends OneShotEffect { class MirrorOfTheForebearsCopyEffect extends OneShotEffect {
public MirrorOfTheForebearsCopyEffect() { MirrorOfTheForebearsCopyEffect() {
super(Outcome.Copy); super(Outcome.Copy);
this.staticText = "until end of turn, {this} becomes a copy of target creature you control of the chosen type, except it's an artifact in addition to its other types"; this.staticText = "until end of turn, {this} becomes a copy of target creature you control of the chosen type, except it's an artifact in addition to its other types";
} }
public MirrorOfTheForebearsCopyEffect(final MirrorOfTheForebearsCopyEffect effect) { private MirrorOfTheForebearsCopyEffect(final MirrorOfTheForebearsCopyEffect effect) {
super(effect); super(effect);
} }
@ -76,11 +78,7 @@ class MirrorOfTheForebearsCopyEffect extends OneShotEffect {
Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (sourcePermanent != null && copyFromPermanent != null) { if (sourcePermanent != null && copyFromPermanent != null) {
game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent()); game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent());
if (!copyFromPermanent.isArtifact()) { game.addEffect(new AddCardTypeSourceEffect(Duration.EndOfTurn, CardType.ARTIFACT), source);
ContinuousEffect effect = new AddCardTypeTargetEffect(Duration.EndOfTurn, CardType.ARTIFACT);
effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
game.addEffect(effect, source);
}
return true; return true;
} }
return false; return false;

View file

@ -1,4 +1,3 @@
package mage.cards.n; package mage.cards.n;
import java.util.UUID; import java.util.UUID;
@ -49,13 +48,13 @@ public final class NahiriTheHarbinger extends CardImpl {
static { static {
filter.add(Predicates.or(new CardTypePredicate(CardType.ENCHANTMENT), filter.add(Predicates.or(new CardTypePredicate(CardType.ENCHANTMENT),
(Predicates.and(new CardTypePredicate(CardType.ARTIFACT), (Predicates.and(new CardTypePredicate(CardType.ARTIFACT),
TappedPredicate.instance)), TappedPredicate.instance)),
(Predicates.and(new CardTypePredicate(CardType.CREATURE), (Predicates.and(new CardTypePredicate(CardType.CREATURE),
TappedPredicate.instance)))); TappedPredicate.instance))));
} }
public NahiriTheHarbinger(UUID ownerId, CardSetInfo setInfo) { public NahiriTheHarbinger(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{2}{R}{W}"); super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{R}{W}");
this.addSuperType(SuperType.LEGENDARY); this.addSuperType(SuperType.LEGENDARY);
this.subtype.add(SubType.NAHIRI); this.subtype.add(SubType.NAHIRI);
@ -114,16 +113,18 @@ class NahiriTheHarbingerEffect extends SearchEffect {
if (controller.searchLibrary(target, game)) { if (controller.searchLibrary(target, game)) {
if (!target.getTargets().isEmpty()) { if (!target.getTargets().isEmpty()) {
Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); Card card = controller.getLibrary().getCard(target.getFirstTarget(), game);
controller.moveCards(card, Zone.BATTLEFIELD, source, game); if (card != null) {
Permanent permanent = game.getPermanent(card.getId()); controller.moveCards(card, Zone.BATTLEFIELD, source, game);
if (permanent != null) { Permanent permanent = game.getPermanent(card.getId());
ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); if (permanent != null) {
effect.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game))); ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom);
game.addEffect(effect, source); effect.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game)));
Effect effect2 = new ReturnToHandTargetEffect(); game.addEffect(effect, source);
effect2.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game))); Effect effect2 = new ReturnToHandTargetEffect();
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect2); effect2.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game)));
game.addDelayedTriggeredAbility(delayedAbility, source); DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect2);
game.addDelayedTriggeredAbility(delayedAbility, source);
}
} }
} }
controller.shuffleLibrary(source, game); controller.shuffleLibrary(source, game);

View file

@ -5,6 +5,8 @@ import mage.ObjectColor;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount; import mage.abilities.dynamicvalue.common.CardsInAllGraveyardsCount;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -23,7 +25,9 @@ import mage.filter.predicate.other.OwnerPredicate;
import mage.filter.predicate.permanent.ControllerPredicate; import mage.filter.predicate.permanent.ControllerPredicate;
import mage.filter.predicate.permanent.TokenPredicate; import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID; import java.util.UUID;
@ -47,7 +51,7 @@ public final class NamelessRace extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield"))); this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("{this}'s power and toughness are each equal to the life paid as it entered the battlefield")));
} }
public NamelessRace(final NamelessRace card) { private NamelessRace(final NamelessRace card) {
super(card); super(card);
} }
@ -59,8 +63,10 @@ public final class NamelessRace extends CardImpl {
class NamelessRaceEffect extends OneShotEffect { class NamelessRaceEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("white nontoken permanents your opponents control"); private static final FilterPermanent filter
private static final FilterCard filter2 = new FilterCard("white cards in their graveyards"); = new FilterPermanent("white nontoken permanents your opponents control");
private static final FilterCard filter2
= new FilterCard("white cards in their graveyards");
static { static {
filter.add(new ColorPredicate(ObjectColor.WHITE)); filter.add(new ColorPredicate(ObjectColor.WHITE));
@ -70,12 +76,14 @@ class NamelessRaceEffect extends OneShotEffect {
filter2.add(new OwnerPredicate(TargetController.OPPONENT)); filter2.add(new OwnerPredicate(TargetController.OPPONENT));
} }
public NamelessRaceEffect() { NamelessRaceEffect() {
super(Outcome.LoseLife); super(Outcome.LoseLife);
staticText = "pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards"; staticText = "pay any amount of life. The amount you pay can't be more than " +
"the total number of white nontoken permanents your opponents control " +
"plus the total number of white cards in their graveyards";
} }
public NamelessRaceEffect(final NamelessRaceEffect effect) { private NamelessRaceEffect(final NamelessRaceEffect effect) {
super(effect); super(effect);
} }
@ -87,18 +95,25 @@ class NamelessRaceEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { Permanent permanent = game.getPermanentEntering(source.getSourceId());
int permanentsInPlay = new PermanentsOnBattlefieldCount(filter).calculate(game, source, null); if (controller == null || permanent == null) {
int cardsInGraveyards = new CardsInAllGraveyardsCount(filter2).calculate(game, source, null); return false;
int maxAmount = Math.min(permanentsInPlay + cardsInGraveyards, controller.getLife());
int payAmount = controller.getAmount(0, maxAmount, "Pay up to " + maxAmount + " life", game);
controller.loseLife(payAmount, game, false);
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getLogName() : "") + ": " + controller.getLogName() +
" pays " + payAmount + " life");
game.addEffect(new SetPowerToughnessSourceEffect(payAmount, payAmount, Duration.Custom, SubLayer.SetPT_7b), source);
return true;
} }
return false; int permanentsInPlay = new PermanentsOnBattlefieldCount(filter).calculate(game, source, null);
int cardsInGraveyards = new CardsInAllGraveyardsCount(filter2).calculate(game, source, null);
int maxAmount = Math.min(permanentsInPlay + cardsInGraveyards, controller.getLife());
int payAmount = controller.getAmount(0, maxAmount, "Pay up to " + maxAmount + " life", game);
Cost cost = new PayLifeCost(payAmount);
if (!cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) {
return false;
}
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getLogName() : "") + ": " + controller.getLogName() +
" pays " + payAmount + " life");
game.addEffect(new SetPowerToughnessSourceEffect(
payAmount, payAmount, Duration.Custom, SubLayer.CharacteristicDefining_7a
), source);
permanent.addInfo("life paid", CardUtil.addToolTipMarkTags("Life paid: " + payAmount), game);
return true;
} }
} }

View file

@ -1,18 +1,20 @@
package mage.cards.p; package mage.cards.p;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.MinionToken; import mage.game.permanent.token.MinionToken;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
@ -28,14 +30,17 @@ public final class PhyrexianProcessor extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// As {this} enters the battlefield, pay any amount of life. // As {this} enters the battlefield, pay any amount of life.
this.addAbility(new EntersBattlefieldTriggeredAbility(new PhyrexianProcessorEffect())); this.addAbility(new AsEntersBattlefieldAbility(new PhyrexianProcessorPayLifeEffect()));
// {4}, {tap}: Create an X/X black Minion creature token, where X is the life paid as {this} entered the battlefield. // {4}, {tap}: Create an X/X black Minion creature token, where X is the life paid as {this} entered the battlefield.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhyrexianProcessorCreateTokenEffect(), new ManaCostsImpl("{4}")); Ability ability = new SimpleActivatedAbility(
new PhyrexianProcessorCreateTokenEffect(), new GenericManaCost(4)
);
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability); this.addAbility(ability);
} }
public PhyrexianProcessor(final PhyrexianProcessor card) { private PhyrexianProcessor(final PhyrexianProcessor card) {
super(card); super(card);
} }
@ -45,47 +50,53 @@ public final class PhyrexianProcessor extends CardImpl {
} }
} }
class PhyrexianProcessorEffect extends OneShotEffect { class PhyrexianProcessorPayLifeEffect extends OneShotEffect {
public PhyrexianProcessorEffect() { PhyrexianProcessorPayLifeEffect() {
super(Outcome.LoseLife); super(Outcome.LoseLife);
staticText = "Pay any amount of life."; staticText = "pay any amount of life.";
} }
public PhyrexianProcessorEffect(final PhyrexianProcessorEffect effect) { private PhyrexianProcessorPayLifeEffect(final PhyrexianProcessorPayLifeEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public PhyrexianProcessorEffect copy() { public PhyrexianProcessorPayLifeEffect copy() {
return new PhyrexianProcessorEffect(this); return new PhyrexianProcessorPayLifeEffect(this);
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { Permanent permanent = game.getPermanentEntering(source.getSourceId());
int payAmount = controller.getAmount(0, controller.getLife(), staticText, game); if (controller == null || permanent == null) {
controller.loseLife(payAmount, game, false); return false;
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getName() : "") + ": " + controller.getLogName() +
" pays " + payAmount + " life.");
String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game);
game.getState().setValue(key, payAmount);
return true;
} }
return false; int payAmount = controller.getAmount(0, controller.getLife(), "Pay any amount of life", game);
Cost cost = new PayLifeCost(payAmount);
if (!cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) {
return false;
}
Card sourceCard = game.getCard(source.getSourceId());
game.informPlayers((sourceCard != null ? sourceCard.getName() : "") + ": " + controller.getLogName() +
" pays " + payAmount + " life.");
String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game);
game.getState().setValue(key, payAmount);
permanent.addInfo("life paid", CardUtil.addToolTipMarkTags("Life paid: " + payAmount), game);
return true;
} }
} }
class PhyrexianProcessorCreateTokenEffect extends OneShotEffect { class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
public PhyrexianProcessorCreateTokenEffect() { PhyrexianProcessorCreateTokenEffect() {
super(Outcome.PutCreatureInPlay); super(Outcome.PutCreatureInPlay);
staticText = "Create an X/X black Minion creature token"; staticText = "Create an X/X black Minion creature token, " +
"where X is the life paid as {this} entered the battlefield.";
} }
public PhyrexianProcessorCreateTokenEffect(PhyrexianProcessorCreateTokenEffect ability) { private PhyrexianProcessorCreateTokenEffect(PhyrexianProcessorCreateTokenEffect ability) {
super(ability); super(ability);
} }
@ -96,7 +107,7 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game); String key = CardUtil.getCardZoneString("lifePaid", source.getSourceId(), game, true);
Object object = game.getState().getValue(key); Object object = game.getState().getValue(key);
if (object instanceof Integer) { if (object instanceof Integer) {
int lifePaid = (int) object; int lifePaid = (int) object;

View file

@ -114,7 +114,7 @@ class PsychicSurgeryEffect extends OneShotEffect {
} }
} }
} }
controller.putCardsOnBottomOfLibrary(cards, game, source, true); controller.putCardsOnTopOfLibrary(cards, game, source, true);
return true; return true;
} }
return false; return false;

View file

@ -1,17 +1,21 @@
package mage.cards.r; package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.CantBeCounteredControlledEffect; import mage.abilities.effects.common.CantBeCounteredControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.common.continuous.GainAbilityControlledSpellsEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.RiotAbility; import mage.abilities.keyword.RiotAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController; import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.FilterSpell; import mage.filter.FilterSpell;
import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledCreaturePermanent;
@ -19,6 +23,15 @@ import mage.filter.common.FilterCreatureSpell;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.ControllerPredicate; import mage.filter.predicate.permanent.ControllerPredicate;
import mage.filter.predicate.permanent.TokenPredicate; import mage.filter.predicate.permanent.TokenPredicate;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/** /**
* @author TheElk801 * @author TheElk801
@ -44,8 +57,7 @@ public final class RhythmOfTheWild extends CardImpl {
))); )));
// Nontoken creatures you control have riot. // Nontoken creatures you control have riot.
Ability ability = new SimpleStaticAbility(new GainAbilityControlledSpellsEffect( Ability ability = new SimpleStaticAbility(new RhythmOfTheWildEffect());
new RiotAbility(), new FilterCreatureSpell()).setText("Nontoken creatures you control have riot. <i>(They enter the battlefield with your choice of a +1/+1 counter or haste.)</i>"));
ability.addEffect(new GainAbilityControlledEffect( ability.addEffect(new GainAbilityControlledEffect(
new RiotAbility(), Duration.WhileOnBattlefield, filter2 new RiotAbility(), Duration.WhileOnBattlefield, filter2
).setText("")); ).setText(""));
@ -61,3 +73,56 @@ public final class RhythmOfTheWild extends CardImpl {
return new RhythmOfTheWild(this); return new RhythmOfTheWild(this);
} }
} }
class RhythmOfTheWildEffect extends ReplacementEffectImpl {
RhythmOfTheWildEffect() {
super(Duration.WhileOnBattlefield, Outcome.BoostCreature);
staticText = "Nontoken creatures you control have riot. " +
"<i>(They enter the battlefield with your choice of a +1/+1 counter or haste.)</i>";
}
private RhythmOfTheWildEffect(RhythmOfTheWildEffect effect) {
super(effect);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
return creature != null
&& creature.isControlledBy(source.getControllerId())
&& creature.isCreature()
&& !(creature instanceof PermanentToken);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
Player player = game.getPlayer(source.getControllerId());
if (creature == null || player == null) {
return false;
}
if (player.chooseUse(
outcome, "Have " + creature.getLogName() + " enter the battlefield with a +1/+1 counter on it or with haste?",
null, "+1/+1 counter", "Haste", source, game
)) {
game.informPlayers(player.getLogName() + " choose to put a +1/+1 counter on " + creature.getName());
creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} else {
ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom);
effect.setTargetPointer(new FixedTarget(creature.getId(), creature.getZoneChangeCounter(game) + 1));
game.addEffect(effect, source);
}
return false;
}
@Override
public RhythmOfTheWildEffect copy() {
return new RhythmOfTheWildEffect(this);
}
}

View file

@ -1,10 +1,8 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.LookLibraryControllerEffect; import mage.abilities.effects.common.LookLibraryControllerEffect;
import mage.abilities.keyword.EntwineAbility; import mage.abilities.keyword.EntwineAbility;
@ -18,8 +16,9 @@ import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetOpponent; import mage.target.common.TargetOpponent;
import java.util.UUID;
/** /**
*
* @author TheElk801 * @author TheElk801
*/ */
public final class SecondSight extends CardImpl { public final class SecondSight extends CardImpl {
@ -32,22 +31,17 @@ public final class SecondSight extends CardImpl {
this.getSpellAbility().getModes().setMaxModes(1); this.getSpellAbility().getModes().setMaxModes(1);
//Look at the top five cards of target opponent's library, then put them back in any order; //Look at the top five cards of target opponent's library, then put them back in any order;
Effect effect = new SecondSightEffect(); this.getSpellAbility().addEffect(new SecondSightEffect());
this.getSpellAbility().addEffect(effect);
this.getSpellAbility().addTarget(new TargetOpponent()); this.getSpellAbility().addTarget(new TargetOpponent());
//or look at the top five cards of your library, then put them back in any order. //or look at the top five cards of your library, then put them back in any order.
effect = new LookLibraryControllerEffect(5); this.getSpellAbility().getModes().addMode(new Mode(new LookLibraryControllerEffect(5)));
Mode mode = new Mode();
mode.addEffect(effect);
this.getSpellAbility().getModes().addMode(mode);
// Entwine {U} // Entwine {U}
this.addAbility(new EntwineAbility("{U}")); this.addAbility(new EntwineAbility("{U}"));
} }
public SecondSight(final SecondSight card) { private SecondSight(final SecondSight card) {
super(card); super(card);
} }
@ -59,12 +53,12 @@ public final class SecondSight extends CardImpl {
class SecondSightEffect extends OneShotEffect { class SecondSightEffect extends OneShotEffect {
public SecondSightEffect() { SecondSightEffect() {
super(Outcome.DrawCard); super(Outcome.DrawCard);
this.staticText = "look at the top five cards of target opponent's library, then put them back in any order"; this.staticText = "look at the top five cards of target opponent's library, then put them back in any order";
} }
public SecondSightEffect(final SecondSightEffect effect) { private SecondSightEffect(final SecondSightEffect effect) {
super(effect); super(effect);
} }

View file

@ -0,0 +1,80 @@
package mage.cards.v;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.SourceTappedCondition;
import mage.abilities.costs.VariableCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.DamageControllerEffect;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.abilities.effects.common.DestroySourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetAnyTarget;
/**
*
* @author L_J
*/
public final class VoodooDoll extends CardImpl {
public VoodooDoll(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}");
// At the beginning of your upkeep, put a pin counter on Voodoo Doll.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.PIN.createInstance()), TargetController.YOU, false));
// At the beginning of your end step, if Voodoo Doll is untapped, destroy Voodoo Doll and it deals damage to you equal to the number of pin counters on it.
Ability ability = new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DestroySourceEffect(), TargetController.YOU,
new InvertCondition(SourceTappedCondition.instance), false);
ability.addEffect(new DamageControllerEffect(new CountersSourceCount(CounterType.PIN)));
this.addAbility(ability);
// {X}{X}, {T}: Voodoo Doll deals damage equal to the number of pin counters on it to any target. X is the number of pin counters on Voodoo Doll.
Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.PIN)), new ManaCostsImpl("{X}{X}"));
ability2.addCost(new TapSourceCost());
ability2.addTarget(new TargetAnyTarget());
for (VariableCost cost : ability2.getManaCosts().getVariableCosts()) {
if (cost instanceof VariableManaCost) {
((VariableManaCost) cost).setMaxX(0);
break;
}
}
this.addAbility(ability2);
}
@Override
public void adjustCosts(Ability ability, Game game) {
if (ability instanceof SimpleActivatedAbility) {
Permanent sourcePermanent = game.getPermanent(ability.getSourceId());
if (sourcePermanent != null) {
int pin = sourcePermanent.getCounters(game).getCount(CounterType.PIN);
ability.getManaCostsToPay().clear();
ability.getManaCostsToPay().add(0, new GenericManaCost(pin * 2));
}
}
}
public VoodooDoll(final VoodooDoll card) {
super(card);
}
@Override
public VoodooDoll copy() {
return new VoodooDoll(this);
}
}

View file

@ -54,6 +54,7 @@ public final class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Bartel Runeaxe", 222, Rarity.RARE, mage.cards.b.BartelRuneaxe.class)); cards.add(new SetCardInfo("Bartel Runeaxe", 222, Rarity.RARE, mage.cards.b.BartelRuneaxe.class));
cards.add(new SetCardInfo("Beasts of Bogardan", 133, Rarity.UNCOMMON, mage.cards.b.BeastsOfBogardan.class)); cards.add(new SetCardInfo("Beasts of Bogardan", 133, Rarity.UNCOMMON, mage.cards.b.BeastsOfBogardan.class));
cards.add(new SetCardInfo("Black Mana Battery", 274, Rarity.UNCOMMON, mage.cards.b.BlackManaBattery.class)); cards.add(new SetCardInfo("Black Mana Battery", 274, Rarity.UNCOMMON, mage.cards.b.BlackManaBattery.class));
cards.add(new SetCardInfo("Blazing Effigy", 134, Rarity.COMMON, mage.cards.b.BlazingEffigy.class));
cards.add(new SetCardInfo("Blight", 89, Rarity.UNCOMMON, mage.cards.b.Blight.class)); cards.add(new SetCardInfo("Blight", 89, Rarity.UNCOMMON, mage.cards.b.Blight.class));
cards.add(new SetCardInfo("Blood Lust", 135, Rarity.UNCOMMON, mage.cards.b.BloodLust.class)); cards.add(new SetCardInfo("Blood Lust", 135, Rarity.UNCOMMON, mage.cards.b.BloodLust.class));
cards.add(new SetCardInfo("Blue Mana Battery", 275, Rarity.UNCOMMON, mage.cards.b.BlueManaBattery.class)); cards.add(new SetCardInfo("Blue Mana Battery", 275, Rarity.UNCOMMON, mage.cards.b.BlueManaBattery.class));
@ -152,6 +153,7 @@ public final class Legends extends ExpansionSet {
cards.add(new SetCardInfo("In the Eye of Chaos", 61, Rarity.RARE, mage.cards.i.InTheEyeOfChaos.class)); cards.add(new SetCardInfo("In the Eye of Chaos", 61, Rarity.RARE, mage.cards.i.InTheEyeOfChaos.class));
cards.add(new SetCardInfo("Indestructible Aura", 21, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); cards.add(new SetCardInfo("Indestructible Aura", 21, Rarity.COMMON, mage.cards.i.IndestructibleAura.class));
cards.add(new SetCardInfo("Infernal Medusa", 108, Rarity.UNCOMMON, mage.cards.i.InfernalMedusa.class)); cards.add(new SetCardInfo("Infernal Medusa", 108, Rarity.UNCOMMON, mage.cards.i.InfernalMedusa.class));
cards.add(new SetCardInfo("Infinite Authority", 22, Rarity.RARE, mage.cards.i.InfiniteAuthority.class));
cards.add(new SetCardInfo("Invoke Prejudice", 62, Rarity.RARE, mage.cards.i.InvokePrejudice.class)); cards.add(new SetCardInfo("Invoke Prejudice", 62, Rarity.RARE, mage.cards.i.InvokePrejudice.class));
cards.add(new SetCardInfo("Ivory Guardians", 23, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); cards.add(new SetCardInfo("Ivory Guardians", 23, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class));
cards.add(new SetCardInfo("Jacques le Vert", 232, Rarity.RARE, mage.cards.j.JacquesLeVert.class)); cards.add(new SetCardInfo("Jacques le Vert", 232, Rarity.RARE, mage.cards.j.JacquesLeVert.class));
@ -299,6 +301,7 @@ public final class Legends extends ExpansionSet {
cards.add(new SetCardInfo("Vaevictis Asmadi", 269, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); cards.add(new SetCardInfo("Vaevictis Asmadi", 269, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class));
cards.add(new SetCardInfo("Vampire Bats", 125, Rarity.COMMON, mage.cards.v.VampireBats.class)); cards.add(new SetCardInfo("Vampire Bats", 125, Rarity.COMMON, mage.cards.v.VampireBats.class));
cards.add(new SetCardInfo("Visions", 41, Rarity.UNCOMMON, mage.cards.v.Visions.class)); cards.add(new SetCardInfo("Visions", 41, Rarity.UNCOMMON, mage.cards.v.Visions.class));
cards.add(new SetCardInfo("Voodoo Doll", 298, Rarity.RARE, mage.cards.v.VoodooDoll.class));
cards.add(new SetCardInfo("Walking Dead", 126, Rarity.COMMON, mage.cards.w.WalkingDead.class)); cards.add(new SetCardInfo("Walking Dead", 126, Rarity.COMMON, mage.cards.w.WalkingDead.class));
cards.add(new SetCardInfo("Wall of Caltrops", 42, Rarity.COMMON, mage.cards.w.WallOfCaltrops.class)); cards.add(new SetCardInfo("Wall of Caltrops", 42, Rarity.COMMON, mage.cards.w.WallOfCaltrops.class));
cards.add(new SetCardInfo("Wall of Dust", 168, Rarity.UNCOMMON, mage.cards.w.WallOfDust.class)); cards.add(new SetCardInfo("Wall of Dust", 168, Rarity.UNCOMMON, mage.cards.w.WallOfDust.class));

View file

@ -8,7 +8,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public class RiotTest extends CardTestPlayerBase { public class RiotTest extends CardTestPlayerBase {
@ -17,7 +16,7 @@ public class RiotTest extends CardTestPlayerBase {
* A creature with riot enters the battlefield with a +1/+1 counter on it or * A creature with riot enters the battlefield with a +1/+1 counter on it or
* with haste, its controller's choice. This choice is made as the creature * with haste, its controller's choice. This choice is made as the creature
* enters the battlefield, so no one can respond to the choice. * enters the battlefield, so no one can respond to the choice.
* * <p>
* The creature will have the chosen bonus the moment it enters the * The creature will have the chosen bonus the moment it enters the
* battlefield. If you choose to have the creature gain haste, it keeps * battlefield. If you choose to have the creature gain haste, it keeps
* haste even after the turn ends. This could matter if another player gains * haste even after the turn ends. This could matter if another player gains
@ -113,4 +112,56 @@ public class RiotTest extends CardTestPlayerBase {
assertAbility(playerA, "Silvercoat Lion", HasteAbility.getInstance(), true); assertAbility(playerA, "Silvercoat Lion", HasteAbility.getInstance(), true);
assertAbility(playerA, "Silvercoat Lion", new RiotAbility(), true); assertAbility(playerA, "Silvercoat Lion", new RiotAbility(), true);
} }
@Test
public void RiotRhythmOfTheWildNotCastBoost() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// Creature spells you control can't be countered.
// Nontoken creatures you control have riot.
addCard(Zone.BATTLEFIELD, playerA, "Rhythm of the Wild", 1);
// Riot (This creature enters the battleifled with your choice of a +1/+1 counter or haste.)
addCard(Zone.HAND, playerA, "Exhume", 1); // Each player returns a creature card from their graveyard to the battlefield
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion", 1); // Creature {1}{W} 2/2
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Exhume");
setChoice(playerA, "Yes"); // yes - counter
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPowerToughness(playerA, "Silvercoat Lion", 3, 3);
assertAbility(playerA, "Silvercoat Lion", HasteAbility.getInstance(), false);
assertAbility(playerA, "Silvercoat Lion", new RiotAbility(), true);
}
@Test
public void RiotRhythmOfTheWildNotCastHaste() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
// Creature spells you control can't be countered.
// Nontoken creatures you control have riot.
addCard(Zone.BATTLEFIELD, playerA, "Rhythm of the Wild", 1);
// Riot (This creature enters the battleifled with your choice of a +1/+1 counter or haste.)
addCard(Zone.HAND, playerA, "Exhume", 1); // Each player returns a creature card from their graveyard to the battlefield
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion", 1); // Creature {1}{W} 2/2
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Exhume");
setChoice(playerA, "No"); // no - haste
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertPowerToughness(playerA, "Silvercoat Lion", 2, 2);
assertAbility(playerA, "Silvercoat Lion", HasteAbility.getInstance(), true);
assertAbility(playerA, "Silvercoat Lion", new RiotAbility(), true);
}
} }

View file

@ -51,7 +51,7 @@ public class BuybackAbility extends StaticAbility implements OptionalAdditionalS
public BuybackAbility(Cost cost) { public BuybackAbility(Cost cost) {
super(Zone.STACK, new BuybackEffect()); super(Zone.STACK, new BuybackEffect());
this.buybackCost = new OptionalAdditionalCostImpl(keywordText, "-", reminderTextCost, cost); this.buybackCost = new OptionalAdditionalCostImpl(keywordText, "&mdash;", reminderTextCost, cost);
setRuleAtTheTop(true); setRuleAtTheTop(true);
} }

View file

@ -134,7 +134,7 @@ public class FlashbackAbility extends SpellAbility {
public String getRule() { public String getRule() {
StringBuilder sbRule = new StringBuilder("Flashback"); StringBuilder sbRule = new StringBuilder("Flashback");
if (!costs.isEmpty()) { if (!costs.isEmpty()) {
sbRule.append(" - "); sbRule.append("&mdash;");
} else { } else {
sbRule.append(' '); sbRule.append(' ');
} }

View file

@ -93,7 +93,7 @@ public class ModularAbility extends DiesTriggeredAbility {
public String getRule() { public String getRule() {
StringBuilder sb = new StringBuilder("Modular"); StringBuilder sb = new StringBuilder("Modular");
if (sunburst) { if (sunburst) {
sb.append("-Sunburst <i>(This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it. When it dies, you may put its +1/+1 counters on target artifact creature.)</i>"); sb.append("&mdash;Sunburst <i>(This enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it. When it dies, you may put its +1/+1 counters on target artifact creature.)</i>");
} else { } else {
sb.append(' ').append(amount).append(" <i>(This enters the battlefield with ") sb.append(' ').append(amount).append(" <i>(This enters the battlefield with ")
.append(CardUtil.numberToText(amount, "a")) .append(CardUtil.numberToText(amount, "a"))

View file

@ -108,7 +108,8 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost
name = ABILITY_KEYWORD; name = ABILITY_KEYWORD;
for (Cost cost : morphCosts) { for (Cost cost : morphCosts) {
if (!(cost instanceof ManaCosts)) { if (!(cost instanceof ManaCosts)) {
sb.append("- "); sb.setLength(sb.length() - 1);
sb.append("&mdash;");
break; break;
} }
} }

View file

@ -43,7 +43,7 @@ public class ReinforceAbility extends SimpleActivatedAbility {
@Override @Override
public String getRule() { public String getRule() {
StringBuilder sb = new StringBuilder("Reinforce "); StringBuilder sb = new StringBuilder("Reinforce ");
sb.append(count.toString()).append(" - "); sb.append(count.toString()).append("&mdash;");
sb.append(cost.getText()); sb.append(cost.getText());
sb.append(" <i>(").append(cost.getText()).append(", Discard this card: Put "); sb.append(" <i>(").append(cost.getText()).append(", Discard this card: Put ");
if (count.toString().equals("1")) { if (count.toString().equals("1")) {

View file

@ -71,10 +71,8 @@ class RiotReplacementEffect extends ReplacementEffectImpl {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (creature != null && controller != null) { if (creature != null && controller != null) {
if (controller.chooseUse(outcome, "Have " + creature.getLogName() + " enter the battlefield with a +1/+1 counter on it or with haste?",null, "+1/+1 counter", "Haste", source, game)) { if (controller.chooseUse(outcome, "Have " + creature.getLogName() + " enter the battlefield with a +1/+1 counter on it or with haste?", null, "+1/+1 counter", "Haste", source, game)) {
if (!game.isSimulation()) { game.informPlayers(controller.getLogName() + " choose to put a +1/+1 counter on " + creature.getName());
game.informPlayers(controller.getLogName() + " choose to put a +1/+1 counter on " + creature.getName());
}
creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects()); creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} else { } else {
game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.Custom), source); game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.Custom), source);

View file

@ -112,7 +112,7 @@ public class SpliceOntoArcaneAbility extends SimpleStaticAbility {
@Override @Override
public String getRule() { public String getRule() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(KEYWORD_TEXT).append(nonManaCosts ? "-" : " "); sb.append(KEYWORD_TEXT).append(nonManaCosts ? "&mdash;" : " ");
sb.append(spliceCosts.getText()).append(nonManaCosts ? ". " : " "); sb.append(spliceCosts.getText()).append(nonManaCosts ? ". " : " ");
sb.append("<i>(As you cast an Arcane spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell.)</i>"); sb.append("<i>(As you cast an Arcane spell, you may reveal this card from your hand and pay its splice cost. If you do, add this card's effects to that spell.)</i>");
return sb.toString(); return sb.toString();

View file

@ -140,7 +140,7 @@ public class SuspendAbility extends SpecialAction {
} }
StringBuilder sb = new StringBuilder("Suspend "); StringBuilder sb = new StringBuilder("Suspend ");
if (cost != null) { if (cost != null) {
sb.append(suspend == Integer.MAX_VALUE ? "X" : suspend).append(" - ").append(cost.getText()).append(suspend == Integer.MAX_VALUE ? ". X can't be 0" : ""); sb.append(suspend == Integer.MAX_VALUE ? "X" : suspend).append("&mdash;").append(cost.getText()).append(suspend == Integer.MAX_VALUE ? ". X can't be 0" : "");
if (!shortRule) { if (!shortRule) {
sb.append(" <i>(Rather than cast this card from your hand, pay ") sb.append(" <i>(Rather than cast this card from your hand, pay ")
.append(cost.getText()) .append(cost.getText())

View file

@ -85,6 +85,12 @@ public final class StaticFilters {
FILTER_CARD_CREATURE_YOUR_GRAVEYARD.setLockedFilter(true); FILTER_CARD_CREATURE_YOUR_GRAVEYARD.setLockedFilter(true);
} }
public static final FilterCreatureCard FILTER_CARD_CREATURES_YOUR_GRAVEYARD = new FilterCreatureCard("creature cards from your graveyard");
static {
FILTER_CARD_CREATURES_YOUR_GRAVEYARD.setLockedFilter(true);
}
public static final FilterCard FILTER_CARD_FROM_YOUR_GRAVEYARD = new FilterCard("card from your graveyard"); public static final FilterCard FILTER_CARD_FROM_YOUR_GRAVEYARD = new FilterCard("card from your graveyard");
static { static {

View file

@ -989,6 +989,7 @@ public class Spell extends StackObjImpl implements Card {
@Override @Override
public StackObject createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets) { public StackObject createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets) {
Spell copy = this.copySpell(newControllerId); Spell copy = this.copySpell(newControllerId);
game.getState().setZone(copy.getId(), Zone.STACK); // required for targeting ex: Nivmagus Elemental
game.getStack().push(copy); game.getStack().push(copy);
if (chooseNewTargets) { if (chooseNewTargets) {
copy.chooseNewTargets(game, newControllerId); copy.chooseNewTargets(game, newControllerId);