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>
<Component class="mage.client.components.ColorPane" name="txtConversation">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EmptyBorderInfo">
<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.setPreferredSize(new java.awt.Dimension(32767, 32767));
txtConversation.setEditable(false);
txtConversation.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
txtConversation.setFont(new java.awt.Font("Arial", 0, 14)); // NOI18N
txtConversation.setFocusCycleRoot(false);

View file

@ -28,6 +28,7 @@ import org.ocpsoft.prettytime.units.JustNow;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
@ -163,13 +164,33 @@ public class TablesPanel extends javax.swing.JPanel {
}
};
// center text render
TableCellRenderer centerCellRenderer = new DefaultTableCellRenderer() {
// seats render
TableCellRenderer seatsCellRenderer = new DefaultTableCellRenderer() {
JLabel greenLabel = new JLabel();
@Override
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);
label.setHorizontalAlignment(JLabel.CENTER);
return label;
JLabel defaultLabel = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
defaultLabel.setHorizontalAlignment(JLabel.CENTER);
// 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
tableTables.getColumnModel().getColumn(TablesTableModel.COLUMN_SKILL).setCellRenderer(skillCellRenderer);
// 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)
activeTablesSorter.setComparator(TablesTableModel.COLUMN_CREATED, new Comparator<Date>() {
@ -626,16 +647,21 @@ public class TablesPanel extends javax.swing.JPanel {
// reload server messages
java.util.List<String> serverMessages = SessionHandler.getServerMessages();
synchronized (this) {
this.messages = serverMessages;
if (serverMessages != null) {
this.messages = serverMessages;
} else {
this.messages = new ArrayList<>();
}
this.currentMessage = 0;
}
if (serverMessages.isEmpty()) {
if (this.messages.isEmpty()) {
this.jPanelBottom.setVisible(false);
} else {
this.jPanelBottom.setVisible(true);
URLHandler.RemoveMouseAdapter(jLabelFooterText);
URLHandler.handleMessage(serverMessages.get(0), this.jLabelFooterText);
this.jButtonFooterNext.setVisible(serverMessages.size() > 1);
URLHandler.handleMessage(this.messages.get(0), this.jLabelFooterText);
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);
}
}
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;
}
@ -516,6 +539,8 @@ public final class SystemUtil {
game.getExile().getPermanentExile().remove(card);
player.getLibrary().putOnTop(card, game);
break;
case STACK:
card.cast(game, Zone.EXILED, card.getSpellAbility(), player.getId());
default:
card.moveToZone(zone, null, game, false);
}

View file

@ -1,11 +1,11 @@
package mage.cards.a;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
import mage.abilities.costs.common.ExileSourceCost;
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.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -16,27 +16,32 @@ import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
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 {
filter.add(Predicates.or(
new CardTypePredicate(CardType.ARTIFACT),
new CardTypePredicate(CardType.CREATURE),
new CardTypePredicate(CardType.ENCHANTMENT)));
new CardTypePredicate(CardType.LAND)
));
}
public AmuletOfUnmaking(UUID ownerId, CardSetInfo setInfo) {
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.
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 ExileSourceCost());
ability.addTarget(new TargetPermanent(filter));
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;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.RemoveAllCountersSourceEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.cards.CardImpl;
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.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class BloodHound extends CardImpl {
@ -33,10 +34,12 @@ public final class BloodHound extends CardImpl {
this.addAbility(new BloodHoundTriggeredAbility());
// 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);
}
@ -48,11 +51,11 @@ public final class BloodHound extends CardImpl {
class BloodHoundTriggeredAbility extends TriggeredAbilityImpl {
public BloodHoundTriggeredAbility() {
super(Zone.BATTLEFIELD, new BloodHoundEffect(), true);
BloodHoundTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), true);
}
public BloodHoundTriggeredAbility(final BloodHoundTriggeredAbility ability) {
private BloodHoundTriggeredAbility(final BloodHoundTriggeredAbility ability) {
super(ability);
}
@ -68,8 +71,9 @@ class BloodHoundTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getTargetId().equals(this.getControllerId())) {
this.getEffects().get(0).setValue("damageAmount", event.getAmount());
if (event.getTargetId().equals(this.getControllerId()) && event.getAmount() > 0) {
this.getEffects().clear();
this.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(event.getAmount())));
return true;
}
return false;
@ -77,31 +81,6 @@ class BloodHoundTriggeredAbility extends TriggeredAbilityImpl {
@Override
public String getRule() {
return "Whenever you are 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;
return "Whenever you're dealt damage, you may put that many +1/+1 counters on {this}.";
}
}

View file

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

View file

@ -1,7 +1,6 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -12,12 +11,12 @@ import mage.abilities.keyword.ShroudAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.constants.SubType;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class CephalidInkshrouder extends CardImpl {
@ -30,12 +29,17 @@ public final class CephalidInkshrouder extends CardImpl {
this.toughness = new MageInt(1);
// 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.addEffect(new CantBeBlockedSourceEffect(Duration.EndOfTurn));
Ability ability = new SimpleActivatedAbility(
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);
}
public CephalidInkshrouder(final CephalidInkshrouder card) {
private CephalidInkshrouder(final CephalidInkshrouder card) {
super(card);
}

View file

@ -1,21 +1,20 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.FirstStrikeAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.filter.common.FilterAttackingCreature;
import mage.constants.SubType;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class ChieftainEnDal extends CardImpl {
@ -29,11 +28,12 @@ public final class ChieftainEnDal extends CardImpl {
this.toughness = new MageInt(2);
// 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(ability);
this.addAbility(new AttacksTriggeredAbility(new GainAbilityAllEffect(
FirstStrikeAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_ATTACKING_CREATURES
), false));
}
public ChieftainEnDal(final ChieftainEnDal card) {
private ChieftainEnDal(final ChieftainEnDal card) {
super(card);
}

View file

@ -1,7 +1,6 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.costs.common.ExileXFromYourGraveCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.GetXValue;
@ -11,28 +10,30 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.filter.common.FilterCreatureCard;
import mage.filter.StaticFilters;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class ChillHaunting extends CardImpl {
private static final DynamicValue xval = new SignInversionDynamicValue(GetXValue.instance);
public ChillHaunting(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}");
// 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.
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
DynamicValue xval = new SignInversionDynamicValue(GetXValue.instance);
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);
}

View file

@ -1,9 +1,7 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.CompoundCondition;
import mage.abilities.condition.Condition;
@ -22,18 +20,28 @@ import mage.filter.common.FilterControlledPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
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 {
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) {
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);
// 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));
Ability ability = new ActivateIfConditionActivatedAbility(Zone.GRAVEYARD,
this.addAbility(new ActivateIfConditionActivatedAbility(
Zone.GRAVEYARD,
new ReturnSourceFromGraveyardToBattlefieldEffect(),
new SacrificeTargetCost(new TargetControlledPermanent(2, 2, new FilterControlledLandPermanent("two lands"), true)),
condition);
this.addAbility(ability);
new SacrificeTargetCost(
new TargetControlledPermanent(2, 2, filter2, true)
), condition
));
}
public CoffinPuppets(final CoffinPuppets card) {

View file

@ -1,9 +1,9 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.effects.common.continuous.SetPowerSourceEffect;
import mage.cards.CardImpl;
@ -13,19 +13,17 @@ import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class CoilingWoodworm extends CardImpl {
final static FilterPermanent filterLands = new FilterPermanent("Forests you control");
static {
filterLands.add(new SubtypePredicate(SubType.FOREST));
}
private static final DynamicValue count = new PermanentsOnBattlefieldCount(
new FilterPermanent(SubType.FOREST, "Forests on the battlefield")
);
public CoilingWoodworm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");
@ -36,10 +34,10 @@ public final class CoilingWoodworm extends CardImpl {
this.toughness = new MageInt(1);
// 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);
}

View file

@ -1,7 +1,6 @@
package mage.cards.c;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
@ -12,15 +11,15 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
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}");
// 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),
new AllColorCondition(),
"nonartifact creatures get +2/+2 as long as they all share a color.")));
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
new BoostAllEffect(2, 2, Duration.WhileOnBattlefield, filter, false),
AllColorCondition.instance,
"nonartifact creatures get +2/+2 as long as they all share a color.")
));
}
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
public boolean apply(Game game, Ability source) {
@ -58,7 +60,7 @@ class AllColorCondition implements Condition {
filter.add(Predicates.not(new CardTypePredicate(CardType.ARTIFACT)));
ObjectColor allColor = new ObjectColor("WUBRG");
for (Permanent thing : game.getBattlefield().getAllActivePermanents(filter, game)) {
allColor = allColor.intersection(thing.getColor(game));
allColor = allColor.intersection(thing.getColor(game));
}
return !allColor.isColorless();
}

View file

@ -1,27 +1,31 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbility;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.ComparisonType;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.filter.common.FilterControlledPermanent;
import mage.filter.StaticFilters;
import java.util.UUID;
/**
*
* @author TheElk801
*/
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) {
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);
// 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(ability, new PermanentsOnTheBattlefieldCondition(new FilterControlledPermanent(), ComparisonType.MORE_THAN, 6),
"At the beginning of your upkeep, if you control seven or more permanents, return Complex Automaton to its owner's hand."));
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new BeginningOfUpkeepTriggeredAbility(
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);
}

View file

@ -1,7 +1,6 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -14,28 +13,29 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.predicate.permanent.TappedPredicate;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class CrookclawElder extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Bird you control");
private static final FilterControlledCreaturePermanent filter2 = new FilterControlledCreaturePermanent("untapped Wizards you control");
private static final FilterControlledCreaturePermanent filter
= 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 {
filter.add(new SubtypePredicate(SubType.BIRD));
filter.add(Predicates.not(TappedPredicate.instance));
filter2.add(new SubtypePredicate(SubType.WIZARD));
filter2.add(Predicates.not(TappedPredicate.instance));
filter.add(pred);
filter2.add(pred);
}
public CrookclawElder(UUID ownerId, CardSetInfo setInfo) {
@ -50,16 +50,26 @@ public final class CrookclawElder extends CardImpl {
this.addAbility(FlyingAbility.getInstance());
// 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);
// 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());
this.addAbility(ability);
}
public CrookclawElder(final CrookclawElder card) {
private CrookclawElder(final CrookclawElder card) {
super(card);
}

View file

@ -1,7 +1,7 @@
package mage.cards.d;
import java.util.UUID;
import mage.abilities.condition.Condition;
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
import mage.abilities.costs.AlternativeCostSourceAbility;
import mage.abilities.costs.common.SacrificeTargetCost;
@ -11,30 +11,30 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
import mage.filter.common.FilterLandPermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.filter.FilterPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import java.util.UUID;
import static mage.filter.StaticFilters.FILTER_CONTROLLED_CREATURE_SHORT_TEXT;
/**
*
* @author TheElk801
*/
public final class DarkTriumph extends CardImpl {
private static final FilterLandPermanent filterSwamp = new FilterLandPermanent("If you control a Swamp");
static {
filterSwamp.add(new SubtypePredicate(SubType.SWAMP));
}
private static final Condition condition = new PermanentsOnTheBattlefieldCondition(
new FilterPermanent(SubType.SWAMP, "If you control a Swamp")
);
public DarkTriumph(UUID ownerId, CardSetInfo setInfo) {
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.
this.addAbility(new AlternativeCostSourceAbility(
new SacrificeTargetCost(new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT)),
new PermanentsOnTheBattlefieldCondition(filterSwamp), null
new SacrificeTargetCost(
new TargetControlledCreaturePermanent(FILTER_CONTROLLED_CREATURE_SHORT_TEXT)
), condition
));
// Creatures you control get +2/+0 until end of turn.

View file

@ -1,4 +1,3 @@
package mage.cards.d;
import java.util.UUID;
@ -21,13 +20,10 @@ import mage.players.Player;
*
* @author LevelX2
*/
public final class DeadbridgeChant extends CardImpl {
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.
this.addAbility(new EntersBattlefieldTriggeredAbility(new PutTopCardOfLibraryIntoGraveControllerEffect(10)));
@ -64,9 +60,10 @@ class DeadbridgeChantEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null && !player.getGraveyard().isEmpty()) {
Card card = player.getGraveyard().getRandom(game);
Player controller = game.getPlayer(source.getControllerId());
if (controller != null
&& !controller.getGraveyard().isEmpty()) {
Card card = controller.getGraveyard().getRandom(game);
if (card != null) {
Zone targetZone = Zone.HAND;
String text = " put into hand of ";
@ -74,8 +71,8 @@ class DeadbridgeChantEffect extends OneShotEffect {
targetZone = Zone.BATTLEFIELD;
text = " put onto battlefield for ";
}
card.moveToZone(targetZone, source.getSourceId(), game, false);
game.informPlayers("Deadbridge Chant: " + card.getName() + text + player.getLogName());
controller.moveCards(card, targetZone, source, game);
game.informPlayers("Deadbridge Chant: " + card.getName() + text + controller.getLogName());
return true;
}
}

View file

@ -1,7 +1,6 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.ObjectColor;
import mage.abilities.costs.AlternativeCostSourceAbility;
@ -15,13 +14,15 @@ import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.target.common.TargetControlledPermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
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 {
filter.add(new ColorPredicate(ObjectColor.BLACK));
@ -34,15 +35,16 @@ public final class Delraich extends CardImpl {
this.power = 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
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);
}

View file

@ -1,23 +1,23 @@
package mage.cards.d;
import java.util.UUID;
import mage.target.common.TargetCreaturePermanent;
import mage.abilities.Ability;
import mage.abilities.common.DealsDamageToAPlayerAttachedTriggeredAbility;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.SacrificeEffect;
import mage.constants.Outcome;
import mage.target.TargetPermanent;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
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
*/
public final class DestructiveUrge extends CardImpl {
@ -35,8 +35,10 @@ public final class DestructiveUrge extends CardImpl {
this.addAbility(ability);
// 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(ability);
this.addAbility(new DealsDamageToAPlayerAttachedTriggeredAbility(
new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "that player"),
"enchanted", false, true
));
}
public DestructiveUrge(final DestructiveUrge card) {

View file

@ -1,7 +1,6 @@
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
@ -10,13 +9,14 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import java.util.UUID;
/**
*
* @author TheElk801
*/
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));
}
public DivineCongregation(final DivineCongregation card) {
private DivineCongregation(final DivineCongregation card) {
super(card);
}
@ -44,12 +44,12 @@ public final class DivineCongregation extends CardImpl {
class DivineCongregationEffect extends OneShotEffect {
public DivineCongregationEffect() {
DivineCongregationEffect() {
super(Outcome.Benefit);
staticText = "You gain 2 life for each creature target player controls";
}
public DivineCongregationEffect(final DivineCongregationEffect effect) {
private DivineCongregationEffect(final DivineCongregationEffect effect) {
super(effect);
}
@ -63,7 +63,7 @@ class DivineCongregationEffect extends OneShotEffect {
Player controller = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(source.getFirstTarget());
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);
}
return true;

View file

@ -1,8 +1,6 @@
package mage.cards.e;
import java.util.Iterator;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.condition.InvertCondition;
import mage.abilities.condition.common.CardsInControllerGraveCondition;
@ -18,8 +16,10 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPlayer;
import java.util.Iterator;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class Epicenter extends CardImpl {
@ -31,12 +31,15 @@ public final class Epicenter extends CardImpl {
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new SacrificeEffect(StaticFilters.FILTER_LAND, 1, "Target player"),
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.
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
new EpicenterEffect(),
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());
}
@ -55,10 +58,9 @@ class EpicenterEffect extends OneShotEffect {
EpicenterEffect() {
super(Outcome.DestroyPermanent);
staticText = "Each player sacrifices all lands he or she controls";
}
EpicenterEffect(final EpicenterEffect effect) {
private EpicenterEffect(final EpicenterEffect effect) {
super(effect);
}

View file

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

View file

@ -1,7 +1,6 @@
package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.common.SpellCastOpponentTriggeredAbility;
import mage.abilities.effects.common.CreateTokenEffect;
@ -11,22 +10,21 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.FilterSpell;
import mage.filter.common.FilterArtifactCard;
import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.common.FilterArtifactSpell;
import mage.game.permanent.token.InsectToken;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class InfestedRoothold extends CardImpl {
private final static FilterSpell filter = new FilterSpell("an artifact spell");
static {
filter.add(new CardTypePredicate(CardType.ARTIFACT));
}
private static final FilterCard filter = new FilterArtifactCard("artifacts");
private static final FilterSpell filter2 = new FilterArtifactSpell("an artifact spell");
public InfestedRoothold(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}");
@ -39,10 +37,12 @@ public final class InfestedRoothold extends CardImpl {
this.addAbility(DefenderAbility.getInstance());
// 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.
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;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
@ -40,13 +37,17 @@ public final class IntetTheDreamer extends CardImpl {
// Flying
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.
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
new DoIfCostPaid(new IntetTheDreamerExileEffect(), new ManaCostsImpl("{2}{U}")), false, true));
// You may look at that card for as long as it remains exiled.
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.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new IntetTheDreamerCastEffect()));
}
public IntetTheDreamer(final IntetTheDreamer card) {
@ -76,17 +77,20 @@ class IntetTheDreamerExileEffect extends OneShotEffect {
if (controller != null) {
Card card = controller.getLibrary().getFromTop(game);
MageObject sourceObject = source.getSourceObject(game);
if (card != null && sourceObject != null) {
UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
if (card != null
&& sourceObject != null) {
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);
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(IntetTheDreamer.VALUE_PREFIX + source.getSourceId().toString());
if (exileZones == null) {
exileZones = new HashSet<>();
game.getState().setValue(IntetTheDreamer.VALUE_PREFIX + source.getSourceId().toString(), exileZones);
}
exileZones.add(exileZoneId);
game.getState().setValue("Exiled_IntetTheDreamer" + card.getId(), Boolean.TRUE);
return true;
}
}
@ -122,20 +126,29 @@ class IntetTheDreamerCastEffect extends AsThoughEffectImpl {
@Override
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());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
if (controller != null
&& sourceObject != null) {
Card card = game.getCard(objectId);
if (card != null && card.isFaceDown(game)) {
ExileZone zone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()));
if (zone != null && zone.contains(card.getId())/* && CardUtil.cardCanBePlayedNow(card, controller.getId(), game)*/) {
if (card != null
&& card.isFaceDown(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 (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);
}
} else {
controller.setCastSourceIdWithAlternateMana(objectId, null, card.getSpellAbility().getCosts());
controller.setCastSourceIdWithAlternateMana(objectId,
null,
card.getSpellAbility().getCosts());
return true;
}
}
@ -170,24 +183,14 @@ class IntetTheDreamerLookEffect extends AsThoughEffectImpl {
@Override
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());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
if (controller != null) {
Card card = game.getCard(objectId);
if (card != null && card.isFaceDown(game)) {
Set<UUID> exileZones = (Set<UUID>) game.getState().getValue(IntetTheDreamer.VALUE_PREFIX + source.getSourceId().toString());
if (exileZones != null) {
for (ExileZone exileZone : game.getExile().getExileZones()) {
if (exileZone.contains(objectId)) {
if (!exileZones.contains(exileZone.getId())) {
return false;
}
}
}
return true;
}
}
return (card != null
&& card.isFaceDown(game)
&& game.getExile().containsId(card.getId(), game)
&& (Boolean) game.getState().getValue("Exiled_IntetTheDreamer" + card.getId()));
}
}
return false;

View file

@ -19,6 +19,7 @@ import mage.game.stack.StackObject;
import mage.players.Player;
import mage.target.TargetSpell;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
@ -81,7 +82,8 @@ class KheruSpellsnatcherEffect extends OneShotEffect {
if (!stackObject.isCopy()) {
MageObject card = game.getObject(stackObject.getSourceId());
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();
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);

View file

@ -1,37 +1,30 @@
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
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.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.target.TargetPermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class KnightOfTheMists extends CardImpl {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Knight");
static {
filter.add(new SubtypePredicate(SubType.KNIGHT));
}
private static final FilterPermanent filter = new FilterCreaturePermanent(SubType.KNIGHT, "Knight");
public KnightOfTheMists(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
@ -45,12 +38,14 @@ public final class KnightOfTheMists extends CardImpl {
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.
Ability ability = new EntersBattlefieldTriggeredAbility(new KnightOfTheMistsEffect());
ability.addTarget(new TargetCreaturePermanent(filter));
Ability ability = new EntersBattlefieldTriggeredAbility(new DoIfCostPaid(
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);
}
public KnightOfTheMists(final KnightOfTheMists card) {
private KnightOfTheMists(final KnightOfTheMists card) {
super(card);
}
@ -59,35 +54,3 @@ public final class KnightOfTheMists extends CardImpl {
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;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
@ -10,7 +9,10 @@ import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect;
import mage.cards.CardImpl;
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.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
@ -19,14 +21,15 @@ import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class MasterBiomancer extends CardImpl {
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.WIZARD);
@ -34,10 +37,10 @@ public final class MasterBiomancer extends CardImpl {
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.
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);
}
@ -49,12 +52,12 @@ public final class MasterBiomancer extends CardImpl {
class MasterBiomancerEntersBattlefieldEffect extends ReplacementEffectImpl {
public MasterBiomancerEntersBattlefieldEffect() {
MasterBiomancerEntersBattlefieldEffect() {
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);
}

View file

@ -4,6 +4,8 @@ import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
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.common.InfoEffect;
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
@ -13,7 +15,9 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
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")));
}
public MinionOfTheWastes(final MinionOfTheWastes card) {
private MinionOfTheWastes(final MinionOfTheWastes card) {
super(card);
}
@ -50,12 +54,12 @@ public final class MinionOfTheWastes extends CardImpl {
class MinionOfTheWastesEffect extends OneShotEffect {
public MinionOfTheWastesEffect() {
MinionOfTheWastesEffect() {
super(Outcome.LoseLife);
staticText = "pay any amount of life";
}
public MinionOfTheWastesEffect(final MinionOfTheWastesEffect effect) {
private MinionOfTheWastesEffect(final MinionOfTheWastesEffect effect) {
super(effect);
}
@ -67,15 +71,22 @@ class MinionOfTheWastesEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int payAmount = controller.getAmount(0, controller.getLife(), "Pay any amount of 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;
Permanent permanent = game.getPermanentEntering(source.getSourceId());
if (controller == null || permanent == null) {
return false;
}
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;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
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.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.mageobject.ChosenSubtypePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.targetpointer.FixedTarget;
import mage.util.functions.EmptyApplyToPermanent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class MirrorOfTheForebears extends CardImpl {
private static final FilterPermanent filter = new FilterControlledCreaturePermanent();
static {
filter.add(new ChosenSubtypePredicate());
}
public MirrorOfTheForebears(UUID ownerId, CardSetInfo setInfo) {
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)));
// 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();
filter.add(new ChosenSubtypePredicate());
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MirrorOfTheForebearsCopyEffect(), new ManaCostsImpl("{1}"));
Ability ability = new SimpleActivatedAbility(new MirrorOfTheForebearsCopyEffect(), new GenericManaCost(1));
ability.addTarget(new TargetPermanent(filter));
this.addAbility(ability);
}
public MirrorOfTheForebears(final MirrorOfTheForebears card) {
private MirrorOfTheForebears(final MirrorOfTheForebears card) {
super(card);
}
@ -56,12 +58,12 @@ public final class MirrorOfTheForebears extends CardImpl {
class MirrorOfTheForebearsCopyEffect extends OneShotEffect {
public MirrorOfTheForebearsCopyEffect() {
MirrorOfTheForebearsCopyEffect() {
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";
}
public MirrorOfTheForebearsCopyEffect(final MirrorOfTheForebearsCopyEffect effect) {
private MirrorOfTheForebearsCopyEffect(final MirrorOfTheForebearsCopyEffect effect) {
super(effect);
}
@ -76,11 +78,7 @@ class MirrorOfTheForebearsCopyEffect extends OneShotEffect {
Permanent copyFromPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (sourcePermanent != null && copyFromPermanent != null) {
game.copyPermanent(Duration.EndOfTurn, copyFromPermanent, sourcePermanent.getId(), source, new EmptyApplyToPermanent());
if (!copyFromPermanent.isArtifact()) {
ContinuousEffect effect = new AddCardTypeTargetEffect(Duration.EndOfTurn, CardType.ARTIFACT);
effect.setTargetPointer(new FixedTarget(sourcePermanent, game));
game.addEffect(effect, source);
}
game.addEffect(new AddCardTypeSourceEffect(Duration.EndOfTurn, CardType.ARTIFACT), source);
return true;
}
return false;

View file

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

View file

@ -5,6 +5,8 @@ import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility;
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.PermanentsOnBattlefieldCount;
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.TokenPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
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")));
}
public NamelessRace(final NamelessRace card) {
private NamelessRace(final NamelessRace card) {
super(card);
}
@ -59,8 +63,10 @@ public final class NamelessRace extends CardImpl {
class NamelessRaceEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterPermanent("white nontoken permanents your opponents control");
private static final FilterCard filter2 = new FilterCard("white cards in their graveyards");
private static final FilterPermanent filter
= new FilterPermanent("white nontoken permanents your opponents control");
private static final FilterCard filter2
= new FilterCard("white cards in their graveyards");
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
@ -70,12 +76,14 @@ class NamelessRaceEffect extends OneShotEffect {
filter2.add(new OwnerPredicate(TargetController.OPPONENT));
}
public NamelessRaceEffect() {
NamelessRaceEffect() {
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);
}
@ -87,18 +95,25 @@ class NamelessRaceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
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);
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;
Permanent permanent = game.getPermanentEntering(source.getSourceId());
if (controller == null || permanent == null) {
return false;
}
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;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.AsEntersBattlefieldAbility;
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.mana.ManaCostsImpl;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.MinionToken;
import mage.players.Player;
import mage.util.CardUtil;
@ -28,14 +30,17 @@ public final class PhyrexianProcessor extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}");
// 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.
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhyrexianProcessorCreateTokenEffect(), new ManaCostsImpl("{4}"));
Ability ability = new SimpleActivatedAbility(
new PhyrexianProcessorCreateTokenEffect(), new GenericManaCost(4)
);
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
public PhyrexianProcessor(final PhyrexianProcessor card) {
private PhyrexianProcessor(final PhyrexianProcessor 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);
staticText = "Pay any amount of life.";
staticText = "pay any amount of life.";
}
public PhyrexianProcessorEffect(final PhyrexianProcessorEffect effect) {
private PhyrexianProcessorPayLifeEffect(final PhyrexianProcessorPayLifeEffect effect) {
super(effect);
}
@Override
public PhyrexianProcessorEffect copy() {
return new PhyrexianProcessorEffect(this);
public PhyrexianProcessorPayLifeEffect copy() {
return new PhyrexianProcessorPayLifeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
int payAmount = controller.getAmount(0, controller.getLife(), staticText, game);
controller.loseLife(payAmount, game, 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;
Permanent permanent = game.getPermanentEntering(source.getSourceId());
if (controller == null || permanent == null) {
return false;
}
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 {
public PhyrexianProcessorCreateTokenEffect() {
PhyrexianProcessorCreateTokenEffect() {
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);
}
@ -96,7 +107,7 @@ class PhyrexianProcessorCreateTokenEffect extends OneShotEffect {
@Override
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);
if (object instanceof Integer) {
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 false;

View file

@ -1,17 +1,21 @@
package mage.cards.r;
import java.util.UUID;
import mage.abilities.Ability;
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.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.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.filter.FilterSpell;
import mage.filter.common.FilterControlledCreaturePermanent;
@ -19,6 +23,15 @@ import mage.filter.common.FilterCreatureSpell;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.permanent.ControllerPredicate;
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
@ -44,8 +57,7 @@ public final class RhythmOfTheWild extends CardImpl {
)));
// Nontoken creatures you control have riot.
Ability ability = new SimpleStaticAbility(new GainAbilityControlledSpellsEffect(
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 ability = new SimpleStaticAbility(new RhythmOfTheWildEffect());
ability.addEffect(new GainAbilityControlledEffect(
new RiotAbility(), Duration.WhileOnBattlefield, filter2
).setText(""));
@ -61,3 +73,56 @@ public final class RhythmOfTheWild extends CardImpl {
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;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.LookLibraryControllerEffect;
import mage.abilities.keyword.EntwineAbility;
@ -18,8 +16,9 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
import java.util.UUID;
/**
*
* @author TheElk801
*/
public final class SecondSight extends CardImpl {
@ -32,22 +31,17 @@ public final class SecondSight extends CardImpl {
this.getSpellAbility().getModes().setMaxModes(1);
//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(effect);
this.getSpellAbility().addEffect(new SecondSightEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
//or look at the top five cards of your library, then put them back in any order.
effect = new LookLibraryControllerEffect(5);
Mode mode = new Mode();
mode.addEffect(effect);
this.getSpellAbility().getModes().addMode(mode);
this.getSpellAbility().getModes().addMode(new Mode(new LookLibraryControllerEffect(5)));
// Entwine {U}
this.addAbility(new EntwineAbility("{U}"));
}
public SecondSight(final SecondSight card) {
private SecondSight(final SecondSight card) {
super(card);
}
@ -59,12 +53,12 @@ public final class SecondSight extends CardImpl {
class SecondSightEffect extends OneShotEffect {
public SecondSightEffect() {
SecondSightEffect() {
super(Outcome.DrawCard);
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);
}

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("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("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("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));
@ -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("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("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("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));
@ -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("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("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("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));

View file

@ -8,7 +8,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
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
* with haste, its controller's choice. This choice is made as the creature
* enters the battlefield, so no one can respond to the choice.
*
* <p>
* The creature will have the chosen bonus the moment it enters the
* 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
@ -113,4 +112,56 @@ public class RiotTest extends CardTestPlayerBase {
assertAbility(playerA, "Silvercoat Lion", HasteAbility.getInstance(), 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) {
super(Zone.STACK, new BuybackEffect());
this.buybackCost = new OptionalAdditionalCostImpl(keywordText, "-", reminderTextCost, cost);
this.buybackCost = new OptionalAdditionalCostImpl(keywordText, "&mdash;", reminderTextCost, cost);
setRuleAtTheTop(true);
}

View file

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

View file

@ -93,7 +93,7 @@ public class ModularAbility extends DiesTriggeredAbility {
public String getRule() {
StringBuilder sb = new StringBuilder("Modular");
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 {
sb.append(' ').append(amount).append(" <i>(This enters the battlefield with ")
.append(CardUtil.numberToText(amount, "a"))

View file

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

View file

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

View file

@ -71,10 +71,8 @@ class RiotReplacementEffect extends ReplacementEffectImpl {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
Player controller = game.getPlayer(source.getControllerId());
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 (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + " choose to put a +1/+1 counter on " + creature.getName());
}
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)) {
game.informPlayers(controller.getLogName() + " choose to put a +1/+1 counter on " + creature.getName());
creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} else {
game.addEffect(new GainAbilitySourceEffect(HasteAbility.getInstance(), Duration.Custom), source);

View file

@ -112,7 +112,7 @@ public class SpliceOntoArcaneAbility extends SimpleStaticAbility {
@Override
public String getRule() {
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("<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();

View file

@ -140,7 +140,7 @@ public class SuspendAbility extends SpecialAction {
}
StringBuilder sb = new StringBuilder("Suspend ");
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) {
sb.append(" <i>(Rather than cast this card from your hand, pay ")
.append(cost.getText())

View file

@ -85,6 +85,12 @@ public final class StaticFilters {
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");
static {

View file

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