diff --git a/Mage.Sets/src/mage/cards/a/AshlingTheExtinguisher.java b/Mage.Sets/src/mage/cards/a/AshlingTheExtinguisher.java index 0cd79b5ec8c..70eb75951fa 100644 --- a/Mage.Sets/src/mage/cards/a/AshlingTheExtinguisher.java +++ b/Mage.Sets/src/mage/cards/a/AshlingTheExtinguisher.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -27,7 +26,7 @@ import mage.target.common.TargetCreaturePermanent; public final class AshlingTheExtinguisher extends CardImpl { public AshlingTheExtinguisher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}{B}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.ELEMENTAL); this.subtype.add(SubType.SHAMAN); @@ -89,6 +88,6 @@ class AshlingTheExtinguisherTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} deals combat damage to a player, choose target creature that player controls. He or she sacrifices that creature."; + return "Whenever {this} deals combat damage to a player, choose target creature that player controls. The player sacrifices that creature."; } } diff --git a/Mage.Sets/src/mage/cards/b/BlindZealot.java b/Mage.Sets/src/mage/cards/b/BlindZealot.java index ebe2d5360ba..c1de1d9731b 100644 --- a/Mage.Sets/src/mage/cards/b/BlindZealot.java +++ b/Mage.Sets/src/mage/cards/b/BlindZealot.java @@ -1,19 +1,16 @@ - package mage.cards.b; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.keyword.IntimidateAbility; 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.filter.common.FilterCreaturePermanent; @@ -21,11 +18,8 @@ import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; -import mage.game.stack.Spell; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; /** * @@ -40,10 +34,11 @@ public final class BlindZealot extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); + // Intimidate this.addAbility(IntimidateAbility.getInstance()); + // Whenever Blind Zealot deals combat damage to a player, you may sacrifice it. If you do, destroy target creature that player controls. Ability ability = new BlindZealotTriggeredAbility(); - ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); } @@ -60,7 +55,7 @@ public final class BlindZealot extends CardImpl { class BlindZealotTriggeredAbility extends TriggeredAbilityImpl { public BlindZealotTriggeredAbility() { - super(Zone.BATTLEFIELD, new BlindZealotEffect(), true); + super(Zone.BATTLEFIELD, new DoIfCostPaid(new DestroyTargetEffect(), new SacrificeSourceCost()), true); } public BlindZealotTriggeredAbility(final BlindZealotTriggeredAbility ability) { @@ -92,48 +87,7 @@ class BlindZealotTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} deals combat damage to a player, you may sacrifice it. If you do, destroy target creature that player controls"; - } -} - -class BlindZealotEffect extends OneShotEffect { - - public BlindZealotEffect() { - super(Outcome.DestroyPermanent); - staticText = "sacrifice {this}"; - } - - public BlindZealotEffect(final BlindZealotEffect effect) { - super(effect); - } - - @Override - public BlindZealotEffect copy() { - return new BlindZealotEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent targetPermanent = game.getPermanent(source.getFirstTarget()); - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (sourceObject == null) { - if (source.getSourceObject(game) instanceof Spell) { - sourceObject = game.getPermanent(source.getSourceId()); - if (sourceObject != null && sourceObject.getZoneChangeCounter(game) > source.getSourceObjectZoneChangeCounter() + 1) { - return false; - } - } - } - if (sourceObject instanceof Permanent) { - Permanent permanent = (Permanent) sourceObject; - if (source.getControllerId().equals(permanent.getControllerId())) { - Effect effect = new DestroyTargetEffect(); - effect.setTargetPointer(new FixedTarget(targetPermanent.getId())); - effect.apply(game, source); - return permanent.sacrifice(source.getSourceId(), game); - } - return true; - } - return false; + return "Whenever {this} deals combat damage to a player, you may sacrifice it. " + + "If you do, destroy target creature that player controls"; } } diff --git a/Mage.Sets/src/mage/cards/i/InkEyesServantOfOni.java b/Mage.Sets/src/mage/cards/i/InkEyesServantOfOni.java index 0f4759bab34..3628872503c 100644 --- a/Mage.Sets/src/mage/cards/i/InkEyesServantOfOni.java +++ b/Mage.Sets/src/mage/cards/i/InkEyesServantOfOni.java @@ -1,27 +1,25 @@ - package mage.cards.i; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.RegenerateSourceEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.NinjutsuAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; import mage.target.common.TargetCardInGraveyard; @@ -32,7 +30,7 @@ import mage.target.common.TargetCardInGraveyard; public final class InkEyesServantOfOni extends CardImpl { public InkEyesServantOfOni(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}{B}"); this.subtype.add(SubType.RAT); this.subtype.add(SubType.NINJA); addSuperType(SuperType.LEGENDARY); @@ -44,7 +42,7 @@ public final class InkEyesServantOfOni extends CardImpl { this.addAbility(new NinjutsuAbility(new ManaCostsImpl("{3}{B}{B}"))); // Whenever Ink-Eyes, Servant of Oni deals combat damage to a player, you may put target creature card from that player's graveyard onto the battlefield under your control. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new InkEyesServantOfOniEffect(), true, true)); + this.addAbility(new InkEyesServantOfOniTriggeredAbility()); // {1}{B}: Regenerate Ink-Eyes. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new RegenerateSourceEffect(), new ManaCostsImpl("{1}{B}"))); @@ -60,39 +58,48 @@ public final class InkEyesServantOfOni extends CardImpl { } } -class InkEyesServantOfOniEffect extends OneShotEffect { +class InkEyesServantOfOniTriggeredAbility extends TriggeredAbilityImpl { - public InkEyesServantOfOniEffect() { - super(Outcome.PutCreatureInPlay); - this.staticText = "you may put target creature card from that player's graveyard onto the battlefield under your control"; + public InkEyesServantOfOniTriggeredAbility() { + super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), true); } - public InkEyesServantOfOniEffect(final InkEyesServantOfOniEffect effect) { - super(effect); + public InkEyesServantOfOniTriggeredAbility(final InkEyesServantOfOniTriggeredAbility ability) { + super(ability); } @Override - public InkEyesServantOfOniEffect copy() { - return new InkEyesServantOfOniEffect(this); + public InkEyesServantOfOniTriggeredAbility copy() { + return new InkEyesServantOfOniTriggeredAbility(this); } @Override - public boolean apply(Game game, Ability source) { - Player damagedPlayer = game.getPlayer(targetPointer.getFirst(game, source)); - Player you = game.getPlayer(source.getControllerId()); - FilterCard filter = new FilterCard("creature in that player's graveyard"); + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; + } + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { + return false; + } + FilterCard filter = new FilterCard("creature in " + damagedPlayer.getName() + "'s graveyard"); filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(new OwnerIdPredicate(damagedPlayer.getId())); TargetCardInGraveyard target = new TargetCardInGraveyard(filter); - if (target.canChoose(source.getSourceId(), you.getId(), game)) { - if (you.chooseTarget(Outcome.PutCreatureInPlay, target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - you.moveCards(card, Zone.BATTLEFIELD, source, game); - return true; - } - } - } - return false; + this.getTargets().clear(); + this.addTarget(target); + return true; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may put target creature card from that player's " + + "graveyard onto the battlefield under your control"; } } diff --git a/Mage.Sets/src/mage/cards/m/MordantDragon.java b/Mage.Sets/src/mage/cards/m/MordantDragon.java index a53bf5a8f5e..3960e387e61 100644 --- a/Mage.Sets/src/mage/cards/m/MordantDragon.java +++ b/Mage.Sets/src/mage/cards/m/MordantDragon.java @@ -1,13 +1,14 @@ - package mage.cards.m; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -16,8 +17,11 @@ import mage.constants.*; import mage.filter.common.FilterCreaturePermanent; 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.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -26,7 +30,7 @@ import mage.target.common.TargetCreaturePermanent; public final class MordantDragon extends CardImpl { public MordantDragon(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}{R}"); this.subtype.add(SubType.DRAGON); this.power = new MageInt(5); @@ -39,7 +43,7 @@ public final class MordantDragon extends CardImpl { this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 0, Duration.EndOfTurn), new ManaCostsImpl("{1}{R}"))); // Whenever Mordant Dragon deals combat damage to a player, you may have it deal that much damage to target creature that player controls. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new MordantDragonEffect(), true, true)); + this.addAbility(new MordantDragonTriggeredAbility()); } public MordantDragon(final MordantDragon card) { @@ -52,6 +56,53 @@ public final class MordantDragon extends CardImpl { } } +class MordantDragonTriggeredAbility extends TriggeredAbilityImpl { + + public MordantDragonTriggeredAbility() { + super(Zone.BATTLEFIELD, new MordantDragonEffect(), true); + } + + public MordantDragonTriggeredAbility(final MordantDragonTriggeredAbility ability) { + super(ability); + } + + @Override + public MordantDragonTriggeredAbility copy() { + return new MordantDragonTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent) event; + Player opponent = game.getPlayer(event.getPlayerId()); + if (!damageEvent.isCombatDamage() + || !event.getSourceId().equals(this.getSourceId()) + || opponent == null) { + return false; + } + FilterCreaturePermanent filter = new FilterCreaturePermanent("creature " + opponent.getLogName() + " controls"); + filter.add(new ControllerIdPredicate(opponent.getId())); + this.getTargets().clear(); + this.addTarget(new TargetCreaturePermanent(filter)); + for (Effect effect : this.getAllEffects()) { + effect.setTargetPointer(new FixedTarget(event.getPlayerId())); + effect.setValue("damage", event.getAmount()); + } + return true; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may have it deal that much damage to target creature that player controls"; + } +} + class MordantDragonEffect extends OneShotEffect { public MordantDragonEffect() { @@ -65,23 +116,7 @@ class MordantDragonEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(targetPointer.getFirst(game, source)); - if (player != null) { - int amount = (Integer) getValue("damage"); - if (amount > 0) { - FilterCreaturePermanent filter = new FilterCreaturePermanent("creature " + player.getLogName() + " controls"); - filter.add(new ControllerIdPredicate(player.getId())); - TargetCreaturePermanent target = new TargetCreaturePermanent(filter); - if (target.canChoose(source.getControllerId(), game) && target.choose(Outcome.Damage, source.getControllerId(), source.getSourceId(), game)) { - UUID creature = target.getFirstTarget(); - if (creature != null) { - game.getPermanent(creature).damage(amount, source.getSourceId(), game, false, true); - return true; - } - } - } - } - return false; + return new DamageTargetEffect((Integer) getValue("damage")).apply(game, source); } @Override diff --git a/Mage.Sets/src/mage/cards/p/PolisCrusher.java b/Mage.Sets/src/mage/cards/p/PolisCrusher.java index eff3cf8d3dc..22c4d9118b7 100644 --- a/Mage.Sets/src/mage/cards/p/PolisCrusher.java +++ b/Mage.Sets/src/mage/cards/p/PolisCrusher.java @@ -1,13 +1,9 @@ - package mage.cards.p; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.condition.common.MonstrousCondition; -import mage.abilities.decorator.ConditionalTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.keyword.MonstrosityAbility; import mage.abilities.keyword.ProtectionAbility; @@ -16,16 +12,16 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.FilterPermanent; -import mage.filter.common.FilterEnchantmentPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; 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.Target; import mage.target.TargetPermanent; -import mage.target.targetpointer.FirstTargetPointer; /** * @@ -39,10 +35,8 @@ public final class PolisCrusher extends CardImpl { filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); } - private final UUID originalId; - public PolisCrusher(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{G}"); this.subtype.add(SubType.CYCLOPS); this.power = new MageInt(4); @@ -50,42 +44,19 @@ public final class PolisCrusher extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); + // protection from enchantments this.addAbility(new ProtectionAbility(filter)); + // {4}{R}{G}: Monstrosity 3. this.addAbility(new MonstrosityAbility("{4}{R}{G}", 3)); + // Whenever Polis Crusher deals combat damage to a player, if Polis Crusher is monstrous, destroy target enchantment that player controls. - Ability ability = new ConditionalTriggeredAbility( - new DealsCombatDamageToAPlayerTriggeredAbility(new DestroyTargetEffect(), false, true), - MonstrousCondition.instance, - "Whenever {this} deals combat damage to a player, if {this} is monstrous, destroy target enchantment that player controls."); - originalId = ability.getOriginalId(); - this.addAbility(ability); + this.addAbility(new PolisCrusherTriggeredAbility()); } public PolisCrusher(final PolisCrusher card) { super(card); - this.originalId = card.originalId; - } - - @Override - public void adjustTargets(Ability ability, Game game) { - if (ability.getOriginalId().equals(originalId)) { - for (Effect effect : ability.getEffects()) { - if (effect instanceof DestroyTargetEffect) { - Player attackedPlayer = game.getPlayer(effect.getTargetPointer().getFirst(game, ability)); - if (attackedPlayer != null) { - ability.getTargets().clear(); - FilterPermanent filterEnchantment = new FilterEnchantmentPermanent("enchantment attacked player controls"); - filterEnchantment.add(new ControllerIdPredicate(attackedPlayer.getId())); - Target target = new TargetPermanent(filterEnchantment); - ability.addTarget(target); - effect.setTargetPointer(new FirstTargetPointer()); - break; - } - } - } - } } @Override @@ -93,3 +64,51 @@ public final class PolisCrusher extends CardImpl { return new PolisCrusher(this); } } + +class PolisCrusherTriggeredAbility extends TriggeredAbilityImpl { + + public PolisCrusherTriggeredAbility() { + super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true); + } + + public PolisCrusherTriggeredAbility(final PolisCrusherTriggeredAbility ability) { + super(ability); + } + + @Override + public PolisCrusherTriggeredAbility copy() { + return new PolisCrusherTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkInterveningIfClause(Game game) { + return MonstrousCondition.instance.apply(game, this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getSourceId().equals(this.sourceId) && ((DamagedPlayerEvent) event).isCombatDamage()) { + Player player = game.getPlayer(event.getTargetId()); + if (player != null) { + FilterPermanent filter = new FilterPermanent("an enchantment controlled by " + player.getLogName()); + filter.add(new CardTypePredicate(CardType.ENCHANTMENT)); + filter.add(new ControllerIdPredicate(event.getTargetId())); + this.getTargets().clear(); + this.addTarget(new TargetPermanent(filter)); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player," + + " if {this} is monstrous, destroy target enchantment that player controls"; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RiptideEntrancer.java b/Mage.Sets/src/mage/cards/r/RiptideEntrancer.java index cd75e26ce68..26ae787668c 100644 --- a/Mage.Sets/src/mage/cards/r/RiptideEntrancer.java +++ b/Mage.Sets/src/mage/cards/r/RiptideEntrancer.java @@ -1,14 +1,11 @@ - package mage.cards.r; import java.util.UUID; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.MorphAbility; import mage.cards.CardImpl; @@ -16,17 +13,13 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Outcome; 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.permanent.Permanent; -import mage.game.stack.Spell; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; /** * @@ -47,7 +40,6 @@ public final class RiptideEntrancer extends CardImpl { // Morph {U}{U} this.addAbility(new MorphAbility(this, new ManaCostsImpl("{U}{U}"))); - } public RiptideEntrancer(final RiptideEntrancer card) { @@ -63,7 +55,10 @@ public final class RiptideEntrancer extends CardImpl { class RiptideEntrancerTriggeredAbility extends TriggeredAbilityImpl { public RiptideEntrancerTriggeredAbility() { - super(Zone.BATTLEFIELD, new RiptideEntrancerEffect(), true); + super(Zone.BATTLEFIELD, new DoIfCostPaid( + new GainControlTargetEffect(Duration.Custom), + new SacrificeSourceCost() + ), true); } public RiptideEntrancerTriggeredAbility(final RiptideEntrancerTriggeredAbility ability) { @@ -95,48 +90,7 @@ class RiptideEntrancerTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever {this} deals combat damage to a player, you may sacrifice it. If you do, gain control of target creature that player controls"; - } -} - -class RiptideEntrancerEffect extends OneShotEffect { - - public RiptideEntrancerEffect() { - super(Outcome.DestroyPermanent); - staticText = "sacrifice {this}"; - } - - public RiptideEntrancerEffect(final RiptideEntrancerEffect effect) { - super(effect); - } - - @Override - public RiptideEntrancerEffect copy() { - return new RiptideEntrancerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent targetPermanent = game.getPermanent(source.getFirstTarget()); - MageObject sourceObject = source.getSourceObjectIfItStillExists(game); - if (sourceObject == null) { - if (source.getSourceObject(game) instanceof Spell) { - sourceObject = game.getPermanent(source.getSourceId()); - if (sourceObject != null && sourceObject.getZoneChangeCounter(game) > source.getSourceObjectZoneChangeCounter() + 1) { - return false; - } - } - } - if (sourceObject instanceof Permanent) { - Permanent permanent = (Permanent) sourceObject; - if (source.getControllerId().equals(permanent.getControllerId())) { - ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom); - effect.setTargetPointer(new FixedTarget(targetPermanent.getId())); - game.addEffect(effect, source); - return permanent.sacrifice(source.getSourceId(), game); - } - return true; - } - return false; + return "Whenever {this} deals combat damage to a player, you may sacrifice it. " + + "If you do, gain control of target creature that player controls"; } } diff --git a/Mage.Sets/src/mage/cards/s/ScionOfDarkness.java b/Mage.Sets/src/mage/cards/s/ScionOfDarkness.java index f2f1195143e..0580b379d11 100644 --- a/Mage.Sets/src/mage/cards/s/ScionOfDarkness.java +++ b/Mage.Sets/src/mage/cards/s/ScionOfDarkness.java @@ -1,25 +1,23 @@ - package mage.cards.s; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.keyword.CyclingAbility; import mage.abilities.keyword.TrampleAbility; -import mage.cards.Card; 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.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; import mage.target.common.TargetCardInGraveyard; @@ -40,8 +38,7 @@ public final class ScionOfDarkness extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Whenever Scion of Darkness deals combat damage to a player, you may put target creature card from that player's graveyard onto the battlefield under your control. - Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new ScionOfDarknessEffect(), true, true); - this.addAbility(ability); + this.addAbility(new ScionOfDarknessTriggeredAbility()); // Cycling {3} this.addAbility(new CyclingAbility(new ManaCostsImpl("{3}"))); @@ -57,41 +54,48 @@ public final class ScionOfDarkness extends CardImpl { } } -class ScionOfDarknessEffect extends OneShotEffect { +class ScionOfDarknessTriggeredAbility extends TriggeredAbilityImpl { - public ScionOfDarknessEffect() { - super(Outcome.PutCreatureInPlay); - this.staticText = "you may put target creature card from that player's graveyard onto the battlefield under your control"; + public ScionOfDarknessTriggeredAbility() { + super(Zone.BATTLEFIELD, new ReturnFromGraveyardToBattlefieldTargetEffect(), true); } - public ScionOfDarknessEffect(final ScionOfDarknessEffect effect) { - super(effect); + public ScionOfDarknessTriggeredAbility(final ScionOfDarknessTriggeredAbility ability) { + super(ability); } @Override - public ScionOfDarknessEffect copy() { - return new ScionOfDarknessEffect(this); + public ScionOfDarknessTriggeredAbility copy() { + return new ScionOfDarknessTriggeredAbility(this); } @Override - public boolean apply(Game game, Ability source) { - Player damagedPlayer = game.getPlayer(targetPointer.getFirst(game, source)); - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null || damagedPlayer == null) { + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; + } + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { return false; } FilterCard filter = new FilterCard("creature in " + damagedPlayer.getName() + "'s graveyard"); filter.add(new CardTypePredicate(CardType.CREATURE)); filter.add(new OwnerIdPredicate(damagedPlayer.getId())); TargetCardInGraveyard target = new TargetCardInGraveyard(filter); - if (target.canChoose(source.getSourceId(), controller.getId(), game)) { - if (controller.chooseTarget(Outcome.PutCreatureInPlay, target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - } + this.getTargets().clear(); + this.addTarget(target); return true; } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may put target creature card from that player's " + + "graveyard onto the battlefield under your control"; + } } diff --git a/Mage.Sets/src/mage/cards/s/ShockmawDragon.java b/Mage.Sets/src/mage/cards/s/ShockmawDragon.java index e8c5f932a8b..7945aa60f16 100644 --- a/Mage.Sets/src/mage/cards/s/ShockmawDragon.java +++ b/Mage.Sets/src/mage/cards/s/ShockmawDragon.java @@ -1,22 +1,23 @@ - package mage.cards.s; -import java.util.List; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; -import mage.filter.StaticFilters; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; +import mage.target.TargetPermanent; /** * @@ -34,7 +35,7 @@ public final class ShockmawDragon extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // Whenever Shockmaw Dragon deals combat damage to a player, it deals 1 damage to each creature that player controls. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ShockmawDragonEffect(), false, true)); + this.addAbility(new PolisCrusherTriggeredAbility()); } public ShockmawDragon(final ShockmawDragon card) { @@ -47,34 +48,45 @@ public final class ShockmawDragon extends CardImpl { } } -class ShockmawDragonEffect extends OneShotEffect { +class PolisCrusherTriggeredAbility extends TriggeredAbilityImpl { - public ShockmawDragonEffect() { - super(Outcome.Damage); - staticText = "it deals 1 damage to each creature that player controls"; + public PolisCrusherTriggeredAbility() { + super(Zone.BATTLEFIELD, new DamageTargetEffect(1), true); } - public ShockmawDragonEffect(final ShockmawDragonEffect effect) { - super(effect); + public PolisCrusherTriggeredAbility(final PolisCrusherTriggeredAbility ability) { + super(ability); } @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(targetPointer.getFirst(game, source)); - if (player != null) { - List creatures = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, player.getId(), game); - for (Permanent creature : creatures) { - if (creature != null) { - creature.damage(1, source.getSourceId(), game, false, true); - } + public PolisCrusherTriggeredAbility copy() { + return new PolisCrusherTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getSourceId().equals(this.sourceId) && ((DamagedPlayerEvent) event).isCombatDamage()) { + Player player = game.getPlayer(event.getTargetId()); + if (player != null) { + FilterPermanent filter = new FilterPermanent("a creature controlled by " + player.getLogName()); + filter.add(new CardTypePredicate(CardType.CREATURE)); + filter.add(new ControllerIdPredicate(event.getTargetId())); + this.getTargets().clear(); + this.addTarget(new TargetPermanent(filter)); + return true; } - return true; } return false; } @Override - public ShockmawDragonEffect copy() { - return new ShockmawDragonEffect(this); + public String getRule() { + return "Whenever {this} deals combat damage to a player," + + " it deals 1 damage to each creature that player controls"; } } diff --git a/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java b/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java index f4fa1b822ff..5bb8dfcfd18 100644 --- a/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java +++ b/Mage.Sets/src/mage/cards/w/WrexialTheRisenDeep.java @@ -1,11 +1,10 @@ - package mage.cards.w; import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; +import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.ReplacementEffectImpl; import mage.abilities.keyword.IslandwalkAbility; @@ -19,6 +18,7 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; import mage.game.events.ZoneChangeEvent; @@ -47,7 +47,7 @@ public final class WrexialTheRisenDeep extends CardImpl { this.addAbility(new SwampwalkAbility()); // Whenever Wrexial, the Risen Deep deals combat damage to a player, you may cast target instant or sorcery card from that player's graveyard without paying its mana cost. If that card would be put into a graveyard this turn, exile it instead. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new WrexialEffect(), true, true)); + this.addAbility(new WrexialTheRisenDeepTriggeredAbility()); } public WrexialTheRisenDeep(final WrexialTheRisenDeep card) { @@ -60,47 +60,84 @@ public final class WrexialTheRisenDeep extends CardImpl { } } -class WrexialEffect extends OneShotEffect { +class WrexialTheRisenDeepTriggeredAbility extends TriggeredAbilityImpl { - public WrexialEffect() { - super(Outcome.PlayForFree); - staticText = "you may cast target instant or sorcery card from that player's graveyard without paying its mana cost. If that card would be put into a graveyard this turn, exile it instead"; + public WrexialTheRisenDeepTriggeredAbility() { + super(Zone.BATTLEFIELD, new WrexialTheRisenDeepEffect(), true); } - public WrexialEffect(final WrexialEffect effect) { + public WrexialTheRisenDeepTriggeredAbility(final WrexialTheRisenDeepTriggeredAbility ability) { + super(ability); + } + + @Override + public WrexialTheRisenDeepTriggeredAbility copy() { + return new WrexialTheRisenDeepTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; + } + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { + return false; + } + FilterCard filter = new FilterCard("target instant or sorcery card from " + damagedPlayer.getName() + "'s graveyard"); + filter.add(new OwnerIdPredicate(damagedPlayer.getId())); + filter.add(Predicates.or( + new CardTypePredicate(CardType.INSTANT), + new CardTypePredicate(CardType.SORCERY))); + + Target target = new TargetCardInGraveyard(filter); + this.getTargets().clear(); + this.addTarget(target); + return true; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may cast target instant or sorcery card " + + "from that player's graveyard without paying its mana cost. " + + "If that card would be put into a graveyard this turn, exile it instead"; + } +} + +class WrexialTheRisenDeepEffect extends OneShotEffect { + + public WrexialTheRisenDeepEffect() { + super(Outcome.PlayForFree); + staticText = "you may cast target instant or sorcery card from " + + "that player's graveyard without paying its mana cost. " + + "If that card would be put into a graveyard this turn, exile it instead"; + } + + public WrexialTheRisenDeepEffect(final WrexialTheRisenDeepEffect effect) { super(effect); } @Override - public WrexialEffect copy() { - return new WrexialEffect(this); + public WrexialTheRisenDeepEffect copy() { + return new WrexialTheRisenDeepEffect(this); } @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Player damagedPlayer = game.getPlayer(targetPointer.getFirst(game, source)); - if (damagedPlayer == null) { - return false; - } - FilterCard filter = new FilterCard("target instant or sorcery card from " + damagedPlayer.getName() + "'s graveyard"); - filter.add(new OwnerIdPredicate(damagedPlayer.getId())); - filter.add(Predicates.or( - new CardTypePredicate(CardType.INSTANT), - new CardTypePredicate(CardType.SORCERY))); - - Target target = new TargetCardInGraveyard(filter); - if (controller.chooseTarget(Outcome.PlayForFree, target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - controller.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game)); - game.addEffect(new WrexialReplacementEffect(card.getId()), source); - } - } - return true; + Card card = game.getCard(source.getFirstTarget()); + if (controller == null || card == null) { + return false; } - return false; + controller.cast(card.getSpellAbility(), game, true, new MageObjectReference(source.getSourceObject(game), game)); + game.addEffect(new WrexialReplacementEffect(card.getId()), source); + return true; } } diff --git a/Mage.Sets/src/mage/cards/z/ZombieCannibal.java b/Mage.Sets/src/mage/cards/z/ZombieCannibal.java index 36bc2e950a3..d871dff4fda 100644 --- a/Mage.Sets/src/mage/cards/z/ZombieCannibal.java +++ b/Mage.Sets/src/mage/cards/z/ZombieCannibal.java @@ -1,21 +1,20 @@ - package mage.cards.z; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.ExileTargetEffect; 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.filter.FilterCard; import mage.filter.predicate.other.OwnerIdPredicate; import mage.game.Game; +import mage.game.events.DamagedPlayerEvent; +import mage.game.events.GameEvent; import mage.players.Player; -import mage.target.Target; import mage.target.common.TargetCardInGraveyard; /** @@ -25,15 +24,14 @@ import mage.target.common.TargetCardInGraveyard; public final class ZombieCannibal extends CardImpl { public ZombieCannibal(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); this.subtype.add(SubType.ZOMBIE); this.power = new MageInt(1); this.toughness = new MageInt(1); // Whenever Zombie Cannibal deals combat damage to a player, you may exile target card from that player's graveyard. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new ZombieCannibalEffect(), true, true)); - + this.addAbility(new ZombieCannibalTriggeredAbility()); } public ZombieCannibal(final ZombieCannibal card) { @@ -46,32 +44,46 @@ public final class ZombieCannibal extends CardImpl { } } -class ZombieCannibalEffect extends OneShotEffect { - - public ZombieCannibalEffect() { - super(Outcome.Exile); - staticText = "you may exile target card from that player's graveyard."; +class ZombieCannibalTriggeredAbility extends TriggeredAbilityImpl { + + public ZombieCannibalTriggeredAbility() { + super(Zone.BATTLEFIELD, new ExileTargetEffect(null, "", Zone.GRAVEYARD), true); } - - public ZombieCannibalEffect(final ZombieCannibalEffect effect) { - super(effect); + + public ZombieCannibalTriggeredAbility(final ZombieCannibalTriggeredAbility ability) { + super(ability); } - + @Override - public ZombieCannibalEffect copy() { - return new ZombieCannibalEffect(this); + public ZombieCannibalTriggeredAbility copy() { + return new ZombieCannibalTriggeredAbility(this); } - + @Override - public boolean apply(Game game, Ability source) { - FilterCard filter = new FilterCard(); - Player player = game.getPlayer(source.getTargets().getFirstTarget()); - if (player != null) { - filter.add(new OwnerIdPredicate(player.getId())); - Target target = new TargetCardInGraveyard(filter); - game.getPermanent(target.getFirstTarget()).moveToExile(null, null, source.getSourceId(), game); + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!event.getSourceId().equals(this.sourceId) || !((DamagedPlayerEvent) event).isCombatDamage()) { + return false; } - return false; + Player damagedPlayer = game.getPlayer(event.getTargetId()); + if (damagedPlayer == null) { + return false; + } + FilterCard filter = new FilterCard("card in " + damagedPlayer.getName() + "'s graveyard"); + filter.add(new OwnerIdPredicate(damagedPlayer.getId())); + TargetCardInGraveyard target = new TargetCardInGraveyard(filter); + this.getTargets().clear(); + this.addTarget(target); + return true; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage to a player, " + + "you may exile target card from that player's graveyard"; } - }