diff --git a/Mage.Sets/src/mage/cards/n/Nihiloor.java b/Mage.Sets/src/mage/cards/n/Nihiloor.java new file mode 100644 index 0000000000..d619a6f07e --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/Nihiloor.java @@ -0,0 +1,165 @@ +package mage.cards.n; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAllTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.delayed.ReflexiveTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Nihiloor extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(TargetController.OPPONENT.getOwnerPredicate()); + } + + public Nihiloor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}{B}"); + + this.addSuperType(SuperType.LEGENDARY); + this.subtype.add(SubType.HORROR); + this.power = new MageInt(3); + this.toughness = new MageInt(5); + + // When Nihiloor enters the battlefield, for each opponent, tap up to one untapped creature you control. When you do, gain control of target creature that player controls with power less than or equal to the tapped creature's power for as long as you control Nihiloor. + this.addAbility(new EntersBattlefieldTriggeredAbility(new NihiloorControlEffect())); + + // Whenever you attack with a creature an opponent owns, you gain 2 life and that player loses 2 life. + Ability ability = new AttacksAllTriggeredAbility( + new GainLifeEffect(1), false, filter, + SetTargetPointer.PERMANENT, false + ).setTriggerPhrase("Whenever you attack with a creature an opponent owns, "); + ability.addEffect(new NihiloorLoseLifeEffect()); + this.addAbility(ability); + } + + private Nihiloor(final Nihiloor card) { + super(card); + } + + @Override + public Nihiloor copy() { + return new Nihiloor(this); + } +} + +class NihiloorControlEffect extends OneShotEffect { + + private static final FilterPermanent filter + = new FilterControlledCreaturePermanent("untapped creatured you control"); + + static { + filter.add(TappedPredicate.UNTAPPED); + } + + private static final class NihiloorPredicate implements Predicate { + private final Permanent permanent; + private final UUID playerId; + + private NihiloorPredicate(Permanent permanent, UUID playerId) { + this.permanent = permanent; + this.playerId = playerId; + } + + @Override + public boolean apply(Permanent input, Game game) { + return input.isControlledBy(playerId) + && input.getPower().getValue() <= permanent.getPower().getValue(); + } + } + + NihiloorControlEffect() { + super(Outcome.Benefit); + staticText = "for each opponent, tap up to one untapped creature you control. When you do, " + + "gain control of target creature that player controls with power less than " + + "or equal to the tapped creature's power for as long as you control {this}"; + } + + private NihiloorControlEffect(final NihiloorControlEffect effect) { + super(effect); + } + + @Override + public NihiloorControlEffect copy() { + return new NihiloorControlEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + for (UUID playerId : game.getOpponents(source.getControllerId())) { + Player opponent = game.getPlayer(playerId); + if (opponent == null) { + continue; + } + TargetPermanent target = new TargetPermanent(0, 1, filter, true); + target.withChooseHint("tapping a creature controlled by " + opponent.getName()); + controller.choose(outcome, target, source.getControllerId(), game); + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent == null || !permanent.tap(source, game)) { + continue; + } + FilterPermanent filter2 = new FilterPermanent( + "creature controlled by " + opponent.getName() + + " with power " + permanent.getPower().getValue() + " or less" + ); + filter2.add(new NihiloorPredicate(permanent, playerId)); + ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility( + new GainControlTargetEffect(Duration.Custom, true), + false, "gain control of target creature that player controls with " + + "power less than or equal to the tapped creature's power for as long as you control {this}" + ); + ability.addTarget(new TargetPermanent(filter2)); + game.fireReflexiveTriggeredAbility(ability, source); + } + return true; + } + +} + +class NihiloorLoseLifeEffect extends OneShotEffect { + + NihiloorLoseLifeEffect() { + super(Outcome.Benefit); + staticText = "you gain 2 life and that player loses 2 life"; + } + + private NihiloorLoseLifeEffect(final NihiloorLoseLifeEffect effect) { + super(effect); + } + + @Override + public NihiloorLoseLifeEffect copy() { + return new NihiloorLoseLifeEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(game.getControllerId(getTargetPointer().getFirst(game, source))); + return player != null && player.loseLife(2, game, source, false) > 0; + } +} diff --git a/Mage.Sets/src/mage/sets/ForgottenRealmsCommander.java b/Mage.Sets/src/mage/sets/ForgottenRealmsCommander.java index 26c4051ffa..fd846ecca5 100644 --- a/Mage.Sets/src/mage/sets/ForgottenRealmsCommander.java +++ b/Mage.Sets/src/mage/sets/ForgottenRealmsCommander.java @@ -168,6 +168,7 @@ public final class ForgottenRealmsCommander extends ExpansionSet { cards.add(new SetCardInfo("Nature's Lore", 164, Rarity.COMMON, mage.cards.n.NaturesLore.class)); cards.add(new SetCardInfo("Necromantic Selection", 103, Rarity.RARE, mage.cards.n.NecromanticSelection.class)); cards.add(new SetCardInfo("Necrotic Sliver", 188, Rarity.UNCOMMON, mage.cards.n.NecroticSliver.class)); + cards.add(new SetCardInfo("Nihiloor", 53, Rarity.MYTHIC, mage.cards.n.Nihiloor.class)); cards.add(new SetCardInfo("Nimbus Maze", 252, Rarity.RARE, mage.cards.n.NimbusMaze.class)); cards.add(new SetCardInfo("Obsessive Stitcher", 189, Rarity.UNCOMMON, mage.cards.o.ObsessiveStitcher.class)); cards.add(new SetCardInfo("Ogre Slumlord", 104, Rarity.RARE, mage.cards.o.OgreSlumlord.class)); diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbility.java b/Mage/src/main/java/mage/abilities/TriggeredAbility.java index 9387edf1a8..3f4106fe1f 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbility.java @@ -57,4 +57,6 @@ public interface TriggeredAbility extends Ability { GameEvent getTriggerEvent(); String getTriggerPhrase(); + + TriggeredAbility setTriggerPhrase(String triggerPhrase); } diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index b0f929e244..80cef532bb 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -25,6 +25,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge protected boolean leavesTheBattlefieldTrigger; private boolean triggersOnce = false; private GameEvent triggerEvent = null; + private String triggerPhrase = null; public TriggeredAbilityImpl(Zone zone, Effect effect) { this(zone, effect, false); @@ -71,6 +72,12 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge ), game.getTurnNum()); } + @Override + public TriggeredAbilityImpl setTriggerPhrase(String triggerPhrase) { + this.triggerPhrase = triggerPhrase; + return this; + } + @Override public void setTriggerEvent(GameEvent triggerEvent) { this.triggerEvent = triggerEvent; @@ -182,7 +189,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge prefix = ""; } - return prefix + getTriggerPhrase() + sb; + return prefix + triggerPhrase == null ? getTriggerPhrase() : triggerPhrase + sb; } @Override