mirror of
https://github.com/magefree/mage.git
synced 2026-01-19 01:39:58 -08:00
Merge branch 'master' into refactor/multiple-names
This commit is contained in:
commit
d18bd25d21
190 changed files with 4573 additions and 812 deletions
|
|
@ -8,10 +8,12 @@ import mage.client.cards.BigCard;
|
|||
import mage.client.cards.VirtualCardInfo;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.client.game.GamePanel;
|
||||
import mage.game.command.Dungeon;
|
||||
import mage.game.command.Plane;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.GameLog;
|
||||
import mage.view.CardView;
|
||||
import mage.view.DungeonView;
|
||||
import mage.view.PlaneView;
|
||||
|
||||
import javax.swing.*;
|
||||
|
|
@ -156,7 +158,7 @@ public class MageEditorPane extends JEditorPane {
|
|||
// show real object by priority (workable card hints and actual info)
|
||||
CardView cardView = needCard;
|
||||
|
||||
// if no game object found then show default card
|
||||
// if no game object found then show default card/object
|
||||
if (cardView == null) {
|
||||
CardInfo card = CardRepository.instance.findCards(cardName).stream().findFirst().orElse(null);
|
||||
if (card != null) {
|
||||
|
|
@ -172,6 +174,14 @@ public class MageEditorPane extends JEditorPane {
|
|||
}
|
||||
}
|
||||
|
||||
// dungeon
|
||||
if (cardView == null) {
|
||||
Dungeon dungeon = Dungeon.createDungeon(cardName, false);
|
||||
if (dungeon != null) {
|
||||
cardView = new CardView(new DungeonView(dungeon));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add other objects like dungeon, emblem, commander
|
||||
|
||||
if (cardView != null) {
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ public class PickChoiceDialog extends MageDialog {
|
|||
cardInfo.init(item.getHint(), this.bigCard, this.gameId);
|
||||
} else if (item.getHintType() == ChoiceHintType.CARD_DUNGEON) {
|
||||
// as card name
|
||||
CardView cardView = new CardView(new DungeonView(Dungeon.createDungeon(item.getHint())));
|
||||
CardView cardView = new CardView(new DungeonView(Dungeon.createDungeon(item.getHint(), true)));
|
||||
cardInfo.init(cardView, this.bigCard, this.gameId);
|
||||
} else if (item.getHintType() == ChoiceHintType.GAME_OBJECT) {
|
||||
// as object
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ import mage.counters.Counter;
|
|||
import mage.counters.CounterType;
|
||||
import mage.designations.CitysBlessing;
|
||||
import mage.designations.Monarch;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameException;
|
||||
import mage.game.GameImpl;
|
||||
import mage.game.*;
|
||||
import mage.game.command.Dungeon;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.command.Plane;
|
||||
|
|
@ -270,8 +268,8 @@ public class TestCardRenderDialog extends MageDialog {
|
|||
|
||||
// prepare fake game and players without real match
|
||||
// it's a workaround with minimum code and data init
|
||||
this.match = new TestMatch();
|
||||
this.game = new TestGame(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, MulliganType.GAME_DEFAULT.getMulligan(0), 20, 7);
|
||||
this.match = new FakeMatch();
|
||||
this.game = new FakeGame();
|
||||
Deck deck = new Deck();
|
||||
Player playerYou = new StubPlayer("player1", RangeOfInfluence.ALL);
|
||||
playerYou.addDesignation(new CitysBlessing());
|
||||
|
|
@ -977,68 +975,4 @@ public class TestCardRenderDialog extends MageDialog {
|
|||
private javax.swing.JSpinner spinnerCardIconsAdditionalAmount;
|
||||
private javax.swing.JSpinner spinnerCardIconsMaxVisible;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
||||
class TestGame extends GameImpl {
|
||||
|
||||
private int numPlayers;
|
||||
|
||||
public TestGame(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife, int startHandSize) {
|
||||
super(attackOption, range, mulligan, 60, startLife, startHandSize);
|
||||
}
|
||||
|
||||
public TestGame(final TestGame game) {
|
||||
super(game);
|
||||
this.numPlayers = game.numPlayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MatchType getGameType() {
|
||||
return new TestGameType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumPlayers() {
|
||||
return numPlayers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestGame copy() {
|
||||
return new TestGame(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TestGameType extends MatchType {
|
||||
|
||||
public TestGameType() {
|
||||
this.name = "Test Game Type";
|
||||
this.maxPlayers = 10;
|
||||
this.minPlayers = 3;
|
||||
this.numTeams = 0;
|
||||
this.useAttackOption = true;
|
||||
this.useRange = true;
|
||||
this.sideboardingAllowed = true;
|
||||
}
|
||||
|
||||
protected TestGameType(final TestGameType matchType) {
|
||||
super(matchType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestGameType copy() {
|
||||
return new TestGameType(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TestMatch extends MatchImpl {
|
||||
|
||||
public TestMatch() {
|
||||
super(new MatchOptions("fake match", "fake game type", true, 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startGame() throws GameException {
|
||||
throw new IllegalStateException("Can't start fake match");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package mage.client.game;
|
|||
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.SessionHandler;
|
||||
import mage.client.cards.BigCard;
|
||||
import mage.client.chat.ChatPanelBasic;
|
||||
import mage.client.dialog.MageDialog;
|
||||
import mage.client.util.audio.AudioManager;
|
||||
|
|
@ -56,9 +57,9 @@ public class FeedbackPanel extends javax.swing.JPanel {
|
|||
customInitComponents();
|
||||
}
|
||||
|
||||
public void init(UUID gameId) {
|
||||
public void init(UUID gameId, BigCard bigCard) {
|
||||
this.gameId = gameId;
|
||||
helper.init(gameId);
|
||||
helper.init(gameId, bigCard);
|
||||
setGUISize();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,11 +196,20 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
player.getGraveyard().values().forEach(c -> this.allCardsIndex.put(c.getId(), c));
|
||||
Optional.ofNullable(player.getTopCard()).ifPresent(c -> this.allCardsIndex.put(c.getId(), c));
|
||||
// TODO: add support of dungeon, emblem all another non-card objects
|
||||
// commanders and custom emblems
|
||||
player.getCommandObjectList()
|
||||
.stream()
|
||||
.filter(c -> c instanceof CardView)
|
||||
.map(c -> (CardView) c)
|
||||
.forEach(c -> this.allCardsIndex.put(c.getId(), c));
|
||||
.forEach(object -> {
|
||||
if (object instanceof CardView) {
|
||||
// commanders and custom emblems
|
||||
this.allCardsIndex.put(object.getId(), (CardView) object);
|
||||
} else if (object instanceof DungeonView) {
|
||||
// dungeons
|
||||
this.allCardsIndex.put(object.getId(), new CardView((DungeonView) object));
|
||||
} else {
|
||||
// TODO: enable after all view types added here?
|
||||
//throw new IllegalArgumentException("Unsupported object type: " + object.getName() + " - " + object.getClass().getSimpleName());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -808,7 +817,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
this.gamePane = gamePane;
|
||||
this.playerId = playerId;
|
||||
MageFrame.addGame(gameId, this);
|
||||
this.feedbackPanel.init(gameId);
|
||||
this.feedbackPanel.init(gameId, bigCard);
|
||||
this.feedbackPanel.clear();
|
||||
this.abilityPicker.init(gameId, bigCard);
|
||||
this.btnConcede.setVisible(true);
|
||||
|
|
@ -851,7 +860,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
this.gamePane = gamePane;
|
||||
this.playerId = null;
|
||||
MageFrame.addGame(gameId, this);
|
||||
this.feedbackPanel.init(gameId);
|
||||
this.feedbackPanel.init(gameId, bigCard);
|
||||
this.feedbackPanel.clear();
|
||||
|
||||
this.btnConcede.setVisible(false);
|
||||
|
|
@ -886,7 +895,7 @@ public final class GamePanel extends javax.swing.JPanel {
|
|||
this.gameId = gameId;
|
||||
this.playerId = null;
|
||||
MageFrame.addGame(gameId, this);
|
||||
this.feedbackPanel.init(gameId);
|
||||
this.feedbackPanel.init(gameId, bigCard);
|
||||
this.feedbackPanel.clear();
|
||||
this.btnConcede.setVisible(false);
|
||||
this.btnSkipToNextTurn.setVisible(false);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.client.game;
|
||||
|
||||
import mage.client.SessionHandler;
|
||||
import mage.client.cards.BigCard;
|
||||
import mage.client.components.MageTextArea;
|
||||
import mage.client.constants.Constants;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
|
|
@ -89,8 +90,9 @@ public class HelperPanel extends JPanel {
|
|||
initComponents();
|
||||
}
|
||||
|
||||
public void init(UUID gameId) {
|
||||
public void init(UUID gameId, BigCard bigCard) {
|
||||
this.gameId = gameId;
|
||||
this.dialogTextArea.setGameData(gameId, bigCard);
|
||||
}
|
||||
|
||||
public void changeGUISize() {
|
||||
|
|
|
|||
|
|
@ -878,7 +878,8 @@ public class CardView extends SimpleCardView {
|
|||
this.displayName = name;
|
||||
this.displayFullName = name;
|
||||
this.rules = new ArrayList<>(emblem.getRules());
|
||||
// emblem images are always with common (black) symbol
|
||||
|
||||
// image - emblem are always with common (black) symbol
|
||||
this.frameStyle = FrameStyle.M15_NORMAL;
|
||||
this.expansionSetCode = emblem.getExpansionSetCode();
|
||||
this.cardNumber = emblem.getCardNumber();
|
||||
|
|
@ -901,12 +902,13 @@ public class CardView extends SimpleCardView {
|
|||
this.displayName = name;
|
||||
this.displayFullName = name;
|
||||
this.rules = new ArrayList<>(dungeon.getRules());
|
||||
// emblem images are always with common (black) symbol
|
||||
this.frameStyle = FrameStyle.M15_NORMAL;
|
||||
|
||||
// image
|
||||
this.frameStyle = FrameStyle.M15_NORMAL; // TODO: needs in full art? Test dungeon choose dialog
|
||||
this.expansionSetCode = dungeon.getExpansionSetCode();
|
||||
this.cardNumber = "";
|
||||
this.imageFileName = "";
|
||||
this.imageNumber = 0;
|
||||
this.imageFileName = dungeon.getImageFileName();
|
||||
this.imageNumber = dungeon.getImageNumber();
|
||||
this.rarity = Rarity.SPECIAL;
|
||||
|
||||
this.playableStats = dungeon.playableStats.copy();
|
||||
|
|
@ -923,7 +925,8 @@ public class CardView extends SimpleCardView {
|
|||
this.displayName = name;
|
||||
this.displayFullName = name;
|
||||
this.rules = new ArrayList<>(plane.getRules());
|
||||
// Display the plane in landscape (similar to Fused cards)
|
||||
|
||||
// image - display the plane in landscape (similar to Fused cards)
|
||||
this.rotate = true;
|
||||
this.frameStyle = FrameStyle.M15_NORMAL;
|
||||
this.expansionSetCode = plane.getExpansionSetCode();
|
||||
|
|
@ -947,6 +950,8 @@ public class CardView extends SimpleCardView {
|
|||
this.displayFullName = name;
|
||||
this.rules = new ArrayList<>();
|
||||
this.rules.add(stackAbility.getRule(designation.getName()));
|
||||
|
||||
// image
|
||||
this.frameStyle = FrameStyle.M15_NORMAL;
|
||||
this.cardNumber = designation.getCardNumber();
|
||||
this.expansionSetCode = designation.getExpansionSetCode();
|
||||
|
|
@ -954,6 +959,7 @@ public class CardView extends SimpleCardView {
|
|||
this.imageFileName = "";
|
||||
this.imageNumber = 0;
|
||||
this.rarity = Rarity.SPECIAL;
|
||||
|
||||
// no playable/chooseable marks for designations
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class StackAbilityView extends CardView {
|
|||
|
||||
public StackAbilityView(Game game, StackAbility ability, String sourceName, MageObject sourceObject, CardView sourceView) {
|
||||
this.id = ability.getId();
|
||||
this.mageObjectType = MageObjectType.ABILITY_STACK;
|
||||
this.mageObjectType = sourceView.getMageObjectType().isUseTokensRepository() ? MageObjectType.ABILITY_STACK_FROM_TOKEN : MageObjectType.ABILITY_STACK_FROM_CARD;
|
||||
this.abilityType = ability.getStackAbility().getAbilityType();
|
||||
this.sourceCard = sourceView;
|
||||
this.sourceCard.setMageObjectType(mageObjectType);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public final class AbandonHope extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// Look at target opponent's hand and choose X cards from it. That player discards those cards.
|
||||
this.getSpellAbility().addEffect(new LookTargetHandChooseDiscardEffect(false, GetXValue.instance));
|
||||
this.getSpellAbility().addEffect(new LookTargetHandChooseDiscardEffect(false, GetXValue.instance, StaticFilters.FILTER_CARD_CARDS));
|
||||
this.getSpellAbility().addTarget(new TargetOpponent());
|
||||
this.getSpellAbility().setCostAdjuster(AbandonHopeAdjuster.instance);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ReturnToHandSourceEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -50,7 +51,9 @@ public final class AcererakTheArchlich extends CardImpl {
|
|||
"to its owner's hand and venture into the dungeon."
|
||||
);
|
||||
ability.addEffect(new VentureIntoTheDungeonEffect());
|
||||
this.addAbility(ability.addHint(CompletedDungeonCondition.getHint()), new CompletedDungeonWatcher());
|
||||
ability.addHint(CurrentDungeonHint.instance);
|
||||
ability.addHint(CompletedDungeonCondition.getHint());
|
||||
this.addAbility(ability, new CompletedDungeonWatcher());
|
||||
|
||||
// Whenever Acererak the Archlich attacks, for each opponent, you create a 2/2 black Zombie creature token unless that player sacrifices a creature.
|
||||
this.addAbility(new AttacksTriggeredAbility(new AcererakTheArchlichEffect()));
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.DamageControllerEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -24,10 +20,10 @@ public final class AdarkarWastes extends CardImpl {
|
|||
|
||||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
Ability whiteManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana(1), new TapSourceCost());
|
||||
Ability whiteManaAbility = new WhiteManaAbility();
|
||||
whiteManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(whiteManaAbility);
|
||||
Ability blueManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlueMana(1), new TapSourceCost());
|
||||
Ability blueManaAbility = new BlueManaAbility();
|
||||
blueManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(blueManaAbility);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import mage.abilities.condition.Condition;
|
|||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.continuous.AddCardSubTypeSourceEffect;
|
||||
import mage.abilities.hint.ConditionHint;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.constants.*;
|
||||
|
|
@ -45,8 +46,8 @@ public final class Adrestia extends CardImpl {
|
|||
// Whenever Adrestia attacks, if an Assassin crewed it this turn, draw a card. Adrestia becomes an Assassin in addition to its other types until end of turn.
|
||||
Ability ability = new ConditionalInterveningIfTriggeredAbility(
|
||||
new AttacksTriggeredAbility(new DrawCardSourceControllerEffect(1), false),
|
||||
condition, "Whenever Adrestia attacks, if an Assassin crewed it this turn, draw a card. Adrestia becomes an Assassin in addition to its other types until end of turn.");
|
||||
ability.addEffect(new AdrestiaEffect());
|
||||
condition, "Whenever {this} attacks, if an Assassin crewed it this turn, draw a card. {this} becomes an Assassin in addition to its other types until end of turn.");
|
||||
ability.addEffect(new AddCardSubTypeSourceEffect(Duration.EndOfTurn, true, SubType.ASSASSIN));
|
||||
ability.addHint(AdrestiaCondition.getHint());
|
||||
this.addAbility(ability, new AdrestiaWatcher());
|
||||
|
||||
|
|
@ -65,32 +66,6 @@ public final class Adrestia extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class AdrestiaEffect extends ContinuousEffectImpl {
|
||||
|
||||
public AdrestiaEffect() {
|
||||
super(Duration.EndOfTurn, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
||||
}
|
||||
|
||||
protected AdrestiaEffect(final AdrestiaEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdrestiaEffect copy() {
|
||||
return new AdrestiaEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
permanent.addSubType(game, SubType.ASSASSIN);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
enum AdrestiaCondition implements Condition {
|
||||
instance;
|
||||
private static final Hint hint = new ConditionHint(instance, "an Assassin crewed it this turn");
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ public final class AkromaAngelOfWrath extends CardImpl {
|
|||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// Flying, first strike, vigilance, trample, haste, protection from black and from red
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
this.addAbility(FirstStrikeAbility.getInstance());
|
||||
this.addAbility(VigilanceAbility.getInstance());
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
// protection from black and from red
|
||||
this.addAbility(ProtectionAbility.from(ObjectColor.BLACK, ObjectColor.RED));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public final class AkromasWill extends CardImpl {
|
|||
this.getSpellAbility().getModes().setChooseText(
|
||||
"Choose one. If you control a commander as you cast this spell, you may choose both instead."
|
||||
);
|
||||
this.getSpellAbility().getModes().setMoreCondition(ControlACommanderCondition.instance);
|
||||
this.getSpellAbility().getModes().setMoreCondition(2, ControlACommanderCondition.instance);
|
||||
|
||||
// • Creatures you control gain flying, vigilance, and double strike until end of turn.
|
||||
this.getSpellAbility().addEffect(new GainAbilityControlledEffect(
|
||||
|
|
|
|||
|
|
@ -5,19 +5,14 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.AddContinuousEffectToGame;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceCardType;
|
||||
import mage.constants.*;
|
||||
import mage.filter.common.FilterOwnedCard;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -26,6 +21,8 @@ import mage.util.CardUtil;
|
|||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
|
||||
/**
|
||||
* @author jeffwadsworth
|
||||
|
|
@ -40,11 +37,11 @@ public class ApexObservatory extends CardImpl {
|
|||
// Apex Observatory enters the battlefield tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// Apex Observatory enters the battlefield tapped. As it enters, choose a card type shared among two exiled cards used to craft it.
|
||||
// As it enters, choose a card type shared among two exiled cards used to craft it.
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseCardTypeEffect()));
|
||||
|
||||
// The next spell you cast this turn of the chosen type can be cast without paying its mana cost.
|
||||
this.addAbility(new SimpleActivatedAbility(new AddContinuousEffectToGame(new ApexObservatoryEffect()), new TapSourceCost()));
|
||||
this.addAbility(new SimpleActivatedAbility(new ApexObservatoryEffect(), new TapSourceCost()));
|
||||
}
|
||||
|
||||
private ApexObservatory(final ApexObservatory card) {
|
||||
|
|
@ -141,10 +138,10 @@ class ChooseCardTypeEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
|
||||
class ApexObservatoryEffect extends ContinuousEffectImpl {
|
||||
class ApexObservatoryEffect extends OneShotEffect {
|
||||
|
||||
ApexObservatoryEffect() {
|
||||
super(Duration.EndOfTurn, Outcome.Benefit);
|
||||
super(Outcome.Benefit);
|
||||
staticText = "The next spell you cast this turn of the chosen type can be cast without paying its mana cost.";
|
||||
}
|
||||
|
||||
|
|
@ -158,86 +155,85 @@ class ApexObservatoryEffect extends ContinuousEffectImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
public boolean apply(Game game, Ability source) {
|
||||
String chosenCardType = (String) game.getState().getValue("ApexObservatoryType_" + source.getSourceId().toString());
|
||||
if (controller != null
|
||||
&& chosenCardType != null) {
|
||||
Card apexObservatory = game.getCard(source.getSourceId());
|
||||
if (apexObservatory != null) {
|
||||
Boolean wasItUsed = (Boolean) game.getState().getValue(
|
||||
apexObservatory.getId().toString());
|
||||
if (wasItUsed == null) {
|
||||
ApexObservatoryAlternativeCostAbility alternateCostAbility = new ApexObservatoryAlternativeCostAbility(chosenCardType);
|
||||
alternateCostAbility.setSourceId(source.getSourceId());
|
||||
controller.getAlternativeSourceCosts().add(alternateCostAbility);
|
||||
if (chosenCardType == null) {
|
||||
return false;
|
||||
}
|
||||
game.addEffect(new ApexObservatoryCastWithoutManaEffect(chosenCardType, source.getControllerId()), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class ApexObservatoryCastWithoutManaEffect extends CostModificationEffectImpl {
|
||||
|
||||
private final String chosenCardType;
|
||||
private final UUID playerId;
|
||||
private boolean used = false;
|
||||
|
||||
ApexObservatoryCastWithoutManaEffect(String chosenCardType, UUID playerId) {
|
||||
super(Duration.EndOfTurn, Outcome.Benefit, CostModificationType.SET_COST);
|
||||
this.chosenCardType = chosenCardType;
|
||||
this.playerId = playerId;
|
||||
staticText = "The next spell you cast this turn of the chosen type can be cast without paying its mana cost";
|
||||
}
|
||||
|
||||
private ApexObservatoryCastWithoutManaEffect(final ApexObservatoryCastWithoutManaEffect effect) {
|
||||
super(effect);
|
||||
this.chosenCardType = effect.chosenCardType;
|
||||
this.playerId = effect.playerId;
|
||||
this.used = effect.used;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
// Ask the player if they want to use the effect
|
||||
Player controller = game.getPlayer(playerId);
|
||||
if (controller != null) {
|
||||
MageObject spell = abilityToModify.getSourceObject(game);
|
||||
if (spell != null && !game.isSimulation()) {
|
||||
String message = "Cast " + spell.getIdName() + " without paying its mana cost?";
|
||||
if (controller.chooseUse(Outcome.Benefit, message, source, game)) {
|
||||
// Set the cost to zero
|
||||
abilityToModify.getManaCostsToPay().clear();
|
||||
// Mark as used
|
||||
used = true;
|
||||
game.informPlayers(controller.getLogName() + " casts " + spell.getIdName() + " without paying its mana cost.");
|
||||
return true;
|
||||
} else {
|
||||
// Player chose not to use the effect
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
public ApexObservatoryCastWithoutManaEffect copy() {
|
||||
return new ApexObservatoryCastWithoutManaEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.RulesEffects;
|
||||
}
|
||||
}
|
||||
|
||||
class ApexObservatoryAlternativeCostAbility extends AlternativeCostSourceAbility {
|
||||
|
||||
private boolean wasActivated;
|
||||
|
||||
ApexObservatoryAlternativeCostAbility(String chosenCardType) {
|
||||
super(new SpellMatchesChosenTypeCondition(chosenCardType), null, new FilterOwnedCard(), true, null);
|
||||
}
|
||||
|
||||
private ApexObservatoryAlternativeCostAbility(final ApexObservatoryAlternativeCostAbility ability) {
|
||||
super(ability);
|
||||
this.wasActivated = ability.wasActivated;
|
||||
public boolean isInactive(Ability source, Game game) {
|
||||
return used || super.isInactive(source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApexObservatoryAlternativeCostAbility copy() {
|
||||
return new ApexObservatoryAlternativeCostAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activateAlternativeCosts(Ability ability, Game game) {
|
||||
if (!super.activateAlternativeCosts(ability, game)) {
|
||||
public boolean applies(Ability ability, Ability source, Game game) {
|
||||
if (used) {
|
||||
return false;
|
||||
}
|
||||
Card apexObservatory = game.getCard(this.getSourceId());
|
||||
if (apexObservatory != null) {
|
||||
game.getState().setValue(apexObservatory.getId().toString(), true);
|
||||
if (!ability.isControlledBy(playerId)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class SpellMatchesChosenTypeCondition implements Condition {
|
||||
|
||||
final private String chosenCardType;
|
||||
|
||||
public SpellMatchesChosenTypeCondition(String chosenCardType) {
|
||||
this.chosenCardType = chosenCardType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return checkSpell(game.getObject(source), game, chosenCardType);
|
||||
}
|
||||
|
||||
public static boolean checkSpell(MageObject spell, Game game, String chosenCardType) {
|
||||
if (spell instanceof Card) {
|
||||
Card card = (Card) spell;
|
||||
return chosenCardType != null
|
||||
&& card.getCardType(game).toString().contains(chosenCardType);
|
||||
if (!(ability instanceof SpellAbility)) {
|
||||
return false;
|
||||
}
|
||||
MageObject object = game.getObject(ability.getSourceId());
|
||||
if (object != null && object.getCardType(game).stream()
|
||||
.anyMatch(cardType -> cardType.toString().equals(chosenCardType))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,28 +2,19 @@ package mage.cards.a;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.*;
|
||||
import mage.abilities.keyword.DeathtouchAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.keyword.DisguiseAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedPlayerEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -31,6 +22,13 @@ import mage.target.targetpointer.FixedTarget;
|
|||
*/
|
||||
public final class AvelineDeGrandpre extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterControlledCreaturePermanent("a creature you control with deathtouch");
|
||||
|
||||
static {
|
||||
filter.add(new AbilityPredicate(DeathtouchAbility.class));
|
||||
}
|
||||
|
||||
public AvelineDeGrandpre(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
|
||||
|
||||
|
|
@ -44,7 +42,11 @@ public final class AvelineDeGrandpre extends CardImpl {
|
|||
this.addAbility(DeathtouchAbility.getInstance());
|
||||
|
||||
// Whenever a creature you control with deathtouch deals combat damage to a player, put that many +1/+1 counters on that creature.
|
||||
this.addAbility(new AvelineDeGrandpreTriggeredAbility());
|
||||
this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance(), SavedDamageValue.MANY),
|
||||
filter,
|
||||
false, SetTargetPointer.PERMANENT, true
|
||||
));
|
||||
|
||||
// Disguise {B}{G}
|
||||
this.addAbility(new DisguiseAbility(this, new ManaCostsImpl<>("{B}{G}")));
|
||||
|
|
@ -60,52 +62,3 @@ public final class AvelineDeGrandpre extends CardImpl {
|
|||
return new AvelineDeGrandpre(this);
|
||||
}
|
||||
}
|
||||
|
||||
class AvelineDeGrandpreTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterControlledCreaturePermanent("a creature you control with deathtouch");
|
||||
|
||||
static {
|
||||
filter.add(new AbilityPredicate(DeathtouchAbility.class));
|
||||
}
|
||||
|
||||
public AvelineDeGrandpreTriggeredAbility() {
|
||||
// Copied from Necropolis Regent, I don't know why QUEST counters.
|
||||
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.QUEST.createInstance()), false);
|
||||
}
|
||||
|
||||
private AvelineDeGrandpreTriggeredAbility(final AvelineDeGrandpreTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AvelineDeGrandpreTriggeredAbility copy() {
|
||||
return new AvelineDeGrandpreTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (((DamagedPlayerEvent) event).isCombatDamage()) {
|
||||
Permanent creature = game.getPermanent(event.getSourceId());
|
||||
if (creature != null && creature.isControlledBy(controllerId) && filter.match(creature, game)) {
|
||||
this.getEffects().clear();
|
||||
Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(event.getAmount()));
|
||||
effect.setTargetPointer(new FixedTarget(creature.getId(), game));
|
||||
this.addEffect(effect);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a creature you control with deathtouch deals combat damage to a player, put that many +1/+1 counters on it.";
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import java.util.UUID;
|
|||
|
||||
import mage.abilities.effects.common.CounterTargetEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -33,6 +34,7 @@ public final class BarTheGate extends CardImpl {
|
|||
this.getSpellAbility().addTarget(new TargetSpell(filter));
|
||||
this.getSpellAbility().addEffect(new CounterTargetEffect());
|
||||
this.getSpellAbility().addEffect(new VentureIntoTheDungeonEffect());
|
||||
this.getSpellAbility().addHint(CurrentDungeonHint.instance);
|
||||
}
|
||||
|
||||
private BarTheGate(final BarTheGate card) {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import mage.abilities.condition.common.CompletedDungeonCondition;
|
|||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -44,7 +45,8 @@ public final class BarrowinOfClanUndurr extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// When Barrowin of Clan Undurr enters the battlefield, venture into the dungeon.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// Whenever Barrowin of Clan Undurr attacks, return up to one creature card with mana value 3 or less from your graveyard to the battlefield if you've completed a dungeon.
|
||||
Ability ability = new AttacksTriggeredAbility(new ConditionalOneShotEffect(
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.DamageControllerEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -26,10 +22,10 @@ public final class BattlefieldForge extends CardImpl {
|
|||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
// Tap: Add Red or White. Battlefield Forge deals 1 damage to you.
|
||||
Ability redManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana(1), new TapSourceCost());
|
||||
Ability redManaAbility = new RedManaAbility();
|
||||
redManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(redManaAbility);
|
||||
Ability whiteManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana(1), new TapSourceCost());
|
||||
Ability whiteManaAbility = new WhiteManaAbility();
|
||||
whiteManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(whiteManaAbility);
|
||||
}
|
||||
|
|
|
|||
55
Mage.Sets/src/mage/cards/b/BeastieBeatdown.java
Normal file
55
Mage.Sets/src/mage/cards/b/BeastieBeatdown.java
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.abilities.condition.common.DeliriumCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.DamageWithPowerFromOneToAnotherTargetEffect;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.hint.common.CardTypesInGraveyardHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.target.common.TargetControlledCreaturePermanent;
|
||||
import mage.target.common.TargetOpponentsCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BeastieBeatdown extends CardImpl {
|
||||
|
||||
public BeastieBeatdown(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R}{G}");
|
||||
|
||||
// Choose target creature you control and target creature an opponent controls.
|
||||
this.getSpellAbility().addEffect(new InfoEffect(
|
||||
"Choose target creature you control and target creature an opponent controls."
|
||||
));
|
||||
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
|
||||
this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent());
|
||||
|
||||
// Delirium -- If there are four or more card types among cards in your graveyard, put two +1/+1 counters on the creature you control.
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)),
|
||||
DeliriumCondition.instance, AbilityWord.DELIRIUM.formatWord() + "If there are four or more " +
|
||||
"card types among cards in your graveyard, put two +1/+1 counters on the creature you control."
|
||||
).concatBy("<br>"));
|
||||
this.getSpellAbility().addHint(CardTypesInGraveyardHint.YOU);
|
||||
|
||||
// The creature you control deals damage equal to its power to the creature an opponent controls.
|
||||
this.getSpellAbility().addEffect(new DamageWithPowerFromOneToAnotherTargetEffect()
|
||||
.setText("<br>The creature you control deals damage equal to its power to the creature an opponent controls."));
|
||||
}
|
||||
|
||||
private BeastieBeatdown(final BeastieBeatdown card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeastieBeatdown copy() {
|
||||
return new BeastieBeatdown(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -81,6 +81,6 @@ class BloodSeekerTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a creature enters the battlefield under an opponent's control, you may have that player lose 1 life.";
|
||||
return "Whenever a creature an opponent controls enters, you may have that player lose 1 life.";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
48
Mage.Sets/src/mage/cards/b/BoilerbilgesRipper.java
Normal file
48
Mage.Sets/src/mage/cards/b/BoilerbilgesRipper.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.costs.common.SacrificeTargetCost;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.DoWhenCostPaid;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class BoilerbilgesRipper extends CardImpl {
|
||||
|
||||
public BoilerbilgesRipper(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}");
|
||||
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.ASSASSIN);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Boilerbilges Ripper enters, you may sacrifice another creature or enchantment. When you do, Boilerbilges Ripper deals 2 damage to any target.
|
||||
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new DamageTargetEffect(2), false);
|
||||
ability.addTarget(new TargetAnyTarget());
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new DoWhenCostPaid(
|
||||
ability, new SacrificeTargetCost(StaticFilters.FILTER_PERMANENT_ANOTHER_CREATURE_OR_ENCHANTMENT),
|
||||
"Sacrifice another creature or enchantment?"
|
||||
)));
|
||||
}
|
||||
|
||||
private BoilerbilgesRipper(final BoilerbilgesRipper card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BoilerbilgesRipper copy() {
|
||||
return new BoilerbilgesRipper(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,12 +11,10 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
|
|
@ -41,6 +39,7 @@ public final class BoxingRing extends CardImpl {
|
|||
= new FilterCreaturePermanent("creature you don't control with the same mana value");
|
||||
|
||||
static {
|
||||
filter.add(TargetController.NOT_YOU.getControllerPredicate());
|
||||
filter.add(BoxingRingPredicate.instance);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.b;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -100,24 +99,34 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
|||
List<Permanent> fromBattlefield = new ArrayList<>();
|
||||
List<Card> fromHandGraveyard = new ArrayList<>();
|
||||
|
||||
int countBattlefield = game.getBattlefield().getActivePermanents(filterAura, source.getControllerId(), source, game).size() - sourcePermanent.getAttachments().size();
|
||||
int countBattlefield = (int) (game.getBattlefield().getActivePermanents(filterAura, source.getControllerId(), source, game).size()
|
||||
- sourcePermanent.getAttachments().stream().map(game::getPermanent).filter(permanent -> permanent != null
|
||||
&& permanent.hasSubtype(SubType.AURA, game)).count());
|
||||
while (controller.canRespond()
|
||||
&& countBattlefield > 0
|
||||
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from the battlefield?", source, game)) {
|
||||
Target targetAura = new TargetPermanent(filterAura);
|
||||
targetAura.withNotTarget(true);
|
||||
if (!controller.choose(Outcome.Benefit, targetAura, source, game)) { continue; }
|
||||
if (!controller.choose(Outcome.Benefit, targetAura, source, game)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Permanent aura = game.getPermanent(targetAura.getFirstTarget());
|
||||
if (aura == null) { continue; }
|
||||
if (aura == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Target target = aura.getSpellAbility().getTargets().get(0);
|
||||
if (target == null) { continue; }
|
||||
if (target == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fromBattlefield.add(aura);
|
||||
filterAura.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
||||
|
||||
countBattlefield = game.getBattlefield().getActivePermanents(filterAura, source.getControllerId(), source, game).size() - sourcePermanent.getAttachments().size();
|
||||
countBattlefield = (int) (game.getBattlefield().getActivePermanents(filterAura, source.getControllerId(), source, game).size()
|
||||
- sourcePermanent.getAttachments().stream().map(game::getPermanent).filter(permanent -> permanent != null
|
||||
&& permanent.hasSubtype(SubType.AURA, game)).count());
|
||||
}
|
||||
|
||||
int countHand = controller.getHand().count(filterAuraCard, game);
|
||||
|
|
@ -125,13 +134,19 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
|||
&& countHand > 0
|
||||
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from your hand?", source, game)) {
|
||||
TargetCard targetAura = new TargetCard(Zone.HAND, filterAuraCard);
|
||||
if (!controller.choose(Outcome.Benefit, controller.getHand(), targetAura, source, game)) { continue; }
|
||||
if (!controller.choose(Outcome.Benefit, controller.getHand(), targetAura, source, game)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Card aura = game.getCard(targetAura.getFirstTarget());
|
||||
if (aura == null) { continue; }
|
||||
if (aura == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Target target = aura.getSpellAbility().getTargets().get(0);
|
||||
if (target == null) { continue; }
|
||||
if (target == null) {
|
||||
continue;
|
||||
}
|
||||
fromHandGraveyard.add(aura);
|
||||
filterAuraCard.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
||||
|
||||
|
|
@ -143,13 +158,19 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
|||
&& countGraveyard > 0
|
||||
&& controller.chooseUse(Outcome.Benefit, "Attach an Aura from your graveyard?", source, game)) {
|
||||
TargetCard targetAura = new TargetCard(Zone.GRAVEYARD, filterAuraCard);
|
||||
if (!controller.choose(Outcome.Benefit, controller.getGraveyard(), targetAura, source, game)) { continue; }
|
||||
if (!controller.choose(Outcome.Benefit, controller.getGraveyard(), targetAura, source, game)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Card aura = game.getCard(targetAura.getFirstTarget());
|
||||
if (aura == null) { continue; }
|
||||
if (aura == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Target target = aura.getSpellAbility().getTargets().get(0);
|
||||
if (target == null) { continue; }
|
||||
if (target == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fromHandGraveyard.add(aura);
|
||||
filterAuraCard.add(Predicates.not(new CardIdPredicate(aura.getId())));
|
||||
|
|
@ -168,7 +189,9 @@ class BrunaLightOfAlabasterEffect extends OneShotEffect {
|
|||
|
||||
// Move cards
|
||||
for (Card aura : fromHandGraveyard) {
|
||||
if (aura == null) { continue; }
|
||||
if (aura == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
game.getState().setValue("attachTo:" + aura.getId(), sourcePermanent);
|
||||
controller.moveCards(aura, Zone.BATTLEFIELD, source, game);
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@
|
|||
package mage.cards.b;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.DamageControllerEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -23,10 +19,10 @@ public final class Brushland extends CardImpl {
|
|||
super(ownerId,setInfo,new CardType[]{CardType.LAND},"");
|
||||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
Ability greenManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana(1), new TapSourceCost());
|
||||
Ability greenManaAbility = new GreenManaAbility();
|
||||
greenManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(greenManaAbility);
|
||||
Ability whiteManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana(1), new TapSourceCost());
|
||||
Ability whiteManaAbility = new WhiteManaAbility();
|
||||
whiteManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(whiteManaAbility);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public final class BrutalCathar extends CardImpl {
|
|||
Ability ability = new TransformsOrEntersTriggeredAbility(
|
||||
new ExileUntilSourceLeavesEffect()
|
||||
.setText("exile target creature an opponent controls until this creature leaves the battlefield"), false
|
||||
).setTriggerPhrase("When this creature enters the battlefield or transforms into {this}, ");
|
||||
).setTriggerPhrase("When this creature enters or transforms into {this}, ");
|
||||
ability.addTarget(new TargetOpponentsCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledArtifactPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class Caprichrome extends CardImpl {
|
||||
|
||||
private static final FilterControlledPermanent filter = new FilterControlledArtifactPermanent("artifact");
|
||||
private static final FilterPermanent filter = new FilterControlledArtifactPermanent("artifact");
|
||||
|
||||
public Caprichrome(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{W}");
|
||||
|
|
|
|||
47
Mage.Sets/src/mage/cards/c/CatharticParting.java
Normal file
47
Mage.Sets/src/mage/cards/c/CatharticParting.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.abilities.effects.common.ShuffleIntoLibraryTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterArtifactOrEnchantmentPermanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.targetpointer.SecondTargetPointer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class CatharticParting extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterArtifactOrEnchantmentPermanent("artifact or enchantment an opponent controls");
|
||||
|
||||
static {
|
||||
filter.add(TargetController.OPPONENT.getControllerPredicate());
|
||||
}
|
||||
|
||||
public CatharticParting(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}");
|
||||
|
||||
// The owner of target artifact or enchantment an opponent controls shuffles it into their library. You may shuffle up to four target cards from your graveyard into your library.
|
||||
this.getSpellAbility().addEffect(new ShuffleIntoLibraryTargetEffect()
|
||||
.setText("the owner of target artifact or enchantment an opponent controls shuffles it into their library"));
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(filter));
|
||||
this.getSpellAbility().addEffect(new ShuffleIntoLibraryTargetEffect(true)
|
||||
.setTargetPointer(new SecondTargetPointer()));
|
||||
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(0, 4));
|
||||
}
|
||||
|
||||
private CatharticParting(final CatharticParting card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CatharticParting copy() {
|
||||
return new CatharticParting(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,16 +2,12 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.DamageControllerEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -27,10 +23,10 @@ public final class CavesOfKoilos extends CardImpl {
|
|||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
// Tap: Add White or Black. Caves of Koilos deals 1 damage to you.
|
||||
Ability whiteManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.WhiteMana(1), new TapSourceCost());
|
||||
Ability whiteManaAbility = new WhiteManaAbility();
|
||||
whiteManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(whiteManaAbility);
|
||||
Ability blackManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana(1), new TapSourceCost());
|
||||
Ability blackManaAbility = new BlackManaAbility();
|
||||
blackManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(blackManaAbility);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mage.cards.c;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.common.DiesSourceTriggeredAbility;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -23,7 +24,8 @@ public final class ClatteringSkeletons extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// When Clattering Skeletons dies, venture into the dungeon.
|
||||
this.addAbility(new DiesSourceTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new DiesSourceTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
}
|
||||
|
||||
private ClatteringSkeletons(final ClatteringSkeletons card) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
|
|||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -32,7 +33,8 @@ public final class CloisterGargoyle extends CardImpl {
|
|||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Cloister Gargoyle enters the battlefield, venture into the dungeon.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// As long as you've completed a dungeon, Cloister Gargoyle gets +3/+0 and has flying.
|
||||
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
|
|
|
|||
87
Mage.Sets/src/mage/cards/c/ComeBackWrong.java
Normal file
87
Mage.Sets/src/mage/cards/c/ComeBackWrong.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.delayed.AtTheBeginOfPlayersNextEndStepDelayedTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.SacrificeTargetEffect;
|
||||
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.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class ComeBackWrong extends CardImpl {
|
||||
|
||||
public ComeBackWrong(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
|
||||
|
||||
// Destroy target creature. If a creature card is put into a graveyard this way, return it to the battlefield under your control. Sacrifice it at the beginning of your next end step.
|
||||
this.getSpellAbility().addEffect(new ComeBackWrongEffect());
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
}
|
||||
|
||||
private ComeBackWrong(final ComeBackWrong card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComeBackWrong copy() {
|
||||
return new ComeBackWrong(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ComeBackWrongEffect extends OneShotEffect {
|
||||
|
||||
ComeBackWrongEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "destroy target creature. If a creature card is put into a graveyard this way, " +
|
||||
"return it to the battlefield under your control. Sacrifice it at the beginning of your next end step";
|
||||
}
|
||||
|
||||
private ComeBackWrongEffect(final ComeBackWrongEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComeBackWrongEffect copy() {
|
||||
return new ComeBackWrongEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
permanent.destroy(source, game);
|
||||
Card card = permanent.getMainCard();
|
||||
if (card == null || !card.isCreature(game) || !Zone.GRAVEYARD.match(game.getState().getZone(card.getId()))) {
|
||||
return true;
|
||||
}
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
player.moveCards(card, Zone.BATTLEFIELD, source, game);
|
||||
Permanent creature = game.getPermanent(card.getId());
|
||||
if (permanent != null) {
|
||||
game.addDelayedTriggeredAbility(new AtTheBeginOfPlayersNextEndStepDelayedTriggeredAbility(
|
||||
new SacrificeTargetEffect("sacrifice it")
|
||||
.setTargetPointer(new FixedTarget(creature, game)),
|
||||
player.getId()
|
||||
).setTriggerPhrase("At the beginning of your next end step, "), source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -99,12 +99,12 @@ class ConduitOfRuinWatcher extends Watcher {
|
|||
}
|
||||
}
|
||||
|
||||
class FirstCastCreatureSpellPredicate implements ObjectSourcePlayerPredicate<Controllable> {
|
||||
class FirstCastCreatureSpellPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<Controllable> input, Game game) {
|
||||
if (input.getObject() instanceof Card
|
||||
&& ((Card) input.getObject()).isCreature(game)) {
|
||||
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||
if (input.getObject() != null
|
||||
&& input.getObject().isCreature(game)) {
|
||||
ConduitOfRuinWatcher watcher = game.getState().getWatcher(ConduitOfRuinWatcher.class);
|
||||
return watcher != null && watcher.creatureSpellsCastThisTurn(input.getPlayerId()) == 0;
|
||||
}
|
||||
|
|
|
|||
89
Mage.Sets/src/mage/cards/c/CoordinatedClobbering.java
Normal file
89
Mage.Sets/src/mage/cards/c/CoordinatedClobbering.java
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetOpponentsCreaturePermanent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class CoordinatedClobbering extends CardImpl {
|
||||
|
||||
public CoordinatedClobbering(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{G}");
|
||||
|
||||
// Tap one or two target untapped creatures you control. They each deal damage equal to their power to target creature an opponent controls.
|
||||
this.getSpellAbility().addEffect(new CoordinatedClobberingEffect());
|
||||
this.getSpellAbility().addTarget(new TargetPermanent(
|
||||
1, 2, StaticFilters.FILTER_CONTROLLED_UNTAPPED_CREATURES
|
||||
));
|
||||
this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent());
|
||||
}
|
||||
|
||||
private CoordinatedClobbering(final CoordinatedClobbering card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CoordinatedClobbering copy() {
|
||||
return new CoordinatedClobbering(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CoordinatedClobberingEffect extends OneShotEffect {
|
||||
|
||||
CoordinatedClobberingEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "tap one or two target untapped creatures you control. " +
|
||||
"They each deal damage equal to their power to target creature an opponent controls";
|
||||
}
|
||||
|
||||
private CoordinatedClobberingEffect(final CoordinatedClobberingEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CoordinatedClobberingEffect copy() {
|
||||
return new CoordinatedClobberingEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
List<Permanent> permanents = this
|
||||
.getTargetPointer()
|
||||
.getTargets(game, source)
|
||||
.stream()
|
||||
.map(game::getPermanent)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
if (permanents.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (Permanent permanent : permanents) {
|
||||
permanent.tap(source, game);
|
||||
}
|
||||
Permanent targetPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||
if (targetPermanent == null) {
|
||||
return true;
|
||||
}
|
||||
game.processAction();
|
||||
for (Permanent permanent : permanents) {
|
||||
targetPermanent.damage(permanent.getPower().getValue(), permanent.getId(), source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// flame on!
|
||||
60
Mage.Sets/src/mage/cards/c/CrackedSkull.java
Normal file
60
Mage.Sets/src/mage/cards/c/CrackedSkull.java
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealtDamageAttachedTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.effects.common.discard.LookTargetHandChooseDiscardEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.TargetPlayer;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class CrackedSkull extends CardImpl {
|
||||
|
||||
public CrackedSkull(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}");
|
||||
|
||||
this.subtype.add(SubType.AURA);
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
|
||||
this.addAbility(new EnchantAbility(auraTarget));
|
||||
|
||||
// When Cracked Skull enters, look at target player's hand. You may choose a nonland card from it. That player discards that card.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(
|
||||
new LookTargetHandChooseDiscardEffect(true, StaticValue.get(1), StaticFilters.FILTER_CARD_NON_LAND)
|
||||
.setText("look at target player's hand. You may choose a nonland card from it. That player discards that card")
|
||||
);
|
||||
ability.addTarget(new TargetPlayer());
|
||||
this.addAbility(ability);
|
||||
|
||||
// When enchanted creature is dealt damage, destroy it.
|
||||
this.addAbility(new DealtDamageAttachedTriggeredAbility(
|
||||
Zone.BATTLEFIELD, new DestroyTargetEffect("destroy it"),
|
||||
false, SetTargetPointer.PERMANENT
|
||||
).setTriggerPhrase("When enchanted creature is dealt damage, "));
|
||||
}
|
||||
|
||||
private CrackedSkull(final CrackedSkull card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CrackedSkull copy() {
|
||||
return new CrackedSkull(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -33,11 +33,11 @@ public final class CursedRecording extends CardImpl {
|
|||
// Whenever you cast an instant or sorcery spell, put a time counter on Cursed Recording. Then if there are seven or more time counters on it, remove those counters and it deals 20 damage to you.
|
||||
Ability ability = new SpellCastControllerTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.TIME.createInstance()),
|
||||
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, true
|
||||
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY, false
|
||||
);
|
||||
ability.addEffect(new ConditionalOneShotEffect(
|
||||
new RemoveAllCountersSourceEffect(CounterType.TIME),
|
||||
condition, "then if there are seven or more time counters on it, " +
|
||||
condition, "Then if there are seven or more time counters on it, " +
|
||||
"remove those counters and it deals 20 damage to you"
|
||||
).addEffect(new DamageControllerEffect(20)));
|
||||
this.addAbility(ability);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import mage.abilities.common.AttacksAttachedTriggeredAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.constants.SubType;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -27,7 +28,8 @@ public final class DelversTorch extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(1, 1)));
|
||||
|
||||
// Whenever equipped creature attacks, venture into the dungeon.
|
||||
this.addAbility(new AttacksAttachedTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new AttacksAttachedTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// Equip {3}
|
||||
this.addAbility(new EquipAbility(3));
|
||||
|
|
|
|||
|
|
@ -1,24 +1,14 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.DevourEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetSacrifice;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -35,7 +25,11 @@ public final class DevouringHellion extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// As Devouring Hellion enters the battlefield, you may sacrifice any number of creatures and/or planeswalkers. If you do, it enters with twice that many +1/+1 counters on it.
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new DevouringHellionEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL,
|
||||
new DevourEffect(2, StaticFilters.FILTER_CONTROLLED_PERMANENT_CREATURE_OR_PLANESWALKER)
|
||||
.setText("As {this} enters the battlefield, you may sacrifice any number of creatures and/or planeswalkers."
|
||||
+ " If you do, it enters with twice that many +1/+1 counters on it")
|
||||
));
|
||||
}
|
||||
|
||||
private DevouringHellion(final DevouringHellion card) {
|
||||
|
|
@ -47,50 +41,3 @@ public final class DevouringHellion extends CardImpl {
|
|||
return new DevouringHellion(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DevouringHellionEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter = new FilterControlledPermanent("creatures and/or planeswalkers");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.CREATURE.getPredicate(),
|
||||
CardType.PLANESWALKER.getPredicate()
|
||||
));
|
||||
}
|
||||
|
||||
DevouringHellionEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may sacrifice any number of creatures and/or planeswalkers. " +
|
||||
"If you do, it enters with twice that many +1/+1 counters on it.";
|
||||
}
|
||||
|
||||
private DevouringHellionEffect(final DevouringHellionEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DevouringHellionEffect copy() {
|
||||
return new DevouringHellionEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Target target = new TargetSacrifice(0, Integer.MAX_VALUE, filter);
|
||||
if (!player.choose(Outcome.Sacrifice, target, source, game)) {
|
||||
return false;
|
||||
}
|
||||
int xValue = 0;
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
Permanent permanent = game.getPermanent(targetId);
|
||||
if (permanent != null && permanent.sacrifice(source, game)) {
|
||||
xValue++;
|
||||
}
|
||||
}
|
||||
return new AddCountersSourceEffect(CounterType.P1P1.createInstance(2 * xValue)).apply(game, source);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public final class DiscipleOfPerdition extends CardImpl {
|
|||
// * You draw a card and you lose 1 life.
|
||||
Ability ability = new DiesSourceTriggeredAbility(new DrawCardSourceControllerEffect(1, true), false);
|
||||
ability.getModes().setChooseText("choose one. If you have exactly 13 life, you may choose both.");
|
||||
ability.getModes().setMoreCondition(new LifeCompareCondition(TargetController.YOU, ComparisonType.EQUAL_TO, 13));
|
||||
ability.getModes().setMoreCondition(2, new LifeCompareCondition(TargetController.YOU, ComparisonType.EQUAL_TO, 13));
|
||||
ability.addEffect(new LoseLifeSourceControllerEffect(1).concatBy("and"));
|
||||
|
||||
// * Exile target opponent's graveyard. That player loses 1 life.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import mage.abilities.common.SimpleActivatedAbility;
|
|||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.ReturnToHandSourceEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -27,7 +28,8 @@ public final class DisplacerBeast extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// When Displacer Beast enters the battlefield, venture into the dungeon.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// Displacement — {3}{U}: Return Displacer Beast to its owner's hand.
|
||||
this.addAbility(new SimpleActivatedAbility(
|
||||
|
|
|
|||
78
Mage.Sets/src/mage/cards/d/DontMakeASound.java
Normal file
78
Mage.Sets/src/mage/cards/d/DontMakeASound.java
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class DontMakeASound extends CardImpl {
|
||||
|
||||
public DontMakeASound(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
|
||||
|
||||
// Counter target spell unless its controller pays {2}. If they do, surveil 2.
|
||||
this.getSpellAbility().addEffect(new DontMakeASoundEffect());
|
||||
this.getSpellAbility().addTarget(new TargetSpell());
|
||||
}
|
||||
|
||||
private DontMakeASound(final DontMakeASound card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DontMakeASound copy() {
|
||||
return new DontMakeASound(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DontMakeASoundEffect extends OneShotEffect {
|
||||
|
||||
DontMakeASoundEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "counter target spell unless its controller pays {2}. If they do, surveil 2";
|
||||
}
|
||||
|
||||
private DontMakeASoundEffect(final DontMakeASoundEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DontMakeASoundEffect copy() {
|
||||
return new DontMakeASoundEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Spell spell = game.getSpell(getTargetPointer().getFirst(game, source));
|
||||
if (spell == null) {
|
||||
return false;
|
||||
}
|
||||
Player player = game.getPlayer(spell.getControllerId());
|
||||
if (player == null) {
|
||||
return game.getStack().counter(spell.getId(), source, game);
|
||||
}
|
||||
Cost cost = new GenericManaCost(2);
|
||||
if (!cost.canPay(source, source, player.getId(), game)
|
||||
|| !player.chooseUse(outcome, "Pay {2}?", source, game)
|
||||
|| !cost.pay(source, game, source, player.getId(), false)) {
|
||||
return game.getStack().counter(spell.getId(), source, game);
|
||||
}
|
||||
Optional.ofNullable(game.getPlayer(source.getControllerId()))
|
||||
.ifPresent(p -> p.surveil(2, source, game));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ public final class DrownInDreams extends CardImpl {
|
|||
this.getSpellAbility().getModes().setChooseText(
|
||||
"Choose one. If you control a commander as you cast this spell, you may choose both."
|
||||
);
|
||||
this.getSpellAbility().getModes().setMoreCondition(ControlACommanderCondition.instance);
|
||||
this.getSpellAbility().getModes().setMoreCondition(2, ControlACommanderCondition.instance);
|
||||
|
||||
// • Target player draws X cards.
|
||||
this.getSpellAbility().addEffect(new DrawCardTargetEffect(GetXValue.instance));
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import mage.abilities.costs.common.TapSourceCost;
|
|||
import mage.abilities.costs.common.TapTargetCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -45,6 +46,7 @@ public final class DungeonDescent extends CardImpl {
|
|||
Ability ability = new ActivateAsSorceryActivatedAbility(new VentureIntoTheDungeonEffect(), new GenericManaCost(4));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(filter)));
|
||||
ability.addHint(CurrentDungeonHint.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import mage.abilities.common.ActivateAsSorceryActivatedAbility;
|
|||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -28,6 +29,7 @@ public final class DungeonMap extends CardImpl {
|
|||
new VentureIntoTheDungeonEffect(), new GenericManaCost(3)
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addHint(CurrentDungeonHint.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import mage.abilities.condition.common.CompletedDungeonCondition;
|
|||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -36,7 +37,8 @@ public final class EccentricApprentice extends CardImpl {
|
|||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// When Eccentric Apprentice enters the battlefield, venture into the dungeon.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// At the beginning of combat on your turn, if you've completed a dungeon, up to one target creature becomes a Bird with base power and toughness 1/1 and flying until end of turn.
|
||||
Ability ability = new ConditionalInterveningIfTriggeredAbility(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import mage.abilities.LoyaltyAbility;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.GetEmblemEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
|
|
@ -29,7 +30,8 @@ public final class EllywickTumblestrum extends CardImpl {
|
|||
this.setStartingLoyalty(4);
|
||||
|
||||
// +1: Venture into the dungeon.
|
||||
this.addAbility(new LoyaltyAbility(new VentureIntoTheDungeonEffect(), 1));
|
||||
this.addAbility(new LoyaltyAbility(new VentureIntoTheDungeonEffect(), 1)
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// −2: Look at the top six cards of your library. You may reveal a creature card from among them and put it into your hand. If it's legendary, you gain 3 life. Put the rest on the bottom of your library in a random order.
|
||||
this.addAbility(new LoyaltyAbility(new EllywickTumblestrumEffect(), -2));
|
||||
|
|
|
|||
|
|
@ -93,13 +93,13 @@ public final class ElugeTheShorelessSea extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
enum ElugeTheShorelessSeaPredicate implements ObjectSourcePlayerPredicate<Controllable> {
|
||||
enum ElugeTheShorelessSeaPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<Controllable> input, Game game) {
|
||||
if (input.getObject() instanceof Card &&
|
||||
((Card) input.getObject()).isInstantOrSorcery(game)) {
|
||||
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||
if (input.getObject() != null &&
|
||||
input.getObject().isInstantOrSorcery(game)) {
|
||||
ElugeTheShorelessSeaWatcher watcher = game.getState().getWatcher(ElugeTheShorelessSeaWatcher.class);
|
||||
return watcher != null &&
|
||||
watcher.getInstantOrSorcerySpellsCastThisTurn(input.getPlayerId()) == 0;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package mage.cards.f;
|
|||
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -24,6 +25,7 @@ public final class FatesReversal extends CardImpl {
|
|||
0, 1, StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD
|
||||
));
|
||||
this.getSpellAbility().addEffect(new VentureIntoTheDungeonEffect().concatBy("."));
|
||||
this.getSpellAbility().addHint(CurrentDungeonHint.instance);
|
||||
}
|
||||
|
||||
private FatesReversal(final FatesReversal card) {
|
||||
|
|
|
|||
99
Mage.Sets/src/mage/cards/f/FearOfBurningAlive.java
Normal file
99
Mage.Sets/src/mage/cards/f/FearOfBurningAlive.java
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.common.DeliriumCondition;
|
||||
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
||||
import mage.abilities.effects.common.DamagePlayersEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.hint.common.CardTypesInGraveyardHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class FearOfBurningAlive extends CardImpl {
|
||||
|
||||
public FearOfBurningAlive(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{4}{R}{R}");
|
||||
|
||||
this.subtype.add(SubType.NIGHTMARE);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// When Fear of Burning Alive enters, it deals 4 damage to each opponent.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(
|
||||
new DamagePlayersEffect(4, TargetController.OPPONENT, "it")
|
||||
));
|
||||
|
||||
// Delirium -- Whenever a source you control deals noncombat damage to an opponent, if there are four or more card types among cards in your graveyard, Fear of Burning Alive deals that amount of damage to target creature that player controls.
|
||||
this.addAbility(new FearOfBurningAliveTriggeredAbility());
|
||||
}
|
||||
|
||||
private FearOfBurningAlive(final FearOfBurningAlive card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FearOfBurningAlive copy() {
|
||||
return new FearOfBurningAlive(this);
|
||||
}
|
||||
}
|
||||
|
||||
class FearOfBurningAliveTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
FearOfBurningAliveTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new DamageTargetEffect(SavedDamageValue.MANY)
|
||||
.setText("{this} deals that amount of damage to target creature that player controls"));
|
||||
this.setTriggerPhrase("Whenever a source you control deals noncombat damage to an opponent, " +
|
||||
"if there are four or more card types among cards in your graveyard, ");
|
||||
this.setAbilityWord(AbilityWord.DELIRIUM);
|
||||
this.addHint(CardTypesInGraveyardHint.YOU);
|
||||
}
|
||||
|
||||
private FearOfBurningAliveTriggeredAbility(final FearOfBurningAliveTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FearOfBurningAliveTriggeredAbility copy() {
|
||||
return new FearOfBurningAliveTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (((DamagedEvent) event).isCombatDamage()
|
||||
|| !isControlledBy(game.getControllerId(event.getSourceId()))
|
||||
|| !game.getOpponents(getControllerId()).contains(event.getTargetId())) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().setValue("damage", event.getAmount());
|
||||
FilterPermanent filter = new FilterCreaturePermanent();
|
||||
filter.add(new ControllerIdPredicate(event.getTargetId()));
|
||||
this.getTargets().clear();
|
||||
this.addTarget(new TargetPermanent(filter));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
return DeliriumCondition.instance.apply(game, this);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ import mage.filter.StaticFilters;
|
|||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class FeastingHobbit extends CardImpl {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import mage.abilities.costs.mana.ManaCostsImpl;
|
|||
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
|
||||
import mage.abilities.effects.common.combat.CantBlockTargetEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -44,6 +45,7 @@ public final class FiftyFeetOfRope extends CardImpl {
|
|||
// Rappel Down — {4}, {T}: Venture into the dungeon. Activate only as a sorcery.
|
||||
ability = new ActivateAsSorceryActivatedAbility(new VentureIntoTheDungeonEffect(), new ManaCostsImpl<>("{4}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addHint(CurrentDungeonHint.instance);
|
||||
this.addAbility(ability.withFlavorWord("Rappel Down"));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import mage.abilities.costs.common.TapSourceCost;
|
|||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -36,7 +37,8 @@ public final class FindThePath extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// When Find the Path enters the battlefield, venture into the dungeon.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// Enchanted land has "{T}: Add {G}{G}."
|
||||
this.addAbility(new SimpleStaticAbility(new GainAbilityAttachedEffect(
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@ public final class FlameOfAnor extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{R}");
|
||||
|
||||
// Choose one. If you control a Wizard as you cast this spell, you may choose two instead.
|
||||
this.getSpellAbility().getModes().setMoreCondition(condition);
|
||||
this.getSpellAbility().getModes().setMoreLimit(2);
|
||||
this.getSpellAbility().getModes().setMoreCondition(2, condition);
|
||||
this.getSpellAbility().getModes().setChooseText(
|
||||
"Choose one. If you control a Wizard as you cast this spell, you may choose two instead."
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.SubType;
|
||||
|
|
@ -43,6 +44,7 @@ public final class Fly extends CardImpl {
|
|||
new DealsCombatDamageToAPlayerTriggeredAbility(new VentureIntoTheDungeonEffect(), false),
|
||||
AttachmentType.AURA).setText("and \"Whenever this creature deals combat damage to a player, venture into the dungeon.\"")
|
||||
);
|
||||
ability.addHint(CurrentDungeonHint.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
|||
90
Mage.Sets/src/mage/cards/f/ForsakenCrossroads.java
Normal file
90
Mage.Sets/src/mage/cards/f/ForsakenCrossroads.java
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AsEntersBattlefieldAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ChooseColorEffect;
|
||||
import mage.abilities.effects.keyword.ScryEffect;
|
||||
import mage.abilities.effects.mana.AddManaChosenColorEffect;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
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.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Svyatoslav28
|
||||
*/
|
||||
public final class ForsakenCrossroads extends CardImpl {
|
||||
|
||||
public ForsakenCrossroads(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||
|
||||
|
||||
// Forsaken Crossroads enters tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// As Forsaken Crossroads enters, choose a color.
|
||||
this.addAbility(new AsEntersBattlefieldAbility(new ChooseColorEffect(Outcome.Neutral)));
|
||||
|
||||
// When Forskaken Crossroads enters, scry 1. If you weren’t the starting player, you may untap Forsaken Crossroads instead.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new ForsakenCrossroadsEffect()));
|
||||
|
||||
// {T}: Add one mana of the chosen color.
|
||||
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaChosenColorEffect(), new TapSourceCost()));
|
||||
}
|
||||
|
||||
private ForsakenCrossroads(final ForsakenCrossroads card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForsakenCrossroads copy() {
|
||||
return new ForsakenCrossroads(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ForsakenCrossroadsEffect extends OneShotEffect {
|
||||
|
||||
ForsakenCrossroadsEffect() {
|
||||
super(Outcome.PutCardInPlay);
|
||||
this.staticText = "scry 1. If you weren't the starting player, you may untap {this} instead.";
|
||||
}
|
||||
|
||||
private ForsakenCrossroadsEffect(final ForsakenCrossroadsEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForsakenCrossroadsEffect copy() {
|
||||
return new ForsakenCrossroadsEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null && !controller.getId().equals(game.getStartingPlayerId())) {
|
||||
if (controller.chooseUse(Outcome.Untap, "Untap {this} instead of scrying 1?", "", "Untap", "Scry 1", source, game)) {
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
permanent.untap(game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
OneShotEffect scryEffect = new ScryEffect(1);
|
||||
scryEffect.apply(game, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
50
Mage.Sets/src/mage/cards/f/FoundFootage.java
Normal file
50
Mage.Sets/src/mage/cards/f/FoundFootage.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.continuous.LookAtOpponentFaceDownCreaturesAnyTimeEffect;
|
||||
import mage.abilities.effects.keyword.SurveilEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.TargetController;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class FoundFootage extends CardImpl {
|
||||
|
||||
public FoundFootage(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}");
|
||||
|
||||
this.subtype.add(SubType.CLUE);
|
||||
|
||||
// You may look at face-down creatures your opponents control any time.
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
new LookAtOpponentFaceDownCreaturesAnyTimeEffect(Duration.WhileOnBattlefield, TargetController.OPPONENT)
|
||||
));
|
||||
|
||||
// {2}, Sacrifice Found Footage: Surveil 2, then draw a card.
|
||||
Ability ability = new SimpleActivatedAbility(new SurveilEffect(2, false), new GenericManaCost(2));
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
ability.addEffect(new DrawCardSourceControllerEffect(1).concatBy(", then"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private FoundFootage(final FoundFootage card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FoundFootage copy() {
|
||||
return new FoundFootage(this);
|
||||
}
|
||||
}
|
||||
33
Mage.Sets/src/mage/cards/g/Glimmerburst.java
Normal file
33
Mage.Sets/src/mage/cards/g/Glimmerburst.java
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package mage.cards.g;
|
||||
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.game.permanent.token.GlimmerToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class Glimmerburst extends CardImpl {
|
||||
|
||||
public Glimmerburst(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{U}");
|
||||
|
||||
// Draw two cards. Create a 1/1 white Glimmer enchantment creature token.
|
||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new CreateTokenEffect(new GlimmerToken()));
|
||||
}
|
||||
|
||||
private Glimmerburst(final Glimmerburst card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Glimmerburst copy() {
|
||||
return new Glimmerburst(this);
|
||||
}
|
||||
}
|
||||
61
Mage.Sets/src/mage/cards/h/HauntedScreen.java
Normal file
61
Mage.Sets/src/mage/cards/h/HauntedScreen.java
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.ActivateOncePerGameActivatedAbility;
|
||||
import mage.abilities.costs.common.PayLifeCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class HauntedScreen extends CardImpl {
|
||||
|
||||
public HauntedScreen(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
// {T}: Add {W} or {B}.
|
||||
this.addAbility(new WhiteManaAbility());
|
||||
this.addAbility(new BlackManaAbility());
|
||||
|
||||
// {T}, Pay 1 life: Add {G}, {U}, or {R}.
|
||||
Ability ability = new GreenManaAbility();
|
||||
ability.addCost(new PayLifeCost(1));
|
||||
this.addAbility(ability);
|
||||
ability = new BlueManaAbility();
|
||||
ability.addCost(new PayLifeCost(1));
|
||||
this.addAbility(ability);
|
||||
ability = new RedManaAbility();
|
||||
ability.addCost(new PayLifeCost(1));
|
||||
this.addAbility(ability);
|
||||
|
||||
// {7}: Put seven +1/+1 counters on Haunted Screen. It becomes a 0/0 Spirit creature in addition to its other types. Activate only once.
|
||||
ability = new ActivateOncePerGameActivatedAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(7)), new GenericManaCost(7)
|
||||
);
|
||||
ability.addEffect(new BecomesCreatureSourceEffect(new CreatureToken(
|
||||
0, 0, "0/0 Spirit creature", SubType.SPIRIT
|
||||
), CardType.ARTIFACT, Duration.Custom).withKeepCreatureSubtypes(true));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private HauntedScreen(final HauntedScreen card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HauntedScreen copy() {
|
||||
return new HauntedScreen(this);
|
||||
}
|
||||
}
|
||||
72
Mage.Sets/src/mage/cards/h/HollowhengeWrangler.java
Normal file
72
Mage.Sets/src/mage/cards/h/HollowhengeWrangler.java
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.ActivateIfConditionActivatedAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.common.DiscardCardCost;
|
||||
import mage.abilities.effects.common.ConjureCardEffect;
|
||||
import mage.abilities.effects.common.SeekCardEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Svyatoslav28
|
||||
*/
|
||||
|
||||
public final class HollowhengeWrangler extends CardImpl {
|
||||
|
||||
public HollowhengeWrangler(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}");
|
||||
|
||||
this.subtype.add(SubType.ELEMENTAL);
|
||||
this.power = new MageInt(6);
|
||||
this.toughness = new MageInt(6);
|
||||
|
||||
// When Hollowhenge Wrangler enters the battlefield, seek a land card.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new SeekCardEffect(StaticFilters.FILTER_CARD_LAND)));
|
||||
|
||||
// Discard a land card: Conjure a card named Hollowhenge Beast into your hand.
|
||||
// You may also activate this ability while Hollowhenge Wrangler is in your graveyard.
|
||||
Ability ability = new ActivateIfConditionActivatedAbility(
|
||||
Zone.ALL, new ConjureCardEffect("Hollowhenge Beast"), new DiscardCardCost(StaticFilters.FILTER_CARD_LAND), HollowhengeWranglerCondition.instance
|
||||
);
|
||||
this.addAbility(ability);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private HollowhengeWrangler(final HollowhengeWrangler card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HollowhengeWrangler copy() {
|
||||
return new HollowhengeWrangler(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum HollowhengeWranglerCondition implements Condition {
|
||||
instance;
|
||||
private static final List<Zone> zones = Arrays.asList(Zone.BATTLEFIELD, Zone.GRAVEYARD);
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return zones.contains(game.getState().getZone(source.getSourceId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "You may also activate this ability while {this} is in your graveyard";
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import mage.abilities.costs.mana.ManaCostsImpl;
|
|||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.InspiredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -38,7 +39,8 @@ public final class ImmovableRod extends CardImpl {
|
|||
this.addAbility(new SkipUntapOptionalAbility());
|
||||
|
||||
// Whenever Immovable Rod becomes untapped, venture into the dungeon.
|
||||
this.addAbility(new InspiredAbility(new VentureIntoTheDungeonEffect(), false, false));
|
||||
this.addAbility(new InspiredAbility(new VentureIntoTheDungeonEffect(), false, false)
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// {3}{W}, {T}: For as long as Immovable Rod remains tapped, another target permanent loses all abilities and can't attack or block.
|
||||
Ability ability = new SimpleActivatedAbility(new ImmovableRodAbilityEffect(), new ManaCostsImpl<>("{3}{W}"));
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public final class ImposterMech extends CardImpl {
|
|||
|
||||
// You may have Imposter Mech enter the battlefield as a copy of a creature an opponent controls, except its a Vehicle artifact with crew 3 and it loses all other card types.
|
||||
this.addAbility(new EntersBattlefieldAbility(
|
||||
new CopyPermanentEffect(StaticFilters.FILTER_OPPONENTS_PERMANENT_A_CREATURE, applier),
|
||||
new CopyPermanentEffect(StaticFilters.FILTER_OPPONENTS_PERMANENT_A_CREATURE, applier), true,
|
||||
null, "You may have {this} enter the battlefield as a copy of a creature " +
|
||||
"an opponent controls, except it's a Vehicle artifact with crew 3 and it loses all other card types.", null
|
||||
));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.cards.i;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -15,9 +14,7 @@ import mage.players.Player;
|
|||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.XTargetsCountAdjuster;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
|
@ -67,37 +64,48 @@ class IndomitableCreativityEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
List<Permanent> destroyedPermanents = new ArrayList<>();
|
||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
Permanent target = game.getPermanent(targetId);
|
||||
if (target != null) {
|
||||
if (target.destroy(source, game, false)) {
|
||||
destroyedPermanents.add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Permanent permanent : destroyedPermanents) {
|
||||
Player controllerOfDestroyedCreature = game.getPlayer(permanent.getControllerId());
|
||||
if (controllerOfDestroyedCreature != null) {
|
||||
Library library = controllerOfDestroyedCreature.getLibrary();
|
||||
if (library.hasCards()) {
|
||||
Cards cardsToReaveal = new CardsImpl();
|
||||
for (Card card : library.getCards(game)) {
|
||||
cardsToReaveal.add(card);
|
||||
if (card.isCreature(game) || card.isArtifact(game)) {
|
||||
controllerOfDestroyedCreature.moveCards(card, Zone.EXILED, source, game);
|
||||
controllerOfDestroyedCreature.moveCards(card, Zone.BATTLEFIELD, source, game);
|
||||
break;
|
||||
}
|
||||
}
|
||||
controllerOfDestroyedCreature.revealCards(source, " for destroyed " + permanent.getIdName(), cardsToReaveal, game);
|
||||
controllerOfDestroyedCreature.shuffleLibrary(source, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
List<Permanent> destroyedPermanents = new ArrayList<>();
|
||||
for (UUID targetId : getTargetPointer().getTargets(game, source)) {
|
||||
Permanent target = game.getPermanent(targetId);
|
||||
if (target != null && target.destroy(source, game, false)) {
|
||||
destroyedPermanents.add(target);
|
||||
}
|
||||
}
|
||||
if (destroyedPermanents.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
game.processAction();
|
||||
Map<UUID, Set<Card>> playerToBattlefield = new HashMap<>();
|
||||
for (Permanent permanent : destroyedPermanents) {
|
||||
Player controllerOfDestroyedCreature = game.getPlayer(permanent.getControllerId());
|
||||
if (controllerOfDestroyedCreature != null) {
|
||||
Library library = controllerOfDestroyedCreature.getLibrary();
|
||||
if (library.hasCards()) {
|
||||
playerToBattlefield.computeIfAbsent(controllerOfDestroyedCreature.getId(), x -> new HashSet<>());
|
||||
Cards cardsToReveal = new CardsImpl();
|
||||
for (Card card : library.getCards(game)) {
|
||||
cardsToReveal.add(card);
|
||||
if (card.isCreature(game) || card.isArtifact(game)) {
|
||||
controllerOfDestroyedCreature.moveCards(card, Zone.EXILED, source, game);
|
||||
playerToBattlefield.computeIfAbsent(controllerOfDestroyedCreature.getId(), x -> new HashSet<>()).add(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
controllerOfDestroyedCreature.revealCards(source, " for destroyed " + permanent.getIdName(), cardsToReveal, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
game.processAction();
|
||||
for (Map.Entry<UUID, Set<Card>> entry: playerToBattlefield.entrySet()) {
|
||||
Player player = game.getPlayer(entry.getKey());
|
||||
if (player != null) {
|
||||
player.moveCards(entry.getValue(), Zone.BATTLEFIELD, source, game);
|
||||
player.shuffleLibrary(source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package mage.cards.i;
|
|||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.PackTacticsAbility;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -28,7 +29,8 @@ public final class IntrepidOutlander extends CardImpl {
|
|||
this.addAbility(ReachAbility.getInstance());
|
||||
|
||||
// Pack tactics — Whenever Intrepid Outlander attacks, if you attacked with creatures with total power 6 or greater this combat, venture into the dungeon.
|
||||
this.addAbility(new PackTacticsAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new PackTacticsAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
}
|
||||
|
||||
private IntrepidOutlander(final IntrepidOutlander card) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public final class JeskasWill extends CardImpl {
|
|||
this.getSpellAbility().getModes().setChooseText(
|
||||
"Choose one. If you control a commander as you cast this spell, you may choose both instead."
|
||||
);
|
||||
this.getSpellAbility().getModes().setMoreCondition(ControlACommanderCondition.instance);
|
||||
this.getSpellAbility().getModes().setMoreCondition(2, ControlACommanderCondition.instance);
|
||||
|
||||
// • Add {R} for each card in target opponent's hand.
|
||||
this.getSpellAbility().addEffect(new JeskasWillEffect());
|
||||
|
|
|
|||
47
Mage.Sets/src/mage/cards/j/JumpScare.java
Normal file
47
Mage.Sets/src/mage/cards/j/JumpScare.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package mage.cards.j;
|
||||
|
||||
import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.AddCardTypeTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class JumpScare extends CardImpl {
|
||||
|
||||
public JumpScare(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}");
|
||||
|
||||
// Until end of turn, target creature gets +2/+2, gains flying, and becomes a Horror enchantment creature in addition to its other types.
|
||||
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2)
|
||||
.setText("until end of turn, target creature gets +2/+2"));
|
||||
this.getSpellAbility().addEffect(new GainAbilityTargetEffect(FlyingAbility.getInstance())
|
||||
.setText(", gains flying"));
|
||||
this.getSpellAbility().addEffect(new AddCardSubTypeTargetEffect(
|
||||
SubType.HORROR, Duration.EndOfTurn
|
||||
).setText(", and becomes"));
|
||||
this.getSpellAbility().addEffect(new AddCardTypeTargetEffect(
|
||||
Duration.EndOfTurn, CardType.ENCHANTMENT, CardType.CREATURE
|
||||
).setText(" a Horror enchantment creature in addition to its other types"));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
}
|
||||
|
||||
private JumpScare(final JumpScare card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JumpScare copy() {
|
||||
return new JumpScare(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ public final class KamahlsWill extends CardImpl {
|
|||
this.getSpellAbility().getModes().setChooseText(
|
||||
"Choose one. If you control a commander as you cast this spell, you may choose both."
|
||||
);
|
||||
this.getSpellAbility().getModes().setMoreCondition(ControlACommanderCondition.instance);
|
||||
this.getSpellAbility().getModes().setMoreCondition(2, ControlACommanderCondition.instance);
|
||||
|
||||
// • Until end of turn, any number of target lands you control become 1/1 Elemental creatures with vigilance, indestructible, and haste. They're still lands.
|
||||
this.getSpellAbility().addEffect(new BecomesCreatureTargetEffect(
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@
|
|||
package mage.cards.k;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.DamageControllerEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -24,10 +20,10 @@ public final class KarplusanForest extends CardImpl {
|
|||
|
||||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
Ability redManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.RedMana(1), new TapSourceCost());
|
||||
Ability redManaAbility = new RedManaAbility();
|
||||
redManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(redManaAbility);
|
||||
Ability greenManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana(1), new TapSourceCost());
|
||||
Ability greenManaAbility = new GreenManaAbility();
|
||||
greenManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(greenManaAbility);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityControllerEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.HexproofAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -35,7 +36,7 @@ public final class KeenEaredSentry extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(new GainAbilityControllerEffect(HexproofAbility.getInstance())));
|
||||
|
||||
// Your opponents can't venture into the dungeon more than once each turn.
|
||||
this.addAbility(new SimpleStaticAbility(new KeenEaredSentryEffect()), new KeenEaredSentryWatcher());
|
||||
this.addAbility(new SimpleStaticAbility(new KeenEaredSentryEffect()).addHint(CurrentDungeonHint.instance), new KeenEaredSentryWatcher());
|
||||
}
|
||||
|
||||
private KeenEaredSentry(final KeenEaredSentry card) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import mage.abilities.effects.common.combat.CantBeBlockedTargetEffect;
|
|||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -40,6 +41,7 @@ public final class KickInTheDoor extends CardImpl {
|
|||
.setText("and can't be blocked by Walls this turn")
|
||||
);
|
||||
this.getSpellAbility().addEffect(new VentureIntoTheDungeonEffect());
|
||||
this.getSpellAbility().addHint(CurrentDungeonHint.instance);
|
||||
}
|
||||
|
||||
private KickInTheDoor(final KickInTheDoor card) {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public final class KlauthsWill extends CardImpl {
|
|||
this.getSpellAbility().getModes().setChooseText(
|
||||
"Choose one. If you control a commander as you cast this spell, you may choose both."
|
||||
);
|
||||
this.getSpellAbility().getModes().setMoreCondition(ControlACommanderCondition.instance);
|
||||
this.getSpellAbility().getModes().setMoreCondition(2, ControlACommanderCondition.instance);
|
||||
|
||||
// • Breathe Flame — Klauth's Will deals X damage to each creature without flying.
|
||||
this.getSpellAbility().addEffect(new DamageAllEffect(GetXValue.instance, filter));
|
||||
|
|
@ -76,4 +76,4 @@ enum KlauthsWillAdjuster implements TargetAdjuster {
|
|||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package mage.cards.l;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
|
|
@ -14,14 +12,16 @@ import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
|||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author grimreap124
|
||||
*/
|
||||
|
|
@ -31,7 +31,7 @@ public final class LeonardoDaVinci extends CardImpl {
|
|||
|
||||
static {
|
||||
filter.add(SubType.THOPTER.getPredicate());
|
||||
filter.add(TargetController.YOU.getPlayerPredicate());
|
||||
filter.add(TargetController.YOU.getControllerPredicate());
|
||||
}
|
||||
|
||||
public LeonardoDaVinci(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
|
@ -112,4 +112,4 @@ class LeonardoDaVinciEffect extends OneShotEffect {
|
|||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public final class LetsPlayAGame extends CardImpl {
|
|||
this.getSpellAbility().getModes().setChooseText(
|
||||
"choose one. If there are four or more card types among cards in your graveyard, choose one or more instead."
|
||||
);
|
||||
this.getSpellAbility().getModes().setMoreCondition(DeliriumCondition.instance);
|
||||
this.getSpellAbility().getModes().setMoreCondition(3, DeliriumCondition.instance);
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.DELIRIUM);
|
||||
this.getSpellAbility().addHint(CardTypesInGraveyardHint.YOU);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@
|
|||
package mage.cards.l;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.common.DamageControllerEffect;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.abilities.mana.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -26,10 +22,10 @@ public final class LlanowarWastes extends CardImpl {
|
|||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
// Tap: Add Black or Green. Llanowar Wastes deals 1 damage to you.
|
||||
Ability blackManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.BlackMana(1), new TapSourceCost());
|
||||
Ability blackManaAbility = new BlackManaAbility();
|
||||
blackManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(blackManaAbility);
|
||||
Ability greenManaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana(1), new TapSourceCost());
|
||||
Ability greenManaAbility = new GreenManaAbility();
|
||||
greenManaAbility.addEffect(new DamageControllerEffect(1));
|
||||
this.addAbility(greenManaAbility);
|
||||
}
|
||||
|
|
|
|||
87
Mage.Sets/src/mage/cards/m/MarvinMurderousMimic.java
Normal file
87
Mage.Sets/src/mage/cards/m/MarvinMurderousMimic.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class MarvinMurderousMimic extends CardImpl {
|
||||
|
||||
public MarvinMurderousMimic(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.TOY);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Marvin, Murderous Mimic has all activated abilities of creatures you control that don't have the same name as this creature.
|
||||
this.addAbility(new SimpleStaticAbility(new MarvinMurderousMimicEffect()));
|
||||
}
|
||||
|
||||
private MarvinMurderousMimic(final MarvinMurderousMimic card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarvinMurderousMimic copy() {
|
||||
return new MarvinMurderousMimic(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MarvinMurderousMimicEffect extends ContinuousEffectImpl {
|
||||
|
||||
MarvinMurderousMimicEffect() {
|
||||
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
|
||||
staticText = "{this} has all activated abilities of creatures " +
|
||||
"you control that don't have the same name as this creature";
|
||||
}
|
||||
|
||||
private MarvinMurderousMimicEffect(final MarvinMurderousMimicEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MarvinMurderousMimicEffect copy() {
|
||||
return new MarvinMurderousMimicEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
List<Ability> abilities = game
|
||||
.getBattlefield()
|
||||
.getActivePermanents(
|
||||
StaticFilters.FILTER_CONTROLLED_CREATURE,
|
||||
source.getControllerId(), source, game
|
||||
)
|
||||
.stream()
|
||||
.filter(p -> !CardUtil.haveSameNames(p, permanent))
|
||||
.map(p -> p.getAbilities(game))
|
||||
.flatMap(Collection::stream)
|
||||
.filter(Ability::isActivatedAbility)
|
||||
.collect(Collectors.toList());
|
||||
for (Ability ability : abilities) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -71,13 +71,13 @@ public final class MelekReforgedResearcher extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
enum MelekReforgedResearcherPredicate implements ObjectSourcePlayerPredicate<Controllable> {
|
||||
enum MelekReforgedResearcherPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(ObjectSourcePlayer<Controllable> input, Game game) {
|
||||
if (input.getObject() instanceof Card &&
|
||||
((Card) input.getObject()).isInstantOrSorcery(game)) {
|
||||
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||
if (input.getObject() != null &&
|
||||
input.getObject().isInstantOrSorcery(game)) {
|
||||
MelekReforgedResearcherWatcher watcher = game.getState().getWatcher(MelekReforgedResearcherWatcher.class);
|
||||
return watcher != null &&
|
||||
watcher.getInstantOrSorcerySpellsCastThisTurn(input.getPlayerId()) == 0;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import mage.abilities.common.DealCombatDamageControlledTriggeredAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesAllEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -44,7 +45,8 @@ public final class MidnightPathlighter extends CardImpl {
|
|||
)));
|
||||
|
||||
// Whenever one or more creatures you control deal combat damage to a player, venture into the dungeon.
|
||||
this.addAbility(new DealCombatDamageControlledTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new DealCombatDamageControlledTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
}
|
||||
|
||||
private MidnightPathlighter(final MidnightPathlighter card) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import mage.abilities.effects.common.discard.LookTargetHandChooseDiscardEffect;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -18,7 +19,7 @@ public final class MindWarp extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{3}{B}");
|
||||
|
||||
// Look at target player's hand and choose X cards from it. That player discards those cards.
|
||||
this.getSpellAbility().addEffect(new LookTargetHandChooseDiscardEffect(false, GetXValue.instance));
|
||||
this.getSpellAbility().addEffect(new LookTargetHandChooseDiscardEffect(false, GetXValue.instance, StaticFilters.FILTER_CARD_CARDS));
|
||||
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public final class MoltenCollapse extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{B}{R}");
|
||||
|
||||
// Choose one. If you descended this turn, you may choose both instead.
|
||||
this.getSpellAbility().getModes().setMoreCondition(DescendedThisTurnCondition.instance);
|
||||
this.getSpellAbility().getModes().setMoreCondition(2, DescendedThisTurnCondition.instance);
|
||||
this.getSpellAbility().getModes().setChooseText(
|
||||
"Choose one. If you descended this turn, you may choose both instead."
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import mage.abilities.condition.common.CompletedDungeonCondition;
|
|||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -36,7 +37,8 @@ public final class NadaarSelflessPaladin extends CardImpl {
|
|||
this.addAbility(VigilanceAbility.getInstance());
|
||||
|
||||
// Whenever Nadaar, Selfless Paladin enters the battlefield or attacks, venture into the dungeon.
|
||||
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// Other creatures you control get +1/+1 as long as you've completed a dungeon.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
|
|
|
|||
104
Mage.Sets/src/mage/cards/n/NardoleResourcefulCyborg.java
Normal file
104
Mage.Sets/src/mage/cards/n/NardoleResourcefulCyborg.java
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.effects.mana.ManaEffect;
|
||||
import mage.abilities.mana.SimpleManaAbility;
|
||||
import mage.abilities.mana.builder.ConditionalManaBuilder;
|
||||
import mage.abilities.mana.conditional.ConditionalSpellManaBuilder;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.abilities.keyword.UndyingAbility;
|
||||
import mage.abilities.keyword.DoctorsCompanionAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* @author Cguy7777
|
||||
*/
|
||||
public final class NardoleResourcefulCyborg extends CardImpl {
|
||||
|
||||
public NardoleResourcefulCyborg(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{1}{U}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.SCIENTIST);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// {T}: Add {U} for each counter on Nardole. Spend this mana only to cast noncreature spells.
|
||||
this.addAbility(new SimpleManaAbility(new NardoleResourcefulCyborgManaEffect(), new TapSourceCost()));
|
||||
|
||||
// Undying
|
||||
this.addAbility(new UndyingAbility());
|
||||
|
||||
// Doctor's companion
|
||||
this.addAbility(DoctorsCompanionAbility.getInstance());
|
||||
}
|
||||
|
||||
private NardoleResourcefulCyborg(final NardoleResourcefulCyborg card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NardoleResourcefulCyborg copy() {
|
||||
return new NardoleResourcefulCyborg(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NardoleResourcefulCyborgManaEffect extends ManaEffect {
|
||||
|
||||
private final ConditionalManaBuilder manaBuilder
|
||||
= new ConditionalSpellManaBuilder(StaticFilters.FILTER_SPELLS_NON_CREATURE);
|
||||
|
||||
NardoleResourcefulCyborgManaEffect() {
|
||||
this.staticText = "Add {U} for each counter on {this}. " + manaBuilder.getRule();
|
||||
}
|
||||
|
||||
private NardoleResourcefulCyborgManaEffect(final NardoleResourcefulCyborgManaEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mana> getNetMana(Game game, Ability source) {
|
||||
List<Mana> netMana = new ArrayList<>();
|
||||
if (game == null) {
|
||||
return netMana;
|
||||
}
|
||||
Permanent permanent = source.getSourcePermanentOrLKI(game);
|
||||
if (permanent != null) {
|
||||
netMana.add(manaBuilder.setMana(
|
||||
Mana.BlueMana(permanent.getCounters(game).getTotalCount()), source, game).build());
|
||||
}
|
||||
return netMana;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mana produceMana(Game game, Ability source) {
|
||||
Mana mana = new Mana();
|
||||
if (game == null) {
|
||||
return mana;
|
||||
}
|
||||
Permanent permanent = source.getSourcePermanentOrLKI(game);
|
||||
if (permanent == null) {
|
||||
return mana;
|
||||
}
|
||||
return manaBuilder.setMana(
|
||||
Mana.BlueMana(permanent.getCounters(game).getTotalCount()), source, game).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NardoleResourcefulCyborgManaEffect copy() {
|
||||
return new NardoleResourcefulCyborgManaEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,22 +2,17 @@ package mage.cards.n;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedPlayerEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.filter.StaticFilters;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -36,7 +31,12 @@ public final class NecropolisRegent extends CardImpl {
|
|||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever a creature you control deals combat damage to a player, put that many +1/+1 counters on it.
|
||||
this.addAbility(new NecropolisRegentTriggeredAbility());
|
||||
this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance(), SavedDamageValue.MANY)
|
||||
.setText("put that many +1/+1 counters on it"),
|
||||
StaticFilters.FILTER_CONTROLLED_A_CREATURE,
|
||||
false, SetTargetPointer.PERMANENT, true
|
||||
));
|
||||
}
|
||||
|
||||
private NecropolisRegent(final NecropolisRegent card) {
|
||||
|
|
@ -48,44 +48,3 @@ public final class NecropolisRegent extends CardImpl {
|
|||
return new NecropolisRegent(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NecropolisRegentTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public NecropolisRegentTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.QUEST.createInstance()), false);
|
||||
}
|
||||
|
||||
private NecropolisRegentTriggeredAbility(final NecropolisRegentTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NecropolisRegentTriggeredAbility copy() {
|
||||
return new NecropolisRegentTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (((DamagedPlayerEvent) event).isCombatDamage()) {
|
||||
Permanent creature = game.getPermanent(event.getSourceId());
|
||||
if (creature != null && creature.isControlledBy(controllerId)) {
|
||||
this.getEffects().clear();
|
||||
Effect effect = new AddCountersTargetEffect(CounterType.P1P1.createInstance(event.getAmount()));
|
||||
effect.setTargetPointer(new FixedTarget(creature.getId(), game));
|
||||
this.addEffect(effect);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a creature you control deals combat damage to a player, put that many +1/+1 counters on it.";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
87
Mage.Sets/src/mage/cards/n/NorinSwiftSurvivalist.java
Normal file
87
Mage.Sets/src/mage/cards/n/NorinSwiftSurvivalist.java
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BecomesBlockedAllTriggeredAbility;
|
||||
import mage.abilities.common.CantBlockAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class NorinSwiftSurvivalist extends CardImpl {
|
||||
|
||||
public NorinSwiftSurvivalist(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.COWARD);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Norin, Swift Survivalist can't block.
|
||||
this.addAbility(new CantBlockAbility());
|
||||
|
||||
// Whenever a creature you control becomes blocked, you may exile it. You may play that card from exile this turn.
|
||||
this.addAbility(new BecomesBlockedAllTriggeredAbility(
|
||||
new NorinSwiftSurvivalistEffect(), true,
|
||||
StaticFilters.FILTER_CONTROLLED_A_CREATURE, true
|
||||
));
|
||||
}
|
||||
|
||||
private NorinSwiftSurvivalist(final NorinSwiftSurvivalist card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NorinSwiftSurvivalist copy() {
|
||||
return new NorinSwiftSurvivalist(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NorinSwiftSurvivalistEffect extends OneShotEffect {
|
||||
|
||||
NorinSwiftSurvivalistEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "exile it. You may play that card from exile this turn";
|
||||
}
|
||||
|
||||
private NorinSwiftSurvivalistEffect(final NorinSwiftSurvivalistEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NorinSwiftSurvivalistEffect copy() {
|
||||
return new NorinSwiftSurvivalistEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (player == null || permanent == null) {
|
||||
return false;
|
||||
}
|
||||
Card card = permanent.getMainCard();
|
||||
player.moveCards(permanent, Zone.EXILED, source, game);
|
||||
if (card != null) {
|
||||
CardUtil.makeCardPlayable(
|
||||
game, source, card, false,
|
||||
Duration.EndOfTurn, false, player.getId(), null
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ public final class OverlordOfTheBalemurk extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Impending 5--{1}{B}
|
||||
this.addAbility(new ImpendingAbility("{1}{B}", 5));
|
||||
this.addAbility(new ImpendingAbility(5, "{1}{B}"));
|
||||
|
||||
// Whenever Overlord of the Balemurk enters or attacks, mill four cards, then you may return a non-Avatar creature card or a planeswalker card from your graveyard to your hand.
|
||||
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new MillCardsControllerEffect(4));
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public final class OverlordOfTheBoilerbilges extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Impending 4--{2}{R}{R}
|
||||
this.addAbility(new ImpendingAbility("{2}{R}{R}"));
|
||||
this.addAbility(new ImpendingAbility(4, "{2}{R}{R}"));
|
||||
|
||||
// Whenever Overlord of the Boilerbilges enters or attacks, it deals 4 damage to any target.
|
||||
Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DamageTargetEffect(4));
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public final class OverlordOfTheFloodpits extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// Impending 4--{1}{U}{U}
|
||||
this.addAbility(new ImpendingAbility("{1}{U}{U}"));
|
||||
this.addAbility(new ImpendingAbility(4, "{1}{U}{U}"));
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public final class OverlordOfTheHauntwoods extends CardImpl {
|
|||
this.toughness = new MageInt(5);
|
||||
|
||||
// Impending 4--{1}{G}{G}
|
||||
this.addAbility(new ImpendingAbility("{1}{G}{G}"));
|
||||
this.addAbility(new ImpendingAbility(4, "{1}{G}{G}"));
|
||||
|
||||
// Whenever Overlord of the Hauntwoods enters or attacks, create a tapped colorless land token named Everywhere that is every basic land type.
|
||||
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public final class OverlordOfTheMistmoors extends CardImpl {
|
|||
this.toughness = new MageInt(6);
|
||||
|
||||
// Impending 4--{2}{W}{W}
|
||||
this.addAbility(new ImpendingAbility("{2}{W}{W}"));
|
||||
this.addAbility(new ImpendingAbility(4, "{2}{W}{W}"));
|
||||
|
||||
// Whenever Overlord of the Mistmoors enters or attacks, create two 2/1 white Insect creature tokens with flying.
|
||||
this.addAbility(new EntersBattlefieldOrAttacksSourceTriggeredAbility(new CreateTokenEffect(new InsectWhiteToken(), 2)));
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import mage.game.ExileZone;
|
|||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.targetpointer.FixedTargets;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -118,7 +118,7 @@ class PartyThrasherEffect extends OneShotEffect {
|
|||
exileZone.setCleanupOnEndTurn(true);
|
||||
game.getExile().moveToAnotherZone(card, game, exileZone);
|
||||
game.addEffect(new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, Duration.EndOfTurn)
|
||||
.setTargetPointer(new FixedTargets(cards, game)), source);
|
||||
.setTargetPointer(new FixedTarget(card, game)), source);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
242
Mage.Sets/src/mage/cards/p/PhyrexianSplicer.java
Normal file
242
Mage.Sets/src/mage/cards/p/PhyrexianSplicer.java
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
package mage.cards.p;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.keyword.FirstStrikeAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.ShadowAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.AbilityPredicate;
|
||||
import mage.filter.predicate.other.AnotherTargetPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.StackAbility;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public final class PhyrexianSplicer extends CardImpl {
|
||||
|
||||
static final FilterCreaturePermanent filterLose = new FilterCreaturePermanent("creature with the chosen ability");
|
||||
private static final FilterCreaturePermanent filterGain = new FilterCreaturePermanent("another target creature");
|
||||
|
||||
static {
|
||||
filterLose.add(Predicates.or(
|
||||
new AbilityPredicate(FlyingAbility.class),
|
||||
new AbilityPredicate(FirstStrikeAbility.class),
|
||||
new AbilityPredicate(TrampleAbility.class),
|
||||
new AbilityPredicate(ShadowAbility.class)
|
||||
));
|
||||
filterLose.add(new AnotherTargetPredicate(1));
|
||||
|
||||
filterGain.add(new AnotherTargetPredicate(2));
|
||||
}
|
||||
|
||||
public PhyrexianSplicer(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
// {2}, {T}, Choose flying, first strike, trample, or shadow: Until end of turn, target creature with the chosen ability loses it and another target creature gains it.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PhyrexianSplicerEffect(), new ManaCostsImpl<>("{2}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new PhyrexianSplicerChooseCost());
|
||||
ability.addTarget(new TargetPermanent(filterLose).withChooseHint("to lose ability").setTargetTag(1));
|
||||
ability.addTarget(new TargetPermanent(filterGain).withChooseHint("to gain ability").setTargetTag(2));
|
||||
ability.addHint(PhyrexianSplicerCardHint.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private PhyrexianSplicer(final PhyrexianSplicer card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhyrexianSplicer copy() {
|
||||
return new PhyrexianSplicer(this);
|
||||
}
|
||||
}
|
||||
|
||||
class PhyrexianSplicerEffect extends OneShotEffect {
|
||||
|
||||
PhyrexianSplicerEffect() {
|
||||
super(Outcome.LoseAbility);
|
||||
this.staticText = "Until end of turn, target creature with the chosen ability loses it and another target creature gains it.";
|
||||
}
|
||||
|
||||
private PhyrexianSplicerEffect(final PhyrexianSplicerEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhyrexianSplicerEffect copy() {
|
||||
return new PhyrexianSplicerEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Ability loseAbility = findChosenAbility(source);
|
||||
if (loseAbility == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the target which is having the ability removed does not have that ability during the resolution of this
|
||||
// effect, then this effect still grants the chosen ability. The reason is that the second target is still
|
||||
// legal even if the first one is not.
|
||||
// (2004-10-04)
|
||||
|
||||
Permanent targetLose = game.getPermanent(source.getTargets().get(0).getFirstTarget());
|
||||
Permanent targetGain = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||
if (targetGain == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// lose
|
||||
if (targetLose != null) {
|
||||
ContinuousEffect effect = new LoseAbilityTargetEffect(loseAbility, Duration.EndOfTurn);
|
||||
effect.setTargetPointer(new FixedTarget(targetLose, game));
|
||||
game.addEffect(effect, source);
|
||||
}
|
||||
|
||||
// gain
|
||||
ContinuousEffect effect = new GainAbilityTargetEffect(loseAbility, Duration.EndOfTurn);
|
||||
effect.setTargetPointer(new FixedTarget(targetGain, game));
|
||||
game.addEffect(effect, source);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static Ability findChosenAbility(Ability source) {
|
||||
return CardUtil
|
||||
.castStream(source.getCosts().stream(), PhyrexianSplicerChooseCost.class)
|
||||
.map(PhyrexianSplicerChooseCost::getTargetedAbility)
|
||||
.filter(Objects::nonNull)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
class PhyrexianSplicerChooseCost extends CostImpl {
|
||||
|
||||
private static final Map<String, Ability> allChoices = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
allChoices.put("Flying", FlyingAbility.getInstance());
|
||||
allChoices.put("First Strike", FirstStrikeAbility.getInstance());
|
||||
allChoices.put("Trample", TrampleAbility.getInstance());
|
||||
allChoices.put("Shadow", ShadowAbility.getInstance());
|
||||
}
|
||||
|
||||
Ability targetedAbility = null;
|
||||
|
||||
public PhyrexianSplicerChooseCost() {
|
||||
this.text = "Choose flying, first strike, trample, or shadow";
|
||||
}
|
||||
|
||||
private PhyrexianSplicerChooseCost(final PhyrexianSplicerChooseCost cost) {
|
||||
super(cost);
|
||||
this.targetedAbility = cost.targetedAbility == null ? null : cost.targetedAbility.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
this.paid = false;
|
||||
this.targetedAbility = null;
|
||||
|
||||
Permanent losePermanent = game.getPermanent(source.getTargets().get(0).getFirstTarget());
|
||||
Permanent gainPermanent = game.getPermanent(source.getTargets().get(1).getFirstTarget());
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (losePermanent == null || gainPermanent == null || controller == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// choose ability to lose
|
||||
Set<String> choices = allChoices.entrySet().stream()
|
||||
.filter(entry -> losePermanent.hasAbility(entry.getValue(), game))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
|
||||
Ability chosenAbility;
|
||||
if (choices.size() == 1) {
|
||||
chosenAbility = allChoices.getOrDefault(choices.stream().findFirst().orElse(null), null);
|
||||
} else {
|
||||
Choice choice = new ChoiceImpl(true);
|
||||
choice.setMessage("Choose ability to remove from " + losePermanent.getLogName() + " to " + gainPermanent.getLogName());
|
||||
choice.setChoices(choices);
|
||||
controller.choose(Outcome.LoseAbility, choice, game);
|
||||
chosenAbility = allChoices.getOrDefault(choice.getChoice(), null);
|
||||
}
|
||||
if (chosenAbility == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// all fine
|
||||
this.targetedAbility = chosenAbility;
|
||||
paid = true;
|
||||
|
||||
// additional logs
|
||||
game.informPlayers(controller.getLogName() + " chosen ability to lose and gain: "
|
||||
+ CardUtil.getTextWithFirstCharUpperCase(chosenAbility.getRule()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhyrexianSplicerChooseCost copy() {
|
||||
return new PhyrexianSplicerChooseCost(this);
|
||||
}
|
||||
|
||||
Ability getTargetedAbility() {
|
||||
return this.targetedAbility;
|
||||
}
|
||||
}
|
||||
|
||||
enum PhyrexianSplicerCardHint implements Hint {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public String getText(Game game, Ability ability) {
|
||||
// works on stack only
|
||||
if (ability instanceof StackAbility) {
|
||||
Ability loseAbility = PhyrexianSplicerEffect.findChosenAbility(((StackAbility) ability).getStackAbility());
|
||||
if (loseAbility != null) {
|
||||
return String.format("Chosen ability to lose and gain: " + CardUtil.getTextWithFirstCharUpperCase(loseAbility.getRule()));
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PhyrexianSplicerCardHint copy() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package mage.cards.p;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -27,7 +28,8 @@ public final class PlanarAlly extends CardImpl {
|
|||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Whenever Planar Ally attacks, venture into the dungeon.
|
||||
this.addAbility(new AttacksTriggeredAbility(new VentureIntoTheDungeonEffect(), false));
|
||||
this.addAbility(new AttacksTriggeredAbility(new VentureIntoTheDungeonEffect(), false)
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
}
|
||||
|
||||
private PlanarAlly(final PlanarAlly card) {
|
||||
|
|
|
|||
98
Mage.Sets/src/mage/cards/p/PossessedGoat.java
Normal file
98
Mage.Sets/src/mage/cards/p/PossessedGoat.java
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
package mage.cards.p;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.ActivateOncePerGameActivatedAbility;
|
||||
import mage.abilities.costs.common.DiscardCardCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class PossessedGoat extends CardImpl {
|
||||
|
||||
public PossessedGoat(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{W}");
|
||||
|
||||
this.subtype.add(SubType.GOAT);
|
||||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// {3}, Discard a card: Put three +1/+1 counters on Possessed Goat and it becomes a black Demon in addition to its other colors and types. Activate only once.
|
||||
Ability ability = new ActivateOncePerGameActivatedAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)), new GenericManaCost(3)
|
||||
);
|
||||
ability.addCost(new DiscardCardCost());
|
||||
ability.addEffect(new PossessedGoatEffect());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private PossessedGoat(final PossessedGoat card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PossessedGoat copy() {
|
||||
return new PossessedGoat(this);
|
||||
}
|
||||
}
|
||||
|
||||
class PossessedGoatEffect extends ContinuousEffectImpl {
|
||||
|
||||
PossessedGoatEffect() {
|
||||
super(Duration.Custom, Outcome.Benefit);
|
||||
staticText = "and it becomes a black Demon in addition to its other colors and types";
|
||||
}
|
||||
|
||||
private PossessedGoatEffect(final PossessedGoatEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PossessedGoatEffect copy() {
|
||||
return new PossessedGoatEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null) {
|
||||
discard();
|
||||
return false;
|
||||
}
|
||||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
permanent.addSubType(game, SubType.DEMON);
|
||||
return true;
|
||||
case ColorChangingEffects_5:
|
||||
permanent.getColor(game).setBlack(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
case ColorChangingEffects_5:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
|
|||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -38,7 +39,8 @@ public final class PrecipitousDrop extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// When Precipitous Drop enters the battlefield, venture into the dungeon.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new VentureIntoTheDungeonEffect())
|
||||
.addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// Enchanted creature gets -2/-2. It gets -5/-5 instead as long as you've completed a dungeon.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import mage.abilities.costs.common.DiscardSourceCost;
|
|||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -48,7 +49,7 @@ public final class RadiantSolar extends CardImpl {
|
|||
// Whenever Radiant Solar or another nontoken creature you control enters, venture into the dungeon.
|
||||
this.addAbility(new EntersBattlefieldThisOrAnotherTriggeredAbility(
|
||||
new VentureIntoTheDungeonEffect(), filter, false, true
|
||||
));
|
||||
).addHint(CurrentDungeonHint.instance));
|
||||
|
||||
// {W}, Discard Radiant Solar: Venture into the dungeon and you gain 3 life.
|
||||
Ability ability = new SimpleActivatedAbility(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import mage.abilities.costs.common.TapSourceCost;
|
|||
import mage.abilities.costs.common.TapTargetCost;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.abilities.hint.common.CurrentDungeonHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
|
@ -49,6 +50,7 @@ public final class RangersHawk extends CardImpl {
|
|||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new TapTargetCost(new TargetControlledPermanent(filter)));
|
||||
ability.addHint(CurrentDungeonHint.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ public final class RestlessSpire extends CardImpl {
|
|||
new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.WhileOnBattlefield),
|
||||
MyTurnCondition.instance, "As long as it's your turn, this creature has first strike."
|
||||
)).addHint(MyTurnHint.instance)),
|
||||
CardType.LAND, Duration.EndOfTurn, true
|
||||
), new ManaCostsImpl<>("{U}{R}")));
|
||||
CardType.LAND, Duration.EndOfTurn
|
||||
).withDurationRuleAtStart(true), new ManaCostsImpl<>("{U}{R}")));
|
||||
|
||||
// Whenever Restless Spire attacks, scry 1.
|
||||
this.addAbility(new AttacksTriggeredAbility(new ScryEffect(1, false), false));
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ public final class RestlessVinestalk extends CardImpl {
|
|||
new CreatureToken(5, 5, "5/5 green and blue Plant creature with trample")
|
||||
.withColor("GU").withSubType(SubType.PLANT)
|
||||
.withAbility(TrampleAbility.getInstance()),
|
||||
CardType.LAND, Duration.EndOfTurn, true
|
||||
), new ManaCostsImpl<>("{3}{G}{U}")));
|
||||
CardType.LAND, Duration.EndOfTurn
|
||||
).withDurationRuleAtStart(true), new ManaCostsImpl<>("{3}{G}{U}")));
|
||||
|
||||
// Whenever Restless Vinestalk attacks, up to one other target creature has base power and toughness 3/3 until end of turn.
|
||||
Ability ability = new AttacksTriggeredAbility(new SetBasePowerToughnessTargetEffect(3, 3, Duration.EndOfTurn), false);
|
||||
|
|
|
|||
135
Mage.Sets/src/mage/cards/r/RipSpawnHunter.java
Normal file
135
Mage.Sets/src/mage/cards/r/RipSpawnHunter.java
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.abilityword.SurvivalAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class RipSpawnHunter extends CardImpl {
|
||||
|
||||
public RipSpawnHunter(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{W}");
|
||||
|
||||
this.supertype.add(SuperType.LEGENDARY);
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.SURVIVOR);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Survival -- At the beginning of your second main phase, if Rip, Spawn Hunter is tapped, reveal the top X cards of your library, where X is its power. Put any number of creature and/or Vehicle cards with different powers from among them into your hand. Put the rest on the bottom of your library in a random order.
|
||||
this.addAbility(new SurvivalAbility(new RipSpawnHunterEffect()));
|
||||
}
|
||||
|
||||
private RipSpawnHunter(final RipSpawnHunter card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RipSpawnHunter copy() {
|
||||
return new RipSpawnHunter(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RipSpawnHunterEffect extends OneShotEffect {
|
||||
|
||||
RipSpawnHunterEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "reveal the top X cards of your library, where X is its power. " +
|
||||
"Put any number of creature and/or Vehicle cards with different powers from among them into your hand. " +
|
||||
"Put the rest on the bottom of your library in a random order";
|
||||
}
|
||||
|
||||
private RipSpawnHunterEffect(final RipSpawnHunterEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RipSpawnHunterEffect copy() {
|
||||
return new RipSpawnHunterEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
int power = Optional
|
||||
.ofNullable(source.getSourcePermanentOrLKI(game))
|
||||
.map(MageObject::getPower)
|
||||
.map(MageInt::getValue)
|
||||
.orElse(0);
|
||||
if (player == null || power < 1) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, power));
|
||||
if (cards.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
player.revealCards(source, cards, game);
|
||||
TargetCard target = new RipSpawnHunterTarget();
|
||||
player.choose(Outcome.ReturnToHand, cards, target, source, game);
|
||||
player.moveCards(new CardsImpl(target.getTargets()), Zone.HAND, source, game);
|
||||
cards.retainZone(Zone.LIBRARY, game);
|
||||
player.putCardsOnBottomOfLibrary(cards, game, source, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class RipSpawnHunterTarget extends TargetCardInLibrary {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("creature and/or Vehicle cards with different powers");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
CardType.CREATURE.getPredicate(),
|
||||
SubType.VEHICLE.getPredicate()
|
||||
));
|
||||
}
|
||||
|
||||
public RipSpawnHunterTarget() {
|
||||
super(0, Integer.MAX_VALUE, filter);
|
||||
}
|
||||
|
||||
private RipSpawnHunterTarget(final RipSpawnHunterTarget target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RipSpawnHunterTarget copy() {
|
||||
return new RipSpawnHunterTarget(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
|
||||
if (!super.canTarget(playerId, id, source, game)) {
|
||||
return false;
|
||||
}
|
||||
Card card = game.getCard(id);
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
int power = card.getPower().getValue();
|
||||
return this
|
||||
.getTargets()
|
||||
.stream()
|
||||
.map(game::getCard)
|
||||
.filter(Objects::nonNull)
|
||||
.map(MageObject::getPower)
|
||||
.mapToInt(MageInt::getValue)
|
||||
.noneMatch(x -> x == power);
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ public final class SakashimasWill extends CardImpl {
|
|||
this.getSpellAbility().getModes().setChooseText(
|
||||
"Choose one. If you control a commander as you cast this spell, you may choose both."
|
||||
);
|
||||
this.getSpellAbility().getModes().setMoreCondition(ControlACommanderCondition.instance);
|
||||
this.getSpellAbility().getModes().setMoreCondition(2, ControlACommanderCondition.instance);
|
||||
|
||||
// • Target opponent chooses a creature they control. You gain control of it.
|
||||
this.getSpellAbility().addEffect(new SakashimasWillStealEffect());
|
||||
|
|
|
|||
93
Mage.Sets/src/mage/cards/s/Saw.java
Normal file
93
Mage.Sets/src/mage/cards/s/Saw.java
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageItem;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksAttachedTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.filter.predicate.permanent.PermanentIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetSacrifice;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class Saw extends CardImpl {
|
||||
|
||||
public Saw(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
this.subtype.add(SubType.EQUIPMENT);
|
||||
|
||||
// Equipped creature gets +2/+0.
|
||||
this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(2, 0)));
|
||||
|
||||
// Whenever equipped creature attacks, you may sacrifice a permanent other than that creature or Saw. If you do, draw a card.
|
||||
this.addAbility(new AttacksAttachedTriggeredAbility(
|
||||
new SawEffect(), AttachmentType.EQUIPMENT, false, SetTargetPointer.PERMANENT
|
||||
));
|
||||
|
||||
// Equip {2}
|
||||
this.addAbility(new EquipAbility(2));
|
||||
}
|
||||
|
||||
private Saw(final Saw card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Saw copy() {
|
||||
return new Saw(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SawEffect extends OneShotEffect {
|
||||
|
||||
SawEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "you may sacrifice a permanent other than that creature or {this}. If you do, draw a card";
|
||||
}
|
||||
|
||||
private SawEffect(final SawEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SawEffect copy() {
|
||||
return new SawEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
FilterPermanent filter = new FilterPermanent("another permanent");
|
||||
filter.add(AnotherPredicate.instance);
|
||||
Optional.ofNullable(getTargetPointer().getFirst(game, source))
|
||||
.map(game::getPermanent)
|
||||
.map(MageItem::getId)
|
||||
.map(PermanentIdPredicate::new)
|
||||
.map(Predicates::not)
|
||||
.ifPresent(filter::add);
|
||||
TargetSacrifice target = new TargetSacrifice(0, 1, filter);
|
||||
player.choose(outcome, target, source, game);
|
||||
Permanent permanent = game.getPermanent(target.getFirstTarget());
|
||||
return permanent != null && permanent.sacrifice(source, game) && player.drawCards(1, source, game) > 0;
|
||||
}
|
||||
}
|
||||
// I see, said the blind man
|
||||
|
|
@ -44,7 +44,7 @@ public final class SeasonOfGathering extends CardImpl {
|
|||
|
||||
// {P} -- Put a +1/+1 counter on a creature you control. It gains vigilance and trample until end of turn.
|
||||
this.getSpellAbility().addEffect(new SeasonOfGatheringCounterEffect());
|
||||
this.spellAbility.getModes().getMode().withPawPrintValue(1);
|
||||
this.getSpellAbility().getModes().getMode().withPawPrintValue(1);
|
||||
|
||||
// {P}{P} -- Choose artifact or enchantment. Destroy all permanents of the chosen type.
|
||||
Mode mode2 = new Mode(new SeasonOfGatheringRemovalEffect());
|
||||
|
|
@ -159,4 +159,4 @@ class SeasonOfGatheringRemovalEffect extends OneShotEffect {
|
|||
game.informPlayers(controller.getLogName() + " has chosen " + choiceImpl.getChoiceKey());
|
||||
return new DestroyAllEffect(filter).apply(game, source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue