From 32eba22309719bef3cf240ec49bccd13c78e80af Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Wed, 18 Mar 2015 15:59:16 +0100 Subject: [PATCH] [DTK] Added 5 multicolor cards. --- .gitignore | 2 + .../sets/commander/BasandraBattleSeraph.java | 8 +- .../dragonsoftarkir/ArashinSovereign.java | 104 +++++++ .../sets/dragonsoftarkir/AtarkasCommand.java | 92 ++++++ .../dragonsoftarkir/DragonlordDromoka.java | 117 ++++++++ .../dragonsoftarkir/DragonlordKolaghan.java | 140 +++++++++ .../dragonsoftarkir/NarsetTranscendent.java | 265 ++++++++++++++++++ .../src/mage/sets/gatecrash/AureliasFury.java | 17 +- .../src/mage/sets/gatecrash/DomriRade.java | 11 +- .../mage/sets/newphyrexia/IsolationCell.java | 8 +- .../ContinuousRuleModifyingEffectImpl.java | 2 +- .../continuous/CantGainLifeAllEffect.java | 84 +++++- .../abilities/keyword/ReboundAbility.java | 26 +- Utils/mtg-cards-data.txt | 3 +- 14 files changed, 837 insertions(+), 42 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/dragonsoftarkir/ArashinSovereign.java create mode 100644 Mage.Sets/src/mage/sets/dragonsoftarkir/AtarkasCommand.java create mode 100644 Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordDromoka.java create mode 100644 Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordKolaghan.java create mode 100644 Mage.Sets/src/mage/sets/dragonsoftarkir/NarsetTranscendent.java diff --git a/.gitignore b/.gitignore index f92c34058d2..2d4ddf9ef24 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,8 @@ Mage.Server/mageserver.log Mage.Server/magediag.log Mage.Sets/target Mage.Stats/server.log +Mage.Stats/mageserver.log +Mage.Stats/magediag.log Mage.Tests/target Mage.Tests/cache Mage.Tests/db diff --git a/Mage.Sets/src/mage/sets/commander/BasandraBattleSeraph.java b/Mage.Sets/src/mage/sets/commander/BasandraBattleSeraph.java index 971b6414f25..1be9ccd5424 100644 --- a/Mage.Sets/src/mage/sets/commander/BasandraBattleSeraph.java +++ b/Mage.Sets/src/mage/sets/commander/BasandraBattleSeraph.java @@ -111,10 +111,14 @@ class BasandraBattleSeraphEffect extends ContinuousRuleModifyingEffectImpl { return true; } + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL - && game.getPhase().getType() == TurnPhase.COMBAT) { + if (game.getPhase().getType() == TurnPhase.COMBAT) { return true; } return false; diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/ArashinSovereign.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/ArashinSovereign.java new file mode 100644 index 00000000000..bf6814cea5c --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/ArashinSovereign.java @@ -0,0 +1,104 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dragonsoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.DiesTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class ArashinSovereign extends CardImpl { + + public ArashinSovereign(UUID ownerId) { + super(ownerId, 212, "Arashin Sovereign", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{5}{G}{W}"); + this.expansionSetCode = "DTK"; + this.subtype.add("Dragon"); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Arashin Sovereign dies, you may put it on the top or bottom of its owner's library. + this.addAbility(new DiesTriggeredAbility(new ArashinSovereignEffect())); + } + + public ArashinSovereign(final ArashinSovereign card) { + super(card); + } + + @Override + public ArashinSovereign copy() { + return new ArashinSovereign(this); + } +} + +class ArashinSovereignEffect extends OneShotEffect { + + public ArashinSovereignEffect() { + super(Outcome.Benefit); + this.staticText = "you may put it on the top or bottom of its owner's library"; + } + + public ArashinSovereignEffect(final ArashinSovereignEffect effect) { + super(effect); + } + + @Override + public ArashinSovereignEffect copy() { + return new ArashinSovereignEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Card sourceCard = game.getCard(source.getSourceId()); + if (controller != null && sourceCard != null) { + if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { + boolean onTop = controller.chooseUse(outcome, "Put " + sourceCard.getName() + " on top of it's owners library (otherwise on bottom)?", game); + controller.moveCardToLibraryWithInfo(sourceCard, source.getSourceId(), game, Zone.GRAVEYARD, onTop, true); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/AtarkasCommand.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/AtarkasCommand.java new file mode 100644 index 00000000000..d0e79f4b708 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/AtarkasCommand.java @@ -0,0 +1,92 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dragonsoftarkir; + +import java.util.UUID; +import mage.abilities.Mode; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.common.PutLandFromHandOntoBattlefieldEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.CantGainLifeAllEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.ReachAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.TargetController; + +/** + * + * @author LevelX2 + */ +public class AtarkasCommand extends CardImpl { + + public AtarkasCommand(UUID ownerId) { + super(ownerId, 213, "Atarka's Command", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{R}{G}"); + this.expansionSetCode = "DTK"; + + // Choose two - + this.getSpellAbility().getModes().setMinModes(2); + this.getSpellAbility().getModes().setMaxModes(2); + + // Your opponents can't gain life this turn; + this.getSpellAbility().addEffect(new CantGainLifeAllEffect(Duration.EndOfTurn, TargetController.OPPONENT)); + + // or Atarka's Command deals 3 damage to each opponent; + Mode mode = new Mode(); + mode.getEffects().add(new DamagePlayersEffect(3, TargetController.OPPONENT)); + this.getSpellAbility().addMode(mode); + + // or You may put a land card from your hand onto the battlefield; + mode = new Mode(); + mode.getEffects().add(new PutLandFromHandOntoBattlefieldEffect()); + this.getSpellAbility().addMode(mode); + + // or Creatures you control get +1/+1 and gain reach until the end of turn. + mode = new Mode(); + Effect effect = new BoostControlledEffect(1,1, Duration.EndOfTurn); + effect.setText("Creatures you control get +1/+1"); + mode.getEffects().add(effect); + effect = new GainAbilityControlledEffect(ReachAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and gain reach until the end of turn"); + mode.getEffects().add(effect); + this.getSpellAbility().addMode(mode); + + } + + public AtarkasCommand(final AtarkasCommand card) { + super(card); + } + + @Override + public AtarkasCommand copy() { + return new AtarkasCommand(this); + } +} diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordDromoka.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordDromoka.java new file mode 100644 index 00000000000..3ec8fffdf35 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordDromoka.java @@ -0,0 +1,117 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dragonsoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.CantBeCounteredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author LevelX2 + */ +public class DragonlordDromoka extends CardImpl { + + public DragonlordDromoka(UUID ownerId) { + super(ownerId, 217, "Dragonlord Dromoka", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{4}{G}{W}"); + this.expansionSetCode = "DTK"; + this.supertype.add("Legendary"); + this.subtype.add("Elder"); + this.subtype.add("Dragon"); + this.power = new MageInt(5); + this.toughness = new MageInt(7); + + // Dragonlord Dromoka can't be countered + this.addAbility(new CantBeCounteredAbility()); + // Flying + this.addAbility(FlyingAbility.getInstance()); + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + // Your opponents can't cast spells during your turn. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new DragonlordDromokaEffect())); + + } + + public DragonlordDromoka(final DragonlordDromoka card) { + super(card); + } + + @Override + public DragonlordDromoka copy() { + return new DragonlordDromoka(this); + } +} + +class DragonlordDromokaEffect extends ContinuousRuleModifyingEffectImpl { + + public DragonlordDromokaEffect() { + super(Duration.WhileOnBattlefield, Outcome.Benefit); + staticText = "Your opponents can't cast spells during your turn"; + } + + public DragonlordDromokaEffect(final DragonlordDromokaEffect effect) { + super(effect); + } + + @Override + public DragonlordDromokaEffect copy() { + return new DragonlordDromokaEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (game.getActivePlayerId().equals(source.getSourceId()) && + game.getPlayer(source.getControllerId()).hasOpponent(event.getPlayerId(), game)) { + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordKolaghan.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordKolaghan.java new file mode 100644 index 00000000000..e6fce2ff0d8 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordKolaghan.java @@ -0,0 +1,140 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dragonsoftarkir; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 + */ +public class DragonlordKolaghan extends CardImpl { + + public DragonlordKolaghan(UUID ownerId) { + super(ownerId, 218, "Dragonlord Kolaghan", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{4}{B}{R}"); + this.expansionSetCode = "DTK"; + this.supertype.add("Legendary"); + this.subtype.add("Elder"); + this.subtype.add("Dragon"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Haste + this.addAbility(HasteAbility.getInstance()); + + // Other creatures you control have haste. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new GainAbilityControlledEffect(HasteAbility.getInstance(), Duration.WhileOnBattlefield, new FilterControlledCreaturePermanent(), true))); + + // Whenever an opponent casts a creature or planeswalker spell with the same name as a card in their graveyard, that player loses 10 life. + Effect effect = new LoseLifeTargetEffect(10); + effect.setText("that player loses 10 life"); + this.addAbility(new DragonlordKolaghanTriggeredAbility(effect)); + + } + + public DragonlordKolaghan(final DragonlordKolaghan card) { + super(card); + } + + @Override + public DragonlordKolaghan copy() { + return new DragonlordKolaghan(this); + } +} + +class DragonlordKolaghanTriggeredAbility extends TriggeredAbilityImpl { + + public DragonlordKolaghanTriggeredAbility(Effect effect) { + super(Zone.BATTLEFIELD, effect, false); + } + + public DragonlordKolaghanTriggeredAbility(final DragonlordKolaghanTriggeredAbility ability) { + super(ability); + } + + @Override + public DragonlordKolaghanTriggeredAbility copy() { + return new DragonlordKolaghanTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Player controller = game.getPlayer(getControllerId()); + if (controller != null && controller.hasOpponent(event.getPlayerId(), game)) { + Card card = game.getCard(event.getSourceId()); + if (card != null && (card.getCardType().contains(CardType.CREATURE) || card.getCardType().contains(CardType.PLANESWALKER))) { + Player opponent = game.getPlayer(event.getPlayerId()); + boolean sameName = false; + for (Card graveCard :opponent.getGraveyard().getCards(game)) { + if (graveCard.getName().equals(card.getName())) { + sameName = true; + break; + } + } + if (sameName) { + this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId())); + return true; + } + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever an opponent casts a creature or planeswalker spell with the same name as a card in their graveyard, " + super.getRule(); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/NarsetTranscendent.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/NarsetTranscendent.java new file mode 100644 index 00000000000..acfe95ba890 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/NarsetTranscendent.java @@ -0,0 +1,265 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.dragonsoftarkir; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.LoyaltyAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect; +import mage.abilities.effects.common.GetEmblemEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.ReboundAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.command.Emblem; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.targetpointer.FixedTarget; + + +/** + * + * @author LevelX2 + */ +public class NarsetTranscendent extends CardImpl { + + public NarsetTranscendent(UUID ownerId) { + super(ownerId, 225, "Narset Transcendent", Rarity.MYTHIC, new CardType[]{CardType.PLANESWALKER}, "{2}{W}{U}"); + this.expansionSetCode = "DTK"; + this.subtype.add("Narset"); + + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.LOYALTY.createInstance(6)), false)); + + // +1: Look at the top card of your library. If it's a noncreature, nonland card, you may reveal it and put it into your hand. + this.addAbility(new LoyaltyAbility(new NarsetTranscendentEffect1(), 1)); + + // -2: When you cast your next instant or sorcery spell from your hand this turn, it gains rebound. + this.addAbility(new LoyaltyAbility(new CreateDelayedTriggeredAbilityEffect(new NarsetTranscendentTriggeredAbility()), -2)); + + + + // -9:You get an emblem with "Your opponents can't cast noncreature spells." + this.addAbility(new LoyaltyAbility(new GetEmblemEffect(new NarsetTranscendentEmblem()), -9)); + } + + public NarsetTranscendent(final NarsetTranscendent card) { + super(card); + } + + @Override + public NarsetTranscendent copy() { + return new NarsetTranscendent(this); + } +} + +class NarsetTranscendentEffect1 extends OneShotEffect { + + public NarsetTranscendentEffect1() { + super(Outcome.DrawCard); + this.staticText = "Look at the top card of your library. If it's a noncreature, nonland card, you may reveal it and put it into your hand"; + } + + public NarsetTranscendentEffect1(final NarsetTranscendentEffect1 effect) { + super(effect); + } + + @Override + public NarsetTranscendentEffect1 copy() { + return new NarsetTranscendentEffect1(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null && controller != null && controller.getLibrary().size() > 0) { + Card card = controller.getLibrary().getFromTop(game); + if (card != null) { + CardsImpl cards = new CardsImpl(); + cards.add(card); + controller.lookAtCards(sourceObject.getLogName(), cards, game); + if (!card.getCardType().contains(CardType.CREATURE) && !card.getCardType().contains(CardType.LAND)) { + if (controller.chooseUse(outcome, "Reveal " + card.getName() + " and put it into your hand?", game)) { + controller.moveCardToHandWithInfo(card, source.getSourceId(), game, Zone.LIBRARY); + controller.revealCards(sourceObject.getLogName(), cards, game); + } + } + return true; + } + } + return false; + } +} + + +class NarsetTranscendentTriggeredAbility extends DelayedTriggeredAbility { + + public NarsetTranscendentTriggeredAbility() { + super(new NarsetTranscendentGainAbilityEffect(), Duration.EndOfTurn, true); + } + + private NarsetTranscendentTriggeredAbility(final NarsetTranscendentTriggeredAbility ability) { + super(ability); + } + @Override + public NarsetTranscendentTriggeredAbility copy() { + return new NarsetTranscendentTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getPlayerId().equals(this.getControllerId())) { + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell != null && spell.getFromZone().equals(Zone.HAND)) { + if (spell.getCard() != null && + spell.getCard().getCardType().contains(CardType.INSTANT) || spell.getCard().getCardType().contains(CardType.SORCERY)) { + for(Effect effect: getEffects()) { + effect.setTargetPointer(new FixedTarget(spell.getId())); + } + return true; + } + } + } + return false; + } + + @Override + public String getRule() { + return "When you cast your next instant or sorcery spell from your hand this turn, " + super.getRule() ; + } +} + +class NarsetTranscendentGainAbilityEffect extends OneShotEffect { + + private final Ability ability; + + public NarsetTranscendentGainAbilityEffect() { + super(Outcome.AddAbility); + this.ability = new ReboundAbility(); + staticText = "it gains rebound"; + } + + public NarsetTranscendentGainAbilityEffect(final NarsetTranscendentGainAbilityEffect effect) { + super(effect); + this.ability = effect.ability; + } + + @Override + public NarsetTranscendentGainAbilityEffect copy() { + return new NarsetTranscendentGainAbilityEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Spell spell = game.getState().getStack().getSpell(getTargetPointer().getFirst(game, source)); + if (spell != null) { + ReboundAbility.addReboundEffectToSpellIfMissing(spell); + } + return true; + } +} + +class NarsetTranscendentEmblem extends Emblem { + // "Your opponents can't cast noncreature spells. + + public NarsetTranscendentEmblem() { + + this.setName("EMBLEM: Narset Transcendent"); + + this.getAbilities().add(new SimpleStaticAbility(Zone.COMMAND, new NarsetTranscendentCantCastEffect())); + } +} + +class NarsetTranscendentCantCastEffect extends ContinuousRuleModifyingEffectImpl { + + public NarsetTranscendentCantCastEffect() { + super(Duration.EndOfGame, Outcome.Benefit); + staticText = "Your opponents can't cast noncreature spells"; + } + + public NarsetTranscendentCantCastEffect(final NarsetTranscendentCantCastEffect effect) { + super(effect); + } + + @Override + public NarsetTranscendentCantCastEffect copy() { + return new NarsetTranscendentCantCastEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public String getInfoMessage(Ability source, GameEvent event, Game game) { + MageObject mageObject = game.getObject(source.getSourceId()); + if (mageObject != null) { + return "You can't cast can't cast noncreature spells (it is prevented by emblem of " + mageObject.getLogName() + ")"; + } + return null; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && controller.hasOpponent(event.getPlayerId(), game)) { + Card card = game.getCard(event.getSourceId()); + if (card != null && !card.getCardType().contains(CardType.CREATURE)) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/gatecrash/AureliasFury.java b/Mage.Sets/src/mage/sets/gatecrash/AureliasFury.java index 563f826fb9c..78da253b9cc 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/AureliasFury.java +++ b/Mage.Sets/src/mage/sets/gatecrash/AureliasFury.java @@ -177,16 +177,19 @@ class AureliasFuryCantCastEffect extends ContinuousRuleModifyingEffectImpl { } return null; } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.CAST_SPELL; + } @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType() == GameEvent.EventType.CAST_SPELL ) { - Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (player != null && player.getId().equals(event.getPlayerId())) { - Card card = game.getCard(event.getSourceId()); - if (card != null && !card.getCardType().contains(CardType.CREATURE)) { - return true; - } + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player != null && player.getId().equals(event.getPlayerId())) { + Card card = game.getCard(event.getSourceId()); + if (card != null && !card.getCardType().contains(CardType.CREATURE)) { + return true; } } return false; diff --git a/Mage.Sets/src/mage/sets/gatecrash/DomriRade.java b/Mage.Sets/src/mage/sets/gatecrash/DomriRade.java index 3bcbea992a1..a88d2a40809 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/DomriRade.java +++ b/Mage.Sets/src/mage/sets/gatecrash/DomriRade.java @@ -28,6 +28,7 @@ package mage.sets.gatecrash; import java.util.UUID; +import mage.MageObject; import mage.constants.CardType; import mage.constants.Duration; @@ -117,17 +118,17 @@ class DomriRadeEffect1 extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null && controller.getLibrary().size() > 0) { + MageObject sourceObject = source.getSourceObject(game); + if (sourceObject != null && controller != null && controller.getLibrary().size() > 0) { Card card = controller.getLibrary().getFromTop(game); if (card != null) { CardsImpl cards = new CardsImpl(); cards.add(card); - controller.lookAtCards("Domri Rade", cards, game); + controller.lookAtCards(sourceObject.getLogName(), cards, game); if (card.getCardType().contains(CardType.CREATURE)) { - if (controller.chooseUse(outcome, new StringBuilder("Reveal ").append(card.getName()).append(" and put it into your hand?").toString(), game)) { - card = controller.getLibrary().removeFromTop(game); + if (controller.chooseUse(outcome, "Reveal " + card.getName() + " and put it into your hand?", game)) { controller.moveCardToHandWithInfo(card, source.getSourceId(), game, Zone.LIBRARY); - controller.revealCards("Domri Rade", cards, game); + controller.revealCards(sourceObject.getLogName(), cards, game); } } return true; diff --git a/Mage.Sets/src/mage/sets/newphyrexia/IsolationCell.java b/Mage.Sets/src/mage/sets/newphyrexia/IsolationCell.java index dde6436feb9..02f45a9ffcb 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/IsolationCell.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/IsolationCell.java @@ -81,11 +81,15 @@ class IsolationCellTriggeredAbility extends TriggeredAbilityImpl { public IsolationCellTriggeredAbility copy() { return new IsolationCellTriggeredAbility(this); } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.SPELL_CAST - && game.getOpponents(controllerId).contains(event.getPlayerId())) { + if (game.getOpponents(controllerId).contains(event.getPlayerId())) { Card card = game.getCard(event.getSourceId()); if (card != null && card.getCardType().contains(CardType.CREATURE)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId())); diff --git a/Mage/src/mage/abilities/effects/ContinuousRuleModifyingEffectImpl.java b/Mage/src/mage/abilities/effects/ContinuousRuleModifyingEffectImpl.java index 8704d77e731..5dcf58d5e90 100644 --- a/Mage/src/mage/abilities/effects/ContinuousRuleModifyingEffectImpl.java +++ b/Mage/src/mage/abilities/effects/ContinuousRuleModifyingEffectImpl.java @@ -68,7 +68,7 @@ public abstract class ContinuousRuleModifyingEffectImpl extends ContinuousEffect * @param duration * @param outcome * @param messageToUser - Every time the effect replaces an event, the user gets a message in a dialog window. - * Don't set it to true if the event heppens regularly or very often. The message can be + * Don't set it to true if the event happens regularly or very often. The message itself can be * changed by overriding the getInfoMessage method. * @param messageToLog - Every time the effect replaces an event, a message is posted to the game log. The message * can be changed by overriding the getInfoMessage method. diff --git a/Mage/src/mage/abilities/effects/common/continuous/CantGainLifeAllEffect.java b/Mage/src/mage/abilities/effects/common/continuous/CantGainLifeAllEffect.java index 5b977d1031a..ff4c157bfc3 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/CantGainLifeAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/CantGainLifeAllEffect.java @@ -34,6 +34,7 @@ import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; +import mage.constants.TargetController; import mage.game.Game; import mage.players.Player; @@ -42,22 +43,27 @@ import mage.players.Player; * @author LevelX2 */ public class CantGainLifeAllEffect extends ContinuousEffectImpl { - + + private TargetController targetController; + public CantGainLifeAllEffect() { this(Duration.WhileOnBattlefield); } public CantGainLifeAllEffect(Duration duration) { + this(duration, TargetController.ANY); + } + + public CantGainLifeAllEffect(Duration duration, TargetController targetController) { super(duration, Layer.PlayerEffects, SubLayer.NA, Outcome.Benefit); - StringBuilder sb = new StringBuilder("Players can't gain life"); - if (!this.duration.toString().isEmpty()) { - sb.append(" ").append(duration.toString()); - } - staticText = sb.toString(); + this.targetController = targetController; + staticText = setText(); + } public CantGainLifeAllEffect(final CantGainLifeAllEffect effect) { super(effect); + this.targetController = effect.targetController; } @Override @@ -68,17 +74,69 @@ public class CantGainLifeAllEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - for (UUID playerId: controller.getInRange()) { - Player player = game.getPlayer(playerId); - if (player != null) - { - player.setCanGainLife(false); - } + if (controller != null) { + switch (targetController) { + case YOU: + controller.setCanGainLife(false); + break; + case NOT_YOU: + for (UUID playerId: controller.getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null && !player.equals(controller)) { + player.setCanGainLife(false); + } + } + break; + case OPPONENT: + for (UUID playerId: controller.getInRange()) { + if (controller.hasOpponent(playerId, game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.setCanGainLife(false); + } + } + } + break; + case ANY: + for (UUID playerId: controller.getInRange()) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.setCanGainLife(false); + } + } + break; } return true; } return false; } + private String setText() { + StringBuilder sb = new StringBuilder(); + switch (targetController) { + case YOU: + sb.append("You"); + break; + case NOT_YOU: + sb.append("Other players"); + break; + case OPPONENT: + sb.append("Your opponents"); + break; + case ANY: + sb.append("Players"); + break; + } + sb.append(" can't gain life"); + if (!this.duration.toString().isEmpty()) { + sb.append(" "); + if (duration.equals(Duration.EndOfTurn)) { + sb.append("this turn"); + } else { + sb.append(duration.toString()); + } + + } + return sb.toString(); + } } diff --git a/Mage/src/mage/abilities/keyword/ReboundAbility.java b/Mage/src/mage/abilities/keyword/ReboundAbility.java index 6edb0518186..59f56ad6f6e 100644 --- a/Mage/src/mage/abilities/keyword/ReboundAbility.java +++ b/Mage/src/mage/abilities/keyword/ReboundAbility.java @@ -106,17 +106,7 @@ public class ReboundAbility extends TriggeredAbilityImpl { if (event.getType() == EventType.SPELL_CAST && this.installReboundEffect) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && spell.getSourceId().equals(this.getSourceId())) { - Effect reboundEffect = new ReboundEffect(); - boolean found = false; - for (Effect effect : spell.getSpellAbility().getEffects()) { - if (effect instanceof ReboundEffect) { - found = true; - break; - } - } - if (!found) { - spell.getSpellAbility().addEffect(reboundEffect); - } + addReboundEffectToSpellIfMissing(spell); this.installReboundEffect = false; } } @@ -132,6 +122,20 @@ public class ReboundAbility extends TriggeredAbilityImpl { public ReboundAbility copy() { return new ReboundAbility(this); } + + static public void addReboundEffectToSpellIfMissing(Spell spell) { + Effect reboundEffect = new ReboundEffect(); + boolean found = false; + for (Effect effect : spell.getSpellAbility().getEffects()) { + if (effect instanceof ReboundEffect) { + found = true; + break; + } + } + if (!found) { + spell.getSpellAbility().addEffect(reboundEffect); + } + } } /** diff --git a/Utils/mtg-cards-data.txt b/Utils/mtg-cards-data.txt index 5ec3d72317d..8210af87927 100644 --- a/Utils/mtg-cards-data.txt +++ b/Utils/mtg-cards-data.txt @@ -25878,7 +25878,8 @@ Stampeding Elk Herd|Dragons of Tarkir|208|C|{3}{G}{G}|Creature - Elk|5|5|Form Sunbringer's Touch|Dragons of Tarkir|209|R|{2}{G}{G}|Sorcery|||Bolster X, where X is the number of cards in your hand. Each creature you control with a +1/+1 counter on it gains trample until end of turn. (To bolster X, choose a creature with the least toughness among creature you control and put X +1/+1 counters on it.)| Surrak, the Hunt Caller|Dragons of Tarkir|210|R|{2}{G}{G}|Legendary Creature - Human Warrior|5|4|Formidable - At the beginning of combat on your turn, if creatures you control have total power 8 or greater, target creature you control gains haste until end of turn.| Tread Upon|Dragons of Tarkir|211|C|{1}{G}|Instant|||Target creature gets +2/+2 and gains trample until end of turn.| -Arashin Sovereign|Dragons of Tarkir|212|R|{5}{G}{W}|Creature - Dragon|6|6|Flying$When Arashin Sovereign dies, you may put it on the top or bottom of its owner's library.|Atarka's Command|Dragons of Tarkir|213|R|{R}{G}|Instant|||Choose two - Your opponents can't gain life this turn; or Atarka's Command deals 3 damage to each opponent; or You may put a land card from your hand onto the battlefield; or Creatures you control get +1/+1 and gain reach until the end of turn.| +Arashin Sovereign|Dragons of Tarkir|212|R|{5}{G}{W}|Creature - Dragon|6|6|Flying$When Arashin Sovereign dies, you may put it on the top or bottom of its owner's library.| +Atarka's Command|Dragons of Tarkir|213|R|{R}{G}|Instant|||Choose two - Your opponents can't gain life this turn; or Atarka's Command deals 3 damage to each opponent; or You may put a land card from your hand onto the battlefield; or Creatures you control get +1/+1 and gain reach until the end of turn.| Boltwing Marauder|Dragons of Tarkir|214|R|{3}{B}{R}|Creature - Dragon|5|4|Flying$Whenever another creature enters the battlefield under your control, target creature gets +2/+0 until end of turn.| Cunning Breezedancer|Dragons of Tarkir|215|U|{4}{W}{U}|Creature - Dragon|4|4|Flying$Whenever you cast a noncreature spell, Cunning Breezedancer gets +2/+2 until end of turn.| Dragonlord Atarka|Dragons of Tarkir|216|M|{5}{R}{G}|Legendary Creature - Elder Dragon|8|8|Flying, trample$When Dragonlord Atarka enters the battlefield, it deals 5 damage divided as you choose among any number of target creatures and/or planeswalkers your opponents control.|