From 01c3408356fb3a389c86a057616cfc7744c9302a Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:16:29 +0100 Subject: [PATCH 01/38] Implemented Desperate Gambit --- Mage.Sets/src/mage/sets/DesperateGambit.java | 231 +++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/DesperateGambit.java diff --git a/Mage.Sets/src/mage/sets/DesperateGambit.java b/Mage.Sets/src/mage/sets/DesperateGambit.java new file mode 100644 index 00000000000..1272b4c7291 --- /dev/null +++ b/Mage.Sets/src/mage/sets/DesperateGambit.java @@ -0,0 +1,231 @@ +/* + * 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.cards.d; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.PreventDamageBySourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.events.DamageEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.filter.FilterObject; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.players.Player; +import mage.target.TargetSource; + +/** + * + * @author L_J + */ +public class DesperateGambit extends CardImpl { + + public DesperateGambit(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R}"); + + // Choose a source you control and flip a coin. If you win the flip, the next time that source would deal damage this turn, it deals double that damage instead. If you lose the flip, the next time it would deal damage this turn, prevent that damage. + this.getSpellAbility().addEffect(new DesperateGambitEffect()); + } + + public DesperateGambit(final DesperateGambit card) { + super(card); + } + + @Override + public DesperateGambit copy() { + return new DesperateGambit(this); + } +} + +class DesperateGambitEffect extends PreventionEffectImpl { + + private final TargetSource target; + private boolean wonFlip; + + public DesperateGambitEffect() { + super(Duration.EndOfTurn, Integer.MAX_VALUE, false); + staticText = "Choose a source you control and flip a coin. If you win the flip, the next time that source would deal damage this turn, it deals double that damage instead. If you lose the flip, the next time it would deal damage this turn, prevent that damage"; + this.target = new TargetControlledSource(); + } + + public DesperateGambitEffect(final DesperateGambitEffect effect) { + super(effect); + this.target = effect.target.copy(); + } + + @Override + public void init(Ability source, Game game) { + this.target.choose(Outcome.Benefit, source.getControllerId(), source.getSourceId(), game); + this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(game); + super.init(source, game); + } + + @Override + public DesperateGambitEffect copy() { + return new DesperateGambitEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE || + event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER || + event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getSourceId().equals(target.getFirstTarget())) { + // check source + MageObject object = game.getObject(event.getSourceId()); + if (object == null) { + game.informPlayers("Couldn't find source of damage"); + return false; + } + return true; + } + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + MageObject object = game.getObject(event.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && object != null) { + if (super.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0) { + if (wonFlip) { + event.setAmount(event.getAmount() * 2); + this.discard(); + } else { + preventDamageAction(event, source, game); + this.discard(); + return true; + } + } + } + return false; + } +} + +class TargetControlledSource extends TargetSource { + + public TargetControlledSource() { + super(1, 1, new FilterObject("source you control")); + } + + public TargetControlledSource(final TargetControlledSource target) { + super(target); + } + + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + int count = 0; + for (StackObject stackObject: game.getStack()) { + if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId()) + && stackObject.getControllerId() == sourceControllerId) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + for (Permanent permanent: game.getBattlefield().getActivePermanents(sourceControllerId, game)) { + if (permanent.getControllerId() == sourceControllerId) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + for (Player player : game.getPlayers().values()) { + if (player == game.getPlayer(sourceControllerId)) { + for (Card card : player.getGraveyard().getCards(game)) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + // 108.4a If anything asks for the controller of a card that doesn’t have one (because it’s not a permanent or spell), use its owner instead. + for (Card card : game.getExile().getAllCards(game)) { + if (card.getOwnerId() == sourceControllerId) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + } + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet<>(); + for (StackObject stackObject: game.getStack()) { + if (game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId()) + && stackObject.getControllerId() == sourceControllerId) { + possibleTargets.add(stackObject.getId()); + } + } + for (Permanent permanent: game.getBattlefield().getActivePermanents(sourceControllerId, game)) { + if (permanent.getControllerId() == sourceControllerId) { + possibleTargets.add(permanent.getId()); + } + } + for (Player player : game.getPlayers().values()) { + if (player == game.getPlayer(sourceControllerId)) { + for (Card card : player.getGraveyard().getCards(game)) { + possibleTargets.add(card.getId()); + } + // 108.4a If anything asks for the controller of a card that doesn’t have one (because it’s not a permanent or spell), use its owner instead. + for (Card card : game.getExile().getAllCards(game)) { + if (card.getOwnerId() == sourceControllerId) { + possibleTargets.add(card.getId()); + } + } + } + } + return possibleTargets; + } + + @Override + public TargetControlledSource copy() { + return new TargetControlledSource(this); + } +} From fa89c2681f89d7b8d99b19fef90d5b89fbe4d1b5 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:18:01 +0100 Subject: [PATCH 02/38] Moved Desperate Gambit --- Mage.Sets/src/mage/{sets => cards/d}/DesperateGambit.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Mage.Sets/src/mage/{sets => cards/d}/DesperateGambit.java (100%) diff --git a/Mage.Sets/src/mage/sets/DesperateGambit.java b/Mage.Sets/src/mage/cards/d/DesperateGambit.java similarity index 100% rename from Mage.Sets/src/mage/sets/DesperateGambit.java rename to Mage.Sets/src/mage/cards/d/DesperateGambit.java From a3eec223192dcb7eeb17519092ea9c1aba3c4ae9 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:18:47 +0100 Subject: [PATCH 03/38] Implemented Impulsive Maneuvers --- .../src/mage/cards/i/ImpulsiveManeuvers.java | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/i/ImpulsiveManeuvers.java diff --git a/Mage.Sets/src/mage/cards/i/ImpulsiveManeuvers.java b/Mage.Sets/src/mage/cards/i/ImpulsiveManeuvers.java new file mode 100644 index 00000000000..dd8af49bc75 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/ImpulsiveManeuvers.java @@ -0,0 +1,136 @@ +/* + * 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.cards.i; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.AttacksAllTriggeredAbility; +import mage.abilities.effects.PreventionEffectImpl; +import mage.abilities.effects.common.PreventDamageBySourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SetTargetPointer; +import mage.game.Game; +import mage.game.events.DamageEvent; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.filter.StaticFilters; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.players.Player; + +/** + * + * @author L_J + */ +public class ImpulsiveManeuvers extends CardImpl { + + public ImpulsiveManeuvers(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{R}{R}"); + + // Whenever a creature attacks, flip a coin. If you win the flip, the next time that creature would deal combat damage this turn, it deals double that damage instead. If you lose the flip, the next time that creature would deal combat damage this turn, prevent that damage. + this.addAbility(new AttacksAllTriggeredAbility(new ImpulsiveManeuversEffect(), false, StaticFilters.FILTER_PERMANENT_CREATURE, + SetTargetPointer.PERMANENT, false)); + } + + public ImpulsiveManeuvers(final ImpulsiveManeuvers card) { + super(card); + } + + @Override + public ImpulsiveManeuvers copy() { + return new ImpulsiveManeuvers(this); + } +} + +class ImpulsiveManeuversEffect extends PreventionEffectImpl { + + private boolean wonFlip; + + public ImpulsiveManeuversEffect() { + super(Duration.EndOfTurn, Integer.MAX_VALUE, false); + staticText = "flip a coin. If you win the flip, the next time that creature would deal combat damage this turn, it deals double that damage instead. If you lose the flip, the next time that creature would deal combat damage this turn, prevent that damage"; + } + + public ImpulsiveManeuversEffect(final ImpulsiveManeuversEffect effect) { + super(effect); + } + + @Override + public void init(Ability source, Game game) { + this.wonFlip = game.getPlayer(source.getControllerId()).flipCoin(game); + super.init(source, game); + } + + @Override + public ImpulsiveManeuversEffect copy() { + return new ImpulsiveManeuversEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE || + event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER || + event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + MageObject object = game.getObject(event.getSourceId()); + if (object == null) { + game.informPlayers("Couldn't find source of damage"); + return false; + } + return event.getSourceId().equals(this.getTargetPointer().getFirst(game, source)); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + MageObject object = game.getObject(event.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && object != null) { + if (super.applies(event, source, game) && event instanceof DamageEvent && event.getAmount() > 0) { + DamageEvent damageEvent = (DamageEvent) event; + if (damageEvent.isCombatDamage()) { + if (wonFlip) { + event.setAmount(event.getAmount() * 2); + this.discard(); + } else { + preventDamageAction(event, source, game); + this.discard(); + return true; + } + } + } + } + return false; + } +} From d3fac33b71964ac3958511f8bbd78c8561aa26de Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:30:37 +0100 Subject: [PATCH 04/38] Implemented Endbringer's Revel --- .../src/mage/cards/e/EndbringersRevel.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EndbringersRevel.java diff --git a/Mage.Sets/src/mage/cards/e/EndbringersRevel.java b/Mage.Sets/src/mage/cards/e/EndbringersRevel.java new file mode 100644 index 00000000000..0ac33742af7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EndbringersRevel.java @@ -0,0 +1,69 @@ +/* + * 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.cards.e; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.ReturnToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreatureCard; +import mage.target.common.TargetCardInGraveyard; + +/** + * + * @author L_J + */ +public class EndbringersRevel extends CardImpl { + + public EndbringersRevel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{2}{B}"); + + // {4}: Return target creature card from a graveyard to its owner's hand. Any player may activate this ability but only any time he or she could cast a sorcery. + ActivateAsSorceryActivatedAbility ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{4}")); + ability.addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card in a graveyard"))); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new InfoEffect("Any player may activate this ability")); + this.addAbility(ability); + } + + public EndbringersRevel(final EndbringersRevel card) { + super(card); + } + + @Override + public EndbringersRevel copy() { + return new EndbringersRevel(this); + } +} From ab84698172066307bc78d45198b89e632fea2895 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:31:17 +0100 Subject: [PATCH 05/38] Implemented Eye of Yawgmoth --- Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java diff --git a/Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java b/Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java new file mode 100644 index 00000000000..737236f7d2d --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java @@ -0,0 +1,148 @@ +/* + * 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.cards.e; + +import java.util.UUID; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.target.common.TargetControlledCreaturePermanent; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.costs.Cost; +import mage.abilities.costs.VariableCost; +import mage.abilities.costs.common.PayVariableLifeCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.EntwineAbility; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetCard; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author L_J + */ +public class EyeOfYawgmoth extends CardImpl { + + public EyeOfYawgmoth(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}"); + + // {3}, {T}, Sacrifice a creature: Reveal a number of cards from the top of your library equal to the sacrificed creature's power. Put one into your hand and exile the rest. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new EyeOfYawgmothEffect(), new GenericManaCost(3)); + ability.addCost(new TapSourceCost()); + ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, new FilterControlledCreaturePermanent("a creature"), true))); + this.addAbility(ability); + } + + public EyeOfYawgmoth(final EyeOfYawgmoth card) { + super(card); + } + + @Override + public EyeOfYawgmoth copy() { + return new EyeOfYawgmoth(this); + } +} + +class EyeOfYawgmothEffect extends OneShotEffect { + + EyeOfYawgmothEffect() { + super(Outcome.Benefit); + this.staticText = "Reveal a number of cards from the top of your library equal to the sacrificed creature's power. Put one into your hand and exile the rest"; + } + + EyeOfYawgmothEffect(final EyeOfYawgmothEffect effect) { + super(effect); + } + + @Override + public EyeOfYawgmothEffect copy() { + return new EyeOfYawgmothEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + int power = 0; + for (Cost cost: source.getCosts()) { + if (cost instanceof SacrificeTargetCost && !((SacrificeTargetCost) cost).getPermanents().isEmpty()) { + power = ((SacrificeTargetCost)cost).getPermanents().get(0).getPower().getValue(); + break; + } + } + if (power > 0) { + Cards cards = new CardsImpl(); + int count = Math.min(controller.getLibrary().size(), power); + for (int i = 0; i < count; i++) { + Card card = controller.getLibrary().removeFromTop(game); + if (card != null) { + cards.add(card); + } + } + controller.revealCards(source.getSourceObject(game).getIdName(), cards, game); + + TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to put into your hand")); + if (controller.choose(Outcome.DrawCard, cards, target, game)) { + Card card = cards.get(target.getFirstTarget(), game); + if (card != null) { + cards.remove(card); + card.moveToZone(Zone.HAND, source.getSourceId(), game, false); + game.informPlayers(source.getSourceObject(game).getIdName() + ": " + controller.getLogName() + " puts " + card.getIdName() + " into his or her hand"); + } + } + for (UUID cardId : cards) { + Card card = game.getCard(cardId); + card.moveToExile(null, "", source.getSourceId(), game); + } + } + return true; + } +} From afd532146d7c4ca22316e65b463045bb2eaa15a4 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:33:36 +0100 Subject: [PATCH 06/38] Cleaned up imports --- Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java b/Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java index 737236f7d2d..b597cb6fa60 100644 --- a/Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java +++ b/Mage.Sets/src/mage/cards/e/EyeOfYawgmoth.java @@ -28,24 +28,13 @@ package mage.cards.e; import java.util.UUID; +import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.Cost; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.constants.CardType; -import mage.constants.Zone; -import mage.target.common.TargetControlledCreaturePermanent; - -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.costs.Cost; -import mage.abilities.costs.VariableCost; -import mage.abilities.costs.common.PayVariableLifeCost; import mage.abilities.effects.OneShotEffect; -import mage.abilities.keyword.EntwineAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; From e2dfa61fa6771339a5639b98cf13651689fe30d3 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:35:04 +0100 Subject: [PATCH 07/38] Fix for #4137 --- Mage.Sets/src/mage/cards/p/PaleWayfarer.java | 71 ++++++++++++++++++-- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/cards/p/PaleWayfarer.java b/Mage.Sets/src/mage/cards/p/PaleWayfarer.java index ea50659cbf7..60b860f48f0 100644 --- a/Mage.Sets/src/mage/cards/p/PaleWayfarer.java +++ b/Mage.Sets/src/mage/cards/p/PaleWayfarer.java @@ -29,27 +29,36 @@ package mage.cards.p; import java.util.UUID; import mage.MageInt; +import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.UntapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.ChoiceColor; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Layer; import mage.constants.Outcome; +import mage.constants.SubLayer; import mage.constants.Zone; +import mage.filter.FilterObject; +import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; /** * - * @author jeffwadsworth - * + * @author jeffwadsworth & L_J */ public class PaleWayfarer extends CardImpl { @@ -91,8 +100,8 @@ class PaleWayfarerEffect extends OneShotEffect { } @Override - public boolean apply(Game game, Ability source) { - Permanent targetCreature = game.getPermanent(source.getFirstTarget()); + public boolean apply(Game game, Ability source + Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); if (targetCreature != null) { Player player = game.getPlayer(targetCreature.getControllerId()); if (player != null) { @@ -100,6 +109,13 @@ class PaleWayfarerEffect extends OneShotEffect { if (player.choose(Outcome.Neutral, colorChoice, game)) { game.informPlayers(targetCreature.getName() + ": " + player.getLogName() + " has chosen " + colorChoice.getChoice()); game.getState().setValue(targetCreature.getId() + "_color", colorChoice.getColor()); + + ObjectColor protectColor = (ObjectColor) game.getState().getValue(targetCreature.getId() + "_color"); + if (protectColor != null) { + ContinuousEffect effect = new ProtectionChosenColorTargetEffect(); + effect.setTargetPointer(new FixedTarget(targetCreature, game)); + game.addEffect(effect, source); + } } } } @@ -110,4 +126,49 @@ class PaleWayfarerEffect extends OneShotEffect { public PaleWayfarerEffect copy() { return new PaleWayfarerEffect(this); } -} \ No newline at end of file +} + + +class ProtectionChosenColorTargetEffect extends ContinuousEffectImpl { + + protected ObjectColor chosenColor; + protected ProtectionAbility protectionAbility; + + public ProtectionChosenColorTargetEffect() { + super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + } + + public ProtectionChosenColorTargetEffect(final ProtectionChosenColorTargetEffect effect) { + super(effect); + if (effect.chosenColor != null) { + this.chosenColor = effect.chosenColor.copy(); + } + if (effect.protectionAbility != null) { + this.protectionAbility = effect.protectionAbility.copy(); + } + } + + @Override + public ProtectionChosenColorTargetEffect copy() { + return new ProtectionChosenColorTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color"); + if (color != null && (protectionAbility == null || !color.equals(chosenColor))) { + chosenColor = color; + FilterObject protectionFilter = new FilterObject(chosenColor.getDescription()); + protectionFilter.add(new ColorPredicate(chosenColor)); + protectionAbility = new ProtectionAbility(protectionFilter); + } + if (protectionAbility != null) { + permanent.addAbility(protectionAbility, source.getSourceId(), game); + return true; + } + } + return false; + } +} From 37b665487cff5a218bf5013dfe309b719691c58b Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:36:29 +0100 Subject: [PATCH 08/38] Implemented Sailmonger --- Mage.Sets/src/mage/cards/s/Sailmonger.java | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/Sailmonger.java diff --git a/Mage.Sets/src/mage/cards/s/Sailmonger.java b/Mage.Sets/src/mage/cards/s/Sailmonger.java new file mode 100644 index 00000000000..a5a1846d09f --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/Sailmonger.java @@ -0,0 +1,76 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class Sailmonger extends CardImpl { + + public Sailmonger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.MONGER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // {2}: Target creature gains flying until end of turn. Any player may activate this ability. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GainAbilityTargetEffect(FlyingAbility.getInstance(), Duration.EndOfTurn), new ManaCostsImpl("{2}")); + ability.addTarget(new TargetCreaturePermanent()); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new InfoEffect("Any player may activate this ability")); + this.addAbility(ability); + } + + public Sailmonger(final Sailmonger card) { + super(card); + } + + @Override + public Sailmonger copy() { + return new Sailmonger(this); + } +} From 6249ca857e4327bc9b496a7f4c062774e58a8e1a Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:36:58 +0100 Subject: [PATCH 09/38] Implemented Wishmonger --- Mage.Sets/src/mage/cards/w/Wishmonger.java | 174 +++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/w/Wishmonger.java diff --git a/Mage.Sets/src/mage/cards/w/Wishmonger.java b/Mage.Sets/src/mage/cards/w/Wishmonger.java new file mode 100644 index 00000000000..46da88a3f45 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/Wishmonger.java @@ -0,0 +1,174 @@ +/* + * 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.cards.w; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.FilterObject; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author jeffwadsworth & L_J + */ +public class Wishmonger extends CardImpl { + + public Wishmonger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + this.subtype.add(SubType.UNICORN); + this.subtype.add(SubType.MONGER); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // {2}: Target creature gains protection from the color of its controller's choice until end of turn. Any player may activate this ability. + SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new WishmongerEffect(), new ManaCostsImpl("{2}")); + ability.addTarget(new TargetCreaturePermanent()); + ability.setMayActivate(TargetController.ANY); + ability.addEffect(new InfoEffect("Any player may activate this ability")); + this.addAbility(ability); + } + + public Wishmonger(final Wishmonger card) { + super(card); + } + + @Override + public Wishmonger copy() { + return new Wishmonger(this); + } +} + +class WishmongerEffect extends OneShotEffect { + + public WishmongerEffect() { + super(Outcome.BoostCreature); + staticText = "Target creature gains protection from the color of its controller's choice until end of turn"; + } + + public WishmongerEffect(final WishmongerEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (targetCreature != null) { + Player player = game.getPlayer(targetCreature.getControllerId()); + if (player != null) { + ChoiceColor colorChoice = new ChoiceColor(); + if (player.choose(Outcome.Neutral, colorChoice, game)) { + game.informPlayers(targetCreature.getName() + ": " + player.getLogName() + " has chosen " + colorChoice.getChoice()); + game.getState().setValue(targetCreature.getId() + "_color", colorChoice.getColor()); + + ObjectColor protectColor = (ObjectColor) game.getState().getValue(targetCreature.getId() + "_color"); + if (protectColor != null) { + ContinuousEffect effect = new ProtectionChosenColorTargetEffect(); + effect.setTargetPointer(new FixedTarget(targetCreature, game)); + game.addEffect(effect, source); + } + } + } + } + return false; + } + + @Override + public WishmongerEffect copy() { + return new WishmongerEffect(this); + } +} + + +class ProtectionChosenColorTargetEffect extends ContinuousEffectImpl { + + protected ObjectColor chosenColor; + protected ProtectionAbility protectionAbility; + + public ProtectionChosenColorTargetEffect() { + super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + } + + public ProtectionChosenColorTargetEffect(final ProtectionChosenColorTargetEffect effect) { + super(effect); + if (effect.chosenColor != null) { + this.chosenColor = effect.chosenColor.copy(); + } + if (effect.protectionAbility != null) { + this.protectionAbility = effect.protectionAbility.copy(); + } + } + + @Override + public ProtectionChosenColorTargetEffect copy() { + return new ProtectionChosenColorTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color"); + if (color != null && (protectionAbility == null || !color.equals(chosenColor))) { + chosenColor = color; + FilterObject protectionFilter = new FilterObject(chosenColor.getDescription()); + protectionFilter.add(new ColorPredicate(chosenColor)); + protectionAbility = new ProtectionAbility(protectionFilter); + } + if (protectionAbility != null) { + permanent.addAbility(protectionAbility, source.getSourceId(), game); + return true; + } + } + return false; + } +} From a624f0d4c92cd2af0f0015d64adf0d7d1edc17be Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:38:08 +0100 Subject: [PATCH 10/38] Implemented Desperate Gambit --- Mage.Sets/src/mage/sets/Weatherlight.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/Weatherlight.java b/Mage.Sets/src/mage/sets/Weatherlight.java index 6d2f6558d72..c3832ecdd95 100644 --- a/Mage.Sets/src/mage/sets/Weatherlight.java +++ b/Mage.Sets/src/mage/sets/Weatherlight.java @@ -90,6 +90,7 @@ public class Weatherlight extends ExpansionSet { cards.add(new SetCardInfo("Cone of Flame", 95, Rarity.UNCOMMON, mage.cards.c.ConeOfFlame.class)); cards.add(new SetCardInfo("Debt of Loyalty", 127, Rarity.RARE, mage.cards.d.DebtOfLoyalty.class)); cards.add(new SetCardInfo("Dense Foliage", 66, Rarity.RARE, mage.cards.d.DenseFoliage.class)); + cards.add(new SetCardInfo("Desperate Gambit", 96, Rarity.UNCOMMON, mage.cards.d.DesperateGambit.class)); cards.add(new SetCardInfo("Dingus Staff", 149, Rarity.UNCOMMON, mage.cards.d.DingusStaff.class)); cards.add(new SetCardInfo("Disrupt", 37, Rarity.COMMON, mage.cards.d.Disrupt.class)); cards.add(new SetCardInfo("Doomsday", 8, Rarity.RARE, mage.cards.d.Doomsday.class)); From 3e501932c7dc5848b0bca462982f51e7f08d6ca4 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:39:18 +0100 Subject: [PATCH 11/38] Implemented Impulsive Maneuvers --- Mage.Sets/src/mage/sets/Odyssey.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Mage.Sets/src/mage/sets/Odyssey.java b/Mage.Sets/src/mage/sets/Odyssey.java index 046a90917cc..34e731e088e 100644 --- a/Mage.Sets/src/mage/sets/Odyssey.java +++ b/Mage.Sets/src/mage/sets/Odyssey.java @@ -186,6 +186,7 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Haunting Echoes", 142, Rarity.RARE, mage.cards.h.HauntingEchoes.class)); cards.add(new SetCardInfo("Howling Gale", 244, Rarity.UNCOMMON, mage.cards.h.HowlingGale.class)); cards.add(new SetCardInfo("Immobilizing Ink", 87, Rarity.COMMON, mage.cards.i.ImmobilizingInk.class)); + cards.add(new SetCardInfo("Impulsive Maneuvers", 197, Rarity.RARE, mage.cards.i.ImpulsiveManeuvers.class)); cards.add(new SetCardInfo("Infected Vermin", 144, Rarity.UNCOMMON, mage.cards.i.InfectedVermin.class)); cards.add(new SetCardInfo("Innocent Blood", 145, Rarity.COMMON, mage.cards.i.InnocentBlood.class)); cards.add(new SetCardInfo("Iridescent Angel", 288, Rarity.RARE, mage.cards.i.IridescentAngel.class)); @@ -194,7 +195,7 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Island", 337, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Island", 338, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Ivy Elemental", 245, Rarity.RARE, mage.cards.i.IvyElemental.class)); - cards.add(new SetCardInfo("Junk Golem", 300, Rarity.RARE, mage.cards.j.JunkGolem.class)); + cards.add(new SetCardInfo("Junk Golem", 300, Rarity.RARE, mage.cards.j.JunkGolem.class)); cards.add(new SetCardInfo("Kamahl, Pit Fighter", 198, Rarity.RARE, mage.cards.k.KamahlPitFighter.class)); cards.add(new SetCardInfo("Kamahl's Desire", 199, Rarity.COMMON, mage.cards.k.KamahlsDesire.class)); cards.add(new SetCardInfo("Karmic Justice", 26, Rarity.RARE, mage.cards.k.KarmicJustice.class)); @@ -251,7 +252,7 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Nomad Stadium", 322, Rarity.UNCOMMON, mage.cards.n.NomadStadium.class)); cards.add(new SetCardInfo("Nut Collector", 259, Rarity.RARE, mage.cards.n.NutCollector.class)); cards.add(new SetCardInfo("Obstinate Familiar", 210, Rarity.RARE, mage.cards.o.ObstinateFamiliar.class)); - cards.add(new SetCardInfo("Otarian Juggernaut", 305, Rarity.RARE, mage.cards.o.OtarianJuggernaut.class)); + cards.add(new SetCardInfo("Otarian Juggernaut", 305, Rarity.RARE, mage.cards.o.OtarianJuggernaut.class)); cards.add(new SetCardInfo("Overeager Apprentice", 154, Rarity.COMMON, mage.cards.o.OvereagerApprentice.class)); cards.add(new SetCardInfo("Overrun", 260, Rarity.UNCOMMON, mage.cards.o.Overrun.class)); cards.add(new SetCardInfo("Pardic Firecat", 211, Rarity.COMMON, mage.cards.p.PardicFirecat.class)); @@ -321,11 +322,11 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Soulcatcher", 47, Rarity.UNCOMMON, mage.cards.s.Soulcatcher.class)); cards.add(new SetCardInfo("Spark Mage", 222, Rarity.UNCOMMON, mage.cards.s.SparkMage.class)); cards.add(new SetCardInfo("Spellbane Centaur", 271, Rarity.RARE, mage.cards.s.SpellbaneCentaur.class)); - cards.add(new SetCardInfo("Sphere of Duty", 48, Rarity.UNCOMMON, mage.cards.s.SphereOfDuty.class)); - cards.add(new SetCardInfo("Sphere of Grace", 49, Rarity.UNCOMMON, mage.cards.s.SphereOfGrace.class)); - cards.add(new SetCardInfo("Sphere of Law", 50, Rarity.UNCOMMON, mage.cards.s.SphereOfLaw.class)); - cards.add(new SetCardInfo("Sphere of Reason", 51, Rarity.UNCOMMON, mage.cards.s.SphereOfReason.class)); - cards.add(new SetCardInfo("Sphere of Truth", 52, Rarity.UNCOMMON, mage.cards.s.SphereOfTruth.class)); + cards.add(new SetCardInfo("Sphere of Duty", 48, Rarity.UNCOMMON, mage.cards.s.SphereOfDuty.class)); + cards.add(new SetCardInfo("Sphere of Grace", 49, Rarity.UNCOMMON, mage.cards.s.SphereOfGrace.class)); + cards.add(new SetCardInfo("Sphere of Law", 50, Rarity.UNCOMMON, mage.cards.s.SphereOfLaw.class)); + cards.add(new SetCardInfo("Sphere of Reason", 51, Rarity.UNCOMMON, mage.cards.s.SphereOfReason.class)); + cards.add(new SetCardInfo("Sphere of Truth", 52, Rarity.UNCOMMON, mage.cards.s.SphereOfTruth.class)); cards.add(new SetCardInfo("Spiritualize", 53, Rarity.UNCOMMON, mage.cards.s.Spiritualize.class)); cards.add(new SetCardInfo("Springing Tiger", 272, Rarity.COMMON, mage.cards.s.SpringingTiger.class)); cards.add(new SetCardInfo("Squirrel Mob", 273, Rarity.RARE, mage.cards.s.SquirrelMob.class)); @@ -361,7 +362,7 @@ public class Odyssey extends ExpansionSet { cards.add(new SetCardInfo("Traumatize", 110, Rarity.RARE, mage.cards.t.Traumatize.class)); cards.add(new SetCardInfo("Treetop Sentinel", 111, Rarity.UNCOMMON, mage.cards.t.TreetopSentinel.class)); cards.add(new SetCardInfo("Tremble", 225, Rarity.COMMON, mage.cards.t.Tremble.class)); - cards.add(new SetCardInfo("Twigwalker", 279, Rarity.UNCOMMON, mage.cards.t.Twigwalker.class)); + cards.add(new SetCardInfo("Twigwalker", 279, Rarity.UNCOMMON, mage.cards.t.Twigwalker.class)); cards.add(new SetCardInfo("Unifying Theory", 112, Rarity.RARE, mage.cards.u.UnifyingTheory.class)); cards.add(new SetCardInfo("Upheaval", 113, Rarity.RARE, mage.cards.u.Upheaval.class)); cards.add(new SetCardInfo("Vampiric Dragon", 296, Rarity.RARE, mage.cards.v.VampiricDragon.class)); From ddd74552449d8acac9af6cd9a9c6f2be58294382 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:40:09 +0100 Subject: [PATCH 12/38] Implemented Eye of Yawgmoth --- Mage.Sets/src/mage/sets/Nemesis.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/Nemesis.java b/Mage.Sets/src/mage/sets/Nemesis.java index b8225ffd6af..d84902022d5 100644 --- a/Mage.Sets/src/mage/sets/Nemesis.java +++ b/Mage.Sets/src/mage/sets/Nemesis.java @@ -85,6 +85,7 @@ public class Nemesis extends ExpansionSet { cards.add(new SetCardInfo("Dominate", 31, Rarity.UNCOMMON, mage.cards.d.Dominate.class)); cards.add(new SetCardInfo("Downhill Charge", 79, Rarity.COMMON, mage.cards.d.DownhillCharge.class)); cards.add(new SetCardInfo("Ensnare", 32, Rarity.UNCOMMON, mage.cards.e.Ensnare.class)); + cards.add(new SetCardInfo("Eye of Yawgmoth", 129, Rarity.RARE, mage.cards.e.EyeOfYawgmoth.class)); cards.add(new SetCardInfo("Fanatical Devotion", 8, Rarity.COMMON, mage.cards.f.FanaticalDevotion.class)); cards.add(new SetCardInfo("Flame Rift", 80, Rarity.COMMON, mage.cards.f.FlameRift.class)); cards.add(new SetCardInfo("Flowstone Armor", 131, Rarity.UNCOMMON, mage.cards.f.FlowstoneArmor.class)); From 2979298f7c6b6f8e186e652c62bc661fc151f36d Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:41:20 +0100 Subject: [PATCH 13/38] Implemented Endbringer's Revel --- Mage.Sets/src/mage/sets/Prophecy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/Prophecy.java b/Mage.Sets/src/mage/sets/Prophecy.java index 10b7c6d885f..2a688772e4e 100644 --- a/Mage.Sets/src/mage/sets/Prophecy.java +++ b/Mage.Sets/src/mage/sets/Prophecy.java @@ -83,6 +83,7 @@ public class Prophecy extends ExpansionSet { cards.add(new SetCardInfo("Diving Griffin", 6, Rarity.COMMON, mage.cards.d.DivingGriffin.class)); cards.add(new SetCardInfo("Dual Nature", 112, Rarity.RARE, mage.cards.d.DualNature.class)); cards.add(new SetCardInfo("Elephant Resurgence", 113, Rarity.RARE, mage.cards.e.ElephantResurgence.class)); + cards.add(new SetCardInfo("Endbringer's Revel", 63, Rarity.UNCOMMON, mage.cards.e.EndbringersRevel.class)); cards.add(new SetCardInfo("Entangler", 7, Rarity.UNCOMMON, mage.cards.e.Entangler.class)); cards.add(new SetCardInfo("Excavation", 33, Rarity.UNCOMMON, mage.cards.e.Excavation.class)); cards.add(new SetCardInfo("Fault Riders", 88, Rarity.COMMON, mage.cards.f.FaultRiders.class)); From 56c1e4ff7a4bb1b5e5eb7e356dbc52d28bb148c7 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:42:09 +0100 Subject: [PATCH 14/38] Implemented Sailmonger and Wishmonger --- Mage.Sets/src/mage/sets/MercadianMasques.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mage.Sets/src/mage/sets/MercadianMasques.java b/Mage.Sets/src/mage/sets/MercadianMasques.java index c0bde8f6e10..d20afbfc271 100644 --- a/Mage.Sets/src/mage/sets/MercadianMasques.java +++ b/Mage.Sets/src/mage/sets/MercadianMasques.java @@ -275,6 +275,7 @@ public class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Rushwood Legate", 266, Rarity.UNCOMMON, mage.cards.r.RushwoodLegate.class)); cards.add(new SetCardInfo("Saber Ants", 267, Rarity.UNCOMMON, mage.cards.s.SaberAnts.class)); cards.add(new SetCardInfo("Sacred Prey", 268, Rarity.COMMON, mage.cards.s.SacredPrey.class)); + cards.add(new SetCardInfo("Sailmonger", 95, Rarity.UNCOMMON, mage.cards.s.Sailmonger.class)); cards.add(new SetCardInfo("Sand Squid", 96, Rarity.RARE, mage.cards.s.SandSquid.class)); cards.add(new SetCardInfo("Sandstone Needle", 326, Rarity.COMMON, mage.cards.s.SandstoneNeedle.class)); cards.add(new SetCardInfo("Saprazzan Cove", 327, Rarity.UNCOMMON, mage.cards.s.SaprazzanCove.class)); @@ -353,6 +354,7 @@ public class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Waterfront Bouncer", 114, Rarity.COMMON, mage.cards.w.WaterfrontBouncer.class)); cards.add(new SetCardInfo("Wave of Reckoning", 56, Rarity.RARE, mage.cards.w.WaveOfReckoning.class)); cards.add(new SetCardInfo("Wild Jhovall", 227, Rarity.COMMON, mage.cards.w.WildJhovall.class)); + cards.add(new SetCardInfo("Wishmonger", 57, Rarity.UNCOMMON, mage.cards.w.Wishmonger.class)); cards.add(new SetCardInfo("Word of Blasting", 228, Rarity.UNCOMMON, mage.cards.w.WordOfBlasting.class)); cards.add(new SetCardInfo("Worry Beads", 315, Rarity.RARE, mage.cards.w.WorryBeads.class)); } From 67c1f04cecbbebf027ec04c050fa396d9e73e929 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 16:51:14 +0100 Subject: [PATCH 15/38] Typo fix --- Mage.Sets/src/mage/cards/p/PaleWayfarer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/cards/p/PaleWayfarer.java b/Mage.Sets/src/mage/cards/p/PaleWayfarer.java index 60b860f48f0..e539dd861bf 100644 --- a/Mage.Sets/src/mage/cards/p/PaleWayfarer.java +++ b/Mage.Sets/src/mage/cards/p/PaleWayfarer.java @@ -100,7 +100,7 @@ class PaleWayfarerEffect extends OneShotEffect { } @Override - public boolean apply(Game game, Ability source + public boolean apply(Game game, Ability source) { Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); if (targetCreature != null) { Player player = game.getPlayer(targetCreature.getControllerId()); From 611d806b43cd932b5e5d5e1a97e56bde28ca4466 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 18:58:35 +0100 Subject: [PATCH 16/38] Implemented Timebender --- Mage.Sets/src/mage/cards/t/Timebender.java | 136 +++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/t/Timebender.java diff --git a/Mage.Sets/src/mage/cards/t/Timebender.java b/Mage.Sets/src/mage/cards/t/Timebender.java new file mode 100644 index 00000000000..d817dbafc3e --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/Timebender.java @@ -0,0 +1,136 @@ +/* + * 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.cards.t; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.TurnedFaceUpSourceTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.MorphAbility; +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.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetPermanentOrSuspendedCard; + +/** + * + * @author L_J + */ +public class Timebender extends CardImpl { + + public Timebender(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{U}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.WIZARD); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Morph {U} + this.addAbility(new MorphAbility(this, new ManaCostsImpl("{U}"))); + + // When Timebender is turned face up, choose one — + // Remove two time counters from target permanent or suspended card. + Ability ability = new TurnedFaceUpSourceTriggeredAbility(new TimebenderEffect(false)); + ability.addTarget(new TargetPermanentOrSuspendedCard()); + + // Put two time counters on target permanent with a time counter on it or suspended card. + Mode mode = new Mode(); + mode.getEffects().add(new TimebenderEffect(true)); + mode.getTargets().add(new TargetPermanentOrSuspendedCard()); + ability.addMode(mode); + ability.getModes().addMode(mode); + this.addAbility(ability); + + } + + public Timebender(final Timebender card) { + super(card); + } + + @Override + public Timebender copy() { + return new Timebender(this); + } +} + +class TimebenderEffect extends OneShotEffect { + + private final boolean addCounters; + + public TimebenderEffect(boolean addCounters) { + super(Outcome.Benefit); + this.addCounters = addCounters; + if (addCounters) { + this.staticText = "put two time counters on target permanent or suspended card"; + } else { + this.staticText = "remove two time counters from target permanent or suspended card"; + } + } + + public TimebenderEffect(final TimebenderEffect effect) { + super(effect); + this.addCounters = effect.addCounters; + } + + @Override + public TimebenderEffect copy() { + return new TimebenderEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + if (addCounters) { + permanent.addCounters(CounterType.TIME.createInstance(2), source, game); + } else { + permanent.removeCounters(CounterType.TIME.getName(), 2, game); + } + return true; + } + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + if (card != null) { + if (addCounters) { + card.addCounters(CounterType.TIME.createInstance(2), source, game); + } else { + card.removeCounters(CounterType.TIME.getName(), 2, game); + } + return true; + } + return false; + } +} From 15dd45ff32816754f5fdfbeff3bd9f7c0fba8929 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 18:58:59 +0100 Subject: [PATCH 17/38] Implemented Shivan Sand-Mage --- .../src/mage/cards/s/ShivanSandMage.java | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/s/ShivanSandMage.java diff --git a/Mage.Sets/src/mage/cards/s/ShivanSandMage.java b/Mage.Sets/src/mage/cards/s/ShivanSandMage.java new file mode 100644 index 00000000000..7666241f034 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShivanSandMage.java @@ -0,0 +1,135 @@ +/* + * 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.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.SuspendAbility; +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.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetPermanentOrSuspendedCard; + +/** + * + * @author L_J + */ +public class ShivanSandMage extends CardImpl { + + public ShivanSandMage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}"); + this.subtype.add(SubType.VIASHINO); + this.subtype.add(SubType.SHAMAN); + this.power = new MageInt(3); + this.toughness = new MageInt(2); + + // When Shivan Sand-Mage enters the battlefield, choose one — + // Remove two time counters from target permanent or suspended card. + Ability ability = new EntersBattlefieldTriggeredAbility(new ShivanSandMageEffect(false)); + ability.addTarget(new TargetPermanentOrSuspendedCard()); + + // Put two time counters on target permanent with a time counter on it or suspended card. + Mode mode = new Mode(); + mode.getEffects().add(new ShivanSandMageEffect(true)); + mode.getTargets().add(new TargetPermanentOrSuspendedCard()); + ability.addMode(mode); + ability.getModes().addMode(mode); + this.addAbility(ability); + + // Suspend 4-{R} + this.addAbility(new SuspendAbility(4, new ManaCostsImpl("{R}"), this)); + } + + public ShivanSandMage(final ShivanSandMage card) { + super(card); + } + + @Override + public ShivanSandMage copy() { + return new ShivanSandMage(this); + } +} + +class ShivanSandMageEffect extends OneShotEffect { + + private final boolean addCounters; + + public ShivanSandMageEffect(boolean addCounters) { + super(Outcome.Benefit); + this.addCounters = addCounters; + if (addCounters) { + this.staticText = "put two time counters on target permanent or suspended card"; + } else { + this.staticText = "remove two time counters from target permanent or suspended card"; + } + } + + public ShivanSandMageEffect(final ShivanSandMageEffect effect) { + super(effect); + this.addCounters = effect.addCounters; + } + + @Override + public ShivanSandMageEffect copy() { + return new ShivanSandMageEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(this.getTargetPointer().getFirst(game, source)); + if (permanent != null) { + if (addCounters) { + permanent.addCounters(CounterType.TIME.createInstance(2), source, game); + } else { + permanent.removeCounters(CounterType.TIME.getName(), 2, game); + } + return true; + } + Card card = game.getCard(this.getTargetPointer().getFirst(game, source)); + if (card != null) { + if (addCounters) { + card.addCounters(CounterType.TIME.createInstance(2), source, game); + } else { + card.removeCounters(CounterType.TIME.getName(), 2, game); + } + return true; + } + return false; + } +} From 2b5d818872b6079a2ce8b3c36017814ec210817c Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 19:00:38 +0100 Subject: [PATCH 18/38] Implemented Timebender --- Mage.Sets/src/mage/sets/PlanarChaos.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/PlanarChaos.java b/Mage.Sets/src/mage/sets/PlanarChaos.java index d68966c1571..0e868205755 100644 --- a/Mage.Sets/src/mage/sets/PlanarChaos.java +++ b/Mage.Sets/src/mage/sets/PlanarChaos.java @@ -198,6 +198,7 @@ public class PlanarChaos extends ExpansionSet { cards.add(new SetCardInfo("Teneb, the Harvester", 163, Rarity.RARE, mage.cards.t.TenebTheHarvester.class)); cards.add(new SetCardInfo("Tidewalker", 49, Rarity.UNCOMMON, mage.cards.t.Tidewalker.class)); cards.add(new SetCardInfo("Timbermare", 140, Rarity.RARE, mage.cards.t.Timbermare.class)); + cards.add(new SetCardInfo("Timebender", 50, Rarity.UNCOMMON, mage.cards.t.Timebender.class)); cards.add(new SetCardInfo("Timecrafting", 109, Rarity.UNCOMMON, mage.cards.t.Timecrafting.class)); cards.add(new SetCardInfo("Torchling", 110, Rarity.RARE, mage.cards.t.Torchling.class)); cards.add(new SetCardInfo("Treacherous Urge", 82, Rarity.UNCOMMON, mage.cards.t.TreacherousUrge.class)); From a742414dd9747094841d272f2e1f798712d4d080 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 19:00:50 +0100 Subject: [PATCH 19/38] Implemented Shivan Sand-Mage --- Mage.Sets/src/mage/sets/FutureSight.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/FutureSight.java b/Mage.Sets/src/mage/sets/FutureSight.java index 14ab9c9bfc0..1fd069f0cc7 100644 --- a/Mage.Sets/src/mage/sets/FutureSight.java +++ b/Mage.Sets/src/mage/sets/FutureSight.java @@ -188,6 +188,7 @@ public class FutureSight extends ExpansionSet { cards.add(new SetCardInfo("Seht's Tiger", 31, Rarity.RARE, mage.cards.s.SehtsTiger.class)); cards.add(new SetCardInfo("Shapeshifter's Marrow", 58, Rarity.RARE, mage.cards.s.ShapeshiftersMarrow.class)); cards.add(new SetCardInfo("Shimian Specter", 76, Rarity.RARE, mage.cards.s.ShimianSpecter.class)); + cards.add(new SetCardInfo("Shivan Sand-Mage", 108, Rarity.UNCOMMON, mage.cards.s.ShivanSandMage.class)); cards.add(new SetCardInfo("Skirk Ridge Exhumer", 77, Rarity.UNCOMMON, mage.cards.s.SkirkRidgeExhumer.class)); cards.add(new SetCardInfo("Skizzik Surger", 120, Rarity.UNCOMMON, mage.cards.s.SkizzikSurger.class)); cards.add(new SetCardInfo("Slaughter Pact", 78, Rarity.RARE, mage.cards.s.SlaughterPact.class)); From 1f73993ca6f662f957c99d09ee348ecbb19d9cc8 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 21:29:47 +0100 Subject: [PATCH 20/38] Implemented Latulla's Orders --- .../src/mage/cards/l/LatullasOrders.java | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LatullasOrders.java diff --git a/Mage.Sets/src/mage/cards/l/LatullasOrders.java b/Mage.Sets/src/mage/cards/l/LatullasOrders.java new file mode 100644 index 00000000000..d11ef2b5124 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LatullasOrders.java @@ -0,0 +1,129 @@ +/* + * 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.cards.l; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +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.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class LatullasOrders extends CardImpl { + + public LatullasOrders(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}"); + this.subtype.add(SubType.AURA); + + // Flash + this.addAbility(FlashAbility.getInstance()); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Protect)); + this.addAbility(new EnchantAbility(auraTarget.getTargetName())); + + // Whenever enchanted creature deals combat damage to defending player, you may destroy target artifact that player controls. + this.addAbility(new LatullasOrdersTriggeredAbility()); + } + + public LatullasOrders(final LatullasOrders card) { + super(card); + } + + @Override + public LatullasOrders copy() { + return new LatullasOrders(this); + } +} + +class LatullasOrdersTriggeredAbility extends TriggeredAbilityImpl { + + public LatullasOrdersTriggeredAbility() { + super(Zone.BATTLEFIELD, new DestroyTargetEffect(), true); + } + + public LatullasOrdersTriggeredAbility(final LatullasOrdersTriggeredAbility ability) { + super(ability); + } + + @Override + public LatullasOrdersTriggeredAbility copy() { + return new LatullasOrdersTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGED_PLAYER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent enchantment = game.getPermanentOrLKIBattlefield(this.getSourceId()); + if (event.getSourceId().equals(enchantment.getAttachedTo()) && ((DamagedPlayerEvent) event).isCombatDamage()) { + Player player = game.getPlayer(event.getTargetId()); + if (player != null) { + FilterPermanent filter = new FilterPermanent("an artifact controlled by " + player.getLogName()); + filter.add(new CardTypePredicate(CardType.ARTIFACT)); + filter.add(new ControllerIdPredicate(event.getTargetId())); + + this.getTargets().clear(); + this.addTarget(new TargetPermanent(filter)); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever enchanted creature deals combat damage to defending player, you may destroy target artifact that player controls."; + } +} From 624c61347525b74778f9f3c594b954234423b56c Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 21:30:45 +0100 Subject: [PATCH 21/38] Implemented Latulla's Orders --- Mage.Sets/src/mage/sets/Prophecy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/Prophecy.java b/Mage.Sets/src/mage/sets/Prophecy.java index 2a688772e4e..a34124a6c0a 100644 --- a/Mage.Sets/src/mage/sets/Prophecy.java +++ b/Mage.Sets/src/mage/sets/Prophecy.java @@ -106,6 +106,7 @@ public class Prophecy extends ExpansionSet { cards.add(new SetCardInfo("Keldon Berserker", 93, Rarity.COMMON, mage.cards.k.KeldonBerserker.class)); cards.add(new SetCardInfo("Keldon Firebombers", 94, Rarity.RARE, mage.cards.k.KeldonFirebombers.class)); cards.add(new SetCardInfo("Latulla, Keldon Overseer", 95, Rarity.RARE, mage.cards.l.LatullaKeldonOverseer.class)); + cards.add(new SetCardInfo("Latulla's Orders", 96, Rarity.COMMON, mage.cards.l.LatullasOrders.class)); cards.add(new SetCardInfo("Lesser Gargadon", 97, Rarity.UNCOMMON, mage.cards.l.LesserGargadon.class)); cards.add(new SetCardInfo("Living Terrain", 117, Rarity.UNCOMMON, mage.cards.l.LivingTerrain.class)); cards.add(new SetCardInfo("Mageta's Boon", 14, Rarity.COMMON, mage.cards.m.MagetasBoon.class)); From e6b84efecaddd0833bb127cea5ca107c33956f3b Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 22:52:15 +0100 Subject: [PATCH 22/38] Implemented Laccolith Grunt --- .../src/mage/cards/l/LaccolithGrunt.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LaccolithGrunt.java diff --git a/Mage.Sets/src/mage/cards/l/LaccolithGrunt.java b/Mage.Sets/src/mage/cards/l/LaccolithGrunt.java new file mode 100644 index 00000000000..78edd56552e --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LaccolithGrunt.java @@ -0,0 +1,112 @@ +/* + * 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.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.cards.CardImpl; +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.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class LaccolithGrunt extends CardImpl { + + public LaccolithGrunt(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); + this.subtype.add(SubType.BEAST); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn. + Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true); + ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public LaccolithGrunt(final LaccolithGrunt card) { + super(card); + } + + @Override + public LaccolithGrunt copy() { + return new LaccolithGrunt(this); + } + + class LaccolithEffect extends OneShotEffect { + public LaccolithEffect() { + super(Outcome.Damage); + staticText = "{this} deals damage equal to its power to target creature"; + } + + public LaccolithEffect(final LaccolithEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent == null) { + sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); + } + if (sourcePermanent == null) { + return false; + } + + int damage = sourcePermanent.getPower().getValue(); + + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + permanent.damage(damage, sourcePermanent.getId(), game, false, true); + return true; + } + return false; + } + + @Override + public LaccolithEffect copy() { + return new LaccolithEffect(this); + } + + } +} From c8baeddb2abf8792499ac8df2288f989ef2fd69d Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 22:55:32 +0100 Subject: [PATCH 23/38] Implemented Laccolith Titan --- .../src/mage/cards/l/LaccolithTitan.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LaccolithTitan.java diff --git a/Mage.Sets/src/mage/cards/l/LaccolithTitan.java b/Mage.Sets/src/mage/cards/l/LaccolithTitan.java new file mode 100644 index 00000000000..8e92108948b --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LaccolithTitan.java @@ -0,0 +1,112 @@ +/* + * 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.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.cards.CardImpl; +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.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class LaccolithTitan extends CardImpl { + + public LaccolithTitan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{R}{R}"); + this.subtype.add(SubType.BEAST); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn. + Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true); + ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public LaccolithTitan(final LaccolithTitan card) { + super(card); + } + + @Override + public LaccolithTitan copy() { + return new LaccolithTitan(this); + } + + class LaccolithEffect extends OneShotEffect { + public LaccolithEffect() { + super(Outcome.Damage); + staticText = "{this} deals damage equal to its power to target creature"; + } + + public LaccolithEffect(final LaccolithEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent == null) { + sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); + } + if (sourcePermanent == null) { + return false; + } + + int damage = sourcePermanent.getPower().getValue(); + + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + permanent.damage(damage, sourcePermanent.getId(), game, false, true); + return true; + } + return false; + } + + @Override + public LaccolithEffect copy() { + return new LaccolithEffect(this); + } + + } +} From 090e8ff5a59044d74b4df86fcec456bc1351b634 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 22:56:03 +0100 Subject: [PATCH 24/38] Implemented Laccolith Warrior --- .../src/mage/cards/l/LaccolithWarrior.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LaccolithWarrior.java diff --git a/Mage.Sets/src/mage/cards/l/LaccolithWarrior.java b/Mage.Sets/src/mage/cards/l/LaccolithWarrior.java new file mode 100644 index 00000000000..492d9a50e86 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LaccolithWarrior.java @@ -0,0 +1,113 @@ +/* + * 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.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.cards.CardImpl; +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.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class LaccolithWarrior extends CardImpl { + + public LaccolithWarrior(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + this.subtype.add(SubType.BEAST); + this.subtype.add(SubType.WARRIOR); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn. + Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true); + ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public LaccolithWarrior(final LaccolithWarrior card) { + super(card); + } + + @Override + public LaccolithWarrior copy() { + return new LaccolithWarrior(this); + } + + class LaccolithEffect extends OneShotEffect { + public LaccolithEffect() { + super(Outcome.Damage); + staticText = "{this} deals damage equal to its power to target creature"; + } + + public LaccolithEffect(final LaccolithEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent == null) { + sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); + } + if (sourcePermanent == null) { + return false; + } + + int damage = sourcePermanent.getPower().getValue(); + + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + permanent.damage(damage, sourcePermanent.getId(), game, false, true); + return true; + } + return false; + } + + @Override + public LaccolithEffect copy() { + return new LaccolithEffect(this); + } + + } +} From c0e379354578fa05ca49882ce202a05638a2783f Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 22:56:35 +0100 Subject: [PATCH 25/38] Implemented Laccolith Whelp --- .../src/mage/cards/l/LaccolithWhelp.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LaccolithWhelp.java diff --git a/Mage.Sets/src/mage/cards/l/LaccolithWhelp.java b/Mage.Sets/src/mage/cards/l/LaccolithWhelp.java new file mode 100644 index 00000000000..0d9b1553872 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LaccolithWhelp.java @@ -0,0 +1,112 @@ +/* + * 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.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.cards.CardImpl; +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.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public class LaccolithWhelp extends CardImpl { + + public LaccolithWhelp(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}"); + this.subtype.add(SubType.BEAST); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Whenever Laccolith Grunt becomes blocked, you may have it deal damage equal to its power to target creature. If you do, Laccolith Grunt assigns no combat damage this turn. + Ability ability = new BecomesBlockedTriggeredAbility(new LaccolithEffect().setText("you may have it deal damage equal to its power to target creature"), true); + ability.addEffect(new AssignNoCombatDamageSourceEffect(Duration.EndOfTurn, true)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public LaccolithWhelp(final LaccolithWhelp card) { + super(card); + } + + @Override + public LaccolithWhelp copy() { + return new LaccolithWhelp(this); + } + + class LaccolithEffect extends OneShotEffect { + public LaccolithEffect() { + super(Outcome.Damage); + staticText = "{this} deals damage equal to its power to target creature"; + } + + public LaccolithEffect(final LaccolithEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent sourcePermanent = game.getPermanent(source.getSourceId()); + if (sourcePermanent == null) { + sourcePermanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); + } + if (sourcePermanent == null) { + return false; + } + + int damage = sourcePermanent.getPower().getValue(); + + Permanent permanent = game.getPermanent(source.getFirstTarget()); + if (permanent != null) { + permanent.damage(damage, sourcePermanent.getId(), game, false, true); + return true; + } + return false; + } + + @Override + public LaccolithEffect copy() { + return new LaccolithEffect(this); + } + + } +} From d094e13d250f6cb911d525882c5ced1bd042fe88 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Tue, 31 Oct 2017 22:57:38 +0100 Subject: [PATCH 26/38] Implemented Laccolith creatures --- Mage.Sets/src/mage/sets/Nemesis.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mage.Sets/src/mage/sets/Nemesis.java b/Mage.Sets/src/mage/sets/Nemesis.java index d84902022d5..13cbb2e006a 100644 --- a/Mage.Sets/src/mage/sets/Nemesis.java +++ b/Mage.Sets/src/mage/sets/Nemesis.java @@ -100,6 +100,10 @@ public class Nemesis extends ExpansionSet { cards.add(new SetCardInfo("Jolting Merfolk", 34, Rarity.UNCOMMON, mage.cards.j.JoltingMerfolk.class)); cards.add(new SetCardInfo("Kill Switch", 133, Rarity.RARE, mage.cards.k.KillSwitch.class)); cards.add(new SetCardInfo("Kor Haven", 141, Rarity.RARE, mage.cards.k.KorHaven.class)); + cards.add(new SetCardInfo("Laccolith Grunt", 87, Rarity.COMMON, mage.cards.l.LaccolithGrunt.class)); + cards.add(new SetCardInfo("Laccolith Titan", 89, Rarity.RARE, mage.cards.l.LaccolithTitan.class)); + cards.add(new SetCardInfo("Laccolith Warrior", 90, Rarity.UNCOMMON, mage.cards.l.LaccolithWarrior.class)); + cards.add(new SetCardInfo("Laccolith Whelp", 91, Rarity.COMMON, mage.cards.l.LaccolithWhelp.class)); cards.add(new SetCardInfo("Lashknife", 9, Rarity.COMMON, mage.cards.l.Lashknife.class)); cards.add(new SetCardInfo("Lawbringer", 10, Rarity.COMMON, mage.cards.l.Lawbringer.class)); cards.add(new SetCardInfo("Lightbringer", 11, Rarity.COMMON, mage.cards.l.Lightbringer.class)); From d3f359151378244a47aaf549a50417bc12ec371d Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 12:35:11 +0100 Subject: [PATCH 27/38] Implemented Laccolith Rig --- Mage.Sets/src/mage/cards/l/LaccolithRig.java | 161 +++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/l/LaccolithRig.java diff --git a/Mage.Sets/src/mage/cards/l/LaccolithRig.java b/Mage.Sets/src/mage/cards/l/LaccolithRig.java new file mode 100644 index 00000000000..80eb97f7fac --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LaccolithRig.java @@ -0,0 +1,161 @@ +/* + * 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.cards.l; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BecomesBlockedTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.AssignNoCombatDamageSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +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.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author L_J + */ +public class LaccolithRig extends CardImpl { + + public LaccolithRig(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{R}"); + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Whenever enchanted creature becomes blocked, you may have it deal damage equal to its power to target creature. If you do, the first creature assigns no combat damage this turn. + Ability ability2 = new LaccolithRigTriggeredAbility(new LaccolithRigEffect(), true); + ability2.addTarget(new TargetCreaturePermanent()); + Effect effect = new GainAbilityTargetEffect(new SimpleStaticAbility(Zone.BATTLEFIELD, new AssignNoCombatDamageSourceEffect(Duration.Custom, true).setText("")), Duration.EndOfTurn, "If you do, the first creature assigns no combat damage this turn"); + ability2.addEffect(effect); + this.addAbility(ability2); + } + + public LaccolithRig(final LaccolithRig card) { + super(card); + } + + @Override + public LaccolithRig copy() { + return new LaccolithRig(this); + } +} + +class LaccolithRigTriggeredAbility extends TriggeredAbilityImpl { + + public LaccolithRigTriggeredAbility(Effect effect, boolean optional) { + super(Zone.BATTLEFIELD, effect, optional); + } + + public LaccolithRigTriggeredAbility(final LaccolithRigTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.CREATURE_BLOCKED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent equipment = game.getPermanent(sourceId); + if (equipment != null && equipment.getAttachedTo() != null) { + Permanent equipped = game.getPermanent(equipment.getAttachedTo()); + if (equipped.getId().equals(event.getTargetId())) { + getEffects().get(1).setTargetPointer(new FixedTarget(equipped.getId())); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever enchanted creature becomes blocked by a creature, " + super.getRule(); + } + + @Override + public LaccolithRigTriggeredAbility copy() { + return new LaccolithRigTriggeredAbility(this); + } +} + +class LaccolithRigEffect extends OneShotEffect { + + public LaccolithRigEffect() { + super(Outcome.Damage); + this.staticText = "you may have it deal damage equal to its power to target creature"; + } + + public LaccolithRigEffect(final LaccolithRigEffect effect) { + super(effect); + } + + @Override + public LaccolithRigEffect copy() { + return new LaccolithRigEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); + Permanent ownCreature = game.getPermanent(enchantment.getAttachedTo()); + if (ownCreature != null) { + int damage = ownCreature.getPower().getValue(); + Permanent targetCreature = game.getPermanent(source.getFirstTarget()); + if (targetCreature != null) { + targetCreature.damage(damage, ownCreature.getId(), game, false, true); + return true; + } + } + return false; + } +} From 94e4394c31ac119115447ef714dc569803d4cc65 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 12:35:20 +0100 Subject: [PATCH 28/38] Implemented Martyrdom --- Mage.Sets/src/mage/cards/m/Martyrdom.java | 178 ++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/m/Martyrdom.java diff --git a/Mage.Sets/src/mage/cards/m/Martyrdom.java b/Mage.Sets/src/mage/cards/m/Martyrdom.java new file mode 100644 index 00000000000..cc505a94ae4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/Martyrdom.java @@ -0,0 +1,178 @@ +/* + * 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.cards.m; + +import java.util.UUID; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.ActivatedAbilityImpl; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.Effects; +import mage.abilities.effects.RedirectionEffect; +import mage.abilities.effects.common.RedirectDamageFromSourceToTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.EffectType; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author L_J + */ +public class Martyrdom extends CardImpl { + + public Martyrdom(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}{W}"); + + // Until end of turn, target creature you control gains "{0}: The next 1 damage that would be dealt to target creature or player this turn is dealt to this creature instead." Only you may activate this ability. + this.getSpellAbility().addEffect(new MartyrdomGainAbilityTargetEffect()); + this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); + } + + public Martyrdom(final Martyrdom card) { + super(card); + } + + @Override + public Martyrdom copy() { + return new Martyrdom(this); + } +} + +class MartyrdomGainAbilityTargetEffect extends ContinuousEffectImpl { + + public MartyrdomGainAbilityTargetEffect() { + super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.staticText = "Until end of turn, target creature you control gains \"{0}: The next 1 damage that would be dealt to target creature or player this turn is dealt to this creature instead.\" Only you may activate this ability"; + } + + public MartyrdomGainAbilityTargetEffect(final MartyrdomGainAbilityTargetEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + ActivatedAbilityImpl ability = new MartyrdomActivatedAbility(source.getControllerId()); + ability.setMayActivate(TargetController.ANY); + permanent.addAbility(ability, source.getSourceId(), game, false); + return true; + } + return false; + } + + @Override + public MartyrdomGainAbilityTargetEffect copy() { + return new MartyrdomGainAbilityTargetEffect(this); + } +} + +class MartyrdomActivatedAbility extends ActivatedAbilityImpl { + + private UUID caster; + + public MartyrdomActivatedAbility(UUID caster) { + super(Zone.BATTLEFIELD, new MartyrdomRedirectDamageTargetEffect(Duration.EndOfTurn, 1), new GenericManaCost(0)); + this.addTarget(new TargetCreatureOrPlayer()); + this.caster = caster; + } + + private MartyrdomActivatedAbility(final MartyrdomActivatedAbility ability) { + super(ability); + this.caster = ability.caster; + } + + @Override + public Effects getEffects(Game game, EffectType effectType) { + return super.getEffects(game, effectType); + } + + @Override + public boolean canActivate(UUID playerId, Game game) { + if (playerId == caster) { + return super.canActivate(playerId, game); + } + return false; + } + + @Override + public MartyrdomActivatedAbility copy() { + return new MartyrdomActivatedAbility(this); + } + + @Override + public String getRule() { + return "{0}: The next 1 damage that would be dealt to target creature or player this turn is dealt to {this} instead."; + } +} + +class MartyrdomRedirectDamageTargetEffect extends RedirectionEffect { + + public MartyrdomRedirectDamageTargetEffect(Duration duration, int amount) { + super(duration, amount, true); + staticText = "The next " + amount + " damage that would be dealt to target creature or player this turn is dealt to {this} instead"; + } + + public MartyrdomRedirectDamageTargetEffect(final MartyrdomRedirectDamageTargetEffect effect) { + super(effect); + } + + @Override + public MartyrdomRedirectDamageTargetEffect copy() { + return new MartyrdomRedirectDamageTargetEffect(this); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { + if (event.getTargetId() != null && source.getSourceId() != null) { + TargetCreatureOrPlayer target = new TargetCreatureOrPlayer(); + target.add(source.getSourceId(), game); + redirectTarget = target; + return true; + } + } + return false; + } +} From 84029a99b67e77a184dd12d13cfa460be30ea067 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 12:35:35 +0100 Subject: [PATCH 29/38] Implemented Laccolith Rig --- Mage.Sets/src/mage/sets/Nemesis.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/sets/Nemesis.java b/Mage.Sets/src/mage/sets/Nemesis.java index 13cbb2e006a..f05a4909d36 100644 --- a/Mage.Sets/src/mage/sets/Nemesis.java +++ b/Mage.Sets/src/mage/sets/Nemesis.java @@ -101,6 +101,7 @@ public class Nemesis extends ExpansionSet { cards.add(new SetCardInfo("Kill Switch", 133, Rarity.RARE, mage.cards.k.KillSwitch.class)); cards.add(new SetCardInfo("Kor Haven", 141, Rarity.RARE, mage.cards.k.KorHaven.class)); cards.add(new SetCardInfo("Laccolith Grunt", 87, Rarity.COMMON, mage.cards.l.LaccolithGrunt.class)); + cards.add(new SetCardInfo("Laccolith Rig", 88, Rarity.COMMON, mage.cards.l.LaccolithRig.class)); cards.add(new SetCardInfo("Laccolith Titan", 89, Rarity.RARE, mage.cards.l.LaccolithTitan.class)); cards.add(new SetCardInfo("Laccolith Warrior", 90, Rarity.UNCOMMON, mage.cards.l.LaccolithWarrior.class)); cards.add(new SetCardInfo("Laccolith Whelp", 91, Rarity.COMMON, mage.cards.l.LaccolithWhelp.class)); From 960a6d7d5d63db96c7081014b2ad1adf61c0f962 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 12:35:45 +0100 Subject: [PATCH 30/38] Implemented Martyrdom --- Mage.Sets/src/mage/sets/Alliances.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mage.Sets/src/mage/sets/Alliances.java b/Mage.Sets/src/mage/sets/Alliances.java index 1a67bc92be8..e97dda21691 100644 --- a/Mage.Sets/src/mage/sets/Alliances.java +++ b/Mage.Sets/src/mage/sets/Alliances.java @@ -113,6 +113,8 @@ public class Alliances extends ExpansionSet { cards.add(new SetCardInfo("Lim-Dul's Paladin", 191, Rarity.UNCOMMON, mage.cards.l.LimDulsPaladin.class)); cards.add(new SetCardInfo("Lim-Dul's Vault", 192, Rarity.UNCOMMON, mage.cards.l.LimDulsVault.class)); cards.add(new SetCardInfo("Lord of Tresserhorn", 193, Rarity.RARE, mage.cards.l.LordOfTresserhorn.class)); + cards.add(new SetCardInfo("Martyrdom", 138, Rarity.COMMON, mage.cards.m.Martyrdom.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Martyrdom", 139, Rarity.COMMON, mage.cards.m.Martyrdom.class, NON_FULL_USE_VARIOUS)); cards.add(new SetCardInfo("Mishra's Groundbreaker", 165, Rarity.UNCOMMON, mage.cards.m.MishrasGroundbreaker.class)); cards.add(new SetCardInfo("Misinformation", 19, Rarity.UNCOMMON, mage.cards.m.Misinformation.class)); cards.add(new SetCardInfo("Mystic Compass", 166, Rarity.UNCOMMON, mage.cards.m.MysticCompass.class)); From 4823f25c2975179a9cc661a42a96b0ecf3fb8f93 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 18:06:12 +0100 Subject: [PATCH 31/38] Fixed some microbugs --- Mage.Sets/src/mage/cards/m/Martyrdom.java | 28 +++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Mage.Sets/src/mage/cards/m/Martyrdom.java b/Mage.Sets/src/mage/cards/m/Martyrdom.java index cc505a94ae4..129b444ddad 100644 --- a/Mage.Sets/src/mage/cards/m/Martyrdom.java +++ b/Mage.Sets/src/mage/cards/m/Martyrdom.java @@ -48,6 +48,7 @@ import mage.constants.Outcome; import mage.constants.SubLayer; import mage.constants.TargetController; import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -110,6 +111,7 @@ class MartyrdomGainAbilityTargetEffect extends ContinuousEffectImpl { class MartyrdomActivatedAbility extends ActivatedAbilityImpl { + private static FilterCreaturePermanent filter = new FilterCreaturePermanent(); private UUID caster; public MartyrdomActivatedAbility(UUID caster) { @@ -131,7 +133,12 @@ class MartyrdomActivatedAbility extends ActivatedAbilityImpl { @Override public boolean canActivate(UUID playerId, Game game) { if (playerId == caster) { - return super.canActivate(playerId, game); + Permanent permanent = game.getBattlefield().getPermanent(this.getSourceId()); + if (permanent != null) { + if (filter.match(permanent, permanent.getId(), permanent.getControllerId(), game)) { + return super.canActivate(playerId, game); + } + } } return false; } @@ -149,6 +156,8 @@ class MartyrdomActivatedAbility extends ActivatedAbilityImpl { class MartyrdomRedirectDamageTargetEffect extends RedirectionEffect { + private static FilterCreaturePermanent filter = new FilterCreaturePermanent(); + public MartyrdomRedirectDamageTargetEffect(Duration duration, int amount) { super(duration, amount, true); staticText = "The next " + amount + " damage that would be dealt to target creature or player this turn is dealt to {this} instead"; @@ -165,12 +174,17 @@ class MartyrdomRedirectDamageTargetEffect extends RedirectionEffect { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { - if (event.getTargetId() != null && source.getSourceId() != null) { - TargetCreatureOrPlayer target = new TargetCreatureOrPlayer(); - target.add(source.getSourceId(), game); - redirectTarget = target; - return true; + Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); + if (permanent != null) { + if (filter.match(permanent, permanent.getId(), permanent.getControllerId(), game)) { + if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { + if (event.getTargetId() != null) { + TargetCreatureOrPlayer target = new TargetCreatureOrPlayer(); + target.add(source.getSourceId(), game); + redirectTarget = target; + return true; + } + } } } return false; From 3b237cc94527fd61a08a74748abd0cf3542bf1c8 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 18:45:38 +0100 Subject: [PATCH 32/38] Fixed redirection bug --- .../src/mage/cards/d/DaughterOfAutumn.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/Mage.Sets/src/mage/cards/d/DaughterOfAutumn.java b/Mage.Sets/src/mage/cards/d/DaughterOfAutumn.java index 464864afe58..19cb73f7745 100644 --- a/Mage.Sets/src/mage/cards/d/DaughterOfAutumn.java +++ b/Mage.Sets/src/mage/cards/d/DaughterOfAutumn.java @@ -45,6 +45,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; @@ -71,7 +72,6 @@ public class DaughterOfAutumn extends CardImpl { // {W}: The next 1 damage that would be dealt to target white creature this turn is dealt to Daughter of Autumn instead. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DaughterOfAutumnPreventDamageTargetEffect(Duration.EndOfTurn, 1), new ManaCostsImpl("{W}")); ability.addTarget(new TargetCreaturePermanent(filter)); - this.addAbility(ability); } public DaughterOfAutumn(final DaughterOfAutumn card) { @@ -86,6 +86,8 @@ public class DaughterOfAutumn extends CardImpl { class DaughterOfAutumnPreventDamageTargetEffect extends RedirectionEffect { + private static FilterCreaturePermanent filter = new FilterCreaturePermanent(); + public DaughterOfAutumnPreventDamageTargetEffect(Duration duration, int amount) { super(duration, amount, true); staticText = "The next " + amount + " damage that would be dealt to target white creature this turn is dealt to {this} instead"; @@ -102,13 +104,19 @@ class DaughterOfAutumnPreventDamageTargetEffect extends RedirectionEffect { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { - TargetPermanent target = new TargetPermanent(); - target.add(source.getSourceId(), game); - redirectTarget = target; - return true; + Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); + if (permanent != null) { + if (filter.match(permanent, permanent.getId(), permanent.getControllerId(), game)) { + if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) { + if (event.getTargetId() != null) { + TargetPermanent target = new TargetPermanent(); + target.add(source.getSourceId(), game); + redirectTarget = target; + return true; + } + } + } } return false; } - } From 9423c302452a2579ac6b3e351661bc7d962e64f2 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 20:40:49 +0100 Subject: [PATCH 33/38] Fix for #4131 --- .../mage/abilities/keyword/MeleeAbility.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/keyword/MeleeAbility.java b/Mage/src/main/java/mage/abilities/keyword/MeleeAbility.java index 04d14eff93e..6fc22f88037 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MeleeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MeleeAbility.java @@ -47,7 +47,7 @@ import mage.watchers.Watcher; * * @author emerald000 */ -public class MeleeAbility extends AttacksTriggeredAbility { +public class MeleeAbility extends AttacksTriggeredAbility { public MeleeAbility() { super(new BoostSourceEffect(new MeleeDynamicValue(), new MeleeDynamicValue(), Duration.EndOfTurn), false); @@ -71,7 +71,7 @@ public class MeleeAbility extends AttacksTriggeredAbility { class MeleeWatcher extends Watcher { - private final HashMap> playersAttacked = new HashMap<>(0); + private HashMap> playersAttacked = new HashMap<>(0); MeleeWatcher() { super("MeleeWatcher", WatcherScope.GAME); @@ -95,7 +95,10 @@ class MeleeWatcher extends Watcher { } public int getNumberOfAttackedPlayers(UUID attackerId) { - return this.playersAttacked.get(attackerId).size(); + if (this.playersAttacked.get(attackerId) != null) { + return this.playersAttacked.get(attackerId).size(); + } + return 0; } @Override @@ -106,11 +109,18 @@ class MeleeWatcher extends Watcher { class MeleeDynamicValue implements DynamicValue { + private boolean valueChecked = false; + private int lockedInValue; + @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { MeleeWatcher watcher = (MeleeWatcher) game.getState().getWatchers().get(MeleeWatcher.class.getSimpleName()); if (watcher != null) { - return watcher.getNumberOfAttackedPlayers(sourceAbility.getControllerId()); + if (!valueChecked) { + this.lockedInValue = watcher.getNumberOfAttackedPlayers(sourceAbility.getControllerId()); + valueChecked = true; + } + return this.lockedInValue; } return 0; } From 896bcc504c8ab3192cf740eaf0d1a8498e2f96f0 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 22:17:40 +0100 Subject: [PATCH 34/38] Lousy fix for #4138 --- Mage.Sets/src/mage/cards/b/BatheInLight.java | 81 +++++++++++++++++--- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/Mage.Sets/src/mage/cards/b/BatheInLight.java b/Mage.Sets/src/mage/cards/b/BatheInLight.java index 12dd48dcb4e..396666f53dd 100644 --- a/Mage.Sets/src/mage/cards/b/BatheInLight.java +++ b/Mage.Sets/src/mage/cards/b/BatheInLight.java @@ -31,16 +31,22 @@ import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ChooseColorEffect; import mage.abilities.effects.common.continuous.GainProtectionFromColorTargetEffect; +import mage.abilities.keyword.ProtectionAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.choices.ChoiceColor; import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Layer; import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.filter.FilterObject; import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -49,7 +55,7 @@ import mage.target.targetpointer.FixedTarget; /** * - * @author LevelX2 + * @author LevelX2 & L_J */ public class BatheInLight extends CardImpl { @@ -57,7 +63,6 @@ public class BatheInLight extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); // Radiance - Choose a color. Target creature and each other creature that shares a color with it gain protection from the chosen color until end of turn. - this.getSpellAbility().addEffect(new ChooseColorEffect(Outcome.Benefit)); this.getSpellAbility().addEffect(new BatheInLightEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); this.getSpellAbility().setAbilityWord(AbilityWord.RADIANCE); @@ -95,19 +100,71 @@ class BatheInLightEffect extends OneShotEffect { if (controller != null) { Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); if (target != null) { - ObjectColor protectColor = (ObjectColor) game.getState().getValue(target.getId() + "_color"); - if (protectColor != null) { - ObjectColor color = target.getColor(game); - for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { - if (permanent.getColor(game).shares(color)) { - ContinuousEffect effect = new GainProtectionFromColorTargetEffect(Duration.EndOfTurn, protectColor); - effect.setTargetPointer(new FixedTarget(permanent, game)); - game.addEffect(effect, source); + ChoiceColor colorChoice = new ChoiceColor(); + if (controller.choose(Outcome.Benefit, colorChoice, game)) { + game.informPlayers(target.getName() + ": " + controller.getLogName() + " has chosen " + colorChoice.getChoice()); + game.getState().setValue(target.getId() + "_color", colorChoice.getColor()); + + ObjectColor protectColor = (ObjectColor) game.getState().getValue(target.getId() + "_color"); + if (protectColor != null) { + ContinuousEffect effect = new ProtectionChosenColorTargetEffect(); + game.addEffect(effect, source); + ObjectColor color = target.getColor(game); + for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { + if (permanent != target && permanent.getColor(game).shares(color)) { + game.getState().setValue(permanent.getId() + "_color", colorChoice.getColor()); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); + } } } } - } return true; + } + } + return false; + } +} + +class ProtectionChosenColorTargetEffect extends ContinuousEffectImpl { + + protected ObjectColor chosenColor; + protected ProtectionAbility protectionAbility; + + public ProtectionChosenColorTargetEffect() { + super(Duration.EndOfTurn, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + } + + public ProtectionChosenColorTargetEffect(final ProtectionChosenColorTargetEffect effect) { + super(effect); + if (effect.chosenColor != null) { + this.chosenColor = effect.chosenColor.copy(); + } + if (effect.protectionAbility != null) { + this.protectionAbility = effect.protectionAbility.copy(); + } + } + + @Override + public ProtectionChosenColorTargetEffect copy() { + return new ProtectionChosenColorTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (permanent != null) { + ObjectColor color = (ObjectColor) game.getState().getValue(permanent.getId() + "_color"); + if (color != null && (protectionAbility == null || !color.equals(chosenColor))) { + chosenColor = color; + FilterObject protectionFilter = new FilterObject(chosenColor.getDescription()); + protectionFilter.add(new ColorPredicate(chosenColor)); + protectionAbility = new ProtectionAbility(protectionFilter); + } + if (protectionAbility != null) { + permanent.addAbility(protectionAbility, source.getSourceId(), game); + return true; + } } return false; } From 5aef889ea8bda6973ae79fd52fddc491f787fae7 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 22:20:37 +0100 Subject: [PATCH 35/38] (insignificant?) fix --- Mage.Sets/src/mage/cards/w/Wishmonger.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/w/Wishmonger.java b/Mage.Sets/src/mage/cards/w/Wishmonger.java index 46da88a3f45..46659aab0e5 100644 --- a/Mage.Sets/src/mage/cards/w/Wishmonger.java +++ b/Mage.Sets/src/mage/cards/w/Wishmonger.java @@ -117,6 +117,7 @@ class WishmongerEffect extends OneShotEffect { game.addEffect(effect, source); } } + return true; } } return false; From a9089edff5e767263767673ab6e1d219a9cf37c6 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Wed, 1 Nov 2017 22:20:54 +0100 Subject: [PATCH 36/38] (insignificant?) fix --- Mage.Sets/src/mage/cards/p/PaleWayfarer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Mage.Sets/src/mage/cards/p/PaleWayfarer.java b/Mage.Sets/src/mage/cards/p/PaleWayfarer.java index e539dd861bf..39227fe6a7e 100644 --- a/Mage.Sets/src/mage/cards/p/PaleWayfarer.java +++ b/Mage.Sets/src/mage/cards/p/PaleWayfarer.java @@ -117,6 +117,7 @@ class PaleWayfarerEffect extends OneShotEffect { game.addEffect(effect, source); } } + return true; } } return false; From 4c8245020ab31adb7fff95007edf197ad56657a6 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Thu, 2 Nov 2017 06:41:01 +0100 Subject: [PATCH 37/38] Fixed redirection bug --- Mage.Sets/src/mage/cards/s/ShamanEnKor.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/ShamanEnKor.java b/Mage.Sets/src/mage/cards/s/ShamanEnKor.java index 780c4b58da7..13e67fb808a 100644 --- a/Mage.Sets/src/mage/cards/s/ShamanEnKor.java +++ b/Mage.Sets/src/mage/cards/s/ShamanEnKor.java @@ -43,9 +43,11 @@ import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.TargetSource; @@ -91,6 +93,7 @@ public class ShamanEnKor extends CardImpl { class ShamanEnKorRedirectFromTargetEffect extends RedirectionEffect { + private static FilterCreaturePermanent filter = new FilterCreaturePermanent(); protected MageObjectReference sourceObject; ShamanEnKorRedirectFromTargetEffect() { @@ -122,10 +125,15 @@ class ShamanEnKorRedirectFromTargetEffect extends RedirectionEffect { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (sourceObject.equals(new MageObjectReference(event.getSourceId(), game))) { - redirectTarget = new TargetPermanent(); - redirectTarget.add(source.getSourceId(), game); - return event.getTargetId().equals(getTargetPointer().getFirst(game, source)); + Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); + if (permanent != null) { + if (filter.match(permanent, permanent.getId(), permanent.getControllerId(), game)) { + if (sourceObject.equals(new MageObjectReference(event.getSourceId(), game))) { + redirectTarget = new TargetPermanent(); + redirectTarget.add(source.getSourceId(), game); + return event.getTargetId().equals(getTargetPointer().getFirst(game, source)); + } + } } return false; } From f653ddb9211f2e8e53ea552370c1b9fe31959774 Mon Sep 17 00:00:00 2001 From: Zzooouhh Date: Thu, 2 Nov 2017 07:05:33 +0100 Subject: [PATCH 38/38] Another fix for #4090 --- .../RedirectDamageFromSourceToTargetEffect.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/effects/common/RedirectDamageFromSourceToTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/RedirectDamageFromSourceToTargetEffect.java index 9a1e32f7e0a..bff0d3cceed 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/RedirectDamageFromSourceToTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/RedirectDamageFromSourceToTargetEffect.java @@ -10,6 +10,7 @@ import mage.abilities.effects.RedirectionEffect; import mage.constants.Duration; import mage.game.Game; import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; /** * @@ -33,9 +34,14 @@ public class RedirectDamageFromSourceToTargetEffect extends RedirectionEffect { @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getTargetId().equals(source.getSourceId())) { - this.redirectTarget = source.getTargets().get(0); - return true; + Permanent permanent = game.getBattlefield().getPermanent(source.getSourceId()); + if (permanent != null) { + if (event.getTargetId().equals(source.getSourceId())) { + if (getTargetPointer().getFirst(game, source) != null) { + this.redirectTarget = source.getTargets().get(0); + return true; + } + } } return false; }