mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
Adding targets (Part 2/3) (#13765)
Adds target and/or target adjuster to cards whose abilities have the word "target", cards H-R. fix EffectKeyValue text, NestOfScarabs Add X value to effects for CycleTriggeredAbility, use with ValorsFlagship and SharkTyphoon, add test
This commit is contained in:
parent
7be454fb92
commit
219cc53cf4
24 changed files with 321 additions and 817 deletions
|
|
@ -37,7 +37,7 @@ public final class GaleWaterdeepProdigy extends CardImpl {
|
|||
// If a spell cast from your graveyard this way would be put into your graveyard, exile it instead.
|
||||
Ability ability = new SpellCastControllerTriggeredAbility(Zone.BATTLEFIELD,
|
||||
new MayCastTargetCardEffect(true)
|
||||
.setText("you may cast up to one of the other type from your graveyard. If a spell cast from your graveyard this way would be put into your graveyard, exile it instead."),
|
||||
.setText("you may cast up to one target card of the other type from your graveyard. If a spell cast from your graveyard this way would be put into your graveyard, exile it instead."),
|
||||
StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY,
|
||||
false, SetTargetPointer.SPELL, Zone.HAND
|
||||
);
|
||||
|
|
@ -84,6 +84,6 @@ enum GaleWaterdeepProdigyAdjuster implements TargetAdjuster {
|
|||
} else {
|
||||
filter = SORCERY_FILTER;
|
||||
}
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
ability.addTarget(new TargetCardInYourGraveyard(0, 1, filter));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,21 @@
|
|||
package mage.cards.h;
|
||||
|
||||
import mage.ApprovingObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.abilities.effects.common.MayCastTargetCardEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterInstantOrSorcerySpell;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.watchers.common.CastFromHandWatcher;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
import mage.target.targetpointer.FirstTargetPointer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -26,13 +24,20 @@ import java.util.UUID;
|
|||
* @author LevelX2
|
||||
*/
|
||||
public final class HarnessTheStorm extends CardImpl {
|
||||
static FilterCard filter = new FilterCard("card with the same name as that spell from your graveyard");
|
||||
|
||||
public HarnessTheStorm(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}");
|
||||
|
||||
// Whenever you cast an instant or sorcery spell from your hand, you may cast
|
||||
// target card with the same name as that spell from your graveyard.
|
||||
this.addAbility(new HarnessTheStormTriggeredAbility(), new CastFromHandWatcher());
|
||||
Ability ability = new SpellCastControllerTriggeredAbility(
|
||||
Zone.BATTLEFIELD, new MayCastTargetCardEffect(false), StaticFilters.FILTER_SPELL_AN_INSTANT_OR_SORCERY,
|
||||
false, SetTargetPointer.SPELL, Zone.HAND
|
||||
);
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter)); // Only used for text generation
|
||||
ability.setTargetAdjuster(HarnessTheStormAdjuster.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private HarnessTheStorm(final HarnessTheStorm card) {
|
||||
|
|
@ -45,78 +50,20 @@ public final class HarnessTheStorm extends CardImpl {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class HarnessTheStormTriggeredAbility extends SpellCastControllerTriggeredAbility {
|
||||
|
||||
private static final FilterInstantOrSorcerySpell filterSpell = new FilterInstantOrSorcerySpell("an instant or sorcery spell from your hand");
|
||||
|
||||
HarnessTheStormTriggeredAbility() {
|
||||
super(new HarnessTheStormEffect(), filterSpell, false);
|
||||
}
|
||||
|
||||
private HarnessTheStormTriggeredAbility(final HarnessTheStormTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
enum HarnessTheStormAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (super.checkTrigger(event, game)) {
|
||||
CastFromHandWatcher watcher = game.getState().getWatcher(CastFromHandWatcher.class);
|
||||
if (watcher != null && watcher.spellWasCastFromHand(event.getSourceId())) {
|
||||
Spell spell = game.getState().getStack().getSpell(event.getSourceId());
|
||||
if (spell != null) {
|
||||
FilterCard filterCard = new FilterCard("a card named " + spell.getName() + " in your graveyard");
|
||||
filterCard.add(new NamePredicate(spell.getName()));
|
||||
this.getTargets().clear();
|
||||
this.getTargets().add(new TargetCardInYourGraveyard(filterCard));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
UUID spellId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|
||||
ability.getTargets().clear();
|
||||
ability.getAllEffects().setTargetPointer(new FirstTargetPointer());
|
||||
|
||||
@Override
|
||||
public HarnessTheStormTriggeredAbility copy() {
|
||||
return new HarnessTheStormTriggeredAbility(this);
|
||||
Spell spell = game.getSpellOrLKIStack(spellId);
|
||||
if (spell == null){
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class HarnessTheStormEffect extends OneShotEffect {
|
||||
|
||||
HarnessTheStormEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "you may cast target card with the same name as that "
|
||||
+ "spell from your graveyard. <i>(You still pay its costs.)</i>";
|
||||
}
|
||||
|
||||
private HarnessTheStormEffect(final HarnessTheStormEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HarnessTheStormEffect copy() {
|
||||
return new HarnessTheStormEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Card card = controller.getGraveyard().get(getTargetPointer().getFirst(game, source), game);
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
if (controller.chooseUse(outcome, "Cast " + card.getIdName() + " from your graveyard?", source, game)) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(card, game, false),
|
||||
game, false, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
|
||||
}
|
||||
return true;
|
||||
|
||||
FilterCard filter = new FilterCard("a card named " + spell.getName() + " in your graveyard");
|
||||
filter.add(new NamePredicate(spell.getName()));
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,21 @@
|
|||
|
||||
package mage.cards.i;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.effects.common.SacrificeSourceEffect;
|
||||
import mage.abilities.effects.common.combat.MustBeBlockedByTargetSourceEffect;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.abilities.triggers.BeginningOfEndStepTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.constants.*;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -39,7 +34,12 @@ public final class ImpetuousDevils extends CardImpl {
|
|||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
// When Impetuous Devils attacks, up to one target creature defending player controls blocks it this combat if able.
|
||||
this.addAbility(new ImpetuousDevilsAbility());
|
||||
TriggeredAbility ability = new AttacksTriggeredAbility(new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat)
|
||||
.setText("up to one target creature defending player controls blocks it this combat if able"), false, null, SetTargetPointer.PLAYER);
|
||||
ability.setTriggerPhrase("When {this} attacks, ");
|
||||
ability.addTarget(new TargetCreaturePermanent(0, 1));
|
||||
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||
this.addAbility(ability);
|
||||
|
||||
// At the beginning of the end step, sacrifice Impetuous Devils.
|
||||
this.addAbility(new BeginningOfEndStepTriggeredAbility(TargetController.NEXT, new SacrificeSourceEffect(), false));
|
||||
|
|
@ -54,44 +54,3 @@ public final class ImpetuousDevils extends CardImpl {
|
|||
return new ImpetuousDevils(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ImpetuousDevilsAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public ImpetuousDevilsAbility() {
|
||||
super(Zone.BATTLEFIELD, new MustBeBlockedByTargetSourceEffect(Duration.EndOfCombat), false);
|
||||
}
|
||||
|
||||
private ImpetuousDevilsAbility(final ImpetuousDevilsAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getSourceId().equals(this.getSourceId())) {
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
|
||||
UUID defenderId = game.getCombat().getDefendingPlayerId(sourceId, game);
|
||||
filter.add(new ControllerIdPredicate(defenderId));
|
||||
|
||||
this.getTargets().clear();
|
||||
TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false);
|
||||
this.addTarget(target);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When {this} attacks, up to one target creature defending player controls blocks it this combat if able.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImpetuousDevilsAbility copy() {
|
||||
return new ImpetuousDevilsAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
package mage.cards.k;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
|
|
@ -15,6 +14,9 @@ import mage.game.Game;
|
|||
import mage.game.events.GameEvent;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.DefineByTriggerTargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -25,7 +27,6 @@ public final class KarmicJustice extends CardImpl {
|
|||
public KarmicJustice(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{W}");
|
||||
|
||||
|
||||
// Whenever a spell or ability an opponent controls destroys a noncreature permanent you control, you may destroy target permanent that opponent controls.
|
||||
this.addAbility(new KarmicJusticeTriggeredAbility());
|
||||
}
|
||||
|
|
@ -45,6 +46,7 @@ class KarmicJusticeTriggeredAbility extends TriggeredAbilityImpl {
|
|||
KarmicJusticeTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true);
|
||||
this.setLeavesTheBattlefieldTrigger(true);
|
||||
this.setTargetAdjuster(DefineByTriggerTargetAdjuster.instance);
|
||||
}
|
||||
|
||||
private KarmicJusticeTriggeredAbility(final KarmicJusticeTriggeredAbility ability) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
|
|
@ -13,21 +13,21 @@ import mage.abilities.effects.common.UntapSourceEffect;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author fireshoes
|
||||
*/
|
||||
public final class MageRingResponder extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePermanent filter
|
||||
= new FilterCreaturePermanent("creature defending player controls");
|
||||
public MageRingResponder(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{7}");
|
||||
this.subtype.add(SubType.GOLEM);
|
||||
|
|
@ -41,7 +41,10 @@ public final class MageRingResponder extends CardImpl {
|
|||
this.addAbility(new SimpleActivatedAbility(new UntapSourceEffect(), new ManaCostsImpl<>("{7}")));
|
||||
|
||||
// Whenever Mage-Ring Responder attacks, it deals 7 damage to target creature defending player controls.
|
||||
this.addAbility(new MageRingResponderAbility());
|
||||
Ability ability = new AttacksTriggeredAbility(new DamageTargetEffect(7), false, null, SetTargetPointer.PLAYER);
|
||||
ability.addTarget(new TargetCreaturePermanent(filter));
|
||||
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private MageRingResponder(final MageRingResponder card) {
|
||||
|
|
@ -53,44 +56,3 @@ public final class MageRingResponder extends CardImpl {
|
|||
return new MageRingResponder(this);
|
||||
}
|
||||
}
|
||||
|
||||
class MageRingResponderAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public MageRingResponderAbility() {
|
||||
super(Zone.BATTLEFIELD, new DamageTargetEffect(7));
|
||||
}
|
||||
|
||||
private MageRingResponderAbility(final MageRingResponderAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ATTACKER_DECLARED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getSourceId().equals(this.getSourceId())) {
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("creature defending player controls");
|
||||
UUID defenderId = game.getCombat().getDefenderId(sourceId);
|
||||
filter.add(new ControllerIdPredicate(defenderId));
|
||||
|
||||
this.getTargets().clear();
|
||||
TargetCreaturePermanent target = new TargetCreaturePermanent(filter);
|
||||
this.addTarget(target);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} attacks, it deals 7 damage to target creature defending player controls.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public MageRingResponderAbility copy() {
|
||||
return new MageRingResponderAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,32 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.constants.TargetController;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
import mage.target.targetpointer.FirstTargetPointer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
||||
*/
|
||||
public final class MagusOfTheAbyss extends CardImpl {
|
||||
static FilterPermanent filter = new FilterPermanent("nonartifact creature that player controls of their choice");
|
||||
|
||||
public MagusOfTheAbyss(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}");
|
||||
|
|
@ -33,7 +36,11 @@ public final class MagusOfTheAbyss extends CardImpl {
|
|||
this.toughness = new MageInt(3);
|
||||
|
||||
// At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated.
|
||||
this.addAbility(new MagusOfTheAbyssTriggeredAbility());
|
||||
Ability ability = new BeginningOfUpkeepTriggeredAbility(TargetController.EACH_PLAYER,
|
||||
new DestroyTargetEffect(true), false).withTargetPointerSet(true);
|
||||
ability.addTarget(new TargetPermanent(filter)); // Only used for text generation
|
||||
ability.setTargetAdjuster(MagusOfTheAbyssTargetAdjuster.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private MagusOfTheAbyss(final MagusOfTheAbyss card) {
|
||||
|
|
@ -46,45 +53,24 @@ public final class MagusOfTheAbyss extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class MagusOfTheAbyssTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
MagusOfTheAbyssTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new DestroyTargetEffect(true), false);
|
||||
}
|
||||
|
||||
private MagusOfTheAbyssTriggeredAbility(final MagusOfTheAbyssTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MagusOfTheAbyssTriggeredAbility copy() {
|
||||
return new MagusOfTheAbyssTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.UPKEEP_STEP_PRE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Player player = game.getPlayer(event.getPlayerId());
|
||||
if (player != null) {
|
||||
FilterCreaturePermanent filter = new FilterCreaturePermanent("nonartifact creature you control");
|
||||
enum MagusOfTheAbyssTargetAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
private static final FilterPermanent filter
|
||||
= new FilterPermanent("nonartifact creature that player controls of their choice");
|
||||
static {
|
||||
filter.add(Predicates.not(CardType.ARTIFACT.getPredicate()));
|
||||
filter.add(new ControllerIdPredicate(player.getId()));
|
||||
Target target = new TargetCreaturePermanent(filter);
|
||||
target.setAbilityController(getControllerId());
|
||||
target.setTargetController(player.getId());
|
||||
this.getTargets().clear();
|
||||
this.getTargets().add(target);
|
||||
return true;
|
||||
filter.add(CardType.CREATURE.getPredicate());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "At the beginning of each player's upkeep, destroy target nonartifact creature that player controls of their choice. It can't be regenerated.";
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|
||||
ability.getTargets().clear();
|
||||
ability.getAllEffects().setTargetPointer(new FirstTargetPointer());
|
||||
|
||||
FilterPermanent adjustedFilter = filter.copy();
|
||||
adjustedFilter.add(new ControllerIdPredicate(opponentId));
|
||||
Target newTarget = new TargetPermanent(adjustedFilter);
|
||||
newTarget.setTargetController(opponentId);
|
||||
ability.addTarget(newTarget);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.effects.common.DontUntapInControllersNextUntapStepTargetEffect;
|
||||
import mage.abilities.effects.common.TapTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
|
|
@ -11,13 +11,10 @@ import mage.cards.CardImpl;
|
|||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterLandPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetLandPermanent;
|
||||
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -34,7 +31,11 @@ public final class ManaSkimmer extends CardImpl {
|
|||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
// Whenever Mana Skimmer deals damage to a player, tap target land that player controls. That land doesn't untap during its controller's next untap step.
|
||||
this.addAbility(new ManaSkimmerTriggeredAbility());
|
||||
Ability ability = new DealsDamageToAPlayerTriggeredAbility(new TapTargetEffect(), false, true);
|
||||
ability.addEffect(new DontUntapInControllersNextUntapStepTargetEffect("That land"));
|
||||
ability.addTarget(new TargetLandPermanent().withTargetName("target land that player controls"));
|
||||
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private ManaSkimmer(final ManaSkimmer card) {
|
||||
|
|
@ -46,44 +47,3 @@ public final class ManaSkimmer extends CardImpl {
|
|||
return new ManaSkimmer(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ManaSkimmerTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
ManaSkimmerTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new TapTargetEffect(), false);
|
||||
addEffect(new DontUntapInControllersNextUntapStepTargetEffect());
|
||||
}
|
||||
|
||||
private ManaSkimmerTriggeredAbility(final ManaSkimmerTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ManaSkimmerTriggeredAbility copy() {
|
||||
return new ManaSkimmerTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Permanent source = game.getPermanent(event.getSourceId());
|
||||
if (source != null && source.getId().equals(this.getSourceId())) {
|
||||
FilterLandPermanent filter = new FilterLandPermanent("land that player controls");
|
||||
filter.add(new ControllerIdPredicate(event.getPlayerId()));
|
||||
filter.setMessage("land controlled by " + game.getPlayer(event.getTargetId()).getLogName());
|
||||
this.getTargets().clear();
|
||||
this.addTarget(new TargetPermanent(filter));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} deals damage to a player, tap target land that player controls. That land doesn't untap during its controller's next untap step.";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
|
||||
package mage.cards.m;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.card.OwnerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCardInGraveyard;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class MausoleumTurnkey extends CardImpl {
|
||||
static FilterCreatureCard filter = new FilterCreatureCard("creature card of an opponent's choice");
|
||||
|
||||
public MausoleumTurnkey(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}");
|
||||
|
|
@ -36,8 +36,10 @@ public final class MausoleumTurnkey extends CardImpl {
|
|||
this.toughness = new MageInt(2);
|
||||
|
||||
// When Mausoleum Turnkey enters the battlefield, return target creature card of an opponent's choice from your graveyard to your hand.
|
||||
this.addAbility(new EntersBattlefieldTriggeredAbility(new MausoleumTurnkeyEffect(), false));
|
||||
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToHandTargetEffect());
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
ability.setTargetAdjuster(MausoleumTurnkeyAdjuster.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private MausoleumTurnkey(final MausoleumTurnkey card) {
|
||||
|
|
@ -50,50 +52,27 @@ public final class MausoleumTurnkey extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class MausoleumTurnkeyEffect extends OneShotEffect {
|
||||
|
||||
MausoleumTurnkeyEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "return target creature card of an opponent's choice from your graveyard to your hand";
|
||||
}
|
||||
|
||||
private MausoleumTurnkeyEffect(final MausoleumTurnkeyEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
// Exact copy of KarplusanMinotaurAdjuster
|
||||
enum MausoleumTurnkeyAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public MausoleumTurnkeyEffect copy() {
|
||||
return new MausoleumTurnkeyEffect(this);
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
Player controller = game.getPlayer(ability.getControllerId());
|
||||
if (controller == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
UUID opponentId = null;
|
||||
if (game.getOpponents(controller.getId()).size() > 1) {
|
||||
Target target = new TargetOpponent(true);
|
||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
||||
if (controller.chooseTarget(Outcome.Neutral, target, ability, game)) {
|
||||
opponentId = target.getFirstTarget();
|
||||
}
|
||||
} else {
|
||||
opponentId = game.getOpponents(controller.getId()).iterator().next();
|
||||
}
|
||||
if (opponentId != null) {
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
if (opponent != null) {
|
||||
FilterCreatureCard filter = new FilterCreatureCard("creature card from " + controller.getLogName() + " graveyard");
|
||||
filter.add(new OwnerIdPredicate(controller.getId()));
|
||||
Target target = new TargetCardInGraveyard(filter);
|
||||
opponent.chooseTarget(outcome, target, source, game);
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
controller.moveCards(card, Zone.HAND, source, game);
|
||||
ability.getTargets().get(0).setTargetController(opponentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,30 @@
|
|||
|
||||
package mage.cards.n;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.AttacksAndIsNotBlockedTriggeredAbility;
|
||||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.target.Target;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author MarcoMarin
|
||||
*/
|
||||
public final class Necrite extends CardImpl {
|
||||
static FilterPermanent filter = new FilterCreaturePermanent("creature defending player controls");
|
||||
|
||||
public Necrite(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}{B}");
|
||||
|
|
@ -35,10 +34,10 @@ public final class Necrite extends CardImpl {
|
|||
|
||||
// Whenever Necrite attacks and isn't blocked, you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated.
|
||||
DoIfCostPaid effect = new DoIfCostPaid(new DestroyTargetEffect(true), new SacrificeSourceCost(), "Sacrifice {this} to destroy target creature defending player controls?");
|
||||
effect.setText("you may sacrifice it. If you do, destroy target creature defending player controls. It can't be regenerated.");
|
||||
Ability ability = new NecriteTriggeredAbility(effect);
|
||||
Ability ability = new AttacksAndIsNotBlockedTriggeredAbility(effect, false, SetTargetPointer.PLAYER);
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||
this.addAbility(ability);
|
||||
|
||||
}
|
||||
|
||||
private Necrite(final Necrite card) {
|
||||
|
|
@ -50,33 +49,3 @@ public final class Necrite extends CardImpl {
|
|||
return new Necrite(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NecriteTriggeredAbility extends AttacksAndIsNotBlockedTriggeredAbility{
|
||||
|
||||
public NecriteTriggeredAbility(Effect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
private NecriteTriggeredAbility(final NecriteTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NecriteTriggeredAbility copy() {
|
||||
return new NecriteTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (super.checkTrigger(event, game)){
|
||||
UUID defendingPlayerId = game.getCombat().getDefendingPlayerId(getSourceId(), game);
|
||||
FilterPermanent filter = new FilterCreaturePermanent();
|
||||
filter.add(new ControllerIdPredicate(defendingPlayerId));
|
||||
Target target = new TargetPermanent(filter);
|
||||
this.getTargets().clear();
|
||||
this.addTarget(target);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,8 +20,10 @@ public final class NestOfScarabs extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}");
|
||||
|
||||
// Whenever you put one or more -1/-1 counters on a creature, create that many 1/1 black Insect creature tokens.
|
||||
this.addAbility(new PutCounterOnCreatureTriggeredAbility(new CreateTokenEffect(new NestOfScarabsBlackInsectToken(), new EffectKeyValue("countersAdded"))
|
||||
.setText("create that many 1/1 black Insect creature tokens"), CounterType.M1M1.createInstance()));
|
||||
this.addAbility(new PutCounterOnCreatureTriggeredAbility(
|
||||
new CreateTokenEffect(new NestOfScarabsBlackInsectToken(),
|
||||
new EffectKeyValue("countersAdded", "that many")),
|
||||
CounterType.M1M1.createInstance()));
|
||||
}
|
||||
|
||||
private NestOfScarabs(final NestOfScarabs card) {
|
||||
|
|
|
|||
|
|
@ -1,22 +1,26 @@
|
|||
package mage.cards.o;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.effects.common.ExileTargetEffect;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterNonlandPermanent;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedPlayerEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.ThatPlayerControlsTargetAdjuster;
|
||||
import mage.util.CardUtil;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.*;
|
||||
|
|
@ -25,6 +29,7 @@ import java.util.*;
|
|||
* @author TheElk801
|
||||
*/
|
||||
public final class OKagachiVengefulKami extends CardImpl {
|
||||
static FilterPermanent filter = new FilterNonlandPermanent("nonland permanent that player controls");
|
||||
|
||||
public OKagachiVengefulKami(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{U}{B}{R}{G}");
|
||||
|
|
@ -42,7 +47,11 @@ public final class OKagachiVengefulKami extends CardImpl {
|
|||
this.addAbility(TrampleAbility.getInstance());
|
||||
|
||||
// Whenever O-Kagachi, Vengeful Kami deals combat damage to a player, if that player attacked you during their last turn, exile target nonland permanent that player controls
|
||||
this.addAbility(new OKagachiVengefulKamiTriggeredAbility());
|
||||
TriggeredAbility ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ExileTargetEffect(), false, true);
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
ability.setTargetAdjuster(new ThatPlayerControlsTargetAdjuster());
|
||||
ability.withInterveningIf(KagachiVengefulKamiCondition.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private OKagachiVengefulKami(final OKagachiVengefulKami card) {
|
||||
|
|
@ -55,66 +64,25 @@ public final class OKagachiVengefulKami extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class OKagachiVengefulKamiTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
OKagachiVengefulKamiTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new ExileTargetEffect(), false);
|
||||
this.addWatcher(new OKagachiVengefulKamiWatcher());
|
||||
}
|
||||
|
||||
private OKagachiVengefulKamiTriggeredAbility(final OKagachiVengefulKamiTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
enum KagachiVengefulKamiCondition implements Condition {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public OKagachiVengefulKamiTriggeredAbility copy() {
|
||||
return new OKagachiVengefulKamiTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Player player = game.getPlayer(event.getTargetId());
|
||||
if (player == null
|
||||
|| !((DamagedPlayerEvent) event).isCombatDamage()
|
||||
|| !event.getSourceId().equals(getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().setValue("damagedPlayer", event.getTargetId());
|
||||
FilterPermanent filter = new FilterNonlandPermanent("nonland permanent controlled by " + player.getName());
|
||||
filter.add(new ControllerIdPredicate(event.getTargetId()));
|
||||
this.getTargets().clear();
|
||||
this.addTarget(new TargetPermanent(filter));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
public boolean apply(Game game, Ability source) {
|
||||
OKagachiVengefulKamiWatcher watcher = game.getState().getWatcher(OKagachiVengefulKamiWatcher.class);
|
||||
if (watcher == null) {
|
||||
return false;
|
||||
}
|
||||
UUID playerId = null;
|
||||
for (Effect effect : this.getEffects()) {
|
||||
Object obj = effect.getValue("damagedPlayer");
|
||||
if (obj instanceof UUID) {
|
||||
playerId = (UUID) obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return watcher.checkPlayer(getControllerId(), playerId);
|
||||
return CardUtil.getEffectValueFromAbility(source, "damagedPlayer", UUID.class)
|
||||
.filter(uuid -> watcher.checkPlayer(source.getControllerId(), uuid))
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} deals combat damage to a player, " +
|
||||
"if that player attacked you during their last turn, " +
|
||||
"exile target nonland permanent that player controls.";
|
||||
public String toString() {
|
||||
return "if that player attacked you during their last turn";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class OKagachiVengefulKamiWatcher extends Watcher {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,25 @@
|
|||
package mage.cards.o;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesThisOrAnotherTriggeredAbility;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.keyword.LifelinkAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.ObjectSourcePlayer;
|
||||
import mage.filter.predicate.ObjectSourcePlayerPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -21,6 +27,13 @@ import java.util.UUID;
|
|||
* @author TheElk801
|
||||
*/
|
||||
public final class OrahSkyclaveHierophant extends CardImpl {
|
||||
static FilterPermanent filterTrigger = new FilterControlledPermanent("Cleric you control");
|
||||
static FilterCard filterTarget = new FilterCard("Cleric card with lesser mana value");
|
||||
static {
|
||||
filterTrigger.add(SubType.CLERIC.getPredicate());
|
||||
filterTarget.add(SubType.CLERIC.getPredicate());
|
||||
filterTarget.add(OrahSkyclaveHierophantPredicate.instance);
|
||||
}
|
||||
|
||||
public OrahSkyclaveHierophant(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{B}");
|
||||
|
|
@ -35,7 +48,9 @@ public final class OrahSkyclaveHierophant extends CardImpl {
|
|||
this.addAbility(LifelinkAbility.getInstance());
|
||||
|
||||
// Whenever Orah, Skyclave Hierophant or another Cleric you control dies, return target Cleric card with lesser converted mana cost from your graveyard to the battlefield.
|
||||
this.addAbility(new OrahSkyclaveHierophantTriggeredAbility());
|
||||
Ability ability = new DiesThisOrAnotherTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect(), false, filterTrigger);
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filterTarget));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private OrahSkyclaveHierophant(final OrahSkyclaveHierophant card) {
|
||||
|
|
@ -48,57 +63,15 @@ public final class OrahSkyclaveHierophant extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class OrahSkyclaveHierophantTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
OrahSkyclaveHierophantTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect());
|
||||
setLeavesTheBattlefieldTrigger(true);
|
||||
}
|
||||
|
||||
private OrahSkyclaveHierophantTriggeredAbility(final OrahSkyclaveHierophantTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
enum OrahSkyclaveHierophantPredicate implements ObjectSourcePlayerPredicate<Card> {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
if (!zEvent.isDiesEvent()
|
||||
|| !zEvent.getTarget().isControlledBy(getControllerId())
|
||||
|| (!zEvent.getTarget().hasSubtype(SubType.CLERIC, game)
|
||||
&& !zEvent.getTarget().getId().equals(getSourceId()))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
FilterCard filterCard = new FilterCard(
|
||||
"Cleric card with mana value less than " + (zEvent.getTarget().getManaValue())
|
||||
);
|
||||
filterCard.add(SubType.CLERIC.getPredicate());
|
||||
filterCard.add(new ManaValuePredicate(
|
||||
ComparisonType.FEWER_THAN, zEvent.getTarget().getManaValue()
|
||||
));
|
||||
this.getTargets().clear();
|
||||
this.addTarget(new TargetCardInYourGraveyard(filterCard));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrahSkyclaveHierophantTriggeredAbility copy() {
|
||||
return new OrahSkyclaveHierophantTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} or another Cleric you control dies, return target Cleric card " +
|
||||
"with lesser mana value from your graveyard to the battlefield.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInUseableZone(Game game, MageObject sourceObject, GameEvent event) {
|
||||
return TriggeredAbilityImpl.isInUseableZoneDiesTrigger(this, sourceObject, event, game);
|
||||
public boolean apply(ObjectSourcePlayer<Card> input, Game game) {
|
||||
return CardUtil.getEffectValueFromAbility(
|
||||
input.getSource(), "creatureDied", Permanent.class
|
||||
)
|
||||
.filter(permanent -> input.getObject().getManaValue() < permanent.getManaValue())
|
||||
.isPresent();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,20 +7,14 @@ import mage.abilities.common.SimpleActivatedAbility;
|
|||
import mage.abilities.costs.common.SacrificeSourceCost;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetLandPermanent;
|
||||
import mage.util.CardUtil;
|
||||
import mage.target.targetadjustment.XTargetsCountAdjuster;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -38,9 +32,12 @@ public final class OrcishSettlers extends CardImpl {
|
|||
this.toughness = new MageInt(1);
|
||||
|
||||
// {X}{X}{R}, {tap}, Sacrifice Orcish Settlers: Destroy X target lands.
|
||||
Ability ability = new SimpleActivatedAbility(new OrcishSettlersEffect(), new ManaCostsImpl<>("{X}{X}{R}"));
|
||||
Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect().setText("Destroy X target lands"),
|
||||
new ManaCostsImpl<>("{X}{X}{R}"));
|
||||
ability.addCost(new TapSourceCost());
|
||||
ability.addCost(new SacrificeSourceCost());
|
||||
ability.addTarget(new TargetLandPermanent());
|
||||
ability.setTargetAdjuster(new XTargetsCountAdjuster());
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
@ -53,43 +50,3 @@ public final class OrcishSettlers extends CardImpl {
|
|||
return new OrcishSettlers(this);
|
||||
}
|
||||
}
|
||||
|
||||
class OrcishSettlersEffect extends OneShotEffect {
|
||||
|
||||
OrcishSettlersEffect() {
|
||||
super(Outcome.DestroyPermanent);
|
||||
this.staticText = "Destroy X target lands";
|
||||
}
|
||||
|
||||
private OrcishSettlersEffect(final OrcishSettlersEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrcishSettlersEffect copy() {
|
||||
return new OrcishSettlersEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
int amount = CardUtil.getSourceCostsTag(game, source, "X", 0);
|
||||
if (amount == 0) {
|
||||
return false;
|
||||
}
|
||||
TargetLandPermanent target = new TargetLandPermanent(amount);
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null
|
||||
&& target.canChoose(controller.getId(), source, game)
|
||||
&& controller.choose(Outcome.DestroyPermanent, target, source, game)) {
|
||||
List<UUID> targets = target.getTargets();
|
||||
targets.forEach((landId) -> {
|
||||
Permanent land = game.getPermanent(landId);
|
||||
if (land != null) {
|
||||
land.destroy(source, game, false);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import mage.game.events.GameEvent;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.DefineByTriggerTargetAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ class PawpatchRecruitTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
public PawpatchRecruitTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.P1P1.createInstance()), false);
|
||||
this.setTargetAdjuster(DefineByTriggerTargetAdjuster.instance);
|
||||
}
|
||||
|
||||
private PawpatchRecruitTriggeredAbility(final PawpatchRecruitTriggeredAbility ability) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DealsDamageToOpponentTriggeredAbility;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.SavedDamageValue;
|
||||
|
|
@ -14,16 +15,15 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.predicate.Predicates;
|
||||
import mage.filter.predicate.permanent.ControllerIdPredicate;
|
||||
import mage.filter.predicate.permanent.ProtectorIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.DamagedEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.TargetAdjuster;
|
||||
import mage.target.targetpointer.FirstTargetPointer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -51,7 +51,10 @@ public final class RampagingRaptor extends CardImpl {
|
|||
));
|
||||
|
||||
// Whenever Rampaging Raptor deals combat damage to an opponent, it deals that much damage to target planeswalker that player controls or battle that player protects.
|
||||
this.addAbility(new RampagingRaptorTriggeredAbility());
|
||||
Ability ability = new DealsDamageToOpponentTriggeredAbility(new DamageTargetEffect(SavedDamageValue.MUCH)
|
||||
.withTargetDescription("target planeswalker that player controls or battle that player protects"), false, true, true);
|
||||
ability.setTargetAdjuster(RampagingRaptorTargetAdjuster.instance);
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private RampagingRaptor(final RampagingRaptor card) {
|
||||
|
|
@ -64,33 +67,17 @@ public final class RampagingRaptor extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class RampagingRaptorTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
RampagingRaptorTriggeredAbility() {
|
||||
super(Zone.BATTLEFIELD, new DamageTargetEffect(SavedDamageValue.MUCH), false);
|
||||
}
|
||||
|
||||
private RampagingRaptorTriggeredAbility(final RampagingRaptorTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
enum RampagingRaptorTargetAdjuster implements TargetAdjuster {
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public RampagingRaptorTriggeredAbility copy() {
|
||||
return new RampagingRaptorTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Player opponent = game.getPlayer(event.getPlayerId());
|
||||
if (opponent == null
|
||||
|| !event.getSourceId().equals(this.getSourceId())
|
||||
|| !((DamagedEvent) event).isCombatDamage()) {
|
||||
return false;
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
UUID opponentId = ability.getEffects().get(0).getTargetPointer().getFirst(game, ability);
|
||||
Player opponent = game.getPlayer(opponentId);
|
||||
ability.getTargets().clear();
|
||||
ability.getAllEffects().setTargetPointer(new FirstTargetPointer());
|
||||
if (opponent == null) {
|
||||
return;
|
||||
}
|
||||
FilterPermanent filter = new FilterPermanent(
|
||||
"planeswalker " + opponent.getLogName() + " controls " +
|
||||
|
|
@ -106,15 +93,6 @@ class RampagingRaptorTriggeredAbility extends TriggeredAbilityImpl {
|
|||
new ProtectorIdPredicate(opponent.getId())
|
||||
)
|
||||
));
|
||||
this.getEffects().setValue("damage", event.getAmount());
|
||||
this.getTargets().clear();
|
||||
this.addTarget(new TargetPermanent(filter));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever {this} deals combat damage to an opponent, it deals that much damage " +
|
||||
"to target planeswalker that player controls or battle that player protects.";
|
||||
ability.addTarget(new TargetPermanent(filter));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
package mage.cards.r;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.common.ZoneChangeTriggeredAbility;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CycleTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.EffectKeyValue;
|
||||
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||
import mage.abilities.hint.StaticHint;
|
||||
import mage.abilities.keyword.CyclingAbility;
|
||||
import mage.abilities.keyword.TrampleAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.target.common.TargetArtifactPermanent;
|
||||
import mage.util.CardUtil;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterArtifactPermanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.targetadjustment.TargetsCountAdjuster;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -24,6 +23,7 @@ import java.util.UUID;
|
|||
* @author Susucr
|
||||
*/
|
||||
public final class RampagingWarMammoth extends CardImpl {
|
||||
static FilterPermanent filter = new FilterArtifactPermanent("up to X target artifacts");
|
||||
|
||||
public RampagingWarMammoth(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}");
|
||||
|
|
@ -39,7 +39,10 @@ public final class RampagingWarMammoth extends CardImpl {
|
|||
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{2}{R}")));
|
||||
|
||||
// When you cycle Rampaging War Mammoth, destroy up to X target artifacts.
|
||||
this.addAbility(new RampagingWarMammothTriggeredAbility());
|
||||
Ability ability = new CycleTriggeredAbility(new DestroyTargetEffect());
|
||||
ability.addTarget(new TargetPermanent(0,1, filter));
|
||||
ability.setTargetAdjuster(new TargetsCountAdjuster(new EffectKeyValue("cycleXValue")));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private RampagingWarMammoth(final RampagingWarMammoth card) {
|
||||
|
|
@ -51,56 +54,3 @@ public final class RampagingWarMammoth extends CardImpl {
|
|||
return new RampagingWarMammoth(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RampagingWarMammothTriggeredAbility extends ZoneChangeTriggeredAbility {
|
||||
|
||||
RampagingWarMammothTriggeredAbility() {
|
||||
super(Zone.ALL, null, "", false);
|
||||
}
|
||||
|
||||
private RampagingWarMammothTriggeredAbility(RampagingWarMammothTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (!event.getSourceId().equals(this.getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
StackObject object = game.getStack().getStackObject(event.getSourceId());
|
||||
if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CyclingAbility cyclingAbility = (CyclingAbility) object.getStackAbility();
|
||||
// If X is 0, or cycling from another ability that does not have {X} in cost,
|
||||
// this should trigger (but do nothing).
|
||||
int xValue = CardUtil.getSourceCostsTag(game, cyclingAbility, "X", 0);
|
||||
|
||||
this.getEffects().clear();
|
||||
this.getTargets().clear();
|
||||
|
||||
this.addEffect(new DestroyTargetEffect());
|
||||
// Target up to X artifacts
|
||||
this.addTarget(new TargetArtifactPermanent(0, xValue));
|
||||
this.getHints().clear();
|
||||
this.addHint(new StaticHint("X = " + xValue));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RampagingWarMammothTriggeredAbility copy() {
|
||||
return new RampagingWarMammothTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When you cycle {this}, destroy up to X target artifacts.";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package mage.cards.r;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DamageMultiEffect;
|
||||
import mage.abilities.keyword.DevourAbility;
|
||||
|
|
@ -12,10 +14,10 @@ import mage.constants.CardType;
|
|||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.Target;
|
||||
import mage.target.common.TargetCreaturePermanentAmount;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
|
@ -39,7 +41,11 @@ public final class RavenousGigantotherium extends CardImpl {
|
|||
this.addAbility(new DevourAbility(3));
|
||||
|
||||
// When Ravenous Gigantotherium enters the battlefield, it deals X damage divided as you choose among up to X target creatures, where X is its power. Each of those creatures deals damage equal to its power to Ravenous Gigantotherium.
|
||||
this.addAbility(new RavenousGigantotheriumAbility());
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new DamageMultiEffect());
|
||||
ability.addEffect(new RavenousGigantotheriumEffect());
|
||||
ability.addTarget(new TargetCreaturePermanentAmount(RavenousGigantotheriumAmount.instance)
|
||||
.withTargetName("up to X target creatures, where X is its power"));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private RavenousGigantotherium(final RavenousGigantotherium card) {
|
||||
|
|
@ -52,47 +58,28 @@ public final class RavenousGigantotherium extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class RavenousGigantotheriumAbility extends EntersBattlefieldTriggeredAbility {
|
||||
enum RavenousGigantotheriumAmount implements DynamicValue {
|
||||
instance;
|
||||
|
||||
RavenousGigantotheriumAbility() {
|
||||
super(null, false);
|
||||
}
|
||||
|
||||
private RavenousGigantotheriumAbility(final RavenousGigantotheriumAbility ability) {
|
||||
super(ability);
|
||||
@Override
|
||||
public int calculate(Game game, Ability sourceAbility, Effect effect) {
|
||||
return CardUtil.getEffectValueFromAbility(sourceAbility, "permanentEnteredBattlefield", Permanent.class)
|
||||
.map(permanent -> permanent.getPower().getValue()).orElse(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (!super.checkTrigger(event, game)) {
|
||||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
||||
if (permanent == null) {
|
||||
return false;
|
||||
}
|
||||
int power = Math.max(permanent.getPower().getValue(), 0);
|
||||
this.getEffects().clear();
|
||||
this.addEffect(new DamageMultiEffect());
|
||||
this.addEffect(new RavenousGigantotheriumEffect());
|
||||
this.getTargets().clear();
|
||||
if (power < 1) {
|
||||
return true;
|
||||
}
|
||||
this.addTarget(new TargetCreaturePermanentAmount(power, 0, power));
|
||||
return true;
|
||||
public DynamicValue copy() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When {this} enters, it deals X damage " +
|
||||
"divided as you choose among up to X target creatures, where X is its power. " +
|
||||
"Each of those creatures deals damage equal to its power to {this}.";
|
||||
public String getMessage() {
|
||||
return "its power";
|
||||
}
|
||||
|
||||
@Override
|
||||
public RavenousGigantotheriumAbility copy() {
|
||||
return new RavenousGigantotheriumAbility(this);
|
||||
public String toString() {
|
||||
return "X";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +87,7 @@ class RavenousGigantotheriumEffect extends OneShotEffect {
|
|||
|
||||
RavenousGigantotheriumEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.setText("Each of those creatures deals damage equal to its power to {this}.");
|
||||
}
|
||||
|
||||
private RavenousGigantotheriumEffect(final RavenousGigantotheriumEffect effect) {
|
||||
|
|
|
|||
|
|
@ -3,22 +3,21 @@ package mage.cards.r;
|
|||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.DiesSourceTriggeredAbility;
|
||||
import mage.abilities.costs.common.DynamicValueGenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.dynamicvalue.common.TargetManaValue;
|
||||
import mage.abilities.effects.common.DoIfCostPaid;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.effects.common.ReturnToHandSourceEffect;
|
||||
import mage.abilities.keyword.MenaceAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.common.FilterCreatureCard;
|
||||
import mage.filter.predicate.mageobject.AnotherPredicate;
|
||||
import mage.filter.predicate.mageobject.ManaValuePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.util.ManaUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -26,6 +25,11 @@ import java.util.UUID;
|
|||
* @author LevelX2
|
||||
*/
|
||||
public final class RelentlessDead extends CardImpl {
|
||||
static FilterCard filter = new FilterCreatureCard("another target Zombie creature card with mana value X from your graveyard"); // This target defines X
|
||||
static{
|
||||
filter.add(SubType.ZOMBIE.getPredicate());
|
||||
filter.add(AnotherPredicate.instance);
|
||||
}
|
||||
|
||||
public RelentlessDead(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}");
|
||||
|
|
@ -40,7 +44,11 @@ public final class RelentlessDead extends CardImpl {
|
|||
this.addAbility(new DiesSourceTriggeredAbility(new DoIfCostPaid(new ReturnToHandSourceEffect().setText("return it to its owner's hand"), new ManaCostsImpl<>("{B}"))));
|
||||
|
||||
// When Relentless Dead dies, you may pay {X}. If you do, return another target Zombie creature card with converted mana cost X from your graveyard to the battlefield.
|
||||
this.addAbility(new DiesSourceTriggeredAbility(new RelentlessDeadEffect()));
|
||||
Ability ability = new DiesSourceTriggeredAbility(new DoIfCostPaid(
|
||||
new ReturnFromGraveyardToBattlefieldTargetEffect(),
|
||||
new DynamicValueGenericManaCost(TargetManaValue.instance, "{X}")));
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private RelentlessDead(final RelentlessDead card) {
|
||||
|
|
@ -52,46 +60,3 @@ public final class RelentlessDead extends CardImpl {
|
|||
return new RelentlessDead(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RelentlessDeadEffect extends OneShotEffect {
|
||||
|
||||
RelentlessDeadEffect() {
|
||||
super(Outcome.PutCardInPlay);
|
||||
this.staticText = "you may pay {X}. If you do, return another target Zombie creature card with mana value X from your graveyard to the battlefield";
|
||||
}
|
||||
|
||||
private RelentlessDeadEffect(final RelentlessDeadEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelentlessDeadEffect copy() {
|
||||
return new RelentlessDeadEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
if (controller.chooseUse(Outcome.Benefit, "Do you want to pay {X} to return zombie?", source, game)) {
|
||||
int payCount = ManaUtil.playerPaysXGenericMana(true, "Relentless Dead", controller, source, game);
|
||||
// can be 0
|
||||
FilterCard filter = new FilterCard("Another target Zombie card with mana value {" + payCount + "}");
|
||||
filter.add(SubType.ZOMBIE.getPredicate());
|
||||
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, payCount));
|
||||
filter.add(AnotherPredicate.instance);
|
||||
TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter);
|
||||
if (controller.chooseTarget(outcome, target, source, game)) {
|
||||
Card card = game.getCard(target.getFirstTarget());
|
||||
if (card != null) {
|
||||
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +1,20 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.CycleTriggeredAbility;
|
||||
import mage.abilities.common.SpellCastControllerTriggeredAbility;
|
||||
import mage.abilities.common.ZoneChangeTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.keyword.CyclingAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SetTargetPointer;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.token.SharkToken;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -42,7 +37,7 @@ public final class SharkTyphoon extends CardImpl {
|
|||
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{1}{U}")));
|
||||
|
||||
// When you cycle Shark Typhoon, create an X/X blue Shark creature token with flying.
|
||||
this.addAbility(new SharkTyphoonTriggeredAbility());
|
||||
this.addAbility(new CycleTriggeredAbility(new SharkTyphoonCycleEffect()));
|
||||
}
|
||||
|
||||
private SharkTyphoon(final SharkTyphoon card) {
|
||||
|
|
@ -82,42 +77,29 @@ class SharkTyphoonCastEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
|
||||
class SharkTyphoonTriggeredAbility extends ZoneChangeTriggeredAbility {
|
||||
class SharkTyphoonCycleEffect extends OneShotEffect {
|
||||
|
||||
SharkTyphoonTriggeredAbility() {
|
||||
super(Zone.ALL, null, "", false);
|
||||
SharkTyphoonCycleEffect() {
|
||||
super(Outcome.Benefit);
|
||||
staticText = "create an X/X blue Shark creature token with flying";
|
||||
}
|
||||
|
||||
private SharkTyphoonTriggeredAbility(SharkTyphoonTriggeredAbility ability) {
|
||||
super(ability);
|
||||
private SharkTyphoonCycleEffect(final SharkTyphoonCycleEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY;
|
||||
public SharkTyphoonCycleEffect copy() {
|
||||
return new SharkTyphoonCycleEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (!event.getSourceId().equals(this.getSourceId())) {
|
||||
return false;
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Object xValueObject = getValue("cycleXValue");
|
||||
int xValue = 0;
|
||||
if (xValueObject instanceof Integer) {
|
||||
xValue = (int) xValueObject;
|
||||
}
|
||||
StackObject object = game.getStack().getStackObject(event.getSourceId());
|
||||
if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().clear();
|
||||
this.addEffect(new CreateTokenEffect(new SharkToken(CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0))));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SharkTyphoonTriggeredAbility copy() {
|
||||
return new SharkTyphoonTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When you cycle this card, create an X/X blue Shark creature token with flying.";
|
||||
return new SharkToken(xValue).putOntoBattlefield(1, game, source, source.getControllerId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
package mage.cards.v;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.CycleTriggeredAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.dynamicvalue.common.EffectKeyValue;
|
||||
import mage.abilities.effects.common.CreateTokenEffect;
|
||||
import mage.abilities.keyword.*;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -10,12 +11,7 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.SuperType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.token.PilotSaddleCrewToken;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -48,7 +44,8 @@ public final class ValorsFlagship extends CardImpl {
|
|||
this.addAbility(new CyclingAbility(new ManaCostsImpl<>("{X}{2}{W}")));
|
||||
|
||||
// When you cycle this card, create X 1/1 colorless Pilot creature tokens with "This token saddles Mounts and crews Vehicles as though its power were 2 greater."
|
||||
this.addAbility(new ValorsFlagshipTriggeredAbility());
|
||||
this.addAbility(new CycleTriggeredAbility(
|
||||
new CreateTokenEffect(new PilotSaddleCrewToken(), new EffectKeyValue("cycleXValue", "X"))));
|
||||
}
|
||||
|
||||
private ValorsFlagship(final ValorsFlagship card) {
|
||||
|
|
@ -60,45 +57,3 @@ public final class ValorsFlagship extends CardImpl {
|
|||
return new ValorsFlagship(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ValorsFlagshipTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
ValorsFlagshipTriggeredAbility() {
|
||||
super(Zone.ALL, null);
|
||||
}
|
||||
|
||||
private ValorsFlagshipTriggeredAbility(final ValorsFlagshipTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValorsFlagshipTriggeredAbility copy() {
|
||||
return new ValorsFlagshipTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.ACTIVATED_ABILITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (!event.getSourceId().equals(this.getSourceId())) {
|
||||
return false;
|
||||
}
|
||||
StackObject object = game.getStack().getStackObject(event.getSourceId());
|
||||
if (object == null || !(object.getStackAbility() instanceof CyclingAbility)) {
|
||||
return false;
|
||||
}
|
||||
this.getEffects().clear();
|
||||
int amount = CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0);
|
||||
this.addEffect(new CreateTokenEffect(new PilotSaddleCrewToken(), amount));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When you cycle this card, create X 1/1 colorless Pilot creature tokens with " +
|
||||
"\"This token saddles Mounts and crews Vehicles as though its power were 2 greater.\"";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,24 @@ public class CyclingTest extends CardTestPlayerBase {
|
|||
assertPowerToughness(playerB, "Pillarfield Ox", 0, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that X value is correctly read by the resulting triggered ability
|
||||
*/
|
||||
@Test
|
||||
public void cycleSharkTyphoon() {
|
||||
addCard(Zone.HAND, playerA, "Shark Typhoon", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 8);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cycling");
|
||||
setChoice(playerA, "X=6");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertGraveyardCount(playerA, "Shark Typhoon", 1);
|
||||
assertPowerToughness(playerA, "Shark Token", 6, 6);
|
||||
assertTappedCount("Island", true, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycle from graveyard or battlefield should not work.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import mage.constants.Zone;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author Plopman
|
||||
|
|
@ -40,6 +41,7 @@ public class CycleTriggeredAbility extends ZoneChangeTriggeredAbility {
|
|||
return false;
|
||||
}
|
||||
this.getEffects().setValue("cycleCosts", object.getStackAbility().getCosts());
|
||||
this.getEffects().setValue("cycleXValue", CardUtil.getSourceCostsTag(game, object.getStackAbility(), "X", 0));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import mage.game.Game;
|
|||
* @author stravant
|
||||
*/
|
||||
public class EffectKeyValue implements DynamicValue {
|
||||
private String key;
|
||||
private String description;
|
||||
private final String key;
|
||||
private final String description;
|
||||
|
||||
public EffectKeyValue(String key) {
|
||||
this.key = key;
|
||||
|
|
@ -19,7 +19,7 @@ public class EffectKeyValue implements DynamicValue {
|
|||
}
|
||||
|
||||
public EffectKeyValue(String key, String description) {
|
||||
this(key);
|
||||
this.key = key;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
|
|
@ -35,11 +35,11 @@ public class EffectKeyValue implements DynamicValue {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "equal to";
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return description;
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ public abstract class TargetImpl implements Target {
|
|||
if (min > 0 && max == Integer.MAX_VALUE) {
|
||||
sb.append(CardUtil.numberToText(min));
|
||||
sb.append(" or more ");
|
||||
} else if (!targetName.startsWith("X ") && (min != 1 || max != 1)) {
|
||||
} else if (!targetName.startsWith("X ") && !targetName.startsWith("up to ") && (min != 1 || max != 1)) {
|
||||
targetName = targetName.replace("another", "other"); //If non-singular, use "other" instead of "another"
|
||||
|
||||
if (getUseAnyNumber()) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue