mirror of
https://github.com/correl/mage.git
synced 2024-12-25 11:11:16 +00:00
Merge branch 'master' into wish
This commit is contained in:
commit
96ca260109
213 changed files with 3962 additions and 528 deletions
|
@ -183,6 +183,7 @@
|
|||
if (card instanceof StackAbilityView) {
|
||||
// replace ability by original card
|
||||
CardView tmp = ((StackAbilityView) card).getSourceCard();
|
||||
// sync settings
|
||||
tmp.overrideRules(card.getRules());
|
||||
tmp.setChoosable(card.isChoosable());
|
||||
tmp.setPlayableStats(card.getPlayableStats().copy());
|
||||
|
@ -191,6 +192,9 @@
|
|||
tmp.overrideTargets(card.getTargets());
|
||||
tmp.overrideId(card.getId());
|
||||
tmp.setAbilityType(card.getAbilityType());
|
||||
// sync card icons
|
||||
tmp.getCardIcons().clear();
|
||||
tmp.getCardIcons().addAll(card.getCardIcons());
|
||||
card = tmp;
|
||||
} else {
|
||||
card.setAbilityType(null);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-reply-fill" viewBox="0 0 16 16">
|
||||
<path d="M5.921 11.9 1.353 8.62a.719.719 0 0 1 0-1.238L5.921 4.1A.716.716 0 0 1 7 4.719V6c1.5 0 6 0 7 8-2.5-4.5-7-4-7-4v1.281c0 .56-.606.898-1.079.62z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 291 B |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16.1 16.1" style="enable-background:new 0 0 16.1 16.1;" xml:space="preserve">
|
||||
<path d="M8.5,0.7c-0.3-0.2-0.6-0.2-0.9,0L1.9,4C1.7,4.2,1.5,4.5,1.5,4.8v6.4c0,0.3,0.2,0.6,0.5,0.8l5.6,3.4c0.3,0.2,0.6,0.2,0.9,0
|
||||
l5.6-3.4c0.3-0.2,0.5-0.5,0.5-0.8V4.8c0-0.3-0.2-0.6-0.5-0.8L8.5,0.7z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 562 B |
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<path d="M6.1,11.1L0.8,7.3C0.4,7.1,0.3,6.6,0.5,6.2C0.6,6.1,0.7,6,0.8,5.9l5.3-3.8C6.5,1.9,7,2,7.2,2.4c0.1,0.1,0.1,0.3,0.1,0.4v1.5
|
||||
c1.7,0,6.9,0,8.1,9.3c-2.9-5.2-8.1-4.6-8.1-4.6v1.5C7.4,11.1,6.7,11.5,6.1,11.1L6.1,11.1z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 575 B |
|
@ -7,9 +7,12 @@ import mage.abilities.Abilities;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.Effects;
|
||||
import mage.abilities.icon.CardIcon;
|
||||
import mage.abilities.icon.other.FaceDownCardIcon;
|
||||
import mage.abilities.icon.other.VariableCostCardIcon;
|
||||
import mage.abilities.keyword.AftermathAbility;
|
||||
import mage.cards.*;
|
||||
import mage.cards.mock.MockCard;
|
||||
|
@ -368,7 +371,7 @@ public class CardView extends SimpleCardView {
|
|||
this.manaCostRightStr = String.join("", mainCard.getRightHalfCard().getManaCostSymbols());
|
||||
} else if (card instanceof AdventureCard) {
|
||||
AdventureCard adventureCard = ((AdventureCard) card);
|
||||
AdventureCardSpell adventureCardSpell = ((AdventureCardSpell) adventureCard.getSpellCard());
|
||||
AdventureCardSpell adventureCardSpell = adventureCard.getSpellCard();
|
||||
fullCardName = adventureCard.getName() + MockCard.ADVENTURE_NAME_SEPARATOR + adventureCardSpell.getName();
|
||||
this.manaCostLeftStr = String.join("", adventureCardSpell.getManaCostSymbols());
|
||||
this.manaCostRightStr = String.join("", adventureCard.getManaCostSymbols());
|
||||
|
@ -415,9 +418,14 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
// card icons for permanents on battlefield
|
||||
// abilities
|
||||
permanent.getAbilities(game).forEach(ability -> {
|
||||
this.cardIcons.addAll(ability.getIcons());
|
||||
this.cardIcons.addAll(ability.getIcons(game));
|
||||
});
|
||||
// face down
|
||||
if (permanent.isFaceDown(game)) {
|
||||
this.cardIcons.add(FaceDownCardIcon.instance);
|
||||
}
|
||||
} else {
|
||||
if (card.isCopy()) {
|
||||
this.mageObjectType = MageObjectType.COPY_CARD;
|
||||
|
@ -432,6 +440,25 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// card icons for any permanents and cards
|
||||
if (game != null) {
|
||||
// x cost
|
||||
Zone cardZone = game.getState().getZone(card.getId());
|
||||
if (card.getManaCost().containsX()
|
||||
&& (cardZone.match(Zone.BATTLEFIELD) || cardZone.match(Zone.STACK))) {
|
||||
int costX;
|
||||
if (card instanceof Permanent) {
|
||||
// permanent on battlefield
|
||||
costX = ManacostVariableValue.ETB.calculate(game, card.getSpellAbility(), null);
|
||||
} else {
|
||||
// other like Stack
|
||||
costX = ManacostVariableValue.REGULAR.calculate(game, card.getSpellAbility(), null);
|
||||
}
|
||||
this.cardIcons.add(new VariableCostCardIcon(costX));
|
||||
}
|
||||
}
|
||||
|
||||
this.power = Integer.toString(card.getPower().getValue());
|
||||
this.toughness = Integer.toString(card.getToughness().getValue());
|
||||
this.cardTypes = card.getCardType(game);
|
||||
|
|
|
@ -3,9 +3,11 @@ package mage.view;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.Modes;
|
||||
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.hint.Hint;
|
||||
import mage.abilities.hint.HintUtils;
|
||||
import mage.abilities.icon.other.VariableCostCardIcon;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.CardType;
|
||||
|
@ -28,7 +30,7 @@ public class StackAbilityView extends CardView {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// in GUI: that's view will be replaced by sourceCard, so don't forget to sync settings like
|
||||
// selectable, chooseable, etc. Search by getSourceCard
|
||||
// selectable, chooseable, card icons etc. Search by getSourceCard
|
||||
private final CardView sourceCard;
|
||||
|
||||
public StackAbilityView(Game game, StackAbility ability, String sourceName, CardView sourceCard) {
|
||||
|
@ -73,6 +75,13 @@ public class StackAbilityView extends CardView {
|
|||
this.counters = sourceCard.getCounters();
|
||||
|
||||
updateTargets(game, ability);
|
||||
|
||||
// card icons (warning, it must be synced in gui dialogs with replaced card, see comments at the start of the file)
|
||||
// cost x
|
||||
if (ability.getManaCostsToPay().containsX()) {
|
||||
int costX = ManacostVariableValue.REGULAR.calculate(game, ability, null);
|
||||
this.cardIcons.add(new VariableCostCardIcon(costX));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTargets(Game game, StackAbility ability) {
|
||||
|
@ -108,7 +117,7 @@ public class StackAbilityView extends CardView {
|
|||
}
|
||||
}
|
||||
if (!names.isEmpty()) {
|
||||
getRules().add("<i>Related objects: " + names.toString() + "</i>");
|
||||
getRules().add("<i>Related objects: " + names + "</i>");
|
||||
}
|
||||
|
||||
// show for modal ability, which mode was choosen
|
||||
|
|
|
@ -11,8 +11,8 @@ import mage.interfaces.callback.ClientCallback;
|
|||
import mage.interfaces.callback.ClientCallbackMethod;
|
||||
import mage.players.Player;
|
||||
import mage.server.User;
|
||||
import mage.server.managers.UserManager;
|
||||
import mage.server.managers.ManagerFactory;
|
||||
import mage.server.managers.UserManager;
|
||||
import mage.view.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -195,6 +195,18 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
|||
|
||||
@Override
|
||||
public GameView getGameView() {
|
||||
return prepareGameView(game, playerId, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare client-server data. Can be used in real games or in unit tests
|
||||
*
|
||||
* @param game
|
||||
* @param playerId
|
||||
* @param userId can be null for tests
|
||||
* @return
|
||||
*/
|
||||
public static GameView prepareGameView(Game game, UUID playerId, UUID userId) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
GameView gameView = new GameView(game.getState(), game, playerId, null);
|
||||
gameView.setHand(new CardsView(game, player.getHand().getCards(game)));
|
||||
|
@ -202,8 +214,8 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
|||
gameView.setCanPlayObjects(player.getPlayableObjects(game, Zone.ALL));
|
||||
}
|
||||
|
||||
processControlledPlayers(player, gameView);
|
||||
processWatchedHands(userId, gameView);
|
||||
processControlledPlayers(game, player, gameView);
|
||||
processWatchedHands(game, userId, gameView);
|
||||
//TODO: should player who controls another player's turn be able to look at all these cards?
|
||||
|
||||
List<LookedAtView> list = new ArrayList<>();
|
||||
|
@ -215,7 +227,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
|||
return gameView;
|
||||
}
|
||||
|
||||
private void processControlledPlayers(Player player, GameView gameView) {
|
||||
private static void processControlledPlayers(Game game, Player player, GameView gameView) {
|
||||
if (!player.getPlayersUnderYourControl().isEmpty()) {
|
||||
Map<String, SimpleCardsView> handCards = new HashMap<>();
|
||||
for (UUID controlledPlayerId : player.getPlayersUnderYourControl()) {
|
||||
|
@ -258,7 +270,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
|
|||
if (ex.getCause() != null) {
|
||||
logger.debug("- Cause: " + (ex.getCause().getMessage() == null ? "null" : ex.getCause().getMessage()), ex);
|
||||
} else {
|
||||
logger.debug("- ex: " + ex.toString(), ex);
|
||||
logger.debug("- ex: " + ex, ex);
|
||||
}
|
||||
} else {
|
||||
logger.fatal("Game session game quit exception - null gameId:" + game.getId() + " playerId: " + playerId);
|
||||
|
|
|
@ -99,11 +99,11 @@ public class GameSessionWatcher {
|
|||
|
||||
public GameView getGameView() {
|
||||
GameView gameView = new GameView(game.getState(), game, null, userId);
|
||||
processWatchedHands(userId, gameView);
|
||||
processWatchedHands(game, userId, gameView);
|
||||
return gameView;
|
||||
}
|
||||
|
||||
protected void processWatchedHands(UUID userId, GameView gameView) {
|
||||
protected static void processWatchedHands(Game game, UUID userId, GameView gameView) {
|
||||
Map<String, SimpleCardsView> handCards = new HashMap<>();
|
||||
for (Player player : game.getPlayers().values()) {
|
||||
if (player.hasUserPermissionToSeeHand(userId)) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import mage.game.GameCommanderImpl;
|
|||
import mage.game.command.CommandObject;
|
||||
import mage.game.command.Plane;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.RandomUtil;
|
||||
|
@ -267,8 +268,8 @@ public final class SystemUtil {
|
|||
public static void addCardsForTesting(Game game, String fileSource, Player feedbackPlayer) {
|
||||
|
||||
// fake test ability for triggers and events
|
||||
Ability fakeSourceAbility = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards"));
|
||||
fakeSourceAbility.setControllerId(feedbackPlayer.getId());
|
||||
Ability fakeSourceAbilityTemplate = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards"));
|
||||
fakeSourceAbilityTemplate.setControllerId(feedbackPlayer.getId());
|
||||
|
||||
try {
|
||||
String fileName = fileSource;
|
||||
|
@ -496,9 +497,12 @@ public final class SystemUtil {
|
|||
// eg: token:Human:HippoToken:1
|
||||
Class<?> c = Class.forName("mage.game.permanent.token." + command.cardName);
|
||||
Constructor<?> cons = c.getConstructor();
|
||||
Object token = cons.newInstance();
|
||||
if (token instanceof mage.game.permanent.token.Token) {
|
||||
((mage.game.permanent.token.Token) token).putOntoBattlefield(command.Amount, game, fakeSourceAbility, player.getId(), false, false);
|
||||
Object obj = cons.newInstance();
|
||||
if (obj instanceof Token) {
|
||||
Token token = (Token) obj;
|
||||
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
|
||||
fakeSourceAbility.setSourceId(token.getId());
|
||||
token.putOntoBattlefield(command.Amount, game, fakeSourceAbility, player.getId(), false, false);
|
||||
continue;
|
||||
}
|
||||
} else if ("emblem".equalsIgnoreCase(command.zone)) {
|
||||
|
@ -518,6 +522,8 @@ public final class SystemUtil {
|
|||
} else if ("loyalty".equalsIgnoreCase(command.zone)) {
|
||||
for (Permanent perm : game.getBattlefield().getAllActivePermanents(player.getId())) {
|
||||
if (perm.getName().equals(command.cardName) && perm.getCardType(game).contains(CardType.PLANESWALKER)) {
|
||||
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
|
||||
fakeSourceAbility.setSourceId(perm.getId());
|
||||
perm.addCounters(CounterType.LOYALTY.createInstance(command.Amount), fakeSourceAbility.getControllerId(), fakeSourceAbility, game);
|
||||
}
|
||||
}
|
||||
|
@ -541,6 +547,8 @@ public final class SystemUtil {
|
|||
|
||||
// move card from exile to stack
|
||||
for (Card card : cardsToLoad) {
|
||||
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
|
||||
fakeSourceAbility.setSourceId(card.getId());
|
||||
putCardToZone(fakeSourceAbility, game, player, card, Zone.STACK);
|
||||
}
|
||||
|
||||
|
@ -616,6 +624,8 @@ public final class SystemUtil {
|
|||
} else {
|
||||
// as other card
|
||||
for (Card card : cardsToLoad) {
|
||||
Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy();
|
||||
fakeSourceAbility.setSourceId(card.getId());
|
||||
putCardToZone(fakeSourceAbility, game, player, card, gameZone);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,12 +24,11 @@ public final class AdmiralsOrder extends CardImpl {
|
|||
|
||||
// Raid - If you attacked with a creature this turn, you may pay {U} rather than pay this spell's mana cost.
|
||||
this.addAbility(new AlternativeCostSourceAbility(new ManaCostsImpl("{U}"), RaidCondition.instance,
|
||||
"<br/><br/><i>Raid</i> — If you attacked with a creature this turn, you may pay {U} rather than pay this spell's mana cost"),
|
||||
"<br/><i>Raid</i> — If you attacked this turn, you may pay {U} rather than pay this spell's mana cost"),
|
||||
new PlayerAttackedWatcher());
|
||||
// Counter target spell.
|
||||
this.getSpellAbility().addEffect(new CounterTargetEffect());
|
||||
this.getSpellAbility().addTarget(new TargetSpell());
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.RAID);
|
||||
this.getSpellAbility().addHint(RaidHint.instance);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import mage.watchers.common.RevoltWatcher;
|
|||
public final class AidFromTheCowl extends CardImpl {
|
||||
|
||||
private static final String ruleText = "<i>Revolt</i> — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, "
|
||||
+ "you may reveal the top card of your library. If it's a permanent card, you may put it onto the battlefield. Otherwise, put it on the bottom of your library.";
|
||||
+ "reveal the top card of your library. If it's a permanent card, you may put it onto the battlefield. Otherwise, put it on the bottom of your library.";
|
||||
|
||||
public AidFromTheCowl(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}{G}");
|
||||
|
|
|
@ -20,7 +20,7 @@ import mage.target.common.TargetCreaturePermanent;
|
|||
*/
|
||||
public final class AirCultElemental extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other creature");
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("other target creature");
|
||||
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
|
|
|
@ -44,7 +44,7 @@ public final class AkoumFirebird extends CardImpl {
|
|||
// <i>Landfall</i>-Whenever a land enters the battlefield under your control, you may pay {4}{R}{R}.
|
||||
// If you do, return Akoum Firebird from your graveyard to the battlefield.
|
||||
this.addAbility(new AkoumFirebirdLandfallAbility(new DoIfCostPaid(
|
||||
new ReturnSourceFromGraveyardToBattlefieldEffect(), new ManaCostsImpl("{4}{R}{R}")), false));
|
||||
new ReturnSourceFromGraveyardToBattlefieldEffect(false, false), new ManaCostsImpl("{4}{R}{R}")), false));
|
||||
}
|
||||
|
||||
private AkoumFirebird(final AkoumFirebird card) {
|
||||
|
|
|
@ -86,7 +86,7 @@ class AngelicArbiterEffect2 extends ContinuousRuleModifyingEffectImpl {
|
|||
|
||||
public AngelicArbiterEffect2() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
staticText = "Each opponent who attacked with a creature this turn can't cast spells";
|
||||
staticText = "Each opponent who attacked this turn can't cast spells";
|
||||
}
|
||||
|
||||
public AngelicArbiterEffect2(final AngelicArbiterEffect2 effect) {
|
||||
|
|
|
@ -32,9 +32,8 @@ public final class ArrowStorm extends CardImpl {
|
|||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new DamageTargetEffect(5, false),
|
||||
RaidCondition.instance,
|
||||
"<br/><br/><i>Raid</i> — If you attacked with a creature this turn, instead {this} deals 5 damage to that permanent or player and the damage can't be prevented"));
|
||||
"<br/><br/><i>Raid</i> — If you attacked this turn, instead {this} deals 5 damage to that permanent or player and the damage can't be prevented"));
|
||||
this.getSpellAbility().addWatcher(new PlayerAttackedWatcher());
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.RAID);
|
||||
this.getSpellAbility().addHint(RaidHint.instance);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
package mage.cards.a;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.MetalcraftCondition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.hint.common.MetalcraftHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -20,9 +23,6 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class AuriokSunchaser extends CardImpl {
|
||||
|
||||
protected static String effect1Text = "<i>Metalcraft</i> — As long as you control three or more artifacts, Auriok Sunchaser gets +2/+2";
|
||||
protected static String effect2Text = "<i>Metalcraft</i> — As long as you control three or more artifacts, Auriok Sunchaser has flying";
|
||||
|
||||
public AuriokSunchaser(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}");
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
|
@ -31,19 +31,14 @@ public final class AuriokSunchaser extends CardImpl {
|
|||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
ContinuousEffect effect1 = new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(effect1, MetalcraftCondition.instance, effect1Text))
|
||||
.setAbilityWord(AbilityWord.METALCRAFT)
|
||||
.addHint(MetalcraftHint.instance)
|
||||
);
|
||||
|
||||
ContinuousEffect effect2 = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(effect2, MetalcraftCondition.instance, effect2Text))
|
||||
.setAbilityWord(AbilityWord.METALCRAFT)
|
||||
.addHint(MetalcraftHint.instance)
|
||||
);
|
||||
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
|
||||
MetalcraftCondition.instance, "as long as you control three or more artifacts, {this} gets +2/+2"
|
||||
));
|
||||
ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(
|
||||
FlyingAbility.getInstance(), Duration.WhileOnBattlefield
|
||||
), MetalcraftCondition.instance, "and has flying"));
|
||||
this.addAbility(ability.setAbilityWord(AbilityWord.METALCRAFT).addHint(MetalcraftHint.instance));
|
||||
}
|
||||
|
||||
private AuriokSunchaser(final AuriokSunchaser card) {
|
||||
|
|
|
@ -26,8 +26,8 @@ public final class BalothWoodcrasher extends CardImpl {
|
|||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
LandfallAbility ability = new LandfallAbility(new BoostSourceEffect(4, 4, Duration.EndOfTurn), false);
|
||||
ability.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn));
|
||||
LandfallAbility ability = new LandfallAbility(new BoostSourceEffect(4, 4, Duration.EndOfTurn).setText("{this} gets +4/+4"), false);
|
||||
ability.addEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.EndOfTurn).setText("and gains trample until end of turn"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public final class BardClass extends CardImpl {
|
|||
|
||||
// Legendary spells you cast cost {R}{G} less to cast. This effect reduces only the amount of colored mana you pay.
|
||||
this.addAbility(new SimpleStaticAbility(new GainClassAbilitySourceEffect(
|
||||
new SpellsCostReductionControllerEffect(filter, new ManaCostsImpl<>("{W}{B}")), 2
|
||||
new SpellsCostReductionControllerEffect(filter, new ManaCostsImpl<>("{R}{G}")), 2
|
||||
)));
|
||||
|
||||
// {3}{R}{G}: Level 3
|
||||
|
|
|
@ -32,7 +32,7 @@ public final class BellowingSaddlebrute extends CardImpl {
|
|||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
|
||||
new EntersBattlefieldTriggeredAbility(new LoseLifeSourceControllerEffect(4)),
|
||||
new InvertCondition(RaidCondition.instance),
|
||||
"<i>Raid</i> — When {this} enters the battlefield, you lose 4 life unless you attacked with a creature this turn")
|
||||
"<i>Raid</i> — When {this} enters the battlefield, you lose 4 life unless you attacked this turn.")
|
||||
.setAbilityWord(AbilityWord.RAID)
|
||||
.addHint(RaidHint.instance),
|
||||
new PlayerAttackedWatcher());
|
||||
|
|
|
@ -15,6 +15,8 @@ import mage.constants.Outcome;
|
|||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.DamagedPermanentBatchEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
@ -28,16 +30,16 @@ import java.util.UUID;
|
|||
public final class BlazingSunsteel extends CardImpl {
|
||||
|
||||
public BlazingSunsteel(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{1}{R}");
|
||||
super(ownerId, setInfo, new CardType[] { CardType.ARTIFACT }, "{1}{R}");
|
||||
|
||||
this.subtype.add(SubType.EQUIPMENT);
|
||||
|
||||
// Equipped creature gets +1/+0 for each opponent you have.
|
||||
this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(
|
||||
OpponentsCount.instance, StaticValue.get(0)
|
||||
).setText("equipped creature gets +1/+0 for each opponent you have")));
|
||||
this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect(OpponentsCount.instance, StaticValue.get(0))
|
||||
.setText("equipped creature gets +1/+0 for each opponent you have")));
|
||||
|
||||
// Whenever equipped creature is dealt damage, it deals that much damage to any target.
|
||||
// Whenever equipped creature is dealt damage, it deals that much damage to any
|
||||
// target.
|
||||
this.addAbility(new BlazingSunsteelTriggeredAbility());
|
||||
|
||||
// Equip {4}
|
||||
|
@ -72,20 +74,40 @@ class BlazingSunsteelTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT;
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT_BATCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent equipment = game.getPermanent(this.getSourceId());
|
||||
if (equipment == null
|
||||
|| equipment.getAttachedTo() == null
|
||||
|| !event.getTargetId().equals(equipment.getAttachedTo())) {
|
||||
if (equipment == null) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().setValue("equipped", game.getPermanent(equipment.getAttachedTo()));
|
||||
this.getEffects().setValue("damage", event.getAmount());
|
||||
return true;
|
||||
|
||||
UUID attachedCreature = equipment.getAttachedTo();
|
||||
if (attachedCreature == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int damage = 0;
|
||||
DamagedPermanentBatchEvent dEvent = (DamagedPermanentBatchEvent) event;
|
||||
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
|
||||
UUID targetID = damagedEvent.getTargetId();
|
||||
if (targetID == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetID == attachedCreature) {
|
||||
damage += damagedEvent.getAmount();
|
||||
}
|
||||
}
|
||||
|
||||
if (damage > 0) {
|
||||
this.getEffects().setValue("equipped", attachedCreature);
|
||||
this.getEffects().setValue("damage", damage);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -111,11 +133,13 @@ class BlazingSunsteelEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent creature = (Permanent) getValue("equipped");
|
||||
Integer damage = (Integer) getValue("damage");
|
||||
if (creature == null || damage == null || damage < 1) {
|
||||
Permanent creature = game.getPermanentOrLKIBattlefield((UUID) getValue("equipped"));
|
||||
Integer damage = (Integer)getValue("damage");
|
||||
|
||||
if (creature == null || damage == null || damage < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
permanent.damage(damage, creature.getId(), source, game);
|
||||
|
|
|
@ -7,6 +7,7 @@ import mage.abilities.SpellAbility;
|
|||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.abilities.keyword.DeathtouchAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -19,7 +20,6 @@ import mage.constants.SubType;
|
|||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.common.MorbidWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -35,7 +35,7 @@ public final class BonePicker extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Bone Picker costs {3} less to cast if a creature died this turn.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new BonePickerAdjustingCostsEffect()), new MorbidWatcher());
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new BonePickerAdjustingCostsEffect()).addHint(MorbidHint.instance));
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
|
|
@ -32,7 +32,7 @@ public final class BreakOfDay extends CardImpl {
|
|||
StaticFilters.FILTER_PERMANENT_CREATURES, false
|
||||
), new LockedInCondition(FatefulHourCondition.instance),
|
||||
"<br><i>Fateful hour</i> — If you have 5 or less life, " +
|
||||
"those creatures also are indestructible this turn"
|
||||
"those creatures gain indestructible until end of turn"
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ public final class BrilliantSpectrum extends CardImpl {
|
|||
Effect effect = new DrawCardSourceControllerEffect(ColorsOfManaSpentToCastCount.getInstance());
|
||||
effect.setText("Draw X cards, where X is the number of colors of mana spent to cast this spell");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addEffect(new DiscardControllerEffect(2));
|
||||
this.getSpellAbility().addEffect(new DiscardControllerEffect(2).concatBy("Then"));
|
||||
}
|
||||
|
||||
private BrilliantSpectrum(final BrilliantSpectrum card) {
|
||||
|
|
|
@ -3,11 +3,11 @@ package mage.cards.b;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
import mage.watchers.common.MorbidWatcher;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ public final class BrimstoneVolley extends CardImpl {
|
|||
"<br><i>Morbid</i> — {this} deals 5 damage instead if a creature died this turn."
|
||||
));
|
||||
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
||||
this.getSpellAbility().addWatcher(new MorbidWatcher());
|
||||
this.getSpellAbility().addHint(MorbidHint.instance);
|
||||
}
|
||||
|
||||
private BrimstoneVolley(final BrimstoneVolley card) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.constants.SubType;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -30,7 +31,7 @@ public final class Bulette extends CardImpl {
|
|||
new BeginningOfYourEndStepTriggeredAbility(new AddCountersSourceEffect(CounterType.P1P1.createInstance()), false),
|
||||
MorbidCondition.instance,
|
||||
"At the beginning of your end step, if a creature died this turn, put a +1/+1 counter on {this}."
|
||||
));
|
||||
).addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private Bulette(final Bulette card) {
|
||||
|
|
|
@ -22,7 +22,7 @@ public final class CacklingFlames extends CardImpl {
|
|||
// Hellbent - Cackling Flames deals 5 damage to that creature or player instead if you have no cards in hand.
|
||||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new DamageTargetEffect(5), new DamageTargetEffect(3), HellbentCondition.instance,
|
||||
"{this} deals 3 damage to any target<br><i>Hellbent</i> " +
|
||||
"{this} deals 3 damage to any target.<br><i>Hellbent</i> " +
|
||||
"— {this} deals 5 damage instead if you have no cards in hand."
|
||||
));
|
||||
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
||||
|
|
|
@ -7,12 +7,12 @@ import mage.abilities.condition.common.MorbidCondition;
|
|||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.watchers.common.MorbidWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -34,7 +34,7 @@ public final class CagedZombie extends CardImpl {
|
|||
new ManaCostsImpl("{1}{B}"), MorbidCondition.instance
|
||||
);
|
||||
ability.addCost(new TapSourceCost());
|
||||
this.addAbility(ability, new MorbidWatcher());
|
||||
this.addAbility(ability.addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private CagedZombie(final CagedZombie card) {
|
||||
|
|
|
@ -8,7 +8,10 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
|||
import mage.abilities.hint.common.MetalcraftHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -25,15 +28,11 @@ public final class CarapaceForger extends CardImpl {
|
|||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(
|
||||
new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
|
||||
MetalcraftCondition.instance, "<i>Metalcraft</i> — {this} gets " +
|
||||
"+2/+2 as long as you control three or more artifacts"
|
||||
))
|
||||
.setAbilityWord(AbilityWord.METALCRAFT)
|
||||
.addHint(MetalcraftHint.instance));
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
|
||||
MetalcraftCondition.instance, "{this} gets " +
|
||||
"+2/+2 as long as you control three or more artifacts"
|
||||
)).setAbilityWord(AbilityWord.METALCRAFT).addHint(MetalcraftHint.instance));
|
||||
}
|
||||
|
||||
private CarapaceForger(final CarapaceForger card) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import mage.MageObject;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
|
@ -27,6 +28,7 @@ public final class CaravanVigil extends CardImpl {
|
|||
// Search your library for a basic land card, reveal it, put it into your hand, then shuffle your library.
|
||||
// <i>Morbid</i> — You may put that card onto the battlefield instead of putting it into your hand if a creature died this turn.
|
||||
this.getSpellAbility().addEffect(new CaravanVigilEffect());
|
||||
this.getSpellAbility().addHint(MorbidHint.instance);
|
||||
}
|
||||
|
||||
private CaravanVigil(final CaravanVigil card) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceColor;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
|
@ -39,7 +40,7 @@ public final class ChromeMox extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{0}");
|
||||
|
||||
// Imprint - When Chrome Mox enters the battlefield, you may exile a nonartifact, nonland card from your hand.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new ChromeMoxEffect(), true));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new ChromeMoxEffect(), true).setAbilityWord(AbilityWord.IMPRINT));
|
||||
// {T}: Add one mana of any of the exiled card's colors.
|
||||
this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new ChromeMoxManaEffect(), new TapSourceCost()));
|
||||
}
|
||||
|
|
|
@ -8,7 +8,10 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
|||
import mage.abilities.hint.common.MetalcraftHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -23,15 +26,11 @@ public final class ChromeSteed extends CardImpl {
|
|||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
this.addAbility(new SimpleStaticAbility(
|
||||
Zone.BATTLEFIELD,
|
||||
new ConditionalContinuousEffect(
|
||||
new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
|
||||
MetalcraftCondition.instance, "<i>Metalcraft</i> — {this} gets " +
|
||||
"+2/+2 as long as you control three or more artifacts"
|
||||
))
|
||||
.setAbilityWord(AbilityWord.METALCRAFT)
|
||||
.addHint(MetalcraftHint.instance));
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalContinuousEffect(
|
||||
new BoostSourceEffect(2, 2, Duration.WhileOnBattlefield),
|
||||
MetalcraftCondition.instance, "{this} gets " +
|
||||
"+2/+2 as long as you control three or more artifacts"
|
||||
)).setAbilityWord(AbilityWord.METALCRAFT).addHint(MetalcraftHint.instance));
|
||||
}
|
||||
|
||||
private ChromeSteed(final ChromeSteed card) {
|
||||
|
@ -42,5 +41,4 @@ public final class ChromeSteed extends CardImpl {
|
|||
public ChromeSteed copy() {
|
||||
return new ChromeSteed(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
140
Mage.Sets/src/mage/cards/c/ClayGolem.java
Normal file
140
Mage.Sets/src/mage/cards/c/ClayGolem.java
Normal file
|
@ -0,0 +1,140 @@
|
|||
package mage.cards.c;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BecomesMonstrousSourceTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.hint.common.MonstrousHint;
|
||||
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.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class ClayGolem extends CardImpl {
|
||||
|
||||
public ClayGolem(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{4}");
|
||||
|
||||
this.subtype.add(SubType.GOLEM);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// {6}, Roll a d8: Monstrosity X, where X is the result.
|
||||
Ability ability = new SimpleActivatedAbility(new ClayGolemEffect(), new GenericManaCost(6));
|
||||
ability.addCost(new ClayGolemCost());
|
||||
this.addAbility(ability.addHint(MonstrousHint.instance));
|
||||
|
||||
// Berserk — When Clay Golem becomes monstrous, destroy target permanent.
|
||||
ability = new BecomesMonstrousSourceTriggeredAbility(new DestroyTargetEffect());
|
||||
ability.addTarget(new TargetPermanent());
|
||||
this.addAbility(ability.withFlavorWord("Berserk"));
|
||||
}
|
||||
|
||||
private ClayGolem(final ClayGolem card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClayGolem copy() {
|
||||
return new ClayGolem(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ClayGolemCost extends CostImpl {
|
||||
|
||||
private int lastRoll = 0;
|
||||
|
||||
ClayGolemCost() {
|
||||
super();
|
||||
text = "roll a d8";
|
||||
}
|
||||
|
||||
private ClayGolemCost(final ClayGolemCost cost) {
|
||||
super(cost);
|
||||
this.lastRoll = cost.lastRoll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player == null) {
|
||||
return paid;
|
||||
}
|
||||
lastRoll = player.rollDice(source, game, 8);
|
||||
paid = true;
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClayGolemCost copy() {
|
||||
return new ClayGolemCost(this);
|
||||
}
|
||||
|
||||
public int getLastRoll() {
|
||||
return lastRoll;
|
||||
}
|
||||
}
|
||||
|
||||
class ClayGolemEffect extends OneShotEffect {
|
||||
ClayGolemEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "monstrosity X, where X is the result";
|
||||
}
|
||||
|
||||
private ClayGolemEffect(final ClayGolemEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClayGolemEffect copy() {
|
||||
return new ClayGolemEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null || permanent.isMonstrous()) {
|
||||
return false;
|
||||
}
|
||||
int monstrosityValue = source
|
||||
.getCosts()
|
||||
.stream()
|
||||
.filter(ClayGolemCost.class::isInstance)
|
||||
.map(ClayGolemCost.class::cast)
|
||||
.mapToInt(ClayGolemCost::getLastRoll)
|
||||
.findFirst()
|
||||
.orElse(0);
|
||||
permanent.addCounters(
|
||||
CounterType.P1P1.createInstance(monstrosityValue),
|
||||
source.getControllerId(), source, game
|
||||
);
|
||||
permanent.setMonstrous(true);
|
||||
game.fireEvent(GameEvent.getEvent(
|
||||
GameEvent.EventType.BECOMES_MONSTROUS, source.getSourceId(),
|
||||
source, source.getControllerId(), monstrosityValue
|
||||
));
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -6,10 +6,7 @@ import mage.abilities.common.DiesSourceTriggeredAbility;
|
|||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
@ -33,7 +30,7 @@ public final class CloneShell extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// Imprint - When Clone Shell enters the battlefield, look at the top four cards of your library, exile one face down, then put the rest on the bottom of your library in any order.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new CloneShellEffect(), false));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new CloneShellEffect(), false).setAbilityWord(AbilityWord.IMPRINT));
|
||||
|
||||
// When Clone Shell dies, turn the exiled card face up. If it's a creature card, put it onto the battlefield under your control.
|
||||
this.addAbility(new DiesSourceTriggeredAbility(new CloneShellDiesEffect()));
|
||||
|
|
|
@ -29,7 +29,7 @@ public final class CodeOfConstraint extends CardImpl {
|
|||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
|
||||
// Draw a card.
|
||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
|
||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1).concatBy("<br>"));
|
||||
|
||||
// Addendum — If you cast this spell during your main phase, tap that creature and it doesn't untap during its controller's next untap step.
|
||||
this.getSpellAbility().addEffect(new CodeOfConstraintEffect());
|
||||
|
|
|
@ -34,7 +34,6 @@ public final class ConcussiveBolt extends CardImpl {
|
|||
// <i>Metalcraft</i> — If you control three or more artifacts, creatures that player controls can't block this turn.
|
||||
this.getSpellAbility().addEffect(new ConcussiveBoltEffect());
|
||||
this.getSpellAbility().addEffect(new ConcussiveBoltRestrictionEffect());
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
|
||||
this.getSpellAbility().addHint(MetalcraftHint.instance);
|
||||
}
|
||||
|
||||
|
@ -52,7 +51,7 @@ class ConcussiveBoltEffect extends OneShotEffect {
|
|||
|
||||
public ConcussiveBoltEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "<i>Metalcraft</i> — If you control three or more artifacts, creatures controlled by that player or by that planeswalker's controller can't block this turn.";
|
||||
this.staticText = "<br><i>Metalcraft</i> — If you control three or more artifacts, creatures controlled by that player or by that planeswalker's controller can't block this turn.";
|
||||
}
|
||||
|
||||
public ConcussiveBoltEffect(final ConcussiveBoltEffect effect) {
|
||||
|
|
|
@ -33,7 +33,7 @@ public final class ContactOtherPlane extends CardImpl {
|
|||
// 20 | Scry 3, then draw three cards.
|
||||
effect.addTableEntry(
|
||||
20, 20, new ScryEffect(3, false),
|
||||
new DrawCardSourceControllerEffect(2).concatBy(", then")
|
||||
new DrawCardSourceControllerEffect(3).concatBy(", then")
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public final class CropSigil extends CardImpl {
|
|||
Ability ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(true), new ManaCostsImpl<>("{2}{G}"),
|
||||
DeliriumCondition.instance,
|
||||
"<i>Delirium</i> — {2}{G}, Sacrifice {this}: Return up to one target creature card and up to one target land card from your graveyard to your hand. "
|
||||
+ "Activate only if there are four or more card types among cards in your graveyard");
|
||||
+ "Activate only if there are four or more card types among cards in your graveyard.");
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
ability.addTarget(new TargetCardInYourGraveyard(0, 1, filterCreature));
|
||||
ability.addTarget(new TargetCardInYourGraveyard(0, 1, filterLand));
|
||||
|
|
|
@ -48,7 +48,7 @@ class DarkDabblingEffect extends OneShotEffect {
|
|||
|
||||
public DarkDabblingEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "<i>Spell mastery</i> — If there are two or more instant and/or sorcery cards in your graveyard, also regenerate each other creature you control";
|
||||
this.staticText = "<br><i>Spell mastery</i> — If there are two or more instant and/or sorcery cards in your graveyard, also regenerate each other creature you control";
|
||||
}
|
||||
|
||||
public DarkDabblingEffect(final DarkDabblingEffect effect) {
|
||||
|
|
|
@ -31,7 +31,7 @@ public final class DawnbringerCleric extends CardImpl {
|
|||
|
||||
// When Dawnbringer Cleric enters the battlefield, choose one —
|
||||
// • Cure Wounds — You gain 2 life.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(1));
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2));
|
||||
ability.getModes().getMode().withFlavorWord("Cure Wounds");
|
||||
|
||||
// • Dispel Magic — Destroy target enchantment.
|
||||
|
|
|
@ -3,18 +3,18 @@ package mage.cards.d;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.CompletedDungeonCondition;
|
||||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.permanent.token.SkeletonToken;
|
||||
import mage.watchers.common.CompletedDungeonWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -51,8 +51,8 @@ public final class DeathPriestOfMyrkul extends CardImpl {
|
|||
this.addAbility(new BeginningOfEndStepTriggeredAbility(
|
||||
Zone.BATTLEFIELD,
|
||||
new DoIfCostPaid(new CreateTokenEffect(new SkeletonToken()), new GenericManaCost(1)),
|
||||
TargetController.YOU, CompletedDungeonCondition.instance, false
|
||||
).addHint(CompletedDungeonCondition.getHint()), new CompletedDungeonWatcher());
|
||||
TargetController.YOU, MorbidCondition.instance, false
|
||||
).addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private DeathPriestOfMyrkul(final DeathPriestOfMyrkul card) {
|
||||
|
|
|
@ -5,8 +5,10 @@ import java.util.UUID;
|
|||
import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
|
@ -22,7 +24,7 @@ public final class DeathreapRitual extends CardImpl {
|
|||
|
||||
// <i>Morbid</i> — At the beginning of each end step, if a creature died this turn, you may draw a card.
|
||||
this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1),
|
||||
TargetController.ANY, MorbidCondition.instance, true));
|
||||
TargetController.ANY, MorbidCondition.instance, true).addHint(MorbidHint.instance).setAbilityWord(AbilityWord.MORBID));
|
||||
}
|
||||
|
||||
private DeathreapRitual(final DeathreapRitual card) {
|
||||
|
|
168
Mage.Sets/src/mage/cards/d/Demilich.java
Normal file
168
Mage.Sets/src/mage/cards/d/Demilich.java
Normal file
|
@ -0,0 +1,168 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.abilities.costs.common.ExileFromGraveCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
|
||||
import mage.abilities.hint.ValueHint;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.*;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author weirddan455
|
||||
*/
|
||||
public final class Demilich extends CardImpl {
|
||||
|
||||
public Demilich(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{U}{U}{U}");
|
||||
|
||||
this.subtype.add(SubType.SKELETON);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// This spell costs {U} less to cast for each instant and sorcery you've cast this turn.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionForEachSourceEffect(
|
||||
new ManaCostsImpl<>("{U}"), DemilichValue.instance
|
||||
)).addHint(new ValueHint("Instants and sorceries you've cast this turn", DemilichValue.instance)), new SpellsCastWatcher());
|
||||
|
||||
// Whenever Demilich attacks, exile up to one target instant or sorcery card from your graveyard. Copy it. You may cast the copy.
|
||||
Ability ability = new AttacksTriggeredAbility(new DemilichCopyEffect());
|
||||
ability.addTarget(new TargetCardInYourGraveyard(0, 1, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD));
|
||||
this.addAbility(ability);
|
||||
|
||||
// You may cast Demilich from your graveyard by exiling four instants and/or sorcery cards from your graveyard in addition to paying its other costs.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new DemilichPlayEffect()));
|
||||
}
|
||||
|
||||
private Demilich(final Demilich card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Demilich copy() {
|
||||
return new Demilich(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum DemilichValue implements DynamicValue {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
int spells = 0;
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
if (watcher != null) {
|
||||
for (Spell spell : watcher.getSpellsCastThisTurn(sourceAbility.getControllerId())) {
|
||||
if (spell.isInstantOrSorcery()) {
|
||||
spells++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return spells;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemilichValue copy() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "instant and sorcery you've cast this turn";
|
||||
}
|
||||
}
|
||||
|
||||
class DemilichCopyEffect extends OneShotEffect {
|
||||
|
||||
public DemilichCopyEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "exile up to one target instant or sorcery card from your graveyard. Copy it. You may cast the copy";
|
||||
}
|
||||
|
||||
private DemilichCopyEffect(final DemilichCopyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemilichCopyEffect copy() {
|
||||
return new DemilichCopyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Card card = game.getCard(targetPointer.getFirst(game, source));
|
||||
if (controller == null || card == null) {
|
||||
return false;
|
||||
}
|
||||
controller.moveCards(card, Zone.EXILED, source, game);
|
||||
if (controller.chooseUse(outcome, "Cast copy of " + card.getName() + '?', source, game)) {
|
||||
Card copiedCard = game.copyCard(card, source, controller.getId());
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(copiedCard, game, false),
|
||||
game, false, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + copiedCard.getId(), null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class DemilichPlayEffect extends AsThoughEffectImpl {
|
||||
|
||||
public DemilichPlayEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit);
|
||||
this.staticText = "You may cast {this} from your graveyard by exiling four instants and/or sorcery cards from your graveyard in addition to paying its other costs";
|
||||
}
|
||||
|
||||
private DemilichPlayEffect(final DemilichPlayEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemilichPlayEffect copy() {
|
||||
return new DemilichPlayEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (source.getSourceId().equals(objectId) && source.isControlledBy(affectedControllerId)
|
||||
&& game.getState().getZone(objectId) == Zone.GRAVEYARD) {
|
||||
Player controller = game.getPlayer(affectedControllerId);
|
||||
if (controller != null) {
|
||||
Costs<Cost> costs = new CostsImpl<>();
|
||||
costs.add(new ExileFromGraveCost(new TargetCardInYourGraveyard(4, StaticFilters.FILTER_CARD_INSTANT_OR_SORCERY_FROM_YOUR_GRAVEYARD)));
|
||||
controller.setCastSourceIdWithAlternateMana(objectId, new ManaCostsImpl<>("{U}{U}{U}{U}"), costs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ public final class DispenseJustice extends CardImpl {
|
|||
// Metalcraft — That player sacrifices two attacking creatures instead if you control three or more artifacts.
|
||||
this.getSpellAbility().addEffect(new DispenseJusticeEffect());
|
||||
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
|
||||
this.getSpellAbility().addHint(MetalcraftHint.instance);
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ enum DreadhordeArcanistPredicate implements ObjectSourcePlayerPredicate<ObjectSo
|
|||
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(input.getSourceId());
|
||||
return sourcePermanent != null
|
||||
& input.getObject().getManaValue() <= sourcePermanent.getPower().getValue();
|
||||
&& input.getObject().getManaValue() <= sourcePermanent.getPower().getValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
110
Mage.Sets/src/mage/cards/e/EbonyFly.java
Normal file
110
Mage.Sets/src/mage/cards/e/EbonyFly.java
Normal file
|
@ -0,0 +1,110 @@
|
|||
package mage.cards.e;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTappedAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.mana.ColorlessManaAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterAttackingCreature;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.token.custom.CreatureToken;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class EbonyFly extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterAttackingCreature("another target attacking creature");
|
||||
|
||||
static {
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
public EbonyFly(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
|
||||
|
||||
// Ebony Fly enters the battlefield tapped.
|
||||
this.addAbility(new EntersBattlefieldTappedAbility());
|
||||
|
||||
// {T}: Add {C}.
|
||||
this.addAbility(new ColorlessManaAbility());
|
||||
|
||||
// {4}: Roll a d6. Until end of turn, you may have Ebony Fly become an X/X Insect artifact creature with flying, where X is the result.
|
||||
this.addAbility(new SimpleActivatedAbility(new EbonyFlyEffect(), new GenericManaCost(4)));
|
||||
|
||||
// Whenever Ebony Fly attacks, another target attacking creature gains flying until end of turn.
|
||||
Ability ability = new AttacksTriggeredAbility(new GainAbilityTargetEffect(
|
||||
FlyingAbility.getInstance(), Duration.EndOfTurn
|
||||
));
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private EbonyFly(final EbonyFly card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EbonyFly copy() {
|
||||
return new EbonyFly(this);
|
||||
}
|
||||
}
|
||||
|
||||
class EbonyFlyEffect extends OneShotEffect {
|
||||
|
||||
EbonyFlyEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "roll a d6. Until end of turn, you may have {this} " +
|
||||
"become an X/X Insect artifact creature with flying, where X is the result";
|
||||
}
|
||||
|
||||
private EbonyFlyEffect(final EbonyFlyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EbonyFlyEffect copy() {
|
||||
return new EbonyFlyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
int result = player.rollDice(source, game, 6);
|
||||
Permanent permanent = source.getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null || !player.chooseUse(
|
||||
outcome, "Have " + permanent.getName() + " become a "
|
||||
+ result + '/' + result + " creature until end of turn?", source, game
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
game.addEffect(new BecomesCreatureSourceEffect(
|
||||
new CreatureToken(result, result)
|
||||
.withType(CardType.ARTIFACT)
|
||||
.withAbility(FlyingAbility.getInstance()),
|
||||
"", Duration.EndOfTurn, false, false
|
||||
), source);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -32,7 +33,7 @@ public final class EmissaryOfTheSleepless extends CardImpl {
|
|||
|
||||
// When Emissary of the Sleepless enters the battlefield, if a creature died this turn, create a 1/1 white Spirit creature token with flying.
|
||||
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new SpiritWhiteToken()));
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, "When {this} enters the battlefield, if a creature died this turn, create a 1/1 white Spirit creature token with flying."));
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, "When {this} enters the battlefield, if a creature died this turn, create a 1/1 white Spirit creature token with flying.").addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private EmissaryOfTheSleepless(final EmissaryOfTheSleepless card) {
|
||||
|
|
|
@ -22,7 +22,7 @@ import java.util.UUID;
|
|||
* @author North
|
||||
*/
|
||||
public final class EtchedChampion extends CardImpl {
|
||||
private static final String ruleText = "<i>Metalcraft</i> — Etched Champion has protection from all colors as long as you control three or more artifacts";
|
||||
private static final String ruleText = "{this} has protection from all colors as long as you control three or more artifacts";
|
||||
|
||||
private static final FilterCard filter = new FilterCard("all colors");
|
||||
|
||||
|
|
|
@ -8,10 +8,7 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.game.Game;
|
||||
|
@ -40,7 +37,7 @@ public final class ExclusionRitual extends CardImpl {
|
|||
// Imprint - When Exclusion Ritual enters the battlefield, exile target nonland permanent.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ExclusionRitualImprintEffect(), false);
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(ability.setAbilityWord(AbilityWord.IMPRINT));
|
||||
// Players can't cast spells with the same name as the exiled card.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ExclusionRitualReplacementEffect()));
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ class ExertInfluenceEffect extends OneShotEffect {
|
|||
|
||||
public ExertInfluenceEffect() {
|
||||
super(Outcome.GainControl);
|
||||
this.staticText = "Gain control of target creature if its power is less than or equal to the number of colors spent to cast this spell";
|
||||
this.staticText = "Gain control of target creature if its power is less than or equal to the number of colors of mana spent to cast this spell";
|
||||
}
|
||||
|
||||
public ExertInfluenceEffect(final ExertInfluenceEffect effect) {
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.util.UUID;
|
|||
* @author Loki
|
||||
*/
|
||||
public final class EzurisBrigade extends CardImpl {
|
||||
private static final String rule = "<i>Metalcraft</i> — As long as you control three or more artifacts, Ezuri's Brigade gets +4/+4 and has trample";
|
||||
private static final String rule = "As long as you control three or more artifacts, {this} gets +4/+4";
|
||||
|
||||
public EzurisBrigade(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}");
|
||||
|
@ -33,7 +33,7 @@ public final class EzurisBrigade extends CardImpl {
|
|||
ContinuousEffect boostSource = new BoostSourceEffect(4, 4, Duration.WhileOnBattlefield);
|
||||
ConditionalContinuousEffect effect = new ConditionalContinuousEffect(boostSource, MetalcraftCondition.instance, rule);
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, effect);
|
||||
ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield), MetalcraftCondition.instance, ""));
|
||||
ability.addEffect(new ConditionalContinuousEffect(new GainAbilitySourceEffect(TrampleAbility.getInstance(), Duration.WhileOnBattlefield), MetalcraftCondition.instance, "and has trample"));
|
||||
ability.setAbilityWord(AbilityWord.METALCRAFT);
|
||||
ability.addHint(MetalcraftHint.instance);
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -7,9 +7,11 @@ import mage.abilities.common.EntersBattlefieldAbility;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
|
@ -30,7 +32,7 @@ public final class FesterhideBoar extends CardImpl {
|
|||
this.addAbility(TrampleAbility.getInstance());
|
||||
// <i>Morbid</i> — Festerhide Boar enters the battlefield with two +1/+1 counters on it if a creature died this turn.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)),
|
||||
MorbidCondition.instance, ""), "with two +1/+1 counters on it if a creature died this turn"));
|
||||
MorbidCondition.instance, ""), "with two +1/+1 counters on it if a creature died this turn").addHint(MorbidHint.instance).setAbilityWord(AbilityWord.MORBID));
|
||||
}
|
||||
|
||||
private FesterhideBoar(final FesterhideBoar card) {
|
||||
|
|
110
Mage.Sets/src/mage/cards/f/FeySteed.java
Normal file
110
Mage.Sets/src/mage/cards/f/FeySteed.java
Normal file
|
@ -0,0 +1,110 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.keyword.IndestructibleAbility;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.filter.predicate.permanent.AttackingPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author anonymous
|
||||
*/
|
||||
public final class FeySteed extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(
|
||||
"another target attacking creature you control");
|
||||
|
||||
static {
|
||||
filter.add(TargetController.YOU.getControllerPredicate());
|
||||
filter.add(AnotherPredicate.instance);
|
||||
filter.add(AttackingPredicate.instance);
|
||||
}
|
||||
|
||||
public FeySteed(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[] { CardType.CREATURE }, "{2}{W}{W}");
|
||||
|
||||
this.subtype.add(SubType.ELK);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(4);
|
||||
|
||||
// Whenever Fey Steed attacks, another target attacking creature you control
|
||||
// gains indestructible until end of turn.
|
||||
Ability ability = new AttacksTriggeredAbility(
|
||||
new GainAbilityTargetEffect(IndestructibleAbility.getInstance(), Duration.EndOfTurn), false);
|
||||
ability.addTarget(new TargetCreaturePermanent(filter));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Whenever a creature or planeswalker you control becomes the target of a spell
|
||||
// or ability an opponent controls, you may draw a card.
|
||||
this.addAbility(new FeySteedTriggeredAbility());
|
||||
}
|
||||
|
||||
private FeySteed(final FeySteed card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeySteed copy() {
|
||||
return new FeySteed(this);
|
||||
}
|
||||
}
|
||||
|
||||
class FeySteedTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public FeySteedTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), true);
|
||||
}
|
||||
|
||||
public FeySteedTriggeredAbility(FeySteedTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.TARGETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Player targetter = game.getPlayer(event.getPlayerId());
|
||||
if (targetter == null || !targetter.hasOpponent(this.controllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
||||
if (permanent == null || !permanent.isControlledBy(this.getControllerId())
|
||||
|| (!permanent.isCreature(game) && !permanent.isPlaneswalker(game))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a creature or planeswalker you control becomes the target of a spell or ability an opponent controls, you may draw a card";
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeySteedTriggeredAbility copy() {
|
||||
return new FeySteedTriggeredAbility(this);
|
||||
}
|
||||
}
|
162
Mage.Sets/src/mage/cards/f/Fiendlash.java
Normal file
162
Mage.Sets/src/mage/cards/f/Fiendlash.java
Normal file
|
@ -0,0 +1,162 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostEquippedEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.DamagedPermanentBatchEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetPlayerOrPlaneswalker;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zeffirojoe
|
||||
*/
|
||||
public final class Fiendlash extends CardImpl {
|
||||
|
||||
public Fiendlash(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[] { CardType.ARTIFACT }, "{1}{R}");
|
||||
|
||||
this.subtype.add(SubType.EQUIPMENT);
|
||||
|
||||
// Equipped creature gets +2/+0 and has reach.
|
||||
Ability staticAbility = new SimpleStaticAbility(new BoostEquippedEffect(2, 0));
|
||||
staticAbility.addEffect(new GainAbilityAttachedEffect(ReachAbility.getInstance(), AttachmentType.EQUIPMENT)
|
||||
.setText("and has reach"));
|
||||
this.addAbility(staticAbility);
|
||||
|
||||
// Whenever equipped creature is dealt damage, it deals damage equal to its
|
||||
// power to target player or planeswalker.
|
||||
this.addAbility(new FiendlashTriggeredAbility());
|
||||
|
||||
// Equip {2}{R}
|
||||
this.addAbility(new EquipAbility(Outcome.AddAbility, new ManaCostsImpl<>("{2}{R}")));
|
||||
}
|
||||
|
||||
private Fiendlash(final Fiendlash card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fiendlash copy() {
|
||||
return new Fiendlash(this);
|
||||
}
|
||||
}
|
||||
|
||||
class FiendlashTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
FiendlashTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new FiendlashEffect(), false);
|
||||
this.addTarget(new TargetPlayerOrPlaneswalker());
|
||||
}
|
||||
|
||||
private FiendlashTriggeredAbility(final FiendlashTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FiendlashTriggeredAbility copy() {
|
||||
return new FiendlashTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PERMANENT_BATCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent equipment = game.getPermanent(this.getSourceId());
|
||||
if (equipment == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID attachedCreature = equipment.getAttachedTo();
|
||||
if (attachedCreature == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
game.getState().setValue("Fiendlash" + equipment.getId(), attachedCreature);
|
||||
|
||||
DamagedPermanentBatchEvent dEvent = (DamagedPermanentBatchEvent) event;
|
||||
for (DamagedEvent damagedEvent : dEvent.getEvents()) {
|
||||
UUID targetID = damagedEvent.getTargetId();
|
||||
if (targetID == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetID == attachedCreature) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever equipped creature is dealt damage, it deals damage equal to its power to target player or planeswalker.";
|
||||
}
|
||||
}
|
||||
|
||||
class FiendlashEffect extends OneShotEffect {
|
||||
|
||||
FiendlashEffect() {
|
||||
super(Outcome.Benefit);
|
||||
}
|
||||
|
||||
private FiendlashEffect(final FiendlashEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FiendlashEffect copy() {
|
||||
return new FiendlashEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent creature = game
|
||||
.getPermanentOrLKIBattlefield((UUID) game.getState().getValue("Fiendlash" + source.getSourceId()));
|
||||
if (creature == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int damage = creature.getPower().getValue();
|
||||
if (damage < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
||||
if (permanent != null) {
|
||||
if (permanent.isPlaneswalker()) {
|
||||
permanent.damage(damage, creature.getId(), source, game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Player player = game.getPlayer(source.getFirstTarget());
|
||||
if (player != null) {
|
||||
player.damage(damage, creature.getId(), source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ public final class FighterClass extends CardImpl {
|
|||
|
||||
// When Fighter Class enters the battlefield, search your library for an Equipment card, reveal it, put it into your hand, then shuffle.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(
|
||||
new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter))
|
||||
new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true)
|
||||
));
|
||||
|
||||
// {1}{R}{W}: Level 2
|
||||
|
@ -58,7 +58,7 @@ public final class FighterClass extends CardImpl {
|
|||
// Equip abilities you activate cost {2} less to activate.
|
||||
this.addAbility(new SimpleStaticAbility(new GainClassAbilitySourceEffect(
|
||||
new AbilitiesCostReductionControllerEffect(EquipAbility.class, "Equip")
|
||||
.setText("\"equip abilities you activate cost {2} less to activate\""),
|
||||
.setText("equip abilities you activate cost {2} less to activate"),
|
||||
2
|
||||
)));
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ public final class FindThePath extends CardImpl {
|
|||
new SimpleManaAbility(
|
||||
Zone.BATTLEFIELD, new Mana(ManaType.GREEN, 2), new TapSourceCost()
|
||||
), AttachmentType.AURA
|
||||
)));
|
||||
).setText("enchanted land has \"{T}: Add {G}{G}.\"")));
|
||||
}
|
||||
|
||||
private FindThePath(final FindThePath card) {
|
||||
|
|
156
Mage.Sets/src/mage/cards/f/Flameskull.java
Normal file
156
Mage.Sets/src/mage/cards/f/Flameskull.java
Normal file
|
@ -0,0 +1,156 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CantBlockAbility;
|
||||
import mage.abilities.common.DiesSourceTriggeredAbility;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class Flameskull extends CardImpl {
|
||||
|
||||
public Flameskull(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}");
|
||||
|
||||
this.subtype.add(SubType.SKELETON);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(1);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Flameskull can't block.
|
||||
this.addAbility(new CantBlockAbility());
|
||||
|
||||
// Rejuvenation — When Flameskull dies, exile it. If you do, exile the top card of your library. Until the end of your next turn, you may play one of those cards.
|
||||
this.addAbility(new DiesSourceTriggeredAbility(new FlameskullEffect())
|
||||
.withFlavorWord("Rejuventation"), new FlameskullWatcher());
|
||||
}
|
||||
|
||||
private Flameskull(final Flameskull card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flameskull copy() {
|
||||
return new Flameskull(this);
|
||||
}
|
||||
}
|
||||
|
||||
class FlameskullEffect extends OneShotEffect {
|
||||
|
||||
FlameskullEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "exile it. If you do, exile the top card of your library. " +
|
||||
"Until the end of your next turn, you may play one of those cards";
|
||||
}
|
||||
|
||||
private FlameskullEffect(final FlameskullEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlameskullEffect copy() {
|
||||
return new FlameskullEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = source.getSourceObjectIfItStillExists(game);
|
||||
if (player == null || !(sourceObject instanceof Card)) {
|
||||
return false;
|
||||
}
|
||||
Cards cards = new CardsImpl(player.getLibrary().getFromTop(game));
|
||||
cards.add((Card) sourceObject);
|
||||
player.moveCards(cards, Zone.EXILED, source, game);
|
||||
game.addEffect(new FlameskullPlayEffect(cards, game), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class FlameskullPlayEffect extends AsThoughEffectImpl {
|
||||
|
||||
private final Set<MageObjectReference> morSet = new HashSet<>();
|
||||
|
||||
FlameskullPlayEffect(Cards cards, Game game) {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.UntilEndOfYourNextTurn, Outcome.Benefit);
|
||||
cards.stream()
|
||||
.map(uuid -> new MageObjectReference(uuid, game))
|
||||
.forEach(morSet::add);
|
||||
}
|
||||
|
||||
private FlameskullPlayEffect(final FlameskullPlayEffect effect) {
|
||||
super(effect);
|
||||
this.morSet.addAll(effect.morSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlameskullPlayEffect copy() {
|
||||
return new FlameskullPlayEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
UUID objectIdToCast = CardUtil.getMainCardId(game, sourceId);
|
||||
return source.isControlledBy(affectedControllerId)
|
||||
&& morSet.stream().anyMatch(mor -> mor.refersTo(objectIdToCast, game))
|
||||
&& FlameskullWatcher.checkRef(source, morSet, game);
|
||||
}
|
||||
}
|
||||
|
||||
class FlameskullWatcher extends Watcher {
|
||||
|
||||
private final Map<MageObjectReference, Set<MageObjectReference>> morMap = new HashMap<>();
|
||||
private static final Set<MageObjectReference> emptySet = new HashSet<>();
|
||||
|
||||
FlameskullWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() != GameEvent.EventType.SPELL_CAST
|
||||
|| event.getAdditionalReference() == null) {
|
||||
return;
|
||||
}
|
||||
MageObjectReference mor = event.getAdditionalReference().getApprovingMageObjectReference();
|
||||
Spell spell = game.getSpell(event.getTargetId());
|
||||
if (mor == null || spell == null) {
|
||||
return;
|
||||
}
|
||||
morMap.computeIfAbsent(mor, x -> new HashSet<>())
|
||||
.add(new MageObjectReference(spell.getMainCard(), game, -1));
|
||||
}
|
||||
|
||||
static boolean checkRef(Ability source, Set<MageObjectReference> morSet, Game game) {
|
||||
FlameskullWatcher watcher = game.getState().getWatcher(FlameskullWatcher.class);
|
||||
return watcher != null
|
||||
&& watcher
|
||||
.morMap
|
||||
.getOrDefault(new MageObjectReference(source.getSourceObject(game), game), emptySet)
|
||||
.stream()
|
||||
.noneMatch(morSet::contains);
|
||||
}
|
||||
}
|
|
@ -4,13 +4,13 @@ import mage.abilities.condition.common.MorbidCondition;
|
|||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.permanent.token.SaprolingToken;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.watchers.common.MorbidWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -27,12 +27,12 @@ public final class FungalRebirth extends CardImpl {
|
|||
getSpellAbility().addEffect(
|
||||
new ReturnFromGraveyardToHandTargetEffect().setText("Return target permanent card from your graveyard to your hand")
|
||||
);
|
||||
getSpellAbility().addWatcher(new MorbidWatcher());
|
||||
getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new CreateTokenEffect(new SaprolingToken(), 2),
|
||||
MorbidCondition.instance,
|
||||
"If a creature died this turn, create two 1/1 green Saproling creature tokens"));
|
||||
getSpellAbility().addTarget(new TargetCardInYourGraveyard(StaticFilters.FILTER_CARD_PERMANENT));
|
||||
getSpellAbility().addHint(MorbidHint.instance);
|
||||
}
|
||||
|
||||
private FungalRebirth(final FungalRebirth card) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.keyword.InvestigateEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.abilities.keyword.ReachAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -34,7 +35,7 @@ public final class FunnelWebRecluse extends CardImpl {
|
|||
MorbidCondition.instance, "<i>Morbid</i> — When {this} enters the battlefield, " +
|
||||
"if a creature died this turn, investigate. <i>(Create a colorless Clue artifact token " +
|
||||
"with \"{2}, Sacrifice this artifact: Draw a card.\")</i>"
|
||||
));
|
||||
).addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private FunnelWebRecluse(final FunnelWebRecluse card) {
|
||||
|
|
|
@ -31,7 +31,6 @@ public final class GalvanicBlast extends CardImpl {
|
|||
MetalcraftCondition.instance, effectText
|
||||
));
|
||||
this.getSpellAbility().addTarget(new TargetAnyTarget());
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
|
||||
this.getSpellAbility().addHint(MetalcraftHint.instance);
|
||||
}
|
||||
|
||||
|
|
106
Mage.Sets/src/mage/cards/g/GelatinousCube.java
Normal file
106
Mage.Sets/src/mage/cards/g/GelatinousCube.java
Normal file
|
@ -0,0 +1,106 @@
|
|||
package mage.cards.g;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.delayed.OnLeaveReturnExiledToBattlefieldAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.abilities.effects.common.ExileUntilSourceLeavesEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.common.FilterOpponentsCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class GelatinousCube extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterOpponentsCreaturePermanent("non-Ooze creature an opponent controls");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(SubType.OOZE.getPredicate()));
|
||||
}
|
||||
|
||||
public GelatinousCube(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}");
|
||||
|
||||
this.subtype.add(SubType.OOZE);
|
||||
this.power = new MageInt(4);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Engulf — When Gelatinous Cube enters the battlefield, exile target non-Ooze creature an opponent controls until Gelatinous Cube leaves the battlefield.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileUntilSourceLeavesEffect(filter.getMessage()));
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new OnLeaveReturnExiledToBattlefieldAbility()));
|
||||
this.addAbility(ability.withFlavorWord("Engulf"));
|
||||
|
||||
// Dissolve — {X}{B}: Put target creature card with mana value X exiled with Gelatinous Cube into its owner's graveyard.
|
||||
ability = new SimpleActivatedAbility(new GelatinousCubeEffect(), new ManaCostsImpl<>("{X}{B}"));
|
||||
ability.setTargetAdjuster(GelatinousCubeAdjuster.instance);
|
||||
this.addAbility(ability.withFlavorWord("Dissolve"));
|
||||
}
|
||||
|
||||
private GelatinousCube(final GelatinousCube card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GelatinousCube copy() {
|
||||
return new GelatinousCube(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum GelatinousCubeAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
ability.getTargets().clear();
|
||||
int xValue = ability.getManaCostsToPay().getX();
|
||||
FilterCard filter = new FilterCreatureCard("creature card with mana value " + xValue);
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, xValue));
|
||||
ability.addTarget(new TargetCardInExile(filter, CardUtil.getExileZoneId(game, ability)));
|
||||
}
|
||||
}
|
||||
|
||||
class GelatinousCubeEffect extends OneShotEffect {
|
||||
|
||||
GelatinousCubeEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "put target creature card with mana value X exiled with {this} into its owner's graveyard";
|
||||
}
|
||||
|
||||
private GelatinousCubeEffect(final GelatinousCubeEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GelatinousCubeEffect copy() {
|
||||
return new GelatinousCubeEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Card card = game.getCard(getTargetPointer().getFirst(game, source));
|
||||
return player != null && card != null && player.moveCards(card, Zone.GRAVEYARD, source, game);
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class GhalmasWarden extends CardImpl {
|
||||
|
||||
private static final String rule = "<i>Metalcraft</i> — Ghalma's Warden gets +2/+2 as long as you control three or more artifacts";
|
||||
private static final String rule = "{this} gets +2/+2 as long as you control three or more artifacts";
|
||||
|
||||
public GhalmasWarden(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}");
|
||||
|
|
|
@ -33,7 +33,9 @@ public final class GoblinMorningstar extends CardImpl {
|
|||
|
||||
// Equipped creature gets +1/+0 and has trample.
|
||||
Ability ability = new SimpleStaticAbility(new BoostEquippedEffect(1, 0));
|
||||
ability.addEffect(new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.EQUIPMENT));
|
||||
ability.addEffect(new GainAbilityAttachedEffect(
|
||||
TrampleAbility.getInstance(), AttachmentType.EQUIPMENT
|
||||
).setText("and has trample"));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Equip {1}{R}
|
||||
|
|
|
@ -7,9 +7,11 @@ import mage.abilities.common.EntersBattlefieldAbility;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
|
@ -30,7 +32,7 @@ public final class GravetillerWurm extends CardImpl {
|
|||
this.addAbility(TrampleAbility.getInstance());
|
||||
// <i>Morbid</i> — Gravetiller Wurm enters the battlefield with four +1/+1 counters on it if a creature died this turn.
|
||||
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(4)),
|
||||
MorbidCondition.instance, ""), "with four +1/+1 counters on it if a creature died this turn"));
|
||||
MorbidCondition.instance, ""), "with four +1/+1 counters on it if a creature died this turn").addHint(MorbidHint.instance).setAbilityWord(AbilityWord.MORBID));
|
||||
}
|
||||
|
||||
private GravetillerWurm(final GravetillerWurm card) {
|
||||
|
|
|
@ -36,7 +36,7 @@ public final class GreenDragon extends CardImpl {
|
|||
// Poison Breath — When Green Dragon enters the battlefield, until end of turn, whenever a creature an opponent controls is dealt damage, destroy it.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
|
||||
new GreenDragonDelayedTriggeredAbility(), false
|
||||
)));
|
||||
)).withFlavorWord("Poison Breath"));
|
||||
}
|
||||
|
||||
private GreenDragon(final GreenDragon card) {
|
||||
|
|
|
@ -31,7 +31,7 @@ public final class GreenwheelLiberator extends CardImpl {
|
|||
// permanent you controlled left the battlefield this turn.
|
||||
Ability ability = new EntersBattlefieldAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), false, RevoltCondition.instance,
|
||||
"<i>Revolt</i> — {this} enters the battlefield with two +1/+1 counters on it if a permanent you controlled left the battlefield this turn", null);
|
||||
"<i>Revolt</i> — {this} enters the battlefield with two +1/+1 counters on it if a permanent you controlled left the battlefield this turn.", null);
|
||||
ability.addWatcher(new RevoltWatcher());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
85
Mage.Sets/src/mage/cards/g/GrimHireling.java
Normal file
85
Mage.Sets/src/mage/cards/g/GrimHireling.java
Normal file
|
@ -0,0 +1,85 @@
|
|||
package mage.cards.g;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.ActivateAsSorceryActivatedAbility;
|
||||
import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility;
|
||||
import mage.abilities.costs.common.SacrificeXTargetCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.GetXValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.token.TreasureToken;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class GrimHireling extends CardImpl {
|
||||
|
||||
private static final FilterControlledPermanent filter
|
||||
= new FilterControlledPermanent(SubType.TREASURE, "Treasures");
|
||||
|
||||
public GrimHireling(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||
|
||||
this.subtype.add(SubType.TIEFLING);
|
||||
this.subtype.add(SubType.ROGUE);
|
||||
this.power = new MageInt(3);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Whenever one or more creatures you control deal combat damage to a player, create two Treasure tokens.
|
||||
this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(
|
||||
new CreateTokenEffect(new TreasureToken(), 2)
|
||||
));
|
||||
|
||||
// {B}, Sacrifice X Treasures: Target creature gets -X/-X until end of turn. Activate only as a sorcery.
|
||||
Ability ability = new ActivateAsSorceryActivatedAbility(new GrimHirelingEffect(), new ManaCostsImpl<>("{B}"));
|
||||
ability.addCost(new SacrificeXTargetCost(filter));
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private GrimHireling(final GrimHireling card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrimHireling copy() {
|
||||
return new GrimHireling(this);
|
||||
}
|
||||
}
|
||||
|
||||
class GrimHirelingEffect extends OneShotEffect {
|
||||
|
||||
GrimHirelingEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "target creature gets -X/-X until end of turn";
|
||||
}
|
||||
|
||||
private GrimHirelingEffect(final GrimHirelingEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrimHirelingEffect copy() {
|
||||
return new GrimHirelingEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int xValue = GetXValue.instance.calculate(game, source, this);
|
||||
game.addEffect(new BoostTargetEffect(-xValue, -xValue), source);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import java.util.UUID;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.common.CastOnlyIfConditionIsTrueAbility;
|
||||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -28,7 +29,7 @@ public final class GrimWanderer extends CardImpl {
|
|||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// Tragic Backstory — Cast this spell only if a creature died this turn.
|
||||
this.addAbility(new CastOnlyIfConditionIsTrueAbility(MorbidCondition.instance).withFlavorWord("Tragic Backstory"));
|
||||
this.addAbility(new CastOnlyIfConditionIsTrueAbility(MorbidCondition.instance).withFlavorWord("Tragic Backstory").addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private GrimWanderer(final GrimWanderer card) {
|
||||
|
|
|
@ -5,6 +5,7 @@ import mage.abilities.condition.common.MorbidCondition;
|
|||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.discard.DiscardTargetEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.cards.CardsImpl;
|
||||
|
@ -36,6 +37,7 @@ public final class GruesomeDiscovery extends CardImpl {
|
|||
"you choose two cards from it, then that player discards those cards"
|
||||
));
|
||||
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||
this.getSpellAbility().addHint(MorbidHint.instance);
|
||||
}
|
||||
|
||||
private GruesomeDiscovery(final GruesomeDiscovery card) {
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package mage.cards.g;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -15,7 +12,6 @@ import mage.constants.CardType;
|
|||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.counters.CounterType;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -34,7 +30,9 @@ public final class GuildThief extends CardImpl {
|
|||
|
||||
// Whenever Guild Thief deals combat damage to a player, put a +1/+1 counter on it.
|
||||
this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), false
|
||||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(1))
|
||||
.setText("put a +1/+1 counter on it"),
|
||||
false
|
||||
));
|
||||
|
||||
// Cunning Action — {3}{U}: Guild Thief can't be blocked this turn.
|
||||
|
|
|
@ -31,9 +31,8 @@ public final class HeartlessPillage extends CardImpl {
|
|||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new CreateTokenEffect(new TreasureToken()),
|
||||
RaidCondition.instance,
|
||||
"<br/><br/><i>Raid</i> — If you attacked with a creature this turn, create a colorless Treasure artifact token with \"{T}, Sacrifice this artifact: Add one mana of any color.\""));
|
||||
"<br/><br/><i>Raid</i> — If you attacked this turn, create a colorless Treasure artifact token with \"{T}, Sacrifice this artifact: Add one mana of any color.\""));
|
||||
this.getSpellAbility().addWatcher(new PlayerAttackedWatcher());
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.RAID);
|
||||
this.getSpellAbility().addHint(RaidHint.instance);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ public final class HiddenStockpile extends CardImpl {
|
|||
|
||||
// <i>Revolt</i> — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, create a 1/1 colorless Servo artifact creature token.
|
||||
Ability ability = new ConditionalInterveningIfTriggeredAbility(new BeginningOfYourEndStepTriggeredAbility(new CreateTokenEffect(new ServoToken()), false), RevoltCondition.instance,
|
||||
"<i>Revolt</i> — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, create a 1/1 colorless Servo artifact creature token");
|
||||
"<i>Revolt</i> — At the beginning of your end step, if a permanent you controlled left the battlefield this turn, create a 1/1 colorless Servo artifact creature token.");
|
||||
ability.setAbilityWord(AbilityWord.REVOLT);
|
||||
ability.addWatcher(new RevoltWatcher());
|
||||
this.addAbility(ability);
|
||||
|
|
|
@ -8,6 +8,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -30,7 +31,7 @@ public final class HollowhengeScavenger extends CardImpl {
|
|||
|
||||
// <i>Morbid</i> — When Hollowhenge Scavenger enters the battlefield, if a creature died this turn, you gain 5 life.
|
||||
TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new GainLifeEffect(5));
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, staticText));
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, MorbidCondition.instance, staticText).addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private HollowhengeScavenger(final HollowhengeScavenger card) {
|
||||
|
|
|
@ -38,10 +38,9 @@ public final class HowlOfTheHorde extends CardImpl {
|
|||
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(
|
||||
new CreateDelayedTriggeredAbilityEffect(new HowlOfTheHordeDelayedTriggeredAbility()),
|
||||
RaidCondition.instance,
|
||||
"<br><br><i>Raid</i> — If you attacked with a creature this turn, when you cast your next instant or sorcery spell this turn, copy that spell an additional time. You may choose new targets for the copy.")
|
||||
"<br><br><i>Raid</i> — If you attacked this turn, when you cast your next instant or sorcery spell this turn, copy that spell an additional time. You may choose new targets for the copy.")
|
||||
);
|
||||
this.getSpellAbility().addWatcher(new PlayerAttackedWatcher());
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.RAID);
|
||||
this.getSpellAbility().addHint(RaidHint.instance);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.util.UUID;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -28,8 +29,9 @@ public final class HungerOfTheHowlpack extends CardImpl {
|
|||
new AddCountersTargetEffect(CounterType.P1P1.createInstance(3)),
|
||||
new AddCountersTargetEffect(CounterType.P1P1.createInstance()),
|
||||
MorbidCondition.instance,
|
||||
"Put a +1/+1 counter on target creature. <i>Morbid</i> — Put three +1/+1 counters on that creature instead if a creature died this turn"));
|
||||
"Put a +1/+1 counter on target creature.<br><i>Morbid</i> — Put three +1/+1 counters on that creature instead if a creature died this turn"));
|
||||
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
this.getSpellAbility().addHint(MorbidHint.instance);
|
||||
}
|
||||
|
||||
private HungerOfTheHowlpack(final HungerOfTheHowlpack card) {
|
||||
|
|
|
@ -21,7 +21,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class IndomitableArchangel extends CardImpl {
|
||||
|
||||
private static final String rule = "<i>Metalcraft</i> — Artifacts you control have shroud as long as you control three or more artifacts.";
|
||||
private static final String rule = "Artifacts you control have shroud as long as you control three or more artifacts.";
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("Artifacts");
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ public final class InexorableBlob extends CardImpl {
|
|||
// in your graveyard, create a 3/3 green Ooze creature token that’s tapped and attacking.
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(new AttacksTriggeredAbility(new CreateTokenEffect(new InexorableBlobOozeToken(), 1, true, true), false),
|
||||
DeliriumCondition.instance,
|
||||
"<i>Delirium</i> — Whenever {this} attacks and there are at least four card types among cards in your graveyard, "
|
||||
+ "create a 3/3 green Ooze creature token tapped and attacking.")
|
||||
"<i>Delirium</i> — Whenever {this} attacks, if there are four or more card types among cards in your graveyard, " +
|
||||
"create a 3/3 green Ooze creature token that's tapped and attacking.")
|
||||
.addHint(CardTypesInGraveyardHint.YOU));
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public final class IronGolem extends CardImpl {
|
|||
|
||||
// Iron Golem attacks or blocks each combat if able.
|
||||
Ability ability = new SimpleStaticAbility(new AttacksIfAbleSourceEffect(Duration.WhileOnBattlefield).setText("{this} attacks"));
|
||||
ability.addEffect(new BlocksIfAbleSourceEffect(Duration.WhileOnBattlefield).setText("or blocks each combat if able"));
|
||||
ability.addEffect(new BlocksIfAbleSourceEffect(Duration.WhileOnBattlefield).setText("blocks each combat if able").concatBy("or"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
|
@ -37,7 +38,7 @@ public final class KnowledgePool extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{6}");
|
||||
|
||||
// Imprint - When Knowledge Pool enters the battlefield, each player exiles the top three cards of their library
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new KnowledgePoolEffect1(), false));
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new KnowledgePoolEffect1(), false).setAbilityWord(AbilityWord.IMPRINT));
|
||||
|
||||
// Whenever a player casts a spell from their hand, that player exiles it. If the player does, they may cast another nonland card exiled with Knowledge Pool without paying that card's mana cost.
|
||||
this.addAbility(new KnowledgePoolAbility());
|
||||
|
|
|
@ -49,8 +49,9 @@ class LifeAndLimbEffect extends ContinuousEffectImpl {
|
|||
LifeAndLimbEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Neutral);
|
||||
staticText = "All Forests and all Saprolings are 1/1 green Saproling creatures and Forest lands in addition to their other types";
|
||||
this.dependencyTypes.add(DependencyType.BecomeForest);
|
||||
this.dependencyTypes.add(DependencyType.BecomeCreature);
|
||||
|
||||
this.dependendToTypes.add(DependencyType.BecomeForest);
|
||||
this.dependendToTypes.add(DependencyType.BecomeCreature);
|
||||
}
|
||||
|
||||
LifeAndLimbEffect(final LifeAndLimbEffect effect) {
|
||||
|
|
|
@ -5,10 +5,10 @@ import java.util.UUID;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.watchers.common.MorbidWatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -21,8 +21,8 @@ public final class LifeGoesOn extends CardImpl {
|
|||
|
||||
|
||||
// You gain 4 life. If a creature died this turn, you gain 8 life instead.
|
||||
getSpellAbility().addWatcher(new MorbidWatcher());
|
||||
getSpellAbility().addEffect(new ConditionalOneShotEffect(new GainLifeEffect(8), new GainLifeEffect(4), MorbidCondition.instance, "You gain 4 life. If a creature died this turn, you gain 8 life instead"));
|
||||
this.getSpellAbility().addHint(MorbidHint.instance);
|
||||
}
|
||||
|
||||
private LifeGoesOn(final LifeGoesOn card) {
|
||||
|
|
|
@ -37,7 +37,7 @@ public final class LifecraftCavalry extends CardImpl {
|
|||
new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)),
|
||||
false,
|
||||
RevoltCondition.instance,
|
||||
"<i>Revolt</i> — {this} enters the battlefield with two +1/+1 counter on it if a permanent you controlled left the battlefield this turn", null),
|
||||
"<i>Revolt</i> — {this} enters the battlefield with two +1/+1 counters on it if a permanent you controlled left the battlefield this turn.", null),
|
||||
new RevoltWatcher()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public final class LightfootRogue extends CardImpl {
|
|||
20, 20,
|
||||
new BoostSourceEffect(
|
||||
3, 0, Duration.EndOfTurn
|
||||
).setText("it gets +1/+0"),
|
||||
).setText("it gets +3/+0"),
|
||||
new GainAbilitySourceEffect(
|
||||
FirstStrikeAbility.getInstance(), Duration.EndOfTurn
|
||||
).setText("and gains first strike"),
|
||||
|
|
|
@ -9,6 +9,7 @@ import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
|||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.abilities.effects.common.continuous.BoostControlledEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -17,7 +18,6 @@ import mage.constants.SubType;
|
|||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.permanent.token.ZombieToken;
|
||||
import mage.watchers.common.MorbidWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -48,7 +48,7 @@ public final class LilianasDevotee extends CardImpl {
|
|||
), TargetController.YOU, false), MorbidCondition.instance,
|
||||
"At the beginning of your end step, if a creature died this turn, " +
|
||||
"you may pay {1}{B}. If you do, create a 2/2 black Zombie creature token."
|
||||
), new MorbidWatcher());
|
||||
).addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private LilianasDevotee(final LilianasDevotee card) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import mage.abilities.common.BeginningOfEndStepTriggeredAbility;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -19,7 +20,6 @@ import mage.game.Game;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.watchers.common.MorbidWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -41,7 +41,7 @@ public final class LilianasScrounger extends CardImpl {
|
|||
new LilianasScroungerEffect(), TargetController.ANY, false
|
||||
), MorbidCondition.instance, "At the beginning of each end step, " +
|
||||
"if a creature died this turn, you may put a loyalty counter on a Liliana planeswalker you control."
|
||||
), new MorbidWatcher());
|
||||
).addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private LilianasScrounger(final LilianasScrounger card) {
|
||||
|
|
|
@ -39,7 +39,7 @@ public final class LoathsomeTroll extends CardImpl {
|
|||
));
|
||||
|
||||
// 10-19 | Return Loathsome Troll to your hand.
|
||||
effect.addTableEntry(10, 19, new ReturnToHandSourceEffect().setText("retun {this} to your hand"));
|
||||
effect.addTableEntry(10, 19, new ReturnToHandSourceEffect().setText("return {this} to your hand"));
|
||||
|
||||
// 20 | Return Loathsome Troll to the battlefield tapped.
|
||||
effect.addTableEntry(20, 20, new ReturnSourceFromGraveyardToBattlefieldEffect(true)
|
||||
|
|
|
@ -42,7 +42,7 @@ public final class MalakirSoothsayer extends CardImpl {
|
|||
|
||||
// <i>Cohort</i> — {T}, Tap an untapped Ally you control: You draw a card and you lose a life.
|
||||
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
|
||||
new DrawCardSourceControllerEffect(1),
|
||||
new DrawCardSourceControllerEffect(1).setText("you draw a card"),
|
||||
new TapSourceCost());
|
||||
ability.setAbilityWord(AbilityWord.COHORT);
|
||||
ability.addCost(new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, false)));
|
||||
|
|
|
@ -7,6 +7,7 @@ import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
|||
import mage.abilities.effects.common.CastSourceTriggeredAbility;
|
||||
import mage.abilities.effects.common.CopySourceSpellEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -35,10 +36,10 @@ public final class MaliciousAffliction extends CardImpl {
|
|||
Ability ability = new ConditionalInterveningIfTriggeredAbility(
|
||||
new CastSourceTriggeredAbility(new CopySourceSpellEffect(), true),
|
||||
MorbidCondition.instance, "<i>Morbid</i> — When you cast this spell, " +
|
||||
"if a creature died this turn, you may copy {this} and may choose a new target for the copy"
|
||||
"if a creature died this turn, you may copy {this} and may choose a new target for the copy."
|
||||
);
|
||||
ability.setRuleAtTheTop(true);
|
||||
this.addAbility(ability);
|
||||
this.addAbility(ability.addHint(MorbidHint.instance));
|
||||
|
||||
// Destroy target nonblack creature.
|
||||
this.getSpellAbility().addEffect(new DestroyTargetEffect());
|
||||
|
|
|
@ -58,7 +58,7 @@ enum MercadianAtlasCondition implements Condition {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{this} is attacking";
|
||||
return "you didn't play a land this turn";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
58
Mage.Sets/src/mage/cards/m/MidnightPathlighter.java
Normal file
58
Mage.Sets/src/mage/cards/m/MidnightPathlighter.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.ControlledCreaturesDealCombatDamagePlayerTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesAllEffect;
|
||||
import mage.abilities.effects.keyword.VentureIntoTheDungeonEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class MidnightPathlighter extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter
|
||||
= new FilterCreaturePermanent("except by legendary creatures");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.not(SuperType.LEGENDARY.getPredicate()));
|
||||
}
|
||||
|
||||
public MidnightPathlighter(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}");
|
||||
|
||||
this.subtype.add(SubType.HUMAN);
|
||||
this.subtype.add(SubType.WIZARD);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(3);
|
||||
|
||||
// Creatures you control can't be blocked except by legendary creatures.
|
||||
this.addAbility(new SimpleStaticAbility(new CantBeBlockedByCreaturesAllEffect(
|
||||
StaticFilters.FILTER_PERMANENT_CREATURES_CONTROLLED,
|
||||
filter, Duration.WhileOnBattlefield
|
||||
)));
|
||||
|
||||
// Whenever one or more creatures you control deal combat damage to a player, venture into the dungeon.
|
||||
this.addAbility(new ControlledCreaturesDealCombatDamagePlayerTriggeredAbility(new VentureIntoTheDungeonEffect()));
|
||||
}
|
||||
|
||||
private MidnightPathlighter(final MidnightPathlighter card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MidnightPathlighter copy() {
|
||||
return new MidnightPathlighter(this);
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ public final class MightBeyondReason extends CardImpl {
|
|||
new AddCountersTargetEffect(CounterType.P1P1.createInstance(2)),
|
||||
DeliriumCondition.instance,
|
||||
"Put two +1/+1 counter on target creature.<br>"
|
||||
+ "<i>Delirium</i> — Put three +1/+1 counter on that creature instead if there are four or more card types among cards in your graveyard"
|
||||
+ "<i>Delirium</i> — Put three +1/+1 counters on that creature instead if there are four or more card types among cards in your graveyard"
|
||||
));
|
||||
getSpellAbility().addTarget(new TargetCreaturePermanent());
|
||||
getSpellAbility().addHint(CardTypesInGraveyardHint.YOU);
|
||||
|
|
|
@ -17,6 +17,7 @@ import mage.abilities.effects.common.ExileTargetEffect;
|
|||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
|
@ -102,7 +103,7 @@ class MimicVatTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a nontoken creature dies, you may exile that card. If you do, return each other card exiled with {this} to its owner's graveyard.";
|
||||
return AbilityWord.IMPRINT.formatWord() + "Whenever a nontoken creature dies, you may exile that card. If you do, return each other card exiled with {this} to its owner's graveyard.";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public final class MirranMettle extends CardImpl {
|
||||
|
||||
private static final String effectText = "<i>Metalcraft</i> — That creature gets +4/+4 until end of turn instead if you control three or more artifacts.";
|
||||
private static final String effectText = "<br><i>Metalcraft</i> — That creature gets +4/+4 until end of turn instead if you control three or more artifacts.";
|
||||
|
||||
public MirranMettle(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}");
|
||||
|
@ -31,7 +31,6 @@ public final class MirranMettle extends CardImpl {
|
|||
// Metalcraft — That creature gets +4/+4 until end of turn instead if you control three or more artifacts.
|
||||
this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn),
|
||||
new LockedInCondition(MetalcraftCondition.instance), effectText));
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
|
||||
this.getSpellAbility().addHint(MetalcraftHint.instance);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ public final class MoltenPsyche extends CardImpl {
|
|||
// <i>Metalcraft</i> — If you control three or more artifacts, Molten Psyche deals damage to each opponent equal to the number of cards that player has drawn this turn.
|
||||
this.getSpellAbility().addEffect(new MoltenPsycheEffect());
|
||||
this.getSpellAbility().addWatcher(new MoltenPsycheWatcher());
|
||||
this.getSpellAbility().setAbilityWord(AbilityWord.METALCRAFT);
|
||||
this.getSpellAbility().addHint(MetalcraftHint.instance);
|
||||
}
|
||||
|
||||
|
|
155
Mage.Sets/src/mage/cards/m/MonkClass.java
Normal file
155
Mage.Sets/src/mage/cards/m/MonkClass.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
package mage.cards.m;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BecomesClassLevelTriggeredAbility;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalCostModificationEffect;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.ReturnToHandTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.GainClassAbilitySourceEffect;
|
||||
import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
|
||||
import mage.abilities.keyword.ClassLevelAbility;
|
||||
import mage.abilities.keyword.ClassReminderAbility;
|
||||
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.players.Player;
|
||||
import mage.target.common.TargetNonlandPermanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.common.SpellsCastWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class MonkClass extends CardImpl {
|
||||
|
||||
public MonkClass(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}{U}");
|
||||
|
||||
this.subtype.add(SubType.CLASS);
|
||||
|
||||
// (Gain the next level as a sorcery to add its ability.)
|
||||
this.addAbility(new ClassReminderAbility());
|
||||
|
||||
// The second spell you cast each turn costs {1} less to cast.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalCostModificationEffect(
|
||||
new SpellsCostReductionControllerEffect(StaticFilters.FILTER_CARD, 1),
|
||||
MonkClassCondition.instance, "the second spell you cast each turn costs {1} less to cast"
|
||||
)), new SpellsCastWatcher());
|
||||
|
||||
// {W}{U}: Level 2
|
||||
this.addAbility(new ClassLevelAbility(2, "{W}{U}"));
|
||||
|
||||
// When this Class becomes level 2, return up to one target nonland permanent to its owner's hand.
|
||||
Ability ability = new BecomesClassLevelTriggeredAbility(new ReturnToHandTargetEffect(), 2);
|
||||
ability.addTarget(new TargetNonlandPermanent(0, 1, false));
|
||||
this.addAbility(ability);
|
||||
|
||||
// {1}{W}{U}: Level 3
|
||||
this.addAbility(new ClassLevelAbility(3, "{1}{W}{U}"));
|
||||
|
||||
// At the beginning of your upkeep, exile the top card of your library. For as long as it remains exiled, it has "You may cast this card from exile as long as you've cast another spell this turn."
|
||||
this.addAbility(new SimpleStaticAbility(new GainClassAbilitySourceEffect(
|
||||
new BeginningOfUpkeepTriggeredAbility(
|
||||
new MonkClassEffect(), TargetController.YOU, false
|
||||
), 3
|
||||
)));
|
||||
}
|
||||
|
||||
private MonkClass(final MonkClass card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonkClass copy() {
|
||||
return new MonkClass(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum MonkClassCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
return watcher != null && watcher.getSpellsCastThisTurn(source.getControllerId()).size() == 1;
|
||||
}
|
||||
}
|
||||
|
||||
class MonkClassEffect extends OneShotEffect {
|
||||
|
||||
MonkClassEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "exile the top card of your library. For as long as it remains exiled, " +
|
||||
"it has \"You may cast this card from exile as long as you've cast another spell this turn.\"";
|
||||
}
|
||||
|
||||
private MonkClassEffect(final MonkClassEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonkClassEffect copy() {
|
||||
return new MonkClassEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
Card card = player.getLibrary().getFromTop(game);
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
player.moveCards(card, Zone.EXILED, source, game);
|
||||
game.addEffect(new GainAbilityTargetEffect(
|
||||
new SimpleStaticAbility(new MonkClassCastEffect()),
|
||||
Duration.Custom, null, true
|
||||
).setTargetPointer(new FixedTarget(card, game)), source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class MonkClassCastEffect extends AsThoughEffectImpl {
|
||||
|
||||
MonkClassCastEffect() {
|
||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.Custom, Outcome.Benefit);
|
||||
staticText = "you may cast this card from exile as long as you've cast another spell this turn";
|
||||
}
|
||||
|
||||
private MonkClassCastEffect(final MonkClassCastEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (!sourceId.equals(source.getSourceId()) || !source.isControlledBy(affectedControllerId)) {
|
||||
return false;
|
||||
}
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class);
|
||||
return card != null && watcher != null
|
||||
&& watcher.getSpellsCastThisTurn(affectedControllerId).size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonkClassCastEffect copy() {
|
||||
return new MonkClassCastEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
|||
import mage.abilities.condition.common.MorbidCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
|
@ -34,7 +35,7 @@ public final class MorkrutBanshee extends CardImpl {
|
|||
TriggeredAbility triggeredAbility = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-4, -4, Duration.EndOfTurn));
|
||||
TriggeredAbility ability = new ConditionalInterveningIfTriggeredAbility(triggeredAbility, MorbidCondition.instance, staticText);
|
||||
ability.addTarget(new TargetCreaturePermanent());
|
||||
this.addAbility(ability);
|
||||
this.addAbility(ability.addHint(MorbidHint.instance));
|
||||
}
|
||||
|
||||
private MorkrutBanshee(final MorkrutBanshee card) {
|
||||
|
|
|
@ -12,13 +12,7 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.*;
|
||||
import mage.filter.common.FilterArtifactCard;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
@ -39,7 +33,7 @@ public final class MyrWelder extends CardImpl {
|
|||
// Imprint - {tap}: Exile target artifact card from a graveyard
|
||||
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MyrWelderEffect(), new TapSourceCost());
|
||||
ability.addTarget(new TargetCardInGraveyard(new FilterArtifactCard("artifact card from a graveyard")));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(ability.setAbilityWord(AbilityWord.IMPRINT));
|
||||
|
||||
// Myr Welder has all activated abilities of all cards exiled with it
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new MyrWelderContinuousEffect()));
|
||||
|
|
|
@ -32,7 +32,7 @@ public final class ObNixilisTheFallen extends CardImpl {
|
|||
// Landfall - Whenever a land enters the battlefield under your control, you may have target player lose 3 life.
|
||||
// If you do, put three +1/+1 counters on Ob Nixilis, the Fallen.
|
||||
Ability ability = new LandfallAbility(new LoseLifeTargetEffect(3), true);
|
||||
ability.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)));
|
||||
ability.addEffect(new AddCountersSourceEffect(CounterType.P1P1.createInstance(3)).concatBy("If you do,"));
|
||||
ability.addTarget(new TargetPlayer());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
|
107
Mage.Sets/src/mage/cards/o/OchreJelly.java
Normal file
107
Mage.Sets/src/mage/cards/o/OchreJelly.java
Normal file
|
@ -0,0 +1,107 @@
|
|||
package mage.cards.o;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesSourceTriggeredAbility;
|
||||
import mage.abilities.common.EntersBattlefieldAbility;
|
||||
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
||||
import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
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.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public final class OchreJelly extends CardImpl {
|
||||
|
||||
public OchreJelly(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{X}{G}");
|
||||
|
||||
this.subtype.add(SubType.OOZE);
|
||||
this.power = new MageInt(0);
|
||||
this.toughness = new MageInt(0);
|
||||
|
||||
// Trample
|
||||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// Ochre Jelly enters the battlefield with X +1/+1 counters on it.
|
||||
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.P1P1.createInstance())));
|
||||
|
||||
// Split — When Ochre Jelly dies, if it had two or more +1/+1 counters on it, create a token that's a copy of it at the beginning of the next end step. That token enters the battlefield with half that many +1/+1 counters on it, rounded down.
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
|
||||
new DiesSourceTriggeredAbility(new CreateDelayedTriggeredAbilityEffect(
|
||||
new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new OchreJellyEffect())
|
||||
)), OchreJellyCondition.instance, CardUtil.italicizeWithEmDash("Split")
|
||||
+ "When {this} dies, if it had two or more +1/+1 counters on it, " +
|
||||
"create a token that's a copy of it at the beginning of the next end step. " +
|
||||
"That token enters the battlefield with half that many +1/+1 counters on it, rounded down."
|
||||
));
|
||||
}
|
||||
|
||||
private OchreJelly(final OchreJelly card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OchreJelly copy() {
|
||||
return new OchreJelly(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum OchreJellyCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = (Permanent) source.getEffects().get(0).getValue("permanentLeftBattlefield");
|
||||
return permanent != null && permanent.getCounters(game).getCount(CounterType.P1P1) >= 2;
|
||||
}
|
||||
}
|
||||
|
||||
class OchreJellyEffect extends OneShotEffect {
|
||||
|
||||
OchreJellyEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "create a token that's a copy of {this}";
|
||||
}
|
||||
|
||||
private OchreJellyEffect(final OchreJellyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OchreJellyEffect copy() {
|
||||
return new OchreJellyEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = (Permanent) getValue("permanentLeftBattlefield");
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect();
|
||||
effect.setSavedPermanent(permanent);
|
||||
effect.apply(game, source);
|
||||
int counters = permanent.getCounters(game).getCount(CounterType.P1P1) / 2;
|
||||
for (Permanent token : effect.getAddedPermanent()) {
|
||||
permanent.addCounters(CounterType.P1P1.createInstance(counters), source.getControllerId(), source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import mage.abilities.costs.common.RemoveCountersSourceCost;
|
|||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.common.continuous.BoostSourceEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.abilities.hint.common.MorbidHint;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -37,7 +38,7 @@ public final class OsaiVultures extends CardImpl {
|
|||
// At the beginning of each end step, if a creature died this turn, put a carrion counter on Osai Vultures.
|
||||
this.addAbility(new ConditionalInterveningIfTriggeredAbility(new BeginningOfEndStepTriggeredAbility(
|
||||
new AddCountersSourceEffect(CounterType.CARRION.createInstance()), TargetController.ANY, false), MorbidCondition.instance,
|
||||
"At the beginning of each end step, if a creature died this turn, put a carrion counter on {this}."));
|
||||
"At the beginning of each end step, if a creature died this turn, put a carrion counter on {this}.").addHint(MorbidHint.instance));
|
||||
// Remove two carrion counters from Osai Vultures: Osai Vultures gets +1/+1 until end of turn.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn),
|
||||
new RemoveCountersSourceCost(CounterType.CARRION.createInstance(2))));
|
||||
|
|
|
@ -46,7 +46,7 @@ public final class OswaldFiddlebender extends CardImpl {
|
|||
ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(
|
||||
StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT_AN
|
||||
)));
|
||||
this.addAbility(ability);
|
||||
this.addAbility(ability.withFlavorWord("Magical Tinkering"));
|
||||
}
|
||||
|
||||
private OswaldFiddlebender(final OswaldFiddlebender card) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue